From 438d58a3d487ff95937d2f67a633253fdea0e1ef Mon Sep 17 00:00:00 2001 From: omkar Date: Thu, 20 Nov 2014 10:55:35 -0800 Subject: [PATCH] Device Discovery - C & C++ SDK changes Adding API for setting device information. Currently supports filtering of device information based on device id and device name only. Updated C and C++ sample applications Change-Id: Ie2fbfac8c9444560633b9716e777d4697a146f66 Signed-off-by: omkar --- resource/csdk/occoap/src/occoap.c | 3 +- .../stack/include/internal/ocresourcehandler.h | 10 +- resource/csdk/stack/include/ocstack.h | 35 ++++ resource/csdk/stack/include/ocstackconfig.h | 12 ++ .../samples/linux/SimpleClientServer/occlient.cpp | 57 ++++++ .../samples/linux/SimpleClientServer/occlient.h | 2 + .../samples/linux/SimpleClientServer/ocserver.cpp | 156 +++++++++++++++ .../samples/linux/SimpleClientServer/ocserver.h | 9 + resource/csdk/stack/src/ocresource.c | 221 ++++++++++++++++++++- resource/csdk/stack/src/ocstack.c | 13 ++ resource/examples/SConscript | 4 +- resource/examples/devicediscoveryclient.cpp | 147 ++++++++++++++ resource/examples/devicediscoveryserver.cpp | 170 ++++++++++++++++ resource/examples/makefile | 12 +- resource/include/IClientWrapper.h | 4 + resource/include/IServerWrapper.h | 3 + resource/include/InProcClientWrapper.h | 10 + resource/include/InProcServerWrapper.h | 3 + resource/include/OCApi.h | 2 + resource/include/OCPlatform.h | 27 +++ resource/include/OCPlatform_impl.h | 26 +++ resource/include/OutOfProcClientWrapper.h | 5 + resource/include/OutOfProcServerWrapper.h | 8 + resource/src/InProcClientWrapper.cpp | 87 ++++++-- resource/src/InProcServerWrapper.cpp | 12 ++ resource/src/OCPlatform.cpp | 21 ++ resource/src/OCPlatform_impl.cpp | 23 ++- 27 files changed, 1053 insertions(+), 29 deletions(-) create mode 100644 resource/examples/devicediscoveryclient.cpp create mode 100644 resource/examples/devicediscoveryserver.cpp diff --git a/resource/csdk/occoap/src/occoap.c b/resource/csdk/occoap/src/occoap.c index 5c2e7ed..78bce42 100644 --- a/resource/csdk/occoap/src/occoap.c +++ b/resource/csdk/occoap/src/occoap.c @@ -228,7 +228,8 @@ static void HandleCoAPRequests(struct coap_context_t *ctx, if(requestResult == OC_STACK_VIRTUAL_DO_NOT_HANDLE || requestResult == OC_STACK_OK || requestResult == OC_STACK_RESOURCE_CREATED || - requestResult == OC_STACK_RESOURCE_DELETED) + requestResult == OC_STACK_RESOURCE_DELETED || + requestResult == OC_STACK_INVALID_DEVICE_INFO) { goto exit; } diff --git a/resource/csdk/stack/include/internal/ocresourcehandler.h b/resource/csdk/stack/include/internal/ocresourcehandler.h index 505a598..f56769c 100755 --- a/resource/csdk/stack/include/internal/ocresourcehandler.h +++ b/resource/csdk/stack/include/internal/ocresourcehandler.h @@ -31,6 +31,8 @@ #define OC_RSRVD_RESOURCE_TYPE "rt" #define OC_RSRVD_RESOURCE_TYPE_PRESENCE "core.presence" #define OC_RSRVD_INTERFACE "if" +#define OC_RSRVD_DEVICE_ID "di" +#define OC_RSRVD_DEVICE_NAME "dn" #define OC_RSRVD_INTERFACE_DEFAULT "oc.mi.def" #define OC_RSRVD_INTERFACE_LL "oc.mi.ll" #define OC_RSRVD_INTERFACE_BATCH "oc.mi.b" @@ -53,7 +55,9 @@ typedef enum { STACK_RES_DISCOVERY_NOFILTER = 0, STACK_RES_DISCOVERY_IF_FILTER, - STACK_RES_DISCOVERY_RT_FILTER + STACK_RES_DISCOVERY_RT_FILTER, + STACK_DEVICE_DISCOVERY_DI_FILTER, + STACK_DEVICE_DISCOVERY_DN_FILTER } StackQueryTypes; typedef enum { @@ -80,6 +84,10 @@ OCStackResult DetermineResourceHandling (OCServerRequest *request, OCStackResult ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request); +OCStackResult SaveDeviceInfo(OCDeviceInfo deviceInfo); + +void DeleteDeviceInfo(); + OCStackResult BuildVirtualResourceResponse(OCResource *resourcePtr, uint8_t filterOn, char *filterValue, char * out, uint16_t *remaining); diff --git a/resource/csdk/stack/include/ocstack.h b/resource/csdk/stack/include/ocstack.h index 085f497..ab348f9 100644 --- a/resource/csdk/stack/include/ocstack.h +++ b/resource/csdk/stack/include/ocstack.h @@ -170,6 +170,7 @@ typedef enum { OC_STACK_MALFORMED_RESPONSE, /* the remote reply contained malformed data */ OC_STACK_PERSISTENT_BUFFER_REQUIRED, OC_STACK_INVALID_REQUEST_HANDLE, + OC_STACK_INVALID_DEVICE_INFO, OC_STACK_ERROR /* Error status code - END HERE */ } OCStackResult; @@ -276,6 +277,26 @@ typedef struct { OCHeaderOption rcvdVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS]; }OCClientResponse; +/** + * Following structure describes the device properties. All non-Null properties will be included + * in a device discovery request. + */ +typedef struct +{ + char *deviceName; + char *hostName; + char *deviceUUID; + char *contentType; + char *version; + char *manufacturerName; + char *manufacturerUrl; + char *modelNumber; + char *dateOfManufacture; + char *platformVersion; + char *firmwareVersion; + char *supportUrl; +} OCDeviceInfo; + typedef struct { // Request handle is passed to server via the entity handler for each incoming request. @@ -490,6 +511,20 @@ OCStackResult OCStopPresence(); OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandler); /** + * Set device information. + * + * @param deviceInfo - Structure passed by the server application containing + * the device information. + * + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_INVALID_PARAM - invalid paramerter + * OC_STACK_ERROR - stack process error + */ +OCStackResult OCSetDeviceInfo(OCDeviceInfo deviceInfo); + +/** * Create a resource. * * @param handle - pointer to handle to newly created resource. Set by ocstack. Used to refer to resource diff --git a/resource/csdk/stack/include/ocstackconfig.h b/resource/csdk/stack/include/ocstackconfig.h index 650949c..9e14bd3 100644 --- a/resource/csdk/stack/include/ocstackconfig.h +++ b/resource/csdk/stack/include/ocstackconfig.h @@ -56,6 +56,18 @@ #define MAX_QUERY_LENGTH (64) /** + * Maximum length of the Manufacturer name supported by the server + * for manufacturer name + */ +#define MAX_MANUFACTURER_NAME_LENGTH (16) + +/** + * Maximum length of the URL to the Manufacturer details supported by + * the server. + */ +#define MAX_MANUFACTURER_URL_LENGTH (32) + +/** * Maximum number of resources which can be contained inside collection * resource. */ diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp index 9f70f52..ed5f054 100644 --- a/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp @@ -32,6 +32,8 @@ static int UNICAST_DISCOVERY = 0; static int TEST_CASE = 0; static const char * TEST_APP_UNICAST_DISCOVERY_QUERY = "coap://0.0.0.0:5683/oc/core"; +static const char * TEST_APP_UNICAST_DEVICE_DISCOVERY_QUERY = "coap://0.0.0.0:5683/oc/core/d"; +static const char * TEST_APP_MULTICAST_DEVICE_DISCOVERY_QUERY = "coap://224.0.1.187:5683/oc/core/d"; static std::string putPayload = "{\"state\":\"on\",\"power\":5}"; static std::string coapServerIP = "255.255.255.255"; static std::string coapServerPort = "5683"; @@ -82,6 +84,7 @@ static void PrintUsage() OC_LOG(INFO, TAG, "-t 14 : Discover Resources and Initiate Nonconfirmable Observe Requests then cancel immediately"); OC_LOG(INFO, TAG, "-t 15 : Discover Resources and Initiate Nonconfirmable Get Request and add vendor specific header options"); + OC_LOG(INFO, TAG, "-t 16 : Discover Devices"); } OCStackResult InvokeOCDoResource(std::ostringstream &query, @@ -330,6 +333,9 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle, case TEST_GET_REQ_NON_WITH_VENDOR_HEADER_OPTIONS: InitGetRequest(OC_LOW_QOS, 1); break; + case TEST_DISCOVER_DEV_REQ: + InitDeviceDiscovery(); + break; default: PrintUsage(); break; @@ -339,6 +345,25 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle, return (UNICAST_DISCOVERY) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ; } + +OCStackApplicationResult DeviceDiscoveryReqCB (void* ctx, OCDoHandle handle, + OCClientResponse * clientResponse) +{ + if (ctx == (void*) DEFAULT_CONTEXT_VALUE) + { + OC_LOG(INFO, TAG, "Callback Context for Device DISCOVER query recvd successfully"); + } + + if(clientResponse) + { + //OC_LOG truncates the response as it is too long. + fprintf(stderr, "Discovery response: \n %s\n", clientResponse->resJSONPayload); + fflush(stderr); + } + + return (UNICAST_DISCOVERY) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION; +} + #ifdef WITH_PRESENCE int InitPresence() { @@ -495,6 +520,38 @@ int InitGetRequest(OCQualityOfService qos, uint8_t withVendorSpecificHeaderOptio } } +int InitDeviceDiscovery() +{ + OCStackResult ret; + OCCallbackData cbData; + OCDoHandle handle; + char szQueryUri[64] = { 0 }; + + cbData.cb = DeviceDiscoveryReqCB; + cbData.context = (void*)DEFAULT_CONTEXT_VALUE; + cbData.cd = NULL; + + if(UNICAST_DISCOVERY) + { + strncpy(szQueryUri, TEST_APP_UNICAST_DEVICE_DISCOVERY_QUERY, + (strlen(TEST_APP_UNICAST_DEVICE_DISCOVERY_QUERY) + 1)); + } + else + { + strncpy(szQueryUri, TEST_APP_MULTICAST_DEVICE_DISCOVERY_QUERY, + (strlen(TEST_APP_MULTICAST_DEVICE_DISCOVERY_QUERY) + 1)); + } + + ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0); + + if (ret != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack device error"); + } + + return ret; +} + int InitDiscovery() { OCStackResult ret; diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.h b/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.h index cb59cb0..f106f7b 100644 --- a/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.h +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.h @@ -58,6 +58,7 @@ typedef enum { #endif TEST_OBS_REQ_NON_CANCEL_IMM, TEST_GET_REQ_NON_WITH_VENDOR_HEADER_OPTIONS, + TEST_DISCOVER_DEV_REQ, MAX_TESTS } CLIENT_TEST; @@ -91,6 +92,7 @@ int InitGetRequest(OCQualityOfService qos, uint8_t withVendorSpecificHeaderOptio int InitPostRequest(OCQualityOfService qos); int InitDeleteRequest(OCQualityOfService qos); int InitGetRequest(OCQualityOfService qos); +int InitDeviceDiscovery(); int InitDiscovery(); /* Function to retrieve ip address, port no. of the server diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp index 1bed2bf..0311507 100644 --- a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp @@ -61,6 +61,20 @@ const char responsePayloadDeleteResourceNotSupported[] = char *gResourceUri= (char *)"/a/light"; +const char *contentType = "myContentType"; +const char *dateOfManufacture = "myDateOfManufacture"; +const char *deviceName = "myDeviceName"; +const char *deviceUUID = "myDeviceUUID"; +const char *firmwareVersion = "myFirmwareVersion"; +const char *hostName = "myHostName"; +const char *manufacturerName = "myManufacturerNa"; +const char *manufacturerUrl = "myManufacturerUrl"; +const char *modelNumber = "myModelNumber"; +const char *platformVersion = "myPlatformVersion"; +const char *supportUrl = "mySupportUrl"; +const char *version = "myVersion"; + +OCDeviceInfo deviceInfo; static uint16_t OC_WELL_KNOWN_PORT = 5683; @@ -729,6 +743,24 @@ int main(int argc, char* argv[]) OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandlerCb); + OCStackResult deviceResult = SetDeviceInfo(contentType, dateOfManufacture, deviceName, + deviceUUID, firmwareVersion, hostName, manufacturerName, + manufacturerUrl, modelNumber, platformVersion, supportUrl, version); + + if (deviceResult != OC_STACK_OK) + { + OC_LOG(INFO, TAG, "Device Registration failed!"); + exit (EXIT_FAILURE); + } + + deviceResult = OCSetDeviceInfo(deviceInfo); + + if (deviceResult != OC_STACK_OK) + { + OC_LOG(INFO, TAG, "Device Registration failed!"); + exit (EXIT_FAILURE); + } + /* * Declare and create the example resource: Light */ @@ -747,6 +779,7 @@ int main(int argc, char* argv[]) // Break from loop with Ctrl-C OC_LOG(INFO, TAG, "Entering ocserver main loop..."); + DeleteDeviceInfo(); signal(SIGINT, handleSigInt); while (!gQuitFlag) { if (OCProcess() != OC_STACK_OK) { @@ -792,3 +825,126 @@ int createLightResource (char *uri, LightResource *lightResource) return 0; } + +void DeleteDeviceInfo() +{ + free(deviceInfo.contentType); + free(deviceInfo.dateOfManufacture); + free(deviceInfo.deviceName); + free(deviceInfo.deviceUUID); + free(deviceInfo.firmwareVersion); + free(deviceInfo.hostName); + free(deviceInfo.manufacturerName); + free(deviceInfo.manufacturerUrl); + free(deviceInfo.modelNumber); + free(deviceInfo.platformVersion); + free(deviceInfo.supportUrl); + free(deviceInfo.version); +} + +bool DuplicateString(char** targetString, const char* sourceString) +{ + if(!sourceString) + { + return false; + } + else + { + *targetString = (char *) malloc(strlen(sourceString) + 1); + + if(targetString) + { + strncpy(*targetString, sourceString, (strlen(sourceString) + 1)); + return true; + } + } + return false; +} + +OCStackResult SetDeviceInfo(const char *contentType, const char *dateOfManufacture, + const char *deviceName, const char *deviceUUID, const char *firmwareVersion, + const char *hostName, const char *manufacturerName, const char *manufacturerUrl, + const char *modelNumber, const char *platformVersion, const char *supportUrl, + const char *version) +{ + + bool success = true; + + if(manufacturerName != NULL && (strlen(manufacturerName) > MAX_MANUFACTURER_NAME_LENGTH)) + { + return OC_STACK_INVALID_PARAM; + } + + if(manufacturerUrl != NULL && (strlen(manufacturerUrl) > MAX_MANUFACTURER_URL_LENGTH)) + { + return OC_STACK_INVALID_PARAM; + } + + if(!DuplicateString(&deviceInfo.contentType, contentType)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.dateOfManufacture, dateOfManufacture)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.deviceName, deviceName)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.deviceUUID, deviceUUID)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.firmwareVersion, firmwareVersion)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.hostName, hostName)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.manufacturerName, manufacturerName)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.manufacturerUrl, manufacturerUrl)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.modelNumber, modelNumber)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.platformVersion, platformVersion)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.supportUrl, supportUrl)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.version, version)) + { + success = false; + } + + if(success) + { + return OC_STACK_OK; + } + + DeleteDeviceInfo(); + return OC_STACK_ERROR; +} diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.h b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.h index f5e45e5..81a9507 100644 --- a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.h +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.h @@ -91,6 +91,15 @@ OCEntityHandlerResult ProcessNonExistingResourceRequest (OCEntityHandlerRequest void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest); void ProcessObserveDeregister (OCEntityHandlerRequest *ehRequest); +void DeleteDeviceInfo(); + +OCStackResult SetDeviceInfo(const char *contentType, const char *dateOfManufacture, + const char *deviceName, const char *deviceUUID, const char *firmwareVersion, + const char *hostName, const char *manufacturerName, const char *manufacturerUrl, + const char *modelNumber, const char *platformVersion, const char *supportUrl, + const char *version); + + //----------------------------------------------------------------------------- // Callback functions //----------------------------------------------------------------------------- diff --git a/resource/csdk/stack/src/ocresource.c b/resource/csdk/stack/src/ocresource.c index a2a1c4e..f2267d1 100644 --- a/resource/csdk/stack/src/ocresource.c +++ b/resource/csdk/stack/src/ocresource.c @@ -40,6 +40,7 @@ TAG, PCF(#arg " is NULL")); return (retVal); } } extern OCResource *headResource; +static cJSON *savedDeviceInfo = NULL; static const char * VIRTUAL_RSRCS[] = { "/oc/core", @@ -71,7 +72,8 @@ static OCStackResult ValidateUrlQuery (unsigned char *url, unsigned char *query, if (!url) return OC_STACK_INVALID_URI; - if (strcmp ((char *)url, GetVirtualResourceUri(OC_WELL_KNOWN_URI)) == 0) { + if (strcmp ((char *)url, GetVirtualResourceUri(OC_WELL_KNOWN_URI)) == 0 || + strcmp ((char *)url, GetVirtualResourceUri(OC_DEVICE_URI)) == 0) { *filterOn = STACK_RES_DISCOVERY_NOFILTER; if (query && *query) { char* strTokPtr; @@ -85,6 +87,12 @@ static OCStackResult ValidateUrlQuery (unsigned char *url, unsigned char *query, } else if (strcmp (filterParam, OC_RSRVD_RESOURCE_TYPE) == 0) { // Resource discovery with resource type filter *filterOn = STACK_RES_DISCOVERY_RT_FILTER; + } else if (strcmp (filterParam, OC_RSRVD_DEVICE_ID) == 0) { + //Device ID filter + *filterOn = STACK_DEVICE_DISCOVERY_DI_FILTER; + } else if (strcmp (filterParam, OC_RSRVD_DEVICE_NAME) == 0) { + //Device Name filter + *filterOn = STACK_DEVICE_DISCOVERY_DN_FILTER; } else { // Other filter types not supported return OC_STACK_INVALID_QUERY; @@ -205,6 +213,85 @@ OCStackResult BuildVirtualResourceResponse(OCResource *resourcePtr, uint8_t filt return ret; } +OCStackResult BuildVirtualResourceResponseForDevice(uint8_t filterOn, char *filterValue, + char *out, uint16_t *remaining) +{ + OCStackResult ret = OC_STACK_ERROR; + + if (savedDeviceInfo != NULL) + { + char *jsonStr = NULL; + uint16_t jsonLen = 0; + cJSON *repObj = cJSON_GetObjectItem(savedDeviceInfo, "rep"); + + OC_LOG(INFO, TAG, PCF("Entering BuildVirtualResourceResponseForDevice")); + + if (filterOn == STACK_DEVICE_DISCOVERY_DI_FILTER) + { + if((cJSON_GetObjectItem(repObj,"di") != NULL) && + strcmp(cJSON_GetObjectItem(repObj,"di")->valuestring, filterValue) == 0) + { + ret = OC_STACK_OK; + } + } + else if (filterOn == STACK_DEVICE_DISCOVERY_DN_FILTER) + { + if((cJSON_GetObjectItem(repObj,"dn") != NULL) && + strcmp(cJSON_GetObjectItem(repObj,"dn")->valuestring, filterValue) == 0) + { + ret = OC_STACK_OK; + } + } + else if (filterOn == STACK_RES_DISCOVERY_NOFILTER) + { + ret = OC_STACK_OK; + } + else + { + ret = OC_STACK_INVALID_QUERY; + } + + if (ret == OC_STACK_OK) + { + jsonStr = cJSON_PrintUnformatted (savedDeviceInfo); + + if(jsonStr) + { + jsonLen = strlen(jsonStr); + + if (jsonLen < *remaining) + { + strncpy(out, jsonStr, (jsonLen + 1)); + *remaining = *remaining - jsonLen; + ret = OC_STACK_OK; + } + else + { + ret = OC_STACK_ERROR; + } + + free(jsonStr); + } + else + { + ret = OC_STACK_ERROR; + } + } + else + { + ret = OC_STACK_INVALID_DEVICE_INFO; + } + } + else + { + //error so that stack won't respond with empty payload + ret = OC_STACK_INVALID_DEVICE_INFO; + } + + OC_LOG(INFO, TAG, PCF("Exiting BuildVirtualResourceResponseForDevice")); + return ret; +} + TODO ("Does it make sense to make this method as inline") const char * GetVirtualResourceUri( OCVirtualResources resource) { @@ -429,6 +516,33 @@ HandleVirtualResource (OCServerRequest *request, OCResource* resource) result = OCDoResponse(&response); } } + else if (strcmp ((char *)request->resourceUrl, GetVirtualResourceUri(OC_DEVICE_URI)) == 0) + { + remaining = MAX_RESPONSE_LENGTH; + ptr = discoveryResBuf; + + result = BuildVirtualResourceResponseForDevice(filterOn, filterValue, + (char*)ptr, &remaining); + + if(result == OC_STACK_OK) + { + ptr += strlen((char*)ptr); + } + + if(remaining < MAX_RESPONSE_LENGTH) + { + OCEntityHandlerResponse response = {0}; + + response.ehResult = OC_EH_OK; + response.payload = discoveryResBuf; + response.payloadSize = strlen((const char *)discoveryResBuf) + 1; + response.persistentBufferFlag = 0; + response.requestHandle = (OCRequestHandle) request; + response.resourceHandle = (OCResourceHandle) resource; + + result = OCDoResponse(&response); + } + } #ifdef WITH_PRESENCE else { @@ -644,4 +758,109 @@ ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerReque return ret; } +void DeleteDeviceInfo() +{ + if(savedDeviceInfo) + { + cJSON_Delete(savedDeviceInfo); + } +} + +OCStackResult SaveDeviceInfo(OCDeviceInfo deviceInfo) +{ + DeleteDeviceInfo(); + + savedDeviceInfo = cJSON_CreateObject(); + cJSON *repObj = NULL; + + cJSON_AddItemToObject (savedDeviceInfo, OC_RSRVD_HREF, + cJSON_CreateString(GetVirtualResourceUri(OC_DEVICE_URI))); + + cJSON_AddItemToObject (savedDeviceInfo, "rep", repObj = cJSON_CreateObject()); + + if (deviceInfo.contentType) + { + cJSON_AddItemToObject (repObj, "ct", + cJSON_CreateString(deviceInfo.contentType)); + } + + if (deviceInfo.dateOfManufacture) + { + cJSON_AddItemToObject (repObj, "mndt", + cJSON_CreateString(deviceInfo.dateOfManufacture)); + } + + if (deviceInfo.deviceName) + { + cJSON_AddItemToObject (repObj, "dn", + cJSON_CreateString(deviceInfo.deviceName)); + } + + if (deviceInfo.deviceUUID) + { + cJSON_AddItemToObject (repObj, "di", + cJSON_CreateString(deviceInfo.deviceUUID)); + } + + if (deviceInfo.firmwareVersion) + { + cJSON_AddItemToObject (repObj, "mnfv", + cJSON_CreateString(deviceInfo.firmwareVersion)); + } + + if (deviceInfo.hostName) + { + cJSON_AddItemToObject (repObj, "hn", cJSON_CreateString(deviceInfo.hostName)); + } + + if (deviceInfo.manufacturerName) + { + if(strlen(deviceInfo.manufacturerName) > MAX_MANUFACTURER_NAME_LENGTH) + { + DeleteDeviceInfo(); + return OC_STACK_INVALID_PARAM; + } + + cJSON_AddItemToObject (repObj, "mnmn", + cJSON_CreateString(deviceInfo.manufacturerName)); + } + + if (deviceInfo.manufacturerUrl) + { + if(strlen(deviceInfo.manufacturerUrl) > MAX_MANUFACTURER_URL_LENGTH) + { + DeleteDeviceInfo(); + return OC_STACK_INVALID_PARAM; + } + + cJSON_AddItemToObject (repObj, "mnml", + cJSON_CreateString(deviceInfo.manufacturerUrl)); + } + + if (deviceInfo.modelNumber) + { + cJSON_AddItemToObject (repObj, "mnmo", + cJSON_CreateString(deviceInfo.modelNumber)); + } + + if (deviceInfo.platformVersion) + { + cJSON_AddItemToObject (repObj, "mnpv", + cJSON_CreateString(deviceInfo.platformVersion)); + } + + if (deviceInfo.supportUrl) + { + cJSON_AddItemToObject (repObj, "mnsl", + cJSON_CreateString(deviceInfo.supportUrl)); + } + + if (deviceInfo.version) + { + cJSON_AddItemToObject (repObj, "icv", + cJSON_CreateString(deviceInfo.version)); + } + + return OC_STACK_OK; +} diff --git a/resource/csdk/stack/src/ocstack.c b/resource/csdk/stack/src/ocstack.c index fd4c754..b2aec91 100644 --- a/resource/csdk/stack/src/ocstack.c +++ b/resource/csdk/stack/src/ocstack.c @@ -457,6 +457,7 @@ OCStackResult OCStop() // Free memory dynamically allocated for resources deleteAllResources(); + DeleteDeviceInfo(); // Make call to OCCoAP layer if (OCStopCoAP() == OC_STACK_OK) @@ -913,6 +914,18 @@ OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandle return OC_STACK_OK; } +OCStackResult OCSetDeviceInfo(OCDeviceInfo deviceInfo) +{ + OC_LOG(INFO, TAG, PCF("Entering OCSetDeviceInfo")); + + if(myStackMode == OC_CLIENT) + { + return OC_STACK_ERROR; + } + + return SaveDeviceInfo(deviceInfo); +} + /** * Create a resource * diff --git a/resource/examples/SConscript b/resource/examples/SConscript index 12a7dcc..4a12d01 100644 --- a/resource/examples/SConscript +++ b/resource/examples/SConscript @@ -60,11 +60,13 @@ roomserver = examples_env.Program('roomserver', 'roomserver.cpp') roomclient = examples_env.Program('roomclient', 'roomclient.cpp') garageserver = examples_env.Program('garageserver', 'garageserver.cpp') garageclient = examples_env.Program('garageclient', 'garageclient.cpp') +devicediscoveryserver = examples_env.Program('devicediscoveryserver', 'devicediscoveryserver.cpp') +devicediscoveryclient = examples_env.Program('devicediscoveryclient', 'devicediscoveryclient.cpp') Alias("examples", [simpleserver, simpleserverHQ, simpleclient, simpleclientHQ, fridgeserver, fridgeclient, presenceserver, presenceclient, simpleclientserver, roomserver, roomclient, garageserver, - garageclient]) + garageclient, devicediscoveryserver, devicediscoveryclient]) env.AppendTarget('examples') #ios doesn't allow run application from terminal, so won't build these examples diff --git a/resource/examples/devicediscoveryclient.cpp b/resource/examples/devicediscoveryclient.cpp new file mode 100644 index 0000000..f08a8c7 --- /dev/null +++ b/resource/examples/devicediscoveryclient.cpp @@ -0,0 +1,147 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH 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. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// +///This sample demonstrates the device discovery feature +///The client queries for the device related information +///stored by the server. +/// + +#include +#include + +#include "OCPlatform.h" +#include "OCApi.h" + +using namespace OC; + +//Callback after device information is received +void receivedDeviceInfo(const OCRepresentation& rep) +{ + std::cout << "\nDevice Information received ---->\n"; + + std::string contentType; + std::string dateOfManufacture; + std::string deviceName; + std::string deviceUUID; + std::string firmwareVersion; + std::string hostName; + std::string manufacturerName; + std::string manufacturerUrl; + std::string modelNumber; + std::string platformVersion; + std::string supportUrl; + std::string version; + + if(rep.getValue("ct", contentType)) + { + std::cout << "Content Type: " << contentType << std::endl; + } + + if(rep.getValue("mndt", dateOfManufacture)) + { + std::cout << "Date of manufacture: " << dateOfManufacture << std::endl; + } + + if(rep.getValue("dn", deviceName)) + { + std::cout << "Device Name: " << deviceName << std::endl; + } + + if(rep.getValue("di", deviceUUID)) + { + std::cout << "Device UUID: " << deviceUUID << std::endl; + } + + if(rep.getValue("mnfv", firmwareVersion)) + { + std::cout << "Firmware Version: " << firmwareVersion << std::endl; + } + + if(rep.getValue("hn", hostName)) + { + std::cout << "Host Name: " << hostName << std::endl; + } + + if(rep.getValue("mnmn", manufacturerName)) + { + std::cout << "Manufacturer Name: " << manufacturerName << std::endl; + } + + if(rep.getValue("mnml", manufacturerUrl)) + { + std::cout << "Manufacturer Url: " << manufacturerUrl << std::endl; + } + + if(rep.getValue("mnmo", modelNumber)) + { + std::cout << "Model No. : " << modelNumber << std::endl; + } + + if(rep.getValue("mnpv", platformVersion)) + { + std::cout << "Platform Version: " << platformVersion << std::endl; + } + + if(rep.getValue("mnsl", supportUrl)) + { + std::cout << "Support URL: " << supportUrl << std::endl; + } + + if(rep.getValue("icv", version)) + { + std::cout << "Version: " << version << std::endl; + } +} + +int main() { + + // Create PlatformConfig object + PlatformConfig cfg { + OC::ServiceType::InProc, + OC::ModeType::Client, + "0.0.0.0", + 0, + OC::QualityOfService::LowQos + }; + + OCPlatform::Configure(cfg); + try + { + OCPlatform::getDeviceInfo("", "coap://224.0.1.187/oc/core/d", &receivedDeviceInfo); + std::cout<< "Querying for device information... " < lock(blocker); + cv.wait(lock); + + }catch(OCException& e) + { + //log(e.what()); + } + + return 0; +} + diff --git a/resource/examples/devicediscoveryserver.cpp b/resource/examples/devicediscoveryserver.cpp new file mode 100644 index 0000000..4a7494d --- /dev/null +++ b/resource/examples/devicediscoveryserver.cpp @@ -0,0 +1,170 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH 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. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// +///This sample demonstrates the device discovery feature +///The server sets the device related info. which can +///be later retrieved by a client. +/// + +#include +#include + +#include "OCPlatform.h" +#include "OCApi.h" + +using namespace OC; + +//Set of strings for each of deviceInfo fields +std::string contentType = "myContentType"; +std::string dateOfManufacture = "myDateOfManufacture"; +std::string deviceName = "myDeviceName"; +std::string deviceUUID = "myDeviceUUID"; +std::string firmwareVersion = "myFirmwareVersion"; +std::string hostName = "myHostName"; +std::string manufacturerName = "myManufacturerNa"; +std::string manufacturerUrl = "myManufacturerUrl"; +std::string modelNumber = "myModelNumber"; +std::string platformVersion = "myPlatformVersion"; +std::string supportUrl = "mySupportUrl"; +std::string version = "myVersion"; + +//OCDeviceInfo Contains all the device info to be stored +OCDeviceInfo deviceInfo; + +void DeleteDeviceInfo() +{ + delete deviceInfo.contentType; + delete deviceInfo.dateOfManufacture; + delete deviceInfo.deviceName; + delete deviceInfo.deviceUUID; + delete deviceInfo.firmwareVersion; + delete deviceInfo.hostName; + delete deviceInfo.manufacturerName; + delete deviceInfo.manufacturerUrl; + delete deviceInfo.modelNumber; + delete deviceInfo.platformVersion; + delete deviceInfo.supportUrl; + delete deviceInfo.version; +} + +void DuplicateString(char ** targetString, std::string sourceString) +{ + *targetString = new char[sourceString.length() + 1]; + strncpy(*targetString, sourceString.c_str(), (sourceString.length() + 1)); +} + +OCStackResult SetDeviceInfo(std::string contentType, std::string dateOfManufacture, + std::string deviceName, std::string deviceUUID, std::string firmwareVersion, + std::string hostName, std::string manufacturerName, std::string manufacturerUrl, + std::string modelNumber, std::string platformVersion, std::string supportUrl, + std::string version) +{ + if(manufacturerName.length() > MAX_MANUFACTURER_NAME_LENGTH) + { + return OC_STACK_INVALID_PARAM; + + } + + if(manufacturerUrl.length() > MAX_MANUFACTURER_URL_LENGTH) + { + return OC_STACK_INVALID_PARAM; + + } + + try + { + DuplicateString(&deviceInfo.contentType, contentType); + DuplicateString(&deviceInfo.dateOfManufacture, dateOfManufacture); + DuplicateString(&deviceInfo.deviceName, deviceName); + DuplicateString(&deviceInfo.deviceUUID, deviceUUID); + DuplicateString(&deviceInfo.firmwareVersion, firmwareVersion); + DuplicateString(&deviceInfo.hostName, hostName); + DuplicateString(&deviceInfo.manufacturerName, manufacturerName); + DuplicateString(&deviceInfo.manufacturerUrl, manufacturerUrl); + DuplicateString(&deviceInfo.modelNumber, modelNumber); + DuplicateString(&deviceInfo.platformVersion, platformVersion); + DuplicateString(&deviceInfo.supportUrl, supportUrl); + DuplicateString(&deviceInfo.version, version); + }catch(exception &e) + { + std::cout<<"String Copy failed!!\n"; + return OC_STACK_ERROR; + } + + return OC_STACK_OK; +} + + + +int main() +{ + + // Create PlatformConfig object + PlatformConfig cfg { + OC::ServiceType::InProc, + OC::ModeType::Server, + "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces + 0, // Uses randomly available port + OC::QualityOfService::LowQos + }; + + OCPlatform::Configure(cfg); + + std::cout<<"Starting server & setting device info\n"; + + OCStackResult result = SetDeviceInfo(contentType, dateOfManufacture, deviceName, + deviceUUID, firmwareVersion, hostName, manufacturerName, manufacturerUrl, + modelNumber, platformVersion, supportUrl, version); + + if(result != OC_STACK_OK) + { + std::cout << "Device Registration failed\n"; + return -1; + } + + result = OCPlatform::registerDeviceInfo(deviceInfo); + + if(result != OC_STACK_OK) + { + std::cout << "Device Registration failed\n"; + return -1; + } + + DeleteDeviceInfo(); + + // A condition variable will free the mutex it is given, then do a non- + // intensive block until 'notify' is called on it. In this case, since we + // don't ever call cv.notify, this should be a non-processor intensive version + // of while(true); + std::mutex blocker; + std::condition_variable cv; + std::unique_lock lock(blocker); + cv.wait(lock); + + // No explicit call to stop the platform. + // When OCPlatform::destructor is invoked, internally we do platform cleanup + + return 0; + +} + + + diff --git a/resource/examples/makefile b/resource/examples/makefile index c97f2aa..6347a6d 100644 --- a/resource/examples/makefile +++ b/resource/examples/makefile @@ -43,11 +43,11 @@ LIB_OC_LOGGER := ../oc_logger/lib/oc_logger.a CXX_LIBS := ../$(BUILD)/obj/liboc.a ../csdk/$(PLATFORM)/$(BUILD)/liboctbstack.a $(LIB_OC_LOGGER) # Force metatargets to build: -all.PHONY: prep_dirs oc_cpp_sdk simpleserver simpleserverHQ simpleclient simpleclientHQ simpleclientserver roomserver roomclient presenceserver presenceclient garageserver garageclient fridgeserver fridgeclient ocicuc_target threadingsample +all.PHONY: prep_dirs oc_cpp_sdk simpleserver simpleserverHQ simpleclient simpleclientHQ simpleclientserver roomserver roomclient presenceserver presenceclient garageserver garageclient fridgeserver fridgeclient ocicuc_target threadingsample devicediscoveryserver devicediscoveryclient -apps.PHONY: prep_dirs oc_cpp_sdk simpleserver simpleserverHQ simpleclient simpleclientHQ simpleclientserver roomserver roomclient presenceserver presenceclient garageserver garageclient fridgeserver fridgeclient threadingsample +apps.PHONY: prep_dirs oc_cpp_sdk simpleserver simpleserverHQ simpleclient simpleclientHQ simpleclientserver roomserver roomclient presenceserver presenceclient garageserver garageclient fridgeserver fridgeclient threadingsample devicediscoveryserver devicediscoveryclient -buildScript_all.PHONY: prep_dirs simpleserver simpleserverHQ simpleclient simpleclientHQ simpleclientserver roomserver roomclient presenceserver presenceclient garageserver garageclient fridgeserver fridgeclient threadingsample +buildScript_all.PHONY: prep_dirs simpleserver simpleserverHQ simpleclient simpleclientHQ simpleclientserver roomserver roomclient presenceserver presenceclient garageserver garageclient fridgeserver fridgeclient threadingsample devicediscoveryserver devicediscoveryclient all: all.PHONY @@ -103,6 +103,12 @@ garageclient: garageclient.cpp threadingsample: threadingsample.cpp $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ threadingsample.cpp $(CXX_INC) $(CXX_LIBS) +devicediscoveryserver: devicediscoveryserver.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ devicediscoveryserver.cpp $(CXX_INC) $(CXX_LIBS) + +devicediscoveryclient: devicediscoveryclient.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ devicediscoveryclient.cpp $(CXX_INC) $(CXX_LIBS) + ocicuc_target: cd ocicuc && $(MAKE) apps diff --git a/resource/include/IClientWrapper.h b/resource/include/IClientWrapper.h index 8ec23a5..1e40e23 100644 --- a/resource/include/IClientWrapper.h +++ b/resource/include/IClientWrapper.h @@ -44,6 +44,10 @@ namespace OC const std::string& resourceType, FindCallback& callback, QualityOfService QoS) = 0; + virtual OCStackResult ListenForDevice(const std::string& serviceUrl, + const std::string& deviceURI, FindDeviceCallback& callback, + QualityOfService QoS) = 0; + virtual OCStackResult GetResourceRepresentation(const std::string& host, const std::string& uri, const QueryParamsMap& queryParams, const HeaderOptions& headerOptions, diff --git a/resource/include/IServerWrapper.h b/resource/include/IServerWrapper.h index 10e0515..c6c0b2d 100644 --- a/resource/include/IServerWrapper.h +++ b/resource/include/IServerWrapper.h @@ -51,6 +51,9 @@ namespace OC EntityHandler& entityHandler, uint8_t resourceProperty) = 0; + virtual OCStackResult registerDeviceInfo( + const OCDeviceInfo deviceInfo) = 0; + virtual OCStackResult registerResourceWithHost( OCResourceHandle& resourceHandle, std::string& resourceHOST, diff --git a/resource/include/InProcClientWrapper.h b/resource/include/InProcClientWrapper.h index 9ca0779..ced111d 100644 --- a/resource/include/InProcClientWrapper.h +++ b/resource/include/InProcClientWrapper.h @@ -52,6 +52,12 @@ namespace OC std::weak_ptr clientWrapper; }; + struct DeviceListenContext + { + FindDeviceCallback callback; + IClientWrapper::Ptr clientWrapper; + }; + struct SubscribePresenceContext { SubscribeCallback callback; @@ -81,6 +87,10 @@ namespace OC const std::string& resourceType, FindCallback& callback, QualityOfService QoS); + virtual OCStackResult ListenForDevice(const std::string& serviceUrl, + const std::string& deviceURI, FindDeviceCallback& callback, + QualityOfService QoS); + virtual OCStackResult GetResourceRepresentation(const std::string& host, const std::string& uri, const QueryParamsMap& queryParams, const HeaderOptions& headerOptions, diff --git a/resource/include/InProcServerWrapper.h b/resource/include/InProcServerWrapper.h index aab856b..b68f599 100644 --- a/resource/include/InProcServerWrapper.h +++ b/resource/include/InProcServerWrapper.h @@ -45,6 +45,9 @@ namespace OC EntityHandler& entityHandler, uint8_t resourceProperty); + virtual OCStackResult registerDeviceInfo( + const OCDeviceInfo deviceInfo); + virtual OCStackResult registerResourceWithHost( OCResourceHandle& resourceHandle, std::string& resourceHOST, diff --git a/resource/include/OCApi.h b/resource/include/OCApi.h index f46dac0..b523da5 100755 --- a/resource/include/OCApi.h +++ b/resource/include/OCApi.h @@ -200,6 +200,8 @@ namespace OC typedef std::function)> FindCallback; + typedef std::function FindDeviceCallback; + typedef std::function)> EntityHandler; diff --git a/resource/include/OCPlatform.h b/resource/include/OCPlatform.h index 61a0f48..1cad339 100644 --- a/resource/include/OCPlatform.h +++ b/resource/include/OCPlatform.h @@ -120,6 +120,21 @@ namespace OC FindCallback resourceHandler, QualityOfService QoS); /** + * API for Device Discovery + * + * + * @param host - Host IP Address. If null or empty, Multicast is performed. + * @param resourceURI - Uri containing address to the virtual device in C Stack + ("/oc/core/d") + * @param QualityOfService the quality of communication + * + */ + OCStackResult getDeviceInfo(const std::string& host, const std::string& deviceURI, + FindDeviceCallback deviceInfoHandler); + OCStackResult getDeviceInfo(const std::string& host, const std::string& deviceURI, + FindDeviceCallback deviceInfoHandler, QualityOfService QoS); + + /** * This API registers a resource with the server * NOTE: This API applies to server side only. * @@ -167,6 +182,18 @@ namespace OC const std::shared_ptr< OCResource > resource); /** + * Register Device Info + * + * @param deviceInfo - structure containing all the device specific information + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ + + OCStackResult registerDeviceInfo(const OCDeviceInfo deviceInfo); + + /** * Set default device entity handler * * @param entityHandler - entity handler to handle requests for diff --git a/resource/include/OCPlatform_impl.h b/resource/include/OCPlatform_impl.h index 896ce3a..f25ce2e 100644 --- a/resource/include/OCPlatform_impl.h +++ b/resource/include/OCPlatform_impl.h @@ -146,6 +146,21 @@ namespace OC FindCallback resourceHandler, QualityOfService QoS); /** + * API for Device Discovery + * + * @param host - Host IP Address. If null or empty, Multicast is performed. + * @param resourceURI - Uri containing address to the virtual device in C Stack + * ("/oc/core/d") + * + * @param QualityOfService the quality of communication + * + */ + OCStackResult getDeviceInfo(const std::string& host, const std::string& deviceURI, + FindDeviceCallback deviceInfoHandler); + OCStackResult getDeviceInfo(const std::string& host, const std::string& deviceURI, + FindDeviceCallback deviceInfoHandler, QualityOfService QoS); + + /** * This API registers a resource with the server * NOTE: This API applies to server side only. * @@ -193,6 +208,17 @@ namespace OC const std::shared_ptr resource); /** + * This API registers all the device specific information + * + * @param OCDeviceInfo - Structure containing all the device related information + * + * @return OCStackResult return value of the API. Returns OC_STACK_OK if success + * + * Note: OCDeviceInfo is defined in OCStack.h + */ + OCStackResult registerDeviceInfo(const OCDeviceInfo deviceInfo); + + /** * Set default device entity handler * * @param entityHandler - entity handler to handle requests for diff --git a/resource/include/OutOfProcClientWrapper.h b/resource/include/OutOfProcClientWrapper.h index dfae653..049c445 100644 --- a/resource/include/OutOfProcClientWrapper.h +++ b/resource/include/OutOfProcClientWrapper.h @@ -36,6 +36,11 @@ namespace OC const std::string& resourceType, FindCallback& callback, QualityOfService QoS) {return OC_STACK_NOTIMPL;} + virtual OCStackResult ListenForDevice(const std::string& serviceUrl, + const std::string& deviceURI, FindDeviceCallback& callback, + QualityOfService QoS) + {return OC_STACK_NOTIMPL;} + virtual OCStackResult GetResourceRepresentation(const std::string& host, const std::string& uri, const QueryParamsMap& queryParams, const HeaderOptions& headerOptions, GetCallback& callback, diff --git a/resource/include/OutOfProcServerWrapper.h b/resource/include/OutOfProcServerWrapper.h index be51f3d..91c6f15 100644 --- a/resource/include/OutOfProcServerWrapper.h +++ b/resource/include/OutOfProcServerWrapper.h @@ -43,6 +43,14 @@ namespace OC // Not implemented return OC_STACK_NOTIMPL; } + + virtual OCStackResult registerDeviceInfo( + const OCDeviceInfo deviceInfo) + { + // Not implemented + return OC_STACK_NOTIMPL; + } + virtual OCStackResult registerResourceWithHost( OCResourceHandle& resourceHandle, std::string& resourceHOST, diff --git a/resource/src/InProcClientWrapper.cpp b/resource/src/InProcClientWrapper.cpp index e9580b2..83e4ef8 100644 --- a/resource/src/InProcClientWrapper.cpp +++ b/resource/src/InProcClientWrapper.cpp @@ -92,6 +92,33 @@ namespace OC } } + OCRepresentation parseGetSetCallback(OCClientResponse* clientResponse) + { + if(clientResponse->resJSONPayload == nullptr || clientResponse->resJSONPayload[0] == '\0') + { + throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_ERROR); + } + + MessageContainer oc; + oc.setJSONRepresentation(clientResponse->resJSONPayload); + + std::vector::const_iterator it = oc.representations().begin(); + if(it == oc.representations().end()) + { + throw OCException(OC::Exception::INVALID_REPRESENTATION, OC_STACK_ERROR); + } + + // first one is considered the root, everything else is considered a child of this one. + OCRepresentation root = *it; + ++it; + + std::for_each(it, oc.representations().end(), + [&root](const OCRepresentation& repItr) + {root.addChild(repItr);}); + return root; + + } + OCStackApplicationResult listenCallback(void* ctx, OCDoHandle handle, OCClientResponse* clientResponse) { @@ -143,7 +170,6 @@ namespace OC } return OC_STACK_KEEP_TRANSACTION; - } OCStackResult InProcClientWrapper::ListenForResource(const std::string& serviceUrl, @@ -181,31 +207,52 @@ namespace OC return result; } - OCRepresentation parseGetSetCallback(OCClientResponse* clientResponse) + OCStackApplicationResult listenDeviceCallback(void* ctx, OCDoHandle handle, + OCClientResponse* clientResponse) { - if(clientResponse->resJSONPayload == nullptr || clientResponse->resJSONPayload[0] == '\0') - { - return OCRepresentation(); - } + ClientCallbackContext::DeviceListenContext* context = + static_cast(ctx); - MessageContainer oc; - oc.setJSONRepresentation(clientResponse->resJSONPayload); + OCRepresentation rep = parseGetSetCallback(clientResponse); + std::thread exec(context->callback, rep); + exec.detach(); - std::vector::const_iterator it = oc.representations().begin(); - if(it == oc.representations().end()) - { - return OCRepresentation(); - } + return OC_STACK_KEEP_TRANSACTION; + } - // first one is considered the root, everything else is considered a child of this one. - OCRepresentation root = *it; - ++it; + OCStackResult InProcClientWrapper::ListenForDevice(const std::string& serviceUrl, + const std::string& deviceURI, FindDeviceCallback& callback, QualityOfService QoS) + { + OCStackResult result; - std::for_each(it, oc.representations().end(), - [&root](const OCRepresentation& repItr) - {root.addChild(repItr);}); - return root; + OCCallbackData cbdata = {0}; + ClientCallbackContext::DeviceListenContext* context = + new ClientCallbackContext::DeviceListenContext(); + context->callback = callback; + context->clientWrapper = shared_from_this(); + + cbdata.context = static_cast(context); + cbdata.cb = listenDeviceCallback; + cbdata.cd = [](void* c){delete static_cast(c);}; + + auto cLock = m_csdkLock.lock(); + if(cLock) + { + std::lock_guard lock(*cLock); + OCDoHandle handle; + result = OCDoResource(&handle, OC_REST_GET, + deviceURI.c_str(), + nullptr, nullptr, + static_cast(QoS), + &cbdata, + NULL, 0); + } + else + { + result = OC_STACK_ERROR; + } + return result; } void parseServerHeaderOptions(OCClientResponse* clientResponse, diff --git a/resource/src/InProcServerWrapper.cpp b/resource/src/InProcServerWrapper.cpp index 9dbaa27..0159bb8 100755 --- a/resource/src/InProcServerWrapper.cpp +++ b/resource/src/InProcServerWrapper.cpp @@ -271,6 +271,18 @@ namespace OC } } + OCStackResult InProcServerWrapper::registerDeviceInfo(const OCDeviceInfo deviceInfo) + { + auto cLock = m_csdkLock.lock(); + OCStackResult result = OC_STACK_ERROR; + if(cLock) + { + std::lock_guard lock(*cLock); + result = OCSetDeviceInfo(deviceInfo); + } + return result; + } + OCStackResult InProcServerWrapper::registerResource( OCResourceHandle& resourceHandle, std::string& resourceURI, diff --git a/resource/src/OCPlatform.cpp b/resource/src/OCPlatform.cpp index f26ffc7..9a17833 100644 --- a/resource/src/OCPlatform.cpp +++ b/resource/src/OCPlatform.cpp @@ -95,6 +95,22 @@ namespace OC resourceHandler, QoS); } + OCStackResult getDeviceInfo(const std::string& host, + const std::string& deviceURI, + FindDeviceCallback deviceInfoHandler) + { + return OCPlatform_impl::Instance().getDeviceInfo(host, deviceURI, deviceInfoHandler); + } + + OCStackResult getDeviceInfo(const std::string& host, + const std::string& deviceURI, + FindDeviceCallback deviceInfoHandler, + QualityOfService QoS) + { + return OCPlatform_impl::Instance().getDeviceInfo(host, deviceURI, + deviceInfoHandler, QoS); + } + OCStackResult registerResource(OCResourceHandle& resourceHandle, std::string& resourceURI, @@ -114,6 +130,11 @@ namespace OC return OCPlatform_impl::Instance().registerResource(resourceHandle, resource); } + OCStackResult registerDeviceInfo(const OCDeviceInfo deviceInfo) + { + return OCPlatform_impl::Instance().registerDeviceInfo(deviceInfo); + } + OCStackResult unregisterResource(const OCResourceHandle& resourceHandle) { return OCPlatform_impl::Instance().unregisterResource(resourceHandle); diff --git a/resource/src/OCPlatform_impl.cpp b/resource/src/OCPlatform_impl.cpp index e680943..9d9ae52 100755 --- a/resource/src/OCPlatform_impl.cpp +++ b/resource/src/OCPlatform_impl.cpp @@ -172,6 +172,21 @@ namespace OC host, resourceName, resourceHandler, QoS); } + OCStackResult OCPlatform_impl::getDeviceInfo(const std::string& host, + const std::string& deviceURI, + FindDeviceCallback deviceInfoHandler) + { + return result_guard(getDeviceInfo(host, deviceURI, deviceInfoHandler, m_cfg.QoS)); + } + + OCStackResult OCPlatform_impl::getDeviceInfo(const std::string& host, + const std::string& deviceURI, + FindDeviceCallback deviceInfoHandler, + QualityOfService QoS) + { + return checked_guard(m_client, &IClientWrapper::ListenForDevice, + host, deviceURI, deviceInfoHandler, QoS); + } OCStackResult OCPlatform_impl::registerResource(OCResourceHandle& resourceHandle, std::string& resourceURI, @@ -185,8 +200,12 @@ namespace OC resourceInterface, entityHandler, resourceProperty); } + OCStackResult OCPlatform_impl::registerDeviceInfo(const OCDeviceInfo deviceInfo) + { + return checked_guard(m_server, &IServerWrapper::registerDeviceInfo, deviceInfo); + } - OCStackResult OCPlatform_impl::registerResource(OCResourceHandle& resourceHandle, + OCStackResult OCPlatform_impl::registerResource(OCResourceHandle& resourceHandle, const std::shared_ptr< OCResource > resource) { uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE; @@ -195,8 +214,8 @@ namespace OC return checked_guard(m_server, &IServerWrapper::registerResourceWithHost, ref(resourceHandle), resource->host(), resource->uri(), resourceTypes[0]/*"core.remote"*/, "oc.mi.def", (EntityHandler) nullptr, resourceProperty); - } + OCStackResult OCPlatform_impl::unregisterResource(const OCResourceHandle& resourceHandle) const { return checked_guard(m_server, &IServerWrapper::unregisterResource, -- 2.7.4