From 00380c6e4145bf0f084b235bc153c9617093efe5 Mon Sep 17 00:00:00 2001 From: Phil Coval Date: Thu, 16 Jun 2016 10:25:44 +0200 Subject: [PATCH] ocpayload: Supports multiple data model versions (DMV) using CSV DMV can be CVS if multiple values are supplied. OIC 1.1 has a single value but future spec is expected to have multiple values For more details about this specification please refer to: 20160531-OIC_Core_Specification_v1.1.0_r0.13.docx Section 11.3.4, Table 18 for property description & Section D.3.4 for RAML definition. For now it's supporting simple patterns like "one-1,two-2" In the longer term a full implementation of rfc4180 might be desired. Internally those items are stored in OCStringLL (linked list of strings), and later it would make sense to relocate those helper functions in a common place. This change has been tested on Tizen:3.0:IVI Bug: https://jira.iotivity.org/browse/IOT-1101 Change-Id: I7274d74ba525aedda49b78398743aa24a7999c00 Signed-off-by: Phil Coval Reviewed-on: https://gerrit.iotivity.org/gerrit/8707 Tested-by: jenkins-iotivity Reviewed-by: Uze Choi Reviewed-by: Ziran Sun Reviewed-by: Dwarkaprasad Dayama --- plugins/samples/linux/IotivityandZigbeeServer.c | 4 +- resource/csdk/stack/include/ocpayload.h | 17 +++++ resource/csdk/stack/include/octypes.h | 6 +- resource/csdk/stack/include/payload_logging.h | 9 ++- .../samples/linux/SimpleClientServer/ocserver.cpp | 13 ++-- .../samples/tizen/SimpleClientServer/ocserver.cpp | 13 ++-- .../samples/tizen/build/packaging/com.oic.ri.spec | 1 + resource/csdk/stack/src/ocpayload.c | 87 +++++++++++++++++++++- resource/csdk/stack/src/ocpayloadconvert.c | 14 +++- resource/csdk/stack/src/ocpayloadparse.c | 12 ++- resource/csdk/stack/src/ocresource.c | 36 ++++++--- resource/examples/devicediscoveryserver.cpp | 12 +-- resource/include/OCRepresentation.h | 5 ++ resource/src/OCRepresentation.cpp | 20 ++++- resource/unittests/OCPlatformTest.cpp | 5 +- .../unittests/OCRepresentationEncodingTest.cpp | 13 +++- 16 files changed, 214 insertions(+), 53 deletions(-) diff --git a/plugins/samples/linux/IotivityandZigbeeServer.c b/plugins/samples/linux/IotivityandZigbeeServer.c index df8db7e..8caa729 100644 --- a/plugins/samples/linux/IotivityandZigbeeServer.c +++ b/plugins/samples/linux/IotivityandZigbeeServer.c @@ -140,8 +140,10 @@ OCStackResult SetDeviceInfo() { .deviceName = "IoTivity/Zigbee Server Sample", .specVersion = "IoTivity/Zigbee Device Spec Version", - .dataModelVersion = "IoTivity/Zigbee Data Model Version", }; + char *dmv = OICStrdup("IoTivity/Zigbee Data Model Version"); + deviceInfo.dataModelVersions = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL)); + deviceInfo.dataModelVersions->value = dmv; char *dup = OICStrdup("oic.wk.d"); deviceInfo.types = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL)); deviceInfo.types->value = dup; diff --git a/resource/csdk/stack/include/ocpayload.h b/resource/csdk/stack/include/ocpayload.h index 7e4ed99..992adc8 100644 --- a/resource/csdk/stack/include/ocpayload.h +++ b/resource/csdk/stack/include/ocpayload.h @@ -75,6 +75,7 @@ bool OCRepPayloadSetUri(OCRepPayload* payload, const char* uri); bool OCRepPayloadAddResourceType(OCRepPayload* payload, const char* resourceType); bool OCRepPayloadAddInterface(OCRepPayload* payload, const char* interface); +bool OCRepPayloadAddModelVersion(OCRepPayload* payload, const char* dmv); bool OCRepPayloadAddResourceTypeAsOwner(OCRepPayload* payload, char* resourceType); bool OCRepPayloadAddInterfaceAsOwner(OCRepPayload* payload, char* interface); @@ -258,6 +259,22 @@ void OCPresencePayloadDestroy(OCPresencePayload* payload); OCStringLL* CloneOCStringLL (OCStringLL* ll); void OCFreeOCStringLL(OCStringLL* ll); +/** + * This function creates a list from a string (with separated contents if several) + * @param text single string or CSV text fields + * @return newly allocated linked list + * @note separator is ',' (according to rfc4180) or ';' + **/ +OCStringLL* OCCreateOCStringLL(const char* text); + +/** + * This function creates a string from a list (with separated contents if several) + * @param ll Pointer to list + * @return newly allocated string + * @note separator is ',' (according to rfc4180) + **/ +char* OCCreateString(const OCStringLL* ll); + #ifdef __cplusplus } #endif diff --git a/resource/csdk/stack/include/octypes.h b/resource/csdk/stack/include/octypes.h index e96a648..96b8177 100644 --- a/resource/csdk/stack/include/octypes.h +++ b/resource/csdk/stack/include/octypes.h @@ -949,8 +949,8 @@ typedef struct OCStringLL *types; /** Pointer to the device specification version.*/ char *specVersion; - /** Pointer to the device data model version.*/ - char *dataModelVersion; + /** Pointer to the device data model versions (in CSV format).*/ + OCStringLL *dataModelVersions; } OCDeviceInfo; #ifdef RA_ADAPTER @@ -1239,7 +1239,7 @@ typedef struct char *sid; char* deviceName; char* specVersion; - char* dataModelVersion; + OCStringLL *dataModelVersions; OCStringLL *interfaces; OCStringLL *types; } OCDevicePayload; diff --git a/resource/csdk/stack/include/payload_logging.h b/resource/csdk/stack/include/payload_logging.h index c518be6..14ca4b0 100644 --- a/resource/csdk/stack/include/payload_logging.h +++ b/resource/csdk/stack/include/payload_logging.h @@ -236,7 +236,14 @@ static inline void OCPayloadLogDevice(LogLevel level, OCDevicePayload* payload) OIC_LOG_V(level, PL_TAG, "\tSID:%s", payload->sid); OIC_LOG_V(level, PL_TAG, "\tDevice Name:%s", payload->deviceName); OIC_LOG_V(level, PL_TAG, "\tSpec Version:%s", payload->specVersion); - OIC_LOG_V(level, PL_TAG, "\tData Model Version:%s", payload->dataModelVersion); + if (payload->dataModelVersions) + { + OIC_LOG(level, PL_TAG, "\tData Model Version:"); + for (OCStringLL *strll = payload->dataModelVersions; strll; strll = strll->next) + { + OIC_LOG_V(level, PL_TAG, "\t\t%s", strll->value); + } + } if (payload->types) { OIC_LOG(level, PL_TAG, "\tResource Type:"); diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp index abf908d..9a02020 100644 --- a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp @@ -27,6 +27,7 @@ #include #include #include +#include "oic_malloc.h" #include "ocstack.h" #include "logger.h" #include "ocpayload.h" @@ -75,7 +76,7 @@ const char *supportUrl = "mySupportUrl"; const char *version = "myVersion"; const char *systemTime = "2015-05-15T11.04"; const char *specVersion = "myDeviceSpecVersion"; -const char* dataModelVersion = "myDeviceModelVersion"; +const char *dataModelVersions = "myDeviceModelVersions"; // Entity handler should check for resourceTypeName and ResourceInterface in order to GET // the existence of a known resource @@ -817,7 +818,7 @@ void DeleteDeviceInfo() { free (deviceInfo.deviceName); free (deviceInfo.specVersion); - free (deviceInfo.dataModelVersion); + OCFreeOCStringLL (deviceInfo.dataModelVersions); } bool DuplicateString(char** targetString, const char* sourceString) @@ -921,7 +922,7 @@ OCStackResult SetPlatformInfo(const char* platformID, const char *manufacturerNa return OC_STACK_ERROR; } -OCStackResult SetDeviceInfo(const char* deviceName, const char* specVersion, const char* dataModelVersion) +OCStackResult SetDeviceInfo(const char* deviceName, const char* specVersion, const char* dataModelVersions) { if(!DuplicateString(&deviceInfo.deviceName, deviceName)) { @@ -931,7 +932,9 @@ OCStackResult SetDeviceInfo(const char* deviceName, const char* specVersion, con { return OC_STACK_ERROR; } - if(!DuplicateString(&deviceInfo.dataModelVersion, dataModelVersion)) + OCFreeOCStringLL(deviceInfo.dataModelVersions); + deviceInfo.dataModelVersions = OCCreateOCStringLL(dataModelVersions); + if (!deviceInfo.dataModelVersions) { return OC_STACK_ERROR; } @@ -1055,7 +1058,7 @@ int main(int argc, char* argv[]) exit (EXIT_FAILURE); } - registrationResult = SetDeviceInfo(deviceName, specVersion, dataModelVersion); + registrationResult = SetDeviceInfo(deviceName, specVersion, dataModelVersions); if (registrationResult != OC_STACK_OK) { diff --git a/resource/csdk/stack/samples/tizen/SimpleClientServer/ocserver.cpp b/resource/csdk/stack/samples/tizen/SimpleClientServer/ocserver.cpp index efac31e..b5fc0ca 100644 --- a/resource/csdk/stack/samples/tizen/SimpleClientServer/ocserver.cpp +++ b/resource/csdk/stack/samples/tizen/SimpleClientServer/ocserver.cpp @@ -29,6 +29,7 @@ #include #include #include +#include "oic_malloc.h" #include "ocstack.h" #include "logger.h" #include "ocpayload.h" @@ -77,7 +78,7 @@ const char *supportUrl = "mySupportUrl"; const char *version = "myVersion"; const char *systemTime = "2015-05-15T11.04"; const char *specVersion = "myDeviceSpecVersion"; -const char* dataModelVersion = "myDeviceModelVersion"; +const char *dataModelVersions = "myDeviceModelVersions"; // Entity handler should check for resourceTypeName and ResourceInterface in order to GET // the existence of a known resource @@ -810,7 +811,7 @@ void DeleteDeviceInfo() { free (deviceInfo.deviceName); free (deviceInfo.specVersion); - free (deviceInfo.dataModelVersion); + OCFreeOCStringLL (deviceInfo.dataModelVersions); } bool DuplicateString(char** targetString, const char* sourceString) @@ -914,7 +915,7 @@ OCStackResult SetPlatformInfo(const char* platformID, const char *manufacturerNa return OC_STACK_ERROR; } -OCStackResult SetDeviceInfo(const char* deviceName, const char* specVersion, const char* dataModelVersion) +OCStackResult SetDeviceInfo(const char* deviceName, const char* specVersion, const char* dataModelVersions) { if(!DuplicateString(&deviceInfo.deviceName, deviceName)) { @@ -924,7 +925,9 @@ OCStackResult SetDeviceInfo(const char* deviceName, const char* specVersion, con { return OC_STACK_ERROR; } - if(!DuplicateString(&deviceInfo.dataModelVersion, dataModelVersion)) + OCFreeOCStringLL(deviceInfo.dataModelVersions); + deviceInfo.dataModelVersions = OCCreateOCStringLL(dataModelVersions); + if (!deviceInfo.dataModelVersions) { return OC_STACK_ERROR; } @@ -1029,7 +1032,7 @@ int main(int argc, char* argv[]) exit (EXIT_FAILURE); } - registrationResult = SetDeviceInfo(deviceName, specVersion, dataModelVersion); + registrationResult = SetDeviceInfo(deviceName, specVersion, dataModelVersions); if (registrationResult != OC_STACK_OK) { diff --git a/resource/csdk/stack/samples/tizen/build/packaging/com.oic.ri.spec b/resource/csdk/stack/samples/tizen/build/packaging/com.oic.ri.spec index 7e559c1..5ec325e 100644 --- a/resource/csdk/stack/samples/tizen/build/packaging/com.oic.ri.spec +++ b/resource/csdk/stack/samples/tizen/build/packaging/com.oic.ri.spec @@ -66,6 +66,7 @@ cp resource/oc_logger/include/targets/oc_ostream_logger.h %{DEST_INC_DIR} cp resource/csdk/stack/include/ocpresence.h %{DEST_INC_DIR} cp resource/csdk/stack/include/ocpayload.h %{DEST_INC_DIR} cp resource/c_common/platform_features.h %{DEST_INC_DIR} +cp resource/c_common/*/include/*.h %{DEST_INC_DIR} cp resource/csdk/stack/include/payload_logging.h %{DEST_INC_DIR} cp resource/csdk/stack/include/rdpayload.h %{DEST_INC_DIR} cp extlibs/tinycbor/tinycbor/src/cbor.h %{DEST_INC_DIR} diff --git a/resource/csdk/stack/src/ocpayload.c b/resource/csdk/stack/src/ocpayload.c index da35c63..eef8c3e 100644 --- a/resource/csdk/stack/src/ocpayload.c +++ b/resource/csdk/stack/src/ocpayload.c @@ -18,7 +18,10 @@ // //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// Required for strok_r +#define _POSIX_C_SOURCE 200112L +#include #include "ocpayload.h" #include "octypes.h" #include @@ -30,6 +33,8 @@ #include "rdpayload.h" #define TAG "OIC_RI_PAYLOAD" +#define CSV_SEPARATOR ',' +#define CSV_SEPARATORS ",;" static void OCFreeRepPayloadValueContents(OCRepPayloadValue* val); @@ -1281,6 +1286,82 @@ OCStringLL* CloneOCStringLL (OCStringLL* ll) return headOfClone; } +OCStringLL* OCCreateOCStringLL(const char* text) +{ + char *token = NULL; + char *head = NULL; + char *tail = NULL; + char *backup = NULL; + OCStringLL* result = NULL; + OCStringLL* iter = NULL; + OCStringLL* prev = NULL; + + VERIFY_PARAM_NON_NULL(TAG, text, "Invalid parameter"); + backup = OICStrdup(text); + VERIFY_PARAM_NON_NULL(TAG, backup, "Failed allocating memory"); + for (head = backup; ; head = NULL) + { + token = (char *) strtok_r(head, CSV_SEPARATORS, &tail); + if (!token) break; + iter = (OCStringLL *)OICCalloc(1,sizeof(OCStringLL)); + VERIFY_PARAM_NON_NULL(TAG, iter, "Failed allocating memory"); + if (!result) + { + result = iter; + } + else + { + prev->next = iter; + } + iter->value = OICStrdup(token); + VERIFY_PARAM_NON_NULL(TAG, iter->value, "Failed allocating memory"); + prev = iter; + iter = iter->next; + } + OICFree(backup); + return result; + +exit: + OICFree(backup); + OCFreeOCStringLL(result); + return NULL; +} + +char* OCCreateString(const OCStringLL* ll) +{ + char *str = NULL; + char *pos = NULL; + size_t len = 0; + size_t sublen = 0; + int count = 0; + + if (!ll) return NULL; + + for (const OCStringLL *it = ll; it ; it = it->next ) + { + len += strlen(it->value) + 1; + } + str = (char*) malloc(len + 1); + if (!str) + return NULL; + + pos = str; + for (const OCStringLL *it = ll; it ; it = it->next ) + { + sublen = strlen(it->value) + 1; + count = snprintf(pos, len + 1, "%s%c", it->value, CSV_SEPARATOR); + if (countdataModelVersion = OICStrdup(dmVer); - if (dmVer && !payload->dataModelVersion) + payload->dataModelVersions = OCCreateOCStringLL(dmVer); + if (!payload->dataModelVersions || (dmVer && !payload->dataModelVersions->value)) { goto exit; } @@ -1659,7 +1740,7 @@ void OCDevicePayloadDestroy(OCDevicePayload* payload) OICFree(payload->sid); OICFree(payload->deviceName); OICFree(payload->specVersion); - OICFree(payload->dataModelVersion); + OCFreeOCStringLL(payload->dataModelVersions); OCFreeOCStringLL(payload->types); OCFreeOCStringLL(payload->interfaces); OICFree(payload); diff --git a/resource/csdk/stack/src/ocpayloadconvert.c b/resource/csdk/stack/src/ocpayloadconvert.c index bcaa283..5ee09cc 100644 --- a/resource/csdk/stack/src/ocpayloadconvert.c +++ b/resource/csdk/stack/src/ocpayloadconvert.c @@ -425,10 +425,16 @@ static int64_t OCConvertDevicePayload(OCDevicePayload *payload, uint8_t *outPayl sizeof(OC_RSRVD_SPEC_VERSION) - 1, payload->specVersion); VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding data spec version"); - // Device data Model Version - err |= ConditionalAddTextStringToMap(&repMap, OC_RSRVD_DATA_MODEL_VERSION, - sizeof(OC_RSRVD_DATA_MODEL_VERSION) - 1, payload->dataModelVersion); - VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding data model version"); + // Device data Model Versions + if (payload->dataModelVersions) + { + OIC_LOG(INFO, TAG, "Payload has data models versions"); + char *str = OCCreateString(payload->dataModelVersions); + err |= ConditionalAddTextStringToMap(&repMap, OC_RSRVD_DATA_MODEL_VERSION, + sizeof(OC_RSRVD_DATA_MODEL_VERSION) - 1, str); + OICFree(str); + VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding data model version"); + } err |= cbor_encoder_close_container(&encoder, &repMap); VERIFY_CBOR_SUCCESS(TAG, err, "Failed closing device map"); diff --git a/resource/csdk/stack/src/ocpayloadparse.c b/resource/csdk/stack/src/ocpayloadparse.c index 8b684a6..ea2d484 100755 --- a/resource/csdk/stack/src/ocpayloadparse.c +++ b/resource/csdk/stack/src/ocpayloadparse.c @@ -444,13 +444,17 @@ static OCStackResult OCParseDevicePayload(OCPayload **outPayload, CborValue *roo err = cbor_value_dup_text_string(&curVal, &out->specVersion, &len, NULL); VERIFY_CBOR_SUCCESS(TAG, err, "to find spec version in device payload"); } - // Data Model Version + // Data Model Versions err = cbor_value_map_find_value(rootValue, OC_RSRVD_DATA_MODEL_VERSION, &curVal); - VERIFY_CBOR_SUCCESS(TAG, err, "to find data model ver tag"); + VERIFY_CBOR_SUCCESS(TAG, err, "to find data model versions tag"); if (cbor_value_is_valid(&curVal)) { - err = cbor_value_dup_text_string(&curVal, &out->dataModelVersion, &len, NULL); - VERIFY_CBOR_SUCCESS(TAG, err, "to find data model version in device payload"); + size_t len = 0; + char * str = NULL; + err = cbor_value_dup_text_string(&curVal, &str, &len, NULL); + VERIFY_CBOR_SUCCESS(TAG, err, "to find data model versions in device payload"); + out->dataModelVersions = OCCreateOCStringLL(str); + OICFree(str); } err = cbor_value_advance(rootValue); VERIFY_CBOR_SUCCESS(TAG, err, "to advance device payload"); diff --git a/resource/csdk/stack/src/ocresource.c b/resource/csdk/stack/src/ocresource.c index 469ee2c..c51ac9e 100755 --- a/resource/csdk/stack/src/ocresource.c +++ b/resource/csdk/stack/src/ocresource.c @@ -864,15 +864,24 @@ static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource } else { - payload = (OCPayload*) OCDevicePayloadCreate(deviceId, savedDeviceInfo.deviceName, - savedDeviceInfo.types, savedDeviceInfo.specVersion, savedDeviceInfo.dataModelVersion); - if (!payload) + char *dataModelVersions = OCCreateString(savedDeviceInfo.dataModelVersions); + if (!dataModelVersions) { discoveryResult = OC_STACK_NO_MEMORY; } else { - discoveryResult = OC_STACK_OK; + payload = (OCPayload*) OCDevicePayloadCreate(deviceId, savedDeviceInfo.deviceName, + savedDeviceInfo.types, savedDeviceInfo.specVersion, dataModelVersions); + if (!payload) + { + discoveryResult = OC_STACK_NO_MEMORY; + } + else + { + discoveryResult = OC_STACK_OK; + } + OICFree(dataModelVersions); } } } @@ -1341,10 +1350,10 @@ void DeleteDeviceInfo() OICFree(savedDeviceInfo.deviceName); OCFreeOCStringLL(savedDeviceInfo.types); OICFree(savedDeviceInfo.specVersion); - OICFree(savedDeviceInfo.dataModelVersion); + OCFreeOCStringLL(savedDeviceInfo.dataModelVersions); savedDeviceInfo.deviceName = NULL; savedDeviceInfo.specVersion = NULL; - savedDeviceInfo.dataModelVersion = NULL; + savedDeviceInfo.dataModelVersions = NULL; } static OCStackResult DeepCopyDeviceInfo(OCDeviceInfo info) @@ -1386,10 +1395,10 @@ static OCStackResult DeepCopyDeviceInfo(OCDeviceInfo info) } } - if (info.dataModelVersion) + if (info.dataModelVersions) { - savedDeviceInfo.dataModelVersion = OICStrdup(info.dataModelVersion); - if(!savedDeviceInfo.dataModelVersion && info.dataModelVersion) + savedDeviceInfo.dataModelVersions = CloneOCStringLL(info.dataModelVersions); + if(!savedDeviceInfo.dataModelVersions && info.dataModelVersions) { DeleteDeviceInfo(); return OC_STACK_NO_MEMORY; @@ -1397,8 +1406,13 @@ static OCStackResult DeepCopyDeviceInfo(OCDeviceInfo info) } else { - savedDeviceInfo.dataModelVersion = OICStrdup(OC_DATA_MODEL_VERSION); - if(!savedDeviceInfo.dataModelVersion && OC_DATA_MODEL_VERSION) + savedDeviceInfo.dataModelVersions = (OCStringLL *)OICCalloc(1,sizeof(OCStringLL)); + if (!savedDeviceInfo.dataModelVersions) + { + return OC_STACK_NO_MEMORY; + } + savedDeviceInfo.dataModelVersions->value = OICStrdup(OC_DATA_MODEL_VERSION); + if(!savedDeviceInfo.dataModelVersions->value && OC_DATA_MODEL_VERSION) { DeleteDeviceInfo(); return OC_STACK_NO_MEMORY; diff --git a/resource/examples/devicediscoveryserver.cpp b/resource/examples/devicediscoveryserver.cpp index e97a8bf..dba1515 100644 --- a/resource/examples/devicediscoveryserver.cpp +++ b/resource/examples/devicediscoveryserver.cpp @@ -49,7 +49,7 @@ std::string systemTime = "mySystemTime"; //Set of strings for each of device info fields std::string deviceName = "Bill's Battlestar"; std::string specVersion = "myDeviceSpecVersion"; -std::string dataModelVersion = "myDeviceModelVersion"; +std::string dataModelVersions = "myDeviceModelVersion"; //OCPlatformInfo Contains all the platform info to be stored OCPlatformInfo platformInfo; @@ -77,7 +77,7 @@ void DeleteDeviceInfo() { delete[] deviceInfo.deviceName; delete[] deviceInfo.specVersion; - delete[] deviceInfo.dataModelVersion; + OCFreeOCStringLL(deviceInfo.dataModelVersions); } void DuplicateString(char ** targetString, std::string sourceString) @@ -106,15 +106,15 @@ OCStackResult SetPlatformInfo(std::string platformID, std::string manufacturerNa } -OCStackResult SetDeviceInfo(std::string deviceName, std::string specVersion, std::string dataModelVersion) +OCStackResult SetDeviceInfo(std::string deviceName, std::string specVersion, std::string dataModelVersions) { DuplicateString(&deviceInfo.deviceName, deviceName); if (!specVersion.empty()) DuplicateString(&deviceInfo.specVersion, specVersion); - if (!dataModelVersion.empty()) - DuplicateString(&deviceInfo.dataModelVersion, dataModelVersion); + if (!dataModelVersions.empty()) + OCResourcePayloadAddStringLL(&deviceInfo.dataModelVersions, dataModelVersions.c_str()); return OC_STACK_OK; } @@ -148,7 +148,7 @@ int main() } - result = SetDeviceInfo(deviceName, specVersion, dataModelVersion); + result = SetDeviceInfo(deviceName, specVersion, dataModelVersions); OCResourcePayloadAddStringLL(&deviceInfo.types, "oic.wk.d"); OCResourcePayloadAddStringLL(&deviceInfo.types, "oic.d.tv"); diff --git a/resource/include/OCRepresentation.h b/resource/include/OCRepresentation.h index 4a18fe7..e66719b 100644 --- a/resource/include/OCRepresentation.h +++ b/resource/include/OCRepresentation.h @@ -131,6 +131,8 @@ namespace OC const std::vector& getResourceTypes() const; + const std::vector& getDataModelVersions() const; + void setResourceTypes(const std::vector& resourceTypes); void addResourceType(const std::string& str); @@ -141,6 +143,8 @@ namespace OC void addResourceInterface(const std::string& str); + void addDataModelVersion(const std::string& str); + bool emptyData() const; int numberOfAttributes() const; @@ -456,6 +460,7 @@ namespace OC mutable std::map m_values; std::vector m_resourceTypes; std::vector m_interfaces; + std::vector m_dataModelVersions; InterfaceType m_interfaceType; }; diff --git a/resource/src/OCRepresentation.cpp b/resource/src/OCRepresentation.cpp index f0e8dca..68a14fc 100644 --- a/resource/src/OCRepresentation.cpp +++ b/resource/src/OCRepresentation.cpp @@ -82,9 +82,10 @@ namespace OC rep[OC_RSRVD_SPEC_VERSION] = payload->specVersion ? std::string(payload->specVersion) : std::string(); - rep[OC_RSRVD_DATA_MODEL_VERSION] = payload->dataModelVersion ? - std::string(payload->dataModelVersion) : - std::string(); + for (OCStringLL *strll = payload->dataModelVersions; strll; strll = strll->next) + { + rep.addDataModelVersion(strll->value); + } for (OCStringLL *strll = payload->types; strll; strll = strll->next) { rep.addResourceType(strll->value); @@ -755,6 +756,16 @@ namespace OC m_interfaces = resourceInterfaces; } + const std::vector& OCRepresentation::getDataModelVersions() const + { + return m_dataModelVersions; + } + + void OCRepresentation::addDataModelVersion(const std::string& str) + { + m_dataModelVersions.push_back(str); + } + bool OCRepresentation::hasAttribute(const std::string& str) const { return m_values.find(str) != m_values.end(); @@ -775,7 +786,8 @@ namespace OC else if ((m_interfaceType == InterfaceType::None || m_interfaceType==InterfaceType::DefaultChild || m_interfaceType==InterfaceType::LinkChild) - && (m_resourceTypes.size()>0 || m_interfaces.size()>0)) + && (m_resourceTypes.size()>0 || m_interfaces.size()>0 + || m_dataModelVersions.size()>0)) { return false; } diff --git a/resource/unittests/OCPlatformTest.cpp b/resource/unittests/OCPlatformTest.cpp index 9855686..d5aad2e 100644 --- a/resource/unittests/OCPlatformTest.cpp +++ b/resource/unittests/OCPlatformTest.cpp @@ -88,7 +88,7 @@ namespace OCPlatformTest delete[] deviceInfo.deviceName; DeleteStringLL(deviceInfo.types); delete[] deviceInfo.specVersion; - delete[] deviceInfo.dataModelVersion; + DeleteStringLL(deviceInfo.dataModelVersions); } void DuplicateString(char ** targetString, std::string sourceString) @@ -750,7 +750,8 @@ namespace OCPlatformTest OCResourcePayloadAddStringLL(&deviceInfo.types, "oic.wk.d"); OCResourcePayloadAddStringLL(&deviceInfo.types, "oic.d.tv"); DuplicateString(&deviceInfo.specVersion, "mySpecVersion"); - DuplicateString(&deviceInfo.dataModelVersion, "myDataModelVersion"); + deviceInfo.dataModelVersions = nullptr; + OCResourcePayloadAddStringLL(&deviceInfo.dataModelVersions, "myDataModelVersions"); EXPECT_EQ(OC_STACK_OK, OCPlatform::registerDeviceInfo(deviceInfo)); EXPECT_NO_THROW(DeleteDeviceInfo(deviceInfo)); } diff --git a/resource/unittests/OCRepresentationEncodingTest.cpp b/resource/unittests/OCRepresentationEncodingTest.cpp index 6e41e8f..00a7c06 100644 --- a/resource/unittests/OCRepresentationEncodingTest.cpp +++ b/resource/unittests/OCRepresentationEncodingTest.cpp @@ -52,7 +52,7 @@ namespace OCRepresentationEncodingTest static const char sid1[] = "646F6F72-4465-7669-6365-555549443030"; static const char devicename1[] = "device name"; static const char specver1[] = "spec version"; - static const char dmver1[] = "data model version"; + static const char dmver1[] = "one-1,two-2"; static OCStringLL *types = NULL; // Device Payloads TEST(DeviceDiscoveryEncoding, Normal) @@ -66,10 +66,14 @@ namespace OCRepresentationEncodingTest types, specver1, dmver1); + EXPECT_TRUE(device); EXPECT_STREQ(sid1, device->sid); EXPECT_STREQ(devicename1, device->deviceName); EXPECT_STREQ(specver1, device->specVersion); - EXPECT_STREQ(dmver1, device->dataModelVersion); + EXPECT_TRUE(device->dataModelVersions); + EXPECT_STREQ("one-1", device->dataModelVersions->value); + EXPECT_TRUE(device->dataModelVersions->next); + EXPECT_STREQ("two-2", device->dataModelVersions->next->value); EXPECT_EQ(PAYLOAD_TYPE_DEVICE, ((OCPayload*)device)->type); EXPECT_STREQ("oic.wk.d", device->types->value); EXPECT_STREQ("oic.d.tv", device->types->next->value); @@ -85,7 +89,7 @@ namespace OCRepresentationEncodingTest EXPECT_STREQ(device->sid, ((OCDevicePayload*)parsedDevice)->sid); EXPECT_STREQ(device->deviceName, ((OCDevicePayload*)parsedDevice)->deviceName); EXPECT_STREQ(device->specVersion, ((OCDevicePayload*)parsedDevice)->specVersion); - EXPECT_STREQ(device->dataModelVersion, ((OCDevicePayload*)parsedDevice)->dataModelVersion); + EXPECT_STREQ(device->dataModelVersions->value, ((OCDevicePayload*)parsedDevice)->dataModelVersions->value); EXPECT_STREQ("oic.wk.d", ((OCDevicePayload*)parsedDevice)->types->value); EXPECT_STREQ("oic.d.tv", ((OCDevicePayload*)parsedDevice)->types->next->value); EXPECT_EQ(device->base.type, ((OCDevicePayload*)parsedDevice)->base.type); @@ -99,7 +103,8 @@ namespace OCRepresentationEncodingTest EXPECT_STREQ(sid1, r.getValue(OC_RSRVD_DEVICE_ID).c_str()); EXPECT_STREQ(devicename1, r.getValue(OC_RSRVD_DEVICE_NAME).c_str()); EXPECT_STREQ(specver1, r.getValue(OC_RSRVD_SPEC_VERSION).c_str()); - EXPECT_STREQ(dmver1, r.getValue(OC_RSRVD_DATA_MODEL_VERSION).c_str()); + EXPECT_STREQ("one-1", r.getDataModelVersions()[0].c_str()); + EXPECT_STREQ("two-2", r.getDataModelVersions()[1].c_str()); OCPayloadDestroy(parsedDevice); } -- 2.7.4