mirror of
https://github.com/Fishwaldo/open-zwave.git
synced 2025-07-08 22:19:06 +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 <pthread.h>
|
||||||
#include "Options.h"
|
#include "Options.h"
|
||||||
#include "Manager.h"
|
#include "Manager.h"
|
||||||
|
#include "Driver.h"
|
||||||
#include "Node.h"
|
#include "Node.h"
|
||||||
#include "Group.h"
|
#include "Group.h"
|
||||||
#include "Notification.h"
|
#include "Notification.h"
|
||||||
|
@ -180,6 +181,7 @@ void OnNotification
|
||||||
{
|
{
|
||||||
// We have received an event from the node, caused by a
|
// We have received an event from the node, caused by a
|
||||||
// basic_set or hail message.
|
// basic_set or hail message.
|
||||||
|
// TBD...
|
||||||
nodeInfo = nodeInfo;
|
nodeInfo = nodeInfo;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -208,7 +210,7 @@ void OnNotification
|
||||||
g_homeId = _notification->GetHomeId();
|
g_homeId = _notification->GetHomeId();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
case Notification::Type_DriverFailed:
|
case Notification::Type_DriverFailed:
|
||||||
{
|
{
|
||||||
|
@ -217,7 +219,7 @@ void OnNotification
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Notification::Type_AwakeNodesQueried:
|
case Notification::Type_AwakeNodesQueried:
|
||||||
case Notification::Type_AllNodesQueried:
|
case Notification::Type_AllNodesQueried:
|
||||||
{
|
{
|
||||||
pthread_cond_broadcast(&initCond);
|
pthread_cond_broadcast(&initCond);
|
||||||
|
@ -239,13 +241,13 @@ int main( int argc, char* argv[] )
|
||||||
{
|
{
|
||||||
pthread_mutexattr_t mutexattr;
|
pthread_mutexattr_t mutexattr;
|
||||||
|
|
||||||
pthread_mutexattr_init ( &mutexattr );
|
pthread_mutexattr_init ( &mutexattr );
|
||||||
pthread_mutexattr_settype( &mutexattr, PTHREAD_MUTEX_RECURSIVE );
|
pthread_mutexattr_settype( &mutexattr, PTHREAD_MUTEX_RECURSIVE );
|
||||||
pthread_mutex_init( &g_criticalSection, &mutexattr );
|
pthread_mutex_init( &g_criticalSection, &mutexattr );
|
||||||
pthread_mutexattr_destroy(&mutexattr);
|
pthread_mutexattr_destroy( &mutexattr );
|
||||||
|
|
||||||
pthread_mutex_lock(&initMutex);
|
pthread_mutex_lock( &initMutex );
|
||||||
|
|
||||||
// Create the OpenZWave Manager.
|
// Create the OpenZWave Manager.
|
||||||
// The first argument is the path to the config files (where the manufacturer_specific.xml file is located
|
// 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
|
// The second argument is the path for saved Z-Wave network state and the log file. If you leave it NULL
|
||||||
|
@ -263,18 +265,19 @@ int main( int argc, char* argv[] )
|
||||||
|
|
||||||
// Add a Z-Wave Driver
|
// Add a Z-Wave Driver
|
||||||
// Modify this line to set the correct serial port for your PC interface.
|
// Modify this line to set the correct serial port for your PC interface.
|
||||||
|
|
||||||
string port = "/dev/ttyUSB0";
|
string port = "/dev/ttyUSB0";
|
||||||
|
|
||||||
Manager::Get()->AddDriver((argc > 1) ? argv[1] : port);
|
Manager::Get()->AddDriver( ( argc > 1 ) ? argv[1] : port );
|
||||||
//Manager::Get()->AddDriver( "HID Controller", Driver::ControllerInterface_Hid );
|
//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.
|
// 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.
|
// In a normal app, we would be handling notifications and building a UI for the user.
|
||||||
pthread_cond_wait(&initCond, &initMutex);
|
pthread_cond_wait( &initCond, &initMutex );
|
||||||
|
|
||||||
if (!g_initFailed) {
|
if( !g_initFailed )
|
||||||
|
{
|
||||||
|
|
||||||
//Manager::Get()->BeginAddNode( g_homeId );
|
//Manager::Get()->BeginAddNode( g_homeId );
|
||||||
//sleep(10);
|
//sleep(10);
|
||||||
//Manager::Get()->EndAddNode( g_homeId );
|
//Manager::Get()->EndAddNode( g_homeId );
|
||||||
|
@ -282,11 +285,19 @@ int main( int argc, char* argv[] )
|
||||||
//sleep(10);
|
//sleep(10);
|
||||||
//Manager::Get()->EndRemoveNode( g_homeId );
|
//Manager::Get()->EndRemoveNode( g_homeId );
|
||||||
//sleep(10);
|
//sleep(10);
|
||||||
|
|
||||||
Manager::Get()->WriteConfig(g_homeId);
|
Manager::Get()->WriteConfig( g_homeId );
|
||||||
|
|
||||||
while(true)
|
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 );
|
pthread_mutex_lock( &g_criticalSection );
|
||||||
// Do stuff
|
// Do stuff
|
||||||
pthread_mutex_unlock( &g_criticalSection );
|
pthread_mutex_unlock( &g_criticalSection );
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include "Options.h"
|
#include "Options.h"
|
||||||
#include "Manager.h"
|
#include "Manager.h"
|
||||||
|
#include "Driver.h"
|
||||||
#include "Node.h"
|
#include "Node.h"
|
||||||
#include "Group.h"
|
#include "Group.h"
|
||||||
#include "Notification.h"
|
#include "Notification.h"
|
||||||
|
@ -44,8 +45,9 @@
|
||||||
using namespace OpenZWave;
|
using namespace OpenZWave;
|
||||||
|
|
||||||
static uint32 g_homeId = 0;
|
static uint32 g_homeId = 0;
|
||||||
|
static bool g_initFailed = false;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint32 m_homeId;
|
uint32 m_homeId;
|
||||||
uint8 m_nodeId;
|
uint8 m_nodeId;
|
||||||
|
@ -55,6 +57,8 @@ typedef struct
|
||||||
|
|
||||||
static list<NodeInfo*> g_nodes;
|
static list<NodeInfo*> g_nodes;
|
||||||
static pthread_mutex_t g_criticalSection;
|
static pthread_mutex_t g_criticalSection;
|
||||||
|
static pthread_cond_t initCond = PTHREAD_COND_INITIALIZER;
|
||||||
|
static pthread_mutex_t initMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// <GetNodeInfo>
|
// <GetNodeInfo>
|
||||||
|
@ -127,6 +131,7 @@ void OnNotification
|
||||||
{
|
{
|
||||||
// One of the node values has changed
|
// One of the node values has changed
|
||||||
// TBD...
|
// TBD...
|
||||||
|
nodeInfo = nodeInfo;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -137,6 +142,7 @@ void OnNotification
|
||||||
{
|
{
|
||||||
// One of the node's association groups has changed
|
// One of the node's association groups has changed
|
||||||
// TBD...
|
// TBD...
|
||||||
|
nodeInfo = nodeInfo;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -176,6 +182,7 @@ void OnNotification
|
||||||
// We have received an event from the node, caused by a
|
// We have received an event from the node, caused by a
|
||||||
// basic_set or hail message.
|
// basic_set or hail message.
|
||||||
// TBD...
|
// TBD...
|
||||||
|
nodeInfo = nodeInfo;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -203,11 +210,29 @@ void OnNotification
|
||||||
g_homeId = _notification->GetHomeId();
|
g_homeId = _notification->GetHomeId();
|
||||||
break;
|
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 );
|
pthread_mutex_unlock( &g_criticalSection );
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// <main>
|
// <main>
|
||||||
// Create the driver and then wait
|
// Create the driver and then wait
|
||||||
|
@ -216,10 +241,13 @@ int main( int argc, char* argv[] )
|
||||||
{
|
{
|
||||||
pthread_mutexattr_t mutexattr;
|
pthread_mutexattr_t mutexattr;
|
||||||
|
|
||||||
|
pthread_mutexattr_init ( &mutexattr );
|
||||||
pthread_mutexattr_settype( &mutexattr, PTHREAD_MUTEX_RECURSIVE );
|
pthread_mutexattr_settype( &mutexattr, PTHREAD_MUTEX_RECURSIVE );
|
||||||
pthread_mutex_init( &g_criticalSection, &mutexattr );
|
pthread_mutex_init( &g_criticalSection, &mutexattr );
|
||||||
pthread_mutexattr_destroy( &mutexattr );
|
pthread_mutexattr_destroy( &mutexattr );
|
||||||
|
|
||||||
|
pthread_mutex_lock( &initMutex );
|
||||||
|
|
||||||
// Create the OpenZWave Manager.
|
// Create the OpenZWave Manager.
|
||||||
// The first argument is the path to the config files (where the manufacturer_specific.xml file is located
|
// 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
|
// The second argument is the path for saved Z-Wave network state and the log file. If you leave it NULL
|
||||||
|
@ -237,33 +265,47 @@ int main( int argc, char* argv[] )
|
||||||
|
|
||||||
// Add a Z-Wave Driver
|
// Add a Z-Wave Driver
|
||||||
// Modify this line to set the correct serial port for your PC interface.
|
// 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 );
|
//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.
|
// 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.
|
// 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);
|
||||||
|
//Manager::Get()->EndAddNode( g_homeId );
|
||||||
|
//Manager::Get()->BeginRemoveNode( g_homeId );
|
||||||
|
//sleep(10);
|
||||||
|
//Manager::Get()->EndRemoveNode( g_homeId );
|
||||||
|
//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);
|
||||||
|
|
||||||
|
pthread_mutex_lock( &g_criticalSection );
|
||||||
|
// Do stuff
|
||||||
|
pthread_mutex_unlock( &g_criticalSection );
|
||||||
|
sleep(5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Manager::Get()->BeginAddNode( g_homeId );
|
Manager::Destroy();
|
||||||
//sleep(10);
|
|
||||||
//Manager::Get()->EndAddNode( g_homeId );
|
|
||||||
//Manager::Get()->BeginRemoveNode( g_homeId );
|
|
||||||
//sleep(10);
|
|
||||||
//Manager::Get()->EndRemoveNode( g_homeId );
|
|
||||||
sleep(10);
|
|
||||||
Manager::Get()->WriteConfig( g_homeId );
|
|
||||||
|
|
||||||
while( true )
|
|
||||||
{
|
|
||||||
sleep(10);
|
|
||||||
|
|
||||||
pthread_mutex_lock( &g_criticalSection );
|
|
||||||
// Do stuff
|
|
||||||
pthread_mutex_unlock( &g_criticalSection );
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_destroy( &g_criticalSection );
|
pthread_mutex_destroy( &g_criticalSection );
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -42,6 +42,7 @@ struct hid_device_ {
|
||||||
int uses_numbered_reports;
|
int uses_numbered_reports;
|
||||||
int disconnected;
|
int disconnected;
|
||||||
CFStringRef run_loop_mode;
|
CFStringRef run_loop_mode;
|
||||||
|
CFRunLoopRef runloopref;
|
||||||
uint8_t *input_report_buf;
|
uint8_t *input_report_buf;
|
||||||
struct input_report *input_reports;
|
struct input_report *input_reports;
|
||||||
pthread_mutex_t mutex;
|
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. */
|
Need to get some from the OS. */
|
||||||
|
|
||||||
/* Move the device's run loop to this thread. */
|
/* 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) {
|
if (dev->blocking) {
|
||||||
/* Run the Run Loop until it stops timing out. In other
|
/* Run the Run Loop until it stops timing out. In other
|
||||||
|
@ -633,7 +635,7 @@ int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
|
||||||
SInt32 code;
|
SInt32 code;
|
||||||
while (1) {
|
while (1) {
|
||||||
code = CFRunLoopRunInMode(dev->run_loop_mode, 1000, TRUE);
|
code = CFRunLoopRunInMode(dev->run_loop_mode, 1000, TRUE);
|
||||||
|
|
||||||
/* Return if the device has been disconnected */
|
/* Return if the device has been disconnected */
|
||||||
if (code == kCFRunLoopRunFinished) {
|
if (code == kCFRunLoopRunFinished) {
|
||||||
dev->disconnected = 1;
|
dev->disconnected = 1;
|
||||||
|
@ -729,6 +731,8 @@ void HID_API_EXPORT hid_close(hid_device *dev)
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
CFRunLoopStop(dev->runloopref);
|
||||||
|
|
||||||
/* Close the OS handle to the device, but only if it's not
|
/* Close the OS handle to the device, but only if it's not
|
||||||
been unplugged. If it's been unplugged, then calling
|
been unplugged. If it's been unplugged, then calling
|
||||||
IOHIDDeviceClose() will crash. */
|
IOHIDDeviceClose() will crash. */
|
||||||
|
|
|
@ -106,44 +106,46 @@ namespace OpenZWave
|
||||||
|
|
||||||
#define RECEIVE_STATUS_TYPE_BROAD 0x04
|
#define RECEIVE_STATUS_TYPE_BROAD 0x04
|
||||||
|
|
||||||
#define FUNC_ID_SERIAL_API_GET_INIT_DATA 0x02
|
#define FUNC_ID_SERIAL_API_GET_INIT_DATA 0x02
|
||||||
#define FUNC_ID_APPLICATION_COMMAND_HANDLER 0x04
|
#define FUNC_ID_APPLICATION_COMMAND_HANDLER 0x04
|
||||||
#define FUNC_ID_ZW_GET_CONTROLLER_CAPABILITIES 0x05
|
#define FUNC_ID_ZW_GET_CONTROLLER_CAPABILITIES 0x05
|
||||||
#define FUNC_ID_SERIAL_API_SET_TIMEOUTS 0x06
|
#define FUNC_ID_SERIAL_API_SET_TIMEOUTS 0x06
|
||||||
#define FUNC_ID_SERIAL_API_GET_CAPABILITIES 0x07
|
#define FUNC_ID_SERIAL_API_GET_CAPABILITIES 0x07
|
||||||
#define FUNC_ID_SERIAL_API_SOFT_RESET 0x08
|
#define FUNC_ID_SERIAL_API_SOFT_RESET 0x08
|
||||||
|
|
||||||
#define FUNC_ID_ZW_SEND_DATA 0x13
|
#define FUNC_ID_ZW_SEND_DATA 0x13
|
||||||
#define FUNC_ID_ZW_GET_VERSION 0x15
|
#define FUNC_ID_ZW_GET_VERSION 0x15
|
||||||
#define FUNC_ID_ZW_R_F_POWER_LEVEL_SET 0x17
|
#define FUNC_ID_ZW_R_F_POWER_LEVEL_SET 0x17
|
||||||
#define FUNC_ID_ZW_MEMORY_GET_ID 0x20
|
#define FUNC_ID_ZW_MEMORY_GET_ID 0x20
|
||||||
#define FUNC_ID_MEMORY_GET_BYTE 0x21
|
#define FUNC_ID_MEMORY_GET_BYTE 0x21
|
||||||
#define FUNC_ID_ZW_READ_MEMORY 0x23
|
#define FUNC_ID_ZW_READ_MEMORY 0x23
|
||||||
|
|
||||||
#define FUNC_ID_ZW_SET_LEARN_NODE_STATE 0x40 // Not implemented
|
#define FUNC_ID_ZW_SET_LEARN_NODE_STATE 0x40 // Not implemented
|
||||||
#define FUNC_ID_ZW_GET_NODE_PROTOCOL_INFO 0x41 // Get protocol info (baud rate, listening, etc.) for a given node
|
#define FUNC_ID_ZW_GET_NODE_PROTOCOL_INFO 0x41 // Get protocol info (baud rate, listening, etc.) for a given node
|
||||||
#define FUNC_ID_ZW_SET_DEFAULT 0x42 // Reset controller and node info to default (original) values
|
#define FUNC_ID_ZW_SET_DEFAULT 0x42 // Reset controller and node info to default (original) values
|
||||||
#define FUNC_ID_ZW_NEW_CONTROLLER 0x43 // Not implemented
|
#define FUNC_ID_ZW_NEW_CONTROLLER 0x43 // Not implemented
|
||||||
#define FUNC_ID_ZW_REPLICATION_COMMAND_COMPLETE 0x44 // Replication isn't implemented (yet)
|
#define FUNC_ID_ZW_REPLICATION_COMMAND_COMPLETE 0x44 // Replication isn't implemented (yet)
|
||||||
#define FUNC_ID_ZW_REPLICATION_SEND_DATA 0x45 // Replication isn't implemented (yet)
|
#define FUNC_ID_ZW_REPLICATION_SEND_DATA 0x45 // Replication isn't implemented (yet)
|
||||||
#define FUNC_ID_ZW_ASSIGN_RETURN_ROUTE 0x46 // Assign a return route from the specified node to the controller
|
#define FUNC_ID_ZW_ASSIGN_RETURN_ROUTE 0x46 // Assign a return route from the specified node to the controller
|
||||||
#define FUNC_ID_ZW_DELETE_RETURN_ROUTE 0x47 // Delete all return routes from the specified node
|
#define FUNC_ID_ZW_DELETE_RETURN_ROUTE 0x47 // Delete all return routes from the specified node
|
||||||
#define FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE 0x48 // Ask the specified node to update its neighbors (then read them from the controller)
|
#define FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE 0x48 // Ask the specified node to update its neighbors (then read them from the controller)
|
||||||
#define FUNC_ID_ZW_APPLICATION_UPDATE 0x49 // Get a list of supported (and controller) command classes
|
#define FUNC_ID_ZW_APPLICATION_UPDATE 0x49 // Get a list of supported (and controller) command classes
|
||||||
#define FUNC_ID_ZW_ADD_NODE_TO_NETWORK 0x4a // Control the addnode (or addcontroller) process...start, stop, etc.
|
#define FUNC_ID_ZW_ADD_NODE_TO_NETWORK 0x4a // Control the addnode (or addcontroller) process...start, stop, etc.
|
||||||
#define FUNC_ID_ZW_REMOVE_NODE_FROM_NETWORK 0x4b // Control the removenode (or removecontroller) process...start, stop, etc.
|
#define FUNC_ID_ZW_REMOVE_NODE_FROM_NETWORK 0x4b // Control the removenode (or removecontroller) process...start, stop, etc.
|
||||||
#define FUNC_ID_ZW_CREATE_NEW_PRIMARY 0x4c // Control the createnewprimary process...start, stop, etc.
|
#define FUNC_ID_ZW_CREATE_NEW_PRIMARY 0x4c // Control the createnewprimary process...start, stop, etc.
|
||||||
#define FUNC_ID_ZW_CONTROLLER_CHANGE 0x4d // Control the transferprimary process...start, stop, etc.
|
#define FUNC_ID_ZW_CONTROLLER_CHANGE 0x4d // Control the transferprimary process...start, stop, etc.
|
||||||
#define FUNC_ID_ZW_SET_LEARN_MODE 0x50 // Put a controller into learn mode for replication/ receipt of configuration info
|
#define FUNC_ID_ZW_SET_LEARN_MODE 0x50 // Put a controller into learn mode for replication/ receipt of configuration info
|
||||||
#define FUNC_ID_ZW_ENABLE_SUC 0x52 // Make a controller a Static Update Controller
|
#define FUNC_ID_ZW_ENABLE_SUC 0x52 // Make a controller a Static Update Controller
|
||||||
#define FUNC_ID_ZW_REQUEST_NETWORK_UPDATE 0x53 // Network update for a SUC(?)
|
#define FUNC_ID_ZW_REQUEST_NETWORK_UPDATE 0x53 // Network update for a SUC(?)
|
||||||
#define FUNC_ID_ZW_SET_SUC_NODE_ID 0x54 // Identify a Static Update Controller node id
|
#define FUNC_ID_ZW_SET_SUC_NODE_ID 0x54 // Identify a Static Update Controller node id
|
||||||
#define FUNC_ID_ZW_GET_SUC_NODE_ID 0x56 // Try to retrieve a Static Update Controller node id (zero if no SUC present)
|
#define FUNC_ID_ZW_GET_SUC_NODE_ID 0x56 // Try to retrieve a Static Update Controller node id (zero if no SUC present)
|
||||||
#define FUNC_ID_ZW_REQUEST_NODE_INFO 0x60 // Get info (supported command classes) for the specified node
|
#define FUNC_ID_ZW_REQUEST_NODE_INFO 0x60 // Get info (supported command classes) for the specified node
|
||||||
#define FUNC_ID_ZW_REMOVE_FAILED_NODE_ID 0x61 // Mark a specified node id as failed
|
#define FUNC_ID_ZW_REMOVE_FAILED_NODE_ID 0x61 // Mark a specified node id as failed
|
||||||
#define FUNC_ID_ZW_IS_FAILED_NODE_ID 0x62 // Check to see if a specified node has failed
|
#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_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_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_ANY 0x01
|
||||||
#define ADD_NODE_CONTROLLER 0x02
|
#define ADD_NODE_CONTROLLER 0x02
|
||||||
|
|
|
@ -116,29 +116,39 @@ Driver::Driver
|
||||||
m_controllerCallback( NULL ),
|
m_controllerCallback( NULL ),
|
||||||
m_controllerCallbackContext( NULL ),
|
m_controllerCallbackContext( NULL ),
|
||||||
m_controllerAdded( false ),
|
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
|
// Clear the nodes array
|
||||||
memset( m_nodes, 0, sizeof(Node*) * 256 );
|
memset( m_nodes, 0, sizeof(Node*) * 256 );
|
||||||
|
|
||||||
switch (_interface)
|
switch (_interface)
|
||||||
{
|
{
|
||||||
case ControllerInterface_Serial:
|
case ControllerInterface_Serial:
|
||||||
{
|
{
|
||||||
m_controller = (IController*) new SerialController();
|
m_controller = (IController*) new SerialController();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ControllerInterface_Hid:
|
case ControllerInterface_Hid:
|
||||||
{
|
{
|
||||||
m_controller = (IController*) new HidController();
|
m_controller = (IController*) new HidController();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
m_controller = (IController*) new SerialController();
|
m_controller = (IController*) new SerialController();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -159,11 +169,12 @@ Driver::~Driver
|
||||||
m_exitEvent->Set();
|
m_exitEvent->Set();
|
||||||
m_wakeEvent->Set();
|
m_wakeEvent->Set();
|
||||||
m_pollThread->Stop();
|
m_pollThread->Stop();
|
||||||
m_controllerThread->Stop();
|
|
||||||
m_driverThread->Stop();
|
|
||||||
|
|
||||||
delete m_controller;
|
delete m_controller;
|
||||||
|
|
||||||
|
m_controllerThread->Stop();
|
||||||
|
m_driverThread->Stop();
|
||||||
|
|
||||||
delete m_pollThread;
|
delete m_pollThread;
|
||||||
delete m_controllerThread;
|
delete m_controllerThread;
|
||||||
delete m_driverThread;
|
delete m_driverThread;
|
||||||
|
@ -301,6 +312,7 @@ void Driver::DriverThreadProc
|
||||||
{
|
{
|
||||||
node->m_queryStageCompleted = true;
|
node->m_queryStageCompleted = true;
|
||||||
}
|
}
|
||||||
|
m_dropped++;
|
||||||
RemoveMsg();
|
RemoveMsg();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -329,6 +341,7 @@ void Driver::DriverThreadProc
|
||||||
{
|
{
|
||||||
node->m_queryStageCompleted = true;
|
node->m_queryStageCompleted = true;
|
||||||
}
|
}
|
||||||
|
m_dropped++;
|
||||||
RemoveMsg();
|
RemoveMsg();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -336,7 +349,8 @@ void Driver::DriverThreadProc
|
||||||
{
|
{
|
||||||
// Node is listening, so we'll just retry sending the message.
|
// Node is listening, so we'll just retry sending the message.
|
||||||
Log::Write( "Resending message (attempt %d)", msg->GetSendAttempts() );
|
Log::Write( "Resending message (attempt %d)", msg->GetSendAttempts() );
|
||||||
}
|
m_retries++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -418,12 +432,16 @@ bool Driver::Init
|
||||||
uint8 nak = NAK;
|
uint8 nak = NAK;
|
||||||
m_controller->Write( &nak, 1 );
|
m_controller->Write( &nak, 1 );
|
||||||
|
|
||||||
// Get/set ZWave controller information in its preferred initialization order
|
// Get/set ZWave controller information in its preferred initialization order
|
||||||
list<Msg*>* const pMsgInitArray = m_controller->GetMsgInitializationSequence();
|
list<Msg*>* const pMsgInitArray = m_controller->GetMsgInitializationSequence();
|
||||||
for (list<Msg*>::iterator it = pMsgInitArray->begin(); it != pMsgInitArray->end(); it++)
|
for (list<Msg*>::iterator it = pMsgInitArray->begin(); it != pMsgInitArray->end(); it++)
|
||||||
{
|
{
|
||||||
SendMsg(*it);
|
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
|
// Init successful
|
||||||
return true;
|
return true;
|
||||||
|
@ -769,6 +787,7 @@ bool Driver::WriteMsg()
|
||||||
Log::Write( "" );
|
Log::Write( "" );
|
||||||
Log::Write( "Sending command (Callback ID=0x%.2x, Expected Reply=0x%.2x) - %s", msg->GetCallbackId(), msg->GetExpectedReply(), msg->GetAsString().c_str() );
|
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_controller->Write( msg->GetBuffer(), msg->GetLength() );
|
||||||
|
m_writeCnt++;
|
||||||
dataWritten = true;
|
dataWritten = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -945,14 +964,16 @@ bool Driver::IsControllerCommand
|
||||||
// ranges of commands are used to enhance performance
|
// ranges of commands are used to enhance performance
|
||||||
// the commands identified as "Controller Commands" needs to be reviewed as we
|
// the commands identified as "Controller Commands" needs to be reviewed as we
|
||||||
// understand the protocol better and implement handlers
|
// understand the protocol better and implement handlers
|
||||||
if( ( _command >= FUNC_ID_ZW_SET_DEFAULT ) &&
|
if( ( _command >= FUNC_ID_ZW_SET_DEFAULT ) && // 0x42
|
||||||
( _command <= FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE ) )
|
( _command <= FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE ) ) // 0x48
|
||||||
return true;
|
return true;
|
||||||
if( ( _command >= FUNC_ID_ZW_ADD_NODE_TO_NETWORK ) &&
|
if( ( _command >= FUNC_ID_ZW_ADD_NODE_TO_NETWORK ) && // 0x4a
|
||||||
( _command <= FUNC_ID_ZW_SET_LEARN_MODE ) )
|
( _command <= FUNC_ID_ZW_SET_LEARN_MODE ) ) // 0x50
|
||||||
return true;
|
return true;
|
||||||
if( ( _command >= FUNC_ID_ZW_REMOVE_FAILED_NODE_ID ) &&
|
if( ( _command >= FUNC_ID_ZW_REMOVE_FAILED_NODE_ID ) && // 0x61
|
||||||
( _command <= FUNC_ID_ZW_REPLACE_FAILED_NODE ) )
|
( _command <= FUNC_ID_ZW_REPLACE_FAILED_NODE ) ) // 0x63
|
||||||
|
return true;
|
||||||
|
if( _command == FUNC_ID_ZW_GET_ROUTING_INFO ) // 0x80
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -982,9 +1003,11 @@ bool Driver::ReadMsg
|
||||||
{
|
{
|
||||||
case SOF:
|
case SOF:
|
||||||
{
|
{
|
||||||
|
m_SOFCnt++;
|
||||||
if( m_waitingForAck )
|
if( m_waitingForAck )
|
||||||
{
|
{
|
||||||
Log::Write( "Unsolicited message received while waiting for ACK." );
|
Log::Write( "Unsolicited message received while waiting for ACK." );
|
||||||
|
m_ACKWaiting++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the length byte. Keep trying until we get it.
|
// Read the length byte. Keep trying until we get it.
|
||||||
|
@ -1005,6 +1028,7 @@ bool Driver::ReadMsg
|
||||||
if( loops == 10 )
|
if( loops == 10 )
|
||||||
{
|
{
|
||||||
Log::Write( "100ms passed without finding the length byte...aborting frame read");
|
Log::Write( "100ms passed without finding the length byte...aborting frame read");
|
||||||
|
m_readAborts++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1028,6 +1052,7 @@ bool Driver::ReadMsg
|
||||||
if( loops == 50 )
|
if( loops == 50 )
|
||||||
{
|
{
|
||||||
Log::Write( "500ms passed without reading the rest of the frame...aborting frame read" );
|
Log::Write( "500ms passed without reading the rest of the frame...aborting frame read" );
|
||||||
|
m_readAborts++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1061,12 +1086,14 @@ bool Driver::ReadMsg
|
||||||
uint8 ack = ACK;
|
uint8 ack = ACK;
|
||||||
m_controller->Write( &ack, 1 );
|
m_controller->Write( &ack, 1 );
|
||||||
|
|
||||||
|
m_readCnt++;
|
||||||
// Process the received message
|
// Process the received message
|
||||||
ProcessMsg( &buffer[2] );
|
ProcessMsg( &buffer[2] );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log::Write( "Checksum incorrect - sending NAK" );
|
Log::Write( "Checksum incorrect - sending NAK" );
|
||||||
|
m_badChecksum++;
|
||||||
uint8 nak = NAK;
|
uint8 nak = NAK;
|
||||||
m_controller->Write( &nak, 1 );
|
m_controller->Write( &nak, 1 );
|
||||||
}
|
}
|
||||||
|
@ -1076,6 +1103,7 @@ bool Driver::ReadMsg
|
||||||
case CAN:
|
case CAN:
|
||||||
{
|
{
|
||||||
Log::Write( "CAN received...triggering resend" );
|
Log::Write( "CAN received...triggering resend" );
|
||||||
|
m_CANCnt++;
|
||||||
TriggerResend();
|
TriggerResend();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1083,6 +1111,7 @@ bool Driver::ReadMsg
|
||||||
case NAK:
|
case NAK:
|
||||||
{
|
{
|
||||||
Log::Write( "NAK received...triggering resend" );
|
Log::Write( "NAK received...triggering resend" );
|
||||||
|
m_NAKCnt++;
|
||||||
TriggerResend();
|
TriggerResend();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1090,6 +1119,7 @@ bool Driver::ReadMsg
|
||||||
case ACK:
|
case ACK:
|
||||||
{
|
{
|
||||||
Log::Write( " ACK received CallbackId 0x%.2x Reply 0x%.2x", m_expectedCallbackId, m_expectedReply );
|
Log::Write( " ACK received CallbackId 0x%.2x Reply 0x%.2x", m_expectedCallbackId, m_expectedReply );
|
||||||
|
m_ACKCnt++;
|
||||||
m_waitingForAck = false;
|
m_waitingForAck = false;
|
||||||
|
|
||||||
if( ( 0 == m_expectedCallbackId ) && ( 0 == m_expectedReply ) )
|
if( ( 0 == m_expectedCallbackId ) && ( 0 == m_expectedReply ) )
|
||||||
|
@ -1103,6 +1133,7 @@ bool Driver::ReadMsg
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
Log::Write( "ERROR! Out of frame flow! (0x%.2x). Sending NAK.", buffer[0] );
|
Log::Write( "ERROR! Out of frame flow! (0x%.2x). Sending NAK.", buffer[0] );
|
||||||
|
m_OOFCnt++;
|
||||||
uint8 nak = NAK;
|
uint8 nak = NAK;
|
||||||
m_controller->Write( &nak, 1 );
|
m_controller->Write( &nak, 1 );
|
||||||
break;
|
break;
|
||||||
|
@ -1399,6 +1430,12 @@ void Driver::ProcessMsg
|
||||||
HandleReplaceFailedNodeRequest( _data );
|
HandleReplaceFailedNodeRequest( _data );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case FUNC_ID_PROMISCUOUS_APPLICATION_COMMAND_HANDLER:
|
||||||
|
{
|
||||||
|
Log::Write( "" );
|
||||||
|
HandlePromiscuousApplicationCommandHandlerRequest( _data );
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
@ -1990,6 +2027,7 @@ bool Driver::HandleSendDataRequest
|
||||||
{
|
{
|
||||||
node->m_queryStageCompleted = true;
|
node->m_queryStageCompleted = true;
|
||||||
}
|
}
|
||||||
|
m_dropped++;
|
||||||
RemoveMsg();
|
RemoveMsg();
|
||||||
messageRemoved = true;
|
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>
|
// <Driver::HandleAssignReturnRouteRequest>
|
||||||
// Process a request from the Z-Wave PC interface
|
// 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");
|
Log::Write("Received reply to FUNC_ID_MEMORY_GET_BYTE");
|
||||||
return res;
|
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 HandleReplaceFailedNodeRequest( uint8* _data );
|
||||||
void HandleRemoveNodeFromNetworkRequest( uint8* _data );
|
void HandleRemoveNodeFromNetworkRequest( uint8* _data );
|
||||||
void HandleApplicationCommandHandlerRequest( uint8* _data );
|
void HandleApplicationCommandHandlerRequest( uint8* _data );
|
||||||
|
void HandlePromiscuousApplicationCommandHandlerRequest( uint8* _data );
|
||||||
void HandleAssignReturnRouteRequest( uint8* _data );
|
void HandleAssignReturnRouteRequest( uint8* _data );
|
||||||
void HandleDeleteReturnRouteRequest( uint8* _data );
|
void HandleDeleteReturnRouteRequest( uint8* _data );
|
||||||
void HandleNodeNeighborUpdateRequest( 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.
|
void NotifyWatchers(); // Passes the notifications to all the registered watcher callbacks in turn.
|
||||||
|
|
||||||
list<Notification*> m_notifications;
|
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
|
} // namespace OpenZWave
|
||||||
|
|
||||||
#endif // _Driver_H
|
#endif // _Driver_H
|
||||||
|
|
||||||
|
|
|
@ -3329,3 +3329,20 @@ bool Manager::ActivateScene
|
||||||
return false;
|
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 );
|
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
|
} // namespace OpenZWave
|
||||||
|
|
||||||
#endif // _Manager_H
|
#endif // _Manager_H
|
||||||
|
|
|
@ -517,6 +517,11 @@ uint32 Node::GetNeighbors
|
||||||
// determine how many neighbors there are
|
// determine how many neighbors there are
|
||||||
int i;
|
int i;
|
||||||
uint32 numNeighbors = 0;
|
uint32 numNeighbors = 0;
|
||||||
|
if( m_queryStage < QueryStage_Session )
|
||||||
|
{
|
||||||
|
*o_neighbors = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
for( i = 0; i < 29; i++ )
|
for( i = 0; i < 29; i++ )
|
||||||
{
|
{
|
||||||
for( unsigned char mask = 0x80; mask != 0; mask >>= 1 )
|
for( unsigned char mask = 0x80; mask != 0; mask >>= 1 )
|
||||||
|
|
|
@ -166,48 +166,53 @@ bool SensorMultilevel::HandleMsg
|
||||||
if (SensorMultilevelCmd_Report == (SensorMultilevelCmd)_data[0])
|
if (SensorMultilevelCmd_Report == (SensorMultilevelCmd)_data[0])
|
||||||
{
|
{
|
||||||
uint8 scale;
|
uint8 scale;
|
||||||
|
uint8 sensorType = _data[1];
|
||||||
string valueStr = ExtractValue( &_data[2], &scale );
|
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]] );
|
ValueDecimal* value = static_cast<ValueDecimal*>( GetValue( _instance, sensorType ) );
|
||||||
switch( _data[1] )
|
if( value == NULL)
|
||||||
{
|
{
|
||||||
case SensorType_Temperature: value->SetUnits( scale ? "F" : "C" ); break;
|
char const* units = "";
|
||||||
case SensorType_General: value->SetUnits( scale ? "" : "%" ); break;
|
switch( sensorType )
|
||||||
case SensorType_Luminance: value->SetUnits( scale ? "lux" : "%" ); break;
|
{
|
||||||
case SensorType_Power: value->SetUnits( scale ? "BTU/h" : "W" ); break;
|
case SensorType_Temperature: units = scale ? "F" : "C"; break;
|
||||||
case SensorType_RelativeHumidity: value->SetUnits( "%" ); break;
|
case SensorType_General: units = scale ? "" : "%"; break;
|
||||||
case SensorType_Velocity: value->SetUnits( scale ? "mph" : "m/s" ); break;
|
case SensorType_Luminance: units = scale ? "lux" : "%"; break;
|
||||||
case SensorType_Direction: value->SetUnits( "" ); break;
|
case SensorType_Power: units = scale ? "BTU/h" : "W"; break;
|
||||||
case SensorType_AtmosphericPressure: value->SetUnits( scale ? "inHg" : "kPa" ); break;
|
case SensorType_RelativeHumidity: units = "%"; break;
|
||||||
case SensorType_BarometricPressure: value->SetUnits( scale ? "inHg" : "kPa" ); break;
|
case SensorType_Velocity: units = scale ? "mph" : "m/s"; break;
|
||||||
case SensorType_SolarRadiation: value->SetUnits( "W/m2" ); break;
|
case SensorType_Direction: units = ""; break;
|
||||||
case SensorType_DewPoint: value->SetUnits( scale ? "in/h" : "mm/h" ); break;
|
case SensorType_AtmosphericPressure: units = scale ? "inHg" : "kPa"; break;
|
||||||
case SensorType_RainRate: value->SetUnits( scale ? "F" : "C" ); break;
|
case SensorType_BarometricPressure: units = scale ? "inHg" : "kPa"; break;
|
||||||
case SensorType_TideLevel: value->SetUnits( scale ? "ft" : "m" ); break;
|
case SensorType_SolarRadiation: units = "W/m2"; break;
|
||||||
case SensorType_Weight: value->SetUnits( scale ? "lb" : "kg" ); break;
|
case SensorType_DewPoint: units = scale ? "in/h" : "mm/h"; break;
|
||||||
case SensorType_Voltage: value->SetUnits( scale ? "mV" : "V" ); break;
|
case SensorType_RainRate: units = scale ? "F" : "C"; break;
|
||||||
case SensorType_Current: value->SetUnits( scale ? "mA" : "A" ); break;
|
case SensorType_TideLevel: units = scale ? "ft" : "m"; break;
|
||||||
case SensorType_CO2: value->SetUnits( "ppm" ); break;
|
case SensorType_Weight: units = scale ? "lb" : "kg"; break;
|
||||||
case SensorType_AirFlow: value->SetUnits( scale ? "cfm" : "m3/h" ); break;
|
case SensorType_Voltage: units = scale ? "mV" : "V"; break;
|
||||||
case SensorType_TankCapacity: value->SetUnits( c_tankCapcityUnits[scale] ); break;
|
case SensorType_Current: units = scale ? "mA" : "A"; break;
|
||||||
case SensorType_Distance: value->SetUnits( c_distanceUnits[scale] ); break;
|
case SensorType_CO2: units = "ppm"; break;
|
||||||
default: 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() );
|
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 );
|
value->OnValueChanged( valueStr );
|
||||||
}
|
|
||||||
|
|
||||||
Node* node = GetNodeUnsafe();
|
if( node->m_queryPending )
|
||||||
if( node != NULL && node->m_queryPending )
|
{
|
||||||
{
|
node->m_queryStageCompleted = true;
|
||||||
node->m_queryStageCompleted = true;
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,10 +225,7 @@ void SensorMultilevel::CreateVars
|
||||||
uint8 const _instance
|
uint8 const _instance
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if( Node* node = GetNodeUnsafe() )
|
// Don't create anything here. We do it in the report.
|
||||||
{
|
|
||||||
node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Unknown", "", true, false, "0.0" );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -41,20 +41,20 @@ namespace OpenZWave
|
||||||
/**
|
/**
|
||||||
* ReadPacketSegment enum
|
* ReadPacketSegment enum
|
||||||
* Signals the IController::Read() which part of the rx packet is being retrieved by the caller.
|
* Signals the IController::Read() which part of the rx packet is being retrieved by the caller.
|
||||||
* This is used by controllers that must internally read the entire rx packet in one operation.
|
* This is used by controllers that must internally read the entire rx packet in one operation.
|
||||||
*/
|
*/
|
||||||
enum ReadPacketSegment
|
enum ReadPacketSegment
|
||||||
{
|
{
|
||||||
ReadPacketSegment_FrameType = 0,
|
ReadPacketSegment_FrameType = 0,
|
||||||
ReadPacketSegment_FrameLength,
|
ReadPacketSegment_FrameLength,
|
||||||
ReadPacketSegment_FrameData
|
ReadPacketSegment_FrameData
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor.
|
* Destructor.
|
||||||
* Destroys the controller object.
|
* Destroys the controller object.
|
||||||
*/
|
*/
|
||||||
virtual ~IController() {};
|
virtual ~IController() {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves an array of Msg object pointers in the correct order needed to initialize the IController implementation.
|
* Retrieves an array of Msg object pointers in the correct order needed to initialize the IController implementation.
|
||||||
|
|
|
@ -89,26 +89,26 @@ bool HidControllerImpl::Open
|
||||||
m_hHidController = hid_open( _vendorId, _productId, NULL );
|
m_hHidController = hid_open( _vendorId, _productId, NULL );
|
||||||
if ( !m_hHidController )
|
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
|
// Enumerate connected HIDs for debugging purposes
|
||||||
// Note: most OS intentionally hide keyboard/mouse devices from HID access
|
// Note: most OS intentionally hide keyboard/mouse devices from HID access
|
||||||
struct hid_device_info *devices, *currentDevice;
|
struct hid_device_info *devices, *currentDevice;
|
||||||
devices = hid_enumerate(0x0, 0x0);
|
devices = hid_enumerate( 0x0, 0x0 );
|
||||||
currentDevice = devices;
|
currentDevice = devices;
|
||||||
|
|
||||||
Log::Write( "Enumerating connected HIDs:\n" );
|
Log::Write( "Enumerating connected HIDs:" );
|
||||||
while (currentDevice)
|
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->vendor_id,
|
||||||
currentDevice->product_id,
|
currentDevice->product_id,
|
||||||
currentDevice->serial_number,
|
currentDevice->serial_number,
|
||||||
currentDevice->manufacturer_string,
|
currentDevice->manufacturer_string,
|
||||||
currentDevice->product_string,
|
currentDevice->product_string,
|
||||||
currentDevice->path);
|
currentDevice->path);
|
||||||
currentDevice = currentDevice->next;
|
currentDevice = currentDevice->next;
|
||||||
}
|
}
|
||||||
hid_free_enumeration( devices );
|
hid_free_enumeration( devices );
|
||||||
|
|
||||||
goto HidOpenFailure;
|
goto HidOpenFailure;
|
||||||
|
@ -222,7 +222,7 @@ uint32 HidControllerImpl::Read
|
||||||
if( !m_hidControllerOpen )
|
if( !m_hidControllerOpen )
|
||||||
{
|
{
|
||||||
//Error
|
//Error
|
||||||
Log::Write( "Error: HID port must be opened before reading\n" );
|
Log::Write( "Error: HID port must be opened before reading" );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,8 +275,7 @@ uint32 HidControllerImpl::Read
|
||||||
return _length;
|
return _length;
|
||||||
HidPortError:
|
HidPortError:
|
||||||
//Error
|
//Error
|
||||||
Log::Write( "Error: HID port returned error reading rest of packet: 0x%08hx, HIDAPI error string:", m_hidFeatureReportReadBufferBytes );
|
Log::Write( "Error: HID port returned error reading rest of packet: %d, HIDAPI error string: %ls", m_hidFeatureReportReadBufferBytes, hid_error(m_hHidController));
|
||||||
Log::Write("%ls\n", hid_error(m_hHidController));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,14 +292,14 @@ uint32 HidControllerImpl::Write
|
||||||
if( !m_hidControllerOpen )
|
if( !m_hidControllerOpen )
|
||||||
{
|
{
|
||||||
//Error
|
//Error
|
||||||
Log::Write( "Error: HID port must be opened before writing\n" );
|
Log::Write( "Error: HID port must be opened before writing" );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( FEATURE_REPORT_LENGTH - 2 < _length)
|
if ( FEATURE_REPORT_LENGTH - 2 < _length)
|
||||||
{
|
{
|
||||||
//Error
|
//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,
|
_length,
|
||||||
FEATURE_REPORT_LENGTH - 2 );
|
FEATURE_REPORT_LENGTH - 2 );
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -320,9 +319,7 @@ uint32 HidControllerImpl::Write
|
||||||
if (bytesSent < 2)
|
if (bytesSent < 2)
|
||||||
{
|
{
|
||||||
//Error
|
//Error
|
||||||
Log::Write( "Error: HID port returned error sending bytes: 0x%08hx, HIDAPI error string:", bytesSent );
|
Log::Write( "Error: HID port returned error sending bytes: %d, HIDAPI error string: %ls", bytesSent, hid_error( m_hHidController ) );
|
||||||
const wchar_t* errString = hid_error( m_hHidController );
|
|
||||||
Log::Write( "%ls\n", errString );
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,18 +370,13 @@ bool HidControllerImpl::Wait
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
//Error
|
//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;
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// continue looping until some rx feature report data is reported via input report
|
// 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;
|
return false;
|
||||||
|
@ -406,7 +398,7 @@ int HidControllerImpl::GetFeatureReport
|
||||||
result = hid_get_feature_report( m_hHidController, _buffer, _length );
|
result = hid_get_feature_report( m_hHidController, _buffer, _length );
|
||||||
if (result < 0)
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -426,7 +418,7 @@ int HidControllerImpl::SendFeatureReport
|
||||||
result = hid_send_feature_report( m_hHidController, _data, _length );
|
result = hid_send_feature_report( m_hHidController, _data, _length );
|
||||||
if (result < 0)
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue