This commit is contained in:
2015-06-09 13:55:31 +02:00
parent d6c4b72278
commit 3451e66f16
9 changed files with 103 additions and 42 deletions
@@ -38,39 +38,39 @@ HOS_SERVICE_IMPL_INFO( DeviceRepoHandlerFactory, // Implementation
DeviceRepoHandlerFactory::DeviceRepoHandlerFactory(devicerepository::DeviceRepositoryService* repoService)
: repoService(repoService) {
infoCategoryFuncs.insert({"id", [](devicerepository::Device* device, const std::string& category)->Variant {
deviceInfoFuncs.add("id", [](Device* device, const std::string& category)->Variant {
return device->getDeviceID();
} });
});
infoCategoryFuncs.insert({"type", [](devicerepository::Device* device, const std::string& category)->Variant {
deviceInfoFuncs.add("type", [](Device* device, const std::string& category)->Variant {
return device->getDeviceType();
} });
});
infoCategoryFuncs.insert({"status_topic", [](devicerepository::Device* device, const std::string& category)->Variant {
deviceInfoFuncs.add("status_topic", [](Device* device, const std::string& category)->Variant {
return device->getStatusTopic();
} });
});
infoCategoryFuncs.insert({"command_topic", [](devicerepository::Device* device, const std::string& category)->Variant {
deviceInfoFuncs.add("command_topic", [](Device* device, const std::string& category)->Variant {
return device->getCmdTopic();
} });
});
infoCategoryFuncs.insert({"current_state", [](devicerepository::Device* device, const std::string& category)->Variant {
deviceInfoFuncs.add("current_state", [](Device* device, const std::string& category)->Variant {
auto retval = device->getCurrentState();
if (retval.IsMap()) {
retval["timestamp"] = utils::timestamp_to_ISO8601(device->getCurrentStateTimestamp());
}
return retval;
} });
});
infoCategoryFuncs.insert({"last_state", [](devicerepository::Device* device, const std::string& category)->Variant {
deviceInfoFuncs.add("last_state", [](Device* device, const std::string& category)->Variant {
auto retval = device->getLastState();
if (retval.IsMap()) {
retval["timestamp"] = utils::timestamp_to_ISO8601(device->getLastStateTimestamp());
}
return retval;
} });
});
infoCategoryFuncs.insert({"uri", [=](devicerepository::Device* device, const std::string& category)->Variant {
deviceInfoFuncs.add("uri", [=](Device* device, const std::string& category)->Variant {
std::stringstream ss;
/*if (ssl) {
ss << "https://";
@@ -80,7 +80,7 @@ DeviceRepoHandlerFactory::DeviceRepoHandlerFactory(devicerepository::DeviceRepos
ss << req.getHost() << matchUri.toString() << device->getDeviceID();*/
ss << "<???>";
return ss.str();
} });
});
}
Net::HTTPRequestHandler* DeviceRepoHandlerFactory::createRequestHandler( Poco::URI matchUri, const Net::HTTPServerRequest& request, bool ssl ) noexcept {
@@ -492,26 +492,20 @@ Variant DeviceRepoHandlerFactory::getDeviceInfo(devicerepository::Device* device
// We want all info categories
if (category.empty()) {
for (auto c : infoCategoryFuncs) {
retval[c.first] = c.second(device, category);
}
deviceInfoFuncs.forEach([&](const std::string& key, const Variant& value){
retval[key] = value;
}, device, category);
// We want a single info category
} else {
auto c = infoCategoryFuncs.find(category);
if (c != infoCategoryFuncs.end()) {
retval = c->second(device, category);
if (!path.empty()) {
if (retval.HasPath(path)) {
retval = retval.GetPath(path);
} else {
throw webserver::webresource::WebResourceHandlerException((boost::format("Unknown path \"%1%\" for device info category \"%2%\".") % path % category).str(),
Poco::Net::HTTPResponse::HTTPStatus::HTTP_NOT_FOUND);
}
retval = deviceInfoFuncs.call(category, device, category);
if (!path.empty()) {
if (retval.HasPath(path)) {
retval = retval.GetPath(path);
} else {
throw webserver::webresource::WebResourceHandlerException((boost::format("Unknown path \"%1%\" for device info category \"%2%\".") % path % category).str(),
Poco::Net::HTTPResponse::HTTPStatus::HTTP_NOT_FOUND);
}
} else {
throw webserver::webresource::WebResourceHandlerException((boost::format("Unknown device info category \"%1%\"") % category).str(),
Poco::Net::HTTPResponse::HTTPStatus::HTTP_NOT_FOUND);
}
}
@@ -6,6 +6,7 @@
#include <hos/cosgi/service/webserver/WebServerService.h>
#include <hos/cosgi/service/webserver/webresource/WebResourceHandlerImpl.h>
#include <hos/cosgi/service/devicerepository/DeviceRepositoryService.h>
#include <hos/utils/FunctionTable.h>
#include <Poco/Net/HTTPRequestHandler.h>
#include <Variant/Variant.h>
#include <ros/ros.h>
@@ -80,8 +81,9 @@ class DeviceRepoHandlerFactory
public:
typedef std::function<libvariant::Variant( devicerepository::Device* device, const std::string& category )> infoCategoryFunc_t;
private:
typedef utils::FunctionTable<std::string, Variant, Device*, const std::string&> deviceInfoFuncs_t;
DeviceRepositoryService* repoService;
std::map<std::string, infoCategoryFunc_t> infoCategoryFuncs;
deviceInfoFuncs_t deviceInfoFuncs;
public:
DeviceRepoHandlerFactory(devicerepository::DeviceRepositoryService* repoService);
@@ -22,6 +22,7 @@ namespace service {
// forward declarations
namespace devicerepository { class DeviceRepositoryService; }
namespace core { class CoreService; }
namespace scripting { class ScriptingService; }
// service namespace
@@ -159,6 +160,12 @@ public:
* \return core service.
*/
virtual core::CoreService* getCoreService() noexcept = 0;
virtual void registerExecutionBackend(scripting::ScriptingService* service) noexcept = 0;
virtual scripting::ScriptingService* getExecutionBackend(const std::string& language) noexcept = 0;
virtual std::vector<scripting::ScriptingService*> getExecutionBackends() noexcept = 0;
};
@@ -56,7 +56,7 @@ celix_status_t cb_serviceChanged(void* listener, service_event_pt event) {
} else if (serviceName && std::strcmp(serviceName, ScriptingService::SERVICE_NAME) == 0) {
ScriptingService *service = nullptr;
bundleContext_getService(myUserData->bundleContext, event->reference, (void**)&service);
myUserData->serviceImpl->addExecutionBackend(service);
myUserData->serviceImpl->registerExecutionBackend(service);
checkReg = true;
}
@@ -147,7 +147,7 @@ void RuleEngineServiceImpl::removeRulePkg(const std::string& name) noexcept {
}
void RuleEngineServiceImpl::addExecutionBackend(scripting::ScriptingService* service) noexcept {
void RuleEngineServiceImpl::registerExecutionBackend(scripting::ScriptingService* service) noexcept {
if (execServices.find(service->getLanguage()) == execServices.end()) {
execServices.insert({service->getLanguage(), service});
ROS_INFO_STREAM("RuleEngineService: Added execution service \"" << service->getLanguage() << "\".");
@@ -164,6 +164,15 @@ scripting::ScriptingService* RuleEngineServiceImpl::getExecutionBackend(const st
}
std::vector<scripting::ScriptingService*> RuleEngineServiceImpl::getExecutionBackends() noexcept {
std::vector<scripting::ScriptingService*> retval;
for (auto e : execServices) {
retval.push_back(e.second);
}
return retval;
}
void RuleEngineServiceImpl::registerRuleConditionFactory(const std::string& type, std::shared_ptr<RuleConditionFactory> factory) noexcept {
condFactories.insert({type, factory});
}
@@ -123,9 +123,11 @@ public:
bool isInitialized() noexcept { return initialized; }
void addExecutionBackend(scripting::ScriptingService* service) noexcept;
virtual void registerExecutionBackend(scripting::ScriptingService* service) noexcept override;
scripting::ScriptingService* getExecutionBackend(const std::string& language) noexcept;
virtual scripting::ScriptingService* getExecutionBackend(const std::string& language) noexcept override;
virtual std::vector<scripting::ScriptingService*> getExecutionBackends() noexcept override;
};
@@ -39,6 +39,10 @@ HOS_SERVICE_IMPL_INFO( RuleEngineHandlerFactory, // Implementation
RuleEngineHandlerFactory::RuleEngineHandlerFactory(RuleEngineService* ruleService)
: ruleService(ruleService),
engineInfoFuncs([](const std::string& key)->engineInfoFuncs_t::Func_t {
throw webserver::webresource::WebResourceHandlerException((boost::format("Unknown category \"%1%\"") % key).str(),
Poco::Net::HTTPResponse::HTTPStatus::HTTP_NOT_FOUND);
}),
pkgInfoFuncs([](const std::string& key)->pkgInfoFuncs_t::Func_t {
throw webserver::webresource::WebResourceHandlerException((boost::format("Unknown category \"%1%\"") % key).str(),
Poco::Net::HTTPResponse::HTTPStatus::HTTP_NOT_FOUND);
@@ -48,6 +52,24 @@ RuleEngineHandlerFactory::RuleEngineHandlerFactory(RuleEngineService* ruleServic
Poco::Net::HTTPResponse::HTTPStatus::HTTP_NOT_FOUND);
}) {
engineInfoFuncs.add("languages", [](RuleEngineService* engine, const std::string& category)->Variant {
Variant retval = libvariant::Variant::List();
for (auto e : engine->getExecutionBackends()) {
retval.Append(e->getLanguage());
}
return retval;
});
engineInfoFuncs.add("packages", [this](RuleEngineService* engine, const std::string& category)->Variant {
Variant retval = libvariant::Variant::List();
for (auto r : engine->getRulePackages()) {
if (!r.expired()) {
retval.Append(getRulePkgInfo(r.lock().get()));
}
}
return retval;
});
pkgInfoFuncs.add("id", [](rules::RulePackage* pkg, const std::string& category)->Variant {
return pkg->getName();
});
@@ -119,6 +141,29 @@ Net::HTTPRequestHandler* RuleEngineHandlerFactory::createRequestHandler( Poco::U
}
Variant RuleEngineHandlerFactory::getEngineInfo( RuleEngineService* engine, const std::string& category, const std::string& path ) {
Variant retval;
// We want all info categories
if (category.empty()) {
engineInfoFuncs.forEach([&](const std::string& key, const Variant& value){
retval[key] = value;
}, engine, category);
// We want a single info category
} else {
retval = engineInfoFuncs.call(category, engine, category);
if (!path.empty()) {
if (retval.HasPath(path)) {
retval = retval.GetPath(path);
} else {
throw webserver::webresource::WebResourceHandlerException((boost::format("Unknown path \"%1%\" for rule package info category \"%2%\".") % path % category).str(),
Poco::Net::HTTPResponse::HTTPStatus::HTTP_NOT_FOUND);
}
}
}
return retval;
}
Variant RuleEngineHandlerFactory::getRulePkgInfo( rules::RulePackage* pkg, const std::string& category, const std::string& path ) {
Variant retval;
@@ -214,9 +259,11 @@ void RuleEngineHandler::__handleInfo(Poco::Net::HTTPServerRequest &req, Poco::Ne
form.reset(new Net::HTMLForm(req));
}
// Nothing given, query mode (there is no real query functionality implemented yet though)
// Nothing given, return engine info
if (pathPieces.size() <= matchPieces.size()) {
auto pkgs = ruleService->getRulePackages();
handleResponse(req, resp, parent->getEngineInfo(ruleService, "", ""));
/*auto pkgs = ruleService->getRulePackages();
// Parse HTTP header "Range" parameter (to support dojo/store)
size_t rangeStart = 0;
@@ -270,7 +317,7 @@ void RuleEngineHandler::__handleInfo(Poco::Net::HTTPServerRequest &req, Poco::Ne
resp.set("Content-Range", rangeOut);
resp.set("X-Content-Range", rangeOut);
handleResponse(req, resp, result);
}
}*/
// rule package given
} else if (pathPieces.size() == matchPieces.size() + 1) {
@@ -78,13 +78,12 @@ public:
class RuleEngineHandlerFactory
: public webserver::webresource::WebResourceHandlerFactoryImpl<RuleEngineHandlerFactory, false, RuleEngineEventQueue> {
public:
typedef std::function<libvariant::Variant( rules::RulePackage* pkg, const std::string& category )> pkgInfoFunc_t;
typedef std::function<libvariant::Variant( rules::Rule* pkg, const std::string& category )> ruleInfoFuncFunc_t;
private:
typedef utils::FunctionTable<std::string, libvariant::Variant, RuleEngineService*, const std::string&> engineInfoFuncs_t;
typedef utils::FunctionTable<std::string, libvariant::Variant, rules::RulePackage*, const std::string&> pkgInfoFuncs_t;
typedef utils::FunctionTable<std::string, libvariant::Variant, rules::Rule*, const std::string&> ruleInfoFuncs_t;
RuleEngineService* ruleService;
engineInfoFuncs_t engineInfoFuncs;
pkgInfoFuncs_t pkgInfoFuncs;
ruleInfoFuncs_t ruleInfoFuncs;
@@ -93,6 +92,8 @@ public:
virtual Poco::Net::HTTPRequestHandler* createRequestHandler(Poco::URI matchUri, const Poco::Net::HTTPServerRequest& request, bool ssl ) noexcept override;
libvariant::Variant getEngineInfo( RuleEngineService* engine, const std::string& category = "", const std::string& path = "" );
libvariant::Variant getRulePkgInfo( rules::RulePackage* pkg, const std::string& category = "", const std::string& path = "" );
libvariant::Variant getRuleInfo( rules::Rule* pkg, const std::string& category = "", const std::string& path = "" );
@@ -692,7 +692,6 @@ protected:
}
handleResponse(req, resp, msg);
}
};