mirror of
https://github.com/Fishwaldo/open-zwave.git
synced 2025-07-08 05:58:55 +00:00
Add promiscuous message handling but left commented out.
Added tracking and returning driver specific message count and error data. see Manager::GetDriverStatistics Random formatting changes for consistency. Class SensorMultilevel will use multiple indexes for multiple sensors. Node::GetNeighbors will only return valid data. Wait for proper query stage to complete. On Driver shutdown stop threads then remove controller object. Add extra comments to Driver::IsControllerCommand so we can better track commands. Update Mac OS X example Main.cpp to be consistent with Linux version. Handle more notifications and add a thread to wait for query completion. Add statistics print out to both Linux and Mac OS X example apps. Fix Mac hidapi to terminate its background CFRunLoop upon hid_close.
This commit is contained in:
parent
01aa2c7853
commit
3a85a66464
12 changed files with 381 additions and 177 deletions
|
@ -34,6 +34,7 @@
|
|||
#include <pthread.h>
|
||||
#include "Options.h"
|
||||
#include "Manager.h"
|
||||
#include "Driver.h"
|
||||
#include "Node.h"
|
||||
#include "Group.h"
|
||||
#include "Notification.h"
|
||||
|
@ -180,6 +181,7 @@ void OnNotification
|
|||
{
|
||||
// We have received an event from the node, caused by a
|
||||
// basic_set or hail message.
|
||||
// TBD...
|
||||
nodeInfo = nodeInfo;
|
||||
}
|
||||
break;
|
||||
|
@ -273,7 +275,8 @@ int main( int argc, char* argv[] )
|
|||
// In a normal app, we would be handling notifications and building a UI for the user.
|
||||
pthread_cond_wait( &initCond, &initMutex );
|
||||
|
||||
if (!g_initFailed) {
|
||||
if( !g_initFailed )
|
||||
{
|
||||
|
||||
//Manager::Get()->BeginAddNode( g_homeId );
|
||||
//sleep(10);
|
||||
|
@ -285,8 +288,16 @@ int main( int argc, char* argv[] )
|
|||
|
||||
Manager::Get()->WriteConfig( g_homeId );
|
||||
|
||||
Driver::DriverData data;
|
||||
Manager::Get()->GetDriverStatistics( g_homeId, &data );
|
||||
printf("SOF: %d ACK Waiting: %d Read Aborts: %d Bad Checksums: %d\n", data.s_SOFCnt, data.s_ACKWaiting, data.s_readAborts, data.s_badChecksum);
|
||||
printf("Reads: %d Writes: %d CAN: %d NAK: %d ACK: %d Out of Frame: %d\n", data.s_readCnt, data.s_writeCnt, data.s_CANCnt, data.s_NAKCnt, data.s_ACKCnt, data.s_OOFCnt);
|
||||
printf("Dropped: %d Retries: %d\n", data.s_dropped, data.s_retries);
|
||||
|
||||
while( true )
|
||||
{
|
||||
sleep(10);
|
||||
|
||||
pthread_mutex_lock( &g_criticalSection );
|
||||
// Do stuff
|
||||
pthread_mutex_unlock( &g_criticalSection );
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <pthread.h>
|
||||
#include "Options.h"
|
||||
#include "Manager.h"
|
||||
#include "Driver.h"
|
||||
#include "Node.h"
|
||||
#include "Group.h"
|
||||
#include "Notification.h"
|
||||
|
@ -44,6 +45,7 @@
|
|||
using namespace OpenZWave;
|
||||
|
||||
static uint32 g_homeId = 0;
|
||||
static bool g_initFailed = false;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -55,6 +57,8 @@ typedef struct
|
|||
|
||||
static list<NodeInfo*> g_nodes;
|
||||
static pthread_mutex_t g_criticalSection;
|
||||
static pthread_cond_t initCond = PTHREAD_COND_INITIALIZER;
|
||||
static pthread_mutex_t initMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// <GetNodeInfo>
|
||||
|
@ -127,6 +131,7 @@ void OnNotification
|
|||
{
|
||||
// One of the node values has changed
|
||||
// TBD...
|
||||
nodeInfo = nodeInfo;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -137,6 +142,7 @@ void OnNotification
|
|||
{
|
||||
// One of the node's association groups has changed
|
||||
// TBD...
|
||||
nodeInfo = nodeInfo;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -176,6 +182,7 @@ void OnNotification
|
|||
// We have received an event from the node, caused by a
|
||||
// basic_set or hail message.
|
||||
// TBD...
|
||||
nodeInfo = nodeInfo;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -203,11 +210,29 @@ void OnNotification
|
|||
g_homeId = _notification->GetHomeId();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case Notification::Type_DriverFailed:
|
||||
{
|
||||
g_initFailed = true;
|
||||
pthread_cond_broadcast(&initCond);
|
||||
break;
|
||||
}
|
||||
|
||||
case Notification::Type_AwakeNodesQueried:
|
||||
case Notification::Type_AllNodesQueried:
|
||||
{
|
||||
pthread_cond_broadcast(&initCond);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock( &g_criticalSection );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// <main>
|
||||
// Create the driver and then wait
|
||||
|
@ -216,10 +241,13 @@ int main( int argc, char* argv[] )
|
|||
{
|
||||
pthread_mutexattr_t mutexattr;
|
||||
|
||||
pthread_mutexattr_init ( &mutexattr );
|
||||
pthread_mutexattr_settype( &mutexattr, PTHREAD_MUTEX_RECURSIVE );
|
||||
pthread_mutex_init( &g_criticalSection, &mutexattr );
|
||||
pthread_mutexattr_destroy( &mutexattr );
|
||||
|
||||
pthread_mutex_lock( &initMutex );
|
||||
|
||||
// Create the OpenZWave Manager.
|
||||
// The first argument is the path to the config files (where the manufacturer_specific.xml file is located
|
||||
// The second argument is the path for saved Z-Wave network state and the log file. If you leave it NULL
|
||||
|
@ -237,15 +265,18 @@ int main( int argc, char* argv[] )
|
|||
|
||||
// Add a Z-Wave Driver
|
||||
// Modify this line to set the correct serial port for your PC interface.
|
||||
Manager::Get()->AddDriver( "/dev/cu.usbserial");
|
||||
|
||||
string port = "/dev/cu.usbserial";
|
||||
|
||||
Manager::Get()->AddDriver( ( argc > 1 ) ? argv[1] : port );
|
||||
//Manager::Get()->AddDriver( "HID Controller", Driver::ControllerInterface_Hid );
|
||||
|
||||
// Now we just wait for the driver to become ready, and then write out the loaded config.
|
||||
// In a normal app, we would be handling notifications and building a UI for the user.
|
||||
while( !g_homeId )
|
||||
pthread_cond_wait( &initCond, &initMutex );
|
||||
|
||||
if( !g_initFailed )
|
||||
{
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
//Manager::Get()->BeginAddNode( g_homeId );
|
||||
//sleep(10);
|
||||
|
@ -253,9 +284,16 @@ int main( int argc, char* argv[] )
|
|||
//Manager::Get()->BeginRemoveNode( g_homeId );
|
||||
//sleep(10);
|
||||
//Manager::Get()->EndRemoveNode( g_homeId );
|
||||
sleep(10);
|
||||
//sleep(10);
|
||||
|
||||
Manager::Get()->WriteConfig( g_homeId );
|
||||
|
||||
Driver::DriverData data;
|
||||
Manager::Get()->GetDriverStatistics( g_homeId, &data );
|
||||
printf("SOF: %d ACK Waiting: %d Read Aborts: %d Bad Checksums: %d\n", data.s_SOFCnt, data.s_ACKWaiting, data.s_readAborts, data.s_badChecksum);
|
||||
printf("Reads: %d Writes: %d CAN: %d NAK: %d ACK: %d Out of Frame: %d\n", data.s_readCnt, data.s_writeCnt, data.s_CANCnt, data.s_NAKCnt, data.s_ACKCnt, data.s_OOFCnt);
|
||||
printf("Dropped: %d Retries: %d\n", data.s_dropped, data.s_retries);
|
||||
|
||||
while( true )
|
||||
{
|
||||
sleep(10);
|
||||
|
@ -263,7 +301,11 @@ int main( int argc, char* argv[] )
|
|||
pthread_mutex_lock( &g_criticalSection );
|
||||
// Do stuff
|
||||
pthread_mutex_unlock( &g_criticalSection );
|
||||
sleep(5);
|
||||
}
|
||||
}
|
||||
|
||||
Manager::Destroy();
|
||||
|
||||
pthread_mutex_destroy( &g_criticalSection );
|
||||
return 0;
|
||||
|
|
|
@ -42,6 +42,7 @@ struct hid_device_ {
|
|||
int uses_numbered_reports;
|
||||
int disconnected;
|
||||
CFStringRef run_loop_mode;
|
||||
CFRunLoopRef runloopref;
|
||||
uint8_t *input_report_buf;
|
||||
struct input_report *input_reports;
|
||||
pthread_mutex_t mutex;
|
||||
|
@ -624,7 +625,8 @@ int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
|
|||
Need to get some from the OS. */
|
||||
|
||||
/* Move the device's run loop to this thread. */
|
||||
IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetCurrent(), dev->run_loop_mode);
|
||||
dev->runloopref = CFRunLoopGetCurrent();
|
||||
IOHIDDeviceScheduleWithRunLoop(dev->device_handle, dev->runloopref, dev->run_loop_mode);
|
||||
|
||||
if (dev->blocking) {
|
||||
/* Run the Run Loop until it stops timing out. In other
|
||||
|
@ -729,6 +731,8 @@ void HID_API_EXPORT hid_close(hid_device *dev)
|
|||
if (!dev)
|
||||
return;
|
||||
|
||||
CFRunLoopStop(dev->runloopref);
|
||||
|
||||
/* Close the OS handle to the device, but only if it's not
|
||||
been unplugged. If it's been unplugged, then calling
|
||||
IOHIDDeviceClose() will crash. */
|
||||
|
|
|
@ -144,6 +144,8 @@ namespace OpenZWave
|
|||
#define FUNC_ID_ZW_IS_FAILED_NODE_ID 0x62 // Check to see if a specified node has failed
|
||||
#define FUNC_ID_ZW_REPLACE_FAILED_NODE 0x63 // Remove a failed node from the controller's list (?)
|
||||
#define FUNC_ID_ZW_GET_ROUTING_INFO 0x80 // Get a specified node's neighbor information from the controller
|
||||
#define FUNC_ID_ZW_SET_PROMISCUOUS_MODE 0xD0 // Set controller into promiscuous mode to listen to all frames
|
||||
#define FUNC_ID_PROMISCUOUS_APPLICATION_COMMAND_HANDLER 0xD1
|
||||
|
||||
#define ADD_NODE_ANY 0x01
|
||||
#define ADD_NODE_CONTROLLER 0x02
|
||||
|
|
|
@ -116,7 +116,17 @@ Driver::Driver
|
|||
m_controllerCallback( NULL ),
|
||||
m_controllerCallbackContext( NULL ),
|
||||
m_controllerAdded( false ),
|
||||
m_controllerCommandNode( 0 )
|
||||
m_controllerCommandNode( 0 ),
|
||||
m_SOFCnt( 0 ),
|
||||
m_ACKWaiting( 0 ),
|
||||
m_readAborts( 0 ),
|
||||
m_badChecksum( 0 ),
|
||||
m_readCnt( 0 ),
|
||||
m_writeCnt( 0 ),
|
||||
m_CANCnt( 0 ),
|
||||
m_NAKCnt( 0 ),
|
||||
m_ACKCnt( 0 ),
|
||||
m_OOFCnt( 0 )
|
||||
{
|
||||
// Clear the nodes array
|
||||
memset( m_nodes, 0, sizeof(Node*) * 256 );
|
||||
|
@ -159,11 +169,12 @@ Driver::~Driver
|
|||
m_exitEvent->Set();
|
||||
m_wakeEvent->Set();
|
||||
m_pollThread->Stop();
|
||||
m_controllerThread->Stop();
|
||||
m_driverThread->Stop();
|
||||
|
||||
delete m_controller;
|
||||
|
||||
m_controllerThread->Stop();
|
||||
m_driverThread->Stop();
|
||||
|
||||
delete m_pollThread;
|
||||
delete m_controllerThread;
|
||||
delete m_driverThread;
|
||||
|
@ -301,6 +312,7 @@ void Driver::DriverThreadProc
|
|||
{
|
||||
node->m_queryStageCompleted = true;
|
||||
}
|
||||
m_dropped++;
|
||||
RemoveMsg();
|
||||
}
|
||||
else
|
||||
|
@ -329,6 +341,7 @@ void Driver::DriverThreadProc
|
|||
{
|
||||
node->m_queryStageCompleted = true;
|
||||
}
|
||||
m_dropped++;
|
||||
RemoveMsg();
|
||||
}
|
||||
}
|
||||
|
@ -336,6 +349,7 @@ void Driver::DriverThreadProc
|
|||
{
|
||||
// Node is listening, so we'll just retry sending the message.
|
||||
Log::Write( "Resending message (attempt %d)", msg->GetSendAttempts() );
|
||||
m_retries++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -424,6 +438,10 @@ bool Driver::Init
|
|||
{
|
||||
SendMsg(*it);
|
||||
}
|
||||
//If we ever want promiscuous mode uncomment this code.
|
||||
//Msg* msg = new Msg( "FUNC_ID_ZW_SET_PROMISCUOUS_MODE", 0xff, REQUEST, FUNC_ID_ZW_SET_PROMISCUOUS_MODE, false, false );
|
||||
//msg->Append( 0xff );
|
||||
//SendMsg( msg );
|
||||
|
||||
// Init successful
|
||||
return true;
|
||||
|
@ -769,6 +787,7 @@ bool Driver::WriteMsg()
|
|||
Log::Write( "" );
|
||||
Log::Write( "Sending command (Callback ID=0x%.2x, Expected Reply=0x%.2x) - %s", msg->GetCallbackId(), msg->GetExpectedReply(), msg->GetAsString().c_str() );
|
||||
m_controller->Write( msg->GetBuffer(), msg->GetLength() );
|
||||
m_writeCnt++;
|
||||
dataWritten = true;
|
||||
}
|
||||
else
|
||||
|
@ -945,14 +964,16 @@ bool Driver::IsControllerCommand
|
|||
// ranges of commands are used to enhance performance
|
||||
// the commands identified as "Controller Commands" needs to be reviewed as we
|
||||
// understand the protocol better and implement handlers
|
||||
if( ( _command >= FUNC_ID_ZW_SET_DEFAULT ) &&
|
||||
( _command <= FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE ) )
|
||||
if( ( _command >= FUNC_ID_ZW_SET_DEFAULT ) && // 0x42
|
||||
( _command <= FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE ) ) // 0x48
|
||||
return true;
|
||||
if( ( _command >= FUNC_ID_ZW_ADD_NODE_TO_NETWORK ) &&
|
||||
( _command <= FUNC_ID_ZW_SET_LEARN_MODE ) )
|
||||
if( ( _command >= FUNC_ID_ZW_ADD_NODE_TO_NETWORK ) && // 0x4a
|
||||
( _command <= FUNC_ID_ZW_SET_LEARN_MODE ) ) // 0x50
|
||||
return true;
|
||||
if( ( _command >= FUNC_ID_ZW_REMOVE_FAILED_NODE_ID ) &&
|
||||
( _command <= FUNC_ID_ZW_REPLACE_FAILED_NODE ) )
|
||||
if( ( _command >= FUNC_ID_ZW_REMOVE_FAILED_NODE_ID ) && // 0x61
|
||||
( _command <= FUNC_ID_ZW_REPLACE_FAILED_NODE ) ) // 0x63
|
||||
return true;
|
||||
if( _command == FUNC_ID_ZW_GET_ROUTING_INFO ) // 0x80
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -982,9 +1003,11 @@ bool Driver::ReadMsg
|
|||
{
|
||||
case SOF:
|
||||
{
|
||||
m_SOFCnt++;
|
||||
if( m_waitingForAck )
|
||||
{
|
||||
Log::Write( "Unsolicited message received while waiting for ACK." );
|
||||
m_ACKWaiting++;
|
||||
}
|
||||
|
||||
// Read the length byte. Keep trying until we get it.
|
||||
|
@ -1005,6 +1028,7 @@ bool Driver::ReadMsg
|
|||
if( loops == 10 )
|
||||
{
|
||||
Log::Write( "100ms passed without finding the length byte...aborting frame read");
|
||||
m_readAborts++;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1028,6 +1052,7 @@ bool Driver::ReadMsg
|
|||
if( loops == 50 )
|
||||
{
|
||||
Log::Write( "500ms passed without reading the rest of the frame...aborting frame read" );
|
||||
m_readAborts++;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1061,12 +1086,14 @@ bool Driver::ReadMsg
|
|||
uint8 ack = ACK;
|
||||
m_controller->Write( &ack, 1 );
|
||||
|
||||
m_readCnt++;
|
||||
// Process the received message
|
||||
ProcessMsg( &buffer[2] );
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::Write( "Checksum incorrect - sending NAK" );
|
||||
m_badChecksum++;
|
||||
uint8 nak = NAK;
|
||||
m_controller->Write( &nak, 1 );
|
||||
}
|
||||
|
@ -1076,6 +1103,7 @@ bool Driver::ReadMsg
|
|||
case CAN:
|
||||
{
|
||||
Log::Write( "CAN received...triggering resend" );
|
||||
m_CANCnt++;
|
||||
TriggerResend();
|
||||
break;
|
||||
}
|
||||
|
@ -1083,6 +1111,7 @@ bool Driver::ReadMsg
|
|||
case NAK:
|
||||
{
|
||||
Log::Write( "NAK received...triggering resend" );
|
||||
m_NAKCnt++;
|
||||
TriggerResend();
|
||||
break;
|
||||
}
|
||||
|
@ -1090,6 +1119,7 @@ bool Driver::ReadMsg
|
|||
case ACK:
|
||||
{
|
||||
Log::Write( " ACK received CallbackId 0x%.2x Reply 0x%.2x", m_expectedCallbackId, m_expectedReply );
|
||||
m_ACKCnt++;
|
||||
m_waitingForAck = false;
|
||||
|
||||
if( ( 0 == m_expectedCallbackId ) && ( 0 == m_expectedReply ) )
|
||||
|
@ -1103,6 +1133,7 @@ bool Driver::ReadMsg
|
|||
default:
|
||||
{
|
||||
Log::Write( "ERROR! Out of frame flow! (0x%.2x). Sending NAK.", buffer[0] );
|
||||
m_OOFCnt++;
|
||||
uint8 nak = NAK;
|
||||
m_controller->Write( &nak, 1 );
|
||||
break;
|
||||
|
@ -1399,6 +1430,12 @@ void Driver::ProcessMsg
|
|||
HandleReplaceFailedNodeRequest( _data );
|
||||
break;
|
||||
}
|
||||
case FUNC_ID_PROMISCUOUS_APPLICATION_COMMAND_HANDLER:
|
||||
{
|
||||
Log::Write( "" );
|
||||
HandlePromiscuousApplicationCommandHandlerRequest( _data );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
|
@ -1990,6 +2027,7 @@ bool Driver::HandleSendDataRequest
|
|||
{
|
||||
node->m_queryStageCompleted = true;
|
||||
}
|
||||
m_dropped++;
|
||||
RemoveMsg();
|
||||
messageRemoved = true;
|
||||
}
|
||||
|
@ -2461,6 +2499,21 @@ void Driver::HandleApplicationCommandHandlerRequest
|
|||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// <Driver::HandlePromiscuousApplicationCommandHandlerRequest>
|
||||
// Process a request from the Z-Wave PC interface when in promiscuous mode.
|
||||
//-----------------------------------------------------------------------------
|
||||
void Driver::HandlePromiscuousApplicationCommandHandlerRequest
|
||||
(
|
||||
uint8* _data
|
||||
)
|
||||
{
|
||||
//uint8 nodeId = _data[3];
|
||||
//uint8 len = _data[4];
|
||||
//uint8 classId = _data[5];
|
||||
//uint8 destNodeId = _data[5+len];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// <Driver::HandleAssignReturnRouteRequest>
|
||||
// Process a request from the Z-Wave PC interface
|
||||
|
@ -4339,3 +4392,27 @@ bool Driver::HandleReadMemoryResponse
|
|||
Log::Write("Received reply to FUNC_ID_MEMORY_GET_BYTE");
|
||||
return res;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// <Driver::GetDriverStatistics>
|
||||
// Return driver statistics
|
||||
//-----------------------------------------------------------------------------
|
||||
void Driver::GetDriverStatistics
|
||||
(
|
||||
DriverData* _data
|
||||
)
|
||||
{
|
||||
_data->s_SOFCnt = m_SOFCnt;
|
||||
_data->s_ACKWaiting = m_ACKWaiting;
|
||||
_data->s_readAborts = m_readAborts;
|
||||
_data->s_badChecksum = m_badChecksum;
|
||||
_data->s_readCnt = m_readCnt;
|
||||
_data->s_writeCnt = m_writeCnt;
|
||||
_data->s_writeCnt = m_writeCnt;
|
||||
_data->s_CANCnt = m_CANCnt;
|
||||
_data->s_NAKCnt = m_NAKCnt;
|
||||
_data->s_ACKCnt = m_ACKCnt;
|
||||
_data->s_OOFCnt = m_OOFCnt;
|
||||
_data->s_dropped = m_dropped;
|
||||
_data->s_retries = m_retries;
|
||||
}
|
||||
|
|
|
@ -319,6 +319,7 @@ namespace OpenZWave
|
|||
void HandleReplaceFailedNodeRequest( uint8* _data );
|
||||
void HandleRemoveNodeFromNetworkRequest( uint8* _data );
|
||||
void HandleApplicationCommandHandlerRequest( uint8* _data );
|
||||
void HandlePromiscuousApplicationCommandHandlerRequest( uint8* _data );
|
||||
void HandleAssignReturnRouteRequest( uint8* _data );
|
||||
void HandleDeleteReturnRouteRequest( uint8* _data );
|
||||
void HandleNodeNeighborUpdateRequest( uint8* _data );
|
||||
|
@ -529,9 +530,44 @@ namespace OpenZWave
|
|||
void NotifyWatchers(); // Passes the notifications to all the registered watcher callbacks in turn.
|
||||
|
||||
list<Notification*> m_notifications;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Statistics
|
||||
//-----------------------------------------------------------------------------
|
||||
public:
|
||||
struct DriverData
|
||||
{
|
||||
uint32 s_SOFCnt; // Number of SOF bytes received
|
||||
uint32 s_ACKWaiting; // Number of unsolcited messages while waiting for an ACK
|
||||
uint32 s_readAborts; // Number of times read were aborted due to timeouts
|
||||
uint32 s_badChecksum; // Number of bad checksums
|
||||
uint32 s_readCnt; // Number of messages successfully read
|
||||
uint32 s_writeCnt; // Number of messages successfully sent
|
||||
uint32 s_CANCnt; // Number of CAN bytes received
|
||||
uint32 s_NAKCnt; // Number of NAK bytes received
|
||||
uint32 s_ACKCnt; // Number of ACK bytes received
|
||||
uint32 s_OOFCnt; // Number of bytes out of framing
|
||||
uint32 s_dropped; // Number of messages dropped & not delivered
|
||||
uint32 s_retries; // Number of messages retransmitted
|
||||
};
|
||||
|
||||
private:
|
||||
void GetDriverStatistics( DriverData* _data );
|
||||
|
||||
uint32 m_SOFCnt; // Number of SOF bytes received
|
||||
uint32 m_ACKWaiting; // Number of unsolcited messages while waiting for an ACK
|
||||
uint32 m_readAborts; // Number of times read were aborted due to timeouts
|
||||
uint32 m_badChecksum; // Number of bad checksums
|
||||
uint32 m_readCnt; // Number of messages successfully read
|
||||
uint32 m_writeCnt; // Number of messages successfully sent
|
||||
uint32 m_CANCnt; // Number of CAN bytes received
|
||||
uint32 m_NAKCnt; // Number of NAK bytes received
|
||||
uint32 m_ACKCnt; // Number of ACK bytes received
|
||||
uint32 m_OOFCnt; // Number of bytes out of framing
|
||||
uint32 m_dropped; // Number of messages dropped & not delivered
|
||||
uint32 m_retries; // Number of messages retransmitted
|
||||
};
|
||||
|
||||
} // namespace OpenZWave
|
||||
|
||||
#endif // _Driver_H
|
||||
|
||||
|
|
|
@ -3329,3 +3329,20 @@ bool Manager::ActivateScene
|
|||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// <Manager::DriverStatistics>
|
||||
// Retrieve driver based counters.
|
||||
//-----------------------------------------------------------------------------
|
||||
void Manager::GetDriverStatistics
|
||||
(
|
||||
uint32 const _homeId,
|
||||
Driver::DriverData* _data
|
||||
)
|
||||
{
|
||||
if( Driver* driver = GetDriver( _homeId ) )
|
||||
{
|
||||
driver->GetDriverStatistics( _data );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1660,8 +1660,24 @@ namespace OpenZWave
|
|||
bool ActivateScene( uint8 const _sceneId );
|
||||
|
||||
/*@}*/
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Statistics interface
|
||||
//-----------------------------------------------------------------------------
|
||||
/** \name Statistics retrieval interface
|
||||
* Commands for Z-Wave statistics interface.
|
||||
*/
|
||||
/*@{*/
|
||||
public:
|
||||
/**
|
||||
* \brief Retrieve statistics from driver
|
||||
* \param _homeId The Home ID of the driver to obtain counters
|
||||
* \param _data Pointer to structure DriverData to return values
|
||||
*/
|
||||
void GetDriverStatistics( uint32 const _homeId, Driver::DriverData* _data );
|
||||
|
||||
};
|
||||
/*@}*/
|
||||
} // namespace OpenZWave
|
||||
|
||||
#endif // _Manager_H
|
||||
|
|
|
@ -517,6 +517,11 @@ uint32 Node::GetNeighbors
|
|||
// determine how many neighbors there are
|
||||
int i;
|
||||
uint32 numNeighbors = 0;
|
||||
if( m_queryStage < QueryStage_Session )
|
||||
{
|
||||
*o_neighbors = NULL;
|
||||
return 0;
|
||||
}
|
||||
for( i = 0; i < 29; i++ )
|
||||
{
|
||||
for( unsigned char mask = 0x80; mask != 0; mask >>= 1 )
|
||||
|
|
|
@ -166,48 +166,53 @@ bool SensorMultilevel::HandleMsg
|
|||
if (SensorMultilevelCmd_Report == (SensorMultilevelCmd)_data[0])
|
||||
{
|
||||
uint8 scale;
|
||||
uint8 sensorType = _data[1];
|
||||
string valueStr = ExtractValue( &_data[2], &scale );
|
||||
|
||||
if( ValueDecimal* value = static_cast<ValueDecimal*>( GetValue( _instance, 0 ) ) )
|
||||
Node* node = GetNodeUnsafe();
|
||||
if( node != NULL )
|
||||
{
|
||||
value->SetLabel( c_sensorTypeNames[_data[1]] );
|
||||
switch( _data[1] )
|
||||
ValueDecimal* value = static_cast<ValueDecimal*>( GetValue( _instance, sensorType ) );
|
||||
if( value == NULL)
|
||||
{
|
||||
case SensorType_Temperature: value->SetUnits( scale ? "F" : "C" ); break;
|
||||
case SensorType_General: value->SetUnits( scale ? "" : "%" ); break;
|
||||
case SensorType_Luminance: value->SetUnits( scale ? "lux" : "%" ); break;
|
||||
case SensorType_Power: value->SetUnits( scale ? "BTU/h" : "W" ); break;
|
||||
case SensorType_RelativeHumidity: value->SetUnits( "%" ); break;
|
||||
case SensorType_Velocity: value->SetUnits( scale ? "mph" : "m/s" ); break;
|
||||
case SensorType_Direction: value->SetUnits( "" ); break;
|
||||
case SensorType_AtmosphericPressure: value->SetUnits( scale ? "inHg" : "kPa" ); break;
|
||||
case SensorType_BarometricPressure: value->SetUnits( scale ? "inHg" : "kPa" ); break;
|
||||
case SensorType_SolarRadiation: value->SetUnits( "W/m2" ); break;
|
||||
case SensorType_DewPoint: value->SetUnits( scale ? "in/h" : "mm/h" ); break;
|
||||
case SensorType_RainRate: value->SetUnits( scale ? "F" : "C" ); break;
|
||||
case SensorType_TideLevel: value->SetUnits( scale ? "ft" : "m" ); break;
|
||||
case SensorType_Weight: value->SetUnits( scale ? "lb" : "kg" ); break;
|
||||
case SensorType_Voltage: value->SetUnits( scale ? "mV" : "V" ); break;
|
||||
case SensorType_Current: value->SetUnits( scale ? "mA" : "A" ); break;
|
||||
case SensorType_CO2: value->SetUnits( "ppm" ); break;
|
||||
case SensorType_AirFlow: value->SetUnits( scale ? "cfm" : "m3/h" ); break;
|
||||
case SensorType_TankCapacity: value->SetUnits( c_tankCapcityUnits[scale] ); break;
|
||||
case SensorType_Distance: value->SetUnits( c_distanceUnits[scale] ); break;
|
||||
char const* units = "";
|
||||
switch( sensorType )
|
||||
{
|
||||
case SensorType_Temperature: units = scale ? "F" : "C"; break;
|
||||
case SensorType_General: units = scale ? "" : "%"; break;
|
||||
case SensorType_Luminance: units = scale ? "lux" : "%"; break;
|
||||
case SensorType_Power: units = scale ? "BTU/h" : "W"; break;
|
||||
case SensorType_RelativeHumidity: units = "%"; break;
|
||||
case SensorType_Velocity: units = scale ? "mph" : "m/s"; break;
|
||||
case SensorType_Direction: units = ""; break;
|
||||
case SensorType_AtmosphericPressure: units = scale ? "inHg" : "kPa"; break;
|
||||
case SensorType_BarometricPressure: units = scale ? "inHg" : "kPa"; break;
|
||||
case SensorType_SolarRadiation: units = "W/m2"; break;
|
||||
case SensorType_DewPoint: units = scale ? "in/h" : "mm/h"; break;
|
||||
case SensorType_RainRate: units = scale ? "F" : "C"; break;
|
||||
case SensorType_TideLevel: units = scale ? "ft" : "m"; break;
|
||||
case SensorType_Weight: units = scale ? "lb" : "kg"; break;
|
||||
case SensorType_Voltage: units = scale ? "mV" : "V"; break;
|
||||
case SensorType_Current: units = scale ? "mA" : "A"; break;
|
||||
case SensorType_CO2: units = "ppm"; break;
|
||||
case SensorType_AirFlow: units = scale ? "cfm" : "m3/h"; break;
|
||||
case SensorType_TankCapacity: units = c_tankCapcityUnits[scale]; break;
|
||||
case SensorType_Distance: units = c_distanceUnits[scale]; break;
|
||||
default: break;
|
||||
}
|
||||
value = node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, sensorType, c_sensorTypeNames[sensorType], units, true, false, "0.0" );
|
||||
}
|
||||
|
||||
Log::Write( "Received SensorMultiLevel report from node %d, instance %d: value=%s%s", GetNodeId(), _instance, valueStr.c_str(), value->GetUnits().c_str() );
|
||||
value->OnValueChanged( valueStr );
|
||||
}
|
||||
|
||||
Node* node = GetNodeUnsafe();
|
||||
if( node != NULL && node->m_queryPending )
|
||||
if( node->m_queryPending )
|
||||
{
|
||||
node->m_queryStageCompleted = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -220,10 +225,7 @@ void SensorMultilevel::CreateVars
|
|||
uint8 const _instance
|
||||
)
|
||||
{
|
||||
if( Node* node = GetNodeUnsafe() )
|
||||
{
|
||||
node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Unknown", "", true, false, "0.0" );
|
||||
}
|
||||
// Don't create anything here. We do it in the report.
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ bool HidControllerImpl::Open
|
|||
m_hHidController = hid_open( _vendorId, _productId, NULL );
|
||||
if ( !m_hHidController )
|
||||
{
|
||||
Log::Write( "Cannot find specified HID port with VID:%04hx and PID:0x%04hx.\n", _vendorId, _productId );
|
||||
Log::Write( "Cannot find specified HID port with VID:%04hx and PID:0x%04hx.", _vendorId, _productId );
|
||||
|
||||
// Enumerate connected HIDs for debugging purposes
|
||||
// Note: most OS intentionally hide keyboard/mouse devices from HID access
|
||||
|
@ -97,10 +97,10 @@ bool HidControllerImpl::Open
|
|||
devices = hid_enumerate( 0x0, 0x0 );
|
||||
currentDevice = devices;
|
||||
|
||||
Log::Write( "Enumerating connected HIDs:\n" );
|
||||
Log::Write( "Enumerating connected HIDs:" );
|
||||
while( currentDevice )
|
||||
{
|
||||
Log::Write( "\tVID:%04hx\tPID:0x%04hx\tSN:%ls\tMfg:%ls\tProd:%ls\tPath:%s\n",
|
||||
Log::Write( "\tVID:%04hx\tPID:0x%04hx\tSN:%ls\tMfg:%ls\tProd:%ls\tPath:%s",
|
||||
currentDevice->vendor_id,
|
||||
currentDevice->product_id,
|
||||
currentDevice->serial_number,
|
||||
|
@ -222,7 +222,7 @@ uint32 HidControllerImpl::Read
|
|||
if( !m_hidControllerOpen )
|
||||
{
|
||||
//Error
|
||||
Log::Write( "Error: HID port must be opened before reading\n" );
|
||||
Log::Write( "Error: HID port must be opened before reading" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -275,8 +275,7 @@ uint32 HidControllerImpl::Read
|
|||
return _length;
|
||||
HidPortError:
|
||||
//Error
|
||||
Log::Write( "Error: HID port returned error reading rest of packet: 0x%08hx, HIDAPI error string:", m_hidFeatureReportReadBufferBytes );
|
||||
Log::Write("%ls\n", hid_error(m_hHidController));
|
||||
Log::Write( "Error: HID port returned error reading rest of packet: %d, HIDAPI error string: %ls", m_hidFeatureReportReadBufferBytes, hid_error(m_hHidController));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -293,14 +292,14 @@ uint32 HidControllerImpl::Write
|
|||
if( !m_hidControllerOpen )
|
||||
{
|
||||
//Error
|
||||
Log::Write( "Error: HID port must be opened before writing\n" );
|
||||
Log::Write( "Error: HID port must be opened before writing" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( FEATURE_REPORT_LENGTH - 2 < _length)
|
||||
{
|
||||
//Error
|
||||
Log::Write( "Error: Write buffer length %d exceeded feature report data capacity %d\n",
|
||||
Log::Write( "Error: Write buffer length %d exceeded feature report data capacity %d",
|
||||
_length,
|
||||
FEATURE_REPORT_LENGTH - 2 );
|
||||
return 0;
|
||||
|
@ -320,9 +319,7 @@ uint32 HidControllerImpl::Write
|
|||
if (bytesSent < 2)
|
||||
{
|
||||
//Error
|
||||
Log::Write( "Error: HID port returned error sending bytes: 0x%08hx, HIDAPI error string:", bytesSent );
|
||||
const wchar_t* errString = hid_error( m_hHidController );
|
||||
Log::Write( "%ls\n", errString );
|
||||
Log::Write( "Error: HID port returned error sending bytes: %d, HIDAPI error string: %ls", bytesSent, hid_error( m_hHidController ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -373,18 +370,13 @@ bool HidControllerImpl::Wait
|
|||
default:
|
||||
{
|
||||
//Error
|
||||
Log::Write( "Error: HID port returned unexpected input report data in byte 2 during Wait(): 0x%08hx\n", inputReport[2] );
|
||||
Log::Write( "Error: HID port returned unexpected input report data in byte 2 during Wait(): 0x%08hx", inputReport[2] );
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// continue looping until some rx feature report data is reported via input report
|
||||
}
|
||||
|
||||
//Error
|
||||
Log::Write( "Error: HID port returned error reading input bytes: 0x%08hx, HIDAPI error string:", hidApiResult );
|
||||
const wchar_t* errString = hid_error( m_hHidController );
|
||||
Log::Write( "%ls\n", errString );
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -406,7 +398,7 @@ int HidControllerImpl::GetFeatureReport
|
|||
result = hid_get_feature_report( m_hHidController, _buffer, _length );
|
||||
if (result < 0)
|
||||
{
|
||||
Log::Write( "Error: HID GetFeatureReport on ID 0x%hx returned (0x%.8x)\n", _reportId, result );
|
||||
Log::Write( "Error: HID GetFeatureReport on ID 0x%hx returned (0x%.8x)", _reportId, result );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -426,7 +418,7 @@ int HidControllerImpl::SendFeatureReport
|
|||
result = hid_send_feature_report( m_hHidController, _data, _length );
|
||||
if (result < 0)
|
||||
{
|
||||
Log::Write( "Error: HID SendFeatureReport on ID 0x%hx returned (0x%.8x)\n", _data[0], result );
|
||||
Log::Write( "Error: HID SendFeatureReport on ID 0x%hx returned (0x%.8x)", _data[0], result );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue