1 //-----------------------------------------------------------------------------
2 //
3 // CommandClasses.cpp
4 //
5 // Singleton holding methods to create each command class object
6 //
7 // Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
8 //
9 // SOFTWARE NOTICE AND LICENSE
10 //
11 // This file is part of OpenZWave.
12 //
13 // OpenZWave is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU Lesser General Public License as published
15 // by the Free Software Foundation, either version 3 of the License,
16 // or (at your option) any later version.
17 //
18 // OpenZWave is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU Lesser General Public License for more details.
22 //
23 // You should have received a copy of the GNU Lesser General Public License
24 // along with OpenZWave. If not, see <http://www.gnu.org/licenses/>.
25 //
26 //-----------------------------------------------------------------------------
27
28 #include <string.h>
29
30 #include "command_classes/CommandClasses.h"
31
32 using namespace OpenZWave;
33
34 #include "command_classes/Alarm.h"
35 #include "command_classes/ApplicationStatus.h"
36 #include "command_classes/Association.h"
37 #include "command_classes/AssociationCommandConfiguration.h"
38 #include "command_classes/Basic.h"
39 #include "command_classes/BasicWindowCovering.h"
40 #include "command_classes/Battery.h"
41 #include "command_classes/CentralScene.h"
42 #include "command_classes/ClimateControlSchedule.h"
43 #include "command_classes/Clock.h"
44 #include "command_classes/Color.h"
45 #include "command_classes/Configuration.h"
46 #include "command_classes/ControllerReplication.h"
47 #include "command_classes/CRC16Encap.h"
48 #include "command_classes/DeviceResetLocally.h"
49 #include "command_classes/DoorLock.h"
50 #include "command_classes/DoorLockLogging.h"
51 #include "command_classes/EnergyProduction.h"
52 #include "command_classes/Hail.h"
53 #include "command_classes/Indicator.h"
54 #include "command_classes/Language.h"
55 #include "command_classes/Lock.h"
56 #include "command_classes/ManufacturerSpecific.h"
57 #include "command_classes/Meter.h"
58 #include "command_classes/MeterPulse.h"
59 #include "command_classes/MultiCmd.h"
60 #include "command_classes/MultiInstance.h"
61 #include "command_classes/MultiChannelAssociation.h"
62 #include "command_classes/NodeNaming.h"
63 #include "command_classes/NoOperation.h"
64 #include "command_classes/Powerlevel.h"
65 #include "command_classes/Proprietary.h"
66 #include "command_classes/Protection.h"
67 #include "command_classes/SceneActivation.h"
68 #include "command_classes/Security.h"
69 #include "command_classes/SensorAlarm.h"
70 #include "command_classes/SensorBinary.h"
71 #include "command_classes/SensorMultilevel.h"
72 #include "command_classes/SwitchAll.h"
73 #include "command_classes/SwitchBinary.h"
74 #include "command_classes/SwitchMultilevel.h"
75 #include "command_classes/SwitchToggleBinary.h"
76 #include "command_classes/SwitchToggleMultilevel.h"
77 #include "command_classes/TimeParameters.h"
78 #include "command_classes/ThermostatFanMode.h"
79 #include "command_classes/ThermostatFanState.h"
80 #include "command_classes/ThermostatMode.h"
81 #include "command_classes/ThermostatOperatingState.h"
82 #include "command_classes/ThermostatSetpoint.h"
83 #include "command_classes/UserCode.h"
84 #include "command_classes/Version.h"
85 #include "command_classes/WakeUp.h"
86 #include "command_classes/ZWavePlusInfo.h"
87
88 #include "value_classes/ValueBool.h"
89 #include "value_classes/ValueButton.h"
90 #include "value_classes/ValueByte.h"
91 #include "value_classes/ValueDecimal.h"
92 #include "value_classes/ValueInt.h"
93 #include "value_classes/ValueList.h"
94 #include "value_classes/ValueSchedule.h"
95 #include "value_classes/ValueShort.h"
96 #include "value_classes/ValueString.h"
97
98 #include "Manager.h"
99 #include "Options.h"
100 #include "Utils.h"
101
102 //-----------------------------------------------------------------------------
103 // <CommandClasses::CommandClasses>
104 // Constructor
105 //-----------------------------------------------------------------------------
CommandClasses()106 CommandClasses::CommandClasses
107 (
108 )
109 {
110 memset( m_commandClassCreators, 0, sizeof(pfnCreateCommandClass_t)*256 );
111 memset( m_supportedCommandClasses, 0, sizeof(uint32)*8 );
112 }
113
114 //-----------------------------------------------------------------------------
115 // <CommandClasses::IsSupported>
116 // Static method to determine whether a command class is supported
117 //-----------------------------------------------------------------------------
IsSupported(uint8 const _commandClassId)118 bool CommandClasses::IsSupported
119 (
120 uint8 const _commandClassId
121 )
122 {
123 // Test the bit representing the command class
124 return( (Get().m_supportedCommandClasses[_commandClassId>>5] & (1u<<(_commandClassId&0x1f))) != 0 );
125 }
GetName(uint8 const _commandClassId)126 string CommandClasses::GetName(
127 uint8 const _commandClassId
128 )
129 {
130 for (std::map<string,uint8>::iterator it = Get().m_namesToIDs.begin(); it != Get().m_namesToIDs.end(); it++) {
131 if (it->second == _commandClassId)
132 return it->first;
133 }
134 return string("Unknown");
135 }
136 //-----------------------------------------------------------------------------
137 // <CommandClasses::Register>
138 // Static method to register a command class creator method
139 //-----------------------------------------------------------------------------
Register(uint8 const _commandClassId,string const & _commandClassName,pfnCreateCommandClass_t _creator)140 void CommandClasses::Register
141 (
142 uint8 const _commandClassId,
143 string const& _commandClassName,
144 pfnCreateCommandClass_t _creator
145 )
146 {
147 m_commandClassCreators[_commandClassId] = _creator;
148
149 // Set the bit representing the command class
150 Get().m_supportedCommandClasses[_commandClassId>>5] |= (1u<<(_commandClassId&0x1f));
151
152 m_namesToIDs[_commandClassName] = _commandClassId;
153 }
154
155 //-----------------------------------------------------------------------------
156 // <CommandClasses::CreateCommandClass>
157 // Create a command class object using the registered method
158 //-----------------------------------------------------------------------------
CreateCommandClass(uint8 const _commandClassId,uint32 const _homeId,uint8 const _nodeId)159 CommandClass* CommandClasses::CreateCommandClass
160 (
161 uint8 const _commandClassId,
162 uint32 const _homeId,
163 uint8 const _nodeId
164 )
165 {
166 // Get a pointer to the required CommandClass's Create method
167 pfnCreateCommandClass_t creator = Get().m_commandClassCreators[_commandClassId];
168 if( NULL == creator )
169 {
170 return NULL;
171 }
172
173 // Create an instance of the command class
174 return creator( _homeId, _nodeId );
175 }
176
177 //-----------------------------------------------------------------------------
178 // <CommandClasses::RegisterCommandClasses>
179 // Register all our implemented command classes
180 //-----------------------------------------------------------------------------
RegisterCommandClasses()181 void CommandClasses::RegisterCommandClasses
182 (
183 )
184 {
185 CommandClasses& cc = Get();
186 cc.Register( Alarm::StaticGetCommandClassId(), Alarm::StaticGetCommandClassName(), Alarm::Create );
187 cc.Register( ApplicationStatus::StaticGetCommandClassId(), ApplicationStatus::StaticGetCommandClassName(), ApplicationStatus::Create );
188 cc.Register( Association::StaticGetCommandClassId(), Association::StaticGetCommandClassName(), Association::Create );
189 cc.Register( AssociationCommandConfiguration::StaticGetCommandClassId(), AssociationCommandConfiguration::StaticGetCommandClassName(), AssociationCommandConfiguration::Create );
190 cc.Register( Basic::StaticGetCommandClassId(), Basic::StaticGetCommandClassName(), Basic::Create );
191 cc.Register( BasicWindowCovering::StaticGetCommandClassId(), BasicWindowCovering::StaticGetCommandClassName(), BasicWindowCovering::Create );
192 cc.Register( Battery::StaticGetCommandClassId(), Battery::StaticGetCommandClassName(), Battery::Create );
193 cc.Register( CentralScene::StaticGetCommandClassId(), CentralScene::StaticGetCommandClassName(), CentralScene::Create );
194 cc.Register( ClimateControlSchedule::StaticGetCommandClassId(), ClimateControlSchedule::StaticGetCommandClassName(), ClimateControlSchedule::Create );
195 cc.Register( Clock::StaticGetCommandClassId(), Clock::StaticGetCommandClassName(), Clock::Create );
196 cc.Register( Color::StaticGetCommandClassId(), Color::StaticGetCommandClassName(), Color::Create );
197 cc.Register( Configuration::StaticGetCommandClassId(), Configuration::StaticGetCommandClassName(), Configuration::Create );
198 cc.Register( ControllerReplication::StaticGetCommandClassId(), ControllerReplication::StaticGetCommandClassName(), ControllerReplication::Create );
199 cc.Register( CRC16Encap::StaticGetCommandClassId(), CRC16Encap::StaticGetCommandClassName(), CRC16Encap::Create );
200 cc.Register( DeviceResetLocally::StaticGetCommandClassId(), DeviceResetLocally::StaticGetCommandClassName(), DeviceResetLocally::Create );
201 cc.Register( DoorLock::StaticGetCommandClassId(), DoorLock::StaticGetCommandClassName(), DoorLock::Create );
202 cc.Register( DoorLockLogging::StaticGetCommandClassId(), DoorLockLogging::StaticGetCommandClassName(), DoorLockLogging::Create);
203 cc.Register( EnergyProduction::StaticGetCommandClassId(), EnergyProduction::StaticGetCommandClassName(), EnergyProduction::Create );
204 cc.Register( Hail::StaticGetCommandClassId(), Hail::StaticGetCommandClassName(), Hail::Create );
205 cc.Register( Indicator::StaticGetCommandClassId(), Indicator::StaticGetCommandClassName(), Indicator::Create );
206 cc.Register( Language::StaticGetCommandClassId(), Language::StaticGetCommandClassName(), Language::Create );
207 cc.Register( Lock::StaticGetCommandClassId(), Lock::StaticGetCommandClassName(), Lock::Create );
208 cc.Register( ManufacturerSpecific::StaticGetCommandClassId(), ManufacturerSpecific::StaticGetCommandClassName(), ManufacturerSpecific::Create );
209 cc.Register( Meter::StaticGetCommandClassId(), Meter::StaticGetCommandClassName(), Meter::Create );
210 cc.Register( MeterPulse::StaticGetCommandClassId(), MeterPulse::StaticGetCommandClassName(), MeterPulse::Create );
211 cc.Register( MultiCmd::StaticGetCommandClassId(), MultiCmd::StaticGetCommandClassName(), MultiCmd::Create );
212 cc.Register( MultiInstance::StaticGetCommandClassId(), MultiInstance::StaticGetCommandClassName(), MultiInstance::Create );
213 cc.Register( MultiChannelAssociation::StaticGetCommandClassId(), MultiChannelAssociation::StaticGetCommandClassName(), MultiChannelAssociation::Create );
214 cc.Register( NodeNaming::StaticGetCommandClassId(), NodeNaming::StaticGetCommandClassName(), NodeNaming::Create );
215 cc.Register( NoOperation::StaticGetCommandClassId(), NoOperation::StaticGetCommandClassName(), NoOperation::Create );
216 cc.Register( Powerlevel::StaticGetCommandClassId(), Powerlevel::StaticGetCommandClassName(), Powerlevel::Create );
217 cc.Register( Proprietary::StaticGetCommandClassId(), Proprietary::StaticGetCommandClassName(), Proprietary::Create );
218 cc.Register( Protection::StaticGetCommandClassId(), Protection::StaticGetCommandClassName(), Protection::Create );
219 cc.Register( SceneActivation::StaticGetCommandClassId(), SceneActivation::StaticGetCommandClassName(), SceneActivation::Create );
220 cc.Register( Security::StaticGetCommandClassId(), Security::StaticGetCommandClassName(), Security::Create);
221 cc.Register( SensorAlarm::StaticGetCommandClassId(), SensorAlarm::StaticGetCommandClassName(), SensorAlarm::Create );
222 cc.Register( SensorBinary::StaticGetCommandClassId(), SensorBinary::StaticGetCommandClassName(), SensorBinary::Create );
223 cc.Register( SensorMultilevel::StaticGetCommandClassId(), SensorMultilevel::StaticGetCommandClassName(), SensorMultilevel::Create );
224 cc.Register( SwitchAll::StaticGetCommandClassId(), SwitchAll::StaticGetCommandClassName(), SwitchAll::Create );
225 cc.Register( SwitchBinary::StaticGetCommandClassId(), SwitchBinary::StaticGetCommandClassName(), SwitchBinary::Create );
226 cc.Register( SwitchMultilevel::StaticGetCommandClassId(), SwitchMultilevel::StaticGetCommandClassName(), SwitchMultilevel::Create );
227 cc.Register( SwitchToggleBinary::StaticGetCommandClassId(), SwitchToggleBinary::StaticGetCommandClassName(), SwitchToggleBinary::Create );
228 cc.Register( SwitchToggleMultilevel::StaticGetCommandClassId(), SwitchToggleMultilevel::StaticGetCommandClassName(), SwitchToggleMultilevel::Create );
229 cc.Register( TimeParameters::StaticGetCommandClassId(), TimeParameters::StaticGetCommandClassName(), TimeParameters::Create);
230 cc.Register( ThermostatFanMode::StaticGetCommandClassId(), ThermostatFanMode::StaticGetCommandClassName(), ThermostatFanMode::Create );
231 cc.Register( ThermostatFanState::StaticGetCommandClassId(), ThermostatFanState::StaticGetCommandClassName(), ThermostatFanState::Create );
232 cc.Register( ThermostatMode::StaticGetCommandClassId(), ThermostatMode::StaticGetCommandClassName(), ThermostatMode::Create );
233 cc.Register( ThermostatOperatingState::StaticGetCommandClassId(), ThermostatOperatingState::StaticGetCommandClassName(), ThermostatOperatingState::Create );
234 cc.Register( ThermostatSetpoint::StaticGetCommandClassId(), ThermostatSetpoint::StaticGetCommandClassName(), ThermostatSetpoint::Create );
235 cc.Register( UserCode::StaticGetCommandClassId(), UserCode::StaticGetCommandClassName(), UserCode::Create );
236 cc.Register( Version::StaticGetCommandClassId(), Version::StaticGetCommandClassName(), Version::Create );
237 cc.Register( WakeUp::StaticGetCommandClassId(), WakeUp::StaticGetCommandClassName(), WakeUp::Create );
238 cc.Register( ZWavePlusInfo::StaticGetCommandClassId(), ZWavePlusInfo::StaticGetCommandClassName(), ZWavePlusInfo::Create );
239
240 // Now all the command classes have been registered, we can modify the
241 // supported command classes array according to the program options.
242 string str;
243 Options::Get()->GetOptionAsString( "Include", &str );
244 if( str != "" )
245 {
246 // The include list has entries, so we assume that it is a
247 // complete list of what should be supported.
248 // Any existing support is cleared first.
249 memset( cc.m_supportedCommandClasses, 0, sizeof(uint32)*8 );
250 cc.ParseCommandClassOption( str, true );
251 }
252
253 // Apply the excluded command class option
254 Options::Get()->GetOptionAsString( "Exclude", &str );
255 if( str != "" )
256 {
257 cc.ParseCommandClassOption( str, false );
258 }
259 }
260
261 //-----------------------------------------------------------------------------
262 // <CommandClasses::ParseCommandClassOption>
263 // Parse a comma delimited list of included/excluded command classes
264 //-----------------------------------------------------------------------------
ParseCommandClassOption(string const & _optionStr,bool const _include)265 void CommandClasses::ParseCommandClassOption
266 (
267 string const& _optionStr,
268 bool const _include
269 )
270 {
271 size_t pos = 0;
272 size_t start = 0;
273 bool parsing = true;
274 while( parsing )
275 {
276 string ccStr;
277
278 pos = _optionStr.find_first_of( ",", start );
279 if( string::npos == pos )
280 {
281 ccStr = _optionStr.substr( start );
282 parsing = false;
283 }
284 else
285 {
286 ccStr = _optionStr.substr( start, pos-start );
287 start = pos + 1;
288 }
289
290 if( ccStr != "" )
291 {
292 uint8 ccIdx = GetCommandClassId( ccStr );
293 if( _include )
294 {
295 m_supportedCommandClasses[ccIdx>>5] |= (1u<<(ccIdx&0x1f));
296 }
297 else
298 {
299 m_supportedCommandClasses[ccIdx>>5] &= ~(1u<<(ccIdx&0x1f));
300 }
301 }
302 }
303 }
304
305 //-----------------------------------------------------------------------------
306 // <CommandClasses::GetCommandClassId>
307 // Convert a command class name (e.g COMMAND_CLASS_BASIC) into its 8-bit ID
308 //-----------------------------------------------------------------------------
GetCommandClassId(string const & _name)309 uint8 CommandClasses::GetCommandClassId
310 (
311 string const& _name
312 )
313 {
314 string upperName = ToUpper( _name );
315 map<string,uint8>::iterator it = m_namesToIDs.find( upperName );
316 if( it != m_namesToIDs.end() )
317 {
318 return it->second;
319 }
320
321 return 0xff;
322 }
323
324
325