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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
33 #include "oic_string.h"
34 #include "oic_malloc.h"
38 #include "telegesis_socket.h"
39 #include "telegesis_wrapper.h"
42 #define TAG PCF("telegesiswrapper") // Module Name
44 #define ARRAY_LENGTH 100
46 #define RESPONSE_PARAMS_COUNT_NETWORK_INFO_1 (1)
47 #define RESPONSE_PARAMS_COUNT_NETWORK_INFO_5 (5)
48 #define RESPONSE_PARAMS_COUNT_JPAN (3)
49 #define RESPONSE_PARAMS_COUNT_DEVICE_JOINED (2)
50 #define RESPONSE_PARAMS_COUNT_MATCH_DESC (3)
51 #define RESPONSE_PARAMS_COUNT_SIMPLE_DESC (2)
52 #define RESPONSE_PARAMS_COUNT_SIMPLE_DESC_IN_CLUSTER_MIN (1)
53 #define RESPONSE_PARAMS_COUNT_WRITE_ATTR_4 (4)
54 #define RESPONSE_PARAMS_COUNT_WRITE_ATTR_5 (5)
55 #define RESPONSE_PARAMS_COUNT_TEMPERATURE (5)
56 #define RESPONSE_PARAMS_COUNT_RESPATTR (6)
57 #define RESPONSE_PARAMS_COUNT_ADDRESS_RESPONSE (3)
58 #define RESPONSE_PARAMS_COUNT_DFTREP (5)
59 #define RESPONSE_PARAMS_COUNT_DRLOCKUNLOCKRSP (3)
60 #define RESPONSE_PARAMS_COUNT_ZENROLLREQ (4)
61 #define RESPONSE_PARAMS_COUNT_ENROLLED (3)
62 #define RESPONSE_PARAMS_COUNT_ZONESTATUS_4 (4)
63 #define RESPONSE_PARAMS_COUNT_ZONESTATUS_6 (6)
65 //-----------------------------------------------------------------------------
66 // Private internal function prototypes
67 //-----------------------------------------------------------------------------
69 static TWResultCode HandleATResponse(TWEntry* entry);
71 static TWResultCode processEntry(TWEntry* entry);
72 static TWResultCode processEntryNETWORK_INFO(TWEntry* entry);
73 static TWResultCode processEntryJPAN(TWEntry* entry);
74 static TWResultCode processEntryEndDevice(TWEntry* entry);
75 static TWResultCode processEntryMatchDesc(TWEntry* entry);
76 static TWResultCode processEntrySimpleDesc(TWEntry* entry);
77 static TWResultCode processEntryWriteAttr(TWEntry* entry);
78 static TWResultCode processEntryReadAttr(TWEntry* entry);
79 static TWResultCode processEntryTemperature(TWEntry* entry);
80 static TWResultCode processEntrySwitchDoorLockState(TWEntry* entry);
81 static TWResultCode processEntryZCLDefaultResponse(TWEntry* entry);
82 static TWResultCode processEntryZoneEnrollRequest(TWEntry* entry);
83 static TWResultCode processEntryEnrolled(TWEntry* entry);
84 static TWResultCode processEntryZoneStatus(TWEntry* entry);
85 static TWResultCode processEntryAddressResponse(TWEntry* entry);
87 static TWResultCode Reset();
88 static TWResultCode GetRemoteEUI();
89 static TWResultCode CreatePAN();
90 static TWResultCode EnableJoin(bool isKeyEncrypted);
91 static TWResultCode FindMatchNodes();
92 static TWResultCode FindClusters(char nodeId[], char endpoint[]);
94 static TWResultCode TelNetworkInfoHandler(int count, char* tokens[]);
95 static TWResultCode TelJpanHandler(int count, char* tokens[]);
96 static TWResultCode TelEndDeviceJoinHandler(int count, char* tokens[]);
97 static TWResultCode TelMatchDescHandler(int count, char* tokens[]);
98 static TWResultCode TelAddressResponseHandler(int count, char* tokens[]);
99 static TWResultCode TelSimpleDescHandler(int count, char* tokens[]);
100 static TWResultCode TelSimpleDescInClusterHandler(int count, char* tokens[]);
101 static TWResultCode TelWriteAttrHandler(int count, char* tokens[]);
102 static TWResultCode TelReadAttrHandler(int count, char* tokens[]);
103 static TWResultCode TelReadAttrHandlerTemperature(int count, char* tokens[]);
104 static TWResultCode TelZCLDefaultResponseHandler(int count, char* tokens[]);
105 static TWResultCode TelSwitchDoorLockStateHandler(int count, char* tokens[]);
106 static TWResultCode TelZoneEnrollRequestHandler(int count, char* tokens[]);
107 static TWResultCode TelEnrolledHandler(int count, char* tokens[]);
108 static TWResultCode TelZoneStatusHandler(int count, char* tokens[]);
110 static TWResultCode AsciiHexToValue(char* hexString, int length, uint64_t* value);
111 static int AsciiToHex(char c);
112 static int Tokenize(const char *input, const char* delimiters, char* output[]);
114 static void DeallocateTWDeviceList();
116 //-----------------------------------------------------------------------------
118 //-----------------------------------------------------------------------------
120 static TWATResultHandlerPair g_TWATResultHandlerPairArray[] =
122 {"+N=", TelNetworkInfoHandler},
123 {"JPAN:", TelJpanHandler},
124 {"RFD:", TelEndDeviceJoinHandler}, //e.g SmartThings Open/Closed Sensor
125 {"FFD:", TelEndDeviceJoinHandler}, //e.g SmartThings Plug
126 {"SED:", TelEndDeviceJoinHandler},
127 {"ZED:", TelEndDeviceJoinHandler},
128 {"MatchDesc:", TelMatchDescHandler},
129 {"SimpleDesc:", TelSimpleDescHandler},
130 {"InCluster:", TelSimpleDescInClusterHandler},
131 {"WRITEATTR:", TelWriteAttrHandler},
132 {"RESPATTR:", TelReadAttrHandler},
133 {"TEMPERATURE:",TelReadAttrHandlerTemperature},
134 {"DFTREP", TelZCLDefaultResponseHandler},
135 {"DRLOCRSP:", TelSwitchDoorLockStateHandler},
136 {"DRUNLOCKRSP:",TelSwitchDoorLockStateHandler},
137 {"ZENROLLREQ:", TelZoneEnrollRequestHandler},
138 {"ENROLLED:", TelEnrolledHandler},
139 {"ZONESTATUS:", TelZoneStatusHandler},
140 {"AddrResp:", TelAddressResponseHandler},
141 {"Unknown:", TelNetworkInfoHandler}
144 //TODO: Take care of all global variables
145 static PIPlugin* g_plugin = (PIPlugin*)1;
146 static const char* g_port = NULL;
148 static char g_LocalEUI[SIZE_EUI] = "";
149 static char g_WIPRemoteEUI[SIZE_EUI] = "";
150 static char g_WIPRemoteNodeId[SIZE_NODEID] = "";
152 static TWStatus g_ZigBeeStatus = {ZB_STATE_UNKNOWN,0,0,NULL,0};
153 static TWDeviceList* g_FoundMatchedDeviceList = NULL;
154 static TWDevice* g_WIPDevice = NULL;
156 static TWDeviceFoundCallback g_DeviceFoundCallback = NULL;
157 static TWEnrollmentSucceedCallback g_EnrollmentSucceedCallback = NULL;
158 static TWDeviceStatusUpdateCallback g_DeviceStatusUpdateCallback = NULL;
160 /*****************************************************************************/
162 /* Public functions */
164 /*****************************************************************************/
165 OCStackResult TWInitialize(const char* deviceDevPath)
167 OC_LOG_V(INFO, TAG, "Enter TWInitialize()");
169 TWResultCode twCode = TW_RESULT_ERROR;
171 g_port = deviceDevPath;
172 OC_LOG_V(INFO, TAG, "Attempt to open %s", deviceDevPath);
174 twCode = TWStartSock(g_plugin, deviceDevPath); //TODO:
176 if (twCode != TW_RESULT_OK)
178 OC_LOG_V(ERROR, TAG, "Failed to open %s because of error: %d", deviceDevPath, twCode);
179 return OC_STACK_ERROR;
183 twCode = TWGetEUI(g_plugin, &eui);
184 if (twCode != TW_RESULT_OK)
186 OC_LOG_V(ERROR, TAG, "Failed to get EUI because of error: %d", twCode);
187 return OC_STACK_ERROR;
189 OICStrcpy(g_LocalEUI, SIZE_EUI, eui);
190 OC_LOG_V(INFO, TAG, "LocalEUI=%s", g_LocalEUI);
193 bool wantReset = false; //TODO:
197 if (twCode != TW_RESULT_OK)
199 OC_LOG_V(ERROR, TAG, "ZigBee Initialization - Reset");
200 return OC_STACK_ERROR;
204 twCode = CreatePAN();
205 if (twCode != TW_RESULT_OK)
207 OC_LOG_V(ERROR, TAG, "CreatePan Failed");
208 OC_LOG_V(ERROR, TAG, "TWInitialize() - MUST STOP NOW");
209 g_ZigBeeStatus.state = ZB_STATE_UNKNOWN;
210 return OC_STACK_ERROR;
214 OC_LOG_V(INFO, TAG, "CreatePan Succeed");
215 OC_LOG_V(INFO, TAG, "TWInitialize() Succeed");
220 OCStackResult TWDiscover()
222 OC_LOG_V(INFO, TAG, "Enter TWDiscover()");
224 OCStackResult ret = OC_STACK_ERROR;
225 TWResultCode twRet = TW_RESULT_ERROR;
227 if (g_DeviceFoundCallback == NULL)
229 OC_LOG_V(INFO, TAG, "Required TWDeviceFoundCallback.");
230 return OC_STACK_ERROR;
233 twRet = EnableJoin(false);
234 if (twRet != TW_RESULT_OK)
236 OC_LOG_V(ERROR, TAG, "EnableJoin");
237 return OC_STACK_ERROR;
240 twRet = FindMatchNodes();
241 if (twRet == TW_RESULT_OK)
243 OC_LOG_V(INFO, TAG, "FindMatchNodes");
248 OC_LOG_V(ERROR, TAG, "FindMatchNodes");
249 ret = OC_STACK_ERROR;
252 OC_LOG_V(INFO, TAG, "Leave TWDiscover() with ret=%d", ret);
256 OCStackResult TWSetAttribute(char* extendedUniqueId, char* nodeId, char* endpointId,
257 char* clusterId, char* attributeId, char* attributeType,
260 //Ask: AT+WRITEATR:5DA7,01,0,0003,0000,21,01
262 OC_LOG_V(INFO, TAG, "Enter TWSetAttribute()");
264 (void)extendedUniqueId;
266 OCStackResult ret = OC_STACK_ERROR;
267 TWResultCode twRet = TW_RESULT_ERROR;
269 int size = strlen(AT_CMD_WRITE_ATR) + strlen(nodeId) +
270 SEPARATOR_LENGTH + strlen(endpointId) +
271 SEPARATOR_LENGTH + strlen(SENDMODE) +
272 SEPARATOR_LENGTH + strlen(clusterId) +
273 SEPARATOR_LENGTH + strlen(attributeId) +
274 SEPARATOR_LENGTH + strlen(attributeType) +
275 SEPARATOR_LENGTH + strlen(newValue) + 1;
277 char* cmdString = (char*)OICMalloc(size * sizeof(char));
278 if (cmdString == NULL)
280 OC_LOG_V(ERROR, TAG, "No Memory");
281 ret = OC_STACK_ERROR;
284 snprintf(cmdString, size, "%s%s,%s,%s,%s,%s,%s,%s",
285 AT_CMD_WRITE_ATR, nodeId, endpointId, SENDMODE,
286 clusterId, attributeId, attributeType, newValue);
288 twRet = TWIssueATCommand(g_plugin, cmdString);
289 if (twRet != TW_RESULT_OK)
291 OC_LOG_V(ERROR, TAG, "Write %s", cmdString);
292 ret = OC_STACK_ERROR;
295 OC_LOG_V(INFO, TAG, "Write %s", cmdString);
297 TWEntry* entry = NULL;
298 twRet = TWDequeueEntry(g_plugin, &entry, TW_WRITEATTR);
299 if (twRet != TW_RESULT_OK)
301 OC_LOG_V(ERROR, TAG, "TWDequeueEntry");
302 ret = OC_STACK_ERROR;
307 OC_LOG_V(INFO, TAG, "TWEntry is NULL.");
308 ret = OC_STACK_ERROR;
312 twRet = processEntry(entry);
313 if (twRet != TW_RESULT_OK)
315 OC_LOG_V(ERROR, TAG, "processEntry");
316 ret = OC_STACK_ERROR;
323 TWDeleteEntry(g_plugin, entry);
325 OC_LOG_V(INFO, TAG, "Leave TWSetAttribute() with ret=%d", ret);
329 OCStackResult TWGetAttribute(char* extendedUniqueId, char* nodeId, char* endpointId,
330 char* clusterId, char* attributeId,
331 char** outValue, uint8_t* outValueLength)
333 //Ask: AT+READATR:FE5A,01,0,0402,0002
335 OC_LOG_V(INFO, TAG, "Enter TWGetAttribute()");
337 (void)extendedUniqueId;
339 OCStackResult ret = OC_STACK_ERROR;
340 TWResultCode twRet = TW_RESULT_ERROR;
342 int size = strlen(AT_CMD_READ_ATR) + strlen(nodeId) +
343 SEPARATOR_LENGTH + strlen(endpointId) +
344 SEPARATOR_LENGTH + strlen(SENDMODE) +
345 SEPARATOR_LENGTH + strlen(clusterId) +
346 SEPARATOR_LENGTH + strlen(attributeId) + 1;
348 char* cmdString = (char*)OICMalloc(size * sizeof(char));
349 if (cmdString == NULL)
351 OC_LOG_V(ERROR, TAG, "No Memory");
352 ret = OC_STACK_NO_MEMORY;
355 int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s",
356 AT_CMD_READ_ATR, nodeId,
357 SEPARATOR, endpointId,
359 SEPARATOR, clusterId,
360 SEPARATOR, attributeId);
363 OC_LOG_V(ERROR, TAG, "Build command error.");
364 ret = OC_STACK_ERROR;
367 twRet = TWIssueATCommand(g_plugin, cmdString);
368 if (twRet != TW_RESULT_OK)
370 OC_LOG_V(ERROR, TAG, "Write %s", cmdString);
371 ret = OC_STACK_ERROR;
374 OC_LOG_V(INFO, TAG, "Write %s", cmdString);
376 TWEntry* entry = NULL;
377 twRet = TWDequeueEntry(g_plugin, &entry, TW_RESPATTR);
378 if (twRet != TW_RESULT_OK)
380 OC_LOG_V(ERROR, TAG, "TWDequeueEntry");
381 ret = OC_STACK_ERROR;
386 OC_LOG_V(INFO, TAG, "TWEntry is NULL");
387 ret = OC_STACK_ERROR;
391 twRet = processEntry(entry);
392 if (twRet != TW_RESULT_REMOTE_ATTR_HAS_VALUE)
394 OC_LOG_V(ERROR, TAG, "processEntry.");
395 ret = OC_STACK_ERROR;
399 size = strlen(g_ZigBeeStatus.remoteAttributeValueRead) + 1;
400 *outValue = (char*)OICMalloc(sizeof(char) * size);
401 if (*outValue == NULL)
403 OC_LOG_V(ERROR, TAG, "No Memory");
404 ret = OC_STACK_NO_MEMORY;
408 OICStrcpy(*outValue, size, g_ZigBeeStatus.remoteAttributeValueRead);
409 *outValueLength = g_ZigBeeStatus.remoteAtrributeValueReadLength;
410 OICFree(g_ZigBeeStatus.remoteAttributeValueRead);
411 g_ZigBeeStatus.remoteAttributeValueRead = NULL;
412 g_ZigBeeStatus.remoteAtrributeValueReadLength = 0;
413 OC_LOG_V(INFO, TAG, "TWGetAttribute() gets an attribute value.");
417 TWDeleteEntry(g_plugin, entry);
419 OC_LOG_V(INFO, TAG, "Leave TWGetAttribute() with ret=%d", ret);
423 OCStackResult TWSwitchOnOff(char* nodeId, char* endpointId, char* newState)
425 //AT+RONOFF:<Address>,<EP>,<SendMode>[,<ON/OFF>]
426 //AT+RONOFF:9E2B,01,0,1
428 // DFTREP:9E2B,01,0006,01,00
430 OC_LOG_V(INFO, TAG, "Enter TWSwitchOnOff()");
432 OCStackResult ret = OC_STACK_ERROR;
433 TWResultCode twRet = TW_RESULT_UNKNOWN;
436 if (newState == NULL)
438 size = strlen(AT_CMD_RUN_ON_OFF) + strlen(nodeId) +
439 SEPARATOR_LENGTH + strlen(endpointId) +
440 SEPARATOR_LENGTH + strlen(SENDMODE) + 1;
444 size = strlen(AT_CMD_RUN_ON_OFF) + strlen(nodeId) +
445 SEPARATOR_LENGTH + strlen(endpointId) +
446 SEPARATOR_LENGTH + strlen(SENDMODE) +
447 SEPARATOR_LENGTH + strlen(newState) + 1;
450 char* cmdString = (char*)OICMalloc(size * sizeof(char));
451 if (cmdString == NULL)
453 OC_LOG_V(ERROR, TAG, "No Memory");
454 ret = OC_STACK_NO_MEMORY;
458 int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s",
459 AT_CMD_RUN_ON_OFF, nodeId, SEPARATOR,
460 endpointId, SEPARATOR, SENDMODE);
463 OC_LOG_V(ERROR, TAG, "Build command error.");
464 ret = OC_STACK_ERROR;
467 if (newState != NULL)
469 OICStrcat(cmdString, size, SEPARATOR);
470 OICStrcat(cmdString, size, newState);
473 twRet = TWIssueATCommand(g_plugin, cmdString);
474 if (twRet != TW_RESULT_OK)
476 OC_LOG_V(ERROR, TAG, "Write %s", cmdString);
477 ret = OC_STACK_ERROR;
480 OC_LOG_V(INFO, TAG, "Write %s", cmdString);
482 TWEntry* entry = NULL;
483 twRet = TWDequeueEntry(g_plugin, &entry, TW_DFTREP);
484 if (twRet != TW_RESULT_OK)
486 OC_LOG_V(ERROR, TAG, "TWDequeueEntry");
487 ret = OC_STACK_ERROR;
492 OC_LOG_V(ERROR, TAG, "TWEntry is NULL");
493 ret = OC_STACK_ERROR;
497 twRet = processEntry(entry);
498 if (twRet != TW_RESULT_OK)
500 OC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString);
501 ret = OC_STACK_ERROR;
508 TWDeleteEntry(g_plugin, entry);
510 OC_LOG_V(INFO, TAG, "Leave TWSwitchOnOff() with ret=%d", ret);
514 OCStackResult TWMoveToLevel(char* nodeId, char* endpointId,
515 char* onOffState, char* level, char* transTime)
517 //AT+LCMVTOLEV:<Address>,<EP>,<SendMode>,<ON/OFF>,<LevelValue>,<TransTime>
519 OC_LOG_V(INFO, TAG, "Enter TWMoveToLevel()");
521 OCStackResult ret = OC_STACK_ERROR;
522 TWResultCode twRet = TW_RESULT_UNKNOWN;
525 size = strlen(AT_CMD_MOVE_TO_LEVEL) + strlen(nodeId) +
526 SEPARATOR_LENGTH + strlen(endpointId) +
527 SEPARATOR_LENGTH + strlen(SENDMODE) +
528 SEPARATOR_LENGTH + strlen(onOffState) +
529 SEPARATOR_LENGTH + strlen(level) +
530 SEPARATOR_LENGTH + strlen(transTime) + 1;
532 char* cmdString = (char*)OICMalloc(size * sizeof(char));
533 if (cmdString == NULL)
535 OC_LOG_V(ERROR, TAG, "No Memory");
536 ret = OC_STACK_NO_MEMORY;
540 int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s%s%s",
541 AT_CMD_MOVE_TO_LEVEL, nodeId,
542 SEPARATOR, endpointId,
544 SEPARATOR, onOffState,
546 SEPARATOR, transTime);
549 OC_LOG_V(ERROR, TAG, "Build command error.");
550 ret = OC_STACK_ERROR;
554 twRet = TWIssueATCommand(g_plugin, cmdString);
555 if (twRet != TW_RESULT_OK)
557 OC_LOG_V(ERROR, TAG, "Write %s", cmdString);
558 ret = OC_STACK_ERROR;
562 OC_LOG_V(INFO, TAG, "Write %s", cmdString);
564 TWEntry* entry = NULL;
565 twRet = TWDequeueEntry(g_plugin, &entry, TW_DFTREP);
566 if (twRet != TW_RESULT_OK)
568 OC_LOG_V(ERROR, TAG, "TWDequeueEntry");
569 ret = OC_STACK_ERROR;
574 OC_LOG_V(ERROR, TAG, "TWEntry is NULL");
575 ret = OC_STACK_ERROR;
579 twRet = processEntry(entry);
580 if (twRet != TW_RESULT_OK)
582 OC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString);
583 ret = OC_STACK_ERROR;
590 TWDeleteEntry(g_plugin, entry);
592 OC_LOG_V(INFO, TAG, "Leave TWMoveToLevel() with ret=%d", ret);
596 OCStackResult TWSwitchDoorLockState(char* nodeId, char* endpointId, char* newState)
598 //AT+DRLOCK:<Address>,<EP>,<SendMode>,<Lock/Unlock>
600 OC_LOG_V(INFO, TAG, "Enter TWSwitchDoorLockState()");
602 OCStackResult ret = OC_STACK_ERROR;
603 TWResultCode twRet = TW_RESULT_UNKNOWN;
606 size = strlen(AT_CMD_DOOR_LOCK) + strlen(nodeId) +
607 SEPARATOR_LENGTH + strlen(endpointId) +
608 SEPARATOR_LENGTH + strlen(SENDMODE) +
609 SEPARATOR_LENGTH + strlen(newState) + 1;
611 char* cmdString = (char*)OICMalloc(size * sizeof(char));
612 if (cmdString == NULL)
614 OC_LOG_V(ERROR, TAG, "No Memory");
615 ret = OC_STACK_NO_MEMORY;
619 int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s%s%s",
620 AT_CMD_DOOR_LOCK, nodeId,
621 SEPARATOR, endpointId,
623 SEPARATOR, newState);
626 OC_LOG_V(ERROR, TAG, "Build command error.");
627 ret = OC_STACK_ERROR;
631 twRet = TWIssueATCommand(g_plugin, cmdString);
632 if (twRet != TW_RESULT_OK)
634 OC_LOG_V(ERROR, TAG, "Write %s", cmdString);
635 ret = OC_STACK_ERROR;
639 OC_LOG_V(INFO, TAG, "Write %s", cmdString);
641 TWEntry* entry = NULL;
642 twRet = TWDequeueEntry(g_plugin, &entry, TW_DFTREP);
643 if (twRet != TW_RESULT_OK)
645 OC_LOG_V(ERROR, TAG, "TWDequeueEntry");
646 ret = OC_STACK_ERROR;
652 OC_LOG_V(ERROR, TAG, "TWEntry is NULL");
653 ret = OC_STACK_ERROR;
657 twRet = processEntry(entry);
658 if (twRet != TW_RESULT_OK)
660 OC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString);
661 ret = OC_STACK_ERROR;
668 TWDeleteEntry(g_plugin, entry);
670 OC_LOG_V(INFO, TAG, "Leave TWSwitchDoorLockState() with ret=%d", ret);
674 OCStackResult TWColorMoveToColorTemperature(char* nodeId, char* endpointId,
675 char* colorTemperature, char* transTime)
678 //AT+CCMVTOCT:<Address>,<EP>,<SendMode>,<ColorTemperature>,<TransTime>
682 OC_LOG_V(INFO, TAG, "Enter TWColorMoveToColorTemperature()");
684 OCStackResult ret = OC_STACK_ERROR;
685 TWResultCode twRet = TW_RESULT_UNKNOWN;
688 size = strlen(AT_CMD_COLOR_CTRL_MOVE_TO_COLOR_TEMPERATURE) + strlen(nodeId) +
689 SEPARATOR_LENGTH + strlen(endpointId) +
690 SEPARATOR_LENGTH + strlen(SENDMODE) +
691 SEPARATOR_LENGTH + strlen(colorTemperature) +
692 SEPARATOR_LENGTH + strlen(transTime) + 1;
694 char* cmdString = (char*)OICMalloc(size * sizeof(char));
695 if (cmdString == NULL)
697 OC_LOG_V(ERROR, TAG, "No Memory");
698 ret = OC_STACK_NO_MEMORY;
702 int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s",
703 AT_CMD_COLOR_CTRL_MOVE_TO_COLOR_TEMPERATURE, nodeId,
704 SEPARATOR, endpointId,
706 SEPARATOR, colorTemperature,
707 SEPARATOR, transTime);
710 OC_LOG_V(ERROR, TAG, "Build command error.");
711 ret = OC_STACK_ERROR;
714 twRet = TWIssueATCommand(g_plugin, cmdString);
715 if (twRet != TW_RESULT_OK)
717 OC_LOG_V(ERROR, TAG, "Write %s", cmdString);
718 ret = OC_STACK_ERROR;
721 OC_LOG_V(INFO, TAG, "Write %s", cmdString);
723 TWEntry* entry = NULL;
724 twRet = TWDequeueEntry(g_plugin, &entry, TW_DFTREP);
725 if (twRet != TW_RESULT_OK)
727 OC_LOG_V(ERROR, TAG, "TWDequeueEntry - %s", cmdString);
728 ret = OC_STACK_ERROR;
733 OC_LOG_V(ERROR, TAG, "TWEntry is NULL - %s", cmdString);
734 ret = OC_STACK_ERROR;
738 twRet = processEntry(entry);
739 if (twRet != TW_RESULT_OK)
741 OC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString);
742 ret = OC_STACK_ERROR;
749 TWDeleteEntry(g_plugin, entry);
751 OC_LOG_V(INFO, TAG, "Leave TWColorMoveToColorTemperature() with ret=%d", ret);
755 OCStackResult TWSetDiscoveryCallback(const TWDeviceFoundCallback callback)
757 OC_LOG_V(INFO, TAG, "Enter TWSetDiscoveryCallback()");
758 if (callback != NULL)
760 g_DeviceFoundCallback= callback;
764 g_DeviceFoundCallback = NULL;
767 OC_LOG_V(INFO, TAG, "Leave TWSetDiscoveryCallback() with ret=%d", OC_STACK_OK);
771 OCStackResult TWSetStatusUpdateCallback(TWDeviceStatusUpdateCallback callback)
773 OC_LOG_V(INFO, TAG, "Enter TWSetStatusUpdateCallback()");
774 if (callback != NULL)
776 g_DeviceStatusUpdateCallback= callback;
780 g_DeviceStatusUpdateCallback = NULL;
783 OC_LOG_V(INFO, TAG, "Leave TWSetStatusUpdateCallback() with ret=%d", OC_STACK_OK);
787 OCStackResult TWListenForStatusUpdates(char* nodeId, char* endpointId)
789 OC_LOG_V(INFO, TAG, "Enter TWListenForStatusUpdates()");
791 char* zoneClusterID = "0500";
792 char* zoneAttributeID = "0010";
793 char* attributeDateType = "F0";
795 OCStackResult ret = TWSetAttribute(NULL, nodeId, endpointId,
796 zoneClusterID, zoneAttributeID, attributeDateType,
799 OC_LOG_V(INFO, TAG, "Leave TWListenForStatusUpdates() with ret=%d", ret);
803 OCStackResult TWProcess()
806 TWResultCode ret = TW_RESULT_UNKNOWN;
810 TWEntry* entry = NULL;
811 ret = TWDequeueEntry(g_plugin, &entry, TW_NONE);
812 if (ret != TW_RESULT_OK)
814 OC_LOG_V(ERROR, TAG, "TWDequeueEntry");
815 ret = OC_STACK_ERROR;
824 ret = processEntry(entry);
825 if (ret != TW_RESULT_OK)
827 OC_LOG_V(ERROR, TAG, "processEntry");
828 ret = TWDeleteEntry(g_plugin, entry);
829 if(ret != TW_RESULT_OK)
831 OC_LOG_V(ERROR, TAG, "Failed to delete entry.");
832 ret = OC_STACK_ERROR;
838 OC_LOG_V(INFO, TAG, "processEntry");
839 ret = TWDeleteEntry(g_plugin, entry);
840 if(ret != TW_RESULT_OK)
842 OC_LOG_V(ERROR, TAG, "Failed to delete entry.");
843 ret = OC_STACK_ERROR;
852 OCStackResult TWUninitialize()
854 OC_LOG_V(INFO, TAG, "Enter TWUninitializeZigBee()");
855 OCStackResult ret = OC_STACK_ERROR;
857 TWResultCode twRet = TWStopSock(g_plugin);
858 if (twRet == TW_RESULT_OK)
860 OC_LOG_V(INFO, TAG, "TWStopSock");
865 OC_LOG_V(ERROR, TAG, "TWStopSock");
866 ret = OC_STACK_ERROR;
869 DeallocateTWDeviceList();
871 OC_LOG_V(INFO, TAG, "Leave TWUninitializeZigBee() with ret=%d", ret);
875 //-----------------------------------------------------------------------------
876 // Internal functions
877 //-----------------------------------------------------------------------------
879 TWResultCode processEntry(TWEntry *entry)
881 OC_LOG_V(INFO, TAG, "Enter processEntry()");
883 TWResultCode ret = TW_RESULT_UNKNOWN;
887 TW_OK, TODO: Joey to return an TWEntry for OK
888 TW_ERROR, TODO: Joey to return an TWEntry for ERROR
908 case TW_NETWORK_INFO:
909 ret = processEntryNETWORK_INFO(entry);
910 if ((ret != TW_RESULT_NO_LOCAL_PAN) &&
911 (ret != TW_RESULT_HAS_LOCAL_PAN))
913 OC_LOG_V(ERROR, TAG, "processEntryNETWORK_INFO.");
917 ret = processEntryJPAN(entry);
918 if (ret != TW_RESULT_OK)
920 OC_LOG_V(ERROR, TAG, "processEntryJPAN.");
924 ret = processEntryEndDevice(entry);
925 if (ret != TW_RESULT_OK)
927 OC_LOG_V(ERROR, TAG, "processEntrySED.");
931 ret = processEntryEndDevice(entry);
932 if (ret != TW_RESULT_OK)
934 OC_LOG_V(ERROR, TAG, "processEntryRFD.");
938 ret = processEntryEndDevice(entry);
939 if (ret != TW_RESULT_OK)
941 OC_LOG_V(ERROR, TAG, "processEntryFFD.");
945 ret = processEntryEndDevice(entry);
946 if (ret != TW_RESULT_OK)
948 OC_LOG_V(ERROR, TAG, "processEntryZED.");
952 ret = processEntryMatchDesc(entry);
953 if (ret != TW_RESULT_OK)
955 OC_LOG_V(ERROR, TAG, "processEntryMatchDesc.");
959 ret = processEntrySimpleDesc(entry);
960 if (ret != TW_RESULT_OK)
962 OC_LOG_V(ERROR, TAG, "processEntrySimpleDesc.");
966 ret = processEntryWriteAttr(entry);
967 if (ret != TW_RESULT_OK)
969 OC_LOG_V(ERROR, TAG, "processEntryWriteAttr.");
973 ret = processEntryReadAttr(entry);
974 if (ret != TW_RESULT_REMOTE_ATTR_HAS_VALUE)
976 OC_LOG_V(ERROR, TAG, "processEntryReadAttr.");
980 ret = processEntryTemperature(entry);
981 if (ret != TW_RESULT_REMOTE_ATTR_HAS_VALUE)
983 OC_LOG_V(ERROR, TAG, "processEntryTemperature.");
987 ret = processEntrySwitchDoorLockState(entry);
988 if (ret != TW_RESULT_OK)
990 OC_LOG_V(ERROR, TAG, "processEntrySwitchDoorLockState.");
994 ret = processEntrySwitchDoorLockState(entry);
995 if (ret != TW_RESULT_OK)
997 OC_LOG_V(ERROR, TAG, "processEntrySwitchDoorLockState.");
1001 ret = processEntryZCLDefaultResponse(entry);
1002 if (ret != TW_RESULT_OK)
1004 OC_LOG_V(ERROR, TAG, "processEntryZCLDefaultResponse.");
1008 ret = processEntryZoneEnrollRequest(entry);
1009 if (ret != TW_RESULT_OK)
1011 OC_LOG_V(ERROR, TAG, "processEntryZoneEnrollRequest.");
1015 ret = processEntryEnrolled(entry);
1016 if (ret != TW_RESULT_OK)
1018 OC_LOG_V(ERROR, TAG, "processEntryEnrolled.");
1022 ret = processEntryZoneStatus(entry);
1023 if (ret != TW_RESULT_OK)
1025 OC_LOG_V(ERROR, TAG, "processEntryZoneStatus.");
1028 case TW_ADDRESS_RESPONSE:
1029 ret = processEntryAddressResponse(entry);
1030 if (ret != TW_RESULT_OK)
1032 OC_LOG_V(ERROR, TAG, "processEntryAddressResponse.");
1036 OC_LOG_V(ERROR, TAG, "processEntry() doesn't receive an valid entry.");
1037 ret = TW_RESULT_ERROR;
1041 OC_LOG_V(INFO, TAG, "Leave processEntry() with ret=%d", ret);
1045 TWResultCode processEntryNETWORK_INFO(TWEntry* entry)
1053 // +N=COO,26,-6,7306,133F04EA669C6B24
1057 OC_LOG_V(INFO, TAG, "Enter processEntryNETWORK_INFO()");
1059 TWResultCode ret = TW_RESULT_UNKNOWN;
1061 if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0)
1063 OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode);
1064 ret = TW_RESULT_ERROR;
1068 ret = HandleATResponse(entry);
1071 OC_LOG_V(INFO, TAG, "Leave processEntryNETWORK_INFO() with ret=%d", ret);
1075 TWResultCode processEntryJPAN(TWEntry* entry)
1080 // JPAN:26,7306,133F04EA669C6B24
1086 OC_LOG_V(INFO, TAG, "Enter processEntryJPAN()");
1088 TWResultCode ret = TW_RESULT_UNKNOWN;
1089 if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) == 0)
1091 ret = HandleATResponse(entry);
1092 if (ret == TW_RESULT_NEW_LOCAL_PAN_ESTABLISHED)
1094 OC_LOG_V(INFO, TAG, "New Local PAN established.");
1099 ret = TW_RESULT_ERROR;
1102 else if (strcmp(entry->atErrorCode, AT_STR_ERROR_NODE_IS_PART_OF_PAN) == 0)
1104 OC_LOG_V(INFO, TAG, "Already Established PAN.");
1109 OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode);
1110 ret = TW_RESULT_ERROR;
1113 OC_LOG_V(INFO, TAG, "Leave processEntryJPAN() with ret=%d", ret);
1117 TWResultCode processEntryEndDevice(TWEntry* entry)
1119 OC_LOG_V(INFO, TAG, "Enter processEntryEndDevice()");
1121 TWResultCode ret = TW_RESULT_UNKNOWN;
1122 ret = HandleATResponse(entry);
1123 if (ret != TW_RESULT_OK)
1125 OC_LOG_V(ERROR, TAG, "HandleATResponse");
1128 OC_LOG_V(INFO, TAG, "Leave processEntryEndDevice() with ret=%d", ret);
1132 TWResultCode processEntryMatchDesc(TWEntry* entry)
1134 //MatchDesc:0B4A,00,01
1136 OC_LOG_V(INFO, TAG, "Enter processEntryMatchDesc()");
1137 TWResultCode ret = TW_RESULT_UNKNOWN;
1139 if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0)
1141 OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode);
1142 ret = TW_RESULT_ERROR;
1146 ret = HandleATResponse(entry);
1147 if (ret == TW_RESULT_OK)
1149 OC_LOG_V(INFO, TAG, "HandleATResponse");
1150 ret = FindClusters(g_WIPDevice->nodeId,
1151 g_WIPDevice->endpointOfInterest->endpointId);
1152 if (ret == TW_RESULT_OK)
1154 OC_LOG_V(INFO, TAG, "FindClusters - Found a match node");
1155 if (g_DeviceFoundCallback != NULL)
1157 OC_LOG_V(INFO, TAG, "Found a match node -- invoke callback");
1158 g_DeviceFoundCallback(g_WIPDevice);
1164 OC_LOG_V(ERROR, TAG, "FindClusters");
1165 ret = TW_RESULT_ERROR;
1170 OC_LOG_V(ERROR, TAG, "HandleATResponse");
1171 ret = TW_RESULT_ERROR;
1174 g_WIPDevice = NULL; //reset and do not deallocate it
1177 OC_LOG_V(INFO, TAG, "Leave processEntryMatchDesc() with ret=%d", ret);
1181 TWResultCode processEntrySimpleDesc(TWEntry* entry)
1184 //AT+SIMPLEDESC:3746,3746,01
1188 // SimpleDesc:3746,00
1192 // InCluster:0000,0001,0003,0402,0500,0020,0B05
1197 OC_LOG_V(INFO, TAG, "Enter processEntrySimpleDesc()");
1199 TWResultCode ret = TW_RESULT_UNKNOWN;
1201 if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0)
1203 OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", (entry->atErrorCode));
1204 ret = TW_RESULT_ERROR;
1208 if (entry->count == 6) //must be 6 as it is the number of lines to expect
1210 ret = HandleATResponse(entry);
1211 if (ret == TW_RESULT_HAS_CLUSTERS)
1213 OC_LOG_V(INFO, TAG, "has clusters.");
1219 OC_LOG_V(INFO, TAG, "Received an invalid Simple Descriptor.");
1220 ret = TW_RESULT_ERROR;
1224 OC_LOG_V(INFO, TAG, "Leave processEntrySimpleDesc() returns with ret=%d", ret);
1228 TWResultCode processEntryWriteAttr(TWEntry* entry)
1230 //AT+WRITEATR:3A3D,01,0,0003,0000,21,00
1232 // WRITEATTR:3A3D,01,0003,,00
1234 OC_LOG_V(INFO, TAG, "Enter processEntryWriteAttr()");
1236 TWResultCode ret = TW_RESULT_UNKNOWN;
1238 if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0)
1240 OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode);
1241 ret = TW_RESULT_ERROR;
1245 ret = HandleATResponse(entry);
1248 OC_LOG_V(INFO, TAG, "Leave processEntryWriteAttr() returns with ret=%d", ret);
1252 TWResultCode processEntryReadAttr(TWEntry* entry)
1254 OC_LOG_V(INFO, TAG, "Enter processEntryWriteAttr()");
1256 TWResultCode ret = TW_RESULT_UNKNOWN;
1258 if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0)
1260 OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode);
1261 ret = TW_RESULT_ERROR;
1265 ret = HandleATResponse(entry);
1268 OC_LOG_V(INFO, TAG, "Leave processEntryWriteAttr() returns with ret=%d", ret);
1272 TWResultCode processEntryTemperature(TWEntry* entry)
1274 OC_LOG_V(INFO, TAG, "Enter processEntryTemperature()");
1276 TWResultCode ret = TW_RESULT_UNKNOWN;
1278 if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0)
1280 OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode);
1281 ret = TW_RESULT_ERROR;
1285 ret = HandleATResponse(entry);
1288 OC_LOG_V(INFO, TAG, "Leave processEntryTemperature() returns with ret=%d", ret);
1292 TWResultCode processEntrySwitchDoorLockState(TWEntry* entry)
1294 OC_LOG_V(INFO, TAG, "Enter processEntrySwitchDoorLockState()");
1296 TWResultCode ret = TW_RESULT_UNKNOWN;
1298 if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0)
1300 OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode);
1301 ret = TW_RESULT_ERROR;
1305 ret = HandleATResponse(entry);
1308 OC_LOG_V(INFO, TAG, "Leave processEntrySwitchDoorLockState() returns with ret=%d", ret);
1312 TWResultCode processEntryZCLDefaultResponse(TWEntry* entry)
1314 OC_LOG_V(INFO, TAG, "Enter processEntryZCLDefaultResponse()");
1316 TWResultCode ret = TW_RESULT_UNKNOWN;
1318 if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0)
1320 if (strcmp(entry->atErrorCode, AT_STR_ERROR_MESSAGE_NOT_SENT_TO_TARGET_SUCCESSFULLY) == 0)
1322 OC_LOG_V(ERROR, TAG, "Send to the target not succeed.");
1323 ret = TW_RESULT_ERROR;
1327 OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode);
1328 ret = TW_RESULT_ERROR;
1333 ret = HandleATResponse(entry);
1336 OC_LOG_V(INFO, TAG, "Leave processEntryZCLDefaultResponse() returns with ret=%d", ret);
1340 TWResultCode processEntryZoneEnrollRequest(TWEntry* entry)
1342 OC_LOG_V(INFO, TAG, "Enter processEntryZoneEnrollRequest()");
1344 TWResultCode ret = TW_RESULT_UNKNOWN;
1345 if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0)
1347 OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode);
1348 ret = TW_RESULT_ERROR;
1352 ret = HandleATResponse(entry);
1355 OC_LOG_V(INFO, TAG, "Leave processEntryZoneEnrollRequest() with ret=%d", ret);
1359 TWResultCode processEntryEnrolled(TWEntry* entry)
1361 OC_LOG_V(INFO, TAG, "Enter processEntryEnrolled()");
1363 TWResultCode ret = TW_RESULT_UNKNOWN;
1364 if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0)
1366 OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode);
1367 ret = TW_RESULT_ERROR;
1371 ret = HandleATResponse(entry);
1374 OC_LOG_V(INFO, TAG, "Leave processEntryEnrolled() with ret=%d", ret);
1378 TWResultCode processEntryZoneStatus(TWEntry* entry)
1380 OC_LOG_V(INFO, TAG, "Enter processEntryZoneStatus()");
1382 TWResultCode ret = TW_RESULT_UNKNOWN;
1383 if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0)
1385 OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode);
1386 ret = TW_RESULT_ERROR;
1390 ret = HandleATResponse(entry);
1393 OC_LOG_V(INFO, TAG, "Leave processEntryZoneStatus() with ret=%d", ret);
1397 TWResultCode processEntryAddressResponse(TWEntry* entry)
1399 OC_LOG_V(INFO, TAG, "Enter processEntryAddressResponse()");
1401 TWResultCode ret = TW_RESULT_UNKNOWN;
1402 if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0)
1404 OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode);
1405 ret = TW_RESULT_ERROR;
1409 ret = HandleATResponse(entry);
1412 OC_LOG_V(INFO, TAG, "Leave processEntryAddressResponse() with ret=%d", ret);
1416 TWResultCode Reset()
1418 OC_LOG_V(INFO, TAG, "Enter Reset()");
1420 TWResultCode ret = TW_RESULT_ERROR;
1421 ret = TWIssueATCommand(g_plugin, AT_CMD_RESET);
1422 if (ret == TW_RESULT_OK)
1424 OC_LOG_V(INFO, TAG, "Write %s", AT_CMD_RESET);
1428 OC_LOG_V(ERROR, TAG, "Write %s", AT_CMD_RESET);
1430 OC_LOG_V(INFO, TAG, "Leave Reset() with ret=%d", ret);
1434 TWResultCode CreatePAN()
1442 // +N=COO,26,-6,7306,133F04EA669C6B24
1447 // JPAN:26,7306,133F04EA669C6B24
1453 OC_LOG_V(INFO, TAG, "Enter CreatePAN()");
1455 TWResultCode twRet1 = TW_RESULT_UNKNOWN;
1456 TWResultCode twRet2 = TW_RESULT_UNKNOWN;
1457 TWResultCode ret = TW_RESULT_UNKNOWN;
1458 ret = TWIssueATCommand(g_plugin, AT_CMD_GET_NETWORK_INFO);
1459 if (ret != TW_RESULT_OK)
1461 OC_LOG_V(ERROR, TAG, "Write %s", AT_CMD_GET_NETWORK_INFO);
1464 OC_LOG_V(INFO, TAG, "Write %s", AT_CMD_GET_NETWORK_INFO);
1465 TWEntry* entry = NULL;
1466 TWEntry* entry2 = NULL;
1467 ret = TWDequeueEntry(g_plugin, &entry, TW_NETWORK_INFO);
1468 if (ret != TW_RESULT_OK)
1470 OC_LOG_V(ERROR, TAG, "TWDequeueEntry - %s", AT_CMD_GET_NETWORK_INFO);
1475 OC_LOG_V(ERROR, TAG, "TWEntry is NULL - %s", AT_CMD_GET_NETWORK_INFO);
1476 ret = TW_RESULT_ERROR;
1479 ret = processEntry(entry);
1480 if (ret == TW_RESULT_HAS_LOCAL_PAN)
1482 OC_LOG_V(INFO, TAG, "Has local PAN.");
1485 else if (ret == TW_RESULT_NO_LOCAL_PAN)
1487 OC_LOG_V(INFO, TAG, "Has no local PAN.");
1488 ret = TWIssueATCommand(g_plugin, AT_CMD_ESTABLISH_NETWORK);
1489 if (ret != TW_RESULT_OK)
1491 OC_LOG_V(ERROR, TAG, "Write %s", AT_CMD_ESTABLISH_NETWORK);
1494 OC_LOG_V(INFO, TAG, "Write %s", AT_CMD_ESTABLISH_NETWORK);
1496 ret = TWDequeueEntry(g_plugin, &entry2, TW_JPAN);
1497 if (ret != TW_RESULT_OK)
1499 OC_LOG_V(ERROR, TAG, "TWDequeueEntry - %s", AT_CMD_ESTABLISH_NETWORK);
1504 OC_LOG_V(ERROR, TAG, "TWEntry is NULL - %s", AT_CMD_ESTABLISH_NETWORK);
1505 ret = TW_RESULT_ERROR;
1508 ret = processEntry(entry2);
1509 if (ret == TW_RESULT_OK)
1511 OC_LOG_V(INFO, TAG, "processEntry - %s", AT_CMD_ESTABLISH_NETWORK);
1512 g_ZigBeeStatus.state = ZB_STATE_INIT;
1517 OC_LOG_V(ERROR, TAG, "processEntry - %s", AT_CMD_ESTABLISH_NETWORK);
1518 ret = TW_RESULT_ERROR;
1523 OC_LOG_V(ERROR, TAG, "processEntry - unexpected return code: %d", ret);
1524 ret = TW_RESULT_ERROR;
1530 twRet1 = TWDeleteEntry(g_plugin, entry);
1531 if(twRet1 != TW_RESULT_OK)
1533 OC_LOG_V(ERROR, TAG, "TWDeleteEntry 1 - ret=%d", twRet1);
1538 twRet2 = TWDeleteEntry(g_plugin, entry2);
1539 if(twRet2 != TW_RESULT_OK)
1541 OC_LOG_V(ERROR, TAG, "TWDeleteEntry 2 - ret=%d", twRet2);
1545 OC_LOG_V(INFO, TAG, "Leave CreatePan with ret=%d", ret);
1549 TWResultCode EnableJoin(bool isKeyEncrypted)
1555 //Response: ERROR:70
1557 (void)isKeyEncrypted;
1558 isKeyEncrypted = false; //TODO: for now - don't encrypt
1560 TWResultCode ret = TW_RESULT_ERROR;
1561 char* joinTimeHex = "0F"; //TODO: for now - 15 seconds
1562 char* broadcast = "FFFC";
1564 int size = strlen(AT_CMD_PERMIT_JOIN) + strlen(joinTimeHex) +
1565 SEPARATOR_LENGTH + strlen(broadcast) + 1;
1566 char* cmdString = (char*)OICMalloc(size * sizeof(char));
1567 if (cmdString == NULL)
1569 OC_LOG_V(ERROR, TAG, "No Memory");
1570 ret = TW_RESULT_ERROR_NO_MEMORY;
1573 snprintf(cmdString, size, "%s%s%s%s",
1574 AT_CMD_PERMIT_JOIN, joinTimeHex, SEPARATOR, broadcast);
1575 ret = TWIssueATCommand(g_plugin, cmdString);
1576 if (ret != TW_RESULT_OK)
1578 OC_LOG_V(ERROR, TAG, "Write %s", cmdString);
1579 ret = TW_RESULT_ERROR;
1582 OC_LOG_V(INFO, TAG, "Write %s", cmdString);
1584 sleep(15); //must sleep here to permit joining for 15 seconds
1588 OC_LOG_V(INFO, TAG, "Leave EnableJoin() with ret=%d", ret);
1592 TWResultCode FindMatchNodes()
1594 //AT+MATCHREQ:0104,03,0003,0006,0402,00
1596 // MatchDesc:0B4A,00,01
1598 //AT+MATCHREQ:0104,03,0999,0999,0999,00
1601 OC_LOG_V(INFO, TAG, "Enter FindMatchNodes()");
1603 TWResultCode ret = TW_RESULT_UNKNOWN;
1605 char* profileHomeAutomation = "0104";
1606 char* inClusterCount = "04";
1607 char* outClusterCount = "00";
1609 //TODO: add more clusters
1610 char* clusterIdentify = "0003";
1611 char* clusterOnOff = "0006";
1612 char* clusterTemperatureMeasurement = "0402";
1613 char* clusterIASZone = "0500";
1615 int size = strlen(AT_CMD_MATCH_REQUEST) + strlen(profileHomeAutomation) +
1616 SEPARATOR_LENGTH + strlen(inClusterCount) +
1617 SEPARATOR_LENGTH + strlen(clusterIdentify) +
1618 SEPARATOR_LENGTH + strlen(clusterOnOff) +
1619 SEPARATOR_LENGTH + strlen(clusterTemperatureMeasurement) +
1620 SEPARATOR_LENGTH + strlen(clusterIASZone) +
1621 SEPARATOR_LENGTH + strlen(outClusterCount) + 1;
1623 char* cmdString = (char*)OICMalloc(size * sizeof(char));
1624 if (cmdString == NULL)
1626 OC_LOG_V(INFO, TAG, "No Memory");
1627 ret = TW_RESULT_ERROR_NO_MEMORY;
1631 int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
1632 AT_CMD_MATCH_REQUEST, profileHomeAutomation,
1633 SEPARATOR, inClusterCount,
1634 SEPARATOR, clusterIdentify,
1635 SEPARATOR, clusterOnOff,
1636 SEPARATOR, clusterTemperatureMeasurement,
1637 SEPARATOR, clusterIASZone,
1638 SEPARATOR, outClusterCount);
1641 OC_LOG_V(ERROR, TAG, "Build command error.");
1642 ret = OC_STACK_ERROR;
1645 ret = TWIssueATCommand(g_plugin, cmdString);
1646 if (ret != TW_RESULT_OK)
1648 OC_LOG_V(ERROR, TAG, "Write %s.", cmdString);
1651 OC_LOG_V(INFO, TAG, "Write %s.", cmdString);
1655 OC_LOG_V(INFO, TAG, "Leave FindMatchNodes() with ret=%d", ret);
1659 TWResultCode FindClusters(char nodeId[], char endpoint[])
1662 //AT+SIMPLEDESC:3746,3746,01
1666 // SimpleDesc:3746,00
1670 // InCluster:0000,0001,0003,0402,0500,0020,0B05
1676 OC_LOG_V(INFO, TAG, "Enter FindClusters()");
1678 TWResultCode ret = TW_RESULT_UNKNOWN;
1680 int size = strlen(AT_CMD_SIMPLE_DESC) + strlen(nodeId) +
1681 SEPARATOR_LENGTH + strlen(nodeId) +
1682 SEPARATOR_LENGTH + strlen(endpoint) + 1;
1684 char* cmdString = (char*)OICMalloc(size * sizeof(char));
1685 if (cmdString == NULL)
1687 OC_LOG_V(ERROR, TAG, "No Memory");
1688 ret = TW_RESULT_ERROR_NO_MEMORY;
1692 int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s",
1693 AT_CMD_SIMPLE_DESC, nodeId,
1695 SEPARATOR, endpoint);
1698 OC_LOG_V(ERROR, TAG, "Build command error.");
1699 ret = OC_STACK_ERROR;
1702 ret = TWIssueATCommand(g_plugin, cmdString);
1703 if (ret != TW_RESULT_OK)
1705 OC_LOG_V(ERROR, TAG, "Write %s", cmdString);
1706 ret = TW_RESULT_ERROR;
1709 OC_LOG_V(INFO, TAG, "Write %s", cmdString);
1711 TWEntry* entry = NULL;
1712 ret = TWDequeueEntry(g_plugin, &entry, TW_SIMPLEDESC);
1713 if (ret != TW_RESULT_OK)
1715 OC_LOG_V(ERROR, TAG, "TWDequeueEntry - %s", cmdString);
1720 OC_LOG_V(ERROR, TAG, "TWEntry is NULL - %s", cmdString);
1721 ret = TW_RESULT_ERROR;
1725 ret = processEntry(entry);
1726 if (ret == TW_RESULT_OK)
1728 OC_LOG_V(INFO, TAG, "processEntry - %s", cmdString);
1732 OC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString);
1736 TWDeleteEntry(g_plugin, entry);
1738 OC_LOG_V(INFO, TAG, "Leave FindClusters() with ret=%d", ret);
1742 TWResultCode GetRemoteEUI(char *nodeId, char* outRemoteEUI)
1744 //AT+EUIREQ:< Address>,<NodeID>[,XX]
1745 // AddrResp:<errorcode>[,<NodeID>,<EUI64>]
1746 // AddrResp:00,15ED,000D6F00040574B8
1748 OC_LOG_V(INFO, TAG, "Enter GetRemoteEUI()");
1749 TWResultCode ret = TW_RESULT_UNKNOWN;
1751 int size = strlen(AT_CMD_REMOTE_EUI_REQUEST) + strlen(nodeId) +
1752 SEPARATOR_LENGTH + strlen(nodeId) + 1;
1753 char* cmdString = (char*)OICMalloc(size * sizeof(char));
1754 if (cmdString == NULL)
1756 OC_LOG_V(ERROR, TAG, "No Memory");
1757 ret = TW_RESULT_ERROR_NO_MEMORY;
1761 int stringRet = snprintf(cmdString, size, "%s%s%s%s",
1762 AT_CMD_REMOTE_EUI_REQUEST, nodeId,
1766 OC_LOG_V(ERROR, TAG, "Build command error.");
1767 ret = OC_STACK_ERROR;
1770 ret = TWIssueATCommand(g_plugin, cmdString);
1771 if (ret != TW_RESULT_OK)
1773 OC_LOG_V(ERROR, TAG, "Write %s", cmdString);
1774 ret = TW_RESULT_ERROR;
1777 OC_LOG_V(INFO, TAG, "Write %s", cmdString);
1779 TWEntry* entry = NULL;
1780 ret = TWDequeueEntry(g_plugin, &entry, TW_ADDRESS_RESPONSE);
1781 if (ret != TW_RESULT_OK)
1783 OC_LOG_V(ERROR, TAG, "TWDequeueEntry - %s", cmdString);
1784 ret = TW_RESULT_ERROR;
1789 OC_LOG_V(ERROR, TAG, "TWEntry is NULL - %s", cmdString);
1790 ret = TW_RESULT_ERROR;
1794 ret = processEntry(entry);
1795 if (ret != TW_RESULT_OK)
1797 OC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString);
1798 ret = TW_RESULT_ERROR;
1801 OC_LOG_V(INFO, TAG, "Wanted eui of NodeID=%s ", nodeId);
1802 OC_LOG_V(INFO, TAG, "Received eui of g_WIPRemoteNodeId=%s ", g_WIPRemoteNodeId);
1803 if (strcmp(nodeId, g_WIPRemoteNodeId) != 0)
1805 OC_LOG_V(ERROR, TAG, "Received eui for an unexpected remote node id.");
1806 ret = TW_RESULT_ERROR;
1810 OC_LOG_V(INFO, TAG, "Remote NodeId:%s has EUI: %s \n",
1811 g_WIPRemoteNodeId, g_WIPRemoteEUI);
1812 OICStrcpy(outRemoteEUI, SIZE_EUI, g_WIPRemoteEUI);
1817 memset(g_WIPRemoteEUI, '\0', SIZE_EUI);
1818 memset(g_WIPRemoteNodeId, '\0', SIZE_NODEID);
1819 TWDeleteEntry(g_plugin, entry);
1821 OC_LOG_V(INFO, TAG, "Leave GetRemoteEUI() with ret=%d", ret);
1825 TWResultCode HandleATResponse(TWEntry* entry)
1827 OC_LOG_V(INFO, TAG, "Enter HandleATResponse()");
1829 TWResultCode ret = TW_RESULT_ERROR;
1832 for (; i < entry->count; i++)
1835 for (; k < sizeof(g_TWATResultHandlerPairArray)/sizeof(TWATResultHandlerPair); ++k)
1837 const char* line = (entry)->lines[i].line;
1839 g_TWATResultHandlerPairArray[k].resultTxt,
1840 strlen(g_TWATResultHandlerPairArray[k].resultTxt)
1843 char* tokens[ARRAY_LENGTH] = {};
1844 const char* delimiters = ",\r\n";
1845 int paramCount = Tokenize((entry)->lines[i].line +
1846 strlen(g_TWATResultHandlerPairArray[k].resultTxt),
1847 delimiters, tokens);
1850 ret = g_TWATResultHandlerPairArray[k].handler(paramCount, tokens);
1854 for (; n < paramCount; n++)
1864 OC_LOG_V(INFO, TAG, "Leave HandleATResponse() with ret=%d", ret);
1868 //-----------------------------------------------------------------------------
1869 // Internal functions - AT Response/Prompt Handlers
1870 //-----------------------------------------------------------------------------
1872 TWResultCode TelAddressResponseHandler(int count, char* tokens[])
1874 //AT+EUIREQ:< Address>,<NodeID>[,XX]
1875 // AddrResp:<errorcode>[,<NodeID>,<EUI64>]
1876 // AddrResp:00,15ED,000D6F00040574B8
1878 OC_LOG_V(INFO, TAG, "Enter TelAddressResponseHandler()");
1880 TWResultCode ret = TW_RESULT_UNKNOWN;
1882 if(!tokens || count != RESPONSE_PARAMS_COUNT_ADDRESS_RESPONSE)
1884 ret = TW_RESULT_ERROR_INVALID_PARAMS;
1888 if (strcmp(tokens[0], AT_STR_ERROR_OK) != 0)
1890 OC_LOG_V(ERROR, TAG, "AddrResp prompt contained error status.");
1891 ret = TW_RESULT_ERROR;
1895 OICStrcpy(g_WIPRemoteNodeId, SIZE_NODEID, tokens[1]);
1896 OICStrcpy(g_WIPRemoteEUI, SIZE_EUI, tokens[2]);
1897 OC_LOG_V(INFO, TAG, "Received eui %s for g_WIPRemoteNodeId=%s ",
1904 OC_LOG_V(INFO, TAG, "Leave TelAddressResponseHandler() with ret=%d", ret);
1908 TWResultCode TelNetworkInfoHandler(int count, char* tokens[])
1911 // Response: +N=COO,24,-6,9726,12BB200F073AB573
1915 // +N=<devicetype>,<channel>,<power>,<PANID>,<EPANID>
1917 OC_LOG_V(INFO, TAG, "Enter TelNetworkInfoHandler()");
1919 TWResultCode ret = TW_RESULT_UNKNOWN;
1922 ((count != RESPONSE_PARAMS_COUNT_NETWORK_INFO_1) &&
1923 (count != RESPONSE_PARAMS_COUNT_NETWORK_INFO_5)))
1925 ret = TW_RESULT_ERROR_INVALID_PARAMS;
1930 for (; i < count; ++i)
1932 if (tokens[i] != NULL)
1934 OC_LOG_V(INFO, TAG, "Token[%d] = %s", i, tokens[i]);
1938 char* temp = tokens[0];
1939 if (strcmp(temp, "NoPAN") == 0)
1941 OC_LOG_V(INFO, TAG, "It is NoPan.");
1942 ret = TW_RESULT_NO_LOCAL_PAN;
1946 OC_LOG_V(INFO, TAG, "Already have an established network.");
1947 ret = AsciiHexToValue(tokens[3], strlen(tokens[3]), &g_ZigBeeStatus.panId);
1948 if(ret != TW_RESULT_OK)
1950 OC_LOG_V(ERROR, TAG, "AsciiHexToValue - panId");
1953 ret = AsciiHexToValue(tokens[4], strlen(tokens[4]), &g_ZigBeeStatus.extPanId);
1954 if(ret != TW_RESULT_OK)
1956 OC_LOG_V(ERROR, TAG, "AsciiHexToValue - extPanId");
1959 OC_LOG_V(INFO, TAG, "PanId=%" PRId64 , g_ZigBeeStatus.panId);
1960 OC_LOG_V(INFO, TAG, "ExtPanId=%" PRId64 , g_ZigBeeStatus.extPanId);
1961 OC_LOG_V(INFO, TAG, "PanId=%s", tokens[3]);
1962 OC_LOG_V(INFO, TAG, "ExtPanId=%s", tokens[4]);
1964 OC_LOG_V(INFO, TAG, "TelNetworkInfoHandler set ExtPanId to %08X%08X",
1965 (unsigned int)(g_ZigBeeStatus.extPanId >> 32),
1966 (unsigned int)(g_ZigBeeStatus.extPanId & 0xFFFFFFFF));
1968 ret = TW_RESULT_HAS_LOCAL_PAN;
1971 OC_LOG_V(INFO, TAG, "Leave TelNetworkInfoHandler() with ret=%d", ret);
1975 TWResultCode TelJpanHandler(int count, char* tokens[])
1977 //Ask: AT+EN:[<channel>],[<POWER>],[<PANID>]
1978 //Response: JPAN:<channel>,<PANID>,<EPANID>
1980 OC_LOG_V(INFO, TAG, "Enter TelJpanHandler()");
1982 TWResultCode ret = TW_RESULT_UNKNOWN;
1984 if(!tokens || count != RESPONSE_PARAMS_COUNT_JPAN)
1986 ret = TW_RESULT_ERROR_INVALID_PARAMS;
1990 ret = AsciiHexToValue(tokens[1], strlen(tokens[1]), &g_ZigBeeStatus.panId);
1991 if(ret != TW_RESULT_OK)
1993 OC_LOG_V(ERROR, TAG, "AsciiHexToValue - panId");
1996 ret = AsciiHexToValue(tokens[2], strlen(tokens[2]), &g_ZigBeeStatus.extPanId);
1997 if(ret != TW_RESULT_OK)
1999 OC_LOG_V(ERROR, TAG, "AsciiHexToValue - extPanId");
2002 OC_LOG_V(INFO, TAG, "PanId = %" PRId64 "\n", g_ZigBeeStatus.panId);
2003 OC_LOG_V(INFO, TAG, "ExtPanId = %" PRId64 "\n", g_ZigBeeStatus.extPanId);
2004 ret = TW_RESULT_NEW_LOCAL_PAN_ESTABLISHED;
2007 OC_LOG_V(INFO, TAG, "Leave TelJpanHandler() with ret=%d", ret);
2011 TWResultCode TelEndDeviceJoinHandler(int count, char* tokens[])
2015 //Prompt: RFD:<IEEE Address>,<NodeID>
2016 //Prompt: FFD:<IEEE Address>,<NodeID>
2017 //Prompt: SED:<IEEE Address>,<NodeID>
2018 //Prompt: ZED:<IEEE Address>,<NodeID>
2020 OC_LOG_V(INFO, TAG, "Enter TelEndDeviceJoinHandler()");
2021 TWResultCode ret = TW_RESULT_UNKNOWN;
2023 if(!tokens || count != RESPONSE_PARAMS_COUNT_DEVICE_JOINED)
2025 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2029 //TODO: Might need to add into the list if needed - log it for now.
2030 OC_LOG_V(INFO, TAG, "Just Joined - EUI:%s; NodeID:%s.\n", tokens[0], tokens[1]);
2034 OC_LOG_V(INFO, TAG, "Leave TelEndDeviceJoinHandler() with ret=%d", ret);
2038 TWResultCode TelMatchDescHandler(int count, char* tokens[])
2040 //Prompt: MatchDesc:0B4A,00,01
2042 OC_LOG_V(INFO, TAG, "Enter TelMatchDescHandler()");
2043 TWResultCode ret = TW_RESULT_ERROR;
2045 if(!tokens || count != RESPONSE_PARAMS_COUNT_MATCH_DESC)
2047 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2051 if (strcmp(tokens[1], AT_STR_ERROR_OK) != 0)
2053 OC_LOG_V(INFO, TAG, "MatchDesc prompt contained error status.");
2054 ret = TW_RESULT_ERROR;
2059 char remoteEUI[SIZE_EUI];
2060 ret = GetRemoteEUI(tokens[0], remoteEUI);
2061 if (ret != TW_RESULT_OK)
2063 OC_LOG_V(ERROR, TAG, "GetRemoteEUI()");
2068 //Step 1: Create TWDevice
2069 TWDevice* device = (TWDevice*)OICCalloc(1, sizeof(TWDevice));
2072 ret = TW_RESULT_ERROR_NO_MEMORY;
2077 device->endpointOfInterest = (TWEndpoint*)OICCalloc(1, sizeof(TWEndpoint));
2078 if (device->endpointOfInterest == NULL)
2081 ret = TW_RESULT_ERROR_NO_MEMORY;
2085 OICStrcpy(device->eui, SIZE_EUI, remoteEUI);
2086 OICStrcpy(device->nodeId, SIZE_NODEID, tokens[0]);
2087 OICStrcpy(device->endpointOfInterest->endpointId, SIZE_ENDPOINTID, tokens[2]);
2088 g_WIPDevice = device;
2090 //Step 2: Add to list
2091 if (g_FoundMatchedDeviceList == NULL)
2093 //Create a list of promptCount entries
2094 g_FoundMatchedDeviceList = (TWDeviceList*)OICMalloc(sizeof(TWDeviceList));
2095 if (g_FoundMatchedDeviceList == NULL)
2097 OICFree(device->endpointOfInterest);
2099 ret = TW_RESULT_ERROR_NO_MEMORY;
2103 g_FoundMatchedDeviceList->count = 1;
2104 g_FoundMatchedDeviceList->deviceList =
2105 (TWDevice*)OICMalloc(sizeof(TWDevice));
2106 if (g_FoundMatchedDeviceList->deviceList == NULL)
2108 OICFree(device->endpointOfInterest);
2110 ret = TW_RESULT_ERROR_NO_MEMORY;
2114 memcpy(g_FoundMatchedDeviceList->deviceList,
2124 int newSize = sizeof(TWDevice) * (g_FoundMatchedDeviceList->count + 1);
2125 TWDevice* temp = (TWDevice*)realloc(g_FoundMatchedDeviceList->deviceList,
2129 OICFree(device->endpointOfInterest);
2131 ret =TW_RESULT_ERROR_NO_MEMORY;
2135 g_FoundMatchedDeviceList->deviceList = temp;
2137 //Add to the end of list
2138 int count = g_FoundMatchedDeviceList->count;
2139 memcpy(&g_FoundMatchedDeviceList->deviceList[count],
2143 //Increase the count
2144 g_FoundMatchedDeviceList->count++;
2155 OC_LOG_V(INFO, TAG, "Leave TelMatchDescHandler() with ret=%d", ret);
2159 TWResultCode TelSimpleDescHandler(int count, char* tokens[])
2161 //AT+SIMPLEDESC:3746,3746,01
2165 // SimpleDesc:3746,00 <<<<<<<---------------------
2169 // InCluster:0000,0001,0003,0402,0500,0020,0B05
2173 OC_LOG_V(INFO, TAG, "Enter TelSimpleDescHandler().");
2174 TWResultCode ret = TW_RESULT_UNKNOWN;
2176 if(!tokens || count != RESPONSE_PARAMS_COUNT_SIMPLE_DESC)
2178 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2182 if (g_WIPDevice == NULL)
2184 OC_LOG_V(ERROR, TAG,
2185 "Receive simple descriptor unexpectedly - %s", tokens[0]);
2186 ret = TW_RESULT_ERROR;
2190 if (strcmp(tokens[1], AT_STR_ERROR_OK) != 0)
2192 OC_LOG_V(ERROR, TAG, "SimpleDesc: prompt contained error status %s.", tokens[1]);
2193 ret = TW_RESULT_ERROR;
2197 if (strcmp(tokens[0], g_WIPDevice->nodeId) == 0)
2199 OC_LOG_V(INFO, TAG, "Got simple descriptor for nodeid %s", tokens[0]);
2204 OC_LOG_V(ERROR, TAG,
2205 "Finding simple descriptor for non existing nodeid %s.", tokens[0]);
2206 ret = TW_RESULT_ERROR;
2211 OC_LOG_V(INFO, TAG, "Leave TelSimpleDescHandler() with ret=%d", ret);
2215 TWResultCode TelSimpleDescInClusterHandler(int count, char* tokens[])
2217 //AT+SIMPLEDESC:3746,3746,01
2221 // SimpleDesc:3746,00
2225 // InCluster:0000,0001,0003,0402,0500,0020,0B05 <<<<<<<<--------------
2229 OC_LOG_V(INFO, TAG, "Enter TelSimpleDescInClusterHandler()");
2230 TWResultCode ret = TW_RESULT_ERROR;
2232 if (!tokens || count < RESPONSE_PARAMS_COUNT_SIMPLE_DESC_IN_CLUSTER_MIN )
2234 OC_LOG_V(ERROR, TAG, "Invalid Params");
2235 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2239 if (g_WIPDevice == NULL)
2241 OC_LOG_V(ERROR, TAG,
2242 "Receive simple descriptor unexpectedly - %s", tokens[0]);
2243 ret = TW_RESULT_ERROR;
2247 if (g_WIPDevice->endpointOfInterest->clusterList != NULL)
2249 OC_LOG_V(ERROR, TAG, "Expected an empty cluster list.");
2250 ret = TW_RESULT_ERROR;
2254 //Add found clusters for the node.
2255 g_WIPDevice->endpointOfInterest->clusterList =
2256 (TWClusterList*)OICMalloc(sizeof(TWClusterList));
2257 if (g_WIPDevice->endpointOfInterest->clusterList == NULL)
2259 OC_LOG_V(ERROR, TAG, "No Memory - clusterList");
2260 ret = TW_RESULT_ERROR_NO_MEMORY;
2264 g_WIPDevice->endpointOfInterest->clusterList->clusterIds =
2265 (TWClusterId*)OICMalloc(sizeof(TWClusterId) * count);
2266 if (g_WIPDevice->endpointOfInterest->clusterList->clusterIds == NULL)
2268 OICFree(g_WIPDevice->endpointOfInterest->clusterList);
2269 OC_LOG_V(ERROR, TAG, "No Memory - clusterIds");
2270 ret = TW_RESULT_ERROR_NO_MEMORY;
2275 for (; i < count; i++)
2277 OICStrcpy(g_WIPDevice->endpointOfInterest->clusterList->
2278 clusterIds[i].clusterId,
2282 OC_LOG_V(INFO, TAG, "ClusterIds[%d]=%s",
2284 g_WIPDevice->endpointOfInterest->
2285 clusterList->clusterIds[i].clusterId);
2287 g_WIPDevice->endpointOfInterest->clusterList->count = count;
2288 ret = TW_RESULT_HAS_CLUSTERS;
2291 OC_LOG_V(INFO, TAG, "Leave TelSimpleDescInClusterHandler() with ret=%d", ret);
2295 TWResultCode TelWriteAttrHandler(int count, char* tokens[])
2297 //AT+WRITEATR:3A3D,01,0,0003,0000,21,00
2299 // WRITEATTR:3A3D,01,0003,,00
2301 //AT+WRITEATR:B826,01,0,0500,0010,F0,000D6F0000D59E92
2303 // WRITEATTR:B826,01,0500,0010,70
2305 OC_LOG_V(INFO, TAG, "Enter TelWriteAttrHandler()");
2307 TWResultCode ret = TW_RESULT_ERROR;
2310 (count < RESPONSE_PARAMS_COUNT_WRITE_ATTR_4) ||
2311 (count > RESPONSE_PARAMS_COUNT_WRITE_ATTR_5))
2313 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2317 if (count == RESPONSE_PARAMS_COUNT_WRITE_ATTR_4)
2319 if (strcmp(tokens[3], AT_STR_ERROR_OK) == 0)
2324 else if (count == RESPONSE_PARAMS_COUNT_WRITE_ATTR_5)
2326 if (strcmp(tokens[4], AT_STR_ERROR_INVALID_OP) == 0)
2328 ret = TW_RESULT_ERROR_INVALID_OP;
2333 OC_LOG_V(INFO, TAG, "Leave TelWriteAttrHandler() with ret=%d", ret);
2337 TWResultCode TelReadAttrHandlerTemperature(int count, char* tokens[])
2339 //AT+READATR:F2D7,01,0,0402,0002
2341 // TEMPERATURE:F2D7,01,0002,00,1770
2343 //AT+READATR:F2D7,01,0,0402,0002
2347 OC_LOG_V(INFO, TAG, "Enter TelReadAttrHandlerTemperature().");
2348 TWResultCode ret = TW_RESULT_UNKNOWN;
2350 if(!tokens || count != RESPONSE_PARAMS_COUNT_TEMPERATURE)
2352 OC_LOG_V(ERROR, TAG, "Invalid Params");
2353 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2357 if (strcmp(tokens[3], AT_STR_ERROR_OK) != 0)
2359 OC_LOG_V(ERROR, TAG, "TEMPERATURE prompt contained error status.");
2360 ret = TW_RESULT_ERROR;
2364 // AttrInfo is 16-bit value representing (100 * Degrees Celsius)
2365 // so 0x812 = 20.66 C = 69.188 F
2366 if (g_ZigBeeStatus.remoteAttributeValueRead != NULL)
2368 OICFree(g_ZigBeeStatus.remoteAttributeValueRead);
2369 g_ZigBeeStatus.remoteAttributeValueRead = NULL;
2371 OC_LOG_V(INFO, TAG, "Read Attribute Value: %s", tokens[4]);
2372 g_ZigBeeStatus.remoteAttributeValueRead =
2373 (char*)OICMalloc(sizeof(char) * strlen(tokens[4]));
2374 if (g_ZigBeeStatus.remoteAttributeValueRead == NULL)
2376 OC_LOG_V(ERROR, TAG, "No Memory");
2377 ret = TW_RESULT_ERROR_NO_MEMORY;
2381 strcpy(g_ZigBeeStatus.remoteAttributeValueRead, tokens[4]);
2382 g_ZigBeeStatus.remoteAtrributeValueReadLength = strlen(tokens[4]);
2383 ret = TW_RESULT_REMOTE_ATTR_HAS_VALUE;
2387 OC_LOG_V(INFO, TAG, "Leave TelReadAttrHandlerTemperature() with ret=%d", ret);
2391 TWResultCode TelReadAttrHandler(int count, char* tokens[])
2393 //AT+READATR:F2D7,01,0,0402,0002
2395 // RESPATTR:<NodeID>,<EP>,<ClusterID>,<AttrID>,<Status>,<AttrInfo>
2397 //AT+READATR:F2D7,01,0,0402,0002
2401 OC_LOG_V(INFO, TAG, "Enter TelReadAttrHandler()");
2402 TWResultCode ret = TW_RESULT_UNKNOWN;
2404 if(!tokens || count != RESPONSE_PARAMS_COUNT_RESPATTR)
2406 OC_LOG_V(ERROR, TAG, "Invalid Params");
2407 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2411 if (strcmp(tokens[4], AT_STR_ERROR_OK) != 0)
2413 OC_LOG_V(INFO, TAG, "READATTR prompt contained error status.");
2414 ret = TW_RESULT_ERROR;
2418 if (g_ZigBeeStatus.remoteAttributeValueRead != NULL)
2420 OICFree(g_ZigBeeStatus.remoteAttributeValueRead);
2422 OC_LOG_V(INFO, TAG, "Read Attribute Value: %s.", tokens[5]);
2423 g_ZigBeeStatus.remoteAttributeValueRead =
2424 (char*)OICMalloc(sizeof(char) * strlen(tokens[5]));
2425 if (g_ZigBeeStatus.remoteAttributeValueRead != NULL)
2427 strcpy(g_ZigBeeStatus.remoteAttributeValueRead, tokens[5]);
2428 g_ZigBeeStatus.remoteAtrributeValueReadLength = strlen(tokens[5]);
2429 ret = TW_RESULT_REMOTE_ATTR_HAS_VALUE;
2433 OC_LOG_V(ERROR, TAG, "No Memory");
2434 ret = TW_RESULT_ERROR_NO_MEMORY;
2438 OC_LOG_V(INFO, TAG, "Leave TelReadAttrHandler().\n");
2442 TWResultCode TelZCLDefaultResponseHandler(int count, char* tokens[])
2444 //AT+RONOFF:<Address>,<EP>,<SendMode>[,<ON/OFF>]
2445 // DFTREP:<NodeID>,<EP>,<ClusterID>,<CMD>,<Status>
2447 //AT+DRLOCK:<Address>,<EP>,<SendMode>,<Lock/Unlock>
2448 // DFTREP:<NodeID>,<EP>,<ClusterID>,<CMD>,<Status>
2450 //AT+LCMVTOLEV:<Address>,<EP>,<SendMode>,<ON/OFF>,<LevelValue>,<TransTime>
2451 // DFTREP:<NodeID>,<EP>,<ClusterID>,<CMD>,<Status>
2453 OC_LOG_V(INFO, TAG, "Enter TelZCLDefaultResponseHandler()");
2454 TWResultCode ret = TW_RESULT_UNKNOWN;
2456 if(!tokens || count != RESPONSE_PARAMS_COUNT_DFTREP)
2458 OC_LOG_V(ERROR, TAG, "Invalid Params");
2459 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2464 "DFTREP prompt succeed for NodeId:%s, EP:%s, ClusterId:%s, CMD:%s.\n",
2465 tokens[0], tokens[1], tokens[2], tokens[3]);
2467 if (strcmp(tokens[4], AT_STR_ERROR_OK) != 0)
2469 ret = TW_RESULT_ERROR;
2477 OC_LOG_V(INFO, TAG, "Leave TelZCLDefaultResponseHandler()");
2481 TWResultCode TelSwitchDoorLockStateHandler(int count, char* tokens[])
2483 //AT+DRLOCK:<Address>,<EP>,<SendMode>,<Lock/Unlock>
2484 // DRLOCRSP:<nodeID>,<ep>,<status>
2486 // DRUNLOCKRSP:<nodeID>,<ep>,<status>
2488 OC_LOG_V(INFO, TAG, "Enter TelSwitchDoorLockStateHandler()");
2489 TWResultCode ret = TW_RESULT_UNKNOWN;
2491 if(!tokens || count != RESPONSE_PARAMS_COUNT_DRLOCKUNLOCKRSP)
2493 OC_LOG_V(ERROR, TAG, "Invalid Params");
2494 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2498 if (strcmp(tokens[2], AT_STR_ERROR_OK) != 0)
2501 "DRLOCRSP/DRUNLOCKRSP prompt contained error status %s.", tokens[4]);
2502 ret = TW_RESULT_ERROR;
2506 OC_LOG_V(INFO, TAG, "DRLOCRSP/DRUNLOCKRSP prompt succeed for nodeId:%s, ep:%s.",
2507 tokens[0], tokens[1]);
2512 OC_LOG_V(INFO, TAG, "Leave TelSwitchDoorLockStateHandler() with ret=%d", ret);
2516 TWResultCode TelZoneEnrollRequestHandler(int count, char* tokens[])
2518 //ZENROLLREQ:<NodeID>,<EndPoint>,<ZoneType>,<ManufactureCode>
2520 OC_LOG_V(INFO, TAG, "Enter TelZoneEnrollRequestHandler()");
2521 TWResultCode ret = TW_RESULT_UNKNOWN;
2523 if(!tokens || count != RESPONSE_PARAMS_COUNT_ZENROLLREQ)
2525 OC_LOG_V(ERROR, TAG, "Invalid Params");
2526 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2530 OC_LOG_V(INFO, TAG, "Received zone request from:");
2531 OC_LOG_V(INFO, TAG, "Node:%s", tokens[0]);
2532 OC_LOG_V(INFO, TAG, "EP:%s", tokens[1]);
2533 OC_LOG_V(INFO, TAG, "ZoneType:%s", tokens[2]);
2534 OC_LOG_V(INFO, TAG, "ManufactureCode:%s", tokens[3]);
2538 OC_LOG_V(INFO, TAG, "Leave TelZoneEnrollRequestHandler() with ret=%d", ret);
2542 TWResultCode TelEnrolledHandler(int count, char* tokens[])
2544 //ENROLLED:<ZID>,<ZoneType>,<EUI>
2546 OC_LOG_V(INFO, TAG, "Enter TelEnrolledHandler()");
2547 TWResultCode ret = TW_RESULT_OK;
2549 if(!tokens || count != RESPONSE_PARAMS_COUNT_ENROLLED)
2551 OC_LOG_V(ERROR, TAG, "Invalid Params");
2552 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2556 OC_LOG_V(INFO, TAG, "Received zone enrollment for:");
2557 OC_LOG_V(INFO, TAG, "ZID:%s", tokens[0]);
2558 OC_LOG_V(INFO, TAG, "ZoneType:%s", tokens[1]);
2559 OC_LOG_V(INFO, TAG, "EUI:%s", tokens[2]);
2561 TWEnrollee enrollee;
2562 OICStrcpy(enrollee.zoneId, SIZE_ZONEID, tokens[0]);
2563 OICStrcpy(enrollee.zoneType, SIZE_ZONETYPE, tokens[1]);
2564 OICStrcpy(enrollee.eui, SIZE_EUI, tokens[2]);
2566 if (g_EnrollmentSucceedCallback != NULL)
2568 OC_LOG_V(INFO, TAG, "Enrolled - Invoke callback");
2569 g_EnrollmentSucceedCallback(&enrollee);
2574 OC_LOG_V(INFO, TAG, "Leave TelEnrolledHandler() with ret=%d", ret);
2578 TWResultCode TelZoneStatusHandler(int count, char* tokens[])
2580 //ZONESTATUS:<NodeID>,<EP>,<ZoneStatus>,<ExtendStatus>[,<ZoneID>,<Delay>]
2581 //ZONESTATUS:5FBA,01,0021,00,01,00AF
2583 OC_LOG_V(INFO, TAG, "Enter TelZoneStatusHandler()");
2584 TWResultCode ret = TW_RESULT_UNKNOWN;
2586 ((count != RESPONSE_PARAMS_COUNT_ZONESTATUS_4) &&
2587 (count != RESPONSE_PARAMS_COUNT_ZONESTATUS_6)))
2589 OC_LOG_V(ERROR, TAG, "Invalid Params");
2590 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2595 OICStrcpy(update.nodeId, SIZE_NODEID, tokens[0]);
2596 OICStrcpy(update.endpoint, SIZE_NODEID, tokens[1]);
2597 OICStrcpy(update.status, SIZE_NODEID, tokens[2]);
2598 OICStrcpy(update.extendedStatus, SIZE_NODEID, tokens[3]);
2600 if (count == RESPONSE_PARAMS_COUNT_ZONESTATUS_6)
2602 OICStrcpy(update.zoneId, SIZE_NODEID, tokens[4]);
2603 OICStrcpy(update.delay, SIZE_NODEID, tokens[5]);
2606 if (g_DeviceStatusUpdateCallback != NULL)
2608 OC_LOG_V(INFO, TAG, "device status update - invoke callback");
2609 g_DeviceStatusUpdateCallback(&update);
2614 OC_LOG_V(INFO, TAG, "Leave TelZoneStatusHandler() with ret=%d", ret);
2618 //-----------------------------------------------------------------------------
2619 // Internal functions - Helpers
2620 //-----------------------------------------------------------------------------
2624 * Tokenize 'input' parameter by 'delimiters' into 'output' array.
2627 int Tokenize(const char *input, const char* delimiters, char* output[])
2629 OC_LOG_V(INFO, TAG, "Enter Tokenize() - %s", input);
2633 OC_LOG_V(INFO, TAG, "Invalid parameter.");
2637 int length = strlen(input);
2638 char * str = (char *) OICCalloc(1, length + 1);
2639 OICStrcpy(str, length+1, input);
2641 char* savePtr = NULL;
2642 char* p = strtok_r(str, delimiters, &savePtr);
2644 while (p && index <= ARRAY_LENGTH)
2646 int size = strlen(p) + 1; //for null char
2647 output[index] = (char*)OICCalloc(size, sizeof(char));
2648 OICStrcpy(output[index], size, p);
2649 OC_LOG_V(INFO, TAG, "Token[%d]=%s", index, output[index]);
2650 p = strtok_r (NULL, delimiters, &savePtr);
2655 OC_LOG_V(INFO, TAG, "Leave Tokenize()");
2659 int AsciiToHex(char c)
2662 if(c >= '0' && c <= '9')
2667 if(num >= 'A' && num <= 'F')
2669 return num - 'A' + 10;
2674 TWResultCode AsciiHexToValue(char* hexString, int length, uint64_t* value)
2676 if(!hexString || !value || length < 0)
2678 return TW_RESULT_ERROR_INVALID_PARAMS;
2680 int retVal = AsciiToHex(hexString[0]);
2683 OC_LOG(ERROR, TAG, "Bad conversion from ASCII To Hex.");
2684 return TW_RESULT_ERROR;
2686 *value = (uint64_t)retVal;
2687 for (int i = 1; i < length; ++i)
2689 if (sizeof(hexString) > (uint32_t)i)
2692 retVal = AsciiToHex(hexString[i]);
2695 OC_LOG(ERROR, TAG, "Bad conversion from ASCII To Hex.");
2696 return TW_RESULT_ERROR;
2698 *value |= (uint64_t)retVal;
2701 return TW_RESULT_OK;
2706 * Deallocate device list.
2709 void DeallocateTWDeviceList()
2711 if (g_FoundMatchedDeviceList == NULL)
2716 if (g_FoundMatchedDeviceList->deviceList == NULL)
2718 OICFree(g_FoundMatchedDeviceList);
2719 g_FoundMatchedDeviceList = NULL;
2723 if (g_FoundMatchedDeviceList->deviceList->endpointOfInterest == NULL)
2725 OICFree(g_FoundMatchedDeviceList->deviceList);
2726 g_FoundMatchedDeviceList->deviceList = NULL;
2728 OICFree(g_FoundMatchedDeviceList);
2729 g_FoundMatchedDeviceList = NULL;
2733 if (g_FoundMatchedDeviceList->deviceList->endpointOfInterest->clusterList == NULL)
2735 OICFree(g_FoundMatchedDeviceList->deviceList->endpointOfInterest);
2736 g_FoundMatchedDeviceList->deviceList->endpointOfInterest = NULL;
2738 OICFree(g_FoundMatchedDeviceList->deviceList);
2739 g_FoundMatchedDeviceList->deviceList = NULL;
2741 OICFree(g_FoundMatchedDeviceList);
2742 g_FoundMatchedDeviceList = NULL;
2746 if (g_FoundMatchedDeviceList->deviceList->endpointOfInterest-> clusterList->clusterIds == NULL)
2748 OICFree(g_FoundMatchedDeviceList->deviceList->endpointOfInterest->clusterList);
2749 g_FoundMatchedDeviceList->deviceList->endpointOfInterest->clusterList = NULL;
2751 OICFree(g_FoundMatchedDeviceList->deviceList->endpointOfInterest);
2752 g_FoundMatchedDeviceList->deviceList->endpointOfInterest = NULL;
2754 OICFree(g_FoundMatchedDeviceList->deviceList);
2755 g_FoundMatchedDeviceList->deviceList = NULL;
2757 OICFree(g_FoundMatchedDeviceList);
2758 g_FoundMatchedDeviceList = NULL;
2762 OICFree(g_FoundMatchedDeviceList->deviceList->endpointOfInterest-> clusterList->clusterIds);
2763 g_FoundMatchedDeviceList->deviceList->endpointOfInterest->clusterList->clusterIds = NULL;
2765 OICFree(g_FoundMatchedDeviceList->deviceList->endpointOfInterest->clusterList);
2766 g_FoundMatchedDeviceList->deviceList->endpointOfInterest->clusterList = NULL;
2768 OICFree(g_FoundMatchedDeviceList->deviceList->endpointOfInterest);
2769 g_FoundMatchedDeviceList->deviceList->endpointOfInterest = NULL;
2771 OICFree(g_FoundMatchedDeviceList->deviceList);
2772 g_FoundMatchedDeviceList->deviceList = NULL;
2774 OICFree(g_FoundMatchedDeviceList);
2775 g_FoundMatchedDeviceList = NULL;