Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use supervision to set thermostat setpoint #2584

Merged
merged 19 commits into from
Sep 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion cpp/src/Msg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "ZWSecurity.h"
#include "platform/Log.h"
#include "command_classes/MultiInstance.h"
#include "command_classes/Supervision.h"
#include "command_classes/Security.h"
#include "aes/aescpp.h"

Expand All @@ -50,7 +51,7 @@ namespace OpenZWave
//-----------------------------------------------------------------------------
Msg::Msg(string const& _logText, uint8 _targetNodeId, uint8 const _msgType, uint8 const _function, bool const _bCallbackRequired, bool const _bReplyRequired, // = true
uint8 const _expectedReply, // = 0
uint8 const _expectedCommandClassId // = 0
uint8 const _expectedCommandClassId // = 0
) :
m_logText(_logText), m_bFinal(false), m_bCallbackRequired(_bCallbackRequired), m_callbackId(0), m_expectedReply(0), m_expectedCommandClassId(_expectedCommandClassId), m_length(4), m_targetNodeId(_targetNodeId), m_sendAttempts(0), m_maxSendAttempts( MAX_TRIES), m_instance(1), m_endPoint(0), m_flags(0), m_encrypted(false), m_noncerecvd(false), m_homeId(0), m_resendDuetoCANorNAK(false)
{
Expand Down Expand Up @@ -102,6 +103,19 @@ namespace OpenZWave
}
}

//-----------------------------------------------------------------------------
// <Msg::SetSupervision>
// Encapsulate the data inside a Supervision message
//-----------------------------------------------------------------------------
void Msg::SetSupervision(uint8 _supervision_session_id)
{
if (_supervision_session_id != Internal::CC::Supervision::StaticNoSessionId())
{
m_supervision_session_id = _supervision_session_id;
m_flags |= m_Supervision;
}
}

//-----------------------------------------------------------------------------
// <Msg::Append>
// Add a byte to the message
Expand Down Expand Up @@ -135,6 +149,12 @@ namespace OpenZWave
return;
}

// Deal with Supervision encapsulation
if ((m_flags & m_Supervision) != 0)
{
SupervisionEncap();
}

// Deal with Multi-Channel/Instance encapsulation
if ((m_flags & (m_MultiChannel | m_MultiInstance)) != 0)
{
Expand Down Expand Up @@ -280,6 +300,33 @@ namespace OpenZWave
}
}

//-----------------------------------------------------------------------------
// <Msg::SupervisionEncap>
// Encapsulate the data inside a Supervision message
//-----------------------------------------------------------------------------
void Msg::SupervisionEncap()
{
char str[256];
if (m_buffer[3] != FUNC_ID_ZW_SEND_DATA)
{
return;
}

for (uint32 i = m_length - 1; i >= 6; --i)
{
m_buffer[i + 4] = m_buffer[i];
}
m_buffer[6] = Internal::CC::Supervision::StaticGetCommandClassId();
m_buffer[7] = Internal::CC::Supervision::SupervisionCmd_Get;
m_buffer[8] = Internal::CC::Supervision::SupervisionMoreStatusUpdates_MoreReports | m_supervision_session_id;
m_buffer[9] = m_buffer[5];
m_buffer[5] += 4;
m_length += 4;

snprintf(str, sizeof(str), "Supervisioned (session=%d): %s", m_supervision_session_id, m_logText.c_str());
m_logText = str;
}

//-----------------------------------------------------------------------------
// <Node::GetDriver>
// Get a pointer to our driver
Expand Down
6 changes: 5 additions & 1 deletion cpp/src/Msg.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ namespace OpenZWave
{
m_MultiChannel = 0x01, // Indicate MultiChannel encapsulation
m_MultiInstance = 0x02, // Indicate MultiInstance encapsulation
m_Supervision = 0x04, // Indicate Supervision encapsulation
};

Msg(string const& _logtext, uint8 _targetNodeId, uint8 const _msgType, uint8 const _function, bool const _bCallbackRequired, bool const _bReplyRequired = true, uint8 const _expectedReply = 0, uint8 const _expectedCommandClassId = 0);
Expand All @@ -62,6 +63,7 @@ namespace OpenZWave
}

void SetInstance(OpenZWave::Internal::CC::CommandClass * _cc, uint8 const _instance); // Used to enable wrapping with MultiInstance/MultiChannel during finalize.
void SetSupervision(uint8 _session_id);

void Append(uint8 const _data);
void AppendArray(const uint8* const _data, const uint8 _length);
Expand Down Expand Up @@ -215,7 +217,7 @@ namespace OpenZWave
{
m_homeId = homeId;
}
void setResendDuetoCANorNAK()
void setResendDuetoCANorNAK()
{
m_resendDuetoCANorNAK = true;
}
Expand All @@ -231,6 +233,7 @@ namespace OpenZWave
private:

void MultiEncap(); // Encapsulate the data inside a MultiInstance/Multicommand message
void SupervisionEncap(); // Encapsulate the data inside a Supervision message
string m_logText;
bool m_bFinal;
bool m_bCallbackRequired;
Expand All @@ -249,6 +252,7 @@ namespace OpenZWave
uint8 m_instance;
uint8 m_endPoint; // Endpoint to use if the message must be wrapped in a multiInstance or multiChannel command class
uint8 m_flags;
uint8 m_supervision_session_id;

bool m_encrypted;
bool m_noncerecvd;
Expand Down
33 changes: 33 additions & 0 deletions cpp/src/Node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
#include "command_classes/NodeNaming.h"
#include "command_classes/NoOperation.h"
#include "command_classes/Version.h"
#include "command_classes/Supervision.h"
#include "command_classes/SwitchAll.h"
#include "command_classes/ZWavePlusInfo.h"
#include "command_classes/DeviceResetLocally.h"
Expand Down Expand Up @@ -4049,3 +4050,35 @@ void Node::WriteMetaDataXML(TiXmlElement *mdElement)
mdElement->LinkEndChild(cl);
}
}

//-----------------------------------------------------------------------------
// <Node::CreateSupervisionSession>
// Generate a new session id for Supervision encapsulation, if supported
//-----------------------------------------------------------------------------
uint8 Node::CreateSupervisionSession(uint8 _command_class_id, uint8 _index)
{
if (Internal::CC::CommandClass* cc = GetCommandClass(Internal::CC::Supervision::StaticGetCommandClassId()))
{
return cc->CreateSupervisionSession(_command_class_id, _index);
}
else
{
return Internal::CC::Supervision::StaticNoSessionId();
}
}

//-----------------------------------------------------------------------------
// <Node::GetSupervisionIndex>
// Get the index used by a session
//-----------------------------------------------------------------------------
uint32 Node::GetSupervisionIndex(uint8 _session_id)
{
if (Internal::CC::CommandClass* cc = GetCommandClass(Internal::CC::Supervision::StaticGetCommandClassId()))
{
return cc->GetSupervisionIndex(_session_id);
}
else
{
return Internal::CC::Supervision::StaticNoIndex();
}
}
4 changes: 4 additions & 0 deletions cpp/src/Node.h
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,10 @@ namespace OpenZWave
void WriteMetaDataXML(TiXmlElement*);
map<MetaDataFields, string> m_metadata;
map<uint32_t, ChangeLogEntry> m_changeLog;

public:
uint8 CreateSupervisionSession(uint8 _command_class_id, uint8 _index);
uint32 GetSupervisionIndex(uint8 _session_id);
};

} //namespace OpenZWave
Expand Down
7 changes: 7 additions & 0 deletions cpp/src/command_classes/CommandClass.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,13 @@ namespace OpenZWave
virtual bool supportsMultiInstance() {
return true;
}
virtual uint8 CreateSupervisionSession(uint8 _command_class_id, uint8 _index) {
return 0;
}
virtual uint32 GetSupervisionIndex(uint8 _session_id) {
return 0;
}
virtual void SupervisionSessionSuccess(uint8 _session_id, uint32 const _instance) {};

void SetInstances(uint8 const _instances);
void SetInstance(uint8 const _endPoint);
Expand Down
2 changes: 2 additions & 0 deletions cpp/src/command_classes/CommandClasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
#include "command_classes/SensorBinary.h"
#include "command_classes/SensorMultilevel.h"
#include "command_classes/SoundSwitch.h"
#include "command_classes/Supervision.h"
#include "command_classes/SwitchAll.h"
#include "command_classes/SwitchBinary.h"
#include "command_classes/SwitchMultilevel.h"
Expand Down Expand Up @@ -226,6 +227,7 @@ namespace OpenZWave
cc.Register(SensorBinary::StaticGetCommandClassId(), SensorBinary::StaticGetCommandClassName(), SensorBinary::Create);
cc.Register(SensorMultilevel::StaticGetCommandClassId(), SensorMultilevel::StaticGetCommandClassName(), SensorMultilevel::Create);
cc.Register(SoundSwitch::StaticGetCommandClassId(), SoundSwitch::StaticGetCommandClassName(), SoundSwitch::Create);
cc.Register(Supervision::StaticGetCommandClassId(), Supervision::StaticGetCommandClassName(), Supervision::Create);
cc.Register(SwitchAll::StaticGetCommandClassId(), SwitchAll::StaticGetCommandClassName(), SwitchAll::Create);
cc.Register(SwitchBinary::StaticGetCommandClassId(), SwitchBinary::StaticGetCommandClassName(), SwitchBinary::Create);
cc.Register(SwitchMultilevel::StaticGetCommandClassId(), SwitchMultilevel::StaticGetCommandClassName(), SwitchMultilevel::Create);
Expand Down
174 changes: 174 additions & 0 deletions cpp/src/command_classes/Supervision.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
//-----------------------------------------------------------------------------
//
// Supervision.h
//
// Implementation of the Z-Wave COMMAND_CLASS_SUPERVISION
//
// Copyright (c) 2020 Mark Ruys <mark@paracas.nl>
//
// SOFTWARE NOTICE AND LICENSE
//
// This file is part of OpenZWave.
//
// OpenZWave is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// OpenZWave is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenZWave. If not, see <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------

#include "command_classes/CommandClasses.h"
#include "command_classes/Supervision.h"
#include "Defs.h"
#include "Msg.h"
#include "Node.h"
#include "Driver.h"
#include "platform/Log.h"

#include "value_classes/Value.h"

namespace OpenZWave
{
namespace Internal
{
namespace CC
{
uint8 Supervision::CreateSupervisionSession(uint8 _command_class_id, uint8 _index)
{
m_last_session_id++;
m_last_session_id &= 0x3f;

if (m_sessions.size() >= 6)
{
// Clean up oldest session, we support max 6 simultaneous sessions per node
m_sessions.pop_front();
}

m_sessions.push_back({
.session_id = m_last_session_id,
.command_class_id = _command_class_id,
.index = _index
});

return m_last_session_id;
}

uint32 Supervision::GetSupervisionIndex(uint8 _session_id)
{
for (auto it = m_sessions.cbegin(); it != m_sessions.cend(); ++it)
{
if (it->session_id == _session_id)
{
return it->index;
}
}

return StaticNoIndex();
}

//-----------------------------------------------------------------------------
// <Supervision::HandleSupervisionReport>
// Handle a supervision report message from the Z-Wave network
//-----------------------------------------------------------------------------
void Supervision::HandleSupervisionReport(uint8 const* _data, uint32 const _length, uint32 const _instance)
{
if (Node* node = GetNodeUnsafe())
{
if (_length >= 4)
{
uint8 more_status_updates = _data[1] >> 7;
uint8 session_id = _data[1] & 0x3f;
uint8 status = _data[2];
int duration = _data[3];

const char *status_identifier;
switch (status) {
case 0x00: status_identifier = "NO_SUPPORT"; break;
case 0x01: status_identifier = "WORKING"; break;
case 0x02: status_identifier = "FAIL"; break;
case 0xff: status_identifier = "SUCCESS"; break;
default: status_identifier = "UNKNOWN"; break;
}

for (auto it = m_sessions.cbegin(); it != m_sessions.cend(); ++it)
{
if (it->session_id == session_id)
{
if (CommandClass* pCommandClass = node->GetCommandClass(it->command_class_id))
{
Log::Write(LogLevel_Info, GetNodeId(), "Received SupervisionReport: session %d, %s index %d, status %s, duration %d sec, more status updates %d",
session_id,
pCommandClass->GetCommandClassName().c_str(), it->index,
status_identifier, decodeDuration(duration), more_status_updates);

if (status == SupervisionStatus::SupervisionStatus_Success)
{
pCommandClass->SupervisionSessionSuccess(session_id, _instance);
}
}
else
{
Log::Write(LogLevel_Warning, GetNodeId(), "Received SupervisionReport for unknown CC %d", it->command_class_id);
}

if (more_status_updates == 0)
{
m_sessions.erase(it);
}

return;
}
}

Log::Write(LogLevel_Warning, GetNodeId(), "Received SupervisionReport: unknown session %d, status %s, duration %d sec, more status updates %d",
session_id,
status_identifier, decodeDuration(duration), more_status_updates);
}
}
}

bool Supervision::HandleIncomingMsg(uint8 const* _data, uint32 const _length, uint32 const _instance)
{
return HandleMsg(_data, _length, _instance);
}

//-----------------------------------------------------------------------------
// <Supervision::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool Supervision::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance) // = 1
{
bool handled = false;
Node* node = GetNodeUnsafe();
if (node != NULL)
{
handled = true;
switch ((SupervisionCmd) _data[0])
{
case SupervisionCmd_Report:
{
HandleSupervisionReport(_data, _length, _instance);
break;
}
default:
{
handled = false;
break;
}
}
}

return handled;
}
} // namespace CC
} // namespace Internal
} // namespace OpenZWave

Loading