update esppilight lib
content of the library is not filtered on 433mhz only
This commit is contained in:
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
|
||||
|
||||
+281
@@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
+70
@@ -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
Reference in new issue
Block a user