aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Trulson <jtrulson@ics.com>2015-10-23 18:00:33 -0600
committerMihai Tudor Panu <mihai.tudor.panu@intel.com>2015-11-25 13:55:19 -0800
commitfd509c7d790991c6ce65c4613d3ab92de71e5113 (patch)
treee9560e18c5419d613f284eedcbcc2f2ae9cee49d
parent287250b32dc18c781e45c103b0b4e3e5917d6c2e (diff)
ozw: Initial implementation
This module was developed using the OpenZWave library (v1.3): http://www.openzwave.com/ It was developed using a collection of devices (switches and a multi-sensor) connected via an Aeon Z-Stick Gen5 USB dongle. It can be used to query (and, where appropriate, set) Values on Nodes connected to the ZWave network. Checks are made in src/ozw/CMakeLists.txt to ensure that the libopenzwave library is installed (via pkg-config). If not present, then neither the module, nor the example will be built. Signed-off-by: Jon Trulson <jtrulson@ics.com> Signed-off-by: Mihai Tudor Panu <mihai.tudor.panu@intel.com>
-rw-r--r--examples/c++/CMakeLists.txt11
-rw-r--r--examples/c++/ozw.cxx141
-rw-r--r--examples/javascript/ozw.js128
-rw-r--r--examples/python/ozw.py126
-rw-r--r--src/ozw/CMakeLists.txt21
-rw-r--r--src/ozw/javaupm_ozw.i12
-rw-r--r--src/ozw/jsupm_ozw.i12
-rw-r--r--src/ozw/ozw.cxx909
-rw-r--r--src/ozw/ozw.h574
-rw-r--r--src/ozw/pyupm_ozw.i15
-rw-r--r--src/ozw/zwNode.cxx168
-rw-r--r--src/ozw/zwNode.h105
12 files changed, 2222 insertions, 0 deletions
diff --git a/examples/c++/CMakeLists.txt b/examples/c++/CMakeLists.txt
index ce4265f..b004ff4 100644
--- a/examples/c++/CMakeLists.txt
+++ b/examples/c++/CMakeLists.txt
@@ -157,6 +157,10 @@ add_executable (mcp9808-example mcp9808.cxx)
add_executable (groveultrasonic-example groveultrasonic.cxx)
add_executable (sx1276-lora-example sx1276-lora.cxx)
add_executable (sx1276-fsk-example sx1276-fsk.cxx)
+# availability of libopenzwave is tested in src/ozw/CMakeLists.txt
+if (OPENZWAVE_FOUND)
+ add_executable (ozw-example ozw.cxx)
+endif ()
include_directories (${PROJECT_SOURCE_DIR}/src/hmc5883l)
include_directories (${PROJECT_SOURCE_DIR}/src/grove)
@@ -277,6 +281,10 @@ include_directories (${PROJECT_SOURCE_DIR}/src/dfrph)
include_directories (${PROJECT_SOURCE_DIR}/src/mcp9808)
include_directories (${PROJECT_SOURCE_DIR}/src/groveultrasonic)
include_directories (${PROJECT_SOURCE_DIR}/src/sx1276)
+if (OPENZWAVE_FOUND)
+ include_directories(${PROJECT_SOURCE_DIR}/src/ozw)
+ include_directories(${OPENZWAVE_INCLUDE_DIRS})
+endif ()
target_link_libraries (hmc5883l-example hmc5883l ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (groveled-example grove ${CMAKE_THREAD_LIBS_INIT})
@@ -435,3 +443,6 @@ target_link_libraries (mcp9808-example mcp9808 ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (groveultrasonic-example groveultrasonic ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (sx1276-lora-example sx1276 ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (sx1276-fsk-example sx1276 ${CMAKE_THREAD_LIBS_INIT})
+if (OPENZWAVE_FOUND)
+ target_link_libraries (ozw-example ozw ${CMAKE_THREAD_LIBS_INIT})
+endif ()
diff --git a/examples/c++/ozw.cxx b/examples/c++/ozw.cxx
new file mode 100644
index 0000000..40c30f4
--- /dev/null
+++ b/examples/c++/ozw.cxx
@@ -0,0 +1,141 @@
+/*
+ * Author: Jon Trulson <jtrulson@ics.com>
+ * Copyright (c) 2015 Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <unistd.h>
+#include <iostream>
+
+#include "ozw.h"
+
+using namespace std;
+
+int main(int argc, char **argv)
+{
+//! [Interesting]
+
+ string defaultDev = "/dev/ttyACM0";
+
+ // if an argument was specified, use it as the device instead
+ if (argc > 1)
+ defaultDev = string(argv[1]);
+
+ // Instantiate an OZW instance
+ upm::OZW *sensor = new upm::OZW();
+
+ // The first thing to do is create options, then lock them when done.
+ sensor->optionsCreate();
+ sensor->optionsLock();
+
+ // Next, initialize it.
+ cout << "Initializing, this may take awhile depending on your ZWave network"
+ << endl;
+
+ if (!sensor->init(defaultDev))
+ {
+ cerr << "Init failed." << endl;
+ return 0;
+ }
+ cout << "Initialization complete" << endl;
+
+ cout << "Dumping nodes..." << endl;
+
+ sensor->dumpNodes();
+
+ // The following is example output of dumpNodes:
+ //
+ // Dumping nodes...
+ // Node 1: Z-Stick Gen5
+ // Node 2: Smart Switch 6
+ // Index: 0, Type: bool, Label: Switch, Value: False
+ // Index: 2, Type: float, Label: Energy, Value: 1.190 kWh
+ // Index: 3, Type: float, Label: Previous Reading, Value: 1.190 kWh
+ // Index: 4, Type: int32, Label: Interval, Value: 1521 seconds
+ // Index: 5, Type: float, Label: Power, Value: 0.000 W
+ // Index: 6, Type: float, Label: Voltage, Value: 121.256 V
+ // Index: 7, Type: float, Label: Current, Value: 0.000 A
+ // Index: 8, Type: bool, Label: Exporting, Value: False
+ // Index: 45, Type: list, Label: Day, Value: Friday
+ // Index: 46, Type: byte, Label: Hour, Value: 5
+ // Index: 47, Type: byte, Label: Minute, Value: 53
+ // Node 3: Multi Sensor
+ // Index: 0, Type: bool, Label: Sensor, Value: True
+ // Index: 1, Type: float, Label: Temperature, Value: 72.8 F
+ // Index: 2, Type: float, Label: Luminance, Value: 4 lux
+ // Index: 3, Type: float, Label: Relative Humidity, Value: 22 %
+ // Index: 17, Type: byte, Label: Battery Level, Value: 98 %
+ // Node 5: Minimote
+ // Node 6: Smart Energy Switch
+ // Index: 0, Type: bool, Label: Switch, Value: False
+ // Index: 2, Type: float, Label: Power, Value: 0.000 W
+ // Index: 3, Type: float, Label: Energy, Value: 1.609 kWh
+ // Index: 4, Type: float, Label: Previous Reading, Value: 1.609 kWh
+ // Index: 5, Type: int32, Label: Interval, Value: 1521 seconds
+ // Index: 6, Type: float, Label: Power, Value: 0.000 W
+ // Index: 7, Type: float, Label: Previous Reading, Value: 1.609 W
+ // Index: 8, Type: int32, Label: Interval, Value: 1521 seconds
+ // Index: 9, Type: bool, Label: Exporting, Value: False
+ // Node 7: Smart Energy Switch
+ // Index: 0, Type: bool, Label: Switch, Value: False
+ // Index: 2, Type: float, Label: Power, Value: 0.000 W
+ // Index: 3, Type: float, Label: Energy, Value: 0.000 kWh
+ // Index: 4, Type: float, Label: Previous Reading, Value: 0.000 kWh
+ // Index: 5, Type: int32, Label: Interval, Value: 1521 seconds
+ // Index: 6, Type: float, Label: Power, Value: 0.000 W
+ // Index: 7, Type: float, Label: Previous Reading, Value: 0.000 W
+ // Index: 8, Type: int32, Label: Interval, Value: 1521 seconds
+ // Index: 9, Type: bool, Label: Exporting, Value: False
+ //
+ // So, with the above in mind:
+ //
+ // 1. Query the temperature on node 3 and print it out (as a
+ // string), along with the units of measure:
+ //
+ // cout << "Temperature: " << sensor->getValueAsString(3, 1)
+ // << " " << sensor->getValueUnits(3, 1) << endl;
+ //
+ // 2. query the same temperature as a float:
+ //
+ // float temperature = sensor->getValueAsFloat(3, 1);
+ //
+ // 3. Turn on the light plugged into the switch on Node 7, wait 5
+ // seconds, then turn it back off again:
+ //
+ // cout << "Turning ON node 7" << endl;
+ // sensor->setValueAsBool(7, 0, true);
+ //
+ // cout << "Sleeping for 5 seconds" << endl;
+ // sleep(5);
+ //
+ // cout << "Turning OFF node 7" << endl;
+ // sensor->setValueAsBool(7, 0, false);
+
+
+//! [Interesting]
+
+
+ cout << "Exiting..." << endl;
+
+ delete sensor;
+
+ return 0;
+}
diff --git a/examples/javascript/ozw.js b/examples/javascript/ozw.js
new file mode 100644
index 0000000..5c5c7d5
--- /dev/null
+++ b/examples/javascript/ozw.js
@@ -0,0 +1,128 @@
+/*jslint node:true, vars:true, bitwise:true, unparam:true */
+/*jshint unused:true */
+
+/*
+ * Author: Jon Trulson <jtrulson@ics.com>
+ * Copyright (c) 2015 Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+var sensorObj = require('jsupm_ozw');
+
+
+/************** Main code **************/
+// Instantiate an OZW instance
+var sensor = new sensorObj.OZW();
+
+var defaultDev = "/dev/ttyACM0";
+
+// if an argument was specified, use it as the device instead
+if (process.argv.length > 2)
+{
+ defaultDev = process.argv[2];
+}
+
+// The first thing to do is create options, then lock them when done.
+sensor.optionsCreate();
+sensor.optionsLock();
+
+// Next, initialize it.
+console.log("Initializing, this may take awhile depending on your ZWave network");
+
+if (!sensor.init(defaultDev))
+{
+ console.log("Init failed.");
+ process.exit(0);
+}
+console.log("Initialization complete");
+
+console.log("Dumping nodes...");
+
+sensor.dumpNodes();
+
+// The following is example output of dumpNodes:
+//
+// Dumping nodes...
+// Node 1: Z-Stick Gen5
+// Node 2: Smart Switch 6
+// Index: 0, Type: bool, Label: Switch, Value: False
+// Index: 2, Type: float, Label: Energy, Value: 1.190 kWh
+// Index: 3, Type: float, Label: Previous Reading, Value: 1.190 kWh
+// Index: 4, Type: int32, Label: Interval, Value: 1521 seconds
+// Index: 5, Type: float, Label: Power, Value: 0.000 W
+// Index: 6, Type: float, Label: Voltage, Value: 121.256 V
+// Index: 7, Type: float, Label: Current, Value: 0.000 A
+// Index: 8, Type: bool, Label: Exporting, Value: False
+// Index: 45, Type: list, Label: Day, Value: Friday
+// Index: 46, Type: byte, Label: Hour, Value: 5
+// Index: 47, Type: byte, Label: Minute, Value: 53
+// Node 3: Multi Sensor
+// Index: 0, Type: bool, Label: Sensor, Value: True
+// Index: 1, Type: float, Label: Temperature, Value: 72.8 F
+// Index: 2, Type: float, Label: Luminance, Value: 4 lux
+// Index: 3, Type: float, Label: Relative Humidity, Value: 22 %
+// Index: 17, Type: byte, Label: Battery Level, Value: 98 %
+// Node 5: Minimote
+// Node 6: Smart Energy Switch
+// Index: 0, Type: bool, Label: Switch, Value: False
+// Index: 2, Type: float, Label: Power, Value: 0.000 W
+// Index: 3, Type: float, Label: Energy, Value: 1.609 kWh
+// Index: 4, Type: float, Label: Previous Reading, Value: 1.609 kWh
+// Index: 5, Type: int32, Label: Interval, Value: 1521 seconds
+// Index: 6, Type: float, Label: Power, Value: 0.000 W
+// Index: 7, Type: float, Label: Previous Reading, Value: 1.609 W
+// Index: 8, Type: int32, Label: Interval, Value: 1521 seconds
+// Index: 9, Type: bool, Label: Exporting, Value: False
+// Node 7: Smart Energy Switch
+// Index: 0, Type: bool, Label: Switch, Value: False
+// Index: 2, Type: float, Label: Power, Value: 0.000 W
+// Index: 3, Type: float, Label: Energy, Value: 0.000 kWh
+// Index: 4, Type: float, Label: Previous Reading, Value: 0.000 kWh
+// Index: 5, Type: int32, Label: Interval, Value: 1521 seconds
+// Index: 6, Type: float, Label: Power, Value: 0.000 W
+// Index: 7, Type: float, Label: Previous Reading, Value: 0.000 W
+// Index: 8, Type: int32, Label: Interval, Value: 1521 seconds
+// Index: 9, Type: bool, Label: Exporting, Value: False
+//
+// So, with the above in mind:
+//
+// 1. Query the temperature on node 3 and print it out (as a
+// string), along with the units of measure:
+//
+// console.log("Temperature: " + sensor.getValueAsString(3, 1) +
+// " " + sensor.getValueUnits(3, 1));
+//
+// 2. query the same temperature as a float:
+//
+// var temperature = sensor.getValueAsFloat(3, 1);
+//
+// 3. Turn on the light plugged into the switch on Node 7
+//
+// console.log("Turning ON node 7");
+// sensor.setValueAsBool(7, 0, true);
+//
+
+sensor = null;
+sensorObj.cleanUp();
+sensorObj = null;
+console.log("Exiting...");
+process.exit(0);
diff --git a/examples/python/ozw.py b/examples/python/ozw.py
new file mode 100644
index 0000000..010c1fc
--- /dev/null
+++ b/examples/python/ozw.py
@@ -0,0 +1,126 @@
+#!/usr/bin/python
+# Author: Jon Trulson <jtrulson@ics.com>
+# Copyright (c) 2015 Intel Corporation.
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+import time, sys, signal, atexit
+import pyupm_ozw as sensorObj
+
+# Instantiate an OZW instance
+sensor = sensorObj.OZW()
+
+# This function lets you run code on exit
+def exitHandler():
+ print "Exiting"
+ sys.exit(0)
+
+# Register exit handlers
+atexit.register(exitHandler)
+
+defaultDev = "/dev/ttyACM0"
+if (len(sys.argv) > 1):
+ defaultDev = sys.argv[1]
+
+# The first thing to do is create options, then lock them when done.
+sensor.optionsCreate()
+sensor.optionsLock()
+
+# Next, initialize it.
+print "Initializing, this may take awhile depending on your ZWave network"
+
+if (not sensor.init(defaultDev)):
+ print "Init failed."
+ sys.exit(1)
+
+print "Initialization complete"
+
+print "Dumping nodes..."
+
+sensor.dumpNodes()
+
+# The following is example output of dumpNodes:
+#
+# Dumping nodes...
+# Node 1: Z-Stick Gen5
+# Node 2: Smart Switch 6
+# Index: 0, Type: bool, Label: Switch, Value: False
+# Index: 2, Type: float, Label: Energy, Value: 1.190 kWh
+# Index: 3, Type: float, Label: Previous Reading, Value: 1.190 kWh
+# Index: 4, Type: int32, Label: Interval, Value: 1521 seconds
+# Index: 5, Type: float, Label: Power, Value: 0.000 W
+# Index: 6, Type: float, Label: Voltage, Value: 121.256 V
+# Index: 7, Type: float, Label: Current, Value: 0.000 A
+# Index: 8, Type: bool, Label: Exporting, Value: False
+# Index: 45, Type: list, Label: Day, Value: Friday
+# Index: 46, Type: byte, Label: Hour, Value: 5
+# Index: 47, Type: byte, Label: Minute, Value: 53
+# Node 3: Multi Sensor
+# Index: 0, Type: bool, Label: Sensor, Value: True
+# Index: 1, Type: float, Label: Temperature, Value: 72.8 F
+# Index: 2, Type: float, Label: Luminance, Value: 4 lux
+# Index: 3, Type: float, Label: Relative Humidity, Value: 22 %
+# Index: 17, Type: byte, Label: Battery Level, Value: 98 %
+# Node 5: Minimote
+# Node 6: Smart Energy Switch
+# Index: 0, Type: bool, Label: Switch, Value: False
+# Index: 2, Type: float, Label: Power, Value: 0.000 W
+# Index: 3, Type: float, Label: Energy, Value: 1.609 kWh
+# Index: 4, Type: float, Label: Previous Reading, Value: 1.609 kWh
+# Index: 5, Type: int32, Label: Interval, Value: 1521 seconds
+# Index: 6, Type: float, Label: Power, Value: 0.000 W
+# Index: 7, Type: float, Label: Previous Reading, Value: 1.609 W
+# Index: 8, Type: int32, Label: Interval, Value: 1521 seconds
+# Index: 9, Type: bool, Label: Exporting, Value: False
+# Node 7: Smart Energy Switch
+# Index: 0, Type: bool, Label: Switch, Value: False
+# Index: 2, Type: float, Label: Power, Value: 0.000 W
+# Index: 3, Type: float, Label: Energy, Value: 0.000 kWh
+# Index: 4, Type: float, Label: Previous Reading, Value: 0.000 kWh
+# Index: 5, Type: int32, Label: Interval, Value: 1521 seconds
+# Index: 6, Type: float, Label: Power, Value: 0.000 W
+# Index: 7, Type: float, Label: Previous Reading, Value: 0.000 W
+# Index: 8, Type: int32, Label: Interval, Value: 1521 seconds
+# Index: 9, Type: bool, Label: Exporting, Value: False
+#
+# So, with the above in mind:
+#
+# 1. Query the temperature on node 3 and print it out (as a
+# string), along with the units of measure:
+#
+# print "Temperature:", sensor.getValueAsString(3, 1),
+# sensor->getValueUnits(3, 1)
+#
+# 2. query the same temperature as a float:
+#
+# temperature = sensor.getValueAsFloat(3, 1)
+#
+# 3. Turn on the light plugged into the switch on Node 7, wait 5
+# seconds, then turn it back off again:
+#
+# print "Turning ON node 7"
+# sensor.setValueAsBool(7, 0, true)
+#
+# print "Sleeping for 5 seconds";
+# time.sleep(5)
+#
+# print "Turning OFF node 7"
+# sensor.setValueAsBool(7, 0, false);
+
diff --git a/src/ozw/CMakeLists.txt b/src/ozw/CMakeLists.txt
new file mode 100644
index 0000000..6c67157
--- /dev/null
+++ b/src/ozw/CMakeLists.txt
@@ -0,0 +1,21 @@
+set (libname "ozw")
+set (libdescription "upm module for the OpenZWave library interface")
+set (module_src ${libname}.cxx zwNode.cxx)
+set (module_h ${libname}.h)
+
+pkg_search_module(OPENZWAVE libopenzwave)
+if (OPENZWAVE_FOUND)
+ set (reqlibname "libopenzwave")
+ include_directories(${OPENZWAVE_INCLUDE_DIRS})
+ upm_module_init()
+ add_dependencies(${libname} ${OPENZWAVE_LIBRARIES})
+ target_link_libraries(${libname} ${OPENZWAVE_LIBRARIES})
+ if (BUILDSWIG)
+ if (BUILDSWIGNODE)
+ swig_link_libraries (jsupm_${libname} ${OPENZWAVE_LIBRARIES} ${MRAA_LIBRARIES} ${NODE_LIBRARIES})
+ endif()
+ if (BUILDSWIGPYTHON)
+ swig_link_libraries (pyupm_${libname} ${OPENZWAVE_LIBRARIES} ${PYTHON_LIBRARIES} ${MRAA_LIBRARIES})
+ endif()
+ endif()
+endif ()
diff --git a/src/ozw/javaupm_ozw.i b/src/ozw/javaupm_ozw.i
new file mode 100644
index 0000000..dcb7f3a
--- /dev/null
+++ b/src/ozw/javaupm_ozw.i
@@ -0,0 +1,12 @@
+%module javaupm_ozw
+%include "../upm.i"
+%include "cpointer.i"
+%include "typemaps.i"
+%include "arrays_java.i";
+%include "../java_buffer.i"
+
+%{
+ #include "ozw.h"
+%}
+
+%include "ozw.h"
diff --git a/src/ozw/jsupm_ozw.i b/src/ozw/jsupm_ozw.i
new file mode 100644
index 0000000..209fe62
--- /dev/null
+++ b/src/ozw/jsupm_ozw.i
@@ -0,0 +1,12 @@
+%module jsupm_ozw
+%include "../upm.i"
+%include "cpointer.i"
+%include "stdint.i"
+
+%pointer_functions(float, floatp);
+
+%include "ozw.h"
+%{
+ #include "ozw.h"
+%}
+
diff --git a/src/ozw/ozw.cxx b/src/ozw/ozw.cxx
new file mode 100644
index 0000000..4f8df34
--- /dev/null
+++ b/src/ozw/ozw.cxx
@@ -0,0 +1,909 @@
+/*
+ * Author: Jon Trulson <jtrulson@ics.com>
+ * Copyright (c) 2015 Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <unistd.h>
+#include <iostream>
+#include <stdexcept>
+#include <string>
+#include <pthread.h>
+
+#include "platform/Log.h"
+
+#include "zwNode.h"
+
+#include "ozw.h"
+
+using namespace upm;
+using namespace std;
+using namespace OpenZWave;
+
+
+OZW::OZW()
+{
+ m_mgrCreated = false;
+ m_driverFailed = false;
+ m_homeId = 0;
+
+ pthread_mutexattr_t mutexAttrib;
+ pthread_mutexattr_init(&mutexAttrib);
+ pthread_mutexattr_settype(&mutexAttrib, PTHREAD_MUTEX_RECURSIVE);
+
+ if (pthread_mutex_init(&m_nodeLock, &mutexAttrib))
+ {
+ throw std::runtime_error(std::string(__FUNCTION__) +
+ ": pthread_mutex_init(nodeLock) failed");
+ }
+
+ pthread_mutexattr_destroy(&mutexAttrib);
+
+ if (pthread_mutex_init(&m_initLock, NULL))
+ {
+ throw std::runtime_error(std::string(__FUNCTION__) +
+ ": pthread_mutex_init(initLock) failed");
+ }
+
+ // initialize our init conditional
+ if (pthread_cond_init(&m_initCond, NULL))
+ {
+ throw std::runtime_error(std::string(__FUNCTION__) +
+ ": pthread_cond_init() failed");
+ }
+
+ setDebug(false);
+}
+
+OZW::~OZW()
+{
+ if (m_mgrCreated)
+ {
+ // remove the driver
+ if (m_driverIsHID)
+ Manager::Get()->RemoveDriver("HID");
+ else
+ Manager::Get()->RemoveDriver(m_devicePath);
+
+ // remove the notification handler
+ Manager::Get()->RemoveWatcher(notificationHandler, this);
+
+ // now destroy Manager and Options. Options must be destroyed
+ // after the Manager is destroyed.
+ Manager::Destroy();
+ Options::Destroy();
+ }
+
+ pthread_mutex_destroy(&m_nodeLock);
+ pthread_mutex_destroy(&m_initLock);
+ pthread_cond_destroy(&m_initCond);
+
+ // delete any nodes. This should be safe after deleting the node
+ // mutex since the handler is no longer registered.
+ for (zwNodeMap_t::iterator it = m_zwNodeMap.begin();
+ it != m_zwNodeMap.end(); ++it)
+ {
+ // delete the zwNode pointer
+ delete (*it).second;
+ }
+ // empty the map
+ m_zwNodeMap.clear();
+}
+
+void OZW::optionsCreate(std::string configPath,
+ std::string userConfigDir,
+ std::string cmdLine)
+{
+ Options::Create(configPath, userConfigDir, cmdLine);
+}
+
+void OZW::optionAddInt(std::string name, int val)
+{
+ Options::Get()->AddOptionInt(name, val);
+}
+
+void OZW::optionAddBool(std::string name, bool val)
+{
+ Options::Get()->AddOptionBool(name, val);
+}
+
+void OZW::optionAddString(std::string name, std::string val, bool append)
+{
+ Options::Get()->AddOptionString(name, val, append);
+}
+
+void OZW::optionsLock()
+{
+ // lock the options if not already locked
+ if (!Options::Get()->AreLocked())
+ Options::Get()->Lock();
+}
+
+bool OZW::init(string devicePath, bool isHID)
+{
+ // make sure options are locked
+ optionsLock();
+
+ pthread_mutex_lock(&m_initLock);
+
+ // the fun begins
+ Manager::Create();
+
+ // add our event handler
+ Manager::Get()->AddWatcher(notificationHandler, this);
+
+ // now add the driver
+ m_devicePath = devicePath;
+ if (isHID)
+ {
+ m_driverIsHID = true;
+ Manager::Get()->AddDriver("HID",
+ Driver::ControllerInterface_Hid);
+ }
+ else
+ Manager::Get()->AddDriver(devicePath);
+
+ m_mgrCreated = true;
+
+ // now we block here waiting for the driver to get far enough along
+ // (or fail) to proceed further
+ pthread_cond_wait(&m_initCond, &m_initLock);
+
+ if (m_driverFailed)
+ {
+ throw std::runtime_error(std::string(__FUNCTION__) +
+ ": driver initialization failed");
+ return false;
+ }
+
+ return true;
+}
+
+void OZW::notificationHandler(Notification const* notification, void *ctx)
+{
+ upm::OZW *This = (upm::OZW *)ctx;
+
+ This->lockNodes();
+
+ if (This->m_debugging)
+ fprintf(stderr, "### %s: homeId %08x, nodeId %d, type %x\n",
+ __FUNCTION__,
+ notification->GetHomeId(),
+ notification->GetNodeId(),
+ notification->GetType());
+
+ const uint32_t homeId = notification->GetHomeId();
+ const uint8_t nodeId = notification->GetNodeId();
+
+ switch (notification->GetType())
+ {
+
+ case Notification::Type_NodeAdded:
+ case Notification::Type_NodeNew:
+ {
+ if (This->m_debugging)
+ cerr << "### ### ADDING NODE: " << int(nodeId) << endl;
+ zwNode *node = new zwNode(homeId, nodeId);
+ This->m_zwNodeMap.insert(std::pair<uint8_t, zwNode *>(nodeId, node));
+
+ break;
+ }
+
+ case Notification::Type_NodeRemoved:
+ {
+ if (This->m_debugging)
+ cerr << "### ### REMOVING NODE: " << int(nodeId) << endl;
+ if (This->m_zwNodeMap.count(nodeId) != 0)
+ {
+ delete This->m_zwNodeMap[nodeId];
+ This->m_zwNodeMap.erase(nodeId);
+ }
+
+ break;
+ }
+
+ case Notification::Type_ValueAdded:
+ {
+ if (This->m_debugging)
+ cerr << "### ### VALUE ADDED " << endl;
+ This->m_zwNodeMap[nodeId]->addValueID(notification->GetValueID());
+
+ break;
+ }
+
+ case Notification::Type_ValueRemoved:
+ {
+ if (This->m_debugging)
+ cerr << "### ### VALUE DELETED " << endl;
+ This->m_zwNodeMap[nodeId]->removeValueID(notification->GetValueID());
+
+ break;
+ }
+
+ case Notification::Type_ValueChanged:
+ {
+ // might be able to do something with this someday...
+ break;
+ }
+
+ case Notification::Type_DriverReset:
+ {
+ // all nodes deleted. According to OZW docs, this happens
+ // when a driver is reset, instead of sending potentially
+ // hundreds of ValueRemoved/NodeRemoved events.
+ for (zwNodeMap_t::iterator it = This->m_zwNodeMap.begin();
+ it != This->m_zwNodeMap.end(); ++it)
+ {
+ // delete the zwNode pointer
+ delete (*it).second;
+ }
+ // empty the map
+ This->m_zwNodeMap.clear();
+
+ break;
+ }
+
+ case Notification::Type_DriverReady:
+ {
+ if (This->m_debugging)
+ fprintf(stderr, "### DriverReady, homeID = %08x\n", This->m_homeId);
+ This->m_homeId = notification->GetHomeId();
+ break;
+ }
+
+ case Notification::Type_DriverFailed:
+ {
+ if (This->m_debugging)
+ cerr << "### Driver FAILED" << endl;
+ This->m_driverFailed = true;
+ // wake up init()
+ pthread_cond_broadcast(&(This->m_initCond));
+ break;
+ }
+
+ case Notification::Type_AwakeNodesQueried:
+ case Notification::Type_AllNodesQueried:
+ case Notification::Type_AllNodesQueriedSomeDead:
+ {
+ if (This->m_debugging)
+ cerr << "### Awake/All/SomeDead complete" << endl;
+ // wake up init()
+ pthread_cond_broadcast(&(This->m_initCond));
+ break;
+ }
+
+ // might be able to do something with these someday too
+ case Notification::Type_Notification:
+ case Notification::Type_NodeNaming:
+ case Notification::Type_NodeProtocolInfo:
+ case Notification::Type_NodeQueriesComplete:
+ case Notification::Type_PollingEnabled:
+ case Notification::Type_PollingDisabled:
+ case Notification::Type_NodeEvent:
+ case Notification::Type_Group:
+ default:
+ {
+ break;
+ }
+ }
+
+ This->unlockNodes();
+}
+
+void OZW::dumpNodes(bool all)
+{
+ // iterate through all the nodes and dump various info on them
+
+ lockNodes();
+
+ for (zwNodeMap_t::iterator it = m_zwNodeMap.begin();
+ it != m_zwNodeMap.end(); ++it)
+ {
+ uint8_t nodeId = (*it).first;
+
+ cerr << "Node " << int(nodeId)
+ << ": "
+ << Manager::Get()->GetNodeProductName(m_homeId, nodeId)
+ << endl;
+ (*it).second->dumpNode(all);
+ }
+
+ unlockNodes();
+}
+
+bool OZW::getValueID(int nodeId, int index, ValueID *vid)
+{
+ // nodeId's are uint8_t's in OpenZWave, but we want to use int's to
+ // avoid hassles when dealing with SWIG, so here we just throw away
+ // everything except the first byte.
+ nodeId &= 0xff;
+
+ lockNodes();
+
+ zwNodeMap_t::iterator it;
+
+ it = m_zwNodeMap.find(nodeId);
+
+ if (it == m_zwNodeMap.end())
+ {
+ cerr << __FUNCTION__ << ": Node " << nodeId
+ << " does not exist" << endl;
+ unlockNodes();
+ return false;
+ }
+
+ // now get the ValueID
+ if (!(*it).second->indexToValueID(index, vid))
+ {
+ cerr << __FUNCTION__ << ": Index " << index
+ << " for node " << nodeId
+ << " does not exist" << endl;
+ unlockNodes();
+ return false;
+ }
+
+ unlockNodes();
+ return true;
+}
+
+string OZW::getValueAsString(int nodeId, int index)
+{
+ // we have to play this game since there is no default ctor for ValueID
+ ValueID vid(m_homeId, (uint64)0);
+
+ string rv;
+
+ lockNodes();
+
+ if (getValueID(nodeId, index, &vid))
+ Manager::Get()->GetValueAsString(vid, &rv);
+
+ unlockNodes();
+
+ return rv;
+}
+
+string OZW::getValueUnits(int nodeId, int index)
+{
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ string rv;
+ if (getValueID(nodeId, index, &vid))
+ rv = Manager::Get()->GetValueUnits(vid);
+
+ unlockNodes();
+
+ return rv;
+}
+
+void OZW::setValueUnits(int nodeId, int index, string text)
+{
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ if (getValueID(nodeId, index, &vid))
+ Manager::Get()->SetValueUnits(vid, text);
+
+ unlockNodes();
+}
+
+string OZW::getValueLabel(int nodeId, int index)
+{
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ string rv;
+ if (getValueID(nodeId, index, &vid))
+ rv = Manager::Get()->GetValueLabel(vid);
+
+ unlockNodes();
+
+ return rv;
+}
+
+void OZW::setValueLabel(int nodeId, int index, string text)
+{
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ if (getValueID(nodeId, index, &vid))
+ Manager::Get()->SetValueLabel(vid, text);
+
+ unlockNodes();
+}
+
+string OZW::getValueHelp(int nodeId, int index)
+{
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ string rv;
+ if (getValueID(nodeId, index, &vid))
+ rv = Manager::Get()->GetValueHelp(vid);
+
+ unlockNodes();
+
+ return rv;
+}
+
+void OZW::setValueHelp(int nodeId, int index, string text)
+{
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ if (getValueID(nodeId, index, &vid))
+ Manager::Get()->SetValueHelp(vid, text);
+
+ unlockNodes();
+}
+
+void OZW::setValueAsBool(int nodeId, int index, bool val)
+{
+ if (isValueReadOnly(nodeId, index))
+ {
+ cerr << __FUNCTION__ << ": Node " << nodeId << " index " << index
+ << " is ReadOnly" << endl;
+ return;
+ }
+
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ if (getValueID(nodeId, index, &vid))
+ {
+ if (!Manager::Get()->SetValue(vid, val))
+ {
+ cerr << __FUNCTION__ << ": Value is not a bool type" << endl;
+ }
+ }
+
+ unlockNodes();
+}
+
+void OZW::setValueAsByte(int nodeId, int index, uint8_t val)
+{
+ if (isValueReadOnly(nodeId, index))
+ {
+ cerr << __FUNCTION__ << ": Node " << nodeId << " index " << index
+ << " is ReadOnly" << endl;
+ return;
+ }
+
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ if (getValueID(nodeId, index, &vid))
+ {
+ if (!Manager::Get()->SetValue(vid, val))
+ {
+ cerr << __FUNCTION__ << ": Value is not a byte type" << endl;
+ }
+ }
+
+ unlockNodes();
+}
+
+void OZW::setValueAsFloat(int nodeId, int index, float val)
+{
+ if (isValueReadOnly(nodeId, index))
+ {
+ cerr << __FUNCTION__ << ": Node " << nodeId << " index " << index
+ << " is ReadOnly" << endl;
+ return;
+ }
+
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ if (getValueID(nodeId, index, &vid))
+ {
+ if (!Manager::Get()->SetValue(vid, val))
+ {
+ cerr << __FUNCTION__ << ": Value is not a float type" << endl;
+ }
+ }
+
+ unlockNodes();
+}
+
+void OZW::setValueAsInt32(int nodeId, int index, int32_t val)
+{
+ if (isValueReadOnly(nodeId, index))
+ {
+ cerr << __FUNCTION__ << ": Node " << nodeId << " index " << index
+ << " is ReadOnly" << endl;
+ return;
+ }
+
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ if (getValueID(nodeId, index, &vid))
+ {
+ if (!Manager::Get()->SetValue(vid, val))
+ {
+ cerr << __FUNCTION__ << ": Value is not a int32 type" << endl;
+ }
+ }
+
+ unlockNodes();
+}
+
+void OZW::setValueAsInt16(int nodeId, int index, int16_t val)
+{
+ if (isValueReadOnly(nodeId, index))
+ {
+ cerr << __FUNCTION__ << ": Node " << nodeId << " index " << index
+ << " is ReadOnly" << endl;
+ return;
+ }
+
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ if (getValueID(nodeId, index, &vid))
+ {
+ if (!Manager::Get()->SetValue(vid, val))
+ {
+ cerr << __FUNCTION__ << ": Value is not a int16 type" << endl;
+ }
+ }
+
+ unlockNodes();
+}
+
+void OZW::setValueAsBytes(int nodeId, int index, uint8_t *val, uint8_t len)
+{
+ if (isValueReadOnly(nodeId, index))
+ {
+ cerr << __FUNCTION__ << ": Node " << nodeId << " index " << index
+ << " is ReadOnly" << endl;
+ return;
+ }
+
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ if (getValueID(nodeId, index, &vid))
+ {
+ if (!Manager::Get()->SetValue(vid, val, len))
+ {
+ cerr << __FUNCTION__ << ": Value is not a bytes type" << endl;
+ }
+ }
+
+ unlockNodes();
+}
+
+void OZW::setValueAsString(int nodeId, int index, string val)
+{
+ if (isValueReadOnly(nodeId, index))
+ {
+ cerr << __FUNCTION__ << ": Node " << nodeId << " index " << index
+ << " is ReadOnly" << endl;
+ return;
+ }
+
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ if (getValueID(nodeId, index, &vid))
+ {
+ if (!Manager::Get()->SetValue(vid, val))
+ {
+ // this should always succeed, but for consistancy...
+ cerr << __FUNCTION__ << ": Value is not a string type" << endl;
+ }
+ }
+
+ unlockNodes();
+}
+
+void OZW::refreshValue(int nodeId, int index)
+{
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ if (getValueID(nodeId, index, &vid))
+ Manager::Get()->RefreshValue(vid);
+
+ unlockNodes();
+}
+
+int OZW::getValueMin(int nodeId, int index)
+{
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ int rv = 0;
+ if (getValueID(nodeId, index, &vid))
+ rv = Manager::Get()->GetValueMin(vid);
+
+ unlockNodes();
+ return rv;
+}
+
+int OZW::getValueMax(int nodeId, int index)
+{
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ int rv = 0;
+ if (getValueID(nodeId, index, &vid))
+ rv = Manager::Get()->GetValueMax(vid);
+
+ unlockNodes();
+ return rv;
+}
+
+bool OZW::isValueReadOnly(int nodeId, int index)
+{
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ bool rv = false;
+ if (getValueID(nodeId, index, &vid))
+ rv = Manager::Get()->IsValueReadOnly(vid);
+
+ unlockNodes();
+ return rv;
+}
+
+bool OZW::isValueWriteOnly(int nodeId, int index)
+{
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ bool rv = false;
+ if (getValueID(nodeId, index, &vid))
+ rv = Manager::Get()->IsValueWriteOnly(vid);
+
+ unlockNodes();
+ return rv;
+}
+
+bool OZW::isValueSet(int nodeId, int index)
+{
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ bool rv = false;
+ if (getValueID(nodeId, index, &vid))
+ rv = Manager::Get()->IsValueSet(vid);
+
+ unlockNodes();
+ return rv;
+}
+
+bool OZW::isValuePolled(int nodeId, int index)
+{
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ bool rv = false;
+ if (getValueID(nodeId, index, &vid))
+ rv = Manager::Get()->IsValuePolled(vid);
+
+ unlockNodes();
+ return rv;
+}
+
+bool OZW::getValueAsBool(int nodeId, int index)
+{
+ if (isValueWriteOnly(nodeId, index))
+ {
+ cerr << __FUNCTION__ << ": Node " << nodeId << " index " << index
+ << " is WriteOnly" << endl;
+ return false;
+ }
+
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ bool rv = false;
+ if (getValueID(nodeId, index, &vid))
+ {
+ if (!Manager::Get()->GetValueAsBool(vid, &rv))
+ {
+ cerr << __FUNCTION__ << ": Value is not a bool type, returning "
+ << rv << endl;
+ }
+ }
+
+ unlockNodes();
+ return rv;
+}
+
+uint8_t OZW::getValueAsByte(int nodeId, int index)
+{
+ if (isValueWriteOnly(nodeId, index))
+ {
+ cerr << __FUNCTION__ << ": Node " << nodeId << " index " << index
+ << " is WriteOnly" << endl;
+ return 0;
+ }
+
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ uint8_t rv = false;
+ if (getValueID(nodeId, index, &vid))
+ {
+ if (!Manager::Get()->GetValueAsByte(vid, &rv))
+ {
+ cerr << __FUNCTION__ << ": Value is not a byte type, returning "
+ << int(rv) << endl;
+ }
+ }
+
+ unlockNodes();
+ return rv;
+}
+
+float OZW::getValueAsFloat(int nodeId, int index)
+{
+ if (isValueWriteOnly(nodeId, index))
+ {
+ cerr << __FUNCTION__ << ": Node " << nodeId << " index " << index
+ << " is WriteOnly" << endl;
+ return 0.0;
+ }
+
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ float rv = 0.0;
+ if (getValueID(nodeId, index, &vid))
+ {
+ if (!Manager::Get()->GetValueAsFloat(vid, &rv))
+ {
+ cerr << __FUNCTION__ << ": Value is not a float type, returning "
+ << rv << endl;
+ }
+ }
+
+ unlockNodes();
+ return rv;
+}
+
+int OZW::getValueAsInt32(int nodeId, int index)
+{
+ if (isValueWriteOnly(nodeId, index))
+ {
+ cerr << __FUNCTION__ << ": Node " << nodeId << " index " << index
+ << " is WriteOnly" << endl;
+ return 0;
+ }
+
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ int32_t rv = 0;
+ if (getValueID(nodeId, index, &vid))
+ {
+ if (!Manager::Get()->GetValueAsInt(vid, &rv))
+ {
+ cerr << __FUNCTION__ << ": Value is not an int32 type, returning "
+ << rv << endl;
+ }
+ }
+
+ unlockNodes();
+ return int(rv);
+}
+
+int OZW::getValueAsInt16(int nodeId, int index)
+{
+ if (isValueWriteOnly(nodeId, index))
+ {
+ cerr << __FUNCTION__ << ": Node " << nodeId << " index " << index
+ << " is WriteOnly" << endl;
+ return 0;
+ }
+
+ ValueID vid(m_homeId, (uint64)0);
+
+ lockNodes();
+
+ int16_t rv = 0;
+ if (getValueID(nodeId, index, &vid))
+ {
+ if (!Manager::Get()->GetValueAsShort(vid, &rv))
+ {
+ cerr << __FUNCTION__ << ": Value is not an int16 type, returning "
+ << rv << endl;
+ }
+ }
+
+ unlockNodes();
+ return int(rv);
+}
+
+bool OZW::isNodeListeningDevice(int nodeId)
+{
+ nodeId &= 0xff;
+
+ lockNodes();
+
+ bool rv = Manager::Get()->IsNodeListeningDevice(m_homeId, nodeId);
+
+ unlockNodes();
+ return rv;
+}
+
+bool OZW::isNodeFrequentListeningDevice(int nodeId)
+{
+ nodeId &= 0xff;
+
+ lockNodes();
+
+ bool rv = Manager::Get()->IsNodeFrequentListeningDevice(m_homeId, nodeId);
+
+ unlockNodes();
+ return rv;
+}
+
+bool OZW::isNodeAwake(int nodeId)
+{
+ nodeId &= 0xff;
+
+ lockNodes();
+
+ bool rv = Manager::Get()->IsNodeAwake(m_homeId, nodeId);
+
+ unlockNodes();
+ return rv;
+}
+
+void OZW::setDebug(bool enable)
+{
+ m_debugging = enable;
+
+ // To bad the following does not seem to affect anything. The only
+ // way I've found to control it is via the options.xml file.
+
+ // Log::SetLoggingState(enable);
+}
diff --git a/src/ozw/ozw.h b/src/ozw/ozw.h
new file mode 100644
index 0000000..e4f4152
--- /dev/null
+++ b/src/ozw/ozw.h
@@ -0,0 +1,574 @@
+/*
+ * Author: Jon Trulson <jtrulson@ics.com>
+ * Copyright (c) 2015 Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#pragma once
+
+#include <string>
+#include <map>
+
+#include "Manager.h"
+#include "Notification.h"
+#include "Options.h"
+#include "Driver.h"
+#include "Node.h"
+#include "Group.h"
+#include "platform/Log.h"
+
+namespace upm {
+
+ /**
+ * @brief OZW OpenZWave library
+ * @defgroup ozw libupm-ozw
+ * @ingroup uart wifi
+ */
+
+ /**
+ * @library ozw
+ * @sensor ozw
+ * @comname UPM wrapper for the OpenZWave library
+ * @type wifi
+ * @man other
+ * @con uart
+ * @web http://www.openzwave.com/
+ *
+ * @brief UPM API for the OpenZWave library
+ *
+ * This module implements a wrapper around the OpenZWave library.
+ * OpenZWave must be compiled and installed on your machine in order
+ * to use this library.
+ *
+ * This module was developed with OpenZWave 1.3, and an Aeon Z-Stick
+ * Gen5 configured as a Primary Controller. It provides the ability
+ * to query and set various values that can be used to control ZWave
+ * devices. It does not concern itself with configuration of
+ * devices. It is assumed that you have already setup your ZWave
+ * network using a tool like the OpenZWave control panel, and have
+ * already configured your devices as appropriate.
+ *
+ * To avoid exposing some of the internals of OpenZWave, devices
+ * (nodes) and their values, are accessed via a nodeId and a value
+ * index number. The example will run dumpNodes() which will list
+ * the currently connected devices and the values that are available
+ * to them, along with an index number for that value. It is
+ * through these values (nodeId and index) that you can query and
+ * set device values.
+ *
+ * In addition to querying values from a device (such as state
+ * (on/off), or temperature, etc), methods are provided to allow you
+ * to control these devices to the extent they allow, for example,
+ * using a ZWave connected switch to turn on a lamp.
+ *
+ * Since it's likely no two ZWave networks are going to be the same,
+ * the example will just initialize OpenZWave and run the
+ * dumpNodes() method to allow you to see what devices are present,
+ * the values they support and their current content, along with the
+ * per-node index number you can use to address them. There will be
+ * commented out code examples showing you how to query or set a
+ * specific value for a device.
+ *
+ * See the ozw example code comments for an example of the ouput of
+ * running dumpNodes().
+ *
+ * In most of the methods below, You will need the NodeId (Node
+ * number), and the Index number to access or otherwise affect these
+ * values.
+ *
+ * @snippet openzwave.cxx Interesting
+ */
+
+ // forward declaration of private zwNode data
+ class zwNode;
+
+ class OZW {
+ public:
+
+ typedef std::map<uint8_t, zwNode *> zwNodeMap_t;
+
+ /**
+ * OZW constructor
+ */
+ OZW();
+
+ /**
+ * OZW Destructor
+ */
+ ~OZW();
+
+ /**
+ * Start configuration with basic options. This must be called
+ * prior to init(), after the OZW() contructor is called.
+ *
+ * @param configPath Set the location of the OpenZWave config
+ * directory, default is /etc/openzwave
+ * @param userConfigDir Set the path to the user configuration
+ * directory. This is the location of the zwcfg*.xml and
+ * option.xml files for the user (probably created by the
+ * OpenZWave Control Panel example application). The default is
+ * the current directory ("").
+ * @param cmdLine Specify command line formatted options to
+ * OpenZWave. The default is "".
+ */
+ void optionsCreate(std::string configPath="/etc/openzwave",
+ std::string userConfigDir="",
+ std::string cmdLine="");
+
+ /**
+ * Add an integer Option. See the OpenZWave documentation for
+ * valid values.
+ *
+ * @param name The name of the configuration option
+ * @param val The value to set it to
+ */
+ void optionAddInt(std::string name, int val);
+
+ /**
+ * Add a boolean Option. See the OpenZWave documentation for
+ * valid values.
+ *
+ * @param name The name of the configuration option
+ * @param val The value to set it to
+ */
+ void optionAddBool(std::string name, bool val);
+
+ /**
+ * Add a string Option. See the OpenZWave documentation for valid
+ * values.
+ *
+ * @param name The name of the configuration option
+ * @param val The value to set it to
+ * @append true to append to the option, false to override
+ */
+ void optionAddString(std::string name, std::string val, bool append);
+
+ /**
+ * Lock the Options. This must be called after all options have
+ * been set, and before init() is called. If init() is called
+ * without locking the Options, init() will lock them itself.
+ * After the options have been locked, no further options can be
+ * specified.
+ */
+ void optionsLock();
+
+ /**
+ * Initialize the ZWave network. This method will start a probe
+ * of all defined devices on the ZWave network and query essential
+ * information about them. This function will not return until
+ * either initialization has failed, or has succeeded far enough
+ * along for the following methods to work. Depending on the size
+ * an complexity of the ZWave network, this may take anywhere from
+ * seconds to several minutes to complete.
+ *
+ * All Options (via option*()) must have been specified before
+ * this function is called. If the Options have not been locked
+ * via optionsLock() prior to calling init(), this method will
+ * lock them for you before proceeding.
+ *
+ * @param devicePath The device path for the ZWave controller,
+ * typically something like /dev/ttyACM0, or similiar
+ * @param isHID true if this is a HID device, false otherwise (ie:
+ * a serial port like /dev/ttyACM0, /dev/ttyUSB0, etc). Default
+ * is false.
+ * @return true if init succeeded, false otherwise
+ */
+ bool init(std::string devicePath, bool isHID=false);
+
+ /**
+ * Dump information about all configured nodes and their values to
+ * stdout. This is useful to determine what nodes are available,
+ * and the index (used for querying and seting values for them).
+ * In addition, it includes information about each value (type,
+ * current value, etc).
+ *
+ * @param all set to true to dump information about all values
+ * available for each node. If false, only information about
+ * 'user' values (ignoring 'system' and 'configuration') are
+ * output. The default is false ('user' values only).
+ */
+ void dumpNodes(bool all=false);
+
+ /**
+ * Return a string (which may be empty) indicating the Units of
+ * measure for a given value. For example, querying a temperature
+ * value may return "F" to indicate Fahrenheit.
+ *
+ * @param nodeId The node ID to query
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @return A string containing the Unit of measure for the value
+ */
+ std::string getValueUnits(int nodeId, int index);
+
+ /**
+ * Set the text for the Units of measure for a value.
+ *
+ * @param nodeId The node ID to query
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @param text The text to set
+ */
+ void setValueUnits(int nodeId, int index, std::string text);
+
+ /**
+ * Return a string (which may be empty) containing the
+ * user-freindly Label for a value.
+ *
+ * @param nodeId The node ID to query
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @return A string containing the Value's label
+ */
+ std::string getValueLabel(int nodeId, int index);
+
+ /**
+ * Set the text for a Value's label.
+ *
+ * @param nodeId The node ID to query
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @param text The text to set
+ */
+ void setValueLabel(int nodeId, int index, std::string text);
+
+ /**
+ * Return a string (which may be empty) indicating the Help text
+ * of a value, if available.
+ *
+ * @param nodeId The node ID to query
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @return A string containing the Help text, if available
+ */
+ std::string getValueHelp(int nodeId, int index);
+
+ /**
+ * Set the text for a Value's help text.
+ *
+ * @param nodeId The node ID to query
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @param text The text to set
+ */
+ void setValueHelp(int nodeId, int index, std::string text);
+
+ /**
+ * Set the contents of a Value to a string. This should always
+ * succeed if the supplied content makes sense for a given value,
+ * regardless of the value's actual type.
+ *
+ * @param nodeId The node ID
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @param val the content to assign to the value referenced by
+ * nodeId, and index.
+ */
+ void setValueAsString(int nodeId, int index, std::string val);
+
+ /**
+ * Set the contents of a Value, to a bool. This will fail, and an
+ * error message printed if the value type is not a boolean value.
+ *
+ * @param nodeId The node ID
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @param val the boolean content to assign to the value referenced
+ * by nodeId, and index.
+ */
+ void setValueAsBool(int nodeId, int index, bool val);
+
+ /**
+ * Set the contents of a Value, to a byte. This will fail, and an
+ * error message printed if the value type is not a byte value.
+ *
+ * @param nodeId The node ID
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @param val the byte content to assign to the value referenced
+ * by nodeId, and index.
+ */
+ void setValueAsByte(int nodeId, int index, uint8_t val);
+
+ /**
+ * Set the contents of a Value, to a float. This will fail, and an
+ * error message printed if the value type is not a float value.
+ *
+ * @param nodeId The node ID
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @param val the float content to assign to the value referenced
+ * by nodeId, and index.
+ */
+ void setValueAsFloat(int nodeId, int index, float val);
+
+ /**
+ * Set the contents of a Value, to a 32 bit integer (int32). This
+ * will fail, and an error message printed if the value type is
+ * not an int32.
+ *
+ * @param nodeId The node ID
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @param val the int32 content to assign to the value referenced
+ * by nodeId, and index.
+ */
+ void setValueAsInt32(int nodeId, int index, int32_t val);
+
+ /**
+ * Set the contents of a Value, to a 16 bit integer (int16). This
+ * will fail, and an error message printed if the value type is
+ * not an int16.
+ *
+ * @param nodeId The node ID
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @param val the int16 content to assign to the value referenced
+ * by nodeId, and index.
+ */
+ void setValueAsInt16(int nodeId, int index, int16_t val);
+
+ /**
+ * Set the contents of a Value, to an array of bytes. This will
+ * fail, and an error message printed if the value type is not
+ * settable as an array of bytes.
+ *
+ * @param nodeId The node ID
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @param val the byte array content to assign to the value referenced
+ * by nodeId, and index.
+ * @param len The length of the byte array
+ */
+ void setValueAsBytes(int nodeId, int index, uint8_t *val, uint8_t len);
+
+ /**
+ * Get the minimum allowed value for a node's Value.
+ *
+ * @param nodeId The node ID
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @return The minumum allowed value
+ */
+ int getValueMin(int nodeId, int index);
+
+ /**
+ * Get the maximum allowed value for a node's Value.
+ *
+ * @param nodeId The node ID
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @return The maximum allowed value
+ */
+ int getValueMax(int nodeId, int index);
+
+ /**
+ * Test whether a value is read-only.
+ *
+ * @param nodeId The node ID
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @return true if the value is read-only, false otherwise
+ */
+ bool isValueReadOnly(int nodeId, int index);
+
+ /**
+ * Test whether a value is write only.
+ *
+ * @param nodeId The node ID
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @return true if the value is write-only, false otherwise
+ */
+ bool isValueWriteOnly(int nodeId, int index);
+
+ /**
+ * Test whether a value is really set on a node, and not a default
+ * value chosen by the OpenZWave library.
+ *
+ * @param nodeId The node ID
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @return true if the value is really set, false if a default value is
+ * being reported
+ */
+ bool isValueSet(int nodeId, int index);
+
+ /**
+ * Test whether a value is being manually polled by the OpenZWave
+ * library. Most modern devices are never polled, rather they are
+ * configured to report changing values to the controller on their
+ * own at device specific intervals or when appropriate events
+ * (depending the device) have occured.
+ *
+ * @param nodeId The node ID
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @return true if the value is being maually polled, false otherwise
+ * being reported
+ */
+ bool isValuePolled(int nodeId, int index);
+
+ /**
+ * Return the content of a value as a string. This should always
+ * succeed, regardless of the actual value type.
+ *
+ * @param nodeId The node ID
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @return A string representing the current contents of a value.
+ */
+ std::string getValueAsString(int nodeId, int index);
+
+ /**
+ * Return the content of a value as a booleang. This will fail,
+ * and an error message printed if the value type is not boolean.
+ *
+ * @param nodeId The node ID
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @return A boolean representing the current contents of a value.
+ */
+ bool getValueAsBool(int nodeId, int index);
+
+ /**
+ * Return the content of a value as a byte. This will fail, and
+ * an error message printed if the value type is not a byte.
+ *
+ * @param nodeId The node ID
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @return A byte representing the current contents of a value.
+ */
+ uint8_t getValueAsByte(int nodeId, int index);
+
+ /**
+ * Return the content of a value as a float. This will fail, and
+ * an error message printed if the value type is not a floating
+ * point value.
+ *
+ * @param nodeId The node ID
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @return A float representing the current contents of a value.
+ */
+ float getValueAsFloat(int nodeId, int index);
+
+ /**
+ * Return the content of a value as an int32. This will fail, and
+ * an error message printed if the value type is not an int32.
+ *
+ * @param nodeId The node ID
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @return An int32 representing the current contents of a value.
+ */
+ int getValueAsInt32(int nodeId, int index);
+
+ /**
+ * Return the content of a value as an int16. This will fail, and
+ * an error message printed if the value type is not an int16.
+ *
+ * @param nodeId The node ID
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @return An int16 representing the current contents of a value.
+ */
+ int getValueAsInt16(int nodeId, int index);
+
+ /**
+ * Issue a refresh request for a value on a node. OpenZWave will
+ * query the value and update it's internal state when the device
+ * responds. Note, this happens asynchronously - it may take some
+ * time before the current value is reported to OpenZWave by the
+ * node. If the node is asleep, you may not get a current value
+ * for some time (or at all, depending on the device). This
+ * method will return immediately after the request has been
+ * queued.
+ *
+ * @param nodeId The node ID
+ * @param index The value index (see dumpNodes()) of the value to query.
+ */
+ void refreshValue(int nodeId, int index);
+
+ /**
+ * Enable or disable some debugging output. Note, this will not
+ * affect OpenZWave's own debugging, which is usually set in the
+ * option.xml file.
+ *
+ * @param enable true to enable debugging, false otherwise
+ */
+ void setDebug(bool enable);
+
+ /**
+ * Determine if a node is a listening device -- in other words, the
+ * node never sleeps.
+ *
+ * @param nodeId The node ID
+ * @return true if the node never sleeps, false otherwise
+ */
+ bool isNodeListeningDevice(int nodeId);
+
+ /**
+ * Determine if a node is a frequent listening device -- in other
+ * words, if the node is asleep, can it be woken by a beam.
+ *
+ * @param nodeId The node ID
+ * @return true if the node is a frequent listening device, false
+ * otherwise
+ */
+ bool isNodeFrequentListeningDevice(int nodeId);
+
+ /**
+ * Determine if a node is awake.
+ *
+ * @param nodeId The node ID
+ * @return true if the node is awake, false otherwise
+ */
+ bool isNodeAwake(int nodeId);
+
+ protected:
+ /**
+ * Based on a nodeId and a value index, lookup the corresponding
+ * OpenZWave ValueID.
+ *
+ * @param nodeId The node ID
+ * @param index The value index (see dumpNodes()) of the value to query.
+ * @param A pointer to a ValueID that will be returned if successful
+ * @return true of the nodeId and index was found, false otherwise
+ */
+ bool getValueID(int nodeId, int index, OpenZWave::ValueID *vid);
+
+ /**
+ * Lock the m_zwNodeMap mutex to protect against changes made to
+ * the the the map by the OpenZWave notification handler. Always
+ * lock this mutex when acessing anything in the zwNodeMap map.
+ */
+
+ void lockNodes() { pthread_mutex_lock(&m_nodeLock); };
+ /**
+ * Unlock the m_zwNodeMap mutex after lockNodes() has been called.
+ */
+ void unlockNodes() { pthread_mutex_unlock(&m_nodeLock); };
+
+ private:
+ uint32_t m_homeId;
+ bool m_mgrCreated;
+ bool m_driverFailed;
+ bool m_debugging;
+
+ bool m_driverIsHID;
+ std::string m_devicePath;
+
+ // our notification handler, called by OpenZWave for events on the
+ // network.
+ static void notificationHandler(OpenZWave::Notification
+ const* notification,
+ void *ctx);
+
+ // a map of added nodes
+ zwNodeMap_t m_zwNodeMap;
+
+ // for coordinating access to the node list
+ pthread_mutex_t m_nodeLock;
+
+ // We use these to determine init failure or success (if OpenZWave
+ // has successfully queried essential data about the network).
+ pthread_mutex_t m_initLock;
+ pthread_cond_t m_initCond;
+ };
+}
+
+
diff --git a/src/ozw/pyupm_ozw.i b/src/ozw/pyupm_ozw.i
new file mode 100644
index 0000000..ad6d19e
--- /dev/null
+++ b/src/ozw/pyupm_ozw.i
@@ -0,0 +1,15 @@
+%module pyupm_ozw
+%include "../upm.i"
+%include "cpointer.i"
+
+%include "stdint.i"
+
+%feature("autodoc", "3");
+
+%pointer_functions(float, floatp);
+
+%include "ozw.h"
+%{
+ #include "ozw.h"
+%}
+
diff --git a/src/ozw/zwNode.cxx b/src/ozw/zwNode.cxx
new file mode 100644
index 0000000..a55729b
--- /dev/null
+++ b/src/ozw/zwNode.cxx
@@ -0,0 +1,168 @@
+/*
+ * Author: Jon Trulson <jtrulson@ics.com>
+ * Copyright (c) 2015 Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdint.h>
+#include <string>
+#include "zwNode.h"
+
+#include "Node.h"
+
+using namespace upm;
+using namespace std;
+using namespace OpenZWave;
+
+zwNode::zwNode(uint32_t homeId, uint8_t nodeId)
+{
+ m_homeId = homeId;
+ m_nodeId = nodeId;
+
+ m_vindex = 0;
+}
+
+zwNode::~zwNode()
+{
+}
+
+uint8_t zwNode::nodeId()
+{
+ return m_nodeId;
+}
+
+uint32_t zwNode::homeId()
+{
+ return m_homeId;
+}
+
+void zwNode::addValueID(ValueID vid)
+{
+ // We need to use insert since ValueID's default ctor is private
+ m_values.insert(std::pair<int, ValueID>(m_vindex++, vid));
+}
+
+void zwNode::removeValueID(ValueID vid)
+{
+ //we have to get a little complicated here since we need to delete
+ //the value id, but the map is indexed by m_vindex
+ for (valueMap_t::iterator it = m_values.begin();
+ it != m_values.end(); ++it)
+ {
+ if ((*it).second == vid)
+ {
+ m_values.erase((*it).first);
+ break;
+ }
+ }
+}
+
+bool zwNode::indexToValueID(int index, ValueID *vid)
+{
+ valueMap_t::iterator it;
+
+ it = m_values.find(index);
+
+ if (it == m_values.end())
+ {
+ // not found, return false
+ return false;
+ }
+ else
+ *vid = (*it).second;
+
+ return true;
+}
+
+void zwNode::dumpNode(bool all)
+{
+ for (valueMap_t::iterator it = m_values.begin();
+ it != m_values.end(); ++it)
+ {
+ int vindex = (*it).first;
+ ValueID vid = (*it).second;
+ string label = Manager::Get()->GetValueLabel(vid);
+ string valueAsStr;
+ Manager::Get()->GetValueAsString(vid, &valueAsStr);
+ string valueUnits = Manager::Get()->GetValueUnits(vid);
+ ValueID::ValueType vType = vid.GetType();
+ string vTypeStr;
+
+ switch (vType)
+ {
+ case ValueID::ValueType_Bool:
+ vTypeStr = "bool";
+ break;
+
+ case ValueID::ValueType_Byte:
+ vTypeStr = "byte";
+ break;
+
+ case ValueID::ValueType_Decimal:
+ vTypeStr = "float";
+ break;
+
+ case ValueID::ValueType_Int:
+ vTypeStr = "int32";
+ break;
+
+ case ValueID::ValueType_List:
+ vTypeStr = "list";
+ break;
+
+ case ValueID::ValueType_Schedule:
+ vTypeStr = "schedule";
+ break;
+
+ case ValueID::ValueType_Short:
+ vTypeStr = "int16";
+ break;
+
+ case ValueID::ValueType_String:
+ vTypeStr = "string";
+ break;
+
+ case ValueID::ValueType_Button:
+ vTypeStr = "button";
+ break;
+
+ case ValueID::ValueType_Raw:
+ vTypeStr = "raw";
+ break;
+
+ default:
+ vTypeStr = "undefined";
+ break;
+ }
+
+ // by default we only want user values, unless 'all' is true
+ if (all || (vid.GetGenre() == ValueID::ValueGenre_User))
+ fprintf(stderr, "\t Index: %2d, Type: %s, Label: %s, Value: %s %s\n",
+ vindex,
+ vTypeStr.c_str(),
+ label.c_str(),
+ valueAsStr.c_str(),
+ valueUnits.c_str());
+ }
+}
+
+
+
diff --git a/src/ozw/zwNode.h b/src/ozw/zwNode.h
new file mode 100644
index 0000000..0b01dc6
--- /dev/null
+++ b/src/ozw/zwNode.h
@@ -0,0 +1,105 @@
+/*
+ * Author: Jon Trulson <jtrulson@ics.com>
+ * Copyright (c) 2015 Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#pragma once
+
+#include <map>
+
+#include "Manager.h"
+
+namespace upm {
+
+ class zwNode {
+ public:
+ typedef std::map<int, OpenZWave::ValueID> valueMap_t;
+
+ /**
+ * zwNode contructor.
+ *
+ * @param homeId the homeId os the network controller
+ * @param nodeId the node index
+ */
+ zwNode(uint32_t homeId, uint8_t nodeId);
+
+ ~zwNode();
+
+ /**
+ * get the nodeId
+ *
+ * @return The nodeId for this node
+ */
+ uint8_t nodeId();
+
+ /**
+ * get the homeId
+ *
+ * @return The homeId for this node
+ */
+ uint32_t homeId();
+
+ /**
+ * Add an OpenZWave ValueID and index to the value map,
+ * incrementing m_vindex.
+ *
+ * @param vid The OpenZWave ValueID
+ */
+ void addValueID(OpenZWave::ValueID vid);
+
+ /**
+ * Remove an OpenZWave ValueID from the value map.
+ *
+ * @param vid The OpenZWave ValueID
+ */
+ void removeValueID(OpenZWave::ValueID vid);
+
+ /**
+ * Lookup and return a ValueID corresponding to an index.
+ *
+ * @param index the index to look up
+ * @param vid The pointer to the returned ValueID, if it exists
+ * @return true if the index was found, false otherwise
+ */
+ bool indexToValueID(int index, OpenZWave::ValueID *vid);
+
+ /**
+ * Dump various information about the ValueIDs stored in this
+ * node.
+ *
+ * @param all true to dump all values, false to limit dumping only
+ * 'user' values.
+ */
+ void dumpNode(bool all=false);
+
+ protected:
+
+ private:
+ uint32_t m_homeId;
+ uint8_t m_nodeId;
+
+ valueMap_t m_values;
+
+ // we increment this index for every ValueID we add
+ unsigned int m_vindex;
+ };
+
+}