//----------------------------------------------------------------------------- // // Version.cpp // // Implementation of the Z-Wave COMMAND_CLASS_VERSION // // Copyright (c) 2010 Mal Lansell // // 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 . // //----------------------------------------------------------------------------- #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 }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- Version::Version ( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ), m_classGetSupported( true ) { SetStaticRequest( StaticRequest_Values ); } //----------------------------------------------------------------------------- // // Read configuration. //----------------------------------------------------------------------------- void Version::ReadXML ( TiXmlElement const* _ccElement ) { CommandClass::ReadXML( _ccElement ); char const* str = _ccElement->Attribute("classgetsupported"); if( str ) { m_classGetSupported = !strcmp( str, "true"); } } //----------------------------------------------------------------------------- // // Save changed configuration //----------------------------------------------------------------------------- void Version::WriteXML ( TiXmlElement* _ccElement ) { CommandClass::WriteXML( _ccElement ); if( !m_classGetSupported ) { _ccElement->SetAttribute( "classgetsupported", "false" ); } } //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // 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( GetValue( _instance, VersionIndex_Library ) ) ) { libraryValue->OnValueRefreshed( library ); libraryValue->Release(); } if( ValueString* protocolValue = static_cast( GetValue( _instance, VersionIndex_Protocol ) ) ) { protocolValue->OnValueRefreshed( protocol ); protocolValue->Release(); } if( ValueString* applicationValue = static_cast( 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; } //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // 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 ); } }