Improved sitemap.

This commit is contained in:
2016-03-18 01:52:20 +01:00
parent 0cfd72374b
commit 98297a1f59
20 changed files with 483 additions and 378 deletions
@@ -25,5 +25,5 @@
}
},
"additionalProperties": false,
"required": [ "type", "colormode", "set" ]
"required": [ "colormode", "set" ]
}
+27 -47
View File
@@ -31,17 +31,13 @@
"id": "dummySwitch0",
"pointer": "/switch/value"
},
"commandTemplate": {
"switch": {
"set": null
}
},
"commandValuePointer": "/switch/set"
"commandTemplate": "{\"switch\": {\"set\": %1%}}"
}, {
"type": "sitemap/sitemap_template#/definitions/text_element",
"label": "Slider0",
"icon" : "some_icon01",
"format" : "Value: %1%",
"linkedPage" : "page02",
"device": {
"id": "dummyDimmer0",
"pointer": "/dimmer/value"
@@ -50,6 +46,7 @@
"type": "sitemap/sitemap_template#/definitions/slider_element",
"label": "Slider0",
"icon" : "some_icon03",
"linkedPage" : "page02",
"device": {
"id": "dummyDimmer0",
"pointer": "/dimmer/value"
@@ -57,12 +54,16 @@
"min": 0,
"max": 1,
"step": 0.1,
"commandTemplate": {
"dimmer": {
"set": null
}
},
"commandValuePointer": "/dimmer/set"
"commandTemplate": "{\"dimmer\": {\"set\": %1%}}"
}, {
"type": "sitemap/sitemap_template#/definitions/colorpicker_element",
"label": "color0",
"icon" : "some_icon01",
"linkedPage" : "page02",
"device": {
"id": "dummyDimmer0",
"pointer": "/dimmer/value"
}
}
]
},
@@ -88,12 +89,7 @@
"id": "dummySwitch1",
"pointer": "/switch/value"
},
"commandTemplate": {
"switch": {
"set": null
}
},
"commandValuePointer": "/switch/set"
"commandTemplate": "{\"switch\": {\"set\": %1%}}"
}, {
"type": "sitemap/sitemap_template#/definitions/text_element",
"label": "Slider1",
@@ -114,12 +110,7 @@
"min": 0,
"max": 1,
"step": 0.1,
"commandTemplate": {
"dimmer": {
"set": null
}
},
"commandValuePointer": "/dimmer/set"
"commandTemplate": "{\"dimmer\": {\"set\": %1%}}"
}
]
},
@@ -145,12 +136,7 @@
"id": "dummySwitch2",
"pointer": "/switch/value"
},
"commandTemplate": {
"switch": {
"set": null
}
},
"commandValuePointer": "/switch/set"
"commandTemplate": "{\"switch\": {\"set\": %1%}}"
}, {
"type": "sitemap/sitemap_template#/definitions/text_element",
"label": "Slider2",
@@ -171,12 +157,7 @@
"min": 0,
"max": 1,
"step": 0.1,
"commandTemplate": {
"dimmer": {
"set": null
}
},
"commandValuePointer": "/dimmer/set"
"commandTemplate": "{\"dimmer\": {\"set\": %1%}}"
}
]
},
@@ -202,12 +183,16 @@
"id": "dummySwitch3",
"pointer": "/switch/value"
},
"commandTemplate": {
"switch": {
"set": null
}
"commandTemplate": "{\"switch\": {\"set\": %1%}}"
}, {
"type": "sitemap/sitemap_template#/definitions/switch_element",
"label": "Switch3 fast",
"icon" : "some_icon02",
"device": {
"id": "dummySwitch3",
"pointer": "/switch/value"
},
"commandValuePointer": "/switch/set"
"commandTemplate": "{\"dimmer\": {\"set\": %1%},\"advproperties\": {\"transitiontime\": 1}}"
}, {
"type": "sitemap/sitemap_template#/definitions/text_element",
"label": "Slider3",
@@ -228,12 +213,7 @@
"min": 0,
"max": 1,
"step": 0.1,
"commandTemplate": {
"dimmer": {
"set": null
}
},
"commandValuePointer": "/dimmer/set"
"commandTemplate": "{\"dimmer\": {\"set\": %1%}}"
}
]
}
+26 -46
View File
@@ -20,12 +20,7 @@
"id": "huelight1",
"pointer": "/switch/value"
},
"commandTemplate": {
"switch": {
"set": null
}
},
"commandValuePointer": "/switch/set"
"commandTemplate": "{\"switch\": {\"set\": %1%}}"
}, {
"type": "sitemap/sitemap_template#/definitions/slider_element",
"label": "Lightstrips 1 Slider",
@@ -37,12 +32,18 @@
"min": 0,
"max": 1,
"step": 0.1,
"commandTemplate": {
"brightness": {
"set": null
}
"commandTemplate": "{\"brightness\": {\"set\": %1%}}"
}, {
"type": "sitemap/sitemap_template#/definitions/colorpicker_element",
"label": "color0",
"icon" : "some_icon01",
"linkedPage" : "page02",
"colormode" : "hsv",
"device": {
"id": "huelight1",
"pointer": ["/color/value[0]", "/color/value[1]", "/brightness/value"]
},
"commandValuePointer": "/brightness/set"
"commandTemplate": "{\"color\": {\"set\": [%1%, %2%], \"colormode\": \"hs\"}, \"brightness\": {\"set\": %3%}}"
}
]
}, {
@@ -58,12 +59,7 @@
"id": "huelight2",
"pointer": "/switch/value"
},
"commandTemplate": {
"switch": {
"set": null
}
},
"commandValuePointer": "/switch/set"
"commandTemplate": "{\"switch\": {\"set\": %1%}}"
}, {
"type": "sitemap/sitemap_template#/definitions/slider_element",
"label": "Lightstrips 2 Slider",
@@ -75,12 +71,7 @@
"min": 0,
"max": 1,
"step": 0.1,
"commandTemplate": {
"brightness": {
"set": null
}
},
"commandValuePointer": "/brightness/set"
"commandTemplate": "{\"brightness\": {\"set\": %1%}}"
}
]
}, {
@@ -96,12 +87,16 @@
"id": "huelight3",
"pointer": "/switch/value"
},
"commandTemplate": {
"switch": {
"set": null
}
"commandTemplate": "{\"switch\": {\"set\": %1%}}"
}, {
"type": "sitemap/sitemap_template#/definitions/switch_element",
"label": "ZimmerLampe Switch fast",
"icon" : "some_icon02",
"device": {
"id": "huelight3",
"pointer": "/switch/value"
},
"commandValuePointer": "/switch/set"
"commandTemplate": "{\"switch\": {\"set\": %1%},\"brightness\": {\"set\": 1}, \"advproperties\": {\"transitiontime\": 0}}"
}, {
"type": "sitemap/sitemap_template#/definitions/slider_element",
"label": "ZimmerLampe Slider",
@@ -113,12 +108,7 @@
"min": 0,
"max": 1,
"step": 0.1,
"commandTemplate": {
"brightness": {
"set": null
}
},
"commandValuePointer": "/brightness/set"
"commandTemplate": "{\"brightness\": {\"set\": %1%}}"
}
]
}, {
@@ -134,12 +124,7 @@
"id": "huelight4",
"pointer": "/switch/value"
},
"commandTemplate": {
"switch": {
"set": null
}
},
"commandValuePointer": "/switch/set"
"commandTemplate": "{\"switch\": {\"set\": %1%}}"
}, {
"type": "sitemap/sitemap_template#/definitions/slider_element",
"label": "TischLampe Slider",
@@ -151,12 +136,7 @@
"min": 0,
"max": 1,
"step": 0.1,
"commandTemplate": {
"brightness": {
"set": null
}
},
"commandValuePointer": "/brightness/set"
"commandTemplate": "{\"brightness\": {\"set\": %1%}}"
}
]
}
@@ -119,7 +119,8 @@ enum class ElementType {
// atomic elements
Text,
Switch,
Slider
Slider,
ColorPicker
};
class Element
@@ -169,7 +170,7 @@ public:
virtual std::weak_ptr<Element> getParent() noexcept = 0;
virtual const std::string& getDeviceID() noexcept = 0;
virtual std::weak_ptr<devicerepository::Device> getDevice() noexcept = 0;
virtual const std::string& getPointer() noexcept = 0;
virtual const libvariant::Variant& getPointer() noexcept = 0;
virtual bool deviceExists() noexcept = 0;
virtual void sendCommand(const libvariant::Variant& cmd) = 0;
};
@@ -69,7 +69,8 @@
"anyOf": [
{ "$ref": "#/definitions/text_element" },
{ "$ref": "#/definitions/slider_element" },
{ "$ref": "#/definitions/switch_element" }
{ "$ref": "#/definitions/switch_element" },
{ "$ref": "#/definitions/colorpicker_element" }
]
},
@@ -177,6 +178,20 @@
],
"required": ["type"]
},
"colorpicker_element": {
"allOf": [
{ "$ref": "#/definitions/atomic_element_base" },
{
"properties": {
"type": {
"type": "string",
"pattern": "sitemap/sitemap_template#/definitions/colorpicker_element"
}
}
}
],
"required": ["type"]
},
"device": {
"type": "object",
@@ -185,7 +200,15 @@
"type": "string"
},
"pointer": {
"type": "string"
"anyOf": [
{ "type": "string" },
{
"type": "array",
"items": {
"type": "string"
}
}
]
}
},
"required": ["id"]
@@ -23,7 +23,8 @@ _elementTypeInfo elementTypeInfo[] = {
{ "sitemap/sitemap_template#/definitions/frame_element", "sitemap/sitemap#/definitions/frame_element", ElementType::Frame, true },
{ "sitemap/sitemap_template#/definitions/text_element", "sitemap/sitemap#/definitions/text_element", ElementType::Text, false },
{ "sitemap/sitemap_template#/definitions/slider_element", "sitemap/sitemap#/definitions/slider_element", ElementType::Slider, false },
{ "sitemap/sitemap_template#/definitions/switch_element", "sitemap/sitemap#/definitions/switch_element", ElementType::Switch, false }
{ "sitemap/sitemap_template#/definitions/switch_element", "sitemap/sitemap#/definitions/switch_element", ElementType::Switch, false },
{ "sitemap/sitemap_template#/definitions/colorpicker_element", "sitemap/sitemap#/definitions/colorpicker_element", ElementType::ColorPicker, false }
};
}
@@ -85,22 +86,19 @@ std::weak_ptr<Element> SitemapTemplateImpl::getPageElement(size_t& uid) noexcept
return std::weak_ptr<Element>();
}
std::shared_ptr<DeviceImpl> SitemapTemplateImpl::createDevice(const libvariant::Variant& param, const libvariant::Variant& commandTemplate, const std::string& commandValuePointer) {
std::shared_ptr<DeviceImpl> SitemapTemplateImpl::createDevice(const libvariant::Variant& param, const std::string& commandTemplate) {
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 pointer = param["pointer"];
if (!pointer.IsString() && !pointer.IsList()) {
throw std::runtime_error("pointer is not a string or an array.");
}
auto devRepo = parent.getDeviceRepository();
auto device = devRepo->getDevice(id);
std::shared_ptr<DeviceImpl> newDevice = std::make_shared<DeviceImpl>(id, device, pointer, commandTemplate, commandValuePointer);
std::shared_ptr<DeviceImpl> newDevice = std::make_shared<DeviceImpl>(id, device, pointer, commandTemplate);
devices.insert({id, newDevice});
return newDevice;
}
@@ -180,17 +178,12 @@ std::shared_ptr<ElementImpl> SitemapTemplateImpl::createElement(PageImpl& page,
if (!deviceRaw.IsMap()) {
throw std::runtime_error("device is not a map.");
} else {
libvariant::Variant commandTemplate;
std::string commandValuePointer;
if (param.Contains("commandTemplate")) {
commandTemplate = param["commandTemplate"];
std::string commandTemplate;
if (param.Contains("commandTemplate") && param["commandTemplate"].IsString()) {
commandTemplate = param["commandTemplate"].AsString();
addParams.Erase("commandTemplate");
}
if (param.Contains("commandValuePointer") && param["commandValuePointer"].IsString()) {
commandValuePointer = param["commandValuePointer"].AsString();
addParams.Erase("commandValuePointer");
}
device = createDevice(deviceRaw, commandTemplate, commandValuePointer);
device = createDevice(deviceRaw, commandTemplate);
addParams.Erase("device");
}
}
@@ -214,6 +207,9 @@ std::shared_ptr<ElementImpl> SitemapTemplateImpl::createElement(PageImpl& page,
case ElementType::Switch:
newAElement = std::make_shared<SwitchElementImpl>(page, info->typeString, label, icon, format, device, addParams, parent);
break;
case ElementType::ColorPicker:
newAElement = std::make_shared<ColorPickerElementImpl>(page, info->typeString, label, icon, format, device, addParams, parent);
break;
default:
throw std::runtime_error((boost::format("Registered element type %1% is unknown.") % info->typeName).str());
}
@@ -387,9 +383,25 @@ libvariant::Variant AtomicElementImpl::_getDeviceValue() {
libvariant::Variant devState;
if (device && device->deviceExists()) {
try {
devState = device->getDevice().lock()->getCurrentState();
if (!device->getPointer().empty()) {
devState = devState.GetPath(device->getPointer());
auto devStateRaw = device->getDevice().lock()->getCurrentState();
auto& pointer = device->getPointer();
if (pointer.IsString()) {
auto str = pointer.AsString();
if (!str.empty()) {
devState = devStateRaw.GetPath(str);
} else {
devState = devStateRaw;
}
} else {
devState = libvariant::Variant::List();
for (auto p : pointer.AsList()) {
auto str = p.AsString();
if (!str.empty()) {
devState.Append(devStateRaw.GetPath(str));
} else {
devState.Append(devStateRaw);
}
}
}
} catch (...) {
devState = "NaN";
@@ -407,42 +419,6 @@ libvariant::Variant AtomicElementImpl::_getDeviceValue() {
return devState;
}
libvariant::Variant SliderElementImpl::_getDeviceValue() {
libvariant::Variant devState;
if (device->deviceExists()) {
try {
devState = device->getDevice().lock()->getCurrentState();
if (!device->getPointer().empty()) {
devState = devState.GetPath(device->getPointer());
}
devState = devState.AsDouble();
} catch (...) {
devState = "NaN";
}
} else {
devState = "NaN";
}
return devState;
}
libvariant::Variant SwitchElementImpl::_getDeviceValue() {
libvariant::Variant devState;
if (device->deviceExists()) {
try {
devState = device->getDevice().lock()->getCurrentState();
if (!device->getPointer().empty()) {
devState = devState.GetPath(device->getPointer());
}
devState = devState.AsBool();
} catch (...) {
devState = "NaN";
}
} else {
devState = "NaN";
}
return devState;
}
void DeviceImpl::resolveDevice() noexcept {
if (!parent.expired()) {
auto devRepo = parent.lock()->getPage()->getSiteMap()->getParent()->getDeviceRepository();
@@ -451,10 +427,27 @@ void DeviceImpl::resolveDevice() noexcept {
}
void DeviceImpl::sendCommand(const libvariant::Variant& cmd) {
if (!device.expired() && commandTemplate.IsMap() && !commandValuePointer.empty()) {
if (!device.expired() && !commandTemplate.empty()) {
static void (*_handleArgs)(boost::format& ,const libvariant::Variant&)
= [](boost::format& format ,const libvariant::Variant& arg){
if (arg.IsList()) {
for (auto e : arg.AsList()) {
_handleArgs(format, e);
}
} else if (arg.IsString()) {
format % arg.AsString();
} else if (arg.IsFloat()) {
format % arg.AsDouble();
} else if (arg.IsInt()) {
format % arg.AsInt();
} else if (arg.IsBool()) {
format % (arg.AsBool() ? "true" : "false");
}
};
std::cout << "DeviceImpl::sendCommand: " << libvariant::SerializeJSON(cmd) << std::endl;
auto msg = commandTemplate.Copy();
msg.SetPath(commandValuePointer, cmd);
auto formatobj = boost::format(commandTemplate);
_handleArgs(formatobj, cmd);
auto msg = libvariant::DeserializeYAML(formatobj.str());
device.lock()->sendCommand(msg);
}
}
@@ -71,7 +71,7 @@ public:
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<DeviceImpl> createDevice(const libvariant::Variant& param, const std::string& commandTemplate);
std::shared_ptr<ElementImpl> createElement(PageImpl& page, const libvariant::Variant& param, CompositeElementImpl* parent);
virtual SitemapService* getParent() noexcept override { return dynamic_cast<SitemapService*>(&parent); }
@@ -227,8 +227,6 @@ public:
class SliderElementImpl : public AtomicElementImpl {
private:
virtual libvariant::Variant _getDeviceValue() override;
public:
SliderElementImpl(PageImpl& page, std::string typeStr, const std::string& label, const std::string& icon, const std::string& format,
std::shared_ptr<DeviceImpl> device, libvariant::Variant additionalParams, CompositeElementImpl* parent = nullptr)
@@ -237,8 +235,6 @@ public:
class SwitchElementImpl : public AtomicElementImpl {
private:
virtual libvariant::Variant _getDeviceValue() override;
public:
SwitchElementImpl(PageImpl& page, std::string typeStr, const std::string& label, const std::string& icon, const std::string& format,
std::shared_ptr<DeviceImpl> device, libvariant::Variant additionalParams, CompositeElementImpl* parent = nullptr)
@@ -246,6 +242,14 @@ public:
};
class ColorPickerElementImpl : public AtomicElementImpl {
public:
ColorPickerElementImpl(PageImpl& page, std::string typeStr, const std::string& label, const std::string& icon, const std::string& format,
std::shared_ptr<DeviceImpl> device, libvariant::Variant additionalParams, CompositeElementImpl* parent = nullptr)
: AtomicElementImpl(page, ElementType::ColorPicker, typeStr, label, icon, format, device, additionalParams, parent) {}
};
class DeviceImpl
: public virtual Device,
@@ -253,14 +257,13 @@ class DeviceImpl
private:
std::string deviceID;
std::weak_ptr<devicerepository::Device> device;
std::string pointer;
libvariant::Variant pointer;
std::weak_ptr<ElementImpl> parent;
libvariant::Variant commandTemplate;
std::string commandValuePointer;
std::string commandTemplate;
public:
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), commandTemplate(commandTemplate), commandValuePointer(commandValuePointer) {}
DeviceImpl(const std::string& deviceID, std::weak_ptr<devicerepository::Device> device, const libvariant::Variant& pointer, const std::string& commandTemplate)
: deviceID(deviceID), device(device), pointer(pointer), commandTemplate(commandTemplate) {}
virtual std::weak_ptr<Element> getParent() noexcept override { return parent; }
void setParent(std::weak_ptr<ElementImpl> parent) noexcept { this->parent = parent; }
@@ -269,7 +272,7 @@ public:
virtual const std::string& getDeviceID() noexcept override { return deviceID; }
virtual std::weak_ptr<devicerepository::Device> getDevice() noexcept override { return device; }
virtual const std::string& getPointer() noexcept override { return pointer; }
virtual const libvariant::Variant& getPointer() noexcept override { return pointer; }
virtual bool deviceExists() noexcept override { return !device.expired(); }
virtual void sendCommand(const libvariant::Variant& cmd) override;
};
@@ -1,12 +1,17 @@
define([
"dojo/_base/config",
'dojo/_base/declare',
'dojo/_base/lang',
"dojo/Deferred",
"dojo/dom",
"dojo/dom-construct",
"dojo/dom-style",
"dijit/layout/ContentPane",
"hos/sitemap/PageElementFactory"
], function(config, declare, Deferred, dom, domConstruct, ContentPane, PageElementFactory) {
"hos/sitemap/PageElementFactory",
"dojox/mobile/View",
"dojox/mobile/Pane",
"dojox/mobile/EdgeToEdgeList"
], function(config, declare, lang, Deferred, dom, domConstruct, domStyle, ContentPane, PageElementFactory, View, Pane, EdgeToEdgeList) {
/*
* Class representing a page.
@@ -35,30 +40,19 @@ define([
});
},
/* 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.widget = new View({
id: this.name
});
this.elementList = new EdgeToEdgeList();
this.elements.forEach(lang.hitch(this, function(e) {
this.elementList.addChild(e);
}));
this.widget.addChild(this.elementList);
this.domNode = this.widget.domNode;
}
@@ -8,6 +8,7 @@ define([
"hos/sitemap/pageelements/TextElement",
"hos/sitemap/pageelements/SwitchElement",
"hos/sitemap/pageelements/SliderElement",
"hos/sitemap/pageelements/ColorPickerElement",
"hos/sitemap/pageelements/ErrorElement",
], function(
config,
@@ -19,6 +20,7 @@ define([
TextElement,
SwitchElement,
SliderElement,
ColorPickerElement,
ErrorElement
) {
@@ -41,6 +43,8 @@ define([
element = new SwitchElement(page, data, this, parent);
} else if (data["type"] == "sitemap/sitemap#/definitions/slider_element") {
element = new SliderElement(page, data, this, parent);
} else if (data["type"] == "sitemap/sitemap#/definitions/colorpicker_element") {
element = new ColorPickerElement(page, data, this, parent);
} else {
element = new ErrorElement(page, data, this, parent);
}
@@ -44,7 +44,6 @@ define([
this.api = api;
this.name = name;
// parse json data
this.rootPageName = data["rootpage"];
this.title = data["title"];
// Create pages
this.pages = {}
@@ -55,39 +54,32 @@ define([
this.pages[_pageName] = _page
}
}
rootPageName = data["rootpage"];
this.rootPage = this.pages[rootPageName];
this.buildDom();
},
/*
* Dictionary containing all page elements.
*/
pageElements: {},
rootPage: null,
/*
* Stack containing name of visited pages.
* Stack containing visited pages.
* Needed for bread crumbs and back button.
*/
pageNameStack: [],
pageStack: [],
/* 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;
},
pageElements: {},
/*
* Build the DOM.
*/
buildDom: function() {
this.widget = new SitemapWidget({sitemap: this});
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.widget.addPage(page);
}
this.domNode = this.widget.domNode;
},
@@ -97,36 +89,55 @@ define([
*/
startup: function() {
this.widget.startup();
this.goToRootPage();
this.widget.showPage(this.rootPage);
this.updateBreadCrumbs();
this.enableUpdates();
},
getCurrentPage() {
if (this.pageStack.length > 0) {
return this.pageStack[this.pageStack.length-1];
} else {
return this.rootPage;
}
},
/*
* Update the bread crumbs in the ui.
*/
updateBreadCrumbs: function() {
var str = "> " + this.rootPageName;
this.pageNameStack.forEach(function(e) {
str += " > " + e;
});
this.widget.setBreadCrumbs(str);
var pages = [ this.rootPage ];
if (this.pageStack.length > 0) {
this.widget.setTitle(this.title + ": " + this.getCurrentPage().title);
this.widget.setBackButtonVisibility(true);
pages = pages.concat(this.pageStack);
} else {
this.widget.setTitle(this.title);
this.widget.setBackButtonVisibility(false);
}
this.widget.setBreadCrumbs(pages);
},
/*
* Go to page with given name.
*/
goToPage: function(/*string*/ name) {
this.pageNameStack.push(name);
this.widget.stackContainer.selectChild(name, true);
this.updateBreadCrumbs();
var page = this.pages[name];
if (page) {
this.widget.goToPage(page, 1);
this.pageStack.push(page);
this.updateBreadCrumbs();
return true;
}
return false;
},
/*
* Go to root page.
*/
goToRootPage: function() {
this.pageNameStack = [];
this.widget.stackContainer.selectChild(this.rootPageName);
this.widget.goToPage(this.rootPage, -99);
this.pageStack = [];
this.updateBreadCrumbs();
},
@@ -134,13 +145,14 @@ define([
* 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();
if (this.pageStack.length > 0) {
var bp = this.rootPage;
if (this.pageStack.length > 1) {
bp = this.pageStack[this.pageStack.length-2];
}
this.widget.goToPage(bp, -1);
this.pageStack.pop();
this.updateBreadCrumbs();
return true;
} else {
return false;
@@ -195,16 +207,14 @@ define([
* 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)
});
}
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)
});
}
});
@@ -0,0 +1,71 @@
define([
"dojo/_base/config",
"dojo/_base/lang",
"dojo/_base/declare",
"dojo/Deferred",
"dojo/dom",
"dojo/dom-construct",
"hos/sitemap/pageelements/AtomicElement",
"dojox/mobile/Button",
"dojox/mobile/ListItem",
"dojox/mobile/Overlay",
"dojox/widget/ColorPicker",
"dojox/color"
], function(config, lang, declare, Deferred, dom, domConstruct, AtomicElement, Button, ListItem, Overlay, ColorPicker, Color) {
return declare([AtomicElement], {
/* returns string representation for debugging. */
toString: function() {
var str = " <b>SwitchElement (" + this.uid + ")</b> ";
return str;
},
setColor: function(h, s, v) {
this.page.sitemap.sendPageElementCommand(this.uid, [h, s, v]);
},
/*
* Build the DOM.
*/
buildDom: function() {
this.widget = new ListItem({
label: this.label,
onClick: lang.hitch(this, function() {
this.goToLinkedPage();
}),
variableHeight: true
});
this.colorWidget = ColorPicker({
"class": "mblListItemLayoutRight",
onChange: lang.hitch(this, function(hex){
var color = Color.fromHex(hex).toHsv();
this.setColor(color["h"]/359, color["s"]/100, color["v"]/100);
})
});
this.widget.addChild(this.colorWidget, 0);
this.updateDom();
this.domNode = this.widget.domNode;
},
/*
* Update data.
*/
updateData: function(data) {
this.inherited(arguments);
this.updateDom();
},
/*
* Update DOM.
*/
updateDom: function() {
this.widget.set("label", this.label);
var color = Color.fromHsv(this.value[0]*359, this.value[1]*100, this.value[2]*100);
console.log("Color: " + color.toHex());
this.colorWidget.setColor(color.toHex(), false);
}
});
});
@@ -1,11 +1,12 @@
define([
"dojo/_base/config",
'dojo/_base/declare',
'dojo/_base/lang',
"dojo/Deferred",
"dojo/dom",
"dojo/dom-construct",
"hos/sitemap/pageelements/ElementBase"
], function(config, declare, Deferred, dom, domConstruct, ElementBase) {
], function(config, declare, lang, Deferred, dom, domConstruct, ElementBase) {
return declare([ElementBase], {
@@ -22,12 +23,11 @@ define([
*/
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)
});
data["elements"].forEach(lang.hitch(this, function(data) {
var element = factory.createPageElement(page, data, this)
this.page.sitemap.pageElements[element.uid] = element;
this.elements.push(element)
}));
}
});
@@ -1,12 +1,16 @@
define([
"dojo/_base/config",
'dojo/_base/declare',
'dojo/_base/lang',
"dojo/Deferred",
"dojo/dom",
"dojo/dom-construct",
"dojo/dom-style",
"hos/sitemap/pageelements/CompositeElement",
"dijit/TitlePane"
], function(config, declare, Deferred, dom, domConstruct, CompositeElement, TitlePane) {
"dojox/mobile/RoundRectList",
"dojox/mobile/Pane",
"dojox/mobile/ListItem"
], function(config, declare, lang, Deferred, dom, domConstruct, domStyle, CompositeElement, RoundRectList, Pane, ListItem) {
return declare([CompositeElement], {
@@ -24,14 +28,21 @@ define([
* Build the DOM.
*/
buildDom: function() {
var nodes = []
this.elements.forEach(function(e) {
nodes.push(e.domNode);
this.widget = Pane();
//this.heading = domConstruct.toDom("<div style=\"padding-left: 40px;\"><b>" + this.label + "</b></div>");
//domConstruct.place(this.heading, this.widget.domNode);
this.elementList = new RoundRectList({
baseClass: "mblRoundRectList"
});
this.widget = new TitlePane({
title:this.label,
content:nodes
this.headerItem = new ListItem({
label: this.label,
header: true
});
this.elementList.addChild(this.headerItem);
this.elements.forEach(lang.hitch(this, function(e) {
this.elementList.addChild(e);
}));
domConstruct.place(this.elementList.domNode, this.widget.domNode);
this.domNode = this.widget.domNode
}
@@ -6,9 +6,9 @@ define([
"dojo/dom",
"dojo/dom-construct",
"hos/sitemap/pageelements/AtomicElement",
"hos/sitemap/pageelements/widgets/ElementWidget",
"dojox/mobile/ListItem",
"dojox/mobile/Slider"
], function(config, declare, lang, Deferred, dom, domConstruct, AtomicElement, ElementWidget, Slider) {
], function(config, declare, lang, Deferred, dom, domConstruct, AtomicElement, ListItem, Slider) {
return declare([AtomicElement], {
@@ -46,21 +46,26 @@ define([
* 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.widget = new ListItem({
label: this.label,
onClick: lang.hitch(this, function() {
this.goToLinkedPage();
})
});
this.sliderWidget = Slider({
minimum: this.min*100,
maximum: this.max*100,
value: this.value*100,
style: "width: 95%;",
onChange: lang.hitch(this, this.setSliderValue)
onClick: lang.hitch(this, function() {
console.log("onClick");
}),
onChange: lang.hitch(this, this.setSliderValue),
style: {
width: "40%"
},
"data-mobile-layout": "right"
});
this.widget.setValue(this.sliderWidget.domNode);
this.widget.addChild(this.sliderWidget, 0);
this.updateDom();
this.domNode = this.widget.domNode;
},
@@ -77,22 +82,13 @@ define([
* 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: " &gt;&gt; ",
onclick: lang.hitch(this, this.goToLinkedPage)
});
this.widget.setLink(tmp2);
this.widget.set("label", this.label);
this.sliderWidget.set("value", this.value*100, false);
if (this.linkedPageName) {
this.widget.set("clickable", true);
} else {
this.widget.setLabel(domConstruct.toDom("<b>" + this.label + "</b>"));
this.widget.set("clickable", false);
}
this.sliderWidget.set("value", this.value*100);
}
});
@@ -6,9 +6,9 @@ define([
"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) {
"dojox/mobile/Switch",
"dojox/mobile/ListItem"
], function(config, lang, declare, Deferred, dom, domConstruct, AtomicElement, Switch, ListItem) {
return declare([AtomicElement], {
@@ -22,11 +22,22 @@ define([
* Build the DOM.
*/
buildDom: function() {
this.widget = new ElementWidget({baseClass: "SwitchElementWidget"});
this.buttonWidget = Switch({
this.widget = new ListItem({
label: this.label,
onClick: lang.hitch(this, function() {
this.goToLinkedPage();
})
});
this.buttonWidget.on("stateChanged", lang.hitch(this, this.setSwitch));
this.widget.setValue(this.buttonWidget.domNode);
this.buttonWidget = Switch({
onClick: lang.hitch(this, function() {
this.setSwitch(this.buttonWidget.get("value") == "on" ? "off" : "on");
return false;
}),
style: {
"margin-right": "30px"
}
});
this.widget.addChild(this.buttonWidget);
this.updateDom();
this.domNode = this.widget.domNode;
},
@@ -37,7 +48,11 @@ define([
toggleSwitch: function() {
this.value = !this.value;
this.updateDom();
this.page.sitemap.sendPageElementCommand(this.uid, this.value);
if (this.page.sitemap.sendPageElementCommand(this.uid, this.value)) {
return true;
} else {
return false;
}
},
/*
@@ -46,7 +61,11 @@ define([
setSwitch: function(value) {
this.value = (value == "on");
this.updateDom();
this.page.sitemap.sendPageElementCommand(this.uid, this.value);
if (this.page.sitemap.sendPageElementCommand(this.uid, this.value)) {
return true;
} else {
return false;
}
},
/*
@@ -61,22 +80,13 @@ define([
* 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: " &gt;&gt; ",
onclick: lang.hitch(this, this.goToLinkedPage)
});
this.widget.setLink(tmp2);
this.widget.set("label", this.label);
this.buttonWidget.set("value", this.value ? "on" : "off", false);
if (this.linkedPageName) {
this.widget.set("clickable", true);
} else {
this.widget.setLabel(domConstruct.toDom("<b>" + this.label + "</b>"));
this.widget.set("clickable", false);
}
this.buttonWidget.set("value", this.value ? "on" : "off");
}
});
@@ -6,8 +6,8 @@ define([
"dojo/dom",
"dojo/dom-construct",
"hos/sitemap/pageelements/AtomicElement",
"hos/sitemap/pageelements/widgets/ElementWidget"
], function(config, declare, lang, Deferred, dom, domConstruct, AtomicElement, ElementWidget) {
"dojox/mobile/ListItem"
], function(config, declare, lang, Deferred, dom, domConstruct, AtomicElement, ListItem) {
return declare([AtomicElement], {
@@ -21,7 +21,13 @@ define([
* Build the DOM.
*/
buildDom: function() {
this.widget= new ElementWidget({baseClass: "TextElementWidget"});
this.widget = new ListItem({
label: this.label,
rightText: this.value,
onClick: lang.hitch(this, function() {
this.goToLinkedPage();
})
});
this.updateDom();
this.domNode = this.widget.domNode;
},
@@ -38,22 +44,13 @@ define([
* 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: " &gt;&gt; ",
onclick: lang.hitch(this, this.goToLinkedPage)
});
this.widget.setLink(tmp2);
this.widget.set("label", this.label);
this.widget.set("rightText", this.value);
if (this.linkedPageName) {
this.widget.set("clickable", true);
} else {
this.widget.setLabel(domConstruct.toDom("<b>" + this.label + "</b>"));
this.widget.set("clickable", false);
}
this.widget.setValue(domConstruct.toDom("<b>" + this.value + "</b>"));
}
});
@@ -3,66 +3,75 @@ define([
"dojo/_base/lang",
"dojo/dom",
"dojo/dom-construct",
"dojo/dom-style",
"dijit/_WidgetBase",
"dijit/layout/BorderContainer",
"dijit/layout/StackContainer",
"dijit/layout/ContentPane",
"dijit/form/Button"
], function(declare, lang, dom, domConstruct, _WidgetBase, BorderContainer, StackContainer, ContentPane, Button) {
"dojox/mobile/ScrollablePane",
"dojox/mobile/Container",
"dojox/mobile/Heading",
"dojox/mobile/ScrollablePane",
"dojox/mobile/ToolBarButton",
"dojox/mobile/RoundRect"
], function(declare, lang, dom, domConstruct, domStyle, _WidgetBase, ScrollablePane, Container, Heading, ScrollablePane, ToolBarButton, RoundRect) {
return declare([_WidgetBase], {
/*
*
*/
addPage: function(page) {
this.widget.addChild(page.widget);
},
/*
*
*/
goToPage: function(page, direction) {
var curpage = this.sitemap.getCurrentPage();
curpage.widget.performTransition(page.name, direction, "slide");
},
showPage: function(page, noEvents) {
page.widget.show(noEvents);
},
/*
* 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({
this.scrollPane = new ScrollablePane({
scrollableParams: {
scrollBar: true,
scrollDir: "v"
}
});
this.widget = new Container();
this.widget.placeAt(this.scrollPane);
this.h1 = new Heading({
label: this.sitemap.title
});
this.backButton = new ToolBarButton({
arrow: "left",
label: "Back",
onClick: lang.hitch(this, function(){
this.sitemap.goBack();
})
});
this.homeButton = new Button({
onClick: lang.hitch(this.sitemap, this.sitemap.goBack)
});
this.backButton.placeAt(this.h1.domNode);
this.homeButton = new ToolBarButton({
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);
onClick: lang.hitch(this.sitemap, this.sitemap.goToRootPage)
});
this.homeButton.placeAt(this.h1.domNode);
this.widget.addChild(this.h1);
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.breadCrumbs = new RoundRect({
innerHTML: "Bread crumbs here",
shadows: true
});
this.widget.addChild(this.breadCrumbs);
this.domNode = this.bc.domNode;
this.domNode = this.scrollPane.domNode;
}
this.inherited(arguments);
this._rendered = true;
@@ -72,14 +81,27 @@ define([
* startup function.
*/
startup: function() {
this.bc.startup();
this.scrollPane.startup();
},
setTitle: function(title) {
this.h1.set("label", title);
},
/*
* Set bread crumbs.
*/
setBreadCrumbs: function(/*string*/ text) {
this.breadCrumbNode.innerHTML=text
setBreadCrumbs: function(/*array*/ pages) {
var text = "";
pages.forEach(lang.hitch(this, function(p){
text += "> " + p.title + " ";
}));
this.breadCrumbs.set("innerHTML", text);
},
setBackButtonVisibility: function(value) {
domStyle.set(this.backButton.domNode, "display", value ? "" : "none");
domStyle.set(this.homeButton.domNode, "display", value ? "" : "none");
}
});
@@ -2,11 +2,14 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no"/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<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">
<!-- <link rel="stylesheet" href="libs/dijit/themes/claro/claro.css" media="screen">
<link rel="stylesheet" href="libs/dojox/mobile/themes/android/android.css" media="screen">
<link rel="stylesheet" href="sitemap01.css" media="screen"> -->
<!-- configure Dojo -->
<script>
@@ -2,11 +2,14 @@
<html>
<head>
<meta charset="utf-8">
<title>Sitemap Test 01</title>
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no"/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<title>Sitemap Test 02</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">
<!-- <link rel="stylesheet" href="libs/dijit/themes/claro/claro.css" media="screen">
<link rel="stylesheet" href="libs/dojox/mobile/themes/android/android.css" media="screen">
<link rel="stylesheet" href="sitemap01.css" media="screen"> -->
<!-- configure Dojo -->
<script>
@@ -33,7 +33,7 @@ class HueController(object):
self.cmd_topic = rospy.get_param('~cmd_topic', "/hos/devices/cmd")
self.hos_update_topic = rospy.get_param('~hos_update_topic', "/hos/status/updates")
self.loop_frequency = rospy.get_param('~loop_frequency', 100)
self.statusmsg_interval = rospy.get_param('~statusmsg_interval', 6000000)
self.statusmsg_interval = rospy.get_param('~statusmsg_interval', 5000)
self.bridge_ip = rospy.get_param('~bridge_ip', "192.168.168.90")
self.bridge_secret = rospy.get_param('~bridge_secret', "matzman666")
self.device_name_base = rospy.get_param('~device_name_base', "huelight")
@@ -122,6 +122,10 @@ class HueController(object):
validator.validate(msg_body)
msg.msg_body = json.dumps(msg_body)
print "==== HOS Status Msg Start ===="
print msg_body
print "==== HOS Status Msg End ===="
return msg