Пример #1
0
//-----------------------------------------------------------------------------
// <MultiInstance::HandleMultiChannelEndPointFindReport>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
void MultiInstance::HandleMultiChannelEndPointFindReport
(	
	uint8 const* _data,
	uint32 const _length
)
{
	Log::Write( LogLevel_Info, GetNodeId(), "Received MultiChannelEndPointFindReport from node %d", GetNodeId() );
	uint8 numEndPoints = _length - 5;
	for( uint8 i=0; i<numEndPoints; ++i )
	{
		uint8 endPoint = _data[i+4] & 0x7f;

		if( m_endPointsAreSameClass )
		{
			// Use the stored command class list to set up the endpoint.
			if( Node* node = GetNodeUnsafe() )
			{
				for( set<uint8>::iterator it=m_endPointCommandClasses.begin(); it!=m_endPointCommandClasses.end(); ++it )
				{
					uint8 commandClassId = *it;
					CommandClass* cc = node->GetCommandClass( commandClassId );
					if( cc )
					{	
						Log::Write( LogLevel_Info, GetNodeId(), "    Endpoint %d: Adding %s", endPoint, cc->GetCommandClassName().c_str() );
						cc->SetInstance( endPoint );
					}
				}
			}
		}
		else
		{
			// Endpoints are different, so request the capabilities
			char str[128];
			snprintf( str, 128, "MultiChannelCmd_CapabilityGet for node %d, endpoint %d", GetNodeId(), endPoint );
			Msg* msg = new Msg( str, GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
			msg->Append( GetNodeId() );
			msg->Append( 3 );
			msg->Append( GetCommandClassId() );
			msg->Append( MultiChannelCmd_CapabilityGet );
			msg->Append( endPoint );
			msg->Append( GetDriver()->GetTransmitOptions() );
			GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
		}
	}

	m_numEndPointsFound += numEndPoints;
	if( !m_endPointsAreSameClass )
	{
		if( _data[1] == 0 )
		{
			// No more reports to follow this one, so we can continue the search.
			if( m_numEndPointsFound < numEndPoints )
			{
				// We have not yet found all the endpoints, so move to the next generic class request
				++m_endPointFindIndex;
				if( c_genericClass[m_endPointFindIndex] > 0 )
				{
					char str[128];
					snprintf( str, 128, "MultiChannelCmd_EndPointFind for generic device class 0x%.2x (%s)", c_genericClass[m_endPointFindIndex], c_genericClassName[m_endPointFindIndex] );
					Msg* msg = new Msg( str, GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
					msg->Append( GetNodeId() );
					msg->Append( 4 );
					msg->Append( GetCommandClassId() );
					msg->Append( MultiChannelCmd_EndPointFind );
					msg->Append( c_genericClass[m_endPointFindIndex] );		// Generic device class
					msg->Append( 0xff );									// Any specific device class
					msg->Append( GetDriver()->GetTransmitOptions() );
					GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
				}
			}
		}
	}
}
Пример #2
0
//-----------------------------------------------------------------------------
// <MultiInstance::HandleMultiChannelCapabilityReport>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
void MultiInstance::HandleMultiChannelCapabilityReport
(	
	uint8 const* _data,
	uint32 const _length
)
{
	if( Node* node = GetNodeUnsafe() )
	{
		uint8 endPoint = _data[1] & 0x7f;
		bool dynamic = ((_data[1] & 0x80)!=0);

		Log::Write( LogLevel_Info, GetNodeId(), "Received MultiChannelCapabilityReport from node %d for endpoint %d", GetNodeId(), endPoint );
		Log::Write( LogLevel_Info, GetNodeId(), "    Endpoint is%sdynamic, and is a %s", dynamic ? " " : " not ", node->GetEndPointDeviceClassLabel( _data[2], _data[3] ).c_str() );
		Log::Write( LogLevel_Info, GetNodeId(), "    Command classes supported by the endpoint are:" );

		// Store the command classes for later use
		bool afterMark = false;
		m_endPointCommandClasses.clear();
		uint8 numCommandClasses = _length - 5;
		for( uint8 i = 0; i < numCommandClasses; ++i )
		{
			uint8 commandClassId = _data[i+4];
			if( commandClassId == 0xef )
			{
				afterMark = true;
				continue;
			}

			m_endPointCommandClasses.insert( commandClassId );

			// Ensure the node supports this command class
			CommandClass* cc = node->GetCommandClass( commandClassId );
			if( !cc )
			{
				cc = node->AddCommandClass( commandClassId );
				if( cc && afterMark )
				{
					cc->SetAfterMark();
				}
			}
			if( cc )
			{
				Log::Write( LogLevel_Info, GetNodeId(), "        %s", cc->GetCommandClassName().c_str() );
			}
 		}

		// Create internal library instances for each command class in the list
		// Also set up mapping from intances to endpoints for encapsulation
		Basic* basic = static_cast<Basic*>( node->GetCommandClass( Basic::StaticGetCommandClassId() ) );
		if( m_endPointsAreSameClass )				// Create all the same instances here
		{
			int len;

			if( m_endPointMap == MultiInstanceMapAll )	// Include the non-endpoint instance
			{
				endPoint = 0;
				len = m_numEndPoints + 1;
			}
			else
			{
				endPoint = 1;
				len = m_numEndPoints;
			}

			// Create all the command classes for all the endpoints
			for( uint8 i = 1; i <= len; i++ )
			{
				for( set<uint8>::iterator it = m_endPointCommandClasses.begin(); it != m_endPointCommandClasses.end(); ++it )
				{
					uint8 commandClassId = *it;
					CommandClass* cc = node->GetCommandClass( commandClassId );
					if( cc )
					{	
						cc->SetInstance( i );
						if( m_endPointMap != MultiInstanceMapAll || i != 1 )
						{
							cc->SetEndPoint( i, endPoint );
						}
						// If we support the BASIC command class and it is mapped to a command class
						// assigned to this end point, make sure the BASIC command class is also associated
						// with this end point.
						if( basic != NULL && basic->GetMapping() == commandClassId )
						{
							basic->SetInstance( i );
							if( m_endPointMap != MultiInstanceMapAll || i != 1 )
							{
								basic->SetEndPoint( i, endPoint );
							}
						}
					}
				}
				endPoint++;
			}
		}
		else							// Endpoints are different
		{
			for( set<uint8>::iterator it = m_endPointCommandClasses.begin(); it != m_endPointCommandClasses.end(); ++it )
			{
				uint8 commandClassId = *it;
				CommandClass* cc = node->GetCommandClass( commandClassId );
				if( cc )
				{
					uint8 i;
					// Find the next free instance of this class
					for( i = 1; i <= 127; i++ )
					{
						if( m_endPointMap == MultiInstanceMapAll ) // Include the non-endpoint instance
						{
							if( !cc->GetInstances()->IsSet( i ) )
							{
								break;
							}
						}
						// Reuse non-endpoint instances first time we see it
						else if( i == 1 && cc->GetInstances()->IsSet( i ) && cc->GetEndPoint( i ) == 0 )
						{
							break;
						}
						// Find the next free instance
						else if( !cc->GetInstances()->IsSet( i ) )
						{
							break;
						}
					}
					cc->SetInstance( i );
					cc->SetEndPoint( i, endPoint );
					// If we support the BASIC command class and it is mapped to a command class
					// assigned to this end point, make sure the BASIC command class is also associated
					// with this end point.
					if( basic != NULL && basic->GetMapping() == commandClassId )
					{
						basic->SetInstance( i );
						basic->SetEndPoint( i, endPoint );
					}
				}
			}
		}
	}
}
Пример #3
0
//-----------------------------------------------------------------------------
// <MultiInstance::HandleMultiChannelCapabilityReport>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
void MultiInstance::HandleMultiChannelCapabilityReport
(
		uint8 const* _data,
		uint32 const _length
)
{

	bool dynamic = ((_data[1] & 0x80)!=0);


	if( Node* node = GetNodeUnsafe() )
	{
		/* if you having problems with Dynamic Devices not correctly
		 * updating the commandclasses, see this email thread:
		 * https://groups.google.com/d/topic/openzwave/IwepxScRAVo/discussion
		 */
		if ((m_ignoreUnsolicitedMultiChannelCapabilityReport && (node->GetCurrentQueryStage() != Node::QueryStage_Instances))
				&& !dynamic && m_endPointCommandClasses.size() > 0) {
			Log::Write(LogLevel_Error, GetNodeId(), "Recieved a Unsolicited MultiChannelEncap when we are not in QueryState_Instances");
			return;
		}

		uint8 endPoint = _data[1] & 0x7f;

		Log::Write( LogLevel_Info, GetNodeId(), "Received MultiChannelCapabilityReport from node %d for endpoint %d", GetNodeId(), endPoint );
		Log::Write( LogLevel_Info, GetNodeId(), "    Endpoint is%sdynamic, and is a %s", dynamic ? " " : " not ", node->GetEndPointDeviceClassLabel( _data[2], _data[3] ).c_str() );
		Log::Write( LogLevel_Info, GetNodeId(), "    Command classes supported by the endpoint are:" );

		// Store the command classes for later use
		bool afterMark = false;
		m_endPointCommandClasses.clear();
		uint8 numCommandClasses = _length - 5;
		for( uint8 i = 0; i < numCommandClasses; ++i )
		{
			uint8 commandClassId = _data[i+4];
			if( commandClassId == 0xef )
			{
				afterMark = true;
				continue;
			}

			m_endPointCommandClasses.insert( commandClassId );

			// Ensure the node supports this command class
			CommandClass* cc = node->GetCommandClass( commandClassId );
			if( !cc )
			{
				cc = node->AddCommandClass( commandClassId );
				if( cc && afterMark )
				{
					cc->SetAfterMark();
				}
			}
			if( cc )
			{
				Log::Write( LogLevel_Info, GetNodeId(), "        %s", cc->GetCommandClassName().c_str() );
			}
		}

		// Create internal library instances for each command class in the list
		// Also set up mapping from intances to endpoints for encapsulation
		Basic* basic = static_cast<Basic*>( node->GetCommandClass( Basic::StaticGetCommandClassId() ) );
		if( m_endPointsAreSameClass )				// Create all the same instances here
		{
			int len;

			if( m_endPointMap == MultiInstanceMapAll )	// Include the non-endpoint instance
			{
				endPoint = 0;
				len = m_numEndPoints + 1;
			}
			else
			{
				endPoint = 1;
				len = m_numEndPoints;
			}

			// Create all the command classes for all the endpoints
			for( uint8 i = 1; i <= len; i++ )
			{
				std::cout << "Num Instances: " << len << std::endl;
				for( set<uint8>::iterator it = m_endPointCommandClasses.begin(); it != m_endPointCommandClasses.end(); ++it )
				{
					uint8 commandClassId = *it;
					CommandClass* cc = node->GetCommandClass( commandClassId );
					if( cc )
					{
						cc->SetInstance( i );
						if( m_endPointMap != MultiInstanceMapAll || i != 1 )
						{
							cc->SetEndPoint( i, endPoint );
						}
						// If we support the BASIC command class and it is mapped to a command class
						// assigned to this end point, make sure the BASIC command class is also associated
						// with this end point.
						if( basic != NULL && basic->GetMapping() == commandClassId )
						{
							basic->SetInstance( i );
							if( m_endPointMap != MultiInstanceMapAll || i != 1 )
							{
								basic->SetEndPoint( i, endPoint );
							}
						}
					}
				}
				endPoint++;
			}
		}
		else							// Endpoints are different
		{
			for( set<uint8>::iterator it = m_endPointCommandClasses.begin(); it != m_endPointCommandClasses.end(); ++it )
			{
				uint8 commandClassId = *it;
				CommandClass* cc = node->GetCommandClass( commandClassId );
				if( cc )
				{
					uint8 i;
					// Find the next free instance of this class
					for( i = 1; i <= 127; i++ )
					{
						if( m_endPointMap == MultiInstanceMapAll ) // Include the non-endpoint instance
						{
							if( !cc->GetInstances()->IsSet( i ) )
							{
								break;
							}
						}
						// Reuse non-endpoint instances first time we see it
						else if( i == 1 && cc->GetInstances()->IsSet( i ) && cc->GetEndPoint( i ) == 0 )
						{
							break;
						}
						// Find the next free instance
						else if( !cc->GetInstances()->IsSet( i ) )
						{
							break;
						}
					}
					cc->SetInstance( i );
					cc->SetEndPoint( i, endPoint );
					// If we support the BASIC command class and it is mapped to a command class
					// assigned to this end point, make sure the BASIC command class is also associated
					// with this end point.
					if( basic != NULL && basic->GetMapping() == commandClassId )
					{
						basic->SetInstance( i );
						basic->SetEndPoint( i, endPoint );
					}
				}
			}
		}
	}
}
Пример #4
0
//-----------------------------------------------------------------------------
// <MultiInstance::HandleMultiChannelCapabilityReport>
// Handle a message from the Z-Wave network
//-----------------------------------------------------------------------------
void MultiInstance::HandleMultiChannelCapabilityReport
(	
	uint8 const* _data,
	uint32 const _length
)
{
	if( Node* node = GetNodeUnsafe() )
	{
		uint8 endPoint = _data[1] & 0x7f;
		bool dynamic = ((_data[1] & 0x80)!=0);

		Log::Write( LogLevel_Info, GetNodeId(), "Received MultiChannelCapabilityReport from node %d for endpoint %d", GetNodeId(), endPoint );
		Log::Write( LogLevel_Info, GetNodeId(), "    Endpoint is%sdynamic, and is a %s", dynamic ? " " : " not ", node->GetEndPointDeviceClassLabel( _data[2], _data[3] ).c_str() );
		Log::Write( LogLevel_Info, GetNodeId(), "    Command classes supported by the endpoint are:" );

		// Store the command classes for later use
		bool afterMark = false;
		m_endPointCommandClasses.clear();
		uint8 numCommandClasses = _length - 5;
		for( uint8 i=0; i<numCommandClasses; ++i )
		{
			uint8 commandClassId = _data[i+4];
			if( commandClassId == 0xef )
			{
				afterMark = true;
				continue;
			}

			m_endPointCommandClasses.insert( commandClassId );

			// Ensure the node supports this command class
			CommandClass* cc = node->GetCommandClass( commandClassId );
			if( !cc )
			{
				cc = node->AddCommandClass( commandClassId );
				if( cc && afterMark )
				{
					cc->SetAfterMark();
				}
			}
			if( cc )
			{
				Log::Write( LogLevel_Info, GetNodeId(), "        %s", cc->GetCommandClassName().c_str() );
			}
 		}

		if( ( endPoint == 1 ) && m_endPointsAreSameClass )
		{
			Log::Write( LogLevel_Info, GetNodeId(), "All endpoints in this device are the same as endpoint 1.  Searching for the other endpoints..." );
	
			// All end points have the same command classes.
			// We just need to find them...
			if (node->MultiEndPointFindSupported()) {
				char str[128];
				snprintf( str, sizeof( str ), "MultiChannelCmd_EndPointFind for generic device class 0x%.2x", _data[2] );
				Msg* msg = new Msg( str, GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
				msg->Append( GetNodeId() );
				msg->Append( 4 );
				msg->Append( GetCommandClassId() );
				msg->Append( MultiChannelCmd_EndPointFind );
				msg->Append( _data[2] );	// Generic device class
				msg->Append( 0xff );		// Any specific device class
				msg->Append( TRANSMIT_OPTION_ACK | TRANSMIT_OPTION_AUTO_ROUTE );
				GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
			} else {
				// no way to find them, assume they are in ascending order
				for( uint8 endPoint=1; endPoint<=m_numEndpoints; ++endPoint )
				{
					// Use the stored command class list to set up the endpoint.
					for( set<uint8>::iterator it=m_endPointCommandClasses.begin(); it!=m_endPointCommandClasses.end(); ++it )
					{
						uint8 commandClassId = *it;
						CommandClass* cc = node->GetCommandClass( commandClassId );
						if( cc )
						{
							Log::Write( LogLevel_Info, GetNodeId(), "    Endpoint %d: Adding %s", endPoint, cc->GetCommandClassName().c_str() );
							cc->SetInstance( endPoint );
						}
					}
				}
			}
		}
		else
		{
			// Create instances (endpoints) for each command class in the list
			for( set<uint8>::iterator it=m_endPointCommandClasses.begin(); it!=m_endPointCommandClasses.end(); ++it )
			{
				uint8 commandClassId = *it;
				CommandClass* cc = node->GetCommandClass( commandClassId );
				if( cc )
				{	
					cc->SetInstance( endPoint );
				}
			}
		}
	}
}
Пример #5
-1
//-----------------------------------------------------------------------------
// <MultiInstance::RequestInstances>
// Request number of instances of the specified command class from the device
//-----------------------------------------------------------------------------
bool MultiInstance::RequestInstances
(
)
{
	bool res = false;

	if( GetVersion() == 1 )
	{
		if( Node* node = GetNodeUnsafe() )
		{
			// MULTI_INSTANCE
			char str[128];
			for( map<uint8,CommandClass*>::const_iterator it = node->m_commandClassMap.begin(); it != node->m_commandClassMap.end(); ++it )
			{
				CommandClass* cc = it->second;
				if( cc->GetCommandClassId() == NoOperation::StaticGetCommandClassId() )
				{
					continue;
				}
 				if( cc->HasStaticRequest( StaticRequest_Instances ) )
				{
					snprintf( str, sizeof( str ), "MultiInstanceCmd_Get for %s", cc->GetCommandClassName().c_str() );

					Msg* msg = new Msg( str, GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
					msg->Append( GetNodeId() );
					msg->Append( 3 );
					msg->Append( GetCommandClassId() );
					msg->Append( MultiInstanceCmd_Get );
					msg->Append( cc->GetCommandClassId() );
					msg->Append( GetDriver()->GetTransmitOptions() );
					GetDriver()->SendMsg( msg, Driver::MsgQueue_Query );
					res = true;
				}
			}
		}
	}
	else
	{
		// MULTI_CHANNEL
		char str[128];
		snprintf( str, sizeof( str ), "MultiChannelCmd_EndPointGet for node %d", GetNodeId() );

		Msg* msg = new Msg( str, GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
		msg->Append( GetNodeId() );
		msg->Append( 2 );
		msg->Append( GetCommandClassId() );
		msg->Append( MultiChannelCmd_EndPointGet );
		msg->Append( GetDriver()->GetTransmitOptions() );
		GetDriver()->SendMsg( msg, Driver::MsgQueue_Query );
		res = true;
	}

	return res;
}