This commit is contained in:
Matthias Janetschek
2015-06-01 16:33:09 +02:00
parent 03d71034f8
commit 8de7d5b10c
8 changed files with 292 additions and 144 deletions
@@ -324,7 +324,7 @@ public:
* \param[in] e event. * \param[in] e event.
* \return notified observer count. * \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); std::lock_guard<std::recursive_mutex> lock(_observersMutex);
size_t retval = 0; size_t retval = 0;
// We work with a copy so that we can insert/remove observers within a callback. // We work with a copy so that we can insert/remove observers within a callback.
@@ -337,6 +337,27 @@ public:
return retval; 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; 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;
}; };
@@ -38,7 +38,8 @@ enum class DeviceEventType : int {
DEVICE_REMOVED = 2, DEVICE_REMOVED = 2,
STATUS_UPDATE_RECEIVED = 3, STATUS_UPDATE_RECEIVED = 3,
COMMAND_RECEIVED = 4, COMMAND_RECEIVED = 4,
STATE_CHANGED = 5 STATE_CHANGED = 5,
ALL_EVENTS = 6
}; };
@@ -40,10 +40,12 @@ bool DeviceImpl::handleStatusMsg(const Variant& msg, const timestamp_t& stamp) n
DeviceStatusMsgEvent event(this, msg, stamp); DeviceStatusMsgEvent event(this, msg, stamp);
notifyObservers(DeviceEventType::STATUS_UPDATE_RECEIVED, &event); notifyObservers(DeviceEventType::STATUS_UPDATE_RECEIVED, &event);
notifyObservers(DeviceEventType::ALL_EVENTS, DeviceEventType::STATUS_UPDATE_RECEIVED, &event);
if (stateChanged){ if (stateChanged){
DeviceStateChangeEvent event(this, msg, stamp); DeviceStateChangeEvent event(this, msg, stamp);
notifyObservers(DeviceEventType::STATE_CHANGED, &event); notifyObservers(DeviceEventType::STATE_CHANGED, &event);
notifyObservers(DeviceEventType::ALL_EVENTS, DeviceEventType::STATE_CHANGED, &event);
} }
return stateChanged; return stateChanged;
@@ -54,6 +56,7 @@ void DeviceImpl::handleCommandMsg(const Variant& msg, const timestamp_t& stamp)
std::lock_guard<std::recursive_mutex> lock(objMutex); std::lock_guard<std::recursive_mutex> lock(objMutex);
DeviceCmdMsgEvent event(this, msg, stamp); DeviceCmdMsgEvent event(this, msg, stamp);
notifyObservers(DeviceEventType::COMMAND_RECEIVED, &event); 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 // send device added event
DeviceAddedEvent event(dev.get(), std::chrono::system_clock::now()); DeviceAddedEvent event(dev.get(), std::chrono::system_clock::now());
notifyObservers(DeviceEventType::DEVICE_ADDED, &event); 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()) { if (dev != devices.end()) {
DeviceRemovedEvent event(dev->second.get(), std::chrono::system_clock::now()); DeviceRemovedEvent event(dev->second.get(), std::chrono::system_clock::now());
notifyObservers(DeviceEventType::DEVICE_REMOVED, &event); notifyObservers(DeviceEventType::DEVICE_REMOVED, &event);
notifyObservers(DeviceEventType::ALL_EVENTS, DeviceEventType::DEVICE_REMOVED, &event);
dev->second->notifyObservers(DeviceEventType::DEVICE_REMOVED, &event); dev->second->notifyObservers(DeviceEventType::DEVICE_REMOVED, &event);
dev->second->notifyObservers(DeviceEventType::ALL_EVENTS, DeviceEventType::DEVICE_REMOVED, &event);
devices.erase(name); devices.erase(name);
} }
} }
@@ -232,7 +238,15 @@ void DeviceRepositoryServiceImpl::statusMsgCallback(const hos_core_msgs::DeviceS
auto dev = devices.find(msg->device_id); auto dev = devices.find(msg->device_id);
if (dev != devices.end()) { if (dev != devices.end()) {
auto stamp = std::chrono::system_clock::now(); 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 { } else {
@@ -261,6 +275,9 @@ void DeviceRepositoryServiceImpl::cmdMsgCallback(const hos_core_msgs::DeviceComm
if (dev != devices.end()) { if (dev != devices.end()) {
auto stamp = std::chrono::system_clock::now(); auto stamp = std::chrono::system_clock::now();
dev->second->handleCommandMsg(m, stamp); 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 { } else {
@@ -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 { 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; Variant DeviceRepoHandlerBase::getDeviceInfo(devicerepository::Device* device, Net::HTTPServerRequest &req, const std::string& category, const std::vector<std::string>& path) {
if (form.has("method")) { Variant retval;
std::string methodRaw = form.get("method");
bool requireValue = false; // We want all info categories
if (methodRaw == "get") { if (category.empty()) {
// do nothing for (auto c : infoCategoryFuncs) {
} else if (methodRaw == "command") { retval[c.first] = c.second(matchUri, device, req, category, ssl);
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);
} }
if (requireValue) {
if (form.has("value")) { // We want a single info category
methodValue = form.get("value"); } else {
} else { auto c = infoCategoryFuncs.find(category);
throw webserver::webresource::WebResourceHandlerException((boost::format("API method \"%1%\" requires a value parameter.") % methodRaw).str(), if (c != infoCategoryFuncs.end()) {
Poco::Net::HTTPResponse::HTTPStatus::HTTP_BAD_REQUEST); 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 // No device given
if (pathPieces.size() <= matchPieces.size()) { if (pathPieces.size() <= matchPieces.size()) {
if (dataMethod != DeviceAPIMethod::GET) { if (method != DeviceAPIMethod::GET) {
throw webserver::webresource::WebResourceHandlerException("Requested API method requires a device", throw webserver::webresource::WebResourceHandlerException("Requested API method requires a device",
Poco::Net::HTTPResponse::HTTPStatus::HTTP_BAD_REQUEST); 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()]; std::string devid = pathPieces[matchPieces.size()];
auto device = repoService->getDevice(devid); auto device = repoService->getDevice(devid);
if (!device.expired()) { if (!device.expired()) {
switch (dataMethod) { switch (method) {
case DeviceAPIMethod::GET: case DeviceAPIMethod::GET:
{ {
std::string category; 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) { void DeviceRepoInfoHandler::_handleGET(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp) {
throw webserver::webresource::WebResourceHandlerException("ToDo: Implement POST."); Net::HTMLForm form(req);
__handle(req, resp, form);
} }
void DeviceRepoInfoHandler::_handlePOST(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp) {
Net::HTMLForm form(req, req.stream());
Variant DeviceRepoHandler::getDeviceInfo(devicerepository::Device* device, Net::HTTPServerRequest &req, const std::string& category, const std::vector<std::string>& path) { __handle(req, resp, form);
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;
}
} }
@@ -11,6 +11,8 @@
#include <ros/ros.h> #include <ros/ros.h>
#include <vector> #include <vector>
#include <string> #include <string>
#include <queue>
#include <memory>
#include <functional> #include <functional>
@@ -27,7 +29,51 @@ namespace webresource {
enum class DeviceAPIMethod { enum class DeviceAPIMethod {
GET, GET,
COMMAND, 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; bool ssl )> infoCategoryFunc_t;
private: private:
webserver::WebServerService* service = nullptr; webserver::WebServerService* service = nullptr;
devicerepository::DeviceRepositoryService* repoService; DeviceRepositoryService* repoService;
std::map<std::string, infoCategoryFunc_t> infoCategoryFuncs; std::map<std::string, infoCategoryFunc_t> infoCategoryFuncs;
std::map<std::string, std::shared_ptr<DeviceEventQueue>> deviceEventQueues;
public: public:
DeviceRepoHandlerFactory(devicerepository::DeviceRepositoryService* repoService); DeviceRepoHandlerFactory(devicerepository::DeviceRepositoryService* repoService);
@@ -60,6 +108,12 @@ public:
static DeviceAPIMethod getDeviceAPIMethod() noexcept; 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 class DeviceRepoHandlerBase
: public interface::Observer<devicerepository::DeviceEventType, devicerepository::DeviceEvent>, : public webserver::webresource::WebResourceHandlerImpl {
public webserver::webresource::WebResourceHandlerImpl {
protected: protected:
Poco::URI matchUri; Poco::URI matchUri;
@@ -116,56 +169,74 @@ public:
bool ssl = false ) bool ssl = false )
: matchUri(matchUri), repoService(repoService), infoCategoryFuncs(infoCategoryFuncs), ssl(ssl) {} : 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 _handleGET(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp) override;
virtual void _handlePOST(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, virtual void __handle(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp, Poco::Net::HTMLForm& form);
devicerepository::DeviceEvent>::observable_type* o,
const devicerepository::DeviceEventType& key,
const devicerepository::DeviceEvent* e) noexcept override;
}; };
class DeviceRepoHandler class DeviceRepoEventLongPollingHandler
: public interface::Observer<devicerepository::DeviceEventType, devicerepository::DeviceEvent>, : public DeviceRepoHandlerBase {
public webserver::webresource::WebResourceHandlerImpl {
private: protected:
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>() );
public: public:
DeviceRepoHandler( Poco::URI matchUri, DeviceRepoEventLongPollingHandler( Poco::URI matchUri,
devicerepository::DeviceRepositoryService* repoService, devicerepository::DeviceRepositoryService* repoService,
const std::map<std::string, DeviceRepoHandlerFactory::infoCategoryFunc_t>& infoCategoryFuncs, const std::map<std::string, DeviceRepoHandlerFactory::infoCategoryFunc_t>& infoCategoryFuncs,
bool ssl = false ) 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 _handleGET(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp) override;
virtual void _handlePOST(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;
}; };
+29 -3
View File
@@ -2,12 +2,33 @@
HTTP - GET / HTTP - POST (application/x-www-form-urlencoded): HTTP - GET / HTTP - POST (application/x-www-form-urlencoded):
============================================================== ==============================================================
x) [OUT] DeviceAPIMethod::GET [Args: format, pointer, query?] x) [OUT] DeviceAPIMethod::GET [Args: format, pointer, query?]
-- http[s]://<baseURL>/devices[/<id>/<pointer>]
x) [IN] DeviceAPIMethod::COMMAND [Args: format, pointer, msg] x) [IN] DeviceAPIMethod::COMMAND [Args: format, pointer, msg]
-- http[s]://<baseURL>/devices/<id>[/<pointer>]
x) [IN] DeviceAPIMethod::STATUS_UPDATE [Args: format, pointer, msg] x) [IN] DeviceAPIMethod::STATUS_UPDATE [Args: format, pointer, msg]
x) [EVENT] DeviceAPIMethod::REGISTER_EVENT [Args: format, pointer, event] -- http[s]://<baseURL>/devices/<id>[/<pointer>]
- Long-Polling
- WebSocket
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: API Method Parameter:
-- Query: method = get | command | statusupdate | event -- Query: method = get | command | statusupdate | event
@@ -30,3 +51,8 @@ COMMAND/STATUS_UPDATE Parameters:
EVENT Parameters: EVENT Parameters:
-- Query: event = command | statusupdate | statechange | added | removed | all -- Query: event = command | statusupdate | statechange | added | removed | all
==============================================================
@@ -261,6 +261,10 @@ protected:
throw NotImplementedException(); 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 { virtual void handleRequest(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp) override {
try { try {
try { try {
@@ -271,14 +275,16 @@ protected:
_handleGET(req, resp); _handleGET(req, resp);
} else if (req.getMethod() == Poco::Net::HTTPRequest::HTTP_POST) { } else if (req.getMethod() == Poco::Net::HTTPRequest::HTTP_POST) {
_handlePOST(req, resp); _handlePOST(req, resp);
} else if (req.getMethod() == Poco::Net::HTTPRequest::HTTP_PUT) {
_handlePUT(req, resp);
} else { } else {
std::cout << "Unsupported HTTP Request Method" << std::endl; 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); Poco::Net::HTTPResponse::HTTPStatus::HTTP_NOT_IMPLEMENTED);
} }
} catch (NotImplementedException& e) { } catch (NotImplementedException& e) {
std::cout << "Unsupported HTTP Request Method" << std::endl; 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); Poco::Net::HTTPResponse::HTTPStatus::HTTP_NOT_IMPLEMENTED);
} }
} }