First working sitemap version.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
PYTHON_PATH=/opt/ros/indigo/lib/python2.7/dist-packages
|
PYTHON_PATH=/home/matzman/tmp/ros_catkin_ws/install_isolated/lib/python2.7/dist-packages
|
||||||
|
|
||||||
# delete old files
|
# delete old files
|
||||||
rm -rf devel devel_isolated build build_isolated install install_isolated
|
rm -rf devel devel_isolated build build_isolated install install_isolated
|
||||||
|
|||||||
-1
@@ -62,7 +62,6 @@ void DeviceImpl::handleCommandMsg(const Variant& msg, const timestamp_t& stamp)
|
|||||||
|
|
||||||
|
|
||||||
void DeviceImpl::sendCommand(const Variant& cmd) {
|
void DeviceImpl::sendCommand(const Variant& cmd) {
|
||||||
std::lock_guard<std::recursive_mutex> lock(objMutex);
|
|
||||||
parent->sendDeviceCommand(this, cmd);
|
parent->sendDeviceCommand(this, cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,40 +1,291 @@
|
|||||||
{
|
{
|
||||||
"type": "sitemap/sitemap_template",
|
"type": "sitemap/sitemap_template",
|
||||||
"title": "TestApp",
|
"title": "TestApp",
|
||||||
"rootpage": {
|
"rootpage": "page01",
|
||||||
"type": "sitemap/sitemap_template#/definitions/page",
|
"pages": {
|
||||||
"title": "Root Page",
|
"page01": {
|
||||||
"elements": [
|
"type": "sitemap/sitemap_template#/definitions/page",
|
||||||
{
|
"title": "Root Page",
|
||||||
"type": "sitemap/sitemap_template#/definitions/text_element",
|
"elements": [
|
||||||
"label": "Switch0 Text",
|
{
|
||||||
"icon" : "some_icon01",
|
"type": "sitemap/sitemap_template#/definitions/frame_element",
|
||||||
"format" : "Format: %1%",
|
"label": "Group 0",
|
||||||
"device": {
|
"icon" : "some_icon01",
|
||||||
"id": "dummySwitch0",
|
"elements" : [
|
||||||
"pointer": "/switch/value"
|
{
|
||||||
}
|
"type": "sitemap/sitemap_template#/definitions/text_element",
|
||||||
}, {
|
"label": "Switch0",
|
||||||
"type": "sitemap/sitemap_template#/definitions/switch_element",
|
"icon" : "some_icon01",
|
||||||
"label": "Switch0",
|
"format" : "Value: %1%",
|
||||||
"icon" : "some_icon02",
|
"linkedPage" : "page02",
|
||||||
"format" : "bla: %1%",
|
"device": {
|
||||||
"device": {
|
"id": "dummySwitch0",
|
||||||
"id": "dummySwitch0",
|
"pointer": "/switch/value"
|
||||||
"pointer": "/switch/value"
|
}
|
||||||
}
|
}, {
|
||||||
}, {
|
"type": "sitemap/sitemap_template#/definitions/switch_element",
|
||||||
"type": "sitemap/sitemap_template#/definitions/slider_element",
|
"label": "Switch0",
|
||||||
"label": "Slider0",
|
"icon" : "some_icon02",
|
||||||
"icon" : "some_icon03",
|
"linkedPage" : "page02",
|
||||||
"device": {
|
"device": {
|
||||||
"id": "dummyDimmer0",
|
"id": "dummySwitch0",
|
||||||
"pointer": "/dimmer/value"
|
"pointer": "/switch/value"
|
||||||
|
},
|
||||||
|
"commandTemplate": {
|
||||||
|
"switch": {
|
||||||
|
"set": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandValuePointer": "/switch/set"
|
||||||
|
}, {
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/text_element",
|
||||||
|
"label": "Slider0",
|
||||||
|
"icon" : "some_icon01",
|
||||||
|
"format" : "Value: %1%",
|
||||||
|
"device": {
|
||||||
|
"id": "dummyDimmer0",
|
||||||
|
"pointer": "/dimmer/value"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/slider_element",
|
||||||
|
"label": "Slider0",
|
||||||
|
"icon" : "some_icon03",
|
||||||
|
"device": {
|
||||||
|
"id": "dummyDimmer0",
|
||||||
|
"pointer": "/dimmer/value"
|
||||||
|
},
|
||||||
|
"min": 0,
|
||||||
|
"max": 1,
|
||||||
|
"step": 0.1,
|
||||||
|
"commandTemplate": {
|
||||||
|
"dimmer": {
|
||||||
|
"set": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandValuePointer": "/dimmer/set"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"min": 0,
|
{
|
||||||
"max": 1,
|
"type": "sitemap/sitemap_template#/definitions/frame_element",
|
||||||
"step": 0.1
|
"label": "Group 1",
|
||||||
}
|
"icon" : "some_icon01",
|
||||||
]
|
"elements" : [
|
||||||
|
{
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/text_element",
|
||||||
|
"label": "Switch1",
|
||||||
|
"icon" : "some_icon01",
|
||||||
|
"format" : "Value: %1%",
|
||||||
|
"device": {
|
||||||
|
"id": "dummySwitch1",
|
||||||
|
"pointer": "/switch/value"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/switch_element",
|
||||||
|
"label": "Switch1",
|
||||||
|
"icon" : "some_icon02",
|
||||||
|
"device": {
|
||||||
|
"id": "dummySwitch1",
|
||||||
|
"pointer": "/switch/value"
|
||||||
|
},
|
||||||
|
"commandTemplate": {
|
||||||
|
"switch": {
|
||||||
|
"set": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandValuePointer": "/switch/set"
|
||||||
|
}, {
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/text_element",
|
||||||
|
"label": "Slider1",
|
||||||
|
"icon" : "some_icon01",
|
||||||
|
"format" : "Value: %1%",
|
||||||
|
"device": {
|
||||||
|
"id": "dummyDimmer1",
|
||||||
|
"pointer": "/dimmer/value"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/slider_element",
|
||||||
|
"label": "Slider1",
|
||||||
|
"icon" : "some_icon03",
|
||||||
|
"device": {
|
||||||
|
"id": "dummyDimmer1",
|
||||||
|
"pointer": "/dimmer/value"
|
||||||
|
},
|
||||||
|
"min": 0,
|
||||||
|
"max": 1,
|
||||||
|
"step": 0.1,
|
||||||
|
"commandTemplate": {
|
||||||
|
"dimmer": {
|
||||||
|
"set": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandValuePointer": "/dimmer/set"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/frame_element",
|
||||||
|
"label": "Group 2",
|
||||||
|
"icon" : "some_icon01",
|
||||||
|
"elements" : [
|
||||||
|
{
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/text_element",
|
||||||
|
"label": "Switch2",
|
||||||
|
"icon" : "some_icon01",
|
||||||
|
"format" : "Value: %1%",
|
||||||
|
"device": {
|
||||||
|
"id": "dummySwitch2",
|
||||||
|
"pointer": "/switch/value"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/switch_element",
|
||||||
|
"label": "Switch2",
|
||||||
|
"icon" : "some_icon02",
|
||||||
|
"device": {
|
||||||
|
"id": "dummySwitch2",
|
||||||
|
"pointer": "/switch/value"
|
||||||
|
},
|
||||||
|
"commandTemplate": {
|
||||||
|
"switch": {
|
||||||
|
"set": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandValuePointer": "/switch/set"
|
||||||
|
}, {
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/text_element",
|
||||||
|
"label": "Slider2",
|
||||||
|
"icon" : "some_icon01",
|
||||||
|
"format" : "Value: %1%",
|
||||||
|
"device": {
|
||||||
|
"id": "dummyDimmer2",
|
||||||
|
"pointer": "/dimmer/value"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/slider_element",
|
||||||
|
"label": "Slider2",
|
||||||
|
"icon" : "some_icon03",
|
||||||
|
"device": {
|
||||||
|
"id": "dummyDimmer2",
|
||||||
|
"pointer": "/dimmer/value"
|
||||||
|
},
|
||||||
|
"min": 0,
|
||||||
|
"max": 1,
|
||||||
|
"step": 0.1,
|
||||||
|
"commandTemplate": {
|
||||||
|
"dimmer": {
|
||||||
|
"set": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandValuePointer": "/dimmer/set"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/frame_element",
|
||||||
|
"label": "Group 3",
|
||||||
|
"icon" : "some_icon01",
|
||||||
|
"elements" : [
|
||||||
|
{
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/text_element",
|
||||||
|
"label": "Switch3",
|
||||||
|
"icon" : "some_icon01",
|
||||||
|
"format" : "Value: %1%",
|
||||||
|
"device": {
|
||||||
|
"id": "dummySwitch3",
|
||||||
|
"pointer": "/switch/value"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/switch_element",
|
||||||
|
"label": "Switch3",
|
||||||
|
"icon" : "some_icon02",
|
||||||
|
"device": {
|
||||||
|
"id": "dummySwitch3",
|
||||||
|
"pointer": "/switch/value"
|
||||||
|
},
|
||||||
|
"commandTemplate": {
|
||||||
|
"switch": {
|
||||||
|
"set": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandValuePointer": "/switch/set"
|
||||||
|
}, {
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/text_element",
|
||||||
|
"label": "Slider3",
|
||||||
|
"icon" : "some_icon01",
|
||||||
|
"format" : "Value: %1%",
|
||||||
|
"device": {
|
||||||
|
"id": "dummyDimmer3",
|
||||||
|
"pointer": "/dimmer/value"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/slider_element",
|
||||||
|
"label": "Slider3",
|
||||||
|
"icon" : "some_icon03",
|
||||||
|
"device": {
|
||||||
|
"id": "dummyDimmer3",
|
||||||
|
"pointer": "/dimmer/value"
|
||||||
|
},
|
||||||
|
"min": 0,
|
||||||
|
"max": 1,
|
||||||
|
"step": 0.1,
|
||||||
|
"commandTemplate": {
|
||||||
|
"dimmer": {
|
||||||
|
"set": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandValuePointer": "/dimmer/set"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"page02": {
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/page",
|
||||||
|
"title": "Page 2",
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/frame_element",
|
||||||
|
"label": "Some Text",
|
||||||
|
"icon" : "some_icon01",
|
||||||
|
"elements" : [
|
||||||
|
{
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/text_element",
|
||||||
|
"label": "Switch0 Text",
|
||||||
|
"icon" : "some_icon01",
|
||||||
|
"format" : "blabla: %1%",
|
||||||
|
"device": {
|
||||||
|
"id": "dummyDimmer1",
|
||||||
|
"pointer": "/dimmer/value"
|
||||||
|
},
|
||||||
|
"linkedPage" : "page03"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"page03": {
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/page",
|
||||||
|
"title": "Page 3",
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/frame_element",
|
||||||
|
"label": "Some Text 2",
|
||||||
|
"icon" : "some_icon01",
|
||||||
|
"elements" : [
|
||||||
|
{
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/text_element",
|
||||||
|
"label": "Switch2 Text",
|
||||||
|
"icon" : "some_icon01",
|
||||||
|
"format" : "blabla: %1%",
|
||||||
|
"device": {
|
||||||
|
"id": "dummyDimmer3",
|
||||||
|
"pointer": "/dimmer/value"
|
||||||
|
},
|
||||||
|
"linkedPage" : "page01"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,166 @@
|
|||||||
|
{
|
||||||
|
"type": "sitemap/sitemap_template",
|
||||||
|
"title": "Hue Lights App",
|
||||||
|
"rootpage": "page01",
|
||||||
|
"pages": {
|
||||||
|
"page01": {
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/page",
|
||||||
|
"title": "My Room",
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/frame_element",
|
||||||
|
"label": "Lightstrips 1",
|
||||||
|
"icon" : "some_icon01",
|
||||||
|
"elements" : [
|
||||||
|
{
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/switch_element",
|
||||||
|
"label": "Lightstrips 1 Switch",
|
||||||
|
"icon" : "some_icon02",
|
||||||
|
"device": {
|
||||||
|
"id": "huelight1",
|
||||||
|
"pointer": "/switch/value"
|
||||||
|
},
|
||||||
|
"commandTemplate": {
|
||||||
|
"switch": {
|
||||||
|
"set": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandValuePointer": "/switch/set"
|
||||||
|
}, {
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/slider_element",
|
||||||
|
"label": "Lightstrips 1 Slider",
|
||||||
|
"icon" : "some_icon03",
|
||||||
|
"device": {
|
||||||
|
"id": "huelight1",
|
||||||
|
"pointer": "/brightness/value"
|
||||||
|
},
|
||||||
|
"min": 0,
|
||||||
|
"max": 1,
|
||||||
|
"step": 0.1,
|
||||||
|
"commandTemplate": {
|
||||||
|
"brightness": {
|
||||||
|
"set": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandValuePointer": "/brightness/set"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/frame_element",
|
||||||
|
"label": "Lightstrips 2",
|
||||||
|
"icon" : "some_icon01",
|
||||||
|
"elements" : [
|
||||||
|
{
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/switch_element",
|
||||||
|
"label": "Lightstrips 2 Switch",
|
||||||
|
"icon" : "some_icon02",
|
||||||
|
"device": {
|
||||||
|
"id": "huelight2",
|
||||||
|
"pointer": "/switch/value"
|
||||||
|
},
|
||||||
|
"commandTemplate": {
|
||||||
|
"switch": {
|
||||||
|
"set": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandValuePointer": "/switch/set"
|
||||||
|
}, {
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/slider_element",
|
||||||
|
"label": "Lightstrips 2 Slider",
|
||||||
|
"icon" : "some_icon03",
|
||||||
|
"device": {
|
||||||
|
"id": "huelight2",
|
||||||
|
"pointer": "/brightness/value"
|
||||||
|
},
|
||||||
|
"min": 0,
|
||||||
|
"max": 1,
|
||||||
|
"step": 0.1,
|
||||||
|
"commandTemplate": {
|
||||||
|
"brightness": {
|
||||||
|
"set": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandValuePointer": "/brightness/set"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/frame_element",
|
||||||
|
"label": "ZimmerLampe",
|
||||||
|
"icon" : "some_icon01",
|
||||||
|
"elements" : [
|
||||||
|
{
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/switch_element",
|
||||||
|
"label": "ZimmerLampe Switch",
|
||||||
|
"icon" : "some_icon02",
|
||||||
|
"device": {
|
||||||
|
"id": "huelight3",
|
||||||
|
"pointer": "/switch/value"
|
||||||
|
},
|
||||||
|
"commandTemplate": {
|
||||||
|
"switch": {
|
||||||
|
"set": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandValuePointer": "/switch/set"
|
||||||
|
}, {
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/slider_element",
|
||||||
|
"label": "ZimmerLampe Slider",
|
||||||
|
"icon" : "some_icon03",
|
||||||
|
"device": {
|
||||||
|
"id": "huelight3",
|
||||||
|
"pointer": "/brightness/value"
|
||||||
|
},
|
||||||
|
"min": 0,
|
||||||
|
"max": 1,
|
||||||
|
"step": 0.1,
|
||||||
|
"commandTemplate": {
|
||||||
|
"brightness": {
|
||||||
|
"set": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandValuePointer": "/brightness/set"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/frame_element",
|
||||||
|
"label": "TischLampe",
|
||||||
|
"icon" : "some_icon01",
|
||||||
|
"elements" : [
|
||||||
|
{
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/switch_element",
|
||||||
|
"label": "TischLampe Switch",
|
||||||
|
"icon" : "some_icon02",
|
||||||
|
"device": {
|
||||||
|
"id": "huelight4",
|
||||||
|
"pointer": "/switch/value"
|
||||||
|
},
|
||||||
|
"commandTemplate": {
|
||||||
|
"switch": {
|
||||||
|
"set": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandValuePointer": "/switch/set"
|
||||||
|
}, {
|
||||||
|
"type": "sitemap/sitemap_template#/definitions/slider_element",
|
||||||
|
"label": "TischLampe Slider",
|
||||||
|
"icon" : "some_icon03",
|
||||||
|
"device": {
|
||||||
|
"id": "huelight4",
|
||||||
|
"pointer": "/brightness/value"
|
||||||
|
},
|
||||||
|
"min": 0,
|
||||||
|
"max": 1,
|
||||||
|
"step": 0.1,
|
||||||
|
"commandTemplate": {
|
||||||
|
"brightness": {
|
||||||
|
"set": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandValuePointer": "/brightness/set"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
@@ -59,6 +59,8 @@ public:
|
|||||||
virtual std::map<std::string, std::weak_ptr<sitemaptemplate::SitemapTemplate>> getSitemaps() noexcept = 0;
|
virtual std::map<std::string, std::weak_ptr<sitemaptemplate::SitemapTemplate>> getSitemaps() noexcept = 0;
|
||||||
virtual std::vector<std::string> getSitemapNames() noexcept = 0;
|
virtual std::vector<std::string> getSitemapNames() noexcept = 0;
|
||||||
|
|
||||||
|
virtual std::weak_ptr<sitemaptemplate::SitemapTemplate> getDefaultSitemap() noexcept = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+65
-4
@@ -20,20 +20,78 @@ class SitemapService;
|
|||||||
|
|
||||||
namespace sitemaptemplate {
|
namespace sitemaptemplate {
|
||||||
|
|
||||||
|
class SitemapTemplate;
|
||||||
class Page;
|
class Page;
|
||||||
class Element;
|
class Element;
|
||||||
class AtomicElement;
|
class AtomicElement;
|
||||||
class CompositeElement;
|
class CompositeElement;
|
||||||
class Device;
|
class Device;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sitemap event type.
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
enum class SitemapEventType : int {
|
||||||
|
ALL_EVENTS = 1,
|
||||||
|
SITEMAP_ELEMENT_CHANGED = 2,
|
||||||
|
SITEMAP_INVALIDATED = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for sitemap events.
|
||||||
|
*/
|
||||||
|
class SitemapEvent {
|
||||||
|
public:
|
||||||
|
typedef std::chrono::system_clock::time_point timestamp_t;
|
||||||
|
|
||||||
|
SitemapEventType eventType;
|
||||||
|
|
||||||
|
SitemapTemplate* const sitemap;
|
||||||
|
|
||||||
|
const timestamp_t timestamp;
|
||||||
|
|
||||||
|
SitemapEvent(SitemapTemplate* sitemap, const SitemapEventType& type, const timestamp_t& timestamp)
|
||||||
|
: eventType(type), sitemap(sitemap), timestamp(timestamp) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sitemap element changed event.
|
||||||
|
*/
|
||||||
|
class SitemapElementChangedEvent
|
||||||
|
: public SitemapEvent {
|
||||||
|
public:
|
||||||
|
std::vector<std::weak_ptr<Element>> elements;
|
||||||
|
|
||||||
|
SitemapElementChangedEvent(SitemapTemplate* sitemap, const timestamp_t& timestamp)
|
||||||
|
: SitemapEvent(sitemap,SitemapEventType::SITEMAP_ELEMENT_CHANGED, timestamp) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sitemap invalidated event.
|
||||||
|
*/
|
||||||
|
class SitemapInvalidatedEvent
|
||||||
|
: public SitemapEvent {
|
||||||
|
public:
|
||||||
|
SitemapInvalidatedEvent(SitemapTemplate* sitemap, const timestamp_t& timestamp)
|
||||||
|
: SitemapEvent(sitemap,SitemapEventType::SITEMAP_INVALIDATED, timestamp) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class SitemapTemplate
|
class SitemapTemplate
|
||||||
: public virtual interface::Object {
|
: public virtual interface::Observer<devicerepository::DeviceEventType, devicerepository::DeviceEvent>,
|
||||||
|
public virtual interface::ObservableObject<SitemapEventType, SitemapEvent> {
|
||||||
public:
|
public:
|
||||||
virtual SitemapService* getParent() noexcept = 0;
|
virtual SitemapService* getParent() noexcept = 0;
|
||||||
|
virtual size_t pageCount() noexcept = 0;
|
||||||
|
virtual std::weak_ptr<Page> getPage(const std::string& name) noexcept = 0;
|
||||||
|
virtual std::vector<std::weak_ptr<Page>> getPages(const std::string& name) noexcept = 0;
|
||||||
virtual std::weak_ptr<Page> getRootPage() noexcept = 0;
|
virtual std::weak_ptr<Page> getRootPage() noexcept = 0;
|
||||||
|
virtual const std::string& getRootPageName() noexcept = 0;
|
||||||
|
virtual std::weak_ptr<Element> getPageElement(size_t& uid) noexcept = 0;
|
||||||
|
|
||||||
|
virtual const std::string& getName() noexcept = 0;
|
||||||
|
|
||||||
virtual libvariant::Variant renderSitemap() = 0;
|
virtual libvariant::Variant renderSitemap() = 0;
|
||||||
};
|
};
|
||||||
@@ -44,7 +102,7 @@ class Page
|
|||||||
: public virtual interface::Object {
|
: public virtual interface::Object {
|
||||||
public:
|
public:
|
||||||
virtual SitemapTemplate* getSiteMap() noexcept = 0;
|
virtual SitemapTemplate* getSiteMap() noexcept = 0;
|
||||||
virtual Page* getParent() noexcept = 0;
|
virtual const std::string& getName() noexcept = 0;
|
||||||
|
|
||||||
virtual size_t elementCount() noexcept = 0;
|
virtual size_t elementCount() noexcept = 0;
|
||||||
virtual std::weak_ptr<Element> getElement(size_t index) noexcept = 0;
|
virtual std::weak_ptr<Element> getElement(size_t index) noexcept = 0;
|
||||||
@@ -99,7 +157,8 @@ public:
|
|||||||
virtual const std::string& getFormat() noexcept = 0;
|
virtual const std::string& getFormat() noexcept = 0;
|
||||||
virtual std::weak_ptr<Device> getDevice() noexcept = 0;
|
virtual std::weak_ptr<Device> getDevice() noexcept = 0;
|
||||||
virtual const libvariant::Variant& getAdditionalParams() noexcept = 0;
|
virtual const libvariant::Variant& getAdditionalParams() noexcept = 0;
|
||||||
virtual std::weak_ptr<Page> getLinkedToPage() noexcept = 0;
|
virtual std::weak_ptr<Page> getLinkedPage() noexcept = 0;
|
||||||
|
virtual const std::string& getLinkedPageName() noexcept = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -107,10 +166,12 @@ public:
|
|||||||
class Device
|
class Device
|
||||||
: public virtual interface::Object {
|
: public virtual interface::Object {
|
||||||
public:
|
public:
|
||||||
|
virtual std::weak_ptr<Element> getParent() noexcept = 0;
|
||||||
virtual const std::string& getDeviceID() noexcept = 0;
|
virtual const std::string& getDeviceID() noexcept = 0;
|
||||||
virtual std::weak_ptr<devicerepository::Device> getDevice() noexcept = 0;
|
virtual std::weak_ptr<devicerepository::Device> getDevice() noexcept = 0;
|
||||||
virtual const std::string& getPointer() noexcept = 0;
|
virtual const std::string& getPointer() noexcept = 0;
|
||||||
virtual bool deviceExists() noexcept = 0;
|
virtual bool deviceExists() noexcept = 0;
|
||||||
|
virtual void sendCommand(const libvariant::Variant& cmd) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<launch>
|
<launch>
|
||||||
<group ns="/hos/sitemap/sitemap_templates">
|
<group ns="/hos/sitemap/sitemap_templates">
|
||||||
<param name="test01" textfile="$(find hos_cosgi_sitemap)/examples/test01.json"/>
|
<param name="test01" textfile="$(find hos_cosgi_sitemap)/examples/test01.json"/>
|
||||||
|
<param name="test02" textfile="$(find hos_cosgi_sitemap)/examples/test02.json"/>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<group ns="/hos/types/repository/sitemap">
|
<group ns="/hos/types/repository/sitemap">
|
||||||
|
|||||||
@@ -13,12 +13,24 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": ""
|
"description": ""
|
||||||
},
|
},
|
||||||
|
"default": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": ""
|
||||||
|
},
|
||||||
|
"pages": {
|
||||||
|
"type": "object",
|
||||||
|
"patternProperties": {
|
||||||
|
"[A-Za-z0-9_-]+": {
|
||||||
|
"$ref": "#/definitions/page"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"rootpage": {
|
"rootpage": {
|
||||||
"$ref": "#/definitions/page"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"required": ["title", "rootpage"],
|
"required": ["title", "pages", "rootpage"],
|
||||||
|
|
||||||
"definitions": {
|
"definitions": {
|
||||||
|
|
||||||
@@ -109,7 +121,7 @@
|
|||||||
"icon": {
|
"icon": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"page": {
|
"linkedPage": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,13 +103,38 @@ void SitemapServiceImpl::addSitemap(const std::string& name, XmlRpc::XmlRpcValue
|
|||||||
throw std::runtime_error("title is not a string.");
|
throw std::runtime_error("title is not a string.");
|
||||||
}
|
}
|
||||||
std::string title = titleRaw.AsString();
|
std::string title = titleRaw.AsString();
|
||||||
auto rootpage = value["rootpage"];
|
auto rootpageRaw = value["rootpage"];
|
||||||
if (!rootpage.IsMap()) {
|
if (!rootpageRaw.IsString()) {
|
||||||
throw std::runtime_error("rootpage is not a map.");
|
throw std::runtime_error("rootpage is not a string.");
|
||||||
|
}
|
||||||
|
std::string rootpage = rootpageRaw.AsString();
|
||||||
|
bool isDefault = false;
|
||||||
|
if (value.Contains("default")) {
|
||||||
|
auto isDefaultRaw = value["default"];
|
||||||
|
if (!isDefaultRaw.IsBool()) {
|
||||||
|
throw std::runtime_error("default is not a boolean.");
|
||||||
|
}
|
||||||
|
isDefault = isDefaultRaw.IsTrue();
|
||||||
|
}
|
||||||
|
auto pages = value["pages"];
|
||||||
|
if (!pages.IsMap()) {
|
||||||
|
throw std::runtime_error("pages is not a map.");
|
||||||
|
}
|
||||||
|
std::shared_ptr<sitemaptemplate::SitemapTemplateImpl> st = std::make_shared<sitemaptemplate::SitemapTemplateImpl>(*this, name, title);
|
||||||
|
for (auto page : pages.AsMap()) {
|
||||||
|
st->addPage(page.first, page.second);
|
||||||
|
}
|
||||||
|
if (!st->setRootPageName(rootpage)) {
|
||||||
|
ROS_WARN_STREAM("Sitemap " << st->getName() << " has unknown root page " << rootpage << ".");
|
||||||
}
|
}
|
||||||
std::shared_ptr<sitemaptemplate::SitemapTemplateImpl> st = std::make_shared<sitemaptemplate::SitemapTemplateImpl>(*this, title);
|
|
||||||
st->createPage(rootpage);
|
|
||||||
sitemapTemplates.insert({name, st});
|
sitemapTemplates.insert({name, st});
|
||||||
|
if (!sitemapDefault || isDefault) {
|
||||||
|
sitemapDefault = st;
|
||||||
|
}
|
||||||
|
repoService->addObserver(devicerepository::DeviceEventType::ALL_EVENTS, st.get());
|
||||||
|
if (name.compare("default") == 0) {
|
||||||
|
ROS_WARN("There exists a sitemap with name \"default\".");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "Could not validate sitemap config value: " << sr.PrettyPrintMessage();
|
ss << "Could not validate sitemap config value: " << sr.PrettyPrintMessage();
|
||||||
@@ -146,6 +171,10 @@ std::vector<std::string> SitemapServiceImpl::getSitemapNames() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::weak_ptr<sitemaptemplate::SitemapTemplate> SitemapServiceImpl::getDefaultSitemap() noexcept {
|
||||||
|
return std::static_pointer_cast<sitemaptemplate::SitemapTemplate>(sitemapDefault);
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace sitemap */
|
} /* namespace sitemap */
|
||||||
} /* namespace service */
|
} /* namespace service */
|
||||||
} /* namespace cosgi */
|
} /* namespace cosgi */
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ private:
|
|||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
|
|
||||||
std::map<std::string, std::shared_ptr<sitemaptemplate::SitemapTemplateImpl>> sitemapTemplates;
|
std::map<std::string, std::shared_ptr<sitemaptemplate::SitemapTemplateImpl>> sitemapTemplates;
|
||||||
|
std::shared_ptr<sitemaptemplate::SitemapTemplateImpl> sitemapDefault;
|
||||||
|
|
||||||
|
|
||||||
void init() noexcept;
|
void init() noexcept;
|
||||||
void addSitemap(const std::string& name, XmlRpc::XmlRpcValue& rawValue);
|
void addSitemap(const std::string& name, XmlRpc::XmlRpcValue& rawValue);
|
||||||
@@ -72,6 +74,8 @@ public:
|
|||||||
|
|
||||||
virtual std::vector<std::string> getSitemapNames() noexcept override;
|
virtual std::vector<std::string> getSitemapNames() noexcept override;
|
||||||
|
|
||||||
|
virtual std::weak_ptr<sitemaptemplate::SitemapTemplate> getDefaultSitemap() noexcept override;
|
||||||
|
|
||||||
|
|
||||||
/* Internal */
|
/* Internal */
|
||||||
|
|
||||||
|
|||||||
+220
-83
@@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
#include "SitemapTemplateImpl.h"
|
#include "SitemapTemplateImpl.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace hos {
|
namespace hos {
|
||||||
namespace cosgi {
|
namespace cosgi {
|
||||||
@@ -9,54 +10,6 @@ namespace sitemaptemplate {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::atomic<uint64_t> ElementImpl::nextID;
|
|
||||||
|
|
||||||
std::shared_ptr<PageImpl> SitemapTemplateImpl::createPage(const libvariant::Variant& param, PageImpl* parent) {
|
|
||||||
std::shared_ptr<PageImpl> newPage;
|
|
||||||
if (!parent && rootPage) {
|
|
||||||
throw std::runtime_error("There is already a root page.");
|
|
||||||
}
|
|
||||||
auto titleRaw = param["title"];
|
|
||||||
if (!titleRaw.IsString()) {
|
|
||||||
throw std::runtime_error("title is not a string.");
|
|
||||||
}
|
|
||||||
std::string title = titleRaw.AsString();
|
|
||||||
auto elements = param["elements"];
|
|
||||||
if (!elements.IsList()) {
|
|
||||||
throw std::runtime_error("elements is not a list.");
|
|
||||||
}
|
|
||||||
newPage = std::make_shared<PageImpl>(*this, title, parent);
|
|
||||||
for ( auto e : elements.AsList()) {
|
|
||||||
newPage->createElement(e);
|
|
||||||
}
|
|
||||||
if (!parent) {
|
|
||||||
rootPage = newPage;
|
|
||||||
}
|
|
||||||
return newPage;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<DeviceImpl> SitemapTemplateImpl::createDevice(const libvariant::Variant& param) {
|
|
||||||
auto idRaw = param["id"];
|
|
||||||
if (!idRaw.IsString()) {
|
|
||||||
throw std::runtime_error("id is not a string.");
|
|
||||||
}
|
|
||||||
std::string id = idRaw.AsString();
|
|
||||||
std::string pointer;
|
|
||||||
auto pointerRaw = param["pointer"];
|
|
||||||
if (!pointerRaw.IsString()) {
|
|
||||||
throw std::runtime_error("pointer is not a string.");
|
|
||||||
} else if (pointerRaw.IsString()) {
|
|
||||||
pointer = pointerRaw.AsString();
|
|
||||||
}
|
|
||||||
auto devRepo = parent.getDeviceRepository();
|
|
||||||
auto device = devRepo->getDevice(id);
|
|
||||||
std::shared_ptr<DeviceImpl> newDevice = std::make_shared<DeviceImpl>(id, device, pointer);
|
|
||||||
return newDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct _elementTypeInfo {
|
struct _elementTypeInfo {
|
||||||
@@ -75,26 +28,85 @@ _elementTypeInfo elementTypeInfo[] = {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::atomic<uint64_t> ElementImpl::nextID;
|
||||||
|
|
||||||
|
std::shared_ptr<PageImpl> SitemapTemplateImpl::addPage(const std::string& name, const libvariant::Variant& pageRaw) {
|
||||||
|
auto titleRaw = pageRaw["title"];
|
||||||
|
if (!titleRaw.IsString()) {
|
||||||
|
throw std::runtime_error("title is not a string.");
|
||||||
|
}
|
||||||
|
std::string title = titleRaw.AsString();
|
||||||
|
auto elements = pageRaw["elements"];
|
||||||
|
if (!elements.IsList()) {
|
||||||
|
throw std::runtime_error("elements is not a list.");
|
||||||
|
}
|
||||||
|
auto newPage = std::make_shared<PageImpl>(*this, name, title);
|
||||||
|
for (auto element : elements.AsList()) {
|
||||||
|
newPage->addElement(element);
|
||||||
|
}
|
||||||
|
pages.insert({name, newPage});
|
||||||
|
return newPage;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::weak_ptr<Element>> PageImpl::getElements() noexcept {
|
std::weak_ptr<Page> SitemapTemplateImpl::getPage(const std::string& name) noexcept {
|
||||||
std::vector<std::weak_ptr<Element>> retval;
|
auto page = pages.find(name);
|
||||||
for (auto i : elements) {
|
if (page == pages.end()) {
|
||||||
retval.push_back(std::static_pointer_cast<Element>(i));
|
return std::weak_ptr<Page>();
|
||||||
|
} else {
|
||||||
|
return page->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::weak_ptr<Page>> SitemapTemplateImpl::getPages(const std::string& name) noexcept {
|
||||||
|
std::vector<std::weak_ptr<Page>> retval;
|
||||||
|
for (auto page : pages) {
|
||||||
|
retval.push_back(page.second);
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::weak_ptr<Element>> CompositeElementImpl::getElements() noexcept {
|
std::weak_ptr<Page> SitemapTemplateImpl::getRootPage() noexcept {
|
||||||
std::vector<std::weak_ptr<Element>> retval;
|
return getPage(rootPageName);
|
||||||
for (auto i : elements) {
|
}
|
||||||
retval.push_back(std::static_pointer_cast<Element>(i));
|
|
||||||
|
bool SitemapTemplateImpl::setRootPageName(const std::string& name) noexcept {
|
||||||
|
rootPageName = name;
|
||||||
|
if (pages.find(name) != pages.end()) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return retval;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::weak_ptr<Element> SitemapTemplateImpl::getPageElement(size_t& uid) noexcept {
|
||||||
|
auto r = pageElements.find(uid);
|
||||||
|
if (r != pageElements.end()) {
|
||||||
|
return r->second;
|
||||||
|
}
|
||||||
|
return std::weak_ptr<Element>();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<DeviceImpl> SitemapTemplateImpl::createDevice(const libvariant::Variant& param, const libvariant::Variant& commandTemplate, const std::string& commandValuePointer) {
|
||||||
|
auto idRaw = param["id"];
|
||||||
|
if (!idRaw.IsString()) {
|
||||||
|
throw std::runtime_error("id is not a string.");
|
||||||
|
}
|
||||||
|
std::string id = idRaw.AsString();
|
||||||
|
std::string pointer;
|
||||||
|
auto pointerRaw = param["pointer"];
|
||||||
|
if (!pointerRaw.IsString()) {
|
||||||
|
throw std::runtime_error("pointer is not a string.");
|
||||||
|
} else if (pointerRaw.IsString()) {
|
||||||
|
pointer = pointerRaw.AsString();
|
||||||
|
}
|
||||||
|
auto devRepo = parent.getDeviceRepository();
|
||||||
|
auto device = devRepo->getDevice(id);
|
||||||
|
std::shared_ptr<DeviceImpl> newDevice = std::make_shared<DeviceImpl>(id, device, pointer, commandTemplate, commandValuePointer);
|
||||||
|
devices.insert({id, newDevice});
|
||||||
|
return newDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<ElementImpl> PageImpl::createElement(const libvariant::Variant& param, CompositeElementImpl* parent) {
|
std::shared_ptr<ElementImpl> SitemapTemplateImpl::createElement(PageImpl& page, const libvariant::Variant& param, CompositeElementImpl* parent) {
|
||||||
std::shared_ptr<ElementImpl> newElement;
|
std::shared_ptr<ElementImpl> newElement;
|
||||||
libvariant::Variant addParams = param.Copy();
|
libvariant::Variant addParams = param.Copy();
|
||||||
auto typeRaw = param["type"];
|
auto typeRaw = param["type"];
|
||||||
@@ -134,13 +146,23 @@ std::shared_ptr<ElementImpl> PageImpl::createElement(const libvariant::Variant&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (info->isComposite) {
|
if (info->isComposite) {
|
||||||
|
auto elements = param["elements"];
|
||||||
|
if (elements.IsNull()) {
|
||||||
|
throw std::runtime_error("elements is missing.");
|
||||||
|
} else if (!elements.IsList()) {
|
||||||
|
throw std::runtime_error("elements is not an array.");
|
||||||
|
}
|
||||||
|
addParams.Erase("elements");
|
||||||
switch (info->type) {
|
switch (info->type) {
|
||||||
case ElementType::Frame:
|
case ElementType::Frame:
|
||||||
newElement = std::make_shared<FrameElementImpl>(*this, info->typeString, label, icon, parent);
|
newElement = std::make_shared<FrameElementImpl>(page, info->typeString, label, icon, parent);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error((boost::format("Registered element type %1% is unknown.") % info->typeName).str());
|
throw std::runtime_error((boost::format("Registered element type %1% is unknown.") % info->typeName).str());
|
||||||
}
|
}
|
||||||
|
for (auto element : elements.AsList()) {
|
||||||
|
std::static_pointer_cast<CompositeElementImpl>(newElement)->addElement(element);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
std::string format;
|
std::string format;
|
||||||
if (param.Contains("format")) {
|
if (param.Contains("format")) {
|
||||||
@@ -158,38 +180,120 @@ std::shared_ptr<ElementImpl> PageImpl::createElement(const libvariant::Variant&
|
|||||||
if (!deviceRaw.IsMap()) {
|
if (!deviceRaw.IsMap()) {
|
||||||
throw std::runtime_error("device is not a map.");
|
throw std::runtime_error("device is not a map.");
|
||||||
} else {
|
} else {
|
||||||
device = sitemap.createDevice(deviceRaw);
|
libvariant::Variant commandTemplate;
|
||||||
|
std::string commandValuePointer;
|
||||||
|
if (param.Contains("commandTemplate")) {
|
||||||
|
commandTemplate = param["commandTemplate"];
|
||||||
|
addParams.Erase("commandTemplate");
|
||||||
|
}
|
||||||
|
if (param.Contains("commandValuePointer") && param["commandValuePointer"].IsString()) {
|
||||||
|
commandValuePointer = param["commandValuePointer"].AsString();
|
||||||
|
addParams.Erase("commandValuePointer");
|
||||||
|
}
|
||||||
|
device = createDevice(deviceRaw, commandTemplate, commandValuePointer);
|
||||||
addParams.Erase("device");
|
addParams.Erase("device");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
libvariant::Variant pageRaw;
|
libvariant::Variant linkedPageRaw;
|
||||||
if (param.Contains("page")) {
|
if (param.Contains("linkedPage")) {
|
||||||
pageRaw = param["page"];
|
linkedPageRaw = param["linkedPage"];
|
||||||
if (!pageRaw.IsMap()) {
|
if (!linkedPageRaw.IsString()) {
|
||||||
throw std::runtime_error("page is not a map.");
|
throw std::runtime_error("linkedPage is not a string.");
|
||||||
} else {
|
} else {
|
||||||
addParams.Erase("page");
|
addParams.Erase("linkedPage");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::shared_ptr<AtomicElementImpl> newAElement;
|
std::shared_ptr<AtomicElementImpl> newAElement;
|
||||||
switch (info->type) {
|
switch (info->type) {
|
||||||
case ElementType::Text:
|
case ElementType::Text:
|
||||||
newAElement = std::make_shared<TextElementImpl>(*this, info->typeString, label, icon, format, device, addParams, parent);
|
newAElement = std::make_shared<TextElementImpl>(page, info->typeString, label, icon, format, device, addParams, parent);
|
||||||
break;
|
break;
|
||||||
case ElementType::Slider:
|
case ElementType::Slider:
|
||||||
newAElement = std::make_shared<SliderElementImpl>(*this, info->typeString, label, icon, format, device, addParams, parent);
|
newAElement = std::make_shared<SliderElementImpl>(page, info->typeString, label, icon, format, device, addParams, parent);
|
||||||
break;
|
break;
|
||||||
case ElementType::Switch:
|
case ElementType::Switch:
|
||||||
newAElement = std::make_shared<SwitchElementImpl>(*this, info->typeString, label, icon, format, device, addParams, parent);
|
newAElement = std::make_shared<SwitchElementImpl>(page, info->typeString, label, icon, format, device, addParams, parent);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error((boost::format("Registered element type %1% is unknown.") % info->typeName).str());
|
throw std::runtime_error((boost::format("Registered element type %1% is unknown.") % info->typeName).str());
|
||||||
}
|
}
|
||||||
if (pageRaw.IsMap()) {
|
if (device) {
|
||||||
newAElement->createLinkedToPage(pageRaw);
|
device->setParent(newAElement);
|
||||||
|
}
|
||||||
|
if (linkedPageRaw.IsString()) {
|
||||||
|
newAElement->setLinkedPage(linkedPageRaw.AsString());
|
||||||
}
|
}
|
||||||
newElement = newAElement;
|
newElement = newAElement;
|
||||||
}
|
}
|
||||||
|
pageElements.insert({newElement->getID(), newElement});
|
||||||
|
return newElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SitemapTemplateImpl::notificationReceived(observable_type* o, const devicerepository::DeviceEventType& key, const devicerepository::DeviceEvent* e) noexcept {
|
||||||
|
SitemapElementChangedEvent event(this, std::chrono::system_clock::now());
|
||||||
|
switch (e->eventType) {
|
||||||
|
case devicerepository::DeviceEventType::DEVICE_ADDED:
|
||||||
|
{
|
||||||
|
auto range = devices.equal_range(e->device->getDeviceID());
|
||||||
|
for (auto i = range.first; i != range.second && i != devices.end(); i++) {
|
||||||
|
auto dev = i->second.lock();
|
||||||
|
if (!dev->deviceExists()) {
|
||||||
|
dev->resolveDevice();
|
||||||
|
event.elements.push_back(dev->getParent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case devicerepository::DeviceEventType::DEVICE_REMOVED:
|
||||||
|
{
|
||||||
|
auto range = devices.equal_range(e->device->getDeviceID());
|
||||||
|
for (auto i = range.first; i != range.second && i != devices.end(); i++) {
|
||||||
|
auto dev = i->second.lock();
|
||||||
|
dev->resolveDevice();
|
||||||
|
event.elements.push_back(dev->getParent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case devicerepository::DeviceEventType::STATE_CHANGED:
|
||||||
|
{
|
||||||
|
auto range = devices.equal_range(e->device->getDeviceID());
|
||||||
|
for (auto i = range.first; i != range.second && i != devices.end(); i++) {
|
||||||
|
auto dev = i->second.lock();
|
||||||
|
event.elements.push_back(dev->getParent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (event.elements.size() > 0) {
|
||||||
|
notifyObservers(SitemapEventType::ALL_EVENTS, SitemapEventType::SITEMAP_ELEMENT_CHANGED, &event);
|
||||||
|
notifyObservers(SitemapEventType::SITEMAP_ELEMENT_CHANGED, &event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<std::weak_ptr<Element>> PageImpl::getElements() noexcept {
|
||||||
|
std::vector<std::weak_ptr<Element>> retval;
|
||||||
|
for (auto i : elements) {
|
||||||
|
retval.push_back(std::static_pointer_cast<Element>(i));
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::weak_ptr<Element>> CompositeElementImpl::getElements() noexcept {
|
||||||
|
std::vector<std::weak_ptr<Element>> retval;
|
||||||
|
for (auto i : elements) {
|
||||||
|
retval.push_back(std::static_pointer_cast<Element>(i));
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::shared_ptr<ElementImpl> PageImpl::addElement(const libvariant::Variant& param, CompositeElementImpl* parent) {
|
||||||
|
std::shared_ptr<ElementImpl> newElement = sitemap.createElement(*this, param, parent);
|
||||||
if (!parent) {
|
if (!parent) {
|
||||||
elements.push_back(newElement);
|
elements.push_back(newElement);
|
||||||
}
|
}
|
||||||
@@ -198,33 +302,40 @@ std::shared_ptr<ElementImpl> PageImpl::createElement(const libvariant::Variant&
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<ElementImpl> CompositeElementImpl::createElement(const libvariant::Variant& param) {
|
std::shared_ptr<ElementImpl> CompositeElementImpl::addElement(const libvariant::Variant& param) {
|
||||||
std::shared_ptr<ElementImpl> newElement = page.createElement(param, this);
|
std::shared_ptr<ElementImpl> newElement = page.addElement(param, this);
|
||||||
elements.push_back(newElement);
|
elements.push_back(newElement);
|
||||||
return newElement;
|
return newElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<PageImpl> AtomicElementImpl::createLinkedToPage(const libvariant::Variant& param) {
|
bool AtomicElementImpl::setLinkedPage(const std::string& pagename) noexcept {
|
||||||
if (linkedToPage) {
|
linkedPageName = pagename;
|
||||||
throw std::runtime_error("There is already a linked page.");
|
if (!this->page.getSiteMap()->getPage(linkedPageName).expired()) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
linkedToPage = page.sitemap.createPage(param, &page);
|
return false;
|
||||||
return linkedToPage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
libvariant::Variant SitemapTemplateImpl::renderSitemap() {
|
libvariant::Variant SitemapTemplateImpl::renderSitemap() {
|
||||||
libvariant::Variant retval = libvariant::Variant::Map();
|
libvariant::Variant retval = libvariant::Variant::Map();
|
||||||
retval["title"] = title;
|
retval["title"] = title;
|
||||||
retval["rootpage"] = rootPage->renderSitemap();
|
retval["name"] = name;
|
||||||
retval["type"] = "sitemap/sitemap";
|
retval["type"] = "sitemap/sitemap";
|
||||||
|
retval["rootpage"] = rootPageName;
|
||||||
|
auto tmp = libvariant::Variant::Map();
|
||||||
|
for (auto page : pages) {
|
||||||
|
tmp[page.first] = page.second->renderSitemap();
|
||||||
|
}
|
||||||
|
retval["pages"] = tmp;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
libvariant::Variant PageImpl::renderSitemap() {
|
libvariant::Variant PageImpl::renderSitemap() {
|
||||||
libvariant::Variant retval = libvariant::Variant::Map();
|
libvariant::Variant retval = libvariant::Variant::Map();
|
||||||
retval["title"] = title;
|
retval["title"] = title;
|
||||||
|
retval["name"] = name;
|
||||||
libvariant::Variant elements = libvariant::Variant::List();
|
libvariant::Variant elements = libvariant::Variant::List();
|
||||||
for (auto i : this->elements) {
|
for (auto i : this->elements) {
|
||||||
elements.Append(i->renderSitemap());
|
elements.Append(i->renderSitemap());
|
||||||
@@ -246,20 +357,27 @@ libvariant::Variant CompositeElementImpl::renderSitemap() {
|
|||||||
}
|
}
|
||||||
retval["elements"] = elements;
|
retval["elements"] = elements;
|
||||||
retval["type"] = typeString;
|
retval["type"] = typeString;
|
||||||
|
retval["uid"] = id;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::weak_ptr<Page> AtomicElementImpl::getLinkedPage() noexcept {
|
||||||
|
return this->page.getSiteMap()->getPage(linkedPageName);
|
||||||
|
}
|
||||||
|
|
||||||
libvariant::Variant AtomicElementImpl::renderSitemap() {
|
libvariant::Variant AtomicElementImpl::renderSitemap() {
|
||||||
libvariant::Variant retval = libvariant::Variant::Map();
|
libvariant::Variant retval = libvariant::Variant::Map();
|
||||||
retval["label"] = label;
|
retval["label"] = label;
|
||||||
if (!icon.empty()) {
|
if (!icon.empty()) {
|
||||||
retval["icon"] = icon;
|
retval["icon"] = icon;
|
||||||
}
|
}
|
||||||
if (linkedToPage) {
|
if (!linkedPageName.empty()) {
|
||||||
retval["page"] = linkedToPage->renderSitemap();
|
retval["linkedPage"] = linkedPageName;
|
||||||
}
|
}
|
||||||
retval["value"] = _getDeviceValue();
|
retval["value"] = _getDeviceValue();
|
||||||
retval["type"] = typeString;
|
retval["type"] = typeString;
|
||||||
|
retval["uid"] = id;
|
||||||
retval.Merge(additionalParams);
|
retval.Merge(additionalParams);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@@ -267,7 +385,7 @@ libvariant::Variant AtomicElementImpl::renderSitemap() {
|
|||||||
|
|
||||||
libvariant::Variant AtomicElementImpl::_getDeviceValue() {
|
libvariant::Variant AtomicElementImpl::_getDeviceValue() {
|
||||||
libvariant::Variant devState;
|
libvariant::Variant devState;
|
||||||
if (device->deviceExists()) {
|
if (device && device->deviceExists()) {
|
||||||
try {
|
try {
|
||||||
devState = device->getDevice().lock()->getCurrentState();
|
devState = device->getDevice().lock()->getCurrentState();
|
||||||
if (!device->getPointer().empty()) {
|
if (!device->getPointer().empty()) {
|
||||||
@@ -280,7 +398,11 @@ libvariant::Variant AtomicElementImpl::_getDeviceValue() {
|
|||||||
devState = "NaN";
|
devState = "NaN";
|
||||||
}
|
}
|
||||||
if (!format.empty()) {
|
if (!format.empty()) {
|
||||||
devState = (boost::format(format) % devState.AsString()).str();
|
try {
|
||||||
|
devState = (boost::format(format) % devState.AsString()).str();
|
||||||
|
} catch (boost::io::format_error& e) {
|
||||||
|
devState = format;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return devState;
|
return devState;
|
||||||
}
|
}
|
||||||
@@ -321,6 +443,21 @@ libvariant::Variant SwitchElementImpl::_getDeviceValue() {
|
|||||||
return devState;
|
return devState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeviceImpl::resolveDevice() noexcept {
|
||||||
|
if (!parent.expired()) {
|
||||||
|
auto devRepo = parent.lock()->getPage()->getSiteMap()->getParent()->getDeviceRepository();
|
||||||
|
device = devRepo->getDevice(deviceID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceImpl::sendCommand(const libvariant::Variant& cmd) {
|
||||||
|
if (!device.expired() && commandTemplate.IsMap() && !commandValuePointer.empty()) {
|
||||||
|
std::cout << "DeviceImpl::sendCommand: " << libvariant::SerializeJSON(cmd) << std::endl;
|
||||||
|
auto msg = commandTemplate.Copy();
|
||||||
|
msg.SetPath(commandValuePointer, cmd);
|
||||||
|
device.lock()->sendCommand(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sitemaptemplate
|
} // namespace sitemaptemplate
|
||||||
} // namespace sitemap
|
} // namespace sitemap
|
||||||
|
|||||||
+62
-17
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
// hos includes
|
// hos includes
|
||||||
#include <hos/cosgi/service/sitemap/sitemap_template/SitemapTemplate.h>
|
#include <hos/cosgi/service/sitemap/sitemap_template/SitemapTemplate.h>
|
||||||
|
#include <hos/cosgi/service/devicerepository/DeviceRepositoryService.h>
|
||||||
|
#include <hos/cosgi/service/Interface.h>
|
||||||
#include "../SitemapServiceImpl.h"
|
#include "../SitemapServiceImpl.h"
|
||||||
#include <hos/utils/SchemaLoader.h>
|
#include <hos/utils/SchemaLoader.h>
|
||||||
// libvariant
|
// libvariant
|
||||||
@@ -15,6 +17,22 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
/**
|
||||||
|
* Specialization of std::hash for DeviceEventType.
|
||||||
|
*
|
||||||
|
* Required by std::map.
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
class hash <hos::cosgi::service::sitemap::sitemaptemplate::SitemapEventType>{
|
||||||
|
public :
|
||||||
|
size_t operator()(const hos::cosgi::service::sitemap::sitemaptemplate::SitemapEventType& x) const {
|
||||||
|
return static_cast<size_t>(x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
|
|
||||||
namespace hos {
|
namespace hos {
|
||||||
namespace cosgi {
|
namespace cosgi {
|
||||||
namespace service {
|
namespace service {
|
||||||
@@ -35,20 +53,37 @@ class DeviceImpl;
|
|||||||
|
|
||||||
class SitemapTemplateImpl
|
class SitemapTemplateImpl
|
||||||
: public virtual SitemapTemplate,
|
: public virtual SitemapTemplate,
|
||||||
public implementation::Object {
|
public implementation::ObservableObject<SitemapEventType, SitemapEvent> {
|
||||||
private:
|
private:
|
||||||
SitemapServiceImpl& parent;
|
SitemapServiceImpl& parent;
|
||||||
|
std::string name;
|
||||||
std::string title;
|
std::string title;
|
||||||
std::shared_ptr<PageImpl> rootPage;
|
std::map<std::string, std::shared_ptr<PageImpl>> pages;
|
||||||
|
std::map<size_t, std::shared_ptr<ElementImpl>> pageElements;
|
||||||
|
std::string rootPageName;
|
||||||
|
std::multimap<std::string, std::weak_ptr<DeviceImpl>> devices;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SitemapTemplateImpl(SitemapServiceImpl& parent, const std::string& title) : parent(parent), title(title) {}
|
SitemapTemplateImpl(SitemapServiceImpl& parent, const std::string& name, const std::string& title)
|
||||||
|
: parent(parent), name(name), title(title) {}
|
||||||
|
|
||||||
std::shared_ptr<PageImpl> createPage(const libvariant::Variant& param, PageImpl* parent = nullptr);
|
virtual void notificationReceived(observable_type* o, const devicerepository::DeviceEventType& key, const devicerepository::DeviceEvent* e) noexcept override;
|
||||||
std::shared_ptr<DeviceImpl> createDevice(const libvariant::Variant& param);
|
|
||||||
|
std::shared_ptr<PageImpl> addPage(const std::string& name, const libvariant::Variant& page);
|
||||||
|
bool setRootPageName(const std::string& name) noexcept;
|
||||||
|
std::shared_ptr<DeviceImpl> createDevice(const libvariant::Variant& param, const libvariant::Variant& commandTemplate, const std::string& commandValuePointer);
|
||||||
|
std::shared_ptr<ElementImpl> createElement(PageImpl& page, const libvariant::Variant& param, CompositeElementImpl* parent);
|
||||||
|
|
||||||
virtual SitemapService* getParent() noexcept override { return dynamic_cast<SitemapService*>(&parent); }
|
virtual SitemapService* getParent() noexcept override { return dynamic_cast<SitemapService*>(&parent); }
|
||||||
virtual std::weak_ptr<Page> getRootPage() noexcept override { return std::static_pointer_cast<Page>(rootPage); };
|
virtual size_t pageCount() noexcept override { return pages.size(); }
|
||||||
|
virtual std::weak_ptr<Page> getPage(const std::string& name) noexcept override;
|
||||||
|
virtual std::vector<std::weak_ptr<Page>> getPages(const std::string& name) noexcept override;
|
||||||
|
virtual std::weak_ptr<Page> getRootPage() noexcept override;
|
||||||
|
virtual const std::string& getRootPageName() noexcept override { return rootPageName; }
|
||||||
|
virtual std::weak_ptr<Element> getPageElement(size_t& uid) noexcept override;
|
||||||
|
|
||||||
|
|
||||||
|
virtual const std::string& getName() noexcept { return name; };
|
||||||
|
|
||||||
virtual libvariant::Variant renderSitemap() override;
|
virtual libvariant::Variant renderSitemap() override;
|
||||||
};
|
};
|
||||||
@@ -61,18 +96,18 @@ class PageImpl
|
|||||||
friend class AtomicElementImpl;
|
friend class AtomicElementImpl;
|
||||||
private:
|
private:
|
||||||
SitemapTemplateImpl& sitemap;
|
SitemapTemplateImpl& sitemap;
|
||||||
PageImpl* parent;
|
std::string name;
|
||||||
std::string title;
|
std::string title;
|
||||||
std::vector<std::shared_ptr<ElementImpl>> elements;
|
std::vector<std::shared_ptr<ElementImpl>> elements;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PageImpl(SitemapTemplateImpl& sitemap, const std::string& title, PageImpl* parent = nullptr)
|
PageImpl(SitemapTemplateImpl& sitemap, const std::string& name, const std::string& title)
|
||||||
: sitemap(sitemap), parent(parent), title(title) {}
|
: sitemap(sitemap), name(name), title(title) {}
|
||||||
|
|
||||||
virtual SitemapTemplate* getSiteMap() noexcept override { return static_cast<SitemapTemplate*>(&sitemap); }
|
virtual SitemapTemplate* getSiteMap() noexcept override { return static_cast<SitemapTemplate*>(&sitemap); }
|
||||||
virtual Page* getParent() noexcept override { return static_cast<Page*>(parent); }
|
virtual const std::string& getName() noexcept { return name; }
|
||||||
|
|
||||||
std::shared_ptr<ElementImpl> createElement(const libvariant::Variant& param, CompositeElementImpl* parent = nullptr);
|
std::shared_ptr<ElementImpl> addElement(const libvariant::Variant& param, CompositeElementImpl* parent = nullptr);
|
||||||
|
|
||||||
virtual size_t elementCount() noexcept override { return elements.size(); }
|
virtual size_t elementCount() noexcept override { return elements.size(); }
|
||||||
virtual std::weak_ptr<Element> getElement(size_t index) noexcept override
|
virtual std::weak_ptr<Element> getElement(size_t index) noexcept override
|
||||||
@@ -135,7 +170,7 @@ public:
|
|||||||
CompositeElementImpl* parent = nullptr)
|
CompositeElementImpl* parent = nullptr)
|
||||||
: ElementImpl(page, true, etype, typeStr, parent, label, icon) {}
|
: ElementImpl(page, true, etype, typeStr, parent, label, icon) {}
|
||||||
|
|
||||||
std::shared_ptr<ElementImpl> createElement(const libvariant::Variant& param);
|
std::shared_ptr<ElementImpl> addElement(const libvariant::Variant& param);
|
||||||
|
|
||||||
virtual size_t elementCount() noexcept override { return elements.size(); }
|
virtual size_t elementCount() noexcept override { return elements.size(); }
|
||||||
virtual std::weak_ptr<Element> getElement(size_t index) noexcept override { return std::static_pointer_cast<Element>(elements.at(index)); }
|
virtual std::weak_ptr<Element> getElement(size_t index) noexcept override { return std::static_pointer_cast<Element>(elements.at(index)); }
|
||||||
@@ -153,7 +188,7 @@ protected:
|
|||||||
std::string format;
|
std::string format;
|
||||||
std::shared_ptr<DeviceImpl> device;
|
std::shared_ptr<DeviceImpl> device;
|
||||||
libvariant::Variant additionalParams;
|
libvariant::Variant additionalParams;
|
||||||
std::shared_ptr<PageImpl> linkedToPage;
|
std::string linkedPageName;
|
||||||
|
|
||||||
virtual libvariant::Variant _getDeviceValue();
|
virtual libvariant::Variant _getDeviceValue();
|
||||||
|
|
||||||
@@ -163,12 +198,13 @@ public:
|
|||||||
CompositeElementImpl* parent = nullptr)
|
CompositeElementImpl* parent = nullptr)
|
||||||
: ElementImpl(page, false, etype, typeStr, parent, label, icon), format(format), device(device), additionalParams(additionalParams) {}
|
: ElementImpl(page, false, etype, typeStr, parent, label, icon), format(format), device(device), additionalParams(additionalParams) {}
|
||||||
|
|
||||||
std::shared_ptr<PageImpl> createLinkedToPage(const libvariant::Variant& param);
|
bool setLinkedPage(const std::string& pagename) noexcept;
|
||||||
|
|
||||||
virtual const std::string& getFormat() noexcept override { return format; }
|
virtual const std::string& getFormat() noexcept override { return format; }
|
||||||
virtual std::weak_ptr<Device> getDevice() noexcept override;
|
virtual std::weak_ptr<Device> getDevice() noexcept override;
|
||||||
virtual const libvariant::Variant& getAdditionalParams() noexcept override { return additionalParams; }
|
virtual const libvariant::Variant& getAdditionalParams() noexcept override { return additionalParams; }
|
||||||
virtual std::weak_ptr<Page> getLinkedToPage() noexcept override { return linkedToPage; }
|
virtual std::weak_ptr<Page> getLinkedPage() noexcept override;
|
||||||
|
virtual const std::string& getLinkedPageName() noexcept override { return linkedPageName; }
|
||||||
|
|
||||||
virtual libvariant::Variant renderSitemap() override;
|
virtual libvariant::Variant renderSitemap() override;
|
||||||
};
|
};
|
||||||
@@ -218,15 +254,24 @@ private:
|
|||||||
std::string deviceID;
|
std::string deviceID;
|
||||||
std::weak_ptr<devicerepository::Device> device;
|
std::weak_ptr<devicerepository::Device> device;
|
||||||
std::string pointer;
|
std::string pointer;
|
||||||
|
std::weak_ptr<ElementImpl> parent;
|
||||||
|
libvariant::Variant commandTemplate;
|
||||||
|
std::string commandValuePointer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DeviceImpl(const std::string& deviceID, std::weak_ptr<devicerepository::Device> device, const std::string& pointer)
|
DeviceImpl(const std::string& deviceID, std::weak_ptr<devicerepository::Device> device, const std::string& pointer, const libvariant::Variant& commandTemplate, const std::string& commandValuePointer)
|
||||||
: deviceID(deviceID), device(device), pointer(pointer) {}
|
: deviceID(deviceID), device(device), pointer(pointer), commandTemplate(commandTemplate), commandValuePointer(commandValuePointer) {}
|
||||||
|
|
||||||
|
virtual std::weak_ptr<Element> getParent() noexcept override { return parent; }
|
||||||
|
void setParent(std::weak_ptr<ElementImpl> parent) noexcept { this->parent = parent; }
|
||||||
|
void resolveDevice() noexcept;
|
||||||
|
void setDevice(std::weak_ptr<devicerepository::Device> device) noexcept { this->device = device; }
|
||||||
|
|
||||||
virtual const std::string& getDeviceID() noexcept override { return deviceID; }
|
virtual const std::string& getDeviceID() noexcept override { return deviceID; }
|
||||||
virtual std::weak_ptr<devicerepository::Device> getDevice() noexcept override { return device; }
|
virtual std::weak_ptr<devicerepository::Device> getDevice() noexcept override { return device; }
|
||||||
virtual const std::string& getPointer() noexcept override { return pointer; }
|
virtual const std::string& getPointer() noexcept override { return pointer; }
|
||||||
virtual bool deviceExists() noexcept override { return !device.expired(); }
|
virtual bool deviceExists() noexcept override { return !device.expired(); }
|
||||||
|
virtual void sendCommand(const libvariant::Variant& cmd) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+196
-5
@@ -85,14 +85,23 @@ void SitemapHandler::__handleInfo(Poco::Net::HTTPServerRequest &req, Poco::Net::
|
|||||||
for (auto s : sitemaps) {
|
for (auto s : sitemaps) {
|
||||||
result.Append(s);
|
result.Append(s);
|
||||||
}
|
}
|
||||||
|
Variant message = Variant::Map();
|
||||||
|
message["sitemaps"] = result;
|
||||||
|
auto dsm = service->getDefaultSitemap();
|
||||||
|
if (!dsm.expired()) {
|
||||||
|
message["default"] = dsm.lock()->getName();
|
||||||
|
}
|
||||||
|
|
||||||
handleResponse(req, resp, form, result);
|
handleResponse(req, resp, form, message);
|
||||||
|
|
||||||
// Single sitemap mode
|
// Single sitemap mode
|
||||||
} else {
|
} else {
|
||||||
// Get sitemap
|
// Get sitemap
|
||||||
std::string sitemapName = pathPieces[matchPieces.size()];
|
std::string sitemapName = pathPieces[matchPieces.size()];
|
||||||
auto sitemap = service->getSitemap(sitemapName);
|
auto sitemap = service->getSitemap(sitemapName);
|
||||||
|
if (sitemap.expired() && sitemapName.compare("default") == 0) {
|
||||||
|
sitemap = service->getDefaultSitemap();
|
||||||
|
}
|
||||||
if (!sitemap.expired()) {
|
if (!sitemap.expired()) {
|
||||||
// Get path from url and append pointer parameter
|
// Get path from url and append pointer parameter
|
||||||
std::stringstream path;
|
std::stringstream path;
|
||||||
@@ -108,6 +117,15 @@ void SitemapHandler::__handleInfo(Poco::Net::HTTPServerRequest &req, Poco::Net::
|
|||||||
}
|
}
|
||||||
// Render sitemap
|
// Render sitemap
|
||||||
Variant result = sitemap.lock()->renderSitemap();
|
Variant result = sitemap.lock()->renderSitemap();
|
||||||
|
std::string pathStr = path.str();
|
||||||
|
if (!pathStr.empty()) {
|
||||||
|
if (result.HasPath(pathStr)) {
|
||||||
|
result = result.GetPath(pathStr);
|
||||||
|
} else {
|
||||||
|
throw webserver::webresource::WebResourceHandlerException((boost::format("Unknown path \"%1%\" for sitemap \"%2%\".") % path % sitemapName).str(),
|
||||||
|
Poco::Net::HTTPResponse::HTTPStatus::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
// Return device info
|
// Return device info
|
||||||
handleResponse(req, resp, form, result);
|
handleResponse(req, resp, form, result);
|
||||||
} else {
|
} else {
|
||||||
@@ -119,14 +137,131 @@ void SitemapHandler::__handleInfo(Poco::Net::HTTPServerRequest &req, Poco::Net::
|
|||||||
|
|
||||||
|
|
||||||
void SitemapHandler::__handleCommand(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp, SitemapAPIMethod method, Net::HTMLForm& form) {
|
void SitemapHandler::__handleCommand(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp, SitemapAPIMethod method, Net::HTMLForm& form) {
|
||||||
throw webserver::webresource::WebResourceHandlerException("ToDo. Implement that shit.",
|
std::vector<std::string> pathPieces, matchPieces;
|
||||||
Poco::Net::HTTPResponse::HTTPStatus::HTTP_NOT_IMPLEMENTED);
|
matchUri.getPathSegments(matchPieces);
|
||||||
|
Poco::URI uri(req.getURI());
|
||||||
|
uri.getPathSegments(pathPieces);
|
||||||
|
|
||||||
|
// No sitemap given, error
|
||||||
|
if (pathPieces.size() <= matchPieces.size()) {
|
||||||
|
throw webserver::webresource::WebResourceHandlerException("Missing sitemap.",
|
||||||
|
Poco::Net::HTTPResponse::HTTPStatus::HTTP_BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get sitemap and do stuff
|
||||||
|
std::string sitemapName = pathPieces[matchPieces.size()];
|
||||||
|
std::weak_ptr<sitemaptemplate::SitemapTemplate> sitemap = service->getSitemap(sitemapName);
|
||||||
|
if (!sitemap.expired()) {
|
||||||
|
|
||||||
|
Variant result;
|
||||||
|
std::string msg;
|
||||||
|
if (form.has("value")) {
|
||||||
|
msg = form.get("value");
|
||||||
|
}
|
||||||
|
if (!msg.empty()) {
|
||||||
|
result = libvariant::DeserializeYAML(msg);
|
||||||
|
if (result.Contains("eventtype")) {
|
||||||
|
auto eventtype = result["eventtype"].AsString();
|
||||||
|
if (eventtype == "sitemap_element_command") {
|
||||||
|
auto uid = result["uid"].AsUnsigned();
|
||||||
|
auto value = result["value"];
|
||||||
|
auto pe = sitemap.lock()->getPageElement(uid);
|
||||||
|
if (!pe.expired()) {
|
||||||
|
auto spe = pe.lock();
|
||||||
|
if (!spe->isComposite()) {
|
||||||
|
auto ae = std::dynamic_pointer_cast<sitemaptemplate::AtomicElement>(spe);
|
||||||
|
auto dev = ae->getDevice();
|
||||||
|
if (!dev.expired()) {
|
||||||
|
dev.lock()->sendCommand(value);
|
||||||
|
handleResponse(req, resp, form, std::string("OK: Command executed"));
|
||||||
|
} else {
|
||||||
|
throw webserver::webresource::WebResourceHandlerException("No device associated with element.",
|
||||||
|
Poco::Net::HTTPResponse::HTTPStatus::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw webserver::webresource::WebResourceHandlerException("Cannot send a command to a composite element.",
|
||||||
|
Poco::Net::HTTPResponse::HTTPStatus::HTTP_BAD_REQUEST);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw webserver::webresource::WebResourceHandlerException((boost::format("Couldn't find element uid \"%1%\"") % uid).str(),
|
||||||
|
Poco::Net::HTTPResponse::HTTPStatus::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw webserver::webresource::WebResourceHandlerException((boost::format("Unknown eventtype \"%1%\"") % eventtype).str(),
|
||||||
|
Poco::Net::HTTPResponse::HTTPStatus::HTTP_BAD_REQUEST);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw webserver::webresource::WebResourceHandlerException("Missing eventtype.",
|
||||||
|
Poco::Net::HTTPResponse::HTTPStatus::HTTP_BAD_REQUEST);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw webserver::webresource::WebResourceHandlerException("Missing msg.",
|
||||||
|
Poco::Net::HTTPResponse::HTTPStatus::HTTP_BAD_REQUEST);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw webserver::webresource::WebResourceHandlerException((boost::format("Could not find sitemap \"%1%\"") % sitemapName).str(),
|
||||||
|
Poco::Net::HTTPResponse::HTTPStatus::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SitemapHandler::__handleEvent(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp, Net::HTMLForm& form, bool websocket) {
|
void SitemapHandler::__handleEvent(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp, Net::HTMLForm& form, bool websocket) {
|
||||||
throw webserver::webresource::WebResourceHandlerException("ToDo. Implement that shit.",
|
std::vector<std::string> pathPieces, matchPieces;
|
||||||
Poco::Net::HTTPResponse::HTTPStatus::HTTP_NOT_IMPLEMENTED);
|
matchUri.getPathSegments(matchPieces);
|
||||||
|
Poco::URI uri(req.getURI());
|
||||||
|
uri.getPathSegments(pathPieces);
|
||||||
|
|
||||||
|
// No sitemap given, error
|
||||||
|
if (pathPieces.size() <= matchPieces.size()) {
|
||||||
|
throw webserver::webresource::WebResourceHandlerException("Missing sitemap.",
|
||||||
|
Poco::Net::HTTPResponse::HTTPStatus::HTTP_BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get sitemap and do stuff
|
||||||
|
std::string sitemapName = pathPieces[matchPieces.size()];
|
||||||
|
std::weak_ptr<sitemaptemplate::SitemapTemplate> sitemap = service->getSitemap(sitemapName);
|
||||||
|
if (!sitemap.expired()) {
|
||||||
|
// Get client ID
|
||||||
|
std::string clientID;
|
||||||
|
if (form.has("clientid")) {
|
||||||
|
clientID = form.get("clientid");
|
||||||
|
} else if (req.has("Client-Id")) {
|
||||||
|
clientID = req.get("Client-Id");
|
||||||
|
} else if (req.has("X-Client-Id")) {
|
||||||
|
clientID = req.get("X-Client-Id");
|
||||||
|
}
|
||||||
|
// Get path from url and append pointer parameter
|
||||||
|
std::stringstream path;
|
||||||
|
for (int i = matchPieces.size() + 2; i < pathPieces.size(); i++) {
|
||||||
|
path << "/" << pathPieces[i];
|
||||||
|
}
|
||||||
|
std::string pointer;
|
||||||
|
if (getPointerParameter(pointer, form)) {
|
||||||
|
if (pointer.size() > 0 && pointer[0] != '/') {
|
||||||
|
path << "/";
|
||||||
|
}
|
||||||
|
path << pointer;
|
||||||
|
}
|
||||||
|
// Get event queue
|
||||||
|
auto eventQueue = parent->getEventQueue(clientID, service);
|
||||||
|
if (!eventQueue->setHandler(this, &req, &resp)) {
|
||||||
|
throw webserver::webresource::WebResourceHandlerException((boost::format("Client id \"%1%\" already in use.") % clientID).str(),
|
||||||
|
Poco::Net::HTTPResponse::HTTPStatus::HTTP_BAD_REQUEST);
|
||||||
|
}
|
||||||
|
std::cout << "Got EventQueue \"" << eventQueue->clientID << "\"" << std::endl;
|
||||||
|
eventQueue->checkRegistration(sitemaptemplate::SitemapEventType::ALL_EVENTS, sitemap.lock().get());
|
||||||
|
if (websocket) {
|
||||||
|
__handleEventWebSocket(req, resp, form, eventQueue.get(), parent);
|
||||||
|
} else {
|
||||||
|
__handleEventLongPolling(req, resp, form, eventQueue.get(), parent);
|
||||||
|
}
|
||||||
|
eventQueue->unsetHandler();
|
||||||
|
} else {
|
||||||
|
throw webserver::webresource::WebResourceHandlerException((boost::format("Could not find sitemap \"%1%\"") % sitemapName).str(),
|
||||||
|
Poco::Net::HTTPResponse::HTTPStatus::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
/*throw webserver::webresource::WebResourceHandlerException("ToDo. Implement that shit.",
|
||||||
|
Poco::Net::HTTPResponse::HTTPStatus::HTTP_NOT_IMPLEMENTED);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -160,6 +295,62 @@ SitemapAPIMethod SitemapHandler::getSitemapAPIMethod(Net::HTTPServerRequest &req
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void SitemapEventQueue::checkRegistration(sitemaptemplate::SitemapEventType eventType, sitemaptemplate::SitemapTemplate* sitemap) {
|
||||||
|
if (!registeredToEvent || eventType != this->eventType || sitemap != this->sitemap) {
|
||||||
|
unregisterEvents();
|
||||||
|
registerEvents(eventType, sitemap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SitemapEventQueue::registerEvents(sitemaptemplate::SitemapEventType eventType, sitemaptemplate::SitemapTemplate* sitemap) {
|
||||||
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
|
if (!registeredToEvent) {
|
||||||
|
std::cout << "SitemapEventQueue::registerEvents" << std::endl;
|
||||||
|
sitemap->addObserver(eventType, this);
|
||||||
|
this->sitemap = sitemap;
|
||||||
|
this->eventType = eventType;
|
||||||
|
registeredToEvent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SitemapEventQueue::unregisterEvents() {
|
||||||
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
|
if (registeredToEvent) {
|
||||||
|
std::cout << "SitemapEventQueue::unregisterEvents" << std::endl;
|
||||||
|
if (sitemap) {
|
||||||
|
sitemap->deleteObserver(this);
|
||||||
|
}
|
||||||
|
registeredToEvent = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SitemapEventQueue::notificationReceived( interface::Observer<sitemaptemplate::SitemapEventType, sitemaptemplate::SitemapEvent>::observable_type* o,
|
||||||
|
const sitemaptemplate::SitemapEventType& key,
|
||||||
|
const sitemaptemplate::SitemapEvent* e) noexcept {
|
||||||
|
Variant event;
|
||||||
|
switch (key) {
|
||||||
|
case sitemaptemplate::SitemapEventType::SITEMAP_INVALIDATED:
|
||||||
|
event["eventtype"] = "sitemap_invalidated";
|
||||||
|
break;
|
||||||
|
case sitemaptemplate::SitemapEventType::SITEMAP_ELEMENT_CHANGED:
|
||||||
|
{
|
||||||
|
const sitemaptemplate::SitemapElementChangedEvent* event2 = static_cast<const sitemaptemplate::SitemapElementChangedEvent*>(e);
|
||||||
|
event["eventtype"] = "sitemap_element_changed";
|
||||||
|
auto elements = Variant::List();
|
||||||
|
for (auto el : event2->elements) {
|
||||||
|
elements.push_back(el.lock()->renderSitemap());
|
||||||
|
}
|
||||||
|
event["elements"] = elements;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!event.IsNull()) {
|
||||||
|
pushEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webresource
|
} // namespace webresource
|
||||||
} // namespace sitemap
|
} // namespace sitemap
|
||||||
} // namespace service
|
} // namespace service
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <hos/cosgi/service/webserver/WebServerService.h>
|
#include <hos/cosgi/service/webserver/WebServerService.h>
|
||||||
#include <hos/cosgi/service/webserver/webresource/WebResourceHandlerImpl.h>
|
#include <hos/cosgi/service/webserver/webresource/WebResourceHandlerImpl.h>
|
||||||
#include <hos/cosgi/service/sitemap/SitemapService.h>
|
#include <hos/cosgi/service/sitemap/SitemapService.h>
|
||||||
|
#include <hos/cosgi/service/sitemap/sitemap_template/SitemapTemplate.h>
|
||||||
#include <hos/utils/FunctionTable.h>
|
#include <hos/utils/FunctionTable.h>
|
||||||
#include <Poco/Net/HTTPRequestHandler.h>
|
#include <Poco/Net/HTTPRequestHandler.h>
|
||||||
#include <Variant/Variant.h>
|
#include <Variant/Variant.h>
|
||||||
@@ -40,8 +41,42 @@ enum class SitemapAPIMethod {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef webserver::webresource::WebResourceEventQueue<
|
||||||
|
interface::Observer<sitemaptemplate::SitemapEventType, sitemaptemplate::SitemapEvent>,
|
||||||
|
SitemapHandlerFactory,
|
||||||
|
SitemapHandler
|
||||||
|
> SitemapEventQueueBase;
|
||||||
|
|
||||||
|
class SitemapEventQueue
|
||||||
|
: public SitemapEventQueueBase {
|
||||||
|
public:
|
||||||
|
sitemaptemplate::SitemapEventType eventType = sitemaptemplate::SitemapEventType::ALL_EVENTS;
|
||||||
|
SitemapService* const sitemapService;
|
||||||
|
sitemaptemplate::SitemapTemplate* sitemap = nullptr;
|
||||||
|
|
||||||
|
SitemapEventQueue( const std::string& clientID,
|
||||||
|
SitemapHandlerFactory* handlerFactory,
|
||||||
|
SitemapService* sitemapService )
|
||||||
|
: WebResourceEventQueue(clientID, handlerFactory), sitemapService(sitemapService) {}
|
||||||
|
virtual ~SitemapEventQueue() {
|
||||||
|
unregisterEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkRegistration(sitemaptemplate::SitemapEventType eventType, sitemaptemplate::SitemapTemplate* sitemap);
|
||||||
|
void registerEvents(sitemaptemplate::SitemapEventType eventType, sitemaptemplate::SitemapTemplate* sitemap = nullptr);
|
||||||
|
void unregisterEvents();
|
||||||
|
|
||||||
|
virtual void notificationReceived( interface::Observer<sitemaptemplate::SitemapEventType, sitemaptemplate::SitemapEvent>::observable_type* o,
|
||||||
|
const sitemaptemplate::SitemapEventType& key,
|
||||||
|
const sitemaptemplate::SitemapEvent* e) noexcept override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SitemapHandlerFactory
|
class SitemapHandlerFactory
|
||||||
: public webserver::webresource::WebResourceHandlerFactoryImpl<SitemapHandlerFactory, false> {
|
: public webserver::webresource::WebResourceHandlerFactoryImpl<SitemapHandlerFactory, false, SitemapEventQueue> {
|
||||||
private:
|
private:
|
||||||
SitemapService* service;
|
SitemapService* service;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
define([
|
||||||
|
"dojo/_base/config",
|
||||||
|
'dojo/_base/declare',
|
||||||
|
"dojo/Deferred",
|
||||||
|
"dojo/dom",
|
||||||
|
"dojo/dom-construct",
|
||||||
|
"dijit/layout/ContentPane",
|
||||||
|
"hos/sitemap/PageElementFactory"
|
||||||
|
], function(config, declare, Deferred, dom, domConstruct, ContentPane, PageElementFactory) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class representing a page.
|
||||||
|
*/
|
||||||
|
var PageClass = declare(null, {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* constructor.
|
||||||
|
*
|
||||||
|
* sitemap: parent sitemap.
|
||||||
|
*
|
||||||
|
* name: page name.
|
||||||
|
*
|
||||||
|
* data: page json object received from server
|
||||||
|
*/
|
||||||
|
constructor: function(/*hos/sitemap/Sitemap*/ sitemap, /*string*/ name, /*json object*/ data) {
|
||||||
|
this.sitemap = sitemap;
|
||||||
|
this.name = name;
|
||||||
|
this.title = data["title"];
|
||||||
|
this.elements = [];
|
||||||
|
var _this = this;
|
||||||
|
data["elements"].forEach(function(data) {
|
||||||
|
var element = PageElementFactory.createPageElement(_this, data);
|
||||||
|
_this.elements.push(element);
|
||||||
|
_this.sitemap.pageElements[element.uid] = element;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/* returns string representation for debugging. */
|
||||||
|
toString: function() {
|
||||||
|
var str = "Page <b>\"" + this.name + "\"<b> {<br> \n";
|
||||||
|
this.elements.forEach(function(e) {
|
||||||
|
str += e.toString() + "<br> \n";
|
||||||
|
});
|
||||||
|
str += "} ";
|
||||||
|
return str;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build the DOM.
|
||||||
|
*/
|
||||||
|
buildDom: function() {
|
||||||
|
var nodes = []
|
||||||
|
this.elements.forEach(function(e) {
|
||||||
|
nodes.push(e.domNode);
|
||||||
|
});
|
||||||
|
this.widget = new ContentPane({
|
||||||
|
title: this.title,
|
||||||
|
id: this.name,
|
||||||
|
content: nodes,
|
||||||
|
style: "height: 100%; width: 100%;"
|
||||||
|
});
|
||||||
|
this.domNode = this.widget.domNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
return PageClass;
|
||||||
|
});
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
define([
|
||||||
|
"dojo/_base/config",
|
||||||
|
'dojo/_base/declare',
|
||||||
|
"dojo/Deferred",
|
||||||
|
"dojo/dom",
|
||||||
|
"dojo/dom-construct",
|
||||||
|
"hos/sitemap/pageelements/FrameElement",
|
||||||
|
"hos/sitemap/pageelements/TextElement",
|
||||||
|
"hos/sitemap/pageelements/SwitchElement",
|
||||||
|
"hos/sitemap/pageelements/SliderElement",
|
||||||
|
"hos/sitemap/pageelements/ErrorElement",
|
||||||
|
], function(
|
||||||
|
config,
|
||||||
|
declare,
|
||||||
|
Deferred,
|
||||||
|
dom,
|
||||||
|
domConstruct,
|
||||||
|
FrameElement,
|
||||||
|
TextElement,
|
||||||
|
SwitchElement,
|
||||||
|
SliderElement,
|
||||||
|
ErrorElement
|
||||||
|
) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class representing a page element factory.
|
||||||
|
*/
|
||||||
|
var ElementFactoryClass = declare(null, {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates and returns a page element.
|
||||||
|
*/
|
||||||
|
createPageElement: function(/*hos/sitemap/Page*/ page, /*json object*/ data, /*hos/sitemap/pageelements/CompositeElement*/ parent) {
|
||||||
|
if (typeof(parent)==='undefined') parent = null;
|
||||||
|
var element = null;
|
||||||
|
if (data["type"] == "sitemap/sitemap#/definitions/frame_element") {
|
||||||
|
element = new FrameElement(page, data, this, parent);
|
||||||
|
} else if (data["type"] == "sitemap/sitemap#/definitions/text_element") {
|
||||||
|
element = new TextElement(page, data, this, parent);
|
||||||
|
} else if (data["type"] == "sitemap/sitemap#/definitions/switch_element") {
|
||||||
|
element = new SwitchElement(page, data, this, parent);
|
||||||
|
} else if (data["type"] == "sitemap/sitemap#/definitions/slider_element") {
|
||||||
|
element = new SliderElement(page, data, this, parent);
|
||||||
|
} else {
|
||||||
|
element = new ErrorElement(page, data, this, parent);
|
||||||
|
}
|
||||||
|
element.buildDom();
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Create and return factory instance. */
|
||||||
|
var factory = new ElementFactoryClass();
|
||||||
|
return factory;
|
||||||
|
});
|
||||||
@@ -0,0 +1,213 @@
|
|||||||
|
define([
|
||||||
|
"dojo/_base/config",
|
||||||
|
'dojo/_base/declare',
|
||||||
|
'dojo/_base/lang',
|
||||||
|
"dojo/dom",
|
||||||
|
"dojo/dom-construct",
|
||||||
|
"dojo/Deferred",
|
||||||
|
"dojox/uuid/generateRandomUuid",
|
||||||
|
"hos/sitemap/Page",
|
||||||
|
"hos/sitemap/widgets/SitemapWidget",
|
||||||
|
"dojox/socket",
|
||||||
|
"dojox/socket/Reconnect",
|
||||||
|
"dojo/request/xhr"
|
||||||
|
], function(
|
||||||
|
config,
|
||||||
|
declare,
|
||||||
|
lang,
|
||||||
|
dom,
|
||||||
|
domConstruct,
|
||||||
|
Deferred,
|
||||||
|
generateRandomUuid,
|
||||||
|
Page,
|
||||||
|
SitemapWidget,
|
||||||
|
Socket,
|
||||||
|
Reconnect,
|
||||||
|
xhr
|
||||||
|
) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class representing a sitemap.
|
||||||
|
*/
|
||||||
|
var SitemapClass = declare(null, {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* api: parent API.
|
||||||
|
*
|
||||||
|
* name: sitemap name.
|
||||||
|
*
|
||||||
|
* data: sitemap json object received from server
|
||||||
|
*/
|
||||||
|
constructor: function(/*hos.sitemap.SitemapAPI*/ api, /*string*/ name, /*json object*/ data) {
|
||||||
|
this.api = api;
|
||||||
|
this.name = name;
|
||||||
|
// parse json data
|
||||||
|
this.rootPageName = data["rootpage"];
|
||||||
|
this.title = data["title"];
|
||||||
|
// Create pages
|
||||||
|
this.pages = {}
|
||||||
|
var _pages = data["pages"];
|
||||||
|
for (var _pageName in _pages) {
|
||||||
|
if (_pages.hasOwnProperty(_pageName)) {
|
||||||
|
var _page = new Page(this, _pageName, _pages[_pageName]);
|
||||||
|
this.pages[_pageName] = _page
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.buildDom();
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dictionary containing all page elements.
|
||||||
|
*/
|
||||||
|
pageElements: {},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stack containing name of visited pages.
|
||||||
|
* Needed for bread crumbs and back button.
|
||||||
|
*/
|
||||||
|
pageNameStack: [],
|
||||||
|
|
||||||
|
/* returns string representation for debugging. */
|
||||||
|
toString: function() {
|
||||||
|
var str = "Sitemap <b>\"" + this.name + "\"<b> {<br> \n";
|
||||||
|
for (var pageName in this.pages) {
|
||||||
|
str += this.pages[pageName].toString() + "<br> \n";
|
||||||
|
}
|
||||||
|
str += "} ";
|
||||||
|
return str;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build the DOM.
|
||||||
|
*/
|
||||||
|
buildDom: function() {
|
||||||
|
this.widget = new SitemapWidget({sitemap: this});
|
||||||
|
for (var pageName in this.pages) {
|
||||||
|
var page = this.pages[pageName];
|
||||||
|
page.buildDom();
|
||||||
|
this.widget.stackContainer.addChild(page.widget);
|
||||||
|
}
|
||||||
|
this.domNode = this.widget.domNode;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Startup function.
|
||||||
|
*/
|
||||||
|
startup: function() {
|
||||||
|
this.widget.startup();
|
||||||
|
this.goToRootPage();
|
||||||
|
this.enableUpdates();
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update the bread crumbs in the ui.
|
||||||
|
*/
|
||||||
|
updateBreadCrumbs: function() {
|
||||||
|
var str = "> " + this.rootPageName;
|
||||||
|
this.pageNameStack.forEach(function(e) {
|
||||||
|
str += " > " + e;
|
||||||
|
});
|
||||||
|
this.widget.setBreadCrumbs(str);
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Go to page with given name.
|
||||||
|
*/
|
||||||
|
goToPage: function(/*string*/ name) {
|
||||||
|
this.pageNameStack.push(name);
|
||||||
|
this.widget.stackContainer.selectChild(name, true);
|
||||||
|
this.updateBreadCrumbs();
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Go to root page.
|
||||||
|
*/
|
||||||
|
goToRootPage: function() {
|
||||||
|
this.pageNameStack = [];
|
||||||
|
this.widget.stackContainer.selectChild(this.rootPageName);
|
||||||
|
this.updateBreadCrumbs();
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Go one page back.
|
||||||
|
*/
|
||||||
|
goBack: function() {
|
||||||
|
if (this.pageNameStack.length > 0) {
|
||||||
|
this.pageNameStack.pop();
|
||||||
|
if (this.pageNameStack.length > 0) {
|
||||||
|
this.goToPage(this.pageNameStack.pop());
|
||||||
|
} else {
|
||||||
|
this.goToRootPage();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Connect to server and listen for updates.
|
||||||
|
*/
|
||||||
|
enableUpdates: function() {
|
||||||
|
this._updateSocketOpened = false;
|
||||||
|
this._updateSocketClientId = generateRandomUuid();
|
||||||
|
this._updateSocket = Reconnect(new Socket({
|
||||||
|
url: config.hos.sitemapUrl + "/" + this.name + '?onevent=all&clientid=' + this._updateSocketClientId,
|
||||||
|
headers: {
|
||||||
|
"On-Event": "changes",
|
||||||
|
/*"Connection-Timeout": 60000,*/
|
||||||
|
"Client-Id": 1234
|
||||||
|
},
|
||||||
|
transport: xhr.post
|
||||||
|
}),{});
|
||||||
|
this._updateSocket.on("open", lang.hitch(this, function(event){
|
||||||
|
this._socketOpened = true;
|
||||||
|
console.log("Socket Opened ", event.message);
|
||||||
|
}));
|
||||||
|
this._updateSocket.on("close", lang.hitch(this, function(event){
|
||||||
|
this._socketOpened = false;
|
||||||
|
console.log("Socket Closed ", event.message);
|
||||||
|
}));
|
||||||
|
this._updateSocket.on("error", lang.hitch(this, function(event){
|
||||||
|
this._socketOpened = false;
|
||||||
|
console.log("Socket Error ", event.message);
|
||||||
|
}));
|
||||||
|
this._updateSocket.on("message", lang.hitch(this, function(event) {
|
||||||
|
var data = JSON.parse(event.data);
|
||||||
|
console.log("Message: " + event);
|
||||||
|
//console.log("Message: " + event.data);
|
||||||
|
if (data && data["eventtype"] == "sitemap_element_changed") {
|
||||||
|
var elements = data["elements"];
|
||||||
|
elements.forEach(lang.hitch(this, function(e) {
|
||||||
|
var uid = e["uid"];
|
||||||
|
if (uid in this.pageElements) {
|
||||||
|
var el = this.pageElements[uid];
|
||||||
|
el.updateData(e);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send command.
|
||||||
|
*/
|
||||||
|
sendPageElementCommand: function(uid, value) {
|
||||||
|
if (this._updateSocket) {
|
||||||
|
var msg = {eventtype: "sitemap_element_command", uid: uid, value: value};
|
||||||
|
xhr.post(config.hos.sitemapUrl + "/" + this.name, {
|
||||||
|
data: {method: 'command', value: JSON.stringify(msg)}
|
||||||
|
}).then(function(data){
|
||||||
|
console.log("sendPageElementCommand ok: " + data)
|
||||||
|
}, function(err){
|
||||||
|
console.log("sendPageElementCommand error: " + err)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
return SitemapClass;
|
||||||
|
});
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
define([
|
||||||
|
"dojo/_base/config",
|
||||||
|
'dojo/_base/declare',
|
||||||
|
"dojo/request/xhr",
|
||||||
|
"dojo/Deferred",
|
||||||
|
"hos/sitemap/Sitemap"
|
||||||
|
], function(config, declare, xhr, Deferred, Sitemap) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class representing the sitemap API.
|
||||||
|
*/
|
||||||
|
var ApiClass = declare(null, {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Constructor.
|
||||||
|
*/
|
||||||
|
constructor: function(/*string*/ baseUrl) {
|
||||||
|
this.baseUrl = baseUrl;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns name of default sitemap.
|
||||||
|
*
|
||||||
|
* returns: Promise(string)
|
||||||
|
*/
|
||||||
|
getDefaultSitemapName: function() {
|
||||||
|
var deferred = new Deferred();
|
||||||
|
xhr.get(this.baseUrl, {
|
||||||
|
handleAs: "json"
|
||||||
|
}).then(function(data){
|
||||||
|
deferred.resolve(data["default"]);
|
||||||
|
}, function(err){
|
||||||
|
deferred.reject(err);
|
||||||
|
});
|
||||||
|
return deferred;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns an array containing the names of all available sitemaps.
|
||||||
|
*
|
||||||
|
* returns: Promise(array(string))
|
||||||
|
*/
|
||||||
|
getSitemapNames: function() {
|
||||||
|
var deferred = new Deferred();
|
||||||
|
xhr.get(this.baseUrl, {
|
||||||
|
handleAs: "json"
|
||||||
|
}).then(function(data){
|
||||||
|
deferred.resolve(data["sitemaps"]);
|
||||||
|
}, function(err){
|
||||||
|
deferred.reject(err);
|
||||||
|
});
|
||||||
|
return deferred;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the sitemap with given name.
|
||||||
|
*
|
||||||
|
* returns: Promise(hos.sitemap.Sitemap)
|
||||||
|
*/
|
||||||
|
getSitemap: function(/*string*/ name) {
|
||||||
|
var deferred = new Deferred();
|
||||||
|
var _this = this
|
||||||
|
xhr.get(this.baseUrl + "/" + name, {
|
||||||
|
handleAs: "json"
|
||||||
|
}).then(function(data){
|
||||||
|
var sitemap = new Sitemap(_this, name, data)
|
||||||
|
deferred.resolve(sitemap);
|
||||||
|
}, function(err){
|
||||||
|
deferred.reject(err);
|
||||||
|
});
|
||||||
|
return deferred;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the default sitemap.
|
||||||
|
*
|
||||||
|
* returns: Promise(hos.sitemap.Sitemap)
|
||||||
|
*/
|
||||||
|
getDefaultSitemap: function() {
|
||||||
|
var deferred = new Deferred();
|
||||||
|
var _this = this
|
||||||
|
this.getDefaultSitemapName().then(function(name){
|
||||||
|
_this.getSitemap(name).then(function(sitemap){
|
||||||
|
deferred.resolve(sitemap);
|
||||||
|
}, function(err){
|
||||||
|
deferred.reject(err);
|
||||||
|
});
|
||||||
|
}, function(err){
|
||||||
|
deferred.reject(err);
|
||||||
|
});
|
||||||
|
return deferred;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Create and returns API instance. */
|
||||||
|
var api = new ApiClass(config.hos.sitemapUrl);
|
||||||
|
return api;
|
||||||
|
});
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
define([
|
||||||
|
"dojo/_base/config",
|
||||||
|
'dojo/_base/declare',
|
||||||
|
"dojo/Deferred",
|
||||||
|
"dojo/dom",
|
||||||
|
"dojo/dom-construct",
|
||||||
|
"hos/sitemap/pageelements/ElementBase"
|
||||||
|
], function(config, declare, Deferred, dom, domConstruct, ElementBase) {
|
||||||
|
|
||||||
|
return declare([ElementBase], {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* constructor.
|
||||||
|
*
|
||||||
|
* page: parent page.
|
||||||
|
*
|
||||||
|
* data: page element json object received from server
|
||||||
|
*
|
||||||
|
* factory: reference to page element factory
|
||||||
|
*
|
||||||
|
* parent: parent page element
|
||||||
|
*/
|
||||||
|
constructor: function(/*hos.sitemap.Page*/ page, /*json object*/ data, /*hos.sitemap.PageElementFactory*/ factory, /*hos/sitemap/pageelements/CompositeElement*/ parent) {
|
||||||
|
this.linkedPageName = data["linkedPage"];
|
||||||
|
this.value = data["value"];
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Go to linked page.
|
||||||
|
*/
|
||||||
|
goToLinkedPage: function() {
|
||||||
|
if (this.linkedPageName) {
|
||||||
|
this.page.sitemap.goToPage(this.linkedPageName);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update data.
|
||||||
|
*/
|
||||||
|
updateData: function(data) {
|
||||||
|
this.inherited(arguments);
|
||||||
|
this.value = data["value"];
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
define([
|
||||||
|
"dojo/_base/config",
|
||||||
|
'dojo/_base/declare',
|
||||||
|
"dojo/Deferred",
|
||||||
|
"dojo/dom",
|
||||||
|
"dojo/dom-construct",
|
||||||
|
"hos/sitemap/pageelements/ElementBase"
|
||||||
|
], function(config, declare, Deferred, dom, domConstruct, ElementBase) {
|
||||||
|
|
||||||
|
return declare([ElementBase], {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* constructor.
|
||||||
|
*
|
||||||
|
* page: parent page.
|
||||||
|
*
|
||||||
|
* data: page element json object received from server
|
||||||
|
*
|
||||||
|
* factory: reference to page element factory
|
||||||
|
*
|
||||||
|
* parent: parent page element
|
||||||
|
*/
|
||||||
|
constructor: function(/*hos.sitemap.Page*/ page, /*json object*/ data, /*hos.sitemap.PageElementFactory*/ factory, /*hos/sitemap/pageelements/CompositeElement*/ parent) {
|
||||||
|
this.elements = []
|
||||||
|
var _this = this;
|
||||||
|
data["elements"].forEach(function(data) {
|
||||||
|
var element = factory.createPageElement(page, data, _this)
|
||||||
|
_this.page.sitemap.pageElements[element.uid] = element;
|
||||||
|
_this.elements.push(element)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
define([
|
||||||
|
"dojo/_base/config",
|
||||||
|
'dojo/_base/declare',
|
||||||
|
"dojo/Deferred",
|
||||||
|
"dojo/dom",
|
||||||
|
"dojo/dom-construct"
|
||||||
|
], function(config, declare, Deferred, dom, domConstruct) {
|
||||||
|
|
||||||
|
return declare(null, {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* constructor.
|
||||||
|
*
|
||||||
|
* page: parent page.
|
||||||
|
*
|
||||||
|
* data: page element json object received from server
|
||||||
|
*
|
||||||
|
* factory: reference to page element factory
|
||||||
|
*
|
||||||
|
* parent: parent page element
|
||||||
|
*/
|
||||||
|
constructor: function(/*hos.sitemap.Page*/ page, /*json object*/ data, /*hos.sitemap.PageElementFactory*/ factory, /*hos/sitemap/pageelements/CompositeElement*/ parent) {
|
||||||
|
this.page = page;
|
||||||
|
this.parent = parent;
|
||||||
|
this.factory = factory;
|
||||||
|
this.uid = data["uid"];
|
||||||
|
this.type = data["type"];
|
||||||
|
this.icon = data["icon"];
|
||||||
|
this.label = data["label"];
|
||||||
|
},
|
||||||
|
|
||||||
|
/* returns string representation for debugging. */
|
||||||
|
toString: function() {
|
||||||
|
return " <b>**Unknown(" + this.uid + ")**</b> ";
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build the DOM.
|
||||||
|
*/
|
||||||
|
buildDom: function() {
|
||||||
|
this.domNode = domConstruct.toDom(this.toString());
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update data.
|
||||||
|
*/
|
||||||
|
updateData: function(data) {
|
||||||
|
this.label = data["label"];
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update DOM.
|
||||||
|
*/
|
||||||
|
updateDom: function() {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
define([
|
||||||
|
"dojo/_base/config",
|
||||||
|
'dojo/_base/declare',
|
||||||
|
"dojo/Deferred",
|
||||||
|
"dojo/dom",
|
||||||
|
"dojo/dom-construct",
|
||||||
|
"hos/sitemap/pageelements/AtomicElement"
|
||||||
|
], function(config, declare, Deferred, dom, domConstruct, AtomicElement) {
|
||||||
|
|
||||||
|
return declare([AtomicElement], {
|
||||||
|
|
||||||
|
/* returns string representation for debugging. */
|
||||||
|
toString: function() {
|
||||||
|
var str = " <b>ErrorElement (" + this.uid + ")</b> ";
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
define([
|
||||||
|
"dojo/_base/config",
|
||||||
|
'dojo/_base/declare',
|
||||||
|
"dojo/Deferred",
|
||||||
|
"dojo/dom",
|
||||||
|
"dojo/dom-construct",
|
||||||
|
"hos/sitemap/pageelements/CompositeElement",
|
||||||
|
"dijit/TitlePane"
|
||||||
|
], function(config, declare, Deferred, dom, domConstruct, CompositeElement, TitlePane) {
|
||||||
|
|
||||||
|
return declare([CompositeElement], {
|
||||||
|
|
||||||
|
/* returns string representation for debugging. */
|
||||||
|
toString: function() {
|
||||||
|
var str = " <b>FrameElement (" + this.uid + ")</b>{<br> \n";
|
||||||
|
this.elements.forEach(function(e) {
|
||||||
|
str += e.toString() + "<br> \n";
|
||||||
|
});
|
||||||
|
str += "} ";
|
||||||
|
return str;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build the DOM.
|
||||||
|
*/
|
||||||
|
buildDom: function() {
|
||||||
|
var nodes = []
|
||||||
|
this.elements.forEach(function(e) {
|
||||||
|
nodes.push(e.domNode);
|
||||||
|
});
|
||||||
|
this.widget = new TitlePane({
|
||||||
|
title:this.label,
|
||||||
|
content:nodes
|
||||||
|
});
|
||||||
|
this.domNode = this.widget.domNode
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
define([
|
||||||
|
"dojo/_base/config",
|
||||||
|
'dojo/_base/declare',
|
||||||
|
'dojo/_base/lang',
|
||||||
|
"dojo/Deferred",
|
||||||
|
"dojo/dom",
|
||||||
|
"dojo/dom-construct",
|
||||||
|
"hos/sitemap/pageelements/AtomicElement",
|
||||||
|
"hos/sitemap/pageelements/widgets/ElementWidget",
|
||||||
|
"dojox/mobile/Slider"
|
||||||
|
], function(config, declare, lang, Deferred, dom, domConstruct, AtomicElement, ElementWidget, Slider) {
|
||||||
|
|
||||||
|
return declare([AtomicElement], {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* constructor.
|
||||||
|
*
|
||||||
|
* page: parent page.
|
||||||
|
*
|
||||||
|
* data: page element json object received from server
|
||||||
|
*
|
||||||
|
* factory: reference to page element factory
|
||||||
|
*
|
||||||
|
* parent: parent page element
|
||||||
|
*/
|
||||||
|
constructor: function(/*hos.sitemap.Page*/ page, /*json object*/ data, /*hos.sitemap.PageElementFactory*/ factory, /*hos/sitemap/pageelements/CompositeElement*/ parent) {
|
||||||
|
this.min = data["min"];
|
||||||
|
this.max = data["max"];
|
||||||
|
},
|
||||||
|
|
||||||
|
/* returns string representation for debugging. */
|
||||||
|
toString: function() {
|
||||||
|
var str = " <b>SliderElement (" + this.uid + ")</b> ";
|
||||||
|
return str;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set Slider value.
|
||||||
|
*/
|
||||||
|
setSliderValue: function(value) {
|
||||||
|
this.value = value/100;
|
||||||
|
this.page.sitemap.sendPageElementCommand(this.uid, this.value);
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build the DOM.
|
||||||
|
*/
|
||||||
|
buildDom: function() {
|
||||||
|
this.widget = new ElementWidget({baseClass: "SliderElementWidget"});
|
||||||
|
/*this.sliderWidget = HorizontalSlider({
|
||||||
|
minimum: this.min,
|
||||||
|
maximum: this.max,
|
||||||
|
value: this.value,
|
||||||
|
onChange: lang.hitch(this, this.setSliderValue)
|
||||||
|
});*/
|
||||||
|
this.sliderWidget = Slider({
|
||||||
|
minimum: this.min*100,
|
||||||
|
maximum: this.max*100,
|
||||||
|
value: this.value*100,
|
||||||
|
style: "width: 95%;",
|
||||||
|
onChange: lang.hitch(this, this.setSliderValue)
|
||||||
|
});
|
||||||
|
this.widget.setValue(this.sliderWidget.domNode);
|
||||||
|
this.updateDom();
|
||||||
|
this.domNode = this.widget.domNode;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update data.
|
||||||
|
*/
|
||||||
|
updateData: function(data) {
|
||||||
|
this.inherited(arguments);
|
||||||
|
this.updateDom();
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update DOM.
|
||||||
|
*/
|
||||||
|
updateDom: function() {
|
||||||
|
if (typeof(this.linkedPageName) != "undefined") {
|
||||||
|
var tmp = domConstruct.create("a",{
|
||||||
|
href: "javascript:void(0)",
|
||||||
|
innerHTML: "<b>" + this.label + "</b>",
|
||||||
|
onclick: lang.hitch(this, this.goToLinkedPage)
|
||||||
|
});
|
||||||
|
this.widget.setLabel(tmp);
|
||||||
|
var tmp2 = domConstruct.create("div",{
|
||||||
|
innerHTML: " >> ",
|
||||||
|
onclick: lang.hitch(this, this.goToLinkedPage)
|
||||||
|
});
|
||||||
|
this.widget.setLink(tmp2);
|
||||||
|
} else {
|
||||||
|
this.widget.setLabel(domConstruct.toDom("<b>" + this.label + "</b>"));
|
||||||
|
}
|
||||||
|
this.sliderWidget.set("value", this.value*100);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
define([
|
||||||
|
"dojo/_base/config",
|
||||||
|
"dojo/_base/lang",
|
||||||
|
"dojo/_base/declare",
|
||||||
|
"dojo/Deferred",
|
||||||
|
"dojo/dom",
|
||||||
|
"dojo/dom-construct",
|
||||||
|
"hos/sitemap/pageelements/AtomicElement",
|
||||||
|
"hos/sitemap/pageelements/widgets/ElementWidget",
|
||||||
|
"dojox/mobile/Switch"
|
||||||
|
], function(config, lang, declare, Deferred, dom, domConstruct, AtomicElement, ElementWidget, Switch) {
|
||||||
|
|
||||||
|
return declare([AtomicElement], {
|
||||||
|
|
||||||
|
/* returns string representation for debugging. */
|
||||||
|
toString: function() {
|
||||||
|
var str = " <b>SwitchElement (" + this.uid + ")</b> ";
|
||||||
|
return str;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build the DOM.
|
||||||
|
*/
|
||||||
|
buildDom: function() {
|
||||||
|
this.widget = new ElementWidget({baseClass: "SwitchElementWidget"});
|
||||||
|
this.buttonWidget = Switch({
|
||||||
|
});
|
||||||
|
this.buttonWidget.on("stateChanged", lang.hitch(this, this.setSwitch));
|
||||||
|
this.widget.setValue(this.buttonWidget.domNode);
|
||||||
|
this.updateDom();
|
||||||
|
this.domNode = this.widget.domNode;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Toggle switch.
|
||||||
|
*/
|
||||||
|
toggleSwitch: function() {
|
||||||
|
this.value = !this.value;
|
||||||
|
this.updateDom();
|
||||||
|
this.page.sitemap.sendPageElementCommand(this.uid, this.value);
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set switch.
|
||||||
|
*/
|
||||||
|
setSwitch: function(value) {
|
||||||
|
this.value = (value == "on");
|
||||||
|
this.updateDom();
|
||||||
|
this.page.sitemap.sendPageElementCommand(this.uid, this.value);
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update data.
|
||||||
|
*/
|
||||||
|
updateData: function(data) {
|
||||||
|
this.inherited(arguments);
|
||||||
|
this.updateDom();
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update DOM.
|
||||||
|
*/
|
||||||
|
updateDom: function() {
|
||||||
|
if (typeof(this.linkedPageName) != "undefined") {
|
||||||
|
var tmp = domConstruct.create("a",{
|
||||||
|
href: "javascript:void(0)",
|
||||||
|
innerHTML: "<b>" + this.label + "</b>",
|
||||||
|
onclick: lang.hitch(this, this.goToLinkedPage)
|
||||||
|
});
|
||||||
|
this.widget.setLabel(tmp);
|
||||||
|
var tmp2 = domConstruct.create("div",{
|
||||||
|
innerHTML: " >> ",
|
||||||
|
onclick: lang.hitch(this, this.goToLinkedPage)
|
||||||
|
});
|
||||||
|
this.widget.setLink(tmp2);
|
||||||
|
} else {
|
||||||
|
this.widget.setLabel(domConstruct.toDom("<b>" + this.label + "</b>"));
|
||||||
|
}
|
||||||
|
this.buttonWidget.set("value", this.value ? "on" : "off");
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
define([
|
||||||
|
"dojo/_base/config",
|
||||||
|
'dojo/_base/declare',
|
||||||
|
"dojo/_base/lang",
|
||||||
|
"dojo/Deferred",
|
||||||
|
"dojo/dom",
|
||||||
|
"dojo/dom-construct",
|
||||||
|
"hos/sitemap/pageelements/AtomicElement",
|
||||||
|
"hos/sitemap/pageelements/widgets/ElementWidget"
|
||||||
|
], function(config, declare, lang, Deferred, dom, domConstruct, AtomicElement, ElementWidget) {
|
||||||
|
|
||||||
|
return declare([AtomicElement], {
|
||||||
|
|
||||||
|
/* returns string representation for debugging. */
|
||||||
|
toString: function() {
|
||||||
|
var str = " <b>TextElement (" + this.uid + ")</b> ";
|
||||||
|
return str;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build the DOM.
|
||||||
|
*/
|
||||||
|
buildDom: function() {
|
||||||
|
this.widget= new ElementWidget({baseClass: "TextElementWidget"});
|
||||||
|
this.updateDom();
|
||||||
|
this.domNode = this.widget.domNode;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update data.
|
||||||
|
*/
|
||||||
|
updateData: function(data) {
|
||||||
|
this.inherited(arguments);
|
||||||
|
this.updateDom();
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update DOM.
|
||||||
|
*/
|
||||||
|
updateDom: function() {
|
||||||
|
if (typeof(this.linkedPageName) != "undefined") {
|
||||||
|
var tmp = domConstruct.create("a",{
|
||||||
|
href: "javascript:void(0)",
|
||||||
|
innerHTML: "<b>" + this.label + "</b>",
|
||||||
|
onclick: lang.hitch(this, this.goToLinkedPage)
|
||||||
|
});
|
||||||
|
this.widget.setLabel(tmp);
|
||||||
|
var tmp2 = domConstruct.create("div",{
|
||||||
|
innerHTML: " >> ",
|
||||||
|
onclick: lang.hitch(this, this.goToLinkedPage)
|
||||||
|
});
|
||||||
|
this.widget.setLink(tmp2);
|
||||||
|
} else {
|
||||||
|
this.widget.setLabel(domConstruct.toDom("<b>" + this.label + "</b>"));
|
||||||
|
}
|
||||||
|
this.widget.setValue(domConstruct.toDom("<b>" + this.value + "</b>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
define([
|
||||||
|
"dojo/_base/declare",
|
||||||
|
"dojo/dom",
|
||||||
|
"dojo/dom-construct",
|
||||||
|
"dijit/_WidgetBase",
|
||||||
|
"dijit/_TemplatedMixin",
|
||||||
|
"dojo/text!./templates/ElementWidget.html"
|
||||||
|
], function(declare, dom, domConstruct, _WidgetBase, _TemplatedMixin, template) {
|
||||||
|
|
||||||
|
return declare([_WidgetBase, _TemplatedMixin], {
|
||||||
|
|
||||||
|
templateString: template,
|
||||||
|
|
||||||
|
setLabel: function(label) {
|
||||||
|
domConstruct.empty(this.domLabelNode);
|
||||||
|
domConstruct.place(label, this.domLabelNode);
|
||||||
|
},
|
||||||
|
|
||||||
|
setValue: function(value) {
|
||||||
|
domConstruct.empty(this.domValueNode);
|
||||||
|
domConstruct.place(value, this.domValueNode);
|
||||||
|
},
|
||||||
|
|
||||||
|
setLink: function(link) {
|
||||||
|
domConstruct.empty(this.domLinkNode);
|
||||||
|
domConstruct.place(link, this.domLinkNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
<div class="${baseClass}" data-dojo-attach-point="domNode" style="background-color: #fcfcfc;">
|
||||||
|
<table class="${baseClass}Table" data-dojo-attach-point="domTableNode" style="width:100%;">
|
||||||
|
<tr>
|
||||||
|
<td class="${baseClass}Icon" data-dojo-attach-point="domIconNode"></td>
|
||||||
|
<td class="${baseClass}Label" data-dojo-attach-point="domLabelNode" style="width: 50%;"></td>
|
||||||
|
<td class="${baseClass}Value" data-dojo-attach-point="domValueNode" style="text-align: right; width: 50%;"></td>
|
||||||
|
<td class="${baseClass}Link" data-dojo-attach-point="domLinkNode"></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
define([
|
||||||
|
"dojo/_base/declare",
|
||||||
|
"dojo/_base/lang",
|
||||||
|
"dojo/dom",
|
||||||
|
"dojo/dom-construct",
|
||||||
|
"dijit/_WidgetBase",
|
||||||
|
"dijit/layout/BorderContainer",
|
||||||
|
"dijit/layout/StackContainer",
|
||||||
|
"dijit/layout/ContentPane",
|
||||||
|
"dijit/form/Button"
|
||||||
|
], function(declare, lang, dom, domConstruct, _WidgetBase, BorderContainer, StackContainer, ContentPane, Button) {
|
||||||
|
|
||||||
|
return declare([_WidgetBase], {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* buildRendering function.
|
||||||
|
*/
|
||||||
|
buildRendering: function() {
|
||||||
|
if(!this._rendered){
|
||||||
|
|
||||||
|
// create a BorderContainer as the top widget in the hierarchy
|
||||||
|
this.bc = new BorderContainer({
|
||||||
|
style: "width: 100%; height: 100%;"
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// create a ContentPane as the left pane in the BorderContainer
|
||||||
|
/*this.cp1 = new ContentPane({
|
||||||
|
region: "left",
|
||||||
|
splitter: true,
|
||||||
|
style: "width: 150px;",
|
||||||
|
content: "<h4>Sitemap/Navigation</h4><ul><li>ToDo</li></ul>"
|
||||||
|
});
|
||||||
|
this.bc.addChild(this.cp1);*/
|
||||||
|
|
||||||
|
this.stackContainer = StackContainer();
|
||||||
|
this.backButton = new Button({
|
||||||
|
label: "Back",
|
||||||
|
onClick: lang.hitch(this, function(){
|
||||||
|
this.sitemap.goBack();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
this.homeButton = new Button({
|
||||||
|
label: "Home",
|
||||||
|
onClick: lang.hitch(this, function(){
|
||||||
|
this.sitemap.goToRootPage();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
// create a ContentPane as the center pane in the BorderContainer
|
||||||
|
this.cp2 = new ContentPane({
|
||||||
|
region: "center",
|
||||||
|
content: [this.stackContainer.domNode, this.backButton.domNode, this.homeButton.domNode]
|
||||||
|
});
|
||||||
|
this.bc.addChild(this.cp2);
|
||||||
|
|
||||||
|
var contentNode = domConstruct.toDom("<b>Home Operating System:</b> <div id=\"breadCrumbNode\">bread crumbs here</div>");
|
||||||
|
this.breadCrumbNode = dom.byId("breadCrumbNode", contentNode)
|
||||||
|
// create a ContentPane as the top pane in the BorderContainer
|
||||||
|
this.cp3 = new ContentPane({
|
||||||
|
region: "top",
|
||||||
|
content: contentNode
|
||||||
|
});
|
||||||
|
this.bc.addChild(this.cp3);
|
||||||
|
|
||||||
|
this.domNode = this.bc.domNode;
|
||||||
|
}
|
||||||
|
this.inherited(arguments);
|
||||||
|
this._rendered = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* startup function.
|
||||||
|
*/
|
||||||
|
startup: function() {
|
||||||
|
this.bc.startup();
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set bread crumbs.
|
||||||
|
*/
|
||||||
|
setBreadCrumbs: function(/*string*/ text) {
|
||||||
|
this.breadCrumbNode.innerHTML=text
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<?php
|
|
||||||
echo 'Hello World! Running on "'.php_uname().'" and time is '.date('Y-m-d H:i:s')."\n";
|
|
||||||
echo "debug1\n";
|
|
||||||
require_once('../index.php');
|
|
||||||
echo "debug2\n";
|
|
||||||
?>
|
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#appLayout {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
#leftCol {
|
||||||
|
width: 14em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .demoLayout .edgePanel {
|
||||||
|
background-color: #d0e9fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#viewsChart {
|
||||||
|
width: 550px;
|
||||||
|
height: 550px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.claro .dijitToggleButtonChecked .dijitButtonNode {
|
||||||
|
background-color: #0090ff;
|
||||||
|
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2) inset;
|
||||||
|
transition-duration: 0.1s;
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Sitemap Test 01</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="libs/dijit/themes/claro/claro.css" media="screen">
|
||||||
|
<link rel="stylesheet" href="libs/dojox/mobile/themes/ios7/ios7.css" media="screen">
|
||||||
|
<link rel="stylesheet" href="sitemap01.css" media="screen">
|
||||||
|
|
||||||
|
<!-- configure Dojo -->
|
||||||
|
<script>
|
||||||
|
var dojoConfig = {
|
||||||
|
async: true,
|
||||||
|
parseOnLoad: true,
|
||||||
|
isDebug: true,
|
||||||
|
deps: [
|
||||||
|
"dojo/parser",
|
||||||
|
"dijit/layout/BorderContainer",
|
||||||
|
"dijit/layout/TabContainer",
|
||||||
|
"dijit/layout/ContentPane",
|
||||||
|
"dijit/Calendar",
|
||||||
|
"dijit/Fieldset",
|
||||||
|
"dijit/TitlePane",
|
||||||
|
"dijit/form/HorizontalSlider",
|
||||||
|
"dijit/form/HorizontalRule",
|
||||||
|
"dijit/form/HorizontalRuleLabels"
|
||||||
|
],
|
||||||
|
hos: {
|
||||||
|
deviceRepoUrl: "/hos/api/devices",
|
||||||
|
sitemapUrl: "/hos/api/sitemap"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- load Dojo -->
|
||||||
|
<script src="libs/dojo/dojo.js"
|
||||||
|
data-dojo-config="async: true"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
|
||||||
|
<body class="claro">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
require([
|
||||||
|
"hos/sitemap/SitemapAPI",
|
||||||
|
"dojo/dom-construct",
|
||||||
|
"dojo/dom",
|
||||||
|
"dojo/domReady!"
|
||||||
|
], function(sitemapAPI, domConstruct, dom) {
|
||||||
|
sitemapAPI.getDefaultSitemap().then(function(sitemap) {
|
||||||
|
domConstruct.place(sitemap.domNode, "contentPane");
|
||||||
|
sitemap.startup();
|
||||||
|
}, function(error) {
|
||||||
|
var node = domConstruct.toDom("<b>Error: " + error + "</b>");
|
||||||
|
domConstruct.place(node, "contentPane");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div id="contentPane" style="width: 100%; height: 100%;"></div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Sitemap Test 01</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="libs/dijit/themes/claro/claro.css" media="screen">
|
||||||
|
<link rel="stylesheet" href="libs/dojox/mobile/themes/ios7/ios7.css" media="screen">
|
||||||
|
<link rel="stylesheet" href="sitemap01.css" media="screen">
|
||||||
|
|
||||||
|
<!-- configure Dojo -->
|
||||||
|
<script>
|
||||||
|
var dojoConfig = {
|
||||||
|
async: true,
|
||||||
|
parseOnLoad: true,
|
||||||
|
isDebug: true,
|
||||||
|
deps: [
|
||||||
|
"dojo/parser",
|
||||||
|
"dijit/layout/BorderContainer",
|
||||||
|
"dijit/layout/TabContainer",
|
||||||
|
"dijit/layout/ContentPane",
|
||||||
|
"dijit/Calendar",
|
||||||
|
"dijit/Fieldset",
|
||||||
|
"dijit/TitlePane",
|
||||||
|
"dijit/form/HorizontalSlider",
|
||||||
|
"dijit/form/HorizontalRule",
|
||||||
|
"dijit/form/HorizontalRuleLabels"
|
||||||
|
],
|
||||||
|
hos: {
|
||||||
|
deviceRepoUrl: "/hos/api/devices",
|
||||||
|
sitemapUrl: "/hos/api/sitemap"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- load Dojo -->
|
||||||
|
<script src="libs/dojo/dojo.js"
|
||||||
|
data-dojo-config="async: true"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
|
||||||
|
<body class="claro">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
require([
|
||||||
|
"hos/sitemap/SitemapAPI",
|
||||||
|
"dojo/dom-construct",
|
||||||
|
"dojo/dom",
|
||||||
|
"dojo/domReady!"
|
||||||
|
], function(sitemapAPI, domConstruct, dom) {
|
||||||
|
sitemapAPI.getSitemap("test02").then(function(sitemap) {
|
||||||
|
domConstruct.place(sitemap.domNode, "contentPane");
|
||||||
|
sitemap.startup();
|
||||||
|
}, function(error) {
|
||||||
|
var node = domConstruct.toDom("<b>Error: " + error + "</b>");
|
||||||
|
domConstruct.place(node, "contentPane");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div id="contentPane" style="width: 100%; height: 100%;"></div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"required": [ "type", "set" ]
|
"required": [ "set" ]
|
||||||
},
|
},
|
||||||
"effect": {
|
"effect": {
|
||||||
"description": "",
|
"description": "",
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"required": [ "type", "set" ]
|
"required": [ "set" ]
|
||||||
},
|
},
|
||||||
"advproperties": {
|
"advproperties": {
|
||||||
"description": "",
|
"description": "",
|
||||||
@@ -64,15 +64,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": true,
|
"additionalProperties": true,
|
||||||
"required": [ "type" ]
|
"required": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{ "required": [ "type", "switch" ] },
|
{ "required": [ "switch" ] },
|
||||||
{ "required": [ "type", "brightness" ] },
|
{ "required": [ "brightness" ] },
|
||||||
{ "required": [ "type", "color" ] },
|
{ "required": [ "color" ] },
|
||||||
{ "required": [ "type", "alert" ] },
|
{ "required": [ "alert" ] },
|
||||||
{ "required": [ "type", "effect" ] }
|
{ "required": [ "effect" ] }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user