[IOT-1941] Add support for all oic.wk.d properties to 39/19539/5
authorTodd Malsbary <todd.malsbary@intel.com>
Tue, 2 May 2017 18:52:27 +0000 (11:52 -0700)
committerAshok Babu Channa <ashok.channa@samsung.com>
Fri, 5 May 2017 11:53:55 +0000 (11:53 +0000)
OCSetPropertyValue, OCGetPropertyValue.

Bug: https://jira.iotivity.org/browse/IOT-1941
Change-Id: Ia594c1e0dc8c47b4bbc430e630b5ad025544d2fd
Signed-off-by: Todd Malsbary <todd.malsbary@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/19539
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Uze Choi <uzchoi@samsung.com>
Reviewed-by: Ashok Babu Channa <ashok.channa@samsung.com>
resource/csdk/include/octypes.h
resource/csdk/stack/include/ocstack.h
resource/csdk/stack/src/ocresource.c
resource/csdk/stack/test/stacktests.cpp

index 117ef7e..cc78cf7 100644 (file)
@@ -264,6 +264,9 @@ extern "C" {
 /** To represent priority.*/
 #define OC_RSRVD_PRIORITY               "pri"
 
+/** For resource instance ID.*/
+#define OC_RSRVD_INSTANCE_ID            "id"
+
 /**
  *  Platform.
  */
@@ -303,37 +306,50 @@ extern "C" {
 
 /** VID for the platform. */
 #define OC_RSRVD_VID                    "vid"
+
 /**
  *  Device.
  */
 
 /** Device ID.*/
-#define OC_RSRVD_DEVICE_ID              "di"
+#define OC_RSRVD_DEVICE_ID               "di"
 
 /** Device Name.*/
-#define OC_RSRVD_DEVICE_NAME            "n"
+#define OC_RSRVD_DEVICE_NAME             "n"
 
 /** Device specification version.*/
-#define OC_RSRVD_SPEC_VERSION           "icv"
+#define OC_RSRVD_SPEC_VERSION            "icv"
 
 /** Device data model.*/
-#define OC_RSRVD_DATA_MODEL_VERSION     "dmv"
+#define OC_RSRVD_DATA_MODEL_VERSION      "dmv"
 
-/** Device specification version.*/
-#define OC_SPEC_VERSION                 "ocf.1.1.0"
+/** Device description, localized */
+#define OC_RSRVD_DEVICE_DESCRIPTION      "ld"
 
-/** Integer value of spec version (OCF1.0 0b0000:1000:0000:0000).*/
-#define OC_SPEC_VERSION_VALUE           2048
+/** Device software version */
+#define OC_RSRVD_SOFTWARE_VERSION        "sv"
 
-/** Device Data Model version.*/
-#define OC_DATA_MODEL_VERSION           "ocf.res.1.1.0,ocf.sh.1.1.0"
+/** Device manufacturer name, localized */
+#define OC_RSRVD_DEVICE_MFG_NAME         "dmn"
+
+/** Device model number */
+#define OC_RSRVD_DEVICE_MODEL_NUM        "dmno"
 
 /** Protocol-Independent ID.*/
 #define OC_RSRVD_PROTOCOL_INDEPENDENT_ID "piid"
 
+/** Device specification version.*/
+#define OC_SPEC_VERSION                  "ocf.1.1.0"
+
+/** Integer value of spec version (OCF1.0 0b0000:1000:0000:0000).*/
+#define OC_SPEC_VERSION_VALUE            2048
+
+/** Device Data Model version.*/
+#define OC_DATA_MODEL_VERSION            "ocf.res.1.1.0,ocf.sh.1.1.0"
+
 /**
-*  Introspection.
-*/
+ *  Introspection.
+ */
 /** Name.*/
 #define OC_RSRVD_INTROSPECTION_NAME     "name"
 
index 33630c1..5871a3c 100644 (file)
@@ -841,6 +841,11 @@ OCStackResult OCDecodeAddressForRFC6874(char* outputAddress,
  * Set the value of /oic/d and /oic/p properties. This function is a generic function that sets for
  * all OCF defined properties.
  *
+ * For PAYLOAD_TYPE_DEVICE and OC_RSRVD_DATA_MODEL_VERSION, value must be a const char* CSV string.
+ * For PAYLOAD_TYPE_DEVICE and OC_RSRVD_DEVICE_DESCRIPTION, or OC_RSRVD_DEVICE_MFG_NAME, value must
+ * be an OCStringLL* with pairs of language tag and value elements.  For all other
+ * PAYLOAD_TYPE_DEVICE properties, value must be a const char* string.
+ *
  * @param type the payload type for device and platform as defined in @ref OCPayloadType.
  * @param propName the pre-defined property as per OCF spec.
  * @param value the value of the property to be set.
@@ -850,8 +855,15 @@ OCStackResult OCDecodeAddressForRFC6874(char* outputAddress,
 OCStackResult OCSetPropertyValue(OCPayloadType type, const char *propName, const void *value);
 
 /**
- * Get the value of /oic/d and /oic/p properties. This function is a generic function that get value
- * for all OCF defined properties.
+ * Get the value of /oic/d and /oic/p properties. This function is a generic function that gets the
+ * value for all OCF defined properties.
+ *
+ * For PAYLOAD_TYPE_DEVICE and OC_RSRVD_RESOURCE_TYPE, OC_RSRVD_INTERFACE,
+ * OC_RSRVD_DATA_MODEL_VERSION, OC_RSRVD_DEVICE_DESCRIPTION, or OC_RSRVD_DEVICE_MFG_NAME, the value
+ * will be an OCStringLL*. For all other PAYLOAD_TYPE_DEVICE properties, value will be a char*.
+ *
+ * When the returned value is non-NULL, the memory must be OCFreeOCStringLL()'d or OICFree()'d by
+ * the caller (depending on the underlying type returned).
  *
  * @param type the payload type for device and platform as defined in @ref OCPayloadType.
  * @param propName the pre-defined as per OCF spec.
index 98e41ff..9a9a2c1 100755 (executable)
@@ -409,6 +409,33 @@ static OCStackResult BuildDevicePlatformPayload(const OCResource *resourcePtr, O
                     OICFree(dmv);
                 }
             }
+            else if (0 == strcmp(OC_RSRVD_DEVICE_DESCRIPTION, resAttrib->attrName) ||
+                    0 == strcmp(OC_RSRVD_DEVICE_MFG_NAME, resAttrib->attrName))
+            {
+                size_t dim[MAX_REP_ARRAY_DEPTH] = { 0 };
+                for (OCStringLL *ll = (OCStringLL *)resAttrib->attrValue; ll && ll->next;
+                     ll = ll->next->next)
+                {
+                    ++dim[0];
+                }
+                OCRepPayload **items = (OCRepPayload**)OICCalloc(dim[0], sizeof(OCRepPayload*));
+                if (items)
+                {
+                    OCRepPayload **item = items;
+                    for (OCStringLL *ll = (OCStringLL *)resAttrib->attrValue; ll && ll->next;
+                         ll = ll->next->next)
+                    {
+                        *item = OCRepPayloadCreate();
+                        if (*item)
+                        {
+                            OCRepPayloadSetPropString(*item, "language", ll->value);
+                            OCRepPayloadSetPropString(*item, "value", ll->next->value);
+                            ++item;
+                        }
+                    }
+                }
+                OCRepPayloadSetPropObjectArrayAsOwner(tempPayload, resAttrib->attrName, items, dim);
+            }
             else
             {
                 OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, (char *)resAttrib->attrValue);
@@ -2339,12 +2366,40 @@ OCStackResult OCGetAttribute(const OCResource *resource, const char *attribute,
     {
         return OC_STACK_INVALID_PARAM;
     }
+    // Special attributes - these values are not in rsrcAttributes
+    if (0 == strcmp(OC_RSRVD_DEVICE_ID, attribute))
+    {
+        *value = OICStrdup(OCGetServerInstanceIDString());
+        return OC_STACK_OK;
+    }
+    if (0 == strcmp(OC_RSRVD_RESOURCE_TYPE, attribute))
+    {
+        *value = NULL;
+        for (OCResourceType *resType = resource->rsrcType; resType; resType = resType->next)
+        {
+            OCResourcePayloadAddStringLL((OCStringLL**)&value, resType->resourcetypename);
+        }
+        return OC_STACK_OK;
+    }
+    if (0 == strcmp(OC_RSRVD_INTERFACE, attribute))
+    {
+        *value = NULL;
+        for (OCResourceInterface *resInterface = resource->rsrcInterface; resInterface;
+             resInterface = resInterface->next)
+        {
+            OCResourcePayloadAddStringLL((OCStringLL**)&value, resInterface->name);
+        }
+        return OC_STACK_OK;
+    }
+    // Generic attributes
     for (OCAttribute *temp = resource->rsrcAttributes; temp; temp = temp->next)
     {
         if (0 == strcmp(attribute, temp->attrName))
         {
             // A special case as this type return OCStringLL
-            if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, attribute))
+            if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, attribute) ||
+                    0 == strcmp(OC_RSRVD_DEVICE_DESCRIPTION, attribute) ||
+                    0 == strcmp(OC_RSRVD_DEVICE_MFG_NAME, attribute))
             {
                 *value = CloneOCStringLL((OCStringLL *)temp->attrValue);
                 return OC_STACK_OK;
@@ -2395,13 +2450,23 @@ static OCStackResult SetAttributeInternal(OCResource *resource,
 {
     OCAttribute *resAttrib = NULL;
 
+    // Read-only attributes - these values are set via other APIs
+    if (0 == strcmp(attribute, OC_RSRVD_RESOURCE_TYPE) ||
+            0 == strcmp(attribute, OC_RSRVD_INTERFACE) ||
+            0 == strcmp(attribute, OC_RSRVD_DEVICE_ID))
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
     // See if the attribute already exists in the list.
     for (resAttrib = resource->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
     {
         if (0 == strcmp(attribute, resAttrib->attrName))
         {
             // Found, free the old value.
-            if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName))
+            if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName) ||
+                    0 == strcmp(OC_RSRVD_DEVICE_DESCRIPTION, resAttrib->attrName) ||
+                    0 == strcmp(OC_RSRVD_DEVICE_MFG_NAME, resAttrib->attrName))
             {
                 OCFreeOCStringLL((OCStringLL *)resAttrib->attrValue);
             }
@@ -2429,6 +2494,11 @@ static OCStackResult SetAttributeInternal(OCResource *resource,
     {
         resAttrib->attrValue = OCCreateOCStringLL((char *)value);
     }
+    else if (0 == strcmp(OC_RSRVD_DEVICE_DESCRIPTION, attribute) ||
+            0 == strcmp(OC_RSRVD_DEVICE_MFG_NAME, attribute))
+    {
+        resAttrib->attrValue = CloneOCStringLL((OCStringLL *)value);
+    }
     else
     {
         resAttrib->attrValue = OICStrdup((char *)value);
index 435a1bb..39a804a 100644 (file)
@@ -616,6 +616,137 @@ TEST(StackStart, GetDeviceInfoAPI)
     EXPECT_EQ(OC_STACK_OK, OCStop());
 }
 
+TEST(StackStart, SetGetDevicePropertyValues)
+{
+    itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+    EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_SERVER));
+    OCResourceHandle handle = OCGetResourceHandleAtUri(OC_RSRVD_DEVICE_URI);
+    EXPECT_TRUE(handle != NULL);
+    EXPECT_EQ(OC_STACK_OK, OCBindResourceTypeToResource(handle, "oic.wk.tv"));
+    EXPECT_EQ(OC_STACK_OK, OCBindResourceInterfaceToResource(handle, "oic.if.tv"));
+
+    void *value = NULL;
+    OCStringLL *x, *y;
+
+    OCStringLL *rts = NULL;
+    OCResourcePayloadAddStringLL(&rts, "oic.wk.d");
+    OCResourcePayloadAddStringLL(&rts, "oic.wk.tv");
+    EXPECT_NE(OC_STACK_OK, OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_RESOURCE_TYPE, &value));
+    EXPECT_EQ(OC_STACK_OK, OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_RESOURCE_TYPE, &value));
+    for (x = rts, y = (OCStringLL *) value; x && y; x = x->next, y = y->next)
+    {
+        EXPECT_STREQ(x->value, y->value);
+    }
+    EXPECT_TRUE(!x && !y);
+    OCFreeOCStringLL((OCStringLL *) value);
+    value = NULL;
+    OCFreeOCStringLL(rts);
+
+    OCStringLL *itfs = NULL;
+    OCResourcePayloadAddStringLL(&itfs, "oic.if.baseline");
+    OCResourcePayloadAddStringLL(&itfs, "oic.if.r");
+    OCResourcePayloadAddStringLL(&itfs, "oic.if.tv");
+    EXPECT_NE(OC_STACK_OK, OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_INTERFACE, &value));
+    EXPECT_EQ(OC_STACK_OK, OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_INTERFACE, &value));
+    for (x = itfs, y = (OCStringLL *) value; x && y; x = x->next, y = y->next)
+    {
+        EXPECT_STREQ(x->value, y->value);
+    }
+    EXPECT_TRUE(!x && !y);
+    OCFreeOCStringLL((OCStringLL *) value);
+    value = NULL;
+    OCFreeOCStringLL(itfs);
+
+    const char *n = "name";
+    EXPECT_EQ(OC_STACK_OK, OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, n));
+    EXPECT_EQ(OC_STACK_OK, OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, &value));
+    EXPECT_STREQ(n, (char *) value);
+    OICFree(value);
+    value = NULL;
+
+    const char *id = "instance-identifier";
+    EXPECT_EQ(OC_STACK_OK, OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_INSTANCE_ID, id));
+    EXPECT_EQ(OC_STACK_OK, OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_INSTANCE_ID, &value));
+    EXPECT_STREQ(id, (char *) value);
+    OICFree(value);
+    value = NULL;
+
+    EXPECT_NE(OC_STACK_OK, OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_ID, &value));
+    EXPECT_EQ(OC_STACK_OK, OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_ID, &value));
+    EXPECT_STREQ(OCGetServerInstanceIDString(), (char *) value);
+    OICFree(value);
+    value = NULL;
+
+    EXPECT_EQ(OC_STACK_OK, OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_SPEC_VERSION, OC_SPEC_VERSION));
+    EXPECT_EQ(OC_STACK_OK, OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_SPEC_VERSION, &value));
+    EXPECT_STREQ(OC_SPEC_VERSION, (char *) value);
+    OICFree(value);
+    value = NULL;
+
+    EXPECT_EQ(OC_STACK_OK, OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION, OC_DATA_MODEL_VERSION));
+    EXPECT_EQ(OC_STACK_OK, OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION, &value));
+    char *dmv = OCCreateString((OCStringLL *) value);
+    EXPECT_STREQ(OC_DATA_MODEL_VERSION, dmv);
+    OICFree(dmv);
+    OCFreeOCStringLL((OCStringLL *) value);
+    value = NULL;
+
+    OCStringLL *ld = NULL;
+    OCResourcePayloadAddStringLL(&ld, "en");
+    OCResourcePayloadAddStringLL(&ld, "Description");
+    OCResourcePayloadAddStringLL(&ld, "de");
+    OCResourcePayloadAddStringLL(&ld, "Beschriebung");
+    EXPECT_EQ(OC_STACK_OK, OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_DESCRIPTION, ld));
+    EXPECT_EQ(OC_STACK_OK, OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_DESCRIPTION, &value));
+    for (x = ld, y = (OCStringLL *) value; x && y; x = x->next, y = y->next)
+    {
+        EXPECT_STREQ(x->value, y->value);
+    }
+    EXPECT_TRUE(!x && !y);
+    OCFreeOCStringLL((OCStringLL *) value);
+    value = NULL;
+    OCFreeOCStringLL(ld);
+
+    const char *sv = "software-version";
+    EXPECT_EQ(OC_STACK_OK, OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_SOFTWARE_VERSION, sv));
+    EXPECT_EQ(OC_STACK_OK, OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_SOFTWARE_VERSION, &value));
+    EXPECT_STREQ(sv, (char *) value);
+    OICFree(value);
+    value = NULL;
+
+    OCStringLL *dmn = NULL;
+    OCResourcePayloadAddStringLL(&dmn, "en");
+    OCResourcePayloadAddStringLL(&dmn, "Manufacturer");
+    OCResourcePayloadAddStringLL(&dmn, "de");
+    OCResourcePayloadAddStringLL(&dmn, "Hersteller");
+    EXPECT_EQ(OC_STACK_OK, OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_MFG_NAME, dmn));
+    EXPECT_EQ(OC_STACK_OK, OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_MFG_NAME, &value));
+    for (x = dmn, y = (OCStringLL *) value; x && y; x = x->next, y = y->next)
+    {
+        EXPECT_STREQ(x->value, y->value);
+    }
+    EXPECT_TRUE(!x && !y);
+    OCFreeOCStringLL((OCStringLL *) value);
+    value = NULL;
+    OCFreeOCStringLL(dmn);
+
+    const char *dmno = "device-model-number";
+    EXPECT_EQ(OC_STACK_OK, OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_MODEL_NUM, dmno));
+    EXPECT_EQ(OC_STACK_OK, OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_MODEL_NUM, &value));
+    EXPECT_STREQ(dmno, (char *) value);
+    OICFree(value);
+    value = NULL;
+
+    const char *piid = "protocol-independent-identifier";
+    EXPECT_EQ(OC_STACK_OK, OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_PROTOCOL_INDEPENDENT_ID, piid));
+    EXPECT_EQ(OC_STACK_OK, OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_PROTOCOL_INDEPENDENT_ID, &value));
+    EXPECT_STREQ(piid, (char *) value);
+    OICFree(value);
+    value = NULL;
+
+    EXPECT_EQ(OC_STACK_OK, OCStop());
+}
+
 TEST(StackDiscovery, DISABLED_DoResourceDeviceDiscovery)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);