1 //******************************************************************
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
24 * This file contains defined interface for the Zigbee Radio.
36 #include <inttypes.h> // To convert "int64_t" to string.
40 #include "zigbee_wrapper.h"
41 #include "telegesis_wrapper.h"
42 #include "pluginlist.h"
44 #include "ocpayload.h"
45 #include "oic_malloc.h"
46 #include "oic_string.h"
49 #define HexPrepend "0x"
51 #define TAG "zigbeeWrapper"
53 // TODO: These should eventually go into an XML/JSON/Mapping thing
54 #define MAX_ATTRIBUTES 10
55 #define ZB_TEMPERATURE_CLUSTER "0402"
56 #define ZB_TEMPERATURE_ATTRIBUTE_ID "0000"
57 #define ZB_CURRENT_LEVEL_ATTRIBUTE_READONLY "0000"
58 #define ZB_ON_LEVEL_ATTRIBUTE "0011"
59 #define ZB_LEVEL_CONTROL_CLUSTER "0008"
60 #define ZB_IAS_ZONE_CLUSTER "0500"
61 #define ZB_IAS_ZONE_STATUS_ATTRIBUTE_ID "0002"
62 #define ZB_INDICATOR_CLUSTER "0003"
63 #define ZB_INDICATOR_ATTRIBUTE_ID "0000"
64 #define ZB_ON_OFF_CLUSTER "0006"
65 #define ZB_ON_OFF_ATTRIBUTE_ID "0000"
66 #define ZB_IAS_ZONE_TYPE_ATTRIBUTE_ID "0001"
68 #define IAS_ZONE_TYPE_MOTION_SENSOR "000d"
69 #define IAS_ZONE_TYPE_CONTACT_SENSOR "0015"
70 #define IAS_ZONE_TYPE_WATER_SENSOR "002a"
72 #define ZB_DATA_TYPE_NULL "00"
73 #define ZB_DATA_TYPE_1_BYTE "08"
74 #define ZB_DATA_TYPE_2_BYTE "09"
75 #define ZB_DATA_TYPE_3_BYTE "0a"
76 #define ZB_DATA_TYPE_4_BYTE "0b"
77 #define ZB_DATA_TYPE_5_BYTE "0c"
78 #define ZB_DATA_TYPE_6_BYTE "0d"
79 #define ZB_DATA_TYPE_7_BYTE "0e"
80 #define ZB_DATA_TYPE_8_BYTE "0f"
81 #define ZB_DATA_TYPE_BOOL "10"
82 #define ZB_DATA_TYPE_SIGNED_INT_16 "29"
83 #define ZB_DATA_TYPE_UNSIGNED_INT_8 "20"
84 #define ZB_DATA_TYPE_UNSIGNED_INT_16 "21"
86 #define MAX_STRLEN_INT (10)
87 // DBL_MANT_DIG = Max # of digits after decimal after the leading zeros.
88 // DBL_MIN_EXP = Max # of leading zeros of the mantissa.
89 // Magic number '3' represents a '-' (negative sign), '0' (a possible zero), and '.' (a period).
90 // "-0." from a number like "-0.999999991245", the "-0." adds 3 unaccounted characters.
91 #define MAX_STRLEN_DOUBLE (3 + DBL_MANT_DIG - DBL_MIN_EXP)
92 #define MAX_STRLEN_BOOL (1)
94 #define DEFAULT_TRANS_TIME "0000"
95 #define DEFAULT_MOVETOLEVEL_MODE "0"
97 static const char* OIC_TEMPERATURE_SENSOR = "oic.r.temperature";
98 static const char* OIC_DIMMABLE_LIGHT = "oic.r.light.dimming";
99 static const char* OIC_CONTACT_SENSOR = "oic.r.sensor.contact";
100 static const char* OIC_MOTION_SENSOR = "oic.r.sensor.motion";
101 static const char* OIC_WATER_SENSOR = "oic.r.sensor.water";
102 static const char* OIC_BINARY_SWITCH = "oic.r.switch.binary";
104 static const char* OIC_TEMPERATURE_ATTRIBUTE = "temperature";
105 static const char* OIC_DIMMING_ATTRIBUTE = "dimmingSetting";
106 static const char* OIC_CONTACT_ATTRIBUTE = "value";
107 static const char* OIC_ON_OFF_ATTRIBUTE = "value";
109 PIPlugin_Zigbee ** gPlugin = NULL;
115 ZB_16_BIT, // 2 bytes
116 ZB_24_BIT, // 3 bytes
117 ZB_32_BIT, // 4 bytes
118 ZB_40_BIT, // 5 bytes
119 ZB_48_BIT, // 6 bytes
120 ZB_56_BIT, // 7 bytes
121 ZB_64_BIT, // 8 bytes
134 } ZigBeeAttributeDataType;
136 char * getZBDataTypeString(ZigBeeAttributeDataType attrType);
137 OCEntityHandlerResult ProcessEHRequest(PIPluginBase * plugin, OCEntityHandlerRequest *ehRequest,
138 OCRepPayload **payload);
152 char *zigBeeAttribute;
153 OICAttributeType oicType;
154 ZigBeeAttributeDataType zigbeeType;
163 } OICZigBeeAttributePair;
167 CIE_RON_OFF = 1 << 1,
168 CIE_MOVE_TO_LEVEL = 1 << 2
175 CIECommandMask CIEMask;
176 OICZigBeeAttributePair list[MAX_ATTRIBUTES];
179 const char* ZigBeeClusterIDToOICResourceType(const char * clusterID);
181 OCStackResult getZigBeeAttributesForOICResource(const char * OICResourceType,
182 AttributeList *attributeList);
184 bool getZigBeeAttributesIfValid(const char * OICResourceType,
185 AttributeList *attributeList,
186 OCRepPayload *payload);
188 const char * getResourceTypeForIASZoneType(TWDevice *device)
194 char *IASZoneType = NULL;
195 const char *resourceType = NULL;
198 OCStackResult ret = TWGetAttribute(
201 device->endpointOfInterest->endpointId,
203 ZB_IAS_ZONE_TYPE_ATTRIBUTE_ID,
208 if (ret != OC_STACK_OK || !IASZoneType)
210 OC_LOG_V (ERROR, TAG, "Error %u getting IAS Zone Type", ret);
214 if (strcmp (IASZoneType, IAS_ZONE_TYPE_CONTACT_SENSOR) == 0)
216 resourceType = OIC_CONTACT_SENSOR;
218 else if (strcmp (IASZoneType, IAS_ZONE_TYPE_MOTION_SENSOR) == 0)
220 resourceType = OIC_MOTION_SENSOR;
222 else if (strcmp (IASZoneType, IAS_ZONE_TYPE_WATER_SENSOR) == 0)
224 resourceType = OIC_WATER_SENSOR;
228 OC_LOG_V (ERROR, TAG, "Unsupported Zone Type %s", IASZoneType);
232 OICFree(IASZoneType);
237 OCStackResult buildURI(char ** output,
240 const char * endpointId,
241 const char * clusterId)
243 if(!output || !prefix || !nodeId || !endpointId || !clusterId)
245 return OC_STACK_INVALID_PARAM;
247 const char LEN_SEPARATOR[] = "/";
248 size_t lenSeparatorSize = sizeof(LEN_SEPARATOR) - 1;
249 size_t newUriSize = strlen(prefix) + lenSeparatorSize +
250 strlen(nodeId) + lenSeparatorSize +
251 strlen(endpointId) + lenSeparatorSize +
253 + 1; // NULL Terminator
254 *output = (char *) OICCalloc(1, newUriSize);
258 OC_LOG (ERROR, TAG, "Out of memory");
259 return OC_STACK_NO_MEMORY;
262 char * temp = OICStrcpy(*output, newUriSize, prefix);
267 temp = OICStrcat(*output, newUriSize, LEN_SEPARATOR);
272 temp = OICStrcat(*output, newUriSize, nodeId);
277 temp = OICStrcat(*output, newUriSize, LEN_SEPARATOR);
282 temp = OICStrcat(*output, newUriSize, endpointId);
287 temp = OICStrcat(*output, newUriSize, LEN_SEPARATOR);
292 temp = OICStrcat(*output, newUriSize, clusterId);
303 return OC_STACK_NO_MEMORY;
306 void foundZigbeeCallback(TWDevice *device)
310 OC_LOG(ERROR, TAG, "foundZigbeeCallback: Invalid parameter.");
313 int count = device->endpointOfInterest->clusterList->count;
314 for(int i=0; i < count; i++)
316 PIResource_Zigbee *piResource = (PIResource_Zigbee *) OICMalloc(sizeof(*piResource));
319 OC_LOG (ERROR, TAG, "Out of memory");
322 piResource->header.plugin = (PIPluginBase *)gPlugin;
324 OCStackResult result = buildURI(&piResource->header.piResource.uri,
327 device->endpointOfInterest->endpointId,
328 device->endpointOfInterest->clusterList->clusterIds[i].clusterId);
330 if(result != OC_STACK_OK)
336 char * foundClusterID =
337 device->endpointOfInterest->clusterList->clusterIds[i].clusterId;
339 if (strcmp (foundClusterID, ZB_IAS_ZONE_CLUSTER) == 0)
341 piResource->header.piResource.resourceTypeName
342 = getResourceTypeForIASZoneType (device);
344 OCStackResult ret = TWListenForStatusUpdates (device->nodeId,
345 device->endpointOfInterest->endpointId);
347 if (ret != OC_STACK_OK)
349 // Just log it and move on if this fails?
350 // or not create this resource at all?
351 OC_LOG (ERROR, TAG, "Command to listen for status updates failed");
356 piResource->header.piResource.resourceTypeName =
357 (char *) ZigBeeClusterIDToOICResourceType(foundClusterID);
360 if(piResource->header.piResource.resourceTypeName == NULL)
362 OC_LOG_V (ERROR, TAG, "unsupported clusterId : %s",
363 device->endpointOfInterest->clusterList->clusterIds[i].clusterId);
364 OICFree(piResource->header.piResource.uri);
368 piResource->header.piResource.resourceInterfaceName =
369 OC_RSRVD_INTERFACE_DEFAULT;
371 piResource->header.piResource.callbackParam = NULL;
372 piResource->header.piResource.resourceProperties = 0;
373 piResource->eui = OICStrdup(device->eui);
374 piResource->nodeId = OICStrdup(device->nodeId);
375 piResource->endpointId = OICStrdup(device->endpointOfInterest->endpointId);
376 piResource->clusterId =
377 OICStrdup(device->endpointOfInterest->clusterList->clusterIds[i].clusterId);
378 (*gPlugin)->header.NewResourceFoundCB(&(*gPlugin)->header, &piResource->header);
382 void zigbeeZoneStatusUpdate(TWUpdate * update)
390 OCStackResult result = buildURI(&uri,
394 ZB_IAS_ZONE_CLUSTER);
395 if(result != OC_STACK_OK || !uri)
397 OC_LOG_V(ERROR, TAG, "Failed to build URI with result: %d", result);
401 (*gPlugin)->header.ObserveNotificationUpdate((PIPluginBase *)*gPlugin, uri);
405 OCStackResult ZigbeeInit(const char * comPort, PIPlugin_Zigbee ** plugin,
406 PINewResourceFound newResourceCB,
407 PIObserveNotificationUpdate observeNotificationUpdate)
411 return OC_STACK_INVALID_PARAM;
413 *plugin = (PIPlugin_Zigbee *) OICMalloc(sizeof(PIPlugin_Zigbee) + sizeof(PIPluginBase));
416 return OC_STACK_NO_MEMORY;
418 ((*plugin)->header).type = PLUGIN_ZIGBEE;
419 ((*plugin)->header).comPort = comPort;
420 ((*plugin)->header).NewResourceFoundCB = newResourceCB;
421 ((*plugin)->header).ObserveNotificationUpdate = observeNotificationUpdate;
422 ((*plugin)->header).next = NULL;
423 ((*plugin)->header).resourceList = NULL;
424 ((*plugin)->header).processEHRequest = ProcessEHRequest;
427 OCStackResult result = TWInitialize(comPort);
428 if(result != OC_STACK_OK)
433 return TWSetStatusUpdateCallback(zigbeeZoneStatusUpdate);
436 OCStackResult ZigbeeDiscover(PIPlugin_Zigbee * plugin)
438 OCStackResult result = OC_STACK_ERROR;
440 TWSetDiscoveryCallback(foundZigbeeCallback);
441 result = TWDiscover(NULL);
442 OC_LOG_V (DEBUG, TAG, "ZigbeeDiscover : Status = %d\n", result);
447 OCStackResult ZigbeeStop(PIPlugin_Zigbee * plugin)
450 return TWUninitialize();
453 OCStackResult ZigbeeProcess(PIPlugin_Zigbee * plugin)
459 // Function returns an OIC Smart Home resource Type
460 // from the cluster ID. If the cluster is not supported, null is
462 // NOTE: The returned string is NOT malloc'ed.
463 const char* ZigBeeClusterIDToOICResourceType(const char * clusterID) //Discovery/CreateResource
465 if (strcmp(clusterID, ZB_TEMPERATURE_CLUSTER) == 0)
467 return OIC_TEMPERATURE_SENSOR;
469 else if (strcmp(clusterID, ZB_LEVEL_CONTROL_CLUSTER) == 0)
471 return OIC_DIMMABLE_LIGHT;
473 else if (strcmp(clusterID, ZB_IAS_ZONE_CLUSTER) == 0)
475 return OIC_CONTACT_SENSOR;
477 else if (strcmp(clusterID, ZB_ON_OFF_CLUSTER) == 0)
479 return OIC_BINARY_SWITCH;
487 const char* OICResourceToZigBeeClusterID(char *oicResourceType)
489 if (strcmp(oicResourceType, OIC_TEMPERATURE_SENSOR) == 0)
491 return ZB_TEMPERATURE_CLUSTER;
493 else if (strcmp(oicResourceType, OIC_DIMMABLE_LIGHT) == 0)
495 return ZB_LEVEL_CONTROL_CLUSTER;
497 else if (strcmp(oicResourceType, OIC_CONTACT_SENSOR) == 0)
499 return ZB_IAS_ZONE_CLUSTER;
501 else if (strcmp(oicResourceType, OIC_BINARY_SWITCH) == 0)
503 return ZB_ON_OFF_CLUSTER;
505 else if (strcmp(oicResourceType, OIC_BINARY_SWITCH) == 0)
507 return ZB_INDICATOR_CLUSTER;
515 OCStackResult getZigBeeAttributesForOICResource(const char * OICResourceType,
516 AttributeList *attributeList) // GET
518 if (strcmp (OICResourceType, OIC_TEMPERATURE_SENSOR) == 0)
520 attributeList->count = 1;
521 attributeList->list[0].oicAttribute = OICStrdup(OIC_TEMPERATURE_ATTRIBUTE);
522 attributeList->list[0].zigBeeAttribute = ZB_TEMPERATURE_ATTRIBUTE_ID;
523 attributeList->list[0].oicType = OIC_ATTR_DOUBLE;
524 attributeList->list[0].zigbeeType = ZB_16_SINT;
527 else if (strcmp (OICResourceType, OIC_DIMMABLE_LIGHT) == 0)
529 attributeList->count = 1;
530 attributeList->list[0].oicAttribute = OICStrdup(OIC_DIMMING_ATTRIBUTE);
531 attributeList->list[0].zigBeeAttribute = ZB_CURRENT_LEVEL_ATTRIBUTE_READONLY;
532 attributeList->list[0].oicType = OIC_ATTR_INT;
533 attributeList->list[0].zigbeeType = ZB_8_UINT;
536 else if (strcmp (OICResourceType, OIC_CONTACT_SENSOR) == 0)
538 attributeList->count = 1;
539 attributeList->list[0].oicAttribute = OICStrdup(OIC_CONTACT_ATTRIBUTE);
540 attributeList->list[0].zigBeeAttribute = ZB_IAS_ZONE_STATUS_ATTRIBUTE_ID;
541 attributeList->list[0].oicType = OIC_ATTR_BOOL;
542 attributeList->list[0].zigbeeType = ZB_BOOL;
545 else if (strcmp (OICResourceType, OIC_BINARY_SWITCH) == 0)
547 attributeList->count = 1;
548 attributeList->list[0].oicAttribute = OICStrdup(OIC_ON_OFF_ATTRIBUTE);
549 attributeList->list[0].zigBeeAttribute = ZB_ON_OFF_ATTRIBUTE_ID;
550 attributeList->list[0].oicType = OIC_ATTR_BOOL;
551 attributeList->list[0].zigbeeType = ZB_BOOL;
555 return OC_STACK_ERROR;
558 bool getZigBeeAttributesIfValid(const char * OICResourceType,
559 AttributeList *attributeList,
560 OCRepPayload *payload) // Put
566 if(strcmp(OICResourceType, OIC_TEMPERATURE_SENSOR) == 0)
568 // Cant really PUT on the temp sensor, but the code is still there.
569 int64_t temperature = 0;
571 // TODO: This if should only look for attributes it supports and ignore the rest
572 // or examine every attribute in the payload and complain about unsupported attributes?
573 if(OCRepPayloadGetPropInt(payload, OIC_TEMPERATURE_ATTRIBUTE, &temperature))
575 attributeList->count = 1;
576 attributeList->list[0].oicAttribute = OICStrdup(OIC_TEMPERATURE_ATTRIBUTE);
577 attributeList->list[0].zigBeeAttribute = ZB_TEMPERATURE_ATTRIBUTE_ID;
578 attributeList->list[0].oicType = OIC_ATTR_DOUBLE;
579 attributeList->list[0].val.d = temperature;
580 attributeList->list[0].zigbeeType = ZB_16_SINT;
581 attributeList->CIEMask = (CIECommandMask) 0;
586 else if (strcmp (OICResourceType, OIC_DIMMABLE_LIGHT) == 0)
590 if(OCRepPayloadGetPropInt(payload, OIC_DIMMING_ATTRIBUTE, &onLevel))
592 attributeList->count = 1;
593 attributeList->list[0].oicAttribute = OICStrdup(OIC_DIMMING_ATTRIBUTE);
594 attributeList->list[0].zigBeeAttribute = ZB_ON_LEVEL_ATTRIBUTE;
595 attributeList->list[0].oicType = OIC_ATTR_INT;
596 attributeList->list[0].val.i = onLevel;
597 attributeList->list[0].zigbeeType = ZB_8_UINT;
599 // Level control cluster is dealing with level in the PUT payload.
600 attributeList->CIEMask = attributeList->CIEMask | CIE_MOVE_TO_LEVEL;
604 else if (strcmp (OICResourceType, OIC_CONTACT_SENSOR) == 0)
608 if(OCRepPayloadGetPropInt(payload, OIC_CONTACT_ATTRIBUTE, &value))
610 attributeList->count = 1;
611 attributeList->list[0].oicAttribute = OICStrdup(OIC_CONTACT_ATTRIBUTE);
612 attributeList->list[0].zigBeeAttribute = ZB_IAS_ZONE_STATUS_ATTRIBUTE_ID;
613 attributeList->list[0].oicType = OIC_ATTR_BOOL;
614 attributeList->list[0].val.i = value;
615 attributeList->list[0].zigbeeType = ZB_BOOL;
616 attributeList->CIEMask = (CIECommandMask) 0;
621 else if (strcmp (OICResourceType, OIC_BINARY_SWITCH) == 0)
625 if(OCRepPayloadGetPropBool(payload, OIC_ON_OFF_ATTRIBUTE, &value))
627 attributeList->count = 1;
628 attributeList->list[0].oicAttribute = OICStrdup(OIC_ON_OFF_ATTRIBUTE);
629 attributeList->list[0].zigBeeAttribute = ZB_ON_OFF_ATTRIBUTE_ID;
630 attributeList->list[0].oicType = OIC_ATTR_BOOL;
631 attributeList->list[0].val.b = value;
632 attributeList->list[0].zigbeeType = ZB_BOOL;
634 attributeList->CIEMask = attributeList->CIEMask | CIE_RON_OFF;
641 OCEntityHandlerResult getDoubleValueFromString (const char *str, double *outDouble)
643 size_t hexOutValSize = strlen(HexPrepend) + strlen(str) + 1;
644 char * hexOutVal = (char *) OICCalloc(1, hexOutValSize);
649 OICStrcpy(hexOutVal, hexOutValSize, HexPrepend);
650 OICStrcat(hexOutVal, hexOutValSize, str);
654 double value = strtod(hexOutVal, &endPtr);
656 if(errno != 0 || *endPtr != 0 || value == HUGE_VALF || value == HUGE_VALL)
668 OCEntityHandlerResult processGetRequest (PIPluginBase * plugin,
669 OCEntityHandlerRequest *ehRequest, OCRepPayload **payload)
671 if (!plugin || !ehRequest || !payload)
675 uint32_t attributeListIndex = 0;
676 OCStackResult stackResult = OC_STACK_OK;
677 PIResource_Zigbee * piResource = NULL;
679 AttributeList attributeList = { 0, (CIECommandMask) 0,
680 .list[0] = { NULL, NULL, OIC_ATTR_NULL, ZB_NULL, { .i = 0 } } };
681 stackResult = GetResourceFromHandle(plugin, (PIResource**) (&piResource),
682 ehRequest->resource);
683 if (stackResult != OC_STACK_OK)
685 OC_LOG (ERROR, TAG, "Failed to get resource from handle");
688 stackResult = getZigBeeAttributesForOICResource (
689 piResource->header.piResource.resourceTypeName, &attributeList);
690 if(stackResult != OC_STACK_OK)
692 OC_LOG_V (ERROR, TAG, "Failed to fetch attributes for %s",
693 piResource->header.piResource.resourceTypeName);
697 *payload = OCRepPayloadCreate();
700 OC_LOG(ERROR, TAG, PCF("Failed to allocate Payload"));
703 bool boolRes = OCRepPayloadSetUri(*payload, piResource->header.piResource.uri);
704 if (boolRes == false)
706 OCRepPayloadDestroy (*payload);
709 for(uint32_t i = 0; i<attributeList.count; i++)
711 char * outVal = NULL;
712 uint8_t outValLength = 0;
714 stackResult = TWGetAttribute(piResource->eui,
716 piResource->endpointId,
717 piResource->clusterId,
718 attributeList.list[i].zigBeeAttribute,
722 if (stackResult != OC_STACK_OK || !outVal)
724 stackResult = OC_EH_ERROR;
725 OCRepPayloadDestroy (*payload);
728 if (attributeList.list[i].oicType == OIC_ATTR_INT)
731 // Third arg is 16 as outVal is a hex Number
732 uint64_t value = strtol (outVal, &endPtr, 16);
738 if (strcmp(attributeList.list[i].oicAttribute, OIC_DIMMING_ATTRIBUTE) == 0)
740 // OIC Dimming operates between 0-100, while Zigbee operates
741 // between 0-254 (ie. 0xFE).
748 value = value / 2.54;
751 boolRes = OCRepPayloadSetPropInt(*payload,
752 attributeList.list[i].oicAttribute,
755 else if (attributeList.list[i].oicType == OIC_ATTR_DOUBLE)
759 if (getDoubleValueFromString (outVal, &value) != OC_EH_OK)
763 if (strcmp(piResource->clusterId, ZB_TEMPERATURE_CLUSTER) == 0)
765 // Divide by 100 as temperature readings have a resolution of
766 // 0.01 or one hundreth of a degree celsius.
769 boolRes = OCRepPayloadSetPropDouble(*payload,
770 attributeList.list[i].oicAttribute,
773 else if (attributeList.list[i].oicType == OIC_ATTR_STRING)
775 boolRes = OCRepPayloadSetPropString(*payload,
776 attributeList.list[i].oicAttribute,
779 else if (attributeList.list[i].oicType == OIC_ATTR_BOOL)
783 // Third arg is 16 as outVal is a hex Number
784 uint64_t value = strtol (outVal, &endPtr, 16);
786 if (errno != 0 || *endPtr != 0)
790 // value COULD be a bit mask and the LSB indicates boolean true/false.
791 // If not a bit mask, it'll be plain 0 or 1.
793 boolRes = OCRepPayloadSetPropBool(*payload,
794 attributeList.list[i].oicAttribute,
801 if (boolRes == false)
803 stackResult = OC_EH_ERROR;
808 for(; attributeListIndex < attributeList.count; attributeListIndex++)
810 OICFree(attributeList.list[attributeListIndex].oicAttribute);
815 OCEntityHandlerResult processPutRequest(PIPluginBase * plugin,
816 OCEntityHandlerRequest *ehRequest, OCRepPayload **payload)
818 if (!plugin || !ehRequest || !payload)
822 OCStackResult stackResult = OC_STACK_OK;
823 PIResource_Zigbee *piResource = NULL;
824 AttributeList attributeList = {
827 .list[0] = { NULL, NULL, OIC_ATTR_NULL, ZB_NULL, { .i = 0 } }
830 stackResult = GetResourceFromHandle(plugin,
831 ((PIResource **) (&piResource)),
832 ehRequest->resource);
833 if (stackResult != OC_STACK_OK)
835 OC_LOG (ERROR, TAG, "Failed to get resource from handle");
839 bool boolRes = getZigBeeAttributesIfValid (
840 piResource->header.piResource.resourceTypeName,
841 &attributeList, *payload);
844 OC_LOG_V (ERROR, TAG, "Failed to fetch attributes for %s",
845 piResource->header.piResource.resourceTypeName);
850 for(; i<attributeList.count; i++)
852 if (attributeList.list[i].oicType == OIC_ATTR_INT)
854 char value[MAX_STRLEN_INT] = {};
855 if (attributeList.CIEMask || CIE_MOVE_TO_LEVEL)
857 int64_t rangeDiff = 0;
858 // OIC Dimming operates between 0-100, while Zigbee
859 // operates between 0-254 (ie. 0xFE).
860 rangeDiff = attributeList.list[i].val.i * 0xFE/100;
861 if (rangeDiff > 0xFE)
869 if (rangeDiff <= 0xFE)
871 snprintf(value, sizeof(value), "%02x", (unsigned int) rangeDiff);
873 stackResult = TWMoveToLevel(piResource->nodeId, piResource->endpointId,
874 DEFAULT_MOVETOLEVEL_MODE, value, DEFAULT_TRANS_TIME);
878 snprintf(value, sizeof(value), "%"PRId64, attributeList.list[i].val.i);
879 stackResult = TWSetAttribute(piResource->eui,
880 piResource->nodeId, piResource->endpointId,
881 piResource->clusterId, attributeList.list[i].zigBeeAttribute,
882 getZBDataTypeString(attributeList.list[i].zigbeeType), value);
884 if (stackResult != OC_STACK_OK)
889 else if (attributeList.list[i].oicType == OIC_ATTR_DOUBLE)
891 char value[MAX_STRLEN_DOUBLE] = {};
892 snprintf(value, sizeof(value), "%f", attributeList.list[i].val.d);
893 stackResult = TWSetAttribute(piResource->eui,
894 piResource->nodeId, piResource->endpointId,
895 piResource->clusterId, attributeList.list[i].zigBeeAttribute,
896 getZBDataTypeString(attributeList.list[i].zigbeeType), value);
898 else if (attributeList.list[i].oicType == OIC_ATTR_STRING)
900 stackResult = TWSetAttribute(piResource->eui,
901 piResource->nodeId, piResource->endpointId,
902 piResource->clusterId, attributeList.list[i].zigBeeAttribute,
903 getZBDataTypeString(attributeList.list[i].zigbeeType),
904 attributeList.list[i].val.str);
905 if (stackResult != OC_STACK_OK)
910 else if (attributeList.list[i].oicType == OIC_ATTR_BOOL)
912 char * value = attributeList.list[i].val.b ? "1" : "0";
913 if (attributeList.CIEMask || CIE_RON_OFF)
915 stackResult = TWSwitchOnOff(piResource->nodeId, piResource->endpointId, value);
919 stackResult = TWSetAttribute(piResource->eui,
920 piResource->nodeId, piResource->endpointId,
921 piResource->clusterId, attributeList.list[i].zigBeeAttribute,
922 getZBDataTypeString(attributeList.list[i].zigbeeType),
925 if (stackResult != OC_STACK_OK)
936 return processGetRequest(plugin, ehRequest, payload);
939 OCEntityHandlerResult ProcessEHRequest(PIPluginBase * plugin,
940 OCEntityHandlerRequest *ehRequest, OCRepPayload **payload)
942 if(!ehRequest || !payload)
946 if(ehRequest->method == OC_REST_GET)
948 return processGetRequest(plugin, ehRequest, payload);
950 else if(ehRequest->method == OC_REST_PUT)
952 return processPutRequest(plugin, ehRequest, payload);
956 return OC_EH_FORBIDDEN;
960 char * getZBDataTypeString(ZigBeeAttributeDataType attrType)
965 return ZB_DATA_TYPE_NULL;
967 return ZB_DATA_TYPE_1_BYTE;
969 return ZB_DATA_TYPE_2_BYTE;
971 return ZB_DATA_TYPE_3_BYTE;
973 return ZB_DATA_TYPE_4_BYTE;
975 return ZB_DATA_TYPE_5_BYTE;
977 return ZB_DATA_TYPE_6_BYTE;
979 return ZB_DATA_TYPE_7_BYTE;
981 return ZB_DATA_TYPE_8_BYTE;
983 return ZB_DATA_TYPE_BOOL;
985 return ZB_DATA_TYPE_1_BYTE;
987 return ZB_DATA_TYPE_2_BYTE;
989 return ZB_DATA_TYPE_3_BYTE;
991 return ZB_DATA_TYPE_4_BYTE;
993 return ZB_DATA_TYPE_5_BYTE;
995 return ZB_DATA_TYPE_6_BYTE;
997 return ZB_DATA_TYPE_7_BYTE;
999 return ZB_DATA_TYPE_8_BYTE;
1001 return ZB_DATA_TYPE_SIGNED_INT_16;
1003 return ZB_DATA_TYPE_UNSIGNED_INT_8;
1005 return ZB_DATA_TYPE_UNSIGNED_INT_16;
1007 return ZB_DATA_TYPE_NULL;