//-----------------------------------------------------------------------------
//
//	Node.h
//
//	A node in the Z-Wave network
//
//	Copyright (c) 2010 Mal Lansell <openzwave@lansell.org>
//
//	SOFTWARE NOTICE AND LICENSE
//
//	This file is part of OpenZWave.
//
//	OpenZWave is free software: you can redistribute it and/or modify
//	it under the terms of the GNU Lesser General Public License as published
//	by the Free Software Foundation, either version 3 of the License,
//	or (at your option) any later version.
//
//	OpenZWave is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU Lesser General Public License for more details.
//
//	You should have received a copy of the GNU Lesser General Public License
//	along with OpenZWave.  If not, see <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------

#ifndef _Node_H
#define _Node_H

#include <string>
#include <vector>
#include <list>
#include <map>
#include "Defs.h"
#include "value_classes/ValueID.h"
#include "value_classes/ValueList.h"
#include "Msg.h"
#include "platform/TimeStamp.h"
#include "Group.h"

class TiXmlElement;

namespace OpenZWave
{
	class CommandClass;
	class Driver;
	class Group;
	class ValueStore;
	class Value;
	class ValueBool;
	class ValueButton;
	class ValueByte;
	class ValueDecimal;
	class ValueInt;
	class ValueSchedule;
	class ValueShort;
	class ValueString;
	class Mutex;

	/** \brief The Node class describes a Z-Wave node object...typically a device on the
	 *  Z-Wave network.
	 */
	class Node
	{
			friend class Manager;
			friend class Driver;
			friend class Group;
			friend class Value;
			friend class ValueButton;
			friend class Alarm;
			friend class Association;
			friend class AssociationCommandConfiguration;
			friend class Basic;
			friend class Battery;
			friend class ClimateControlSchedule;
			friend class Clock;
			friend class CommandClass;
			friend class ControllerReplication;
			friend class EnergyProduction;
			friend class Hail;
			friend class Indicator;
			friend class Language;
			friend class Lock;
			friend class ManufacturerSpecific;
			friend class Meter;
			friend class MeterPulse;
			friend class MultiInstance;
			friend class MultiChannelAssociation;
			friend class NodeNaming;
			friend class Protection;
			friend class Security;
			friend class SensorAlarm;
			friend class SensorBinary;
			friend class SensorMultilevel;
			friend class SwitchAll;
			friend class SwitchBinary;
			friend class SwitchMultilevel;
			friend class SwitchToggleBinary;
			friend class SwitchToggleMultilevel;
			friend class ThermostatFanMode;
			friend class ThermostatFanState;
			friend class ThermostatMode;
			friend class ThermostatOperatingState;
			friend class ThermostatSetpoint;
			friend class Version;
			friend class WakeUp;
			friend class ZWavePlusInfo;

			//-----------------------------------------------------------------------------
			// Construction
			//-----------------------------------------------------------------------------
		public:
			/** Constructor initializes the node object, associating it with a specific
			 *  network (_homeId) and network node (_nodeId).
			 *  \param _homeId The homeId of the network to which this node is connected.
			 *  \param _nodeId The nodeId of this node.
			 */
			Node( uint32 const _homeId, uint8 const _nodeId );
			/** Destructor cleans up memory allocated to node and its child objects.
			 */
			virtual ~Node();

		private:
			/** Returns a pointer to the driver (interface with a Z-Wave controller)
			 *  associated with this node.
			 */
			Driver* GetDriver()const;

			//-----------------------------------------------------------------------------
			// Initialization
			//-----------------------------------------------------------------------------
		public:
			enum QueryStage
			{
				QueryStage_None,							/**< Query process hasn't started for this node */
				QueryStage_ProtocolInfo,					/**< Retrieve protocol information */
				QueryStage_Probe,							/**< Ping device to see if alive */
				QueryStage_WakeUp,							/**< Start wake up process if a sleeping node */
				QueryStage_ManufacturerSpecific1,			/**< Retrieve manufacturer name and product ids if ProtocolInfo lets us */
				QueryStage_NodeInfo,						/**< Retrieve info about supported, controlled command classes */
				QueryStage_NodePlusInfo,					/**< Retrieve ZWave+ info and update device classes */
				QueryStage_SecurityReport,					/**< Retrieve a list of Command Classes that require Security */
				QueryStage_ManufacturerSpecific2,			/**< Retrieve manufacturer name and product ids */
				QueryStage_Versions,						/**< Retrieve version information */
				QueryStage_Instances,						/**< Retrieve information about multiple command class instances */
				QueryStage_Static,							/**< Retrieve static information (doesn't change) */
				QueryStage_CacheLoad,						/**< Ping a device upon restarting with cached config for the device */
				QueryStage_Probe1 = QueryStage_CacheLoad,	/** < Depreciated name. /todo Remove in 2.0 timeframe */
				QueryStage_Associations,					/**< Retrieve information about associations */
				QueryStage_Neighbors,						/**< Retrieve node neighbor list */
				QueryStage_Session,							/**< Retrieve session information (changes infrequently) */
				QueryStage_Dynamic,							/**< Retrieve dynamic information (changes frequently) */
				QueryStage_Configuration,					/**< Retrieve configurable parameter information (only done on request) */
				QueryStage_Complete							/**< Query process is completed for this node */
			};


			/**
			 * This function advances the query process (see Remarks below for more detail on the
			 * process).  It iterates through the various query stages enumerated in Node::QueryStage.
			 *
			 * \remark
			 * For OpenZWave to discover everything about a node, we have to follow a certain
			 * order of queries, because the results of one stage may affect what is requested
			 * in the next stage.  The stage is saved with the node data, so that any incomplete
			 * queries can be restarted the next time the application runs.
			 * <p>
			 * The individual command classes also store some state information as to whether
			 * they have had a response to certain queries.  This state information is
			 * initialized by the SetStaticRequests call in QueryStage_None.  It is also saved,
			 * so we do not need to request state  from every command class if some have previously
			 * responded.
			 */
			void AdvanceQueries();

			/**
			 *  Signal that a specific query stage has been completed for this node.  This will
			 *  only work if the query process for this node is indeed at the specified stage.
			 *  Otherwise, the function returns with no action.
			 *  \param _stage The current stage of the query process.
			 */
			void QueryStageComplete( QueryStage const _stage );

			/**
			 *  Retry the specified query stage (up to _maxAttempts retries).  This will
			 *  only work if the query process for this node is indeed at the specified stage.
			 *  Otherwise, the function returns with no action.
			 *  \param _stage The query stage to retry.
			 *  \param _maxAttempts
			 */
			void QueryStageRetry( QueryStage const _stage, uint8 const _maxAttempts = 0 );	    // maxAttempts of zero means no limit

			/**
			 * This function sets the query stage for the node (but only to an earlier stage).
			 * If a later stage is specified than the current one, it is ignored.
			 * \param _stage The desired query stage.
			 * \see m_queryStage, m_queryPending
			 */
			void SetQueryStage( QueryStage const _stage, bool const _advance = true );

			/**
			 * Returns the current query stage enum.
			 * \return Enum value with the current query stage.
			 * \see m_queryStage
			 */
			Node::QueryStage GetCurrentQueryStage() { return m_queryStage; }

			/**
			 * Returns the specified query stage string.
			 * \param _stage The query stage.
			 * \return Specified query stage string.
			 * \see m_queryStage, m_queryPending
			 */
			string GetQueryStageName( QueryStage const _stage );

			/**
			 * Returns whether the library thinks a node is functioning properly
			 * \return boolean status of node.
			 */
			bool IsNodeAlive()const{ return m_nodeAlive; }

			/**
			 *  This function handles a response to the FUNC_ID_ZW_GET_NODE_PROTOCOL_INFO
			 *  command for this node.  If protocol information has already been retrieved
			 *  for the node, the function simply returns.  Otherwise, it populates several
			 *  member variables about the device at this node:
			 *  - m_routing (whether it is a routing node (capable of passing commands along to other nodes in the network) or not
			 *  - m_maxBaudRate (the maximum baud rate at which this device can communicate)
			 *  - m_version (TODO)
			 *  - m_security (whether device supports security features)
			 *  - m_listening (device is powered and listening constantly)
			 *  - m_frequentListening (device can be woken up with a beam)
			 *  - m_beaming (device is beam capable)
			 */
			void UpdateProtocolInfo( uint8 const* _data );
			/**
			 * this function is called when the Node is added via a AddNode request. the ProtocolInfo field contains the
			 * devices classes and the CommandClasses that the node supports, so we can build a pretty good Node out of that
			 * info.
			 * @param _protocolInfo Byte 0 - Basic Device Class Byte 1 - Generic Device Class, Byte 2 - Specific Device Classes Remaining Bytes - Supported Command Classes
			 * @param _length length of the _protocolInfo field.
			 */
			void SetProtocolInfo(uint8 const* _protocolInfo, uint8 const _length);
			void UpdateNodeInfo( uint8 const* _data, uint8 const _length );

			bool ProtocolInfoReceived()const{ return m_protocolInfoReceived; }
			bool NodeInfoReceived()const{ return m_nodeInfoReceived; }
			bool IsNodeZWavePlus()const{ return m_nodePlusInfoReceived; }

			bool AllQueriesCompleted()const{ return( QueryStage_Complete == m_queryStage ); }

			void SetNodePlusInfoReceived(const bool _received){ m_nodePlusInfoReceived = _received; }

			/**
			 * Handle dead node detection tracking.
			 * Use this routine to set state of nodes.
			 * Tracks state as well as send notifications.
			 */
			void SetNodeAlive( bool const _isAlive );

		private:
			void SetStaticRequests();

			QueryStage	m_queryStage;
			bool		m_queryPending;
			bool		m_queryConfiguration;
			uint8		m_queryRetries;
			bool		m_protocolInfoReceived;
			bool		m_basicprotocolInfoReceived;
			bool		m_nodeInfoReceived;
			bool		m_nodePlusInfoReceived;
			bool		m_manufacturerSpecificClassReceived;
			bool		m_nodeInfoSupported;
			bool		m_refreshonNodeInfoFrame;
			bool		m_nodeAlive;

			//-----------------------------------------------------------------------------
			// Capabilities
			//-----------------------------------------------------------------------------
		public:
			// Security flags
			enum
			{
				SecurityFlag_Security				= 0x01,
				SecurityFlag_Controller				= 0x02,
				SecurityFlag_SpecificDevice			= 0x04,
				SecurityFlag_RoutingSlave			= 0x08,
				SecurityFlag_BeamCapability			= 0x10,
				SecurityFlag_Sensor250ms			= 0x20,
				SecurityFlag_Sensor1000ms			= 0x40,
				SecurityFlag_OptionalFunctionality	= 0x80
			};

			// Node Ids
			enum
			{
				NodeBroadcast = 0xff
			};

			bool IsListeningDevice()const{ return m_listening; }
			bool IsFrequentListeningDevice()const{ return m_frequentListening; }
			bool IsBeamingDevice()const{ return m_beaming; }
			bool IsRoutingDevice()const{ return m_routing; }
			bool IsSecurityDevice()const{ return m_security; }
			uint32 GetMaxBaudRate()const{ return m_maxBaudRate; }
			uint8 GetVersion()const{ return m_version; }
			uint8 GetSecurity()const{ return m_security; }

			uint8 GetNodeId()const{ return m_nodeId; }

			uint8 GetBasic()const{ return m_basic; }
			uint8 GetGeneric()const{ return m_generic; }
			uint8 GetSpecific()const{ return m_specific; }
			string const& GetType()const{ return m_type; }
			uint32 GetNeighbors( uint8** o_associations );
			bool IsController()const{ return ( m_basic == 0x01 || m_basic == 0x02 ) && ( m_generic == 0x01 || m_generic == 0x02 ); }
			bool IsAddingNode() const { return m_addingNode; }	/* These three *AddingNode functions are used to tell if we this node is just being discovered. Currently used by the Security CC to initiate the Network Key Exchange */
			void SetAddingNode() { m_addingNode = true; }
			void ClearAddingNode() { m_addingNode = false; }
			bool IsNodeReset();
		private:
			bool		m_listening;
			bool		m_frequentListening;
			bool		m_beaming;
			bool		m_routing;
			uint32		m_maxBaudRate;
			uint8		m_version;
			bool		m_security;
			uint32		m_homeId;
			uint8		m_nodeId;
			uint8		m_basic;				//*< Basic device class (0x01-Controller, 0x02-Static Controller, 0x03-Slave, 0x04-Routing Slave
			uint8		m_generic;
			uint8		m_specific;
			string		m_type;					// Label representing the specific/generic/basic value
			uint8		m_neighbors[29];		// Bitmask containing the neighboring nodes
			uint8		m_numRouteNodes;		// number of node routes
			uint8		m_routeNodes[5];		// nodes to route to
			map<uint8,uint8>	m_buttonMap;	// Map button IDs into virtual node numbers
			bool		m_addingNode;

			//-----------------------------------------------------------------------------
			// Device Naming
			//-----------------------------------------------------------------------------
		private:
			// Manufacturer, Product and Name are stored here so they can be set by the
			// user even if the device does not support the relevant command classes.
			string GetManufacturerName()const{ return m_manufacturerName; }
			string GetProductName()const{ return m_productName; }
			string GetNodeName()const{ return m_nodeName; }
			string GetLocation()const{ return m_location; }

//			string GetManufacturerId()const{ return std::to_string(m_manufacturerId); }
			uint16 GetManufacturerId()const{ return m_manufacturerId; }
//			string GetProductType()const{ return string(m_productType); }
			uint16 GetProductType()const{ return m_productType; }
//			string GetProductId()const{ return string(m_productId); }
			uint16 GetProductId()const{ return m_productId; }

			void SetManufacturerName( string const& _manufacturerName ){ m_manufacturerName = _manufacturerName; }
			void SetProductName( string const& _productName ){ m_productName = _productName; }
			void SetNodeName( string const& _nodeName );
			void SetLocation( string const& _location );

			void SetManufacturerId( uint16 const& _manufacturerId ){ m_manufacturerId = _manufacturerId; }
			void SetProductType( uint16 const& _productType ){ m_productType = _productType; }
			void SetProductId( uint16 const& _productId ){ m_productId = _productId; }

			string		m_manufacturerName;
			string		m_productName;
			string		m_nodeName;
			string		m_location;

			uint16		m_manufacturerId;
			uint16		m_productType;
			uint16		m_productId;

			// zwave+ info
			uint16 GetDeviceType() const { return m_deviceType; }
			string GetDeviceTypeString();
			uint8 GetRoleType() const { return m_role; }
			string GetRoleTypeString();
			uint8 GetNodeType() const { return m_nodeType; }
			string GetNodeTypeString();

			uint16 m_deviceType;
			uint8 m_role;
			uint8 m_nodeType;

			//-----------------------------------------------------------------------------
			// Command Classes
			//-----------------------------------------------------------------------------
		public:
			/**
			 * This function retrieves a pointer to the requested command class object (if supported by this node).
			 * \param _commandClassId Class ID (a single byte value) identifying the command class requested.
			 * \return Pointer to the requested CommandClass object if supported, otherwise NULL.
			 * \see CommandClass, m_commandClassMap
			 */
			CommandClass* GetCommandClass( uint8 const _commandClassId )const;
			void ApplicationCommandHandler( uint8 const* _data, bool encrypted );

			/**
			 * This function sets up Secured Command Classes. It iterates over the existing command classes marking them
			 * as Secured if they exist, and if they don't, it creates new Command Classes and sets them up as Secured
			 * @param _data a list of Command Classes that are Secured by the Device
			 * @param _length the length of the _data string
			 */
			void SetSecuredClasses( uint8 const* _data, uint8 const _length );
			void SetSecured(bool secure);
		private:
			/**
			 * Creates the specified command class object and adds it to the node (via the
			 * m_commandClassMap) if it doesn't exist.
			 * No new object is created if it already exists for this node.
			 * \param _commandClassId Class ID (a single byte value) identifying the command class requested.
			 * \return Pointer to the CommandClass object just added to the map (NULL if the object
			 * was already there or if the CommandClass object creation failed).
			 * \see CommandClass, CommandClasses::CreateCommandClass, m_commandClassMap
			 */
			CommandClass* AddCommandClass( uint8 const _commandClassId );
			/**
			 * Removes a command class object from the node (via the m_commandClassMap).  Before removing the
			 * object, this function also removes any values stored in the object's ValueStore.
			 * \param _commandClassId Class ID (a single byte value) identifying the command class to be removed.
			 * \see m_commandClassMap, ValueStore, GetValueStore, ValueStore::RemoveCommandClassValues
			 */
			void RemoveCommandClass( uint8 const _commandClassId );
			void ReadXML( TiXmlElement const* _nodeElement );
			void ReadDeviceProtocolXML( TiXmlElement const* _ccsElement );
			void ReadCommandClassesXML( TiXmlElement const* _ccsElement );
			void WriteXML( TiXmlElement* _nodeElement );

			map<uint8,CommandClass*>		m_commandClassMap;	/**< Map of command class ids and pointers to associated command class objects */
			bool							m_secured; /**< Is this Node added Securely */
			//-----------------------------------------------------------------------------
			// Basic commands (helpers that go through the basic command class)
			//-----------------------------------------------------------------------------
		public:
			void SetLevel( uint8 const _level );

			//-----------------------------------------------------------------------------
			// On/Off commands (helpers that go through the basic or switchall command class)
			//-----------------------------------------------------------------------------
		public:
			void SetNodeOn();
			void SetNodeOff();

			//-----------------------------------------------------------------------------
			// Values (handled by the command classes)
			//-----------------------------------------------------------------------------
		public:
			ValueID CreateValueID( ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 const _valueIndex, ValueID::ValueType const _type );

			Value* GetValue( ValueID const& _id );
			Value* GetValue( uint8 const _commandClassId, uint8 const _instance, uint8 const _valueIndex );
			bool RemoveValue( uint8 const _commandClassId, uint8 const _instance, uint8 const _valueIndex );

			// Helpers for creating values
			bool 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 );
			bool CreateValueButton( ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 const _valueIndex, string const& _label, uint8 const _pollIntensity );
			bool 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 );
			bool 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 );
			bool 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 );
			bool 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 );
			bool 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 );
			bool 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 );
			bool 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 );
			bool 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 );

			// helpers for removing values
			void RemoveValueList( ValueList* _value );

			void ReadValueFromXML( uint8 const _commandClassId, TiXmlElement const* _valueElement );
			bool CreateValueFromXML( uint8 const _commandClassId, TiXmlElement const* _valueElement );

		private:
			ValueStore* GetValueStore()const{ return m_values; }

			ValueStore*	m_values;			// Values reported via command classes

			//-----------------------------------------------------------------------------
			// Configuration Parameters (handled by the Configuration command class)
			//-----------------------------------------------------------------------------
		private:
			bool SetConfigParam( uint8 const _param, int32 _value, uint8 const _size );
			void RequestConfigParam( uint8 const _param );
			bool RequestAllConfigParams( uint32 const _requestFlags );

			//-----------------------------------------------------------------------------
			// Dynamic Values (used by query and other command classes for updating)
			//-----------------------------------------------------------------------------
		private:
			bool RequestDynamicValues();
			//-----------------------------------------------------------------------------
			// Groups
			//-----------------------------------------------------------------------------
		private:
			// The public interface is provided via the wrappers in the Manager class
			uint8 GetNumGroups();
			uint32 GetAssociations( uint8 const _groupIdx, uint8** o_associations );
			uint32 GetAssociations( uint8 const _groupIdx, InstanceAssociation** o_associations );
			uint8 GetMaxAssociations( uint8 const _groupIdx );
			string GetGroupLabel( uint8 const _groupIdx );
			void AddAssociation( uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance = 0x00 );
			void RemoveAssociation( uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance = 0x00 );
			void AutoAssociate();

			// The following methods are not exposed
			Group* GetGroup( uint8 const _groupIdx );							// Get a pointer to a Group object.  This must only be called while holding the node Lock.
			void AddGroup( Group* _group );										// The groups are fixed properties of a device, so there is no need for a matching RemoveGroup.
			void WriteGroups( TiXmlElement* _associationsElement );				// Write the group data out to XNL

			map<uint8,Group*> m_groups;											// Maps group indices to Group objects.

			//-----------------------------------------------------------------------------
			// Device Classes (static data read from the device_classes.xml file)
			//-----------------------------------------------------------------------------
		private:
			// Container for device class info
			class DeviceClass
			{
				public:
				DeviceClass( TiXmlElement const* _el );
				~DeviceClass(){ delete [] m_mandatoryCommandClasses; }

				uint8 const*	GetMandatoryCommandClasses(){ return m_mandatoryCommandClasses; }
				uint8			GetBasicMapping(){ return m_basicMapping; }
				string const&	GetLabel(){ return m_label; }

				private:
				uint8*			m_mandatoryCommandClasses;						// Zero terminated array of mandatory command classes for this device type.
				uint8			m_basicMapping;									// Command class that COMMAND_CLASS_BASIC maps on to, or zero if there is no mapping.
				string			m_label;										// Descriptive label for the device.
			};

			// Container for generic device class info
			class GenericDeviceClass : public DeviceClass
			{
				public:
					GenericDeviceClass( TiXmlElement const* _el );
					~GenericDeviceClass();

					DeviceClass* GetSpecificDeviceClass( uint8 const& _specific );

				private:
					map<uint8,DeviceClass*>	m_specificDeviceClasses;
			};


			bool SetDeviceClasses( uint8 const _basic, uint8 const _generic, uint8 const _specific );	// Set the device class data for the node
			bool SetPlusDeviceClasses( uint8 const _role, uint8 const _nodeType, uint16 const _deviceType );	// Set the device class data for the node based on the Zwave+ info report
			bool AddMandatoryCommandClasses( uint8 const* _commandClasses );							// Add mandatory command classes as specified in the device_classes.xml to the node.
			void ReadDeviceClasses();																	// Read the static device class data from the device_classes.xml file
			string GetEndPointDeviceClassLabel( uint8 const _generic, uint8 const _specific );

			static bool								s_deviceClassesLoaded;		// True if the xml file has already been loaded
			static map<uint8,string>				s_basicDeviceClasses;		// Map of basic device classes.
			static map<uint8,GenericDeviceClass*>	s_genericDeviceClasses;		// Map of generic device classes.
			static map<uint8,DeviceClass*> 			s_roleDeviceClasses;		// Map of Zwave+ role device classes.
			static map<uint16,DeviceClass*> 		s_deviceTypeClasses;		// Map of Zwave+ device type device classes.
			static map<uint8, DeviceClass*>			s_nodeTypes;				// Map of ZWave+ Node Types


			//-----------------------------------------------------------------------------
			//	Statistics
			//-----------------------------------------------------------------------------
			public:
			struct CommandClassData
			{
				uint8 m_commandClassId;
				uint32 m_sentCnt;
				uint32 m_receivedCnt;
			};

			struct NodeData
			{
					uint32 m_sentCnt;
					uint32 m_sentFailed;
					uint32 m_retries;
					uint32 m_receivedCnt;
					uint32 m_receivedDups;
					uint32 m_receivedUnsolicited;
					string m_sentTS;
					string m_receivedTS;
					uint32 m_lastRequestRTT;
					uint32 m_averageRequestRTT;				// ms
					uint32 m_lastResponseRTT;
					uint32 m_averageResponseRTT;
					uint8 m_quality;					// Node quality measure
					uint8 m_lastReceivedMessage[254];
					list<CommandClassData> m_ccData;
			};

			private:
			void GetNodeStatistics( NodeData* _data );

			uint32 m_sentCnt;				// Number of messages sent from this node.
			uint32 m_sentFailed;				// Number of sent messages failed
			uint32 m_retries;				// Number of message retries
			uint32 m_receivedCnt;				// Number of messages received from this node.
			uint32 m_receivedDups;				// Number of duplicated messages received;
			uint32 m_receivedUnsolicited;			// Number of messages received unsolicited
			uint32 m_lastRequestRTT;			// Last message request RTT
			uint32 m_lastResponseRTT;			// Last message response RTT
			TimeStamp m_sentTS;				// Last message sent time
			TimeStamp m_receivedTS;				// Last message received time
			uint32 m_averageRequestRTT;			// Average Request round trip time.
			uint32 m_averageResponseRTT;			// Average Response round trip time.
			uint8 m_quality;				// Node quality measure
			uint8 m_lastReceivedMessage[254];		// Place to hold last received message
			uint8 m_errors;					// Count errors for dead node detection

			//-----------------------------------------------------------------------------
			//	Encryption Related
			//-----------------------------------------------------------------------------
			public:

			uint8 *GenerateNonceKey();
			uint8 *GetNonceKey(uint32 nonceid);

			private:
			uint8 m_lastnonce;
			uint8 m_nonces[8][8];
	};


} //namespace OpenZWave

#endif //_Node_H
