This commit is contained in:
2015-10-17 04:30:26 +02:00
parent 7f3395ce7e
commit 8894fe5880
9 changed files with 520 additions and 2 deletions
+6
View File
@@ -55,6 +55,7 @@ bundle(hos_cosgi_sitemap
${PROJECT_SOURCE_DIR}/src/BundleActivator
${PROJECT_SOURCE_DIR}/src/hos/cosgi/service/sitemap/SitemapServiceImpl
${PROJECT_SOURCE_DIR}/src/hos/cosgi/service/sitemap/webresource/SitemapHandler
${PROJECT_SOURCE_DIR}/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplate
)
target_link_libraries(hos_cosgi_sitemap
@@ -85,6 +86,11 @@ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc
OPTIONAL
)
foreach(dir launch schema examples)
install(DIRECTORY ${dir}/
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/${dir}
)
endforeach(dir)
###################
@@ -0,0 +1,35 @@
{
"type": "sitemap/sitemap_template",
"title": "TestApp",
"rootpage": {
"type": "sitemap/sitemap_template#/definitions/page",
"title": "Root Page",
"elements": [
{
"type": "sitemap/sitemap_template#/definitions/text_element",
"label": "Switch0 Text",
"device": {
"id": "dummySwitch0",
"pointer": ""
}
}, {
"type": "sitemap/sitemap_template#/definitions/switch_element",
"label": "Switch0",
"device": {
"id": "dummySwitch0",
"pointer": ""
}
}, {
"type": "sitemap/sitemap_template#/definitions/slider_element",
"label": "Slider0",
"device": {
"id": "dummySlider0",
"pointer": ""
},
"min": 0,
"max": 1,
"step": 0.1
}
]
}
}
@@ -0,0 +1,9 @@
<launch>
<group ns="/hos/sitemap/sitemap_templates">
<param name="test01" textfile="$(find hos_cosgi_sitemap)/examples/test01.json"/>
</group>
<group ns="/hos/types/repository/sitemap">
<param name="sitemap_template" textfile="$(find hos_cosgi_sitemap)/schema/sitemap/sitemap_template.json"/>
</group>
</launch>
@@ -0,0 +1,179 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Sitemap Template Schema",
"description": "",
"version": "1.0.0",
"type": "object",
"properties": {
"type": {
"type": "string",
"pattern": "sitemap/sitemap_template"
},
"title": {
"type": "string",
"description": ""
},
"rootpage": {
"$ref": "#/definitions/page"
}
},
"additionalProperties": false,
"required": ["title", "rootpage"],
"definitions": {
"page": {
"type": "object",
"properties": {
"type": {
"type": "string",
"pattern": "sitemap/sitemap_template#/definitions/page"
},
"title": {
"type": "string"
},
"elements": {
"type": "array",
"items": {
"$ref": "#/definitions/element"
}
}
},
"additionalProperties": false,
"required": ["title", "elements"]
},
"element": {
"anyOf": [
{ "$ref": "#/definitions/composite_element" },
{ "$ref": "#/definitions/atomic_element" }
]
},
"composite_element": {
"anyOf": [
{ "$ref": "#/definitions/frame_element" }
]
},
"atomic_element": {
"anyOf": [
{ "$ref": "#/definitions/text_element" },
{ "$ref": "#/definitions/slider_element" },
{ "$ref": "#/definitions/switch_element" }
]
},
"composite_element_base": {
"type": "object",
"properties": {
"label": {
"type": "string"
},
"icon": {
"type": "string"
},
"elements": {
"type": "array",
"items": {
"$ref": "#/definitions/element"
}
}
},
"required": ["elements"]
},
"frame_element": {
"allOf": [
{ "$ref": "#/definitions/composite_element_base" },
{
"properties": {
"type": {
"type": "string",
"pattern": "sitemap/sitemap_template#/definitions/frame_element"
}
}
}
],
"required": ["type"]
},
"atomic_element_base": {
"type": "object",
"properties": {
"label": {
"type": "string"
},
"format": {
"type": "string"
},
"device": {
"$ref": "#/definitions/device"
},
"icon": {
"type": "string"
}
}
},
"text_element": {
"allOf": [
{ "$ref": "#/definitions/atomic_element_base" },
{
"properties": {
"type": {
"type": "string",
"pattern": "sitemap/sitemap_template#/definitions/text_element"
}
}
}
],
"required": ["type"]
},
"slider_element": {
"allOf": [
{ "$ref": "#/definitions/atomic_element_base" },
{
"properties": {
"type": {
"type": "string",
"pattern": "sitemap/sitemap_template#/definitions/slider_element"
},
"min": {
"type": "number"
},
"max": {
"type": "number"
},
"step": {
"type": "number"
}
}
}
],
"required": ["type"]
},
"switch_element": {
"allOf": [
{ "$ref": "#/definitions/atomic_element_base" },
{
"properties": {
"type": {
"type": "string",
"pattern": "sitemap/sitemap_template#/definitions/switch_element"
}
}
}
],
"required": ["type"]
},
"device": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"pointer": {
"type": "string"
}
},
"required": ["id"]
}
}
}
@@ -19,6 +19,7 @@ namespace cosgi {
namespace service {
namespace sitemap {
using namespace libvariant;
// Service information
HOS_SERVICE_IMPL_INFO( SitemapServiceImpl, // Implementation
@@ -54,11 +55,68 @@ void SitemapServiceImpl::setRepoService(devicerepository::DeviceRepositoryServic
void SitemapServiceImpl::init() noexcept {
// Get public parameters
nodehandle->getParam("sitemap_template_prefix", sitemapTemplatePrefix);
nodehandle->getParam("hos_status_topic", hosStatusTopic);
// Parse sitemaps
XmlRpc::XmlRpcValue rawValue;
nodehandle->getParam(sitemapTemplatePrefix, rawValue);
if (rawValue.getType() == XmlRpc::XmlRpcValue::TypeStruct) {
for (auto dev : rawValue) {
std::string sitemapName = dev.first;
XmlRpc::XmlRpcValue devRaw = dev.second;
try {
addSitemap(sitemapName, devRaw);
ROS_INFO_STREAM("Created sitemap " << sitemapName << ".");
} catch (std::exception& e) {
ROS_ERROR_STREAM("Could not create sitemap " << sitemapName << ": " << e.what());
}
}
}
initialized = true;
ROS_INFO_STREAM("RuleEngineService: Initialized and Ready.");
}
void SitemapServiceImpl::addSitemap(const std::string& name, XmlRpc::XmlRpcValue& rawValue) {
std::lock_guard<std::recursive_mutex> lock(serviceMutex);
if (rawValue.getType() != XmlRpc::XmlRpcValue::TypeString) {
throw std::runtime_error("sitemap config value is not a string.");
}
std::string strValue = static_cast<std::string>(rawValue);
libvariant::Variant value = libvariant::DeserializeJSON(strValue);
Variant schema;
try {
schema = coreService->getSchemaLoader().GetSchema("hos:schema://sitemap/sitemap_template");
} catch(std::exception& e) {
std::stringstream ss;
ss << "Could not load hos:schema://sitemap/sitemap_template: " << e.what();
throw std::runtime_error(ss.str());
}
SchemaResult sr = SchemaValidate(schema, value, &coreService->getSchemaLoader());
if (!sr.Error()) {
auto titleRaw = value["title"];
if (!titleRaw.IsString()) {
throw std::runtime_error("title is not a string.");
}
std::string title = titleRaw.AsString();
auto rootpage = value["rootpage"];
if (!rootpage.IsMap()) {
throw std::runtime_error("rootpage is not a map.");
}
std::shared_ptr<sitemaptemplate::SitemapTemplate> st = std::make_shared<sitemaptemplate::SitemapTemplate>(title);
st->createPage(rootpage);
sitemapTemplates.insert({name, st});
} else {
std::stringstream ss;
ss << "Could not validate sitemap config value: " << sr.PrettyPrintMessage();
throw std::runtime_error(ss.str());
}
}
} /* namespace sitemap */
} /* namespace service */
} /* namespace cosgi */
@@ -6,8 +6,7 @@
#include <hos/cosgi/service/core/CoreService.h>
#include <hos/cosgi/service/devicerepository/DeviceRepositoryService.h>
#include <hos/cosgi/service/Implementation.h>
//#include <hos/utils/SchemaLoader.h>
// ROS includes
#include "sitemap_template/SitemapTemplate.h"
#include <ros/ros.h>
// std includes
#include <mutex>
@@ -30,9 +29,16 @@ private:
devicerepository::DeviceRepositoryService* repoService = nullptr;
ros::NodeHandle* nodehandle = nullptr;
std::recursive_mutex serviceMutex;
std::string sitemapTemplatePrefix = "/hos/sitemap/sitemap_templates";
std::string hosStatusTopic = "/hos/status/updates";
bool initialized = false;
std::map<std::string, std::shared_ptr<sitemaptemplate::SitemapTemplate>> sitemapTemplates;
void init() noexcept;
void addSitemap(const std::string& name, XmlRpc::XmlRpcValue& rawValue);
public:
@@ -0,0 +1,60 @@
#include "../sitemap_template/SitemapTemplate.h"
namespace hos {
namespace cosgi {
namespace service {
namespace sitemap {
namespace sitemaptemplate {
std::shared_ptr<Page> SitemapTemplate::createPage(const libvariant::Variant& param, std::weak_ptr<Page> parent) {
std::shared_ptr<Page> newPage;
if (parent.expired() && 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<Page>(*this, title, parent);
for ( auto e : elements.AsList()) {
newPage->createElement(e);
}
if (parent.expired()) {
rootPage = newPage;
}
return newPage;
}
std::shared_ptr<Element> Page::createElement(const libvariant::Variant& param) {
}
std::shared_ptr<Element> CompositeElement::createElement(const libvariant::Variant& param) {
}
std::shared_ptr<Page> AtomicElement::createLinkedToPage(const libvariant::Variant& param) {
}
std::shared_ptr<Device> AtomicElement::createDevice(const libvariant::Variant& param) {
}
} // namespace sitemaptemplate
} // namespace sitemap
} // namespace service
} // namespace cosgi
} // namespace hos
@@ -0,0 +1,164 @@
#pragma once
// hos includes
#include <hos/utils/SchemaLoader.h>
// libvariant
#include <Variant/Schema.h>
// std includes
#include <map>
#include <vector>
#include <memory>
#include <string>
#include <atomic>
namespace hos {
namespace cosgi {
namespace service {
namespace sitemap {
namespace sitemaptemplate {
class Page;
class Element;
class AtomicElement;
class CompositeElement;
class Device;
class SitemapTemplate {
private:
std::string title;
std::shared_ptr<Page> rootPage;
public:
SitemapTemplate(const std::string& title) : title(title) {}
std::shared_ptr<Page> createPage(const libvariant::Variant& param, std::weak_ptr<Page> parent = std::weak_ptr<Page>());
std::shared_ptr<Page> getRootPage() noexcept { return rootPage; };
};
class Page {
private:
SitemapTemplate& sitemap;
std::weak_ptr<Page> parent;
std::string title;
std::vector<std::shared_ptr<Element>> elements;
public:
Page(SitemapTemplate& sitemap, const std::string& title, std::weak_ptr<Page> parent = std::weak_ptr<Page>())
: sitemap(sitemap), title(title) {}
SitemapTemplate& getSiteMap() noexcept { return sitemap; }
std::shared_ptr<Page> getParent() noexcept { return parent.lock(); }
std::shared_ptr<Element> createElement(const libvariant::Variant& param);
const std::vector<std::shared_ptr<Element>>& getElements() noexcept { return elements; }
};
enum class ElementType {
// composite elements
Frame,
// atomic elements
Text,
Switch,
Slider
};
class Element {
private:
static std::atomic<uint64_t> nextID;
uint64_t id;
bool compositeFlag;
ElementType type;
Page& page;
std::weak_ptr<CompositeElement> parent;
std::string label;
std::string icon;
public:
Element( Page& page,
bool isComposite,
ElementType type,
std::weak_ptr<CompositeElement> parent,
const std::string& label,
const std::string& icon )
: id(nextID.fetch_add(1)), compositeFlag(isComposite), type(type), page(page), parent(parent), label(label), icon(icon) {}
virtual ~Element() {}
uint64_t getID() noexcept { return id; }
const std::string& getLabel() noexcept { return label; }
const std::string& getIcon() noexcept { return icon; }
Page& getPage() noexcept { return page; }
std::shared_ptr<CompositeElement> getParent() noexcept { return parent.lock(); }
bool isComposite() noexcept { return compositeFlag; };
ElementType getType() noexcept { return type; }
};
class CompositeElement : public Element {
private:
std::vector<std::shared_ptr<Element>> elements;
public:
CompositeElement(Page& page, ElementType etype, const std::string& label, const std::string& icon,
std::weak_ptr<CompositeElement> parent = std::weak_ptr<CompositeElement>())
: Element(page, true, etype, parent, label, icon) {}
std::shared_ptr<Element> createElement(const libvariant::Variant& param);
const std::vector<std::shared_ptr<Element>>& getElements() noexcept { return elements; }
};
class AtomicElement : public Element {
private:
std::string format;
std::shared_ptr<Device> device;
libvariant::Variant additionalParams;
std::shared_ptr<Page> linkedToPage;
public:
AtomicElement(Page& page, ElementType etype, const std::string& label, const std::string& icon,
const std::string& format, std::shared_ptr<Device> device, libvariant::Variant additionalParams,
std::weak_ptr<CompositeElement> parent = std::weak_ptr<CompositeElement>())
: Element(page, false, etype, parent, label, icon), format(format), device(device), additionalParams(additionalParams) {}
const std::string& getFormat() { return format; }
std::shared_ptr<Device> createDevice(const libvariant::Variant& param);
std::shared_ptr<Device> getDevice() { return device; }
const libvariant::Variant& getAdditionalParams() { return additionalParams; }
std::shared_ptr<Page> createLinkedToPage(const libvariant::Variant& param);
std::shared_ptr<Page> getLinkedToPage() { return linkedToPage; }
};
class Device {
private:
public:
};
} // namespace sitemaptemplate
} // namespace sitemap
} // namespace service
} // namespace cosgi
} // namespace hos
+1
View File
@@ -1,4 +1,5 @@
<launch>
<include file="$(find hos_core_types)/launch/setup_core_types.launch" />
<include file="$(find hos_philips_hue)/launch/hue_types.launch" />
<include file="$(find hos_cosgi_sitemap)/launch/setup_sitemap.launch" />
</launch>