From bd588935ec725cc85ce3dc98838fa1ff8ccb497d Mon Sep 17 00:00:00 2001 From: Minji Park Date: Tue, 23 Aug 2016 15:36:21 +0900 Subject: [PATCH] add cloud client samples - air conditioner added for cloud client c++ api sample - thin light added for cloud client c api sample Change-Id: Ie054119f8309f554169954a87dec8077973e2ea9 Signed-off-by: Minji Park Reviewed-on: https://gerrit.iotivity.org/gerrit/10771 Tested-by: jenkins-iotivity Reviewed-by: Jee Hyeok Kim --- cloud/samples/client/SConscript | 41 +- .../client/airconditioner/aircon_controlee.cpp | 691 +++++++++++++++++++++ .../client/airconditioner/aircon_controller.cpp | 355 +++++++++++ cloud/samples/client/cloud_connector.c | 292 --------- cloud/samples/client/cloud_connector.h | 43 -- .../thin_room_light.cpp} | 569 +++++++---------- 6 files changed, 1289 insertions(+), 702 deletions(-) create mode 100644 cloud/samples/client/airconditioner/aircon_controlee.cpp create mode 100644 cloud/samples/client/airconditioner/aircon_controller.cpp delete mode 100644 cloud/samples/client/cloud_connector.c delete mode 100644 cloud/samples/client/cloud_connector.h rename cloud/samples/client/{sample_device.cpp => thin_light/thin_room_light.cpp} (57%) diff --git a/cloud/samples/client/SConscript b/cloud/samples/client/SConscript index 7a4ae09..d3a7e37 100644 --- a/cloud/samples/client/SConscript +++ b/cloud/samples/client/SConscript @@ -32,24 +32,41 @@ cc_sample_app_env = lib_env.Clone() # Build flags ###################################################################### cc_sample_app_env.AppendUnique(CPPPATH = [ - '../../../resource/include/', - '../../../resource/csdk/stack/include', - '../../../resource/c_common/ocrandom/include', - '../../../resource/csdk/logger/include', - '../../../resource/oc_logger/include' - ]) + '../../../resource/include/', + '../../../resource/csdk/stack/include', + '../../../resource/c_common/ocrandom/include', + '../../../resource/csdk/logger/include', + '../../../resource/oc_logger/include' + ]) cc_sample_app_env.AppendUnique(CXXFLAGS = ['-O2', '-g', '-Wall', '-Wextra', '-std=c++0x', '-pthread']) cc_sample_app_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')]) cc_sample_app_env.AppendUnique(RPATH = [env.get('BUILD_DIR')]) -cc_sample_app_env.PrependUnique(LIBS = ['octbstack', 'pthread']) +cc_sample_app_env.PrependUnique(LIBS = ['oc', 'octbstack', 'pthread']) + +cc_sample_app_env.AppendUnique(CPPDEFINES = ['WITH_CLOUD', 'RD_CLIENT']) ###################################################################### # Source files and Targets ###################################################################### -cc_sample_src = [ - 'cloud_connector.c', - 'sample_device.cpp', - ] -cc_client = cc_sample_app_env.Program('cloud_device', cc_sample_src) \ No newline at end of file +###################################################################### +# Sample for the thin cloud device +###################################################################### +thin_room_light_src = [ + 'thin_light/thin_room_light.cpp' + ] +cc_sample_app_env.Program('thin_room_light', thin_room_light_src) + +###################################################################### +# Samples for the air conditioner +###################################################################### +aircon_controlee_src = [ + 'airconditioner/aircon_controlee.cpp' + ] +cc_sample_app_env.Program('aircon_controlee', aircon_controlee_src) + +aircon_controller_src = [ + 'airconditioner/aircon_controller.cpp' + ] +cc_sample_app_env.Program('aircon_controller', aircon_controller_src) \ No newline at end of file diff --git a/cloud/samples/client/airconditioner/aircon_controlee.cpp b/cloud/samples/client/airconditioner/aircon_controlee.cpp new file mode 100644 index 0000000..dec0b90 --- /dev/null +++ b/cloud/samples/client/airconditioner/aircon_controlee.cpp @@ -0,0 +1,691 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ocstack.h" +#include "ocpayload.h" +#include "oicresourcedirectory.h" + +#include +#include + +#define DEFAULT_CONTEXT_VALUE 0x99 + +using namespace OC; +using namespace std; + +class Resource +{ + public: + OCResourceHandle m_handle; + Resource(string uri, vector rt, vector itf) + { + m_representation.setUri(uri); + m_representation.setResourceTypes(rt); + m_representation.setResourceInterfaces(itf); + } + + string getResourceUri() + { + return m_representation.getUri(); + } + + vector getResourceType() + { + return m_representation.getResourceTypes(); + } + + vector getInterfaces() + { + return m_representation.getResourceInterfaces(); + } + + OCRepresentation getRepresentation(void) + { + m_representation.clearChildren(); + for (auto it = m_childResources.begin(); it != m_childResources.end(); it++) + { + m_representation.addChild((*it)->getRepresentation()); + } + return m_representation; + } + + OCStackResult addChildResource(Resource *childResource) + { + m_childResources.push_back(childResource); + return OCPlatform::bindResource(m_handle, childResource->m_handle); + } + + OCStackResult sendRepresentation(std::shared_ptr pRequest) + { + auto pResponse = std::make_shared(); + pResponse->setRequestHandle(pRequest->getRequestHandle()); + pResponse->setResourceHandle(pRequest->getResourceHandle()); + + // Check for query params (if any) + QueryParamsMap queryParamsMap = pRequest->getQueryParameters(); + + cout << "\t\t\tquery params: \n"; + for (auto it = queryParamsMap.begin(); it != queryParamsMap.end(); it++) + { + cout << "\t\t\t\t" << it->first << ":" << it->second << endl; + } + + auto findRes = queryParamsMap.find("if"); + + if (findRes != queryParamsMap.end()) + { + pResponse->setResourceRepresentation(getRepresentation(), findRes->second); + } + else + { + pResponse->setResourceRepresentation(getRepresentation(), DEFAULT_INTERFACE); + } + + pResponse->setErrorCode(200); + pResponse->setResponseResult(OC_EH_OK); + + return OCPlatform::sendResponse(pResponse); + } + + OCStackResult propagate() + { + if (m_interestedObservers.size() > 0) + { + std::shared_ptr resourceResponse = + { std::make_shared() }; + + resourceResponse->setErrorCode(200); + resourceResponse->setResourceRepresentation(getRepresentation(), DEFAULT_INTERFACE); + + return OCPlatform::notifyListOfObservers(m_handle, + m_interestedObservers, + resourceResponse); + } + + return OC_STACK_OK; + } + + virtual OCEntityHandlerResult entityHandler(std::shared_ptr request) = 0; + + protected: + OCRepresentation m_representation; + vector m_childResources; + ObservationIds m_interestedObservers; +}; + +class BinarySwitchResource : public Resource //oic.r.switch.binary +{ + private: + bool m_value; + + public: + BinarySwitchResource(string uri, vector rt, vector itf) + : Resource(uri, rt, itf) + { + m_value = false; + m_representation.setValue("value", m_value); + } + + void setBinarySwitchRepresentation(OCRepresentation &rep) + { + bool value; + if (rep.getValue("value", value)) + { + m_value = value; + m_representation.setValue("value", m_value); + cout << "\t\t\t\t" << "value: " << m_value << endl; + + propagate(); + } + } + + OCEntityHandlerResult entityHandler(std::shared_ptr request) + { + cout << "\tIn Server Binaryswitch entity handler:\n"; + OCEntityHandlerResult ehResult = OC_EH_ERROR; + + if (request) + { + // Get the request type and request flag + std::string requestType = request->getRequestType(); + int requestFlag = request->getRequestHandlerFlag(); + + if (requestFlag & RequestHandlerFlag::RequestFlag) + { + cout << "\t\trequestFlag : Request\n"; + + // If the request type is GET + if (requestType == "GET") + { + cout << "\t\t\trequestType : GET\n"; + if (OC_STACK_OK == sendRepresentation(request)) + { + ehResult = OC_EH_OK; + } + } + else if (requestType == "PUT") + { + cout << "\t\t\trequestType : PUT\n"; + // PUT request operations + } + else if (requestType == "POST") + { + cout << "\t\t\trequestType : POST\n"; + // POST request operations + OCRepresentation rep = request->getResourceRepresentation(); + setBinarySwitchRepresentation(rep); + + if (OC_STACK_OK == sendRepresentation(request)) + { + ehResult = OC_EH_OK; + } + } + else if (requestType == "DELETE") + { + cout << "\t\t\trequestType : DELETE\n"; + // DELETE request operations + } + } + + if (requestFlag & RequestHandlerFlag::ObserverFlag) + { + cout << "\t\trequestFlag : Observer\n"; + + ObservationInfo observationInfo = request->getObservationInfo(); + if (ObserveAction::ObserveRegister == observationInfo.action) + { + m_interestedObservers.push_back(observationInfo.obsId); + } + else if (ObserveAction::ObserveUnregister == observationInfo.action) + { + m_interestedObservers.erase(std::remove( + m_interestedObservers.begin(), + m_interestedObservers.end(), + observationInfo.obsId), + m_interestedObservers.end()); + } + } + } + else + { + std::cout << "Request invalid" << std::endl; + } + + return ehResult; + } +}; + +class TemperatureResource : public Resource //oic.r.temperature +{ + private: + int m_temperature; + string m_range; + string m_units; + + public: + TemperatureResource(string uri, vector rt, vector itf) + : Resource(uri, rt, itf) + { + m_temperature = 0; + m_range = ""; + m_units = ""; + m_representation.setValue("temperature", m_temperature); + m_representation.setValue("range", m_range); + m_representation.setValue("units", m_units); + } + + void setTemperatureRepresentation(OCRepresentation &rep) + { + int temperature; + string range; + int units; + + if (rep.getValue("temperature", temperature) && + rep.getValue("range", range) && + rep.getValue("units", units)) + { + m_temperature = temperature; + m_range = range; + m_units = units; + m_representation.setValue("temperature", m_temperature); + m_representation.setValue("range", m_range); + m_representation.setValue("units", m_units); + cout << "\t\t\t\t" << "temperature: " << m_temperature << endl; + cout << "\t\t\t\t" << "range: " << m_range << endl; + cout << "\t\t\t\t" << "units: " << m_units << endl; + + propagate(); + } + } + + OCEntityHandlerResult entityHandler(std::shared_ptr request) + { + cout << "\tIn Server Temperature entity handler:\n"; + OCEntityHandlerResult ehResult = OC_EH_ERROR; + + if (request) + { + // Get the request type and request flag + std::string requestType = request->getRequestType(); + int requestFlag = request->getRequestHandlerFlag(); + + if (requestFlag & RequestHandlerFlag::RequestFlag) + { + cout << "\t\trequestFlag : Request\n"; + + // If the request type is GET + if (requestType == "GET") + { + cout << "\t\t\trequestType : GET\n"; + if (OC_STACK_OK == sendRepresentation(request)) + { + ehResult = OC_EH_OK; + } + } + else if (requestType == "PUT") + { + cout << "\t\t\trequestType : PUT\n"; + // PUT requeist operations + } + else if (requestType == "POST") + { + cout << "\t\t\trequestType : POST\n"; + // POST request operations + OCRepresentation rep = request->getResourceRepresentation(); + setTemperatureRepresentation(rep); + + if (OC_STACK_OK == sendRepresentation(request)) + { + ehResult = OC_EH_OK; + } + } + else if (requestType == "DELETE") + { + cout << "\t\t\trequestType : DELETE\n"; + // DELETE request operations + } + } + + if (requestFlag & RequestHandlerFlag::ObserverFlag) + { + cout << "\t\trequestFlag : Observer\n"; + + ObservationInfo observationInfo = request->getObservationInfo(); + if (ObserveAction::ObserveRegister == observationInfo.action) + { + m_interestedObservers.push_back(observationInfo.obsId); + } + else if (ObserveAction::ObserveUnregister == observationInfo.action) + { + m_interestedObservers.erase(std::remove( + m_interestedObservers.begin(), + m_interestedObservers.end(), + observationInfo.obsId), + m_interestedObservers.end()); + } + } + } + else + { + std::cout << "Request invalid" << std::endl; + } + + return ehResult; + } +}; + +class AirConditionerResource : public Resource // oic.d.airconditioner +{ + private: + + public: + AirConditionerResource(string uri, vector rt, vector itf) + : Resource(uri, rt, itf) + { + + } + + OCEntityHandlerResult entityHandler(std::shared_ptr request) + { + cout << "\tIn Server Airconditioner entity handler:\n"; + OCEntityHandlerResult ehResult = OC_EH_ERROR; + + if (request) + { + // Get the request type and request flag + std::string requestType = request->getRequestType(); + int requestFlag = request->getRequestHandlerFlag(); + + if (requestFlag & RequestHandlerFlag::RequestFlag) + { + cout << "\t\trequestFlag : Request\n"; + + // If the request type is GET + if (requestType == "GET") + { + cout << "\t\t\trequestType : GET\n"; + string findRes = request->getQueryParameters().find("if")->second; + if (findRes.compare(LINK_INTERFACE) == 0) + { + if (OC_STACK_OK == sendRepresentation(request)) + { + ehResult = OC_EH_OK; + } + } + else + { + ehResult = OC_EH_FORBIDDEN; + } + } + else if (requestType == "PUT") + { + cout << "\t\t\trequestType : PUT\n"; + // Call these functions to prepare the response for child resources and + // then send the final response using sendRoomResponse function + + /* + for (auto it = m_childResources.begin(); + it != m_childResources.end(); it++) + { + (*it)->entityHandler(request); + } + + if (OC_STACK_OK == sendRepresentation(request)) + { + ehResult = OC_EH_OK; + } + */ + } + else if (requestType == "POST") + { + // POST request operations + } + else if (requestType == "DELETE") + { + // DELETE request operations + } + } + + if (requestFlag & RequestHandlerFlag::ObserverFlag) + { + cout << "\t\trequestFlag : Observer\n"; + } + } + else + { + std::cout << "Request invalid" << std::endl; + } + + return ehResult; + } +}; + +std::condition_variable g_callbackLock; +std::string g_uid; +std::string g_accesstoken; + +void onPublish(const OCRepresentation &, const int &eCode) +{ + std::cout << "Publish resource response received, code: " << eCode << std::endl; + + g_callbackLock.notify_all(); +} + +void printRepresentation(OCRepPayloadValue *value) +{ + while (value) + { + std::cout << "Key: " << value->name; + switch (value->type) + { + case OCREP_PROP_NULL: + std::cout << " Value: None" << std::endl; + break; + case OCREP_PROP_INT: + std::cout << " Value: " << value->i << std::endl; + break; + case OCREP_PROP_DOUBLE: + std::cout << " Value: " << value->d << std::endl; + break; + case OCREP_PROP_BOOL: + std::cout << " Value: " << value->b << std::endl; + break; + case OCREP_PROP_STRING: + std::cout << " Value: " << value->str << std::endl; + break; + case OCREP_PROP_BYTE_STRING: + std::cout << " Value: Byte String" << std::endl; + break; + case OCREP_PROP_OBJECT: + std::cout << " Value: Object" << std::endl; + break; + case OCREP_PROP_ARRAY: + std::cout << " Value: Array" << std::endl; + break; + } + + if (strcmp(value->name, "accesstoken") == 0) + { + g_accesstoken = value->str; + } + + if (strcmp(value->name, "uid") == 0) + { + g_uid = value->str; + } + + value = value->next; + } +} + +void handleLoginoutCB(const HeaderOptions &, + const OCRepresentation &rep, const int ecode) +{ + cout << "Auth response received code: " << ecode << endl; + + if (rep.getPayload() != NULL) + { + printRepresentation(rep.getPayload()->values); + } + + g_callbackLock.notify_all(); +} + +static FILE *client_open(const char * /*path*/, const char *mode) +{ + return fopen("./resource_server.dat", mode); +} + +int main(int argc, char *argv[]) +{ + if (argc != 4 && argc != 5) + { + cout << "Put \"[host-ipaddress:port] [authprovider] [authcode]\" for sign-up and sign-in and publish resources" + << endl; + cout << "Put \"[host-ipaddress:port] [uid] [accessToken] 1\" for sign-in and publish resources" << + endl; + return 0; + } + + OCPersistentStorage ps{ client_open, fread, fwrite, fclose, unlink }; + + PlatformConfig cfg + { + ServiceType::InProc, + ModeType::Both, + "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces + 0, // Uses randomly available port + QualityOfService::LowQos, + &ps + }; + + OCPlatform::Configure(cfg); + + OCStackResult result = OC_STACK_ERROR; + + string host = "coap+tcp://"; + host += argv[1]; + + OCAccountManager::Ptr accountMgr = OCPlatform::constructAccountManagerObject(host, + CT_ADAPTER_TCP); + + mutex blocker; + unique_lock lock(blocker); + + if (argc == 5) + { + accountMgr->signIn(argv[2], argv[3], &handleLoginoutCB); + g_callbackLock.wait(lock); + } + else + { + accountMgr->signUp(argv[2], argv[3], &handleLoginoutCB); + g_callbackLock.wait(lock); + accountMgr->signIn(g_uid, g_accesstoken, &handleLoginoutCB); + g_callbackLock.wait(lock); + } + + + cout << "Registering resources to platform..." << endl; + + AirConditionerResource airConditioner("/sec/aircon/0", { "x.com.samsung.da.device" }, { DEFAULT_INTERFACE, BATCH_INTERFACE, LINK_INTERFACE }); + + BinarySwitchResource binarySwitch("/power/0", { "oic.r.switch.binary" }, { DEFAULT_INTERFACE }); + + TemperatureResource temperature("/temperature/0", { "oic.r.temperature" }, { DEFAULT_INTERFACE }); + + string uri = airConditioner.getResourceUri(); + string rt = airConditioner.getResourceType()[0]; + string itf = airConditioner.getInterfaces()[0]; + + result = OCPlatform::registerResource(airConditioner.m_handle, + uri, + rt, + itf, + std::bind(&AirConditionerResource::entityHandler + , &airConditioner, std::placeholders::_1), + OC_DISCOVERABLE); + + if (result != OC_STACK_OK) + { + cout << "Resource registration was unsuccessful" << endl; + } + + + itf = airConditioner.getInterfaces()[1]; + result = OCPlatform::bindInterfaceToResource(airConditioner.m_handle, itf); + + if (result != OC_STACK_OK) + { + cout << "Binding second interface was unsuccessful" << endl; + } + + + itf = airConditioner.getInterfaces()[2]; + result = OCPlatform::bindInterfaceToResource(airConditioner.m_handle, itf); + + if (result != OC_STACK_OK) + { + cout << "Binding third interface was unsuccessful" << endl; + } + + + uri = binarySwitch.getResourceUri(); + rt = binarySwitch.getResourceType()[0]; + itf = binarySwitch.getInterfaces()[0]; + + result = OCPlatform::registerResource(binarySwitch.m_handle, + uri, + rt, + itf, + std::bind(&BinarySwitchResource::entityHandler + , &binarySwitch, std::placeholders::_1), + OC_OBSERVABLE); + + uri = temperature.getResourceUri(); + rt = temperature.getResourceType()[0]; + itf = temperature.getInterfaces()[0]; + + result = OCPlatform::registerResource(temperature.m_handle, + uri, + rt, + itf, + std::bind(&TemperatureResource::entityHandler + , &temperature, std::placeholders::_1), + OC_OBSERVABLE); + + result = airConditioner.addChildResource(&binarySwitch); + + result = airConditioner.addChildResource(&temperature); + + cout << "Publishing resources to cloud "; + + + ResourceHandles resourceHandles; + + OCDeviceInfo devInfoAirConditioner; + OCStringLL deviceType; + + deviceType.value = "oic.d.airconditioner"; + deviceType.next = NULL; + devInfoAirConditioner.deviceName = "FAC_2016"; + devInfoAirConditioner.types = &deviceType; + devInfoAirConditioner.specVersion = NULL; + devInfoAirConditioner.dataModelVersions = NULL; + + OCPlatform::registerDeviceInfo(devInfoAirConditioner); + + result = OCPlatform::publishResourceToRD(host, OCConnectivityType::CT_ADAPTER_TCP, + resourceHandles, + &onPublish); + + cout << " result: " << result << " Waiting Publish default resource response from cloud" << endl; + + resourceHandles.push_back(airConditioner.m_handle); + + result = OCPlatform::publishResourceToRD(host, OCConnectivityType::CT_ADAPTER_TCP, + resourceHandles, + &onPublish); + + cout << " result: " << result << " Waiting Publish user resource response from cloud" << endl; + + g_callbackLock.wait(lock); + + + cout << "PUT 1/0 to turn on/off air conditioner for observe testing, q to terminate" << endl; + + string cmd; + + while (true) + { + cin >> cmd; + OCRepresentation rep; + + switch (cmd[0]) + { + case '1': + rep.setValue(string("value"), true); + binarySwitch.setBinarySwitchRepresentation(rep); + break; + + case '0': + rep.setValue(string("value"), false); + binarySwitch.setBinarySwitchRepresentation(rep); + break; + + case 'q': + goto exit; + break; + } + } + +exit: + return 0; +} diff --git a/cloud/samples/client/airconditioner/aircon_controller.cpp b/cloud/samples/client/airconditioner/aircon_controller.cpp new file mode 100644 index 0000000..6dc5e02 --- /dev/null +++ b/cloud/samples/client/airconditioner/aircon_controller.cpp @@ -0,0 +1,355 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ocstack.h" +#include "ocpayload.h" + +#include +#include + +#define DEFAULT_CONTEXT_VALUE 0x99 + +#define maxSequenceNumber 0xFFFFFF + +using namespace OC; +using namespace std; + + +condition_variable g_callbackLock; +std::string g_uid; +std::string g_accesstoken; + +string g_host; +OC::OCResource::Ptr g_binaryswitchResource; + +void printRepresentation(OCRepPayloadValue *value) +{ + while (value) + { + std::cout << "Key: " << value->name; + switch (value->type) + { + case OCREP_PROP_NULL: + std::cout << " Value: None" << std::endl; + break; + case OCREP_PROP_INT: + std::cout << " Value: " << value->i << std::endl; + break; + case OCREP_PROP_DOUBLE: + std::cout << " Value: " << value->d << std::endl; + break; + case OCREP_PROP_BOOL: + std::cout << " Value: " << value->b << std::endl; + break; + case OCREP_PROP_STRING: + std::cout << " Value: " << value->str << std::endl; + break; + case OCREP_PROP_BYTE_STRING: + std::cout << " Value: Byte String" << std::endl; + break; + case OCREP_PROP_OBJECT: + std::cout << " Value: Object" << std::endl; + break; + case OCREP_PROP_ARRAY: + std::cout << " Value: Array" << std::endl; + break; + } + + if (strcmp(value->name, "accesstoken") == 0) + { + g_accesstoken = value->str; + } + + if (strcmp(value->name, "uid") == 0) + { + g_uid = value->str; + } + + value = value->next; + } +} + +void handleLoginoutCB(const HeaderOptions &, + const OCRepresentation &rep, const int ecode) +{ + cout << "Login/out response received code: " << ecode << endl; + + if (rep.getPayload() != NULL) + { + printRepresentation(rep.getPayload()->values); + } + + g_callbackLock.notify_all(); +} + +void printRepresentation(const OCRepresentation &rep) +{ + cout << "URI: " << rep.getUri() << endl; + + vector rt = rep.getResourceTypes(); + for (auto it = rt.begin(); it != rt.end(); it++) + { + cout << "RT: " << (*it) << endl; + } + + for (auto it = rep.begin(); + it != rep.end(); it++) + { + cout << it->attrname() << " : " << it->getValueToString() << endl; + } + + vector children = rep.getChildren(); + + for (auto it = children.begin(); + it != children.end(); it++) + { + printRepresentation(*it); + } +} + +void onObserve(const HeaderOptions /*headerOptions*/, const OCRepresentation &rep, + const int &eCode, const int &sequenceNumber) +{ + try + { + if (eCode == OC_STACK_OK && sequenceNumber != maxSequenceNumber + 1) + { + if (sequenceNumber == OC_OBSERVE_REGISTER) + { + cout << "Observe registration action is successful" << endl; + } + + cout << "OBSERVE RESULT:" << endl; + printRepresentation(rep); + } + else + { + if (eCode == OC_STACK_OK) + { + std::cout << "Observe registration failed or de-registration action failed/succeeded" << std::endl; + } + else + { + cout << "onObserve Response error: " << eCode << endl; + exit(-1); + } + } + } + catch (exception &e) + { + cout << "Exception: " << e.what() << " in onObserve" << endl; + } +} + +void onPut(const HeaderOptions & /*headerOptions*/, const OCRepresentation &rep, const int eCode) +{ + cout << "PUT response: " << eCode << endl; + + printRepresentation(rep); +} + +void turnOnOffSwitch(bool toTurn) +{ + OCRepresentation binarySwitch; + binarySwitch.setValue("value", toTurn); + + QueryParamsMap query; + g_binaryswitchResource->post("oic.r.switch.binary", DEFAULT_INTERFACE, binarySwitch, query, &onPut); +} + +void getCollectionResource(const HeaderOptions &, + const OCRepresentation &rep, const int ecode) +{ + cout << "Resource get: " << ecode << endl; + + printRepresentation(rep); + + vector children = rep.getChildren(); + + cout << "Constructing binary switch" << endl; + + for (auto it = children.begin(); it != children.end(); it++) + { + cout << "RT: " << it->getResourceTypes().at(0) << endl; + + if (it->getResourceTypes().at(0).compare("oic.r.switch.binary") == 0) + { + cout << "Observing " << it->getUri() << endl; + g_binaryswitchResource = OCPlatform::constructResourceObject(g_host, + it->getUri(), + static_cast(CT_ADAPTER_TCP | CT_IP_USE_V4), true, + { string("oic.r.switch.binary") }, { string(DEFAULT_INTERFACE) }); + + QueryParamsMap query; + g_binaryswitchResource->observe(ObserveType::Observe, query, &onObserve); + } + } +} + +void foundAirconditionerResource(shared_ptr resource) +{ + vector rt = resource->getResourceTypes(); + + cout << "Aircondition resource found: " << resource->uri() << endl; + + g_callbackLock.notify_all(); + + for (auto it = rt.begin(); it != rt.end(); it++) + { + cout << "RT: " << *it << endl; + + if (it->compare("x.com.samsung.da.device") == 0) + { + cout << "Found Samsung Airconditioner" << endl; + + QueryParamsMap query; + query["if"] = string(LINK_INTERFACE); + //Request to collection resource + resource->get(query, &getCollectionResource); + } + } +} + +void foundDevice(shared_ptr resource) +{ + vector rt = resource->getResourceTypes(); + + cout << "Device found: " << resource->uri() << endl; + cout << "DI: " << resource->sid() << endl; + + g_callbackLock.notify_all(); + + for (auto it = rt.begin(); it != rt.end(); it++) + { + cout << "RT: " << *it << endl; + + if (it->compare("oic.d.airconditioner") == 0) + { + string searchQuery = "/oic/res?di="; + searchQuery += resource->sid(); + cout << "Airconditioner found" << endl; + OCPlatform::findResource(g_host, searchQuery, + static_cast(CT_ADAPTER_TCP | CT_IP_USE_V4), + &foundAirconditionerResource); + } + } +} + +void presenceDevice(OCStackResult , const unsigned int i, const std::string &str) +{ + cout << "Presence received, i=" << i << " str=" << str << endl; +} + +static FILE *client_open(const char * /*path*/, const char *mode) +{ + return fopen("./resource_controller.dat", mode); +} + +int main(int argc, char *argv[]) +{ + if (argc != 4 && argc != 5) + { + cout << "Put \"[host-ipaddress:port] [authprovider] [authcode]\" for sign-up and sign-in and discover resources" + << endl; + cout << "Put \"[host-ipaddress:port] [uid] [accessToken] 1\" for sign-in and discover resources" << + endl; + return 0; + } + + OCPersistentStorage ps{ client_open, fread, fwrite, fclose, unlink }; + + PlatformConfig cfg + { + ServiceType::InProc, + ModeType::Both, + "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces + 0, // Uses randomly available port + QualityOfService::LowQos, + &ps + }; + + OCPlatform::Configure(cfg); + + OCStackResult result = OC_STACK_ERROR; + + g_host = "coap+tcp://"; + g_host += argv[1]; + + OCAccountManager::Ptr accountMgr = OCPlatform::constructAccountManagerObject(g_host, + CT_ADAPTER_TCP); + + + mutex blocker; + unique_lock lock(blocker); + + if (argc == 5) + { + accountMgr->signIn(argv[2], argv[3], &handleLoginoutCB); + g_callbackLock.wait(lock); + } + else + { + accountMgr->signUp(argv[2], argv[3], &handleLoginoutCB); + g_callbackLock.wait(lock); + accountMgr->signIn(g_uid, g_accesstoken, &handleLoginoutCB); + g_callbackLock.wait(lock); + } + + /* + cout << "Subscribing resource presence "; + + string query = "oic.wk.d&di=F0FDE28F-36BF-49BC-89F1-6AFB8D73E93C"; + + OCPlatform::OCPresenceHandle presenceHandle; + + result = OCPlatform::subscribePresence(presenceHandle, g_host, query, + static_cast(CT_ADAPTER_TCP | CT_IP_USE_V4), &presenceDevice); + + cout << " result: " << result << endl; + */ + + cout << "Finding airconditioner "; + + result = OCPlatform::findResource(g_host, "/oic/res?rt=oic.wk.d", + static_cast(CT_ADAPTER_TCP | CT_IP_USE_V4), + &foundDevice); + + cout << " result: " << result << endl; + + g_callbackLock.wait(lock); + + cout << "PUT 1/0 to turn on/off air conditioner, q to terminate" << endl; + + string cmd; + + while (true) + { + cin >> cmd; + OCRepresentation rep; + + switch (cmd[0]) + { + case '1': + turnOnOffSwitch(true); + break; + + case '0': + turnOnOffSwitch(false); + break; + + case 'q': + goto exit; + break; + } + } + +exit: + return 0; +} diff --git a/cloud/samples/client/cloud_connector.c b/cloud/samples/client/cloud_connector.c deleted file mode 100644 index 1312ff3..0000000 --- a/cloud/samples/client/cloud_connector.c +++ /dev/null @@ -1,292 +0,0 @@ -//****************************************************************** -// -// Copyright 2016 Samsung Electronics All Rights Reserved. -// -//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -#include "cloud_connector.h" - -#include -#include - -#include "oic_string.h" -#include "oic_malloc.h" - -#include "ocpayload.h" - -#include "rdpayload.h" - -#define OC_RD_PUBLISH_TTL 86400 -#define DEFAULT_CONTEXT_VALUE 0x99 - -#define DEFAULT_COAP_TCP_HOST "coap+tcp://" -#define DEFAULT_COAP_TCP_PORT 5683 - -#define DEFAULT_COAP_TCP_SECURE_HOST "coaps+tcp://" -#define DEFAULT_COAP_TCP_SECURE_PORT 5864 - -#define DEFAULT_AUTH_REGISTER_LOGIN "/oic/auth/?reqtype=register" -#define DEFAULT_AUTH_LOGIN "/oic/auth/?reqtype=login" -#define DEFAULT_AUTH_LOGOUT "/oic/auth/?reqtype=logout" - -static OCStackResult createStringLL(uint8_t numElements, OCResourceHandle handle, - const char *(*getValue)(OCResourceHandle handle, uint8_t i), OCStringLL **stringLL) -{ - for (uint8_t i = 0; i < numElements; ++i) - { - const char *value = getValue(handle, i); - if (!*stringLL) - { - *stringLL = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL)); - if (!*stringLL) - { - return OC_STACK_NO_MEMORY; - } - (*stringLL)->value = OICStrdup(value); - if (!(*stringLL)->value) - { - return OC_STACK_NO_MEMORY; - } - } - else - { - OCStringLL *cur = *stringLL; - while (cur->next) - { - cur = cur->next; - } - cur->next = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL)); - if (!cur->next) - { - return OC_STACK_NO_MEMORY; - } - cur->next->value = OICStrdup(value); - if (!cur->next->value) - { - return OC_STACK_NO_MEMORY; - } - } - } - return OC_STACK_OK; -} - -OCStackResult OCCloudRegisterLogin(const char *host, const char *auth_provider, - const char *auth_code, OCClientResponseHandler response) -{ - char targetUri[MAX_URI_LENGTH * 2] = { 0, }; - snprintf(targetUri, MAX_URI_LENGTH * 2, "%s%s", host, DEFAULT_AUTH_REGISTER_LOGIN); - - OCCallbackData cbData; - memset(&cbData, 0, sizeof(OCCallbackData)); - cbData.cb = response; - cbData.cd = NULL; - cbData.context = (void *)DEFAULT_CONTEXT_VALUE; - - OCRepPayload *registerPayload = OCRepPayloadCreate(); - if (!registerPayload) - { - goto no_memory; - } - - OCRepPayloadSetPropString(registerPayload, "authprovider", auth_provider); - OCRepPayloadSetPropString(registerPayload, "authcode", auth_code); - - return OCDoResource(NULL, OC_REST_POST, targetUri, NULL, (OCPayload *)registerPayload, - CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0); - -no_memory: - OCRepPayloadDestroy(registerPayload); - return OC_STACK_NO_MEMORY; -} - -OCStackResult OCCloudLoginout(const char *host, const char *query, const char *auth_session, - OCClientResponseHandler response) -{ - char targetUri[MAX_URI_LENGTH * 2] = { 0, }; - snprintf(targetUri, MAX_URI_LENGTH * 2, "%s%s", host, query); - - OCCallbackData cbData; - memset(&cbData, 0, sizeof(OCCallbackData)); - cbData.cb = response; - cbData.cd = NULL; - cbData.context = (void *)DEFAULT_CONTEXT_VALUE; - - OCRepPayload *loginoutPayload = OCRepPayloadCreate(); - if (!loginoutPayload) - { - goto no_memory; - } - - OCRepPayloadSetPropString(loginoutPayload, "session", auth_session); - - return OCDoResource(NULL, OC_REST_POST, targetUri, NULL, (OCPayload *)loginoutPayload, - CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0); - -no_memory: - OCRepPayloadDestroy(loginoutPayload); - return OC_STACK_NO_MEMORY; -} - - -OCStackResult OCCloudLogin(const char *host, const char *auth_session, - OCClientResponseHandler response) -{ - return OCCloudLoginout(host, DEFAULT_AUTH_LOGIN, auth_session, response); -} - -OCStackResult OCCloudLogout(const char *host, const char *auth_session, - OCClientResponseHandler response) -{ - return OCCloudLoginout(host, DEFAULT_AUTH_LOGOUT, auth_session, response); -} - -OCStackResult OCCloudPublish(const char *host, const char *query, - OCClientResponseHandler response, int numArg, ...) -{ - char targetUri[MAX_URI_LENGTH * 2] = { 0, }; - snprintf(targetUri, MAX_URI_LENGTH * 2, "%s%s", host, query); - - // Gather all resources locally and do publish - OCCallbackData cbData; - memset(&cbData, 0, sizeof(OCCallbackData)); - cbData.cb = response; - cbData.cd = NULL; - cbData.context = (void *)DEFAULT_CONTEXT_VALUE; - - OCTagsPayload *tagsPayload = NULL; - OCLinksPayload *linksPayload = NULL; - OCStringLL *rt = NULL; - OCStringLL *itf = NULL; - OCStringLL *mt = NULL; - - OCRDPayload *rdPayload = OCRDPayloadCreate(); - if (!rdPayload) - { - goto no_memory; - } - - const unsigned char *id = (unsigned char *)OCGetServerInstanceIDString(); - tagsPayload = OCCopyTagsResources(NULL, id, - NULL, OC_DISCOVERABLE, 0, 0, NULL, NULL, OC_RD_PUBLISH_TTL); - if (!tagsPayload) - { - goto no_memory; - } - - va_list arguments; - va_start(arguments, numArg); - - for (int j = 0; j < numArg; j++) - { - OCResourceHandle handle = va_arg(arguments, OCResourceHandle); - if (handle) - { - rt = itf = mt = NULL; - const char *uri = OCGetResourceUri(handle); - uint8_t numElement; - if (OC_STACK_OK == OCGetNumberOfResourceTypes(handle, &numElement)) - { - OCStackResult res = createStringLL(numElement, handle, OCGetResourceTypeName, &rt); - if (res != OC_STACK_OK || !rt) - { - goto no_memory; - } - } - - if (OC_STACK_OK == OCGetNumberOfResourceInterfaces(handle, &numElement)) - { - OCStackResult res = createStringLL(numElement, handle, OCGetResourceInterfaceName, &itf); - if (res != OC_STACK_OK || !itf) - { - goto no_memory; - } - } - - mt = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL)); - if (!mt) - { - goto no_memory; - } - mt->value = OICStrdup("application/cbor"); - if (!mt->value) - { - goto no_memory; - } - - if (!linksPayload) - { - linksPayload = OCCopyLinksResources(uri, rt, itf, NULL, 0, NULL, - NULL, j, mt);; - if (!linksPayload) - { - goto no_memory; - } - } - else - { - OCLinksPayload *temp = linksPayload; - while (temp->next) - { - temp = temp->next; - } - temp->next = OCCopyLinksResources(uri, rt, itf, NULL, 0, NULL, - NULL, j, mt); - if (!temp->next) - { - goto no_memory; - } - } - OCFreeOCStringLL(rt); - OCFreeOCStringLL(itf); - OCFreeOCStringLL(mt); - } - } - va_end(arguments); - - rdPayload->rdPublish = OCCopyCollectionResource(tagsPayload, linksPayload); - if (!rdPayload->rdPublish) - { - goto no_memory; - } - - return OCDoResource(NULL, OC_REST_POST, targetUri, NULL, (OCPayload *)rdPayload, - CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0); - -no_memory: - va_end(arguments); - if (rt) - { - OCFreeOCStringLL(rt); - } - if (itf) - { - OCFreeOCStringLL(itf); - } - if (mt) - { - OCFreeOCStringLL(mt); - } - if (tagsPayload) - { - OCFreeTagsResource(tagsPayload); - } - if (linksPayload) - { - OCFreeLinksResource(linksPayload); - } - OCRDPayloadDestroy(rdPayload); - return OC_STACK_NO_MEMORY; -} diff --git a/cloud/samples/client/cloud_connector.h b/cloud/samples/client/cloud_connector.h deleted file mode 100644 index 2f26a5b..0000000 --- a/cloud/samples/client/cloud_connector.h +++ /dev/null @@ -1,43 +0,0 @@ -//****************************************************************** -// -// Copyright 2016 Samsung Electronics All Rights Reserved. -// -//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - -#ifndef _CLOUD_CONNECTOR_H_ -#define _CLOUD_CONNECTOR_H_ - -#include "ocstack.h" - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -OCStackResult OCCloudRegisterLogin(const char *host, const char *auth_provider, - const char *auth_code, OCClientResponseHandler response); -OCStackResult OCCloudLogin(const char *host, const char *auth_session, - OCClientResponseHandler response); -OCStackResult OCCloudLogout(const char *host, const char *auth_session, - OCClientResponseHandler response); -OCStackResult OCCloudPublish(const char *host, const char *query, - OCClientResponseHandler response, int numArg, ...); - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif diff --git a/cloud/samples/client/sample_device.cpp b/cloud/samples/client/thin_light/thin_room_light.cpp similarity index 57% rename from cloud/samples/client/sample_device.cpp rename to cloud/samples/client/thin_light/thin_room_light.cpp index b7f60cb..33b690a 100644 --- a/cloud/samples/client/sample_device.cpp +++ b/cloud/samples/client/thin_light/thin_room_light.cpp @@ -33,15 +33,135 @@ #include "ocstack.h" #include "ocpayload.h" - -#include "cloud_connector.h" +#include "oicresourcedirectory.h" #define DEFAULT_CONTEXT_VALUE 0x99 -#define DEFAULT_PUBLISH_QUERY "/oic/rd?rt=oic.wk.rdpub" -#define DEFAULT_DISCOVER_QUERY "/oic/res?rt=core.light" +#define DEFAULT_AUTH_SIGNUP "/oic/account" +#define DEFAULT_AUTH_SESSION "/oic/account/session" +#define DEFAULT_AUTH_REFRESH "/oic/account/tokenrefresh" + + +OCStackResult OCCloudSignup(const char *host, const char *deviceId, + const char *authprovider, + const char *authcode, OCClientResponseHandler response) +{ + char targetUri[MAX_URI_LENGTH * 2] = { 0, }; + snprintf(targetUri, MAX_URI_LENGTH * 2, "%s%s", host, DEFAULT_AUTH_SIGNUP); + + OCCallbackData cbData; + memset(&cbData, 0, sizeof(OCCallbackData)); + cbData.cb = response; + cbData.cd = NULL; + cbData.context = (void *)DEFAULT_CONTEXT_VALUE; + + OCRepPayload *registerPayload = OCRepPayloadCreate(); + if (!registerPayload) + { + goto no_memory; + } + + OCRepPayloadSetPropString(registerPayload, "di", deviceId); + OCRepPayloadSetPropString(registerPayload, "authprovider", authprovider); + OCRepPayloadSetPropString(registerPayload, "authcode", authcode); + + return OCDoResource(NULL, OC_REST_POST, targetUri, NULL, (OCPayload *)registerPayload, + CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0); + +no_memory: + OCRepPayloadDestroy(registerPayload); + return OC_STACK_NO_MEMORY; +} + +OCStackResult OCCloudSession(const char *host, const char *query, const char *uId, + const char *deviceId, + const char *accesstoken, + bool isLogin, OCClientResponseHandler response) +{ + char targetUri[MAX_URI_LENGTH * 2] = { 0, }; + snprintf(targetUri, MAX_URI_LENGTH * 2, "%s%s", host, query); + + OCCallbackData cbData; + memset(&cbData, 0, sizeof(OCCallbackData)); + cbData.cb = response; + cbData.cd = NULL; + cbData.context = (void *)DEFAULT_CONTEXT_VALUE; + + OCRepPayload *loginoutPayload = OCRepPayloadCreate(); + if (!loginoutPayload) + { + goto no_memory; + } + + if (uId != NULL) + { + OCRepPayloadSetPropString(loginoutPayload, "uid", uId); + } + + if (deviceId != NULL) + { + OCRepPayloadSetPropString(loginoutPayload, "di", deviceId); + } + + if (accesstoken != NULL) + { + OCRepPayloadSetPropString(loginoutPayload, "accesstoken", accesstoken); + } + OCRepPayloadSetPropBool(loginoutPayload, "login", isLogin); + + return OCDoResource(NULL, OC_REST_POST, targetUri, NULL, (OCPayload *)loginoutPayload, + CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0); + +no_memory: + OCRepPayloadDestroy(loginoutPayload); + return OC_STACK_NO_MEMORY; +} + +//Client should call refresh before expiresin or when receive 4.01 during sign-in +OCStackResult OCCloudRefresh(const char *host, const char *query, const char *uId, + const char *deviceId, const char *refreshtoken, OCClientResponseHandler response) +{ + char targetUri[MAX_URI_LENGTH * 2] = { 0, }; + snprintf(targetUri, MAX_URI_LENGTH * 2, "%s%s", host, query); + + OCCallbackData cbData; + memset(&cbData, 0, sizeof(OCCallbackData)); + cbData.cb = response; + cbData.cd = NULL; + cbData.context = (void *)DEFAULT_CONTEXT_VALUE; + + OCRepPayload *refreshPayload = OCRepPayloadCreate(); + if (!refreshPayload) + { + goto no_memory; + } + + OCRepPayloadSetPropString(refreshPayload, "uid", uId); + OCRepPayloadSetPropString(refreshPayload, "di", deviceId); + OCRepPayloadSetPropString(refreshPayload, "granttype", "refresh_token"); + OCRepPayloadSetPropString(refreshPayload, "refreshtoken", refreshtoken); + + return OCDoResource(NULL, OC_REST_POST, targetUri, NULL, (OCPayload *)refreshPayload, + CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0); + +no_memory: + OCRepPayloadDestroy(refreshPayload); + return OC_STACK_NO_MEMORY; +} + +OCStackResult OCCloudLogin(const char *host, const char *uId, const char *deviceId, + const char *accesstoken, OCClientResponseHandler response) +{ + return OCCloudSession(host, DEFAULT_AUTH_SESSION, uId, deviceId, accesstoken, true, response); +} + +OCStackResult OCCloudLogout(const char *host, OCClientResponseHandler response) +{ + return OCCloudSession(host, DEFAULT_AUTH_SESSION, NULL, NULL, NULL, false, response); +} ////////////////////////////////////////Device Sample -#define SAMPLE_MAX_NUM_POST_INSTANCE 2 + +#define SAMPLE_MAX_NUM_POST_INSTANCE 1 typedef struct LIGHTRESOURCE { OCResourceHandle handle; @@ -336,337 +456,96 @@ OCStackApplicationResult handlePublishCB(void *ctx, return OC_STACK_KEEP_TRANSACTION; } -void PublishResources(std::string host, std::string additionalQuery) +void PublishResources(std::string host) { - std::cout << "Running as Server mode" << std::endl; - - std::string requestQuery = DEFAULT_PUBLISH_QUERY; - requestQuery += additionalQuery; - std::cout << "Publishing resources..." << std::endl; - std::cout << host.c_str() << requestQuery.c_str() << std::endl; if (createLightResource((char *)"/a/light/0", &gLightInstance[0]) != 0) { std::cout << "Unable to create sample resource" << std::endl; } - if (createLightResource((char *)"/a/light/1", &gLightInstance[1]) != 0) + OCResourceHandle resourceHandles[1] = { gLightInstance[0].handle, + }; + OCCallbackData cbData; + cbData.cb = handlePublishCB; + cbData.context = (void *)DEFAULT_CONTEXT_VALUE; + cbData.cd = NULL; + + std::cout << "Publish default resources" << std::endl; + + OCDeviceInfo devInfoRoomLight; + OCStringLL deviceType; + + deviceType.value = "oic.d.light"; + deviceType.next = NULL; + devInfoRoomLight.deviceName = "Living Room Light"; + devInfoRoomLight.types = &deviceType; + devInfoRoomLight.specVersion = NULL; + devInfoRoomLight.dataModelVersions = NULL; + + OCStackResult res = OCSetDeviceInfo(devInfoRoomLight); + + if (res != OC_STACK_OK) + { + std::cout << "Setting device info failed" << std::endl; + } + + res = OCRDPublish(host.c_str(), CT_ADAPTER_TCP, NULL, 0, &cbData, + OC_LOW_QOS); + if (res != OC_STACK_OK) { - std::cout << "Unable to create sample resource" << std::endl; + std::cout << "Unable to publish default resources to cloud" << std::endl; } - if (OCCloudPublish(host.c_str(), requestQuery.c_str(), &handlePublishCB, 2, - gLightInstance[0].handle, gLightInstance[1].handle) != OC_STACK_OK) + std::cout << "Publish user resources" << std::endl; + + res = OCRDPublish(host.c_str(), CT_ADAPTER_TCP, resourceHandles, 1, &cbData, + OC_LOW_QOS); + if (res != OC_STACK_OK) { - std::cout << "Unable to publish resources to cloud" << std::endl; + std::cout << "Unable to publish user resources to cloud" << std::endl; } } -////////////////////////////////////////Client Sample -std::string g_host = "coap+tcp://"; - -void PrintRepresentation(OCRepPayloadValue *val) +/////////////////////////////////////////////Common sample +void printRepresentation(OCRepPayloadValue *value) { - while (val) + while (value) { - std::cout << "Key: " << val->name << " Value: "; - switch (val->type) + std::cout << "Key: " << value->name; + switch (value->type) { case OCREP_PROP_NULL: - std::cout << "NULL" << std::endl; + std::cout << " Value: None" << std::endl; break; - case OCREP_PROP_INT: - std::cout << val->i << std::endl; + std::cout << " Value: " << value->i << std::endl; break; - case OCREP_PROP_DOUBLE: - std::cout << val->d << std::endl; + std::cout << " Value: " << value->d << std::endl; break; - case OCREP_PROP_BOOL: - std::cout << val->b << std::endl; + std::cout << " Value: " << value->b << std::endl; break; - case OCREP_PROP_STRING: - std::cout << val->str << std::endl; + std::cout << " Value: " << value->str << std::endl; break; - case OCREP_PROP_BYTE_STRING: - std::cout << "[ByteString]" << std::endl; + std::cout << " Value: Byte String" << std::endl; break; - case OCREP_PROP_OBJECT: - std::cout << "[Object]" << std::endl; + std::cout << " Value: Object" << std::endl; break; - case OCREP_PROP_ARRAY: - std::cout << "[Array]" << std::endl; + std::cout << " Value: Array" << std::endl; break; } - - val = val->next; - } -} - - -int gNumObserveNotifies = 0; - -OCStackApplicationResult obsReqCB(void *ctx, OCDoHandle handle, - OCClientResponse *clientResponse) -{ - std::cout << "Observe response received from " << clientResponse->resourceUri << std::endl; - - if (ctx != (void *)DEFAULT_CONTEXT_VALUE) - { - std::cout << "Invalid Put callback received" << std::endl; - } - - if (clientResponse) - { - if (clientResponse->payload == NULL) - { - std::cout << "No payload received" << std::endl; - } - - OCRepPayloadValue *val = ((OCRepPayload *)clientResponse->payload)->values; - - PrintRepresentation(val); - - gNumObserveNotifies++; - if (gNumObserveNotifies > 5) //large number to test observing in DELETE case. - { - std::cout << "Cancelling with OC_HIGH_QOS" << std::endl; - if (OCCancel(handle, OC_HIGH_QOS, NULL, 0) != OC_STACK_OK) - { - std::cout << "Observe cancel error" << std::endl; - } - } - if (clientResponse->sequenceNumber == OC_OBSERVE_REGISTER) - { - std::cout << "This also serves as a registration confirmation" << std::endl; - } - else if (clientResponse->sequenceNumber == OC_OBSERVE_DEREGISTER) - { - std::cout << "This also serves as a deregistration confirmation" << std::endl; - return OC_STACK_DELETE_TRANSACTION; - } - else if (clientResponse->sequenceNumber == OC_OBSERVE_NO_OPTION) - { - std::cout << "This also tells you that registration/deregistration failed" << std::endl; - return OC_STACK_DELETE_TRANSACTION; - } - } - else - { - std::cout << "obsReqCB received Null clientResponse" << std::endl; + value = value->next; } - - return OC_STACK_KEEP_TRANSACTION; } -void ObserveResource(std::string uri, std::string additionalQuery) -{ - OCCallbackData cbData; - cbData.cb = obsReqCB; - cbData.context = (void *)DEFAULT_CONTEXT_VALUE; - cbData.cd = NULL; - - uri += additionalQuery; - - std::cout << "Request OBSERVE to resource " << uri.c_str() << std::endl; - - OCStackResult res = OCDoResource(NULL, OC_REST_OBSERVE, uri.c_str(), NULL, NULL, - CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0); - - std::cout << "Requesting OBSERVE res=" << res << std::endl; -} - -OCStackApplicationResult putReqCB(void *ctx, OCDoHandle /*handle*/, - OCClientResponse *clientResponse) -{ - std::cout << "Put response received from " << clientResponse->resourceUri << std::endl; - - if (ctx != (void *)DEFAULT_CONTEXT_VALUE) - { - std::cout << "Invalid Put callback received" << std::endl; - } - - if (clientResponse->payload == NULL) - { - std::cout << "No payload received" << std::endl; - } - - OCRepPayloadValue *val = ((OCRepPayload *)clientResponse->payload)->values; - - PrintRepresentation(val); - - std::string requestUri = g_host; - requestUri += clientResponse->resourceUri; - - ObserveResource(requestUri, ""); - - return OC_STACK_KEEP_TRANSACTION; -} - -OCPayload *putRequestPayload() -{ - OCRepPayload *payload = OCRepPayloadCreate(); - - if (!payload) - { - std::cout << "Failed to create put payload object" << std::endl; - std::exit(1); - } - - OCRepPayloadSetPropInt(payload, "power", 15); - OCRepPayloadSetPropBool(payload, "state", true); - - return (OCPayload *)payload; -} - -void PutResource(std::string uri, std::string additionalQuery) -{ - OCCallbackData cbData; - cbData.cb = putReqCB; - cbData.context = (void *)DEFAULT_CONTEXT_VALUE; - cbData.cd = NULL; - - uri += additionalQuery; - - std::cout << "Request PUT to resource " << uri.c_str() << std::endl; - - OCStackResult res = OCDoResource(NULL, OC_REST_PUT, uri.c_str(), NULL, putRequestPayload(), - CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0); - - std::cout << "Requesting PUT res=" << res << std::endl; -} - -OCStackApplicationResult handleGetCB(void *ctx, - OCDoHandle /*handle*/, - OCClientResponse *clientResponse) -{ - std::cout << "Get response received from " << clientResponse->resourceUri << std::endl; - - if (ctx != (void *)DEFAULT_CONTEXT_VALUE) - { - std::cout << "Invalid Get callback received" << std::endl; - } - - if (clientResponse->payload == NULL) - { - std::cout << "No payload received" << std::endl; - } - - if (clientResponse->payload != NULL && - clientResponse->payload->type == PAYLOAD_TYPE_REPRESENTATION) - { - OCRepPayloadValue *val = ((OCRepPayload *)clientResponse->payload)->values; - - PrintRepresentation(val); - - std::string requestUri = g_host; - requestUri += clientResponse->resourceUri; - - PutResource(requestUri, ""); - } - - return OC_STACK_KEEP_TRANSACTION; -} - -void GetResource(std::string uri, std::string additionalQuery) -{ - OCCallbackData cbData; - cbData.cb = handleGetCB; - cbData.context = (void *)DEFAULT_CONTEXT_VALUE; - cbData.cd = NULL; - - uri += additionalQuery; - - std::cout << "Request GET to resource " << uri.c_str() << std::endl; - - OCStackResult res = OCDoResource(NULL, OC_REST_GET, uri.c_str(), NULL, NULL, - CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0); - - std::cout << "Requesting GET res=" << res << std::endl; -} - -// This is a function called back when a device is discovered -OCStackApplicationResult discoveryReqCB(void *ctx, OCDoHandle /*handle*/, - OCClientResponse *clientResponse) -{ - if (ctx == (void *)DEFAULT_CONTEXT_VALUE) - { - std::cout << "Callback Context for DISCOVER query recvd successfully" << std::endl; - } - - if (clientResponse) - { - std::cout << "StackResult: " << clientResponse->result << std::endl; - - OCDiscoveryPayload *payload = (OCDiscoveryPayload *)clientResponse->payload; - if (!payload) - { - std::cout << "Empty payload" << std::endl; - return OC_STACK_DELETE_TRANSACTION; - } - - OCResourcePayload *resource = (OCResourcePayload *)payload->resources; - if (!resource) - { - std::cout << "No resources in payload" << std::endl; - return OC_STACK_DELETE_TRANSACTION; - } - - while (resource) - { - std::cout << "Found Resource " << resource->uri << std::endl; - - std::string requestUri = g_host; - requestUri += resource->uri; - - GetResource(requestUri, ""); - - resource = resource->next; - } - } - else - { - std::cout << "discoveryReqCB received Null clientResponse" << std::endl; - } - return OC_STACK_KEEP_TRANSACTION; -} - -void DiscoverResources(std::string host, std::string additionalQuery) -{ - std::cout << "Running as Client mode" << std::endl; - - std::string requestQuery = host; - requestQuery += DEFAULT_DISCOVER_QUERY; - requestQuery += additionalQuery; - - std::cout << "Finding resources..." << std::endl; - std::cout << requestQuery.c_str() << std::endl; - - OCCallbackData cbData; - - cbData.cb = discoveryReqCB; - cbData.context = (void *)DEFAULT_CONTEXT_VALUE; - cbData.cd = NULL; - - if (OCDoResource(NULL, OC_REST_DISCOVER, requestQuery.c_str(), NULL, 0, CT_ADAPTER_TCP, - OC_LOW_QOS, &cbData, NULL, 0) != OC_STACK_OK) - { - std::cout << "Unable to find resources from cloud" << std::endl; - } -} - - - -/////////////////////////////////////////////Common sample - -int g_runningMode = 0; +std::string g_host = "coap+tcp://"; OCStackApplicationResult handleLoginoutCB(void *ctx, OCDoHandle /*handle*/, @@ -686,21 +565,12 @@ OCStackApplicationResult handleLoginoutCB(void *ctx, OCRepPayloadValue *val = ((OCRepPayload *)clientResponse->payload)->values; - while (val) - { - std::cout << "Key: " << val->name << " Value: " << val->str << std::endl; - val = val->next; - } - - if (g_runningMode == 1) - { - PublishResources(g_host, ""); - } - else if (g_runningMode == 2) - { - DiscoverResources(g_host, ""); - } + printRepresentation(val); + } + if (clientResponse->result < 5) + { + PublishResources(g_host); } return OC_STACK_KEEP_TRANSACTION; @@ -721,16 +591,12 @@ OCStackApplicationResult handleRegisterCB(void *ctx, clientResponse->payload->type == PAYLOAD_TYPE_REPRESENTATION) { std::cout << "PAYLOAD_TYPE_REPRESENTATION received" << std::endl; - std::cout << "You can login using received session variable after disconnected or reboot" << + std::cout << "You can Sign-In using retrieved accesstoken when disconnected or reboot" << std::endl; OCRepPayloadValue *val = ((OCRepPayload *)clientResponse->payload)->values; - while (val) - { - std::cout << "Key: " << val->name << " Value: " << val->str << std::endl; - val = val->next; - } + printRepresentation(val); } return OC_STACK_KEEP_TRANSACTION; @@ -739,30 +605,30 @@ OCStackApplicationResult handleRegisterCB(void *ctx, void PrintUsage() { std::cout << std::endl; - std::cout << "Usage : cloud_device \n"; + std::cout << "Usage : thin_cloud_device \n"; std::cout << ": Cloud Address, \"127.0.0.1:5683\"\n"; std::cout << - ": String value, Provided by response of onboarding scenario\n\tor kind of registration portal\n\n"; + ": String value, Provided by response of onboarding scenario\n\tor kind of registration portal\n\n"; std::cout << - ": String value, 's' for publish resource, 'c' for start discovery\n\n"; + "sample: \"cloud_device 127.0.0.1:5683\"\n\t-Sign-Up mode\n\n"; std::cout << - "If you want to get session key using OAuth 2 auth code,\n\tleave blank to , fields\n"; - std::cout << - "sample: \"cloud_device 127.0.0.1:5683\"\n\t-OAuth 2 registration mode\n\n"; - std::cout << - "sample: \"cloud_device 127.0.0.1:5683 1234567890123456 s\"\n\t-Publish resource under registered session\n\n"; - std::cout << - "sample: \"cloud_device 127.0.0.1:5683 1234567890123456 c\"\n\t-Discover resource under registered session\n\n"; + "sample: \"cloud_device 127.0.0.1:5683 abcdefg 1234567890123456\"\n\t-Sign-in and Publish resource to registered account\n\n"; +} + +static FILE *client_open(const char * /*path*/, const char *mode) +{ + return fopen("./thin_resource_server.dat", mode); } int main(int argc, char *argv[]) { - std::string session; + std::string uId; + std::string accessToken; std::string authProvider; std::string authCode; - OCMode stackMode = OC_CLIENT; + OCMode stackMode = OC_CLIENT_SERVER; switch (argc) { @@ -774,26 +640,8 @@ int main(int argc, char *argv[]) break; case 4: - session = argv[2]; - if (strlen(argv[3]) != 1) - { - std::cout << "OCStack init error" << std::endl; - return 0; - } - if (strcmp(argv[3], "s") == 0) - { - stackMode = OC_CLIENT_SERVER; - g_runningMode = 1; - } - else if (strcmp(argv[3], "c") == 0) - { - g_runningMode = 2; - } - else - { - std::cout << "Invalid , 's' or 'c' required" << std::endl; - return 0; - } + uId = argv[2]; + accessToken = argv[3]; break; default: @@ -805,6 +653,13 @@ int main(int argc, char *argv[]) std::cout << "Host " << g_host.c_str() << std::endl; + OCPersistentStorage ps{ client_open, fread, fwrite, fclose, unlink }; + if (OCRegisterPersistentStorageHandler(&ps) != OC_STACK_OK) + { + std::cout << "OCStack init persistent storage error" << std::endl; + return 0; + } + if (OCInit(NULL, 0, stackMode) != OC_STACK_OK) { std::cout << "OCStack init error" << std::endl; @@ -816,14 +671,16 @@ int main(int argc, char *argv[]) switch (argc) { case 2: - std::cout << "Register account to cloud using " << authProvider << " " << authCode << std::endl; - res = OCCloudRegisterLogin(g_host.c_str(), authProvider.c_str(), authCode.c_str(), - handleRegisterCB); - std::cout << "OCCloudRegisterLogin return " << res << std::endl; + std::cout << "Sign-Up to cloud using " << authProvider << " " << authCode << std::endl; + res = OCCloudSignup(g_host.c_str(), OCGetServerInstanceIDString(), authProvider.c_str(), + authCode.c_str(), handleRegisterCB); + std::cout << "OCCloudSignup return " << res << std::endl; break; case 4: - res = OCCloudLogin(g_host.c_str(), session.c_str(), handleLoginoutCB); + std::cout << "Sign-In to cloud using " << accessToken << std::endl; + res = OCCloudLogin(g_host.c_str(), uId.c_str(), OCGetServerInstanceIDString(), accessToken.c_str(), + handleLoginoutCB); std::cout << "OCCloudLogin return " << res << std::endl; break; @@ -832,6 +689,8 @@ int main(int argc, char *argv[]) return 0; } + + std::cout << "Waiting response.." << std::endl; while (true) -- 2.7.4