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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
34 #include "oic_string.h"
35 #include "oic_malloc.h"
39 #include "telegesis_socket.h"
40 #include "telegesis_wrapper.h"
41 #include "twsocketlist.h"
44 #define TAG PCF("telegesiswrapper") // Module Name
46 #define ARRAY_LENGTH 100
48 #define RESPONSE_PARAMS_COUNT_NETWORK_INFO_1 (1)
49 #define RESPONSE_PARAMS_COUNT_NETWORK_INFO_5 (5)
50 #define RESPONSE_PARAMS_COUNT_JPAN (3)
51 #define RESPONSE_PARAMS_COUNT_DEVICE_JOINED (2)
52 #define RESPONSE_PARAMS_COUNT_MATCH_DESC (3)
53 #define RESPONSE_PARAMS_COUNT_SIMPLE_DESC (2)
54 #define RESPONSE_PARAMS_COUNT_SIMPLE_DESC_IN_CLUSTER_MIN (1)
55 #define RESPONSE_PARAMS_COUNT_WRITE_ATTR_4 (4)
56 #define RESPONSE_PARAMS_COUNT_WRITE_ATTR_5 (5)
57 #define RESPONSE_PARAMS_COUNT_TEMPERATURE (5)
58 #define RESPONSE_PARAMS_COUNT_RESPATTR (6)
59 #define RESPONSE_PARAMS_COUNT_ADDRESS_RESPONSE (3)
60 #define RESPONSE_PARAMS_COUNT_DFTREP (5)
61 #define RESPONSE_PARAMS_COUNT_DRLOCKUNLOCKRSP (3)
62 #define RESPONSE_PARAMS_COUNT_ZENROLLREQ (4)
63 #define RESPONSE_PARAMS_COUNT_ENROLLED (3)
64 #define RESPONSE_PARAMS_COUNT_ZONESTATUS_4 (4)
65 #define RESPONSE_PARAMS_COUNT_ZONESTATUS_6 (6)
67 #define IN_CLUSTER_COUNT_STRING "05"
68 #define OUT_CLUSTER_COUNT_STRING "00"
70 #define TOKEN_ADDRRESP_STATUS_CODE (0)
71 #define TOKEN_ADDRRESP_NODEID (1)
72 #define TOKEN_ADDRRESP_EUI (2)
74 #define TOKEN_PLUS_N_DEVICE_TYPE (0)
75 #define TOKEN_PLUS_N_PANID (3)
76 #define TOKEN_PLUS_N_PANID_EXTENDED (4)
78 #define TOKEN_JPAN_PANID (1)
79 #define TOKEN_JPAN_PANID_EXTENDED (2)
81 #define TOKEN_PJOIN_RESPONSE_IEEE_ADDRESS (0)
82 #define TOKEN_PJOIN_RESPONSE_NODEID (1)
84 #define TOKEN_MATCHDESC_NODEID (0)
85 #define TOKEN_MATCHDESC_STATUS_CODE (1)
86 #define TOKEN_MATCHDESC_ENDPOINTID (2)
88 #define TOKEN_SIMPLEDESC_SIMPLEDESC_NODEID (0)
89 #define TOKEN_SIMPLEDESC_SIMPLEDESC_STATUS_CODE (1)
90 #define TOKEN_SIMPLEDESC_INCLUSTER_STRING (0)
92 #define TOKEN_WRITEATTR_STATUS_CODE (3)
93 #define TOKEN_WRITEATTR_STATUS_CODE_ALTERNATIVE (4)
95 #define TOKEN_TEMPERATURE_STATUS_CODE (3)
96 #define TOKEN_TEMPERATURE_VALUE (4)
98 #define TOKEN_RESPATTR_STATUS_CODE (4)
99 #define TOKEN_RESPATTR_ATTRIBUTE_VALUE (5)
101 #define TOKEN_DFTREP_NODEID (0)
102 #define TOKEN_DFTREP_ENDPOINTID (1)
103 #define TOKEN_DFTREP_CLUSTERID (2)
104 #define TOKEN_DFTREP_COMMANDID (3)
105 #define TOKEN_DFTREP_STATUS_CODE (4)
107 #define TOKEN_DRLOCKRSP_NODEID (0)
108 #define TOKEN_DRLOCKRSP_ENDPOINTID (1)
109 #define TOKEN_DRLOCKRSP_STATUS_CODE (2)
111 #define TOKEN_ZENROLLREQ_NODEID (0)
112 #define TOKEN_ZENROLLREQ_ENDPOINTID (1)
113 #define TOKEN_ZENROLLREQ_ZONETYPE (2)
114 #define TOKEN_ZENROLLREQ_MANUFACTURE_CODE (3)
115 #define TOKEN_ENROLLED_ZONEID (0)
116 #define TOKEN_ENROLLED_ZONETYPE (1)
117 #define TOKEN_ENROLLED_EUI (2)
119 #define TOKEN_ZONESTATUS_NODEID (0)
120 #define TOKEN_ZONESTATUS_ENDPOINTID (1)
121 #define TOKEN_ZONESTATUS_ZONESTATUS (2)
122 #define TOKEN_ZONESTATUS_ZONESTATUS_EXTENDED (3)
123 #define TOKEN_ZONESTATUS_ZONEID (4)
124 #define TOKEN_ZONESTATUS_DELAY (5)
127 typedef struct TWContext{
128 PIPlugin_Zigbee* g_plugin;
131 char g_LocalEUI[SIZE_EUI];
132 char g_WIPRemoteEUI[SIZE_EUI];
133 char g_WIPRemoteNodeId[SIZE_NODEID];
135 TWStatus g_ZigBeeStatus;
136 TWDeviceList* g_FoundMatchedDeviceList;
137 TWDevice* g_WIPDevice;
139 TWDeviceFoundCallback g_DeviceFoundCallback;
140 TWEnrollmentSucceedCallback g_EnrollmentSucceedCallback;
141 TWDeviceStatusUpdateCallback g_DeviceStatusUpdateCallback;
142 TWDeviceNodeIdChangedCallback g_EndDeviceNodeIdChangedCallback;
144 struct TWContext* next;
147 typedef TWResultCode (*TWATResultHandler)(int count, char** tokens, TWContext* ctx);
151 const char *resultTxt;
152 TWATResultHandler handler;
153 } TWATResultHandlerPair;
156 //-----------------------------------------------------------------------------
157 // Private internal function prototypes
158 //-----------------------------------------------------------------------------
160 static TWResultCode HandleATResponse(TWEntry* entry, TWContext* ctx);
162 static TWResultCode processEntry(TWEntry* entry, TWContext* ctx);
163 static TWResultCode processEntryNETWORK_INFO(TWEntry* entry, TWContext* ctx);
164 static TWResultCode processEntryJPAN(TWEntry* entry, TWContext* ctx);
165 static TWResultCode processEntryEndDevice(TWEntry* entry, TWContext* ctx);
166 static TWResultCode processEntryMatchDesc(TWEntry* entry, TWContext* ctx);
167 static TWResultCode processEntrySimpleDesc(TWEntry* entry, TWContext* ctx);
168 static TWResultCode processEntryWriteAttr(TWEntry* entry, TWContext* ctx);
169 static TWResultCode processEntryReadAttr(TWEntry* entry, TWContext* ctx);
170 static TWResultCode processEntryTemperature(TWEntry* entry, TWContext* ctx);
171 static TWResultCode processEntrySwitchDoorLockState(TWEntry* entry, TWContext* ctx);
172 static TWResultCode processEntryZCLDefaultResponse(TWEntry* entry, TWContext* ctx);
173 static TWResultCode processEntryZoneEnrollRequest(TWEntry* entry, TWContext* ctx);
174 static TWResultCode processEntryEnrolled(TWEntry* entry, TWContext* ctx);
175 static TWResultCode processEntryZoneStatus(TWEntry* entry, TWContext* ctx);
176 static TWResultCode processEntryAddressResponse(TWEntry* entry, TWContext* ctx);
178 static TWResultCode Reset(TWContext* ctx);
179 static TWResultCode GetRemoteEUI(char *nodeId, char* outRemoteEUI, TWContext* ctx);
180 static TWResultCode CreatePAN(TWContext* ctx);
181 static TWResultCode EnableJoin(bool isKeyEncrypted, TWContext* ctx);
182 static TWResultCode FindMatchNodes(TWContext* ctx);
183 static TWResultCode FindClusters(char nodeId[], char endpoint[], TWContext* ctx);
185 static TWResultCode TelNetworkInfoHandler(int count, char* tokens[], TWContext* ctx);
186 static TWResultCode TelJpanHandler(int count, char* tokens[], TWContext* ctx);
187 static TWResultCode TelEndDeviceJoinHandler(int count, char* tokens[], TWContext* ctx);
188 static TWResultCode TelMatchDescHandler(int count, char* tokens[], TWContext* ctx);
189 static TWResultCode TelAddressResponseHandler(int count, char* tokens[], TWContext* ctx);
190 static TWResultCode TelSimpleDescHandler(int count, char* tokens[], TWContext* ctx);
191 static TWResultCode TelSimpleDescInClusterHandler(int count, char* tokens[], TWContext* ctx);
192 static TWResultCode TelWriteAttrHandler(int count, char* tokens[], TWContext* ctx);
193 static TWResultCode TelReadAttrHandler(int count, char* tokens[], TWContext* ctx);
194 static TWResultCode TelReadAttrHandlerTemperature(int count, char* tokens[], TWContext* ctx);
195 static TWResultCode TelZCLDefaultResponseHandler(int count, char* tokens[], TWContext* ctx);
196 static TWResultCode TelSwitchDoorLockStateHandler(int count, char* tokens[], TWContext* ctx);
197 static TWResultCode TelZoneEnrollRequestHandler(int count, char* tokens[], TWContext* ctx);
198 static TWResultCode TelEnrolledHandler(int count, char* tokens[], TWContext* ctx);
199 static TWResultCode TelZoneStatusHandler(int count, char* tokens[], TWContext* ctx);
201 static TWResultCode AsciiHexToValue(char* hexString, int length, uint64_t* value);
202 static int AsciiToHex(char c);
203 static int Tokenize(const char *input, const char* delimiters, char* output[]);
205 static void DeallocateTWDeviceList(TWContext* ctx);
206 static TWContext* GetTWContext(PIPlugin_Zigbee * plugin);
208 //-----------------------------------------------------------------------------
210 //-----------------------------------------------------------------------------
212 static TWATResultHandlerPair g_TWATResultHandlerPairArray[] =
214 {"+N=", TelNetworkInfoHandler},
215 {"JPAN:", TelJpanHandler},
216 {"RFD:", TelEndDeviceJoinHandler}, //e.g SmartThings Open/Closed Sensor
217 {"FFD:", TelEndDeviceJoinHandler}, //e.g SmartThings Plug
218 {"SED:", TelEndDeviceJoinHandler},
219 {"ZED:", TelEndDeviceJoinHandler},
220 {"MatchDesc:", TelMatchDescHandler},
221 {"SimpleDesc:", TelSimpleDescHandler},
222 {"InCluster:", TelSimpleDescInClusterHandler},
223 {"WRITEATTR:", TelWriteAttrHandler},
224 {"RESPATTR:", TelReadAttrHandler},
225 {"TEMPERATURE:",TelReadAttrHandlerTemperature},
226 {"DFTREP", TelZCLDefaultResponseHandler},
227 {"DRLOCRSP:", TelSwitchDoorLockStateHandler},
228 {"DRUNLOCKRSP:",TelSwitchDoorLockStateHandler},
229 {"ZENROLLREQ:", TelZoneEnrollRequestHandler},
230 {"ENROLLED:", TelEnrolledHandler},
231 {"ZONESTATUS:", TelZoneStatusHandler},
232 {"AddrResp:", TelAddressResponseHandler},
233 {"Unknown:", TelNetworkInfoHandler}
236 static TWContext* g_twContextList = NULL;
238 void InitializeContext(TWContext* context)
240 context->g_port = NULL;
241 memset(context->g_LocalEUI, '\0', sizeof(context->g_LocalEUI));
242 memset(context->g_WIPRemoteEUI, '\0', sizeof(context->g_WIPRemoteEUI));
243 memset(context->g_WIPRemoteNodeId, '\0', sizeof(context->g_WIPRemoteNodeId));
245 context->g_ZigBeeStatus.state = ZB_STATE_UNKNOWN;
246 context->g_ZigBeeStatus.panId = 0;
247 context->g_ZigBeeStatus.extPanId = 0;
248 context->g_ZigBeeStatus.remoteAttributeValueRead = NULL;
249 context->g_ZigBeeStatus.remoteAtrributeValueReadLength = 0;
251 context->g_FoundMatchedDeviceList = NULL;
252 context->g_WIPDevice = NULL;
254 context->g_DeviceFoundCallback = NULL;
255 context->g_EnrollmentSucceedCallback = NULL;
256 context->g_DeviceStatusUpdateCallback = NULL;
257 context->g_EndDeviceNodeIdChangedCallback = NULL;
260 /*****************************************************************************/
262 /* Public functions */
264 /*****************************************************************************/
265 OCStackResult TWInitialize(PIPlugin_Zigbee* plugin, const char* deviceDevPath)
267 OIC_LOG(INFO, TAG, "Enter TWInitialize()");
269 TWResultCode twCode = TW_RESULT_ERROR;
271 if ((plugin == NULL) || (deviceDevPath == NULL))
273 return OC_STACK_INVALID_PARAM;
276 if (g_twContextList != NULL)
278 TWContext* out = NULL;
279 TWContext* temp = NULL;
280 LL_FOREACH_SAFE(g_twContextList, out, temp)
282 if (out->g_plugin == plugin)
284 //Ignore because it's already in the list.
290 TWContext* ctx = (TWContext*)OICCalloc(1, sizeof(*ctx));
293 return OC_STACK_NO_MEMORY;
295 InitializeContext(ctx);
296 ctx->g_plugin = plugin;
297 ctx->g_port = deviceDevPath;
299 OIC_LOG_V(INFO, TAG, "Attempt to open %s", deviceDevPath);
301 twCode = TWStartSock(ctx->g_plugin, deviceDevPath); //TODO:
302 if (twCode != TW_RESULT_OK)
304 OIC_LOG_V(ERROR, TAG, "Failed to open %s because of error: %d", deviceDevPath, twCode);
306 return OC_STACK_ERROR;
310 twCode = TWGetEUI(ctx->g_plugin, &eui);
311 if (twCode != TW_RESULT_OK)
313 OIC_LOG_V(ERROR, TAG, "Failed to get EUI because of error: %d", twCode);
315 return OC_STACK_ERROR;
317 OICStrcpy(ctx->g_LocalEUI, sizeof(ctx->g_LocalEUI), eui);
318 OIC_LOG_V(INFO, TAG, "LocalEUI=%s", ctx->g_LocalEUI);
321 bool wantReset = false; //TODO:
325 if (twCode != TW_RESULT_OK)
327 OIC_LOG(ERROR, TAG, "ZigBee Initialization - Reset");
329 return OC_STACK_ERROR;
333 twCode = CreatePAN(ctx);
334 if (twCode != TW_RESULT_OK)
336 OIC_LOG(ERROR, TAG, "CreatePan Failed");
337 OIC_LOG(ERROR, TAG, "TWInitialize() - MUST STOP NOW");
338 ctx->g_ZigBeeStatus.state = ZB_STATE_UNKNOWN;
340 return OC_STACK_ERROR;
344 OIC_LOG(INFO, TAG, "CreatePan Succeed");
345 OIC_LOG(INFO, TAG, "TWInitialize() Succeed");
346 ctx->g_ZigBeeStatus.state = ZB_STATE_INIT;
347 LL_APPEND(g_twContextList, ctx);
352 OCStackResult TWDiscover(PIPlugin_Zigbee* plugin)
354 OIC_LOG(INFO, TAG, "Enter TWDiscover()");
356 OCStackResult ret = OC_STACK_ERROR;
357 TWResultCode twRet = TW_RESULT_ERROR;
359 TWContext* ctx = GetTWContext(plugin);
362 OIC_LOG(ERROR, TAG, "Invalid Param");
363 return OC_STACK_INVALID_PARAM;
366 if (ctx->g_DeviceFoundCallback == NULL)
368 OIC_LOG(INFO, TAG, "Required TWDeviceFoundCallback.");
369 return OC_STACK_ERROR;
372 twRet = EnableJoin(false, ctx);
373 if (twRet != TW_RESULT_OK)
375 OIC_LOG(ERROR, TAG, "EnableJoin");
376 return OC_STACK_ERROR;
379 twRet = FindMatchNodes(ctx);
380 if (twRet == TW_RESULT_OK)
382 OIC_LOG(INFO, TAG, "FindMatchNodes");
387 OIC_LOG(ERROR, TAG, "FindMatchNodes");
388 ret = OC_STACK_ERROR;
391 OIC_LOG_V(INFO, TAG, "Leave TWDiscover() with ret=%d", ret);
395 OCStackResult TWSetAttribute(char* extendedUniqueId, char* nodeId, char* endpointId,
396 char* clusterId, char* attributeId, char* attributeType,
397 char* newValue, PIPlugin_Zigbee* plugin)
399 //Ask: AT+WRITEATR:5DA7,01,0,0003,0000,21,01
401 OIC_LOG(INFO, TAG, "Enter TWSetAttribute()");
403 TWContext* ctx = GetTWContext(plugin);
406 OIC_LOG(ERROR, TAG, "Invalid Param");
407 return OC_STACK_INVALID_PARAM;
410 (void)extendedUniqueId;
412 OCStackResult ret = OC_STACK_ERROR;
413 TWResultCode twRet = TW_RESULT_ERROR;
415 int size = strlen(AT_CMD_WRITE_ATR) + strlen(nodeId) +
416 SEPARATOR_LENGTH + strlen(endpointId) +
417 SEPARATOR_LENGTH + strlen(SENDMODE) +
418 SEPARATOR_LENGTH + strlen(clusterId) +
419 SEPARATOR_LENGTH + strlen(attributeId) +
420 SEPARATOR_LENGTH + strlen(attributeType) +
421 SEPARATOR_LENGTH + strlen(newValue) + 1;
423 char* cmdString = (char*)OICMalloc(size * sizeof(char));
424 if (cmdString == NULL)
426 OIC_LOG(ERROR, TAG, "No Memory");
427 ret = OC_STACK_ERROR;
430 snprintf(cmdString, size, "%s%s,%s,%s,%s,%s,%s,%s",
431 AT_CMD_WRITE_ATR, nodeId, endpointId, SENDMODE,
432 clusterId, attributeId, attributeType, newValue);
434 twRet = TWIssueATCommand(ctx->g_plugin, cmdString);
435 if (twRet != TW_RESULT_OK)
437 OIC_LOG_V(ERROR, TAG, "Write %s", cmdString);
438 ret = OC_STACK_ERROR;
441 OIC_LOG_V(INFO, TAG, "Write %s", cmdString);
443 TWEntry* entry = NULL;
444 twRet = TWDequeueEntry(ctx->g_plugin, &entry, TW_WRITEATTR);
445 if (twRet != TW_RESULT_OK)
447 OIC_LOG(ERROR, TAG, "TWDequeueEntry");
448 ret = OC_STACK_ERROR;
453 OIC_LOG(INFO, TAG, "TWEntry is NULL.");
454 ret = OC_STACK_ERROR;
458 twRet = processEntry(entry, ctx);
459 if (twRet == TW_RESULT_ERROR_INVALID_OP)
461 OIC_LOG_V(INFO, TAG, "Write %s - Invalid Operation", cmdString);
462 ret = OC_STACK_INVALID_OPTION;
465 if (twRet != TW_RESULT_OK)
467 OIC_LOG(ERROR, TAG, "processEntry");
468 ret = OC_STACK_ERROR;
475 TWDeleteEntry(ctx->g_plugin, entry);
477 OIC_LOG_V(INFO, TAG, "Leave TWSetAttribute() with ret=%d", ret);
481 OCStackResult TWGetAttribute(char* extendedUniqueId, char* nodeId, char* endpointId,
482 char* clusterId, char* attributeId,
483 char** outValue, uint8_t* outValueLength,
484 PIPlugin_Zigbee* plugin)
486 //Ask: AT+READATR:FE5A,01,0,0402,0002
488 OIC_LOG(INFO, TAG, "Enter TWGetAttribute()");
490 TWContext* ctx = GetTWContext(plugin);
493 return OC_STACK_INVALID_PARAM;
496 (void)extendedUniqueId;
498 OCStackResult ret = OC_STACK_ERROR;
499 TWResultCode twRet = TW_RESULT_ERROR;
501 int size = strlen(AT_CMD_READ_ATR) + strlen(nodeId) +
502 SEPARATOR_LENGTH + strlen(endpointId) +
503 SEPARATOR_LENGTH + strlen(SENDMODE) +
504 SEPARATOR_LENGTH + strlen(clusterId) +
505 SEPARATOR_LENGTH + strlen(attributeId) + 1;
507 char* cmdString = (char*)OICMalloc(size * sizeof(char));
508 if (cmdString == NULL)
510 OIC_LOG(ERROR, TAG, "No Memory");
511 ret = OC_STACK_NO_MEMORY;
514 int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s",
515 AT_CMD_READ_ATR, nodeId,
516 SEPARATOR, endpointId,
518 SEPARATOR, clusterId,
519 SEPARATOR, attributeId);
522 OIC_LOG(ERROR, TAG, "Build command error.");
523 ret = OC_STACK_ERROR;
526 twRet = TWIssueATCommand(ctx->g_plugin, cmdString);
527 if (twRet != TW_RESULT_OK)
529 OIC_LOG_V(ERROR, TAG, "Write %s", cmdString);
530 ret = OC_STACK_ERROR;
533 OIC_LOG_V(INFO, TAG, "Write %s", cmdString);
535 TWEntry* entry = NULL;
536 twRet = TWDequeueEntry(ctx->g_plugin, &entry, TW_RESPATTR);
537 if (twRet != TW_RESULT_OK)
539 OIC_LOG(ERROR, TAG, "TWDequeueEntry");
540 ret = OC_STACK_ERROR;
545 OIC_LOG(INFO, TAG, "TWEntry is NULL");
546 ret = OC_STACK_ERROR;
550 twRet = processEntry(entry, ctx);
551 if (twRet != TW_RESULT_REMOTE_ATTR_HAS_VALUE)
553 OIC_LOG(ERROR, TAG, "processEntry.");
554 ret = OC_STACK_ERROR;
558 size = strlen(ctx->g_ZigBeeStatus.remoteAttributeValueRead) + 1;
559 *outValue = (char*)OICMalloc(sizeof(char) * size);
560 if (*outValue == NULL)
562 OIC_LOG(ERROR, TAG, "No Memory");
563 ret = OC_STACK_NO_MEMORY;
567 OICStrcpy(*outValue, size, ctx->g_ZigBeeStatus.remoteAttributeValueRead);
568 *outValueLength = ctx->g_ZigBeeStatus.remoteAtrributeValueReadLength;
569 OICFree(ctx->g_ZigBeeStatus.remoteAttributeValueRead);
570 ctx->g_ZigBeeStatus.remoteAttributeValueRead = NULL;
571 ctx->g_ZigBeeStatus.remoteAtrributeValueReadLength = 0;
572 OIC_LOG(INFO, TAG, "TWGetAttribute() gets an attribute value.");
576 TWDeleteEntry(ctx->g_plugin, entry);
578 OIC_LOG_V(INFO, TAG, "Leave TWGetAttribute() with ret=%d", ret);
582 OCStackResult TWSwitchOnOff(char* nodeId, char* endpointId, char* newState,
583 PIPlugin_Zigbee* plugin)
585 //AT+RONOFF:<Address>,<EP>,<SendMode>[,<ON/OFF>]
586 //AT+RONOFF:9E2B,01,0,1
588 // DFTREP:9E2B,01,0006,01,00
590 OIC_LOG(INFO, TAG, "Enter TWSwitchOnOff()");
592 TWContext* ctx = GetTWContext(plugin);
595 OIC_LOG(ERROR, TAG, "Invalid Param");
596 return OC_STACK_INVALID_PARAM;
599 OCStackResult ret = OC_STACK_ERROR;
600 TWResultCode twRet = TW_RESULT_UNKNOWN;
603 if (newState == NULL)
605 size = strlen(AT_CMD_RUN_ON_OFF) + strlen(nodeId) +
606 SEPARATOR_LENGTH + strlen(endpointId) +
607 SEPARATOR_LENGTH + strlen(SENDMODE) + 1;
611 size = strlen(AT_CMD_RUN_ON_OFF) + strlen(nodeId) +
612 SEPARATOR_LENGTH + strlen(endpointId) +
613 SEPARATOR_LENGTH + strlen(SENDMODE) +
614 SEPARATOR_LENGTH + strlen(newState) + 1;
617 char* cmdString = (char*)OICMalloc(size * sizeof(char));
618 if (cmdString == NULL)
620 OIC_LOG(ERROR, TAG, "No Memory");
621 ret = OC_STACK_NO_MEMORY;
625 int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s",
626 AT_CMD_RUN_ON_OFF, nodeId, SEPARATOR,
627 endpointId, SEPARATOR, SENDMODE);
630 OIC_LOG(ERROR, TAG, "Build command error.");
631 ret = OC_STACK_ERROR;
634 if (newState != NULL)
636 OICStrcat(cmdString, size, SEPARATOR);
637 OICStrcat(cmdString, size, newState);
640 twRet = TWIssueATCommand(ctx->g_plugin, cmdString);
641 if (twRet != TW_RESULT_OK)
643 OIC_LOG_V(ERROR, TAG, "Write %s", cmdString);
644 ret = OC_STACK_ERROR;
647 OIC_LOG_V(INFO, TAG, "Write %s", cmdString);
649 TWEntry* entry = NULL;
650 twRet = TWDequeueEntry(ctx->g_plugin, &entry, TW_DFTREP);
651 if (twRet != TW_RESULT_OK)
653 OIC_LOG(ERROR, TAG, "TWDequeueEntry");
654 ret = OC_STACK_ERROR;
659 OIC_LOG(ERROR, TAG, "TWEntry is NULL");
660 ret = OC_STACK_ERROR;
664 twRet = processEntry(entry, ctx);
665 if (twRet != TW_RESULT_OK)
667 OIC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString);
668 ret = OC_STACK_ERROR;
675 TWDeleteEntry(ctx->g_plugin, entry);
677 OIC_LOG_V(INFO, TAG, "Leave TWSwitchOnOff() with ret=%d", ret);
681 OCStackResult TWMoveToLevel(char* nodeId, char* endpointId,
682 char* onOffState, char* level, char* transTime,
683 PIPlugin_Zigbee* plugin)
685 //AT+LCMVTOLEV:<Address>,<EP>,<SendMode>,<ON/OFF>,<LevelValue>,<TransTime>
687 OIC_LOG(INFO, TAG, "Enter TWMoveToLevel()");
689 TWContext* ctx = GetTWContext(plugin);
692 OIC_LOG(ERROR, TAG, "Invalid Param");
693 return OC_STACK_INVALID_PARAM;
696 OCStackResult ret = OC_STACK_ERROR;
697 TWResultCode twRet = TW_RESULT_UNKNOWN;
700 size = strlen(AT_CMD_MOVE_TO_LEVEL) + strlen(nodeId) +
701 SEPARATOR_LENGTH + strlen(endpointId) +
702 SEPARATOR_LENGTH + strlen(SENDMODE) +
703 SEPARATOR_LENGTH + strlen(onOffState) +
704 SEPARATOR_LENGTH + strlen(level) +
705 SEPARATOR_LENGTH + strlen(transTime) + 1;
707 char* cmdString = (char*)OICMalloc(size * sizeof(char));
708 if (cmdString == NULL)
710 OIC_LOG(ERROR, TAG, "No Memory");
711 ret = OC_STACK_NO_MEMORY;
715 int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s%s%s",
716 AT_CMD_MOVE_TO_LEVEL, nodeId,
717 SEPARATOR, endpointId,
719 SEPARATOR, onOffState,
721 SEPARATOR, transTime);
724 OIC_LOG(ERROR, TAG, "Build command error.");
725 ret = OC_STACK_ERROR;
729 twRet = TWIssueATCommand(ctx->g_plugin, cmdString);
730 if (twRet != TW_RESULT_OK)
732 OIC_LOG_V(ERROR, TAG, "Write %s", cmdString);
733 ret = OC_STACK_ERROR;
737 OIC_LOG_V(INFO, TAG, "Write %s", cmdString);
739 TWEntry* entry = NULL;
740 twRet = TWDequeueEntry(ctx->g_plugin, &entry, TW_DFTREP);
741 if (twRet != TW_RESULT_OK)
743 OIC_LOG(ERROR, TAG, "TWDequeueEntry");
744 ret = OC_STACK_ERROR;
749 OIC_LOG(ERROR, TAG, "TWEntry is NULL");
750 ret = OC_STACK_ERROR;
754 twRet = processEntry(entry, ctx);
755 if (twRet != TW_RESULT_OK)
757 OIC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString);
758 ret = OC_STACK_ERROR;
765 TWDeleteEntry(ctx->g_plugin, entry);
767 OIC_LOG_V(INFO, TAG, "Leave TWMoveToLevel() with ret=%d", ret);
771 OCStackResult TWSwitchDoorLockState(char* nodeId, char* endpointId, char* newState,
772 PIPlugin_Zigbee* plugin)
774 //AT+DRLOCK:<Address>,<EP>,<SendMode>,<Lock/Unlock>
776 OIC_LOG(INFO, TAG, "Enter TWSwitchDoorLockState()");
778 TWContext* ctx = GetTWContext(plugin);
781 OIC_LOG(ERROR, TAG, "Invalid Param");
782 return OC_STACK_INVALID_PARAM;
785 OCStackResult ret = OC_STACK_ERROR;
786 TWResultCode twRet = TW_RESULT_UNKNOWN;
789 size = strlen(AT_CMD_DOOR_LOCK) + strlen(nodeId) +
790 SEPARATOR_LENGTH + strlen(endpointId) +
791 SEPARATOR_LENGTH + strlen(SENDMODE) +
792 SEPARATOR_LENGTH + strlen(newState) + 1;
794 char* cmdString = (char*)OICMalloc(size * sizeof(char));
795 if (cmdString == NULL)
797 OIC_LOG(ERROR, TAG, "No Memory");
798 ret = OC_STACK_NO_MEMORY;
802 int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s%s%s",
803 AT_CMD_DOOR_LOCK, nodeId,
804 SEPARATOR, endpointId,
806 SEPARATOR, newState);
809 OIC_LOG(ERROR, TAG, "Build command error.");
810 ret = OC_STACK_ERROR;
814 twRet = TWIssueATCommand(ctx->g_plugin, cmdString);
815 if (twRet != TW_RESULT_OK)
817 OIC_LOG_V(ERROR, TAG, "Write %s", cmdString);
818 ret = OC_STACK_ERROR;
822 OIC_LOG_V(INFO, TAG, "Write %s", cmdString);
824 TWEntry* entry = NULL;
825 twRet = TWDequeueEntry(ctx->g_plugin, &entry, TW_DFTREP);
826 if (twRet != TW_RESULT_OK)
828 OIC_LOG(ERROR, TAG, "TWDequeueEntry");
829 ret = OC_STACK_ERROR;
835 OIC_LOG(ERROR, TAG, "TWEntry is NULL");
836 ret = OC_STACK_ERROR;
840 twRet = processEntry(entry, ctx);
841 if (twRet != TW_RESULT_OK)
843 OIC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString);
844 ret = OC_STACK_ERROR;
851 TWDeleteEntry(ctx->g_plugin, entry);
853 OIC_LOG_V(INFO, TAG, "Leave TWSwitchDoorLockState() with ret=%d", ret);
857 OCStackResult TWColorMoveToColorTemperature(char* nodeId, char* endpointId,
858 char* colorTemperature, char* transTime,
859 PIPlugin_Zigbee* plugin)
862 //AT+CCMVTOCT:<Address>,<EP>,<SendMode>,<ColorTemperature>,<TransTime>
866 OIC_LOG(INFO, TAG, "Enter TWColorMoveToColorTemperature()");
868 TWContext* ctx = GetTWContext(plugin);
871 OIC_LOG(ERROR, TAG, "Invalid Param");
872 return OC_STACK_INVALID_PARAM;
875 OCStackResult ret = OC_STACK_ERROR;
876 TWResultCode twRet = TW_RESULT_UNKNOWN;
879 size = strlen(AT_CMD_COLOR_CTRL_MOVE_TO_COLOR_TEMPERATURE) + strlen(nodeId) +
880 SEPARATOR_LENGTH + strlen(endpointId) +
881 SEPARATOR_LENGTH + strlen(SENDMODE) +
882 SEPARATOR_LENGTH + strlen(colorTemperature) +
883 SEPARATOR_LENGTH + strlen(transTime) + 1;
885 char* cmdString = (char*)OICMalloc(size * sizeof(char));
886 if (cmdString == NULL)
888 OIC_LOG(ERROR, TAG, "No Memory");
889 ret = OC_STACK_NO_MEMORY;
893 int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s",
894 AT_CMD_COLOR_CTRL_MOVE_TO_COLOR_TEMPERATURE, nodeId,
895 SEPARATOR, endpointId,
897 SEPARATOR, colorTemperature,
898 SEPARATOR, transTime);
901 OIC_LOG(ERROR, TAG, "Build command error.");
902 ret = OC_STACK_ERROR;
905 twRet = TWIssueATCommand(ctx->g_plugin, cmdString);
906 if (twRet != TW_RESULT_OK)
908 OIC_LOG_V(ERROR, TAG, "Write %s", cmdString);
909 ret = OC_STACK_ERROR;
912 OIC_LOG_V(INFO, TAG, "Write %s", cmdString);
914 TWEntry* entry = NULL;
915 twRet = TWDequeueEntry(ctx->g_plugin, &entry, TW_DFTREP);
916 if (twRet != TW_RESULT_OK)
918 OIC_LOG_V(ERROR, TAG, "TWDequeueEntry - %s", cmdString);
919 ret = OC_STACK_ERROR;
924 OIC_LOG_V(ERROR, TAG, "TWEntry is NULL - %s", cmdString);
925 ret = OC_STACK_ERROR;
929 twRet = processEntry(entry, ctx);
930 if (twRet != TW_RESULT_OK)
932 OIC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString);
933 ret = OC_STACK_ERROR;
940 TWDeleteEntry(ctx->g_plugin, entry);
942 OIC_LOG_V(INFO, TAG, "Leave TWColorMoveToColorTemperature() with ret=%d", ret);
946 OCStackResult TWSetDiscoveryCallback(const TWDeviceFoundCallback callback, PIPlugin_Zigbee* plugin)
948 OIC_LOG(INFO, TAG, "Enter TWSetDiscoveryCallback()");
950 OCStackResult ret = OC_STACK_OK;
952 TWContext* ctx = GetTWContext(plugin);
955 ret = OC_STACK_INVALID_PARAM;
959 if (callback != NULL)
961 ctx->g_DeviceFoundCallback= callback;
965 ctx->g_DeviceFoundCallback = NULL;
969 OIC_LOG_V(INFO, TAG, "Leave TWSetDiscoveryCallback() with ret=%d", ret);
973 OCStackResult TWSetEndDeviceNodeIdChangedCallback(TWDeviceNodeIdChangedCallback callback,
974 PIPlugin_Zigbee* plugin)
976 OIC_LOG(INFO, TAG, "Enter TWSetEndDeviceNodeIdChangedCallback()");
978 OCStackResult ret = OC_STACK_OK;
980 TWContext* ctx = GetTWContext(plugin);
983 ret = OC_STACK_INVALID_PARAM;
987 if (callback != NULL)
989 ctx->g_EndDeviceNodeIdChangedCallback= callback;
993 ctx->g_EndDeviceNodeIdChangedCallback = NULL;
996 OIC_LOG_V(INFO, TAG, "Leave TWSetEndDeviceNodeIdChangedCallback() with ret=%d", ret);
1000 OCStackResult TWSetStatusUpdateCallback(TWDeviceStatusUpdateCallback callback,
1001 PIPlugin_Zigbee* plugin)
1003 OIC_LOG(INFO, TAG, "Enter TWSetStatusUpdateCallback()");
1005 OCStackResult ret = OC_STACK_OK;
1007 TWContext* ctx = GetTWContext(plugin);
1010 ret = OC_STACK_INVALID_PARAM;
1014 if (callback != NULL)
1016 ctx->g_DeviceStatusUpdateCallback= callback;
1020 ctx->g_DeviceStatusUpdateCallback = NULL;
1024 OIC_LOG_V(INFO, TAG, "Leave TWSetStatusUpdateCallback() with ret=%d", ret);
1028 OCStackResult TWListenForStatusUpdates(char* nodeId, char* endpointId, PIPlugin_Zigbee* plugin)
1030 OIC_LOG(INFO, TAG, "Enter TWListenForStatusUpdates()");
1032 OCStackResult ret = OC_STACK_OK;
1034 TWContext* ctx = GetTWContext(plugin);
1037 ret = OC_STACK_INVALID_PARAM;
1041 char* zoneClusterID = "0500";
1042 char* zoneAttributeID = "0010";
1043 char* attributeDateType = "F0";
1045 ret = TWSetAttribute(NULL, nodeId, endpointId,
1046 zoneClusterID, zoneAttributeID, attributeDateType,
1047 ctx->g_LocalEUI, ctx->g_plugin);
1049 if (ret == OC_STACK_INVALID_OPTION)
1051 OIC_LOG(INFO, TAG, "Already registered for ZoneStatusUpdate");
1055 OIC_LOG_V(INFO, TAG, "Leave TWListenForStatusUpdates() with ret=%d", ret);
1059 OCStackResult TWProcess(PIPlugin_Zigbee* plugin)
1063 return OC_STACK_INVALID_PARAM;
1065 TWContext* ctx = GetTWContext(plugin);
1068 return OC_STACK_INVALID_PARAM;
1071 TWResultCode ret = TW_RESULT_UNKNOWN;
1075 TWEntry* entry = NULL;
1076 ret = TWDequeueEntry(ctx->g_plugin, &entry, TW_NONE);
1077 if (ret != TW_RESULT_OK)
1079 OIC_LOG(ERROR, TAG, "TWDequeueEntry");
1080 ret = OC_STACK_ERROR;
1089 ret = processEntry(entry, ctx);
1090 if (ret != TW_RESULT_OK)
1092 OIC_LOG(ERROR, TAG, "processEntry");
1093 ret = TWDeleteEntry(ctx->g_plugin, entry);
1094 if(ret != TW_RESULT_OK)
1096 OIC_LOG(ERROR, TAG, "Failed to delete entry.");
1097 ret = OC_STACK_ERROR;
1103 OIC_LOG(INFO, TAG, "processEntry");
1104 ret = TWDeleteEntry(ctx->g_plugin, entry);
1105 if(ret != TW_RESULT_OK)
1107 OIC_LOG(ERROR, TAG, "Failed to delete entry.");
1108 ret = OC_STACK_ERROR;
1117 OCStackResult TWUninitialize(PIPlugin_Zigbee* plugin)
1119 OIC_LOG(INFO, TAG, "Enter TWUninitializeZigBee()");
1120 OCStackResult ret = OC_STACK_ERROR;
1122 TWContext* ctx = GetTWContext(plugin);
1125 ret = OC_STACK_INVALID_PARAM;
1129 TWResultCode twRet = TWStopSock(ctx->g_plugin);
1130 if (twRet == TW_RESULT_OK)
1132 OIC_LOG(INFO, TAG, "TWStopSock");
1137 OIC_LOG(ERROR, TAG, "TWStopSock");
1138 ret = OC_STACK_ERROR;
1140 DeallocateTWDeviceList(ctx);
1142 LL_DELETE(g_twContextList, ctx);
1146 OIC_LOG_V(INFO, TAG, "Leave TWUninitializeZigBee() with ret=%d", ret);
1150 //-----------------------------------------------------------------------------
1151 // Internal functions
1152 //-----------------------------------------------------------------------------
1154 TWResultCode processEntry(TWEntry *entry, TWContext* ctx)
1156 OIC_LOG(INFO, TAG, "Enter processEntry()");
1158 TWResultCode ret = TW_RESULT_UNKNOWN;
1161 case TW_NETWORK_INFO:
1162 ret = processEntryNETWORK_INFO(entry, ctx);
1163 if ((ret != TW_RESULT_NO_LOCAL_PAN) &&
1164 (ret != TW_RESULT_HAS_LOCAL_PAN))
1166 OIC_LOG(ERROR, TAG, "processEntryNETWORK_INFO.");
1170 ret = processEntryJPAN(entry, ctx);
1171 if (ret != TW_RESULT_OK)
1173 OIC_LOG(ERROR, TAG, "processEntryJPAN.");
1177 ret = processEntryEndDevice(entry, ctx);
1178 if (ret != TW_RESULT_OK)
1180 OIC_LOG(ERROR, TAG, "processEntrySED.");
1184 ret = processEntryEndDevice(entry, ctx);
1185 if (ret != TW_RESULT_OK)
1187 OIC_LOG(ERROR, TAG, "processEntryRFD.");
1191 ret = processEntryEndDevice(entry, ctx);
1192 if (ret != TW_RESULT_OK)
1194 OIC_LOG(ERROR, TAG, "processEntryFFD.");
1198 ret = processEntryEndDevice(entry, ctx);
1199 if (ret != TW_RESULT_OK)
1201 OIC_LOG(ERROR, TAG, "processEntryZED.");
1205 ret = processEntryMatchDesc(entry, ctx);
1206 if (ret != TW_RESULT_OK)
1208 OIC_LOG(ERROR, TAG, "processEntryMatchDesc.");
1212 ret = processEntrySimpleDesc(entry, ctx);
1213 if (ret != TW_RESULT_OK)
1215 OIC_LOG(ERROR, TAG, "processEntrySimpleDesc.");
1219 ret = processEntryWriteAttr(entry, ctx);
1220 if (ret == TW_RESULT_ERROR_INVALID_OP)
1222 OIC_LOG_V(INFO, TAG, "processEntryWriteAttr - ret=%d", TW_RESULT_ERROR_INVALID_OP);
1224 else if (ret != TW_RESULT_OK)
1226 OIC_LOG(ERROR, TAG, "processEntryWriteAttr.");
1230 ret = processEntryReadAttr(entry, ctx);
1231 if (ret != TW_RESULT_REMOTE_ATTR_HAS_VALUE)
1233 OIC_LOG(ERROR, TAG, "processEntryReadAttr.");
1236 case TW_TEMPERATURE:
1237 ret = processEntryTemperature(entry, ctx);
1238 if (ret != TW_RESULT_REMOTE_ATTR_HAS_VALUE)
1240 OIC_LOG(ERROR, TAG, "processEntryTemperature.");
1244 ret = processEntrySwitchDoorLockState(entry, ctx);
1245 if (ret != TW_RESULT_OK)
1247 OIC_LOG(ERROR, TAG, "processEntrySwitchDoorLockState.");
1250 case TW_DRUNLOCKRSP:
1251 ret = processEntrySwitchDoorLockState(entry, ctx);
1252 if (ret != TW_RESULT_OK)
1254 OIC_LOG(ERROR, TAG, "processEntrySwitchDoorLockState.");
1258 ret = processEntryZCLDefaultResponse(entry, ctx);
1259 if (ret != TW_RESULT_OK)
1261 OIC_LOG(ERROR, TAG, "processEntryZCLDefaultResponse.");
1265 ret = processEntryZoneEnrollRequest(entry, ctx);
1266 if (ret != TW_RESULT_OK)
1268 OIC_LOG(ERROR, TAG, "processEntryZoneEnrollRequest.");
1272 ret = processEntryEnrolled(entry, ctx);
1273 if (ret != TW_RESULT_OK)
1275 OIC_LOG(ERROR, TAG, "processEntryEnrolled.");
1279 ret = processEntryZoneStatus(entry, ctx);
1280 if (ret != TW_RESULT_OK)
1282 OIC_LOG(ERROR, TAG, "processEntryZoneStatus.");
1285 case TW_ADDRESS_RESPONSE:
1286 ret = processEntryAddressResponse(entry, ctx);
1287 if (ret != TW_RESULT_OK)
1289 OIC_LOG(ERROR, TAG, "processEntryAddressResponse.");
1293 OIC_LOG(ERROR, TAG, "processEntry() doesn't receive an valid entry.");
1294 ret = TW_RESULT_ERROR;
1298 OIC_LOG_V(INFO, TAG, "Leave processEntry() with ret=%d", ret);
1302 TWResultCode processEntryNETWORK_INFO(TWEntry* entry, TWContext* ctx)
1310 // +N=COO,26,-6,7306,133F04EA669C6B24
1314 OIC_LOG(INFO, TAG, "Enter processEntryNETWORK_INFO()");
1316 TWResultCode ret = TW_RESULT_UNKNOWN;
1318 if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0)
1320 OIC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode);
1321 ret = TW_RESULT_ERROR;
1325 ret = HandleATResponse(entry,ctx);
1328 OIC_LOG_V(INFO, TAG, "Leave processEntryNETWORK_INFO() with ret=%d", ret);
1332 TWResultCode processEntryJPAN(TWEntry* entry, TWContext* ctx)
1337 // JPAN:26,7306,133F04EA669C6B24
1343 OIC_LOG(INFO, TAG, "Enter processEntryJPAN()");
1345 TWResultCode ret = TW_RESULT_UNKNOWN;
1346 if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) == 0)
1348 ret = HandleATResponse(entry,ctx);
1349 if (ret == TW_RESULT_NEW_LOCAL_PAN_ESTABLISHED)
1351 OIC_LOG(INFO, TAG, "New Local PAN established.");
1356 ret = TW_RESULT_ERROR;
1359 else if (strcmp(entry->atErrorCode, AT_STR_ERROR_NODE_IS_PART_OF_PAN) == 0)
1361 OIC_LOG(INFO, TAG, "Already Established PAN.");
1366 OIC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode);
1367 ret = TW_RESULT_ERROR;
1370 OIC_LOG_V(INFO, TAG, "Leave processEntryJPAN() with ret=%d", ret);
1374 TWResultCode processEntryEndDevice(TWEntry* entry, TWContext* ctx)
1376 OIC_LOG(INFO, TAG, "Enter processEntryEndDevice()");
1378 TWResultCode ret = TW_RESULT_UNKNOWN;
1379 ret = HandleATResponse(entry,ctx);
1380 if (ret != TW_RESULT_OK)
1382 OIC_LOG(ERROR, TAG, "HandleATResponse");
1385 OIC_LOG_V(INFO, TAG, "Leave processEntryEndDevice() with ret=%d", ret);
1389 TWResultCode processEntryMatchDesc(TWEntry* entry, TWContext* ctx)
1391 //MatchDesc:0B4A,00,01
1393 OIC_LOG(INFO, TAG, "Enter processEntryMatchDesc()");
1394 TWResultCode ret = TW_RESULT_UNKNOWN;
1396 if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0)
1398 OIC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode);
1399 ret = TW_RESULT_ERROR;
1403 ret = HandleATResponse(entry,ctx);
1404 if (ret == TW_RESULT_OK)
1406 OIC_LOG(INFO, TAG, "HandleATResponse");
1407 ret = FindClusters(ctx->g_WIPDevice->nodeId,
1408 ctx->g_WIPDevice->endpointOfInterest->endpointId,
1410 if (ret == TW_RESULT_OK)
1412 OIC_LOG(INFO, TAG, "FindClusters - Found a match node");
1413 if (ctx->g_DeviceFoundCallback != NULL)
1415 OIC_LOG(INFO, TAG, "Found a match node -- invoke callback");
1416 ctx->g_DeviceFoundCallback(ctx->g_WIPDevice, ctx->g_plugin);
1422 OIC_LOG(ERROR, TAG, "FindClusters");
1423 ret = TW_RESULT_ERROR;
1428 OIC_LOG(ERROR, TAG, "HandleATResponse");
1429 ret = TW_RESULT_ERROR;
1432 ctx->g_WIPDevice = NULL; //reset and do not deallocate it
1435 OIC_LOG_V(INFO, TAG, "Leave processEntryMatchDesc() with ret=%d", ret);
1439 TWResultCode processEntrySimpleDesc(TWEntry* entry, TWContext* ctx)
1442 //AT+SIMPLEDESC:3746,3746,01
1446 // SimpleDesc:3746,00
1450 // InCluster:0000,0001,0003,0402,0500,0020,0B05
1455 OIC_LOG(INFO, TAG, "Enter processEntrySimpleDesc()");
1457 TWResultCode ret = TW_RESULT_UNKNOWN;
1459 if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0)
1461 OIC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", (entry->atErrorCode));
1462 ret = TW_RESULT_ERROR;
1466 if (entry->count == 6) //must be 6 as it is the number of lines to expect
1468 ret = HandleATResponse(entry,ctx);
1469 if (ret == TW_RESULT_HAS_CLUSTERS)
1471 OIC_LOG(INFO, TAG, "has clusters.");
1477 OIC_LOG(INFO, TAG, "Received an invalid Simple Descriptor.");
1478 ret = TW_RESULT_ERROR;
1482 OIC_LOG_V(INFO, TAG, "Leave processEntrySimpleDesc() returns with ret=%d", ret);
1486 TWResultCode processEntryWriteAttr(TWEntry* entry, TWContext* ctx)
1488 //AT+WRITEATR:3A3D,01,0,0003,0000,21,00
1490 // WRITEATTR:3A3D,01,0003,,00
1492 OIC_LOG(INFO, TAG, "Enter processEntryWriteAttr()");
1494 TWResultCode ret = TW_RESULT_UNKNOWN;
1496 if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0)
1498 OIC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode);
1499 ret = TW_RESULT_ERROR;
1503 ret = HandleATResponse(entry,ctx);
1506 OIC_LOG_V(INFO, TAG, "Leave processEntryWriteAttr() returns with ret=%d", ret);
1510 TWResultCode processEntryReadAttr(TWEntry* entry, TWContext* ctx)
1512 OIC_LOG(INFO, TAG, "Enter processEntryReadAttr()");
1514 TWResultCode ret = TW_RESULT_UNKNOWN;
1516 if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0)
1518 OIC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode);
1519 ret = TW_RESULT_ERROR;
1523 ret = HandleATResponse(entry,ctx);
1526 OIC_LOG_V(INFO, TAG, "Leave processEntryReadAttr() returns with ret=%d", ret);
1530 TWResultCode processEntryTemperature(TWEntry* entry, TWContext* ctx)
1532 OIC_LOG(INFO, TAG, "Enter processEntryTemperature()");
1534 TWResultCode ret = TW_RESULT_UNKNOWN;
1536 if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0)
1538 OIC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode);
1539 ret = TW_RESULT_ERROR;
1543 ret = HandleATResponse(entry,ctx);
1546 OIC_LOG_V(INFO, TAG, "Leave processEntryTemperature() returns with ret=%d", ret);
1550 TWResultCode processEntrySwitchDoorLockState(TWEntry* entry, TWContext* ctx)
1552 OIC_LOG(INFO, TAG, "Enter processEntrySwitchDoorLockState()");
1554 TWResultCode ret = TW_RESULT_UNKNOWN;
1556 if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0)
1558 OIC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode);
1559 ret = TW_RESULT_ERROR;
1563 ret = HandleATResponse(entry,ctx);
1566 OIC_LOG_V(INFO, TAG, "Leave processEntrySwitchDoorLockState() returns with ret=%d", ret);
1570 TWResultCode processEntryZCLDefaultResponse(TWEntry* entry, TWContext* ctx)
1572 OIC_LOG(INFO, TAG, "Enter processEntryZCLDefaultResponse()");
1574 TWResultCode ret = TW_RESULT_UNKNOWN;
1576 if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0)
1578 if (strcmp(entry->atErrorCode, AT_STR_ERROR_MESSAGE_NOT_SENT_TO_TARGET_SUCCESSFULLY) == 0)
1580 OIC_LOG(ERROR, TAG, "Send to the target not succeed.");
1581 ret = TW_RESULT_ERROR;
1585 OIC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode);
1586 ret = TW_RESULT_ERROR;
1591 ret = HandleATResponse(entry,ctx);
1594 OIC_LOG_V(INFO, TAG, "Leave processEntryZCLDefaultResponse() returns with ret=%d", ret);
1598 TWResultCode processEntryZoneEnrollRequest(TWEntry* entry, TWContext* ctx)
1600 OIC_LOG(INFO, TAG, "Enter processEntryZoneEnrollRequest()");
1602 TWResultCode ret = TW_RESULT_UNKNOWN;
1603 if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0)
1605 OIC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode);
1606 ret = TW_RESULT_ERROR;
1610 ret = HandleATResponse(entry,ctx);
1613 OIC_LOG_V(INFO, TAG, "Leave processEntryZoneEnrollRequest() with ret=%d", ret);
1617 TWResultCode processEntryEnrolled(TWEntry* entry, TWContext* ctx)
1619 OIC_LOG(INFO, TAG, "Enter processEntryEnrolled()");
1621 TWResultCode ret = TW_RESULT_UNKNOWN;
1622 if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0)
1624 OIC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode);
1625 ret = TW_RESULT_ERROR;
1629 ret = HandleATResponse(entry,ctx);
1632 OIC_LOG_V(INFO, TAG, "Leave processEntryEnrolled() with ret=%d", ret);
1636 TWResultCode processEntryZoneStatus(TWEntry* entry, TWContext* ctx)
1638 OIC_LOG(INFO, TAG, "Enter processEntryZoneStatus()");
1640 TWResultCode ret = TW_RESULT_UNKNOWN;
1641 if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0)
1643 OIC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode);
1644 ret = TW_RESULT_ERROR;
1648 ret = HandleATResponse(entry,ctx);
1651 OIC_LOG_V(INFO, TAG, "Leave processEntryZoneStatus() with ret=%d", ret);
1655 TWResultCode processEntryAddressResponse(TWEntry* entry, TWContext* ctx)
1657 OIC_LOG(INFO, TAG, "Enter processEntryAddressResponse()");
1659 TWResultCode ret = TW_RESULT_UNKNOWN;
1660 if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0)
1662 OIC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode);
1663 ret = TW_RESULT_ERROR;
1667 ret = HandleATResponse(entry,ctx);
1670 OIC_LOG_V(INFO, TAG, "Leave processEntryAddressResponse() with ret=%d", ret);
1674 TWResultCode Reset(TWContext* ctx)
1676 OIC_LOG(INFO, TAG, "Enter Reset()");
1678 TWResultCode ret = TW_RESULT_ERROR;
1679 ret = TWIssueATCommand(ctx->g_plugin, AT_CMD_RESET);
1680 if (ret == TW_RESULT_OK)
1682 OIC_LOG_V(INFO, TAG, "Write %s", AT_CMD_RESET);
1686 OIC_LOG_V(ERROR, TAG, "Write %s", AT_CMD_RESET);
1688 OIC_LOG_V(INFO, TAG, "Leave Reset() with ret=%d", ret);
1692 TWResultCode CreatePAN(TWContext* ctx)
1700 // +N=COO,26,-6,7306,133F04EA669C6B24
1705 // JPAN:26,7306,133F04EA669C6B24
1711 OIC_LOG(INFO, TAG, "Enter CreatePAN()");
1713 TWResultCode twRet1 = TW_RESULT_UNKNOWN;
1714 TWResultCode twRet2 = TW_RESULT_UNKNOWN;
1715 TWResultCode ret = TW_RESULT_UNKNOWN;
1716 ret = TWIssueATCommand(ctx->g_plugin, AT_CMD_GET_NETWORK_INFO);
1717 if (ret != TW_RESULT_OK)
1719 OIC_LOG_V(ERROR, TAG, "Write %s", AT_CMD_GET_NETWORK_INFO);
1722 OIC_LOG_V(INFO, TAG, "Write %s", AT_CMD_GET_NETWORK_INFO);
1723 TWEntry* entry = NULL;
1724 TWEntry* entry2 = NULL;
1725 ret = TWDequeueEntry(ctx->g_plugin, &entry, TW_NETWORK_INFO);
1726 if (ret != TW_RESULT_OK)
1728 OIC_LOG_V(ERROR, TAG, "TWDequeueEntry - %s", AT_CMD_GET_NETWORK_INFO);
1733 OIC_LOG_V(ERROR, TAG, "TWEntry is NULL - %s", AT_CMD_GET_NETWORK_INFO);
1734 ret = TW_RESULT_ERROR;
1737 ret = processEntry(entry, ctx);
1738 if (ret == TW_RESULT_HAS_LOCAL_PAN)
1740 OIC_LOG(INFO, TAG, "Has local PAN.");
1743 else if (ret == TW_RESULT_NO_LOCAL_PAN)
1745 OIC_LOG(INFO, TAG, "Has no local PAN.");
1746 ret = TWIssueATCommand(ctx->g_plugin, AT_CMD_ESTABLISH_NETWORK);
1747 if (ret != TW_RESULT_OK)
1749 OIC_LOG_V(ERROR, TAG, "Write %s", AT_CMD_ESTABLISH_NETWORK);
1752 OIC_LOG_V(INFO, TAG, "Write %s", AT_CMD_ESTABLISH_NETWORK);
1754 ret = TWDequeueEntry(ctx->g_plugin, &entry2, TW_JPAN);
1755 if (ret != TW_RESULT_OK)
1757 OIC_LOG_V(ERROR, TAG, "TWDequeueEntry - %s", AT_CMD_ESTABLISH_NETWORK);
1762 OIC_LOG_V(ERROR, TAG, "TWEntry is NULL - %s", AT_CMD_ESTABLISH_NETWORK);
1763 ret = TW_RESULT_ERROR;
1766 ret = processEntry(entry2, ctx);
1767 if (ret == TW_RESULT_OK)
1769 OIC_LOG_V(INFO, TAG, "processEntry - %s", AT_CMD_ESTABLISH_NETWORK);
1774 OIC_LOG_V(ERROR, TAG, "processEntry - %s", AT_CMD_ESTABLISH_NETWORK);
1775 ret = TW_RESULT_ERROR;
1780 OIC_LOG_V(ERROR, TAG, "processEntry - unexpected return code: %d", ret);
1781 ret = TW_RESULT_ERROR;
1787 twRet1 = TWDeleteEntry(ctx->g_plugin, entry);
1788 if(twRet1 != TW_RESULT_OK)
1790 OIC_LOG_V(ERROR, TAG, "TWDeleteEntry 1 - ret=%d", twRet1);
1795 twRet2 = TWDeleteEntry(ctx->g_plugin, entry2);
1796 if(twRet2 != TW_RESULT_OK)
1798 OIC_LOG_V(ERROR, TAG, "TWDeleteEntry 2 - ret=%d", twRet2);
1802 OIC_LOG_V(INFO, TAG, "Leave CreatePan with ret=%d", ret);
1806 TWContext * GetTWContext(PIPlugin_Zigbee* plugin)
1812 TWContext * out = NULL;
1813 TWContext * tmp = NULL;
1814 LL_FOREACH_SAFE(g_twContextList, out, tmp)
1816 if(out->g_plugin == plugin)
1824 TWResultCode EnableJoin(bool isKeyEncrypted, TWContext* ctx)
1830 //Response: ERROR:70
1832 (void)isKeyEncrypted;
1833 isKeyEncrypted = false; //TODO: for now - don't encrypt
1835 TWResultCode ret = TW_RESULT_ERROR;
1836 char* joinTimeHex = "0F"; //TODO: for now - 15 seconds
1837 char* broadcast = "FFFC";
1839 int size = strlen(AT_CMD_PERMIT_JOIN) + strlen(joinTimeHex) +
1840 SEPARATOR_LENGTH + strlen(broadcast) + 1;
1841 char* cmdString = (char*)OICMalloc(size * sizeof(char));
1842 if (cmdString == NULL)
1844 OIC_LOG(ERROR, TAG, "No Memory");
1845 ret = TW_RESULT_ERROR_NO_MEMORY;
1848 snprintf(cmdString, size, "%s%s%s%s",
1849 AT_CMD_PERMIT_JOIN, joinTimeHex, SEPARATOR, broadcast);
1850 ret = TWIssueATCommand(ctx->g_plugin, cmdString);
1851 if (ret != TW_RESULT_OK)
1853 OIC_LOG_V(ERROR, TAG, "Write %s", cmdString);
1854 ret = TW_RESULT_ERROR;
1857 OIC_LOG_V(INFO, TAG, "Write %s", cmdString);
1859 sleep(15); //must sleep here to permit joining for 15 seconds
1863 OIC_LOG_V(INFO, TAG, "Leave EnableJoin() with ret=%d", ret);
1867 TWResultCode FindMatchNodes(TWContext* ctx)
1869 //AT+MATCHREQ:0104,03,0003,0006,0402,00
1871 // MatchDesc:0B4A,00,01
1873 //AT+MATCHREQ:0104,03,0999,0999,0999,00
1876 OIC_LOG(INFO, TAG, "Enter FindMatchNodes()");
1878 TWResultCode ret = TW_RESULT_UNKNOWN;
1880 //TODO: add more clusters if needed
1882 int size = strlen(AT_CMD_MATCH_REQUEST) + strlen(ZB_PROFILE_ID_HOME_AUTOMATION) +
1883 SEPARATOR_LENGTH + strlen(IN_CLUSTER_COUNT_STRING) +
1884 SEPARATOR_LENGTH + strlen(ZB_CLUSTER_IDENTIFY) +
1885 SEPARATOR_LENGTH + strlen(ZB_CLUSTER_ON_OFF) +
1886 SEPARATOR_LENGTH + strlen(ZB_CLUSTER_TEMPERATURE_MEASUREMENT) +
1887 SEPARATOR_LENGTH + strlen(ZB_CLUSTER_IAS_ZONE) +
1888 SEPARATOR_LENGTH + strlen(ZB_CLUSTER_COLOR_CONTROL) +
1889 SEPARATOR_LENGTH + strlen(OUT_CLUSTER_COUNT_STRING) + 1;
1891 char* cmdString = (char*)OICMalloc(size * sizeof(char));
1892 if (cmdString == NULL)
1894 OIC_LOG(ERROR, TAG, "No Memory");
1895 ret = TW_RESULT_ERROR_NO_MEMORY;
1899 int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
1900 AT_CMD_MATCH_REQUEST, ZB_PROFILE_ID_HOME_AUTOMATION,
1901 SEPARATOR, IN_CLUSTER_COUNT_STRING,
1902 SEPARATOR, ZB_CLUSTER_IDENTIFY,
1903 SEPARATOR, ZB_CLUSTER_ON_OFF,
1904 SEPARATOR, ZB_CLUSTER_TEMPERATURE_MEASUREMENT,
1905 SEPARATOR, ZB_CLUSTER_IAS_ZONE,
1906 SEPARATOR, ZB_CLUSTER_COLOR_CONTROL,
1907 SEPARATOR, OUT_CLUSTER_COUNT_STRING);
1910 OIC_LOG(ERROR, TAG, "Build command error.");
1911 ret = OC_STACK_ERROR;
1914 ret = TWIssueATCommand(ctx->g_plugin, cmdString);
1915 if (ret != TW_RESULT_OK)
1917 OIC_LOG_V(ERROR, TAG, "Write %s.", cmdString);
1920 OIC_LOG_V(INFO, TAG, "Write %s.", cmdString);
1924 OIC_LOG_V(INFO, TAG, "Leave FindMatchNodes() with ret=%d", ret);
1928 TWResultCode FindClusters(char nodeId[], char endpoint[], TWContext* ctx)
1931 //AT+SIMPLEDESC:3746,3746,01
1935 // SimpleDesc:3746,00
1939 // InCluster:0000,0001,0003,0402,0500,0020,0B05
1945 OIC_LOG(INFO, TAG, "Enter FindClusters()");
1947 TWResultCode ret = TW_RESULT_UNKNOWN;
1949 int size = strlen(AT_CMD_SIMPLE_DESC) + strlen(nodeId) +
1950 SEPARATOR_LENGTH + strlen(nodeId) +
1951 SEPARATOR_LENGTH + strlen(endpoint) + 1;
1953 char* cmdString = (char*)OICMalloc(size * sizeof(char));
1954 if (cmdString == NULL)
1956 OIC_LOG(ERROR, TAG, "No Memory");
1957 ret = TW_RESULT_ERROR_NO_MEMORY;
1961 int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s",
1962 AT_CMD_SIMPLE_DESC, nodeId,
1964 SEPARATOR, endpoint);
1967 OIC_LOG(ERROR, TAG, "Build command error.");
1968 ret = OC_STACK_ERROR;
1971 ret = TWIssueATCommand(ctx->g_plugin, cmdString);
1972 if (ret != TW_RESULT_OK)
1974 OIC_LOG_V(ERROR, TAG, "Write %s", cmdString);
1975 ret = TW_RESULT_ERROR;
1978 OIC_LOG_V(INFO, TAG, "Write %s", cmdString);
1980 TWEntry* entry = NULL;
1981 ret = TWDequeueEntry(ctx->g_plugin, &entry, TW_SIMPLEDESC);
1982 if (ret != TW_RESULT_OK)
1984 OIC_LOG_V(ERROR, TAG, "TWDequeueEntry - %s", cmdString);
1989 OIC_LOG_V(ERROR, TAG, "TWEntry is NULL - %s", cmdString);
1990 ret = TW_RESULT_ERROR;
1994 ret = processEntry(entry, ctx);
1995 if (ret == TW_RESULT_OK)
1997 OIC_LOG_V(INFO, TAG, "processEntry - %s", cmdString);
2001 OIC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString);
2005 TWDeleteEntry(ctx->g_plugin, entry);
2007 OIC_LOG_V(INFO, TAG, "Leave FindClusters() with ret=%d", ret);
2011 TWResultCode GetRemoteEUI(char *nodeId, char* outRemoteEUI, TWContext* ctx)
2013 //AT+EUIREQ:< Address>,<NodeID>[,XX]
2014 // AddrResp:<errorcode>[,<NodeID>,<EUI64>]
2015 // AddrResp:00,15ED,000D6F00040574B8
2017 OIC_LOG(INFO, TAG, "Enter GetRemoteEUI()");
2018 TWResultCode ret = TW_RESULT_UNKNOWN;
2020 int size = strlen(AT_CMD_REMOTE_EUI_REQUEST) + strlen(nodeId) +
2021 SEPARATOR_LENGTH + strlen(nodeId) + 1;
2022 char* cmdString = (char*)OICMalloc(size * sizeof(char));
2023 if (cmdString == NULL)
2025 OIC_LOG(ERROR, TAG, "No Memory");
2026 ret = TW_RESULT_ERROR_NO_MEMORY;
2030 int stringRet = snprintf(cmdString, size, "%s%s%s%s",
2031 AT_CMD_REMOTE_EUI_REQUEST, nodeId,
2035 OIC_LOG(ERROR, TAG, "Build command error.");
2036 ret = OC_STACK_ERROR;
2039 ret = TWIssueATCommand(ctx->g_plugin, cmdString);
2040 if (ret != TW_RESULT_OK)
2042 OIC_LOG_V(ERROR, TAG, "Write %s", cmdString);
2043 ret = TW_RESULT_ERROR;
2046 OIC_LOG_V(INFO, TAG, "Write %s", cmdString);
2048 TWEntry* entry = NULL;
2049 ret = TWDequeueEntry(ctx->g_plugin, &entry, TW_ADDRESS_RESPONSE);
2050 if (ret != TW_RESULT_OK)
2052 OIC_LOG_V(ERROR, TAG, "TWDequeueEntry - %s", cmdString);
2053 ret = TW_RESULT_ERROR;
2058 OIC_LOG_V(ERROR, TAG, "TWEntry is NULL - %s", cmdString);
2059 ret = TW_RESULT_ERROR;
2063 ret = processEntry(entry, ctx);
2064 if (ret != TW_RESULT_OK)
2066 OIC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString);
2067 ret = TW_RESULT_ERROR;
2070 OIC_LOG_V(INFO, TAG, "Wanted eui of NodeID=%s ", nodeId);
2071 OIC_LOG_V(INFO, TAG, "Received eui of g_WIPRemoteNodeId=%s ", ctx->g_WIPRemoteNodeId);
2072 if (strcmp(nodeId, ctx->g_WIPRemoteNodeId) != 0)
2074 OIC_LOG(ERROR, TAG, "Received eui for an unexpected remote node id.");
2075 ret = TW_RESULT_ERROR;
2079 OIC_LOG_V(INFO, TAG, "Remote NodeId:%s has EUI: %s \n",
2080 ctx->g_WIPRemoteNodeId, ctx->g_WIPRemoteEUI);
2081 OICStrcpy(outRemoteEUI, sizeof(ctx->g_WIPRemoteEUI), ctx->g_WIPRemoteEUI);
2086 memset(ctx->g_WIPRemoteEUI, '\0', sizeof(ctx->g_WIPRemoteEUI));
2087 memset(ctx->g_WIPRemoteNodeId, '\0', sizeof(ctx->g_WIPRemoteNodeId));
2088 TWDeleteEntry(ctx->g_plugin, entry);
2090 OIC_LOG_V(INFO, TAG, "Leave GetRemoteEUI() with ret=%d", ret);
2094 TWResultCode HandleATResponse(TWEntry* entry, TWContext* ctx)
2096 OIC_LOG(INFO, TAG, "Enter HandleATResponse()");
2098 TWResultCode ret = TW_RESULT_ERROR;
2101 for (; i < entry->count; i++)
2104 for (; k < sizeof(g_TWATResultHandlerPairArray)/sizeof(TWATResultHandlerPair); ++k)
2106 const char* line = (entry)->lines[i].line;
2108 g_TWATResultHandlerPairArray[k].resultTxt,
2109 strlen(g_TWATResultHandlerPairArray[k].resultTxt)
2112 char* tokens[ARRAY_LENGTH] = {};
2113 const char* delimiters = ",\r\n";
2114 int paramCount = Tokenize((entry)->lines[i].line +
2115 strlen(g_TWATResultHandlerPairArray[k].resultTxt),
2116 delimiters, tokens);
2119 ret = g_TWATResultHandlerPairArray[k].handler(paramCount, tokens, ctx);
2123 for (; n < paramCount; n++)
2133 OIC_LOG_V(INFO, TAG, "Leave HandleATResponse() with ret=%d", ret);
2137 //-----------------------------------------------------------------------------
2138 // Internal functions - AT Response/Prompt Handlers
2139 //-----------------------------------------------------------------------------
2141 TWResultCode TelAddressResponseHandler(int count, char* tokens[], TWContext* ctx)
2143 //AT+EUIREQ:< Address>,<NodeID>[,XX]
2144 // AddrResp:<errorcode>[,<NodeID>,<EUI64>]
2145 // AddrResp:00,15ED,000D6F00040574B8
2147 OIC_LOG(INFO, TAG, "Enter TelAddressResponseHandler()");
2149 TWResultCode ret = TW_RESULT_UNKNOWN;
2151 if(!tokens || count != RESPONSE_PARAMS_COUNT_ADDRESS_RESPONSE)
2153 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2157 if (strcmp(tokens[TOKEN_ADDRRESP_STATUS_CODE], AT_STR_ERROR_OK) != 0)
2159 OIC_LOG(ERROR, TAG, "AddrResp prompt contained error status.");
2160 ret = TW_RESULT_ERROR;
2164 OICStrcpy(ctx->g_WIPRemoteNodeId, SIZE_NODEID, tokens[TOKEN_ADDRRESP_NODEID]);
2165 OICStrcpy(ctx->g_WIPRemoteEUI, SIZE_EUI, tokens[TOKEN_ADDRRESP_EUI]);
2166 OIC_LOG_V(INFO, TAG, "Received eui %s for g_WIPRemoteNodeId=%s ",
2167 ctx->g_WIPRemoteEUI,
2168 ctx->g_WIPRemoteNodeId);
2173 OIC_LOG_V(INFO, TAG, "Leave TelAddressResponseHandler() with ret=%d", ret);
2177 TWResultCode TelNetworkInfoHandler(int count, char* tokens[], TWContext* ctx)
2180 // Response: +N=COO,24,-6,9726,12BB200F073AB573
2184 // +N=<devicetype>,<channel>,<power>,<PANID>,<EPANID>
2186 OIC_LOG(INFO, TAG, "Enter TelNetworkInfoHandler()");
2188 TWResultCode ret = TW_RESULT_UNKNOWN;
2191 ((count != RESPONSE_PARAMS_COUNT_NETWORK_INFO_1) &&
2192 (count != RESPONSE_PARAMS_COUNT_NETWORK_INFO_5)))
2194 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2199 for (; i < count; ++i)
2201 if (tokens[i] != NULL)
2203 OIC_LOG_V(INFO, TAG, "Token[%d] = %s", i, tokens[i]);
2207 char* temp = tokens[TOKEN_PLUS_N_DEVICE_TYPE];
2208 if (strcmp(temp, "NoPAN") == 0)
2210 OIC_LOG(INFO, TAG, "It is NoPan.");
2211 ret = TW_RESULT_NO_LOCAL_PAN;
2215 OIC_LOG(INFO, TAG, "Already have an established network.");
2216 ret = AsciiHexToValue(tokens[TOKEN_PLUS_N_PANID],
2217 strlen(tokens[TOKEN_PLUS_N_PANID]),
2218 &(ctx->g_ZigBeeStatus.panId));
2219 if(ret != TW_RESULT_OK)
2221 OIC_LOG(ERROR, TAG, "AsciiHexToValue - panId");
2225 ret = AsciiHexToValue(tokens[TOKEN_PLUS_N_PANID_EXTENDED],
2226 strlen(tokens[TOKEN_PLUS_N_PANID_EXTENDED]),
2227 &(ctx->g_ZigBeeStatus.extPanId));
2228 if(ret != TW_RESULT_OK)
2230 OIC_LOG(ERROR, TAG, "AsciiHexToValue - extPanId");
2233 OIC_LOG_V(INFO, TAG, "PanId=%" PRId64 , ctx->g_ZigBeeStatus.panId);
2234 OIC_LOG_V(INFO, TAG, "ExtPanId=%" PRId64 , ctx->g_ZigBeeStatus.extPanId);
2235 OIC_LOG_V(INFO, TAG, "PanId=%s", tokens[TOKEN_PLUS_N_PANID]);
2236 OIC_LOG_V(INFO, TAG, "ExtPanId=%s", tokens[TOKEN_PLUS_N_PANID_EXTENDED]);
2238 OIC_LOG_V(INFO, TAG, "TelNetworkInfoHandler set ExtPanId to %08X%08X",
2239 (unsigned int)(ctx->g_ZigBeeStatus.extPanId >> 32),
2240 (unsigned int)(ctx->g_ZigBeeStatus.extPanId & 0xFFFFFFFF));
2242 ret = TW_RESULT_HAS_LOCAL_PAN;
2245 OIC_LOG_V(INFO, TAG, "Leave TelNetworkInfoHandler() with ret=%d", ret);
2249 TWResultCode TelJpanHandler(int count, char* tokens[], TWContext* ctx)
2251 //Ask: AT+EN:[<channel>],[<POWER>],[<PANID>]
2252 //Response: JPAN:<channel>,<PANID>,<EPANID>
2254 OIC_LOG(INFO, TAG, "Enter TelJpanHandler()");
2256 TWResultCode ret = TW_RESULT_UNKNOWN;
2258 if(!tokens || count != RESPONSE_PARAMS_COUNT_JPAN)
2260 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2264 ret = AsciiHexToValue(tokens[TOKEN_JPAN_PANID],
2265 strlen(tokens[TOKEN_JPAN_PANID]),
2266 &(ctx->g_ZigBeeStatus.panId));
2268 if(ret != TW_RESULT_OK)
2270 OIC_LOG(ERROR, TAG, "AsciiHexToValue - panId");
2274 ret = AsciiHexToValue(tokens[TOKEN_JPAN_PANID_EXTENDED],
2275 strlen(tokens[TOKEN_JPAN_PANID_EXTENDED]),
2276 &(ctx->g_ZigBeeStatus.extPanId));
2277 if(ret != TW_RESULT_OK)
2279 OIC_LOG(ERROR, TAG, "AsciiHexToValue - extPanId");
2282 OIC_LOG_V(INFO, TAG, "PanId = %" PRId64 "\n", ctx->g_ZigBeeStatus.panId);
2283 OIC_LOG_V(INFO, TAG, "ExtPanId = %" PRId64 "\n", ctx->g_ZigBeeStatus.extPanId);
2284 ret = TW_RESULT_NEW_LOCAL_PAN_ESTABLISHED;
2287 OIC_LOG_V(INFO, TAG, "Leave TelJpanHandler() with ret=%d", ret);
2291 TWResultCode TelEndDeviceJoinHandler(int count, char* tokens[], TWContext* ctx)
2295 //Prompt: RFD:<IEEE Address>,<NodeID>
2296 //Prompt: FFD:<IEEE Address>,<NodeID>
2297 //Prompt: SED:<IEEE Address>,<NodeID>
2298 //Prompt: ZED:<IEEE Address>,<NodeID>
2300 OIC_LOG(INFO, TAG, "Enter TelEndDeviceJoinHandler()");
2301 TWResultCode ret = TW_RESULT_UNKNOWN;
2303 if(!tokens || count != RESPONSE_PARAMS_COUNT_DEVICE_JOINED)
2305 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2309 //TODO: Might need to add into the list if needed - log it for now.
2310 OIC_LOG_V(INFO, TAG, "Received RFD/FFD/SED/ZED - EUI:%s; NodeID:%s.\n",
2311 tokens[TOKEN_PJOIN_RESPONSE_IEEE_ADDRESS],
2312 tokens[TOKEN_PJOIN_RESPONSE_NODEID]);
2314 if (ctx->g_EndDeviceNodeIdChangedCallback != NULL)
2316 ctx->g_EndDeviceNodeIdChangedCallback(tokens[TOKEN_PJOIN_RESPONSE_IEEE_ADDRESS],
2317 tokens[TOKEN_PJOIN_RESPONSE_NODEID],
2324 OIC_LOG_V(INFO, TAG, "Leave TelEndDeviceJoinHandler() with ret=%d", ret);
2328 TWResultCode TelMatchDescHandler(int count, char* tokens[], TWContext* ctx)
2330 //Prompt: MatchDesc:0B4A,00,01
2332 OIC_LOG(INFO, TAG, "Enter TelMatchDescHandler()");
2333 TWResultCode ret = TW_RESULT_ERROR;
2335 if(!tokens || count != RESPONSE_PARAMS_COUNT_MATCH_DESC)
2337 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2341 if (strcmp(tokens[TOKEN_MATCHDESC_STATUS_CODE], AT_STR_ERROR_OK) != 0)
2343 OIC_LOG(INFO, TAG, "MatchDesc prompt contained error status.");
2344 ret = TW_RESULT_ERROR;
2349 char remoteEUI[SIZE_EUI];
2350 ret = GetRemoteEUI(tokens[TOKEN_MATCHDESC_NODEID], remoteEUI, ctx);
2351 if (ret != TW_RESULT_OK)
2353 OIC_LOG(ERROR, TAG, "GetRemoteEUI()");
2358 //Step 1: Create TWDevice
2359 TWDevice* device = (TWDevice*)OICCalloc(1, sizeof(TWDevice));
2362 ret = TW_RESULT_ERROR_NO_MEMORY;
2367 device->endpointOfInterest = (TWEndpoint*)OICCalloc(1, sizeof(TWEndpoint));
2368 if (device->endpointOfInterest == NULL)
2371 ret = TW_RESULT_ERROR_NO_MEMORY;
2375 OICStrcpy(device->eui, SIZE_EUI, remoteEUI);
2376 OICStrcpy(device->nodeId, SIZE_NODEID, tokens[TOKEN_MATCHDESC_NODEID]);
2377 OICStrcpy(device->endpointOfInterest->endpointId,
2379 tokens[TOKEN_MATCHDESC_ENDPOINTID]);
2380 ctx->g_WIPDevice = device;
2382 //Step 2: Add to list
2383 if (ctx->g_FoundMatchedDeviceList == NULL)
2385 //Create a list of promptCount entries
2386 ctx->g_FoundMatchedDeviceList =
2387 (TWDeviceList*)OICMalloc(sizeof(TWDeviceList));
2388 if (ctx->g_FoundMatchedDeviceList == NULL)
2390 OICFree(device->endpointOfInterest);
2392 ret = TW_RESULT_ERROR_NO_MEMORY;
2396 ctx->g_FoundMatchedDeviceList->count = 1;
2397 ctx->g_FoundMatchedDeviceList->deviceList =
2398 (TWDevice*)OICMalloc(sizeof(TWDevice));
2399 if (ctx->g_FoundMatchedDeviceList->deviceList == NULL)
2401 OICFree(device->endpointOfInterest);
2403 ret = TW_RESULT_ERROR_NO_MEMORY;
2407 memcpy(ctx->g_FoundMatchedDeviceList->deviceList,
2417 int newSize = sizeof(TWDevice)*(ctx->g_FoundMatchedDeviceList->count + 1);
2419 (TWDevice*)realloc(ctx->g_FoundMatchedDeviceList->deviceList,
2423 OICFree(device->endpointOfInterest);
2425 ret =TW_RESULT_ERROR_NO_MEMORY;
2429 ctx->g_FoundMatchedDeviceList->deviceList = temp;
2431 //Add to the end of list
2432 int count = ctx->g_FoundMatchedDeviceList->count;
2433 memcpy(&(ctx->g_FoundMatchedDeviceList->deviceList[count]),
2437 //Increase the count
2438 ctx->g_FoundMatchedDeviceList->count++;
2449 OIC_LOG_V(INFO, TAG, "Leave TelMatchDescHandler() with ret=%d", ret);
2453 TWResultCode TelSimpleDescHandler(int count, char* tokens[], TWContext* ctx)
2455 //AT+SIMPLEDESC:3746,3746,01
2459 // SimpleDesc:3746,00 <<<<<<<---------------------
2463 // InCluster:0000,0001,0003,0402,0500,0020,0B05
2467 OIC_LOG(INFO, TAG, "Enter TelSimpleDescHandler().");
2468 TWResultCode ret = TW_RESULT_UNKNOWN;
2470 if(!tokens || count != RESPONSE_PARAMS_COUNT_SIMPLE_DESC)
2472 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2476 if (ctx->g_WIPDevice == NULL)
2478 OIC_LOG_V(ERROR, TAG,
2479 "Receive simple descriptor unexpectedly - %s",
2480 tokens[TOKEN_SIMPLEDESC_SIMPLEDESC_NODEID]);
2481 ret = TW_RESULT_ERROR;
2485 if (strcmp(tokens[TOKEN_SIMPLEDESC_SIMPLEDESC_STATUS_CODE], AT_STR_ERROR_OK) != 0)
2489 "SimpleDesc: prompt contained error status %s.",
2490 tokens[TOKEN_SIMPLEDESC_SIMPLEDESC_STATUS_CODE]);
2491 ret = TW_RESULT_ERROR;
2495 if (strcmp(tokens[TOKEN_SIMPLEDESC_SIMPLEDESC_NODEID],
2496 ctx->g_WIPDevice->nodeId) == 0)
2500 "Got simple descriptor for nodeid %s",
2501 tokens[TOKEN_SIMPLEDESC_SIMPLEDESC_NODEID]);
2508 "Finding simple descriptor for non existing nodeid %s.",
2509 tokens[TOKEN_SIMPLEDESC_SIMPLEDESC_NODEID]);
2510 ret = TW_RESULT_ERROR;
2515 OIC_LOG_V(INFO, TAG, "Leave TelSimpleDescHandler() with ret=%d", ret);
2519 TWResultCode TelSimpleDescInClusterHandler(int count, char* tokens[], TWContext* ctx)
2521 //AT+SIMPLEDESC:3746,3746,01
2525 // SimpleDesc:3746,00
2529 // InCluster:0000,0001,0003,0402,0500,0020,0B05 <<<<<<<<--------------
2533 OIC_LOG(INFO, TAG, "Enter TelSimpleDescInClusterHandler()");
2534 TWResultCode ret = TW_RESULT_ERROR;
2536 if (!tokens || count < RESPONSE_PARAMS_COUNT_SIMPLE_DESC_IN_CLUSTER_MIN )
2538 OIC_LOG(ERROR, TAG, "Invalid Params");
2539 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2543 if (ctx->g_WIPDevice == NULL)
2545 OIC_LOG_V(ERROR, TAG,
2546 "Receive simple descriptor unexpectedly - %s",
2547 tokens[TOKEN_SIMPLEDESC_INCLUSTER_STRING]);
2548 ret = TW_RESULT_ERROR;
2552 if (ctx->g_WIPDevice->endpointOfInterest->clusterList != NULL)
2554 OIC_LOG(ERROR, TAG, "Expected an empty cluster list.");
2555 ret = TW_RESULT_ERROR;
2559 //Add found clusters for the node.
2560 ctx->g_WIPDevice->endpointOfInterest->clusterList =
2561 (TWClusterList*)OICMalloc(sizeof(TWClusterList));
2562 if (ctx->g_WIPDevice->endpointOfInterest->clusterList == NULL)
2564 OIC_LOG(ERROR, TAG, "No Memory - clusterList");
2565 ret = TW_RESULT_ERROR_NO_MEMORY;
2569 ctx->g_WIPDevice->endpointOfInterest->clusterList->clusterIds =
2570 (TWClusterId*)OICMalloc(sizeof(TWClusterId) * count);
2571 if (ctx->g_WIPDevice->endpointOfInterest->clusterList->clusterIds == NULL)
2573 OICFree(ctx->g_WIPDevice->endpointOfInterest->clusterList);
2574 OIC_LOG(ERROR, TAG, "No Memory - clusterIds");
2575 ret = TW_RESULT_ERROR_NO_MEMORY;
2580 for (; i < count; i++)
2582 OICStrcpy(ctx->g_WIPDevice->endpointOfInterest->clusterList->clusterIds[i].clusterId,
2586 OIC_LOG_V(INFO, TAG, "ClusterIds[%d]=%s",
2588 ctx->g_WIPDevice->endpointOfInterest->clusterList->clusterIds[i].clusterId);
2590 ctx->g_WIPDevice->endpointOfInterest->clusterList->count = count;
2591 ret = TW_RESULT_HAS_CLUSTERS;
2594 OIC_LOG_V(INFO, TAG, "Leave TelSimpleDescInClusterHandler() with ret=%d", ret);
2598 TWResultCode TelWriteAttrHandler(int count, char* tokens[], TWContext* ctx)
2600 //AT+WRITEATR:3A3D,01,0,0003,0000,21,00
2602 // WRITEATTR:3A3D,01,0003,,00
2604 //AT+WRITEATR:B826,01,0,0500,0010,F0,000D6F0000D59E92
2606 // WRITEATTR:B826,01,0500,0010,70
2608 OIC_LOG(INFO, TAG, "Enter TelWriteAttrHandler()");
2611 TWResultCode ret = TW_RESULT_ERROR;
2614 (count < RESPONSE_PARAMS_COUNT_WRITE_ATTR_4) ||
2615 (count > RESPONSE_PARAMS_COUNT_WRITE_ATTR_5))
2617 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2621 if (count == RESPONSE_PARAMS_COUNT_WRITE_ATTR_4)
2623 if (strcmp(tokens[TOKEN_WRITEATTR_STATUS_CODE], AT_STR_ERROR_OK) == 0)
2627 else if (strcmp(tokens[TOKEN_WRITEATTR_STATUS_CODE], AT_STR_ERROR_INVALID_OP) == 0)
2629 ret = TW_RESULT_ERROR_INVALID_OP;
2632 else if (count == RESPONSE_PARAMS_COUNT_WRITE_ATTR_5)
2634 if (strcmp(tokens[TOKEN_WRITEATTR_STATUS_CODE_ALTERNATIVE], AT_STR_ERROR_OK) == 0)
2638 else if (strcmp(tokens[TOKEN_WRITEATTR_STATUS_CODE_ALTERNATIVE],
2639 AT_STR_ERROR_INVALID_OP) == 0)
2641 ret = TW_RESULT_ERROR_INVALID_OP;
2646 OIC_LOG_V(INFO, TAG, "Leave TelWriteAttrHandler() with ret=%d", ret);
2650 TWResultCode TelReadAttrHandlerTemperature(int count, char* tokens[], TWContext* ctx)
2652 //AT+READATR:F2D7,01,0,0402,0002
2654 // TEMPERATURE:F2D7,01,0002,00,1770
2656 //AT+READATR:F2D7,01,0,0402,0002
2660 OIC_LOG(INFO, TAG, "Enter TelReadAttrHandlerTemperature().");
2661 TWResultCode ret = TW_RESULT_UNKNOWN;
2663 if(!tokens || count != RESPONSE_PARAMS_COUNT_TEMPERATURE)
2665 OIC_LOG(ERROR, TAG, "Invalid Params");
2666 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2670 if (strcmp(tokens[TOKEN_TEMPERATURE_STATUS_CODE], AT_STR_ERROR_OK) != 0)
2672 OIC_LOG(ERROR, TAG, "TEMPERATURE prompt contained error status.");
2673 ret = TW_RESULT_ERROR;
2677 // AttrInfo is 16-bit value representing (100 * Degrees Celsius)
2678 // so 0x812 = 20.66 C = 69.188 F
2679 if (ctx->g_ZigBeeStatus.remoteAttributeValueRead != NULL)
2681 OICFree(ctx->g_ZigBeeStatus.remoteAttributeValueRead);
2682 ctx->g_ZigBeeStatus.remoteAttributeValueRead = NULL;
2684 OIC_LOG_V(INFO, TAG, "Read Attribute Value: %s", tokens[TOKEN_TEMPERATURE_VALUE]);
2685 ctx->g_ZigBeeStatus.remoteAttributeValueRead =
2686 (char*)OICMalloc(sizeof(char) * strlen(tokens[TOKEN_TEMPERATURE_VALUE]));
2687 if (ctx->g_ZigBeeStatus.remoteAttributeValueRead == NULL)
2689 OIC_LOG_V(ERROR, TAG, "No Memory");
2690 ret = TW_RESULT_ERROR_NO_MEMORY;
2694 strcpy(ctx->g_ZigBeeStatus.remoteAttributeValueRead,
2695 tokens[TOKEN_TEMPERATURE_VALUE]);
2696 ctx->g_ZigBeeStatus.remoteAtrributeValueReadLength =
2697 strlen(tokens[TOKEN_TEMPERATURE_VALUE]);
2698 ret = TW_RESULT_REMOTE_ATTR_HAS_VALUE;
2702 OIC_LOG_V(INFO, TAG, "Leave TelReadAttrHandlerTemperature() with ret=%d", ret);
2706 TWResultCode TelReadAttrHandler(int count, char* tokens[], TWContext* ctx)
2708 //AT+READATR:F2D7,01,0,0402,0002
2710 // RESPATTR:<NodeID>,<EP>,<ClusterID>,<AttrID>,<Status>,<AttrInfo>
2712 //AT+READATR:F2D7,01,0,0402,0002
2716 OIC_LOG(INFO, TAG, "Enter TelReadAttrHandler()");
2717 TWResultCode ret = TW_RESULT_UNKNOWN;
2719 if(!tokens || count != RESPONSE_PARAMS_COUNT_RESPATTR)
2721 OIC_LOG(ERROR, TAG, "Invalid Params");
2722 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2726 if (strcmp(tokens[TOKEN_RESPATTR_STATUS_CODE], AT_STR_ERROR_OK) != 0)
2728 OIC_LOG(INFO, TAG, "READATTR prompt contained error status.");
2729 ret = TW_RESULT_ERROR;
2733 if (ctx->g_ZigBeeStatus.remoteAttributeValueRead != NULL)
2735 OICFree(ctx->g_ZigBeeStatus.remoteAttributeValueRead);
2737 OIC_LOG_V(INFO, TAG, "Read Attribute Value: %s.", tokens[TOKEN_RESPATTR_ATTRIBUTE_VALUE]);
2738 ctx->g_ZigBeeStatus.remoteAttributeValueRead =
2739 (char*)OICMalloc(sizeof(char) * strlen(tokens[TOKEN_RESPATTR_ATTRIBUTE_VALUE]));
2740 if (ctx->g_ZigBeeStatus.remoteAttributeValueRead != NULL)
2742 strcpy(ctx->g_ZigBeeStatus.remoteAttributeValueRead,
2743 tokens[TOKEN_RESPATTR_ATTRIBUTE_VALUE]);
2744 ctx->g_ZigBeeStatus.remoteAtrributeValueReadLength =
2745 strlen(tokens[TOKEN_RESPATTR_ATTRIBUTE_VALUE]);
2746 ret = TW_RESULT_REMOTE_ATTR_HAS_VALUE;
2750 OIC_LOG(ERROR, TAG, "No Memory");
2751 ret = TW_RESULT_ERROR_NO_MEMORY;
2755 OIC_LOG(INFO, TAG, "Leave TelReadAttrHandler()");
2759 TWResultCode TelZCLDefaultResponseHandler(int count, char* tokens[], TWContext* ctx)
2761 //AT+RONOFF:<Address>,<EP>,<SendMode>[,<ON/OFF>]
2762 // DFTREP:<NodeID>,<EP>,<ClusterID>,<CMD>,<Status>
2764 //AT+DRLOCK:<Address>,<EP>,<SendMode>,<Lock/Unlock>
2765 // DFTREP:<NodeID>,<EP>,<ClusterID>,<CMD>,<Status>
2767 //AT+LCMVTOLEV:<Address>,<EP>,<SendMode>,<ON/OFF>,<LevelValue>,<TransTime>
2768 // DFTREP:<NodeID>,<EP>,<ClusterID>,<CMD>,<Status>
2770 OIC_LOG(INFO, TAG, "Enter TelZCLDefaultResponseHandler()");
2772 TWResultCode ret = TW_RESULT_UNKNOWN;
2774 if(!tokens || count != RESPONSE_PARAMS_COUNT_DFTREP)
2776 OIC_LOG(ERROR, TAG, "Invalid Params");
2777 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2781 OIC_LOG_V(INFO, TAG,
2782 "DFTREP prompt succeed for NodeId:%s, EP:%s, ClusterId:%s, CMD:%s.\n",
2783 tokens[TOKEN_DFTREP_NODEID],
2784 tokens[TOKEN_DFTREP_ENDPOINTID],
2785 tokens[TOKEN_DFTREP_CLUSTERID],
2786 tokens[TOKEN_DFTREP_COMMANDID]);
2788 if (strcmp(tokens[TOKEN_DFTREP_STATUS_CODE], AT_STR_ERROR_OK) != 0)
2790 ret = TW_RESULT_ERROR;
2798 OIC_LOG(INFO, TAG, "Leave TelZCLDefaultResponseHandler()");
2802 TWResultCode TelSwitchDoorLockStateHandler(int count, char* tokens[], TWContext* ctx)
2804 //AT+DRLOCK:<Address>,<EP>,<SendMode>,<Lock/Unlock>
2805 // DRLOCRSP:<nodeID>,<ep>,<status>
2807 // DRUNLOCKRSP:<nodeID>,<ep>,<status>
2809 OIC_LOG(INFO, TAG, "Enter TelSwitchDoorLockStateHandler()");
2811 TWResultCode ret = TW_RESULT_UNKNOWN;
2813 if(!tokens || count != RESPONSE_PARAMS_COUNT_DRLOCKUNLOCKRSP)
2815 OIC_LOG(ERROR, TAG, "Invalid Params");
2816 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2820 if (strcmp(tokens[TOKEN_DRLOCKRSP_STATUS_CODE], AT_STR_ERROR_OK) != 0)
2824 "DRLOCRSP/DRUNLOCKRSP prompt contained error status %s.",
2825 tokens[TOKEN_DRLOCKRSP_STATUS_CODE]);
2826 ret = TW_RESULT_ERROR;
2830 OIC_LOG_V(INFO, TAG, "DRLOCRSP/DRUNLOCKRSP prompt succeed for nodeId:%s, ep:%s.",
2831 tokens[TOKEN_DRLOCKRSP_NODEID],
2832 tokens[TOKEN_DRLOCKRSP_ENDPOINTID]);
2837 OIC_LOG_V(INFO, TAG, "Leave TelSwitchDoorLockStateHandler() with ret=%d", ret);
2841 TWResultCode TelZoneEnrollRequestHandler(int count, char* tokens[], TWContext* ctx)
2843 //ZENROLLREQ:<NodeID>,<EndPoint>,<ZoneType>,<ManufactureCode>
2845 OIC_LOG(INFO, TAG, "Enter TelZoneEnrollRequestHandler()");
2847 TWResultCode ret = TW_RESULT_UNKNOWN;
2849 if(!tokens || count != RESPONSE_PARAMS_COUNT_ZENROLLREQ)
2851 OIC_LOG(ERROR, TAG, "Invalid Params");
2852 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2856 OIC_LOG(INFO, TAG, "Received zone request from:");
2857 OIC_LOG_V(INFO, TAG, "Node:%s", tokens[TOKEN_ZENROLLREQ_NODEID]);
2858 OIC_LOG_V(INFO, TAG, "EP:%s", tokens[TOKEN_ZENROLLREQ_ENDPOINTID]);
2859 OIC_LOG_V(INFO, TAG, "ZoneType:%s", tokens[TOKEN_ZENROLLREQ_ZONETYPE]);
2860 OIC_LOG_V(INFO, TAG, "ManufactureCode:%s", tokens[TOKEN_ZENROLLREQ_MANUFACTURE_CODE]);
2864 OIC_LOG_V(INFO, TAG, "Leave TelZoneEnrollRequestHandler() with ret=%d", ret);
2868 TWResultCode TelEnrolledHandler(int count, char* tokens[], TWContext* ctx)
2870 //ENROLLED:<ZID>,<ZoneType>,<EUI>
2872 OIC_LOG(INFO, TAG, "Enter TelEnrolledHandler()");
2873 TWResultCode ret = TW_RESULT_OK;
2875 if(!tokens || count != RESPONSE_PARAMS_COUNT_ENROLLED)
2877 OIC_LOG(ERROR, TAG, "Invalid Params");
2878 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2882 OIC_LOG(INFO, TAG, "Received zone enrollment for:");
2883 OIC_LOG_V(INFO, TAG, "ZID:%s", tokens[TOKEN_ENROLLED_ZONEID]);
2884 OIC_LOG_V(INFO, TAG, "ZoneType:%s", tokens[TOKEN_ENROLLED_ZONETYPE]);
2885 OIC_LOG_V(INFO, TAG, "EUI:%s", tokens[TOKEN_ENROLLED_EUI]);
2887 TWEnrollee enrollee;
2888 OICStrcpy(enrollee.zoneId, SIZE_ZONEID, tokens[TOKEN_ENROLLED_ZONEID]);
2889 OICStrcpy(enrollee.zoneType, SIZE_ZONETYPE, tokens[TOKEN_ENROLLED_ZONETYPE]);
2890 OICStrcpy(enrollee.eui, SIZE_EUI, tokens[TOKEN_ENROLLED_EUI]);
2892 if (ctx->g_EnrollmentSucceedCallback != NULL)
2894 OIC_LOG_V(INFO, TAG, "Enrolled - Invoke callback");
2895 ctx->g_EnrollmentSucceedCallback(&enrollee, ctx->g_plugin);
2900 OIC_LOG_V(INFO, TAG, "Leave TelEnrolledHandler() with ret=%d", ret);
2904 TWResultCode TelZoneStatusHandler(int count, char* tokens[], TWContext* ctx)
2906 //ZONESTATUS:<NodeID>,<EP>,<ZoneStatus>,<ExtendStatus>[,<ZoneID>,<Delay>]
2907 //ZONESTATUS:5FBA,01,0021,00,01,00AF
2909 OIC_LOG(INFO, TAG, "Enter TelZoneStatusHandler()");
2910 TWResultCode ret = TW_RESULT_UNKNOWN;
2912 ((count != RESPONSE_PARAMS_COUNT_ZONESTATUS_4) &&
2913 (count != RESPONSE_PARAMS_COUNT_ZONESTATUS_6)))
2915 OIC_LOG(ERROR, TAG, "Invalid Params");
2916 ret = TW_RESULT_ERROR_INVALID_PARAMS;
2921 OICStrcpy(update.nodeId, SIZE_NODEID, tokens[TOKEN_ZONESTATUS_NODEID]);
2922 OICStrcpy(update.endpoint, SIZE_NODEID, tokens[TOKEN_ZONESTATUS_ENDPOINTID]);
2923 OICStrcpy(update.status, SIZE_NODEID, tokens[TOKEN_ZONESTATUS_ZONESTATUS]);
2924 OICStrcpy(update.extendedStatus, SIZE_NODEID, tokens[TOKEN_ZONESTATUS_ZONESTATUS_EXTENDED]);
2926 if (count == RESPONSE_PARAMS_COUNT_ZONESTATUS_6)
2928 OICStrcpy(update.zoneId, SIZE_NODEID, tokens[TOKEN_ZONESTATUS_ZONEID]);
2929 OICStrcpy(update.delay, SIZE_NODEID, tokens[TOKEN_ZONESTATUS_DELAY]);
2932 if (ctx->g_DeviceStatusUpdateCallback != NULL)
2934 OIC_LOG(INFO, TAG, "device status update - invoke callback");
2935 ctx->g_DeviceStatusUpdateCallback(&update, ctx->g_plugin);
2936 OIC_LOG(INFO, TAG, "device status update - callback done");
2941 OIC_LOG_V(INFO, TAG, "Leave TelZoneStatusHandler() with ret=%d", ret);
2945 //-----------------------------------------------------------------------------
2946 // Internal functions - Helpers
2947 //-----------------------------------------------------------------------------
2951 * Tokenize 'input' parameter by 'delimiters' into 'output' array.
2954 int Tokenize(const char *input, const char* delimiters, char* output[])
2956 OIC_LOG_V(INFO, TAG, "Enter Tokenize() - %s", input);
2960 OIC_LOG(INFO, TAG, "Invalid parameter.");
2964 int length = strlen(input);
2965 char * str = (char *) OICCalloc(1, length + 1);
2966 OICStrcpy(str, length+1, input);
2968 char* savePtr = NULL;
2969 char* p = strtok_r(str, delimiters, &savePtr);
2971 while (p && index <= ARRAY_LENGTH)
2973 int size = strlen(p) + 1; //for null char
2974 output[index] = (char*)OICCalloc(size, sizeof(char));
2975 OICStrcpy(output[index], size, p);
2976 OIC_LOG_V(INFO, TAG, "Token[%d]=%s", index, output[index]);
2977 p = strtok_r (NULL, delimiters, &savePtr);
2982 OIC_LOG(INFO, TAG, "Leave Tokenize()");
2986 int AsciiToHex(char c)
2989 if(c >= '0' && c <= '9')
2994 if(num >= 'A' && num <= 'F')
2996 return num - 'A' + 10;
3001 TWResultCode AsciiHexToValue(char* hexString, int length, uint64_t* value)
3003 if(!hexString || !value || length < 0)
3005 return TW_RESULT_ERROR_INVALID_PARAMS;
3007 int retVal = AsciiToHex(hexString[0]);
3010 OIC_LOG(ERROR, TAG, "Bad conversion from ASCII To Hex.");
3011 return TW_RESULT_ERROR;
3013 *value = (uint64_t)retVal;
3014 for (int i = 1; i < length; ++i)
3016 if (sizeof(hexString) > (uint32_t)i)
3019 retVal = AsciiToHex(hexString[i]);
3022 OIC_LOG(ERROR, TAG, "Bad conversion from ASCII To Hex.");
3023 return TW_RESULT_ERROR;
3025 *value |= (uint64_t)retVal;
3028 return TW_RESULT_OK;
3033 * Deallocate device list.
3036 void DeallocateTWDeviceList(TWContext* ctx)
3038 if (ctx->g_FoundMatchedDeviceList == NULL)
3043 if (ctx->g_FoundMatchedDeviceList->deviceList == NULL)
3045 OICFree(ctx->g_FoundMatchedDeviceList);
3046 ctx->g_FoundMatchedDeviceList = NULL;
3050 if (ctx->g_FoundMatchedDeviceList->deviceList->endpointOfInterest == NULL)
3052 OICFree(ctx->g_FoundMatchedDeviceList->deviceList);
3053 ctx->g_FoundMatchedDeviceList->deviceList = NULL;
3055 OICFree(ctx->g_FoundMatchedDeviceList);
3056 ctx->g_FoundMatchedDeviceList = NULL;
3060 if (ctx->g_FoundMatchedDeviceList->deviceList->endpointOfInterest->clusterList == NULL)
3062 OICFree(ctx->g_FoundMatchedDeviceList->deviceList->endpointOfInterest);
3063 ctx->g_FoundMatchedDeviceList->deviceList->endpointOfInterest = NULL;
3065 OICFree(ctx->g_FoundMatchedDeviceList->deviceList);
3066 ctx->g_FoundMatchedDeviceList->deviceList = NULL;
3068 OICFree(ctx->g_FoundMatchedDeviceList);
3069 ctx->g_FoundMatchedDeviceList = NULL;
3073 if (ctx->g_FoundMatchedDeviceList->deviceList->endpointOfInterest->clusterList->clusterIds
3076 OICFree(ctx->g_FoundMatchedDeviceList->deviceList->endpointOfInterest->clusterList);
3077 ctx->g_FoundMatchedDeviceList->deviceList->endpointOfInterest->clusterList = NULL;
3079 OICFree(ctx->g_FoundMatchedDeviceList->deviceList->endpointOfInterest);
3080 ctx->g_FoundMatchedDeviceList->deviceList->endpointOfInterest = NULL;
3082 OICFree(ctx->g_FoundMatchedDeviceList->deviceList);
3083 ctx->g_FoundMatchedDeviceList->deviceList = NULL;
3085 OICFree(ctx->g_FoundMatchedDeviceList);
3086 ctx->g_FoundMatchedDeviceList = NULL;
3090 OICFree(ctx->g_FoundMatchedDeviceList->deviceList->
3091 endpointOfInterest->clusterList->clusterIds);
3092 ctx->g_FoundMatchedDeviceList->deviceList->endpointOfInterest->clusterList->clusterIds = NULL;
3094 OICFree(ctx->g_FoundMatchedDeviceList->deviceList->endpointOfInterest->clusterList);
3095 ctx->g_FoundMatchedDeviceList->deviceList->endpointOfInterest->clusterList = NULL;
3097 OICFree(ctx->g_FoundMatchedDeviceList->deviceList->endpointOfInterest);
3098 ctx->g_FoundMatchedDeviceList->deviceList->endpointOfInterest = NULL;
3100 OICFree(ctx->g_FoundMatchedDeviceList->deviceList);
3101 ctx->g_FoundMatchedDeviceList->deviceList = NULL;
3103 OICFree(ctx->g_FoundMatchedDeviceList);
3104 ctx->g_FoundMatchedDeviceList = NULL;