Fix logic in zigbee wrapper to correctly evaluate boolean values.
authorMandeep Shetty <mandeep.shetty@intel.com>
Tue, 22 Sep 2015 22:24:53 +0000 (15:24 -0700)
committerPatrick Lankswert <patrick.lankswert@intel.com>
Tue, 29 Sep 2015 23:30:38 +0000 (23:30 +0000)
Boolean values could be read as either "0" or "00" and thus a simple
strcmp with "0" would not suffice.
Additionally, sometimes, bitmasks are read and so we need the entire
numeric value of the string.

Changed strcmp operations to convert to numeric operations.
Also extracted duplicate code into it's own function

Change-Id: I9a8918d9824dcb452b64fdbe9f344cfa020f9e7c
Signed-off-by: Mandeep Shetty <mandeep.shetty@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/3157
Reviewed-by: Joseph Morrow <joseph.l.morrow@intel.com>
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Patrick Lankswert <patrick.lankswert@intel.com>
plugins/zigbee_wrapper/src/zigbee_wrapper.c

index a21e561c3ede2ea689008d70a15ab27f102676af..7af6390a0fee26c2125875d29721c41d5e727560 100644 (file)
@@ -35,6 +35,7 @@
 #include <stdlib.h>
 #include <inttypes.h> // To convert "int64_t" to string.
 #include <math.h>
+#include <errno.h>
 
 #include "zigbee_wrapper.h"
 #include "telegesis_wrapper.h"
@@ -477,6 +478,33 @@ bool getZigBeeAttributesIfValid (char * OICResourceType,
     return false;
 }
 
+OCEntityHandlerResult getDoubleValueFromString (const char *str, double *outDouble)
+{
+    size_t hexOutValSize = strlen(HexPrepend) + strlen(str) + 1;
+    char * hexOutVal = (char *) OICCalloc(1, hexOutValSize);
+    if(!hexOutVal)
+    {
+        return OC_EH_ERROR;
+    }
+    OICStrcpy(hexOutVal, hexOutValSize, HexPrepend);
+    OICStrcat(hexOutVal, hexOutValSize, str);
+
+    char *endPtr;
+    errno = 0;
+    double value = strtod(hexOutVal, &endPtr);
+
+    if(errno != 0 || *endPtr != 0 || value == HUGE_VALF || value == HUGE_VALL)
+    {
+        OICFree(hexOutVal);
+        return OC_EH_ERROR;
+    }
+
+    OICFree(hexOutVal);
+    *outDouble = value;
+    return OC_EH_OK;
+
+}
+
 OCEntityHandlerResult processGetRequest (PIPluginBase * plugin,
         OCEntityHandlerRequest *ehRequest, OCRepPayload **payload)
 {
@@ -539,22 +567,15 @@ OCEntityHandlerResult processGetRequest (PIPluginBase * plugin,
         }
         if (attributeList.list[i].oicType == OIC_ATTR_INT)
         {
-            size_t hexOutValSize = strlen(HexPrepend) + strlen(outVal) + 1;
-            char * hexOutVal = (char *) OICCalloc(1, hexOutValSize);
-            if(!hexOutVal)
-            {
-                return OC_EH_ERROR;
-            }
-            OICStrcpy(hexOutVal, hexOutValSize, HexPrepend);
-            OICStrcat(hexOutVal, hexOutValSize, outVal);
-            double value = strtod(hexOutVal, NULL);
-            if(value == 0.0 || value == HUGE_VALF || value == HUGE_VALL)
+            char *endPtr = NULL;
+            // Third arg is 16 as outVal is a hex Number
+            uint64_t value = strtol (outVal, &endPtr, 16);
+
+            if (*endPtr != 0)
             {
-                OICFree(hexOutVal);
                 return OC_EH_ERROR;
             }
-            if (strcmp(attributeList.list[i].oicAttribute, OIC_DIMMING_ATTRIBUTE)
-                == 0)
+            if (strcmp(attributeList.list[i].oicAttribute, OIC_DIMMING_ATTRIBUTE) == 0)
             {
                 // OIC Dimming operates between 0-100, while Zigbee operates
                 // between 0-254 (ie. 0xFE).
@@ -570,22 +591,13 @@ OCEntityHandlerResult processGetRequest (PIPluginBase * plugin,
             boolRes = OCRepPayloadSetPropInt(*payload,
                                              attributeList.list[i].oicAttribute,
                                              (uint64_t) value);
-            OICFree (hexOutVal);
         }
         else if (attributeList.list[i].oicType == OIC_ATTR_DOUBLE)
         {
-            size_t hexOutValSize = strlen(HexPrepend) + strlen(outVal) + 1;
-            char * hexOutVal = (char *) OICCalloc(1, hexOutValSize);
-            if(!hexOutVal)
-            {
-                return OC_EH_ERROR;
-            }
-            OICStrcat(hexOutVal, hexOutValSize, HexPrepend);
-            OICStrcat(hexOutVal, hexOutValSize, outVal);
-            double value = strtod(hexOutVal, NULL);
-            if(value == 0.0 || value == HUGE_VAL || value == -HUGE_VAL)
+            double value = 0;
+
+            if (getDoubleValueFromString (outVal, &value) != OC_EH_OK)
             {
-                OICFree(hexOutVal);
                 return OC_EH_ERROR;
             }
             if (strcmp(piResource->clusterId, ZB_TEMPERATURE_CLUSTER) == 0)
@@ -597,7 +609,6 @@ OCEntityHandlerResult processGetRequest (PIPluginBase * plugin,
             boolRes = OCRepPayloadSetPropDouble(*payload,
                                                 attributeList.list[i].oicAttribute,
                                                 value);
-            OICFree(hexOutVal);
         }
         else if (attributeList.list[i].oicType == OIC_ATTR_STRING)
         {
@@ -607,19 +618,24 @@ OCEntityHandlerResult processGetRequest (PIPluginBase * plugin,
         }
         else if (attributeList.list[i].oicType == OIC_ATTR_BOOL)
         {
-            bool value = true;
-            if(strcmp(outVal, "0") == 0)
+            char *endPtr = NULL;
+            errno = 0;
+            // Third arg is 16 as outVal is a hex Number
+            uint64_t value = strtol (outVal, &endPtr, 16);
+
+            if (errno != 0 || *endPtr != 0)
             {
-                value = false;
+                return OC_EH_ERROR;
             }
-
-            // value is a bit mask and the LSB indicates boolean true/false.
+            // value COULD be a bit mask and the LSB indicates boolean true/false.
+            // If not a bit mask, it'll be plain 0 or 1.
             value = value & 1;
             boolRes = OCRepPayloadSetPropBool(*payload,
                                               attributeList.list[i].oicAttribute,
                                               value);
         }
-        OICFree(outVal);
+
+        OICFree (outVal);
     }
 
     if (boolRes == false)