1 //-----------------------------------------------------------------------------
2 //
3 //	Node.cpp
4 //
5 //	A node in the Z-Wave network.
6 //
7 //	Copyright (c) 2009 Mal Lansell <xpl@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 by
15 //	the Free Software Foundation, either version 3 of the License, or
16 //	(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 <iomanip>
29 
30 
31 #include "Node.h"
32 #include "Defs.h"
33 #include "Group.h"
34 #include "Options.h"
35 #include "Manager.h"
36 #include "Driver.h"
37 #include "Notification.h"
38 #include "Msg.h"
39 #include "ZWSecurity.h"
40 #include "platform/Log.h"
41 #include "platform/Mutex.h"
42 #include "Utils.h"
43 
44 #include "tinyxml.h"
45 
46 #include "command_classes/CommandClasses.h"
47 #include "command_classes/CommandClass.h"
48 #include "command_classes/Association.h"
49 #include "command_classes/Basic.h"
50 #include "command_classes/Configuration.h"
51 #include "command_classes/ControllerReplication.h"
52 #include "command_classes/ManufacturerSpecific.h"
53 #include "command_classes/MultiInstance.h"
54 #include "command_classes/MultiChannelAssociation.h"
55 #include "command_classes/Security.h"
56 #include "command_classes/WakeUp.h"
57 #include "command_classes/NodeNaming.h"
58 #include "command_classes/NoOperation.h"
59 #include "command_classes/Version.h"
60 #include "command_classes/SwitchAll.h"
61 #include "command_classes/ZWavePlusInfo.h"
62 #include "command_classes/DeviceResetLocally.h"
63 
64 #include "Scene.h"
65 
66 #include "value_classes/ValueID.h"
67 #include "value_classes/Value.h"
68 #include "value_classes/ValueBool.h"
69 #include "value_classes/ValueButton.h"
70 #include "value_classes/ValueByte.h"
71 #include "value_classes/ValueDecimal.h"
72 #include "value_classes/ValueInt.h"
73 #include "value_classes/ValueRaw.h"
74 #include "value_classes/ValueList.h"
75 #include "value_classes/ValueSchedule.h"
76 #include "value_classes/ValueShort.h"
77 #include "value_classes/ValueString.h"
78 #include "value_classes/ValueStore.h"
79 
80 using namespace OpenZWave;
81 
82 //-----------------------------------------------------------------------------
83 // Statics
84 //-----------------------------------------------------------------------------
85 bool Node::s_deviceClassesLoaded = false;
86 map<uint8,string> Node::s_basicDeviceClasses;
87 map<uint8,Node::GenericDeviceClass*> Node::s_genericDeviceClasses;
88 map<uint8,Node::DeviceClass*> Node::s_roleDeviceClasses;
89 map<uint16,Node::DeviceClass*> Node::s_deviceTypeClasses;
90 map<uint8,Node::DeviceClass*> Node::s_nodeTypes;
91 
92 static char const* c_queryStageNames[] =
93 {
94 		"None",
95 		"ProtocolInfo",
96 		"Probe",
97 		"WakeUp",
98 		"ManufacturerSpecific1",
99 		"NodeInfo",
100 		"NodePlusInfo",
101 		"SecurityReport",
102 		"ManufacturerSpecific2",
103 		"Versions",
104 		"Instances",
105 		"Static",
106 		"CacheLoad",
107 		"Associations",
108 		"Neighbors",
109 		"Session",
110 		"Dynamic",
111 		"Configuration",
112 		"Complete"
113 };
114 
115 //-----------------------------------------------------------------------------
116 // <Node::Node>
117 // Constructor
118 //-----------------------------------------------------------------------------
Node(uint32 const _homeId,uint8 const _nodeId)119 Node::Node
120 (
121 		uint32 const _homeId,
122 		uint8 const _nodeId
123 ):
124 m_queryStage( QueryStage_None ),
125 m_queryPending( false ),
126 m_queryConfiguration( false ),
127 m_queryRetries( 0 ),
128 m_protocolInfoReceived( false ),
129 m_basicprotocolInfoReceived( false ),
130 m_nodeInfoReceived( false ),
131 m_nodePlusInfoReceived( false ),
132 m_manufacturerSpecificClassReceived( false ),
133 m_nodeInfoSupported( true ),
134 m_refreshonNodeInfoFrame ( true ),
135 m_nodeAlive( true ),	// assome live node
136 m_listening( true ),	// assume we start out listening
137 m_frequentListening( false ),
138 m_beaming( false ),
139 m_routing( false ),
140 m_maxBaudRate( 0 ),
141 m_version( 0 ),
142 m_security( false ),
143 m_homeId( _homeId ),
144 m_nodeId( _nodeId ),
145 m_basic( 0 ),
146 m_generic( 0 ),
147 m_specific( 0 ),
148 m_type( "" ),
149 m_numRouteNodes( 0 ),
150 m_addingNode( false ),
151 m_manufacturerName( "" ),
152 m_productName( "" ),
153 m_nodeName( "" ),
154 m_location( "" ),
155 m_manufacturerId( 0 ),
156 m_productType( 0 ),
157 m_productId( 0 ),
158 m_deviceType( 0 ),
159 m_role( 0 ),
160 m_nodeType ( 0 ),
161 m_secured ( false ),
162 m_values( new ValueStore() ),
163 m_sentCnt( 0 ),
164 m_sentFailed( 0 ),
165 m_retries( 0 ),
166 m_receivedCnt( 0 ),
167 m_receivedDups( 0 ),
168 m_receivedUnsolicited( 0 ),
169 m_lastRequestRTT( 0 ),
170 m_lastResponseRTT( 0 ),
171 m_averageRequestRTT( 0 ),
172 m_averageResponseRTT( 0 ),
173 m_quality( 0 ),
174 m_lastReceivedMessage(),
175 m_errors( 0 ),
176 m_lastnonce ( 0 )
177 {
178 	memset( m_neighbors, 0, sizeof(m_neighbors) );
179 	memset( m_routeNodes, 0, sizeof(m_routeNodes) );
180 	memset( m_nonces, 0, sizeof(m_nonces) );
181 	AddCommandClass( 0 );
182 }
183 
184 //-----------------------------------------------------------------------------
185 // <Node::~Node>
186 // Destructor
187 //-----------------------------------------------------------------------------
~Node()188 Node::~Node
189 (
190 )
191 {
192 	// Remove any messages from queues
193 	GetDriver()->RemoveQueues( m_nodeId );
194 
195 	// Remove the values from the poll list
196 	for( ValueStore::Iterator it = m_values->Begin(); it != m_values->End(); ++it )
197 	{
198 		ValueID const& valueId = it->second->GetID();
199 		if( GetDriver()->isPolled( valueId ) )
200 		{
201 			GetDriver()->DisablePoll( valueId );
202 		}
203 	}
204 
205 	Scene::RemoveValues( m_homeId, m_nodeId );
206 
207 	// Delete the values
208 	delete m_values;
209 
210 	// Delete the command classes
211 	while( !m_commandClassMap.empty() )
212 	{
213 		map<uint8,CommandClass*>::iterator it = m_commandClassMap.begin();
214 		delete it->second;
215 		m_commandClassMap.erase( it );
216 	}
217 
218 	// Delete the groups
219 	while( !m_groups.empty() )
220 	{
221 		map<uint8,Group*>::iterator it = m_groups.begin();
222 		delete it->second;
223 		m_groups.erase( it );
224 	}
225 
226 	// Delete the button map
227 	while( !m_buttonMap.empty() )
228 	{
229 		map<uint8,uint8>::iterator it = m_buttonMap.begin();
230 		m_buttonMap.erase( it );
231 	}
232 }
233 
234 //-----------------------------------------------------------------------------
235 // <Node::AdvanceQueries>
236 // Proceed through the initialisation process
237 //-----------------------------------------------------------------------------
AdvanceQueries()238 void Node::AdvanceQueries
239 (
240 )
241 {
242 	// For OpenZWave to discover everything about a node, we have to follow a certain
243 	// order of queries, because the results of one stage may affect what is requested
244 	// in the next stage.  The stage is saved with the node data, so that any incomplete
245 	// queries can be restarted the next time the application runs.
246 	// The individual command classes also store some state as to whether they have
247 	// had a response to certain queries.  This state is initilized by the SetStaticRequests
248 	// call in QueryStage_None.  It is also saved, so we do not need to request state
249 	// from every command class if some have previously responded.
250 	//
251 	// Each stage must generate all the messages for its particular	stage as
252 	// assumptions are made in later code (RemoveMsg) that this is the case. This means
253 	// each stage is only visited once.
254 
255 	Log::Write( LogLevel_Detail, m_nodeId, "AdvanceQueries queryPending=%d queryRetries=%d queryStage=%s live=%d", m_queryPending, m_queryRetries, c_queryStageNames[m_queryStage], m_nodeAlive );
256 	bool addQSC = false;			// We only want to add a query stage complete if we did some work.
257 	while( !m_queryPending && m_nodeAlive )
258 	{
259 		switch( m_queryStage )
260 		{
261 			case QueryStage_None:
262 			{
263 				// Init the node query process
264 				m_queryStage = QueryStage_ProtocolInfo;
265 				m_queryRetries = 0;
266 				break;
267 			}
268 			case QueryStage_ProtocolInfo:
269 			{
270 				// determines, among other things, whether this node is a listener, its maximum baud rate and its device classes
271 				if( !ProtocolInfoReceived() )
272 				{
273 					Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_ProtocolInfo" );
274 					Msg* msg = new Msg( "Get Node Protocol Info", m_nodeId, REQUEST, FUNC_ID_ZW_GET_NODE_PROTOCOL_INFO, false );
275 					msg->Append( m_nodeId );
276 					GetDriver()->SendMsg( msg, Driver::MsgQueue_Query );
277 					m_queryPending = true;
278 					addQSC = true;
279 				}
280 				else
281 				{
282 					// This stage has been done already, so move to the Neighbours stage
283 					m_queryStage = QueryStage_Probe;
284 					m_queryRetries = 0;
285 				}
286 				break;
287 			}
288 			case QueryStage_Probe:
289 			{
290 				Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_Probe" );
291 				//
292 				// Send a NoOperation message to see if the node is awake
293 				// and alive. Based on the response or lack of response
294 				// will determine next step.
295 				//
296 				NoOperation* noop = static_cast<NoOperation*>( GetCommandClass( NoOperation::StaticGetCommandClassId() ) );
297 				/* don't Probe the Controller */
298 				if( GetDriver()->GetControllerNodeId() != m_nodeId )
299 				{
300 					noop->Set( true );
301 					m_queryPending = true;
302 					addQSC = true;
303 				}
304 				else
305 				{
306 					m_queryStage = QueryStage_WakeUp;
307 					m_queryRetries = 0;
308 				}
309 				break;
310 			}
311 			case QueryStage_WakeUp:
312 			{
313 				// For sleeping devices other than controllers, we need to defer the usual requests until
314 				// we have told the device to send it's wake-up notifications to the PC controller.
315 				Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_WakeUp" );
316 
317 				WakeUp* wakeUp = static_cast<WakeUp*>( GetCommandClass( WakeUp::StaticGetCommandClassId() ) );
318 
319 				// if this device is a "sleeping device" and not a controller and not a
320 				// FLiRS device. FLiRS will wake up when you send them something and they
321 				// don't seem to support Wakeup
322 				if( wakeUp && !IsController() && !IsFrequentListeningDevice() )
323 				{
324 					// start the process of requesting node state from this sleeping device
325 					wakeUp->Init();
326 					m_queryPending = true;
327 					addQSC = true;
328 				}
329 				else
330 				{
331 					// this is not a sleeping device, so move to the ManufacturerSpecific1 stage
332 					m_queryStage = QueryStage_ManufacturerSpecific1;
333 					m_queryRetries = 0;
334 				}
335 				break;
336 			}
337 			case QueryStage_ManufacturerSpecific1:
338 			{
339 				// Obtain manufacturer, product type and product ID code from the node device
340 				// Manufacturer Specific data is requested before the other command class data so
341 				// that we can modify the supported command classes list through the product XML files.
342 				Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_ManufacturerSpecific1" );
343 
344 				/* if its the Controller, then we can just load up the XML straight away */
345 				if( GetDriver()->GetControllerNodeId() == m_nodeId )
346 				{
347 					Log::Write( LogLevel_Detail, m_nodeId, "Load Controller Manufacturer Specific Config");
348 					string configPath = ManufacturerSpecific::SetProductDetails( this, GetDriver()->GetManufacturerId(), GetDriver()->GetProductType(), GetDriver()->GetProductId() );
349 					if( configPath.length() > 0 )
350 					{
351 						ManufacturerSpecific::LoadConfigXML( this, configPath );
352 					}
353 					m_queryStage = QueryStage_NodeInfo;
354 					m_queryRetries = 0;
355 				}
356 				else
357 				{
358 					Log::Write( LogLevel_Detail, m_nodeId, "Checking for ManufacturerSpecific CC and Requesting values if present on this node");
359 					/* if the ManufacturerSpecific CC was not specified in the ProtocolInfo packet for the Generic/Specific Device type (as part a Mandatory Command Class)
360 					 * then this will fail, but we will retry in ManufacturerSpecific2
361 					 *
362 					 * XXX TODO: This could probably be reworked a bit to make this a Mandatory CC for all devices regardless
363 					 * of Generic/Specific Type. Then we can drop the Second ManufacturerSpecific QueryStage later.
364 					 */
365 					ManufacturerSpecific* cc = static_cast<ManufacturerSpecific*>( GetCommandClass( ManufacturerSpecific::StaticGetCommandClassId() ) );
366 					if( cc  )
367 					{
368 						m_queryPending = cc->RequestState( CommandClass::RequestFlag_Static, 1, Driver::MsgQueue_Query );
369 						addQSC = m_queryPending;
370 					}
371 					if( !m_queryPending )
372 					{
373 						m_queryStage = QueryStage_NodeInfo;
374 						m_queryRetries = 0;
375 					}
376 				}
377 				break;
378 			}
379 			case QueryStage_NodeInfo:
380 			{
381 				if( !NodeInfoReceived() && m_nodeInfoSupported && (GetDriver()->GetControllerNodeId() != m_nodeId))
382 				{
383 					// obtain from the node a list of command classes that it 1) supports and 2) controls (separated by a mark in the buffer)
384 					Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_NodeInfo" );
385 					Msg* msg = new Msg( "Request Node Info", m_nodeId, REQUEST, FUNC_ID_ZW_REQUEST_NODE_INFO, false, true, FUNC_ID_ZW_APPLICATION_UPDATE );
386 					msg->Append( m_nodeId );
387 					GetDriver()->SendMsg( msg, Driver::MsgQueue_Query );
388 					m_queryPending = true;
389 					addQSC = true;
390 				}
391 				else
392 				{
393 					// This stage has been done already, so move to the Manufacturer Specific stage
394 					m_queryStage = QueryStage_NodePlusInfo;
395 					m_queryRetries = 0;
396 				}
397 				break;
398 			}
399 			case QueryStage_NodePlusInfo:
400 			{
401 				Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_NodePlusInfo" );
402 				ZWavePlusInfo* pluscc = static_cast<ZWavePlusInfo*>( GetCommandClass( ZWavePlusInfo::StaticGetCommandClassId() ) );
403 
404 				if ( pluscc )
405 				{
406 					m_queryPending = pluscc->RequestState( CommandClass::RequestFlag_Static, 1, Driver::MsgQueue_Query );
407 				}
408 				if (m_queryPending)
409 				{
410 					addQSC = m_queryPending;
411 				}
412 				else
413 				{
414 					// this is not a Zwave+ node, so move onto the next querystage
415 					m_queryStage = QueryStage_SecurityReport;
416 					m_queryRetries = 0;
417 				}
418 
419 				break;
420 			}
421 			case QueryStage_SecurityReport:
422 			{
423 				/* For Devices that Support the Security Class, we have to request a list of
424 				 * Command Classes that Require Security.
425 				 */
426 				Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_SecurityReport" );
427 
428 				Security* seccc = static_cast<Security*>( GetCommandClass( Security::StaticGetCommandClassId() ) );
429 
430 				if( seccc )
431 				{
432 					// start the process setting up the Security CommandClass
433 					m_queryPending = seccc->Init();
434 					/* Dont add a QueryStageComplete flag here, as this is a multipacket exchange.
435 					 * the Security Command Class will automatically advance the Query Stage
436 					 * when we recieve a SecurityCmd_SupportedReport
437 					 */
438 					addQSC = true;
439 				}
440 				else
441 				{
442 					// this is not a Security Device, so move onto the next querystage
443 					m_queryStage = QueryStage_ManufacturerSpecific2;
444 					m_queryRetries = 0;
445 				}
446 
447 				break;
448 			}
449 			case QueryStage_ManufacturerSpecific2:
450 			{
451 				if( !m_manufacturerSpecificClassReceived )
452 				{
453 					// Obtain manufacturer, product type and product ID code from the node device
454 					// Manufacturer Specific data is requested before the other command class data so
455 					// that we can modify the supported command classes list through the product XML files.
456 					Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_ManufacturerSpecific2" );
457 					ManufacturerSpecific* cc = static_cast<ManufacturerSpecific*>( GetCommandClass( ManufacturerSpecific::StaticGetCommandClassId() ) );
458 					if( cc  )
459 					{
460 						m_queryPending = cc->RequestState( CommandClass::RequestFlag_Static, 1, Driver::MsgQueue_Query );
461 						addQSC = m_queryPending;
462 					}
463 					if( !m_queryPending )
464 					{
465 						m_queryStage = QueryStage_Versions;
466 						m_queryRetries = 0;
467 					}
468 				}
469 				else
470 				{
471 					ManufacturerSpecific* cc = static_cast<ManufacturerSpecific*>( GetCommandClass( ManufacturerSpecific::StaticGetCommandClassId() ) );
472 					if( cc  )
473 					{
474 						cc->ReLoadConfigXML();
475 					}
476 					m_queryStage = QueryStage_Versions;
477 					m_queryRetries = 0;
478 				}
479 				break;
480 			}
481 			case QueryStage_Versions:
482 			{
483 				// Get the version information (if the device supports COMMAND_CLASS_VERSION
484 				Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_Versions" );
485 				Version* vcc = static_cast<Version*>( GetCommandClass( Version::StaticGetCommandClassId() ) );
486 				if( vcc )
487 				{
488 					Log::Write(LogLevel_Info, m_nodeId, "Requesting Versions");
489 					for( map<uint8,CommandClass*>::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it )
490 					{
491 						CommandClass* cc = it->second;
492 						Log::Write(LogLevel_Info, m_nodeId, "Requesting Versions for %s", cc->GetCommandClassName().c_str());
493 
494 						if( cc->GetMaxVersion() > 1 )
495 						{
496 							Log::Write(LogLevel_Info, m_nodeId, "	ok");
497 							// Get the version for each supported command class that
498 							// we have implemented at greater than version one.
499 							m_queryPending |= vcc->RequestCommandClassVersion( it->second );
500 						}
501 					}
502 					addQSC = m_queryPending;
503 				}
504 				// advance to Instances stage when finished
505 				if( !m_queryPending )
506 				{
507 					m_queryStage = QueryStage_Instances;
508 					m_queryRetries = 0;
509 				}
510 				break;
511 			}
512 			case QueryStage_Instances:
513 			{
514 				// if the device at this node supports multiple instances, obtain a list of these instances
515 				Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_Instances" );
516 				MultiInstance* micc = static_cast<MultiInstance*>( GetCommandClass( MultiInstance::StaticGetCommandClassId() ) );
517 				if( micc )
518 				{
519 					m_queryPending = micc->RequestInstances();
520 					addQSC = m_queryPending;
521 				}
522 
523 				// when done, advance to the Static stage
524 				if( !m_queryPending )
525 				{
526 					m_queryStage = QueryStage_Static;
527 					m_queryRetries = 0;
528 
529 					Log::Write( LogLevel_Info, m_nodeId, "Essential node queries are complete" );
530 					Notification* notification = new Notification( Notification::Type_EssentialNodeQueriesComplete );
531 					notification->SetHomeAndNodeIds( m_homeId, m_nodeId );
532 					GetDriver()->QueueNotification( notification );
533 				}
534 				break;
535 			}
536 			case QueryStage_Static:
537 			{
538 				// Request any other static values associated with each command class supported by this node
539 				// examples are supported thermostat operating modes, setpoints and fan modes
540 				Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_Static" );
541 				for( map<uint8,CommandClass*>::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it )
542 				{
543 					if( !it->second->IsAfterMark() )
544 					{
545 						m_queryPending |= it->second->RequestStateForAllInstances( CommandClass::RequestFlag_Static, Driver::MsgQueue_Query );
546 					} else {
547 						/* Controlling CC's might still need to retrieve some info */
548 						m_queryPending |= it->second->RequestStateForAllInstances( CommandClass::RequestFlag_AfterMark, Driver::MsgQueue_Query );
549 					}
550 				}
551 				addQSC = m_queryPending;
552 
553 				if( !m_queryPending )
554 				{
555 					// when all (if any) static information has been retrieved, advance to the Associations stage
556 					// CacheLoad stage is for Nodes that are read in via the zw state file, as is skipped as we would
557 					// have already queried it at the discovery phase in Probe.
558 					m_queryStage = QueryStage_Associations;
559 					m_queryRetries = 0;
560 				}
561 				break;
562 			}
563 			/* CacheLoad is where we start if we are loading a device from our zwcfg_*.xml file rather than
564 			 * a brand new device.
565 			 */
566 			case QueryStage_CacheLoad:
567 			{
568 				Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_CacheLoad" );
569 				Log::Write( LogLevel_Info, GetNodeId(), "Node Identity Codes: %.4x:%.4x:%.4x", GetManufacturerId(), GetProductType(), GetProductId() );
570 				//
571 				// Send a NoOperation message to see if the node is awake
572 				// and alive. Based on the response or lack of response
573 				// will determine next step. Called here when configuration exists.
574 				//
575 				NoOperation* noop = static_cast<NoOperation*>( GetCommandClass( NoOperation::StaticGetCommandClassId() ) );
576 				/* Don't do this if its to the Controller */
577 				if( GetDriver()->GetControllerNodeId() != m_nodeId )
578 				{
579 					noop->Set( true );
580 					m_queryPending = true;
581 					addQSC = true;
582 				}
583 				else
584 				{
585 					m_queryStage = QueryStage_Associations;
586 					m_queryRetries = 0;
587 				}
588 				break;
589 			}
590 			case QueryStage_Associations:
591 			{
592 				// if this device supports COMMAND_CLASS_ASSOCIATION, determine to which groups this node belong
593 				Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_Associations" );
594 				MultiChannelAssociation* macc = static_cast<MultiChannelAssociation*>( GetCommandClass( MultiChannelAssociation::StaticGetCommandClassId() ) );
595 				if( macc )
596 				{
597 					macc->RequestAllGroups( 0 );
598 					m_queryPending = true;
599 					addQSC = true;
600 				}
601 				else
602 				{
603 					Association* acc = static_cast<Association*>( GetCommandClass( Association::StaticGetCommandClassId() ) );
604 					if( acc )
605 					{
606 						acc->RequestAllGroups( 0 );
607 						m_queryPending = true;
608 						addQSC = true;
609 					}
610 					else
611 					{
612 						// if this device doesn't support Associations, move to retrieve Session information
613 						m_queryStage = QueryStage_Neighbors;
614 						m_queryRetries = 0;
615 					}
616 				}
617 				break;
618 			}
619 			case QueryStage_Neighbors:
620 			{
621 				// retrieves this node's neighbors and stores the neighbor bitmap in the node object
622 				Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_Neighbors" );
623 				GetDriver()->RequestNodeNeighbors( m_nodeId, 0 );
624 				m_queryPending = true;
625 				addQSC = true;
626 				break;
627 			}
628 			case QueryStage_Session:
629 			{
630 				// Request the session values from the command classes in turn
631 				// examples of Session information are: current thermostat setpoints, node names and climate control schedules
632 				Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_Session" );
633 				for( map<uint8,CommandClass*>::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it )
634 				{
635 					if( !it->second->IsAfterMark() )
636 					{
637 						m_queryPending |= it->second->RequestStateForAllInstances( CommandClass::RequestFlag_Session, Driver::MsgQueue_Query );
638 					}
639 				}
640 				addQSC = m_queryPending;
641 				if( !m_queryPending )
642 				{
643 					m_queryStage = QueryStage_Dynamic;
644 					m_queryRetries = 0;
645 				}
646 				break;
647 			}
648 			case QueryStage_Dynamic:
649 			{
650 				// Request the dynamic values from the node, that can change at any time
651 				// Examples include on/off state, heating mode, temperature, etc.
652 				Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_Dynamic" );
653 				m_queryPending = RequestDynamicValues();
654 				addQSC = m_queryPending;
655 
656 				if( !m_queryPending )
657 				{
658 					m_queryStage = QueryStage_Configuration;
659 					m_queryRetries = 0;
660 				}
661 				break;
662 			}
663 			case QueryStage_Configuration:
664 			{
665 				// Request the configurable parameter values from the node.
666 				Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_Configuration" );
667 				if( m_queryConfiguration )
668 				{
669 					if( RequestAllConfigParams( 0 ) )
670 					{
671 						m_queryPending = true;
672 						addQSC = true;
673 					}
674 					m_queryConfiguration = false;
675 				}
676 				if( !m_queryPending )
677 				{
678 					m_queryStage = QueryStage_Complete;
679 					m_queryRetries = 0;
680 				}
681 				break;
682 			}
683 			case QueryStage_Complete:
684 			{
685 				ClearAddingNode();
686 				// Notify the watchers that the queries are complete for this node
687 				Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_Complete" );
688 				Notification* notification = new Notification( Notification::Type_NodeQueriesComplete );
689 				notification->SetHomeAndNodeIds( m_homeId, m_nodeId );
690 				GetDriver()->QueueNotification( notification );
691 
692 				/* if its a sleeping node, this will send a NoMoreInformation Packet to the device */
693 				WakeUp* cc = static_cast<WakeUp*>( GetCommandClass( WakeUp::StaticGetCommandClassId() ) );
694 				if( cc )
695 				{
696 					cc->SendPending();
697 				}
698 				// Check whether all nodes are now complete
699 				GetDriver()->CheckCompletedNodeQueries();
700 				return;
701 			}
702 			default:
703 			{
704 				break;
705 			}
706 		}
707 	}
708 
709 	if( addQSC && m_nodeAlive )
710 	{
711 		// Add a marker to the query queue so this advance method
712 		// gets called again once this stage has completed.
713 		GetDriver()->SendQueryStageComplete( m_nodeId, m_queryStage );
714 	}
715 }
716 
717 //-----------------------------------------------------------------------------
718 // <Node::QueryStageComplete>
719 // We are done with a stage in the query process
720 //-----------------------------------------------------------------------------
QueryStageComplete(QueryStage const _stage)721 void Node::QueryStageComplete
722 (
723 		QueryStage const _stage
724 )
725 {
726 	// Check that we are actually on the specified stage
727 	if( _stage != m_queryStage )
728 	{
729 		return;
730 	}
731 
732 	if( m_queryStage != QueryStage_Complete )
733 	{
734 		// Move to the next stage
735 		m_queryPending = false;
736 		m_queryStage = (QueryStage)( (uint32)m_queryStage + 1 );
737 		if( m_queryStage == QueryStage_CacheLoad )
738 		{
739 			m_queryStage = (QueryStage)( (uint32)m_queryStage + 1 );
740 		}
741 		m_queryRetries = 0;
742 	}
743 }
744 
745 //-----------------------------------------------------------------------------
746 // <Node::QueryStageRetry>
747 // Retry a stage up to the specified maximum
748 //-----------------------------------------------------------------------------
QueryStageRetry(QueryStage const _stage,uint8 const _maxAttempts)749 void Node::QueryStageRetry
750 (
751 		QueryStage const _stage,
752 		uint8 const _maxAttempts // = 0
753 )
754 {
755 	Log::Write( LogLevel_Info, m_nodeId, "QueryStageRetry stage %s requested stage %s max %d retries %d pending %d", c_queryStageNames[_stage], c_queryStageNames[m_queryStage], _maxAttempts, m_queryRetries, m_queryPending);
756 
757 	// Check that we are actually on the specified stage
758 	if( _stage != m_queryStage )
759 	{
760 		return;
761 	}
762 
763 	m_queryPending = false;
764 	if( _maxAttempts && ( ++m_queryRetries >= _maxAttempts ) )
765 	{
766 		m_queryRetries = 0;
767 		// We've retried too many times. Move to the next stage but only if
768 		// we aren't in any of the probe stages.
769 		if( m_queryStage != QueryStage_Probe && m_queryStage != QueryStage_CacheLoad )
770 		{
771 			m_queryStage = (Node::QueryStage)( (uint32)(m_queryStage + 1) );
772 		}
773 	}
774 	// Repeat the current query stage
775 	GetDriver()->RetryQueryStageComplete( m_nodeId, m_queryStage );
776 }
777 
778 //-----------------------------------------------------------------------------
779 // <Node::SetQueryStage>
780 // Set the query stage (but only to an earlier stage)
781 //-----------------------------------------------------------------------------
SetQueryStage(QueryStage const _stage,bool const _advance)782 void Node::SetQueryStage
783 (
784 		QueryStage const _stage,
785 		bool const _advance	// = true
786 )
787 {
788 	if( (int)_stage < (int)m_queryStage )
789 	{
790 		m_queryStage = _stage;
791 		m_queryPending = false;
792 
793 		if( QueryStage_Configuration == _stage )
794 		{
795 			m_queryConfiguration = true;
796 		}
797 	}
798 	if( _advance )
799 	{
800 		AdvanceQueries();
801 	}
802 }
803 
804 //-----------------------------------------------------------------------------
805 // <Node::GetQueryStageName>
806 // Gets the query stage name
807 //-----------------------------------------------------------------------------
GetQueryStageName(QueryStage const _stage)808 string Node::GetQueryStageName
809 (
810 		QueryStage const _stage
811 )
812 {
813 	return c_queryStageNames[_stage];
814 }
815 
816 //-----------------------------------------------------------------------------
817 // <Node::GetNeighbors>
818 // Gets the neighbors of a node
819 //-----------------------------------------------------------------------------
GetNeighbors(uint8 ** o_neighbors)820 uint32 Node::GetNeighbors
821 (
822 		uint8** o_neighbors
823 )
824 {
825 	// determine how many neighbors there are
826 	int i;
827 	uint32 numNeighbors = 0;
828 	if( m_queryStage < QueryStage_Session )
829 	{
830 		*o_neighbors = NULL;
831 		return 0;
832 	}
833 	for( i = 0; i < 29; i++ )
834 	{
835 		for( unsigned char mask = 0x80; mask != 0; mask >>= 1 )
836 			if( ( m_neighbors[i] & mask ) != 0 )
837 				numNeighbors++;
838 	}
839 
840 	// handle the possibility that no neighbors are reported
841 	if( !numNeighbors )
842 	{
843 		*o_neighbors = NULL;
844 		return 0;
845 	}
846 
847 	// create and populate an array with neighbor node ids
848 	uint8* neighbors = new uint8[numNeighbors];
849 	uint32 index = 0;
850 	for( int by=0; by<29; by++ )
851 	{
852 		for( int bi=0; bi<8; bi++ )
853 		{
854 			if( (m_neighbors[by] & ( 0x01<<bi ) ) )
855 				neighbors[index++] = ( ( by<<3 ) + bi + 1 );
856 		}
857 	}
858 
859 	*o_neighbors = neighbors;
860 	return numNeighbors;
861 }
862 
863 //-----------------------------------------------------------------------------
864 // <Node::ReadXML>
865 // Read the node config from XML
866 //-----------------------------------------------------------------------------
ReadXML(TiXmlElement const * _node)867 void Node::ReadXML
868 (
869 		TiXmlElement const* _node
870 )
871 {
872 	char const* str;
873 	int intVal;
874 
875 	str = _node->Attribute( "query_stage" );
876 	if( str )
877 	{
878 		// After restoring state from a file, we need to at least refresh the association, session and dynamic values.
879 		QueryStage queryStage = QueryStage_Associations;
880 		for( uint32 i=0; i<(uint32)QueryStage_Associations; ++i )
881 		{
882 			if( !strcmp( str, c_queryStageNames[i] ) )
883 			{
884 				queryStage = (QueryStage)i;
885 				break;
886 			}
887 		}
888 
889 		/* we cant use the SetQueryStage method here, as it only allows us to
890 		 * go to a lower QueryStage, and not a higher QueryStage. As QueryStage_Complete is higher than
891 		 * QueryStage_None (the default) we manually set it here. Note - in Driver::HandleSerialAPIGetInitDataResponse the
892 		 * QueryStage is set to CacheLoad (which is less than QueryStage_Associations) if this is a existing node read in via the zw state file.
893 		 *
894 		 */
895 		m_queryStage = queryStage;
896 		m_queryPending = false;
897 
898 		if( QueryStage_Configuration == queryStage )
899 		{
900 			m_queryConfiguration = true;
901 		}
902 	}
903 
904 	if( m_queryStage != QueryStage_None )
905 	{
906 		if( m_queryStage > QueryStage_ProtocolInfo )
907 		{
908 			// Notify the watchers of the protocol info.
909 			// We do the notification here so that it gets into the queue ahead of
910 			// any other notifications generated by adding command classes etc.
911 			m_protocolInfoReceived = true;
912 			Notification* notification = new Notification( Notification::Type_NodeProtocolInfo );
913 			notification->SetHomeAndNodeIds( m_homeId, m_nodeId );
914 			GetDriver()->QueueNotification( notification );
915 		}
916 
917 		if( m_queryStage > QueryStage_NodeInfo )
918 		{
919 			m_nodeInfoReceived = true;
920 		}
921 
922 		if( m_queryStage > QueryStage_Instances )
923 		{
924 			Notification* notification = new Notification( Notification::Type_EssentialNodeQueriesComplete );
925 			notification->SetHomeAndNodeIds( m_homeId, m_nodeId );
926 			GetDriver()->QueueNotification( notification );
927 		}
928 	}
929 
930 	str = _node->Attribute( "name" );
931 	if( str )
932 	{
933 		m_nodeName = str;
934 	}
935 
936 	str = _node->Attribute( "location" );
937 	if( str )
938 	{
939 		m_location = str;
940 	}
941 
942 	if( TIXML_SUCCESS == _node->QueryIntAttribute( "basic", &intVal ) )
943 	{
944 		m_basic = (uint8)intVal;
945 	}
946 
947 	if( TIXML_SUCCESS == _node->QueryIntAttribute( "generic", &intVal ) )
948 	{
949 		m_generic = (uint8)intVal;
950 	}
951 
952 	if( TIXML_SUCCESS == _node->QueryIntAttribute( "specific", &intVal ) )
953 	{
954 		m_specific = (uint8)intVal;
955 	}
956 
957 	if( TIXML_SUCCESS == _node->QueryIntAttribute( "roletype", &intVal ) )
958 	{
959 		m_role = (uint8)intVal;
960 		m_nodePlusInfoReceived = true;
961 	}
962 
963 	if( TIXML_SUCCESS == _node->QueryIntAttribute( "devicetype", &intVal ) )
964 	{
965 		m_deviceType = (uint16)intVal;
966 		m_nodePlusInfoReceived = true;
967 	}
968 
969 	if (TIXML_SUCCESS == _node->QueryIntAttribute ( "nodetype", &intVal ) )
970 	{
971 		m_nodeType = (uint8)intVal;
972 		m_nodePlusInfoReceived = true;
973 	}
974 
975 	str = _node->Attribute( "type" );
976 	if( str )
977 	{
978 		m_type = str;
979 	}
980 
981 	m_listening = true;
982 	str = _node->Attribute( "listening" );
983 	if( str )
984 	{
985 		m_listening = !strcmp( str, "true" );
986 	}
987 
988 	m_frequentListening = false;
989 	str = _node->Attribute( "frequentListening" );
990 	if( str )
991 	{
992 		m_frequentListening = !strcmp( str, "true" );
993 	}
994 
995 	m_beaming = false;
996 	str = _node->Attribute( "beaming" );
997 	if( str )
998 	{
999 		m_beaming = !strcmp( str, "true" );
1000 	}
1001 
1002 	m_routing = true;
1003 	str = _node->Attribute( "routing" );
1004 	if( str )
1005 	{
1006 		m_routing = !strcmp( str, "true" );
1007 	}
1008 
1009 	m_maxBaudRate = 0;
1010 	if( TIXML_SUCCESS == _node->QueryIntAttribute( "max_baud_rate", &intVal ) )
1011 	{
1012 		m_maxBaudRate = (uint32)intVal;
1013 	}
1014 
1015 	m_version = 0;
1016 	if( TIXML_SUCCESS == _node->QueryIntAttribute( "version", &intVal ) )
1017 	{
1018 		m_version = (uint8)intVal;
1019 	}
1020 
1021 	m_security = false;
1022 	str = _node->Attribute( "security" );
1023 	if( str )
1024 	{
1025 		m_security = !strcmp( str, "true" );
1026 	}
1027 
1028 	m_secured = false;
1029 	str = _node->Attribute( "secured" );
1030 	if( str )
1031 	{
1032 		m_secured = !strcmp( str, "true" );
1033 	}
1034 
1035 	m_nodeInfoSupported = true;
1036 	str = _node->Attribute( "nodeinfosupported" );
1037 	if( str )
1038 	{
1039 		m_nodeInfoSupported = !strcmp( str, "true" );
1040 	}
1041 
1042 	m_refreshonNodeInfoFrame = true;
1043 	str = _node->Attribute( "refreshonnodeinfoframe" );
1044 	if ( str )
1045 		m_refreshonNodeInfoFrame = !strcmp (str, "true" );
1046 
1047 	// Read the manufacturer info and create the command classes
1048 	TiXmlElement const* child = _node->FirstChildElement();
1049 	while( child )
1050 	{
1051 		str = child->Value();
1052 		if( str )
1053 		{
1054 			if( !strcmp( str, "CommandClasses" ) )
1055 			{
1056 				ReadCommandClassesXML( child );
1057 			}
1058 			else if( !strcmp( str, "Manufacturer" ) )
1059 			{
1060 				str = child->Attribute( "id" );
1061 				if( str )
1062 				{
1063 					m_manufacturerId = strtol(str, NULL, 16);
1064 				}
1065 
1066 				str = child->Attribute( "name" );
1067 				if( str )
1068 				{
1069 					m_manufacturerName = str;
1070 				}
1071 
1072 				TiXmlElement const* product = child->FirstChildElement();
1073 				if( !strcmp( product->Value(), "Product" ) )
1074 				{
1075 					str = product->Attribute( "type" );
1076 					if( str )
1077 					{
1078 						m_productType = strtol(str, NULL, 16);
1079 					}
1080 
1081 					str = product->Attribute( "id" );
1082 					if( str )
1083 					{
1084 						m_productId = strtol(str, NULL, 16);
1085 					}
1086 
1087 					str = product->Attribute( "name" );
1088 					if( str )
1089 					{
1090 						m_productName = str;
1091 					}
1092 				}
1093 			}
1094 		}
1095 
1096 		// Move to the next child node
1097 		child = child->NextSiblingElement();
1098 	}
1099 
1100 	if( m_nodeName.length() > 0 || m_location.length() > 0 || m_manufacturerId > 0 )
1101 	{
1102 		// Notify the watchers of the name changes
1103 		Notification* notification = new Notification( Notification::Type_NodeNaming );
1104 		notification->SetHomeAndNodeIds( m_homeId, m_nodeId );
1105 		GetDriver()->QueueNotification( notification );
1106 	}
1107 }
1108 
1109 //-----------------------------------------------------------------------------
1110 // <Node::ReadDeviceProtocolXML>
1111 // Read the device's protocol configuration from XML
1112 //-----------------------------------------------------------------------------
ReadDeviceProtocolXML(TiXmlElement const * _ccsElement)1113 void Node::ReadDeviceProtocolXML
1114 (
1115 		TiXmlElement const* _ccsElement
1116 )
1117 {
1118 	TiXmlElement const* ccElement = _ccsElement->FirstChildElement();
1119 	while( ccElement )
1120 	{
1121 		char const* str = ccElement->Value();
1122 		if( str && !strcmp( str, "Protocol" ) )
1123 		{
1124 			str = ccElement->Attribute( "nodeinfosupported" );
1125 			if( str )
1126 			{
1127 				m_nodeInfoSupported = !strcmp( str, "true" );
1128 			}
1129 
1130 			str = ccElement->Attribute( "refreshonnodeinfoframe" );
1131 			if ( str )
1132 			{
1133 				m_refreshonNodeInfoFrame = !strcmp( str, "true" );
1134 			}
1135 
1136 			// Some controllers support API calls that aren't advertised in their returned data.
1137 			// So provide a way to manipulate the returned data to reflect reality.
1138 			TiXmlElement const* childElement = _ccsElement->FirstChildElement();
1139 			while( childElement )
1140 			{
1141 				str = childElement->Value();
1142 				if( str && !strcmp( str, "APIcall" ) )
1143 				{
1144 					char const* funcStr = childElement->Attribute( "function" );
1145 					char *p;
1146 					uint8 func = (uint8)strtol( funcStr, &p, 16 );
1147 					if( p != funcStr )
1148 					{
1149 						char const* presStr = ccElement->Attribute( "present" );
1150 						GetDriver()->SetAPICall( func, !strcmp( presStr, "true" ) );
1151 					}
1152 				}
1153 				childElement = childElement->NextSiblingElement();
1154 			}
1155 			return;
1156 		}
1157 		ccElement = ccElement->NextSiblingElement();
1158 	}
1159 }
1160 
1161 //-----------------------------------------------------------------------------
1162 // <Node::ReadCommandClassesXML>
1163 // Read the command classes from XML
1164 //-----------------------------------------------------------------------------
ReadCommandClassesXML(TiXmlElement const * _ccsElement)1165 void Node::ReadCommandClassesXML
1166 (
1167 		TiXmlElement const* _ccsElement
1168 )
1169 {
1170 	char const* str;
1171 	int32 intVal;
1172 
1173 	TiXmlElement const* ccElement = _ccsElement->FirstChildElement();
1174 	while( ccElement )
1175 	{
1176 		str = ccElement->Value();
1177 		if( str && !strcmp( str, "CommandClass" ) )
1178 		{
1179 			if( TIXML_SUCCESS == ccElement->QueryIntAttribute( "id", &intVal ) )
1180 			{
1181 				uint8 id = (uint8)intVal;
1182 
1183 				// Check whether this command class is to be removed (product XMLs might
1184 				// request this if a class is not implemented properly by the device)
1185 				bool remove = false;
1186 				char const* action = ccElement->Attribute( "action" );
1187 				if( action && !strcasecmp( action, "remove" ) )
1188 				{
1189 					remove = true;
1190 				}
1191 
1192 				CommandClass* cc = GetCommandClass( id );
1193 				if( remove )
1194 				{
1195 					// Remove support for the command class
1196 					RemoveCommandClass( id );
1197 				}
1198 				else
1199 				{
1200 					if( NULL == cc )
1201 					{
1202 						if (Security::StaticGetCommandClassId() == id && !GetDriver()->isNetworkKeySet()) {
1203 							Log::Write(LogLevel_Warning, "Security Command Class cannot be Loaded. NetworkKey is not set");
1204 							ccElement = ccElement->NextSiblingElement();
1205 							continue;
1206 						}
1207 
1208 						// Command class support does not exist yet, so we create it
1209 						cc = AddCommandClass( id );
1210 					}
1211 
1212 					if( NULL != cc )
1213 					{
1214 						cc->ReadXML( ccElement );
1215 					}
1216 				}
1217 			}
1218 		}
1219 
1220 		ccElement = ccElement->NextSiblingElement();
1221 	}
1222 }
1223 
1224 //-----------------------------------------------------------------------------
1225 // <Node::WriteXML>
1226 // Save the static node configuration data
1227 //-----------------------------------------------------------------------------
WriteXML(TiXmlElement * _driverElement)1228 void Node::WriteXML
1229 (
1230 		TiXmlElement* _driverElement
1231 )
1232 {
1233 	char str[32];
1234 
1235 	TiXmlElement* nodeElement = new TiXmlElement( "Node" );
1236 	_driverElement->LinkEndChild( nodeElement );
1237 
1238 	snprintf( str, 32, "%d", m_nodeId );
1239 	nodeElement->SetAttribute( "id", str );
1240 
1241 	nodeElement->SetAttribute( "name", m_nodeName.c_str() );
1242 	nodeElement->SetAttribute( "location", m_location.c_str() );
1243 
1244 	snprintf( str, 32, "%d", m_basic );
1245 	nodeElement->SetAttribute( "basic", str );
1246 
1247 	snprintf( str, 32, "%d", m_generic );
1248 	nodeElement->SetAttribute( "generic", str );
1249 
1250 	snprintf( str, 32, "%d", m_specific );
1251 	nodeElement->SetAttribute( "specific", str );
1252 
1253 	if( m_nodePlusInfoReceived )
1254 	{
1255 		snprintf( str, 32, "%d", m_role );
1256 		nodeElement->SetAttribute( "roletype", str );
1257 
1258 		snprintf( str, 32, "%d", m_deviceType );
1259 		nodeElement->SetAttribute( "devicetype", str );
1260 
1261 		snprintf( str, 32, "%d", m_nodeType );
1262 		nodeElement->SetAttribute ( "nodetype", str );
1263 	}
1264 
1265 	nodeElement->SetAttribute( "type", m_type.c_str() );
1266 
1267 	nodeElement->SetAttribute( "listening", m_listening ? "true" : "false" );
1268 	nodeElement->SetAttribute( "frequentListening", m_frequentListening ? "true" : "false" );
1269 	nodeElement->SetAttribute( "beaming", m_beaming ? "true" : "false" );
1270 	nodeElement->SetAttribute( "routing", m_routing ? "true" : "false" );
1271 
1272 	snprintf( str, 32, "%d", m_maxBaudRate );
1273 	nodeElement->SetAttribute( "max_baud_rate", str );
1274 
1275 	snprintf( str, 32, "%d", m_version );
1276 	nodeElement->SetAttribute( "version", str );
1277 
1278 	if( m_security )
1279 	{
1280 		nodeElement->SetAttribute( "security", "true" );
1281 	}
1282 
1283 	if( m_secured )
1284 	{
1285 		nodeElement->SetAttribute( "secured", "true" );
1286 	}
1287 
1288 
1289 	if( !m_nodeInfoSupported )
1290 	{
1291 		nodeElement->SetAttribute( "nodeinfosupported", "false" );
1292 	}
1293 
1294 	if (!m_refreshonNodeInfoFrame)
1295 	{
1296 		nodeElement->SetAttribute( "refreshonnodeinfoframe", "false" );
1297 	}
1298 
1299 	nodeElement->SetAttribute( "query_stage", c_queryStageNames[m_queryStage] );
1300 
1301 	// Write the manufacturer and product data in the same format
1302 	// as used in the ManyfacturerSpecfic.xml file.  This will
1303 	// allow new devices to be added via a simple cut and paste.
1304 	TiXmlElement* manufacturerElement = new TiXmlElement( "Manufacturer" );
1305 	nodeElement->LinkEndChild( manufacturerElement );
1306 
1307 	/* this should be written in hex to avoid confusion... */
1308 	{
1309 		std::stringstream ss;
1310 		ss << std::hex << m_manufacturerId;
1311 		manufacturerElement->SetAttribute( "id", ss.str().c_str() );
1312 	}
1313 	manufacturerElement->SetAttribute( "name", m_manufacturerName.c_str() );
1314 
1315 	TiXmlElement* productElement = new TiXmlElement( "Product" );
1316 	manufacturerElement->LinkEndChild( productElement );
1317 
1318 	/* this should be written in hex to avoid confusion... */
1319 	{
1320 		std::stringstream ss;
1321 		ss << std::hex << m_productType;
1322 		productElement->SetAttribute( "type", ss.str().c_str() );
1323 	}
1324 
1325 	/* this should be written in hex to avoid confusion... */
1326 	{
1327 		std::stringstream ss;
1328 		ss << std::hex << m_productId;
1329 		productElement->SetAttribute( "id", ss.str().c_str() );
1330 	}
1331 	productElement->SetAttribute( "name", m_productName.c_str() );
1332 
1333 	// Write the command classes
1334 	TiXmlElement* ccsElement = new TiXmlElement( "CommandClasses" );
1335 	nodeElement->LinkEndChild( ccsElement );
1336 
1337 	for( map<uint8,CommandClass*>::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it )
1338 	{
1339 		if( it->second->GetCommandClassId() == NoOperation::StaticGetCommandClassId() ) // don't output NoOperation
1340 		{
1341 			continue;
1342 		}
1343 		TiXmlElement* ccElement = new TiXmlElement( "CommandClass" );
1344 		ccsElement->LinkEndChild( ccElement );
1345 		it->second->WriteXML( ccElement );
1346 	}
1347 }
1348 
1349 //-----------------------------------------------------------------------------
1350 // <Node::UpdateProtocolInfo>
1351 // Handle the FUNC_ID_ZW_GET_NODE_PROTOCOL_INFO response
1352 //-----------------------------------------------------------------------------
UpdateProtocolInfo(uint8 const * _data)1353 void Node::UpdateProtocolInfo
1354 (
1355 		uint8 const* _data
1356 )
1357 {
1358 	if( ProtocolInfoReceived() )
1359 	{
1360 		// We already have this info
1361 		return;
1362 	}
1363 
1364 	if( _data[4] == 0 )
1365 	{
1366 		// Node doesn't exist if Generic class is zero.
1367 		Log::Write( LogLevel_Info, m_nodeId, "  Protocol Info for Node %d reports node nonexistent", m_nodeId );
1368 		SetNodeAlive( false );
1369 		return;
1370 	}
1371 
1372 	// Capabilities
1373 	m_listening = ( ( _data[0] & 0x80 ) != 0 );
1374 	m_routing = ( ( _data[0] & 0x40 ) != 0 );
1375 
1376 	m_maxBaudRate = 9600;
1377 	if( ( _data[0] & 0x38 ) == 0x10 )
1378 	{
1379 		m_maxBaudRate = 40000;
1380 	}
1381 
1382 	m_version = ( _data[0] & 0x07 ) + 1;
1383 
1384 	m_frequentListening = ( ( _data[1] & ( SecurityFlag_Sensor250ms | SecurityFlag_Sensor1000ms ) ) != 0 );
1385 	m_beaming = ( ( _data[1] & SecurityFlag_BeamCapability ) != 0 );
1386 
1387 	// Security
1388 	m_security = ( ( _data[1] & SecurityFlag_Security ) != 0 );
1389 
1390 	// Optional flag is true if the device reports optional command classes.
1391 	// NOTE: We stopped using this because not all devices report it properly,
1392 	// and now just request the optional classes regardless.
1393 	// bool optional = (( _data[1] & 0x80 ) != 0 );
1394 	/* dont do any further processing if we have already recieved our Protocol Info, or basicprotocolInfo */
1395 	if( ProtocolInfoReceived())
1396 	{
1397 		// We already have this info
1398 		return;
1399 	}
1400 
1401 	Log::Write( LogLevel_Info, m_nodeId, "  Protocol Info for Node %d:", m_nodeId );
1402 	if( m_listening )
1403 		Log::Write( LogLevel_Info, m_nodeId, "    Listening     = true" );
1404 	else
1405 	{
1406 		Log::Write( LogLevel_Info, m_nodeId, "    Listening     = false" );
1407 		Log::Write( LogLevel_Info, m_nodeId, "    Frequent      = %s", m_frequentListening ? "true" : "false" );
1408 	}
1409 	Log::Write( LogLevel_Info, m_nodeId, "    Beaming       = %s", m_beaming ? "true" : "false" );
1410 	Log::Write( LogLevel_Info, m_nodeId, "    Routing       = %s", m_routing ? "true" : "false" );
1411 	Log::Write( LogLevel_Info, m_nodeId, "    Max Baud Rate = %d", m_maxBaudRate );
1412 	Log::Write( LogLevel_Info, m_nodeId, "    Version       = %d", m_version );
1413 	Log::Write( LogLevel_Info, m_nodeId, "    Security      = %s", m_security ? "true" : "false" );
1414 
1415 	if (m_basicprotocolInfoReceived == false) {
1416 
1417 		// Notify the watchers of the protocol info.
1418 		// We do the notification here so that it gets into the queue ahead of
1419 		// any other notifications generated by adding command classes etc.
1420 		Notification* notification = new Notification( Notification::Type_NodeProtocolInfo );
1421 		notification->SetHomeAndNodeIds( m_homeId, m_nodeId );
1422 		GetDriver()->QueueNotification( notification );
1423 
1424 		// Set up the device class based data for the node, including mandatory command classes
1425 		SetDeviceClasses( _data[3], _data[4], _data[5] );
1426 		// Do this for every controller. A little extra work but it won't be a large file.
1427 		if( IsController() )
1428 		{
1429 			GetDriver()->ReadButtons( m_nodeId );
1430 		}
1431 		m_basicprotocolInfoReceived = true;
1432 	} else {
1433 		/* we have to setup the Wakeup CC if needed here, because
1434 		 * it wouldn't have been created in the SetProtocolInfo function, as we didn't
1435 		 * have the Device Flags then
1436 		 */
1437 		if( !m_listening && !IsFrequentListeningDevice())
1438 		{
1439 			// Device does not always listen, so we need the WakeUp handler.  We can't
1440 			// wait for the command class list because the request for the command
1441 			// classes may need to go in the wakeup queue itself!
1442 			if( CommandClass* pCommandClass = AddCommandClass( WakeUp::StaticGetCommandClassId() ) )
1443 			{
1444 				pCommandClass->SetInstance( 1 );
1445 			}
1446 		}
1447 
1448 	}
1449 	m_protocolInfoReceived = true;
1450 }
1451 
SetProtocolInfo(uint8 const * _protocolInfo,uint8 const _length)1452 void Node::SetProtocolInfo
1453 (
1454 		uint8 const* _protocolInfo,
1455 		uint8 const _length
1456 )
1457 {
1458 
1459 	if( ProtocolInfoReceived() || m_basicprotocolInfoReceived == true )
1460 	{
1461 		// We already have this info
1462 		return;
1463 	}
1464 
1465 	if( _protocolInfo[1] == 0 )
1466 	{
1467 		// Node doesn't exist if Generic class is zero.
1468 		Log::Write( LogLevel_Info, m_nodeId, "  Protocol Info for Node %d reports node nonexistent", m_nodeId );
1469 		SetNodeAlive( false );
1470 		return;
1471 	}
1472 
1473 	// Notify the watchers of the protocol info.
1474 	// We do the notification here so that it gets into the queue ahead of
1475 	// any other notifications generated by adding command classes etc.
1476 	Notification* notification = new Notification( Notification::Type_NodeProtocolInfo );
1477 	notification->SetHomeAndNodeIds( m_homeId, m_nodeId );
1478 	GetDriver()->QueueNotification( notification );
1479 
1480 
1481 	// Set up the device class based data for the node, including mandatory command classes
1482 	SetDeviceClasses( _protocolInfo[0], _protocolInfo[1], _protocolInfo[2] );
1483 
1484 	/* Remaining Bytes in _protocolInfo are the CommandClasses this device supports */
1485 	/* first iterate over them and check for the Security CC, as we want to quickly start exchanging the Network Keys
1486 	 * first (before other CC's start sending stuff and slowing down our exchange
1487 	 */
1488 	if (m_secured) {
1489 		if (Security *pCommandClass = static_cast<Security *>(GetCommandClass(Security::StaticGetCommandClassId()))) {
1490 			/* Security CC has already been loaded, most likely via the SetDeviceClasses Function above */
1491 			if (!GetDriver()->isNetworkKeySet()) {
1492 				Log::Write(LogLevel_Warning, m_nodeId, "Security Command Class Disabled. NetworkKey is not Set");
1493 			} else {
1494 				pCommandClass->ExchangeNetworkKeys();
1495 			}
1496 		} else {
1497 			/* Security CC is not loaded, see if its in our NIF frame and load if necessary */
1498 			for (int i = 3; i < _length; i++) {
1499 				if (_protocolInfo[i] == Security::StaticGetCommandClassId()) {
1500 					pCommandClass = static_cast<Security *>(AddCommandClass(_protocolInfo[i]));
1501 					if (!GetDriver()->isNetworkKeySet()) {
1502 						Log::Write(LogLevel_Warning, m_nodeId, "Security Command Class Disabled. NetworkKey is not Set");
1503 					} else {
1504 						pCommandClass->ExchangeNetworkKeys();
1505 					}
1506 				}
1507 			}
1508 		}
1509 	}
1510 	UpdateNodeInfo(&_protocolInfo[3], _length-3);
1511 
1512 
1513 	m_basicprotocolInfoReceived = true;
1514 }
1515 
SetSecured(bool secure)1516 void Node::SetSecured(bool secure) {
1517 	m_secured = secure;
1518 }
1519 
1520 
1521 
SetSecuredClasses(uint8 const * _data,uint8 const _length)1522 void Node::SetSecuredClasses
1523 (
1524 		uint8 const* _data,
1525 		uint8 const _length
1526 )
1527 {
1528 	uint32 i;
1529 	m_secured = true;
1530 	Log::Write( LogLevel_Info, m_nodeId, "  Secured command classes for node %d:", m_nodeId );
1531 
1532 	if (!GetDriver()->isNetworkKeySet()) {
1533 		Log::Write (LogLevel_Warning, m_nodeId, "  Secured Command Classes cannot be enabled as Network Key is not set");
1534 		return;
1535 	}
1536 
1537 
1538 	bool afterMark = false;
1539 	for( i=0; i<_length; ++i )
1540 	{
1541 		if( _data[i] == 0xef )
1542 		{
1543 			// COMMAND_CLASS_MARK.
1544 			// Marks the end of the list of supported command classes.  The remaining classes
1545 			// are those that can be controlled by the device.  These classes are created
1546 			// without values.  Messages received cause notification events instead.
1547 			afterMark = true;
1548 			continue;
1549 		}
1550 		/* Check if this is a CC that is already registered with the node */
1551 		if (CommandClass *pCommandClass = GetCommandClass(_data[i]))
1552 		{
1553 			/* if it was specified int he NIF frame, and came in as part of the Security SupportedReport message
1554 			 * then it can support both Clear Text and Secured Comms. So do a check first
1555 			 */
1556 			if (pCommandClass->IsInNIF()) {
1557 				/* if the CC Supports Security and our SecurityStrategy says we should encrypt it, then mark it as encrypted */
1558 				if (pCommandClass->IsSecureSupported() && (ShouldSecureCommandClass(_data[i]) == SecurityStrategy_Supported )) {
1559 					pCommandClass->SetSecured();
1560 					Log::Write( LogLevel_Info, m_nodeId, "    %s (Secured) - %s", pCommandClass->GetCommandClassName().c_str(), pCommandClass->IsInNIF() ? "InNIF": "NotInNIF");
1561 				}
1562 				/* if it wasn't in the NIF frame, then it will only support Secured Comms. */
1563 			} else {
1564 				if (pCommandClass->IsSecureSupported()) {
1565 					pCommandClass->SetSecured();
1566 					Log::Write( LogLevel_Info, m_nodeId, "    %s (Secured) - %s", pCommandClass->GetCommandClassName().c_str(), pCommandClass->IsInNIF() ? "InNIF": "NotInNIF");
1567 				}
1568 			}
1569 		}
1570 		/* it might be a new CC we havn't seen as part of the NIF. In that case
1571 		 * its only supported via the Security CC, so no need to check our SecurityStrategy, just
1572 		 * encrypt it regardless */
1573 		else if( CommandClasses::IsSupported( _data[i] ) )
1574 		{
1575 			if( CommandClass* pCommandClass = AddCommandClass( _data[i] ) )
1576 			{
1577 				// If this class came after the COMMAND_CLASS_MARK, then we do not create values.
1578 				if( afterMark )
1579 				{
1580 					pCommandClass->SetAfterMark();
1581 				}
1582 				if (pCommandClass->IsSecureSupported()) {
1583 					pCommandClass->SetSecured();
1584 					Log::Write( LogLevel_Info, m_nodeId, "    %s (Secured) - %s", pCommandClass->GetCommandClassName().c_str(), pCommandClass->IsInNIF() ? "InNIF" : "NotInNIF" );
1585 				}
1586 				// Start with an instance count of one.  If the device supports COMMMAND_CLASS_MULTI_INSTANCE
1587 				// then some command class instance counts will increase once the responses to the RequestState
1588 				// call at the end of this method have been processed.
1589 				pCommandClass->SetInstance( 1 );
1590 
1591 				/* set our Static Request Flags */
1592 				uint8 request = 0;
1593 
1594 				if( GetCommandClass( MultiInstance::StaticGetCommandClassId() ) )
1595 				{
1596 					// Request instances
1597 					request |= (uint8)CommandClass::StaticRequest_Instances;
1598 				}
1599 
1600 				if( GetCommandClass( Version::StaticGetCommandClassId() ) )
1601 				{
1602 					// Request versions
1603 					request |= (uint8)CommandClass::StaticRequest_Version;
1604 				}
1605 
1606 				if( request )
1607 				{
1608 					pCommandClass->SetStaticRequest( request );
1609 				}
1610 			}
1611 		}
1612 		else
1613 		{
1614 			Log::Write( LogLevel_Info, m_nodeId, "    Secure CommandClass 0x%.2x - NOT SUPPORTED", _data[i] );
1615 		}
1616 	}
1617 	Log::Write( LogLevel_Info, m_nodeId, "  UnSecured command classes for node %d:", m_nodeId );
1618 	for( map<uint8,CommandClass*>::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it )
1619 	{
1620 		if (!it->second->IsSecured())
1621 			Log::Write( LogLevel_Info, m_nodeId, "    %s (Unsecured) - %s", it->second->GetCommandClassName().c_str(), it->second->IsInNIF() ? "InNIF" : "NotInNIF" );
1622 	}
1623 
1624 
1625 }
1626 //-----------------------------------------------------------------------------
1627 // <Node::UpdateNodeInfo>
1628 // Set up the command classes from the node info frame
1629 //-----------------------------------------------------------------------------
UpdateNodeInfo(uint8 const * _data,uint8 const _length)1630 void Node::UpdateNodeInfo
1631 (
1632 		uint8 const* _data,
1633 		uint8 const _length
1634 )
1635 {
1636 	if( !NodeInfoReceived() )
1637 	{
1638 		// Add the command classes specified by the device
1639 		Log::Write( LogLevel_Info, m_nodeId, "  Optional command classes for node %d:", m_nodeId );
1640 
1641 		bool newCommandClasses = false;
1642 		uint32 i;
1643 
1644 		bool afterMark = false;
1645 		for( i=0; i<_length; ++i )
1646 		{
1647 			if( _data[i] == 0xef )
1648 			{
1649 				// COMMAND_CLASS_MARK.
1650 				// Marks the end of the list of supported command classes.  The remaining classes
1651 				// are those that can be controlled by the device.  These classes are created
1652 				// without values.  Messages received cause notification events instead.
1653 				afterMark = true;
1654 
1655 				if( !newCommandClasses )
1656 				{
1657 					Log::Write( LogLevel_Info, m_nodeId, "    None" );
1658 				}
1659 				Log::Write( LogLevel_Info, m_nodeId, "  Optional command classes controlled by node %d:", m_nodeId );
1660 				newCommandClasses = false;
1661 				continue;
1662 			}
1663 
1664 			if( CommandClasses::IsSupported( _data[i] ) )
1665 			{
1666 				if (Security::StaticGetCommandClassId() == _data[i] && !GetDriver()->isNetworkKeySet()) {
1667 					Log::Write (LogLevel_Info, m_nodeId, "    %s (Disabled - Network Key Not Set)", Security::StaticGetCommandClassName().c_str());
1668 					continue;
1669 				}
1670 				if( CommandClass* pCommandClass = AddCommandClass( _data[i] ) )
1671 				{
1672 					/* this CC was in the NIF frame */
1673 					pCommandClass->SetInNIF();
1674 					// If this class came after the COMMAND_CLASS_MARK, then we do not create values.
1675 					if( afterMark )
1676 					{
1677 						pCommandClass->SetAfterMark();
1678 					}
1679 
1680 					// Start with an instance count of one.  If the device supports COMMMAND_CLASS_MULTI_INSTANCE
1681 					// then some command class instance counts will increase once the responses to the RequestState
1682 					// call at the end of this method have been processed.
1683 					pCommandClass->SetInstance( 1 );
1684 					newCommandClasses = true;
1685 					Log::Write( LogLevel_Info, m_nodeId, "    %s", pCommandClass->GetCommandClassName().c_str() );
1686 				} else if (CommandClass *pCommandClass = GetCommandClass( _data[i] ) ) {
1687 					/* this CC was in the NIF frame */
1688 					pCommandClass->SetInNIF();
1689 					Log::Write( LogLevel_Info, m_nodeId, "    %s (Existing)", pCommandClass->GetCommandClassName().c_str() );
1690 				}
1691 			}
1692 			else
1693 			{
1694 				Log::Write( LogLevel_Info, m_nodeId, "  CommandClass 0x%.2x - NOT REQUIRED", _data[i] );
1695 			}
1696 		}
1697 
1698 		if( !newCommandClasses )
1699 		{
1700 			// No additional command classes over the mandatory ones.
1701 			Log::Write( LogLevel_Info, m_nodeId, "    None" );
1702 		}
1703 
1704 		SetStaticRequests();
1705 		m_nodeInfoReceived = true;
1706 	}
1707 	else
1708 	{
1709 		/* Only Refresh if the Device Config Specifies it  - Only the dynamic stuff */
1710 		if (m_refreshonNodeInfoFrame)
1711 			SetQueryStage( QueryStage_Dynamic );
1712 	}
1713 
1714 	// Treat the node info frame as a sign that the node is awake
1715 	if( WakeUp* wakeUp = static_cast<WakeUp*>( GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) )
1716 	{
1717 		wakeUp->SetAwake( true );
1718 	}
1719 }
1720 
1721 //-----------------------------------------------------------------------------
1722 // <Node::SetNodeAlive>
1723 // Track alive state of a node for dead node detection.
1724 //-----------------------------------------------------------------------------
SetNodeAlive(bool const _isAlive)1725 void Node::SetNodeAlive
1726 (
1727 		bool const _isAlive
1728 )
1729 {
1730 	Notification* notification;
1731 
1732 	if( _isAlive )
1733 	{
1734 		Log::Write( LogLevel_Error, m_nodeId, "WARNING: node revived" );
1735 		m_nodeAlive = true;
1736 		m_errors = 0;
1737 		if( m_queryStage != Node::QueryStage_Complete )
1738 		{
1739 			m_queryRetries = 0; // restart at last stage
1740 			AdvanceQueries();
1741 		}
1742 		notification = new Notification( Notification::Type_Notification );
1743 		notification->SetHomeAndNodeIds( m_homeId, m_nodeId );
1744 		notification->SetNotification( Notification::Code_Alive );
1745 	}
1746 	else
1747 	{
1748 		Log::Write( LogLevel_Error, m_nodeId, "ERROR: node presumed dead" );
1749 		m_nodeAlive = false;
1750 		if( m_queryStage != Node::QueryStage_Complete )
1751 		{
1752 			// Check whether all nodes are now complete
1753 			GetDriver()->CheckCompletedNodeQueries();
1754 		}
1755 		notification = new Notification( Notification::Type_Notification );
1756 		notification->SetHomeAndNodeIds( m_homeId, m_nodeId );
1757 		notification->SetNotification( Notification::Code_Dead );
1758 	}
1759 	GetDriver()->QueueNotification( notification );
1760 }
1761 
1762 //-----------------------------------------------------------------------------
1763 // <Node::SetStaticRequests>
1764 // The first time we hear from a node, we set flags to indicate the
1765 // need to request certain static data from the device.  This is so that
1766 // we can track which data has been received, and which has not.
1767 //-----------------------------------------------------------------------------
SetStaticRequests()1768 void Node::SetStaticRequests
1769 (
1770 )
1771 {
1772 	uint8 request = 0;
1773 
1774 	if( GetCommandClass( MultiInstance::StaticGetCommandClassId() ) )
1775 	{
1776 		// Request instances
1777 		request |= (uint8)CommandClass::StaticRequest_Instances;
1778 	}
1779 
1780 	if( GetCommandClass( Version::StaticGetCommandClassId() ) )
1781 	{
1782 		// Request versions
1783 		request |= (uint8)CommandClass::StaticRequest_Version;
1784 	}
1785 
1786 	if( request )
1787 	{
1788 		for( map<uint8,CommandClass*>::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it )
1789 		{
1790 			it->second->SetStaticRequest( request );
1791 		}
1792 		SetQueryStage( QueryStage_ManufacturerSpecific2 );
1793 	}
1794 }
1795 
1796 //-----------------------------------------------------------------------------
1797 // <Node::SetNodeName>
1798 // Set the name of the node
1799 //-----------------------------------------------------------------------------
SetNodeName(string const & _nodeName)1800 void Node::SetNodeName
1801 (
1802 		string const& _nodeName
1803 )
1804 {
1805 	m_nodeName = _nodeName;
1806 	// Notify the watchers of the name changes
1807 	Notification* notification = new Notification( Notification::Type_NodeNaming );
1808 	notification->SetHomeAndNodeIds( m_homeId, m_nodeId );
1809 	GetDriver()->QueueNotification( notification );
1810 	if( NodeNaming* cc = static_cast<NodeNaming*>( GetCommandClass( NodeNaming::StaticGetCommandClassId() ) ) )
1811 	{
1812 		// The node supports naming, so we try to write the name into the device
1813 		cc->SetName( _nodeName );
1814 	}
1815 }
1816 
1817 //-----------------------------------------------------------------------------
1818 // <Node::SetLocation>
1819 // Set the location of the node
1820 //-----------------------------------------------------------------------------
SetLocation(string const & _location)1821 void Node::SetLocation
1822 (
1823 		string const& _location
1824 )
1825 {
1826 	m_location = _location;
1827 	// Notify the watchers of the name changes
1828 	Notification* notification = new Notification( Notification::Type_NodeNaming );
1829 	notification->SetHomeAndNodeIds( m_homeId, m_nodeId );
1830 	GetDriver()->QueueNotification( notification );
1831 	if( NodeNaming* cc = static_cast<NodeNaming*>( GetCommandClass( NodeNaming::StaticGetCommandClassId() ) ) )
1832 	{
1833 		// The node supports naming, so we try to write the location into the device
1834 		cc->SetLocation( _location );
1835 	}
1836 }
1837 
1838 //-----------------------------------------------------------------------------
1839 // <Node::ApplicationCommandHandler>
1840 // Handle a command class message
1841 //-----------------------------------------------------------------------------
ApplicationCommandHandler(uint8 const * _data,bool encrypted)1842 void Node::ApplicationCommandHandler
1843 (
1844 		uint8 const* _data,
1845 		bool encrypted
1846 
1847 )
1848 {
1849 	if( CommandClass* pCommandClass = GetCommandClass( _data[5] ) )
1850 	{
1851 		if (pCommandClass->IsSecured() && !encrypted) {
1852 			Log::Write( LogLevel_Warning, m_nodeId, "Received a Clear Text Message for the CommandClass %s which is Secured", pCommandClass->GetCommandClassName().c_str());
1853 			bool drop = true;
1854 			Options::Get()->GetOptionAsBool("EnforceSecureReception", &drop);
1855 			if (drop) {
1856 				Log::Write( LogLevel_Warning, m_nodeId, "   Dropping Message");
1857 				return;
1858 			} else {
1859 				Log::Write( LogLevel_Warning, m_nodeId, "   Allowing Message (EnforceSecureReception is not set)");
1860 			}
1861 		}
1862 
1863 		pCommandClass->ReceivedCntIncr();
1864 		pCommandClass->HandleMsg( &_data[6], _data[4] );
1865 	}
1866 	else
1867 	{
1868 		if( _data[5] == ControllerReplication::StaticGetCommandClassId() )
1869 		{
1870 			// This is a controller replication message, and we do not support it.
1871 			// We have to at least acknowledge the message to avoid locking the sending device.
1872 			Log::Write( LogLevel_Info, m_nodeId, "ApplicationCommandHandler - Default acknowledgement of controller replication data" );
1873 
1874 			Msg* msg = new Msg( "Replication Command Complete", m_nodeId, REQUEST, FUNC_ID_ZW_REPLICATION_COMMAND_COMPLETE, false );
1875 			GetDriver()->SendMsg( msg, Driver::MsgQueue_Command );
1876 		}
1877 		else
1878 		{
1879 			Log::Write( LogLevel_Info, m_nodeId, "ApplicationCommandHandler - Unhandled Command Class 0x%.2x", _data[5] );
1880 		}
1881 	}
1882 }
1883 
1884 //-----------------------------------------------------------------------------
1885 // <Node::GetCommandClass>
1886 // Get the specified command class object if supported, otherwise NULL
1887 //-----------------------------------------------------------------------------
GetCommandClass(uint8 const _commandClassId) const1888 CommandClass* Node::GetCommandClass
1889 (
1890 		uint8 const _commandClassId
1891 )const
1892 {
1893 	map<uint8,CommandClass*>::const_iterator it = m_commandClassMap.find( _commandClassId );
1894 	if( it != m_commandClassMap.end() )
1895 	{
1896 		return it->second;
1897 	}
1898 
1899 	// Not found
1900 	return NULL;
1901 }
1902 
1903 //-----------------------------------------------------------------------------
1904 // <Node::AddCommandClass>
1905 // Add a command class to the node
1906 //-----------------------------------------------------------------------------
AddCommandClass(uint8 const _commandClassId)1907 CommandClass* Node::AddCommandClass
1908 (
1909 		uint8 const _commandClassId
1910 )
1911 {
1912 	if( GetCommandClass( _commandClassId ) )
1913 	{
1914 		// Class and instance have already been added
1915 		return NULL;
1916 	}
1917 
1918 	// Create the command class object and add it to our map
1919 	if( CommandClass* pCommandClass = CommandClasses::CreateCommandClass( _commandClassId, m_homeId, m_nodeId ) )
1920 	{
1921 		m_commandClassMap[_commandClassId] = pCommandClass;
1922 		return pCommandClass;
1923 	}
1924 	else
1925 	{
1926 		Log::Write( LogLevel_Info, m_nodeId, "AddCommandClass - Unsupported Command Class 0x%.2x", _commandClassId );
1927 	}
1928 
1929 	return NULL;
1930 }
1931 
1932 //-----------------------------------------------------------------------------
1933 // <Node::RemoveCommandClass>
1934 // Remove a command class from the node
1935 //-----------------------------------------------------------------------------
RemoveCommandClass(uint8 const _commandClassId)1936 void Node::RemoveCommandClass
1937 (
1938 		uint8 const _commandClassId
1939 )
1940 {
1941 	map<uint8,CommandClass*>::iterator it = m_commandClassMap.find( _commandClassId );
1942 	if( it == m_commandClassMap.end() )
1943 	{
1944 		// Class is not found
1945 		return;
1946 	}
1947 
1948 	// Remove all the values associated with this class
1949 	if( ValueStore* store = GetValueStore() )
1950 	{
1951 		store->RemoveCommandClassValues( _commandClassId );
1952 	}
1953 
1954 	// Destroy the command class object and remove it from our map
1955 	Log::Write( LogLevel_Info, m_nodeId, "RemoveCommandClass - Removed support for %s", it->second->GetCommandClassName().c_str() );
1956 
1957 	delete it->second;
1958 	m_commandClassMap.erase( it );
1959 }
1960 
1961 //-----------------------------------------------------------------------------
1962 // <Node::SetConfigParam>
1963 // Set a configuration parameter in a device
1964 //-----------------------------------------------------------------------------
SetConfigParam(uint8 const _param,int32 _value,uint8 const _size)1965 bool Node::SetConfigParam
1966 (
1967 		uint8 const _param,
1968 		int32 _value,
1969 		uint8 const _size
1970 )
1971 {
1972 	if( Configuration* cc = static_cast<Configuration*>( GetCommandClass( Configuration::StaticGetCommandClassId() ) ) )
1973 	{
1974 		// First try to find an existing value representing the parameter, and set that.
1975 		if( Value* value = cc->GetValue( 1, _param ) )
1976 		{
1977 			switch( value->GetID().GetType() )
1978 			{
1979 				case ValueID::ValueType_Bool:
1980 				{
1981 					ValueBool* valueBool = static_cast<ValueBool*>( value );
1982 					valueBool->Set( _value != 0 );
1983 					break;
1984 				}
1985 				case ValueID::ValueType_Byte:
1986 				{
1987 					ValueByte* valueByte = static_cast<ValueByte*>( value );
1988 					valueByte->Set( (uint8)_value );
1989 					break;
1990 				}
1991 				case ValueID::ValueType_Short:
1992 				{
1993 					ValueShort* valueShort = static_cast<ValueShort*>( value );
1994 					valueShort->Set( (uint16)_value );
1995 					break;
1996 				}
1997 				case ValueID::ValueType_Int:
1998 				{
1999 					ValueInt* valueInt = static_cast<ValueInt*>( value );
2000 					valueInt->Set( _value );
2001 					break;
2002 				}
2003 				case ValueID::ValueType_List:
2004 				{
2005 					ValueList* valueList = static_cast<ValueList*>( value );
2006 					valueList->SetByValue( _value );
2007 					break;
2008 				}
2009 				default:
2010 				{
2011 				}
2012 			}
2013 
2014 			return true;
2015 		}
2016 
2017 		// Failed to find an existing value object representing this
2018 		// configuration parameter, so we try using the default or
2019 		// included size through the Configuration command class.
2020 		cc->Set( _param, _value, _size );
2021 		return true;
2022 	}
2023 
2024 	return false;
2025 }
2026 
2027 //-----------------------------------------------------------------------------
2028 // <Node::RequestConfigParam>
2029 // Request the value of a configuration parameter from the device
2030 //-----------------------------------------------------------------------------
RequestConfigParam(uint8 const _param)2031 void Node::RequestConfigParam
2032 (
2033 		uint8 const _param
2034 )
2035 {
2036 	if( Configuration* cc = static_cast<Configuration*>( GetCommandClass( Configuration::StaticGetCommandClassId() ) ) )
2037 	{
2038 		cc->RequestValue( 0, _param, 1, Driver::MsgQueue_Send );
2039 	}
2040 }
2041 
2042 //-----------------------------------------------------------------------------
2043 // <Node::RequestAllConfigParams>
2044 // Request the values of all known configuration parameters from the device
2045 //-----------------------------------------------------------------------------
RequestAllConfigParams(uint32 const _requestFlags)2046 bool Node::RequestAllConfigParams
2047 (
2048 		uint32 const _requestFlags
2049 )
2050 {
2051 	bool res = false;
2052 	if( Configuration* cc = static_cast<Configuration*>( GetCommandClass( Configuration::StaticGetCommandClassId() ) ) )
2053 	{
2054 		// Go through all the values in the value store, and request all those which are in the Configuration command class
2055 		for( ValueStore::Iterator it = m_values->Begin(); it != m_values->End(); ++it )
2056 		{
2057 			Value* value = it->second;
2058 			if( value->GetID().GetCommandClassId() == Configuration::StaticGetCommandClassId() && !value->IsWriteOnly() )
2059 			{
2060 				/* put the ConfigParams Request into the MsgQueue_Query queue. This is so MsgQueue_Send doesn't get backlogged with a
2061 				 * lot of ConfigParams requests, and should help speed up any user generated messages being sent out (as the MsgQueue_Send has a higher
2062 				 * priority than MsgQueue_Query
2063 				 */
2064 				res |= cc->RequestValue( _requestFlags, value->GetID().GetIndex(), 1, Driver::MsgQueue_Query );
2065 			}
2066 		}
2067 	}
2068 
2069 	return res;
2070 }
2071 
2072 //-----------------------------------------------------------------------------
2073 // <Node::RequestDynamicValues>
2074 // Request an update of all known dynamic values from the device
2075 //-----------------------------------------------------------------------------
RequestDynamicValues()2076 bool Node::RequestDynamicValues
2077 (
2078 )
2079 {
2080 	bool res = false;
2081 	for( map<uint8,CommandClass*>::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it )
2082 	{
2083 		if( !it->second->IsAfterMark() )
2084 		{
2085 			res |= it->second->RequestStateForAllInstances( CommandClass::RequestFlag_Dynamic, Driver::MsgQueue_Send );
2086 		}
2087 	}
2088 
2089 	return res;
2090 }
2091 
2092 //-----------------------------------------------------------------------------
2093 // <Node::SetLevel>
2094 // Helper method to set a device's basic level
2095 //-----------------------------------------------------------------------------
SetLevel(uint8 const _level)2096 void Node::SetLevel
2097 (
2098 		uint8 const _level
2099 )
2100 {
2101 	// Level is 0-99, with 0 = off and 99 = fully on. 255 = turn on at last level.
2102 	uint8 adjustedLevel = _level;
2103 	if( ( _level > 99 ) && ( _level < 255 ) )
2104 	{
2105 		adjustedLevel = 99;
2106 	}
2107 
2108 	if( Basic* cc = static_cast<Basic*>( GetCommandClass( Basic::StaticGetCommandClassId() ) ) )
2109 	{
2110 		cc->Set( adjustedLevel );
2111 	}
2112 }
2113 
2114 //-----------------------------------------------------------------------------
2115 // <Node::SetNodeOn>
2116 // Helper method to set a device to be on
2117 //-----------------------------------------------------------------------------
SetNodeOn()2118 void Node::SetNodeOn
2119 (
2120 )
2121 {
2122 	// Level is 0-99, with 0 = off and 99 = fully on. 255 = turn on at last level.
2123 	if( Basic* cc = static_cast<Basic*>( GetCommandClass( Basic::StaticGetCommandClassId() ) ) )
2124 	{
2125 		cc->Set( 255 );
2126 	}
2127 }
2128 
2129 //-----------------------------------------------------------------------------
2130 // <Node::SetNodeOff>
2131 // Helper method to set a device to be off
2132 //-----------------------------------------------------------------------------
SetNodeOff()2133 void Node::SetNodeOff
2134 (
2135 )
2136 {
2137 	// Level is 0-99, with 0 = off and 99 = fully on. 255 = turn on at last level.
2138 	if( Basic* cc = static_cast<Basic*>( GetCommandClass( Basic::StaticGetCommandClassId() ) ) )
2139 	{
2140 		cc->Set( 0 );
2141 	}
2142 }
2143 
2144 //-----------------------------------------------------------------------------
2145 // <Node::CreateValueID>
2146 // Helper to create a ValueID
2147 //-----------------------------------------------------------------------------
CreateValueID(ValueID::ValueGenre const _genre,uint8 const _commandClassId,uint8 const _instance,uint8 const _valueIndex,ValueID::ValueType const _type)2148 ValueID Node::CreateValueID
2149 (
2150 		ValueID::ValueGenre const _genre,
2151 		uint8 const _commandClassId,
2152 		uint8 const _instance,
2153 		uint8 const _valueIndex,
2154 		ValueID::ValueType const _type
2155 )
2156 {
2157 	return ValueID( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _type );
2158 }
2159 
2160 //-----------------------------------------------------------------------------
2161 // <Node::CreateValueBool>
2162 // Helper to create a new bool value and add it to the value store
2163 //-----------------------------------------------------------------------------
CreateValueBool(ValueID::ValueGenre const _genre,uint8 const _commandClassId,uint8 const _instance,uint8 const _valueIndex,string const & _label,string const & _units,bool const _readOnly,bool const _writeOnly,bool const _default,uint8 const _pollIntensity)2164 bool Node::CreateValueBool
2165 (
2166 		ValueID::ValueGenre const _genre,
2167 		uint8 const _commandClassId,
2168 		uint8 const _instance,
2169 		uint8 const _valueIndex,
2170 		string const& _label,
2171 		string const& _units,
2172 		bool const _readOnly,
2173 		bool const _writeOnly,
2174 		bool const _default,
2175 		uint8 const _pollIntensity
2176 )
2177 {
2178 	ValueBool* value = new ValueBool( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _pollIntensity );
2179 	ValueStore* store = GetValueStore();
2180 	if( store->AddValue( value ) )
2181 	{
2182 		value->Release();
2183 		return true;
2184 	}
2185 
2186 	value->Release();
2187 	return false;
2188 }
2189 
2190 //-----------------------------------------------------------------------------
2191 // <Node::CreateValueButton>
2192 // Helper to create a new trigger value and add it to the value store
2193 //-----------------------------------------------------------------------------
CreateValueButton(ValueID::ValueGenre const _genre,uint8 const _commandClassId,uint8 const _instance,uint8 const _valueIndex,string const & _label,uint8 const _pollIntensity)2194 bool Node::CreateValueButton
2195 (
2196 		ValueID::ValueGenre const _genre,
2197 		uint8 const _commandClassId,
2198 		uint8 const _instance,
2199 		uint8 const _valueIndex,
2200 		string const& _label,
2201 		uint8 const _pollIntensity
2202 )
2203 {
2204 	ValueButton* value = new ValueButton( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _pollIntensity );
2205 	ValueStore* store = GetValueStore();
2206 	if( store->AddValue( value ) )
2207 	{
2208 		value->Release();
2209 		return true;
2210 	}
2211 
2212 	value->Release();
2213 	return false;
2214 }
2215 
2216 //-----------------------------------------------------------------------------
2217 // <Node::CreateValueByte>
2218 // Helper to create a new byte value and add it to the value store
2219 //-----------------------------------------------------------------------------
CreateValueByte(ValueID::ValueGenre const _genre,uint8 const _commandClassId,uint8 const _instance,uint8 const _valueIndex,string const & _label,string const & _units,bool const _readOnly,bool const _writeOnly,uint8 const _default,uint8 const _pollIntensity)2220 bool Node::CreateValueByte
2221 (
2222 		ValueID::ValueGenre const _genre,
2223 		uint8 const _commandClassId,
2224 		uint8 const _instance,
2225 		uint8 const _valueIndex,
2226 		string const& _label,
2227 		string const& _units,
2228 		bool const _readOnly,
2229 		bool const _writeOnly,
2230 		uint8 const _default,
2231 		uint8 const _pollIntensity
2232 )
2233 {
2234 	ValueByte* value = new ValueByte( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _pollIntensity );
2235 	ValueStore* store = GetValueStore();
2236 	if( store->AddValue( value ) )
2237 	{
2238 		value->Release();
2239 		return true;
2240 	}
2241 
2242 	value->Release();
2243 	return false;
2244 }
2245 
2246 //-----------------------------------------------------------------------------
2247 // <Node::CreateValueDecimal>
2248 // Helper to create a new decimal value and add it to the value store
2249 //-----------------------------------------------------------------------------
CreateValueDecimal(ValueID::ValueGenre const _genre,uint8 const _commandClassId,uint8 const _instance,uint8 const _valueIndex,string const & _label,string const & _units,bool const _readOnly,bool const _writeOnly,string const & _default,uint8 const _pollIntensity)2250 bool Node::CreateValueDecimal
2251 (
2252 		ValueID::ValueGenre const _genre,
2253 		uint8 const _commandClassId,
2254 		uint8 const _instance,
2255 		uint8 const _valueIndex,
2256 		string const& _label,
2257 		string const& _units,
2258 		bool const _readOnly,
2259 		bool const _writeOnly,
2260 		string const& _default,
2261 		uint8 const _pollIntensity
2262 )
2263 {
2264 	ValueDecimal* value = new ValueDecimal( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _pollIntensity );
2265 	ValueStore* store = GetValueStore();
2266 	if( store->AddValue( value ) )
2267 	{
2268 		value->Release();
2269 		return true;
2270 	}
2271 
2272 	value->Release();
2273 	return false;
2274 }
2275 
2276 //-----------------------------------------------------------------------------
2277 // <Node::CreateValueInt>
2278 // Helper to create a new int value and add it to the value store
2279 //-----------------------------------------------------------------------------
CreateValueInt(ValueID::ValueGenre const _genre,uint8 const _commandClassId,uint8 const _instance,uint8 const _valueIndex,string const & _label,string const & _units,bool const _readOnly,bool const _writeOnly,int32 const _default,uint8 const _pollIntensity)2280 bool Node::CreateValueInt
2281 (
2282 		ValueID::ValueGenre const _genre,
2283 		uint8 const _commandClassId,
2284 		uint8 const _instance,
2285 		uint8 const _valueIndex,
2286 		string const& _label,
2287 		string const& _units,
2288 		bool const _readOnly,
2289 		bool const _writeOnly,
2290 		int32 const _default,
2291 		uint8 const _pollIntensity
2292 )
2293 {
2294 	ValueInt* value = new ValueInt( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _pollIntensity );
2295 	ValueStore* store = GetValueStore();
2296 	if( store->AddValue( value ) )
2297 	{
2298 		value->Release();
2299 		return true;
2300 	}
2301 
2302 	value->Release();
2303 	return false;
2304 }
2305 
2306 //-----------------------------------------------------------------------------
2307 // <Node::CreateValueList>
2308 // Helper to create a new list value and add it to the value store
2309 //-----------------------------------------------------------------------------
CreateValueList(ValueID::ValueGenre const _genre,uint8 const _commandClassId,uint8 const _instance,uint8 const _valueIndex,string const & _label,string const & _units,bool const _readOnly,bool const _writeOnly,uint8 const _size,vector<ValueList::Item> const & _items,int32 const _default,uint8 const _pollIntensity)2310 bool Node::CreateValueList
2311 (
2312 		ValueID::ValueGenre const _genre,
2313 		uint8 const _commandClassId,
2314 		uint8 const _instance,
2315 		uint8 const _valueIndex,
2316 		string const& _label,
2317 		string const& _units,
2318 		bool const _readOnly,
2319 		bool const _writeOnly,
2320 		uint8 const _size,
2321 		vector<ValueList::Item> const& _items,
2322 		int32 const _default,
2323 		uint8 const _pollIntensity
2324 )
2325 {
2326 	ValueList* value = new ValueList( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _items, _default, _pollIntensity, _size );
2327 	ValueStore* store = GetValueStore();
2328 	if( store->AddValue( value ) )
2329 	{
2330 		value->Release();
2331 		return true;
2332 	}
2333 
2334 	value->Release();
2335 	return false;
2336 }
2337 
2338 //-----------------------------------------------------------------------------
2339 // <Node::CreateValueRaw>
2340 // Helper to create a new raw value and add it to the value store
2341 //-----------------------------------------------------------------------------
CreateValueRaw(ValueID::ValueGenre const _genre,uint8 const _commandClassId,uint8 const _instance,uint8 const _valueIndex,string const & _label,string const & _units,bool const _readOnly,bool const _writeOnly,uint8 const * _default,uint8 const _length,uint8 const _pollIntensity)2342 bool Node::CreateValueRaw
2343 (
2344 		ValueID::ValueGenre const _genre,
2345 		uint8 const _commandClassId,
2346 		uint8 const _instance,
2347 		uint8 const _valueIndex,
2348 		string const& _label,
2349 		string const& _units,
2350 		bool const _readOnly,
2351 		bool const _writeOnly,
2352 		uint8 const* _default,
2353 		uint8 const _length,
2354 		uint8 const _pollIntensity
2355 )
2356 {
2357 	ValueRaw* value = new ValueRaw( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _length, _pollIntensity );
2358 	ValueStore* store = GetValueStore();
2359 	if( store->AddValue( value ) )
2360 	{
2361 		value->Release();
2362 		return true;
2363 	}
2364 
2365 	value->Release();
2366 	return false;
2367 }
2368 
2369 //-----------------------------------------------------------------------------
2370 // <Node::CreateValueSchedule>
2371 // Helper to create a new schedule value and add it to the value store
2372 //-----------------------------------------------------------------------------
CreateValueSchedule(ValueID::ValueGenre const _genre,uint8 const _commandClassId,uint8 const _instance,uint8 const _valueIndex,string const & _label,string const & _units,bool const _readOnly,bool const _writeOnly,uint8 const _pollIntensity)2373 bool Node::CreateValueSchedule
2374 (
2375 		ValueID::ValueGenre const _genre,
2376 		uint8 const _commandClassId,
2377 		uint8 const _instance,
2378 		uint8 const _valueIndex,
2379 		string const& _label,
2380 		string const& _units,
2381 		bool const _readOnly,
2382 		bool const _writeOnly,
2383 		uint8 const _pollIntensity
2384 )
2385 {
2386 	ValueSchedule* value = new ValueSchedule( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _pollIntensity );
2387 	ValueStore* store = GetValueStore();
2388 	if( store->AddValue( value ) )
2389 	{
2390 		value->Release();
2391 		return true;
2392 	}
2393 
2394 	value->Release();
2395 	return false;
2396 }
2397 
2398 //-----------------------------------------------------------------------------
2399 // <Node::CreateValueShort>
2400 // Helper to create a new short value and add it to the value store
2401 //-----------------------------------------------------------------------------
CreateValueShort(ValueID::ValueGenre const _genre,uint8 const _commandClassId,uint8 const _instance,uint8 const _valueIndex,string const & _label,string const & _units,bool const _readOnly,bool const _writeOnly,int16 const _default,uint8 const _pollIntensity)2402 bool Node::CreateValueShort
2403 (
2404 		ValueID::ValueGenre const _genre,
2405 		uint8 const _commandClassId,
2406 		uint8 const _instance,
2407 		uint8 const _valueIndex,
2408 		string const& _label,
2409 		string const& _units,
2410 		bool const _readOnly,
2411 		bool const _writeOnly,
2412 		int16 const _default,
2413 		uint8 const _pollIntensity
2414 )
2415 {
2416 	ValueShort* value = new ValueShort( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _pollIntensity );
2417 	ValueStore* store = GetValueStore();
2418 	if( store->AddValue( value ) )
2419 	{
2420 		value->Release();
2421 		return true;
2422 	}
2423 
2424 	value->Release();
2425 	return false;
2426 }
2427 
2428 //-----------------------------------------------------------------------------
2429 // <Node::CreateValueString>
2430 // Helper to create a new string value and add it to the value store
2431 //-----------------------------------------------------------------------------
CreateValueString(ValueID::ValueGenre const _genre,uint8 const _commandClassId,uint8 const _instance,uint8 const _valueIndex,string const & _label,string const & _units,bool const _readOnly,bool const _writeOnly,string const & _default,uint8 const _pollIntensity)2432 bool Node::CreateValueString
2433 (
2434 		ValueID::ValueGenre const _genre,
2435 		uint8 const _commandClassId,
2436 		uint8 const _instance,
2437 		uint8 const _valueIndex,
2438 		string const& _label,
2439 		string const& _units,
2440 		bool const _readOnly,
2441 		bool const _writeOnly,
2442 		string const& _default,
2443 		uint8 const _pollIntensity
2444 )
2445 {
2446 	ValueString* value = new ValueString( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _pollIntensity );
2447 	ValueStore* store = GetValueStore();
2448 	if( store->AddValue( value ) )
2449 	{
2450 		value->Release();
2451 		return true;
2452 	}
2453 
2454 	value->Release();
2455 	return false;
2456 }
2457 
2458 //-----------------------------------------------------------------------------
2459 // <Node::RemoveValueList>
2460 // Helper to remove an existing list value from the value store
2461 //-----------------------------------------------------------------------------
RemoveValueList(ValueList * _value)2462 void Node::RemoveValueList
2463 (
2464 		ValueList* _value
2465 )
2466 {
2467 	ValueStore* store = GetValueStore();
2468 	store->RemoveValue( _value->GetID().GetValueStoreKey() );
2469 }
2470 
2471 //-----------------------------------------------------------------------------
2472 // <Node::CreateValueFromXML>
2473 // Get the value object with the specified ID
2474 //-----------------------------------------------------------------------------
CreateValueFromXML(uint8 const _commandClassId,TiXmlElement const * _valueElement)2475 bool Node::CreateValueFromXML
2476 (
2477 		uint8 const _commandClassId,
2478 		TiXmlElement const* _valueElement
2479 )
2480 {
2481 	Value* value = NULL;
2482 
2483 	// Create the value
2484 	ValueID::ValueType type = Value::GetTypeEnumFromName( _valueElement->Attribute( "type" ) );
2485 
2486 	switch( type )
2487 	{
2488 		case ValueID::ValueType_Bool:		{	value = new ValueBool();		break;	}
2489 		case ValueID::ValueType_Byte:		{	value = new ValueByte();		break;	}
2490 		case ValueID::ValueType_Decimal:	{	value = new ValueDecimal();		break;	}
2491 		case ValueID::ValueType_Int:		{	value = new ValueInt();			break;	}
2492 		case ValueID::ValueType_List:		{	value = new ValueList();		break;	}
2493 		case ValueID::ValueType_Schedule:	{	value = new ValueSchedule();		break;	}
2494 		case ValueID::ValueType_Short:		{	value = new ValueShort();		break;	}
2495 		case ValueID::ValueType_String:		{	value = new ValueString();		break;	}
2496 		case ValueID::ValueType_Button:		{	value = new ValueButton();		break;	}
2497 		case ValueID::ValueType_Raw:		{	value = new ValueRaw();			break;  }
2498 		default:				{	Log::Write( LogLevel_Info, m_nodeId, "Unknown ValueType in XML: %s", _valueElement->Attribute( "type" ) ); break; }
2499 	}
2500 
2501 	if( value )
2502 	{
2503 		value->ReadXML( m_homeId, m_nodeId, _commandClassId, _valueElement );
2504 
2505 		ValueStore* store = GetValueStore();
2506 		if( store->AddValue( value ) )
2507 		{
2508 			value->Release();
2509 			return true;
2510 		}
2511 
2512 		value->Release();
2513 	}
2514 
2515 	return false;
2516 }
2517 
2518 //-----------------------------------------------------------------------------
2519 // <Node::ReadValueFromXML>
2520 // Apply XML differences to a value
2521 //-----------------------------------------------------------------------------
ReadValueFromXML(uint8 const _commandClassId,TiXmlElement const * _valueElement)2522 void Node::ReadValueFromXML
2523 (
2524 		uint8 const _commandClassId,
2525 		TiXmlElement const* _valueElement
2526 )
2527 {
2528 	int32 intVal;
2529 
2530 	ValueID::ValueGenre genre = Value::GetGenreEnumFromName( _valueElement->Attribute( "genre" ) );
2531 	ValueID::ValueType type = Value::GetTypeEnumFromName( _valueElement->Attribute( "type" ) );
2532 
2533 	uint8 instance = 0;
2534 	if( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "instance", &intVal ) )
2535 	{
2536 		instance = (uint8)intVal;
2537 	}
2538 
2539 	uint8 index = 0;
2540 	if( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "index", &intVal ) )
2541 	{
2542 		index = (uint8)intVal;
2543 	}
2544 
2545 	ValueID id = ValueID( m_homeId, m_nodeId, genre, _commandClassId, instance, index, type );
2546 
2547 	// Try to get the value from the ValueStore (everything except configuration parameters
2548 	// should already have been created when the command class instance count was read in).
2549 	// Create it if it doesn't already exist.
2550 	if( ValueStore* store = GetValueStore() )
2551 	{
2552 		if( Value* value = store->GetValue( id.GetValueStoreKey() ) )
2553 		{
2554 			value->ReadXML( m_homeId, m_nodeId, _commandClassId, _valueElement );
2555 			value->Release();
2556 		}
2557 		else
2558 		{
2559 			CreateValueFromXML( _commandClassId, _valueElement );
2560 		}
2561 	}
2562 }
2563 
2564 //-----------------------------------------------------------------------------
2565 // <Node::GetValue>
2566 // Get the value object with the specified ID
2567 //-----------------------------------------------------------------------------
GetValue(ValueID const & _id)2568 Value* Node::GetValue
2569 (
2570 		ValueID const& _id
2571 )
2572 {
2573 	// This increments the value's reference count
2574 	return GetValueStore()->GetValue( _id.GetValueStoreKey() );
2575 }
2576 
2577 //-----------------------------------------------------------------------------
2578 // <Node::GetValue>
2579 // Get the value object with the specified settings
2580 //-----------------------------------------------------------------------------
GetValue(uint8 const _commandClassId,uint8 const _instance,uint8 const _valueIndex)2581 Value* Node::GetValue
2582 (
2583 		uint8 const _commandClassId,
2584 		uint8 const _instance,
2585 		uint8 const _valueIndex
2586 )
2587 {
2588 	Value* value = NULL;
2589 	ValueStore* store = GetValueStore();
2590 	// This increments the value's reference count
2591 	value = store->GetValue( ValueID::GetValueStoreKey( _commandClassId, _instance, _valueIndex ) );
2592 	return value;
2593 }
2594 
2595 //-----------------------------------------------------------------------------
2596 // <Node::RemoveValue>
2597 // Remove the value object with the specified settings
2598 //-----------------------------------------------------------------------------
RemoveValue(uint8 const _commandClassId,uint8 const _instance,uint8 const _valueIndex)2599 bool Node::RemoveValue
2600 (
2601 		uint8 const _commandClassId,
2602 		uint8 const _instance,
2603 		uint8 const _valueIndex
2604 )
2605 {
2606 	ValueStore* store = GetValueStore();
2607 	return store->RemoveValue( ValueID::GetValueStoreKey( _commandClassId, _instance, _valueIndex ) );
2608 }
2609 
2610 //-----------------------------------------------------------------------------
2611 // <Node::GetGroup>
2612 // Get a Group from the node's map
2613 //-----------------------------------------------------------------------------
GetGroup(uint8 const _groupIdx)2614 Group* Node::GetGroup
2615 (
2616 		uint8 const _groupIdx
2617 )
2618 {
2619 	map<uint8,Group*>::iterator it = m_groups.find( _groupIdx );
2620 	if( it == m_groups.end() )
2621 	{
2622 		return NULL;
2623 	}
2624 
2625 	return it->second;
2626 }
2627 
2628 //-----------------------------------------------------------------------------
2629 // <Node::AddGroup>
2630 // Add a group into the node's map
2631 //-----------------------------------------------------------------------------
AddGroup(Group * _group)2632 void Node::AddGroup
2633 (
2634 		Group* _group
2635 )
2636 {
2637 	map<uint8,Group*>::iterator it = m_groups.find( _group->GetIdx() );
2638 	if( it != m_groups.end() )
2639 	{
2640 		// There is already a group with this id.  We will replace it.
2641 		delete it->second;
2642 		m_groups.erase( it );
2643 	}
2644 
2645 	m_groups[_group->GetIdx()] = _group;
2646 }
2647 
2648 //-----------------------------------------------------------------------------
2649 // <Node::WriteGroups>
2650 // Save the group data
2651 //-----------------------------------------------------------------------------
WriteGroups(TiXmlElement * _associationsElement)2652 void Node::WriteGroups
2653 (
2654 		TiXmlElement* _associationsElement
2655 )
2656 {
2657 	for( map<uint8,Group*>::iterator it = m_groups.begin(); it != m_groups.end(); ++it )
2658 	{
2659 		Group* group = it->second;
2660 
2661 		TiXmlElement* groupElement = new TiXmlElement( "Group" );
2662 		_associationsElement->LinkEndChild( groupElement );
2663 		group->WriteXML( groupElement );
2664 	}
2665 }
2666 
2667 //-----------------------------------------------------------------------------
2668 // <Node::GetNumGroups>
2669 // Gets the number of association groups reported by this node
2670 //-----------------------------------------------------------------------------
GetNumGroups()2671 uint8 Node::GetNumGroups
2672 (
2673 )
2674 {
2675 	return (uint8) m_groups.size();
2676 }
2677 
2678 //-----------------------------------------------------------------------------
2679 // <Node::GetAssociations>
2680 // Gets the associations for a group
2681 //-----------------------------------------------------------------------------
GetAssociations(uint8 const _groupIdx,uint8 ** o_associations)2682 uint32 Node::GetAssociations
2683 (
2684 		uint8 const _groupIdx,
2685 		uint8** o_associations
2686 )
2687 {
2688 	uint32 numAssociations = 0;
2689 	if( Group* group = GetGroup( _groupIdx ) )
2690 	{
2691 		numAssociations = group->GetAssociations( o_associations );
2692 	}
2693 
2694 	return numAssociations;
2695 }
2696 
2697 //-----------------------------------------------------------------------------
2698 // <Node::GetAssociations>
2699 // Gets the associations for a group
2700 //-----------------------------------------------------------------------------
GetAssociations(uint8 const _groupIdx,InstanceAssociation ** o_associations)2701 uint32 Node::GetAssociations
2702 (
2703 		uint8 const _groupIdx,
2704 		InstanceAssociation** o_associations
2705 )
2706 {
2707 	uint32 numAssociations = 0;
2708 	if( Group* group = GetGroup( _groupIdx ) )
2709 	{
2710 		numAssociations = group->GetAssociations( o_associations );
2711 	}
2712 
2713 	return numAssociations;
2714 }
2715 
2716 //-----------------------------------------------------------------------------
2717 // <Node::GetMaxAssociations>
2718 // Gets the maximum number of associations for a group
2719 //-----------------------------------------------------------------------------
GetMaxAssociations(uint8 const _groupIdx)2720 uint8 Node::GetMaxAssociations
2721 (
2722 		uint8 const _groupIdx
2723 )
2724 {
2725 	uint8 maxAssociations = 0;
2726 	if( Group* group = GetGroup( _groupIdx ) )
2727 	{
2728 		maxAssociations = group->GetMaxAssociations();
2729 	}
2730 
2731 	return maxAssociations;
2732 }
2733 
2734 //-----------------------------------------------------------------------------
2735 // <Node::GetGroupLabel>
2736 // Gets the label for a particular group
2737 //-----------------------------------------------------------------------------
GetGroupLabel(uint8 const _groupIdx)2738 string Node::GetGroupLabel
2739 (
2740 		uint8 const _groupIdx
2741 )
2742 {
2743 	string label = "";
2744 	if( Group* group = GetGroup( _groupIdx ) )
2745 	{
2746 		label = group->GetLabel();
2747 	}
2748 
2749 	return label;
2750 }
2751 
2752 //-----------------------------------------------------------------------------
2753 // <Node::AddAssociation>
2754 // Adds a node to an association group
2755 //-----------------------------------------------------------------------------
AddAssociation(uint8 const _groupIdx,uint8 const _targetNodeId,uint8 const _instance)2756 void Node::AddAssociation
2757 (
2758 		uint8 const _groupIdx,
2759 		uint8 const _targetNodeId,
2760 		uint8 const _instance
2761 )
2762 {
2763 	if( Group* group = GetGroup( _groupIdx ) )
2764 	{
2765 		group->AddAssociation( _targetNodeId, _instance  );
2766 	}
2767 }
2768 
2769 //-----------------------------------------------------------------------------
2770 // <Node::RemoveAssociation>
2771 // Removes a node from an association group
2772 //-----------------------------------------------------------------------------
RemoveAssociation(uint8 const _groupIdx,uint8 const _targetNodeId,uint8 const _instance)2773 void Node::RemoveAssociation
2774 (
2775 		uint8 const _groupIdx,
2776 		uint8 const _targetNodeId,
2777 		uint8 const _instance
2778 )
2779 {
2780 	if( Group* group = GetGroup( _groupIdx ) )
2781 	{
2782 		group->RemoveAssociation( _targetNodeId, _instance );
2783 	}
2784 }
2785 
2786 //-----------------------------------------------------------------------------
2787 // <Node::AutoAssociate>
2788 // Automatically associate the controller with certain groups
2789 //-----------------------------------------------------------------------------
AutoAssociate()2790 void Node::AutoAssociate
2791 (
2792 )
2793 {
2794 	bool autoAssociate = false;
2795 	Options::Get()->GetOptionAsBool( "Associate", &autoAssociate );
2796 	if( autoAssociate )
2797 	{
2798 		// Try to automatically associate with any groups that have been flagged.
2799 		uint8 controllerNodeId = GetDriver()->GetControllerNodeId();
2800 
2801 		for( map<uint8,Group*>::iterator it = m_groups.begin(); it != m_groups.end(); ++it )
2802 		{
2803 			Group* group = it->second;
2804 			if( group->IsAuto() && !group->Contains( controllerNodeId ) )
2805 			{
2806 				// Associate the controller into the group
2807 				Log::Write( LogLevel_Info, m_nodeId, "Adding the controller to group %d (%s) of node %d", group->GetIdx(), group->GetLabel().c_str(), GetNodeId() );
2808 				group->AddAssociation( controllerNodeId );
2809 			}
2810 		}
2811 	}
2812 }
2813 
2814 //-----------------------------------------------------------------------------
2815 // <Node::GetDriver>
2816 // Get a pointer to our driver
2817 //-----------------------------------------------------------------------------
GetDriver() const2818 Driver* Node::GetDriver
2819 (
2820 )const
2821 {
2822 	return( Manager::Get()->GetDriver( m_homeId ) );
2823 }
2824 
2825 //-----------------------------------------------------------------------------
2826 // Device Classes
2827 //-----------------------------------------------------------------------------
2828 
2829 //-----------------------------------------------------------------------------
2830 // <Node::GetEndPointDeviceClassLabel>
2831 // Use the device class data to get a label for a MultiChannel EndPoint.
2832 //-----------------------------------------------------------------------------
GetEndPointDeviceClassLabel(uint8 const _generic,uint8 const _specific)2833 string Node::GetEndPointDeviceClassLabel
2834 (
2835 		uint8 const _generic,
2836 		uint8 const _specific
2837 )
2838 {
2839 	char str[32];
2840 	string label;
2841 
2842 	snprintf( str, sizeof(str), "Generic 0x%.2x Specific 0x%.2x", _generic, _specific );
2843 	label = str;
2844 
2845 	// Read in the device class data if it has not been read already.
2846 	if( !s_deviceClassesLoaded )
2847 	{
2848 		ReadDeviceClasses();
2849 	}
2850 
2851 	// Get the Generic device class label
2852 	map<uint8,GenericDeviceClass*>::iterator git = s_genericDeviceClasses.find( _generic );
2853 	if( git != s_genericDeviceClasses.end() )
2854 	{
2855 		GenericDeviceClass* genericDeviceClass = git->second;
2856 		label = genericDeviceClass->GetLabel();
2857 
2858 		// Override with any specific device class label
2859 		if( DeviceClass* specificDeviceClass = genericDeviceClass->GetSpecificDeviceClass( _specific ) )
2860 		{
2861 			label = specificDeviceClass->GetLabel();
2862 		}
2863 	}
2864 
2865 	return label;
2866 }
2867 
2868 //-----------------------------------------------------------------------------
2869 // <Node::SetDeviceClasses>
2870 // Set the device class data for the node
2871 //-----------------------------------------------------------------------------
SetDeviceClasses(uint8 const _basic,uint8 const _generic,uint8 const _specific)2872 bool Node::SetDeviceClasses
2873 (
2874 		uint8 const _basic,
2875 		uint8 const _generic,
2876 		uint8 const _specific
2877 )
2878 {
2879 	m_basic = _basic;
2880 	m_generic = _generic;
2881 	m_specific = _specific;
2882 
2883 	// Read in the device class data if it has not been read already.
2884 	if( !s_deviceClassesLoaded )
2885 	{
2886 		ReadDeviceClasses();
2887 	}
2888 
2889 	// Get the basic device class label
2890 	map<uint8,string>::iterator bit = s_basicDeviceClasses.find( _basic );
2891 	if( bit != s_basicDeviceClasses.end() )
2892 	{
2893 		m_type = bit->second;
2894 		Log::Write( LogLevel_Info, m_nodeId, "  Basic device class    (0x%.2x) - %s", m_basic, m_type.c_str() );
2895 	}
2896 	else
2897 	{
2898 		Log::Write( LogLevel_Info, m_nodeId, "  Basic device class unknown" );
2899 	}
2900 
2901 	// Apply any Generic device class data
2902 	uint8 basicMapping = 0;
2903 	map<uint8,GenericDeviceClass*>::iterator git = s_genericDeviceClasses.find( _generic );
2904 	if( git != s_genericDeviceClasses.end() )
2905 	{
2906 		GenericDeviceClass* genericDeviceClass = git->second;
2907 		m_type = genericDeviceClass->GetLabel();
2908 
2909 		Log::Write( LogLevel_Info, m_nodeId, "  Generic device Class  (0x%.2x) - %s", m_generic, m_type.c_str() );
2910 
2911 		// Add the mandatory command classes for this generic class type
2912 		AddMandatoryCommandClasses( genericDeviceClass->GetMandatoryCommandClasses() );
2913 
2914 		// Get the command class that COMMAND_CLASS_BASIC maps to.
2915 		basicMapping = genericDeviceClass->GetBasicMapping();
2916 
2917 		// Apply any Specific device class data
2918 		if( DeviceClass* specificDeviceClass = genericDeviceClass->GetSpecificDeviceClass( _specific ) )
2919 		{
2920 			m_type = specificDeviceClass->GetLabel();
2921 
2922 			Log::Write( LogLevel_Info, m_nodeId, "  Specific device class (0x%.2x) - %s", m_specific, m_type.c_str() );
2923 
2924 			// Add the mandatory command classes for this specific class type
2925 			AddMandatoryCommandClasses( specificDeviceClass->GetMandatoryCommandClasses() );
2926 
2927 			if( specificDeviceClass->GetBasicMapping() )
2928 			{
2929 				// Override the generic device class basic mapping with the specific device class one.
2930 				basicMapping = specificDeviceClass->GetBasicMapping();
2931 			}
2932 		}
2933 		else
2934 		{
2935 			Log::Write( LogLevel_Info, m_nodeId, "  No specific device class defined" );
2936 		}
2937 	}
2938 	else
2939 	{
2940 		Log::Write( LogLevel_Info, m_nodeId, "  No generic or specific device classes defined" );
2941 	}
2942 
2943 	// Deal with sleeping devices
2944 	if( !m_listening && !IsFrequentListeningDevice())
2945 	{
2946 		// Device does not always listen, so we need the WakeUp handler.  We can't
2947 		// wait for the command class list because the request for the command
2948 		// classes may need to go in the wakeup queue itself!
2949 		if( CommandClass* pCommandClass = AddCommandClass( WakeUp::StaticGetCommandClassId() ) )
2950 		{
2951 			pCommandClass->SetInstance( 1 );
2952 		}
2953 	}
2954 
2955 	// Apply any COMMAND_CLASS_BASIC remapping
2956 	if( Basic* cc = static_cast<Basic*>( GetCommandClass( Basic::StaticGetCommandClassId() ) ) )
2957 	{
2958 		cc->SetMapping( basicMapping );
2959 	}
2960 
2961 	// Write the mandatory command classes to the log
2962 	if( !m_commandClassMap.empty() )
2963 	{
2964 		map<uint8,CommandClass*>::const_iterator cit;
2965 
2966 		Log::Write( LogLevel_Info, m_nodeId, "  Mandatory Command Classes for Node %d:", m_nodeId );
2967 		bool reportedClasses = false;
2968 		for( cit = m_commandClassMap.begin(); cit != m_commandClassMap.end(); ++cit )
2969 		{
2970 			if( !cit->second->IsAfterMark() && cit->second->GetCommandClassId() != NoOperation::StaticGetCommandClassId() )
2971 			{
2972 				Log::Write( LogLevel_Info, m_nodeId, "    %s", cit->second->GetCommandClassName().c_str() );
2973 				reportedClasses = true;
2974 			}
2975 		}
2976 		if( !reportedClasses )
2977 		{
2978 			Log::Write( LogLevel_Info, m_nodeId, "    None" );
2979 		}
2980 
2981 		Log::Write( LogLevel_Info, m_nodeId, "  Mandatory Command Classes controlled by Node %d:", m_nodeId );
2982 		reportedClasses = false;
2983 		for( cit = m_commandClassMap.begin(); cit != m_commandClassMap.end(); ++cit )
2984 		{
2985 			if( cit->second->IsAfterMark() )
2986 			{
2987 				Log::Write( LogLevel_Info, m_nodeId, "    %s", cit->second->GetCommandClassName().c_str() );
2988 				reportedClasses = true;
2989 			}
2990 		}
2991 		if( !reportedClasses )
2992 		{
2993 			Log::Write( LogLevel_Info, m_nodeId, "    None" );
2994 		}
2995 	}
2996 
2997 	return true;
2998 }
2999 
3000 //-----------------------------------------------------------------------------
3001 // <Node::SetPlusDeviceClasses>
3002 // Set the device class data for the node based on the Zwave+ info report
3003 //-----------------------------------------------------------------------------
SetPlusDeviceClasses(uint8 const _role,uint8 const _nodeType,uint16 const _deviceType)3004 bool Node::SetPlusDeviceClasses
3005 (
3006 		uint8 const _role,
3007 		uint8 const _nodeType,
3008 		uint16 const _deviceType
3009 )
3010 {
3011 	if ( m_nodePlusInfoReceived )
3012 	{
3013 		return false; // already set
3014 	}
3015 
3016 	if( !s_deviceClassesLoaded )
3017 	{
3018 		ReadDeviceClasses();
3019 	}
3020 
3021 	m_nodePlusInfoReceived = true;
3022 	m_role = _role;
3023 	m_deviceType = _deviceType;
3024 	m_nodeType = _nodeType;
3025 
3026 	Log::Write (LogLevel_Info, m_nodeId, "ZWave+ Info Received from Node %d", m_nodeId);
3027 	map<uint8,DeviceClass*>::iterator nit = s_nodeTypes.find( m_nodeType );
3028 	if (nit != s_nodeTypes.end())
3029 	{
3030 		DeviceClass* deviceClass = nit->second;
3031 
3032 		Log::Write( LogLevel_Info, m_nodeId, "  Zwave+ Node Type  (0x%.2x) - %s. Mandatory Command Classes:", m_nodeType, deviceClass->GetLabel().c_str() );
3033 		uint8 const *_commandClasses = deviceClass->GetMandatoryCommandClasses();
3034 
3035 		/* no CommandClasses to add */
3036 		if (_commandClasses != NULL)
3037 		{
3038 			int i = 0;
3039 			while (uint8 ccid = _commandClasses[i++])
3040 			{
3041 				if( CommandClasses::IsSupported( ccid ) )
3042 				{
3043 					Log::Write( LogLevel_Info, m_nodeId, "    %s", CommandClasses::GetName(ccid).c_str());
3044 				}
3045 				else
3046 				{
3047 					Log::Write( LogLevel_Info, m_nodeId, "    0x%.2x (Not Supported)", ccid);
3048 				}
3049 			}
3050 
3051 
3052 			// Add the mandatory command classes for this Roletype
3053 			AddMandatoryCommandClasses( deviceClass->GetMandatoryCommandClasses() );
3054 		}
3055 		else
3056 		{
3057 			Log::Write( LogLevel_Info, m_nodeId, "    NONE");
3058 		}
3059 	}
3060 	else
3061 	{
3062 		Log::Write (LogLevel_Warning, m_nodeId, "  Zwave+ Node Type  (0x%.2x) - NOT FOUND. No Mandatory Command Classes Loaded:", m_nodeType);
3063 	}
3064 
3065 
3066 	// Apply any Zwave+ device class data
3067 	map<uint16,DeviceClass*>::iterator dit = s_deviceTypeClasses.find( _deviceType );
3068 	if( dit != s_deviceTypeClasses.end() )
3069 	{
3070 		DeviceClass* deviceClass = dit->second;
3071 		// m_type = deviceClass->GetLabel(); // do we what to update the type with the zwave+ info??
3072 
3073 		Log::Write( LogLevel_Info, m_nodeId, "  Zwave+ Device Type  (0x%.2x) - %s. Mandatory Command Classes:", _deviceType, deviceClass->GetLabel().c_str() );
3074 		uint8 const *_commandClasses = deviceClass->GetMandatoryCommandClasses();
3075 
3076 		/* no CommandClasses to add */
3077 		if (_commandClasses != NULL)
3078 		{
3079 			int i = 0;
3080 			while (uint8 ccid = _commandClasses[i++])
3081 			{
3082 				if( CommandClasses::IsSupported( ccid ) )
3083 				{
3084 					Log::Write( LogLevel_Info, m_nodeId, "    %s", CommandClasses::GetName(ccid).c_str());
3085 				}
3086 				else
3087 				{
3088 					Log::Write( LogLevel_Info, m_nodeId, "    0x%.2x (Not Supported)", ccid);
3089 				}
3090 			}
3091 
3092 
3093 			// Add the mandatory command classes for this device class type
3094 			AddMandatoryCommandClasses( deviceClass->GetMandatoryCommandClasses() );
3095 		}
3096 		else
3097 		{
3098 			Log::Write( LogLevel_Info, m_nodeId, "    NONE");
3099 		}
3100 	}
3101 	else
3102 	{
3103 		Log::Write (LogLevel_Warning, m_nodeId, "  Zwave+ Device Type  (0x%.2x) - NOT FOUND. No Mandatory Command Classes Loaded:", m_nodeType);
3104 	}
3105 
3106 	// Apply any Role device class data
3107 	map<uint8,DeviceClass*>::iterator rit = s_roleDeviceClasses.find( _role );
3108 	if( rit != s_roleDeviceClasses.end() )
3109 	{
3110 		DeviceClass* roleDeviceClass = rit->second;
3111 
3112 		Log::Write( LogLevel_Info, m_nodeId, "  ZWave+ Role Type  (0x%.2x) - %s", m_generic, roleDeviceClass->GetLabel().c_str() );
3113 
3114 		uint8 const *_commandClasses = roleDeviceClass->GetMandatoryCommandClasses();
3115 
3116 		/* no CommandClasses to add */
3117 		if (_commandClasses != NULL)
3118 		{
3119 			int i = 0;
3120 			while (uint8 ccid = _commandClasses[i++])
3121 			{
3122 				if( CommandClasses::IsSupported( ccid ) )
3123 				{
3124 					Log::Write( LogLevel_Info, m_nodeId, "    %s", CommandClasses::GetName(ccid).c_str());
3125 				}
3126 				else
3127 				{
3128 					Log::Write( LogLevel_Info, m_nodeId, "    0x%.2x (Not Supported)", ccid);
3129 				}
3130 			}
3131 
3132 
3133 			// Add the mandatory command classes for this role class type
3134 			AddMandatoryCommandClasses( roleDeviceClass->GetMandatoryCommandClasses() );
3135 		}
3136 		else
3137 		{
3138 			Log::Write( LogLevel_Info, m_nodeId, "    NONE");
3139 		}
3140 
3141 	}
3142 	else
3143 	{
3144 		Log::Write (LogLevel_Warning, m_nodeId, "  ZWave+ Role Type  (0x%.2x) - NOT FOUND. No Mandatory Command Classes Loaded:", m_nodeType);
3145 	}
3146 
3147 
3148 	return true;
3149 }
3150 
3151 //-----------------------------------------------------------------------------
3152 // <Node::AddMandatoryCommandClasses>
3153 // Add mandatory command classes to the node
3154 //-----------------------------------------------------------------------------
AddMandatoryCommandClasses(uint8 const * _commandClasses)3155 bool Node::AddMandatoryCommandClasses
3156 (
3157 		uint8 const* _commandClasses
3158 )
3159 {
3160 	if( NULL == _commandClasses )
3161 	{
3162 		// No command classes to add
3163 		return false;
3164 	}
3165 
3166 	int i=0;
3167 	bool afterMark = false;
3168 	while( uint8 cc = _commandClasses[i++] )
3169 	{
3170 		if( cc == 0xef )
3171 		{
3172 			// COMMAND_CLASS_MARK.
3173 			// Marks the end of the list of supported command classes.  The remaining classes
3174 			// are those that can be controlled by this device, which we can ignore.
3175 			afterMark = true;
3176 			continue;
3177 		}
3178 
3179 		if( CommandClasses::IsSupported( cc ) )
3180 		{
3181 			if (Security::StaticGetCommandClassId() == cc && !GetDriver()->isNetworkKeySet()) {
3182 				Log::Write(LogLevel_Warning, m_nodeId, "Security Command Class Cannot be Enabled - NetworkKey is not set");
3183 				continue;
3184 			}
3185 
3186 			if( CommandClass* commandClass = AddCommandClass( cc ) )
3187 			{
3188 				// If this class came after the COMMAND_CLASS_MARK, then we do not create values.
3189 				if( afterMark )
3190 				{
3191 					commandClass->SetAfterMark();
3192 				}
3193 
3194 				// Start with an instance count of one.  If the device supports COMMMAND_CLASS_MULTI_INSTANCE
3195 				// then some command class instance counts will increase.
3196 				commandClass->SetInstance( 1 );
3197 			}
3198 		}
3199 	}
3200 
3201 	return true;
3202 }
3203 
3204 //-----------------------------------------------------------------------------
3205 // <Node::ReadDeviceClasses>
3206 // Read the static device class data from the device_classes.xml file
3207 //-----------------------------------------------------------------------------
ReadDeviceClasses()3208 void Node::ReadDeviceClasses
3209 (
3210 )
3211 {
3212 	// Load the XML document that contains the device class information
3213 	string configPath;
3214 	Options::Get()->GetOptionAsString( "ConfigPath", &configPath );
3215 
3216 	string filename =  configPath + string("device_classes.xml");
3217 
3218 	TiXmlDocument doc;
3219 	if( !doc.LoadFile( filename.c_str(), TIXML_ENCODING_UTF8 ) )
3220 	{
3221 		Log::Write( LogLevel_Info, "Failed to load device_classes.xml" );
3222 		Log::Write( LogLevel_Info, "Check that the config path provided when creating the Manager points to the correct location." );
3223 		return;
3224 	}
3225 
3226 	TiXmlElement const* deviceClassesElement = doc.RootElement();
3227 
3228 	// Read the basic and generic device classes
3229 	TiXmlElement const* child = deviceClassesElement->FirstChildElement();
3230 	while( child )
3231 	{
3232 		char const* str = child->Value();
3233 		if( str )
3234 		{
3235 			char const* keyStr = child->Attribute( "key" );
3236 			if( keyStr )
3237 			{
3238 				char* pStop;
3239 				uint16 key = (uint16)strtol( keyStr, &pStop, 16 );
3240 
3241 				if( !strcmp( str, "Generic" ) )
3242 				{
3243 					s_genericDeviceClasses[key] = new GenericDeviceClass( child );
3244 				}
3245 				else if( !strcmp( str, "Basic" ) )
3246 				{
3247 					char const* label = child->Attribute( "label" );
3248 					if( label )
3249 					{
3250 						s_basicDeviceClasses[key] = label;
3251 					}
3252 				}
3253 				else if( !strcmp( str, "Role" ) )
3254 				{
3255 					s_roleDeviceClasses[key] = new DeviceClass( child );
3256 				}
3257 				else if( !strcmp( str, "DeviceType" ) )
3258 				{
3259 					s_deviceTypeClasses[key] = new DeviceClass( child );
3260 				}
3261 				else if (!strcmp( str, "NodeType" ) )
3262 				{
3263 					s_nodeTypes[key] = new DeviceClass( child );
3264 				}
3265 			}
3266 		}
3267 
3268 		child = child->NextSiblingElement();
3269 	}
3270 
3271 	s_deviceClassesLoaded = true;
3272 }
3273 
3274 //-----------------------------------------------------------------------------
3275 // <Node::GetNoderStatistics>
3276 // Return driver statistics
3277 //-----------------------------------------------------------------------------
GetNodeStatistics(NodeData * _data)3278 void Node::GetNodeStatistics
3279 (
3280 		NodeData* _data
3281 )
3282 {
3283 	_data->m_sentCnt = m_sentCnt;
3284 	_data->m_sentFailed = m_sentFailed;
3285 	_data->m_retries = m_retries;
3286 	_data->m_receivedCnt = m_receivedCnt;
3287 	_data->m_receivedDups = m_receivedDups;
3288 	_data->m_receivedUnsolicited = m_receivedUnsolicited;
3289 	_data->m_lastRequestRTT = m_lastRequestRTT;
3290 	_data->m_lastResponseRTT = m_lastResponseRTT;
3291 	_data->m_sentTS = m_sentTS.GetAsString();
3292 	_data->m_receivedTS = m_receivedTS.GetAsString();
3293 	_data->m_averageRequestRTT = m_averageRequestRTT;
3294 	_data->m_averageResponseRTT = m_averageResponseRTT;
3295 	_data->m_quality = m_quality;
3296 	memcpy( _data->m_lastReceivedMessage, m_lastReceivedMessage, sizeof(m_lastReceivedMessage) );
3297 	for( map<uint8,CommandClass*>::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it )
3298 	{
3299 		CommandClassData ccData;
3300 		ccData.m_commandClassId = it->second->GetCommandClassId();
3301 		ccData.m_sentCnt = it->second->GetSentCnt();
3302 		ccData.m_receivedCnt = it->second->GetReceivedCnt();
3303 		_data->m_ccData.push_back( ccData );
3304 	}
3305 }
3306 
3307 //-----------------------------------------------------------------------------
3308 // <DeviceClass::DeviceClass>
3309 // Constructor
3310 //-----------------------------------------------------------------------------
DeviceClass(TiXmlElement const * _el)3311 Node::DeviceClass::DeviceClass
3312 (
3313 		TiXmlElement const* _el
3314 ):
3315 m_mandatoryCommandClasses(NULL),
3316 m_basicMapping(0)
3317 {
3318 	char const* str = _el->Attribute( "label" );
3319 	if( str )
3320 	{
3321 		m_label = str;
3322 	}
3323 
3324 	str = _el->Attribute( "command_classes" );
3325 	if( str )
3326 	{
3327 		// Parse the comma delimted command class
3328 		// list into a temporary vector.
3329 		vector<uint8> ccs;
3330 		char* pos = const_cast<char*>(str);
3331 		while( *pos )
3332 		{
3333 			ccs.push_back( (uint8)strtol( pos, &pos, 16 ) );
3334 			if( (*pos) == ',' )
3335 			{
3336 				++pos;
3337 			}
3338 		}
3339 
3340 		// Copy the vector contents into an array.
3341 		size_t numCCs = ccs.size();
3342 		m_mandatoryCommandClasses = new uint8[numCCs+1];
3343 		m_mandatoryCommandClasses[numCCs] = 0;	// Zero terminator
3344 
3345 		for( uint32 i=0; i<numCCs; ++i )
3346 		{
3347 			m_mandatoryCommandClasses[i] = ccs[i];
3348 		}
3349 	}
3350 
3351 	str = _el->Attribute( "basic" );
3352 	if( str )
3353 	{
3354 		char* pStop;
3355 		m_basicMapping = (uint8)strtol( str, &pStop, 16 );
3356 	}
3357 }
3358 
3359 //-----------------------------------------------------------------------------
3360 // <Node::GenericDeviceClass::GenericDeviceClass>
3361 // Constructor
3362 //-----------------------------------------------------------------------------
GenericDeviceClass(TiXmlElement const * _el)3363 Node::GenericDeviceClass::GenericDeviceClass
3364 (
3365 		TiXmlElement const* _el
3366 ):
3367 DeviceClass( _el )
3368 {
3369 	// Add any specific device classes
3370 	TiXmlElement const* child = _el->FirstChildElement();
3371 	while( child )
3372 	{
3373 		char const* str = child->Value();
3374 		if( str && !strcmp( str, "Specific" ) )
3375 		{
3376 			char const* keyStr = child->Attribute( "key" );
3377 			if( keyStr )
3378 			{
3379 				char* pStop;
3380 				uint8 key = (uint8)strtol( keyStr, &pStop, 16 );
3381 
3382 				m_specificDeviceClasses[key] = new DeviceClass( child );
3383 			}
3384 		}
3385 
3386 		child = child->NextSiblingElement();
3387 	}
3388 }
3389 
3390 //-----------------------------------------------------------------------------
3391 // <Node::GenericDeviceClass::~GenericDeviceClass>
3392 // Destructor
3393 //-----------------------------------------------------------------------------
~GenericDeviceClass()3394 Node::GenericDeviceClass::~GenericDeviceClass
3395 (
3396 )
3397 {
3398 	while( !m_specificDeviceClasses.empty() )
3399 	{
3400 		map<uint8,DeviceClass*>::iterator it = m_specificDeviceClasses.begin();
3401 		delete it->second;
3402 		m_specificDeviceClasses.erase( it );
3403 	}
3404 }
3405 
3406 //-----------------------------------------------------------------------------
3407 // <Node::GenericDeviceClass::GetSpecificDeviceClass>
3408 // Get a specific device class object
3409 //-----------------------------------------------------------------------------
GetSpecificDeviceClass(uint8 const & _specific)3410 Node::DeviceClass* Node::GenericDeviceClass::GetSpecificDeviceClass
3411 (
3412 		uint8 const& _specific
3413 )
3414 {
3415 	map<uint8,DeviceClass*>::iterator it = m_specificDeviceClasses.find( _specific );
3416 	if( it != m_specificDeviceClasses.end() )
3417 	{
3418 		return it->second;
3419 	}
3420 
3421 	return NULL;
3422 }
3423 
3424 //-----------------------------------------------------------------------------
3425 // <Node::GenerateNonceKey>
3426 // Generate a NONCE key for this node
3427 //-----------------------------------------------------------------------------
GenerateNonceKey()3428 uint8 *Node::GenerateNonceKey() {
3429 	uint8 idx = this->m_lastnonce;
3430 
3431 	/* The first byte must be unique and non-zero.  The others are random.
3432 	   Per Numerical Recipes in C its best to use the high-order byte.  The
3433 	   floating point calculation here doesn't assume the size of the random
3434 	   integer, otherwise we could just shift the high byte over.
3435 	*/
3436 	uint8 match = 0;
3437 	do {
3438 		this->m_nonces[idx][0] = 1 + (uint8) (255.0 * rand() / (RAND_MAX + 1.0));
3439 		match = 0;
3440 		for (int i = 0; i < 8; i++) {
3441 			if (i == idx) {
3442 				continue;
3443 			}
3444 			if (this->m_nonces[idx][0] == this->m_nonces[i][0]) {
3445 				match = 1;
3446 			}
3447 		}
3448 	} while (match);
3449 
3450 	/* The other bytes have no restrictions. */
3451 	for (int i = 1; i < 8; i++) {
3452 		this->m_nonces[idx][i] = (int) (256.0 * rand() / (RAND_MAX + 1.0));
3453 	}
3454 
3455 	this->m_lastnonce++;
3456 	if (this->m_lastnonce >= 8)
3457 		this->m_lastnonce = 0;
3458 	for (uint8 i = 0; i < 8; i++) {
3459 		PrintHex("NONCES", (const uint8_t*)this->m_nonces[i], 8);
3460 	}
3461 	return &this->m_nonces[idx][0];
3462 }
3463 //-----------------------------------------------------------------------------
3464 // <Node::GetNonceKey>
3465 // Get a NONCE key for this node that matches the nonceid.
3466 //-----------------------------------------------------------------------------
3467 
GetNonceKey(uint32 nonceid)3468 uint8 *Node::GetNonceKey(uint32 nonceid) {
3469 	for (uint8 i = 0; i < 8; i++) {
3470 		/* make sure the nonceid matches the first byte of our stored Nonce */
3471 		if (nonceid == this->m_nonces[i][0]) {
3472 			return &this->m_nonces[i][0];
3473 		}
3474 	}
3475 	Log::Write(LogLevel_Warning, m_nodeId, "A Nonce with id %x does not exist", nonceid);
3476 	for (uint8 i = 0; i < 8; i++) {
3477 		PrintHex("NONCES", (const uint8_t*)this->m_nonces[i], 8);
3478 	}
3479 	return NULL;
3480 }
3481 
3482 //-----------------------------------------------------------------------------
3483 // <Node::GetDeviceTypeString>
3484 // Get the ZWave+ DeviceType as a String
3485 //-----------------------------------------------------------------------------
GetDeviceTypeString()3486 string Node::GetDeviceTypeString() {
3487 
3488 	if( !s_deviceClassesLoaded )
3489 	{
3490 		ReadDeviceClasses();
3491 	}
3492 	map<uint16,DeviceClass*>::iterator nit = s_deviceTypeClasses.find( m_deviceType );
3493 	if (nit != s_deviceTypeClasses.end())
3494 	{
3495 		DeviceClass* deviceClass = nit->second;
3496 		return deviceClass->GetLabel();
3497 	}
3498 	return "";
3499 }
3500 //-----------------------------------------------------------------------------
3501 // <Node::GetRoleTypeString>
3502 // Get the ZWave+ RoleType as a String
3503 //-----------------------------------------------------------------------------
GetRoleTypeString()3504 string Node::GetRoleTypeString() {
3505 	if( !s_deviceClassesLoaded )
3506 	{
3507 		ReadDeviceClasses();
3508 	}
3509 	map<uint8,DeviceClass*>::iterator nit = s_roleDeviceClasses.find( m_role );
3510 	if (nit != s_roleDeviceClasses.end())
3511 	{
3512 		DeviceClass* deviceClass = nit->second;
3513 		return deviceClass->GetLabel();
3514 	}
3515 	return "";
3516 }
3517 //-----------------------------------------------------------------------------
3518 // <Node::GetRoleTypeString>
3519 // Get the ZWave+ NodeType as a String
3520 //-----------------------------------------------------------------------------
GetNodeTypeString()3521 string Node::GetNodeTypeString() {
3522 	if( !s_deviceClassesLoaded )
3523 	{
3524 		ReadDeviceClasses();
3525 	}
3526 	map<uint8,DeviceClass*>::iterator nit = s_nodeTypes.find( m_nodeType );
3527 	if (nit != s_nodeTypes.end())
3528 	{
3529 		DeviceClass* deviceClass = nit->second;
3530 		return deviceClass->GetLabel();
3531 	}
3532 	return "";
3533 }
3534 
3535 //-----------------------------------------------------------------------------
3536 // <Node::GetRoleTypeString>
3537 // Get the ZWave+ NodeType as a String
3538 //-----------------------------------------------------------------------------
IsNodeReset()3539 bool Node::IsNodeReset()
3540 {
3541 	DeviceResetLocally *drl = static_cast<DeviceResetLocally *>(GetCommandClass(DeviceResetLocally::StaticGetCommandClassId()));
3542 	if (drl)
3543 		return drl->IsDeviceReset();
3544 	else return false;
3545 
3546 
3547 }
3548