{
.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;
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);
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
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
char *sid;
char* deviceName;
char* specVersion;
- char* dataModelVersion;
+ OCStringLL *dataModelVersions;
OCStringLL *interfaces;
OCStringLL *types;
} OCDevicePayload;
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:");
#include <signal.h>
#include <pthread.h>
#include <array>
+#include "oic_malloc.h"
#include "ocstack.h"
#include "logger.h"
#include "ocpayload.h"
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
{
free (deviceInfo.deviceName);
free (deviceInfo.specVersion);
- free (deviceInfo.dataModelVersion);
+ OCFreeOCStringLL (deviceInfo.dataModelVersions);
}
bool DuplicateString(char** targetString, const char* sourceString)
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))
{
{
return OC_STACK_ERROR;
}
- if(!DuplicateString(&deviceInfo.dataModelVersion, dataModelVersion))
+ OCFreeOCStringLL(deviceInfo.dataModelVersions);
+ deviceInfo.dataModelVersions = OCCreateOCStringLL(dataModelVersions);
+ if (!deviceInfo.dataModelVersions)
{
return OC_STACK_ERROR;
}
exit (EXIT_FAILURE);
}
- registrationResult = SetDeviceInfo(deviceName, specVersion, dataModelVersion);
+ registrationResult = SetDeviceInfo(deviceName, specVersion, dataModelVersions);
if (registrationResult != OC_STACK_OK)
{
#include <signal.h>
#include <pthread.h>
#include <array>
+#include "oic_malloc.h"
#include "ocstack.h"
#include "logger.h"
#include "ocpayload.h"
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
{
free (deviceInfo.deviceName);
free (deviceInfo.specVersion);
- free (deviceInfo.dataModelVersion);
+ OCFreeOCStringLL (deviceInfo.dataModelVersions);
}
bool DuplicateString(char** targetString, const char* sourceString)
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))
{
{
return OC_STACK_ERROR;
}
- if(!DuplicateString(&deviceInfo.dataModelVersion, dataModelVersion))
+ OCFreeOCStringLL(deviceInfo.dataModelVersions);
+ deviceInfo.dataModelVersions = OCCreateOCStringLL(dataModelVersions);
+ if (!deviceInfo.dataModelVersions)
{
return OC_STACK_ERROR;
}
exit (EXIT_FAILURE);
}
- registrationResult = SetDeviceInfo(deviceName, specVersion, dataModelVersion);
+ registrationResult = SetDeviceInfo(deviceName, specVersion, dataModelVersions);
if (registrationResult != OC_STACK_OK)
{
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}
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+// Required for strok_r
+#define _POSIX_C_SOURCE 200112L
+#include <stdio.h>
#include "ocpayload.h"
#include "octypes.h"
#include <string.h>
#include "rdpayload.h"
#define TAG "OIC_RI_PAYLOAD"
+#define CSV_SEPARATOR ','
+#define CSV_SEPARATORS ",;"
static void OCFreeRepPayloadValueContents(OCRepPayloadValue* val);
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 (count<sublen)
+ {
+ free(str);
+ return NULL;
+ }
+ len-=sublen;
+ pos+=count;
+ }
+
+ return str;
+}
+
OCRepPayload* OCRepPayloadClone (const OCRepPayload* payload)
{
if (!payload)
goto exit;
}
- payload->dataModelVersion = OICStrdup(dmVer);
- if (dmVer && !payload->dataModelVersion)
+ payload->dataModelVersions = OCCreateOCStringLL(dmVer);
+ if (!payload->dataModelVersions || (dmVer && !payload->dataModelVersions->value))
{
goto exit;
}
OICFree(payload->sid);
OICFree(payload->deviceName);
OICFree(payload->specVersion);
- OICFree(payload->dataModelVersion);
+ OCFreeOCStringLL(payload->dataModelVersions);
OCFreeOCStringLL(payload->types);
OCFreeOCStringLL(payload->interfaces);
OICFree(payload);
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");
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");
}
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);
}
}
}
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)
}
}
- 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;
}
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;
//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;
{
delete[] deviceInfo.deviceName;
delete[] deviceInfo.specVersion;
- delete[] deviceInfo.dataModelVersion;
+ OCFreeOCStringLL(deviceInfo.dataModelVersions);
}
void DuplicateString(char ** targetString, std::string sourceString)
}
-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;
}
}
- result = SetDeviceInfo(deviceName, specVersion, dataModelVersion);
+ result = SetDeviceInfo(deviceName, specVersion, dataModelVersions);
OCResourcePayloadAddStringLL(&deviceInfo.types, "oic.wk.d");
OCResourcePayloadAddStringLL(&deviceInfo.types, "oic.d.tv");
const std::vector<std::string>& getResourceTypes() const;
+ const std::vector<std::string>& getDataModelVersions() const;
+
void setResourceTypes(const std::vector<std::string>& resourceTypes);
void addResourceType(const std::string& str);
void addResourceInterface(const std::string& str);
+ void addDataModelVersion(const std::string& str);
+
bool emptyData() const;
int numberOfAttributes() const;
mutable std::map<std::string, AttributeValue> m_values;
std::vector<std::string> m_resourceTypes;
std::vector<std::string> m_interfaces;
+ std::vector<std::string> m_dataModelVersions;
InterfaceType m_interfaceType;
};
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);
m_interfaces = resourceInterfaces;
}
+ const std::vector<std::string>& 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();
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;
}
delete[] deviceInfo.deviceName;
DeleteStringLL(deviceInfo.types);
delete[] deviceInfo.specVersion;
- delete[] deviceInfo.dataModelVersion;
+ DeleteStringLL(deviceInfo.dataModelVersions);
}
void DuplicateString(char ** targetString, std::string sourceString)
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));
}
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)
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);
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);
EXPECT_STREQ(sid1, r.getValue<std::string>(OC_RSRVD_DEVICE_ID).c_str());
EXPECT_STREQ(devicename1, r.getValue<std::string>(OC_RSRVD_DEVICE_NAME).c_str());
EXPECT_STREQ(specver1, r.getValue<std::string>(OC_RSRVD_SPEC_VERSION).c_str());
- EXPECT_STREQ(dmver1, r.getValue<std::string>(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);
}