.
This commit is contained in:
@@ -324,7 +324,7 @@ public:
|
||||
* \param[in] e event.
|
||||
* \return notified observer count.
|
||||
*/
|
||||
size_t notifyObservers(const _Key& k, const _Event* e) noexcept override {
|
||||
virtual size_t notifyObservers(const _Key& k, const _Event* e) noexcept override {
|
||||
std::lock_guard<std::recursive_mutex> lock(_observersMutex);
|
||||
size_t retval = 0;
|
||||
// We work with a copy so that we can insert/remove observers within a callback.
|
||||
@@ -337,6 +337,27 @@ public:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify observers of a new event.
|
||||
*
|
||||
* \param[in] key observer filter key.
|
||||
* \param[in] substkey key that is send to the observers.
|
||||
* \param[in] e event.
|
||||
* \return notified observer count.
|
||||
*/
|
||||
virtual size_t notifyObservers(const _Key& key, const _Key& substkey, const _Event* e) noexcept override {
|
||||
std::lock_guard<std::recursive_mutex> lock(_observersMutex);
|
||||
size_t retval = 0;
|
||||
// We work with a copy so that we can insert/remove observers within a callback.
|
||||
observers_type tmp = _observers;
|
||||
auto ol = tmp.equal_range(key);
|
||||
for (auto i = ol.first; i != ol.second; i++) {
|
||||
i->second->notificationReceived(this, substkey, e);
|
||||
retval++;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -269,6 +269,18 @@ public:
|
||||
*/
|
||||
virtual size_t notifyObservers(const _Key& key, const _Event* e) noexcept = 0;
|
||||
|
||||
/**
|
||||
* Notify observers of a new event.
|
||||
*
|
||||
* The purpose of this function is to implement an all-events key.
|
||||
*
|
||||
* \param[in] key observer filter key.
|
||||
* \param[in] substkey key that is send to the observers.
|
||||
* \param[in] e event.
|
||||
* \return notified observer count.
|
||||
*/
|
||||
virtual size_t notifyObservers(const _Key& key, const _Key& substkey, const _Event* e) noexcept = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
+2
-1
@@ -38,7 +38,8 @@ enum class DeviceEventType : int {
|
||||
DEVICE_REMOVED = 2,
|
||||
STATUS_UPDATE_RECEIVED = 3,
|
||||
COMMAND_RECEIVED = 4,
|
||||
STATE_CHANGED = 5
|
||||
STATE_CHANGED = 5,
|
||||
ALL_EVENTS = 6
|
||||
};
|
||||
|
||||
|
||||
|
||||
+18
-1
@@ -40,10 +40,12 @@ bool DeviceImpl::handleStatusMsg(const Variant& msg, const timestamp_t& stamp) n
|
||||
|
||||
DeviceStatusMsgEvent event(this, msg, stamp);
|
||||
notifyObservers(DeviceEventType::STATUS_UPDATE_RECEIVED, &event);
|
||||
notifyObservers(DeviceEventType::ALL_EVENTS, DeviceEventType::STATUS_UPDATE_RECEIVED, &event);
|
||||
|
||||
if (stateChanged){
|
||||
DeviceStateChangeEvent event(this, msg, stamp);
|
||||
notifyObservers(DeviceEventType::STATE_CHANGED, &event);
|
||||
notifyObservers(DeviceEventType::ALL_EVENTS, DeviceEventType::STATE_CHANGED, &event);
|
||||
}
|
||||
|
||||
return stateChanged;
|
||||
@@ -54,6 +56,7 @@ void DeviceImpl::handleCommandMsg(const Variant& msg, const timestamp_t& stamp)
|
||||
std::lock_guard<std::recursive_mutex> lock(objMutex);
|
||||
DeviceCmdMsgEvent event(this, msg, stamp);
|
||||
notifyObservers(DeviceEventType::COMMAND_RECEIVED, &event);
|
||||
notifyObservers(DeviceEventType::ALL_EVENTS, DeviceEventType::COMMAND_RECEIVED, &event);
|
||||
}
|
||||
|
||||
|
||||
@@ -173,6 +176,7 @@ void DeviceRepositoryServiceImpl::addDevice(const std::string& name, XmlRpc::Xml
|
||||
// send device added event
|
||||
DeviceAddedEvent event(dev.get(), std::chrono::system_clock::now());
|
||||
notifyObservers(DeviceEventType::DEVICE_ADDED, &event);
|
||||
notifyObservers(DeviceEventType::ALL_EVENTS, DeviceEventType::DEVICE_ADDED, &event);
|
||||
}
|
||||
|
||||
|
||||
@@ -182,7 +186,9 @@ void DeviceRepositoryServiceImpl::removeDevice(const std::string& name) {
|
||||
if (dev != devices.end()) {
|
||||
DeviceRemovedEvent event(dev->second.get(), std::chrono::system_clock::now());
|
||||
notifyObservers(DeviceEventType::DEVICE_REMOVED, &event);
|
||||
notifyObservers(DeviceEventType::ALL_EVENTS, DeviceEventType::DEVICE_REMOVED, &event);
|
||||
dev->second->notifyObservers(DeviceEventType::DEVICE_REMOVED, &event);
|
||||
dev->second->notifyObservers(DeviceEventType::ALL_EVENTS, DeviceEventType::DEVICE_REMOVED, &event);
|
||||
devices.erase(name);
|
||||
}
|
||||
}
|
||||
@@ -232,7 +238,15 @@ void DeviceRepositoryServiceImpl::statusMsgCallback(const hos_core_msgs::DeviceS
|
||||
auto dev = devices.find(msg->device_id);
|
||||
if (dev != devices.end()) {
|
||||
auto stamp = std::chrono::system_clock::now();
|
||||
dev->second->handleStatusMsg(m, stamp);
|
||||
bool stateChanged = dev->second->handleStatusMsg(m, stamp);
|
||||
DeviceStatusMsgEvent event(dev->second.get(), m, stamp);
|
||||
notifyObservers(DeviceEventType::STATUS_UPDATE_RECEIVED, &event);
|
||||
notifyObservers(DeviceEventType::ALL_EVENTS, DeviceEventType::STATUS_UPDATE_RECEIVED, &event);
|
||||
if (stateChanged) {
|
||||
DeviceStateChangeEvent event(dev->second.get(), m, stamp);
|
||||
notifyObservers(DeviceEventType::STATE_CHANGED, &event);
|
||||
notifyObservers(DeviceEventType::ALL_EVENTS, DeviceEventType::STATE_CHANGED, &event);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -261,6 +275,9 @@ void DeviceRepositoryServiceImpl::cmdMsgCallback(const hos_core_msgs::DeviceComm
|
||||
if (dev != devices.end()) {
|
||||
auto stamp = std::chrono::system_clock::now();
|
||||
dev->second->handleCommandMsg(m, stamp);
|
||||
DeviceCmdMsgEvent event(dev->second.get(), m, stamp);
|
||||
notifyObservers(DeviceEventType::COMMAND_RECEIVED, &event);
|
||||
notifyObservers(DeviceEventType::ALL_EVENTS, DeviceEventType::COMMAND_RECEIVED, &event);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
+98
-104
@@ -77,39 +77,103 @@ DeviceAPIMethod DeviceRepoHandlerFactory::getDeviceAPIMethod() noexcept {
|
||||
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<DeviceEventQueue> DeviceRepoHandlerFactory::getDeviceEventQueue(std::string clientID) {
|
||||
if (clientID.empty()) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Net::HTTPRequestHandler* DeviceRepoHandlerFactory::createRequestHandler( Poco::URI matchUri, const Net::HTTPServerRequest& request, bool ssl ) noexcept {
|
||||
return new DeviceRepoHandler(matchUri, repoService, infoCategoryFuncs, ssl);
|
||||
if(request.find("Upgrade") != request.end() && Poco::icompare(request["Upgrade"], "websocket") == 0)
|
||||
return new DeviceRepoEventWebSocketHandler(matchUri, repoService, infoCategoryFuncs, ssl);
|
||||
else {
|
||||
DeviceAPIMethod method = getDeviceAPIMethod();
|
||||
if (method == DeviceAPIMethod::REGISTEREVENT) {
|
||||
return new DeviceRepoEventLongPollingHandler(matchUri, repoService, infoCategoryFuncs, ssl);
|
||||
} else {
|
||||
return new DeviceRepoInfoHandler(matchUri, method, repoService, infoCategoryFuncs, ssl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DeviceRepoHandler::_handleGET(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp) {
|
||||
// Get API method parameter
|
||||
Net::HTMLForm form(req);
|
||||
DeviceAPIMethod dataMethod = DeviceAPIMethod::GET; // Default method is get
|
||||
std::string methodValue;
|
||||
if (form.has("method")) {
|
||||
std::string methodRaw = form.get("method");
|
||||
bool requireValue = false;
|
||||
if (methodRaw == "get") {
|
||||
// do nothing
|
||||
} else if (methodRaw == "command") {
|
||||
dataMethod = DeviceAPIMethod::COMMAND;
|
||||
requireValue = true;
|
||||
} else if (methodRaw.compare("statusupdate") == 0) {
|
||||
dataMethod = DeviceAPIMethod::STATUSUPDATE;
|
||||
requireValue = true;
|
||||
} else {
|
||||
throw webserver::webresource::WebResourceHandlerException((boost::format("Unknown API method \"%1%\"") % methodRaw).str(),
|
||||
Poco::Net::HTTPResponse::HTTPStatus::HTTP_BAD_REQUEST);
|
||||
|
||||
|
||||
|
||||
|
||||
Variant DeviceRepoHandlerBase::getDeviceInfo(devicerepository::Device* device, Net::HTTPServerRequest &req, const std::string& category, const std::vector<std::string>& path) {
|
||||
Variant retval;
|
||||
|
||||
// We want all info categories
|
||||
if (category.empty()) {
|
||||
for (auto c : infoCategoryFuncs) {
|
||||
retval[c.first] = c.second(matchUri, device, req, category, ssl);
|
||||
}
|
||||
if (requireValue) {
|
||||
if (form.has("value")) {
|
||||
methodValue = form.get("value");
|
||||
} else {
|
||||
throw webserver::webresource::WebResourceHandlerException((boost::format("API method \"%1%\" requires a value parameter.") % methodRaw).str(),
|
||||
Poco::Net::HTTPResponse::HTTPStatus::HTTP_BAD_REQUEST);
|
||||
|
||||
// We want a single info category
|
||||
} else {
|
||||
auto c = infoCategoryFuncs.find(category);
|
||||
if (c != infoCategoryFuncs.end()) {
|
||||
retval = c->second(matchUri, device, req, category, ssl);
|
||||
if (path.size() > 0) {
|
||||
std::stringstream ss;
|
||||
for (auto p : path) {
|
||||
ss << "/" << p;
|
||||
}
|
||||
std::string pathstr = ss.str();
|
||||
if (retval.HasPath(pathstr)) {
|
||||
retval = retval.GetPath(pathstr);
|
||||
} else {
|
||||
throw webserver::webresource::WebResourceHandlerException((boost::format("Unknown path \"%1%\" for device info category \"%2%\".") % pathstr % 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);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DeviceRepoHandlerBase::sendDeviceCommand(devicerepository::Device* device, Net::HTTPServerRequest &req, const std::string& cmd, const std::vector<std::string>& path) {
|
||||
Variant cmdMsg;
|
||||
VariantRef mPart = cmdMsg.Ref();
|
||||
if (path.size() > 0) {
|
||||
for (int i = 0; i < path.size(); i++) {
|
||||
mPart[path[i]] = Variant();
|
||||
mPart.ReassignRef(mPart[path[i]]);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* The libvariant json deserializer knows nothing about RFC 7159, therefore non-object or non-array values are rejected.
|
||||
* As a workaround we use the yaml deserializer (yaml can be considered a super-set of json).
|
||||
* Fun fact: the json serializer accepts non-object or non-array values.
|
||||
*/
|
||||
//mPart = DeserializeJSON(cmd);
|
||||
mPart = DeserializeYAML(cmd);
|
||||
device->sendCommand(cmdMsg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DeviceRepoInfoHandler::__handle(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp, Net::HTMLForm& form) {
|
||||
|
||||
std::string methodValue;
|
||||
if (method == DeviceAPIMethod::COMMAND || method == DeviceAPIMethod::STATUSUPDATE) {
|
||||
if (form.has("value")) {
|
||||
methodValue = form.get("value");
|
||||
} else {
|
||||
throw webserver::webresource::WebResourceHandlerException("API method requires a value parameter.",
|
||||
Poco::Net::HTTPResponse::HTTPStatus::HTTP_BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +184,7 @@ void DeviceRepoHandler::_handleGET(Poco::Net::HTTPServerRequest &req, Poco::Net:
|
||||
|
||||
// No device given
|
||||
if (pathPieces.size() <= matchPieces.size()) {
|
||||
if (dataMethod != DeviceAPIMethod::GET) {
|
||||
if (method != DeviceAPIMethod::GET) {
|
||||
throw webserver::webresource::WebResourceHandlerException("Requested API method requires a device",
|
||||
Poco::Net::HTTPResponse::HTTPStatus::HTTP_BAD_REQUEST);
|
||||
}
|
||||
@@ -181,7 +245,7 @@ void DeviceRepoHandler::_handleGET(Poco::Net::HTTPServerRequest &req, Poco::Net:
|
||||
std::string devid = pathPieces[matchPieces.size()];
|
||||
auto device = repoService->getDevice(devid);
|
||||
if (!device.expired()) {
|
||||
switch (dataMethod) {
|
||||
switch (method) {
|
||||
case DeviceAPIMethod::GET:
|
||||
{
|
||||
std::string category;
|
||||
@@ -220,84 +284,14 @@ void DeviceRepoHandler::_handleGET(Poco::Net::HTTPServerRequest &req, Poco::Net:
|
||||
|
||||
|
||||
|
||||
void DeviceRepoHandler::_handlePOST(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp) {
|
||||
throw webserver::webresource::WebResourceHandlerException("ToDo: Implement POST.");
|
||||
void DeviceRepoInfoHandler::_handleGET(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp) {
|
||||
Net::HTMLForm form(req);
|
||||
__handle(req, resp, form);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Variant DeviceRepoHandler::getDeviceInfo(devicerepository::Device* device, Net::HTTPServerRequest &req, const std::string& category, const std::vector<std::string>& path) {
|
||||
Variant retval;
|
||||
|
||||
// We want all info categories
|
||||
if (category.empty()) {
|
||||
for (auto c : infoCategoryFuncs) {
|
||||
retval[c.first] = c.second(matchUri, device, req, category, ssl);
|
||||
}
|
||||
|
||||
// We want a single info category
|
||||
} else {
|
||||
auto c = infoCategoryFuncs.find(category);
|
||||
if (c != infoCategoryFuncs.end()) {
|
||||
retval = c->second(matchUri, device, req, category, ssl);
|
||||
if (path.size() > 0) {
|
||||
std::stringstream ss;
|
||||
for (auto p : path) {
|
||||
ss << "/" << p;
|
||||
}
|
||||
std::string pathstr = ss.str();
|
||||
if (retval.HasPath(pathstr)) {
|
||||
retval = retval.GetPath(pathstr);
|
||||
} else {
|
||||
throw webserver::webresource::WebResourceHandlerException((boost::format("Unknown path \"%1%\" for device info category \"%2%\".") % pathstr % 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);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DeviceRepoHandler::sendDeviceCommand(devicerepository::Device* device, Net::HTTPServerRequest &req, const std::string& cmd, const std::vector<std::string>& path) {
|
||||
Variant cmdMsg;
|
||||
VariantRef mPart = cmdMsg.Ref();
|
||||
if (path.size() > 0) {
|
||||
for (int i = 0; i < path.size(); i++) {
|
||||
mPart[path[i]] = Variant();
|
||||
mPart.ReassignRef(mPart[path[i]]);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* The libvariant json deserializer knows nothing about RFC 7159, therefore non-object or non-array values are rejected.
|
||||
* As a workaround we use the yaml deserializer (yaml can be considered a super-set of json).
|
||||
* Fun fact: the json serializer accepts non-object or non-array values.
|
||||
*/
|
||||
//mPart = DeserializeJSON(cmd);
|
||||
mPart = DeserializeYAML(cmd);
|
||||
device->sendCommand(cmdMsg);
|
||||
}
|
||||
|
||||
void DeviceRepoHandler::notificationReceived(interface::Observer<devicerepository::DeviceEventType, devicerepository::DeviceEvent>::observable_type* o, const devicerepository::DeviceEventType& key, const devicerepository::DeviceEvent* e) noexcept {
|
||||
switch (key) {
|
||||
case devicerepository::DeviceEventType::DEVICE_ADDED:
|
||||
break;
|
||||
case devicerepository::DeviceEventType::DEVICE_REMOVED:
|
||||
break;
|
||||
case devicerepository::DeviceEventType::COMMAND_RECEIVED:
|
||||
break;
|
||||
case devicerepository::DeviceEventType::STATUS_UPDATE_RECEIVED:
|
||||
break;
|
||||
case devicerepository::DeviceEventType::STATE_CHANGED:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
void DeviceRepoInfoHandler::_handlePOST(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp) {
|
||||
Net::HTMLForm form(req, req.stream());
|
||||
__handle(req, resp, form);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+103
-32
@@ -11,6 +11,8 @@
|
||||
#include <ros/ros.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <queue>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
|
||||
@@ -27,7 +29,51 @@ namespace webresource {
|
||||
enum class DeviceAPIMethod {
|
||||
GET,
|
||||
COMMAND,
|
||||
STATUSUPDATE
|
||||
STATUSUPDATE,
|
||||
REGISTEREVENT
|
||||
};
|
||||
|
||||
|
||||
class DeviceEventQueue
|
||||
: public virtual interface::Observer<devicerepository::DeviceEventType, devicerepository::DeviceEvent> {
|
||||
public:
|
||||
const std::string clientID;
|
||||
DeviceRepositoryService* const repoService;
|
||||
DeviceEventType eventType;
|
||||
Device* device;
|
||||
std::string pointer;
|
||||
std::queue<libvariant::Variant> eventQueue;
|
||||
size_t openConnectionCount = 0;
|
||||
|
||||
DeviceEventQueue( const std::string& clientID,
|
||||
const DeviceEventType eventType,
|
||||
DeviceRepositoryService* repoService,
|
||||
Device* device,
|
||||
std::string pointer )
|
||||
: clientID(clientID), eventType(eventType), repoService(repoService), device(device), pointer(pointer) {}
|
||||
|
||||
virtual void notificationReceived( interface::Observer<devicerepository::DeviceEventType,
|
||||
devicerepository::DeviceEvent>::observable_type* o,
|
||||
const devicerepository::DeviceEventType& key,
|
||||
const devicerepository::DeviceEvent* e) noexcept override {
|
||||
if (eventType == DeviceEventType::ALL_EVENTS || eventType == key) {
|
||||
switch (key) {
|
||||
case devicerepository::DeviceEventType::COMMAND_RECEIVED:
|
||||
break;
|
||||
case devicerepository::DeviceEventType::STATUS_UPDATE_RECEIVED:
|
||||
break;
|
||||
case devicerepository::DeviceEventType::STATE_CHANGED:
|
||||
break;
|
||||
case devicerepository::DeviceEventType::DEVICE_ADDED:
|
||||
break;
|
||||
case devicerepository::DeviceEventType::DEVICE_REMOVED:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -43,8 +89,10 @@ public:
|
||||
bool ssl )> infoCategoryFunc_t;
|
||||
private:
|
||||
webserver::WebServerService* service = nullptr;
|
||||
devicerepository::DeviceRepositoryService* repoService;
|
||||
DeviceRepositoryService* repoService;
|
||||
std::map<std::string, infoCategoryFunc_t> infoCategoryFuncs;
|
||||
std::map<std::string, std::shared_ptr<DeviceEventQueue>> deviceEventQueues;
|
||||
|
||||
public:
|
||||
DeviceRepoHandlerFactory(devicerepository::DeviceRepositoryService* repoService);
|
||||
|
||||
@@ -60,6 +108,12 @@ public:
|
||||
|
||||
static DeviceAPIMethod getDeviceAPIMethod() noexcept;
|
||||
|
||||
std::shared_ptr<DeviceEventQueue> getDeviceEventQueue( const std::string& clientID,
|
||||
const DeviceEventType eventType,
|
||||
DeviceRepositoryService* repoService,
|
||||
Device* device,
|
||||
std::string pointer );
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -88,8 +142,7 @@ public:
|
||||
*/
|
||||
|
||||
class DeviceRepoHandlerBase
|
||||
: public interface::Observer<devicerepository::DeviceEventType, devicerepository::DeviceEvent>,
|
||||
public webserver::webresource::WebResourceHandlerImpl {
|
||||
: public webserver::webresource::WebResourceHandlerImpl {
|
||||
|
||||
protected:
|
||||
Poco::URI matchUri;
|
||||
@@ -116,56 +169,74 @@ public:
|
||||
bool ssl = false )
|
||||
: matchUri(matchUri), repoService(repoService), infoCategoryFuncs(infoCategoryFuncs), ssl(ssl) {}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
class DeviceRepoInfoHandler
|
||||
: public DeviceRepoHandlerBase {
|
||||
|
||||
protected:
|
||||
DeviceAPIMethod method;
|
||||
|
||||
public:
|
||||
|
||||
DeviceRepoInfoHandler( Poco::URI matchUri,
|
||||
DeviceAPIMethod method,
|
||||
devicerepository::DeviceRepositoryService* repoService,
|
||||
const std::map<std::string, DeviceRepoHandlerFactory::infoCategoryFunc_t>& infoCategoryFuncs,
|
||||
bool ssl = false )
|
||||
: DeviceRepoHandlerBase(matchUri, repoService, infoCategoryFuncs, ssl), method(method) {}
|
||||
|
||||
virtual void _handleGET(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp) override;
|
||||
|
||||
virtual void _handlePOST(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp) override;
|
||||
|
||||
virtual void notificationReceived( interface::Observer<devicerepository::DeviceEventType,
|
||||
devicerepository::DeviceEvent>::observable_type* o,
|
||||
const devicerepository::DeviceEventType& key,
|
||||
const devicerepository::DeviceEvent* e) noexcept override;
|
||||
virtual void __handle(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp, Poco::Net::HTMLForm& form);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
class DeviceRepoHandler
|
||||
: public interface::Observer<devicerepository::DeviceEventType, devicerepository::DeviceEvent>,
|
||||
public webserver::webresource::WebResourceHandlerImpl {
|
||||
class DeviceRepoEventLongPollingHandler
|
||||
: public DeviceRepoHandlerBase {
|
||||
|
||||
private:
|
||||
Poco::URI matchUri;
|
||||
devicerepository::DeviceRepositoryService* repoService;
|
||||
const std::map<std::string, DeviceRepoHandlerFactory::infoCategoryFunc_t>& infoCategoryFuncs;
|
||||
bool ssl;
|
||||
|
||||
libvariant::Variant getDeviceInfo( devicerepository::Device* device,
|
||||
Poco::Net::HTTPServerRequest &req,
|
||||
const std::string& category = std::string(),
|
||||
const std::vector<std::string>& path = std::vector<std::string>() );
|
||||
|
||||
void sendDeviceCommand( devicerepository::Device* device,
|
||||
Poco::Net::HTTPServerRequest &req,
|
||||
const std::string& cmd,
|
||||
const std::vector<std::string>& path = std::vector<std::string>() );
|
||||
protected:
|
||||
|
||||
|
||||
public:
|
||||
|
||||
DeviceRepoHandler( Poco::URI matchUri,
|
||||
DeviceRepoEventLongPollingHandler( Poco::URI matchUri,
|
||||
devicerepository::DeviceRepositoryService* repoService,
|
||||
const std::map<std::string, DeviceRepoHandlerFactory::infoCategoryFunc_t>& infoCategoryFuncs,
|
||||
bool ssl = false )
|
||||
: matchUri(matchUri), repoService(repoService), infoCategoryFuncs(infoCategoryFuncs), ssl(ssl) {}
|
||||
: DeviceRepoHandlerBase(matchUri, repoService, infoCategoryFuncs, ssl) {}
|
||||
|
||||
virtual void _handleGET(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp) override;
|
||||
|
||||
virtual void _handlePOST(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp) override;
|
||||
|
||||
virtual void notificationReceived( interface::Observer<devicerepository::DeviceEventType,
|
||||
devicerepository::DeviceEvent>::observable_type* o,
|
||||
const devicerepository::DeviceEventType& key,
|
||||
const devicerepository::DeviceEvent* e) noexcept override;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class DeviceRepoEventWebSocketHandler
|
||||
: public DeviceRepoHandlerBase {
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
public:
|
||||
|
||||
DeviceRepoEventWebSocketHandler( Poco::URI matchUri,
|
||||
devicerepository::DeviceRepositoryService* repoService,
|
||||
const std::map<std::string, DeviceRepoHandlerFactory::infoCategoryFunc_t>& infoCategoryFuncs,
|
||||
bool ssl = false )
|
||||
: DeviceRepoHandlerBase(matchUri, repoService, infoCategoryFuncs, ssl) {}
|
||||
|
||||
virtual void _handleGET(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp) override;
|
||||
|
||||
virtual void _handlePOST(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -2,12 +2,33 @@
|
||||
HTTP - GET / HTTP - POST (application/x-www-form-urlencoded):
|
||||
==============================================================
|
||||
x) [OUT] DeviceAPIMethod::GET [Args: format, pointer, query?]
|
||||
-- http[s]://<baseURL>/devices[/<id>/<pointer>]
|
||||
|
||||
x) [IN] DeviceAPIMethod::COMMAND [Args: format, pointer, msg]
|
||||
-- http[s]://<baseURL>/devices/<id>[/<pointer>]
|
||||
|
||||
x) [IN] DeviceAPIMethod::STATUS_UPDATE [Args: format, pointer, msg]
|
||||
x) [EVENT] DeviceAPIMethod::REGISTER_EVENT [Args: format, pointer, event]
|
||||
- Long-Polling
|
||||
- WebSocket
|
||||
-- http[s]://<baseURL>/devices/<id>[/<pointer>]
|
||||
|
||||
x) [EVENT] DeviceAPIMethod::REGISTER_EVENT [Args: format, pointer, event]
|
||||
-- http[s]://<baseURL>/devices/<id>[/<pointer>]
|
||||
- Long-Polling
|
||||
|
||||
HTTP - PUT:
|
||||
============
|
||||
x) [IN] DeviceAPIMethod::COMMAND [Args: format, pointer, msg]
|
||||
-- http[s]://<baseURL>/devices/<id>/command[/<pointer>]
|
||||
|
||||
x) [IN] DeviceAPIMethod::STATUS_UPDATE [Args: format, pointer, msg]
|
||||
-- http[s]://<baseURL>/devices/<id>/statusupdate[/<pointer>]
|
||||
|
||||
HTTP - WebSocket:
|
||||
==================
|
||||
x) [EVENT] DeviceAPIMethod::REGISTER_EVENT [Args: format, pointer, event]
|
||||
-- ws://<baseURL>/devices/<id>[/<pointer>]
|
||||
|
||||
|
||||
==============================================================
|
||||
|
||||
API Method Parameter:
|
||||
-- Query: method = get | command | statusupdate | event
|
||||
@@ -30,3 +51,8 @@ COMMAND/STATUS_UPDATE Parameters:
|
||||
|
||||
EVENT Parameters:
|
||||
-- Query: event = command | statusupdate | statechange | added | removed | all
|
||||
|
||||
|
||||
==============================================================
|
||||
|
||||
|
||||
|
||||
+8
-2
@@ -261,6 +261,10 @@ protected:
|
||||
throw NotImplementedException();
|
||||
}
|
||||
|
||||
virtual void _handlePUT(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp) {
|
||||
throw NotImplementedException();
|
||||
}
|
||||
|
||||
virtual void handleRequest(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp) override {
|
||||
try {
|
||||
try {
|
||||
@@ -271,14 +275,16 @@ protected:
|
||||
_handleGET(req, resp);
|
||||
} else if (req.getMethod() == Poco::Net::HTTPRequest::HTTP_POST) {
|
||||
_handlePOST(req, resp);
|
||||
} else if (req.getMethod() == Poco::Net::HTTPRequest::HTTP_PUT) {
|
||||
_handlePUT(req, resp);
|
||||
} else {
|
||||
std::cout << "Unsupported HTTP Request Method" << std::endl;
|
||||
handleErrorResponse(req, resp, (boost::format("HTTP method %1% not implemented") % req.getMethod()).str(),
|
||||
handleErrorResponse(req, resp, (boost::format("HTTP method %1% not supported") % req.getMethod()).str(),
|
||||
Poco::Net::HTTPResponse::HTTPStatus::HTTP_NOT_IMPLEMENTED);
|
||||
}
|
||||
} catch (NotImplementedException& e) {
|
||||
std::cout << "Unsupported HTTP Request Method" << std::endl;
|
||||
handleErrorResponse(req, resp, (boost::format("HTTP method %1% not implemented") % req.getMethod()).str(),
|
||||
handleErrorResponse(req, resp, (boost::format("HTTP method %1% not supported") % req.getMethod()).str(),
|
||||
Poco::Net::HTTPResponse::HTTPStatus::HTTP_NOT_IMPLEMENTED);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user