From 3ff42cb533d0a1b01fbd4aeb6e13c2a2c8218195 Mon Sep 17 00:00:00 2001 From: matzman Date: Tue, 19 May 2015 03:42:02 +0200 Subject: [PATCH] . --- .../launch/setup_core_types.launch | 8 + .../schema/core/devices/dimmer/command.json | 19 ++ .../schema/core/devices/dimmer/status.json | 19 ++ .../schema/core/devices/switch/command.json | 19 ++ .../schema/core/devices/switch/status.json | 19 ++ .../schema/core/types/boolean/command.json | 4 +- .../schema/core/types/boolean/status.json | 2 +- .../schema/core/types/percentage/command.json | 6 +- .../schema/core/types/percentage/status.json | 2 +- .../devicerepository_service.h | 3 + .../devicerepository_serviceimpl.cpp | 14 ++ .../devicerepository_serviceimpl.h | 2 + .../ruleengine/rule/RuleConditionImpl.cpp | 28 ++- .../ruleengine/rule/RuleConditionImpl.h | 6 +- src/hos_cosgi_ruleengine/test/rulepkg01.json | 60 +++-- src/hos_cosgi_scripting_python/CMakeLists.txt | 1 + .../service/scripting/python/PyHOSAPI.cpp | 72 ++++++ .../cosgi/service/scripting/python/PyHOSAPI.h | 71 ++++++ .../python/scripting_serviceimpl.cpp | 64 +----- .../scripting/python/scripting_serviceimpl.h | 1 - src/hos_dummy/CMakeLists.txt | 169 ++++++++++++++ src/hos_dummy/nodes/hos_dummy_controller.py | 28 +++ src/hos_dummy/nodes/hos_dummy_devices.py | 33 +++ src/hos_dummy/package.xml | 56 +++++ .../python/hos_dummy/HosDummyController.py | 144 ++++++++++++ .../python/hos_dummy/HosDummyDevices.py | 206 ++++++++++++++++++ src/hos_dummy/python/hos_dummy/__init__.py | 0 src/hos_dummy/setup.py | 11 + src/hos_philips_hue/nodes/hue_bridge_node.py | 2 +- src/hos_philips_hue/nodes/schema.json | 19 -- 30 files changed, 965 insertions(+), 123 deletions(-) create mode 100644 src/hos_core_types/schema/core/devices/dimmer/command.json create mode 100644 src/hos_core_types/schema/core/devices/dimmer/status.json create mode 100644 src/hos_core_types/schema/core/devices/switch/command.json create mode 100644 src/hos_core_types/schema/core/devices/switch/status.json create mode 100644 src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/PyHOSAPI.cpp create mode 100644 src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/PyHOSAPI.h create mode 100644 src/hos_dummy/CMakeLists.txt create mode 100755 src/hos_dummy/nodes/hos_dummy_controller.py create mode 100755 src/hos_dummy/nodes/hos_dummy_devices.py create mode 100644 src/hos_dummy/package.xml create mode 100644 src/hos_dummy/python/hos_dummy/HosDummyController.py create mode 100644 src/hos_dummy/python/hos_dummy/HosDummyDevices.py create mode 100644 src/hos_dummy/python/hos_dummy/__init__.py create mode 100644 src/hos_dummy/setup.py delete mode 100644 src/hos_philips_hue/nodes/schema.json diff --git a/src/hos_core_types/launch/setup_core_types.launch b/src/hos_core_types/launch/setup_core_types.launch index 2230092a..9768c64e 100644 --- a/src/hos_core_types/launch/setup_core_types.launch +++ b/src/hos_core_types/launch/setup_core_types.launch @@ -10,6 +10,14 @@ + + + + + + + + diff --git a/src/hos_core_types/schema/core/devices/dimmer/command.json b/src/hos_core_types/schema/core/devices/dimmer/command.json new file mode 100644 index 00000000..4119f62a --- /dev/null +++ b/src/hos_core_types/schema/core/devices/dimmer/command.json @@ -0,0 +1,19 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Dimmer Command", + "description": "", + "version": "1.0.0", + "type": "object", + "properties": { + "type": { + "description": "", + "type": "string", + "pattern": "core/devices/switch/command" + }, + "dimmer": { + "$ref": "hos:schema://core/types/percentage/command" + } + }, + "additionalProperties": false, + "required": ["dimmer"] +} \ No newline at end of file diff --git a/src/hos_core_types/schema/core/devices/dimmer/status.json b/src/hos_core_types/schema/core/devices/dimmer/status.json new file mode 100644 index 00000000..1e853ad6 --- /dev/null +++ b/src/hos_core_types/schema/core/devices/dimmer/status.json @@ -0,0 +1,19 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Dimmer Status", + "description": "", + "version": "1.0.0", + "type": "object", + "properties": { + "type": { + "description": "", + "type": "string", + "pattern": "core/devices/switch/status" + }, + "dimmer": { + "$ref": "hos:schema://core/types/percentage/status" + } + }, + "additionalProperties": false, + "required": ["dimmer"] +} \ No newline at end of file diff --git a/src/hos_core_types/schema/core/devices/switch/command.json b/src/hos_core_types/schema/core/devices/switch/command.json new file mode 100644 index 00000000..64174949 --- /dev/null +++ b/src/hos_core_types/schema/core/devices/switch/command.json @@ -0,0 +1,19 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Switch Command", + "description": "", + "version": "1.0.0", + "type": "object", + "properties": { + "type": { + "description": "", + "type": "string", + "pattern": "core/devices/switch/command" + }, + "switch": { + "$ref": "hos:schema://core/types/boolean/command" + } + }, + "additionalProperties": false, + "required": ["switch"] +} \ No newline at end of file diff --git a/src/hos_core_types/schema/core/devices/switch/status.json b/src/hos_core_types/schema/core/devices/switch/status.json new file mode 100644 index 00000000..251c813e --- /dev/null +++ b/src/hos_core_types/schema/core/devices/switch/status.json @@ -0,0 +1,19 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Switch Status", + "description": "", + "version": "1.0.0", + "type": "object", + "properties": { + "type": { + "description": "", + "type": "string", + "pattern": "core/devices/switch/status" + }, + "switch": { + "$ref": "hos:schema://core/types/boolean/status" + } + }, + "additionalProperties": false, + "required": ["switch"] +} \ No newline at end of file diff --git a/src/hos_core_types/schema/core/types/boolean/command.json b/src/hos_core_types/schema/core/types/boolean/command.json index e0e5808f..365b6867 100644 --- a/src/hos_core_types/schema/core/types/boolean/command.json +++ b/src/hos_core_types/schema/core/types/boolean/command.json @@ -22,7 +22,7 @@ }, "additionalProperties": false, "anyOf": [ - { "required": [ "type", "set" ] }, - { "required": [ "type", "command" ] } + { "required": [ "set" ] }, + { "required": [ "command" ] } ] } \ No newline at end of file diff --git a/src/hos_core_types/schema/core/types/boolean/status.json b/src/hos_core_types/schema/core/types/boolean/status.json index 2e4567fb..01394e09 100644 --- a/src/hos_core_types/schema/core/types/boolean/status.json +++ b/src/hos_core_types/schema/core/types/boolean/status.json @@ -16,5 +16,5 @@ } }, "additionalProperties": false, - "required": ["type", "value"] + "required": ["value"] } \ No newline at end of file diff --git a/src/hos_core_types/schema/core/types/percentage/command.json b/src/hos_core_types/schema/core/types/percentage/command.json index 807790c6..94f40b22 100644 --- a/src/hos_core_types/schema/core/types/percentage/command.json +++ b/src/hos_core_types/schema/core/types/percentage/command.json @@ -25,8 +25,8 @@ }, "additionalProperties": false, "anyOf": [ - { "required": [ "type", "set" ] }, - { "required": [ "type", "add" ] }, - { "required": [ "type", "sub" ] } + { "required": [ "set" ] }, + { "required": [ "add" ] }, + { "required": [ "sub" ] } ] } \ No newline at end of file diff --git a/src/hos_core_types/schema/core/types/percentage/status.json b/src/hos_core_types/schema/core/types/percentage/status.json index c6494acb..aea02bba 100644 --- a/src/hos_core_types/schema/core/types/percentage/status.json +++ b/src/hos_core_types/schema/core/types/percentage/status.json @@ -16,5 +16,5 @@ } }, "additionalProperties": false, - "required": ["type", "value"] + "required": ["value"] } \ No newline at end of file diff --git a/src/hos_cosgi_devicerepository/include/hos_cosgi_devicerepository/hos/cosgi/service/devicerepository/devicerepository_service.h b/src/hos_cosgi_devicerepository/include/hos_cosgi_devicerepository/hos/cosgi/service/devicerepository/devicerepository_service.h index 2abf2cbd..4a0500cc 100644 --- a/src/hos_cosgi_devicerepository/include/hos_cosgi_devicerepository/hos/cosgi/service/devicerepository/devicerepository_service.h +++ b/src/hos_cosgi_devicerepository/include/hos_cosgi_devicerepository/hos/cosgi/service/devicerepository/devicerepository_service.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -100,6 +101,8 @@ public: virtual std::shared_ptr getDevice(std::string device_id) = 0; virtual size_t getDevices(std::vector>& devices) = 0; + virtual size_t deviceCount() = 0; + virtual std::set deviceIDs() = 0; }; diff --git a/src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/devicerepository_serviceimpl.cpp b/src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/devicerepository_serviceimpl.cpp index 577fd598..db4e0fe7 100644 --- a/src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/devicerepository_serviceimpl.cpp +++ b/src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/devicerepository_serviceimpl.cpp @@ -167,6 +167,20 @@ size_t DeviceRepositoryServiceImpl::getDevices(std::vector DeviceRepositoryServiceImpl::deviceIDs() { + std::set retval; + for (auto d : devices) { + retval.insert(d.first); + } + return retval; +} + + void DeviceRepositoryServiceImpl::statusMsgCallback(const hos_core_msgs::DeviceStatusUpdate::ConstPtr& msg) { std::lock_guard lock(serviceMutex); std::cout << "HOSDeviceRepositoryServiceImpl::statusMsgCallback" << std::endl; diff --git a/src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/devicerepository_serviceimpl.h b/src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/devicerepository_serviceimpl.h index eb50bcb9..c2a78d31 100644 --- a/src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/devicerepository_serviceimpl.h +++ b/src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/devicerepository_serviceimpl.h @@ -127,6 +127,8 @@ public: virtual std::shared_ptr getDevice(std::string device_id) override; virtual size_t getDevices(std::vector>& devices) override; + virtual size_t deviceCount() override; + virtual std::set deviceIDs() override; /* Message Callbacks */ diff --git a/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/rule/RuleConditionImpl.cpp b/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/rule/RuleConditionImpl.cpp index 401ea9ce..84f8e53f 100644 --- a/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/rule/RuleConditionImpl.cpp +++ b/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/rule/RuleConditionImpl.cpp @@ -262,7 +262,7 @@ void DeviceStatusMsgCondition::notificationReceived(interface::ObserverstatusMsg; } else if (e2->statusMsg.HasPath(msgPointer)) { - value = e2->statusMsg.Get(msgPointer); + value = e2->statusMsg.GetPath(msgPointer); } else { notify = false; } @@ -321,7 +321,7 @@ void DeviceCommandMsgCondition::notificationReceived(interface::ObservercmdMsg; } else if (e2->cmdMsg.HasPath(msgPointer)) { - value = e2->cmdMsg.Get(msgPointer); + value = e2->cmdMsg.GetPath(msgPointer); } else { notify = false; } @@ -362,7 +362,15 @@ std::shared_ptr DeviceStateChangeConditionFactory::createCo throw std::runtime_error("Malformed JSON: property msgpointer is not an string."); } } - retval = std::make_shared(parent, deviceID, statePointer); + Variant fromValue; + if (raw.HasPath("fromvalue")) { + fromValue = raw["fromvalue"]; + } + Variant toValue; + if (raw.HasPath("tovalue")) { + toValue = raw["tovalue"]; + } + retval = std::make_shared(parent, deviceID, statePointer, fromValue, toValue); return retval; } @@ -378,13 +386,19 @@ void DeviceStateChangeCondition::notificationReceived(interface::ObservergetCurrentState(); last = device->getLastState(); } else if (device->getCurrentState().HasPath(msgPointer) && device->getLastState().HasPath(msgPointer)) { - current = device->getCurrentState().Get(msgPointer); - last = device->getLastState().Get(msgPointer); + current = device->getCurrentState().GetPath(msgPointer); + last = device->getLastState().GetPath(msgPointer); } else { notify = false; } - if (notify && current == last) { - notify = false; + if (notify) { + if (current == last) { + notify = false; + } else if (!fromValue.IsNull() && fromValue != last) { + notify = false; + } else if (!msgValue.IsNull() && msgValue != current) { + notify = false; + } } if (notify) { Variant lcontext; diff --git a/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/rule/RuleConditionImpl.h b/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/rule/RuleConditionImpl.h index 9a7383da..046c4e8e 100644 --- a/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/rule/RuleConditionImpl.h +++ b/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/rule/RuleConditionImpl.h @@ -115,9 +115,11 @@ public: class DeviceStateChangeCondition : public DeviceMsgCondition { +protected: + const Variant fromValue; public: - DeviceStateChangeCondition(Rule* parent, const std::string deviceID, const std::string statePointer) : - DeviceMsgCondition(parent, Category::Event, "devicestatechange", deviceID, statePointer, Variant()) {} + DeviceStateChangeCondition(Rule* parent, const std::string deviceID, const std::string statePointer, const Variant fromValue, const Variant toValue) : + DeviceMsgCondition(parent, Category::Event, "devicestatechange", deviceID, statePointer, toValue), fromValue(fromValue) {} virtual void notificationReceived(interface::Observer::observable_type* o, const devicerepository::DeviceEvent* e) override; }; diff --git a/src/hos_cosgi_ruleengine/test/rulepkg01.json b/src/hos_cosgi_ruleengine/test/rulepkg01.json index 5af327a6..422251f3 100644 --- a/src/hos_cosgi_ruleengine/test/rulepkg01.json +++ b/src/hos_cosgi_ruleengine/test/rulepkg01.json @@ -9,31 +9,19 @@ "conditions" : [ { "type": "devicestatusmsg", - "deviceid": "huelight3" - }, - { - "type": "devicestatechange", - "deviceid": "huelight4" + "deviceid": "dummySwitch0", + "msgpointer": "/switch/value", + "msgvalue": true } ] }, - "script": { "code": "global var2\nprint \"Hello World1: \" + str(var2)\nvar2 = var2 + 1\nimport __main__\nprint \"__main__.__dict__: \" + str(__main__.__dict__)\nprint \"test: \" + event_type\ndev1 = Devices.getDevice(\"huelight1\")\nprint \"device: \" + dev1.deviceID()" }, + "script": { "code": "global var2\nprint \"Hello World1: \" + str(var2)\nvar2 = var2 + 1\nimport __main__\nprint \"__main__.__dict__: \" + str(__main__.__dict__)\nprint \"event_type: \" + event_type\nprint \"devices: \" + str(Devices.keys())\nprint \"DeviceCount: \" + str(len(Devices))\nprint \"test: \" + str(Devices[\"dummySwitch1\"])" }, "exitscript": { "code": "print \"Hello from exitscript1\"" } }, "rule02": { "condition": { - "type": "logical_or", - "$schema": "hos:schema://core/configs/rulepackage#/definitions/LogicalOrCondition", - "conditions" : [ - { - "type": "devicecommandmsg", - "deviceid": "huelight4" - }, - { - "type": "devicestatechange", - "deviceid": "huelight3" - } - ] + "type": "devicestatechange", + "deviceid": "dummySwitch0" }, "script": { "code": "print \"Hello World2: \" + str(var2)\nvar2 = var2 + 1\nimport __main__\nprint \"__main__.__dict__: \" + str(__main__.__dict__)\nprint \"test: \" + event_type" }, "exitscript": { "code": "print \"Hello from exitscript2\"" } @@ -45,16 +33,42 @@ "conditions" : [ { "type": "devicecommandmsg", - "deviceid": "huelight1" - }, - { - "type": "devicestatechange", - "deviceid": "huelight2" + "deviceid": "dummySwitch0" } ] }, "script": { "code": "print \"Hello World3: \" + str(var2)\nvar2 = var2 + 1\nimport __main__\nprint \"__main__.__dict__: \" + str(__main__.__dict__)\nprint \"test: \" + event_type" }, "exitscript": { "code": "print \"Hello from exitscript2\"" } + }, + "rule04": { + "condition": { + "type": "logical_or", + "$schema": "hos:schema://core/configs/rulepackage#/definitions/LogicalOrCondition", + "conditions" : [ + { + "type": "devicestatechange", + "deviceid": "dummyDimmer0", + "msgpointer": "/dimmer/value", + "tovalue": 1.0 + } + ] + }, + "script": { "code": "print \"Dimmer 0 reached 100\"" } + }, + "rule05": { + "condition": { + "type": "logical_or", + "$schema": "hos:schema://core/configs/rulepackage#/definitions/LogicalOrCondition", + "conditions" : [ + { + "type": "devicestatechange", + "deviceid": "dummyDimmer0", + "msgpointer": "/dimmer", + "fromvalue": { "value": 1.0 } + } + ] + }, + "script": { "code": "print \"Dimmer 0 left 100\"" } } } } \ No newline at end of file diff --git a/src/hos_cosgi_scripting_python/CMakeLists.txt b/src/hos_cosgi_scripting_python/CMakeLists.txt index 9f2f3f48..146fb4c0 100644 --- a/src/hos_cosgi_scripting_python/CMakeLists.txt +++ b/src/hos_cosgi_scripting_python/CMakeLists.txt @@ -123,6 +123,7 @@ bundle(hos_cosgi_scripting_python SOURCES ${PROJECT_SOURCE_DIR}/src/bundle_activator ${PROJECT_SOURCE_DIR}/src/hos/cosgi/service/scripting/python/scripting_serviceimpl + ${PROJECT_SOURCE_DIR}/src/hos/cosgi/service/scripting/python/PyHOSAPI ) target_link_libraries(hos_cosgi_scripting_python ${catkin_LIBRARIES} diff --git a/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/PyHOSAPI.cpp b/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/PyHOSAPI.cpp new file mode 100644 index 00000000..f46083d8 --- /dev/null +++ b/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/PyHOSAPI.cpp @@ -0,0 +1,72 @@ +/* + * PyHOSAPI.cpp + * + * Created on: 19.05.2015 + * Author: matzman + */ + + + +#include "PyHOSAPI.h" +#include + + +namespace hos { +namespace cosgi { +namespace service { +namespace scripting { +namespace python { + + +BOOST_PYTHON_MODULE(hos) +{ + using namespace boost::python; + + class_("Device", no_init) + .def("deviceID", &PyDeviceWrapper::deviceID) ; + + class_("DeviceRepository", no_init) + .def("getDevice", &PyDeviceRepositoryWrapper::getDevice) + .def("__getitem__", &PyDeviceRepositoryWrapper::getDevice) + .def("__len__", &PyDeviceRepositoryWrapper::deviceCount) + .def("keys", &PyDeviceRepositoryWrapper::deviceIDs) ; +} + +boost::python::object convertVariantToBoostPython(Variant var) { + if (var.IsBool()) { + return boost::python::object(var.AsBool()); + } else if (var.IsFloat()) { + return boost::python::object(var.AsDouble()); + } else if (var.IsInt()) { + return boost::python::object(var.AsInt()); + } else if (var.IsString()) { + return boost::python::str(var.AsString()); + } else if (var.IsUnsigned()) { + return boost::python::object(var.AsUnsigned()); + } else if (var.IsList()) { + boost::python::list list; + for (auto e : var.AsList()) { + list.append(convertVariantToBoostPython(e)); + } + return list; + } else if (var.IsMap()) { + boost::python::dict map; + for (auto e : var.AsMap()) { + map[e.first] = convertVariantToBoostPython(e.second); + } + return map; + } else { + ROS_ERROR("Unknown Variant type encountered while converting to python"); + return boost::python::object(); + } +} + + + +} // namespace python +} // namespace scripting +} // namespace service +} // namespace cosgi +} // namespace hos + + diff --git a/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/PyHOSAPI.h b/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/PyHOSAPI.h new file mode 100644 index 00000000..11caf0d5 --- /dev/null +++ b/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/PyHOSAPI.h @@ -0,0 +1,71 @@ +/* + * PyHOSAPI.h + * + * Created on: 19.05.2015 + * Author: matzman + */ + +#ifndef SRC_HOS_COSGI_SERVICE_SCRIPTING_PYTHON_PYHOSAPI_H_ +#define SRC_HOS_COSGI_SERVICE_SCRIPTING_PYTHON_PYHOSAPI_H_ + +#include +#include +#include + + +namespace hos { +namespace cosgi { +namespace service { +namespace scripting { +namespace python { + +class PyScriptingService; + + +boost::python::object convertVariantToBoostPython(Variant var); + +class PyDeviceWrapper { +private: + devicerepository::Device* device; +public: + PyDeviceWrapper(devicerepository::Device* device) : device(device) {} + + std::string deviceID() { return device->getDeviceID(); } +}; + + +class PyDeviceRepositoryWrapper { +private: + devicerepository::DeviceRepositoryService* service; +public: + PyDeviceRepositoryWrapper(devicerepository::DeviceRepositoryService* service) : service(service) {} + + PyDeviceWrapper getDevice(std::string name) { + return PyDeviceWrapper(service->getDevice(name).get()); + } + + size_t deviceCount() { + return service->deviceCount(); + } + + boost::python::list deviceIDs() { + boost::python::list retval; + for (auto d : service->deviceIDs()) { + retval.append(d); + } + return retval; + } +}; + +extern "C" void inithos(); + + +} // namespace python +} // namespace scripting +} // namespace service +} // namespace cosgi +} // namespace hos + + + +#endif /* SRC_HOS_COSGI_SERVICE_SCRIPTING_PYTHON_PYHOSAPI_H_ */ diff --git a/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/scripting_serviceimpl.cpp b/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/scripting_serviceimpl.cpp index bb576a2d..96858a9a 100644 --- a/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/scripting_serviceimpl.cpp +++ b/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/scripting_serviceimpl.cpp @@ -6,6 +6,7 @@ */ #include "scripting_serviceimpl.h" +#include "PyHOSAPI.h" #include #include @@ -81,39 +82,6 @@ std::shared_ptr PyScriptingService::createScript(ser } -class PyDeviceWrapper { -private: - devicerepository::Device* device; -public: - PyDeviceWrapper(devicerepository::Device* device) : device(device) {} - - std::string deviceID() { return device->getDeviceID(); } -}; - - -class PyDeviceRepositoryWrapper { -private: - devicerepository::DeviceRepositoryService* service; -public: - PyDeviceRepositoryWrapper(devicerepository::DeviceRepositoryService* service) : service(service) {} - - PyDeviceWrapper getDevice(std::string name) { - return PyDeviceWrapper(service->getDevice(name).get()); - } -}; - - -BOOST_PYTHON_MODULE(hos) -{ - using namespace boost::python; - - class_("Device", no_init) - .def("deviceID", &PyDeviceWrapper::deviceID) ; - - class_("DeviceRepository", no_init) - .def("getDevice", &PyDeviceRepositoryWrapper::getDevice) ; -} - void PyScript::exec(service::scripting::GlobalScriptContext* gContext, Variant lContext) { @@ -141,36 +109,6 @@ void PyScript::exec(service::scripting::GlobalScriptContext* gContext, Variant l } -boost::python::object convertVariantToBoostPython(Variant var) { - if (var.IsBool()) { - return boost::python::object(var.AsBool()); - } else if (var.IsFloat()) { - return boost::python::object(var.AsDouble()); - } else if (var.IsInt()) { - return boost::python::object(var.AsInt()); - } else if (var.IsString()) { - return boost::python::str(var.AsString()); - } else if (var.IsUnsigned()) { - return boost::python::object(var.AsUnsigned()); - } else if (var.IsList()) { - boost::python::list list; - for (auto e : var.AsList()) { - list.append(convertVariantToBoostPython(e)); - } - return list; - } else if (var.IsMap()) { - boost::python::dict map; - for (auto e : var.AsMap()) { - map[e.first] = convertVariantToBoostPython(e.second); - } - return map; - } else { - ROS_ERROR("Unknown Variant type encountered while converting to python"); - return boost::python::object(); - } -} - - } // namespace python } // namespace ruleengine diff --git a/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/scripting_serviceimpl.h b/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/scripting_serviceimpl.h index db7a2907..2baef756 100644 --- a/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/scripting_serviceimpl.h +++ b/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/scripting_serviceimpl.h @@ -99,7 +99,6 @@ public: }; -boost::python::object convertVariantToBoostPython(Variant var); } // namespace python diff --git a/src/hos_dummy/CMakeLists.txt b/src/hos_dummy/CMakeLists.txt new file mode 100644 index 00000000..506f8913 --- /dev/null +++ b/src/hos_dummy/CMakeLists.txt @@ -0,0 +1,169 @@ +cmake_minimum_required(VERSION 2.8.3) +project(hos_dummy) + +## Find catkin macros and libraries +## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) +## is used, also find other catkin packages +find_package(catkin REQUIRED COMPONENTS + hos_core_msgs + hos_python_json + rospy +) + +## System dependencies are found with CMake's conventions +# find_package(Boost REQUIRED COMPONENTS system) + + +## Uncomment this if the package has a setup.py. This macro ensures +## modules and global scripts declared therein get installed +## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html +catkin_python_setup() + +################################################ +## Declare ROS messages, services and actions ## +################################################ + +## To declare and build messages, services or actions from within this +## package, follow these steps: +## * Let MSG_DEP_SET be the set of packages whose message types you use in +## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). +## * In the file package.xml: +## * add a build_depend and a run_depend tag for each package in MSG_DEP_SET +## * If MSG_DEP_SET isn't empty the following dependencies might have been +## pulled in transitively but can be declared for certainty nonetheless: +## * add a build_depend tag for "message_generation" +## * add a run_depend tag for "message_runtime" +## * In this file (CMakeLists.txt): +## * add "message_generation" and every package in MSG_DEP_SET to +## find_package(catkin REQUIRED COMPONENTS ...) +## * add "message_runtime" and every package in MSG_DEP_SET to +## catkin_package(CATKIN_DEPENDS ...) +## * uncomment the add_*_files sections below as needed +## and list every .msg/.srv/.action file to be processed +## * uncomment the generate_messages entry below +## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) + +## Generate messages in the 'msg' folder +# add_message_files( +# FILES +# Message1.msg +# Message2.msg +# ) + +## Generate services in the 'srv' folder +# add_service_files( +# FILES +# Service1.srv +# Service2.srv +# ) + +## Generate actions in the 'action' folder +# add_action_files( +# FILES +# Action1.action +# Action2.action +# ) + +## Generate added messages and services with any dependencies listed here +# generate_messages( +# DEPENDENCIES +# hos_core_msgs +# ) + +################################### +## catkin specific configuration ## +################################### +## The catkin_package macro generates cmake config files for your package +## Declare things to be passed to dependent projects +## INCLUDE_DIRS: uncomment this if you package contains header files +## LIBRARIES: libraries you create in this project that dependent projects also need +## CATKIN_DEPENDS: catkin_packages dependent projects also need +## DEPENDS: system dependencies of this project that dependent projects also need +catkin_package( +# INCLUDE_DIRS include +# LIBRARIES hos_dummy + CATKIN_DEPENDS hos_core_msgs hos_python_json rospy +# DEPENDS system_lib +) + +########### +## Build ## +########### + +## Specify additional locations of header files +## Your package locations should be listed before other locations +# include_directories(include) +include_directories( + ${catkin_INCLUDE_DIRS} +) + +## Declare a cpp library +# add_library(hos_dummy +# src/${PROJECT_NAME}/hos_dummy.cpp +# ) + +## Declare a cpp executable +# add_executable(hos_dummy_node src/hos_dummy_node.cpp) + +## Add cmake target dependencies of the executable/library +## as an example, message headers may need to be generated before nodes +# add_dependencies(hos_dummy_node hos_dummy_generate_messages_cpp) + +## Specify libraries to link a library or executable target against +# target_link_libraries(hos_dummy_node +# ${catkin_LIBRARIES} +# ) + +############# +## Install ## +############# + + +#And this will install python nodes +catkin_install_python(PROGRAMS + nodes/hos_dummy_devices.py + DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}) + +# all install targets should use catkin DESTINATION variables +# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html + +## Mark executable scripts (Python etc.) for installation +## in contrast to setup.py, you can choose the destination +# install(PROGRAMS +# scripts/my_python_script +# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +# ) + +## Mark executables and/or libraries for installation +# install(TARGETS hos_dummy hos_dummy_node +# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} +# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} +# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +# ) + +## Mark cpp header files for installation +# install(DIRECTORY include/${PROJECT_NAME}/ +# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} +# FILES_MATCHING PATTERN "*.h" +# PATTERN ".svn" EXCLUDE +# ) + +## Mark other files for installation (e.g. launch and bag files, etc.) +# install(FILES +# # myfile1 +# # myfile2 +# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} +# ) + +############# +## Testing ## +############# + +## Add gtest based cpp test target and link libraries +# catkin_add_gtest(${PROJECT_NAME}-test test/test_hos_dummy.cpp) +# if(TARGET ${PROJECT_NAME}-test) +# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) +# endif() + +## Add folders to be run by python nosetests +# catkin_add_nosetests(test) diff --git a/src/hos_dummy/nodes/hos_dummy_controller.py b/src/hos_dummy/nodes/hos_dummy_controller.py new file mode 100755 index 00000000..54a456ce --- /dev/null +++ b/src/hos_dummy/nodes/hos_dummy_controller.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import sys +import socket +import rospy +import traceback +from hos_core_msgs.msg import DeviceCommand +from hos_dummy.HosDummyController import HosDummyController + +import Tkinter as tk +import Tkconstants + + +if __name__ == '__main__': + try: + root = tk.Tk(); + app = HosDummyController(root) + root.geometry("+200+200") + app.master.title('HOS Dummy Controller') + + app.mainloop() + except socket.error as e: + print "Could not connect to master" + except Exception as inst: + print type(inst) # the exception instance + print inst # __str__ allows args to be printed directly + traceback.print_exc() diff --git a/src/hos_dummy/nodes/hos_dummy_devices.py b/src/hos_dummy/nodes/hos_dummy_devices.py new file mode 100755 index 00000000..b3e479d5 --- /dev/null +++ b/src/hos_dummy/nodes/hos_dummy_devices.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import sys +import socket +import rospy +import traceback +from hos_core_msgs.msg import DeviceCommand +from hos_dummy.HosDummyDevices import HosDummyDevices + +import Tkinter as tk +import Tkconstants + + +def deviceCmdCallback(data): + app.deviceCmdCallback(data) + +if __name__ == '__main__': + try: + root = tk.Tk(); + app = HosDummyDevices(root) + root.geometry("+200+200") + app.master.title('HOS Dummy Devices') + + rospy.Subscriber(app.cmd_topic, DeviceCommand, deviceCmdCallback) + + app.mainloop() + except socket.error as e: + print "Could not connect to master" + except Exception as inst: + print type(inst) # the exception instance + print inst # __str__ allows args to be printed directly + traceback.print_exc() diff --git a/src/hos_dummy/package.xml b/src/hos_dummy/package.xml new file mode 100644 index 00000000..da87f5f0 --- /dev/null +++ b/src/hos_dummy/package.xml @@ -0,0 +1,56 @@ + + + hos_dummy + 0.0.0 + The hos_dummy package + + + + + matzman + + + + + + TODO + + + + + + + + + + + + + + + + + + + + + + + + + + catkin + hos_core_msgs + hos_python_json + rospy + hos_core_msgs + hos_python_json + rospy + + + + + + + + \ No newline at end of file diff --git a/src/hos_dummy/python/hos_dummy/HosDummyController.py b/src/hos_dummy/python/hos_dummy/HosDummyController.py new file mode 100644 index 00000000..244ed0ef --- /dev/null +++ b/src/hos_dummy/python/hos_dummy/HosDummyController.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import sys +import rospy +import json +from hos_pyhue import pyhue +from hos_core_msgs.msg import DeviceCommand +from hos_core_msgs.msg import DeviceStatusUpdate +from hos_core_msgs.msg import HosStatusUpdate +from jsonspec_hos.reference.providers import HOSParamServerProvider +from jsonspec.validators import load +from time import sleep + +import Tkinter as tk +import Tkconstants + + +class HosDummyController(tk.Frame): + def __init__(self, master=None): + # Init ROS node + rospy.init_node('hos_dummy_controller', argv=sys.argv) + # Get ROS parameter + self.status_topic = rospy.get_param('~status_topic', "/hos/devices/status") + self.cmd_topic = rospy.get_param('~cmd_topic', "/hos/devices/cmd") + self.hos_update_topic = rospy.get_param('~hos_update_topic', "/hos/status/updates") + self.loop_frequency = rospy.get_param('~loop_frequency', 100) + self.statusmsg_interval = rospy.get_param('~statusmsg_interval', 6000000) + # Init Variables + self.msg_sequence = 0 + # Init devices + self.switches = dict() + self.dimmers = dict() + for i in range(4): + # switches + name = "dummySwitch" + str(i) + self.switches[i] = dict() + self.switches[i]["value"] = False + self.switches[i]["id"] = name + self.switches[i]["name"] = "Switch " + str(i) + key_base = "/hos/devices/repository/" + name + rospy.set_param(key_base + "/type", "core/devices/switch") + rospy.set_param(key_base + "/status_topic", self.status_topic) + rospy.set_param(key_base + "/cmd_topic", self.cmd_topic) + print "Added dummy switch \"" + name + "\"" + # dimmers + name = "dummyDimmer" + str(i) + self.dimmers[i] = dict() + self.dimmers[i]["value"] = 0.0 + self.dimmers[i]["id"] = name + self.dimmers[i]["name"] = "Dimmer " + str(i) + key_base = "/hos/devices/repository/" + name + rospy.set_param(key_base + "/type", "core/devices/switch") + rospy.set_param(key_base + "/status_topic", self.status_topic) + rospy.set_param(key_base + "/cmd_topic", self.cmd_topic) + print "Added dummy dimmer \"" + name + "\"" + # Create JSON schema provider + self.schemaProvider = HOSParamServerProvider() + # Create message publisher + self.commandPublisher = rospy.Publisher(self.cmd_topic, DeviceCommand, queue_size=10) + # Init GUI + tk.Frame.__init__(self, master, padx="10px", pady="10px") + self.grid() + self.createWidgets() + + + def createWidgets(self): + self.switchframe = tk.LabelFrame(self, text = "Switches", relief=Tkconstants.SUNKEN, bd=1) + self.switchframe.grid(column=0, row=0) + for i in range(4): + self.switches[i]["intvar"] = tk.IntVar(value=int(self.switches[i]["value"])) + self.switches[i]["checkbutton"] = tk.Checkbutton(self.switchframe, text=self.switches[i]["name"], variable = self.switches[i]["intvar"], onvalue = 1, offvalue = 0, height=5, width = 20, command=self.switchCallback) + self.switches[i]["checkbutton"].grid(column=0, row=i) + + self.dimmerframe = tk.LabelFrame(self, text = "Dimmers", relief=Tkconstants.SUNKEN, bd=1) + self.dimmerframe.grid(column=1, row=0) + for i in range(4): + self.dimmers[i]["doublevar"] = tk.DoubleVar(value=float(self.dimmers[i]["value"])) + self.dimmers[i]["label"] = tk.Label(self.dimmerframe, text=self.dimmers[i]["name"]) + self.dimmers[i]["label"].grid(column=0, row=i) + self.dimmers[i]["scale"] = tk.Scale( self.dimmerframe, variable = self.dimmers[i]["doublevar"], from_=0.0, to=100.0, command=self.scaleCallback) + self.dimmers[i]["scale"].grid(column=1, row=i) + + #self.quitButton = tk.Button(self, text='Quit', command=self.quit) + #self.quitButton.grid() + + + def createSwitchMsg(self, switch, seq, stamp): + msg = DeviceCommand() + msg.seq = seq + msg.device_id = switch["id"] + msg.device_type = "core/devices/switch" + msg.stamp = stamp + + msg_body = dict() + + msg_body["switch"] = dict() + msg_body["switch"]["set"] = switch["value"] + + msg_schema = self.schemaProvider.getTypeSchema("core/devices/switch/command") + validator = load(msg_schema, provider=self.schemaProvider) + + validator.validate(msg_body) + + msg.msg_body = json.dumps(msg_body) + return msg + + + def createDimmerMsg(self, dimmer, seq, stamp): + msg = DeviceCommand() + msg.seq = seq + msg.device_id = dimmer["id"] + msg.device_type = "core/devices/dimmer" + msg.stamp = stamp + + msg_body = dict() + + msg_body["dimmer"] = dict() + msg_body["dimmer"]["set"] = dimmer["value"]/100.0 + + msg_schema = self.schemaProvider.getTypeSchema("core/devices/dimmer/command") + validator = load(msg_schema, provider=self.schemaProvider) + validator.validate(msg_body) + + msg.msg_body = json.dumps(msg_body) + return msg + + + def scaleCallback(self, newvalue): + stamp = rospy.get_rostime() + for i in self.dimmers: + if (self.dimmers[i]["value"] != self.dimmers[i]["doublevar"].get()): + self.dimmers[i]["value"] = float(self.dimmers[i]["doublevar"].get()) + self.commandPublisher.publish(self.createDimmerMsg(self.dimmers[i], self.msg_sequence, stamp)) + self.msg_sequence += 1 + + + def switchCallback(self): + stamp = rospy.get_rostime() + for i in self.switches: + if (self.switches[i]["value"] != bool(self.switches[i]["intvar"].get())): + self.switches[i]["value"] = bool(self.switches[i]["intvar"].get()) + self.commandPublisher.publish(self.createSwitchMsg(self.switches[i], self.msg_sequence, stamp)) + self.msg_sequence += 1 diff --git a/src/hos_dummy/python/hos_dummy/HosDummyDevices.py b/src/hos_dummy/python/hos_dummy/HosDummyDevices.py new file mode 100644 index 00000000..fa5111e1 --- /dev/null +++ b/src/hos_dummy/python/hos_dummy/HosDummyDevices.py @@ -0,0 +1,206 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import sys +import rospy +import json +from hos_pyhue import pyhue +from hos_core_msgs.msg import DeviceCommand +from hos_core_msgs.msg import DeviceStatusUpdate +from hos_core_msgs.msg import HosStatusUpdate +from jsonspec_hos.reference.providers import HOSParamServerProvider +from jsonspec.validators import load +from time import sleep + +import Tkinter as tk +import Tkconstants + + +class HosDummyDevices(tk.Frame): + def __init__(self, master=None): + # Init ROS node + rospy.init_node('hos_dummy_devices', argv=sys.argv) + # Get ROS parameter + self.status_topic = rospy.get_param('~status_topic', "/hos/devices/status") + self.cmd_topic = rospy.get_param('~cmd_topic', "/hos/devices/cmd") + self.hos_update_topic = rospy.get_param('~hos_update_topic', "/hos/status/updates") + self.loop_frequency = rospy.get_param('~loop_frequency', 100) + self.statusmsg_interval = rospy.get_param('~statusmsg_interval', 6000000) + # Init Variables + self.msg_sequence = 0 + # Init devices + new_devices = list() + self.switches = dict() + self.dimmers = dict() + for i in range(4): + # switches + name = "dummySwitch" + str(i) + self.switches[i] = dict() + self.switches[i]["value"] = False + self.switches[i]["id"] = name + self.switches[i]["name"] = "Switch " + str(i) + key_base = "/hos/devices/repository/" + name + rospy.set_param(key_base + "/type", "core/devices/switch") + rospy.set_param(key_base + "/status_topic", self.status_topic) + rospy.set_param(key_base + "/cmd_topic", self.cmd_topic) + print "Added dummy switch \"" + name + "\"" + new_devices.append(name) + # dimmers + name = "dummyDimmer" + str(i) + self.dimmers[i] = dict() + self.dimmers[i]["value"] = 0.0 + self.dimmers[i]["id"] = name + self.dimmers[i]["name"] = "Dimmer " + str(i) + key_base = "/hos/devices/repository/" + name + rospy.set_param(key_base + "/type", "core/devices/switch") + rospy.set_param(key_base + "/status_topic", self.status_topic) + rospy.set_param(key_base + "/cmd_topic", self.cmd_topic) + print "Added dummy dimmer \"" + name + "\"" + new_devices.append(name) + # Create JSON schema provider + self.schemaProvider = HOSParamServerProvider() + # Create message publisher + self.statusPublisher = rospy.Publisher(self.status_topic, DeviceStatusUpdate, queue_size=10) + self.hosUpdatePublisher = rospy.Publisher(self.hos_update_topic, HosStatusUpdate, queue_size=10) + # Send HOS Status Update Message + updMsg = HosStatusUpdate() + stamp = rospy.get_rostime() + updMsg.stamp = stamp + updMsg.tags.append("devices") + updBody = dict() + updBody["type"] = "core/msgs/hosstatusupdate" + updBody["devices"] = dict() + updBody["devices"]["type"] = "core/msgs/hosstatusupdate/devices"; + updBody["devices"]["added"] = new_devices + + msg_schema = self.schemaProvider.getTypeSchema("core/msgs/hosstatusupdate") + validator = load(msg_schema, provider=self.schemaProvider) + validator.validate(updBody) + + updMsg.msg_body = json.dumps(updBody) + sleep(1) # Apparently we need to wait before we can send messages + self.hosUpdatePublisher.publish(updMsg) + + # Init GUI + tk.Frame.__init__(self, master, padx="10px", pady="10px") + self.grid() + self.createWidgets() + + self.deviceStatusCallback() + + + def createWidgets(self): + self.switchframe = tk.LabelFrame(self, text = "Switches", relief=Tkconstants.SUNKEN, bd=1) + self.switchframe.grid(column=0, row=0) + for i in range(4): + self.switches[i]["stringvar"] = tk.StringVar(value=str(self.switches[i]["value"])) + self.switches[i]["label1"] = tk.Label(self.switchframe, text=self.switches[i]["name"]) + self.switches[i]["label1"].grid(column=0, row=i) + self.switches[i]["label2"] = tk.Label(self.switchframe, textvariable=self.switches[i]["stringvar"], relief=Tkconstants.GROOVE, width = 4) + self.switches[i]["label2"].grid(column=1, row=i) + + self.dimmerframe = tk.LabelFrame(self, text = "Dimmers", relief=Tkconstants.SUNKEN, bd=1) + self.dimmerframe.grid(column=1, row=0) + for i in range(4): + self.dimmers[i]["stringvar"] = tk.StringVar(value=str(self.dimmers[i]["value"])) + self.dimmers[i]["label1"] = tk.Label(self.dimmerframe, text=self.dimmers[i]["name"]) + self.dimmers[i]["label1"].grid(column=0, row=i) + self.dimmers[i]["label2"] = tk.Label(self.dimmerframe, textvariable=self.dimmers[i]["stringvar"], relief=Tkconstants.GROOVE, width = 4) + self.dimmers[i]["label2"].grid(column=1, row=i) + + #self.quitButton = tk.Button(self, text='Quit', command=self.quit) + #self.quitButton.grid() + + + def createSwitchMsg(self, switch, seq, stamp): + msg = DeviceStatusUpdate() + msg.seq = seq + msg.device_id = switch["id"] + msg.device_type = "core/devices/switch" + msg.stamp = stamp + + msg_body = dict() + + msg_body["switch"] = dict() + msg_body["switch"]["value"] = switch["value"] + + msg_schema = self.schemaProvider.getTypeSchema("core/devices/switch/status") + validator = load(msg_schema, provider=self.schemaProvider) + + validator.validate(msg_body) + + msg.msg_body = json.dumps(msg_body) + return msg + + + def createDimmerMsg(self, dimmer, seq, stamp): + msg = DeviceStatusUpdate() + msg.seq = seq + msg.device_id = dimmer["id"] + msg.device_type = "core/devices/dimmer" + msg.stamp = stamp + + msg_body = dict() + + msg_body["dimmer"] = dict() + msg_body["dimmer"]["value"] = dimmer["value"] + + msg_schema = self.schemaProvider.getTypeSchema("core/devices/dimmer/status") + validator = load(msg_schema, provider=self.schemaProvider) + validator.validate(msg_body) + + msg.msg_body = json.dumps(msg_body) + return msg + + + def deviceStatusCallback(self): + stamp = rospy.get_rostime() + for switch in self.switches: + self.statusPublisher.publish(self.createSwitchMsg(self.switches[switch], self.msg_sequence, stamp)) + for dimmer in self.dimmers: + self.statusPublisher.publish(self.createDimmerMsg(self.dimmers[dimmer], self.msg_sequence, stamp)) + self.msg_sequence += 1 + self.after(10000, self.deviceStatusCallback) + + + def deviceCmdCallback(self, data): + rospy.loginfo(rospy.get_caller_id() + ": I heard %s", str(data)) + for i in self.switches: + if self.switches[i]["id"] == data.device_id: + self.deviceSwitchCmdCallback(self.switches[i], data) + return + for i in self.dimmers: + if self.dimmers[i]["id"] == data.device_id: + self.deviceDimmerCmdCallback(self.dimmers[i], data) + return + + + def deviceSwitchCmdCallback(self, switch, data): + msg_body = json.loads(data.msg_body) + msg_schema = self.schemaProvider.getTypeSchema("core/devices/switch/command") + validator = load(msg_schema, provider=self.schemaProvider) + validator.validate(msg_body) + + value = msg_body["switch"]["set"] + switch["value"] = bool(value) + switch["stringvar"].set(str(value)) + + stamp = rospy.get_rostime() + self.statusPublisher.publish(self.createSwitchMsg(switch, self.msg_sequence, stamp)) + self.msg_sequence += 1 + + + def deviceDimmerCmdCallback(self, dimmer, data): + print + msg_body = json.loads(data.msg_body) + msg_schema = self.schemaProvider.getTypeSchema("core/devices/dimmer/command") + validator = load(msg_schema, provider=self.schemaProvider) + validator.validate(msg_body) + value = msg_body["dimmer"]["set"] + dimmer["value"] = float(value) + dimmer["stringvar"].set(value) + + stamp = rospy.get_rostime() + self.statusPublisher.publish(self.createDimmerMsg(dimmer, self.msg_sequence, stamp)) + self.msg_sequence += 1 + diff --git a/src/hos_dummy/python/hos_dummy/__init__.py b/src/hos_dummy/python/hos_dummy/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/hos_dummy/setup.py b/src/hos_dummy/setup.py new file mode 100644 index 00000000..a7fc4568 --- /dev/null +++ b/src/hos_dummy/setup.py @@ -0,0 +1,11 @@ + #!/usr/bin/env python + +from distutils.core import setup +from catkin_pkg.python_setup import generate_distutils_setup + +package_info = generate_distutils_setup( + packages=['hos_dummy'], + package_dir={'': 'python'}, +) + +setup(**package_info) diff --git a/src/hos_philips_hue/nodes/hue_bridge_node.py b/src/hos_philips_hue/nodes/hue_bridge_node.py index 88a014c6..2bf23c1e 100755 --- a/src/hos_philips_hue/nodes/hue_bridge_node.py +++ b/src/hos_philips_hue/nodes/hue_bridge_node.py @@ -10,13 +10,13 @@ from hos_core_msgs.msg import DeviceCommand from hos_huecontroller.huecontroller import HueController -controller = HueController() def deviceCmdCallback(data): controller.deviceCmdCallback(data) if __name__ == '__main__': try: + controller = HueController() rospy.Subscriber(controller.cmd_topic, DeviceCommand, deviceCmdCallback) controller.mainLoop() except socket.error as e: diff --git a/src/hos_philips_hue/nodes/schema.json b/src/hos_philips_hue/nodes/schema.json deleted file mode 100644 index c0317123..00000000 --- a/src/hos_philips_hue/nodes/schema.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Color Capability", - "description": "", - "type": "object", - "properties": { - "colormode": { - "description": "", - "type": "string", - "persistent": "True", - "volatile": "False" - }, - "prop1": { - "$ref" : "hos:schema://core/capabilities/switch/command#" - } - }, - "test" : "bla", - "persistent": ["bla1", "bla2"] -}