update esppilight lib

content of the library is not filtered on 433mhz only
This commit is contained in:
Florian committed 2018-11-28 20:41:37 +01:00
1 parent a275e48ee1
commit 67dd7ac078
1030 files changed
+203335 -116

No files matched your search

@@ -0,0 +1,148 @@
//-----------------------------------------------------------------------------
//
// Alarm.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_ALARM
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "Alarm.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueByte.h"
using namespace OpenZWave;
enum AlarmCmd
{
AlarmCmd_Get = 0x04,
AlarmCmd_Report = 0x05
};
enum
{
AlarmIndex_Type = 0,
AlarmIndex_Level
};
//-----------------------------------------------------------------------------
// <Alarm::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool Alarm::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _requestFlags & RequestFlag_Dynamic )
{
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <Alarm::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool Alarm::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( IsGetSupported() )
{
Msg* msg = new Msg( "AlarmCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( AlarmCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "AlarmCmd_Get Not Supported on this node");
}
return false;
}
//-----------------------------------------------------------------------------
// <Alarm::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool Alarm::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if (AlarmCmd_Report == (AlarmCmd)_data[0])
{
// We have received a report from the Z-Wave device
Log::Write( LogLevel_Info, GetNodeId(), "Received Alarm report: type=%d, level=%d", _data[1], _data[2] );
ValueByte* value;
if( (value = static_cast<ValueByte*>( GetValue( _instance, AlarmIndex_Type ) )) )
{
value->OnValueRefreshed( _data[1] );
value->Release();
}
if( (value = static_cast<ValueByte*>( GetValue( _instance, AlarmIndex_Level ) )) )
{
value->OnValueRefreshed( _data[2] );
value->Release();
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <Alarm::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void Alarm::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, AlarmIndex_Type, "Alarm Type", "", true, false, 0, 0 );
node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, AlarmIndex_Level, "Alarm Level", "", true, false, 0, 0 );
}
}
@@ -0,0 +1,71 @@
//-----------------------------------------------------------------------------
//
// Alarm.h
//
// Implementation of the Z-Wave COMMAND_CLASS_ALARM
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _Alarm_H
#define _Alarm_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueByte;
/** \brief Implements COMMAND_CLASS_ALARM (0x71), a Z-Wave device command class.
*/
class Alarm: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Alarm( _homeId, _nodeId ); }
virtual ~Alarm(){}
/** \brief Get command class ID (1 byte) identifying this command class. */
static uint8 const StaticGetCommandClassId(){ return 0x71; }
/** \brief Get a string containing the name of this command class. */
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_ALARM"; }
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
/** \brief Get command class ID (1 byte) identifying this command class. (Inherited from CommandClass) */
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
/** \brief Get a string containing the name of this command class. (Inherited from CommandClass) */
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
/** \brief Handle a response to a message associated with this command class. (Inherited from CommandClass) */
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual uint8 GetMaxVersion(){ return 2; }
protected:
virtual void CreateVars( uint8 const _instance );
private:
Alarm( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,93 @@
//-----------------------------------------------------------------------------
//
// ApplicationStatus.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_APPLICATION_STATUS
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "ApplicationStatus.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Driver.h"
#include "../platform/Log.h"
using namespace OpenZWave;
enum ApplicationStatusCmd
{
ApplicationStatusCmd_Busy = 0x01,
ApplicationStatusCmd_RejectedRequest = 0x02
};
//-----------------------------------------------------------------------------
// <ApplicationStatus::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool ApplicationStatus::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( ApplicationStatusCmd_Busy == (ApplicationStatusCmd)_data[0] )
{
char msg[64];
switch( _data[1] )
{
case 0:
{
snprintf( msg, sizeof(msg), "Try again later" );
break;
}
case 1:
{
snprintf( msg, sizeof(msg), "Try again in %d seconds", _data[2] );
break;
}
case 2:
{
snprintf( msg, sizeof(msg), "Request queued, will be executed later" );
break;
}
default:
{
// Invalid status
snprintf( msg, sizeof(msg), "Unknown status %d", _data[1] );
}
}
Log::Write( LogLevel_Info, GetNodeId(), "Received Application Status Busy: %s", msg );
return true;
}
if( ApplicationStatusCmd_RejectedRequest == (ApplicationStatusCmd)_data[0] )
{
Log::Write( LogLevel_Info, "Received Application Rejected Request: Status=%d", _data[1] );
return true;
}
return false;
}
@@ -0,0 +1,58 @@
//-----------------------------------------------------------------------------
//
// ApplicationStatus.h
//
// Implementation of the Z-Wave COMMAND_CLASS_APPLICATION_STATUS
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _ApplicationStatus_H
#define _ApplicationStatus_H
#include "CommandClass.h"
namespace OpenZWave
{
/** \brief Implements COMMAND_CLASS_APPLICATION_STATUS (0x22), a Z-Wave device command class.
*/
class ApplicationStatus: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ApplicationStatus( _homeId, _nodeId ); }
virtual ~ApplicationStatus(){}
static uint8 const StaticGetCommandClassId(){ return 0x22; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_APPLICATION_STATUS"; }
// From CommandClass
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
private:
ApplicationStatus( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,390 @@
//-----------------------------------------------------------------------------
//
// Association.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_ASSOCIATION
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "../tinyxml.h"
#include "CommandClasses.h"
#include "Association.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Driver.h"
#include "../Node.h"
#include "../Group.h"
#include "../platform/Log.h"
using namespace OpenZWave;
enum AssociationCmd
{
AssociationCmd_Set = 0x01,
AssociationCmd_Get = 0x02,
AssociationCmd_Report = 0x03,
AssociationCmd_Remove = 0x04,
AssociationCmd_GroupingsGet = 0x05,
AssociationCmd_GroupingsReport = 0x06
};
//-----------------------------------------------------------------------------
// <Association::Association>
// Constructor
//-----------------------------------------------------------------------------
Association::Association
(
uint32 const _homeId,
uint8 const _nodeId
):
CommandClass( _homeId, _nodeId ),
m_queryAll(false),
m_numGroups(0)
{
SetStaticRequest( StaticRequest_Values );
}
//-----------------------------------------------------------------------------
// <Association::ReadXML>
// Read the saved association data
//-----------------------------------------------------------------------------
void Association::ReadXML
(
TiXmlElement const* _ccElement
)
{
CommandClass::ReadXML( _ccElement );
TiXmlElement const* associationsElement = _ccElement->FirstChildElement();
while( associationsElement )
{
char const* str = associationsElement->Value();
if( str && !strcmp( str, "Associations" ) )
{
int intVal;
if( TIXML_SUCCESS == associationsElement->QueryIntAttribute( "num_groups", &intVal ) )
{
m_numGroups = (uint8)intVal;
}
TiXmlElement const* groupElement = associationsElement->FirstChildElement();
while( groupElement )
{
if( Node* node = GetNodeUnsafe() )
{
Group* group = new Group( GetHomeId(), GetNodeId(), groupElement );
node->AddGroup( group );
}
groupElement = groupElement->NextSiblingElement();
}
break;
}
associationsElement = associationsElement->NextSiblingElement();
}
}
//-----------------------------------------------------------------------------
// <Association::WriteXML>
// Save the association data
//-----------------------------------------------------------------------------
void Association::WriteXML
(
TiXmlElement* _ccElement
)
{
CommandClass::WriteXML( _ccElement );
if( Node* node = GetNodeUnsafe() )
{
TiXmlElement* associationsElement = new TiXmlElement( "Associations" );
char str[8];
snprintf( str, 8, "%d", m_numGroups );
associationsElement->SetAttribute( "num_groups", str );
_ccElement->LinkEndChild( associationsElement );
node->WriteGroups( associationsElement );
}
}
//-----------------------------------------------------------------------------
// <Association::RequestState>
// Nothing to do for Association
//-----------------------------------------------------------------------------
bool Association::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) )
{
// Request the supported group info
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <Association::RequestValue>
// Nothing to do for Association
//-----------------------------------------------------------------------------
bool Association::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _instance != 1 )
{
// This command class doesn't work with multiple instances
return false;
}
// Request the supported group info
Msg* msg = new Msg( "Get Association Groupings", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( AssociationCmd_GroupingsGet );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
}
//-----------------------------------------------------------------------------
// <Association::RequestAllGroups>
// Request the contents of each group in turn
//-----------------------------------------------------------------------------
void Association::RequestAllGroups
(
uint32 const _requestFlags
)
{
m_queryAll = true;
// Request the contents of the individual groups in turn.
if( m_numGroups == 0xff )
{
// We start with group 255, and will then move to group 1, 2 etc and stop when we find a group with a maxAssociations of zero.
Log::Write( LogLevel_Info, GetNodeId(), "Number of association groups reported for node %d is 255, which requires special case handling.", GetNodeId() );
QueryGroup( 0xff, _requestFlags );
}
else
{
// We start with group 1, and will then move to group 2, 3 etc and stop when the group index is greater than m_numGroups.
Log::Write( LogLevel_Info, GetNodeId(), "Number of association groups reported for node %d is %d.", GetNodeId(), m_numGroups );
QueryGroup( 1, _requestFlags );
}
}
//-----------------------------------------------------------------------------
// <Association::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool Association::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
bool handled = false;
uint32 i;
if( Node* node = GetNodeUnsafe() )
{
if( AssociationCmd_GroupingsReport == (AssociationCmd)_data[0] )
{
// Retrieve the number of groups this device supports.
// The groups will be queried with the session data.
m_numGroups = _data[1];
Log::Write( LogLevel_Info, GetNodeId(), "Received Association Groupings report from node %d. Number of groups is %d", GetNodeId(), m_numGroups );
ClearStaticRequest( StaticRequest_Values );
handled = true;
}
else if( AssociationCmd_Report == (AssociationCmd)_data[0] )
{
// Get the group info
uint8 groupIdx = _data[1];
uint8 maxAssociations = _data[2]; // If the maxAssociations is zero, this is not a supported group.
uint8 numReportsToFollow = _data[3]; // If a device supports a lot of associations, they may come in more than one message.
if( maxAssociations )
{
if( _length >= 5 )
{
uint8 numAssociations = _length - 5;
Log::Write( LogLevel_Info, GetNodeId(), "Received Association report from node %d, group %d, containing %d associations", GetNodeId(), groupIdx, numAssociations );
if( numAssociations )
{
Log::Write( LogLevel_Info, GetNodeId(), " The group contains:" );
for( i=0; i<numAssociations; ++i )
{
Log::Write( LogLevel_Info, GetNodeId(), " Node %d", _data[i+4] );
m_pendingMembers.push_back( _data[i+4] );
}
}
}
if( numReportsToFollow )
{
// We're expecting more reports for this group
Log::Write( LogLevel_Info, GetNodeId(), "%d more association reports expected for node %d, group %d", numReportsToFollow, GetNodeId(), groupIdx );
return true;
}
else
{
// No more reports to come for this group, so we can apply the pending list
Group* group = node->GetGroup( groupIdx );
if( NULL == group )
{
// Group has not been created yet
group = new Group( GetHomeId(), GetNodeId(), groupIdx, maxAssociations );
node->AddGroup( group );
}
// Update the group with its new contents
group->OnGroupChanged( m_pendingMembers );
m_pendingMembers.clear();
}
}
else
{
// maxAssociations is zero, so we've reached the end of the query process
Log::Write( LogLevel_Info, GetNodeId(), "Max associations for node %d, group %d is zero. Querying associations for this node is complete.", GetNodeId(), groupIdx );
node->AutoAssociate();
m_queryAll = false;
}
if( m_queryAll )
{
// Work out which is the next group we will query.
// If we are currently on group 255, the next group will be 1.
uint8 nextGroup = groupIdx + 1;
if( !nextGroup )
{
nextGroup = 1;
}
if( nextGroup <= m_numGroups )
{
// Query the next group
QueryGroup( nextGroup, 0 );
}
else
{
// We're all done
Log::Write( LogLevel_Info, GetNodeId(), "Querying associations for node %d is complete.", GetNodeId() );
node->AutoAssociate();
m_queryAll = false;
}
}
handled = true;
}
}
return handled;
}
//-----------------------------------------------------------------------------
// <Association::QueryGroup>
// Request details of an association group
//-----------------------------------------------------------------------------
void Association::QueryGroup
(
uint8 _groupIdx,
uint32 const _requestFlags
)
{
if ( IsGetSupported() )
{
Log::Write( LogLevel_Info, GetNodeId(), "Get Associations for group %d of node %d", _groupIdx, GetNodeId() );
Msg* msg = new Msg( "Get Associations", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( AssociationCmd_Get );
msg->Append( _groupIdx );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "AssociationCmd_Get Not Supported on this node");
}
return;
}
//-----------------------------------------------------------------------------
// <Association::Set>
// Add an association between devices
//-----------------------------------------------------------------------------
void Association::Set
(
uint8 _groupIdx,
uint8 _targetNodeId
)
{
Log::Write( LogLevel_Info, GetNodeId(), "Association::Set - Adding node %d to group %d of node %d", _targetNodeId, _groupIdx, GetNodeId() );
Msg* msg = new Msg( "Association Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->Append( GetNodeId() );
msg->Append( 4 );
msg->Append( GetCommandClassId() );
msg->Append( AssociationCmd_Set );
msg->Append( _groupIdx );
msg->Append( _targetNodeId );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
}
//-----------------------------------------------------------------------------
// <Association::Remove>
// Remove an association between devices
//-----------------------------------------------------------------------------
void Association::Remove
(
uint8 _groupIdx,
uint8 _targetNodeId
)
{
Log::Write( LogLevel_Info, GetNodeId(), "Association::Remove - Removing node %d from group %d of node %d", _targetNodeId, _groupIdx, GetNodeId() );
Msg* msg = new Msg( "Association Remove", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->Append( GetNodeId() );
msg->Append( 4 );
msg->Append( GetCommandClassId() );
msg->Append( AssociationCmd_Remove );
msg->Append( _groupIdx );
msg->Append( _targetNodeId );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
}
@@ -0,0 +1,75 @@
//-----------------------------------------------------------------------------
//
// Association.h
//
// Implementation of the Z-Wave COMMAND_CLASS_ASSOCIATION
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _Association_H
#define _Association_H
#include <vector>
#include "CommandClass.h"
namespace OpenZWave
{
/** \brief Implements COMMAND_CLASS_ASSOCIATION (0x85), a Z-Wave device command class.
*/
class Association: public CommandClass
{
friend class Group;
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Association( _homeId, _nodeId ); }
virtual ~Association(){}
static uint8 const StaticGetCommandClassId(){ return 0x85; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_ASSOCIATION"; }
// From CommandClass
virtual void ReadXML( TiXmlElement const* _ccElement );
virtual void WriteXML( TiXmlElement* _ccElement );
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
void RequestAllGroups( uint32 const _requestFlags );
void Set( uint8 const _group, uint8 const _nodeId );
void Remove( uint8 const _group, uint8 const _nodeId );
private:
Association( uint32 const _homeId, uint8 const _nodeId );
void QueryGroup( uint8 _groupIdx, uint32 const _requestFlags );
void AutoAssociate();
bool m_queryAll; // When true, once a group has been queried, we request the next one.
uint8 m_numGroups; // Number of groups supported by the device. 255 is reported by certain manufacturers and requires special handling.
vector<uint8> m_pendingMembers; // Used to build a list of group members from multiple reports
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,281 @@
//-----------------------------------------------------------------------------
//
// AssociationCommandConfiguration.cpp
//
// Implementation of the COMMAND_CLASS_ASSOCIATION_COMMAND_CONFIGURATION
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "AssociationCommandConfiguration.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Group.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueBool.h"
#include "../value_classes/ValueByte.h"
#include "../value_classes/ValueShort.h"
using namespace OpenZWave;
enum AssociationCommandConfigurationCmd
{
AssociationCommandConfigurationCmd_SupportedRecordsGet = 0x01,
AssociationCommandConfigurationCmd_SupportedRecordsReport = 0x02,
AssociationCommandConfigurationCmd_Set = 0x03,
AssociationCommandConfigurationCmd_Get = 0x04,
AssociationCommandConfigurationCmd_Report = 0x05
};
enum
{
AssociationCommandConfigurationIndex_MaxCommandLength = 0,
AssociationCommandConfigurationIndex_CommandsAreValues,
AssociationCommandConfigurationIndex_CommandsAreConfigurable,
AssociationCommandConfigurationIndex_NumFreeCommands,
AssociationCommandConfigurationIndex_MaxCommands
};
//-----------------------------------------------------------------------------
// <AssociationCommandConfiguration::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool AssociationCommandConfiguration::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _requestFlags & RequestFlag_Session )
{
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <AssociationCommandConfiguration::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool AssociationCommandConfiguration::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _instance != 1 )
{
// This command class doesn't work with multiple instances
return false;
}
Msg* msg = new Msg( "AssociationCommandConfigurationCmd_SupportedRecordsGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( AssociationCommandConfigurationCmd_SupportedRecordsGet );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
}
//-----------------------------------------------------------------------------
// <AssociationCommandConfiguration::RequestCommands>
// Request the command data
//-----------------------------------------------------------------------------
void AssociationCommandConfiguration::RequestCommands
(
uint8 const _groupIdx,
uint8 const _nodeId
)
{
if ( IsGetSupported() )
{
Msg* msg = new Msg( "AssociationCommandConfigurationCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 4 );
msg->Append( GetCommandClassId() );
msg->Append( AssociationCommandConfigurationCmd_Get );
msg->Append( _groupIdx );
msg->Append( _nodeId );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
} else {
Log::Write( LogLevel_Info, GetNodeId(), "AssociationCommandConfigurationCmd_Get Not Supported on this node");
}
}
//-----------------------------------------------------------------------------
// <AssociationCommandConfiguration::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool AssociationCommandConfiguration::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if (AssociationCommandConfigurationCmd_SupportedRecordsReport == (AssociationCommandConfigurationCmd)_data[0])
{
uint8 maxCommandLength = _data[1] >> 2;
bool commandsAreValues = ( (_data[1] & 0x02) != 0 );
bool commandsAreConfigurable = ( (_data[1] & 0x01) != 0 );
int16 numFreeCommands = (((int16)_data[2])<<16) | (int16)_data[3];
int16 maxCommands = (((int16)_data[4])<<16) | (int16)_data[5];
Log::Write( LogLevel_Info, GetNodeId(), "Received AssociationCommandConfiguration Supported Records Report:" );
Log::Write( LogLevel_Info, GetNodeId(), " Maximum command length = %d bytes", maxCommandLength );
Log::Write( LogLevel_Info, GetNodeId(), " Maximum number of commands = %d", maxCommands );
Log::Write( LogLevel_Info, GetNodeId(), " Number of free commands = %d", numFreeCommands );
Log::Write( LogLevel_Info, GetNodeId(), " Commands are %s and are %s", commandsAreValues ? "values" : "not values", commandsAreConfigurable ? "configurable" : "not configurable" );
ValueBool* valueBool;
ValueByte* valueByte;
ValueShort* valueShort;
if( (valueByte = static_cast<ValueByte*>( GetValue( _instance, AssociationCommandConfigurationIndex_MaxCommandLength ) )) )
{
valueByte->OnValueRefreshed( maxCommandLength );
valueByte->Release();
}
if( (valueBool = static_cast<ValueBool*>( GetValue( _instance, AssociationCommandConfigurationIndex_CommandsAreValues ) )) )
{
valueBool->OnValueRefreshed( commandsAreValues );
valueBool->Release();
}
if( (valueBool = static_cast<ValueBool*>( GetValue( _instance, AssociationCommandConfigurationIndex_CommandsAreConfigurable ) )) )
{
valueBool->OnValueRefreshed( commandsAreConfigurable );
valueBool->Release();
}
if( (valueShort = static_cast<ValueShort*>( GetValue( _instance, AssociationCommandConfigurationIndex_NumFreeCommands ) )) )
{
valueShort->OnValueRefreshed( numFreeCommands );
valueShort->Release();
}
if( (valueShort = static_cast<ValueShort*>( GetValue( _instance, AssociationCommandConfigurationIndex_MaxCommands ) )) )
{
valueShort->OnValueRefreshed( maxCommands );
valueShort->Release();
}
return true;
}
if (AssociationCommandConfigurationCmd_Report == (AssociationCommandConfigurationCmd)_data[0])
{
uint8 groupIdx = _data[1];
uint8 nodeIdx = _data[2];
bool firstReports = ( ( _data[3] & 0x80 ) != 0 ); // True if this is the first message containing commands for this group and node.
uint8 numReports = _data[3] & 0x0f;
Log::Write( LogLevel_Info, GetNodeId(), "Received AssociationCommandConfiguration Report from:" );
Log::Write( LogLevel_Info, GetNodeId(), " Commands for node %d in group %d,", nodeIdx, groupIdx );
if( Node* node = GetNodeUnsafe() )
{
Group* group = node->GetGroup( groupIdx );
if( NULL == group )
{
if( firstReports )
{
// This is the first report message, so we should clear any existing command data
group->ClearCommands( nodeIdx );
}
uint8 const* start = &_data[4];
for( uint8 i=0; i<numReports; ++i )
{
uint8 length = start[0];
group->AddCommand( nodeIdx, length, start+1 );
start += length;
}
}
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <AssociationCommandConfiguration::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void AssociationCommandConfiguration::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueByte ( ValueID::ValueGenre_System, GetCommandClassId(), _instance, AssociationCommandConfigurationIndex_MaxCommandLength, "Max Command Length", "", true, false, 0, 0 );
node->CreateValueBool ( ValueID::ValueGenre_System, GetCommandClassId(), _instance, AssociationCommandConfigurationIndex_CommandsAreValues, "Commands are Values", "", true, false, false, 0 );
node->CreateValueBool ( ValueID::ValueGenre_System, GetCommandClassId(), _instance, AssociationCommandConfigurationIndex_CommandsAreConfigurable, "Commands are Configurable", "", true, false, false, 0 );
node->CreateValueShort( ValueID::ValueGenre_System, GetCommandClassId(), _instance, AssociationCommandConfigurationIndex_NumFreeCommands, "Free Commands", "", true, false, 0, 0 );
node->CreateValueShort( ValueID::ValueGenre_System, GetCommandClassId(), _instance, AssociationCommandConfigurationIndex_MaxCommands, "Max Commands", "", true, false, 0, 0 );
}
}
//-----------------------------------------------------------------------------
// <AssociationCommandConfiguration::SetCommand>
// Set a command for the association
//-----------------------------------------------------------------------------
void AssociationCommandConfiguration::SetCommand
(
uint8 const _groupIdx,
uint8 const _nodeId,
uint8 const _length,
uint8 const* _data
)
{
Msg* msg = new Msg( "AssociationCommandConfigurationCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( _length + 5 );
msg->Append( GetCommandClassId() );
msg->Append( AssociationCommandConfigurationCmd_Set );
msg->Append( _groupIdx );
msg->Append( _nodeId );
msg->Append( _length );
for( uint8 i=0; i<_length; ++i )
{
msg->Append( _data[i] );
}
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
}
@@ -0,0 +1,70 @@
//-----------------------------------------------------------------------------
//
// AssociationCommandConfiguration.h
//
// Implementation of the COMMAND_CLASS_ASSOCIATION_COMMAND_CONFIGURATION
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _AssociationCommandConfiguration_H
#define _AssociationCommandConfiguration_H
#include "CommandClass.h"
#include "../value_classes/ValueBool.h"
#include "../value_classes/ValueByte.h"
#include "../value_classes/ValueShort.h"
namespace OpenZWave
{
/** \brief Implements COMMAND_CLASS_ASSOCIATION_COMMAND_CONFIGURATION (0x9b), a Z-Wave device command class.
*/
class AssociationCommandConfiguration: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new AssociationCommandConfiguration( _homeId, _nodeId ); }
virtual ~AssociationCommandConfiguration(){}
static uint8 const StaticGetCommandClassId(){ return 0x9b; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_ASSOCIATION_COMMAND_CONFIGURATION"; }
void RequestCommands( uint8 const _groupIdx, uint8 const _nodeId );
void SetCommand( uint8 const _groupIdx, uint8 const _nodeId, uint8 const _length, uint8 const* _data );
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
protected:
virtual void CreateVars( uint8 const _instance );
private:
AssociationCommandConfiguration( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,345 @@
//-----------------------------------------------------------------------------
//
// Basic.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_BASIC
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "Basic.h"
#include "Association.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../Notification.h"
#include "../platform/Log.h"
#include "../value_classes/ValueByte.h"
#include "NoOperation.h"
#include "../tinyxml.h"
using namespace OpenZWave;
enum BasicCmd
{
BasicCmd_Set = 0x01,
BasicCmd_Get = 0x02,
BasicCmd_Report = 0x03
};
//-----------------------------------------------------------------------------
// <Basic::Basic>
// Constructor
//-----------------------------------------------------------------------------
Basic::Basic
(
uint32 const _homeId,
uint8 const _nodeId
):
CommandClass( _homeId, _nodeId ),
m_mapping( 0 ),
m_ignoreMapping( false ),
m_setAsReport( false )
{
}
//-----------------------------------------------------------------------------
// <Basic::ReadXML>
// Read configuration.
//-----------------------------------------------------------------------------
void Basic::ReadXML
(
TiXmlElement const* _ccElement
)
{
CommandClass::ReadXML( _ccElement );
char const* str = _ccElement->Attribute("ignoremapping");
if( str )
{
m_ignoreMapping = !strcmp( str, "true");
}
int32 intVal;
if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "mapping", &intVal ) )
{
if( intVal < 256 && intVal != 0 )
{
SetMapping( (uint8)intVal, false );
}
}
str = _ccElement->Attribute("setasreport");
if( str )
{
m_setAsReport = !strcmp( str, "true");
}
}
//-----------------------------------------------------------------------------
// <Basic::WriteXML>
// Save changed configuration
//-----------------------------------------------------------------------------
void Basic::WriteXML
(
TiXmlElement* _ccElement
)
{
CommandClass::WriteXML( _ccElement );
if( m_ignoreMapping )
{
_ccElement->SetAttribute( "ignoremapping", "true" );
}
char str[32];
if( m_mapping != 0 )
{
snprintf( str, sizeof(str), "%d", m_mapping );
_ccElement->SetAttribute( "mapping", str );
}
if( m_setAsReport )
{
_ccElement->SetAttribute( "setasreport", "true" );
}
}
//-----------------------------------------------------------------------------
// <Basic::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool Basic::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _requestFlags & RequestFlag_Dynamic )
{
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <Basic::RequestValue>
// Request current state from the device
//-----------------------------------------------------------------------------
bool Basic::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if ( IsGetSupported() )
{
Msg* msg = new Msg( "BasicCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( BasicCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "BasicCmd_Get Not Supported on this node");
}
return false;
}
//-----------------------------------------------------------------------------
// <Basic::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool Basic::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( BasicCmd_Report == (BasicCmd)_data[0] )
{
// Level
Log::Write( LogLevel_Info, GetNodeId(), "Received Basic report from node %d: level=%d", GetNodeId(), _data[1] );
if( !m_ignoreMapping && m_mapping != 0 )
{
UpdateMappedClass( _instance, m_mapping, _data[1] );
}
else if( ValueByte* value = static_cast<ValueByte*>( GetValue( _instance, 0 ) ) )
{
value->OnValueRefreshed( _data[1] );
value->Release();
}
return true;
}
if( BasicCmd_Set == (BasicCmd)_data[0] )
{
if( m_setAsReport )
{
Log::Write( LogLevel_Info, GetNodeId(), "Received Basic set from node %d: level=%d. Treating it as a Basic report.", GetNodeId(), _data[1] );
if( !m_ignoreMapping && m_mapping != 0 )
{
UpdateMappedClass( _instance, m_mapping, _data[1] );
}
else if( ValueByte* value = static_cast<ValueByte*>( GetValue( _instance, 0 ) ) )
{
value->OnValueRefreshed( _data[1] );
value->Release();
}
}
else
{
// Commmand received from the node. Handle as a notification event
Log::Write( LogLevel_Info, GetNodeId(), "Received Basic set from node %d: level=%d. Sending event notification.", GetNodeId(), _data[1] );
Notification* notification = new Notification( Notification::Type_NodeEvent );
notification->SetHomeNodeIdAndInstance( GetHomeId(), GetNodeId(), _instance );
notification->SetEvent( _data[1] );
GetDriver()->QueueNotification( notification );
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <Basic::SetValue>
// Set a value on the Z-Wave device
//-----------------------------------------------------------------------------
bool Basic::SetValue
(
Value const& _value
)
{
if( ValueID::ValueType_Byte == _value.GetID().GetType() )
{
ValueByte const* value = static_cast<ValueByte const*>(&_value);
Log::Write( LogLevel_Info, GetNodeId(), "Basic::Set - Setting node %d to level %d", GetNodeId(), value->GetValue() );
Msg* msg = new Msg( "Basic Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->SetInstance( this, _value.GetID().GetInstance() );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( BasicCmd_Set );
msg->Append( value->GetValue() );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <Basic::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void Basic::CreateVars
(
uint8 const _instance
)
{
if( m_mapping == 0 )
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueByte( ValueID::ValueGenre_Basic, GetCommandClassId(), _instance, 0, "Basic", "", false, false, 0, 0 );
}
}
}
//-----------------------------------------------------------------------------
// <Basic::Set>
// Helper method to set the level
//-----------------------------------------------------------------------------
void Basic::Set
(
uint8 const _level
)
{
// This may look like a long winded way to do this, but
// it ensures that all the proper notifications get sent.
if( ValueByte* value = static_cast<ValueByte*>( GetValue( 1, 0 ) ) )
{
value->Set( _level );
value->Release();
}
}
//-----------------------------------------------------------------------------
// <Basic::SetMapping>
// Map COMMAND_CLASS_BASIC messages to another command class
//-----------------------------------------------------------------------------
bool Basic::SetMapping
(
uint8 const _commandClassId,
bool const _doLog
)
{
bool res = false;
if( _commandClassId != NoOperation::StaticGetCommandClassId() )
{
if( _doLog )
{
char str[16];
snprintf( str, sizeof(str), "0x%02x", _commandClassId );
string ccstr = str;
if( Node const* node = GetNodeUnsafe() )
{
if( CommandClass* cc = node->GetCommandClass( _commandClassId ) )
{
ccstr = cc->GetCommandClassName();
}
}
if( m_ignoreMapping )
{
Log::Write( LogLevel_Info, GetNodeId(), " COMMAND_CLASS_BASIC will not be mapped to %s (ignored)", ccstr.c_str() );
}
else
{
Log::Write( LogLevel_Info, GetNodeId(), " COMMAND_CLASS_BASIC will be mapped to %s", ccstr.c_str() );
}
}
m_mapping = _commandClassId;
RemoveValue( 1, 0 );
res = true;
}
if( m_mapping == 0 && _doLog )
{
Log::Write( LogLevel_Info, GetNodeId(), " COMMAND_CLASS_BASIC is not mapped" );
}
return res;
}
@@ -0,0 +1,77 @@
//-----------------------------------------------------------------------------
//
// Basic.h
//
// Implementation of the Z-Wave COMMAND_CLASS_BASIC
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _Basic_H
#define _Basic_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueByte;
/** \brief Implements COMMAND_CLASS_BASIC (0x20), a Z-Wave device command class.
*/
class Basic: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Basic( _homeId, _nodeId ); }
virtual ~Basic(){}
static uint8 const StaticGetCommandClassId(){ return 0x20; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_BASIC"; }
bool SetMapping( uint8 const _commandClassId, bool const _doLog = true ); // Map COMMAND_CLASS_BASIC messages to another command class
uint8 GetMapping(){ return m_mapping; }
// From CommandClass
virtual void ReadXML( TiXmlElement const* _ccElement );
virtual void WriteXML( TiXmlElement* _ccElement );
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
void Set( uint8 const _level );
protected:
virtual void CreateVars( uint8 const _instance );
private:
Basic( uint32 const _homeId, uint8 const _nodeId );
uint8 m_mapping;
bool m_ignoreMapping;
bool m_setAsReport;
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,118 @@
//-----------------------------------------------------------------------------
//
// BasicWindowCovering.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_BASIC_WINDOW_COVERING
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "BasicWindowCovering.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Driver.h"
#include "../Node.h"
#include "../platform/Log.h"
#include "../value_classes/ValueButton.h"
using namespace OpenZWave;
enum BasicWindowCoveringCmd
{
BasicWindowCoveringCmd_StartLevelChange = 0x01,
BasicWindowCoveringCmd_StopLevelChange = 0x02
};
enum
{
BasicWindowCoveringIndex_Open = 0,
BasicWindowCoveringIndex_Close
};
//-----------------------------------------------------------------------------
// <BasicWindowCovering::SetValue>
// Set a value on the Z-Wave device
//-----------------------------------------------------------------------------
bool BasicWindowCovering::SetValue
(
Value const& _value
)
{
if( ValueID::ValueType_Button == _value.GetID().GetType() )
{
ValueButton const* button = static_cast<ValueButton const*>(&_value);
uint8 action = 0x40;
if( button->GetID().GetIndex() ) // Open is index zero, so non-zero is close.
{
// Close
action = 0;
}
if( button && button->IsPressed() )
{
Log::Write( LogLevel_Info, GetNodeId(), "BasicWindowCovering - Start Level Change (%s)", action ? "Open" : "Close" );
Msg* msg = new Msg( "Basic Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->SetInstance( this, _value.GetID().GetInstance() );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( BasicWindowCoveringCmd_StartLevelChange );
msg->Append( action );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
else
{
Log::Write( LogLevel_Info, GetNodeId(), "BasicWindowCovering - Stop Level Change" );
Msg* msg = new Msg( "Basic Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->SetInstance( this, _value.GetID().GetInstance() );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( BasicWindowCoveringCmd_StopLevelChange );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
// <BasicWindowCovering::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void BasicWindowCovering::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueButton( ValueID::ValueGenre_User, GetCommandClassId(), _instance, BasicWindowCoveringIndex_Open, "Open", 0 );
node->CreateValueButton( ValueID::ValueGenre_User, GetCommandClassId(), _instance, BasicWindowCoveringIndex_Close, "Close", 0 );
}
}
@@ -0,0 +1,64 @@
//-----------------------------------------------------------------------------
//
// BasicWindowCovering.h
//
// Implementation of the Z-Wave COMMAND_CLASS_BASIC_WINDOW_COVERING
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _BasicWindowCovering_H
#define _BasicWindowCovering_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueButton;
/** \brief Implements COMMAND_CLASS_BASIC_WINDOW_COVERING (0x50), a Z-Wave device command class.
*/
class BasicWindowCovering: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new BasicWindowCovering( _homeId, _nodeId ); }
virtual ~BasicWindowCovering(){}
static uint8 const StaticGetCommandClassId(){ return 0x50; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_BASIC_WINDOW_COVERING"; }
// From CommandClass
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ){ return false; }
virtual bool SetValue( Value const& _value );
protected:
virtual void CreateVars( uint8 const _instance );
private:
BasicWindowCovering( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,146 @@
//-----------------------------------------------------------------------------
//
// Battery.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_BATTERY
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "Battery.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueByte.h"
using namespace OpenZWave;
enum BatteryCmd
{
BatteryCmd_Get = 0x02,
BatteryCmd_Report = 0x03
};
//-----------------------------------------------------------------------------
// <Battery::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool Battery::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _requestFlags & RequestFlag_Dynamic )
{
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <Battery::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool Battery::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _instance != 1 )
{
// This command class doesn't work with multiple instances
return false;
}
if ( IsGetSupported() )
{
Msg* msg = new Msg( "BatteryCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( BatteryCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "BatteryCmd_Get Not Supported on this node");
}
return false;
}
//-----------------------------------------------------------------------------
// <Battery::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool Battery::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if (BatteryCmd_Report == (BatteryCmd)_data[0])
{
// We have received a battery level report from the Z-Wave device.
// Devices send 0xff instead of zero for a low battery warning.
uint8 batteryLevel = _data[1];
if( batteryLevel == 0xff )
{
batteryLevel = 0;
}
Log::Write( LogLevel_Info, GetNodeId(), "Received Battery report from node %d: level=%d", GetNodeId(), batteryLevel );
if( ValueByte* value = static_cast<ValueByte*>( GetValue( _instance, 0 ) ) )
{
value->OnValueRefreshed( batteryLevel );
value->Release();
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <Battery::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void Battery::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Battery Level", "%", true, false, 100, 0 );
}
}
@@ -0,0 +1,65 @@
//-----------------------------------------------------------------------------
//
// Battery.h
//
// Implementation of the Z-Wave COMMAND_CLASS_BATTERY
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _Battery_H
#define _Battery_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueByte;
/** \brief Implements COMMAND_CLASS_BATTERY (0x80), a Z-Wave device command class.
*/
class Battery: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Battery( _homeId, _nodeId ); }
virtual ~Battery(){}
static uint8 const StaticGetCommandClassId(){ return 0x80; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_BATTERY"; }
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
protected:
virtual void CreateVars( uint8 const _instance );
private:
Battery( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,6 @@
project(openzwave_command_classes)
file(GLOB ${PROJECT_NAME}_sources "${PROJECT_SOURCE_DIR}/*.cpp")
file(GLOB ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/*.h")
set(${PROJECT_NAME}_files ${${PROJECT_NAME}_sources} ${${PROJECT_NAME}_headers} CACHE INTERNAL "")
@@ -0,0 +1,50 @@
//-----------------------------------------------------------------------------
//
// CRC16Encap.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_CRC_16_ENCAP
//
// Copyright (c) 2012 Greg Satz <satz@iranger.com>
//
// 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 "CommandClasses.h"
#include "CRC16Encap.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
using namespace OpenZWave;
//-----------------------------------------------------------------------------
// <Hail::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool CRC16Encap::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
return false;
}
@@ -0,0 +1,57 @@
//-----------------------------------------------------------------------------
//
// CRC16Encap.h
//
// Implementation of the Z-Wave COMMAND_CLASS_CRC_16_ENCAP
//
// Copyright (c) 2012 Greg Satz <satz@iranger.com>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _CRC16_ENCAP_H
#define _CRC16_ENCAP_H
#include "CommandClass.h"
namespace OpenZWave
{
/** \brief Implements COMMAND_CLASS_CRC_16_ENCAP (0x56), a Z-Wave device command class.
*/
class CRC16Encap: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new CRC16Encap( _homeId, _nodeId ); }
virtual ~CRC16Encap(){}
static uint8 const StaticGetCommandClassId(){ return 0x56; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_CRC_16_ENCAP"; }
// From CommandClass
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
private:
CRC16Encap( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,428 @@
//-----------------------------------------------------------------------------
//
// ClimateControlSchedule.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_CLIMATE_CONTROL_SCHEDULE
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "ClimateControlSchedule.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Driver.h"
#include "../Node.h"
#include "../platform/Log.h"
#include "../value_classes/ValueByte.h"
#include "../value_classes/ValueList.h"
#include "../value_classes/ValueSchedule.h"
#include "../tinyxml.h"
using namespace OpenZWave;
enum ClimateControlScheduleCmd
{
ClimateControlScheduleCmd_Set = 0x01,
ClimateControlScheduleCmd_Get,
ClimateControlScheduleCmd_Report,
ClimateControlScheduleCmd_ChangedGet,
ClimateControlScheduleCmd_ChangedReport,
ClimateControlScheduleCmd_OverrideSet,
ClimateControlScheduleCmd_OverrideGet,
ClimateControlScheduleCmd_OverrideReport
};
enum
{
ClimateControlScheduleIndex_OverrideState = 8,
ClimateControlScheduleIndex_OverrideSetback = 9
};
static char const* c_dayNames[] =
{
"Invalid",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday"
};
static char const* c_overrideStateNames[] =
{
"None",
"Temporary",
"Permanent",
"Invalid"
};
//-----------------------------------------------------------------------------
// <ClimateControlSchedule::ReadXML>
// Read the saved change-counter value
//-----------------------------------------------------------------------------
void ClimateControlSchedule::ReadXML
(
TiXmlElement const* _ccElement
)
{
CommandClass::ReadXML( _ccElement );
int intVal;
if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "change_counter", &intVal ) )
{
m_changeCounter = (uint8)intVal;
}
}
//-----------------------------------------------------------------------------
// <ClimateControlSchedule::WriteXML>
// Write the change-counter value
//-----------------------------------------------------------------------------
void ClimateControlSchedule::WriteXML
(
TiXmlElement* _ccElement
)
{
CommandClass::WriteXML( _ccElement );
char str[8];
snprintf( str, 8, "%d", m_changeCounter );
_ccElement->SetAttribute( "change_counter", str );
}
//-----------------------------------------------------------------------------
// <ClimateControlSchedule::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool ClimateControlSchedule::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _requestFlags & RequestFlag_Session )
{
// See if the schedule has changed since last time
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <ClimateControlSchedule::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool ClimateControlSchedule::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
// See if the schedule has changed since last time
Msg* msg = new Msg( "ClimateControlScheduleCmd_ChangedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( ClimateControlScheduleCmd_ChangedGet );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
}
//-----------------------------------------------------------------------------
// <ClimateControlSchedule::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool ClimateControlSchedule::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( ClimateControlScheduleCmd_Report == (ClimateControlScheduleCmd)_data[0] )
{
uint8 day = _data[1] & 0x07;
if (day > 7) /* size of c_dayNames */
{
Log::Write (LogLevel_Warning, GetNodeId(), "Day Value was greater than range. Setting to Invalid");
day = 0;
}
Log::Write( LogLevel_Info, GetNodeId(), "Received climate control schedule report for %s", c_dayNames[day] );
if( ValueSchedule* value = static_cast<ValueSchedule*>( GetValue( _instance, day ) ) )
{
// Remove any existing data
value->ClearSwitchPoints();
// Parse the switch point data
for( uint8 i=2; i<29; i+=3 )
{
uint8 setback = _data[i+2];
if( setback == 0x7f )
{
// Switch point is unused, so we stop parsing here
break;
}
uint8 hours = _data[i] & 0x1f;
uint8 minutes = _data[i+1] & 0x3f;
if( setback == 0x79 )
{
Log::Write( LogLevel_Info, GetNodeId(), " Switch point at %02d:%02d, Frost Protection Mode", hours, minutes, c_dayNames[day] );
}
else if( setback == 0x7a )
{
Log::Write( LogLevel_Info, GetNodeId(), " Switch point at %02d:%02d, Energy Saving Mode", hours, minutes, c_dayNames[day] );
}
else
{
Log::Write( LogLevel_Info, GetNodeId(), " Switch point at %02d:%02d, Setback %+.1fC", hours, minutes, ((float)setback)*0.1f );
}
value->SetSwitchPoint( hours, minutes, setback );
}
if( !value->GetNumSwitchPoints() )
{
Log::Write( LogLevel_Info, GetNodeId(), " No Switch points have been set" );
}
// Notify the user
value->OnValueRefreshed();
value->Release();
}
return true;
}
if( ClimateControlScheduleCmd_ChangedReport == (ClimateControlScheduleCmd)_data[0] )
{
Log::Write( LogLevel_Info, GetNodeId(), "Received climate control schedule changed report:" );
if( _data[1] )
{
if( _data[1] != m_changeCounter )
{
m_changeCounter = _data[1];
// The schedule has changed and is not in override mode, so request reports for each day
for( int i=1; i<=7; ++i )
{
char str[64];
snprintf( str, 64, "Get climate control schedule for %s", c_dayNames[i] );
Msg* msg = new Msg( str, GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( ClimateControlScheduleCmd_Get );
msg->Append( i );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
}
}
}
else
{
// Device is in override mode, so we request details of that instead
Msg* msg = new Msg( "Get climate control schedule override state", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( ClimateControlScheduleCmd_OverrideGet );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
}
return true;
}
if( ClimateControlScheduleCmd_OverrideReport == (ClimateControlScheduleCmd)_data[0] )
{
uint8 overrideState = _data[1] & 0x03;
if (overrideState > 3) /* size of c_overrideStateNames */
{
Log::Write (LogLevel_Warning, GetNodeId(), "overrideState Value was greater than range. Setting to Invalid");
overrideState = 3;
}
Log::Write( LogLevel_Info, GetNodeId(), "Received climate control schedule override report:" );
Log::Write( LogLevel_Info, GetNodeId(), " Override State: %s:", c_overrideStateNames[overrideState] );
if( ValueList* valueList = static_cast<ValueList*>( GetValue( _instance, ClimateControlScheduleIndex_OverrideState ) ) )
{
valueList->OnValueRefreshed( (int)overrideState );
valueList->Release();
}
uint8 setback = _data[2];
if( overrideState )
{
if( setback == 0x79 )
{
Log::Write( LogLevel_Info, GetNodeId(), " Override Setback: Frost Protection Mode" );
}
else if( setback == 0x7a )
{
Log::Write( LogLevel_Info, GetNodeId(), " Override Setback: Energy Saving Mode" );
}
else
{
Log::Write( LogLevel_Info, GetNodeId(), " Override Setback: %+.1fC", ((float)setback)*0.1f );
}
}
if( ValueByte* valueByte = static_cast<ValueByte*>( GetValue( _instance, ClimateControlScheduleIndex_OverrideSetback ) ) )
{
valueByte->OnValueRefreshed( setback );
valueByte->Release();
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <ClimateControlSchedule::SetValue>
// Set a value in the device
//-----------------------------------------------------------------------------
bool ClimateControlSchedule::SetValue
(
Value const& _value
)
{
// bool res = false;
uint8 instance = _value.GetID().GetInstance();
uint8 idx = _value.GetID().GetIndex();
if( idx < 8 )
{
// Set a schedule
ValueSchedule const* value = static_cast<ValueSchedule const*>(&_value);
char str[64];
snprintf( str, 64, "Set the climate control schedule for %s on node %d", c_dayNames[idx], GetNodeId() );
Msg* msg = new Msg( str, GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, instance );
msg->Append( GetNodeId() );
msg->Append( 30 );
msg->Append( GetCommandClassId() );
msg->Append( ClimateControlScheduleCmd_Set );
msg->Append( idx ); // Day of week
for( uint8 i=0; i<9; ++i )
{
uint8 hours;
uint8 minutes;
int8 setback;
if( value->GetSwitchPoint( i, &hours, &minutes, &setback ) )
{
msg->Append( hours );
msg->Append( minutes );
msg->Append( setback );
}
else
{
// Unused switch point
msg->Append( 0 );
msg->Append( 0 );
msg->Append( 0x7f );
}
}
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
}
else
{
// Set an override
ValueList* state = static_cast<ValueList*>( GetValue( instance, ClimateControlScheduleIndex_OverrideState ) );
ValueByte* setback = static_cast<ValueByte*>( GetValue( instance, ClimateControlScheduleIndex_OverrideSetback ) );
if( state && setback )
{
ValueList::Item const& item = state->GetItem();
Msg* msg = new Msg( "Set climate control schedule override state", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, instance );
msg->Append( GetNodeId() );
msg->Append( 4 );
msg->Append( GetCommandClassId() );
msg->Append( ClimateControlScheduleCmd_OverrideSet );
msg->Append( (uint8)item.m_value );
msg->Append( setback->GetValue() );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
}
}
return true;
}
//-----------------------------------------------------------------------------
// <ClimateControlSchedule::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void ClimateControlSchedule::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
// Add a ValueSchedule for each day of the week.
for( uint8 i=0; i<7; ++i )
{
node->CreateValueSchedule( ValueID::ValueGenre_User, GetCommandClassId(), _instance, i+1, c_dayNames[i+1], "", false, false, 0 );
}
// Add values for the override state and setback
vector<ValueList::Item> items;
ValueList::Item item;
for( uint8 i=0; i<3; ++i )
{
item.m_label = c_overrideStateNames[i];
item.m_value = i;
items.push_back( item );
}
node->CreateValueList( ValueID::ValueGenre_User, GetCommandClassId(), _instance, ClimateControlScheduleIndex_OverrideState, "Override State", "", false, false, 1, items, 0, 0 );
node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, ClimateControlScheduleIndex_OverrideSetback, "Override Setback", "", false, false, 0, 0 );
}
}
@@ -0,0 +1,71 @@
//-----------------------------------------------------------------------------
//
// ClimateControlSchedule.h
//
// Implementation of the Z-Wave COMMAND_CLASS_CLIMATE_CONTROL_SCHEDULE
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _ClimateControlSchedule_H
#define _ClimateControlSchedule_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueSchedule;
class ValueList;
class ValueByte;
/** \brief Implements COMMAND_CLASS_CLIMATE_CONTROL_SCHEDULE (0x46), a Z-Wave device command class.
*/
class ClimateControlSchedule: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ClimateControlSchedule( _homeId, _nodeId ); }
virtual ~ClimateControlSchedule(){}
static uint8 const StaticGetCommandClassId(){ return 0x46; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_CLIMATE_CONTROL_SCHEDULE"; }
// From CommandClass
virtual void ReadXML( TiXmlElement const* _ccElement );
virtual void WriteXML( TiXmlElement* _ccElement );
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
protected:
virtual void CreateVars( uint8 const _instance );
private:
ClimateControlSchedule( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ), m_changeCounter( 0 ){}
uint8 m_changeCounter;
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,237 @@
//-----------------------------------------------------------------------------
//
// Clock.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_CLOCK
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "Clock.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueByte.h"
#include "../value_classes/ValueList.h"
using namespace OpenZWave;
enum ClockCmd
{
ClockCmd_Set = 0x04,
ClockCmd_Get = 0x05,
ClockCmd_Report = 0x06
};
enum
{
ClockIndex_Day = 0,
ClockIndex_Hour,
ClockIndex_Minute
};
static char const* c_dayNames[] =
{
"Invalid",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday"
};
//-----------------------------------------------------------------------------
// <Clock::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool Clock::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _requestFlags & RequestFlag_Dynamic )
{
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <Clock::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool Clock::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if ( IsGetSupported() )
{
Msg* msg = new Msg( "ClockCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( ClockCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "ClockCmd_Get Not Supported on this node");
}
return false;
}
//-----------------------------------------------------------------------------
// <Clock::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool Clock::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if (ClockCmd_Report == (ClockCmd)_data[0])
{
uint8 day = _data[1] >> 5;
uint8 hour = _data[1] & 0x1f;
uint8 minute = _data[2];
if (day > 7) /* size of c_dayNames */
{
Log::Write (LogLevel_Warning, GetNodeId(), "Day Value was greater than range. Setting to Invalid");
day = 0;
}
Log::Write( LogLevel_Info, GetNodeId(), "Received Clock report: %s %.2d:%.2d", c_dayNames[day], hour, minute );
if( ValueList* dayValue = static_cast<ValueList*>( GetValue( _instance, ClockIndex_Day ) ) )
{
dayValue->OnValueRefreshed( day );
dayValue->Release();
}
if( ValueByte* hourValue = static_cast<ValueByte*>( GetValue( _instance, ClockIndex_Hour ) ) )
{
hourValue->OnValueRefreshed( hour );
hourValue->Release();
}
if( ValueByte* minuteValue = static_cast<ValueByte*>( GetValue( _instance, ClockIndex_Minute ) ) )
{
minuteValue->OnValueRefreshed( minute );
minuteValue->Release();
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <Clock::SetValue>
// Set a value in the Z-Wave device
//-----------------------------------------------------------------------------
bool Clock::SetValue
(
Value const& _value
)
{
bool ret = false;
uint8 instance = _value.GetID().GetInstance();
ValueList* dayValue = static_cast<ValueList*>( GetValue( instance, ClockIndex_Day ) );
ValueByte* hourValue = static_cast<ValueByte*>( GetValue( instance, ClockIndex_Hour ) );
ValueByte* minuteValue = static_cast<ValueByte*>( GetValue( instance, ClockIndex_Minute ) );
if( dayValue && hourValue && minuteValue )
{
uint8 day = dayValue->GetItem().m_value;
uint8 hour = hourValue->GetValue();
uint8 minute = minuteValue->GetValue();
Msg* msg = new Msg( "ClockCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->SetInstance( this, instance );
msg->Append( GetNodeId() );
msg->Append( 4 );
msg->Append( GetCommandClassId() );
msg->Append( ClockCmd_Set );
msg->Append( ( day << 5 ) | hour );
msg->Append( minute );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
ret = true;
}
if( dayValue != NULL )
{
dayValue->Release();
}
if( hourValue != NULL )
{
hourValue->Release();
}
if( minuteValue != NULL )
{
minuteValue->Release();
}
return ret;
}
//-----------------------------------------------------------------------------
// <Clock::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void Clock::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
vector<ValueList::Item> items;
for( int i=1; i<=7; ++i )
{
ValueList::Item item;
item.m_label = c_dayNames[i];
item.m_value = i;
items.push_back( item );
}
node->CreateValueList( ValueID::ValueGenre_User, GetCommandClassId(), _instance, ClockIndex_Day, "Day", "", false, false, 1, items, 0, 0 );
node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, ClockIndex_Hour, "Hour", "", false, false, 12, 0 );
node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, ClockIndex_Minute, "Minute", "", false, false, 0, 0 );
}
}
@@ -0,0 +1,67 @@
//-----------------------------------------------------------------------------
//
// Clock.h
//
// Implementation of the Z-Wave COMMAND_CLASS_CLOCK
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _Clock_H
#define _Clock_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueByte;
class ValueList;
/** \brief Implements COMMAND_CLASS_CLOCK (0x81), a Z-Wave device command class.
*/
class Clock: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Clock( _homeId, _nodeId ); }
virtual ~Clock(){}
static uint8 const StaticGetCommandClassId(){ return 0x81; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_CLOCK"; }
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
protected:
virtual void CreateVars( uint8 const _instance );
private:
Clock( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,805 @@
//-----------------------------------------------------------------------------
//
// CommandClass.cpp
//
// Base class for all Z-Wave Command Classes
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 <math.h>
#include <locale.h>
#include "../tinyxml.h"
#include "CommandClass.h"
#include "Basic.h"
#include "MultiInstance.h"
#include "CommandClasses.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../Manager.h"
#include "../platform/Log.h"
#include "../value_classes/ValueStore.h"
using namespace OpenZWave;
static uint8 const c_sizeMask = 0x07;
static uint8 const c_scaleMask = 0x18;
static uint8 const c_scaleShift = 0x03;
static uint8 const c_precisionMask = 0xe0;
static uint8 const c_precisionShift = 0x05;
//-----------------------------------------------------------------------------
// <CommandClass::CommandClass>
// Constructor
//-----------------------------------------------------------------------------
CommandClass::CommandClass
(
uint32 const _homeId,
uint8 const _nodeId
):
m_homeId( _homeId ),
m_nodeId( _nodeId ),
m_version( 1 ),
m_afterMark( false ),
m_createVars( true ),
m_overridePrecision( -1 ),
m_getSupported( true ),
m_isSecured( false ),
m_SecureSupport( true ),
m_staticRequests( 0 ),
m_sentCnt( 0 ),
m_receivedCnt( 0 )
{
}
//-----------------------------------------------------------------------------
// <CommandClass::~CommandClass>
// Destructor
//-----------------------------------------------------------------------------
CommandClass::~CommandClass
(
)
{
while( !m_endPointMap.empty() )
{
map<uint8,uint8>::iterator it = m_endPointMap.begin();
m_endPointMap.erase( it );
}
while ( !m_RefreshClassValues.empty() )
{
for (unsigned int i = 0; i < m_RefreshClassValues.size(); i++)
{
RefreshValue *rcc = m_RefreshClassValues.at(i);
while(!rcc->RefreshClasses.empty()) {
delete rcc->RefreshClasses.back();
rcc->RefreshClasses.pop_back();
}
// for (unsigned int j = 0; j < rcc->RefreshClasses.size(); i++)
// {
// delete rcc->RefreshClasses[j];
// }
rcc->RefreshClasses.clear();
delete rcc;
}
m_RefreshClassValues.clear();
}
}
//-----------------------------------------------------------------------------
// <CommandClass::GetDriver>
// Get a pointer to our driver
//-----------------------------------------------------------------------------
Driver* CommandClass::GetDriver
(
)const
{
return( Manager::Get()->GetDriver( m_homeId ) );
}
//-----------------------------------------------------------------------------
// <CommandClass::GetNode>
// Get a pointer to our node without locking the mutex
//-----------------------------------------------------------------------------
Node* CommandClass::GetNodeUnsafe
(
)const
{
return( GetDriver()->GetNodeUnsafe( m_nodeId ) );
}
//-----------------------------------------------------------------------------
// <CommandClass::GetValue>
// Get a pointer to a value by its instance and index
//-----------------------------------------------------------------------------
Value* CommandClass::GetValue
(
uint8 const _instance,
uint8 const _index
)
{
Value* value = NULL;
if( Node* node = GetNodeUnsafe() )
{
value = node->GetValue( GetCommandClassId(), _instance, _index );
}
return value;
}
//-----------------------------------------------------------------------------
// <CommandClass::RemoveValue>
// Remove a value by its instance and index
//-----------------------------------------------------------------------------
bool CommandClass::RemoveValue
(
uint8 const _instance,
uint8 const _index
)
{
if( Node* node = GetNodeUnsafe() )
{
return node->RemoveValue( GetCommandClassId(), _instance, _index );
}
return false;
}
//-----------------------------------------------------------------------------
// <CommandClass::SetInstances>
// Instances as set by the MultiInstance V1 command class
//-----------------------------------------------------------------------------
void CommandClass::SetInstances
(
uint8 const _instances
)
{
// Ensure we have a set of reported variables for each new instance
if( !m_afterMark )
{
for( uint8 i=0; i<_instances; ++i )
{
SetInstance( i+1 );
}
}
}
//-----------------------------------------------------------------------------
// <CommandClass::SetInstance>
// Instances as set by the MultiChannel (i.e. MultiInstance V2) command class
//-----------------------------------------------------------------------------
void CommandClass::SetInstance
(
uint8 const _endPoint
)
{
if( !m_instances.IsSet( _endPoint ) )
{
m_instances.Set( _endPoint );
if( IsCreateVars() )
{
CreateVars( _endPoint );
}
}
}
//-----------------------------------------------------------------------------
// <CommandClass::ReadXML>
// Read the saved command class data
//-----------------------------------------------------------------------------
void CommandClass::ReadXML
(
TiXmlElement const* _ccElement
)
{
int32 intVal;
char const* str;
if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "version", &intVal ) )
{
m_version = (uint8)intVal;
}
uint8 instances = 1;
if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "instances", &intVal ) )
{
instances = (uint8)intVal;
}
if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "request_flags", &intVal ) )
{
m_staticRequests = (uint8)intVal;
}
if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "override_precision", &intVal ) )
{
m_overridePrecision = (int8)intVal;
}
str = _ccElement->Attribute( "after_mark" );
if( str )
{
m_afterMark = !strcmp( str, "true" );
}
str = _ccElement->Attribute( "create_vars" );
if( str )
{
m_createVars = !strcmp( str, "true" );
}
// Make sure previously created values are removed if create_vars=false
if( !m_createVars )
{
if( Node* node = GetNodeUnsafe() )
{
node->GetValueStore()->RemoveCommandClassValues( GetCommandClassId() );
}
}
str = _ccElement->Attribute( "getsupported" );
if( str )
{
m_getSupported = !strcmp( str, "true" );
}
str = _ccElement->Attribute( "issecured" );
if( str )
{
m_isSecured = !strcmp( str, "true" );
}
// Setting the instance count will create all the values.
SetInstances( instances );
// Apply any differences from the saved XML to the values
TiXmlElement const* child = _ccElement->FirstChildElement();
while( child )
{
str = child->Value();
if( str )
{
if( !strcmp( str, "Instance" ) )
{
uint8 instance = 0;
// Add an instance to the command class
if( TIXML_SUCCESS == child->QueryIntAttribute( "index", &intVal ) )
{
instance = (uint8)intVal;
SetInstance( instance );
}
// See if its associated endpoint is present
if( TIXML_SUCCESS == child->QueryIntAttribute( "endpoint", &intVal ) )
{
uint8 endpoint = (uint8)intVal;
SetEndPoint( instance, endpoint );
}
}
else if( !strcmp( str, "Value" ) )
{
// Apply any differences from the saved XML to the value
GetNodeUnsafe()->ReadValueFromXML( GetCommandClassId(), child );
}
else if (!strcmp( str, "TriggerRefreshValue" ) )
{
ReadValueRefreshXML(child);
}
}
child = child->NextSiblingElement();
}
}
//-----------------------------------------------------------------------------
// <CommandClass::ReadValueRefreshXML>
// Read the config that contains a list of Values that should be refreshed when
// we recieve u updated Value from a device. (This helps Yale Door Locks, which send a
// Alarm Report instead of DoorLock Report when the status of the Door Lock is changed
//-----------------------------------------------------------------------------
void CommandClass::ReadValueRefreshXML
(
TiXmlElement const* _ccElement
)
{
char const* str;
bool ok = false;
const char *genre;
RefreshValue *rcc = new RefreshValue();
rcc->cc = GetCommandClassId();
genre = _ccElement->Attribute( "Genre" );
rcc->genre = Value::GetGenreEnumFromName(genre);
_ccElement->QueryIntAttribute( "Instance", (int*)&rcc->instance);
_ccElement->QueryIntAttribute( "Index", (int*)&rcc->index);
Log::Write(LogLevel_Info, GetNodeId(), "Value Refresh triggered by CommandClass: %s, Genre: %d, Instance: %d, Index: %d for:", GetCommandClassName().c_str(), rcc->genre, rcc->instance, rcc->index);
TiXmlElement const* child = _ccElement->FirstChildElement();
while( child )
{
str = child->Value();
if( str )
{
if ( !strcmp(str, "RefreshClassValue"))
{
RefreshValue *arcc = new RefreshValue();
if (child->QueryIntAttribute( "CommandClass", (int*)&arcc->cc) != TIXML_SUCCESS) {
Log::Write(LogLevel_Warning, GetNodeId(), " Invalid XML - CommandClass Attribute is wrong type or missing");
continue;
}
if (child->QueryIntAttribute( "RequestFlags", (int*)&arcc->genre) != TIXML_SUCCESS) {
Log::Write(LogLevel_Warning, GetNodeId(), " Invalid XML - RequestFlags Attribute is wrong type or missing");
continue;
}
if (child->QueryIntAttribute( "Instance", (int*)&arcc->instance) != TIXML_SUCCESS) {
Log::Write(LogLevel_Warning, GetNodeId(), " Invalid XML - Instance Attribute is wrong type or missing");
continue;
}
if (child->QueryIntAttribute( "Index", (int*)&arcc->index) != TIXML_SUCCESS) {
Log::Write(LogLevel_Warning, GetNodeId(), " Invalid XML - Index Attribute is wrong type or missing");
continue;
}
Log::Write(LogLevel_Info, GetNodeId(), " CommandClass: %s, RequestFlags: %d, Instance: %d, Index: %d", CommandClasses::GetName(arcc->cc).c_str(), arcc->genre, arcc->instance, arcc->index);
rcc->RefreshClasses.push_back(arcc);
ok = true;
}
else
{
Log::Write(LogLevel_Warning, GetNodeId(), "Got Unhandled Child Entry in TriggerRefreshValue XML Config: %s", str);
}
}
child = child->NextSiblingElement();
}
if (ok == true) {
m_RefreshClassValues.push_back( rcc );
} else {
Log::Write(LogLevel_Warning, GetNodeId(), "Failed to add a RefreshClassValue from XML");
delete rcc;
}
}
//-----------------------------------------------------------------------------
// <CommandClass::CheckForRefreshValues>
// Scan our m_RefreshClassValues vector to see if we should call any other
// Command Classes to refresh their value
//-----------------------------------------------------------------------------
bool CommandClass::CheckForRefreshValues (
Value const* _value
)
{
if (m_RefreshClassValues.empty())
{
//Log::Write(LogLevel_Debug, GetNodeId(), "Bailing out of CheckForRefreshValues");
return false;
}
Node* node = GetNodeUnsafe();
if( node != NULL )
{
for (uint32 i = 0; i < m_RefreshClassValues.size(); i++)
{
RefreshValue *rcc = m_RefreshClassValues.at(i);
//Log::Write(LogLevel_Debug, GetNodeId(), "Checking Value Against RefreshClassList: CommandClass %s = %s, Genre %d = %d, Instance %d = %d, Index %d = %d", CommandClasses::GetName(rcc->cc).c_str(), CommandClasses::GetName(_value->GetID().GetCommandClassId()).c_str(), rcc->genre, _value->GetID().GetGenre(), rcc->instance, _value->GetID().GetInstance(), rcc->index, _value->GetID().GetIndex());
if ((rcc->genre == _value->GetID().GetGenre()) && (rcc->instance == _value->GetID().GetInstance()) && (rcc->index == _value->GetID().GetIndex()) )
{
/* we got a match..... */
for (uint32 j = 0; j < rcc->RefreshClasses.size(); j++)
{
RefreshValue *arcc = rcc->RefreshClasses.at(j);
Log::Write(LogLevel_Debug, GetNodeId(), "Requesting Refresh of Value: CommandClass: %s Genre %d, Instance %d, Index %d", CommandClasses::GetName(arcc->cc).c_str(), arcc->genre, arcc->instance, arcc->index);
if( CommandClass* cc = node->GetCommandClass( arcc->cc ) )
{
cc->RequestValue(arcc->genre, arcc->index, arcc->instance, Driver::MsgQueue_Send);
}
}
}
}
}
else /* Driver */
{
Log::Write(LogLevel_Warning, GetNodeId(), "Can't get Node");
}
return true;
}
//-----------------------------------------------------------------------------
// <CommandClass::WriteXML>
// Save the static node configuration data
//-----------------------------------------------------------------------------
void CommandClass::WriteXML
(
TiXmlElement* _ccElement
)
{
char str[32];
snprintf( str, sizeof(str), "%d", GetCommandClassId() );
_ccElement->SetAttribute( "id", str );
_ccElement->SetAttribute( "name", GetCommandClassName().c_str() );
snprintf( str, sizeof(str), "%d", GetVersion() );
_ccElement->SetAttribute( "version", str );
if( m_staticRequests )
{
snprintf( str, sizeof(str), "%d", m_staticRequests );
_ccElement->SetAttribute( "request_flags", str );
}
if( m_overridePrecision >= 0 )
{
snprintf( str, sizeof(str), "%d", m_overridePrecision );
_ccElement->SetAttribute( "override_precision", str );
}
if( m_afterMark )
{
_ccElement->SetAttribute( "after_mark", "true" );
}
if( !m_createVars )
{
_ccElement->SetAttribute( "create_vars", "false" );
}
if( !m_getSupported )
{
_ccElement->SetAttribute( "getsupported", "false" );
}
if ( m_isSecured )
{
_ccElement->SetAttribute( "issecured", "true" );
}
// Write out the instances
for( Bitfield::Iterator it = m_instances.Begin(); it != m_instances.End(); ++ it )
{
TiXmlElement* instanceElement = new TiXmlElement( "Instance" );
_ccElement->LinkEndChild( instanceElement );
snprintf( str, sizeof(str), "%d", *it );
instanceElement->SetAttribute( "index", str );
map<uint8,uint8>::iterator eit = m_endPointMap.find( *it );
if( eit != m_endPointMap.end() )
{
snprintf( str, sizeof(str), "%d", eit->second );
instanceElement->SetAttribute( "endpoint", str );
}
}
// Write out the values for this command class
ValueStore* store = GetNodeUnsafe()->GetValueStore();
for( ValueStore::Iterator it = store->Begin(); it != store->End(); ++it )
{
Value* value = it->second;
if( value->GetID().GetCommandClassId() == GetCommandClassId() )
{
TiXmlElement* valueElement = new TiXmlElement( "Value" );
_ccElement->LinkEndChild( valueElement );
value->WriteXML( valueElement );
}
}
// Write out the TriggerRefreshValue if it exists
for (uint32 i = 0; i < m_RefreshClassValues.size(); i++)
{
RefreshValue *rcc = m_RefreshClassValues.at(i);
TiXmlElement* RefreshElement = new TiXmlElement("TriggerRefreshValue");
_ccElement->LinkEndChild( RefreshElement );
RefreshElement->SetAttribute("Genre", Value::GetGenreNameFromEnum((ValueID::ValueGenre)rcc->genre));
RefreshElement->SetAttribute("Instance", rcc->instance);
RefreshElement->SetAttribute("Index", rcc->index);
for (uint32 j = 0; j < rcc->RefreshClasses.size(); j++)
{
RefreshValue *arcc = rcc->RefreshClasses.at(j);
TiXmlElement *ClassElement = new TiXmlElement("RefreshClassValue");
RefreshElement->LinkEndChild(ClassElement);
ClassElement->SetAttribute("CommandClass", arcc->cc);
ClassElement->SetAttribute("RequestFlags", arcc->genre);
ClassElement->SetAttribute("Instance", arcc->instance);
ClassElement->SetAttribute("Index", arcc->index);
}
}
}
//-----------------------------------------------------------------------------
// <CommandClass::ExtractValue>
// Read a value from a variable length sequence of bytes
//-----------------------------------------------------------------------------
string CommandClass::ExtractValue
(
uint8 const* _data,
uint8* _scale,
uint8* _precision,
uint8 _valueOffset // = 1
)const
{
uint8 const size = _data[0] & c_sizeMask;
uint8 const precision = (_data[0] & c_precisionMask) >> c_precisionShift;
if( _scale )
{
*_scale = (_data[0] & c_scaleMask) >> c_scaleShift;
}
if( _precision )
{
*_precision = precision;
}
uint32 value = 0;
uint8 i;
for( i=0; i<size; ++i )
{
value <<= 8;
value |= (uint32)_data[i+(uint32)_valueOffset];
}
// Deal with sign extension. All values are signed
string res;
if( _data[_valueOffset] & 0x80 )
{
res = "-";
// MSB is signed
if( size == 1 )
{
value |= 0xffffff00;
}
else if( size == 2 )
{
value |= 0xffff0000;
}
}
// Convert the integer to a decimal string. We avoid
// using floats to prevent accuracy issues.
char numBuf[12] = {0};
if( precision == 0 )
{
// The precision is zero, so we can just print the number directly into the string.
snprintf( numBuf, 12, "%d", (signed int)value );
res = numBuf;
}
else
{
// We'll need to insert a decimal point and include any necessary leading zeros.
// Fill the buffer with the value padded with leading zeros.
snprintf( numBuf, 12, "%011d", (signed int)value );
// Calculate the position of the decimal point in the buffer
int32 decimal = 10-precision;
// Shift the characters to make space for the decimal point.
// We don't worry about overwriting any minus sign since that is
// already written into the res string. While we're shifting, we
// also look for the real starting position of the number so we
// can copy it into the res string later.
int32 start = -1;
for( int32 i=0; i<decimal; ++i )
{
numBuf[i] = numBuf[i+1];
if( ( start<0 ) && ( numBuf[i] != '0' ) )
{
start = i;
}
}
if( start<0 )
{
start = decimal-1;
}
// Insert the decimal point
struct lconv const* locale = localeconv();
numBuf[decimal] = *(locale->decimal_point);
// Copy the buffer into res
res += &numBuf[start];
}
return res;
}
//-----------------------------------------------------------------------------
// <CommandClass::AppendValue>
// Add a value to a message as a sequence of bytes
//-----------------------------------------------------------------------------
void CommandClass::AppendValue
(
Msg* _msg,
string const& _value,
uint8 const _scale
)const
{
uint8 precision;
uint8 size;
int32 val = ValueToInteger( _value, &precision, &size );
_msg->Append( (precision<<c_precisionShift) | (_scale<<c_scaleShift) | size );
int32 shift = (size-1)<<3;
for( int32 i=size; i>0; --i, shift-=8 )
{
_msg->Append( (uint8)(val >> shift) );
}
}
//-----------------------------------------------------------------------------
// <CommandClass::GetAppendValueSize>
// Get the number of bytes that would be added by a call to AppendValue
//-----------------------------------------------------------------------------
uint8 const CommandClass::GetAppendValueSize
(
string const& _value
)const
{
uint8 size;
ValueToInteger( _value, NULL, &size );
return size;
}
//-----------------------------------------------------------------------------
// <CommandClass::ValueToInteger>
// Convert a decimal string to an integer and report the precision and
// number of bytes required to store the value.
//-----------------------------------------------------------------------------
int32 CommandClass::ValueToInteger
(
string const& _value,
uint8* o_precision,
uint8* o_size
)const
{
int32 val;
uint8 precision;
// Find the decimal point
size_t pos = _value.find_first_of( "." );
if( pos == string::npos )
pos = _value.find_first_of( "," );
if( pos == string::npos )
{
// No decimal point
precision = 0;
// Convert the string to an integer
val = atol( _value.c_str() );
}
else
{
// Remove the decimal point and convert to an integer
precision = (uint8) ((_value.size()-pos)-1);
string str = _value.substr( 0, pos ) + _value.substr( pos+1 );
val = atol( str.c_str() );
}
if ( m_overridePrecision > 0 )
{
while ( precision < m_overridePrecision ) {
precision++;
val *= 10;
}
}
if ( o_precision ) *o_precision = precision;
if( o_size )
{
// Work out the size as either 1, 2 or 4 bytes
*o_size = 4;
if( val < 0 )
{
if( ( val & 0xffffff80 ) == 0xffffff80 )
{
*o_size = 1;
}
else if( ( val & 0xffff8000 ) == 0xffff8000 )
{
*o_size = 2;
}
}
else
{
if( ( val & 0xffffff00 ) == 0 )
{
*o_size = 1;
}
else if( ( val & 0xffff0000 ) == 0 )
{
*o_size = 2;
}
}
}
return val;
}
//-----------------------------------------------------------------------------
// <CommandClass::UpdateMappedClass>
// Update the mapped class if there is one with BASIC level
//-----------------------------------------------------------------------------
void CommandClass::UpdateMappedClass
(
uint8 const _instance,
uint8 const _classId,
uint8 const _level
)
{
if( _classId )
{
if( Node* node = GetNodeUnsafe() )
{
CommandClass* cc = node->GetCommandClass( _classId );
if( node->GetCurrentQueryStage() == Node::QueryStage_Complete && cc != NULL )
{
cc->SetValueBasic( _instance, _level );
}
}
}
}
//-----------------------------------------------------------------------------
// <CommandClass::ClearStaticRequest>
// The static data for this command class has been read from the device
//-----------------------------------------------------------------------------
void CommandClass::ClearStaticRequest
(
uint8 _request
)
{
m_staticRequests &= ~_request;
}
//-----------------------------------------------------------------------------
// <CommandClass::RequestStateForAllInstances>
// Request current state from the device
//-----------------------------------------------------------------------------
bool CommandClass::RequestStateForAllInstances
(
uint32 const _requestFlags,
Driver::MsgQueue const _queue
)
{
bool res = false;
if( m_createVars )
{
if( Node* node = GetNodeUnsafe() )
{
MultiInstance* multiInstance = static_cast<MultiInstance*>( node->GetCommandClass( MultiInstance::StaticGetCommandClassId() ) );
if( multiInstance != NULL )
{
for( Bitfield::Iterator it = m_instances.Begin(); it != m_instances.End(); ++it )
{
res |= RequestState( _requestFlags, (uint8)*it, _queue );
}
}
else
{
res = RequestState( _requestFlags, 1, _queue );
}
}
}
return res;
}
@@ -0,0 +1,198 @@
//-----------------------------------------------------------------------------
//
// CommandClass.h
//
// Base class for all Z-Wave Command Classes
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _CommandClass_H
#define _CommandClass_H
#include <string>
#include <vector>
#include <map>
#include "../Defs.h"
#include "../Bitfield.h"
#include "../Driver.h"
namespace OpenZWave
{
class Msg;
class Node;
class Value;
/** \brief Base class for all Z-Wave command classes.
*/
class OPENZWAVE_EXPORT CommandClass
{
public:
enum
{
RequestFlag_Static = 0x00000001, /**< Values that never change. */
RequestFlag_Session = 0x00000002, /**< Values that change infrequently, and so only need to be requested at start up, or via a manual refresh. */
RequestFlag_Dynamic = 0x00000004, /**< Values that change and will be requested if polling is enabled on the node. */
};
CommandClass( uint32 const _homeId, uint8 const _nodeId );
virtual ~CommandClass();
virtual void ReadXML( TiXmlElement const* _ccElement );
virtual void WriteXML( TiXmlElement* _ccElement );
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ){ return false; }
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue ) { return false; }
virtual uint8 const GetCommandClassId()const = 0;
virtual string const GetCommandClassName()const = 0;
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ) = 0;
virtual bool SetValue( Value const& _value ){ return false; }
virtual void SetValueBasic( uint8 const _instance, uint8 const _level ){} // Class specific handling of BASIC value mapping
virtual void SetVersion( uint8 const _version ){ m_version = _version; }
bool RequestStateForAllInstances( uint32 const _requestFlags, Driver::MsgQueue const _queue );
bool CheckForRefreshValues(Value const* _value );
// The highest version number of the command class implemented by OpenZWave. We only need
// to do version gets on command classes that override this with a number greater than one.
virtual uint8 GetMaxVersion(){ return 1; }
uint8 GetVersion()const{ return m_version; }
Bitfield const* GetInstances()const{ return &m_instances; }
uint32 GetHomeId()const{ return m_homeId; }
uint8 GetNodeId()const{ return m_nodeId; }
Driver* GetDriver()const;
Node* GetNodeUnsafe()const;
Value* GetValue( uint8 const _instance, uint8 const _index );
bool RemoveValue( uint8 const _instance, uint8 const _index );
uint8 GetEndPoint( uint8 const _instance )
{
map<uint8,uint8>::iterator it = m_endPointMap.find( _instance );
return( it == m_endPointMap.end() ? 0 : it->second );
}
uint8 GetInstance( uint8 const _endPoint )
{
for( map<uint8,uint8>::iterator it = m_endPointMap.begin(); it != m_endPointMap.end(); ++it )
{
if( _endPoint == it->second )
{
return it->first;
}
}
return 0;
}
void SetInstances( uint8 const _instances );
void SetInstance( uint8 const _endPoint );
void SetAfterMark(){ m_afterMark = true; }
void SetEndPoint( uint8 const _instance, uint8 const _endpoint){ m_endPointMap[_instance] = _endpoint; }
bool IsAfterMark()const{ return m_afterMark; }
bool IsCreateVars()const{ return m_createVars; }
bool IsGetSupported()const{ return m_getSupported; }
bool IsSecured()const{ return m_isSecured; }
void SetSecured(){ m_isSecured = true; }
bool IsSecureSupported()const { return m_SecureSupport; }
void ClearSecureSupport() { m_SecureSupport = false; }
void SetSecureSupport() { m_SecureSupport = true; }
// Helper methods
string ExtractValue( uint8 const* _data, uint8* _scale, uint8* _precision, uint8 _valueOffset = 1 )const;
/**
* Append a floating-point value to a message.
* \param _msg The message to which the value should be appended.
* \param _value A string containing a decimal number to be appended.
* \param _scale A byte indicating the scale corresponding to this value (e.g., 1=F and 0=C for temperatures).
* \see Msg
*/
void AppendValue( Msg* _msg, string const& _value, uint8 const _scale )const;
uint8 const GetAppendValueSize( string const& _value )const;
int32 ValueToInteger( string const& _value, uint8* o_precision, uint8* o_size )const;
void UpdateMappedClass( uint8 const _instance, uint8 const _classId, uint8 const _value ); // Update mapped class's value from BASIC class
typedef struct RefreshValue {
uint8 cc;
uint8 genre;
uint8 instance;
uint8 index;
std::vector<RefreshValue *> RefreshClasses;
} RefreshValue;
protected:
virtual void CreateVars( uint8 const _instance ){}
void ReadValueRefreshXML ( TiXmlElement const* _ccElement );
public:
virtual void CreateVars( uint8 const _instance, uint8 const _index ){}
private:
uint32 m_homeId;
uint8 m_nodeId;
uint8 m_version;
Bitfield m_instances;
OPENZWAVE_EXPORT_WARNINGS_OFF
map<uint8,uint8> m_endPointMap;
OPENZWAVE_EXPORT_WARNINGS_ON
bool m_afterMark; // Set to true if the command class is listed after COMMAND_CLASS_MARK, and should not create any values.
bool m_createVars; // Do we want to create variables
int8 m_overridePrecision; // Override precision when writing values if >=0
bool m_getSupported; // Get operation supported
bool m_isSecured; // is this command class secured with the Security Command Class
bool m_SecureSupport; // Does this commandclass support secure encryption (eg, the Security CC doesn't encrypt itself, so it doesn't support encryption)
std::vector<RefreshValue *> m_RefreshClassValues; // what Command Class Values should we refresh ?
//-----------------------------------------------------------------------------
// Record which items of static data have been read from the device
//-----------------------------------------------------------------------------
public:
enum StaticRequest
{
StaticRequest_Instances = 0x01,
StaticRequest_Values = 0x02,
StaticRequest_Version = 0x04
};
bool HasStaticRequest( uint8 _request )const{ return( (m_staticRequests & _request) != 0 ); }
void SetStaticRequest( uint8 _request ){ m_staticRequests |= _request; }
void ClearStaticRequest( uint8 _request );
private:
uint8 m_staticRequests;
//-----------------------------------------------------------------------------
// Statistics
//-----------------------------------------------------------------------------
public:
uint32 GetSentCnt()const{ return m_sentCnt; }
uint32 GetReceivedCnt()const{ return m_receivedCnt; }
void SentCntIncr(){ m_sentCnt++; }
void ReceivedCntIncr(){ m_receivedCnt++; }
private:
uint32 m_sentCnt; // Number of messages sent from this command class.
uint32 m_receivedCnt; // Number of messages received from this commandclass.
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,316 @@
//-----------------------------------------------------------------------------
//
// CommandClasses.cpp
//
// Singleton holding methods to create each command class object
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 <string.h>
#include "CommandClasses.h"
using namespace OpenZWave;
#include "Alarm.h"
#include "ApplicationStatus.h"
#include "Association.h"
#include "AssociationCommandConfiguration.h"
#include "Basic.h"
#include "BasicWindowCovering.h"
#include "Battery.h"
#include "ClimateControlSchedule.h"
#include "Clock.h"
#include "Configuration.h"
#include "ControllerReplication.h"
#include "CRC16Encap.h"
#include "DoorLock.h"
#include "DoorLockLogging.h"
#include "EnergyProduction.h"
#include "Hail.h"
#include "Indicator.h"
#include "Language.h"
#include "Lock.h"
#include "ManufacturerSpecific.h"
#include "Meter.h"
#include "MeterPulse.h"
#include "MultiCmd.h"
#include "MultiInstance.h"
#include "MultiInstanceAssociation.h"
#include "NodeNaming.h"
#include "NoOperation.h"
#include "Powerlevel.h"
#include "Proprietary.h"
#include "Protection.h"
#include "SceneActivation.h"
#include "Security.h"
#include "SensorAlarm.h"
#include "SensorBinary.h"
#include "SensorMultilevel.h"
#include "SwitchAll.h"
#include "SwitchBinary.h"
#include "SwitchMultilevel.h"
#include "SwitchToggleBinary.h"
#include "SwitchToggleMultilevel.h"
#include "TimeParameters.h"
#include "ThermostatFanMode.h"
#include "ThermostatFanState.h"
#include "ThermostatMode.h"
#include "ThermostatOperatingState.h"
#include "ThermostatSetpoint.h"
#include "UserCode.h"
#include "Version.h"
#include "WakeUp.h"
#include "../value_classes/ValueBool.h"
#include "../value_classes/ValueButton.h"
#include "../value_classes/ValueByte.h"
#include "../value_classes/ValueDecimal.h"
#include "../value_classes/ValueInt.h"
#include "../value_classes/ValueList.h"
#include "../value_classes/ValueSchedule.h"
#include "../value_classes/ValueShort.h"
#include "../value_classes/ValueString.h"
#include "../Manager.h"
#include "../Options.h"
#include "../Utils.h"
//-----------------------------------------------------------------------------
// <CommandClasses::CommandClasses>
// Constructor
//-----------------------------------------------------------------------------
CommandClasses::CommandClasses
(
)
{
memset( m_commandClassCreators, 0, sizeof(pfnCreateCommandClass_t)*256 );
memset( m_supportedCommandClasses, 0, sizeof(uint32)*8 );
}
//-----------------------------------------------------------------------------
// <CommandClasses::IsSupported>
// Static method to determine whether a command class is supported
//-----------------------------------------------------------------------------
bool CommandClasses::IsSupported
(
uint8 const _commandClassId
)
{
// Test the bit representing the command class
return( (Get().m_supportedCommandClasses[_commandClassId>>5] & (1u<<(_commandClassId&0x1f))) != 0 );
}
string CommandClasses::GetName(
uint8 const _commandClassId
)
{
for (std::map<string,uint8>::iterator it = Get().m_namesToIDs.begin(); it != Get().m_namesToIDs.end(); it++) {
if (it->second == _commandClassId)
return it->first;
}
return string("Unknown");
}
//-----------------------------------------------------------------------------
// <CommandClasses::Register>
// Static method to register a command class creator method
//-----------------------------------------------------------------------------
void CommandClasses::Register
(
uint8 const _commandClassId,
string const& _commandClassName,
pfnCreateCommandClass_t _creator
)
{
m_commandClassCreators[_commandClassId] = _creator;
// Set the bit representing the command class
Get().m_supportedCommandClasses[_commandClassId>>5] |= (1u<<(_commandClassId&0x1f));
m_namesToIDs[_commandClassName] = _commandClassId;
}
//-----------------------------------------------------------------------------
// <CommandClasses::CreateCommandClass>
// Create a command class object using the registered method
//-----------------------------------------------------------------------------
CommandClass* CommandClasses::CreateCommandClass
(
uint8 const _commandClassId,
uint32 const _homeId,
uint8 const _nodeId
)
{
// Get a pointer to the required CommandClass's Create method
pfnCreateCommandClass_t creator = Get().m_commandClassCreators[_commandClassId];
if( NULL == creator )
{
return NULL;
}
// Create an instance of the command class
return creator( _homeId, _nodeId );
}
//-----------------------------------------------------------------------------
// <CommandClasses::RegisterCommandClasses>
// Register all our implemented command classes
//-----------------------------------------------------------------------------
void CommandClasses::RegisterCommandClasses
(
)
{
CommandClasses& cc = Get();
cc.Register( Alarm::StaticGetCommandClassId(), Alarm::StaticGetCommandClassName(), Alarm::Create );
cc.Register( ApplicationStatus::StaticGetCommandClassId(), ApplicationStatus::StaticGetCommandClassName(), ApplicationStatus::Create );
cc.Register( Association::StaticGetCommandClassId(), Association::StaticGetCommandClassName(), Association::Create );
cc.Register( AssociationCommandConfiguration::StaticGetCommandClassId(), AssociationCommandConfiguration::StaticGetCommandClassName(), AssociationCommandConfiguration::Create );
cc.Register( Basic::StaticGetCommandClassId(), Basic::StaticGetCommandClassName(), Basic::Create );
cc.Register( BasicWindowCovering::StaticGetCommandClassId(), BasicWindowCovering::StaticGetCommandClassName(), BasicWindowCovering::Create );
cc.Register( Battery::StaticGetCommandClassId(), Battery::StaticGetCommandClassName(), Battery::Create );
cc.Register( ClimateControlSchedule::StaticGetCommandClassId(), ClimateControlSchedule::StaticGetCommandClassName(), ClimateControlSchedule::Create );
cc.Register( Clock::StaticGetCommandClassId(), Clock::StaticGetCommandClassName(), Clock::Create );
cc.Register( Configuration::StaticGetCommandClassId(), Configuration::StaticGetCommandClassName(), Configuration::Create );
cc.Register( ControllerReplication::StaticGetCommandClassId(), ControllerReplication::StaticGetCommandClassName(), ControllerReplication::Create );
cc.Register( CRC16Encap::StaticGetCommandClassId(), CRC16Encap::StaticGetCommandClassName(), CRC16Encap::Create );
cc.Register( DoorLock::StaticGetCommandClassId(), DoorLock::StaticGetCommandClassName(), DoorLock::Create );
cc.Register( DoorLockLogging::StaticGetCommandClassId(), DoorLockLogging::StaticGetCommandClassName(), DoorLockLogging::Create);
cc.Register( EnergyProduction::StaticGetCommandClassId(), EnergyProduction::StaticGetCommandClassName(), EnergyProduction::Create );
cc.Register( Hail::StaticGetCommandClassId(), Hail::StaticGetCommandClassName(), Hail::Create );
cc.Register( Indicator::StaticGetCommandClassId(), Indicator::StaticGetCommandClassName(), Indicator::Create );
cc.Register( Language::StaticGetCommandClassId(), Language::StaticGetCommandClassName(), Language::Create );
cc.Register( Lock::StaticGetCommandClassId(), Lock::StaticGetCommandClassName(), Lock::Create );
cc.Register( ManufacturerSpecific::StaticGetCommandClassId(), ManufacturerSpecific::StaticGetCommandClassName(), ManufacturerSpecific::Create );
cc.Register( Meter::StaticGetCommandClassId(), Meter::StaticGetCommandClassName(), Meter::Create );
cc.Register( MeterPulse::StaticGetCommandClassId(), MeterPulse::StaticGetCommandClassName(), MeterPulse::Create );
cc.Register( MultiCmd::StaticGetCommandClassId(), MultiCmd::StaticGetCommandClassName(), MultiCmd::Create );
cc.Register( MultiInstance::StaticGetCommandClassId(), MultiInstance::StaticGetCommandClassName(), MultiInstance::Create );
cc.Register( MultiInstanceAssociation::StaticGetCommandClassId(), MultiInstanceAssociation::StaticGetCommandClassName(), MultiInstanceAssociation::Create );
cc.Register( NodeNaming::StaticGetCommandClassId(), NodeNaming::StaticGetCommandClassName(), NodeNaming::Create );
cc.Register( NoOperation::StaticGetCommandClassId(), NoOperation::StaticGetCommandClassName(), NoOperation::Create );
cc.Register( Powerlevel::StaticGetCommandClassId(), Powerlevel::StaticGetCommandClassName(), Powerlevel::Create );
cc.Register( Proprietary::StaticGetCommandClassId(), Proprietary::StaticGetCommandClassName(), Proprietary::Create );
cc.Register( Protection::StaticGetCommandClassId(), Protection::StaticGetCommandClassName(), Protection::Create );
cc.Register( SceneActivation::StaticGetCommandClassId(), SceneActivation::StaticGetCommandClassName(), SceneActivation::Create );
cc.Register( Security::StaticGetCommandClassId(), Security::StaticGetCommandClassName(), Security::Create);
cc.Register( SensorAlarm::StaticGetCommandClassId(), SensorAlarm::StaticGetCommandClassName(), SensorAlarm::Create );
cc.Register( SensorBinary::StaticGetCommandClassId(), SensorBinary::StaticGetCommandClassName(), SensorBinary::Create );
cc.Register( SensorMultilevel::StaticGetCommandClassId(), SensorMultilevel::StaticGetCommandClassName(), SensorMultilevel::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 );
cc.Register( SwitchToggleBinary::StaticGetCommandClassId(), SwitchToggleBinary::StaticGetCommandClassName(), SwitchToggleBinary::Create );
cc.Register( SwitchToggleMultilevel::StaticGetCommandClassId(), SwitchToggleMultilevel::StaticGetCommandClassName(), SwitchToggleMultilevel::Create );
cc.Register( TimeParameters::StaticGetCommandClassId(), TimeParameters::StaticGetCommandClassName(), TimeParameters::Create);
cc.Register( ThermostatFanMode::StaticGetCommandClassId(), ThermostatFanMode::StaticGetCommandClassName(), ThermostatFanMode::Create );
cc.Register( ThermostatFanState::StaticGetCommandClassId(), ThermostatFanState::StaticGetCommandClassName(), ThermostatFanState::Create );
cc.Register( ThermostatMode::StaticGetCommandClassId(), ThermostatMode::StaticGetCommandClassName(), ThermostatMode::Create );
cc.Register( ThermostatOperatingState::StaticGetCommandClassId(), ThermostatOperatingState::StaticGetCommandClassName(), ThermostatOperatingState::Create );
cc.Register( ThermostatSetpoint::StaticGetCommandClassId(), ThermostatSetpoint::StaticGetCommandClassName(), ThermostatSetpoint::Create );
cc.Register( UserCode::StaticGetCommandClassId(), UserCode::StaticGetCommandClassName(), UserCode::Create );
cc.Register( Version::StaticGetCommandClassId(), Version::StaticGetCommandClassName(), Version::Create );
cc.Register( WakeUp::StaticGetCommandClassId(), WakeUp::StaticGetCommandClassName(), WakeUp::Create );
// Now all the command classes have been registered, we can modify the
// supported command classes array according to the program options.
string str;
Options::Get()->GetOptionAsString( "Include", &str );
if( str != "" )
{
// The include list has entries, so we assume that it is a
// complete list of what should be supported.
// Any existing support is cleared first.
memset( cc.m_supportedCommandClasses, 0, sizeof(uint32)*8 );
cc.ParseCommandClassOption( str, true );
}
// Apply the excluded command class option
Options::Get()->GetOptionAsString( "Exclude", &str );
if( str != "" )
{
cc.ParseCommandClassOption( str, false );
}
}
//-----------------------------------------------------------------------------
// <CommandClasses::ParseCommandClassOption>
// Parse a comma delimited list of included/excluded command classes
//-----------------------------------------------------------------------------
void CommandClasses::ParseCommandClassOption
(
string const& _optionStr,
bool const _include
)
{
size_t pos = 0;
size_t start = 0;
bool parsing = true;
while( parsing )
{
string ccStr;
pos = _optionStr.find_first_of( ",", start );
if( string::npos == pos )
{
ccStr = _optionStr.substr( start );
parsing = false;
}
else
{
ccStr = _optionStr.substr( start, pos-start );
start = pos + 1;
}
if( ccStr != "" )
{
uint8 ccIdx = GetCommandClassId( ccStr );
if( _include )
{
m_supportedCommandClasses[ccIdx>>5] |= (1u<<(ccIdx&0x1f));
}
else
{
m_supportedCommandClasses[ccIdx>>5] &= ~(1u<<(ccIdx&0x1f));
}
}
}
}
//-----------------------------------------------------------------------------
// <CommandClasses::GetCommandClassId>
// Convert a command class name (e.g COMMAND_CLASS_BASIC) into its 8-bit ID
//-----------------------------------------------------------------------------
uint8 CommandClasses::GetCommandClassId
(
string const& _name
)
{
string upperName = ToUpper( _name );
map<string,uint8>::iterator it = m_namesToIDs.find( upperName );
if( it != m_namesToIDs.end() )
{
return it->second;
}
return 0xff;
}
@@ -0,0 +1,79 @@
//-----------------------------------------------------------------------------
//
// CommandClasses.h
//
// Singleton holding methods to create each command class object
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _CommandClasses_H
#define _CommandClasses_H
#include <string>
#include <map>
#include "../Defs.h"
namespace OpenZWave
{
class CommandClass;
/** \brief Manages a map of command classes supported by a specific Z-Wave node.
*/
class CommandClasses
{
public:
typedef CommandClass* (*pfnCreateCommandClass_t)( uint32 const _homeId, uint8 const _nodeId );
static void RegisterCommandClasses();
static CommandClass* CreateCommandClass( uint8 const _commandClassId, uint32 const _homeId, uint8 const _nodeId );
static bool IsSupported( uint8 const _commandClassId );
static string GetName(uint8 const _commandClassId);
private:
CommandClasses();
CommandClasses( CommandClasses const& ); // prevent copy
CommandClasses& operator = ( CommandClasses const& ); // prevent assignment
static CommandClasses& Get()
{
static CommandClasses instance;
return instance;
}
void Register( uint8 const _commandClassId, string const& _commandClassName, pfnCreateCommandClass_t _create );
void ParseCommandClassOption( string const& _optionStr, bool const _include );
uint8 GetCommandClassId( string const& _name );
pfnCreateCommandClass_t m_commandClassCreators[256];
map<string,uint8> m_namesToIDs;
// m_supportedCommandClasses uses single bits to mark whether OpenZWave supports a command class
// Checking this is not the same as looking for non-NULL entried in m_commandClassCreators, since
// this may be modified by the program options --Include and --Ingnore to filter out support
// for unwanted command classes.
uint32 m_supportedCommandClasses[8];
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,277 @@
//-----------------------------------------------------------------------------
//
// Configuration.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_CONFIGURATION
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "Configuration.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Driver.h"
#include "../Node.h"
#include "../platform/Log.h"
#include "../value_classes/ValueBool.h"
#include "../value_classes/ValueButton.h"
#include "../value_classes/ValueByte.h"
#include "../value_classes/ValueInt.h"
#include "../value_classes/ValueList.h"
#include "../value_classes/ValueShort.h"
using namespace OpenZWave;
enum ConfigurationCmd
{
ConfigurationCmd_Set = 0x04,
ConfigurationCmd_Get = 0x05,
ConfigurationCmd_Report = 0x06
};
//-----------------------------------------------------------------------------
// <Configuration::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool Configuration::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if (ConfigurationCmd_Report == (ConfigurationCmd)_data[0])
{
// Extract the parameter index and value
uint8 parameter = _data[1];
uint8 size = _data[2] & 0x07;
int32 paramValue = 0;
for( uint8 i=0; i<size; ++i )
{
paramValue <<= 8;
paramValue |= (int32)_data[i+3];
}
if ( Value* value = GetValue( 1, parameter ) )
{
switch ( value->GetID().GetType() )
{
case ValueID::ValueType_Bool:
{
ValueBool* valueBool = static_cast<ValueBool*>( value );
valueBool->OnValueRefreshed( paramValue != 0 );
break;
}
case ValueID::ValueType_Byte:
{
ValueByte* valueByte = static_cast<ValueByte*>( value );
valueByte->OnValueRefreshed( (uint8)paramValue );
break;
}
case ValueID::ValueType_Short:
{
ValueShort* valueShort = static_cast<ValueShort*>( value );
valueShort->OnValueRefreshed( (int16)paramValue );
break;
}
case ValueID::ValueType_Int:
{
ValueInt* valueInt = static_cast<ValueInt*>( value );
valueInt->OnValueRefreshed( paramValue );
break;
}
case ValueID::ValueType_List:
{
ValueList* valueList = static_cast<ValueList*>( value );
valueList->OnValueRefreshed( paramValue );
break;
}
default:
{
Log::Write( LogLevel_Info, GetNodeId(), "Invalid type (%d) for configuration parameter %d", value->GetID().GetType(), parameter );
}
}
value->Release();
}
else
{
char label[16];
snprintf( label, 16, "Parameter #%d", parameter );
// Create a new value
if( Node* node = GetNodeUnsafe() )
{
switch( size )
{
case 1:
{
node->CreateValueByte( ValueID::ValueGenre_Config, GetCommandClassId(), _instance, parameter, label, "", false, false, (uint8)paramValue, 0 );
break;
}
case 2:
{
node->CreateValueShort( ValueID::ValueGenre_Config, GetCommandClassId(), _instance, parameter, label, "", false, false, (int16)paramValue, 0 );
break;
}
case 4:
{
node->CreateValueInt( ValueID::ValueGenre_Config, GetCommandClassId(), _instance, parameter, label, "", false, false, (int32)paramValue, 0 );
break;
}
default:
{
Log::Write( LogLevel_Info, GetNodeId(), "Invalid size of %d bytes for configuration parameter %d", size, parameter );
}
}
}
}
Log::Write( LogLevel_Info, GetNodeId(), "Received Configuration report: Parameter=%d, Value=%d", parameter, paramValue );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <Configuration::SetValue>
// Set a value in the Z-Wave device
//-----------------------------------------------------------------------------
bool Configuration::SetValue
(
Value const& _value
)
{
uint8 param = _value.GetID().GetIndex();
switch( _value.GetID().GetType() )
{
case ValueID::ValueType_Bool:
{
ValueBool const& valueBool = static_cast<ValueBool const&>( _value );
Set( param, (int32)valueBool.GetValue(), 1 );
return true;
}
case ValueID::ValueType_Byte:
{
ValueByte const& valueByte = static_cast<ValueByte const&>( _value );
Set( param, (int32)valueByte.GetValue(), 1 );
return true;
}
case ValueID::ValueType_Short:
{
ValueShort const& valueShort = static_cast<ValueShort const&>( _value );
Set( param, (int32)valueShort.GetValue(), 2 );
return true;
}
case ValueID::ValueType_Int:
{
ValueInt const& valueInt = static_cast<ValueInt const&>( _value );
Set( param, valueInt.GetValue(), 4 );
return true;
}
case ValueID::ValueType_List:
{
ValueList const& valueList = static_cast<ValueList const&>( _value );
Set( param, valueList.GetItem().m_value, valueList.GetSize() );
return true;
}
case ValueID::ValueType_Button:
{
ValueButton const& valueButton = static_cast<ValueButton const&>( _value );
Set( param, valueButton.IsPressed(), 1 );
return true;
}
default:
{
}
}
Log::Write( LogLevel_Info, GetNodeId(), "Configuration::Set failed (bad value or value type) - Parameter=%d", param );
return false;
}
//-----------------------------------------------------------------------------
// <Configuration::RequestValue>
// Request current parameter value from the device
//-----------------------------------------------------------------------------
bool Configuration::RequestValue
(
uint32 const _requestFlags,
uint8 const _parameter, // parameter number is encoded as the Index portion of ValueID
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _instance != 1 )
{
// This command class doesn't work with multiple instances
return false;
}
if ( IsGetSupported() )
{
Msg* msg = new Msg( "ConfigurationCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( ConfigurationCmd_Get );
msg->Append( _parameter );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "ConfigurationCmd_Get Not Supported on this node");
}
return false;
}
//-----------------------------------------------------------------------------
// <Configuration::Set>
// Set the device's
//-----------------------------------------------------------------------------
void Configuration::Set
(
uint8 const _parameter,
int32 const _value,
uint8 const _size
)
{
Log::Write( LogLevel_Info, GetNodeId(), "Configuration::Set - Parameter=%d, Value=%d Size=%d", _parameter, _value, _size );
Msg* msg = new Msg( "ConfigurationCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->Append( GetNodeId() );
msg->Append( 4 + _size );
msg->Append( GetCommandClassId() );
msg->Append( ConfigurationCmd_Set );
msg->Append( _parameter );
msg->Append( _size );
if( _size > 2 )
{
msg->Append( (uint8)( ( _value>>24 ) & 0xff ) );
msg->Append( (uint8)( ( _value>>16 ) & 0xff ) );
}
if( _size > 1 )
{
msg->Append( (uint8)( ( _value>>8 ) & 0xff ) );
}
msg->Append( (uint8)( _value & 0xff ) );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
}
@@ -0,0 +1,67 @@
//-----------------------------------------------------------------------------
//
// Configuration.h
//
// Implementation of the Z-Wave COMMAND_CLASS_CONFIGURATION
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _Configuration_H
#define _Configuration_H
#include <list>
#include "CommandClass.h"
namespace OpenZWave
{
class Value;
/** \brief Implements COMMAND_CLASS_CONFIGURATION (x70), a Z-Wave device command class.
*/
class Configuration: public CommandClass
{
friend class Node;
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Configuration( _homeId, _nodeId ); }
virtual ~Configuration(){}
static uint8 const StaticGetCommandClassId(){ return 0x70; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_CONFIGURATION"; }
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _parameter, uint8 const _index, Driver::MsgQueue const _queue );
void Set( uint8 const _parameter, int32 const _value, uint8 const _size );
// From CommandClass
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
private:
Configuration( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,326 @@
//-----------------------------------------------------------------------------
//
// ControllerReplication.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_CONTROLLER_REPLICATION
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "ControllerReplication.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Driver.h"
#include "../Node.h"
#include "../platform/Log.h"
#include "../value_classes/ValueByte.h"
#include "../value_classes/ValueList.h"
#include "../value_classes/ValueButton.h"
using namespace OpenZWave;
enum ControllerReplicationCmd
{
ControllerReplicationCmd_TransferGroup = 0x31,
ControllerReplicationCmd_TransferGroupName = 0x32,
ControllerReplicationCmd_TransferScene = 0x33,
ControllerReplicationCmd_TransferSceneName = 0x34
};
enum
{
ControllerReplicationIndex_NodeId = 0,
ControllerReplicationIndex_Function,
ControllerReplicationIndex_Replicate
};
static char const* c_controllerReplicationFunctionNames[] =
{
"Groups",
"Group Names",
"Scenes",
"Scene Names",
};
//-----------------------------------------------------------------------------
// <ControllerReplication::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
ControllerReplication::ControllerReplication
(
uint32 const _homeId,
uint8 const _nodeId
):
CommandClass( _homeId, _nodeId ),
m_busy( false ),
m_targetNodeId( 0 ),
m_funcId( 0 ),
m_nodeId( -1 ),
m_groupCount( -1 ),
m_groupIdx( -1 )
{
}
//-----------------------------------------------------------------------------
// <ControllerReplication::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool ControllerReplication::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
// When creating replication messages, use FUNC_ID_ZW_SEND_REPLICATION_DATA instead of FUNC_ID_ZW_SEND_DATA
// e.g. Msg* msg = new Msg( "TransferGroup", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_REPLICATION_DATA, true, false );
switch( _data[0] )
{
case ControllerReplicationCmd_TransferGroup:
{
break;
}
case ControllerReplicationCmd_TransferGroupName:
{
break;
}
case ControllerReplicationCmd_TransferScene:
{
break;
}
case ControllerReplicationCmd_TransferSceneName:
{
break;
}
}
Msg* msg = new Msg( "ControllerReplication Command Complete", GetNodeId(), REQUEST, FUNC_ID_ZW_REPLICATION_COMMAND_COMPLETE, false, false );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Command );
return true;
}
//-----------------------------------------------------------------------------
// <ControllerReplication::SetValue>
// Set a value on the Z-Wave device
//-----------------------------------------------------------------------------
bool ControllerReplication::SetValue
(
Value const& _value
)
{
bool res = false;
uint8 instance = _value.GetID().GetInstance();
switch( _value.GetID().GetIndex() )
{
case ControllerReplicationIndex_NodeId:
{
if( ValueByte* value = static_cast<ValueByte*>( GetValue( instance, ControllerReplicationIndex_NodeId ) ) )
{
value->OnValueRefreshed( (static_cast<ValueByte const*>( &_value))->GetValue() );
value->Release();
res = true;
}
break;
}
case ControllerReplicationIndex_Function:
{
if( ValueList* value = static_cast<ValueList*>( GetValue( instance, ControllerReplicationIndex_Function ) ) )
{
ValueList::Item const& item = (static_cast<ValueList const*>( &_value))->GetItem();
value->OnValueRefreshed( item.m_value );
value->Release();
res = true;
}
break;
}
case ControllerReplicationIndex_Replicate:
{
if( ValueButton* button = static_cast<ValueButton*>( GetValue( instance, ControllerReplicationIndex_Replicate ) ) )
{
if( button->IsPressed() )
{
res = StartReplication( instance );
}
button->Release();
}
break;
}
}
return res;
}
//-----------------------------------------------------------------------------
// <ControllerReplication::StartReplication>
// Set up the group and scene data to be sent to the other controller
//-----------------------------------------------------------------------------
bool ControllerReplication::StartReplication
(
uint8 const _instance
)
{
if( m_busy )
{
return false;
}
if( ValueByte* value = static_cast<ValueByte*>( GetValue( _instance, ControllerReplicationIndex_NodeId ) ) )
{
m_targetNodeId = value->GetValue();
value->Release();
}
else
{
return false;
}
if( ValueList* value = static_cast<ValueList*>( GetValue( _instance, ControllerReplicationIndex_Function ) ) )
{
ValueList::Item const& item = value->GetItem();
m_funcId = item.m_value;
value->Release();
}
else
{
return false;
}
// Store the Z-Wave command we should use when replication has completed.
m_nodeId = -1;
m_groupCount = -1;
m_groupIdx = -1;
m_busy = true;
// Set up the groups and scenes to be sent
SendNextData();
return true;
}
//-----------------------------------------------------------------------------
// <ControllerReplication::SendNextData>
// Send the next block of replication data
//-----------------------------------------------------------------------------
void ControllerReplication::SendNextData
(
)
{
uint16 i = 255;
if( !m_busy )
{
return;
}
while( 1 )
{
if( m_groupIdx != -1 )
{
m_groupIdx++;
if( m_groupIdx <= m_groupCount )
{
break;
}
}
i = m_nodeId == -1 ? 0 : m_nodeId+1;
GetDriver()->LockNodes();
while( i < 256 )
{
if( GetDriver()->m_nodes[i] )
{
m_groupCount = GetDriver()->m_nodes[i]->GetNumGroups();
if( m_groupCount != 0 )
{
m_groupName = GetDriver()->m_nodes[i]->GetGroupLabel( m_groupIdx );
m_groupIdx = m_groupName.length() > 0 ? 0 : 1;
break;
}
}
i++;
}
GetDriver()->ReleaseNodes();
m_nodeId = i;
break;
}
if( i < 255 )
{
Msg* msg = new Msg( "Replication Send", m_targetNodeId, REQUEST, FUNC_ID_ZW_REPLICATION_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( m_targetNodeId );
if( m_groupName.length() > 0 )
{
msg->Append((uint8) (m_groupName.length() + 4 ));
msg->Append( GetCommandClassId() );
msg->Append( ControllerReplicationCmd_TransferGroupName );
msg->Append( 0 );
msg->Append( m_groupIdx );
for( uint8 j = 0; j < m_groupName.length(); j++ )
{
msg->Append( m_groupName[j] );
}
m_groupName = "";
}
else
{
msg->Append( 5 );
msg->Append( GetCommandClassId() );
msg->Append( ControllerReplicationCmd_TransferGroup );
msg->Append( 0 );
msg->Append( m_groupIdx );
msg->Append( m_nodeId );
}
msg->Append( TRANSMIT_OPTION_ACK );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Command );
}
else
{
GetDriver()->AddNodeStop( m_funcId );
m_busy = false;
}
}
//-----------------------------------------------------------------------------
// <ControllerReplication::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void ControllerReplication::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueByte( ValueID::ValueGenre_System, GetCommandClassId(), _instance, ControllerReplicationIndex_NodeId, "Node", "", false, false, 0, 0 );
vector<ValueList::Item> items;
ValueList::Item item;
for( uint8 i=0; i<4; ++i )
{
item.m_label = c_controllerReplicationFunctionNames[i];
item.m_value = ControllerReplicationCmd_TransferGroup + i;
items.push_back( item );
}
node->CreateValueList( ValueID::ValueGenre_System, GetCommandClassId(), _instance, ControllerReplicationIndex_Function, "Functions", "", false, false, 1, items, 0, 0 );
node->CreateValueButton( ValueID::ValueGenre_System, GetCommandClassId(), _instance, ControllerReplicationIndex_Replicate, "Replicate", 0 );
}
}
@@ -0,0 +1,74 @@
//-----------------------------------------------------------------------------
//
// ControllerReplication.h
//
// Implementation of the Z-Wave COMMAND_CLASS_CONTROLLER_REPLICATION
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _ControllerReplication_H
#define _ControllerReplication_H
#include "CommandClass.h"
namespace OpenZWave
{
/** \brief Implements COMMAND_CLASS_CONTROLLER_REPLICATION (0x21), a Z-Wave device command class.
*/
class ControllerReplication: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ControllerReplication( _homeId, _nodeId ); }
virtual ~ControllerReplication(){}
static uint8 const StaticGetCommandClassId(){ return 0x21; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_CONTROLLER_REPLICATION"; }
// From CommandClass
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
void SendNextData();
protected:
virtual void CreateVars( uint8 const _instance );
private:
ControllerReplication( uint32 const _homeId, uint8 const _nodeId );
bool StartReplication( uint8 const _instance );
bool m_busy;
uint8 m_targetNodeId;
uint8 m_funcId;
int m_nodeId;
int m_groupCount;
int m_groupIdx;
string m_groupName;
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,586 @@
//-----------------------------------------------------------------------------
//
// DoorLock.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_DOOR_LOCK
//
// Copyright (c) 2014 Justin Hammond <justin@dynam.ac>
//
// 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 "CommandClasses.h"
#include "DoorLock.h"
#include "WakeUp.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueBool.h"
#include "../value_classes/ValueByte.h"
#include "../value_classes/ValueInt.h"
#include "../tinyxml.h"
using namespace OpenZWave;
enum DoorLockCmd
{
DoorLockCmd_Set = 0x01,
DoorLockCmd_Get = 0x02,
DoorLockCmd_Report = 0x03,
DoorLockCmd_Configuration_Set = 0x04,
DoorLockCmd_Configuration_Get = 0x05,
DoorLockCmd_Configuration_Report= 0x06
};
enum TimeOutMode
{
DoorLockConfig_NoTimeout = 0x01,
DoorLockConfig_Timeout = 0x02
};
static char const* c_TimeOutModeNames[] =
{
"No Timeout",
"Secure Lock after Timeout"
};
enum DoorLockControlState
{
DoorLockControlState_Handle1 = 0x01,
DoorLockControlState_Handle2 = 0x02,
DoorLockControlState_Handle3 = 0x04,
DoorLockControlState_Handle4 = 0x08
};
enum ValueIDSystemIndexes
{
Value_Lock = 0x00, /* Simple On/Off Mode for Lock */
Value_Lock_Mode = 0x01, /* To Set more Complex Lock Modes (Such as timeouts etc) */
Value_System_Config_Mode = 0x02, /* To Set/Unset if Locks should return to Secured Mode after a timeout */
Value_System_Config_Minutes = 0x03, /* If Timeouts are enabled, how many minutes before a Lock "AutoLocks" */
Value_System_Config_Seconds = 0x04, /* If Timeouts are enabled, how many seconds beofre a Lock "Autolocks" */
Value_System_Config_OutsideHandles = 0x05, /* What Outside Handles are controlled via Z-Wave (BitMask 1-4) */
Value_System_Config_InsideHandles = 0x06, /* What inside Handles are control via ZWave (BitMask 1-4) */
};
enum DoorLockState
{
DoorLockState_Unsecured = 0x00,
DoorLockState_Unsecured_Timeout = 0x01,
DoorLockState_Inside_Unsecured = 0x10,
DoorLockState_Inside_Unsecured_Timeout = 0x11,
DoorLockState_Outside_Unsecured = 0x20,
DoorLockState_Outside_Unsecured_Timeout = 0x21,
DoorLockState_Secured = 0xFF
};
static char const* c_LockStateNames[] =
{
"Unsecure",
"Unsecured with Timeout",
"Inside Handle Unsecured",
"Inside Handle Unsecured with Timeout",
"Outside Handle Unsecured",
"Outside Handle Unsecured with Timeout",
"Secured",
"Invalid"
};
//-----------------------------------------------------------------------------
// <DoorLock::DoorLock>
// Constructor
//-----------------------------------------------------------------------------
DoorLock::DoorLock
(
uint32 const _homeId,
uint8 const _nodeId
):
CommandClass( _homeId, _nodeId ),
m_timeoutsupported(0),
m_insidehandlemode(0),
m_outsidehandlemode(0),
m_timeoutmins(0xFE),
m_timeoutsecs(0xFE)
{
SetStaticRequest( StaticRequest_Values );
}
//-----------------------------------------------------------------------------
// <UserCode::ReadXML>
// Class specific configuration
//-----------------------------------------------------------------------------
void DoorLock::ReadXML
(
TiXmlElement const* _ccElement
)
{
int32 intVal;
CommandClass::ReadXML( _ccElement );
if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "m_timeoutsupported", &intVal ) )
{
m_timeoutsupported = intVal;
}
if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "m_insidehandlemode", &intVal ) )
{
m_insidehandlemode = intVal;
}
if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "m_outsidehandlemode", &intVal ) )
{
m_outsidehandlemode = intVal;
}
if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "m_timeoutmins", &intVal ) )
{
m_timeoutmins = intVal;
}
if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "m_timeoutsecs", &intVal ) )
{
m_timeoutsecs = intVal;
}
}
//-----------------------------------------------------------------------------
// <UserCode::WriteXML>
// Class specific configuration
//-----------------------------------------------------------------------------
void DoorLock::WriteXML
(
TiXmlElement* _ccElement
)
{
char str[32];
CommandClass::WriteXML( _ccElement );
snprintf( str, sizeof(str), "%d", m_timeoutsupported );
_ccElement->SetAttribute( "m_timeoutsupported", str);
snprintf( str, sizeof(str), "%d", m_insidehandlemode );
_ccElement->SetAttribute( "m_insidehandlemode", str);
snprintf( str, sizeof(str), "%d", m_outsidehandlemode );
_ccElement->SetAttribute( "m_outsidehandlemode", str);
snprintf( str, sizeof(str), "%d", m_timeoutmins );
_ccElement->SetAttribute( "m_timeoutmins", str);
snprintf( str, sizeof(str), "%d", m_timeoutsecs );
_ccElement->SetAttribute( "m_timeoutsecs", str);
}
//-----------------------------------------------------------------------------
// <DoorLock::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool DoorLock::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
bool requests = false;
if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) )
{
requests = RequestValue( _requestFlags, Value_System_Config_Mode, _instance, _queue );
}
if( _requestFlags & RequestFlag_Dynamic )
{
requests |= RequestValue( _requestFlags, Value_Lock, _instance, _queue );
}
return requests;
}
//-----------------------------------------------------------------------------
// <DoorLock::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool DoorLock::RequestValue
(
uint32 const _requestFlags,
uint8 const _what,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if ( _what >= Value_System_Config_Mode) {
Msg* msg = new Msg( "DoorLockCmd_Configuration_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( DoorLockCmd_Configuration_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else if ((_what == Value_Lock) || (_what == Value_Lock_Mode)) {
if ( IsGetSupported() )
{
Msg* msg = new Msg( "DoorLockCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( DoorLockCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "DoorLockCmd_Get Not Supported on this node");
}
}
return false;
}
//-----------------------------------------------------------------------------
// <DoorLock::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool DoorLock::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( DoorLockCmd_Report == (DoorLockCmd)_data[0] )
{
uint8 lockState = (_data[1] == 0xFF) ? 6 : _data[1];
if (lockState > 6) /* size of c_LockStateNames minus Invalid Entry */
{
Log::Write (LogLevel_Warning, GetNodeId(), "LockState Value was greater than range. Setting to Invalid");
lockState = 7;
}
Log::Write( LogLevel_Info, GetNodeId(), "Received DoorLock report: DoorLock is %s", c_LockStateNames[lockState] );
if( ValueBool* value = static_cast<ValueBool*>( GetValue( _instance, Value_Lock ) ) )
{
value->OnValueRefreshed( lockState == 0xFF );
value->Release();
}
if( ValueList* value = static_cast<ValueList*>( GetValue( _instance, Value_Lock_Mode ) ) )
{
value->OnValueRefreshed( lockState);
value->Release();
}
return true;
} else if (DoorLockCmd_Configuration_Report == (DoorLockCmd)_data[0] )
{
switch (_data[1]) {
case DoorLockConfig_NoTimeout:
m_timeoutsupported = DoorLockConfig_NoTimeout;
RemoveValue(_instance, Value_System_Config_Minutes);
RemoveValue(_instance, Value_System_Config_Seconds);
m_timeoutmins = 0xFE;
m_timeoutsecs = 0xFE;
break;
case DoorLockConfig_Timeout:
/* if we have a timeout, then create the Values for the timeout config */
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueInt( ValueID::ValueGenre_System, GetCommandClassId(), _instance, Value_System_Config_Minutes, "Timeout Minutes", "Mins", false, false, _data[3], 0 );
node->CreateValueInt( ValueID::ValueGenre_System, GetCommandClassId(), _instance, Value_System_Config_Seconds, "Timeout Seconds", "Secs", false, false, _data[4], 0 );
}
m_timeoutsupported = DoorLockConfig_Timeout;
m_timeoutmins = _data[3];
m_timeoutsecs = _data[4];
break;
default:
Log::Write(LogLevel_Warning, GetNodeId(), "Recieved a Unsupported Door Lock Config Report %d", _data[1]);
}
if( ValueByte* value = static_cast<ValueByte*>( GetValue( _instance, Value_System_Config_OutsideHandles ) ) )
{
value->OnValueRefreshed( ((_data[2] & 0xF0)>>4) );
value->Release();
m_outsidehandlemode = ((_data[2] & 0xF0)>>4);
}
if( ValueByte* value = static_cast<ValueByte*>( GetValue( _instance, Value_System_Config_InsideHandles ) ) )
{
value->OnValueRefreshed( (_data[2] & 0x0F) );
value->Release();
m_insidehandlemode = (_data[2] & 0x0F);
}
ClearStaticRequest( StaticRequest_Values );
}
return false;
}
//-----------------------------------------------------------------------------
// <DoorLock::SetValue>
// Set the lock's state
//-----------------------------------------------------------------------------
bool DoorLock::SetValue
(
Value const& _value
)
{
uint8 instance = _value.GetID().GetInstance();
if( (Value_Lock == _value.GetID().GetIndex()) && ValueID::ValueType_Bool == _value.GetID().GetType() )
{
ValueBool const* value = static_cast<ValueBool const*>(&_value);
Log::Write( LogLevel_Info, GetNodeId(), "Value_Lock::Set - Requesting lock to be %s", value->GetValue() ? "Locked" : "Unlocked" );
Msg* msg = new Msg( "DoorLockCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _value.GetID().GetInstance() );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( DoorLockCmd_Set );
msg->Append( value->GetValue() ? 0xFF:0x00 );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
if ( (Value_Lock_Mode == _value.GetID().GetIndex()) && (ValueID::ValueType_List == _value.GetID().GetType()) )
{
ValueList const* value = static_cast<ValueList const*>(&_value);
ValueList::Item const& item = value->GetItem();
Log::Write( LogLevel_Info, GetNodeId(), "Value_Lock_Mode::Set - Requesting lock to be %s", item.m_label.c_str() );
Msg* msg = new Msg( "DoorLockCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _value.GetID().GetInstance() );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( DoorLockCmd_Set );
msg->Append( item.m_value );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
/* if its any of our System Messages.... */
if ( Value_System_Config_Mode >= _value.GetID().GetIndex() )
{
bool sendmsg = true;
switch (_value.GetID().GetIndex()) {
/* this is a List */
case Value_System_Config_Mode:
if (ValueID::ValueType_List != _value.GetID().GetType()) {
sendmsg = false;
break;
}
if( ValueList* value = static_cast<ValueList*>( GetValue( instance, _value.GetID().GetIndex() ) ) )
{
ValueList::Item const& item = (static_cast<ValueList const*>( &_value))->GetItem();
value->OnValueRefreshed( item.m_value );
value->Release();
}
break;
/* these are a int */
case Value_System_Config_Minutes:
case Value_System_Config_Seconds:
if (ValueID::ValueType_Int != _value.GetID().GetType()) {
sendmsg = false;
break;
}
if( ValueInt* value = static_cast<ValueInt*>( GetValue( instance, _value.GetID().GetIndex() ) ) )
{
value->OnValueRefreshed( (static_cast<ValueInt const*>( &_value))->GetValue() );
value->Release();
}
break;
/* these are a byte */
case Value_System_Config_OutsideHandles:
case Value_System_Config_InsideHandles:
if (ValueID::ValueType_Byte != _value.GetID().GetType()) {
sendmsg = false;
break;
}
if( ValueByte* value = static_cast<ValueByte*>( GetValue( instance, _value.GetID().GetIndex() ) ) )
{
value->OnValueRefreshed( (static_cast<ValueByte const*>( &_value))->GetValue() );
value->Release();
}
break;
default:
Log::Write(LogLevel_Warning, GetNodeId(), "DoorLock::SetValue - Unhandled System_Config Variable %d", _value.GetID().GetIndex());
sendmsg = false;
break;
}
if (sendmsg)
{
bool ok = true;
if( ValueList* value = static_cast<ValueList*>( GetValue( instance, Value_System_Config_Mode ) ) ) {
ValueList::Item const& item = value->GetItem();
m_timeoutsupported = item.m_value;
} else {
ok = false;
Log::Write(LogLevel_Warning, GetNodeId(), "Failed To Retrieve Value_System_Config_Mode For SetValue");
}
uint8 control = 0;
if( ValueByte* value = static_cast<ValueByte*>( GetValue( instance, Value_System_Config_OutsideHandles ) ) )
{
control = (value->GetValue() << 4);
m_insidehandlemode = control;
} else {
ok = false;
Log::Write(LogLevel_Warning, GetNodeId(), "Failed To Retrieve Value_System_Config_OutsideHandles For SetValue");
}
if( ValueByte* value = static_cast<ValueByte*>( GetValue( instance, Value_System_Config_InsideHandles ) ) )
{
control += (value->GetValue() & 0x0F);
m_outsidehandlemode = (value->GetValue() & 0x0F);
} else {
ok = false;
Log::Write(LogLevel_Warning, GetNodeId(), "Failed To Retrieve Value_System_Config_InsideHandles For SetValue");
}
if( ValueInt* value = static_cast<ValueInt*>( GetValue( instance, Value_System_Config_Minutes ) ) )
{
m_timeoutmins = value->GetValue();
} else {
/* Minutes and Seconds Might Not Exist, this is fine. Set to 0xFE */
m_timeoutmins = 0xFE;
}
if( ValueInt* value = static_cast<ValueInt*>( GetValue( instance, Value_System_Config_Seconds ) ) )
{
m_timeoutsecs = value->GetValue();
} else {
/* Minutes and Seconds Might Not Exist, this is fine. Set to 0xFE */
m_timeoutsecs = 0xFE;
}
if (ok) {
Msg* msg = new Msg( "DoorLockCmd_Configuration_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _value.GetID().GetInstance() );
msg->Append( GetNodeId() );
msg->Append( 6 );
msg->Append( GetCommandClassId() );
msg->Append( DoorLockCmd_Configuration_Set );
msg->Append( m_timeoutsupported );
msg->Append( control );
msg->Append( m_timeoutmins );
msg->Append( m_timeoutsecs );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
return false;
}
}
return false;
}
//-----------------------------------------------------------------------------
// <DoorLock::SetValueBasic>
// Update class values based in BASIC mapping
//-----------------------------------------------------------------------------
void DoorLock::SetValueBasic
(
uint8 const _instance,
uint8 const _value
)
{
// Send a request for new value to synchronize it with the BASIC set/report.
// In case the device is sleeping, we set the value anyway so the BASIC set/report
// stays in sync with it. We must be careful mapping the uint8 BASIC value
// into a class specific value.
// When the device wakes up, the real requested value will be retrieved.
RequestValue( 0, DoorLockCmd_Get, _instance, Driver::MsgQueue_Send );
if( Node* node = GetNodeUnsafe() )
{
if( WakeUp* wakeUp = static_cast<WakeUp*>( node->GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) )
{
if( !wakeUp->IsAwake() )
{
if( ValueBool* value = static_cast<ValueBool*>( GetValue( _instance, Value_Lock ) ) )
{
value->OnValueRefreshed( _value != 0 );
value->Release();
}
}
}
}
}
//-----------------------------------------------------------------------------
// <DoorLock::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void DoorLock::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueBool( ValueID::ValueGenre_User, GetCommandClassId(), _instance, Value_Lock, "Locked", "", false, false, false, 0 );
/* Complex Lock Option */
{
vector<ValueList::Item> items;
ValueList::Item item;
for( uint8 i=0; i<8; ++i )
{
item.m_label = c_LockStateNames[i];
item.m_value = (i < 6) ? i : 0xFF;
items.push_back( item );
}
node->CreateValueList( ValueID::ValueGenre_User, GetCommandClassId(), _instance, Value_Lock_Mode, "Locked (Advanced)", "", false, false, 1, items, 0, 0 );
}
/* Timeout mode for Locks that support it */
{
vector<ValueList::Item> items;
ValueList::Item item;
for( uint8 i=0; i<2; ++i )
{
item.m_label = c_TimeOutModeNames[i];
item.m_value = i+1;
items.push_back( item );
}
node->CreateValueList( ValueID::ValueGenre_System, GetCommandClassId(), _instance, Value_System_Config_Mode, "Timeout Mode", "", false, false, 1, items, 0, 0 );
}
node->CreateValueByte( ValueID::ValueGenre_System, GetCommandClassId(), _instance, Value_System_Config_OutsideHandles, "Outside Handle Control", "", false, false, 0x0F, 0 );
node->CreateValueByte( ValueID::ValueGenre_System, GetCommandClassId(), _instance, Value_System_Config_InsideHandles, "Inside Handle Control", "", false, false, 0x0F, 0 );
}
}
@@ -0,0 +1,76 @@
//-----------------------------------------------------------------------------
//
// DoorLock.h
//
// Implementation of the Z-Wave COMMAND_CLASS_DOOR_LOCK
//
// Copyright (c) 2014 Justin Hammond <justin@dynam.ac>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _DoorLock_H
#define _DoorLock_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueBool;
/** \brief Implements COMMAND_CLASS_DOOR_LOCK (0x62), a Z-Wave device command class.
*/
class DoorLock: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new DoorLock( _homeId, _nodeId ); }
virtual ~DoorLock(){}
static uint8 const StaticGetCommandClassId(){ return 0x62; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_DOOR_LOCK"; }
// From CommandClass
virtual void ReadXML( TiXmlElement const* _ccElement );
virtual void WriteXML( TiXmlElement* _ccElement );
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
virtual void SetValueBasic( uint8 const _instance, uint8 const _value );
protected:
virtual void CreateVars( uint8 const _instance );
private:
DoorLock( uint32 const _homeId, uint8 const _nodeId );
uint8 m_timeoutsupported;
uint8 m_insidehandlemode;
uint8 m_outsidehandlemode;
uint8 m_timeoutmins;
uint8 m_timeoutsecs;
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,375 @@
//-----------------------------------------------------------------------------
//
// DoorLockLogging.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_DOOR_LOCK_LOGGING
//
// Copyright (c) 2014 Justin Hammond <justin@dynam.ac>
//
// 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 "CommandClasses.h"
#include "DoorLockLogging.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueBool.h"
#include "../value_classes/ValueByte.h"
#include "../value_classes/ValueInt.h"
#include "../value_classes/ValueString.h"
#include "../tinyxml.h"
using namespace OpenZWave;
enum DoorLockLoggingCmd
{
DoorLockLoggingCmd_RecordSupported_Get = 0x01,
DoorLockLoggingCmd_RecordSupported_Report = 0x02,
DoorLockLoggingCmd_Record_Get = 0x03,
DoorLockLoggingCmd_Record_Report = 0x04
};
enum DoorLockEventType
{
DoorLockEventType_LockCode = 0x01,
DoorLockEventType_UnLockCode = 0x02,
DoorLockEventType_LockButton = 0x03,
DoorLockEventType_UnLockButton = 0x04,
DoorLockEventType_LockCodeOOSchedule = 0x05,
DoorLockEventType_UnLockCodeOOSchedule = 0x06,
DoorLockEventType_IllegalCode = 0x07,
DoorLockEventType_LockManual = 0x08,
DoorLockEventType_UnLockManual = 0x09,
DoorLockEventType_LockAuto = 0x0A,
DoorLockEventType_UnLockAuto = 0x0B,
DoorLockEventType_LockRemoteCode = 0x0C,
DoorLockEventType_UnLockRemoteCode = 0x0D,
DoorLockEventType_LockRemote = 0x0E,
DoorLockEventType_UnLockRemote = 0x0F,
DoorLockEventType_LockRemoteCodeOOSchedule = 0x10,
DoorLockEventType_UnLockRemoteCodeOOSchedule = 0x11,
DoorLockEventType_RemoteIllegalCode = 0x12,
DoorLockEventType_LockManual2 = 0x13,
DoorLockEventType_UnlockManual2 = 0x14,
DoorLockEventType_LockSecured = 0x15,
DoorLockEventType_LockUnsecured = 0x16,
DoorLockEventType_UserCodeAdded = 0x17,
DoorLockEventType_UserCodeDeleted = 0x18,
DoorLockEventType_AllUserCodesDeleted = 0x19,
DoorLockEventType_MasterCodeChanged = 0x1A,
DoorLockEventType_UserCodeChanged = 0x1B,
DoorLockEventType_LockReset = 0x1C,
DoorLockEventType_ConfigurationChanged = 0x1D,
DoorLockEventType_LowBattery = 0x1E,
DoorLockEventType_NewBattery = 0x1F,
DoorLockEventType_Max = 0x20
};
static char const* c_DoorLockEventType[] =
{
"Locked via Access Code",
"Unlocked via Access Code",
"Locked via Lock Button",
"Unlocked via UnLock Botton",
"Lock Attempt via Out of Schedule Access Code",
"Unlock Attemp via Out of Schedule Access Code",
"Illegal Access Code Entered",
"Manually Locked",
"Manually UnLocked",
"Auto Locked",
"Auto Unlocked",
"Locked via Remote Out of Schedule Access Code",
"Unlocked via Remote Out of Schedule Access Code",
"Locked via Remote",
"Unlocked via Remote",
"Lock Attempt via Remote Out of Schedule Access Code",
"Unlock Attempt via Remote Out of Schedule Access Code",
"Illegal Remote Access Code",
"Manually Locked (2)",
"Manually Unlocked (2)",
"Lock Secured",
"Lock Unsecured",
"User Code Added",
"User Code Deleted",
"All User Codes Deleted",
"Master Code Changed",
"User Code Changed",
"Lock Reset",
"Configuration Changed",
"Low Battery",
"New Battery Installed",
"Unknown"
};
/* size = 31 entries */
enum ValueIDSystemIndexes
{
Value_System_Config_MaxRecords = 0x00, /* Max Number of Records the Device can Hold */
Value_GetRecordNo = 0x01, /* Current Record Number after refresh */
Value_LogRecord = 0x02 /* Simple String Representation of the Log Record - Tab Delimited Fields */
};
//-----------------------------------------------------------------------------
// <DoorLockLogging::DoorLockLogging>
// Constructor
//-----------------------------------------------------------------------------
DoorLockLogging::DoorLockLogging
(
uint32 const _homeId,
uint8 const _nodeId
):
CommandClass( _homeId, _nodeId ),
m_MaxRecords(0),
m_CurRecord(0)
{
SetStaticRequest( StaticRequest_Values );
}
//-----------------------------------------------------------------------------
// <UserCode::ReadXML>
// Class specific configuration
//-----------------------------------------------------------------------------
void DoorLockLogging::ReadXML
(
TiXmlElement const* _ccElement
)
{
int32 intVal;
CommandClass::ReadXML( _ccElement );
if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "m_MaxRecords", &intVal ) )
{
m_MaxRecords = intVal;
}
}
//-----------------------------------------------------------------------------
// <UserCode::WriteXML>
// Class specific configuration
//-----------------------------------------------------------------------------
void DoorLockLogging::WriteXML
(
TiXmlElement* _ccElement
)
{
char str[32];
CommandClass::WriteXML( _ccElement );
snprintf( str, sizeof(str), "%d", m_MaxRecords );
_ccElement->SetAttribute( "m_MaxRecords", str);
}
//-----------------------------------------------------------------------------
// <DoorLockLogging::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool DoorLockLogging::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
bool requests = false;
if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) )
{
requests = RequestValue( _requestFlags, DoorLockLoggingCmd_RecordSupported_Get, _instance, _queue );
}
if( _requestFlags & RequestFlag_Dynamic )
{
requests |= RequestValue( _requestFlags, DoorLockLoggingCmd_Record_Get, _instance, _queue );
}
return requests;
}
//-----------------------------------------------------------------------------
// <DoorLockLogging::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool DoorLockLogging::RequestValue
(
uint32 const _requestFlags,
uint8 const _what,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if ( _what == DoorLockLoggingCmd_RecordSupported_Get) {
Msg* msg = new Msg( "DoorLockLoggingCmd_RecordSupported_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( DoorLockLoggingCmd_RecordSupported_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else if (_what == DoorLockLoggingCmd_Record_Get) {
Msg* msg = new Msg( "DoorLockLoggingCmd_Record_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( DoorLockLoggingCmd_Record_Get );
msg->Append( m_CurRecord );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <DoorLockLogging::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool DoorLockLogging::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( DoorLockLoggingCmd_RecordSupported_Report == (DoorLockLoggingCmd)_data[0] )
{
Log::Write( LogLevel_Info, GetNodeId(), "Received DoorLockLoggingCmd_RecordSupported_Report: Max Records is %d ", _data[1]);
if( ValueByte* value = static_cast<ValueByte*>( GetValue( _instance, Value_System_Config_MaxRecords ) ) )
{
value->OnValueRefreshed( _data[1]);
value->Release();
}
ClearStaticRequest( StaticRequest_Values );
return true;
} else if (DoorLockLoggingCmd_Record_Report == (DoorLockLoggingCmd)_data[0] )
{
uint8 EventType = _data[9];
if (EventType >= DoorLockEventType_Max)
EventType = DoorLockEventType_Max;
Log::Write (LogLevel_Info, GetNodeId(), "Recieved a DoorLockLogging Record %d which is \"%s\"", _data[1], c_DoorLockEventType[EventType-1]);
if( ValueByte* value = static_cast<ValueByte*>( GetValue( _instance, Value_GetRecordNo ) ) )
{
value->OnValueRefreshed( _data[1]);
value->Release();
}
if( ValueString* value = static_cast<ValueString*>( GetValue( _instance, Value_LogRecord ) ) )
{
char msg[512];
uint16 year = (_data[2] << 8) + (_data[3] & 0xFF);
uint8 month = (_data[4] & 0x0F);
uint8 day = (_data[5] & 0x1F);
uint8 hour = (_data[6] & 0x1F);
uint8 minute = (_data[7] & 0x3F);
uint8 second = (_data[8] & 0x3F);
bool valid = false;
if (((_data[6] & 0xE0) >> 5) > 0)
{
valid = true;
}
uint8 userid = (_data[10]);
uint8 usercodelength = (_data[11]);
char usercode[254];
snprintf(usercode, sizeof(usercode), "UserCode:");
if (usercodelength > 0)
for (int i = 0; i < usercodelength; i++ )
{
snprintf(usercode, sizeof(usercode), "%s %d", usercode, (int)_data[12+i]);
}
if (valid) {
snprintf(msg, sizeof(msg), "%02d/%02d/%02d %02d:%02d:%02d \tMessage: %s \tUserID: %d \t%s", (int)day, (int)month, (int)year, (int)hour, (int)minute, (int)second, c_DoorLockEventType[EventType], (int)userid, usercode);
} else
snprintf(msg, sizeof(msg), "Invalid Record");
value->OnValueRefreshed(msg);
value->Release();
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <DoorLockLogging::SetValue>
// Set the lock's state
//-----------------------------------------------------------------------------
bool DoorLockLogging::SetValue
(
Value const& _value
)
{
if( (Value_GetRecordNo == _value.GetID().GetIndex()) && ValueID::ValueType_Byte == _value.GetID().GetType() )
{
ValueByte const* value = static_cast<ValueByte const*>(&_value);
Log::Write( LogLevel_Info, GetNodeId(), "DoorLockLoggingCmd_Record_Get - Requesting Log Record %d", value->GetValue() );
Msg* msg = new Msg( "DoorLockLoggingCmd_Record_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _value.GetID().GetInstance() );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( DoorLockLoggingCmd_Record_Get );
msg->Append( value->GetValue() );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
m_CurRecord = value->GetValue();
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <DoorLockLogging::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void DoorLockLogging::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueByte( ValueID::ValueGenre_System, GetCommandClassId(), _instance, Value_System_Config_MaxRecords, "Max Number of Records", "", true, false, 0x0, 0 );
node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, Value_GetRecordNo, "Current Record Number", "", false, false, 0x0, 0 );
node->CreateValueString( ValueID::ValueGenre_User, GetCommandClassId(), _instance, Value_LogRecord, "Log Record", "", true, false, "", 0 );
}
}
@@ -0,0 +1,69 @@
//-----------------------------------------------------------------------------
//
// DoorLockLogging.h
//
// Implementation of the Z-Wave COMMAND_CLASS_DOOR_LOCK_LOGGING
//
// Copyright (c) 2014 Justin Hammond <justin@dynam.ac>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _DoorLockLogging_H
#define _DoorLockLogging_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueBool;
/** \brief Implements COMMAND_CLASS_DOOR_LOCK_LOGGING (0x4C), a Z-Wave device command class.
*/
class DoorLockLogging: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new DoorLockLogging( _homeId, _nodeId ); }
virtual ~DoorLockLogging(){}
static uint8 const StaticGetCommandClassId(){ return 0x4c; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_DOOR_LOCK_LOGGING"; }
// From CommandClass
virtual void ReadXML( TiXmlElement const* _ccElement );
virtual void WriteXML( TiXmlElement* _ccElement );
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
protected:
virtual void CreateVars( uint8 const _instance );
private:
DoorLockLogging( uint32 const _homeId, uint8 const _nodeId );
uint8 m_MaxRecords;
uint8 m_CurRecord;
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,180 @@
//-----------------------------------------------------------------------------
//
// EnergyProduction.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_ENERGY_PRODUCTION
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "EnergyProduction.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueDecimal.h"
using namespace OpenZWave;
enum EnergyProductionCmd
{
EnergyProductionCmd_Get = 0x02,
EnergyProductionCmd_Report = 0x03
};
enum
{
EnergyProductionIndex_Instant = 0,
EnergyProductionIndex_Total,
EnergyProductionIndex_Today,
EnergyProductionIndex_Time
};
static char const* c_energyParameterNames[] =
{
"Instant energy production",
"Total energy production",
"Energy production today",
"Total production time"
};
//-----------------------------------------------------------------------------
// <EnergyProduction::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool EnergyProduction::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
bool request = false;
if( _requestFlags & RequestFlag_Dynamic )
{
// Request each of the production values
request |= RequestValue( _requestFlags, EnergyProductionIndex_Instant, _instance, _queue );
request |= RequestValue( _requestFlags, EnergyProductionIndex_Total, _instance, _queue );
request |= RequestValue( _requestFlags, EnergyProductionIndex_Today, _instance, _queue );
request |= RequestValue( _requestFlags, EnergyProductionIndex_Time, _instance, _queue );
}
return request;
}
//-----------------------------------------------------------------------------
// <EnergyProduction::RequestValue>
// Request current production from the device
//-----------------------------------------------------------------------------
bool EnergyProduction::RequestValue
(
uint32 const _requestFlags,
uint8 const _valueEnum, // one of EnergyProductionIndex enums
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if (_valueEnum > EnergyProductionIndex_Time)
{
Log::Write (LogLevel_Warning, GetNodeId(), "RequestValue _valueEnum was greater than range. Dropping");
return false;
}
if ( IsGetSupported() )
{
Log::Write( LogLevel_Info, GetNodeId(), "Requesting the %s value", c_energyParameterNames[_valueEnum] );
Msg* msg = new Msg( "EnergyProductionCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( EnergyProductionCmd_Get );
msg->Append( _valueEnum );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "EnergyProductionCmd_Get Not Supported on this node");
}
return false;
}
//-----------------------------------------------------------------------------
// <EnergyProduction::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool EnergyProduction::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if (EnergyProductionCmd_Report == (EnergyProductionCmd)_data[0])
{
uint8 scale;
uint8 precision = 0;
string value = ExtractValue( &_data[2], &scale, &precision );
uint8 paramType = _data[1];
if (paramType > 4) /* size of c_energyParameterNames minus Invalid Entry*/
{
Log::Write (LogLevel_Warning, GetNodeId(), "paramType Value was greater than range. Dropping Message");
return false;
}
Log::Write( LogLevel_Info, GetNodeId(), "Received an Energy production report: %s = %s", c_energyParameterNames[_data[1]], value.c_str() );
if( ValueDecimal* decimalValue = static_cast<ValueDecimal*>( GetValue( _instance, _data[1] ) ) )
{
decimalValue->OnValueRefreshed( value );
if( decimalValue->GetPrecision() != precision )
{
decimalValue->SetPrecision( precision );
}
decimalValue->Release();
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <EnergyProduction::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void EnergyProduction::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, (uint8)EnergyProductionIndex_Instant, c_energyParameterNames[EnergyProductionIndex_Instant], "W", true, false, "0.0", 0 );
node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, (uint8)EnergyProductionIndex_Total, c_energyParameterNames[EnergyProductionIndex_Total], "kWh", true, false, "0.0", 0 );
node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, (uint8)EnergyProductionIndex_Today, c_energyParameterNames[EnergyProductionIndex_Today], "kWh", true, false, "0.0", 0 );
node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, (uint8)EnergyProductionIndex_Time, c_energyParameterNames[EnergyProductionIndex_Time], "", true, false, "0.0", 0 );
}
}
@@ -0,0 +1,65 @@
//-----------------------------------------------------------------------------
//
// EnergyProduction.h
//
// Implementation of the Z-Wave COMMAND_CLASS_ENERGY_PRODUCTION
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _EnergyProduction_H
#define _EnergyProduction_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueDecimal;
/** \brief Implements COMMAND_CLASS_ENERGY_PRODUCTION (0x90), a Z-Wave device command class.
*/
class EnergyProduction: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new EnergyProduction( _homeId, _nodeId ); }
virtual ~EnergyProduction(){}
static uint8 const StaticGetCommandClassId(){ return 0x90; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_ENERGY_PRODUCTION"; }
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _valueEnum, uint8 const _dummy, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
protected:
virtual void CreateVars( uint8 const _instance );
private:
EnergyProduction( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,68 @@
//-----------------------------------------------------------------------------
//
// Hail.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_HAIL
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "Hail.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
using namespace OpenZWave;
enum HailCmdEnum
{
HailCmd_Hail = 1
};
//-----------------------------------------------------------------------------
// <Hail::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool Hail::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( HailCmd_Hail == _data[0] )
{
// We have received a hail from the Z-Wave device.
// Request an update of the dynamic values.
Log::Write( LogLevel_Info, GetNodeId(), "Received Hail command from node %d", GetNodeId() );
if( Node* node = GetNodeUnsafe() )
{
node->RequestDynamicValues();
}
return true;
}
return false;
}
@@ -0,0 +1,58 @@
//-----------------------------------------------------------------------------
//
// Hail.h
//
// Implementation of the Z-Wave COMMAND_CLASS_HAIL
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _Hail_H
#define _Hail_H
#include "CommandClass.h"
namespace OpenZWave
{
/** \brief Implements COMMAND_CLASS_HAIL (0x82), a Z-Wave device command class.
*/
class Hail: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Hail( _homeId, _nodeId ); }
virtual ~Hail(){}
static uint8 const StaticGetCommandClassId(){ return 0x82; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_HAIL"; }
// From CommandClass
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
private:
Hail( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,166 @@
//-----------------------------------------------------------------------------
//
// Indicator.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_INDICATOR
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "Indicator.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueByte.h"
using namespace OpenZWave;
enum IndicatorCmd
{
IndicatorCmd_Set = 0x01,
IndicatorCmd_Get = 0x02,
IndicatorCmd_Report = 0x03
};
//-----------------------------------------------------------------------------
// <Indicator::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool Indicator::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _requestFlags & RequestFlag_Dynamic )
{
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <Indicator::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool Indicator::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if ( IsGetSupported() )
{
Msg* msg = new Msg( "IndicatorCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( IndicatorCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "IndicatorCmd_Get Not Supported on this node");
}
return false;
}
//-----------------------------------------------------------------------------
// <Indicator::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool Indicator::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( IndicatorCmd_Report == (IndicatorCmd)_data[0] )
{
Log::Write( LogLevel_Info, GetNodeId(), "Received an Indicator report: Indicator=%d", _data[1] );
if( ValueByte* value = static_cast<ValueByte*>( GetValue( _instance, 0 ) ) )
{
value->OnValueRefreshed( _data[1] != 0 );
value->Release();
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <Indicator::SetValue>
// Set the device's indicator value
//-----------------------------------------------------------------------------
bool Indicator::SetValue
(
Value const& _value
)
{
if( ValueID::ValueType_Byte == _value.GetID().GetType() )
{
ValueByte const* value = static_cast<ValueByte const*>(&_value);
Log::Write( LogLevel_Info, GetNodeId(), "Indicator::SetValue - Setting indicator to %d", value->GetValue());
Msg* msg = new Msg( "Basic Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->SetInstance( this, _value.GetID().GetInstance() );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( IndicatorCmd_Set );
msg->Append( value->GetValue() );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <Indicator::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void Indicator::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Indicator", "", false, false, false, 0 );
}
}
@@ -0,0 +1,66 @@
//-----------------------------------------------------------------------------
//
// Indicator.h
//
// Implementation of the Z-Wave COMMAND_CLASS_INDICATOR
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _Indicator_H
#define _Indicator_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueByte;
/** \brief Implements COMMAND_CLASS_INDICATOR (0x87), a Z-Wave device command class.
*/
class Indicator: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Indicator( _homeId, _nodeId ); }
virtual ~Indicator(){}
static uint8 const StaticGetCommandClassId(){ return 0x87; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_INDICATOR"; }
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
protected:
virtual void CreateVars( uint8 const _instance );
private:
Indicator( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,164 @@
//-----------------------------------------------------------------------------
//
// Language.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_LANGUAGE
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "Language.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueString.h"
using namespace OpenZWave;
enum LanguageCmd
{
LanguageCmd_Set = 0x01,
LanguageCmd_Get = 0x02,
LanguageCmd_Report = 0x03
};
enum
{
LanguageIndex_Language = 0,
LanguageIndex_Country
};
//-----------------------------------------------------------------------------
// <Language::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool Language::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) )
{
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <Language::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool Language::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _instance != 1 )
{
// This command class doesn't work with multiple instances
return false;
}
if ( IsGetSupported() )
{
Msg* msg = new Msg( "LanguageCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( LanguageCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "LanguageCmd_Get Not Supported on this node");
}
return false;
}
//-----------------------------------------------------------------------------
// <Language::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool Language::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( LanguageCmd_Report == (LanguageCmd)_data[0] )
{
char language[4];
char country[3];
language[0] = _data[1];
language[1] = _data[2];
language[2] = _data[3];
language[3] = 0;
country[0] = _data[4];
country[1] = _data[5];
country[2] = 0;
Log::Write( LogLevel_Info, GetNodeId(), "Received Language report: Language=%s, Country=%s", language, country );
ClearStaticRequest( StaticRequest_Values );
if( ValueString* languageValue = static_cast<ValueString*>( GetValue( _instance, LanguageIndex_Language ) ) )
{
languageValue->OnValueRefreshed( language );
languageValue->Release();
}
if( ValueString* countryValue = static_cast<ValueString*>( GetValue( _instance, LanguageIndex_Country ) ) )
{
countryValue->OnValueRefreshed( country );
countryValue->Release();
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <Language::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void Language::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueString( ValueID::ValueGenre_System, GetCommandClassId(), _instance, (uint8)LanguageIndex_Language, "Language", "", false, false, "", 0 );
node->CreateValueString( ValueID::ValueGenre_System, GetCommandClassId(), _instance, (uint8)LanguageIndex_Country, "Country", "", false, false, "", 0 );
}
}
@@ -0,0 +1,65 @@
//-----------------------------------------------------------------------------
//
// Language.h
//
// Implementation of the Z-Wave COMMAND_CLASS_LANGUAGE
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _Language_H
#define _Language_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueString;
/** \brief Implements COMMAND_CLASS_LANGUAGE (0x89), a Z-Wave device command class.
*/
class Language: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Language( _homeId, _nodeId ); }
virtual ~Language(){}
static uint8 const StaticGetCommandClassId(){ return 0x89; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_LANGUAGE"; }
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
protected:
virtual void CreateVars( uint8 const _instance );
private:
Language( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){ SetStaticRequest( StaticRequest_Values ); }
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,166 @@
//-----------------------------------------------------------------------------
//
// Lock.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_LOCK
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "Lock.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueBool.h"
using namespace OpenZWave;
enum LockCmd
{
LockCmd_Set = 0x01,
LockCmd_Get = 0x02,
LockCmd_Report = 0x03
};
//-----------------------------------------------------------------------------
// <Lock::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool Lock::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _requestFlags & RequestFlag_Dynamic )
{
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <Lock::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool Lock::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if ( IsGetSupported() )
{
Msg* msg = new Msg( "LockCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( LockCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "LockCmd_Get Not Supported on this node");
}
return false;
}
//-----------------------------------------------------------------------------
// <Lock::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool Lock::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( LockCmd_Report == (LockCmd)_data[0] )
{
Log::Write( LogLevel_Info, GetNodeId(), "Received Lock report: Lock is %s", _data[1] ? "Locked" : "Unlocked" );
if( ValueBool* value = static_cast<ValueBool*>( GetValue( _instance, 0 ) ) )
{
value->OnValueRefreshed( _data[1] != 0 );
value->Release();
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <Lock::SetValue>
// Set the lock's state
//-----------------------------------------------------------------------------
bool Lock::SetValue
(
Value const& _value
)
{
if( ValueID::ValueType_Bool == _value.GetID().GetType() )
{
ValueBool const* value = static_cast<ValueBool const*>(&_value);
Log::Write( LogLevel_Info, GetNodeId(), "Lock::Set - Requesting lock to be %s", value->GetValue() ? "Locked" : "Unlocked" );
Msg* msg = new Msg( "LockCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->SetInstance( this, _value.GetID().GetInstance() );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( LockCmd_Set );
msg->Append( value->GetValue() ? 0x01:0x00 );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <Lock::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void Lock::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueBool( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Locked", "", false, false, false, 0 );
}
}
@@ -0,0 +1,66 @@
//-----------------------------------------------------------------------------
//
// Lock.h
//
// Implementation of the Z-Wave COMMAND_CLASS_LOCK
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _Lock_H
#define _Lock_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueBool;
/** \brief Implements COMMAND_CLASS_LOCK (0x76), a Z-Wave device command class.
*/
class Lock: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Lock( _homeId, _nodeId ); }
virtual ~Lock(){}
static uint8 const StaticGetCommandClassId(){ return 0x76; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_LOCK"; }
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
protected:
virtual void CreateVars( uint8 const _instance );
private:
Lock( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,444 @@
//-----------------------------------------------------------------------------
//
// ManufacturerSpecific.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_MANUFACTURER_SPECIFIC
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "ManufacturerSpecific.h"
#include "../tinyxml.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Options.h"
#include "../Manager.h"
#include "../Driver.h"
#include "../Notification.h"
#include "../platform/Log.h"
#include "../value_classes/ValueStore.h"
#include "../value_classes/ValueString.h"
using namespace OpenZWave;
enum ManufacturerSpecificCmd
{
ManufacturerSpecificCmd_Get = 0x04,
ManufacturerSpecificCmd_Report = 0x05
};
map<uint16,string> ManufacturerSpecific::s_manufacturerMap;
map<int64,ManufacturerSpecific::Product*> ManufacturerSpecific::s_productMap;
bool ManufacturerSpecific::s_bXmlLoaded = false;
//-----------------------------------------------------------------------------
// <ManufacturerSpecific::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool ManufacturerSpecific::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) )
{
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <ManufacturerSpecific::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool ManufacturerSpecific::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _instance != 1 )
{
// This command class doesn't work with multiple instances
return false;
}
if ( IsGetSupported() )
{
Msg* msg = new Msg( "ManufacturerSpecificCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( ManufacturerSpecificCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "ManufacturerSpecificCmd_Get Not Supported on this node");
}
return false;
}
string ManufacturerSpecific::SetProductDetails
(
Node* node,
uint16 manufacturerId,
uint16 productType,
uint16 productId
)
{
char str[64];
if (!s_bXmlLoaded) LoadProductXML();
snprintf( str, sizeof(str), "Unknown: id=%.4x", manufacturerId );
string manufacturerName = str;
snprintf( str, sizeof(str), "Unknown: type=%.4x, id=%.4x", productType, productId );
string productName = str;
string configPath = "";
// Try to get the real manufacturer and product names
map<uint16,string>::iterator mit = s_manufacturerMap.find( manufacturerId );
if( mit != s_manufacturerMap.end() )
{
// Replace the id with the real name
manufacturerName = mit->second;
// Get the product
map<int64,Product*>::iterator pit = s_productMap.find( Product::GetKey( manufacturerId, productType, productId ) );
if( pit != s_productMap.end() )
{
productName = pit->second->GetProductName();
configPath = pit->second->GetConfigPath();
}
}
// Set the values into the node
// Only set the manufacturer and product name if they are
// empty - we don't want to overwrite any user defined names.
if( node->GetManufacturerName() == "" )
{
node->SetManufacturerName( manufacturerName );
}
if( node->GetProductName() == "" )
{
node->SetProductName( productName );
}
snprintf( str, sizeof(str), "%.4x", manufacturerId );
node->SetManufacturerId( str );
snprintf( str, sizeof(str), "%.4x", productType );
node->SetProductType( str );
snprintf( str, sizeof(str), "%.4x", productId );
node->SetProductId( str );
return configPath;
}
//-----------------------------------------------------------------------------
// <ManufacturerSpecific::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool ManufacturerSpecific::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( ManufacturerSpecificCmd_Report == (ManufacturerSpecificCmd)_data[0] )
{
// first two bytes are manufacturer id code
uint16 manufacturerId = (((uint16)_data[1])<<8) | (uint16)_data[2];
// next four are product type and product id
uint16 productType = (((uint16)_data[3])<<8) | (uint16)_data[4];
uint16 productId = (((uint16)_data[5])<<8) | (uint16)_data[6];
if( Node* node = GetNodeUnsafe() )
{
// Attempt to create the config parameters
string configPath = SetProductDetails( node, manufacturerId, productType, productId);
if( configPath.size() > 0 )
{
LoadConfigXML( node, configPath );
}
Log::Write( LogLevel_Info, GetNodeId(), "Received manufacturer specific report from node %d: Manufacturer=%s, Product=%s",
GetNodeId(), node->GetManufacturerName().c_str(), node->GetProductName().c_str() );
ClearStaticRequest( StaticRequest_Values );
node->m_manufacturerSpecificClassReceived = true;
}
// Notify the watchers of the name changes
Notification* notification = new Notification( Notification::Type_NodeNaming );
notification->SetHomeAndNodeIds( GetHomeId(), GetNodeId() );
GetDriver()->QueueNotification( notification );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <ManufacturerSpecific::LoadProductXML>
// Load the XML that maps manufacturer and product IDs to human-readable names
//-----------------------------------------------------------------------------
bool ManufacturerSpecific::LoadProductXML
(
)
{
s_bXmlLoaded = true;
// Parse the Z-Wave manufacturer and product XML file.
string configPath;
Options::Get()->GetOptionAsString( "ConfigPath", &configPath );
string filename = configPath + "manufacturer_specific.xml";
TiXmlDocument* pDoc = new TiXmlDocument();
if( !pDoc->LoadFile( filename.c_str(), TIXML_ENCODING_UTF8 ) )
{
delete pDoc;
Log::Write( LogLevel_Info, "Unable to load %s", filename.c_str() );
return false;
}
TiXmlElement const* root = pDoc->RootElement();
char const* str;
char* pStopChar;
TiXmlElement const* manufacturerElement = root->FirstChildElement();
while( manufacturerElement )
{
str = manufacturerElement->Value();
if( str && !strcmp( str, "Manufacturer" ) )
{
// Read in the manufacturer attributes
str = manufacturerElement->Attribute( "id" );
if( !str )
{
Log::Write( LogLevel_Info, "Error in manufacturer_specific.xml at line %d - missing manufacturer id attribute", manufacturerElement->Row() );
delete pDoc;
return false;
}
uint16 manufacturerId = (uint16)strtol( str, &pStopChar, 16 );
str = manufacturerElement->Attribute( "name" );
if( !str )
{
Log::Write( LogLevel_Info, "Error in manufacturer_specific.xml at line %d - missing manufacturer name attribute", manufacturerElement->Row() );
delete pDoc;
return false;
}
// Add this manufacturer to the map
s_manufacturerMap[manufacturerId] = str;
// Parse all the products for this manufacturer
TiXmlElement const* productElement = manufacturerElement->FirstChildElement();
while( productElement )
{
str = productElement->Value();
if( str && !strcmp( str, "Product" ) )
{
str = productElement->Attribute( "type" );
if( !str )
{
Log::Write( LogLevel_Info, "Error in manufacturer_specific.xml at line %d - missing product type attribute", productElement->Row() );
delete pDoc;
return false;
}
uint16 productType = (uint16)strtol( str, &pStopChar, 16 );
str = productElement->Attribute( "id" );
if( !str )
{
Log::Write( LogLevel_Info, "Error in manufacturer_specific.xml at line %d - missing product id attribute", productElement->Row() );
delete pDoc;
return false;
}
uint16 productId = (uint16)strtol( str, &pStopChar, 16 );
str = productElement->Attribute( "name" );
if( !str )
{
Log::Write( LogLevel_Info, "Error in manufacturer_specific.xml at line %d - missing product name attribute", productElement->Row() );
delete pDoc;
return false;
}
string productName = str;
// Optional config path
string configPath;
str = productElement->Attribute( "config" );
if( str )
{
configPath = str;
}
// Add the product to the map
Product* product = new Product( manufacturerId, productType, productId, productName, configPath );
if ( s_productMap[product->GetKey()] != NULL )
{
Product *c = s_productMap[product->GetKey()];
Log::Write( LogLevel_Info, "Product name collision: %s type %x id %x manufacturerid %x, collides with %s, type %x id %x manufacturerid %x", productName.c_str(), productType, productId, manufacturerId, c->GetProductName().c_str(), c->GetProductType(), c->GetProductId(), c->GetManufacturerId());
delete product;
}
else
{
s_productMap[product->GetKey()] = product;
}
}
// Move on to the next product.
productElement = productElement->NextSiblingElement();
}
}
// Move on to the next manufacturer.
manufacturerElement = manufacturerElement->NextSiblingElement();
}
delete pDoc;
return true;
}
//-----------------------------------------------------------------------------
// <ManufacturerSpecific::UnloadProductXML>
// Free the XML that maps manufacturer and product IDs
//-----------------------------------------------------------------------------
void ManufacturerSpecific::UnloadProductXML
(
)
{
if (s_bXmlLoaded)
{
map<int64,Product*>::iterator pit = s_productMap.begin();
while( !s_productMap.empty() )
{
delete pit->second;
s_productMap.erase( pit );
pit = s_productMap.begin();
}
map<uint16,string>::iterator mit = s_manufacturerMap.begin();
while( !s_manufacturerMap.empty() )
{
s_manufacturerMap.erase( mit );
mit = s_manufacturerMap.begin();
}
s_bXmlLoaded = false;
}
}
//-----------------------------------------------------------------------------
// <ManufacturerSpecific::LoadConfigXML>
// Try to find and load an XML file describing the device's config params
//-----------------------------------------------------------------------------
bool ManufacturerSpecific::LoadConfigXML
(
Node* _node,
string const& _configXML
)
{
string configPath;
Options::Get()->GetOptionAsString( "ConfigPath", &configPath );
string filename = configPath + _configXML;
TiXmlDocument* doc = new TiXmlDocument();
Log::Write( LogLevel_Info, _node->GetNodeId(), " Opening config param file %s", filename.c_str() );
if( !doc->LoadFile( filename.c_str(), TIXML_ENCODING_UTF8 ) )
{
delete doc;
Log::Write( LogLevel_Info, _node->GetNodeId(), "Unable to find or load Config Param file %s", filename.c_str() );
return false;
}
Node::QueryStage qs = _node->GetCurrentQueryStage();
if( qs == Node::QueryStage_ManufacturerSpecific1 )
{
_node->ReadDeviceProtocolXML( doc->RootElement() );
}
else
{
if( !_node->m_manufacturerSpecificClassReceived )
{
_node->ReadDeviceProtocolXML( doc->RootElement() );
}
_node->ReadCommandClassesXML( doc->RootElement() );
}
delete doc;
return true;
}
//-----------------------------------------------------------------------------
// <ManufacturerSpecific::ReLoadConfigXML>
// Reload previously discovered device configuration.
//-----------------------------------------------------------------------------
void ManufacturerSpecific::ReLoadConfigXML
(
)
{
if( Node* node = GetNodeUnsafe() )
{
if (!s_bXmlLoaded) LoadProductXML();
uint16 manufacturerId = (uint16)strtol( node->GetManufacturerId().c_str(), NULL, 16 );
uint16 productType = (uint16)strtol( node->GetProductType().c_str(), NULL, 16 );
uint16 productId = (uint16)strtol( node->GetProductId().c_str(), NULL, 16 );
map<uint16,string>::iterator mit = s_manufacturerMap.find( manufacturerId );
if( mit != s_manufacturerMap.end() )
{
map<int64,Product*>::iterator pit = s_productMap.find( Product::GetKey( manufacturerId, productType, productId ) );
if( pit != s_productMap.end() )
{
string configPath = pit->second->GetConfigPath();
if( configPath.size() > 0 )
{
LoadConfigXML( node, configPath );
}
}
}
}
}
@@ -0,0 +1,116 @@
//-----------------------------------------------------------------------------
//
// ManufacturerSpecific.h
//
// Implementation of the Z-Wave COMMAND_CLASS_MANUFACTURER_SPECIFIC
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _ManufacturerSpecific_H
#define _ManufacturerSpecific_H
#include <map>
#include "CommandClass.h"
namespace OpenZWave
{
/** \brief Implements COMMAND_CLASS_MANUFACTURER_SPECIFIC (0x72), a Z-Wave device command class.
*/
class ManufacturerSpecific: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ManufacturerSpecific( _homeId, _nodeId ); }
virtual ~ManufacturerSpecific(){ UnloadProductXML(); }
static uint8 const StaticGetCommandClassId(){ return 0x72; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_MANUFACTURER_SPECIFIC"; }
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
static string SetProductDetails( Node *_node, uint16 _manufacturerId, uint16 _productType, uint16 _productId );
static bool LoadConfigXML( Node* _node, string const& _configXML );
void ReLoadConfigXML();
private:
ManufacturerSpecific( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){ SetStaticRequest( StaticRequest_Values ); }
static bool LoadProductXML();
static void UnloadProductXML();
class Product
{
public:
Product
(
uint16 _manufacturerId,
uint16 _productType,
uint16 _productId,
string const& _productName,
string const& _configPath
):
m_manufacturerId( _manufacturerId ),
m_productType( _productType ),
m_productId( _productId ),
m_productName( _productName ),
m_configPath( _configPath )
{
}
int64 GetKey()const
{
return( GetKey( m_manufacturerId, m_productType, m_productId ) );
}
static int64 GetKey( uint16 _manufacturerId, uint16 _productType, uint16 _productId )
{
int64 key = (((int64)_manufacturerId)<<32) | (((int64)_productType)<<16) | (int64)_productId;
return key;
}
uint16 GetManufacturerId()const{ return m_manufacturerId; }
uint16 GetProductType()const{ return m_productType; }
uint16 GetProductId()const{ return m_productId; }
string GetProductName()const{ return m_productName; }
string GetConfigPath()const{ return m_configPath; }
private:
uint16 m_manufacturerId;
uint16 m_productType;
uint16 m_productId;
string m_productName;
string m_configPath;
};
static map<uint16,string> s_manufacturerMap;
static map<int64,Product*> s_productMap;
static bool s_bXmlLoaded;
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,562 @@
//-----------------------------------------------------------------------------
//
// Meter.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_METER
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "Meter.h"
#include "MultiInstance.h"
#include "../Defs.h"
#include "../Bitfield.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueDecimal.h"
#include "../value_classes/ValueList.h"
#include "../value_classes/ValueButton.h"
#include "../value_classes/ValueInt.h"
#include "../value_classes/ValueBool.h"
using namespace OpenZWave;
enum MeterCmd
{
MeterCmd_Get = 0x01,
MeterCmd_Report = 0x02,
// Version 2
MeterCmd_SupportedGet = 0x03,
MeterCmd_SupportedReport = 0x04,
MeterCmd_Reset = 0x05
};
enum MeterType
{
MeterType_Electric = 1,
MeterType_Gas,
MeterType_Water
};
enum
{
MeterIndex_Exporting = 32,
MeterIndex_Reset
};
static char const* c_meterTypes[] =
{
"Unknown",
"Electric",
"Gas",
"Water"
};
static char const* c_electricityUnits[] =
{
"kWh",
"kVAh",
"W",
"pulses",
"V",
"A",
"Power Factor",
""
};
static char const* c_gasUnits[] =
{
"cubic meters",
"cubic feet",
"",
"pulses",
"",
"",
"",
""
};
static char const* c_waterUnits[] =
{
"cubic meters",
"cubic feet",
"US gallons",
"pulses",
"",
"",
"",
""
};
static char const* c_electricityLabels[] =
{
"Energy",
"Energy",
"Power",
"Count",
"Voltage",
"Current",
"Power Factor",
"Unknown"
};
//-----------------------------------------------------------------------------
// <Meter::Meter>
// Constructor
//-----------------------------------------------------------------------------
Meter::Meter
(
uint32 const _homeId,
uint8 const _nodeId
):
CommandClass( _homeId, _nodeId )
{
SetStaticRequest( StaticRequest_Values );
}
//-----------------------------------------------------------------------------
// <Meter::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool Meter::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
bool res = false;
if( GetVersion() > 1 )
{
if( _requestFlags & RequestFlag_Static )
{
Msg* msg = new Msg( "MeterCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( MeterCmd_SupportedGet );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
res = true;
}
}
if( _requestFlags & RequestFlag_Dynamic )
{
res |= RequestValue( _requestFlags, 0, _instance, _queue );
}
return res;
}
//-----------------------------------------------------------------------------
// <Meter::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool Meter::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
bool res = false;
if ( !IsGetSupported())
{
Log::Write( LogLevel_Info, GetNodeId(), "MeterCmd_Get Not Supported on this node");
return false;
}
for( uint8 i=0; i<8; ++i )
{
uint8 baseIndex = i<<2;
Value* value = GetValue( _instance, baseIndex );
if( value != NULL )
{
value->Release();
Msg* msg = new Msg( "MeterCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( MeterCmd_Get );
msg->Append( (uint8)( i << 3 ) );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
res |= true;
}
}
return res;
}
//-----------------------------------------------------------------------------
// <Meter::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool Meter::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
bool handled = false;
if (MeterCmd_SupportedReport == (MeterCmd)_data[0])
{
handled = HandleSupportedReport( _data, _length, _instance );
}
else if (MeterCmd_Report == (MeterCmd)_data[0])
{
handled = HandleReport( _data, _length, _instance );
}
return handled;
}
//-----------------------------------------------------------------------------
// <Meter::HandleSupportedReport>
// Create the values for this command class based on the reported parameters
//-----------------------------------------------------------------------------
bool Meter::HandleSupportedReport
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance
)
{
bool canReset = ((_data[1] & 0x80) != 0);
int8 meterType = (MeterType)(_data[1] & 0x1f);
if (meterType > 4) /* size of c_meterTypes */
{
Log::Write (LogLevel_Warning, GetNodeId(), "meterType Value was greater than range. Dropping Message");
return false;
}
ClearStaticRequest( StaticRequest_Version );
if( Node* node = GetNodeUnsafe() )
{
string msg;
msg = c_meterTypes[meterType];
msg += ": ";
// Create the list of supported scales
uint8 scaleSupported = _data[2];
if( GetVersion() == 2 )
{
// Only four scales are allowed in version 2
scaleSupported &= 0x0f;
}
for( uint8 i=0; i<8; ++i )
{
if( scaleSupported & (1<<i) )
{
uint8 baseIndex = i<<2; // We leave space between the value indices to insert previous and time delta values if we need to later on.
switch( meterType )
{
case MeterType_Electric:
{
if( ValueDecimal* value = static_cast<ValueDecimal*>( GetValue( _instance, baseIndex ) ) )
{
value->SetLabel( c_electricityLabels[i] );
value->SetUnits( c_electricityUnits[i] );
value->Release();
}
else
{
node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, baseIndex, c_electricityLabels[i], c_electricityUnits[i], true, false, "0.0", 0 );
}
if( i != 0 )
msg += ", ";
msg += c_electricityUnits[i];
break;
}
case MeterType_Gas:
{
if( ValueDecimal* value = static_cast<ValueDecimal*>( GetValue( _instance, baseIndex ) ) )
{
value->SetLabel( c_meterTypes[MeterType_Gas] );
value->SetUnits( c_gasUnits[i] );
value->Release();
}
else
{
node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, baseIndex, c_meterTypes[meterType], c_gasUnits[i], true, false, "0.0", 0 );
}
if( i != 0 )
msg += ", ";
msg += c_gasUnits[i];
break;
}
case MeterType_Water:
{
if( ValueDecimal* value = static_cast<ValueDecimal*>( GetValue( _instance, baseIndex ) ) )
{
value->SetLabel( c_meterTypes[MeterType_Water] );
value->SetUnits( c_waterUnits[i] );
value->Release();
}
else
{
node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, baseIndex, c_meterTypes[meterType], c_waterUnits[i], true, false, "0.0", 0 );
}
if( i != 0 )
msg += ", ";
msg += c_waterUnits[i];
break;
}
default:
{
break;
}
}
}
}
// Create the export flag
node->CreateValueBool( ValueID::ValueGenre_User, GetCommandClassId(), _instance, MeterIndex_Exporting, "Exporting", "", true, false, false, 0 );
// Create the reset button
if( canReset )
{
node->CreateValueButton( ValueID::ValueGenre_System, GetCommandClassId(), _instance, MeterIndex_Reset, "Reset", 0 );
}
Log::Write( LogLevel_Info, GetNodeId(), "Received Meter supported report from node %d, %s", GetNodeId(), msg.c_str() );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <Meter::HandleReport>
// Read the reported meter value
//-----------------------------------------------------------------------------
bool Meter::HandleReport
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance
)
{
// Import or Export (only valid in version > 1)
bool exporting = false;
if( GetVersion() > 1 )
{
exporting = ((_data[1] & 0x60) == 0x40 );
if( ValueBool* value = static_cast<ValueBool*>( GetValue( _instance, MeterIndex_Exporting ) ) )
{
value->OnValueRefreshed( exporting );
value->Release();
}
}
// Get the value and scale
uint8 scale;
uint8 precision = 0;
string valueStr = ExtractValue( &_data[2], &scale, &precision );
if (scale > 7) /* size of c_electricityLabels, c_electricityUnits, c_gasUnits, c_waterUnits */
{
Log::Write (LogLevel_Warning, GetNodeId(), "Scale was greater than range. Setting to Invalid");
scale = 7;
}
if( GetVersion() == 1 )
{
// In version 1, we don't know the scale until we get the first value report
string label;
string units;
int8 meterType = (MeterType)(_data[1] & 0x1f);
if (meterType > 4) /* size of c_meterTypes */
{
Log::Write (LogLevel_Warning, GetNodeId(), "meterType Value was greater than range. Dropping Message");
return false;
}
switch( (MeterType)(_data[1] & 0x1f) )
{
case MeterType_Electric:
{
// Electricity Meter
label = c_electricityLabels[scale];
units = c_electricityUnits[scale];
break;
}
case MeterType_Gas:
{
// Gas Meter
label = c_meterTypes[MeterType_Gas];
units = c_gasUnits[scale];
break;
}
case MeterType_Water:
{
// Water Meter
label = c_meterTypes[MeterType_Water];
units = c_waterUnits[scale];
break;
}
default:
{
break;
}
}
if( ValueDecimal* value = static_cast<ValueDecimal*>( GetValue( _instance, 0 ) ) )
{
Log::Write( LogLevel_Info, GetNodeId(), "Received Meter report from node %d: %s=%s%s", GetNodeId(), label.c_str(), valueStr.c_str(), units.c_str() );
value->SetLabel( label );
value->SetUnits( units );
value->OnValueRefreshed( valueStr );
if( value->GetPrecision() != precision )
{
value->SetPrecision( precision );
}
value->Release();
}
}
else
{
// Version 2 and above
uint8 baseIndex = scale << 2;
if( GetVersion() > 2 )
{
// In version 3, an extra scale bit is stored in the meter type byte.
scale |= ((_data[1]&0x80)>>5);
baseIndex = scale << 2;
}
if( ValueDecimal* value = static_cast<ValueDecimal*>( GetValue( _instance, baseIndex ) ) )
{
Log::Write( LogLevel_Info, GetNodeId(), "Received Meter report from node %d: %s%s=%s%s", GetNodeId(), exporting ? "Exporting ": "", value->GetLabel().c_str(), valueStr.c_str(), value->GetUnits().c_str() );
value->OnValueRefreshed( valueStr );
if( value->GetPrecision() != precision )
{
value->SetPrecision( precision );
}
value->Release();
// Read any previous value and time delta
uint8 size = _data[2] & 0x07;
uint16 delta = (uint16)( (_data[3+size]<<8) | _data[4+size]);
if( delta )
{
// There is only a previous value if the time delta is non-zero
ValueDecimal* previous = static_cast<ValueDecimal*>( GetValue( _instance, baseIndex+1 ) );
if( NULL == previous )
{
// We need to create a value to hold the previous
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, baseIndex+1, "Previous Reading", value->GetUnits().c_str(), true, false, "0.0", 0 );
previous = static_cast<ValueDecimal*>( GetValue( _instance, baseIndex+1 ) );
}
}
if( previous )
{
precision = 0;
valueStr = ExtractValue( &_data[2], &scale, &precision, 3+size );
Log::Write( LogLevel_Info, GetNodeId(), " Previous value was %s%s, received %d seconds ago.", valueStr.c_str(), previous->GetUnits().c_str(), delta );
previous->OnValueRefreshed( valueStr );
if( previous->GetPrecision() != precision )
{
previous->SetPrecision( precision );
}
previous->Release();
}
// Time delta
ValueInt* interval = static_cast<ValueInt*>( GetValue( _instance, baseIndex+2 ) );
if( NULL == interval )
{
// We need to create a value to hold the time delta
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueInt( ValueID::ValueGenre_User, GetCommandClassId(), _instance, baseIndex+2, "Interval", "seconds", true, false, 0, 0 );
interval = static_cast<ValueInt*>( GetValue( _instance, baseIndex+2 ) );
}
}
if( interval )
{
interval->OnValueRefreshed( (int32)delta );
interval->Release();
}
}
}
}
return true;
}
//-----------------------------------------------------------------------------
// <Meter::SetValue>
// Set the device's scale, or reset its accumulated values.
//-----------------------------------------------------------------------------
bool Meter::SetValue
(
Value const& _value
)
{
if( MeterIndex_Reset == _value.GetID().GetIndex() )
{
ValueButton const* button = static_cast<ValueButton const*>(&_value);
if( button->IsPressed() )
{
Msg* msg = new Msg( "MeterCmd_Reset", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->SetInstance( this, _value.GetID().GetInstance() );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( MeterCmd_Reset );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
// <Meter::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void Meter::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Unknown", "", true, false, "0.0", 0 );
}
}
@@ -0,0 +1,72 @@
//-----------------------------------------------------------------------------
//
// Meter.h
//
// Implementation of the Z-Wave COMMAND_CLASS_METER
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _Meter_H
#define _Meter_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueDecimal;
/** \brief Implements COMMAND_CLASS_METER (0x32), a Z-Wave device command class.
*/
class Meter: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Meter( _homeId, _nodeId ); }
virtual ~Meter(){}
static uint8 const StaticGetCommandClassId(){ return 0x32; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_METER"; }
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
virtual uint8 GetMaxVersion(){ return 3; }
protected:
virtual void CreateVars( uint8 const _instance );
private:
Meter( uint32 const _homeId, uint8 const _nodeId );
bool HandleSupportedReport( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
bool HandleReport( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,143 @@
//-----------------------------------------------------------------------------
//
// MeterPulse.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_METER_PULSE
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "MeterPulse.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueInt.h"
using namespace OpenZWave;
enum MeterPulseCmd
{
MeterPulseCmd_Get = 0x04,
MeterPulseCmd_Report = 0x05
};
//-----------------------------------------------------------------------------
// <MeterPulse::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool MeterPulse::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _requestFlags & RequestFlag_Dynamic )
{
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <MeterPulse::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool MeterPulse::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if ( IsGetSupported() )
{
Msg* msg = new Msg( "MeterPulseCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( MeterPulseCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "MeterPulseCmd_Get Not Supported on this node");
}
return false;
}
//-----------------------------------------------------------------------------
// <MeterPulse::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool MeterPulse::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( MeterPulseCmd_Report == (MeterPulseCmd)_data[0] )
{
int32 count = 0;
for( uint8 i=0; i<4; ++i )
{
count <<= 8;
count |= (uint32)_data[i+1];
}
Log::Write( LogLevel_Info, GetNodeId(), "Received a meter pulse count: Count=%d", count );
if( ValueInt* value = static_cast<ValueInt*>( GetValue( _instance, 0 ) ) )
{
value->OnValueRefreshed( count );
value->Release();
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <MeterPulse::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void MeterPulse::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueInt( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Count", "", true, false, 0, 0 );
}
}
@@ -0,0 +1,65 @@
//-----------------------------------------------------------------------------
//
// MeterPulse.h
//
// Implementation of the Z-Wave COMMAND_CLASS_METER_PULSE
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _MeterPulse_H
#define _MeterPulse_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueInt;
/** \brief Implements COMMAND_CLASS_METER_PULSE (0x35), a Z-Wave device command class.
*/
class MeterPulse: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new MeterPulse( _homeId, _nodeId ); }
virtual ~MeterPulse(){}
static uint8 const StaticGetCommandClassId(){ return 0x35; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_METER_PULSE"; }
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
protected:
virtual void CreateVars( uint8 const _instance );
private:
MeterPulse( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,77 @@
//-----------------------------------------------------------------------------
//
// MultiCmd.h
//
// Implementation of the Z-Wave COMMAND_CLASS_MULTI_CMD
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "MultiCmd.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
using namespace OpenZWave;
//-----------------------------------------------------------------------------
// <MultiCmd::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool MultiCmd::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( MultiCmdCmd_Encap == (MultiCmdCmd)_data[0] )
{
Log::Write( LogLevel_Info, GetNodeId(), "Received encapsulated multi-command from node %d", GetNodeId() );
if( Node const* node = GetNodeUnsafe() )
{
// Iterate over commands
uint8 base = 2;
for( uint8 i=0; i<_data[1]; ++i )
{
uint8 length = _data[base];
uint8 commandClassId = _data[base+1];
if( CommandClass* pCommandClass = node->GetCommandClass( commandClassId ) )
{
pCommandClass->HandleMsg( &_data[base+2], length-1 );
}
base += (length + 1);
}
}
Log::Write( LogLevel_Info, GetNodeId(), "End of encapsulated multi-command from node %d", GetNodeId() );
return true;
}
return false;
}
@@ -0,0 +1,63 @@
//-----------------------------------------------------------------------------
//
// MultiCmd.h
//
// Implementation of the Z-Wave COMMAND_CLASS_MULTI_CMD
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _MultiCmd_H
#define _MultiCmd_H
#include "CommandClass.h"
namespace OpenZWave
{
/** \brief Implements COMMAND_CLASS_MULTI_CMD (0x8f), a Z-Wave device command class.
*/
class MultiCmd: public CommandClass
{
public:
enum MultiCmdCmd
{
MultiCmdCmd_Encap = 0x01
};
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new MultiCmd( _homeId, _nodeId ); }
virtual ~MultiCmd(){}
static uint8 const StaticGetCommandClassId(){ return 0x8f; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_MULTI_CMD"; }
// From CommandClass
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
private:
MultiCmd( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,676 @@
//-----------------------------------------------------------------------------
//
// MultiInstance.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_MULTI_INSTANCE
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "../tinyxml.h"
#include "CommandClasses.h"
#include "Basic.h"
#include "MultiInstance.h"
#include "NoOperation.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Driver.h"
#include "../Node.h"
#include "../platform/Log.h"
using namespace OpenZWave;
// Reduced set of Generic Device classes sorted to reduce
// the likely number of calls to MultiChannelCmd_EndPointFind.
uint8 const c_genericClass[] =
{
0x21, // Multilevel Sensor
0x20, // Binary Sensor
0x31, // Meter
0x08, // Thermostat
0x11, // Multilevel Switch
0x10, // Binary Switch
0x12, // Remote Switch
0xa1, // Alarm Sensor
0x16, // Ventilation
0x30, // Pulse Meter
0x40, // Entry Control
0x13, // Toggle Switch
0x03, // AV Control Point
0x04, // Display
0x00 // End of list
};
char const* c_genericClassName[] =
{
"Multilevel Sensor",
"Binary Sensor",
"Meter",
"Thermostat",
"Multilevel Switch",
"Binary Switch",
"Remote Switch",
"Alarm Sensor",
"Ventilation",
"Pulse Meter",
"Entry Control",
"Toggle Switch",
"AV Control Point",
"Display",
"Unknown"
};
//-----------------------------------------------------------------------------
// <MultiInstance::MultiInstance>
// Constructor
//-----------------------------------------------------------------------------
MultiInstance::MultiInstance
(
uint32 const _homeId,
uint8 const _nodeId
):
CommandClass( _homeId, _nodeId ),
m_numEndPoints( 0 ),
m_numEndPointsHint( 0 ),
m_endPointMap( MultiInstanceMapAll ),
m_endPointFindSupported( false )
{
}
//-----------------------------------------------------------------------------
// <MultiInstance::ReadXML>
// Class specific configuration
//-----------------------------------------------------------------------------
void MultiInstance::ReadXML
(
TiXmlElement const* _ccElement
)
{
int32 intVal;
char const* str;
CommandClass::ReadXML( _ccElement );
if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "endpoints", &intVal ) )
{
m_numEndPointsHint = (uint8)intVal;
}
str = _ccElement->Attribute("mapping");
if( str )
{
if( strcmp( str, "all") == 0 )
{
m_endPointMap = MultiInstanceMapAll;
}
else if( strcmp( str, "endpoints") == 0 )
{
m_endPointMap = MultiInstanceMapEndPoints;
}
else
{
Log::Write( LogLevel_Info, GetNodeId(), "Bad value for mapping: %s", str);
}
}
str = _ccElement->Attribute("findsupport");
if( str )
{
m_endPointFindSupported = !strcmp( str, "true");
}
str = _ccElement->Attribute("ignoreUnsolicitedMultiChnCapReport");
if( str )
{
m_ignoreUnsolicitedMultiChannelCapabilityReport = !strcmp( str, "true");
}
}
//-----------------------------------------------------------------------------
// <MultiInstance::WriteXML>
// Class specific configuration
//-----------------------------------------------------------------------------
void MultiInstance::WriteXML
(
TiXmlElement* _ccElement
)
{
char str[32];
CommandClass::WriteXML( _ccElement );
if( m_numEndPointsHint != 0 )
{
snprintf( str, sizeof(str), "%d", m_numEndPointsHint );
_ccElement->SetAttribute( "endpoints", str);
}
if( m_endPointMap == MultiInstanceMapEndPoints )
{
_ccElement->SetAttribute( "mapping", "endpoints" );
}
if( m_endPointFindSupported )
{
_ccElement->SetAttribute( "findsupport", "true" );
}
}
//-----------------------------------------------------------------------------
// <MultiInstance::RequestInstances>
// Request number of instances of the specified command class from the device
//-----------------------------------------------------------------------------
bool MultiInstance::RequestInstances
(
)
{
bool res = false;
if( GetVersion() == 1 )
{
if( Node* node = GetNodeUnsafe() )
{
// MULTI_INSTANCE
char str[128];
for( map<uint8,CommandClass*>::const_iterator it = node->m_commandClassMap.begin(); it != node->m_commandClassMap.end(); ++it )
{
CommandClass* cc = it->second;
if( cc->GetCommandClassId() == NoOperation::StaticGetCommandClassId() )
{
continue;
}
if( cc->HasStaticRequest( StaticRequest_Instances ) )
{
snprintf( str, sizeof( str ), "MultiInstanceCmd_Get for %s", cc->GetCommandClassName().c_str() );
Msg* msg = new Msg( str, GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( MultiInstanceCmd_Get );
msg->Append( cc->GetCommandClassId() );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Query );
res = true;
}
}
}
}
else
{
// MULTI_CHANNEL
char str[128];
snprintf( str, sizeof( str ), "MultiChannelCmd_EndPointGet for node %d", GetNodeId() );
Msg* msg = new Msg( str, GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( MultiChannelCmd_EndPointGet );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Query );
res = true;
}
return res;
}
//-----------------------------------------------------------------------------
// <MultiInstance::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool MultiInstance::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
bool handled = false;
Node* node = GetNodeUnsafe();
if( node != NULL )
{
handled = true;
switch( (MultiInstanceCmd)_data[0] )
{
case MultiInstanceCmd_Report:
{
HandleMultiInstanceReport( _data, _length );
break;
}
case MultiInstanceCmd_Encap:
{
HandleMultiInstanceEncap( _data, _length );
break;
}
case MultiChannelCmd_EndPointReport:
{
HandleMultiChannelEndPointReport( _data, _length );
break;
}
case MultiChannelCmd_CapabilityReport:
{
HandleMultiChannelCapabilityReport( _data, _length );
break;
}
case MultiChannelCmd_EndPointFindReport:
{
HandleMultiChannelEndPointFindReport( _data, _length );
break;
}
case MultiChannelCmd_Encap:
{
HandleMultiChannelEncap( _data, _length );
break;
}
default:
{
handled = false;
break;
}
}
}
return handled;
}
//-----------------------------------------------------------------------------
// <MultiInstance::HandleMultiInstanceReport>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
void MultiInstance::HandleMultiInstanceReport
(
uint8 const* _data,
uint32 const _length
)
{
if( Node* node = GetNodeUnsafe() )
{
uint8 commandClassId = _data[1];
uint8 instances = _data[2];
if( CommandClass* pCommandClass = node->GetCommandClass( commandClassId ) )
{
Log::Write( LogLevel_Info, GetNodeId(), "Received MultiInstanceReport from node %d for %s: Number of instances = %d", GetNodeId(), pCommandClass->GetCommandClassName().c_str(), instances );
pCommandClass->SetInstances( instances );
pCommandClass->ClearStaticRequest( StaticRequest_Instances );
}
}
}
//-----------------------------------------------------------------------------
// <MultiInstance::HandleMultiInstanceEncap>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
void MultiInstance::HandleMultiInstanceEncap
(
uint8 const* _data,
uint32 const _length
)
{
if( Node* node = GetNodeUnsafe() )
{
uint8 instance = _data[1];
if( GetVersion() > 1 )
{
instance &= 0x7f;
}
uint8 commandClassId = _data[2];
if( CommandClass* pCommandClass = node->GetCommandClass( commandClassId ) )
{
Log::Write( LogLevel_Info, GetNodeId(), "Received a MultiInstanceEncap from node %d, instance %d, for Command Class %s", GetNodeId(), instance, pCommandClass->GetCommandClassName().c_str() );
pCommandClass->ReceivedCntIncr();
pCommandClass->HandleMsg( &_data[3], _length-3, instance );
}
}
}
//-----------------------------------------------------------------------------
// <MultiInstance::HandleMultiChannelEndPointReport>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
void MultiInstance::HandleMultiChannelEndPointReport
(
uint8 const* _data,
uint32 const _length
)
{
int len;
if( m_numEndPoints != 0 )
{
return;
}
m_numEndPointsCanChange = (( _data[1] & 0x80 ) != 0 ); // Number of endpoints can change.
m_endPointsAreSameClass = (( _data[1] & 0x40 ) != 0 ); // All endpoints are the same command class.
m_numEndPoints = _data[2] & 0x7f;
if( m_numEndPointsHint != 0 )
{
m_numEndPoints = m_numEndPointsHint; // don't use device's number
}
len = m_numEndPoints;
if( m_endPointsAreSameClass ) // only need to check single end point
{
len = 1;
Log::Write( LogLevel_Info, GetNodeId(), "Received MultiChannelEndPointReport from node %d. All %d endpoints are the same.", GetNodeId(), m_numEndPoints );
}
else
{
Log::Write( LogLevel_Info, GetNodeId(), "Received MultiChannelEndPointReport from node %d. %d endpoints are not all the same.", GetNodeId(), m_numEndPoints );
}
// This code assumes the endpoints are all in numeric sequential order.
// Since the end point finds do not appear to work this is the best estimate.
for( uint8 i = 1; i <= len; i++ )
{
// Send a single capability request to each endpoint
char str[128];
snprintf( str, sizeof( str ), "MultiChannelCmd_CapabilityGet for endpoint %d", i );
Msg* msg = new Msg( str, GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( MultiChannelCmd_CapabilityGet );
msg->Append( i );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
}
}
//-----------------------------------------------------------------------------
// <MultiInstance::HandleMultiChannelCapabilityReport>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
void MultiInstance::HandleMultiChannelCapabilityReport
(
uint8 const* _data,
uint32 const _length
)
{
bool dynamic = ((_data[1] & 0x80)!=0);
if( Node* node = GetNodeUnsafe() )
{
/* if you having problems with Dynamic Devices not correctly
* updating the commandclasses, see this email thread:
* https://groups.google.com/d/topic/openzwave/IwepxScRAVo/discussion
*/
if ((m_ignoreUnsolicitedMultiChannelCapabilityReport && (node->GetCurrentQueryStage() != Node::QueryStage_Instances))
&& !dynamic && m_endPointCommandClasses.size() > 0) {
Log::Write(LogLevel_Error, GetNodeId(), "Recieved a Unsolicited MultiChannelEncap when we are not in QueryState_Instances");
return;
}
uint8 endPoint = _data[1] & 0x7f;
Log::Write( LogLevel_Info, GetNodeId(), "Received MultiChannelCapabilityReport from node %d for endpoint %d", GetNodeId(), endPoint );
Log::Write( LogLevel_Info, GetNodeId(), " Endpoint is%sdynamic, and is a %s", dynamic ? " " : " not ", node->GetEndPointDeviceClassLabel( _data[2], _data[3] ).c_str() );
Log::Write( LogLevel_Info, GetNodeId(), " Command classes supported by the endpoint are:" );
// Store the command classes for later use
bool afterMark = false;
m_endPointCommandClasses.clear();
uint8 numCommandClasses = _length - 5;
for( uint8 i = 0; i < numCommandClasses; ++i )
{
uint8 commandClassId = _data[i+4];
if( commandClassId == 0xef )
{
afterMark = true;
continue;
}
m_endPointCommandClasses.insert( commandClassId );
// Ensure the node supports this command class
CommandClass* cc = node->GetCommandClass( commandClassId );
if( !cc )
{
cc = node->AddCommandClass( commandClassId );
if( cc && afterMark )
{
cc->SetAfterMark();
}
}
if( cc )
{
Log::Write( LogLevel_Info, GetNodeId(), " %s", cc->GetCommandClassName().c_str() );
}
}
// Create internal library instances for each command class in the list
// Also set up mapping from intances to endpoints for encapsulation
Basic* basic = static_cast<Basic*>( node->GetCommandClass( Basic::StaticGetCommandClassId() ) );
if( m_endPointsAreSameClass ) // Create all the same instances here
{
int len;
if( m_endPointMap == MultiInstanceMapAll ) // Include the non-endpoint instance
{
endPoint = 0;
len = m_numEndPoints + 1;
}
else
{
endPoint = 1;
len = m_numEndPoints;
}
// Create all the command classes for all the endpoints
for( uint8 i = 1; i <= len; i++ )
{
for( set<uint8>::iterator it = m_endPointCommandClasses.begin(); it != m_endPointCommandClasses.end(); ++it )
{
uint8 commandClassId = *it;
CommandClass* cc = node->GetCommandClass( commandClassId );
if( cc )
{
cc->SetInstance( i );
if( m_endPointMap != MultiInstanceMapAll || i != 1 )
{
cc->SetEndPoint( i, endPoint );
}
// If we support the BASIC command class and it is mapped to a command class
// assigned to this end point, make sure the BASIC command class is also associated
// with this end point.
if( basic != NULL && basic->GetMapping() == commandClassId )
{
basic->SetInstance( i );
if( m_endPointMap != MultiInstanceMapAll || i != 1 )
{
basic->SetEndPoint( i, endPoint );
}
}
}
}
endPoint++;
}
}
else // Endpoints are different
{
for( set<uint8>::iterator it = m_endPointCommandClasses.begin(); it != m_endPointCommandClasses.end(); ++it )
{
uint8 commandClassId = *it;
CommandClass* cc = node->GetCommandClass( commandClassId );
if( cc )
{
uint8 i;
// Find the next free instance of this class
for( i = 1; i <= 127; i++ )
{
if( m_endPointMap == MultiInstanceMapAll ) // Include the non-endpoint instance
{
if( !cc->GetInstances()->IsSet( i ) )
{
break;
}
}
// Reuse non-endpoint instances first time we see it
else if( i == 1 && cc->GetInstances()->IsSet( i ) && cc->GetEndPoint( i ) == 0 )
{
break;
}
// Find the next free instance
else if( !cc->GetInstances()->IsSet( i ) )
{
break;
}
}
cc->SetInstance( i );
cc->SetEndPoint( i, endPoint );
// If we support the BASIC command class and it is mapped to a command class
// assigned to this end point, make sure the BASIC command class is also associated
// with this end point.
if( basic != NULL && basic->GetMapping() == commandClassId )
{
basic->SetInstance( i );
basic->SetEndPoint( i, endPoint );
}
}
}
}
}
}
//-----------------------------------------------------------------------------
// <MultiInstance::HandleMultiChannelEndPointFindReport>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
void MultiInstance::HandleMultiChannelEndPointFindReport
(
uint8 const* _data,
uint32 const _length
)
{
Log::Write( LogLevel_Info, GetNodeId(), "Received MultiChannelEndPointFindReport from node %d", GetNodeId() );
uint8 numEndPoints = _length - 5;
for( uint8 i=0; i<numEndPoints; ++i )
{
uint8 endPoint = _data[i+4] & 0x7f;
if( m_endPointsAreSameClass )
{
// Use the stored command class list to set up the endpoint.
if( Node* node = GetNodeUnsafe() )
{
for( set<uint8>::iterator it=m_endPointCommandClasses.begin(); it!=m_endPointCommandClasses.end(); ++it )
{
uint8 commandClassId = *it;
CommandClass* cc = node->GetCommandClass( commandClassId );
if( cc )
{
Log::Write( LogLevel_Info, GetNodeId(), " Endpoint %d: Adding %s", endPoint, cc->GetCommandClassName().c_str() );
cc->SetInstance( endPoint );
}
}
}
}
else
{
// Endpoints are different, so request the capabilities
char str[128];
snprintf( str, 128, "MultiChannelCmd_CapabilityGet for node %d, endpoint %d", GetNodeId(), endPoint );
Msg* msg = new Msg( str, GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( MultiChannelCmd_CapabilityGet );
msg->Append( endPoint );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
}
}
m_numEndPointsFound += numEndPoints;
if( !m_endPointsAreSameClass )
{
if( _data[1] == 0 )
{
// No more reports to follow this one, so we can continue the search.
if( m_numEndPointsFound < numEndPoints )
{
// We have not yet found all the endpoints, so move to the next generic class request
++m_endPointFindIndex;
if (m_endPointFindIndex <= 13) /* we are finished */
{
if( c_genericClass[m_endPointFindIndex] > 0 )
{
if (m_endPointFindIndex > 13) /* size of c_genericClassName minus Unknown Entry */
{
Log::Write (LogLevel_Warning, GetNodeId(), "m_endPointFindIndex Value was greater than range. Setting to Unknown");
m_endPointFindIndex = 14;
}
char str[128];
snprintf( str, 128, "MultiChannelCmd_EndPointFind for generic device class 0x%.2x (%s)", c_genericClass[m_endPointFindIndex], c_genericClassName[m_endPointFindIndex] );
Msg* msg = new Msg( str, GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 4 );
msg->Append( GetCommandClassId() );
msg->Append( MultiChannelCmd_EndPointFind );
msg->Append( c_genericClass[m_endPointFindIndex] ); // Generic device class
msg->Append( 0xff ); // Any specific device class
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
}
} else {
Log::Write (LogLevel_Warning, GetNodeId(), "m_endPointFindIndex is higher than range. Not Sending MultiChannelCmd_EndPointFind message");
}
}
}
}
}
//-----------------------------------------------------------------------------
// <MultiInstance::HandleMultiChannelEncap>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
void MultiInstance::HandleMultiChannelEncap
(
uint8 const* _data,
uint32 const _length
)
{
if( Node* node = GetNodeUnsafe() )
{
uint8 endPoint = _data[1] & 0x7f;
uint8 commandClassId = _data[3];
if( CommandClass* pCommandClass = node->GetCommandClass( commandClassId ) )
{
uint8 instance = pCommandClass->GetInstance( endPoint );
if( instance == 0 )
{
Log::Write( LogLevel_Error, GetNodeId(), "Cannot find endpoint map to instance for Command Class %s endpoint %d", pCommandClass->GetCommandClassName().c_str(), endPoint );
}
else
{
Log::Write( LogLevel_Info, GetNodeId(), "Received a MultiChannelEncap from node %d, endpoint %d for Command Class %s", GetNodeId(), endPoint, pCommandClass->GetCommandClassName().c_str() );
pCommandClass->HandleMsg( &_data[4], _length-4, instance );
}
} else {
Log::Write(LogLevel_Error, GetNodeId(), "Recieved a MultiChannelEncap for endpoint %d for Command Class %d, which we can't find", endPoint, commandClassId);
}
}
}
@@ -0,0 +1,111 @@
//-----------------------------------------------------------------------------
//
// MultiInstance.h
//
// Implementation of the Z-Wave COMMAND_CLASS_MULTI_INSTANCE
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _MultiInstance_H
#define _MultiInstance_H
#include <set>
#include "CommandClass.h"
namespace OpenZWave
{
/** \brief Implements COMMAND_CLASS_MULTI_INSTANCE (0x60), a Z-Wave device command class.
*/
class MultiInstance: public CommandClass
{
public:
enum MultiInstanceCmd
{
MultiInstanceCmd_Get = 0x04,
MultiInstanceCmd_Report = 0x05,
MultiInstanceCmd_Encap = 0x06,
// Version 2
MultiChannelCmd_EndPointGet = 0x07,
MultiChannelCmd_EndPointReport = 0x08,
MultiChannelCmd_CapabilityGet = 0x09,
MultiChannelCmd_CapabilityReport = 0x0a,
MultiChannelCmd_EndPointFind = 0x0b,
MultiChannelCmd_EndPointFindReport = 0x0c,
MultiChannelCmd_Encap = 0x0d
};
enum MultiInstanceMapping
{
MultiInstanceMapAll,
MultiInstanceMapEndPoints,
MultiInstanceMapOther
};
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new MultiInstance( _homeId, _nodeId ); }
virtual ~MultiInstance(){}
static uint8 const StaticGetCommandClassId(){ return 0x60; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_MULTI_INSTANCE/CHANNEL"; }
bool RequestInstances();
// From CommandClass
virtual void ReadXML( TiXmlElement const* _ccElement );
virtual void WriteXML( TiXmlElement* _ccElement );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual uint8 GetMaxVersion(){ return 2; }
MultiInstanceMapping GetEndPointMap(){ return m_endPointMap; }
private:
MultiInstance( uint32 const _homeId, uint8 const _nodeId );
void HandleMultiInstanceReport( uint8 const* _data, uint32 const _length );
void HandleMultiInstanceEncap( uint8 const* _data, uint32 const _length );
void HandleMultiChannelEndPointReport( uint8 const* _data, uint32 const _length );
void HandleMultiChannelCapabilityReport( uint8 const* _data, uint32 const _length );
void HandleMultiChannelEndPointFindReport( uint8 const* _data, uint32 const _length );
void HandleMultiChannelEncap( uint8 const* _data, uint32 const _length );
bool m_numEndPointsCanChange;
bool m_endPointsAreSameClass;
uint8 m_numEndPoints;
// Finding endpoints
uint8 m_endPointFindIndex;
uint8 m_numEndPointsFound;
set<uint8> m_endPointCommandClasses;
// configuration
uint8 m_numEndPointsHint; // for nodes that do not report correct number of end points
MultiInstanceMapping m_endPointMap; // Determine how to map end points to value id instances
bool m_endPointFindSupported; // for nodes that (someday may) support endpointfind
bool m_ignoreUnsolicitedMultiChannelCapabilityReport;
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,61 @@
//-----------------------------------------------------------------------------
//
// MultiInstanceAssociation.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_MULTI_INSTANCE_ASSOCIATION
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "MultiInstanceAssociation.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Driver.h"
#include "../platform/Log.h"
using namespace OpenZWave;
enum MultiInstanceAssociationCmd
{
MultiInstanceAssociationCmd_Set = 0x01,
MultiInstanceAssociationCmd_Get = 0x02,
MultiInstanceAssociationCmd_Report = 0x03,
MultiInstanceAssociationCmd_Remove = 0x04,
MultiInstanceAssociationCmd_GroupingsGet = 0x05,
MultiInstanceAssociationCmd_GroupingsReport = 0x06
};
//-----------------------------------------------------------------------------
// <MultiInstanceAssociation::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool MultiInstanceAssociation::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
return false;
}
@@ -0,0 +1,59 @@
//-----------------------------------------------------------------------------
//
// MultiInstanceAssociation.h
//
// Implementation of the Z-Wave COMMAND_CLASS_MULTI_INSTANCE_ASSOCIATION
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _MultiInstanceAssociation_H
#define _MultiInstanceAssociation_H
#include <vector>
#include "CommandClass.h"
namespace OpenZWave
{
/** \brief Implements COMMAND_CLASS_MULTI_INSTANCE_ASSOCIATION (0x8E), a Z-Wave device command class.
*/
class MultiInstanceAssociation: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new MultiInstanceAssociation( _homeId, _nodeId ); }
virtual ~MultiInstanceAssociation(){}
static uint8 const StaticGetCommandClassId(){ return 0x8e; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_MULTI_INSTANCE_ASSOCIATION"; }
// From CommandClass
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
private:
MultiInstanceAssociation( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,76 @@
//-----------------------------------------------------------------------------
//
// NoOperation.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_NO_OPERATION
//
// Copyright (c) 2012 Greg Satz <satz@iranger.com>
//
// 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 "CommandClasses.h"
#include "NoOperation.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
using namespace OpenZWave;
//-----------------------------------------------------------------------------
// <NoOperation::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool NoOperation::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
// We have received a no operation from the Z-Wave device.
Log::Write( LogLevel_Info, GetNodeId(), "Received NoOperation command from node %d", GetNodeId() );
return true;
}
//-----------------------------------------------------------------------------
// <NoOperation::Set>
// Send a No Operation message class.
//-----------------------------------------------------------------------------
void NoOperation::Set
(
bool const _route,
Driver::MsgQueue _queue // = Driver::MsgQueue_NoOp
)
{
Log::Write( LogLevel_Info, GetNodeId(), "NoOperation::Set - Routing=%s", _route ? "true" : "false" );
Msg* msg = new Msg( "NoOperation_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( 0 );
if( _route )
msg->Append( GetDriver()->GetTransmitOptions() );
else
msg->Append( TRANSMIT_OPTION_ACK | TRANSMIT_OPTION_NO_ROUTE );
GetDriver()->SendMsg( msg, _queue );
}
@@ -0,0 +1,60 @@
//-----------------------------------------------------------------------------
//
// NoOperation.h
//
// Implementation of the Z-Wave COMMAND_CLASS_NO_OPERATION
//
// Copyright (c) 2012 Greg Satz <satz@iranger.com>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _NoOperation_H
#define _NoOperation_H
#include "CommandClass.h"
namespace OpenZWave
{
/** \brief Implements COMMAND_CLASS_NO_OPERATION (0x00), a Z-Wave device command class.
*/
class NoOperation: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new NoOperation( _homeId, _nodeId ); }
virtual ~NoOperation(){}
static uint8 const StaticGetCommandClassId(){ return 0x00; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_NO_OPERATION"; }
void Set( bool const _route, Driver::MsgQueue const _queue = Driver::MsgQueue_NoOp );
// From CommandClass
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
private:
NoOperation( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,531 @@
//-----------------------------------------------------------------------------
//
// NodeNaming.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_NODE_NAMING
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "NodeNaming.h"
#include "Association.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../Notification.h"
#include "../platform/Log.h"
using namespace OpenZWave;
enum NodeNamingCmd
{
NodeNamingCmd_Set = 0x01,
NodeNamingCmd_Get = 0x02,
NodeNamingCmd_Report = 0x03,
NodeNamingCmd_LocationSet = 0x04,
NodeNamingCmd_LocationGet = 0x05,
NodeNamingCmd_LocationReport = 0x06
};
enum StringEncoding
{
StringEncoding_ASCII = 0,
StringEncoding_ExtendedASCII,
StringEncoding_UTF16
};
// Mapping of characters 0x80 and above to Unicode.
uint16 const c_extendedAsciiToUnicode[] =
{
0x20ac, // 0x80 - Euro Sign
0x0081, // 0x81 -
0x201a, // 0x82 - Single Low-9 Quotation Mark
0x0192, // 0x83 - Latin Small Letter F With Hook
0x201e, // 0x84 - Double Low-9 Quotation Mark
0x2026, // 0x85 - Horizontal Ellipsis
0x2020, // 0x86 - Dagger
0x2021, // 0x87 - Double Dagger
0x02c6, // 0x88 - Modifier Letter Circumflex Accent
0x2030, // 0x89 - Per Mille Sign
0x0160, // 0x8a - Latin Capital Letter S With Caron
0x2039, // 0x8b - Single Left-Pointing Angle Quotation Mark
0x0152, // 0x8c - Latin Capital Ligature Oe
0x008d, // 0x8d -
0x017d, // 0x8e - Latin Capital Letter Z With Caron
0x008f, // 0x8f -
0x0090, // 0x90 -
0x2018, // 0x91 - Left Single Quotation Mark
0x2019, // 0x92 - Right Single Quotation Mark
0x201c, // 0x93 - Left Double Quotation Mark
0x201d, // 0x94 - Right Double Quotation Mark
0x2022, // 0x95 - Bullet
0x2013, // 0x96 - En Dash
0x2014, // 0x97 - Em Dash
0x02dc, // 0x98 - Small Tilde
0x2122, // 0x99 - Trade Mark Sign
0x0161, // 0x9a - Latin Small Letter S With Caron
0x203a, // 0x9b - Single Right-Pointing Angle Quotation Mark
0x0153, // 0x9c - Latin Small Ligature Oe
0x009d, // 0x9d -
0x017e, // 0x9e - Latin Small Letter Z With Caron
0x0178, // 0x9f - Latin Capital Letter Y With Diaeresis
0x00a0, // 0xa0 - No-Break Space
0x00a1, // 0xa1 - Inverted Exclamation Mark
0x00a2, // 0xa2 - Cent Sign
0x00a3, // 0xa3 - Pound Sign
0x00a4, // 0xa4 - Currency Sign
0x00a5, // 0xa5 - Yen Sign
0x00a6, // 0xa6 - Broken Bar
0x00a7, // 0xa7 - Section Sign
0x00a8, // 0xa8 - Diaeresis
0x00a9, // 0xa9 - Copyright Sign
0x00aa, // 0xaa - Feminine Ordinal Indicator
0x00ab, // 0xab - Left-Pointing Double Angle Quotation Mark
0x00ac, // 0xac - Not Sign
0x00ad, // 0xad - Soft Hyphen
0x00ae, // 0xae - Registered Sign
0x00af, // 0xaf - Macron
0x00b0, // 0xb0 - Degree Sign
0x00b1, // 0xb1 - Plus-Minus Sign
0x00b2, // 0xb2 - Superscript Two
0x00b3, // 0xb3 - Superscript Three
0x00b4, // 0xb4 - Acute Accent
0x00b5, // 0xb5 - Micro Sign
0x00b6, // 0xb6 - Pilcrow Sign
0x00b7, // 0xb7 - Middle Dot
0x00b8, // 0xb8 - Cedilla
0x00b9, // 0xb9 - Superscript One
0x00ba, // 0xba - Masculine Ordinal Indicator
0x00bb, // 0xbb - Right-Pointing Double Angle Quotation Mark
0x00bc, // 0xbc - Vulgar Fraction One Quarter
0x00bd, // 0xbd - Vulgar Fraction One Half
0x00be, // 0xbe - Vulgar Fraction Three Quarters
0x00bf, // 0xbf - Inverted Question Mark
0x00c0, // 0xc0 - Latin Capital Letter A With Grave
0x00c1, // 0xc1 - Latin Capital Letter A With Acute
0x00c2, // 0xc2 - Latin Capital Letter A With Circumflex
0x00c3, // 0xc3 - Latin Capital Letter A With Tilde
0x00c4, // 0xc4 - Latin Capital Letter A With Diaeresis
0x00c5, // 0xc5 - Latin Capital Letter A With Ring Above
0x00c6, // 0xc6 - Latin Capital Ligature Ae
0x00c7, // 0xc7 - Latin Capital Letter C With Cedilla
0x00c8, // 0xc8 - Latin Capital Letter E With Grave
0x00c9, // 0xc9 - Latin Capital Letter E With Acute
0x00ca, // 0xca - Latin Capital Letter E With Circumflex
0x00cb, // 0xcb - Latin Capital Letter E With Diaeresis
0x00cc, // 0xcc - Latin Capital Letter I With Grave
0x00cd, // 0xcd - Latin Capital Letter I With Acute
0x00ce, // 0xce - Latin Capital Letter I With Circumflex
0x00cf, // 0xcf - Latin Capital Letter I With Diaeresis
0x00d0, // 0xd0 - Latin Capital Letter Eth
0x00d1, // 0xd1 - Latin Capital Letter N With Tilde
0x00d2, // 0xd2 - Latin Capital Letter O With Grave
0x00d3, // 0xd3 - Latin Capital Letter O With Acute
0x00d4, // 0xd4 - Latin Capital Letter O With Circumflex
0x00d5, // 0xd5 - Latin Capital Letter O With Tilde
0x00d6, // 0xd6 - Latin Capital Letter O With Diaeresis
0x00d7, // 0xd7 - Multiplication Sign
0x00d8, // 0xd8 - Latin Capital Letter O With Stroke
0x00d9, // 0xd9 - Latin Capital Letter U With Grave
0x00da, // 0xda - Latin Capital Letter U With Acute
0x00db, // 0xdb - Latin Capital Letter U With Circumflex
0x00dc, // 0xdc - Latin Capital Letter U With Diaeresis
0x00dd, // 0xdd - Latin Capital Letter Y With Acute
0x00de, // 0xde - Latin Capital Letter Thorn
0x00df, // 0xdf - Latin Small Letter Sharp S
0x00e0, // 0xe0 - Latin Small Letter A With Grave
0x00e1, // 0xe1 - Latin Small Letter A With Acute
0x00e2, // 0xe2 - Latin Small Letter A With Circumflex
0x00e3, // 0xe3 - Latin Small Letter A With Tilde
0x00e4, // 0xe4 - Latin Small Letter A With Diaeresis
0x00e5, // 0xe5 - Latin Small Letter A With Ring Above
0x00e6, // 0xe6 - Latin Small Ligature Ae
0x00e7, // 0xe7 - Latin Small Letter C With Cedilla
0x00e8, // 0xe8 - Latin Small Letter E With Grave
0x00e9, // 0xe9 - Latin Small Letter E With Acute
0x00ea, // 0xea - Latin Small Letter E With Circumflex
0x00eb, // 0xeb - Latin Small Letter E With Diaeresis
0x00ec, // 0xec - Latin Small Letter I With Grave
0x00ed, // 0xed - Latin Small Letter I With Acute
0x00ee, // 0xee - Latin Small Letter I With Circumflex
0x00ef, // 0xef - Latin Small Letter I With Diaeresis
0x00f0, // 0xf0 - Latin Small Letter Eth
0x00f1, // 0xf1 - Latin Small Letter N With Tilde
0x00f2, // 0xf2 - Latin Small Letter O With Grave
0x00f3, // 0xf3 - Latin Small Letter O With Acute
0x00f4, // 0xf4 - Latin Small Letter O With Circumflex
0x00f5, // 0xf5 - Latin Small Letter O With Tilde
0x00f6, // 0xf6 - Latin Small Letter O With Diaeresis
0x00f7, // 0xf7 - Division Sign
0x00f8, // 0xf8 - Latin Small Letter O With Stroke
0x00f9, // 0xf9 - Latin Small Letter U With Grave
0x00fa, // 0xfa - Latin Small Letter U With Acute
0x00fb, // 0xfb - Latin Small Letter U With Circumflex
0x00fc, // 0xfc - Latin Small Letter U With Diaeresis
0x00fd, // 0xfd - Latin Small Letter Y With Acute
0x00fe, // 0xfe - Latin Small Letter Thorn
0x00ff // 0xff - Latin Small Letter Y With Diaeresis
};
//-----------------------------------------------------------------------------
// <NodeNaming::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool NodeNaming::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
bool res = false;
if( _requestFlags & RequestFlag_Session )
{
if( Node* node = GetNodeUnsafe() )
{
if( node->m_nodeName == "" )
{
// If we don't already have a user-defined name, fetch it from the device
res |= RequestValue( _requestFlags, NodeNamingCmd_Get, _instance, _queue );
}
if( node->m_location == "" )
{
// If we don't already have a user-defined location, fetch it from the device
res |= RequestValue( _requestFlags, NodeNamingCmd_LocationGet, _instance, _queue );
}
}
}
return res;
}
//-----------------------------------------------------------------------------
// <NodeNaming::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool NodeNaming::RequestValue
(
uint32 const _requestFlags,
uint8 const _getTypeEnum,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _instance != 1 )
{
// This command class doesn't work with multiple instances
return false;
}
Msg* msg;
if( _getTypeEnum == NodeNamingCmd_Get )
{
if ( IsGetSupported() )
{
msg = new Msg( "NodeNamingCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( NodeNamingCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "NodeNamingCmd_Get Not Supported on this node");
}
return false;
}
if( _getTypeEnum == NodeNamingCmd_LocationGet )
{
// If we don't already have a user-defined name, fetch it from the device
msg = new Msg( "NodeNamingCmd_LocationGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( NodeNamingCmd_LocationGet );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <NodeNaming::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool NodeNaming::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
bool updated = false;
if( Node* node = GetNodeUnsafe() )
{
if( NodeNamingCmd_Report == (NodeNamingCmd)_data[0] )
{
string name = ExtractString( _data, _length );
if( node->m_nodeName == "" )
{
// We only overwrite the name if it is empty
node->m_nodeName = name;
Log::Write( LogLevel_Info, GetNodeId(), "Received the name: %s.", name.c_str() );
updated = true;
}
}
else if( NodeNamingCmd_LocationReport == (NodeNamingCmd)_data[0] )
{
string location = ExtractString( _data, _length );
if( node->m_location == "" )
{
// We only overwrite the location if it is empty
node->m_location = location;
Log::Write( LogLevel_Info, GetNodeId(), "Received the location: %s.", location.c_str() );
updated = true;
}
}
}
if( updated )
{
Notification* notification = new Notification( Notification::Type_NodeNaming );
notification->SetHomeAndNodeIds( GetHomeId(), GetNodeId() );
GetDriver()->QueueNotification( notification );
}
return true;
}
//-----------------------------------------------------------------------------
// <NodeNaming::SetName>
// Set the name in the device
//-----------------------------------------------------------------------------
void NodeNaming::SetName
(
string const& _name
)
{
size_t length = _name.size();
if( length > 16 )
{
length = 16;
}
Log::Write( LogLevel_Info, GetNodeId(), "NodeNaming::Set - Naming to '%s'", _name.c_str() );
Msg* msg = new Msg( "NodeNaming Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->Append( GetNodeId() );
msg->Append( (uint8)(length + 3) );
msg->Append( GetCommandClassId() );
msg->Append( NodeNamingCmd_Set );
msg->Append( (uint8)StringEncoding_ASCII );
for( uint32 i=0; i<length; ++i )
{
msg->Append( _name[i] );
}
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
}
//-----------------------------------------------------------------------------
// <NodeNaming::SetLocation>
// Set the location in the device
//-----------------------------------------------------------------------------
void NodeNaming::SetLocation
(
string const& _location
)
{
size_t length = _location.size();
if( length > 16 )
{
length = 16;
}
Log::Write( LogLevel_Info, GetNodeId(), "NodeNaming::SetLocation - Setting location to '%s'", _location.c_str() );
Msg* msg = new Msg( "NodeNaming Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->Append( GetNodeId() );
msg->Append( (uint8)(length + 3) );
msg->Append( GetCommandClassId() );
msg->Append( NodeNamingCmd_LocationSet );
msg->Append( (uint8)StringEncoding_ASCII );
for( uint32 i=0; i<length; ++i )
{
msg->Append( _location[i] );
}
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
}
//-----------------------------------------------------------------------------
// <NodeNaming::ExtractString>
// Extract a string from the report data
//-----------------------------------------------------------------------------
string NodeNaming::ExtractString
(
uint8 const* _data,
uint32 const _length
)
{
uint8 i;
char str[32];
uint32 pos = 0;
str[0] = 0;
StringEncoding encoding = (StringEncoding)( _data[1] & 0x07 );
if( _length >= 3 )
{
// Get the length of the string (maximum allowed is 16 bytes)
uint8 numBytes = _length - 3;
if( numBytes > 16 )
{
numBytes = 16;
}
switch( encoding )
{
case StringEncoding_ASCII:
{
// Copy data as-is
for( i=0; i<numBytes; ++i )
{
str[pos++] = _data[i+2];
}
break;
}
case StringEncoding_ExtendedASCII:
{
// Convert Extended ASCII characters to UTF-8
for( i=0; i<numBytes; ++i )
{
uint8 ch = _data[i+2];
if( ch >= 0x80 )
{
uint16 utf16 = c_extendedAsciiToUnicode[ch-0x80];
pos = ConvertUFT16ToUTF8( utf16, str, pos );
}
else
{
str[pos++] = (char)ch;
}
}
break;
}
case StringEncoding_UTF16:
{
// Convert UTF-16 characters to UTF-8
for( i=0; i<numBytes; i+=2 )
{
uint16 utf16 = (((uint16)_data[i+2])<<8) | (uint16)_data[i+3];
pos = ConvertUFT16ToUTF8( utf16, str, pos );
}
break;
}
default:
{
}
}
str[pos] = 0;
}
return string( str );
}
//-----------------------------------------------------------------------------
// <NodeNaming::ConvertUFT16ToUTF8>
// Convert a UTF-16 string into UTF-8 encoding.
//-----------------------------------------------------------------------------
uint32 NodeNaming::ConvertUFT16ToUTF8
(
uint16 _utf16,
char* _buffer,
uint32 pos
)
{
static uint16 surrogate = 0;
if( ( surrogate != 0 ) && ( ( _utf16 & 0xdc00 ) == 0xdc00 ) )
{
// UTF-16 surrogate character pair converts to four UTF-8 characters.
// We have the second member of the pair, so we can do the conversion now.
_buffer[pos++] = (char)( ((surrogate>>7) & 0x0007) | 0x00f0 );
_buffer[pos++] = (char)( ((surrogate>>1) & 0x0020) | ((surrogate>>2) & 0x000f) | 0x0090 );
_buffer[pos++] = (char)( ((_utf16>>6) & 0x000f) | ((surrogate<<4) & 0x0030) | 0x0080 );
_buffer[pos++] = (char)( (_utf16 & 0x003f) | 0x0080 );
}
else
{
surrogate = 0;
if( _utf16 & 0xff80 )
{
if( _utf16 & 0xf800 )
{
if( ( _utf16 & 0xd800 ) == 0xd800 )
{
// UTF-16 surrogate character pair converts to four UTF-8 characters.
// We have the first member of the pair, so we store it for next time.
surrogate = _utf16;
}
else
{
// UTF-16 character can be represented by three UTF-8 characters.
_buffer[pos++] = (char)( (_utf16>>12) | 0x00e0 );
_buffer[pos++] = (char)( ((_utf16>>6) & 0x003f) | 0x0080 );
_buffer[pos++] = (char)( (_utf16 & 0x003f) | 0x0080 );
}
}
else
{
// UTF-16 character can be represented by two UTF-8 characters.
_buffer[pos++] = (char)( (_utf16>>6) | 0x00c0 );
_buffer[pos++] = (char)( (_utf16 & 0x003f) | 0x0080 );
}
}
else
{
// UTF-16 character matches single ascii character.
_buffer[pos++] = (char)_utf16;
}
}
return pos;
}
@@ -0,0 +1,66 @@
//-----------------------------------------------------------------------------
//
// NodeNaming.h
//
// Implementation of the Z-Wave COMMAND_CLASS_NODE_NAMING
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _NodeNaming_H
#define _NodeNaming_H
#include "CommandClass.h"
namespace OpenZWave
{
/** \brief Implements COMMAND_CLASS_NODE_NAMING (0x77), a Z-Wave device command class.
*/
class NodeNaming: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new NodeNaming( _homeId, _nodeId ); }
virtual ~NodeNaming(){}
static uint8 const StaticGetCommandClassId(){ return 0x77; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_NODE_NAMING"; }
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
void SetName( string const& _name );
void SetLocation( string const& _location );
private:
NodeNaming( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
string ExtractString( uint8 const* _data, uint32 const _length );
uint32 ConvertUFT16ToUTF8( uint16 _utf16, char* _buffer, uint32 pos );
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,501 @@
//-----------------------------------------------------------------------------
//
// Powerlevel.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_POWERLEVEL
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 <vector>
#include "CommandClasses.h"
#include "Powerlevel.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueByte.h"
#include "../value_classes/ValueShort.h"
#include "../value_classes/ValueList.h"
#include "../value_classes/ValueButton.h"
using namespace OpenZWave;
enum PowerlevelCmd
{
PowerlevelCmd_Set = 0x01,
PowerlevelCmd_Get = 0x02,
PowerlevelCmd_Report = 0x03,
PowerlevelCmd_TestNodeSet = 0x04,
PowerlevelCmd_TestNodeGet = 0x05,
PowerlevelCmd_TestNodeReport = 0x06
};
enum
{
PowerlevelIndex_Powerlevel = 0,
PowerlevelIndex_Timeout,
PowerlevelIndex_Set,
PowerlevelIndex_TestNode,
PowerlevelIndex_TestPowerlevel,
PowerlevelIndex_TestFrames,
PowerlevelIndex_Test,
PowerlevelIndex_Report,
PowerlevelIndex_TestStatus,
PowerlevelIndex_TestAckFrames
};
static char const* c_powerLevelNames[] =
{
"Normal",
"-1dB",
"-2dB",
"-3dB",
"-4dB",
"-5dB",
"-6dB",
"-7dB",
"-8dB",
"-9dB",
"Unknown"
};
static char const* c_powerLevelStatusNames[] =
{
"Failed",
"Success",
"In Progress",
"Unknown"
};
//-----------------------------------------------------------------------------
// <Powerlevel::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool Powerlevel::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _requestFlags & RequestFlag_Session )
{
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <Powerlevel::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool Powerlevel::RequestValue
(
uint32 const _requestFlags,
uint8 const _index,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _index == 0 )
{
if ( IsGetSupported() )
{
Msg* msg = new Msg( "Powerlevel_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( PowerlevelCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "Powerlevel_Get Not Supported on this node");
}
}
return false;
}
//-----------------------------------------------------------------------------
// <Powerlevel::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool Powerlevel::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( PowerlevelCmd_Report == (PowerlevelCmd)_data[0] )
{
PowerLevelEnum powerLevel = (PowerLevelEnum)_data[1];
if (powerLevel > 9) /* size of c_powerLevelNames minus Unknown*/
{
Log::Write (LogLevel_Warning, GetNodeId(), "powerLevel Value was greater than range. Setting to Invalid");
powerLevel = (PowerLevelEnum)10;
}
uint8 timeout = _data[2];
Log::Write( LogLevel_Info, GetNodeId(), "Received a PowerLevel report: PowerLevel=%s, Timeout=%d", c_powerLevelNames[powerLevel], timeout );
if( ValueList* value = static_cast<ValueList*>( GetValue( _instance, PowerlevelIndex_Powerlevel ) ) )
{
value->OnValueRefreshed( (int)powerLevel );
value->Release();
}
if( ValueByte* value = static_cast<ValueByte*>( GetValue( _instance, PowerlevelIndex_Timeout ) ) )
{
value->OnValueRefreshed( timeout );
value->Release();
}
return true;
}
if( PowerlevelCmd_TestNodeReport == (PowerlevelCmd)_data[0] )
{
uint8 testNode = _data[1];
PowerLevelStatusEnum status = (PowerLevelStatusEnum)_data[2];
uint16 ackCount = (((uint16)_data[3])<<8) | (uint16)_data[4];
if (status > 2) /* size of c_powerLevelStatusNames minus Unknown */
{
Log::Write (LogLevel_Warning, GetNodeId(), "status Value was greater than range. Setting to Unknown");
status = (PowerLevelStatusEnum)3;
}
Log::Write( LogLevel_Info, GetNodeId(), "Received a PowerLevel Test Node report: Test Node=%d, Status=%s, Test Frame ACK Count=%d", testNode, c_powerLevelStatusNames[status], ackCount );
if( ValueByte* value = static_cast<ValueByte*>( GetValue( _instance, PowerlevelIndex_TestNode ) ) )
{
value->OnValueRefreshed( testNode );
value->Release();
}
if( ValueList* value = static_cast<ValueList*>( GetValue( _instance, PowerlevelIndex_TestStatus ) ) )
{
value->OnValueRefreshed( (int)status );
value->Release();
}
if( ValueShort* value = static_cast<ValueShort*>( GetValue( _instance, PowerlevelIndex_TestAckFrames ) ) )
{
value->OnValueRefreshed( (short)ackCount );
value->Release();
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <Powerlevel::SetValue>
// Set a value on the Z-Wave device
//-----------------------------------------------------------------------------
bool Powerlevel::SetValue
(
Value const& _value
)
{
bool res = false;
uint8 instance = _value.GetID().GetInstance();
switch( _value.GetID().GetIndex() )
{
case PowerlevelIndex_Powerlevel:
{
if( ValueList* value = static_cast<ValueList*>( GetValue( instance, PowerlevelIndex_Powerlevel ) ) )
{
ValueList::Item const& item = (static_cast<ValueList const*>( &_value))->GetItem();
value->OnValueRefreshed( item.m_value );
value->Release();
}
res = true;
break;
}
case PowerlevelIndex_Timeout:
{
if( ValueByte* value = static_cast<ValueByte*>( GetValue( instance, PowerlevelIndex_Timeout ) ) )
{
value->OnValueRefreshed( (static_cast<ValueByte const*>( &_value))->GetValue() );
value->Release();
}
res = true;
break;
}
case PowerlevelIndex_Set:
{
// Set
if( ValueButton* button = static_cast<ValueButton*>( GetValue( instance, PowerlevelIndex_Set ) ) )
{
if( button->IsPressed() )
{
res = Set( instance );
}
button->Release();
}
break;
}
case PowerlevelIndex_TestNode:
{
if( ValueByte* value = static_cast<ValueByte*>( GetValue( instance, PowerlevelIndex_TestNode ) ) )
{
value->OnValueRefreshed( (static_cast<ValueByte const*>( &_value))->GetValue() );
value->Release();
}
res = true;
break;
}
case PowerlevelIndex_TestPowerlevel:
{
if( ValueList* value = static_cast<ValueList*>( GetValue( instance, PowerlevelIndex_TestPowerlevel ) ) )
{
ValueList::Item const& item = (static_cast<ValueList const*>( &_value))->GetItem();
value->OnValueRefreshed( item.m_value );
value->Release();
}
res = true;
break;
}
case PowerlevelIndex_TestFrames:
{
if( ValueShort* value = static_cast<ValueShort*>( GetValue( instance, PowerlevelIndex_TestFrames ) ) )
{
value->OnValueRefreshed( (static_cast<ValueByte const*>( &_value))->GetValue() );
value->Release();
}
res = true;
break;
}
case PowerlevelIndex_Test:
{
// Test
if( ValueButton* button = static_cast<ValueButton*>( GetValue( instance, PowerlevelIndex_Test ) ) )
{
if( button->IsPressed() )
{
res = Test( instance );
}
button->Release();
}
break;
}
case PowerlevelIndex_Report:
{
// Test
if( ValueButton* button = static_cast<ValueButton*>( GetValue( instance, PowerlevelIndex_Report ) ) )
{
if( button->IsPressed() )
{
res = Report( instance );
}
button->Release();
}
break;
}
}
return res;
}
//-----------------------------------------------------------------------------
// <Powerlevel::Set>
// Set the transmit power of a node for a specified time
//-----------------------------------------------------------------------------
bool Powerlevel::Set
(
uint8 const _instance
)
{
PowerLevelEnum powerLevel;
uint8 timeout;
if( ValueList* value = static_cast<ValueList*>( GetValue( _instance, PowerlevelIndex_Powerlevel ) ) )
{
ValueList::Item const& item = value->GetItem();
powerLevel = (PowerLevelEnum)item.m_value;
value->Release();
}
else
{
return false;
}
if( ValueByte* value = static_cast<ValueByte*>( GetValue( _instance, PowerlevelIndex_Timeout ) ) )
{
timeout = value->GetValue();
value->Release();
}
else
{
return false;
}
if (powerLevel > 9) /* size of c_powerLevelNames minus Unknown */
{
Log::Write (LogLevel_Warning, GetNodeId(), "powerLevel Value was greater than range. Dropping");
/* Drop it */
return false;
}
Log::Write( LogLevel_Info, GetNodeId(), "Setting the power level to %s for %d seconds", c_powerLevelNames[powerLevel], timeout );
Msg* msg = new Msg( "PowerlevelCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 4 );
msg->Append( GetCommandClassId() );
msg->Append( PowerlevelCmd_Set );
msg->Append( (uint8)powerLevel );
msg->Append( timeout );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
//-----------------------------------------------------------------------------
// <Powerlevel::Test>
// Test node to node communications
//-----------------------------------------------------------------------------
bool Powerlevel::Test
(
uint8 const _instance
)
{
uint8 testNodeId;
PowerLevelEnum powerLevel;
uint16 numFrames;
if( ValueByte* value = static_cast<ValueByte*>( GetValue( _instance, PowerlevelIndex_TestNode ) ) )
{
testNodeId = value->GetValue();
value->Release();
}
else
{
return false;
}
if( ValueList* value = static_cast<ValueList*>( GetValue( _instance, PowerlevelIndex_TestPowerlevel ) ) )
{
ValueList::Item const& item = value->GetItem();
powerLevel = (PowerLevelEnum)item.m_value;
value->Release();
}
else
{
return false;
}
if( ValueShort* value = static_cast<ValueShort*>( GetValue( _instance, PowerlevelIndex_TestFrames ) ) )
{
numFrames = value->GetValue();
value->Release();
}
else
{
return false;
}
if (powerLevel > 9) /* size of c_powerLevelNames minus Unknown */
{
Log::Write (LogLevel_Warning, GetNodeId(), "powerLevel Value was greater than range. Dropping");
return false;
}
Log::Write( LogLevel_Info, GetNodeId(), "Running a Power Level Test: Target Node = %d, Power Level = %s, Number of Frames = %d", testNodeId, c_powerLevelNames[powerLevel], numFrames );
Msg* msg = new Msg( "PowerlevelCmd_TestNodeSet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 6 );
msg->Append( GetCommandClassId() );
msg->Append( PowerlevelCmd_TestNodeSet );
msg->Append( testNodeId );
msg->Append( (uint8)powerLevel );
msg->Append( (uint8)(numFrames >> 8) );
msg->Append( (uint8)(numFrames & 0x00ff) );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
//-----------------------------------------------------------------------------
// <Powerlevel::Report>
// Request test report
//-----------------------------------------------------------------------------
bool Powerlevel::Report
(
uint8 const _instance
)
{
Log::Write( LogLevel_Info, GetNodeId(), "Power Level Report" );
Msg* msg = new Msg( "PowerlevelCmd_TestNodeGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 6 );
msg->Append( GetCommandClassId() );
msg->Append( PowerlevelCmd_TestNodeGet );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
//-----------------------------------------------------------------------------
// <Powerlevel::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void Powerlevel::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
vector<ValueList::Item> items;
ValueList::Item item;
for( uint8 i=0; i<10; ++i )
{
item.m_label = c_powerLevelNames[i];
item.m_value = i;
items.push_back( item );
}
node->CreateValueList( ValueID::ValueGenre_System, GetCommandClassId(), _instance, PowerlevelIndex_Powerlevel, "Powerlevel", "dB", false, false, 1, items, 0, 0 );
node->CreateValueByte( ValueID::ValueGenre_System, GetCommandClassId(), _instance, PowerlevelIndex_Timeout, "Timeout", "seconds", false, false, 0, 0 );
node->CreateValueButton( ValueID::ValueGenre_System, GetCommandClassId(), _instance, PowerlevelIndex_Set, "Set Powerlevel", 0 );
node->CreateValueByte( ValueID::ValueGenre_System, GetCommandClassId(), _instance, PowerlevelIndex_TestNode, "Test Node", "", false, false, 0, 0 );
node->CreateValueList( ValueID::ValueGenre_System, GetCommandClassId(), _instance, PowerlevelIndex_TestPowerlevel, "Test Powerlevel", "dB", false, false, 1, items, 0, 0 );
node->CreateValueShort( ValueID::ValueGenre_System, GetCommandClassId(), _instance, PowerlevelIndex_TestFrames, "Frame Count", "", false, false, 0, 0 );
node->CreateValueButton( ValueID::ValueGenre_System, GetCommandClassId(), _instance, PowerlevelIndex_Test, "Test", 0 );
node->CreateValueButton( ValueID::ValueGenre_System, GetCommandClassId(), _instance, PowerlevelIndex_Report, "Report", 0 );
items.clear();
for( uint8 i=0; i<3; ++i )
{
item.m_label = c_powerLevelStatusNames[i];
item.m_value = i;
items.push_back( item );
}
node->CreateValueList( ValueID::ValueGenre_System, GetCommandClassId(), _instance, PowerlevelIndex_TestStatus, "Test Status", "", true, false, 1, items, 0, 0 );
node->CreateValueShort( ValueID::ValueGenre_System, GetCommandClassId(), _instance, PowerlevelIndex_TestAckFrames, "Acked Frames", "", true, false, 0, 0 );
}
}
@@ -0,0 +1,91 @@
//-----------------------------------------------------------------------------
//
// Powerlevel.h
//
// Implementation of the Z-Wave COMMAND_CLASS_POWERLEVEL
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _Powerlevel_H
#define _Powerlevel_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueList;
/** \brief Implements COMMAND_CLASS_POWERLEVEL (0x73), a Z-Wave device command class.
*/
class Powerlevel: public CommandClass
{
public:
enum PowerLevelEnum
{
PowerLevel_Normal = 0,
PowerLevel_Minus1dB,
PowerLevel_Minus2dB,
PowerLevel_Minus3dB,
PowerLevel_Minus4dB,
PowerLevel_Minus5dB,
PowerLevel_Minus6dB,
PowerLevel_Minus7dB,
PowerLevel_Minus8dB,
PowerLevel_Minus9dB
};
enum PowerLevelStatusEnum
{
PowerLevelStatus_Failed = 0,
PowerLevelStatus_Success,
PowerLevelStatus_InProgress
};
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Powerlevel( _homeId, _nodeId ); }
virtual ~Powerlevel(){}
static uint8 const StaticGetCommandClassId(){ return 0x73; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_POWERLEVEL"; }
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
protected:
virtual void CreateVars( uint8 const _instance );
private:
Powerlevel( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
bool Set( uint8 const _instance );
bool Test( uint8 const _instance );
bool Report( uint8 const _instance );
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,62 @@
//-----------------------------------------------------------------------------
//
// Proprietary.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_PROPRIETARY
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "Proprietary.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Driver.h"
#include "../platform/Log.h"
using namespace OpenZWave;
enum ProprietaryCmd
{
ProprietaryCmd_Set = 0x01,
ProprietaryCmd_Get = 0x02,
ProprietaryCmd_Report = 0x03
};
//-----------------------------------------------------------------------------
// <Proprietary::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool Proprietary::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if (ProprietaryCmd_Report == (ProprietaryCmd)_data[0])
{
return true;
}
return false;
}
@@ -0,0 +1,58 @@
//-----------------------------------------------------------------------------
//
// Proprietary.h
//
// Implementation of the Z-Wave COMMAND_CLASS_PROPRIETARY
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _Proprietary_H
#define _Proprietary_H
#include "CommandClass.h"
namespace OpenZWave
{
/** \brief Implements COMMAND_CLASS_PROPRIETARY (0x88), a Z-Wave device command class.
*/
class Proprietary: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Proprietary( _homeId, _nodeId ); }
virtual ~Proprietary(){}
static uint8 const StaticGetCommandClassId(){ return 0x88; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_PROPRIETARY"; }
// From CommandClass
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
private:
Proprietary( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,190 @@
//-----------------------------------------------------------------------------
//
// Protection.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_PROTECTION
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 <vector>
#include "CommandClasses.h"
#include "Protection.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueList.h"
using namespace OpenZWave;
enum ProtectionCmd
{
ProtectionCmd_Set = 0x01,
ProtectionCmd_Get = 0x02,
ProtectionCmd_Report = 0x03
};
static char const* c_protectionStateNames[] =
{
"Unprotected",
"Protection by Sequence",
"No Operation Possible",
"Unknown"
};
//-----------------------------------------------------------------------------
// <Protection::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool Protection::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _requestFlags & RequestFlag_Session )
{
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <Protection::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool Protection::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if ( IsGetSupported() )
{
Msg* msg = new Msg( "ProtectionCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( ProtectionCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "ProtectionCmd_Get Not Supported on this node");
}
return false;
}
//-----------------------------------------------------------------------------
// <Protection::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool Protection::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if (ProtectionCmd_Report == (ProtectionCmd)_data[0])
{
int8 stateValue = _data[1];
if (stateValue > 2) /* size of c_protectionStateNames minus Invalid */
{
Log::Write (LogLevel_Warning, GetNodeId(), "State Value was greater than range. Setting to Invalid");
stateValue = 3;
}
Log::Write( LogLevel_Info, GetNodeId(), "Received a Protection report: %s", c_protectionStateNames[_data[1]] );
if( ValueList* value = static_cast<ValueList*>( GetValue( _instance, 0 ) ) )
{
value->OnValueRefreshed( (int)_data[1] );
value->Release();
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <Protection::SetValue>
// Set the device's protection state
//-----------------------------------------------------------------------------
bool Protection::SetValue
(
Value const& _value
)
{
if( ValueID::ValueType_List == _value.GetID().GetType() )
{
ValueList const* value = static_cast<ValueList const*>(&_value);
ValueList::Item const& item = value->GetItem();
Log::Write( LogLevel_Info, GetNodeId(), "Protection::Set - Setting protection state to '%s'", item.m_label.c_str() );
Msg* msg = new Msg( "Protection Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->SetInstance( this, _value.GetID().GetInstance() );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( ProtectionCmd_Set );
msg->Append( (uint8)item.m_value );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <Protection::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void Protection::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
vector<ValueList::Item> items;
ValueList::Item item;
for( uint8 i=0; i<3; ++i )
{
item.m_label = c_protectionStateNames[i];
item.m_value = i;
items.push_back( item );
}
node->CreateValueList( ValueID::ValueGenre_System, GetCommandClassId(), _instance, 0, "Protection", "", false, false, 1, items, 0, 0 );
}
}
@@ -0,0 +1,73 @@
//-----------------------------------------------------------------------------
//
// Protection.h
//
// Implementation of the Z-Wave COMMAND_CLASS_PROTECTION
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _Protection_H
#define _Protection_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueList;
/** \brief Implements COMMAND_CLASS_PROTECTION (0x75), a Z-Wave device command class.
*/
class Protection: public CommandClass
{
public:
enum ProtectionEnum
{
Protection_Unprotected = 0,
Protection_Sequence,
Protection_NOP
};
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Protection( _homeId, _nodeId ); }
virtual ~Protection(){}
static uint8 const StaticGetCommandClassId(){ return 0x75; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_PROTECTION"; }
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
protected:
virtual void CreateVars( uint8 const _instance );
private:
Protection( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,78 @@
//-----------------------------------------------------------------------------
//
// SceneActivation.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_SCENE_ACTIVATION
//
// Copyright (c) 2012 Greg Satz <satz@iranger.com>
//
// 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 "CommandClasses.h"
#include "SceneActivation.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../Notification.h"
#include "../platform/Log.h"
using namespace OpenZWave;
enum SceneActivationCmd
{
SceneActivationCmd_Set = 0x01
};
//-----------------------------------------------------------------------------
// <SceneActivation::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool SceneActivation::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( SceneActivationCmd_Set == (SceneActivationCmd)_data[0] )
{
// Scene Activation Set received so send notification
char msg[64];
if( _data[2] == 0 )
snprintf( msg, sizeof(msg), "now" );
else if( _data[2] <= 0x7F )
snprintf( msg, sizeof(msg), "%d seconds", _data[2] );
else if( _data[2] <= 0xFE )
snprintf( msg, sizeof(msg), "%d minutes", _data[2] );
else
snprintf( msg, sizeof(msg), "via configuration" );
Log::Write( LogLevel_Info, GetNodeId(), "Received Scene Activation set from node %d: scene id=%d %s. Sending event notification.", GetNodeId(), _data[1], msg );
Notification* notification = new Notification( Notification::Type_SceneEvent );
notification->SetHomeAndNodeIds( GetHomeId(), GetNodeId() );
notification->SetSceneId( _data[1] );
GetDriver()->QueueNotification( notification );
return true;
}
return false;
}
@@ -0,0 +1,64 @@
//-----------------------------------------------------------------------------
//
// SceneActivation.h
//
// Implementation of the Z-Wave COMMAND_CLASS_SCENE_ACTIVATION
//
// Copyright (c) 2012 Greg Satz <satz@iranger.com>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _SceneActivation_H
#define _SceneActivation_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueByte;
/** \brief Implements COMMAND_CLASS_SCENEACTIVATION (0x2B), a Z-Wave device command class.
*/
class SceneActivation: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SceneActivation( _homeId, _nodeId ); }
virtual ~SceneActivation(){}
/** \brief Get command class ID (1 byte) identifying this command class. */
static uint8 const StaticGetCommandClassId(){ return 0x2B; }
/** \brief Get a string containing the name of this command class. */
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SCENE_ACTIVATION"; }
// From CommandClass
/** \brief Get command class ID (1 byte) identifying this command class. (Inherited from CommandClass) */
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
/** \brief Get a string containing the name of this command class. (Inherited from CommandClass) */
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
/** \brief Handle a response to a message associated with this command class. (Inherited from CommandClass) */
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
private:
SceneActivation( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,124 @@
//-----------------------------------------------------------------------------
//
// Security.h
//
// Implementation of the Z-Wave COMMAND_CLASS_Security
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _Security_H
#define _Security_H
#include <ctime>
#include "../aes/aescpp.h"
#include "CommandClass.h"
namespace OpenZWave
{
/** \brief Implements COMMAND_CLASS_SECURITY (0x98), a Z-Wave device command class.
*/
typedef struct SecurityPayload {
uint8 m_length;
uint8 m_part;
uint8 m_data[32];
string logmsg;
} SecurityPayload;
/* This should probably go into its own file, but its so simple... and only the Security Command Class uses it currently
*/
class Timer {
public:
Timer() {
this->Reset();
};
virtual ~Timer() {};
void Reset() {
start = clock();
}
inline uint64 GetMilliseconds() {
return (uint64 )(((clock() - start) / (double)CLOCKS_PER_SEC) / 1000);
}
private:
clock_t start;
};
class Security: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Security( _homeId, _nodeId ); }
virtual ~Security();
static uint8 const StaticGetCommandClassId(){ return 0x98; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SECURITY"; }
bool Init();
// From CommandClass
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
void ReadXML(TiXmlElement const* _ccElement);
void WriteXML(TiXmlElement* _ccElement);
void SendMsg( Msg* _msg );
protected:
void CreateVars( uint8 const _instance );
private:
Security( uint32 const _homeId, uint8 const _nodeId );
bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue);
bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue);
bool HandleSupportedReport(uint8 const* _data, uint32 const _length);
void SendNonceReport();
void RequestNonce();
bool GenerateAuthentication( uint8 const* _data, uint32 const _length, uint8 const _sendingNode, uint8 const _receivingNode, uint8 *iv, uint8* _authentication);
bool DecryptMessage( uint8 const* _data, uint32 const _length );
bool EncryptMessage( uint8 const* _nonce );
void QueuePayload( SecurityPayload * _payload );
bool createIVFromPacket_inbound(uint8 const* _data, uint8 *iv);
bool createIVFromPacket_outbound(uint8 const* _data, uint8 *iv);
void SetupNetworkKey();
Mutex *m_queueMutex;
list<SecurityPayload *> m_queue; // Messages waiting to be sent when the device wakes up
bool m_waitingForNonce;
uint8 m_sequenceCounter;
Timer m_nonceTimer;
uint8 currentNonce[8];
bool m_networkkeyset;
aes_encrypt_ctx *AuthKey;
aes_encrypt_ctx *EncryptKey;
uint8 *nk;
bool m_schemeagreed;
bool m_secured;
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,215 @@
//-----------------------------------------------------------------------------
//
// SensorAlarm.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_SENSOR_ALARM
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "SensorAlarm.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueByte.h"
using namespace OpenZWave;
enum SensorAlarmCmd
{
SensorAlarmCmd_Get = 0x01,
SensorAlarmCmd_Report = 0x02,
SensorAlarmCmd_SupportedGet = 0x03,
SensorAlarmCmd_SupportedReport = 0x04
};
static char const* c_alarmTypeName[] =
{
"General",
"Smoke",
"Carbon Monoxide",
"Carbon Dioxide",
"Heat",
"Flood"
};
//-----------------------------------------------------------------------------
// <SensorAlarm::SensorAlarm>
// Constructor
//-----------------------------------------------------------------------------
SensorAlarm::SensorAlarm
(
uint32 const _homeId,
uint8 const _nodeId
):
CommandClass( _homeId, _nodeId )
{
SetStaticRequest( StaticRequest_Values );
}
//-----------------------------------------------------------------------------
// <SensorAlarm::RequestState>
// Get the static thermostat setpoint details from the device
//-----------------------------------------------------------------------------
bool SensorAlarm::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
bool requests = false;
if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) )
{
requests = RequestValue( _requestFlags, 0xff, _instance, _queue );
}
if( _requestFlags & RequestFlag_Dynamic )
{
for( uint8 i=0; i<SensorAlarm_Count; ++i )
{
Value* value = GetValue( 1, i );
if( value != NULL )
{
value->Release();
// There is a value for this alarm type, so request it
requests |= RequestValue( _requestFlags, i, _instance, _queue );
}
}
}
return requests;
}
//-----------------------------------------------------------------------------
// <SensorAlarm::RequestValue>
// Get the sensor alarm details from the device
//-----------------------------------------------------------------------------
bool SensorAlarm::RequestValue
(
uint32 const _requestFlags,
uint8 const _alarmType,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _alarmType == 0xff )
{
// Request the supported alarm types
Msg* msg = new Msg( "SensorAlarmCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( SensorAlarmCmd_SupportedGet );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
}
else
{
// Request the alarm state
if ( IsGetSupported() )
{
Msg* msg = new Msg( "SensorAlarmCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( SensorAlarmCmd_Get );
msg->Append( _alarmType );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "SensorAlarmCmd_Get Not Supported on this node");
}
}
return false;
}
//-----------------------------------------------------------------------------
// <SensorAlarm::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool SensorAlarm::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( SensorAlarmCmd_Report == (SensorAlarmCmd)_data[0] )
{
// We have received an alarm state report from the Z-Wave device
if( ValueByte* value = static_cast<ValueByte*>( GetValue( _instance, _data[2] ) ) )
{
uint8 sourceNodeId = _data[1];
uint8 state = _data[3];
// uint16 time = (((uint16)_data[4])<<8) | (uint16)_data[5]; Don't know what to do with this yet.
value->OnValueRefreshed( state );
value->Release();
Log::Write( LogLevel_Info, GetNodeId(), "Received alarm state report from node %d: %s = %d", sourceNodeId, value->GetLabel().c_str(), state );
}
return true;
}
if( SensorAlarmCmd_SupportedReport == (SensorAlarmCmd)_data[0] )
{
if( Node* node = GetNodeUnsafe() )
{
// We have received the supported alarm types from the Z-Wave device
Log::Write( LogLevel_Info, GetNodeId(), "Received supported alarm types" );
// Parse the data for the supported alarm types
uint8 numBytes = _data[1];
for( uint32 i=0; i<numBytes; ++i )
{
for( int32 bit=0; bit<8; ++bit )
{
if( ( _data[i+2] & (1<<bit) ) != 0 )
{
// Add supported setpoint
int32 index = (int32)(i<<3) + bit;
if( index < SensorAlarm_Count )
{
node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, index, c_alarmTypeName[index], "", true, false, 0, 0 );
Log::Write( LogLevel_Info, GetNodeId(), " Added alarm type: %s", c_alarmTypeName[index] );
}
}
}
}
}
ClearStaticRequest( StaticRequest_Values );
return true;
}
return false;
}
@@ -0,0 +1,77 @@
//-----------------------------------------------------------------------------
//
// SensorAlarm.h
//
// Implementation of the Z-Wave COMMAND_CLASS_SENSOR_ALARM
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _SensorAlarm_H
#define _SensorAlarm_H
#include <vector>
#include <string>
#include "CommandClass.h"
namespace OpenZWave
{
class ValueByte;
/** \brief Implements COMMAND_CLASS_SENSOR_ALARM (0x9c), a Z-Wave device command class.
*/
class SensorAlarm: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SensorAlarm( _homeId, _nodeId ); }
virtual ~SensorAlarm(){}
static uint8 const StaticGetCommandClassId(){ return 0x9c; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SENSOR_ALARM"; }
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _alarmType, uint8 const _dummy, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
private:
SensorAlarm( uint32 const _homeId, uint8 const _nodeId );
enum
{
SensorAlarm_General = 0,
SensorAlarm_Smoke,
SensorAlarm_CarbonMonoxide,
SensorAlarm_CarbonDioxide,
SensorAlarm_Heat,
SensorAlarm_Flood,
SensorAlarm_Count
};
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,243 @@
//-----------------------------------------------------------------------------
//
// SensorBinary.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_SENSOR_BINARY
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "SensorBinary.h"
#include "WakeUp.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueBool.h"
#include "../tinyxml.h"
using namespace OpenZWave;
enum SensorBinaryCmd
{
SensorBinaryCmd_Get = 0x02,
SensorBinaryCmd_Report = 0x03
};
//-----------------------------------------------------------------------------
// <SensorBinary::ReadXML>
// Read node configuration data
//-----------------------------------------------------------------------------
void SensorBinary::ReadXML
(
TiXmlElement const* _ccElement
)
{
CommandClass::ReadXML( _ccElement );
TiXmlElement const* child = _ccElement->FirstChildElement();
char const* str; int index; int type;
while( child )
{
str = child->Value();
if( str )
{
if( !strcmp( str, "SensorMap" ) )
{
if( TIXML_SUCCESS == child->QueryIntAttribute( "index", &index ) &&
TIXML_SUCCESS == child->QueryIntAttribute( "type", &type ) )
{
m_sensorsMap[(uint8)type] = (uint8)index;
}
}
}
child = child->NextSiblingElement();
}
}
//-----------------------------------------------------------------------------
// <SensorBinary::WriteXML>
// Write node configuration data
//-----------------------------------------------------------------------------
void SensorBinary::WriteXML
(
TiXmlElement* _ccElement
)
{
CommandClass::WriteXML( _ccElement );
char str[8];
for( map<uint8,uint8>::iterator it = m_sensorsMap.begin(); it != m_sensorsMap.end(); it++ )
{
TiXmlElement* sensorMapElement = new TiXmlElement( "SensorMap" );
_ccElement->LinkEndChild( sensorMapElement );
snprintf( str, 8, "%d", it->second );
sensorMapElement->SetAttribute( "index", str );
snprintf( str, 8, "%d", it->first );
sensorMapElement->SetAttribute( "type", str );
}
}
//-----------------------------------------------------------------------------
// <SensorBinary::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool SensorBinary::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _requestFlags & RequestFlag_Dynamic )
{
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <SensorBinary::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool SensorBinary::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if ( IsGetSupported() )
{
Msg* msg = new Msg( "SensorBinaryCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( SensorBinaryCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "SensorBinaryCmd_Get Not Supported on this node");
}
return false;
}
//-----------------------------------------------------------------------------
// <SensorBinary::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool SensorBinary::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if (SensorBinaryCmd_Report == (SensorBinaryCmd)_data[0])
{
if( _length > 2 )
{
uint8 index = m_sensorsMap[_data[2]];
Log::Write( LogLevel_Info, GetNodeId(), "Received SensorBinary report: Sensor:%d State=%s", _data[2], _data[1] ? "On" : "Off" );
if( ValueBool* value = static_cast<ValueBool*>( GetValue( _instance, index ) ) )
{
value->OnValueRefreshed( _data[1] != 0 );
value->Release();
}
return true;
}
else
{
Log::Write( LogLevel_Info, GetNodeId(), "Received SensorBinary report: State=%s", _data[1] ? "On" : "Off" );
if( ValueBool* value = static_cast<ValueBool*>( GetValue( _instance, 0 ) ) )
{
value->OnValueRefreshed( _data[1] != 0 );
value->Release();
}
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
// <SensorBinary::SetValueBasic>
// Update class values based in BASIC mapping
//-----------------------------------------------------------------------------
void SensorBinary::SetValueBasic
(
uint8 const _instance,
uint8 const _value
)
{
// Send a request for new value to synchronize it with the BASIC set/report.
// In case the device is sleeping, we set the value anyway so the BASIC set/report
// stays in sync with it. We must be careful mapping the uint8 BASIC value
// into a class specific value.
// When the device wakes up, the real requested value will be retrieved.
RequestValue( 0, 0, _instance, Driver::MsgQueue_Send );
if( Node* node = GetNodeUnsafe() )
{
if( WakeUp* wakeUp = static_cast<WakeUp*>( node->GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) )
{
if( !wakeUp->IsAwake() )
{
if( ValueBool* value = static_cast<ValueBool*>( GetValue( _instance, 0 ) ) )
{
value->OnValueRefreshed( _value != 0 );
value->Release();
}
}
}
}
}
//-----------------------------------------------------------------------------
// <SensorBinary::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void SensorBinary::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueBool( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Sensor", "", true, false, false, 0 );
}
}
@@ -0,0 +1,69 @@
//-----------------------------------------------------------------------------
//
// SensorBinary.h
//
// Implementation of the Z-Wave COMMAND_CLASS_SENSOR_BINARY
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _SensorBinary_H
#define _SensorBinary_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueBool;
/** \brief Implements COMMAND_CLASS_SENSOR_BINARY (0x30), a Z-Wave device command class.
*/
class SensorBinary: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SensorBinary( _homeId, _nodeId ); }
virtual ~SensorBinary(){}
static uint8 const StaticGetCommandClassId(){ return 0x30; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SENSOR_BINARY"; }
// From CommandClass
virtual void ReadXML( TiXmlElement const* _ccElement );
virtual void WriteXML( TiXmlElement* _ccElement );
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual void SetValueBasic( uint8 const _instance, uint8 const _value );
protected:
virtual void CreateVars( uint8 const _instance );
private:
SensorBinary( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
map<uint8,uint8> m_sensorsMap;
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,460 @@
//-----------------------------------------------------------------------------
//
// SensorMultilevel.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_SENSOR_MULTILEVEL
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "SensorMultilevel.h"
#include "MultiInstance.h"
#include "../Defs.h"
#include "../Bitfield.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueDecimal.h"
using namespace OpenZWave;
enum SensorMultilevelCmd
{
SensorMultilevelCmd_SupportedGet = 0x01,
SensorMultilevelCmd_SupportedReport = 0x02,
SensorMultilevelCmd_Get = 0x04,
SensorMultilevelCmd_Report = 0x05
};
enum SensorType
{
SensorType_Temperature = 1,
SensorType_General,
SensorType_Luminance,
SensorType_Power,
SensorType_RelativeHumidity,
SensorType_Velocity,
SensorType_Direction,
SensorType_AtmosphericPressure,
SensorType_BarometricPressure,
SensorType_SolarRadiation,
SensorType_DewPoint,
SensorType_RainRate,
SensorType_TideLevel,
SensorType_Weight,
SensorType_Voltage,
SensorType_Current,
SensorType_CO2,
SensorType_AirFlow,
SensorType_TankCapacity,
SensorType_Distance,
SensorType_AnglePosition,
SensorType_Rotation,
SensorType_WaterTemperature,
SensorType_SoilTemperature,
SensorType_SeismicIntensity,
SensorType_SeismicMagnitude,
SensorType_Ultraviolet,
SensorType_ElectricalResistivity,
SensorType_ElectricalConductivity,
SensorType_Loudness,
SensorType_Moisture,
SensorType_MaxType
};
static char const* c_sensorTypeNames[] =
{
"Undefined",
"Temperature",
"General",
"Luminance",
"Power",
"Relative Humidity",
"Velocity",
"Direction",
"Atmospheric Pressure",
"Barometric Pressure",
"Solar Radiation",
"Dew Point",
"Rain Rate",
"Tide Level",
"Weight",
"Voltage",
"Current",
"CO2 Level",
"Air Flow",
"Tank Capacity",
"Distance",
"Angle Position",
"Rotation",
"Water Temperature",
"Soil Temperature",
"Seismic Intensity",
"Seismic Magnitude",
"Utraviolet",
"Electrical Resistivity",
"Electrical Conductivity",
"Loudness",
"Moisture"
};
static char const* c_tankCapcityUnits[] =
{
"l",
"cbm",
"gal",
""
};
static char const* c_distanceUnits[] =
{
"m",
"cm",
"ft",
""
};
static char const* c_anglePositionUnits[] =
{
"%",
"deg N",
"deg S",
""
};
static char const* c_seismicIntensityUnits[] =
{
"mercalli",
"EU macroseismic",
"liedu",
"shindo",
""
};
static char const* c_seismicMagnitudeUnits[] =
{
"local",
"moment",
"surface wave",
"body wave",
""
};
static char const* c_moistureUnits[] =
{
"%",
"content",
"k ohms",
"water activity",
""
};
//-----------------------------------------------------------------------------
// <SensorMultilevel::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool SensorMultilevel::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
bool res = false;
if( GetVersion() > 4 )
{
if( _requestFlags & RequestFlag_Static )
{
Msg* msg = new Msg( "SensorMultilevelCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( SensorMultilevelCmd_SupportedGet );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
res = true;
}
}
if( _requestFlags & RequestFlag_Dynamic )
{
res |= RequestValue( _requestFlags, 0, _instance, _queue );
}
return res;
}
//-----------------------------------------------------------------------------
// <SensorMultilevel::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool SensorMultilevel::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
bool res = false;
if ( !IsGetSupported() ) {
Log::Write( LogLevel_Info, GetNodeId(), "SensorMultilevelCmd_Get Not Supported on this node");
return false;
}
if( GetVersion() < 5 )
{
Msg* msg = new Msg( "SensorMultilevelCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( SensorMultilevelCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
res = true;
}
else
{
for( uint8 i = 1; i < SensorType_MaxType; i++ )
{
Value* value = GetValue( _instance, i );
if( value != NULL )
{
value->Release();
Msg* msg = new Msg( "SensorMultilevelCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( SensorMultilevelCmd_Get );
msg->Append( i );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
res = true;
}
}
}
return res;
}
//-----------------------------------------------------------------------------
// <SensorMultilevel::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool SensorMultilevel::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if (SensorMultilevelCmd_SupportedReport == (SensorMultilevelCmd)_data[0])
{
string msg = "";
if( Node* node = GetNodeUnsafe() )
{
for( uint8 i = 1; i <= ( _length - 2 ); i++ )
{
for( uint8 j = 0; j < 8; j++ )
{
if( _data[i] & ( 1 << j ) )
{
if( msg != "" )
msg += ", ";
uint8 index = ( ( i - 1 ) * 8 ) + j + 1;
if (index >= SensorType_MaxType) /* max size for c_sensorTypeNames */
{
Log::Write (LogLevel_Warning, GetNodeId(), "SensorType Value was greater than range. Dropping");
continue;
}
msg += c_sensorTypeNames[index];
ValueDecimal* value = static_cast<ValueDecimal*>( GetValue( _instance, index ) );
if( value == NULL)
{
node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, index, c_sensorTypeNames[index], "", true, false, "0.0", 0 );
}
}
}
}
}
Log::Write( LogLevel_Info, GetNodeId(), "Received SensorMultiLevel supported report from node %d: %s", GetNodeId(), msg.c_str() );
}
else if (SensorMultilevelCmd_Report == (SensorMultilevelCmd)_data[0])
{
uint8 scale;
uint8 precision = 0;
uint8 sensorType = _data[1];
string valueStr = ExtractValue( &_data[2], &scale, &precision );
Node* node = GetNodeUnsafe();
if( node != NULL )
{
char const* units = "";
switch( sensorType )
{
case SensorType_Temperature: units = scale ? "F" : "C"; break;
case SensorType_General: units = scale ? "" : "%"; break;
case SensorType_Luminance: units = scale ? "lux" : "%"; break;
case SensorType_Power: units = scale ? "BTU/h" : "W"; break;
case SensorType_RelativeHumidity: units = scale ? "" : "%"; break;
case SensorType_Velocity: units = scale ? "mph" : "m/s"; break;
case SensorType_Direction: units = ""; break;
case SensorType_AtmosphericPressure: units = scale ? "inHg" : "kPa"; break;
case SensorType_BarometricPressure: units = scale ? "inHg" : "kPa"; break;
case SensorType_SolarRadiation: units = "W/m2"; break;
case SensorType_DewPoint: units = scale ? "F" : "C"; break;
case SensorType_RainRate: units = scale ? "in/h" : "mm/h"; break;
case SensorType_TideLevel: units = scale ? "ft" : "m"; break;
case SensorType_Weight: units = scale ? "lb" : "kg"; break;
case SensorType_Voltage: units = scale ? "mV" : "V"; break;
case SensorType_Current: units = scale ? "mA" : "A"; break;
case SensorType_CO2: units = "ppm"; break;
case SensorType_AirFlow: units = scale ? "cfm" : "m3/h"; break;
case SensorType_TankCapacity: {
if (scale > 2) /* size of c_tankCapcityUnits minus invalid */
{
Log::Write (LogLevel_Warning, GetNodeId(), "Scale Value for c_tankCapcityUnits was greater than range. Setting to empty");
units = c_tankCapcityUnits[3]; /* empty entry */
}
else
{
units = c_tankCapcityUnits[scale];
}
}
break;
case SensorType_Distance: {
if (scale > 2) /* size of c_distanceUnits minus invalid */
{
Log::Write (LogLevel_Warning, GetNodeId(), "Scale Value for c_distanceUnits was greater than range. Setting to empty");
units = c_distanceUnits[3]; /* empty entry */
}
else
{
units = c_distanceUnits[scale];
}
}
break;
case SensorType_AnglePosition: {
if (scale > 2) /* size of c_anglePositionUnits minus invalid */
{
Log::Write (LogLevel_Warning, GetNodeId(), "Scale Value for c_anglePositionUnits was greater than range. Setting to empty");
units = c_anglePositionUnits[3]; /* empty entry */
}
else
{
units = c_anglePositionUnits[scale];
}
}
break;
case SensorType_Rotation: units = scale ? "hz" : "rpm"; break;
case SensorType_WaterTemperature: units = scale ? "F" : "C"; break;
case SensorType_SoilTemperature: units = scale ? "F" : "C"; break;
case SensorType_SeismicIntensity: {
if (scale > 3) /* size of c_seismicIntensityUnits minus invalid */
{
Log::Write (LogLevel_Warning, GetNodeId(), "Scale Value for c_seismicIntensityUnits was greater than range. Setting to empty");
units = c_seismicIntensityUnits[4]; /* empty entry */
}
else
{
units = c_seismicIntensityUnits[scale];
}
}
break;
case SensorType_SeismicMagnitude: {
if (scale > 3) /* size of c_seismicMagnitudeUnits minus invalid */
{
Log::Write (LogLevel_Warning, GetNodeId(), "Scale Value for c_seismicMagnitudeUnits was greater than range. Setting to empty");
units = c_seismicMagnitudeUnits[4]; /* empty entry */
}
else
{
units = c_seismicMagnitudeUnits[scale];
}
}
break;
case SensorType_Ultraviolet: units = ""; break;
case SensorType_ElectricalResistivity: units = "ohm"; break;
case SensorType_ElectricalConductivity: units = "siemens/m"; break;
case SensorType_Loudness: units = scale ? "dBA" : "db"; break;
case SensorType_Moisture: {
if (scale > 3) /* size of c_moistureUnits minus invalid */
{
Log::Write (LogLevel_Warning, GetNodeId(), "Scale Value for c_moistureUnits was greater than range. Setting to empty");
units = c_moistureUnits[4]; /* empty entry */
}
else
{
units = c_moistureUnits[scale];
}
}
break;
default: {
Log::Write (LogLevel_Warning, GetNodeId(), "sensorType Value was greater than range. Dropping");
return false;
}
break;
}
ValueDecimal* value = static_cast<ValueDecimal*>( GetValue( _instance, sensorType ) );
if( value == NULL)
{
node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, sensorType, c_sensorTypeNames[sensorType], units, true, false, "0.0", 0 );
value = static_cast<ValueDecimal*>( GetValue( _instance, sensorType ) );
}
else
{
value->SetUnits(units);
}
Log::Write( LogLevel_Info, GetNodeId(), "Received SensorMultiLevel report from node %d, instance %d, %s: value=%s%s", GetNodeId(), _instance, c_sensorTypeNames[sensorType], valueStr.c_str(), value->GetUnits().c_str() );
if( value->GetPrecision() != precision )
{
value->SetPrecision( precision );
}
value->OnValueRefreshed( valueStr );
value->Release();
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
// <SensorMultilevel::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void SensorMultilevel::CreateVars
(
uint8 const _instance
)
{
// Don't create anything here. We do it in the report.
}
@@ -0,0 +1,68 @@
//-----------------------------------------------------------------------------
//
// SensorMultilevel.h
//
// Implementation of the Z-Wave COMMAND_CLASS_SENSOR_MULTILEVEL
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _SensorMultilevel_H
#define _SensorMultilevel_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueDecimal;
/** \brief Implements COMMAND_CLASS_SENSOR_MULTILEVEL (0x31), a Z-Wave device command class.
*/
class SensorMultilevel: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SensorMultilevel( _homeId, _nodeId ); }
virtual ~SensorMultilevel(){}
static uint8 const StaticGetCommandClassId(){ return 0x31; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SENSOR_MULTILEVEL"; }
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _dummy, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual uint8 GetMaxVersion(){ return 5; }
protected:
virtual void CreateVars( uint8 const _instance );
private:
SensorMultilevel( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,225 @@
//-----------------------------------------------------------------------------
//
// SwitchAll.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_SWITCH_ALL
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "SwitchAll.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueList.h"
using namespace OpenZWave;
enum SwitchAllCmd
{
SwitchAllCmd_Set = 0x01,
SwitchAllCmd_Get = 0x02,
SwitchAllCmd_Report = 0x03,
SwitchAllCmd_On = 0x04,
SwitchAllCmd_Off = 0x05
};
static char const* c_switchAllStateName[] =
{
"Disabled",
"Off Enabled",
"On Enabled",
"On and Off Enabled"
};
//-----------------------------------------------------------------------------
// <SwitchAll::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool SwitchAll::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _requestFlags & RequestFlag_Session )
{
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <SwitchAll::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool SwitchAll::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if ( IsGetSupported() )
{
Msg* msg = new Msg( "SwitchAllCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( SwitchAllCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "SwitchAllCmd_Get Not Supported on this node");
}
return false;
}
//-----------------------------------------------------------------------------
// <SwitchAll::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool SwitchAll::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if (SwitchAllCmd_Report == (SwitchAllCmd)_data[0])
{
if( ValueList* value = static_cast<ValueList*>( GetValue( _instance, 0 ) ) )
{
value->OnValueRefreshed( (int32)_data[1] );
value->Release();
Log::Write( LogLevel_Info, GetNodeId(), "Received SwitchAll report from node %d: %s", GetNodeId(), value->GetItem().m_label.c_str() );
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <SwitchAll::SetValue>
// Set the device's response to SWITCH_ALL commands
//-----------------------------------------------------------------------------
bool SwitchAll::SetValue
(
Value const& _value
)
{
if( ValueID::ValueType_List == _value.GetID().GetType() )
{
ValueList const* value = static_cast<ValueList const*>(&_value);
ValueList::Item const& item = value->GetItem();
Log::Write( LogLevel_Info, GetNodeId(), "SwitchAll::Set - %s on node %d", item.m_label.c_str(), GetNodeId() );
Msg* msg = new Msg( "SwitchAllCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->SetInstance( this, _value.GetID().GetInstance() );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( SwitchAllCmd_Set );
msg->Append( (uint8)item.m_value );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <SwitchAll::Off>
// Send a command to switch all devices off
//-----------------------------------------------------------------------------
void SwitchAll::Off
(
Driver* _driver,
uint8 const _nodeId
)
{
Log::Write( LogLevel_Info, _nodeId, "SwitchAll::Off (Node=%d)", _nodeId );
Msg* msg = new Msg( "SwitchAllCmd_Off", _nodeId, REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->Append( _nodeId );
msg->Append( 2 );
msg->Append( StaticGetCommandClassId() );
msg->Append( SwitchAllCmd_Off );
msg->Append( _driver->GetTransmitOptions() );
_driver->SendMsg( msg, Driver::MsgQueue_Send );
}
//-----------------------------------------------------------------------------
// <SwitchAll::On>
// Send a command to switch all devices on
//-----------------------------------------------------------------------------
void SwitchAll::On
(
Driver* _driver,
uint8 const _nodeId
)
{
Log::Write( LogLevel_Info, _nodeId, "SwitchAll::On (Node=%d)", _nodeId );
Msg* msg = new Msg( "SwitchAllCmd_On", _nodeId, REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->Append( _nodeId );
msg->Append( 2 );
msg->Append( StaticGetCommandClassId() );
msg->Append( SwitchAllCmd_On );
msg->Append( _driver->GetTransmitOptions() );
_driver->SendMsg( msg, Driver::MsgQueue_Send );
}
//-----------------------------------------------------------------------------
// <SwitchAll::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void SwitchAll::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
vector<ValueList::Item> items;
for( int i=0; i<4; ++i )
{
ValueList::Item item;
item.m_label = c_switchAllStateName[i];
item.m_value = (i==3) ? 0x000000ff : i;
items.push_back( item );
}
node->CreateValueList( ValueID::ValueGenre_System, GetCommandClassId(), _instance, 0, "Switch All", "", false, false, 1, items, 0, 0 );
}
}
@@ -0,0 +1,69 @@
//-----------------------------------------------------------------------------
//
// SwitchAll.h
//
// Implementation of the Z-Wave COMMAND_CLASS_SWITCH_ALL
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _SwitchAll_H
#define _SwitchAll_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueList;
/** \brief Implements COMMAND_CLASS_SWITCH_ALL (0x27), a Z-Wave device command class.
*/
class SwitchAll: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SwitchAll( _homeId, _nodeId ); }
virtual ~SwitchAll(){}
static uint8 const StaticGetCommandClassId(){ return 0x27; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SWITCH_ALL"; }
static void On( Driver* _driver, uint8 const _nodeId );
static void Off( Driver* _driver, uint8 const _nodeId );
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
protected:
virtual void CreateVars( uint8 const _instance );
private:
SwitchAll( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,196 @@
//-----------------------------------------------------------------------------
//
// SwitchBinary.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_SWITCH_BINARY
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "SwitchBinary.h"
#include "WakeUp.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Driver.h"
#include "../Node.h"
#include "../platform/Log.h"
#include "../value_classes/ValueBool.h"
using namespace OpenZWave;
enum SwitchBinaryCmd
{
SwitchBinaryCmd_Set = 0x01,
SwitchBinaryCmd_Get = 0x02,
SwitchBinaryCmd_Report = 0x03
};
//-----------------------------------------------------------------------------
// <SwitchBinary::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool SwitchBinary::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _requestFlags & RequestFlag_Dynamic )
{
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <SwitchBinary::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool SwitchBinary::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if ( IsGetSupported() )
{
Msg* msg = new Msg( "SwitchBinaryCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( SwitchBinaryCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "SwitchBinaryCmd_Get Not Supported on this node");
}
return false;
}
//-----------------------------------------------------------------------------
// <SwitchBinary::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool SwitchBinary::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if (SwitchBinaryCmd_Report == (SwitchBinaryCmd)_data[0])
{
Log::Write( LogLevel_Info, GetNodeId(), "Received SwitchBinary report from node %d: level=%s", GetNodeId(), _data[1] ? "On" : "Off" );
if( ValueBool* value = static_cast<ValueBool*>( GetValue( _instance, 0 ) ) )
{
value->OnValueRefreshed( _data[1] != 0 );
value->Release();
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <SwitchBinary::SetValue>
// Set the state of the switch
//-----------------------------------------------------------------------------
bool SwitchBinary::SetValue
(
Value const& _value
)
{
if( ValueID::ValueType_Bool == _value.GetID().GetType() )
{
ValueBool const* value = static_cast<ValueBool const*>(&_value);
Log::Write( LogLevel_Info, GetNodeId(), "SwitchBinary::Set - Setting node %d to %s", GetNodeId(), value->GetValue() ? "On" : "Off" );
Msg* msg = new Msg( "SwitchBinary Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->SetInstance( this, _value.GetID().GetInstance() );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( SwitchBinaryCmd_Set );
msg->Append( value->GetValue() ? 0xff : 0x00 );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <SwitchBinary::SetValueBasic>
// Update class values based in BASIC mapping
//-----------------------------------------------------------------------------
void SwitchBinary::SetValueBasic
(
uint8 const _instance,
uint8 const _value
)
{
// Send a request for new value to synchronize it with the BASIC set/report.
// In case the device is sleeping, we set the value anyway so the BASIC set/report
// stays in sync with it. We must be careful mapping the uint8 BASIC value
// into a class specific value.
// When the device wakes up, the real requested value will be retrieved.
RequestValue( 0, 0, _instance, Driver::MsgQueue_Send );
if( Node* node = GetNodeUnsafe() )
{
if( WakeUp* wakeUp = static_cast<WakeUp*>( node->GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) )
{
if( !wakeUp->IsAwake() )
{
if( ValueBool* value = static_cast<ValueBool*>( GetValue( _instance, 0 ) ) )
{
value->OnValueRefreshed( _value != 0 );
value->Release();
}
}
}
}
}
//-----------------------------------------------------------------------------
// <SwitchBinary::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void SwitchBinary::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueBool( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Switch", "", false, false, false, 0 );
}
}
@@ -0,0 +1,67 @@
//-----------------------------------------------------------------------------
//
// SwitchBinary.h
//
// Implementation of the Z-Wave COMMAND_CLASS_SWITCH_BINARY
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _SwitchBinary_H
#define _SwitchBinary_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueBool;
/** \brief Implements COMMAND_CLASS_SWITCH_BINARY (0x25), a Z-Wave device command class.
*/
class SwitchBinary: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SwitchBinary( _homeId, _nodeId ); }
virtual ~SwitchBinary(){}
static uint8 const StaticGetCommandClassId(){ return 0x25; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SWITCH_BINARY"; }
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
virtual void SetValueBasic( uint8 const _instance, uint8 const _value );
protected:
virtual void CreateVars( uint8 const _instance );
private:
SwitchBinary( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,631 @@
//-----------------------------------------------------------------------------
//
// SwitchMultilevel.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_SWITCH_MULTILEVEL
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "SwitchMultilevel.h"
#include "WakeUp.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Driver.h"
#include "../Node.h"
#include "../platform/Log.h"
#include "../value_classes/ValueBool.h"
#include "../value_classes/ValueButton.h"
#include "../value_classes/ValueByte.h"
using namespace OpenZWave;
enum SwitchMultilevelCmd
{
SwitchMultilevelCmd_Set = 0x01,
SwitchMultilevelCmd_Get = 0x02,
SwitchMultilevelCmd_Report = 0x03,
SwitchMultilevelCmd_StartLevelChange = 0x04,
SwitchMultilevelCmd_StopLevelChange = 0x05,
SwitchMultilevelCmd_SupportedGet = 0x06,
SwitchMultilevelCmd_SupportedReport = 0x07
};
enum
{
SwitchMultilevelIndex_Level = 0,
SwitchMultilevelIndex_Bright,
SwitchMultilevelIndex_Dim,
SwitchMultilevelIndex_IgnoreStartLevel,
SwitchMultilevelIndex_StartLevel,
SwitchMultilevelIndex_Duration,
SwitchMultilevelIndex_Step,
SwitchMultilevelIndex_Inc,
SwitchMultilevelIndex_Dec
};
static uint8 c_directionParams[] =
{
0x18,
0x58,
0xc0,
0xc8
};
static char const* c_directionDebugLabels[] =
{
"Up",
"Down",
"Inc",
"Dec"
};
static char const* c_switchLabelsPos[] =
{
"Undefined",
"On",
"Up",
"Open",
"Clockwise",
"Right",
"Forward",
"Push"
};
static char const* c_switchLabelsNeg[] =
{
"Undefined",
"Off",
"Down",
"Close",
"Counter-Clockwise",
"Left",
"Reverse",
"Pull"
};
//-----------------------------------------------------------------------------
// <SwitchMultilevel::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool SwitchMultilevel::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _requestFlags & RequestFlag_Dynamic )
{
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <SwitchMultilevel::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool SwitchMultilevel::RequestValue
(
uint32 const _requestFlags,
uint8 const _index,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _index == SwitchMultilevelIndex_Level )
{
if ( IsGetSupported() )
{
Msg* msg = new Msg( "SwitchMultilevelCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( SwitchMultilevelCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "SwitchMultilevelCmd_Get Not Supported on this node");
}
}
return false;
}
//-----------------------------------------------------------------------------
// <SwitchMultilevel::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool SwitchMultilevel::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( SwitchMultilevelCmd_Report == (SwitchMultilevelCmd)_data[0] )
{
Log::Write( LogLevel_Info, GetNodeId(), "Received SwitchMultiLevel report: level=%d", _data[1] );
if( ValueByte* value = static_cast<ValueByte*>( GetValue( _instance, SwitchMultilevelIndex_Level ) ) )
{
value->OnValueRefreshed( _data[1] );
value->Release();
}
return true;
}
if( SwitchMultilevelCmd_SupportedReport == (SwitchMultilevelCmd)_data[0] )
{
uint8 switchType1 = _data[1] & 0x1f;
uint8 switchType2 = _data[2] & 0x1f;
uint8 switchtype1label = switchType1;
uint8 switchtype2label = switchType2;
if (switchtype1label > 7) /* size of c_switchLabelsPos, c_switchLabelsNeg */
{
Log::Write (LogLevel_Warning, GetNodeId(), "switchtype1label Value was greater than range. Setting to Invalid");
switchtype1label = 0;
}
if (switchtype2label > 7) /* sizeof c_switchLabelsPos, c_switchLabelsNeg */
{
Log::Write (LogLevel_Warning, GetNodeId(), "switchtype2label Value was greater than range. Setting to Invalid");
switchtype2label = 0;
}
Log::Write( LogLevel_Info, GetNodeId(), "Received SwitchMultiLevel supported report: Switch1=%s/%s, Switch2=%s/%s", c_switchLabelsPos[switchtype1label], c_switchLabelsNeg[switchtype1label], c_switchLabelsPos[switchtype2label], c_switchLabelsNeg[switchtype2label] );
ClearStaticRequest( StaticRequest_Version );
// Set the labels on the values
ValueButton* button;
if( switchType1 )
{
if( NULL != ( button = static_cast<ValueButton*>( GetValue( _instance, SwitchMultilevelIndex_Bright ) ) ) )
{
button->SetLabel( c_switchLabelsPos[switchtype1label] );
button->Release();
}
if( NULL != ( button = static_cast<ValueButton*>( GetValue( _instance, SwitchMultilevelIndex_Dim ) ) ) )
{
button->SetLabel( c_switchLabelsNeg[switchtype1label] );
button->Release();
}
}
if( switchType2 )
{
if( NULL != ( button = static_cast<ValueButton*>( GetValue( _instance, SwitchMultilevelIndex_Inc ) ) ) )
{
button->SetLabel( c_switchLabelsPos[switchtype2label] );
button->Release();
}
if( NULL != ( button = static_cast<ValueButton*>( GetValue( _instance, SwitchMultilevelIndex_Dec ) ) ) )
{
button->SetLabel( c_switchLabelsNeg[switchtype2label] );
button->Release();
}
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <SwitchMultilevel::SetVersion>
// Set the command class version
//-----------------------------------------------------------------------------
void SwitchMultilevel::SetVersion
(
uint8 const _version
)
{
CommandClass::SetVersion( _version );
if( _version == 3 )
{
// Request the supported switch types
Msg* msg = new Msg( "SwitchMultilevelCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( SwitchMultilevelCmd_SupportedGet );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
// Set the request flag again - it will be cleared when we get a
// response to the SwitchMultilevelCmd_SupportedGet message.
SetStaticRequest( StaticRequest_Version );
}
}
//-----------------------------------------------------------------------------
// <SwitchMultilevel::SetValue>
// Set the level on a device
//-----------------------------------------------------------------------------
bool SwitchMultilevel::SetValue
(
Value const& _value
)
{
bool res = false;
uint8 instance = _value.GetID().GetInstance();
switch( _value.GetID().GetIndex() )
{
case SwitchMultilevelIndex_Level:
{
// Level
if( ValueByte* value = static_cast<ValueByte*>( GetValue( instance, SwitchMultilevelIndex_Level ) ) )
{
res = SetLevel( instance, (static_cast<ValueByte const*>(&_value))->GetValue() );
value->Release();
}
break;
}
case SwitchMultilevelIndex_Bright:
{
// Bright
if( ValueButton* button = static_cast<ValueButton*>( GetValue( instance, SwitchMultilevelIndex_Bright ) ) )
{
if( button->IsPressed() )
{
res = StartLevelChange( instance, SwitchMultilevelDirection_Up );
}
else
{
res = StopLevelChange( instance );
}
button->Release();
}
break;
}
case SwitchMultilevelIndex_Dim:
{
// Dim
if( ValueButton* button = static_cast<ValueButton*>( GetValue( instance, SwitchMultilevelIndex_Dim ) ) )
{
if( button->IsPressed() )
{
res = StartLevelChange( instance, SwitchMultilevelDirection_Down );
}
else
{
res = StopLevelChange( instance );
}
button->Release();
}
break;
}
case SwitchMultilevelIndex_IgnoreStartLevel:
{
if( ValueBool* value = static_cast<ValueBool*>( GetValue( instance, SwitchMultilevelIndex_IgnoreStartLevel ) ) )
{
value->OnValueRefreshed( (static_cast<ValueBool const*>( &_value))->GetValue() );
value->Release();
}
res = true;
break;
}
case SwitchMultilevelIndex_StartLevel:
{
if( ValueByte* value = static_cast<ValueByte*>( GetValue( instance, SwitchMultilevelIndex_StartLevel ) ) )
{
value->OnValueRefreshed( (static_cast<ValueByte const*>( &_value))->GetValue() );
value->Release();
}
res = true;
break;
}
case SwitchMultilevelIndex_Duration:
{
if( ValueByte* value = static_cast<ValueByte*>( GetValue( instance, SwitchMultilevelIndex_Duration ) ) )
{
value->OnValueRefreshed( (static_cast<ValueByte const*>( &_value))->GetValue() );
value->Release();
}
res = true;
break;
}
case SwitchMultilevelIndex_Step:
{
if( ValueByte* value = static_cast<ValueByte*>( GetValue( instance, SwitchMultilevelIndex_Step ) ) )
{
value->OnValueRefreshed( (static_cast<ValueByte const*>( &_value))->GetValue() );
value->Release();
}
res = true;
break;
}
case SwitchMultilevelIndex_Inc:
{
// Inc
if( ValueButton* button = static_cast<ValueButton*>( GetValue( instance, SwitchMultilevelIndex_Inc ) ) )
{
if( button->IsPressed() )
{
res = StartLevelChange( instance, SwitchMultilevelDirection_Inc );
}
else
{
res = StopLevelChange( instance );
}
button->Release();
}
break;
}
case SwitchMultilevelIndex_Dec:
{
// Dec
if( ValueButton* button = static_cast<ValueButton*>( GetValue( instance, SwitchMultilevelIndex_Dec ) ) )
{
if( button->IsPressed() )
{
res = StartLevelChange( instance, SwitchMultilevelDirection_Dec );
}
else
{
res = StopLevelChange( instance );
}
button->Release();
}
break;
}
}
return res;
}
//-----------------------------------------------------------------------------
// <SwitchMultilevel::SetValueBasic>
// Update class values based in BASIC mapping
//-----------------------------------------------------------------------------
void SwitchMultilevel::SetValueBasic
(
uint8 const _instance,
uint8 const _value
)
{
// Send a request for new value to synchronize it with the BASIC set/report.
// In case the device is sleeping, we set the value anyway so the BASIC set/report
// stays in sync with it. We must be careful mapping the uint8 BASIC value
// into a class specific value.
// When the device wakes up, the real requested value will be retrieved.
RequestValue( 0, 0, _instance, Driver::MsgQueue_Send );
if( Node* node = GetNodeUnsafe() )
{
if( WakeUp* wakeUp = static_cast<WakeUp*>( node->GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) )
{
if( !wakeUp->IsAwake() )
{
if( ValueByte* value = static_cast<ValueByte*>( GetValue( _instance, SwitchMultilevelIndex_Level ) ) )
{
value->OnValueRefreshed( _value != 0 );
value->Release();
}
}
}
}
}
//-----------------------------------------------------------------------------
// <SwitchMultilevel::SetLevel>
// Set a new level for the switch
//-----------------------------------------------------------------------------
bool SwitchMultilevel::SetLevel
(
uint8 const _instance,
uint8 const _level
)
{
Log::Write( LogLevel_Info, GetNodeId(), "SwitchMultilevel::Set - Setting to level %d", _level );
Msg* msg = new Msg( "SwitchMultiLevel Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
if( ValueByte* durationValue = static_cast<ValueByte*>( GetValue( _instance, SwitchMultilevelIndex_Duration ) ) )
{
uint8 duration = durationValue->GetValue();
durationValue->Release();
if( duration == 0xff )
{
Log::Write( LogLevel_Info, GetNodeId(), " Duration: Default" );
}
else if( duration >= 0x80 )
{
Log::Write( LogLevel_Info, GetNodeId(), " Duration: %d minutes", duration - 0x7f );
}
else
{
Log::Write( LogLevel_Info, GetNodeId(), " Duration: %d seconds", duration );
}
msg->Append( 4 );
msg->Append( GetCommandClassId() );
msg->Append( SwitchMultilevelCmd_Set );
msg->Append( _level );
msg->Append( duration );
}
else
{
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( SwitchMultilevelCmd_Set );
msg->Append( _level );
}
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
//-----------------------------------------------------------------------------
// <SwitchMultilevel::SwitchMultilevelCmd_StartLevelChange>
// Start the level changing
//-----------------------------------------------------------------------------
bool SwitchMultilevel::StartLevelChange
(
uint8 const _instance,
SwitchMultilevelDirection const _direction
)
{
Log::Write( LogLevel_Info, GetNodeId(), "SwitchMultilevel::StartLevelChange - Starting a level change" );
uint8 length = 4;
if (_direction > 3) /* size of c_directionParams, c_directionDebugLabels */
{
Log::Write (LogLevel_Warning, GetNodeId(), "_direction Value was greater than range. Dropping");
return false;
}
uint8 direction = c_directionParams[_direction];
Log::Write( LogLevel_Info, GetNodeId(), " Direction: %s", c_directionDebugLabels[_direction] );
if( ValueBool* ignoreStartLevel = static_cast<ValueBool*>( GetValue( _instance, SwitchMultilevelIndex_IgnoreStartLevel ) ) )
{
if( ignoreStartLevel->GetValue() )
{
ignoreStartLevel->Release();
// Set the ignore start level flag
direction |= 0x20;
}
}
Log::Write( LogLevel_Info, GetNodeId(), " Ignore Start Level: %s", (direction & 0x20) ? "True" : "False" );
uint8 startLevel = 0;
if( ValueByte* startLevelValue = static_cast<ValueByte*>( GetValue( _instance, SwitchMultilevelIndex_StartLevel ) ) )
{
startLevel = startLevelValue->GetValue();
startLevelValue->Release();
}
Log::Write( LogLevel_Info, GetNodeId(), " Start Level: %d", startLevel );
uint8 duration = 0;
if( ValueByte* durationValue = static_cast<ValueByte*>( GetValue( _instance, SwitchMultilevelIndex_Duration ) ) )
{
length = 5;
duration = durationValue->GetValue();
durationValue->Release();
Log::Write( LogLevel_Info, GetNodeId(), " Duration: %d", duration );
}
uint8 step = 0;
if( ( SwitchMultilevelDirection_Inc == _direction ) || ( SwitchMultilevelDirection_Dec == _direction ) )
{
if( ValueByte* stepValue = static_cast<ValueByte*>( GetValue( _instance, SwitchMultilevelIndex_Step ) ) )
{
length = 6;
step = stepValue->GetValue();
stepValue->Release();
Log::Write( LogLevel_Info, GetNodeId(), " Step Size: %d", step );
}
}
Msg* msg = new Msg( "SwitchMultilevel StartLevelChange", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( length );
msg->Append( GetCommandClassId() );
msg->Append( SwitchMultilevelCmd_StartLevelChange );
msg->Append( direction );
msg->Append( startLevel );
if( length >= 5 )
{
msg->Append( duration );
}
if( length == 6 )
{
msg->Append( step );
}
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
//-----------------------------------------------------------------------------
// <SwitchMultilevel::StopLevelChange>
// Stop the level changing
//-----------------------------------------------------------------------------
bool SwitchMultilevel::StopLevelChange
(
uint8 const _instance
)
{
Log::Write( LogLevel_Info, GetNodeId(), "SwitchMultilevel::StopLevelChange - Stopping the level change" );
Msg* msg = new Msg( "SwitchMultilevel StopLevelChange", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( SwitchMultilevelCmd_StopLevelChange );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
//-----------------------------------------------------------------------------
// <SwitchMultilevel::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void SwitchMultilevel::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
switch( GetVersion() )
{
case 3:
{
node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, SwitchMultilevelIndex_Step, "Step Size", "", false, false, 0, 0 );
node->CreateValueButton( ValueID::ValueGenre_User, GetCommandClassId(), _instance, SwitchMultilevelIndex_Inc, "Inc", 0 );
node->CreateValueButton( ValueID::ValueGenre_User, GetCommandClassId(), _instance, SwitchMultilevelIndex_Dec, "Dec", 0 );
// Fall through to version 2
}
case 2:
{
node->CreateValueByte( ValueID::ValueGenre_System, GetCommandClassId(), _instance, SwitchMultilevelIndex_Duration, "Dimming Duration", "", false, false, 0xff, 0 );
// Fall through to version 1
}
case 1:
{
node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, SwitchMultilevelIndex_Level, "Level", "", false, false, 0, 0 );
node->CreateValueButton( ValueID::ValueGenre_User, GetCommandClassId(), _instance, SwitchMultilevelIndex_Bright, "Bright", 0 );
node->CreateValueButton( ValueID::ValueGenre_User, GetCommandClassId(), _instance, SwitchMultilevelIndex_Dim, "Dim", 0 );
node->CreateValueBool( ValueID::ValueGenre_System, GetCommandClassId(), _instance, SwitchMultilevelIndex_IgnoreStartLevel, "Ignore Start Level", "", false, false, true, 0 );
node->CreateValueByte( ValueID::ValueGenre_System, GetCommandClassId(), _instance, SwitchMultilevelIndex_StartLevel, "Start Level", "", false, false, 0, 0 );
break;
}
}
}
}
@@ -0,0 +1,84 @@
//-----------------------------------------------------------------------------
//
// SwitchMultilevel.h
//
// Implementation of the Z-Wave COMMAND_CLASS_SWITCH_MULTILEVEL
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _SwitchMultilevel_H
#define _SwitchMultilevel_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueBool;
class ValueButton;
class ValueByte;
/** \brief Implements COMMAND_CLASS_SWITCH_MULTILEVEL (0x26), a Z-Wave device command class.
*/
class SwitchMultilevel: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SwitchMultilevel( _homeId, _nodeId ); }
virtual ~SwitchMultilevel(){}
static uint8 const StaticGetCommandClassId(){ return 0x26; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SWITCH_MULTILEVEL"; }
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
virtual void SetValueBasic( uint8 const _instance, uint8 const _value );
virtual void SetVersion( uint8 const _version );
virtual uint8 GetMaxVersion(){ return 3; }
protected:
virtual void CreateVars( uint8 const _instance );
private:
enum SwitchMultilevelDirection
{
SwitchMultilevelDirection_Up = 0,
SwitchMultilevelDirection_Down,
SwitchMultilevelDirection_Inc,
SwitchMultilevelDirection_Dec
};
SwitchMultilevel( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
bool SetLevel( uint8 const _instance, uint8 const _level );
bool StartLevelChange( uint8 const _instance, SwitchMultilevelDirection const _direction );
bool StopLevelChange( uint8 const _instance );
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,157 @@
//-----------------------------------------------------------------------------
//
// SwitchToggleBinary.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_SWITCH_TOGGLE_BINARY
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "SwitchToggleBinary.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Driver.h"
#include "../Node.h"
#include "../platform/Log.h"
#include "../value_classes/ValueBool.h"
using namespace OpenZWave;
enum SwitchToggleBinaryCmd
{
SwitchToggleBinaryCmd_Set = 0x01,
SwitchToggleBinaryCmd_Get = 0x02,
SwitchToggleBinaryCmd_Report = 0x03
};
//-----------------------------------------------------------------------------
// <SwitchToggleBinary::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool SwitchToggleBinary::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _requestFlags & RequestFlag_Dynamic )
{
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <SwitchToggleBinary::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool SwitchToggleBinary::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if ( IsGetSupported() )
{
Msg* msg = new Msg( "SwitchToggleBinaryCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( SwitchToggleBinaryCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "SwitchToggleBinaryCmd_Get Not Supported on this node");
}
return false;
}
//-----------------------------------------------------------------------------
// <SwitchToggleBinary::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool SwitchToggleBinary::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( SwitchToggleBinaryCmd_Report == (SwitchToggleBinaryCmd)_data[0] )
{
Log::Write( LogLevel_Info, GetNodeId(), "Received SwitchToggleBinary report: %s", _data[1] ? "On" : "Off" );
if( ValueBool* value = static_cast<ValueBool*>( GetValue( _instance, 0 ) ) )
{
value->OnValueRefreshed( _data[1] != 0 );
value->Release();
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <SwitchToggleBinary::SetValue>
// Toggle the state of the switch
//-----------------------------------------------------------------------------
bool SwitchToggleBinary::SetValue
(
Value const& _value
)
{
Log::Write( LogLevel_Info, GetNodeId(), "SwitchToggleBinary::Set - Toggling the state" );
Msg* msg = new Msg( "SwitchToggleBinary Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->SetInstance( this, _value.GetID().GetInstance() );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( SwitchToggleBinaryCmd_Set );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
//-----------------------------------------------------------------------------
// <SwitchToggleBinary::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void SwitchToggleBinary::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueBool( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Toggle Switch", "", false, false, false, 0 );
}
}
@@ -0,0 +1,66 @@
//-----------------------------------------------------------------------------
//
// SwitchToggleBinary.h
//
// Implementation of the Z-Wave COMMAND_CLASS_SWITCH_TOGGLE_BINARY
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _SwitchToggleBinary_H
#define _SwitchToggleBinary_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueBool;
/** \brief Implements COMMAND_CLASS_SWITCH_TOGGLE_BINARY (0x28), a Z-Wave device command class.
*/
class SwitchToggleBinary: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SwitchToggleBinary( _homeId, _nodeId ); }
virtual ~SwitchToggleBinary(){}
static uint8 const StaticGetCommandClassId(){ return 0x28; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SWITCH_TOGGLE_BINARY"; }
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
protected:
virtual void CreateVars( uint8 const _instance );
private:
SwitchToggleBinary( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,201 @@
//-----------------------------------------------------------------------------
//
// SwitchToggleMultilevel.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_SWITCH_TOGGLE_MULTILEVEL
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "SwitchToggleMultilevel.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Driver.h"
#include "../Node.h"
#include "../platform/Log.h"
#include "../value_classes/ValueByte.h"
using namespace OpenZWave;
enum SwitchToggleMultilevelCmd
{
SwitchToggleMultilevelCmd_Set = 0x01,
SwitchToggleMultilevelCmd_Get = 0x02,
SwitchToggleMultilevelCmd_Report = 0x03,
SwitchToggleMultilevelCmd_StartLevelChange = 0x04,
SwitchToggleMultilevelCmd_StopLevelChange = 0x05
};
//-----------------------------------------------------------------------------
// <SwitchToggleMultilevel::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool SwitchToggleMultilevel::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _requestFlags & RequestFlag_Dynamic )
{
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <SwitchToggleMultilevel::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool SwitchToggleMultilevel::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if ( IsGetSupported() )
{
Msg* msg = new Msg( "SwitchToggleMultilevelCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( SwitchToggleMultilevelCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "SwitchToggleMultilevelCmd_Get Not Supported on this node");
}
return false;
}
//-----------------------------------------------------------------------------
// <SwitchToggleMultilevel::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool SwitchToggleMultilevel::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( SwitchToggleMultilevelCmd_Report == (SwitchToggleMultilevelCmd)_data[0] )
{
Log::Write( LogLevel_Info, GetNodeId(), "Received SwitchToggleMultiLevel report: level=%d", _data[1] );
if( ValueByte* value = static_cast<ValueByte*>( GetValue( _instance, 0 ) ) )
{
value->OnValueRefreshed( _data[1] );
value->Release();
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <SwitchToggleMultilevel::SetValue>
// Toggle the state of the switch
//-----------------------------------------------------------------------------
bool SwitchToggleMultilevel::SetValue
(
Value const& _value
)
{
Log::Write( LogLevel_Info, GetNodeId(), "SwitchToggleMultilevel::Set - Toggling the state" );
Msg* msg = new Msg( "SwitchToggleMultilevel Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->SetInstance( this, _value.GetID().GetInstance() );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( SwitchToggleMultilevelCmd_Set );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
//-----------------------------------------------------------------------------
// <SwitchToggleMultilevel::StartLevelChange>
// Start the level changing
//-----------------------------------------------------------------------------
void SwitchToggleMultilevel::StartLevelChange
(
SwitchToggleMultilevelDirection const _direction,
bool const _bIgnoreStartLevel,
bool const _bRollover
)
{
uint8 param = (uint8)_direction;
param |= ( _bIgnoreStartLevel ? 0x20 : 0x00 );
param |= ( _bRollover ? 0x80 : 0x00 );
Log::Write( LogLevel_Info, GetNodeId(), "SwitchMultilevel::StartLevelChange - Starting a level change, Direction=%d, IgnoreStartLevel=%s and rollover=%s", (_direction==SwitchToggleMultilevelDirection_Up) ? "Up" : "Down", _bIgnoreStartLevel ? "True" : "False", _bRollover ? "True" : "False" );
Msg* msg = new Msg( "SwitchMultilevel StartLevelChange", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( SwitchToggleMultilevelCmd_StartLevelChange );
msg->Append( param );
msg->Append( GetDriver()->GetTransmitOptions() );
}
//-----------------------------------------------------------------------------
// <SwitchToggleMultilevel::StopLevelChange>
// Stop the level changing
//-----------------------------------------------------------------------------
void SwitchToggleMultilevel::StopLevelChange
(
)
{
Log::Write( LogLevel_Info, GetNodeId(), "SwitchToggleMultilevel::StopLevelChange - Stopping the level change" );
Msg* msg = new Msg( "SwitchToggleMultilevel StopLevelChange", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( SwitchToggleMultilevelCmd_StopLevelChange );
msg->Append( GetDriver()->GetTransmitOptions() );
}
//-----------------------------------------------------------------------------
// <SwitchToggleMultilevel::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void SwitchToggleMultilevel::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Level", "", false, false, 0, 0 );
}
}
@@ -0,0 +1,75 @@
//-----------------------------------------------------------------------------
//
// SwitchToggleMultilevel.h
//
// Implementation of the Z-Wave COMMAND_CLASS_SWITCH_TOGGLE_MULTILEVEL
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _SwitchToggleMultilevel_H
#define _SwitchToggleMultilevel_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueByte;
/** \brief Implements COMMAND_CLASS_SWITCH_TOGGLE_MULTILEVEL (0x29), a Z-Wave device command class.
*/
class SwitchToggleMultilevel: public CommandClass
{
public:
enum SwitchToggleMultilevelDirection
{
SwitchToggleMultilevelDirection_Up = 0x00,
SwitchToggleMultilevelDirection_Down = 0x40
};
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SwitchToggleMultilevel( _homeId, _nodeId ); }
virtual ~SwitchToggleMultilevel(){}
static uint8 const StaticGetCommandClassId(){ return 0x29; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SWITCH_TOGGLE_MULTILEVEL"; }
void StartLevelChange( SwitchToggleMultilevelDirection const _direction, bool const _bIgnoreStartLevel, bool const _bRollover );
void StopLevelChange();
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
protected:
virtual void CreateVars( uint8 const _instance );
private:
SwitchToggleMultilevel( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,344 @@
//-----------------------------------------------------------------------------
//
// ThermostatFanMode.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_THERMOSTAT_FAN_MODE
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 <string>
#include "CommandClasses.h"
#include "ThermostatFanMode.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueList.h"
#include "../tinyxml.h"
using namespace OpenZWave;
enum ThermostatFanModeCmd
{
ThermostatFanModeCmd_Set = 0x01,
ThermostatFanModeCmd_Get = 0x02,
ThermostatFanModeCmd_Report = 0x03,
ThermostatFanModeCmd_SupportedGet = 0x04,
ThermostatFanModeCmd_SupportedReport = 0x05
};
static string const c_modeName[] =
{
"Auto Low",
"On Low",
"Auto High",
"On High",
"Unknown 4",
"Unknown 5",
"Circulate",
"Unknown"
};
//-----------------------------------------------------------------------------
// <ThermostatFanMode::ReadXML>
// Read the supported modes
//-----------------------------------------------------------------------------
void ThermostatFanMode::ReadXML
(
TiXmlElement const* _ccElement
)
{
CommandClass::ReadXML( _ccElement );
if( GetNodeUnsafe() )
{
vector<ValueList::Item> supportedModes;
TiXmlElement const* supportedModesElement = _ccElement->FirstChildElement( "SupportedModes" );
if( supportedModesElement )
{
TiXmlElement const* modeElement = supportedModesElement->FirstChildElement();
while( modeElement )
{
char const* str = modeElement->Value();
if( str && !strcmp( str, "Mode" ) )
{
int index;
if( TIXML_SUCCESS == modeElement->QueryIntAttribute( "index", &index ) )
{
if (index > 6) /* size of c_modeName excluding Invalid */
{
Log::Write (LogLevel_Warning, GetNodeId(), "index Value in XML was greater than range. Setting to Invalid");
index = 7;
}
ValueList::Item item;
item.m_value = index;
item.m_label = c_modeName[index];
supportedModes.push_back( item );
}
}
modeElement = modeElement->NextSiblingElement();
}
}
if( !supportedModes.empty() )
{
m_supportedModes = supportedModes;
ClearStaticRequest( StaticRequest_Values );
CreateVars( 1 );
}
}
}
//-----------------------------------------------------------------------------
// <ThermostatFanMode::WriteXML>
// Save the supported modes
//-----------------------------------------------------------------------------
void ThermostatFanMode::WriteXML
(
TiXmlElement* _ccElement
)
{
CommandClass::WriteXML( _ccElement );
if( GetNodeUnsafe() )
{
TiXmlElement* supportedModesElement = new TiXmlElement( "SupportedModes" );
_ccElement->LinkEndChild( supportedModesElement );
for( vector<ValueList::Item>::iterator it = m_supportedModes.begin(); it != m_supportedModes.end(); ++it )
{
ValueList::Item const& item = *it;
TiXmlElement* modeElement = new TiXmlElement( "Mode" );
supportedModesElement->LinkEndChild( modeElement );
char str[8];
snprintf( str, 8, "%d", item.m_value );
modeElement->SetAttribute( "index", str );
modeElement->SetAttribute( "label", item.m_label.c_str() );
}
}
}
//-----------------------------------------------------------------------------
// <ThermostatFanMode::RequestState>
// Get the static thermostat fan mode details from the device
//-----------------------------------------------------------------------------
bool ThermostatFanMode::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
bool requests = false;
if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) )
{
// Request the supported modes
requests |= RequestValue( _requestFlags, ThermostatFanModeCmd_SupportedGet, _instance, _queue );
}
if( _requestFlags & RequestFlag_Dynamic )
{
// Request the current fan mode
requests |= RequestValue( _requestFlags, ThermostatFanModeCmd_Get, _instance, _queue );
}
return requests;
}
//-----------------------------------------------------------------------------
// <ThermostatFanMode::RequestValue>
// Get the thermostat fan mode details from the device
//-----------------------------------------------------------------------------
bool ThermostatFanMode::RequestValue
(
uint32 const _requestFlags,
uint8 const _getTypeEnum,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _getTypeEnum == ThermostatFanModeCmd_SupportedGet )
{
// Request the supported modes
Msg* msg = new Msg( "ThermostatFanModeCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( ThermostatFanModeCmd_SupportedGet );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
}
if( _getTypeEnum == ThermostatFanModeCmd_Get || _getTypeEnum == 0 )
{
if ( IsGetSupported() )
{
// Request the current fan mode
Msg* msg = new Msg( "ThermostatFanModeCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( ThermostatFanModeCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "ThermostatFanModeCmd_Get Not Supported on this node");
}
}
return false;
}
//-----------------------------------------------------------------------------
// <ThermostatFanMode::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool ThermostatFanMode::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( ThermostatFanModeCmd_Report == (ThermostatFanModeCmd)_data[0] )
{
uint8 mode = (int32)_data[1];
if( mode < m_supportedModes.size() )
{
// We have received the thermostat mode from the Z-Wave device
if( ValueList* valueList = static_cast<ValueList*>( GetValue( _instance, 0 ) ) )
{
valueList->OnValueRefreshed( (int32)_data[1] );
Log::Write( LogLevel_Info, GetNodeId(), "Received thermostat fan mode: %s", valueList->GetItem().m_label.c_str() );
valueList->Release();
}
else
{
Log::Write( LogLevel_Info, GetNodeId(), "Received thermostat fan mode: index %d", mode );
}
}
else
{
Log::Write( LogLevel_Info, GetNodeId(), "Received unknown thermostat fan mode: %d", mode );
}
return true;
}
if( ThermostatFanModeCmd_SupportedReport == (ThermostatFanModeCmd)_data[0] )
{
// We have received the supported thermostat fan modes from the Z-Wave device
Log::Write( LogLevel_Info, GetNodeId(), "Received supported thermostat fan modes" );
m_supportedModes.clear();
for( uint32 i=1; i<_length-1; ++i )
{
for( int32 bit=0; bit<8; ++bit )
{
if( ( _data[i] & (1<<bit) ) != 0 )
{
ValueList::Item item;
item.m_value = (int32)((i-1)<<3) + bit;
/* Minus 1 here as the Unknown Entry is our addition */
if ((size_t)item.m_value >= (sizeof(c_modeName)/sizeof(*c_modeName) -1))
{
Log::Write( LogLevel_Info, GetNodeId(), "Received unknown fan mode: 0x%x", item.m_value);
}
else
{
item.m_label = c_modeName[item.m_value];
m_supportedModes.push_back( item );
Log::Write( LogLevel_Info, GetNodeId(), " Added fan mode: %s", c_modeName[item.m_value].c_str() );
}
}
}
}
ClearStaticRequest( StaticRequest_Values );
CreateVars( _instance );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <ThermostatFanMode::SetValue>
// Set the device's thermostat fan mode
//-----------------------------------------------------------------------------
bool ThermostatFanMode::SetValue
(
Value const& _value
)
{
if( ValueID::ValueType_List == _value.GetID().GetType() )
{
ValueList const* value = static_cast<ValueList const*>(&_value);
uint8 state = (uint8)value->GetItem().m_value;
Msg* msg = new Msg( "ThermostatFanModeCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->SetInstance( this, _value.GetID().GetInstance() );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( ThermostatFanModeCmd_Set );
msg->Append( state );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <ThermostatFanMode::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void ThermostatFanMode::CreateVars
(
uint8 const _instance
)
{
if( m_supportedModes.empty() )
{
return;
}
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueList( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Fan Mode", "", false, false, 1, m_supportedModes, m_supportedModes[0].m_value, 0 );
}
}
@@ -0,0 +1,77 @@
//-----------------------------------------------------------------------------
//
// ThermostatFanMode.h
//
// Implementation of the Z-Wave COMMAND_CLASS_THERMOSTAT_FAN_MODE
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _ThermostatFanMode_H
#define _ThermostatFanMode_H
#include <vector>
#include <string>
#include "CommandClass.h"
#include "../value_classes/ValueList.h"
namespace OpenZWave
{
class ValueList;
/** \brief Implements COMMAND_CLASS_THERMOSTAT_FAN_MODE (0x44), a Z-Wave device command class.
*/
class ThermostatFanMode: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ThermostatFanMode( _homeId, _nodeId ); }
virtual ~ThermostatFanMode(){}
static uint8 const StaticGetCommandClassId(){ return 0x44; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_THERMOSTAT_FAN_MODE"; }
// From CommandClass
virtual void ReadXML( TiXmlElement const* _ccElement );
virtual void WriteXML( TiXmlElement* _ccElement );
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _getTypeEnum, uint8 const _dummy, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
protected:
virtual void CreateVars( uint8 const _instance );
private:
ThermostatFanMode( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){ SetStaticRequest( StaticRequest_Values ); }
vector<ValueList::Item> m_supportedModes;
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,158 @@
//-----------------------------------------------------------------------------
//
// ThermostatFanState.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_THERMOSTAT_FAN_STATE
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "ThermostatFanState.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueString.h"
using namespace OpenZWave;
enum ThermostatFanStateCmd
{
ThermostatFanStateCmd_Get = 0x02,
ThermostatFanStateCmd_Report = 0x03
};
static char const* c_stateName[] =
{
"Idle",
"Running",
"Running High",
"State 03", // Undefined states. May be used in the future.
"State 04",
"State 05",
"State 06",
"State 07",
"State 08",
"State 09",
"State 10",
"State 11",
"State 12",
"State 13",
"State 14",
"State 15",
};
//-----------------------------------------------------------------------------
// <ThermostatFanState::RequestState>
// Get the static thermostat mode details from the device
//-----------------------------------------------------------------------------
bool ThermostatFanState::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _requestFlags & RequestFlag_Dynamic )
{
// Request the current state
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <ThermostatFanState::RequestValue>
// Get the thermostat fan state details from the device
//-----------------------------------------------------------------------------
bool ThermostatFanState::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if ( IsGetSupported() )
{
// Request the current state
Msg* msg = new Msg( "ThermostatFanStateCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( ThermostatFanStateCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "ThermostatFanStateCmd_Get Not Supported on this node");
}
return false;
}
//-----------------------------------------------------------------------------
// <ThermostatFanState::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool ThermostatFanState::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( ThermostatFanStateCmd_Report == (ThermostatFanStateCmd)_data[0] )
{
// We have received the thermostat fan state from the Z-Wave device
if( ValueString* valueString = static_cast<ValueString*>( GetValue( _instance, 0 ) ) )
{
/* No need bounds checking as the state can only be a single byte - No larger than our Char array anyway */
uint8 state = (_data[1]&0x0f);
valueString->OnValueRefreshed( c_stateName[state] );
valueString->Release();
Log::Write( LogLevel_Info, GetNodeId(), "Received thermostat fan state: %s", valueString->GetValue().c_str() );
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <ThermostatFanState::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void ThermostatFanState::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueString( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Fan State", "", true, false, c_stateName[0], 0 );
}
}
@@ -0,0 +1,71 @@
//-----------------------------------------------------------------------------
//
// ThermostatFanState.h
//
// Implementation of the Z-Wave COMMAND_CLASS_THERMOSTAT_FAN_STATE
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _ThermostatFanState_H
#define _ThermostatFanState_H
#include <vector>
#include <string>
#include "CommandClass.h"
#include "../value_classes/ValueList.h"
namespace OpenZWave
{
class ValueString;
/** \brief Implements COMMAND_CLASS_THERMOSTAT_FAN_STATE (0x45), a Z-Wave device command class.
*/
class ThermostatFanState: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ThermostatFanState( _homeId, _nodeId ); }
virtual ~ThermostatFanState(){}
static uint8 const StaticGetCommandClassId(){ return 0x45; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_THERMOSTAT_FAN_STATE"; }
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
protected:
virtual void CreateVars( uint8 const _instance );
private:
ThermostatFanState( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,395 @@
//-----------------------------------------------------------------------------
//
// ThermostatMode.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_THERMOSTAT_MODE
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "ThermostatMode.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueList.h"
#include "../tinyxml.h"
using namespace OpenZWave;
enum ThermostatModeCmd
{
ThermostatModeCmd_Set = 0x01,
ThermostatModeCmd_Get = 0x02,
ThermostatModeCmd_Report = 0x03,
ThermostatModeCmd_SupportedGet = 0x04,
ThermostatModeCmd_SupportedReport = 0x05
};
static char const* c_modeName[] =
{
"Off",
"Heat",
"Cool",
"Auto",
"Aux Heat",
"Resume",
"Fan Only",
"Furnace",
"Dry Air",
"Moist Air",
"Auto Changeover",
"Heat Econ",
"Cool Econ",
"Away",
"Unknown"
};
//-----------------------------------------------------------------------------
// <ThermostatMode::ReadXML>
// Read the supported modes
//-----------------------------------------------------------------------------
void ThermostatMode::ReadXML
(
TiXmlElement const* _ccElement
)
{
CommandClass::ReadXML( _ccElement );
if( GetNodeUnsafe() )
{
vector<ValueList::Item> supportedModes;
TiXmlElement const* supportedModesElement = _ccElement->FirstChildElement( "SupportedModes" );
if( supportedModesElement )
{
TiXmlElement const* modeElement = supportedModesElement->FirstChildElement();
while( modeElement )
{
char const* str = modeElement->Value();
if( str && !strcmp( str, "Mode" ) )
{
int index;
if( TIXML_SUCCESS == modeElement->QueryIntAttribute( "index", &index ) )
{
if (index > 13) /* size of c_modeName minus Invalid */
{
Log::Write (LogLevel_Warning, GetNodeId(), "index Value in XML was greater than range. Setting to Invalid");
index = 14;
}
ValueList::Item item;
item.m_value = index;
item.m_label = c_modeName[index];
supportedModes.push_back( item );
}
}
modeElement = modeElement->NextSiblingElement();
}
}
if( !supportedModes.empty() )
{
m_supportedModes = supportedModes;
ClearStaticRequest( StaticRequest_Values );
CreateVars( 1 );
}
}
}
//-----------------------------------------------------------------------------
// <ThermostatMode::WriteXML>
// Save the supported modes
//-----------------------------------------------------------------------------
void ThermostatMode::WriteXML
(
TiXmlElement* _ccElement
)
{
if( m_supportedModes.empty() )
{
return;
}
CommandClass::WriteXML( _ccElement );
if( GetNodeUnsafe() )
{
TiXmlElement* supportedModesElement = new TiXmlElement( "SupportedModes" );
_ccElement->LinkEndChild( supportedModesElement );
for( vector<ValueList::Item>::iterator it = m_supportedModes.begin(); it != m_supportedModes.end(); ++it )
{
ValueList::Item const& item = *it;
TiXmlElement* modeElement = new TiXmlElement( "Mode" );
supportedModesElement->LinkEndChild( modeElement );
char str[8];
snprintf( str, 8, "%d", item.m_value );
modeElement->SetAttribute( "index", str );
modeElement->SetAttribute( "label", item.m_label.c_str() );
}
}
}
//-----------------------------------------------------------------------------
// <ThermostatMode::RequestState>
// Get the static thermostat mode details from the device
//-----------------------------------------------------------------------------
bool ThermostatMode::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
bool requests = false;
if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) )
{
// request supported mode list
requests |= RequestValue( _requestFlags, ThermostatModeCmd_SupportedGet, _instance, _queue );
}
if( _requestFlags & RequestFlag_Dynamic )
{
// Request the current mode
requests |= RequestValue( _requestFlags, 0, _instance, _queue );
}
return requests;
}
//-----------------------------------------------------------------------------
// <ThermostatMode::RequestValue>
// Get the static thermostat mode details from the device
//-----------------------------------------------------------------------------
bool ThermostatMode::RequestValue
(
uint32 const _requestFlags,
uint8 const _getTypeEnum,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _getTypeEnum == ThermostatModeCmd_SupportedGet )
{
// Request the supported modes
Msg* msg = new Msg( "ThermostatModeCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( ThermostatModeCmd_SupportedGet );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
}
if( _getTypeEnum == 0 ) // get current mode
{
if ( IsGetSupported() )
{
// Request the current mode
Msg* msg = new Msg( "ThermostatModeCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( ThermostatModeCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "ThermostatModeCmd_Get Not Supported on this node");
}
}
return false;
}
//-----------------------------------------------------------------------------
// <ThermostatMode::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool ThermostatMode::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( ThermostatModeCmd_Report == (ThermostatModeCmd)_data[0] )
{
uint8 mode = _data[1]&0x1f;
bool validMode = false;
for (vector<ValueList::Item>::iterator it = m_supportedModes.begin(); it != m_supportedModes.end(); ++it )
{
ValueList::Item const& item = *it;
if (item.m_value == mode) {
validMode = true;
break;
}
}
if( validMode )
{
// We have received the thermostat mode from the Z-Wave device
if( ValueList* valueList = static_cast<ValueList*>( GetValue( _instance, 0 ) ) )
{
valueList->OnValueRefreshed( mode );
Log::Write( LogLevel_Info, GetNodeId(), "Received thermostat mode: %s", valueList->GetItem().m_label.c_str() );
valueList->Release();
}
else
{
Log::Write( LogLevel_Info, GetNodeId(), "Received thermostat mode: index %d", mode );
}
}
else
{
Log::Write( LogLevel_Info, GetNodeId(), "Received unknown thermostat mode: index %d", mode );
}
return true;
}
if( ThermostatModeCmd_SupportedReport == (ThermostatModeCmd)_data[0] )
{
// We have received the supported thermostat modes from the Z-Wave device
// these values are used to populate m_supportedModes which, in turn, is used to "seed" the values
// for each m_modes instance
Log::Write( LogLevel_Info, GetNodeId(), "Received supported thermostat modes" );
m_supportedModes.clear();
for( uint32 i=1; i<_length-1; ++i )
{
for( int32 bit=0; bit<8; ++bit )
{
if( ( _data[i] & (1<<bit) ) != 0 )
{
ValueList::Item item;
item.m_value = (int32)((i-1)<<3) + bit;
/* minus 1 in the sizeof calc here, as the Unknown entry is our addition */
if ((size_t)item.m_value >= (sizeof(c_modeName)/sizeof(*c_modeName) -1))
{
Log::Write( LogLevel_Info, GetNodeId(), "Received unknown thermostat mode: 0x%x", item.m_value);
}
else
{
item.m_label = c_modeName[item.m_value];
m_supportedModes.push_back( item );
Log::Write( LogLevel_Info, GetNodeId(), " Added mode: %s", c_modeName[item.m_value] );
}
}
}
}
ClearStaticRequest( StaticRequest_Values );
CreateVars( _instance );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <ThermostatMode::SetValue>
// Set the device's thermostat mode
//-----------------------------------------------------------------------------
bool ThermostatMode::SetValue
(
Value const& _value
)
{
if( ValueID::ValueType_List == _value.GetID().GetType() )
{
ValueList const* value = static_cast<ValueList const*>(&_value);
uint8 state = (uint8)value->GetItem().m_value;
Msg* msg = new Msg( "ThermostatModeCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( ThermostatModeCmd_Set );
msg->Append( state );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <ThermostatMode::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void ThermostatMode::CreateVars
(
uint8 const _instance
)
{
// There are three ways to get here...each needs to be handled differently:
// QueryStage_ProtocolInfo:
// Don't know what's supported yet, so do nothing
// QueryStage_NodeInfo:
// Need to create the instance so the values can be read from the xml file
// QueryStage_Static:
// Need to create the instance (processing SupportedReport) if it doesn't exist
// If it does, populate with the appropriate values
if( Node* node = GetNodeUnsafe() )
{
Node::QueryStage qs = node->GetCurrentQueryStage();
if( qs == Node::QueryStage_ProtocolInfo )
{
// this call is from QueryStage_ProtocolInfo,
// so just return (don't know which modes are supported yet)
return;
}
// identify the lowest supported mode as the "default" (or default to 0 if no supported modes identified yet)
int32 defaultValue = 0;
if( !m_supportedModes.empty() )
{
defaultValue = m_supportedModes[0].m_value;
}
if( qs == Node::QueryStage_Static )
{
// This instance might already have been created (in NodeInfo, in preparation for loading the values
// from zwcfg xml file). So, if the instance already exists, we delete its value and add a new one below
if( ValueList* valueList = static_cast<ValueList*>( GetValue( _instance, 0 ) ) )
{
node->RemoveValueList( valueList );
valueList->Release();
}
}
node->CreateValueList( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Mode", "", false, false, 1, m_supportedModes, defaultValue, 0 );
}
}
@@ -0,0 +1,76 @@
//-----------------------------------------------------------------------------
//
// ThermostatMode.h
//
// Implementation of the Z-Wave COMMAND_CLASS_THERMOSTAT_MODE
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _ThermostatMode_H
#define _ThermostatMode_H
#include <vector>
#include <string>
#include "CommandClass.h"
#include "../value_classes/ValueList.h"
namespace OpenZWave
{
class ValueList;
/** \brief Implements COMMAND_CLASS_THERMOSTAT_MODE (0x40), a Z-Wave device command class.
*/
class ThermostatMode: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ThermostatMode( _homeId, _nodeId ); }
virtual ~ThermostatMode(){}
static uint8 const StaticGetCommandClassId(){ return 0x40; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_THERMOSTAT_MODE"; }
// From CommandClass
virtual void ReadXML( TiXmlElement const* _ccElement );
virtual void WriteXML( TiXmlElement* _ccElement );
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _getTypeEnum, uint8 const _dummy, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
protected:
virtual void CreateVars( uint8 const _instance );
private:
ThermostatMode( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){ SetStaticRequest( StaticRequest_Values ); }
vector<ValueList::Item> m_supportedModes;
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,154 @@
//-----------------------------------------------------------------------------
//
// ThermostatOperatingState.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_THERMOSTAT_OPERATING_STATE
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "ThermostatOperatingState.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueString.h"
using namespace OpenZWave;
enum ThermostatOperatingStateCmd
{
ThermostatOperatingStateCmd_Get = 0x02,
ThermostatOperatingStateCmd_Report = 0x03
};
static char const* c_stateName[] =
{
"Idle",
"Heating",
"Cooling",
"Fan Only",
"Pending Heat",
"Pending Cool",
"Vent / Economizer",
"State 07", // Undefined states. May be used in the future.
"State 08",
"State 09",
"State 10",
"State 11",
"State 12",
"State 13",
"State 14",
"State 15"
};
//-----------------------------------------------------------------------------
// <ThermostatOperatingState::RequestState>
// Get the static thermostat mode details from the device
//-----------------------------------------------------------------------------
bool ThermostatOperatingState::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _requestFlags & RequestFlag_Dynamic )
{
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <ThermostatOperatingState::RequestValue>
// Get a thermostat mode value from the device
//-----------------------------------------------------------------------------
bool ThermostatOperatingState::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if ( IsGetSupported() )
{
Msg* msg = new Msg( "ThermostatOperatingStateCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( ThermostatOperatingStateCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "ThermostatOperatingStateCmd_Get Not Supported on this node");
}
return false;
}
//-----------------------------------------------------------------------------
// <ThermostatOperatingState::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool ThermostatOperatingState::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( ThermostatOperatingStateCmd_Report == (ThermostatOperatingStateCmd)_data[0] )
{
// We have received the thermostat operating state from the Z-Wave device
if( ValueString* valueString = static_cast<ValueString*>( GetValue( _instance, 0 ) ) )
{
/* no need bounds checking on c_stateName here, as it can only be 1 Byte anyway */
valueString->OnValueRefreshed( c_stateName[_data[1]&0x0f] );
valueString->Release();
Log::Write( LogLevel_Info, GetNodeId(), "Received thermostat operating state: %s", valueString->GetValue().c_str() );
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <ThermostatOperatingState::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void ThermostatOperatingState::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueString( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Operating State", "", true, false, c_stateName[0], 0 );
}
}
@@ -0,0 +1,71 @@
//-----------------------------------------------------------------------------
//
// ThermostatOperatingState.h
//
// Implementation of the Z-Wave COMMAND_CLASS_THERMOSTAT_OPERATING_STATE
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _ThermostatOperatingState_H
#define _ThermostatOperatingState_H
#include <vector>
#include <string>
#include "CommandClass.h"
#include "../value_classes/ValueList.h"
namespace OpenZWave
{
class ValueString;
/** \brief Implements COMMAND_CLASS_THERMOSTAT_OPERATING_STATE (0x42), a Z-Wave device command class.
*/
class ThermostatOperatingState: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ThermostatOperatingState( _homeId, _nodeId ); }
virtual ~ThermostatOperatingState(){}
static uint8 const StaticGetCommandClassId(){ return 0x42; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_THERMOSTAT_OPERATING_STATE"; }
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
protected:
virtual void CreateVars( uint8 const _instance );
private:
ThermostatOperatingState( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){}
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,323 @@
//-----------------------------------------------------------------------------
//
// ThermostatSetpoint.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_THERMOSTAT_SETPOINT
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "ThermostatSetpoint.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueDecimal.h"
#include "../tinyxml.h"
using namespace OpenZWave;
enum ThermostatSetpointCmd
{
ThermostatSetpointCmd_Set = 0x01,
ThermostatSetpointCmd_Get = 0x02,
ThermostatSetpointCmd_Report = 0x03,
ThermostatSetpointCmd_SupportedGet = 0x04,
ThermostatSetpointCmd_SupportedReport = 0x05
};
enum
{
ThermostatSetpoint_Unused0 = 0,
ThermostatSetpoint_Heating1,
ThermostatSetpoint_Cooling1,
ThermostatSetpoint_Unused3,
ThermostatSetpoint_Unused4,
ThermostatSetpoint_Unused5,
ThermostatSetpoint_Unused6,
ThermostatSetpoint_Furnace,
ThermostatSetpoint_DryAir,
ThermostatSetpoint_MoistAir,
ThermostatSetpoint_AutoChangeover,
ThermostatSetpoint_HeatingEcon,
ThermostatSetpoint_CoolingEcon,
ThermostatSetpoint_AwayHeating,
ThermostatSetpoint_Count
};
static char const* c_setpointName[] =
{
"Unused 0",
"Heating 1",
"Cooling 1",
"Unused 3",
"Unused 4",
"Unused 5",
"Unused 6",
"Furnace",
"Dry Air",
"Moist Air",
"Auto Changeover",
"Heating Econ",
"Cooling Econ",
"Away Heating"
};
//-----------------------------------------------------------------------------
// <ThermostatSetpoint::ThermostatSetpoint>
// Constructor
//-----------------------------------------------------------------------------
ThermostatSetpoint::ThermostatSetpoint
(
uint32 const _homeId,
uint8 const _nodeId
):
CommandClass( _homeId, _nodeId ), m_setPointBase( 1 )
{
SetStaticRequest( StaticRequest_Values );
}
//-----------------------------------------------------------------------------
// <ThermostatSetpoint::ReadXML>
// Read the saved change-counter value
//-----------------------------------------------------------------------------
void ThermostatSetpoint::ReadXML
(
TiXmlElement const* _ccElement
)
{
CommandClass::ReadXML( _ccElement );
int intVal;
if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "base", &intVal ) )
{
m_setPointBase = (uint8)intVal;
}
}
//-----------------------------------------------------------------------------
// <ThermostatSetpoint::WriteXML>
// Write the change-counter value
//-----------------------------------------------------------------------------
void ThermostatSetpoint::WriteXML
(
TiXmlElement* _ccElement
)
{
CommandClass::WriteXML( _ccElement );
char str[8];
snprintf( str, 8, "%d", m_setPointBase );
_ccElement->SetAttribute( "base", str );
}
//-----------------------------------------------------------------------------
// <ThermostatSetpoint::RequestState>
// Get the static thermostat setpoint details from the device
//-----------------------------------------------------------------------------
bool ThermostatSetpoint::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
bool requests = false;
if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) )
{
requests |= RequestValue( _requestFlags, 0xff, _instance, _queue );
}
if( _requestFlags & RequestFlag_Session )
{
for( uint8 i=0; i<ThermostatSetpoint_Count; ++i )
{
requests |= RequestValue( _requestFlags, i, _instance, _queue );
}
}
return requests;
}
//-----------------------------------------------------------------------------
// <ThermostatSetpoint::RequestValue>
// Request current state from the device
//-----------------------------------------------------------------------------
bool ThermostatSetpoint::RequestValue
(
uint32 const _requestFlags,
uint8 const _setPointIndex,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _setPointIndex == 0xff ) // check for supportedget
{
// Request the supported setpoints
Msg* msg = new Msg( "ThermostatSetpointCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( ThermostatSetpointCmd_SupportedGet );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
}
if ( !IsGetSupported() )
{
Log::Write( LogLevel_Info, GetNodeId(), "ThermostatSetpointCmd_Get Not Supported on this node");
return false;
}
Value* value = GetValue( 1, _setPointIndex );
if( value != NULL )
{
value->Release();
// Request the setpoint value
Msg* msg = new Msg( "ThermostatSetpointCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( ThermostatSetpointCmd_Get );
msg->Append( _setPointIndex );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <ThermostatSetpoint::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool ThermostatSetpoint::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( ThermostatSetpointCmd_Report == (ThermostatSetpointCmd)_data[0] )
{
// We have received a thermostat setpoint value from the Z-Wave device
if( ValueDecimal* value = static_cast<ValueDecimal*>( GetValue( _instance, _data[1] ) ) )
{
uint8 scale;
uint8 precision = 0;
string temperature = ExtractValue( &_data[2], &scale, &precision );
value->SetUnits( scale ? "F" : "C" );
value->OnValueRefreshed( temperature );
if( value->GetPrecision() != precision )
{
value->SetPrecision( precision );
}
value->Release();
Log::Write( LogLevel_Info, GetNodeId(), "Received thermostat setpoint report: Setpoint %s = %s%s", value->GetLabel().c_str(), value->GetValue().c_str(), value->GetUnits().c_str() );
}
return true;
}
if( ThermostatSetpointCmd_SupportedReport == (ThermostatSetpointCmd)_data[0] )
{
if( Node* node = GetNodeUnsafe() )
{
// We have received the supported thermostat setpoints from the Z-Wave device
Log::Write( LogLevel_Info, GetNodeId(), "Received supported thermostat setpoints" );
// Parse the data for the supported setpoints
for( uint32 i=1; i<_length-1; ++i )
{
for( int32 bit=0; bit<8; ++bit )
{
if( ( _data[i] & (1<<bit) ) != 0 )
{
// Add supported setpoint
int32 index = (int32)((i-1)<<3) + bit + m_setPointBase;
if( index < ThermostatSetpoint_Count )
{
node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, index, c_setpointName[index], "C", false, false, "0.0", 0 );
Log::Write( LogLevel_Info, GetNodeId(), " Added setpoint: %s", c_setpointName[index] );
}
}
}
}
}
ClearStaticRequest( StaticRequest_Values );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <ThermostatSetpoint::SetValue>
// Set a thermostat setpoint temperature
//-----------------------------------------------------------------------------
bool ThermostatSetpoint::SetValue
(
Value const& _value
)
{
if( ValueID::ValueType_Decimal == _value.GetID().GetType() )
{
ValueDecimal const* value = static_cast<ValueDecimal const*>(&_value);
uint8 scale = strcmp( "C", value->GetUnits().c_str() ) ? 1 : 0;
Msg* msg = new Msg( "Set Thermostat Setpoint", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->SetInstance( this, _value.GetID().GetInstance() );
msg->Append( GetNodeId() );
msg->Append( 4 + GetAppendValueSize( value->GetValue() ) );
msg->Append( GetCommandClassId() );
msg->Append( ThermostatSetpointCmd_Set );
msg->Append( value->GetID().GetIndex() );
AppendValue( msg, value->GetValue(), scale );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <ThermostatSetpoint::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void ThermostatSetpoint::CreateVars
(
uint8 const _instance,
uint8 const _index
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, _index, "Setpoint", "C", false, false, "0.0", 0 );
}
}
@@ -0,0 +1,73 @@
//-----------------------------------------------------------------------------
//
// ThermostatSetpoint.h
//
// Implementation of the Z-Wave COMMAND_CLASS_THERMOSTAT_SETPOINT
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _ThermostatSetpoint_H
#define _ThermostatSetpoint_H
#include <vector>
#include <string>
#include "CommandClass.h"
namespace OpenZWave
{
class ValueDecimal;
/** \brief Implements COMMAND_CLASS_THERMOSTAT_SETPOINT (0x43), a Z-Wave device command class.
*/
class ThermostatSetpoint: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ThermostatSetpoint( _homeId, _nodeId ); }
virtual ~ThermostatSetpoint(){}
static uint8 const StaticGetCommandClassId(){ return 0x43; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_THERMOSTAT_SETPOINT"; }
// From CommandClass
virtual void ReadXML( TiXmlElement const* _ccElement );
virtual void WriteXML( TiXmlElement* _ccElement );
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _setPointIndex, uint8 const _dummy, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
public:
virtual void CreateVars( uint8 const _instance, uint8 const _index );
private:
ThermostatSetpoint( uint32 const _homeId, uint8 const _nodeId );
uint8 m_setPointBase;
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,236 @@
//-----------------------------------------------------------------------------
//
// TimeParameters.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_TIME_PARAMETERS
//
// Copyright (c) 2014 Justin Hammond <Justin@dynam.ac>
//
// 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 <time.h>
#include "CommandClasses.h"
#include "TimeParameters.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Node.h"
#include "../Driver.h"
#include "../platform/Log.h"
#include "../value_classes/ValueButton.h"
#include "../value_classes/ValueString.h"
using namespace OpenZWave;
enum TimeParametersCmd
{
TimeParametersCmd_Set = 0x01,
TimeParametersCmd_Get = 0x02,
TimeParametersCmd_Report = 0x03
};
enum
{
TimeParametersIndex_Date = 0,
TimeParametersIndex_Time,
TimeParametersIndex_Set,
TimeParametersIndex_Refresh
};
//-----------------------------------------------------------------------------
// <DoorLockLogging::DoorLockLogging>
// Constructor
//-----------------------------------------------------------------------------
TimeParameters::TimeParameters
(
uint32 const _homeId,
uint8 const _nodeId
):
CommandClass( _homeId, _nodeId )
{
SetStaticRequest( StaticRequest_Values );
}
//-----------------------------------------------------------------------------
// <TimeParameters::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool TimeParameters::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) )
{
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <TimeParameters::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool TimeParameters::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0 (not used)
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if ( IsGetSupported() )
{
Msg* msg = new Msg( "TimeParametersCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, _instance );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( TimeParametersCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "TimeParametersCmd_Get Not Supported on this node");
}
return false;
}
//-----------------------------------------------------------------------------
// <TimeParameters::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool TimeParameters::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if (TimeParametersCmd_Report == (TimeParametersCmd)_data[0])
{
uint16 year = (_data[1] << 8) + (_data[2] & 0xFF);
uint8 month = (_data[3] & 0x0F);
uint8 day = (_data[4] & 0x1F);
uint8 hour = (_data[5] & 0x1F);
uint8 minute = (_data[6] & 0x3F);
uint8 second = (_data[7] & 0x3F);
Log::Write( LogLevel_Info, GetNodeId(), "Received TimeParameters report: %02d/%02d/%04d %02d:%02d:%02d", (int)day, (int)month, (int)year, (int)hour, (int)minute, (int)second);
if( ValueString* value = static_cast<ValueString*>( GetValue( _instance, TimeParametersIndex_Date ) ) )
{
char msg[512];
snprintf(msg, sizeof(msg), "%02d/%02d/%04d", (int)day, (int)month, (int)year);
value->OnValueRefreshed( msg );
value->Release();
}
if( ValueString* value = static_cast<ValueString*>( GetValue( _instance, TimeParametersIndex_Time ) ) )
{
char msg[512];
snprintf(msg, sizeof(msg), "%02d:%02d:%02d", (int)hour, (int)minute, (int)second);
value->OnValueRefreshed( msg );
value->Release();
}
ClearStaticRequest( StaticRequest_Values );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <TimeParameters::SetValue>
// Set a value in the Z-Wave device
//-----------------------------------------------------------------------------
bool TimeParameters::SetValue
(
Value const& _value
)
{
bool ret = false;
uint8 instance = _value.GetID().GetInstance();
if ( (ValueID::ValueType_Button == _value.GetID().GetType()) && (_value.GetID().GetIndex() == TimeParametersIndex_Set) )
{
time_t rawtime;
struct tm *timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
Msg* msg = new Msg( "TimeParametersCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->SetInstance( this, instance );
msg->Append( GetNodeId() );
msg->Append( 9 );
msg->Append( GetCommandClassId() );
msg->Append( TimeParametersCmd_Set );
/* Year 1 */
msg->Append( ((timeinfo->tm_year + 1900)>> 8) & 0xFF);
/* Year 2 */
msg->Append( ((timeinfo->tm_year + 1900) & 0xFF));
/* Month */
msg->Append( (timeinfo->tm_mon & 0x0F)+1);
/* Day */
msg->Append( (timeinfo->tm_mday & 0x1F));
/* Hour */
msg->Append( (timeinfo->tm_hour & 0x1F));
/* Minute */
msg->Append( (timeinfo->tm_min & 0x3F));
/* Second */
msg->Append( (timeinfo->tm_sec & 0x3F));
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
/* Refresh after we send updated date/time */
SetStaticRequest( StaticRequest_Values );
ret = RequestValue( RequestFlag_Static, 0, instance, Driver::MsgQueue_Query );
}
if ( (ValueID::ValueType_Button == _value.GetID().GetType()) && (_value.GetID().GetIndex() == TimeParametersIndex_Refresh) )
{
SetStaticRequest( StaticRequest_Values );
ret = RequestValue( RequestFlag_Static, 0, instance, Driver::MsgQueue_Query );
}
return ret;
}
//-----------------------------------------------------------------------------
// <TimeParameters::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void TimeParameters::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueString( ValueID::ValueGenre_System, GetCommandClassId(), _instance, TimeParametersIndex_Date, "Date", "", true, false, "", 0 );
node->CreateValueString( ValueID::ValueGenre_System, GetCommandClassId(), _instance, TimeParametersIndex_Time, "Time", "", true, false, "", 0 );
node->CreateValueButton( ValueID::ValueGenre_System, GetCommandClassId(), _instance, TimeParametersIndex_Set, "Set Date/Time", 0);
node->CreateValueButton( ValueID::ValueGenre_System, GetCommandClassId(), _instance, TimeParametersIndex_Refresh, "Refresh Date/Time", 0);
}
}
@@ -0,0 +1,67 @@
//-----------------------------------------------------------------------------
//
// TimeParameters.h
//
// Implementation of the Z-Wave COMMAND_CLASS_TIME_PARAMETERS
//
// Copyright (c) 2014 Justin Hammond <Justin@dynam.ac>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _TimeParameters_H
#define _TimeParameters_H
#include "CommandClass.h"
namespace OpenZWave
{
class ValueByte;
class ValueList;
/** \brief Implements COMMAND_CLASS_TIME_PARAMETERS (0x8B), a Z-Wave device command class.
*/
class TimeParameters: public CommandClass
{
public:
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new TimeParameters( _homeId, _nodeId ); }
virtual ~TimeParameters(){}
static uint8 const StaticGetCommandClassId(){ return 0x8B; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_TIME_PARAMETERS"; }
// From CommandClass
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
protected:
virtual void CreateVars( uint8 const _instance );
private:
TimeParameters( uint32 const _homeId, uint8 const _nodeId );
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,355 @@
//-----------------------------------------------------------------------------
//
// UserCode.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_USER_CODE
//
// Copyright (c) 2012 Greg Satz <satz@iranger.com>
//
// 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 "../tinyxml.h"
#include "CommandClasses.h"
#include "UserCode.h"
#include "../Node.h"
#include "../Options.h"
#include "../platform/Log.h"
#include "../value_classes/ValueByte.h"
#include "../value_classes/ValueRaw.h"
using namespace OpenZWave;
enum UserCodeCmd
{
UserCodeCmd_Set = 0x01,
UserCodeCmd_Get = 0x02,
UserCodeCmd_Report = 0x03,
UserNumberCmd_Get = 0x04,
UserNumberCmd_Report = 0x05
};
enum
{
UserCodeIndex_Refresh = 254,
UserCodeIndex_Count = 255
};
const uint8 UserCodeLength = 10;
//-----------------------------------------------------------------------------
// <UserCode::UserCode>
// Constructor
//-----------------------------------------------------------------------------
UserCode::UserCode
(
uint32 const _homeId,
uint8 const _nodeId
):
CommandClass( _homeId, _nodeId ),
m_queryAll( false ),
m_currentCode( 0 ),
m_userCodeCount( 0 ),
m_refreshUserCodes(false)
{
SetStaticRequest( StaticRequest_Values );
memset( m_userCodesStatus, 0xff, sizeof(m_userCodesStatus) );
Options::Get()->GetOptionAsBool("RefreshAllUserCodes", &m_refreshUserCodes );
}
//-----------------------------------------------------------------------------
// <UserCode::ReadXML>
// Class specific configuration
//-----------------------------------------------------------------------------
void UserCode::ReadXML
(
TiXmlElement const* _ccElement
)
{
int32 intVal;
CommandClass::ReadXML( _ccElement );
if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "codes", &intVal ) )
{
m_userCodeCount = intVal;
}
}
//-----------------------------------------------------------------------------
// <UserCode::WriteXML>
// Class specific configuration
//-----------------------------------------------------------------------------
void UserCode::WriteXML
(
TiXmlElement* _ccElement
)
{
char str[32];
CommandClass::WriteXML( _ccElement );
snprintf( str, sizeof(str), "%d", m_userCodeCount );
_ccElement->SetAttribute( "codes", str);
}
//-----------------------------------------------------------------------------
// <UserCode::RequestState>
// Nothing to do for UserCode
//-----------------------------------------------------------------------------
bool UserCode::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
bool requests = false;
if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) )
{
requests |= RequestValue( _requestFlags, UserCodeIndex_Count, _instance, _queue );
}
if( _requestFlags & RequestFlag_Session )
{
if( m_userCodeCount > 0 )
{
m_queryAll = true;
m_currentCode = 1;
requests |= RequestValue( _requestFlags, m_currentCode, _instance, _queue );
}
}
return requests;
}
//-----------------------------------------------------------------------------
// <UserCode::RequestValue>
// Nothing to do for UserCode
//-----------------------------------------------------------------------------
bool UserCode::RequestValue
(
uint32 const _requestFlags,
uint8 const _userCodeIdx,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _instance != 1 )
{
// This command class doesn't work with multiple instances
return false;
}
if ( !IsGetSupported() )
{
Log::Write( LogLevel_Info, GetNodeId(), "UserNumberCmd_Get Not Supported on this node");
return false;
}
if( _userCodeIdx == UserCodeIndex_Count )
{
// Get number of supported user codes.
Msg* msg = new Msg( "UserNumberCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( UserNumberCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
}
if (_userCodeIdx == 0)
{
Log::Write( LogLevel_Warning, GetNodeId(), "UserCodeCmd_Get with Index 0 not Supported");
return false;
}
Msg* msg = new Msg( "UserCodeCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( UserCodeCmd_Get );
msg->Append( _userCodeIdx );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
}
//-----------------------------------------------------------------------------
// <UserCode::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool UserCode::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( UserNumberCmd_Report == (UserCodeCmd)_data[0] )
{
m_userCodeCount = _data[1];
if( m_userCodeCount > 254 )
{
// Make space for code count.
m_userCodeCount = 254;
}
ClearStaticRequest( StaticRequest_Values );
if( m_userCodeCount == 0 )
{
Log::Write( LogLevel_Info, GetNodeId(), "Received User Number report from node %d: Not supported", GetNodeId() );
}
else
{
Log::Write( LogLevel_Info, GetNodeId(), "Received User Number report from node %d: Supported Codes %d (%d)", GetNodeId(), m_userCodeCount, _data[1] );
}
if( ValueByte* value = static_cast<ValueByte*>( GetValue( _instance, UserCodeIndex_Count ) ) )
{
value->OnValueRefreshed( m_userCodeCount );
value->Release();
}
if( Node* node = GetNodeUnsafe() )
{
uint8 data[UserCodeLength];
memset( data, 0, UserCodeLength );
for( uint8 i = 0; i <= m_userCodeCount; i++ )
{
char str[16];
if (i == 0)
{
snprintf( str, sizeof(str), "Enrollment Code");
node->CreateValueRaw( ValueID::ValueGenre_User, GetCommandClassId(), _instance, i, str, "", true, false, data, UserCodeLength, 0 );
}
else
{
snprintf( str, sizeof(str), "Code %d:", i);
node->CreateValueRaw( ValueID::ValueGenre_User, GetCommandClassId(), _instance, i, str, "", false, false, data, UserCodeLength, 0 );
}
}
}
return true;
}
else if( UserCodeCmd_Report == (UserCodeCmd)_data[0] )
{
int i = _data[1];
if( ValueRaw* value = static_cast<ValueRaw*>( GetValue( _instance, i ) ) )
{
uint8 data[UserCodeLength];
uint8 size = _length - 4;
if( size > UserCodeLength )
{
Log::Write( LogLevel_Warning, GetNodeId(), "User Code length %d is larger then maximum %d", size, UserCodeLength );
size = UserCodeLength;
}
m_userCodesStatus[i] = _data[2];
memcpy( data, &_data[3], size );
value->OnValueRefreshed( data, size );
value->Release();
}
Log::Write( LogLevel_Info, GetNodeId(), "Received User Code Report from node %d for User Code %d (%s)", GetNodeId(), i, CodeStatus( _data[2] ).c_str() );
if( m_queryAll && i == m_currentCode )
{
if (m_refreshUserCodes && (_data[2] != UserCode_Available)) {
if( ++i <= m_userCodeCount )
{
m_currentCode = i;
RequestValue( 0, m_currentCode, _instance, Driver::MsgQueue_Query );
}
else
{
m_queryAll = false;
/* we might have reset this as part of the RefreshValues Button Value */
Options::Get()->GetOptionAsBool("RefreshAllUserCodes", &m_refreshUserCodes );
}
} else {
Log::Write( LogLevel_Info, GetNodeId(), "Not Requesting additional UserCode Slots as RefreshAllUserCodes is false, and slot %d is available", i);
m_queryAll = false;
}
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <UserCode::SetValue>
// Set a User Code value
//-----------------------------------------------------------------------------
bool UserCode::SetValue
(
Value const& _value
)
{
if( (ValueID::ValueType_Raw == _value.GetID().GetType()) && (_value.GetID().GetIndex() < UserCodeIndex_Refresh) )
{
ValueRaw const* value = static_cast<ValueRaw const*>(&_value);
uint8* s = value->GetValue();
uint8 len = value->GetLength();
if( len > UserCodeLength )
{
return false;
}
m_userCodesStatus[value->GetID().GetIndex()] = UserCode_Occupied;
Msg* msg = new Msg( "UserCodeCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
msg->SetInstance( this, _value.GetID().GetInstance() );
msg->Append( GetNodeId() );
msg->Append( 4 + len );
msg->Append( GetCommandClassId() );
msg->Append( UserCodeCmd_Set );
msg->Append( value->GetID().GetIndex() );
msg->Append( UserCode_Occupied );
for( uint8 i = 0; i < len; i++ )
{
msg->Append( s[i] );
}
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
if ( (ValueID::ValueType_Button == _value.GetID().GetType()) && (_value.GetID().GetIndex() == UserCodeIndex_Refresh) )
{
m_refreshUserCodes = true;
m_currentCode = 1;
m_queryAll = true;
RequestValue( 0, m_currentCode, _value.GetID().GetInstance(), Driver::MsgQueue_Query );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// <UserCode::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void UserCode::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueByte( ValueID::ValueGenre_System, GetCommandClassId(), _instance, UserCodeIndex_Count, "Code Count", "", true, false, 0, 0 );
node->CreateValueButton( ValueID::ValueGenre_System, GetCommandClassId(), _instance, UserCodeIndex_Refresh, "Refresh All UserCodes", 0);
}
}
@@ -0,0 +1,113 @@
//-----------------------------------------------------------------------------
//
// UserCode.h
//
// Implementation of the Z-Wave COMMAND_CLASS_USER_CODE
//
// Copyright (c) 2012 Greg Satz <satz@iranger.com>
//
// 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/>.
//
//-----------------------------------------------------------------------------
#ifndef _UserCode_H
#define _UserCode_H
#include "CommandClass.h"
namespace OpenZWave
{
/** \brief Implements COMMAND_CLASS_USER_CODE (0x63), a Z-Wave device command class.
*/
class UserCode: public CommandClass
{
public:
enum UserCodeStatus
{
UserCode_Available = 0x00,
UserCode_Occupied = 0x01,
UserCode_Reserved = 0x02,
UserCode_NotAvailable = 0xfe,
UserCode_Unset = 0xff
};
static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new UserCode( _homeId, _nodeId ); }
virtual ~UserCode(){}
static uint8 const StaticGetCommandClassId(){ return 0x63; }
static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_USER_CODE"; }
// From CommandClass
virtual void ReadXML( TiXmlElement const* _ccElement );
virtual void WriteXML( TiXmlElement* _ccElement );
virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue );
virtual bool RequestValue( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue );
virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); }
virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); }
virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 );
virtual bool SetValue( Value const& _value );
protected:
virtual void CreateVars( uint8 const _instance );
private:
UserCode( uint32 const _homeId, uint8 const _nodeId );
string CodeStatus( uint8 const _byte )
{
switch( _byte )
{
case UserCode_Available:
{
return "Available";
}
case UserCode_Occupied:
{
return "Occupied";
}
case UserCode_Reserved:
{
return "Reserved";
}
case UserCode_NotAvailable:
{
return "Not Available";
}
case UserCode_Unset:
{
return "Unset";
}
default:
{
return "Unknown";
}
}
}
bool m_queryAll; // True while we are requesting all the user codes.
uint8 m_currentCode;
uint8 m_userCodeCount;
uint8 m_userCodesStatus[256];
bool m_refreshUserCodes;
};
} // namespace OpenZWave
#endif
@@ -0,0 +1,263 @@
//-----------------------------------------------------------------------------
//
// Version.cpp
//
// Implementation of the Z-Wave COMMAND_CLASS_VERSION
//
// Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
// 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 "CommandClasses.h"
#include "Version.h"
#include "../Defs.h"
#include "../Msg.h"
#include "../Driver.h"
#include "../Node.h"
#include "../platform/Log.h"
#include "../value_classes/ValueString.h"
#include "../tinyxml.h"
using namespace OpenZWave;
enum VersionCmd
{
VersionCmd_Get = 0x11,
VersionCmd_Report = 0x12,
VersionCmd_CommandClassGet = 0x13,
VersionCmd_CommandClassReport = 0x14
};
enum
{
VersionIndex_Library = 0,
VersionIndex_Protocol,
VersionIndex_Application
};
//-----------------------------------------------------------------------------
// <Version::Version>
// Constructor
//-----------------------------------------------------------------------------
Version::Version
(
uint32 const _homeId,
uint8 const _nodeId
):
CommandClass( _homeId, _nodeId ),
m_classGetSupported( true )
{
SetStaticRequest( StaticRequest_Values );
}
//-----------------------------------------------------------------------------
// <Version::ReadXML>
// Read configuration.
//-----------------------------------------------------------------------------
void Version::ReadXML
(
TiXmlElement const* _ccElement
)
{
CommandClass::ReadXML( _ccElement );
char const* str = _ccElement->Attribute("classgetsupported");
if( str )
{
m_classGetSupported = !strcmp( str, "true");
}
}
//-----------------------------------------------------------------------------
// <Version::WriteXML>
// Save changed configuration
//-----------------------------------------------------------------------------
void Version::WriteXML
(
TiXmlElement* _ccElement
)
{
CommandClass::WriteXML( _ccElement );
if( !m_classGetSupported )
{
_ccElement->SetAttribute( "classgetsupported", "false" );
}
}
//-----------------------------------------------------------------------------
// <Version::RequestState>
// Request current state from the device
//-----------------------------------------------------------------------------
bool Version::RequestState
(
uint32 const _requestFlags,
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) )
{
return RequestValue( _requestFlags, 0, _instance, _queue );
}
return false;
}
//-----------------------------------------------------------------------------
// <Version::RequestValue>
// Request current value from the device
//-----------------------------------------------------------------------------
bool Version::RequestValue
(
uint32 const _requestFlags,
uint8 const _dummy1, // = 0
uint8 const _instance,
Driver::MsgQueue const _queue
)
{
if( _instance != 1 )
{
// This command class doesn't work with multiple instances
return false;
}
if ( IsGetSupported() )
{
Msg* msg = new Msg( "VersionCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 2 );
msg->Append( GetCommandClassId() );
msg->Append( VersionCmd_Get );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, _queue );
return true;
} else {
Log::Write( LogLevel_Info, GetNodeId(), "VersionCmd_Get Not Supported on this node");
}
return false;
}
//-----------------------------------------------------------------------------
// <Version::HandleMsg>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
bool Version::HandleMsg
(
uint8 const* _data,
uint32 const _length,
uint32 const _instance // = 1
)
{
if( Node* node = GetNodeUnsafe() )
{
if( VersionCmd_Report == (VersionCmd)_data[0] )
{
char library[8];
char protocol[16];
char application[16];
snprintf( library, sizeof(library), "%d", _data[1] );
snprintf( protocol, sizeof(protocol), "%d.%.2d", _data[2], _data[3] );
snprintf( application, sizeof(application), "%d.%.2d", _data[4], _data[5] );
Log::Write( LogLevel_Info, GetNodeId(), "Received Version report from node %d: Library=%s, Protocol=%s, Application=%s", GetNodeId(), library, protocol, application );
ClearStaticRequest( StaticRequest_Values );
if( ValueString* libraryValue = static_cast<ValueString*>( GetValue( _instance, VersionIndex_Library ) ) )
{
libraryValue->OnValueRefreshed( library );
libraryValue->Release();
}
if( ValueString* protocolValue = static_cast<ValueString*>( GetValue( _instance, VersionIndex_Protocol ) ) )
{
protocolValue->OnValueRefreshed( protocol );
protocolValue->Release();
}
if( ValueString* applicationValue = static_cast<ValueString*>( GetValue( _instance, VersionIndex_Application ) ) )
{
applicationValue->OnValueRefreshed( application );
applicationValue->Release();
}
return true;
}
if (VersionCmd_CommandClassReport == (VersionCmd)_data[0])
{
if( CommandClass* pCommandClass = node->GetCommandClass( _data[1] ) )
{
Log::Write( LogLevel_Info, GetNodeId(), "Received Command Class Version report from node %d: CommandClass=%s, Version=%d", GetNodeId(), pCommandClass->GetCommandClassName().c_str(), _data[2] );
pCommandClass->ClearStaticRequest( StaticRequest_Version );
pCommandClass->SetVersion( _data[2] );
}
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
// <Version::RequestCommandClassVersion>
// Request the version of a command class used by the device
//-----------------------------------------------------------------------------
bool Version::RequestCommandClassVersion
(
CommandClass const* _commandClass
)
{
if( m_classGetSupported )
{
if( _commandClass->HasStaticRequest( StaticRequest_Version ) )
{
Msg* msg = new Msg( "VersionCmd_CommandClassGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
msg->Append( GetNodeId() );
msg->Append( 3 );
msg->Append( GetCommandClassId() );
msg->Append( VersionCmd_CommandClassGet );
msg->Append( _commandClass->GetCommandClassId() );
msg->Append( GetDriver()->GetTransmitOptions() );
GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
// <Version::CreateVars>
// Create the values managed by this command class
//-----------------------------------------------------------------------------
void Version::CreateVars
(
uint8 const _instance
)
{
if( Node* node = GetNodeUnsafe() )
{
node->CreateValueString( ValueID::ValueGenre_System, GetCommandClassId(), _instance, VersionIndex_Library, "Library Version", "", true, false, "Unknown", 0 );
node->CreateValueString( ValueID::ValueGenre_System, GetCommandClassId(), _instance, VersionIndex_Protocol, "Protocol Version", "", true, false, "Unknown", 0 );
node->CreateValueString( ValueID::ValueGenre_System, GetCommandClassId(), _instance, VersionIndex_Application, "Application Version", "", true, false, "Unknown", 0 );
}
}
Loaded 100 of 1030 files, more files were not shown because too many files have changed in this diff. Show more