CXX=g++
#CXX=clang
-CXX_FLAGS=-std=c++11 -Wall -pthread -ggdb
+CXX_FLAGS=-std=c++11 -Wall -pthread
CXX_INC=-I./include/ -I./csdk/stack/include -I./csdk/ocsocket/include -I./csdk/ocrandom/include -I./csdk/logger/include
# Force metatargets to build:
-.PHONY: c_sdk simpleserver simpleclient examples
+.PHONY: c_sdk simpleserver simpleclient
all: .PHONY
clean:
rm -f -v OCLib.a *.o simpleserver simpleclient
- cd examples && $(MAKE) clean
-
cd csdk && $(MAKE) clean
cd csdk && $(MAKE) deepclean
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-#include "OCResource.h"
#include "InProcClientWrapper.h"
-
#include "ocstack.h"
+#include "OCResource.h"
using namespace std;
{
while(m_threadRun)
{
- OCStackResult result;
- {
- std::lock_guard<std::mutex> lock(m_csdkLock);
- result = OCProcess();
- }
+ OCStackResult result;
+ {
+ std::lock_guard<std::mutex> lock(m_csdkLock);
+ result = OCProcess();
+ }
if(result != OC_STACK_OK)
{
// TODO: @Erich do something with result if failed?
}
- std::this_thread::yield();
+ //std::this_thread::yield();
// To minimize CPU utilization we may wish to do this with sleep
- //std::this_thread::sleep_for(std::chrono::milliseconds(1));
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
std::string convertOCAddrToString(OCDevAddr* addr)
{
- if(addr->size != 4) { return "NOT SUPPORTED ADDR;";}
+ // TODO: we currently assume this is a IPV4 address, need to figure out the actual value
- if(addr->size == 4) // IPV4
- {
- std::ostringstream address;
- address<<"coap://"<<addr->addr[0]<<"."<<addr->addr[1]<<"."<<addr->addr[2]<<"."<<addr->addr[3]<<"/";
- return address.str();
- }
+ uint8_t a, b, c, d;
+ uint16_t port;
- // TODO: @Erich Convert the device address to a valid string!
- return "";
+ if(OCDevAddrToIPv4Addr(addr, &a, &b, &c, &d) ==0 && OCDevAddrToPort(addr, &port)==0)
+ {
+ ostringstream os;
+ os << "coap://"<<(int)a<<'.'<<(int)b<<'.'<<(int)c<<'.'<<(int)d<<':'<<(int)port;
+ return os.str();
+ }
+ else
+ {
+ return "INVALID IP";
+ }
}
+ struct ListenContext
+ {
+ std::function<void(std::shared_ptr<OCResource>)> callback;
+ IClientWrapper::Ptr clientWrapper;
+ };
+
+
+ const std::string URIKEY = "href";
+ const std::string OBSERVABLEKEY = "obs";
+ const std::string RESOURCETYPESKEY= "rt";
+ const std::string INTERFACESKEY = "if";
- OCStackApplicationResult listenCallback(void* ctx, OCClientResponse* clientResponse)
+ std::shared_ptr<OCResource> InProcClientWrapper::parseOCResource(IClientWrapper::Ptr clientWrapper, const std::string& host, const boost::property_tree::ptree resourceNode)
{
- auto &callback =*(std::function <void(OCResource::Ptr)>*)ctx;
- std::stringstream requestStream;
- requestStream << clientResponse->resJSONPayload;
+ std::string uri = resourceNode.get<std::string>(URIKEY, "");
+ bool obs = resourceNode.get<int>(OBSERVABLEKEY,0) == 1;
+ std::vector<std::string> rTs;
+ std::vector<std::string> ifaces;
+ boost::property_tree::ptree resourceTypes = resourceNode.get_child(RESOURCETYPESKEY, boost::property_tree::ptree());
+ for(auto itr : resourceTypes)
+ {
+ rTs.push_back(itr.second.data());
+ }
- boost::property_tree::ptree root;
- boost::property_tree::read_json(requestStream, root);
-
- boost::property_tree::ptree payload = root.get_child("oc.payload", boost::property_tree::ptree());
-
+ boost::property_tree::ptree interfaces = resourceNode.get_child(INTERFACESKEY, boost::property_tree::ptree());
+ for(auto itr : interfaces)
+ {
+ ifaces.push_back(itr.second.data());
+ }
+ return std::shared_ptr<OCResource>(new OCResource(clientWrapper, host, uri, obs, rTs, ifaces));
+ }
+
+ OCStackApplicationResult listenCallback(void* ctx, OCDoHandle handle, OCClientResponse* clientResponse)
+ {
+ if(clientResponse->result == OC_STACK_OK)
+ {
+ ListenContext* context = (ListenContext*)ctx;
+
+ std::stringstream requestStream;
+ requestStream << clientResponse->resJSONPayload;
+ boost::property_tree::ptree root;
+ boost::property_tree::read_json(requestStream, root);
+
+ boost::property_tree::ptree payload = root.get_child("oc.payload", boost::property_tree::ptree());
- for(auto payloadItr : payload)
- {
- try
- {
- std::string host = convertOCAddrToString(clientResponse->addr);
- OCResource::Ptr resource = std::make_shared<OCResource>(host, payloadItr.second);
-
- // Note: the call to detach allows the underlying thread to continue until completion
- // and allows us to destroy the exec object.
- // This is apparently NOT a memory leak, as the thread will apparently take care of itself.
- // Additionally, the only parameter here is
- // a shared ptr, so OCResource will be disposed of properly upon completion of the callback handler.
- std::thread exec(callback,resource);
- exec.detach();
- }
- catch(ResourceInitException)
- {
- // TODO: Do we want to handle this somehow? Perhaps we need to log this?
- }
-
- }
- delete clientResponse;
-
- return OC_STACK_KEEP_TRANSACTION;
+ for(auto payloadItr : payload)
+ {
+ try
+ {
+ std::string host = convertOCAddrToString(clientResponse->addr);
+ std::shared_ptr<OCResource> resource = context->clientWrapper->parseOCResource(context->clientWrapper, host, payloadItr.second);
+
+ // Note: the call to detach allows the underlying thread to continue until completion
+ // and allows us to destroy the exec object.
+ // This is apparently NOT a memory leak, as the thread will apparently take care of itself.
+ // Additionally, the only parameter here is
+ // a shared ptr, so OCResource will be disposed of properly upon completion of the callback handler.
+ std::thread exec(context->callback,resource);
+ exec.detach();
+ }
+ catch(ResourceInitException& e)
+ {
+ std::cout << "Failed to create resource: "<< e.what() <<std::endl;
+ // TODO: Do we want to handle this somehow? Perhaps we need to log this?
+ }
+
+ }
+ return OC_STACK_DELETE_TRANSACTION;
+
+ }
+ else
+ {
+ std::cout<<"listen Callback got failed result: " << clientResponse->result<<std::endl;
+ return OC_STACK_KEEP_TRANSACTION;
+ }
}
- int InProcClientWrapper::ListenForResource(const std::string& serviceUrl, const std::string& resourceType, std::function<void (OCResource::Ptr)>& callback)
+ OCStackResult InProcClientWrapper::ListenForResource(const std::string& serviceUrl, const std::string& resourceType, std::function<void (std::shared_ptr<OCResource>)>& callback)
+ {
+ OCStackResult result;
+
+ OCCallbackData* cbdata = new OCCallbackData();
+
+ ListenContext* context = new ListenContext();
+ context->callback = callback;
+ context->clientWrapper = shared_from_this();
+
+ cbdata->context = (void*)context;
+ cbdata->cb = listenCallback;
+
+ {
+ std::lock_guard<std::mutex> lock(m_csdkLock);
+ OCDoHandle handle;
+ result = OCDoResource(&handle, OC_REST_GET, resourceType.c_str(), nullptr, nullptr, OC_NON_CONFIRMABLE, cbdata);
+ }
+ return result;
+ }
+
+ struct GetSetContext
+ {
+ std::function<void(const AttributeMap&, const int&)> callback;
+ };
+
+ AttributeMap parseGetSetCallback(OCClientResponse* clientResponse)
+ {
+ std::stringstream requestStream;
+ requestStream<<clientResponse->resJSONPayload;
+
+ if(strlen((char*)clientResponse->resJSONPayload) == 0)
+ {
+ return AttributeMap();
+ }
+
+ boost::property_tree::ptree root;
+ boost::property_tree::read_json(requestStream, root);
+ boost::property_tree::ptree payload = root.get_child("oc.payload", boost::property_tree::ptree());
+
+ AttributeMap attrs;
+ for(auto& item : payload)
+ {
+ if(item.first.data() == URIKEY)
+ {
+ continue;
+ }
+
+ std::string name = item.first.data();
+ std::string value = item.second.data();
+ AttributeValues values;
+ values.push_back(value);
+ attrs[name] = values;
+ }
+
+ return attrs;
+ }
+ OCStackApplicationResult getResourceCallback(void* ctx, OCDoHandle handle, OCClientResponse* clientResponse)
+ {
+ if(clientResponse->result == OC_STACK_OK)
+ {
+ GetSetContext* context = (GetSetContext*)ctx;
+ AttributeMap attrs = parseGetSetCallback(clientResponse);
+
+ std::thread exec(context->callback,attrs, 200);
+ exec.detach();
+
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ else
+ {
+ std::cout<<"listen Callback got failed result: " << clientResponse->result<<std::endl;
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ }
+ OCStackResult InProcClientWrapper::GetResourceAttributes(const std::string& host, const std::string& uri, std::function<void(const AttributeMap&, const int&)>& callback)
+ {
+ OCStackResult result;
+ OCCallbackData* cbdata = new OCCallbackData();
+ GetSetContext* ctx = new GetSetContext();
+ ctx->callback = callback;
+ cbdata->context = (void*)ctx;
+ cbdata->cb = &getResourceCallback;
+
+ // TODO: in the future the cstack should be combining these two strings!
+ ostringstream os;
+ os << host << uri;
+
+ // TODO: end of above
+
+ {
+ std::lock_guard<std::mutex> lock(m_csdkLock);
+ OCDoHandle handle;
+ //TODO: use above and this line! result = OCDoResource(&handle, OC_REST_GET, uri.c_str(), host.c_str(), nullptr, OC_CONFIRMABLE, cbdata);
+ result = OCDoResource(&handle, OC_REST_GET, os.str().c_str(), nullptr, nullptr, OC_NON_CONFIRMABLE, cbdata);
+ }
+ return result;
+ }
+
+
+ OCStackApplicationResult setResourceCallback(void* ctx, OCDoHandle handle, OCClientResponse* clientResponse)
+ {
+ if(clientResponse->result == OC_STACK_OK)
+ {
+ GetSetContext* context = (GetSetContext*)ctx;
+ AttributeMap attrs = parseGetSetCallback(clientResponse);
+
+ std::thread exec(context->callback, attrs, 200);
+ exec.detach();
+
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ else
+ {
+ std::cout<<"listen Callback got failed result: " << clientResponse->result<<std::endl;
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ }
+
+ std::string InProcClientWrapper::assembleSetResourceUri(std::string uri, const QueryParamsMap& queryParams)
+ {
+ if(uri.back() == '/')
+ {
+ uri.pop_back();
+ }
+
+ ostringstream paramsList;
+ if(queryParams.size() > 0)
+ {
+ paramsList << '?';
+ }
+
+ for(auto& param : queryParams)
+ {
+ paramsList << param.first <<'='<<param.second<<'&';
+ }
+
+ std::string ret = uri + paramsList.str();
+ return ret;
+ }
+
+ std::string InProcClientWrapper::assembleSetResourcePayload(const AttributeMap& attributes)
+ {
+ ostringstream payload;
+ payload << "{\"oc\":{\"payload\":{";
+
+ for(AttributeMap::const_iterator itr = attributes.begin(); itr!= attributes.end(); ++ itr)
+ {
+ if(itr != attributes.begin())
+ {
+ payload << ',';
+ }
+
+ payload << "\""<<itr->first<<"\":\""<< itr->second.front()<<"\"";
+ }
+ payload << "}}}";
+ return payload.str();
+ }
+
+ OCStackResult InProcClientWrapper::SetResourceAttributes(const std::string& host, const std::string& uri, const AttributeMap& attributes, const QueryParamsMap& queryParams, std::function<void(const AttributeMap&,const int&)>& callback)
{
- OCStackResult result;
+ OCStackResult result;
+ OCCallbackData* cbdata = new OCCallbackData();
+ GetSetContext* ctx = new GetSetContext();
+ ctx->callback = callback;
+ cbdata->cb = &setResourceCallback;
- OCCallbackData* cbdata = new OCCallbackData();
- cbdata->context = (void*)(&callback);
- cbdata->cb = &listenCallback;
- {
- std::lock_guard<std::mutex> lock(m_csdkLock);
+ // TODO: in the future the cstack should be combining these two strings!
+ ostringstream os;
+ os << host << assembleSetResourceUri(uri, queryParams).c_str();
- result = OCDoResource(OC_REST_GET, resourceType.c_str(), nullptr, nullptr, OC_NON_CONFIRMABLE, cbdata);
+ // TODO: end of above
- }
- return result;
+ cbdata->context = (void*)ctx;
+ {
+ std::lock_guard<std::mutex> lock(m_csdkLock);
+ OCDoHandle handle;
+ //OCDoResource(&handle, OC_REST_PUT, assembleSetResourceUri(uri.c_str(), queryParams).c_str(), host.c_str(), assembleSetResourcePayload(uri, attributes).c_str(), OC_CONFIRMABLE, cbdata);
+ //TODO: use above and this line! result = OCDoResource(&handle, OC_REST_GET, uri.c_str(), host.c_str(), nullptr, OC_CONFIRMABLE, cbdata);
+ result = OCDoResource(&handle, OC_REST_PUT, os.str().c_str(), nullptr, assembleSetResourcePayload(attributes).c_str(), OC_NON_CONFIRMABLE, cbdata);
+ }
+ return result;
+ }
+
+ struct ObserveContext
+ {
+ std::function<void(const AttributeMap&, const int&)> callback;
+ };
+
+ OCStackApplicationResult observeResourceCallback(void* ctx, OCDoHandle handle, OCClientResponse* clientResponse)
+ {
+ if(clientResponse->result == OC_STACK_OK)
+ {
+ ObserveContext* context = (ObserveContext*)ctx;
+ AttributeMap attrs = parseGetSetCallback(clientResponse);
+
+ std::thread exec(context->callback, attrs, 200);
+ exec.detach();
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ else
+ {
+ std::cout<<"Observe Callback got failed result: "<<clientResponse->result << std::endl;
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ }
+ OCStackResult InProcClientWrapper::ObserveResource(OCDoHandle* handle, const std::string& host, const std::string& uri, std::function<void(const AttributeMap&, const int&)>& callback)
+ {
+ OCStackResult result;
+ OCCallbackData* cbdata = new OCCallbackData();
+ ObserveContext* ctx = new ObserveContext();
+ ctx->callback = callback;
+ cbdata->context = (void*)ctx;
+ cbdata->cb = &observeResourceCallback;
+
+ ostringstream os;
+ os << host<< uri;
+
+ {
+ std::lock_guard<std::mutex> lock(m_csdkLock);
+ //result = OCDoResource(handle, OC_REST_OBSERVE, uri.c_str(), host.c_str(), nullptr, OC_CONFIRMABLE, cbdata);
+ result = OCDoResource(handle, OC_REST_OBSERVE, os.str().c_str(), nullptr, nullptr, OC_NON_CONFIRMABLE, cbdata);
+ }
+ return result;
+ }
+
+ struct UnobserveContext
+ {
+ std::function<void(const int&)> callback;
+ };
+
+ OCStackApplicationResult unobserveResourceCallback(void* ctx, OCDoHandle handle, OCClientResponse* clientResponse)
+ {
+ std::cout << "Unobserve callback called...."<<std::endl;
+ UnobserveContext* context = (UnobserveContext*)ctx;
+ if(clientResponse->result == OC_STACK_OK)
+ {
+ std::thread exec(context->callback, 200);
+ exec.detach();
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ else
+ {
+ std::cout<<"Unobserve callback got failed result: "<<clientResponse->result <<std::endl;
+ std::thread exec(context->callback, clientResponse->result);
+ exec.detach();
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ }
+ OCStackResult InProcClientWrapper::CancelObserveResource(OCDoHandle handle, const std::string& host, const std::string& uri)
+ {
+ OCStackResult result;
+ {
+ std::lock_guard<std::mutex> lock(m_csdkLock);
+ result = OCCancel(handle);
+ }
+ return result;
}
}
#include <cstdlib>
#include <iostream>
#include <algorithm>
+#include <map>
+#include <sstream>
+#include <string>
-#include "InProcServerWrapper.h"
+#include <InProcServerWrapper.h>
#include <InitializeException.h>
#include <OCReflect.h>
+#include <OCResourceRequest.h>
+#include <OCResourceResponse.h>
#include <ocstack.h>
+#include <OCApi.h>
using namespace OC::OCReflect;
using namespace std;
-void entityHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest* eHandlerReq)
+std::map <OCResourceHandle, std::function<void(const OC::OCResourceRequest::Ptr, const OC::OCResourceResponse::Ptr)>> entityHandlerMap;
+
+void defaultEntityHandler(const OC::OCResourceRequest::Ptr request, const OC::OCResourceResponse::Ptr response)
{
- cout << "Resource Handler: " << eHandlerReq->resource << endl;
- cout << "Method: " << eHandlerReq->method << endl;
- cout << "reqJSONPayLoad: " << eHandlerReq->reqJSONPayload << endl;
+ cout << "\nSomething wrong: We are in default entity handler: " << endl;
+}
+
+OCStackResult entityHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest ) {
+
+ // TODO @SASHI we need to have a better way of logging (with various levels of logging)
+ cout << "\nIn C entity handler: " << endl;
+
+ // TODO @SASHI dow we need shared pointer?
+ auto pRequest = std::make_shared<OC::OCResourceRequest>();
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+
+ // TODO @ SASHI Utility to convert from C to C++ (every).
+ switch (flag) {
+ case OC_INIT_FLAG:
+ // TODO @SASHI We can fill the common data (resource Handle, etc.. )
+ // init time.
+ pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::InitFlag);
+ break;
+ case OC_REQUEST_FLAG:
+ pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::RequestFlag);
+
+ if(entityHandlerRequest)
+ {
+ if(OC_REST_GET == entityHandlerRequest->method)
+ {
+ // TODO @SASHI Why strings : "GET"??
+ pRequest->setRequestType("GET");
+ }
+
+ if(OC_REST_PUT == entityHandlerRequest->method)
+ {
+ pRequest->setRequestType("PUT");
+ pRequest->setPayload(std::string(reinterpret_cast<const char*>(entityHandlerRequest->reqJSONPayload)));
+ }
+ }
+ break;
+ case OC_OBSERVE_FLAG:
+ pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::ObserverFlag);
+ break;
+ }
+
+
+ // Finding the corresponding CPP Application entityHandler for a given resource
+ auto entityHandlerEntry = entityHandlerMap.find(entityHandlerRequest->resource);
+
+ if(entityHandlerEntry != entityHandlerMap.end()) {
+ // Call CPP Application Entity Handler
+ entityHandlerEntry->second(pRequest, pResponse);
+ }
+ else {
+ std::cout << "No eintity handler found." << endl;
+ return OC_STACK_ERROR;
+ }
+
+
+ if(flag == OC_REQUEST_FLAG)
+ {
+ // TODO @SASHI we could use const reference
+ std::string payLoad = pResponse->getPayload();
+
+ if(OC_REST_GET == entityHandlerRequest->method)
+ {
+ cout << "\t\t\tGoing from stack for GET: " << payLoad << endl;
+ }
+ else if (OC_REST_PUT == entityHandlerRequest->method)
+ {
+ cout << "\t\t\tGoing from stack for PUT: " << payLoad << endl;
+ }
+
+ // TODO @SASHI Now there is memory that needs to be freed.
+ entityHandlerRequest->resJSONPayload = reinterpret_cast<unsigned char *>(OC::OCReflect::OCStack::strdup(payLoad.c_str()));
+
+ if(nullptr == entityHandlerRequest->resJSONPayload)
+ {
+ // TODO @SASHI throw std::runtime_error("out of memory");
+ cout << "Out of memory in copying to resJSONPayload" << endl;
+ }
+ }
+
+ return OC_STACK_OK;
}
namespace OC
{
OCStackResult result = OCInit(cfg.ipAddress.c_str(), cfg.port, OC_SERVER);
+ // Setting default entity Handler
+ entityHandlerMap[(OCResourceHandle) 0] = defaultEntityHandler;
+
if(OC_STACK_OK != result)
{
throw InitializeException("Error Initializing Stack", result);
}
-
- m_threadRun = true;
+
+ m_threadRun = true;
m_processThread = std::thread(&InProcServerWrapper::processFunc, this);
}
-
- void InProcServerWrapper::processFunc()
+
+ void InProcServerWrapper::processFunc()
{
while(m_threadRun)
{
- OCStackResult result;
- {
- std::lock_guard<std::mutex> lock(m_csdkLock);
- result = OCProcess();
- }
+ OCStackResult result;
+ {
+ // TODO Fix Lock issue
+ // std::lock_guard<std::mutex> lock(m_csdkLock);
+ result = OCProcess();
+ }
if(result != OC_STACK_OK)
{
std::this_thread::yield();
// To minimize CPU utilization we may wish to do this with sleep
- //std::this_thread::sleep_for(std::chrono::milliseconds(1));
+ //std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
- void InProcServerWrapper::registerResource(const std::string& resourceURI,
- const std::string& resourceTypeName,
- property_binding_vector properties)
- {
- using OC::OCReflect::property_type;
- using OC::OCReflect::property_binding;
- using namespace OC::OCReflect::OCStack;
+ OCStackResult InProcServerWrapper::registerResource(
+ OCResourceHandle& resourceHandle,
+ std::string& resourceURI,
+ const std::string& resourceTypeName,
+ const std::string& resourceInterface,
+ std::function<void(const OCResourceRequest::Ptr, const OCResourceResponse::Ptr)> eHandler,
+ uint8_t resourceProperties)
- std::vector<std::string> reps { convert(properties) };
-
- char *resourceTypeRepresentation = flatten(reps);
-
- std::cout << "Resource type representation: " << resourceTypeRepresentation << "\n";
-
- OCResourceHandle resourceHandle;
-
- {
- std::lock_guard<std::mutex> lock(m_csdkLock);
+ {
+ OCStackResult result;
- OCStackResult result;
+ cout << "Registering Resource: \n";
+ cout << "\tResource URI: " << resourceURI << endl;
+ cout << "\tResource TypeName: " << resourceTypeName << endl;
+ cout << "\tResource Interface: " << resourceInterface << endl;
- result = OCCreateResource(&resourceHandle, // OCResourceHandle *handl
- resourceTypeName.c_str(), // const char * resourceTypeName
- resourceTypeRepresentation, //const char * resourceTypeRepresentation
- "core.rw", //const char * resourceInterfaceName
- OC_REST_GET | OC_REST_PUT, // uint8_t allowedMethods
- resourceURI.c_str(), // const char * uri
- entityHandler, // OCEntityHandler entityHandler
- OC_DISCOVERABLE | OC_OBSERVABLE // uint8_t resourceProperties
- );
+ {
+ // TODO @SASHI : Something wrong with lock usage
+ // std::lock_guard<std::mutex> lock(m_csdkLock);
+
+ result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
+ resourceTypeName.c_str(), // const char * resourceTypeName
+ "state:oc.bt.b;power:oc.bt.i", // TODO @SASHI why are we still sending this??
+ resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
+ OC_REST_GET | OC_REST_PUT, // uint8_t allowedMethods
+ resourceURI.c_str(), // const char * uri
+ entityHandler, // OCEntityHandler entityHandler
+ resourceProperties // uint8_t resourceProperties
+ );
if(result != OC_STACK_OK)
{
- cout << "Something wrong in OCCreateResource" << endl;
+ cout << "\tSomething wrong in creating the resource" << endl;
+ resourceHandle = (OCResourceHandle) 0;
// TODO: SASHI
}
else
{
- cout << "Resource creation is successful" << endl;
+ cout << "\tResource creation is successful with resource handle: " << resourceHandle << endl;
+ entityHandlerMap[resourceHandle] = eHandler;
}
-
- }
-
+ }
+
+ return result;
}
InProcServerWrapper::~InProcServerWrapper()
{
- if(m_processThread.joinable())
+ if(m_processThread.joinable())
{
m_threadRun = false;
m_processThread.join();
}
-
+
OCStop();
}
}
#include <random>
#include "OCPlatform.h"
+#include "OCApi.h"
namespace OC
{
cleanup();
}
+ OCStackResult OCPlatform::notifyObservers(OCResourceHandle resourceHandle)
+ {
+ return OCNotifyObservers(resourceHandle);
+ }
+
void OCPlatform::init(const PlatformConfig& config)
{
std::unique_ptr<WrapperFactory> wrapperInstance(new WrapperFactory());
}
- void OCPlatform::findResource(const std::string& host, const std::string& resourceName,
+ OCStackResult OCPlatform::findResource(const std::string& host, const std::string& resourceName,
std::function<void(OCResource::Ptr)> resourceHandler)
{
+ OCStackResult result = OC_STACK_OK;
+
if(m_client)
{
+ // TODO this should return
m_client->ListenForResource(host, resourceName, resourceHandler);
}
+
+ return result;
}
- void OCPlatform::registerResource(std::string& resourceURI, const std::string& resourceTypeName, const std::string& resourceInterface,
- std::function<void(const OCResourceRequest::Ptr, const OCResourceResponse::Ptr)> entityHandler, ResourceFlag resourceFlag)
+ OCStackResult OCPlatform::registerResource(OCResourceHandle& resourceHandle,
+ std::string& resourceURI,
+ const std::string& resourceTypeName,
+ const std::string& resourceInterface,
+ std::function<void(const OCResourceRequest::Ptr, const OCResourceResponse::Ptr)> entityHandler,
+ uint8_t resourceProperty)
{
+ OCStackResult result = OC_STACK_OK;
+
if(m_server)
{
try{
- // Adding below statement for compilation sake
- property_binding_vector properties;
- m_server->registerResource(resourceURI, resourceTypeName, properties);
- }catch(std::exception e) // define our own expception.
+ result = m_server->registerResource(resourceHandle, resourceURI, resourceTypeName, resourceInterface, entityHandler, resourceProperty);
+ }
+ catch(std::exception e) // define our own expception.
{
throw e;
}
}
+
+ return result;
}
} //namespace OC
#include "OCReflect.h"
namespace OC {
- OCResource::OCResource(const std::string host, boost::property_tree::ptree& resourceNode) : m_isCollection(false)
- {
- m_host = host;
- m_uri = resourceNode.get<std::string>("href","");
- m_isObservable = resourceNode.get<int>("obs",0)==1;
-
- boost::property_tree::ptree resourceTypes = resourceNode.get_child("rt", boost::property_tree::ptree());
- for(auto itr : resourceTypes)
+ OCResource::OCResource(IClientWrapper::Ptr clientWrapper, const std::string& host, const std::string& uri, bool observable, const std::vector<std::string>& resourceTypes, const std::vector<std::string>& interfaces) :
+ m_clientWrapper(clientWrapper), m_uri(uri), m_host(host), m_isObservable(observable), m_isCollection(false), m_resourceTypes(resourceTypes), m_interfaces(interfaces), m_observeHandle(nullptr)
+ {
+ m_isCollection = std::find(m_interfaces.begin(), m_interfaces.end(), LINK_INTERFACE) != m_interfaces.end();
+
+ if (m_uri.empty() || resourceTypes.empty() || interfaces.empty()|| ! m_clientWrapper)
+ {
+ throw ResourceInitException(m_uri.empty(), resourceTypes.empty(), interfaces.empty(), m_clientWrapper.get() == nullptr);
+ }
+ }
+
+ OCResource::~OCResource()
+ {
+ }
+
+ OCStackResult OCResource::get(std::function<void(const AttributeMap&, const int&)> attributeHandler)
+ {
+ return m_clientWrapper->GetResourceAttributes(m_host, m_uri, attributeHandler);
+ }
+
+ OCStackResult OCResource::put(const AttributeMap& attributeMap, const QueryParamsMap& queryParametersMap, std::function<void(const AttributeMap&, const int&)> attributeHandler)
+ {
+ return m_clientWrapper->SetResourceAttributes(m_host, m_uri, attributeMap, queryParametersMap, attributeHandler);
+ }
+
+ OCStackResult OCResource::observe(std::function<void(const AttributeMap&, const int&)> observeHandler)
+ {
+ if(m_observeHandle != nullptr)
{
- m_resourceTypes.push_back(itr.second.data());
+ return OC_STACK_INVALID_PARAM;
}
-
- boost::property_tree::ptree interfaces = resourceNode.get_child("if", boost::property_tree::ptree());
- for(auto itr : interfaces)
+ else
+ {
+ return m_clientWrapper->ObserveResource(&m_observeHandle, m_host, m_uri, observeHandler);
+ }
+ }
+
+ OCStackResult OCResource::cancelObserve()
+ {
+ if(m_observeHandle == nullptr)
{
- if(itr.second.data() == "oc.mi.ll")
- {
- m_isCollection = true;
- }
-
- m_interfaces.push_back(itr.second.data());
+ return OC_STACK_INVALID_PARAM;
}
-
- // TODO: If collection, load children, assuming this becomes a thing
-
- // TODO: Load attributes, assuming this becomes a 'thing'
-
- if (m_uri.empty() || resourceTypes.empty() || interfaces.empty())
+ else
{
- throw ResourceInitException(m_uri.empty(), resourceTypes.empty(), interfaces.empty());
+ OCStackResult ret = m_clientWrapper->CancelObserveResource(m_observeHandle, m_host, m_uri);
+ m_observeHandle = nullptr;
+ return ret;
}
}
-
- OCResource::~OCResource()
+
+ std::string OCResource::host() const
+ {
+ return m_host;
+ }
+ std::string OCResource::uri() const
+ {
+ return m_uri;
+ }
+ bool OCResource::isObservable() const
{
+ return m_isObservable;
}
} // namespace OC
// OCClient.cpp : Defines the entry point for the console application.
//
#include <string>
-
+#include <cstdlib>
+#include <pthread.h>
#include "OCPlatform.h"
using namespace OC;
const int SUCCESS_RESPONSE = 200;
+std::shared_ptr<OCResource> curResource;
-// callback handler on GET request
-void onGet(const AttributeMap& attributeMap, const int& eCode)
+int observe_count()
+{
+ static int oc = 0;
+ return ++oc;
+}
+
+void onObserve(const AttributeMap& attributeMap, const int& eCode)
{
if(eCode == SUCCESS_RESPONSE)
{
+ std::cout << "OBSERVE RESULT:"<<std::endl;
for(auto it = attributeMap.begin(); it != attributeMap.end(); ++it)
{
- std::cout << "Attribute name: "<< it->first << " value: ";
+ std::cout << "\tAttribute name: "<< it->first << " value: ";
for(auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr)
{
- std::cout << *valueItr << " ";
+ std::cout <<"\t"<< *valueItr << " ";
}
std::cout << std::endl;
}
- }
- else
- {
- std::cout << "Response error: " << eCode << std::endl;
- }
-}
+
+ if(observe_count() > 3)
+ {
+ std::cout<<"Cancelling Observe..."<<std::endl;
+ OCStackResult result = curResource->cancelObserve();
-// callback handler on PUT request
-void onPut(const int& eCode)
-{
- if(eCode == SUCCESS_RESPONSE)
- {
- std::cout << "Put request was successful" << std::endl;
+ std::cout << "Cancel result: "<< result <<std::endl;
+ sleep(10);
+ std::cout << "DONE"<<std::endl;
+ std::exit(0);
+ }
}
else
{
- std::cout << "Response error: " << eCode << std::endl;
+ std::cout << "onObserve Response error: " << eCode << std::endl;
+ std::exit(-1);
}
}
-// callback handler on observation
-void onObserve(const AttributeMap& attributeMap, const int& eCode)
+// callback handler on PUT request
+void onPut(const AttributeMap& attributeMap, const int& eCode)
{
if(eCode == SUCCESS_RESPONSE)
{
- std::cout << "Observe callback invoked" << std::endl;
+ std::cout << "PUT request was successful" << std::endl;
+
for(auto it = attributeMap.begin(); it != attributeMap.end(); ++it)
{
- std::cout << "Attribute name: "<< it->first << " value: ";
+ std::cout << "\tAttribute name: "<< it->first << " value: ";
for(auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr)
{
- std::cout << *valueItr << " ";
+ std::cout <<"\t"<< *valueItr << " ";
}
std::cout << std::endl;
}
+ curResource->observe(&onObserve);
}
else
{
- std::cout << "Response error: " << eCode << std::endl;
- }
-}
-
-// callback handler for observe cancellation
-void onCancelObservation(const int& eCode)
-{
- if(eCode == SUCCESS_RESPONSE)
- {
- std::cout << "Put request was successful" << std::endl;
- }
- else
- {
- std::cout << "Response error: " << eCode << std::endl;
+ std::cout << "onPut Response error: " << eCode << std::endl;
+ std::exit(-1);
}
}
{
if(resource)
{
+ std::cout << "Putting light representation..."<<std::endl;
// Create AttributeMap
AttributeMap attributeMap;
// Add the attribute name and values in the attribute map
stateVal.push_back("true");
AttributeValues powerVal;
- powerVal.push_back("100");
+ powerVal.push_back("10");
attributeMap["state"] = stateVal;
attributeMap["power"] = powerVal;
}
}
-// Local function to get representation of light resource
-void getLightRepresentation(std::shared_ptr<OCResource> resource)
+// callback handler on GET request
+void onGet(const AttributeMap& attributeMap, const int& eCode)
{
- if(resource)
+ if(eCode == SUCCESS_RESPONSE)
{
- // Invoke resource's get API with the callback parameter
- resource->get(&onGet);
- }
-}
+ std::cout << "GET Succeeded:"<<std::endl;
+ for(auto it = attributeMap.begin(); it != attributeMap.end(); ++it)
+ {
+ std::cout << "\tAttribute name: "<< it->first << " value: ";
+ for(auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr)
+ {
+ std::cout <<"\t"<< *valueItr << " ";
+ }
-// Local function to observe on a resource (in this case light)
-void observeOnLight(std::shared_ptr<OCResource> resource)
-{
- if(resource)
+ std::cout << std::endl;
+ }
+
+ putLightRepresentation(curResource);
+ }
+ else
{
- // Invoke resource's observe API with the callback parameter
- resource->observe(&onObserve);
+ std::cout << "onGet Response error: " << eCode << std::endl;
+ std::exit(-1);
}
}
-
-// Local function to cancel the observation on a resource
-void cancelObservation(std::shared_ptr<OCResource> resource)
+// Local function to get representation of light resource
+void getLightRepresentation(std::shared_ptr<OCResource> resource)
{
if(resource)
{
- // Invoke resource's cancelObserve API with the callback parameter
- resource->cancelObserve(&onCancelObservation);
+ std::cout << "Getting Light Representation..."<<std::endl;
+ // Invoke resource's get API with the callback parameter
+ resource->get(&onGet);
}
}
// Callback to found resources
void foundResource(std::shared_ptr<OCResource> resource)
{
+
+ if(curResource)
+ {
+ std::cout << "Found another resource, ignoring"<<std::endl;
+ }
+
std::string resourceURI;
std::string hostAddress;
try
// Do some operations with resource object.
if(resource)
{
+ std::cout<<"DISCOVERED Resource:"<<std::endl;
// Get the resource URI
resourceURI = resource->uri();
- std::cout << "URI of the resource: " << resourceURI << std::endl;
+ std::cout << "\tURI of the resource: " << resourceURI << std::endl;
// Get the resource host address
hostAddress = resource->host();
- std::cout << "Host address of the resource: " << hostAddress << std::endl;
+ std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
if(resourceURI == "/a/light")
{
+ curResource = resource;
// Call a local function which will internally invoke get API on the resource pointer
getLightRepresentation(resource);
-
- // Do some operations
-
- // Call a local function which will internally invoke get API on the resource pointer
- putLightRepresentation(resource);
-
- // Do some operations
-
- // Call a local function which will internally observe on this resource for further notifications
- observeOnLight(resource);
-
- // Do some operations
-
- // Call a local function which will internally cancel observation on this resource
- cancelObservation(resource);
}
}
else
try
{
OCPlatform platform(cfg);
-
+ std::cout << "Created Platform..."<<std::endl;
// Find all resources
- platform.findResource("", "coap://224.0.1.187/oc/core", &foundResource);
-
+ platform.findResource("", "coap://224.0.1.187/oc/core?rt=core.light", &foundResource);
+ std::cout<< "Finding Resource... " <<std::endl;
while(true)
{
// some operations
#include <functional>
+#include <pthread.h>
+
#include "OCPlatform.h"
#include "OCApi.h"
using namespace OC;
+using namespace std;
+
+int gObservation = 0;
+
+// Forward declaring the entityHandler
+void entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
+
+/// This class represents a single resource named 'lightResource'. This resource has
+/// two simple properties named 'state' and 'power'
+
+class LightResource
+{
+public:
+ /// Access this property from a TB client
+ bool m_state;
+ int m_power;
+ OCResourceHandle m_resourceHandle;
+
+public:
+ /// Constructor
+ LightResource(): m_state(false), m_power(0){}
+
+ /* Note that this does not need to be a member function: for classes you do not have
+ access to, you can accomplish this with a free function: */
+
+ /// This function internally calls registerResource API.
+ void createResource(OC::OCPlatform& platform)
+ {
+ std::string resourceURI = "/a/light"; // URI of the resource
+ std::string resourceTypeName = "core.light"; // resource type name. In this case, it is light
+ std::string resourceInterface = PARAMETER_INTERFACE; // resource interface.
+
+ // OCResourceProperty is defined ocstack.h
+ uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
+
+ // This will internally create and register the resource.
+ OCStackResult result = platform.registerResource(
+ m_resourceHandle, resourceURI, resourceTypeName,
+ resourceInterface, &entityHandler, resourceProperty);
+
+ if (OC_STACK_OK != result)
+ {
+ cout << "Resource creation was unsuccessful\n";
+ }
+ }
+
+ OCResourceHandle getHandle()
+ {
+ return m_resourceHandle;
+ }
+
+ void setRepresentation(AttributeMap& attributeMap)
+ {
+ cout << "\t\t\t" << "Received representation: " << endl;
+ cout << "\t\t\t\t" << "power: " << attributeMap["power"][0] << endl;
+ cout << "\t\t\t\t" << "state: " << attributeMap["state"][0] << endl;
+
+ m_state = attributeMap["state"][0].compare("true") == 0;
+ m_power = std::stoi(attributeMap["power"][0]);
+ }
+
+ void getRepresentation(AttributeMap& attributeMap)
+ {
+ AttributeValues stateVal;
+ if(m_state)
+ {
+ stateVal.push_back("true");
+ }
+ else
+ {
+ stateVal.push_back("false");
+ }
+
+ AttributeValues powerVal;
+ powerVal.push_back(to_string(m_power));
+
+ attributeMap["state"] = stateVal;
+ attributeMap["power"] = powerVal;
+ }
+};
+
+// Create the instance of the resource class (in this case instance of class 'LightResource').
+LightResource myLightResource;
+
+// ChangeLightRepresentaion is an observation function,
+// which notifies any changes to the resource to stack
+// via notifyObservers
+void * ChangeLightRepresentation (void *param)
+{
+ // This function continuously monitors for the changes
+ while (1)
+ {
+ sleep (5);
+
+ if (gObservation)
+ {
+ // If under observation if there are any changes to the light resource
+ // we call notifyObservors
+ //
+ // For demostration we are changing the power value and notifying.
+ myLightResource.m_power += 10;
+
+ cout << "\nPower updated to : " << myLightResource.m_power << endl;
+ cout << "Notifying observers with resource handle: " << myLightResource.getHandle() << endl;
+
+ OCStackResult result = OCPlatform::notifyObservers(myLightResource.getHandle());
+
+ if(OC_STACK_NO_OBSERVERS == result)
+ {
+ cout << "No More observers, stopping notifications" << endl;
+ gObservation = 0;
+ }
+ }
+ }
+
+ return NULL;
+}
+
// This is just a sample implementation of entity handler.
// Entity handler can be implemented in several ways by the manufacturer
void entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
{
- // add the headers in this map before sending the response
- HeadersMap headersMap;
- headersMap["content-type"] = "text";
- headersMap["server"] = "serverName";
+ cout << "\tIn Server CPP entity handler:\n";
if(request)
{
if(requestFlag == RequestHandlerFlag::InitFlag)
{
+ cout << "\t\trequestFlag : Init\n";
+
// entity handler to perform resource initialization operations
}
else if(requestFlag == RequestHandlerFlag::RequestFlag)
{
+ cout << "\t\trequestFlag : Request\n";
+
// If the request type is GET
if(requestType == "GET")
{
+ cout << "\t\t\trequestType : GET\n";
+
// Check for query params (if any)
QueryParamsMap queryParamsMap = request->getQueryParameters();
// Get the representation of this resource at this point and send it as response
AttributeMap attributeMap;
- AttributeValues stateVal;
- stateVal.push_back("false");
-
- AttributeValues powerVal;
- powerVal.push_back("0");
- attributeMap["state"] = stateVal;
- attributeMap["power"] = powerVal;
+ myLightResource.getRepresentation(attributeMap);
if(response)
- {
- response->setResponseHeaders(headersMap);
- response->setHTTPErrorCode(200);
+ {
+ // TODO Error Code
+ response->setErrorCode(200);
response->setResourceRepresentation(attributeMap);
}
}
else if(requestType == "PUT")
{
+ cout << "\t\t\trequestType : PUT\n";
+
// Check for query params (if any)
QueryParamsMap queryParamsMap = request->getQueryParameters();
// Get the representation from the request
AttributeMap attributeMap = request->getResourceRepresentation();
-
- // Do related operations related to PUT request
- // Change the attribute map accordingly and send a response
- AttributeValues stateVal;
- stateVal.push_back("true");
+ myLightResource.setRepresentation(attributeMap);
- AttributeValues powerVal;
- powerVal.push_back("100");
-
- attributeMap["state"] = stateVal;
- attributeMap["power"] = powerVal;
+ // Do related operations related to PUT request
+
+ myLightResource.getRepresentation(attributeMap);
if(response)
{
- response->setResponseHeaders(headersMap);
- response->setHTTPErrorCode(200);
+ response->setErrorCode(200);
response->setResourceRepresentation(attributeMap);
}
}
}
else if(requestFlag == RequestHandlerFlag::ObserverFlag)
{
- // perform observe related operations on the resource.
- // Add the attributes to the map and send a response
-
- // on any attribute change on the light resource hardware,
- // set the attributes and send response
- AttributeMap attributeMap;
+ pthread_t threadId;
- AttributeValues stateVal;
- stateVal.push_back("false");
-
- AttributeValues powerVal;
- powerVal.push_back("0");
+ cout << "\t\trequestFlag : Observer\n";
+ gObservation = 1;
- attributeMap["state"] = stateVal;
- attributeMap["power"] = powerVal;
-
- if(response)
+ static int startedThread = 0;
+
+ // Observation happens on a different thread in ChangeLightRepresentation function.
+ // If we have not created the thread already, we will create one here.
+ if(!startedThread)
{
- response->setResponseHeaders(headersMap);
- response->setHTTPErrorCode(200);
- response->setResourceRepresentation(attributeMap);
+ pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL);
+ startedThread = 1;
}
+
}
}
else
}
}
-/// This class represents a single resource named 'lightResource'. This resource has
-/// two simple properties named 'state' and 'power'
-
-class LightResource
-{
-public:
- /// Access this property from a TB client
- bool m_state;
- int m_power;
-
-public:
- /// Constructor
- LightResource(): m_state(false), m_power(0){}
-
- /* Note that this does not need to be a member function: for classes you do not have
- access to, you can accomplish this with a free function: */
-
- /// This function internally calls registerResource API.
- void createResource(OC::OCPlatform& platform)
- {
- std::string resourceURI = "a/light"; // URI of the resource
- std::string resourceTypeName = "light"; // resource type name. In this case, it is light
- std::string resourceInterface = LINK_INTERFACE; // resource interface.
- ResourceFlag resourceFlag = ResourceFlag::ObserverFlag; // set the resource flag to Observerable
-
- // This will internally create and register the resource.
- platform.registerResource(resourceURI, resourceTypeName, resourceInterface, &entityHandler, resourceFlag);
- }
-};
-
int main()
{
// Create PlatformConfig object
PlatformConfig cfg;
cfg.ipAddress = "134.134.161.33";
- cfg.port = 5683;
+ cfg.port = 56832;
cfg.mode = ModeType::Server;
cfg.serviceType = ServiceType::InProc;
{
OCPlatform platform(cfg);
- // Create the instance of the resource class (in this case instance of class 'LightResource').
- // Invoke bindTo function of class light.
+ // Invoke createResource function of class light.
- LightResource myLightResource;
myLightResource.createResource(platform);
-
+
// Perform app tasks
while(true)
{
#include <string>
#include <OCApi.h>
-#include <OCResource.h>
-
namespace OC
{
- class OCResource;
- class IClientWrapper
+ class IClientWrapper : public std::enable_shared_from_this<IClientWrapper>
{
public:
typedef std::shared_ptr<IClientWrapper> Ptr;
-
- virtual int ListenForResource(const std::string& serviceUrl, const std::string& resourceType,
- std::function<void(OCResource::Ptr)>& callback) = 0;
+ virtual OCStackResult ListenForResource(const std::string& serviceUrl, const std::string& resourceType,
+ std::function<void(std::shared_ptr<OCResource>)>& callback) = 0;
+ virtual OCStackResult GetResourceAttributes(const std::string& host, const std::string& uri, std::function<void(const AttributeMap&, const int&)>& callback)=0;
+ virtual OCStackResult SetResourceAttributes(const std::string& host, const std::string& uri, const AttributeMap& attributes, const QueryParamsMap& queryParams, std::function<void(const AttributeMap&,const int&)>& callback)=0;
+ virtual OCStackResult ObserveResource(OCDoHandle* handle, const std::string& host, const std::string& uri, std::function<void(const AttributeMap&, const int&)>& callback)=0;
+ virtual OCStackResult CancelObserveResource(OCDoHandle handle, const std::string& host, const std::string& uri)=0;
virtual ~IClientWrapper(){}
+
+ // Note: this should never be called by anyone but the handler for the listen command. It is public becuase that needs to be a non-instance callback
+ virtual std::shared_ptr<OCResource> parseOCResource(IClientWrapper::Ptr clientWrapper, const std::string& host, const boost::property_tree::ptree resourceNode)=0;
private:
};
}
#include <string>
#include <OCReflect.h>
+#include <OCResourceRequest.h>
+#include <OCResourceResponse.h>
+#include <OCApi.h>
using namespace OC::OCReflect;
virtual ~IServerWrapper(){};
- virtual void registerResource( const std::string& resourceURI,
- const std::string& resourceTypeName,
- property_binding_vector properties) = 0;
+ virtual OCStackResult registerResource(
+ OCResourceHandle& resourceHandle,
+ std::string& resourceURI,
+ const std::string& resourceTypeName,
+ const std::string& resourceInterface,
+ std::function<void(const OCResourceRequest::Ptr, const OCResourceResponse::Ptr)> entityHandler,
+ uint8_t resourceProperty) = 0;
+
};
}
InProcClientWrapper(PlatformConfig cfg);
virtual ~InProcClientWrapper();
- virtual int ListenForResource(const std::string& serviceUrl, const std::string& resourceType, std::function<void(OCResource::Ptr)>& callback);
-
+ virtual OCStackResult ListenForResource(const std::string& serviceUrl, const std::string& resourceType, std::function<void(std::shared_ptr<OCResource>)>& callback);
+ virtual OCStackResult GetResourceAttributes(const std::string& host, const std::string& uri, std::function<void(const AttributeMap&, const int&)>& callback);
+ virtual OCStackResult SetResourceAttributes(const std::string& host, const std::string& uri, const AttributeMap& attributes, const QueryParamsMap& queryParams, std::function<void(const AttributeMap&,const int&)>& callback);
+ virtual OCStackResult ObserveResource(OCDoHandle* handle, const std::string& host, const std::string& uri, std::function<void(const AttributeMap&, const int&)>& callback);
+ virtual OCStackResult CancelObserveResource(OCDoHandle handle, const std::string& host, const std::string& uri);
+
+ // Note: this should never be called by anyone but the handler for the listen command. It is public becuase that needs to be a non-instance callback
+ virtual std::shared_ptr<OCResource> parseOCResource(IClientWrapper::Ptr clientWrapper, const std::string& host, const boost::property_tree::ptree resourceNode);
private:
void listeningFunc();
+ std::string assembleSetResourceUri(std::string uri, const QueryParamsMap& queryParams);
+ std::string assembleSetResourcePayload(const AttributeMap& attributes);
std::thread m_listeningThread;
bool m_threadRun;
std::mutex m_resourceListenerLock;
- std::mutex m_csdkLock;
+ std::mutex m_csdkLock;
std::vector<std::function<void(OCClientResponse*)>> callbackList;
+
};
}
#include <thread>
#include <mutex>
#include <ocstack.h>
-#include <OCApi.h>
+
#include <IServerWrapper.h>
-#include <OCReflect.h>
using namespace OC::OCReflect;
InProcServerWrapper(PlatformConfig cfg);
virtual ~InProcServerWrapper();
- void registerResource( const std::string& resourceURI,
- const std::string& resourceTypeName,
- property_binding_vector properties);
-
+ virtual OCStackResult registerResource(
+ OCResourceHandle& resourceHandle,
+ std::string& resourceURI,
+ const std::string& resourceTypeName,
+ const std::string& resourceInterface,
+ std::function<void(const OCResourceRequest::Ptr, const OCResourceResponse::Ptr)> entityHandler,
+ uint8_t resourceProperty);
+
private:
void processFunc();
std::thread m_processThread;
ObserverFlag
};
- enum class ResourceFlag
- {
- DiscoverableFlag,
- ObserverFlag
- };
-
// TODO: To find the complete JSon data structure and modify map value type
+ // Typedef for attribute values and attribute map.
typedef std::vector<std::string> AttributeValues;
typedef std::map<std::string, AttributeValues> AttributeMap;
+ // Typedef for query parameter map
typedef std::map<std::string, std::string> QueryParamsMap;
- typedef std::map<std::string, std::string> HeadersMap;
-
+ // const strings for different interfaces
+ // Used in discovering (GET) links to other resources of a container/collection.
const std::string LINK_INTERFACE = "oc.mi.ll";
+
+ // Used in GET, PUT, POST, DELETE methods on links to other resources of a container/collection.
const std::string BATCH_INTERFACE = "oc.mi.b";
+
+ // Used to signify that the resource supports ONLY GET method
const std::string SENSOR_INTERFACE = "oc.mi.s";
+
+ // Used to signify that the resource supports GET, PUT, POST, DELETE methods
const std::string ACTUATOR_INTERFACE = "oc.mi.a";
+
+ // OPENS
const std::string PARAMETER_INTERFACE = "oc.mi.p";
const std::string READ_PARAMETER_INTERFACE = "oc.mi.rp";
*/
virtual ~OCPlatform(void);
+ /**
+ * API for notifying core that resource's attributes have changed.
+ *
+ * @param OCResourceHandle resource handle of the resource
+ *
+ * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * NOTE: This API is for server side only.
+ * NOTE: OCResourceHandle is defined in ocstack.h.
+ * NOTE: OCStackResult is defined in ocstack.h.
+ */
+ static OCStackResult notifyObservers(OCResourceHandle resourceHandle);
+
/**
* API for Service and Resource Discovery.
* NOTE: This API applies to client side only.
* (Not Empty, NULL/Empty) - Performs ALL resource discovery on a particular service.
* (Not Empty, Not Empty) - Performs query for a filtered/scoped/particular resource(s)
* from a particular service.
+ *
+ * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
* NOTE: First parameter 'host' currently represents an IP address. This will change in future
* and will refer to endpoint interface so that we can refer to other transports such as BTH etc.
- * Example:
- *
+ * NOTE: OCStackResult is defined in ocstack.h.
*/
- void findResource(const std::string& host, const std::string& resourceURI,
+ OCStackResult findResource(const std::string& host, const std::string& resourceURI,
std::function<void(OCResource::Ptr)> resourceHandler);
/**
* This API registers a resource with the server
* NOTE: This API applies to server side only.
*
+ * @param resourceHandle - Upon successful registration, resourceHandle will be filled
* @param resourceURI - The URI of the resource. Example: "a/light". See NOTE below
* @param resourceTypeName - The resource type. Example: "light"
* @param resourceInterface - The resource interface (whether it is collection etc).
* @param entityHandler - entity handler callback.
- * @param resourceFlag - flag to indicate discoverable/observable etc.
+ * @param resourceProperty - indicates the property of the resource. Defined in ocstack.h.
+ * setting resourceProperty as OC_DISCOVERABLE will allow Discovery of this resource
+ * setting resourceProperty as OC_OBSERVABLE will allow observation
+ * settings resourceProperty as OC_DISCOVERABLE | OC_OBSERVABLE will allow both discovery and observation
*
+ * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
* NOTE: "a/light" is a relative URI.
* Above relative URI will be prepended (by core) with a host IP + namespace "oc"
* Therefore, fully qualified URI format would be //HostIP-Address/namespace/relativeURI"
* First parameter can take a relative URI and core will take care of preparing the fully qualified URI
* OR
* first paramter can take fully qualified URI and core will take that as is for further operations
+ * NOTE: OCStackResult is defined in ocstack.h.
*/
- void registerResource(std::string& resourceURI, const std::string& resourceTypeName, const std::string& resourceInterface,
- std::function<void(const OCResourceRequest::Ptr, const OCResourceResponse::Ptr)> entityHandler, ResourceFlag resourceFlag);
+ OCStackResult registerResource(OCResourceHandle& resourceHandle,
+ std::string& resourceURI,
+ const std::string& resourceTypeName,
+ const std::string& resourceInterface,
+ std::function<void(const OCResourceRequest::Ptr, const OCResourceResponse::Ptr)> entityHandler,
+ uint8_t resourceProperty);
private:
std::unique_ptr<WrapperFactory> m_WrapperInstance;
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-/// @file OCResource.h
+/// @file OCResource.h
/// @brief This file contains the declaration of classes and its members related to
/// Resource.
#include <memory>
#include <random>
+#include <algorithm>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <OCApi.h>
#include <ResourceInitException.h>
+#include <IClientWrapper.h>
+#include <InProcClientWrapper.h>
namespace OC
{
*/
class OCResource
{
+ friend class InProcClientWrapper;
public:
typedef std::shared_ptr<OCResource> Ptr;
- // TODO: This constructor needs to be removed when we give the final version
- // TODO: See if we can do const prop tree
- OCResource(const std::string host, boost::property_tree::ptree& resourceNode);
-
+ /**
+ * Virtual destructor
+ */
virtual ~OCResource(void);
/**
* Function to get the attributes of a resource.
- * TODO : Need to have query params? Add implementation in .cpp
* @param attributeHandler handles callback
* The callback function will be invoked with a map of attribute name and values.
* The callback function will also have the result from this Get operation
- * This will have HTTP error codes
+ * This will have error codes
+ * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * NOTE: OCStackResult is defined in ocstack.h.
*/
- void get(std::function<void(const AttributeMap&, const int&)> attributeHandler) { return; }
+ OCStackResult get(std::function<void(const AttributeMap&, const int&)> attributeHandler);
/**
* Function to set the attributes of a resource (via PUT)
- * TODO Add implementation in .cpp
- * @param AttributeMap Map which can either have all the attribute names and values
- (which will represent entire state of the resource) or a
- * set of attribute names and values which needs to be modified
- * (which will represent part of the resoruce state) via PUT
- * @param queryParametersMap a map which will have the query parameters (if any)
- * NOTE: For the current release, only '&' semantics will be provided
- * @param attributeHandler handles callback
- * The callback function will be invoked with a map of attribute name and values.
- * The callback function will also have the result from this Put operation
- * This will have HTTP error codes
+ * @param AttributeMap Map which can either have all the attribute names and values
+ (which will represent entire state of the resource) or a
+ * set of attribute names and values which needs to be modified
+ * The callback function will be invoked with a map of attribute name and values.
+ * The callback function will also have the result from this Put operation
+ * This will have error codes
+ * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * NOTE: OCStackResult is defined in ocstack.h.
*/
- void put(const AttributeMap& attributeMap, const QueryParamsMap& queryParametersMap, std::function<void(const int&)> attributeHandler) { return; }
+ OCStackResult put(const AttributeMap& attributeMap, const QueryParamsMap& queryParametersMap, std::function< void(const AttributeMap&,const int&)> attributeHandler);
/**
- * Function to set observation on the resource
- * TODO Add implementation in .cpp
+ * Function to set observation on the resource
* @param observeHandler handles callback
- * The callback function will be invoked with a map of attribute name and values.
- * The callback function will also have the result from this observe operation
- * This will have HTTP error codes
+ * The callback function will be invoked with a map of attribute name and values.
+ * The callback function will also have the result from this observe operation
+ * This will have error codes
+ * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * NOTE: OCStackResult is defined in ocstack.h.
*/
- void observe(std::function<void(const AttributeMap&, const int&)> observeHandler) { return; }
+ OCStackResult observe(std::function<void(const AttributeMap&, const int&)> observeHandler);
/**
* Function to cancel the observation on the resource
- * TODO Add implementation in .cpp
* @param observeCancellationHandler handles callback
- * The callback function will also have the result from this operation
- * This will have HTTP error codes
+ * The callback function will also have the result from this operation
+ * This will have error codes
+ * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * NOTE: OCStackResult is defined in ocstack.h.
*/
- void cancelObserve(std::function<void(const int&)> observeCancellationHandler) { return; }
+ OCStackResult cancelObserve();
/**
* Function to get the host address of this resource
* @return std::string host address
* NOTE: This might or might not be exposed in future due to security concerns
*/
- std::string host() const {return m_host;}
-
+ std::string host() const;
+
/**
* Function to get the URI for this resource
- * @return std::string resource URI
+ * @return std::string resource URI
*/
- std::string uri() const {return m_uri;}
+ std::string uri() const;
/**
* Function to provide ability to check if this resource is observable or not
* @return bool true indicates resource is observable; false indicates resource is
* not observable.
*/
- bool isObservable() const {return m_isObservable;}
-
- /*
- * Allows the server to call notifyObserver
- * @return bool true indicates this operation was success; false indicates this
- * operation failed
- */
- //static bool notifyObservers(const std::string& resourceURI);
+ bool isObservable() const;
// bool whether this is a collection type, and will have children that can be queried
//bool isCollection() const {return m_isCollection;}
/*void post(const AttributeMap&, std::function<void(const int&)> attributeHandler);
- NOTE: dont expose the host ip .. so some kind of handle is required
- static OCResource::Ptr getResource(const std::string& host, const std::string& resourceURI, const std::string& resourceName,
+ NOTE: dont expose the host ip .. so some kind of handle is required
+ static OCResource::Ptr getResource(const std::string& host, const std::string& resourceURI, const std::string& resourceName,
const std::string interfaceName, bool observerable);*/
-
- private:
+
+ private:
+ IClientWrapper::Ptr m_clientWrapper;
std::string m_uri;
std::string m_host;
bool m_isObservable;
std::vector<std::string> m_interfaces;
std::vector<std::string> m_children;
AttributeMap m_attributeMap;
+ OCDoHandle m_observeHandle;
+
+ private:
+ OCResource(IClientWrapper::Ptr clientWrapper, const std::string& host, const std::string& uri,
+ bool observable, const std::vector<std::string>& resourceTypes, const std::vector<std::string>& interfaces);
};
} // namespace OC
#ifndef __OCRESOURCEREQUEST_H
#define __OCRESOURCEREQUEST_H
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/json_parser.hpp>
+
#include "OCApi.h"
namespace OC
/**
* Virtual destructor
*/
- virtual ~OCResourceRequest(void);
+ virtual ~OCResourceRequest(void)
+ {
+ }
/**
* Retrieves the type of request string for the entity handler function to operate
*/
std::string getRequestType() const {return m_requestType;}
- /**
- * Retrieves the payload from the request.
- * NOTE: Query parameters are retrived in a separate API (see 'getRequestPayload')
- * @return std:string request payload
- */
- std::string getRequestPayload() const {return m_requestPayload;}
-
/**
* Retrieves the query parameters from the request
* @return std::string query parameters in the request
const QueryParamsMap& getQueryParameters() const {return m_queryParameters;}
/**
- * Retrieves the request handler flag type. This can be either INIT flag or REQUEST flag
- * OBSERVE flag.
+ * Retrieves the request handler flag type. This can be either INIT flag or REQUEST flag or OBSERVE flag.
* NOTE:
* INIT indicates that the vendor's entity handler should go and perform initialization operations
* REQUEST indicates that it is a request of certain type (GET/PUT/POST/DELETE) and entity handler needs to perform
private:
std::string m_requestType;
- std::string m_requestPayload;
QueryParamsMap m_queryParameters;
RequestHandlerFlag m_requestHandlerFlag;
AttributeMap m_attributeMap;
- private:
- void setRequestType(const std::string& requestType);
- void setRequestPayload(const std::string& requestPayload);
- void setQueryParams(QueryParamsMap& queryParams);
- void setRequestHandlerFlag(RequestHandlerFlag requestHandlerFlag);
- void setResourceRepresentation(AttributeMap& attributeMap);
+ public:
+ // TODO: This is not a public API for app developers.
+ // This function will not be exposed in future
+ void setRequestType(const std::string& requestType)
+ {
+ m_requestType = requestType;
+ }
+
+ // TODO: This is not a public API for app developers.
+ // This function will not be exposed in future
+ void setPayload(const std::string& requestPayload)
+ {
+ // TODO: The following JSON Parse implementation should be seperated into utitilites
+ // and used wherever required.
+ // e.g. parse(std::string& payload, Attributemap& attributeMap)
+
+ std::stringstream requestStream;
+ requestStream << requestPayload;
+ boost::property_tree::ptree root;
+ boost::property_tree::read_json(requestStream, root);
+ boost::property_tree::ptree payload = root.get_child("oc.payload", boost::property_tree::ptree());
+
+ for(auto& item : payload)
+ {
+ std::string name = item.first.data();
+ std::string value = item.second.data();
+
+ AttributeValues values;
+ values.push_back(value);
+
+ m_attributeMap[name] = values;
+ }
+ }
+
+ // TODO: This is not a public API for app developers.
+ // This function will not be exposed in future
+ void setQueryParams(QueryParamsMap& queryParams)
+ {
+
+ }
+
+ // TODO: This is not a public API for app developers.
+ // This function will not be exposed in future
+ void setRequestHandlerFlag(RequestHandlerFlag requestHandlerFlag)
+ {
+ m_requestHandlerFlag = requestHandlerFlag;
+ }
};
} // namespace OC
#define __OCRESOURCERESPONSE_H
#include "OCApi.h"
+#include <IServerWrapper.h>
+#include <ocstack.h>
+
+using namespace std;
namespace OC
{
typedef std::shared_ptr<OCResourceResponse> Ptr;
/**
- * OCResourceResponse Construtor
- * @param responseHeaders response header information in a map
- * @param eCode HTTP error code for this response.
- * @param attributeMap reference to AttributeMap which contains the full attribute representation
- * of the resource.
+ * Default destructor
*/
- OCResourceResponse(HeadersMap& responseHeaders, int eCode, AttributeMap& attributeMap) :
- m_responseHeaders(responseHeaders), m_HTTPErrorCode(eCode), m_attributeMap(attributeMap) {}
+ OCResourceResponse() {}
/**
* Virtual destructor
*/
- virtual ~OCResourceResponse(void);
+ virtual ~OCResourceResponse(void) {}
/**
- * This API sets the response headers for the response
- * @param responseHeaders std::string reference
- */
- void setResponseHeaders(HeadersMap& responseHeaders) { m_responseHeaders = responseHeaders; }
-
- /**
- * This API sets the HTTP error code for this response
- * @param eCode HTTP error code to set
+ * This API sets the error code for this response
+ * @param eCode error code to set
*/
- void setHTTPErrorCode(const int eCode) { m_HTTPErrorCode = eCode; }
+ void setErrorCode(const int eCode) { m_errorCode = eCode; }
/**
* API to set the entire resource attribute representation
* @param attributeMap reference containing the name value pairs representing the resource's attributes
*/
- void setResourceRepresentation(AttributeMap& attributeMap) { m_attributeMap = attributeMap; }
+ void setResourceRepresentation(AttributeMap& attributes) {
- private:
- HeadersMap m_responseHeaders;
- int m_HTTPErrorCode; // TODO remove 'HTTP'. It can be any protocol and ISV need not know it
- AttributeMap m_attributeMap;
+ // TODO To be refactored
+ ostringstream payload;
+
+ payload << "{\"oc\":{\"payload\":{";
+
+ for(AttributeMap::const_iterator itr = attributes.begin(); itr!= attributes.end(); ++ itr)
+ {
+ if(itr != attributes.begin())
+ {
+ payload << ',';
+ }
+ // cout << itr->first << ":" <, itr->second.front() << endl;
+ payload << "\""<<itr->first<<"\":" << itr->second.front();
+ }
+ payload << "}}}";
+
+ m_payload = payload.str();
+ }
private:
+ std::string m_payload;
+ int m_errorCode;
+
+ // TODO only stack should have visibility and apps should not
+ public:
/**
- * Get response headers
- */
- HeadersMap& getResponseHeaders() const;
-
- /**
- * Get HTTP status error code
+ * Get error code
*/
- int getHTTPErrorCode() const;
+ int getErrorCode() const;
/**
* Get the resource attribute representation
*/
AttributeMap& getResourceRepresentation() const;
+
+ // TODO This should go away & just use getResourceRepresentation
+ std::string getPayload()
+ {
+ return m_payload;
+ }
};
} // namespace OC
{
public:
OutOfProcClientWrapper(PlatformConfig cfg) { }
- virtual int ListenForResource(const std::string& serviceUrl, const std::string& resourceType, std::function<void(OCResource::Ptr)>& callback) {return 0;}
+ virtual OCStackResult ListenForResource(const std::string& serviceUrl, const std::string& resourceType, std::function<void(std::shared_ptr<OCResource>)>& callback) {return OC_STACK_NOTIMPL;}
+
+ virtual OCStackResult GetResourceAttributes(const std::string& host, const std::string& uri, std::function<void(const AttributeMap&, const int&)>& callback){return OC_STACK_NOTIMPL;}
+ virtual OCStackResult SetResourceAttributes(const std::string& host, const std::string& uri, const AttributeMap& attributes, const QueryParamsMap& queryParams, std::function<void(const AttributeMap&,const int&)>& callback){return OC_STACK_NOTIMPL;}
+ virtual OCStackResult ObserveResource(OCDoHandle* handle, const std::string& host, const std::string& uri, std::function<void(const AttributeMap&, const int&)>& callback){return OC_STACK_NOTIMPL;}
+ virtual OCStackResult CancelObserveResource(OCDoHandle handle, const std::string& host, const std::string& uri){return OC_STACK_NOTIMPL;}
+
+ virtual std::shared_ptr<OCResource> parseOCResource(IClientWrapper::Ptr clientWrapper, const std::string& host, const boost::property_tree::ptree resourceNode) {return nullptr;}
};
}
#include <OCApi.h>
-#include <OCReflect.h>
-
-using namespace OC::OCReflect;
-
namespace OC
{
class OutOfProcServerWrapper : public IServerWrapper
public:
OutOfProcServerWrapper(PlatformConfig cfg) {};
- void registerResource( const std::string& resourceURI,
- const std::string& resourceTypeName,
- property_binding_vector properties)
+ virtual OCStackResult registerResource(
+ OCResourceHandle& resourceHandle,
+ std::string& resourceURI,
+ const std::string& resourceTypeName,
+ const std::string& resourceInterface,
+ std::function<void(const OCResourceRequest::Ptr, const OCResourceResponse::Ptr)> entityHandler,
+ uint8_t resourceProperty)
+
{
+ // Not implemented
+ return OC_STACK_ERROR;
}
-
};
}
class ResourceInitException : public std::exception
{
public:
- ResourceInitException(bool missingUri, bool missingType, bool missingInterface)
- : m_missingUri(missingUri), m_missingType(missingType), m_missingInterface(missingInterface)
+ ResourceInitException(bool missingUri, bool missingType, bool missingInterface, bool missingClientWrapper)
+ : m_missingUri(missingUri), m_missingType(missingType), m_missingInterface(missingInterface), m_missingClientWrapper(missingClientWrapper)
{
}
-
- bool isUriMissing()
- {
- return m_missingUri;
- }
-
- bool isTypeMissing()
- {
- return m_missingType;
- }
-
- bool isInterfaceMissing()
- {
- return m_missingInterface;
- }
-
- std::string Reason()
- {
- std::string ret;
-
- if(isUriMissing())
- {
- ret += "Missing URI;";
- }
-
- if(isTypeMissing())
- {
- ret += "Missing Resource Type;";
- }
-
- if(isInterfaceMissing())
- {
- ret += "Missing Interface;";
- }
-
- return ret;
- }
+
+ bool isClientWrapperMissing() const
+ {
+ return m_missingClientWrapper;
+ }
+
+ bool isUriMissing() const
+ {
+ return m_missingUri;
+ }
+
+ bool isTypeMissing() const
+ {
+ return m_missingType;
+ }
+
+ bool isInterfaceMissing() const
+ {
+ return m_missingInterface;
+ }
+
+ virtual const char* what() noexcept
+ {
+ std::string ret;
+
+ if(isUriMissing())
+ {
+ ret += "Missing URI;";
+ }
+
+ if(isTypeMissing())
+ {
+ ret += "Missing Resource Type;";
+ }
+
+ if(isInterfaceMissing())
+ {
+ ret += "Missing Interface;";
+ }
+
+ if(isClientWrapperMissing())
+ {
+ ret += "Missing ClientWrapper;";
+ }
+
+ return ret.c_str();
+ }
private:
+
bool m_missingUri;
- bool m_missingType;
- bool m_missingInterface;
+ bool m_missingType;
+ bool m_missingInterface;
+ bool m_missingClientWrapper;
};
}
-#endif
\ No newline at end of file
+#endif