From b220dde4db08d13fa6ac2fa2f3cf5d0a73bf0ff5 Mon Sep 17 00:00:00 2001 From: Joseph Morrow Date: Wed, 30 Sep 2015 12:54:44 -0700 Subject: [PATCH] Add event feature. Change-Id: Iafae4e422c43bc37e4304f0a00d980b38a13aa99 Signed-off-by: Thuyen Tran Signed-off-by: Joseph Morrow Reviewed-on: https://gerrit.iotivity.org/gerrit/2953 Tested-by: jenkins-iotivity Reviewed-by: Jon A. Cruz --- plugins/zigbee_wrapper/src/zigbee_wrapper.c | 3 +- .../telegesis_wrapper/include/telegesis_socket.h | 2 + .../telegesis_wrapper/include/telegesis_wrapper.h | 24 +- .../telegesis_wrapper/include/twtypes.h | 41 +- .../telegesis_wrapper/src/telegesis_socket.c | 2 + .../telegesis_wrapper/src/telegesis_wrapper.c | 3764 ++++++++++---------- 6 files changed, 1951 insertions(+), 1885 deletions(-) diff --git a/plugins/zigbee_wrapper/src/zigbee_wrapper.c b/plugins/zigbee_wrapper/src/zigbee_wrapper.c index 7af6390..0b242d1 100644 --- a/plugins/zigbee_wrapper/src/zigbee_wrapper.c +++ b/plugins/zigbee_wrapper/src/zigbee_wrapper.c @@ -292,8 +292,7 @@ OCStackResult ZigbeeStop(PIPlugin_Zigbee * plugin) OCStackResult ZigbeeProcess(PIPlugin_Zigbee * plugin) { (void)plugin; - // Invoke TelegesisProcess() at some point. - return OC_STACK_OK; + return TWProcess(); } // Function returns an OIC Smart Home resource Type diff --git a/plugins/zigbee_wrapper/telegesis_wrapper/include/telegesis_socket.h b/plugins/zigbee_wrapper/telegesis_wrapper/include/telegesis_socket.h index 23cde1d..4ef6489 100644 --- a/plugins/zigbee_wrapper/telegesis_wrapper/include/telegesis_socket.h +++ b/plugins/zigbee_wrapper/telegesis_wrapper/include/telegesis_socket.h @@ -59,6 +59,8 @@ typedef enum TW_SEQ, TW_ZENROLLREQ, TW_ENROLLED, + TW_ZONESTATUS, + TW_ADDRESS_RESPONSE, TW_NONE, TW_MAX_ENTRY } TWEntryType; diff --git a/plugins/zigbee_wrapper/telegesis_wrapper/include/telegesis_wrapper.h b/plugins/zigbee_wrapper/telegesis_wrapper/include/telegesis_wrapper.h index 28d6825..eea7128 100644 --- a/plugins/zigbee_wrapper/telegesis_wrapper/include/telegesis_wrapper.h +++ b/plugins/zigbee_wrapper/telegesis_wrapper/include/telegesis_wrapper.h @@ -132,6 +132,7 @@ typedef struct typedef void (*TWDeviceFoundCallback)(TWDevice* device); typedef void (*TWEnrollmentSucceedCallback)(TWEnrollee* enrollee); typedef void (*TWDeviceStatusUpdateCallback)(TWUpdate* update); +typedef void (*TWInitCompleteCallback)(bool status); /** * @@ -208,7 +209,7 @@ OCStackResult TWSwitchOnOff(char* nodeId, char* endpointId, char* newState); * * @param[in] level The The meaning of ‘level’ is device dependent * e.g. for a light it may mean brightness level. - + * * @param[in] transTime The time taken to move to the new level * */ @@ -228,12 +229,24 @@ OCStackResult TWSwitchDoorLockState(char* nodeId, char* endpointId, char* newSta /** * + * Move Color Temperature + * + * @param[in] nodeId The node id of the device. + * @param[in] endpointId The endpoint id from which the attribute belongs. + * @param[in] colorTemperature 16 bit hexadecimal number. + * @param[in] transTime The time taken to move to the new level. + * + */ +OCStackResult TWColorMoveToColorTemperature(char* nodeId, char* endpointId, + char* colorTemperature, char* transTime); + +/** + * * Sets discovery callback. * This callback will be called when TWDiscover() discovers ZigBee device(s). * */ OCStackResult TWSetDiscoveryCallback(const TWDeviceFoundCallback callback); - /** * * Sets status update callback. @@ -255,6 +268,13 @@ OCStackResult TWListenForStatusUpdates(char* nodeId, char* endpointId); /** * + * Process TWEntry. + * + */ +OCStackResult TWProcess(); + +/** + * * Uninitializes the Telegesis module. * */ diff --git a/plugins/zigbee_wrapper/telegesis_wrapper/include/twtypes.h b/plugins/zigbee_wrapper/telegesis_wrapper/include/twtypes.h index 6b98a64..373bed7 100644 --- a/plugins/zigbee_wrapper/telegesis_wrapper/include/twtypes.h +++ b/plugins/zigbee_wrapper/telegesis_wrapper/include/twtypes.h @@ -50,27 +50,35 @@ extern "C" { #define SIMPLEDESC_RESPONSE_EXPECTED_LINES (6) -#define AT_STR_ERROR_OK "00" +#define AT_STR_ERROR_OK "00" +#define AT_STR_ERROR_INVALID_OP "70" + +#define AT_STR_ERROR_EVERYTHING_OK "00" +#define AT_STR_ERROR_NODE_IS_PART_OF_PAN "28" +#define AT_STR_ERROR_MESSAGE_NOT_SENT_TO_TARGET_SUCCESSFULLY "66" +#define AT_STR_ERROR_INVALID_OPERATION "70" + #define SENDMODE "0" #define SEPARATOR "," #define SEPARATOR_LENGTH strlen(SEPARATOR) -#define AT_CMD_RESET "AT&F" -#define AT_CMD_GET_NETWORK_INFO "AT+N" -#define AT_CMD_ESTABLISH_NETWORK "AT+EN" -#define AT_CMD_PERMIT_JOIN "AT+PJOIN:" -#define AT_CMD_MATCH_REQUEST "AT+MATCHREQ:" -#define AT_CMD_SIMPLE_DESC "AT+SIMPLEDESC:" -#define AT_CMD_WRITE_ATR "AT+WRITEATR:" -#define AT_CMD_READ_ATR "AT+READATR:" -#define AT_CMD_RUN_ON_OFF "AT+RONOFF:" -#define AT_CMD_MOVE_TO_LEVEL "AT+LCMVTOLEV:" -#define AT_CMD_DOOR_LOCK "AT+DRLOCK:" -#define AT_CMD_GET_LOCAL_EUI "ATS04?" -#define AT_CMD_REMOTE_EUI_REQUEST "AT+EUIREQ:" - -#define TW_ENDCONTROL_ERROR_STRING "ERROR:" +#define AT_CMD_RESET "AT&F" +#define AT_CMD_GET_NETWORK_INFO "AT+N" +#define AT_CMD_ESTABLISH_NETWORK "AT+EN" +#define AT_CMD_PERMIT_JOIN "AT+PJOIN:" +#define AT_CMD_MATCH_REQUEST "AT+MATCHREQ:" +#define AT_CMD_SIMPLE_DESC "AT+SIMPLEDESC:" +#define AT_CMD_WRITE_ATR "AT+WRITEATR:" +#define AT_CMD_READ_ATR "AT+READATR:" +#define AT_CMD_RUN_ON_OFF "AT+RONOFF:" +#define AT_CMD_MOVE_TO_LEVEL "AT+LCMVTOLEV:" +#define AT_CMD_DOOR_LOCK "AT+DRLOCK:" +#define AT_CMD_COLOR_CTRL_MOVE_TO_COLOR_TEMPERATURE "AT+CCMVTOCT:" +#define AT_CMD_GET_LOCAL_EUI "ATS04?" +#define AT_CMD_REMOTE_EUI_REQUEST "AT+EUIREQ:" + +#define TW_ENDCONTROL_ERROR_STRING "ERROR:" #define SIZE_EUI (17) #define SIZE_NODEID (5) @@ -122,6 +130,7 @@ typedef enum TW_RESULT_ERROR_INVALID_PARAMS, TW_RESULT_ERROR_INVALID_PORT, TW_RESULT_ERROR_NO_MEMORY, + TW_RESULT_ERROR_INVALID_OP, TW_RESULT_ERROR_NOTIMPL, TW_RESULT_ERROR = 255 diff --git a/plugins/zigbee_wrapper/telegesis_wrapper/src/telegesis_socket.c b/plugins/zigbee_wrapper/telegesis_wrapper/src/telegesis_socket.c index e7cc356..d4c592d 100644 --- a/plugins/zigbee_wrapper/telegesis_wrapper/src/telegesis_socket.c +++ b/plugins/zigbee_wrapper/telegesis_wrapper/src/telegesis_socket.c @@ -88,6 +88,8 @@ static TWEntryTypePair TWEntryTypePairArray[] = {"SEQ:", 1, TW_SEQ}, {"ZENROLLREQ:", 1, TW_ZENROLLREQ}, {"ENROLLED:", 1, TW_ENROLLED}, + {"ZONESTATUS:", 1, TW_ZONESTATUS}, + {"AddrResp:", 1, TW_ADDRESS_RESPONSE}, {"Unknown:", 0, TW_NONE}, {"Unknown:", 1, TW_MAX_ENTRY} }; diff --git a/plugins/zigbee_wrapper/telegesis_wrapper/src/telegesis_wrapper.c b/plugins/zigbee_wrapper/telegesis_wrapper/src/telegesis_wrapper.c index 2a45992..6a55aeb 100644 --- a/plugins/zigbee_wrapper/telegesis_wrapper/src/telegesis_wrapper.c +++ b/plugins/zigbee_wrapper/telegesis_wrapper/src/telegesis_wrapper.c @@ -34,29 +34,63 @@ #include "oic_malloc.h" #include "logger.h" -#include "telegesis_wrapper.h" #include "twtypes.h" +#include "telegesis_socket.h" +#include "telegesis_wrapper.h" + #define TAG PCF("telegesiswrapper") // Module Name -#define ARRAY_LENGTH (100) + +#define ARRAY_LENGTH 100 + +#define RESPONSE_PARAMS_COUNT_NETWORK_INFO_1 (1) +#define RESPONSE_PARAMS_COUNT_NETWORK_INFO_5 (5) +#define RESPONSE_PARAMS_COUNT_JPAN (3) +#define RESPONSE_PARAMS_COUNT_DEVICE_JOINED (2) +#define RESPONSE_PARAMS_COUNT_MATCH_DESC (3) +#define RESPONSE_PARAMS_COUNT_SIMPLE_DESC (2) +#define RESPONSE_PARAMS_COUNT_SIMPLE_DESC_IN_CLUSTER_MIN (1) +#define RESPONSE_PARAMS_COUNT_WRITE_ATTR_4 (4) +#define RESPONSE_PARAMS_COUNT_WRITE_ATTR_5 (5) +#define RESPONSE_PARAMS_COUNT_TEMPERATURE (5) +#define RESPONSE_PARAMS_COUNT_RESPATTR (6) +#define RESPONSE_PARAMS_COUNT_ADDRESS_RESPONSE (3) +#define RESPONSE_PARAMS_COUNT_DFTREP (5) +#define RESPONSE_PARAMS_COUNT_DRLOCKUNLOCKRSP (3) +#define RESPONSE_PARAMS_COUNT_ZENROLLREQ (4) +#define RESPONSE_PARAMS_COUNT_ENROLLED (3) +#define RESPONSE_PARAMS_COUNT_ZONESTATUS_4 (4) +#define RESPONSE_PARAMS_COUNT_ZONESTATUS_6 (6) //----------------------------------------------------------------------------- // Private internal function prototypes //----------------------------------------------------------------------------- -static TWResultCode IssueATCommand(const char* command, uint8_t timeout, - uint64_t* atErrorCode, - char* responseArray[], char* promptArray[], - uint8_t* responseCount, uint8_t* promptCount); - -static TWResultCode HandleATResponse(char* responseArray[], int count); +static TWResultCode HandleATResponse(TWEntry* entry); + +static TWResultCode processEntry(TWEntry* entry); +static TWResultCode processEntryNETWORK_INFO(TWEntry* entry); +static TWResultCode processEntryJPAN(TWEntry* entry); +static TWResultCode processEntryEndDevice(TWEntry* entry); +static TWResultCode processEntryMatchDesc(TWEntry* entry); +static TWResultCode processEntrySimpleDesc(TWEntry* entry); +static TWResultCode processEntryWriteAttr(TWEntry* entry); +static TWResultCode processEntryReadAttr(TWEntry* entry); +static TWResultCode processEntryTemperature(TWEntry* entry); +static TWResultCode processEntrySwitchDoorLockState(TWEntry* entry); +static TWResultCode processEntryZCLDefaultResponse(TWEntry* entry); +static TWResultCode processEntryZoneEnrollRequest(TWEntry* entry); +static TWResultCode processEntryEnrolled(TWEntry* entry); +static TWResultCode processEntryZoneStatus(TWEntry* entry); +static TWResultCode processEntryAddressResponse(TWEntry* entry); static TWResultCode Reset(); -static TWResultCode GetLocalEUI(); +static TWResultCode GetRemoteEUI(); static TWResultCode CreatePAN(); -static TWResultCode EnableJoin(bool isKeyEncrypted, uint8_t* outDeviceJoinedCount); -static TWResultCode FindMatchNodes(uint8_t* outDeviceMatchedCount); +static TWResultCode EnableJoin(bool isKeyEncrypted); +static TWResultCode FindMatchNodes(); static TWResultCode FindClusters(char nodeId[], char endpoint[]); + static TWResultCode TelNetworkInfoHandler(int count, char* tokens[]); static TWResultCode TelJpanHandler(int count, char* tokens[]); static TWResultCode TelEndDeviceJoinHandler(int count, char* tokens[]); @@ -73,29 +107,10 @@ static TWResultCode TelZoneEnrollRequestHandler(int count, char* tokens[]); static TWResultCode TelEnrolledHandler(int count, char* tokens[]); static TWResultCode TelZoneStatusHandler(int count, char* tokens[]); -static TWResultCode OpenPort(int * fd); -static TWResultCode ClosePort(int fd); - -static TWResultCode WriteBuffer(const char * command); -static TWResultCode ReadBuffer(uint64_t * atErrorCode, - char * responseArray[], - uint8_t * count, - const char * command, - uint8_t timeout); - static TWResultCode AsciiHexToValue(char* hexString, int length, uint64_t* value); static int AsciiToHex(char c); static int Tokenize(const char *input, const char* delimiters, char* output[]); -static int SetTerminalInfo(int fd, int speed, int parity, int shouldBlock); - -static void CleanArray(char* responseArray[], char* promptArray[], - uint8_t responseCount, uint8_t promptCount); -static void PrintArray(char* responseArray[], char* promptArray[], - uint8_t responseCount, uint8_t promptCount); - -static void PrintTWDevice(TWDevice* device); -static void PrintTWDeviceList(TWDeviceList* list); static void DeallocateTWDeviceList(); //----------------------------------------------------------------------------- @@ -126,17 +141,9 @@ static TWATResultHandlerPair g_TWATResultHandlerPairArray[] = {"Unknown:", TelNetworkInfoHandler} }; -static TWEndControlMap g_TWEndMessageMap[] = -{ - {"OK", TW_ENDCONTROL_OK}, - {"ERROR:", TW_ENDCONTROL_ERROR}, - {"ACK:", TW_ENDCONTROL_ACK}, - {"SEQ:", TW_ENDCONTROL_SEQ} -}; - //TODO: Take care of all global variables +static PIPlugin* g_plugin = (PIPlugin*)1; static const char* g_port = NULL; -static int g_fd = 0; static char g_LocalEUI[SIZE_EUI] = ""; static char g_WIPRemoteEUI[SIZE_EUI] = ""; @@ -157,160 +164,92 @@ static TWDeviceStatusUpdateCallback g_DeviceStatusUpdateCallback = NULL; /*****************************************************************************/ OCStackResult TWInitialize(const char* deviceDevPath) { - OC_LOG_V(INFO, TAG, "Enter TWInitializeZigBee()."); + OC_LOG_V(INFO, TAG, "Enter TWInitialize()"); - OCStackResult ret = OC_STACK_ERROR; TWResultCode twCode = TW_RESULT_ERROR; g_port = deviceDevPath; - OC_LOG_V(INFO, TAG, "Attempt to open %s", deviceDevPath); - twCode = OpenPort(&g_fd); + + twCode = TWStartSock(g_plugin, deviceDevPath); //TODO: if (twCode != TW_RESULT_OK) { - OC_LOG_V(ERROR, TAG, "Failed to open %s because of error: %d", deviceDevPath, ret); - ret = OC_STACK_ERROR; + OC_LOG_V(ERROR, TAG, "Failed to open %s because of error: %d", deviceDevPath, twCode); + return OC_STACK_ERROR; } - else - { - twCode = TW_RESULT_ERROR; - - bool continueInit = true; - bool wantReset = false; - - if (wantReset) - { - twCode = Reset(); - if (twCode == TW_RESULT_OK) - { - OC_LOG_V(INFO, TAG, "ZigBee Initialization - Reset - OK."); - continueInit = true; - } - else - { - OC_LOG_V(INFO, TAG, "ZigBee Initialization - Reset - FAILED."); - continueInit = false; - } - } - if (continueInit) - { - twCode = CreatePAN(); - if (twCode == TW_RESULT_OK) - { - OC_LOG_V(INFO, TAG, "CreatePan OK."); + char* eui = NULL; + twCode = TWGetEUI(g_plugin, &eui); + if (twCode != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "Failed to get EUI because of error: %d", twCode); + return OC_STACK_ERROR; + } + OICStrcpy(g_LocalEUI, SIZE_EUI, eui); + OC_LOG_V(INFO, TAG, "LocalEUI=%s", g_LocalEUI); + OICFree(eui); - twCode = GetLocalEUI(); - if (twCode == TW_RESULT_OK) - { - OC_LOG_V(INFO, TAG, "GetLocalEUI OK."); - OC_LOG_V(INFO, TAG, "ZigBee Initialization - DONE."); - g_ZigBeeStatus.state = ZB_STATE_INIT; - ret = OC_STACK_OK; - } - else - { - OC_LOG_V(ERROR, TAG, "GetLocalEUI FAILED."); - OC_LOG_V(ERROR, TAG, "ZigBee Initialization - FAILED - MUST STOP NOW."); - g_ZigBeeStatus.state = ZB_STATE_UNKNOWN; - ret = OC_STACK_ERROR; - } - } - else - { - OC_LOG_V(ERROR, TAG, "CreatePan FAILED. Result: %d", twCode); - OC_LOG_V(ERROR, TAG, "ZigBee Initialization - FAILED - MUST STOP NOW."); - g_ZigBeeStatus.state = ZB_STATE_UNKNOWN; - ret = OC_STACK_ERROR; - } - } - else + bool wantReset = false; //TODO: + if (wantReset) + { + twCode = Reset(); + if (twCode != TW_RESULT_OK) { - OC_LOG_V(ERROR, TAG, "ZigBee Initialization - FAILED - MUST STOP NOW."); - ret = OC_STACK_ERROR; + OC_LOG_V(ERROR, TAG, "ZigBee Initialization - Reset"); + return OC_STACK_ERROR; } } - OC_LOG_V(INFO, TAG, "Leave TWInitializeZigBee()."); - return ret; + twCode = CreatePAN(); + if (twCode != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "CreatePan Failed"); + OC_LOG_V(ERROR, TAG, "TWInitialize() - MUST STOP NOW"); + g_ZigBeeStatus.state = ZB_STATE_UNKNOWN; + return OC_STACK_ERROR; + } + else + { + OC_LOG_V(INFO, TAG, "CreatePan Succeed"); + OC_LOG_V(INFO, TAG, "TWInitialize() Succeed"); + return OC_STACK_OK; + } } OCStackResult TWDiscover() { - OC_LOG_V(INFO, TAG, "Enter TWDiscover()."); + OC_LOG_V(INFO, TAG, "Enter TWDiscover()"); OCStackResult ret = OC_STACK_ERROR; TWResultCode twRet = TW_RESULT_ERROR; - uint8_t deviceJoinedCount = 0; if (g_DeviceFoundCallback == NULL) { - OC_LOG_V(ERROR, TAG, "Required TWDeviceFoundCallback."); - ret = OC_STACK_ERROR; + OC_LOG_V(INFO, TAG, "Required TWDeviceFoundCallback."); + return OC_STACK_ERROR; } - else - { - twRet = EnableJoin(false, &deviceJoinedCount); - - if (twRet == TW_RESULT_OK) - { - OC_LOG_V(INFO, TAG, "Number of devices joined:%d.", deviceJoinedCount); - uint8_t nodeMatchedCount = 0; - twRet = FindMatchNodes(&nodeMatchedCount); - if (twRet == TW_RESULT_FOUND_NO_MATCHED_DEVICE) - { - ret = OC_STACK_OK; - } - else if (twRet == TW_RESULT_FOUND_MATCHED_DEVICES) - { - ret = OC_STACK_OK; - int i = 0; - for (; i < g_FoundMatchedDeviceList->count; i++) - { - g_WIPDevice = &g_FoundMatchedDeviceList->deviceList[i]; - twRet = FindClusters(g_WIPDevice->nodeId, - g_WIPDevice->endpointOfInterest->endpointId); - - if (twRet == TW_RESULT_HAS_CLUSTERS) - { - OC_LOG_V(INFO, TAG, "Attempt to invoke a callback."); - g_DeviceFoundCallback(g_WIPDevice); - } - else - { - OC_LOG_V(ERROR, TAG, - "ERROR finding cluster for NodeID=%s,EUI=%s,EP=%s.", - g_WIPDevice->nodeId, - g_WIPDevice->eui, - g_WIPDevice->endpointOfInterest->endpointId); - ret = OC_STACK_ERROR; - break; - } - g_WIPDevice = NULL; - } - } - else - { - OC_LOG_V(ERROR, TAG, "Find matched nodes."); - ret = OC_STACK_ERROR; - } - } - else - { - OC_LOG_V(ERROR, TAG, "Enable joining."); - ret = OC_STACK_ERROR; - } - //Done with wip device. - g_WIPDevice = NULL; + twRet = EnableJoin(false); + if (twRet != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "EnableJoin"); + return OC_STACK_ERROR; + } - //deallocate the list of found devices. - //so that it's cleaned for the next TWDiscover() call. - DeallocateTWDeviceList(); + twRet = FindMatchNodes(); + if (twRet == TW_RESULT_OK) + { + OC_LOG_V(INFO, TAG, "FindMatchNodes"); + ret = OC_STACK_OK; + } + else + { + OC_LOG_V(ERROR, TAG, "FindMatchNodes"); + ret = OC_STACK_ERROR; } - OC_LOG_V(INFO, TAG, "Leave TWDiscover()."); + OC_LOG_V(INFO, TAG, "Leave TWDiscover() with ret=%d", ret); return ret; } @@ -320,7 +259,7 @@ OCStackResult TWSetAttribute(char* extendedUniqueId, char* nodeId, char* endpoin { //Ask: AT+WRITEATR:5DA7,01,0,0003,0000,21,01 - OC_LOG_V(INFO, TAG, "Enter TWSetAttribute()."); + OC_LOG_V(INFO, TAG, "Enter TWSetAttribute()"); (void)extendedUniqueId; @@ -336,74 +275,54 @@ OCStackResult TWSetAttribute(char* extendedUniqueId, char* nodeId, char* endpoin SEPARATOR_LENGTH + strlen(newValue) + 1; char* cmdString = (char*)OICMalloc(size * sizeof(char)); - if (cmdString != NULL) + if (cmdString == NULL) { - snprintf(cmdString, size, "%s%s,%s,%s,%s,%s,%s,%s", - AT_CMD_WRITE_ATR, nodeId, endpointId, SENDMODE, - clusterId, attributeId, attributeType, newValue); - - char* responseArray[ARRAY_LENGTH] = {}; - uint8_t responseCount = 0; - - char* promptArray[ARRAY_LENGTH] = {}; - uint8_t promptCount = 0; + OC_LOG_V(ERROR, TAG, "No Memory"); + ret = OC_STACK_ERROR; + goto exit; + } + snprintf(cmdString, size, "%s%s,%s,%s,%s,%s,%s,%s", + AT_CMD_WRITE_ATR, nodeId, endpointId, SENDMODE, + clusterId, attributeId, attributeType, newValue); - uint64_t atErrorCode = 0; + twRet = TWIssueATCommand(g_plugin, cmdString); + if (twRet != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "Write %s", cmdString); + ret = OC_STACK_ERROR; + goto exit; + } + OC_LOG_V(INFO, TAG, "Write %s", cmdString); - OC_LOG_V(INFO, TAG, "Issued Command: %s.", cmdString); - twRet = IssueATCommand(cmdString, TIME_OUT_05_SECONDS, - &atErrorCode, - responseArray, promptArray, - &responseCount, &promptCount); + TWEntry* entry = NULL; + twRet = TWDequeueEntry(g_plugin, &entry, TW_WRITEATTR); + if (twRet != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "TWDequeueEntry"); + ret = OC_STACK_ERROR; + goto exit; + } + if (entry == NULL) + { + OC_LOG_V(INFO, TAG, "TWEntry is NULL."); + ret = OC_STACK_ERROR; + goto exit; + } - if (twRet != TW_RESULT_OK) - { - OC_LOG_V(ERROR, TAG, "Failed to write: %s", cmdString); - ret = OC_STACK_ERROR; - } - else - { - if (atErrorCode != AT_ERROR_EVERYTHING_OK) - { - OC_LOG_V(ERROR, TAG, - "Write to a remote attribute - AT_ERROR: %" PRId64 "", atErrorCode); - ret = OC_STACK_ERROR; - } - else - { - OC_LOG_V(INFO, TAG, "Issue AT Command %s returned OK.", cmdString); - PrintArray(responseArray, promptArray, responseCount, promptCount); - - //IMPORTANT NOTE: - // Although responseArray is not NULL sometimes, - // do not use it to check for prompt. - // WRITEATTR prompt is stored in promptArray. - if (promptCount > 0) - { - twRet = HandleATResponse(promptArray, promptCount); - if (twRet == TW_RESULT_OK) - { - OC_LOG_V(INFO, TAG, "Set attribute value received a succeed prompt."); - ret = OC_STACK_OK; - } - else - { - OC_LOG_V(ERROR, TAG, "Set attribute value received an error prompt."); - ret = OC_STACK_ERROR; - } - } - else - { - OC_LOG_V(ERROR, TAG, "Why didn't it receive WRITEATTR prompt?"); - ret = OC_STACK_ERROR; - } - } - } - CleanArray(responseArray, promptArray, responseCount, promptCount); - OICFree(cmdString); + twRet = processEntry(entry); + if (twRet != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "processEntry"); + ret = OC_STACK_ERROR; + goto exit; } - OC_LOG_V(INFO, TAG, "Leave TWSetAttribute()."); + ret = OC_STACK_OK; + +exit: + TWDeleteEntry(g_plugin, entry); + OICFree(cmdString); + OC_LOG_V(INFO, TAG, "Leave TWSetAttribute() with ret=%d", ret); return ret; } @@ -413,7 +332,7 @@ OCStackResult TWGetAttribute(char* extendedUniqueId, char* nodeId, char* endpoin { //Ask: AT+READATR:FE5A,01,0,0402,0002 - OC_LOG_V(INFO, TAG, "Enter TWGetAttribute()."); + OC_LOG_V(INFO, TAG, "Enter TWGetAttribute()"); (void)extendedUniqueId; @@ -431,86 +350,73 @@ OCStackResult TWGetAttribute(char* extendedUniqueId, char* nodeId, char* endpoin { OC_LOG_V(ERROR, TAG, "No Memory"); ret = OC_STACK_NO_MEMORY; + goto exit; } - else + int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s", + AT_CMD_READ_ATR, nodeId, + SEPARATOR, endpointId, + SEPARATOR, SENDMODE, + SEPARATOR, clusterId, + SEPARATOR, attributeId); + if(stringRet <= 0) { - snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s", - AT_CMD_READ_ATR, nodeId, - SEPARATOR, endpointId, - SEPARATOR, SENDMODE, - SEPARATOR, clusterId, - SEPARATOR, attributeId); - - char* responseArray[ARRAY_LENGTH] = {}; - uint8_t responseCount = 0; - - char* promptArray[ARRAY_LENGTH] = {}; - uint8_t promptCount = 0; - - uint64_t atErrorCode = 0; + OC_LOG_V(ERROR, TAG, "Build command error."); + ret = OC_STACK_ERROR; + goto exit; + } + twRet = TWIssueATCommand(g_plugin, cmdString); + if (twRet != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "Write %s", cmdString); + ret = OC_STACK_ERROR; + goto exit; + } + OC_LOG_V(INFO, TAG, "Write %s", cmdString); - OC_LOG_V(INFO, TAG, "Issued Command: %s.", cmdString); - twRet = IssueATCommand(cmdString, TIME_OUT_05_SECONDS, - &atErrorCode, - responseArray, promptArray, - &responseCount, &promptCount); + TWEntry* entry = NULL; + twRet = TWDequeueEntry(g_plugin, &entry, TW_RESPATTR); + if (twRet != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "TWDequeueEntry"); + ret = OC_STACK_ERROR; + goto exit; + } + if (entry == NULL) + { + OC_LOG_V(INFO, TAG, "TWEntry is NULL"); + ret = OC_STACK_ERROR; + goto exit; + } - if (twRet != TW_RESULT_OK) - { - OC_LOG_V(ERROR, TAG, "Write %s", cmdString); - ret = OC_STACK_ERROR; - } - else - { - if (atErrorCode != AT_ERROR_EVERYTHING_OK) - { - OC_LOG_V(ERROR, TAG, - "Read a remote attribute - AT_ERROR: %" PRId64 ".", atErrorCode); - ret = OC_STACK_ERROR; - } - else - { - OC_LOG_V(INFO, TAG, "Issue AT Command %s returned OK.", cmdString); - PrintArray(responseArray, promptArray, responseCount, promptCount); + twRet = processEntry(entry); + if (twRet != TW_RESULT_REMOTE_ATTR_HAS_VALUE) + { + OC_LOG_V(ERROR, TAG, "processEntry."); + ret = OC_STACK_ERROR; + goto exit; + } - if (promptCount > 0) - { - twRet = HandleATResponse(promptArray, promptCount); - if (twRet == TW_RESULT_REMOTE_ATTR_HAS_VALUE) - { - OC_LOG_V(INFO, TAG, "Get attribute value received a succeed prompt."); - int size = strlen(g_ZigBeeStatus.remoteAttributeValueRead) + 1; - *outValue = (char*)OICMalloc(sizeof(char) * size); - if (*outValue != NULL) - { - OICStrcpy(*outValue, size, g_ZigBeeStatus.remoteAttributeValueRead); - *outValueLength = g_ZigBeeStatus.remoteAtrributeValueReadLength; - ret = OC_STACK_OK; - } - else - { - ret = OC_STACK_NO_MEMORY; - } - } - else - { - OC_LOG_V(ERROR, TAG, "Get attribute value received an error prompt."); - ret = OC_STACK_ERROR; - } - } - else - { - OC_LOG_V(ERROR, TAG, "Didn't receive READATTR prompt."); - ret = OC_STACK_ERROR; - } - } - } - OICFree(cmdString); - CleanArray(responseArray, promptArray, responseCount, promptCount); + size = strlen(g_ZigBeeStatus.remoteAttributeValueRead) + 1; + *outValue = (char*)OICMalloc(sizeof(char) * size); + if (*outValue == NULL) + { + OC_LOG_V(ERROR, TAG, "No Memory"); + ret = OC_STACK_NO_MEMORY; + goto exit; } - OC_LOG_V(INFO, TAG, "Leave TWGetAttribute()."); + OICStrcpy(*outValue, size, g_ZigBeeStatus.remoteAttributeValueRead); + *outValueLength = g_ZigBeeStatus.remoteAtrributeValueReadLength; + OICFree(g_ZigBeeStatus.remoteAttributeValueRead); + g_ZigBeeStatus.remoteAttributeValueRead = NULL; + g_ZigBeeStatus.remoteAtrributeValueReadLength = 0; + OC_LOG_V(INFO, TAG, "TWGetAttribute() gets an attribute value."); + ret = OC_STACK_OK; +exit: + TWDeleteEntry(g_plugin, entry); + OICFree(cmdString); + OC_LOG_V(INFO, TAG, "Leave TWGetAttribute() with ret=%d", ret); return ret; } @@ -521,7 +427,7 @@ OCStackResult TWSwitchOnOff(char* nodeId, char* endpointId, char* newState) // OK // DFTREP:9E2B,01,0006,01,00 - OC_LOG_V(INFO, TAG, "Enter TWSwitchOnOff()."); + OC_LOG_V(INFO, TAG, "Enter TWSwitchOnOff()"); OCStackResult ret = OC_STACK_ERROR; TWResultCode twRet = TW_RESULT_UNKNOWN; @@ -544,69 +450,64 @@ OCStackResult TWSwitchOnOff(char* nodeId, char* endpointId, char* newState) char* cmdString = (char*)OICMalloc(size * sizeof(char)); if (cmdString == NULL) { + OC_LOG_V(ERROR, TAG, "No Memory"); ret = OC_STACK_NO_MEMORY; + goto exit; } - else + + int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s", + AT_CMD_RUN_ON_OFF, nodeId, SEPARATOR, + endpointId, SEPARATOR, SENDMODE); + if(stringRet <= 0) + { + OC_LOG_V(ERROR, TAG, "Build command error."); + ret = OC_STACK_ERROR; + goto exit; + } + if (newState != NULL) { - snprintf(cmdString, size, "%s%s%s%s%s%s", - AT_CMD_RUN_ON_OFF, nodeId, SEPARATOR, - endpointId, SEPARATOR, SENDMODE); + OICStrcat(cmdString, size, SEPARATOR); + OICStrcat(cmdString, size, newState); + } - if (newState != NULL) - { - OICStrcat(cmdString, size, SEPARATOR); - OICStrcat(cmdString, size, newState); - } + twRet = TWIssueATCommand(g_plugin, cmdString); + if (twRet != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "Write %s", cmdString); + ret = OC_STACK_ERROR; + goto exit; + } + OC_LOG_V(INFO, TAG, "Write %s", cmdString); - char* responseArray[ARRAY_LENGTH] = {}; - uint8_t responseCount = 0; + TWEntry* entry = NULL; + twRet = TWDequeueEntry(g_plugin, &entry, TW_DFTREP); + if (twRet != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "TWDequeueEntry"); + ret = OC_STACK_ERROR; + goto exit; + } + if (entry == NULL) + { + OC_LOG_V(ERROR, TAG, "TWEntry is NULL"); + ret = OC_STACK_ERROR; + goto exit; + } - char* promptArray[ARRAY_LENGTH] = {}; - uint8_t promptCount = 0; + twRet = processEntry(entry); + if (twRet != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString); + ret = OC_STACK_ERROR; + goto exit; + } - uint64_t atErrorCode = 0; - twRet = IssueATCommand(cmdString, TIME_OUT_05_SECONDS, - &atErrorCode, - responseArray, promptArray, - &responseCount, &promptCount); + ret = OC_STACK_OK; - if (twRet != TW_RESULT_OK) - { - OC_LOG_V(ERROR, TAG, "Write AT+RONOFF - FAILED."); - ret = OC_STACK_ERROR; - } - else - { - if (atErrorCode == AT_ERROR_EVERYTHING_OK) - { - twRet = HandleATResponse(promptArray, promptCount); - if (twRet == TW_RESULT_OK) - { - ret = OC_STACK_OK; - } - else - { - ret = OC_STACK_ERROR; - } - } - else - { - if (atErrorCode == AT_ERROR_MESSAGE_NOT_SENT_TO_TARGET_SUCCESSFULLY) - { - OC_LOG_V(ERROR, TAG, - "Switch to ON/OFF - FAILED - Send to the target not succeed."); - } - else - { - OC_LOG_V(ERROR, TAG, "Switch to ON/OFF - FAILED."); - } - ret = OC_STACK_ERROR; - } - } - CleanArray(responseArray, promptArray, responseCount, promptCount); - OICFree(cmdString); - } - OC_LOG_V(INFO, TAG, "Leave TWSwitchOnOff()."); +exit: + TWDeleteEntry(g_plugin, entry); + OICFree(cmdString); + OC_LOG_V(INFO, TAG, "Leave TWSwitchOnOff() with ret=%d", ret); return ret; } @@ -615,7 +516,7 @@ OCStackResult TWMoveToLevel(char* nodeId, char* endpointId, { //AT+LCMVTOLEV:
,,,,, - OC_LOG_V(INFO, TAG, "Enter TWMoveToLevel()."); + OC_LOG_V(INFO, TAG, "Enter TWMoveToLevel()"); OCStackResult ret = OC_STACK_ERROR; TWResultCode twRet = TW_RESULT_UNKNOWN; @@ -631,69 +532,64 @@ OCStackResult TWMoveToLevel(char* nodeId, char* endpointId, char* cmdString = (char*)OICMalloc(size * sizeof(char)); if (cmdString == NULL) { + OC_LOG_V(ERROR, TAG, "No Memory"); ret = OC_STACK_NO_MEMORY; + goto exit; } - else + + int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s%s%s", + AT_CMD_MOVE_TO_LEVEL, nodeId, + SEPARATOR, endpointId, + SEPARATOR, SENDMODE, + SEPARATOR, onOffState, + SEPARATOR, level, + SEPARATOR, transTime); + if(stringRet <= 0) { - snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s%s%s", - AT_CMD_MOVE_TO_LEVEL, nodeId, - SEPARATOR, endpointId, - SEPARATOR, SENDMODE, - SEPARATOR, onOffState, - SEPARATOR, level, - SEPARATOR, transTime); + OC_LOG_V(ERROR, TAG, "Build command error."); + ret = OC_STACK_ERROR; + goto exit; + } - char* responseArray[ARRAY_LENGTH] = {}; - uint8_t responseCount = 0; + twRet = TWIssueATCommand(g_plugin, cmdString); + if (twRet != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "Write %s", cmdString); + ret = OC_STACK_ERROR; + goto exit; + } - char* promptArray[ARRAY_LENGTH] = {}; - uint8_t promptCount = 0; + OC_LOG_V(INFO, TAG, "Write %s", cmdString); - uint64_t atErrorCode = 0; - twRet = IssueATCommand(cmdString, TIME_OUT_05_SECONDS, - &atErrorCode, - responseArray, promptArray, - &responseCount, &promptCount); + TWEntry* entry = NULL; + twRet = TWDequeueEntry(g_plugin, &entry, TW_DFTREP); + if (twRet != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "TWDequeueEntry"); + ret = OC_STACK_ERROR; + goto exit; + } + if (entry == NULL) + { + OC_LOG_V(ERROR, TAG, "TWEntry is NULL"); + ret = OC_STACK_ERROR; + goto exit; + } - if (twRet != TW_RESULT_OK) - { - OC_LOG_V(ERROR, TAG, "Write AT+RONOFF - FAILED."); - ret = OC_STACK_ERROR; - } - else - { - if (atErrorCode == AT_ERROR_EVERYTHING_OK) - { - twRet = HandleATResponse(promptArray, promptCount); - if (twRet == TW_RESULT_OK) - { - ret = OC_STACK_OK; - } - else - { - ret = OC_STACK_ERROR; - } - } - else - { - if (atErrorCode == AT_ERROR_MESSAGE_NOT_SENT_TO_TARGET_SUCCESSFULLY) - { - OC_LOG_V(ERROR, TAG, - "Turn To Level - FAILED - Send to the target not succeeded."); - } - else - { - OC_LOG_V(ERROR, TAG, "Turn To Level - FAILED."); - } - ret = OC_STACK_ERROR; - } - } - - CleanArray(responseArray, promptArray, responseCount, promptCount); - OICFree(cmdString); + twRet = processEntry(entry); + if (twRet != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString); + ret = OC_STACK_ERROR; + goto exit; } - OC_LOG_V(INFO, TAG, "Leave TWMoveToLevel()."); + ret = OC_STACK_OK; + +exit: + TWDeleteEntry(g_plugin, entry); + OICFree(cmdString); + OC_LOG_V(INFO, TAG, "Leave TWMoveToLevel() with ret=%d", ret); return ret; } @@ -701,7 +597,7 @@ OCStackResult TWSwitchDoorLockState(char* nodeId, char* endpointId, char* newSta { //AT+DRLOCK:
,,, - OC_LOG_V(INFO, TAG, "Enter TWSwitchDoorLockState()."); + OC_LOG_V(INFO, TAG, "Enter TWSwitchDoorLockState()"); OCStackResult ret = OC_STACK_ERROR; TWResultCode twRet = TW_RESULT_UNKNOWN; @@ -715,73 +611,150 @@ OCStackResult TWSwitchDoorLockState(char* nodeId, char* endpointId, char* newSta char* cmdString = (char*)OICMalloc(size * sizeof(char)); if (cmdString == NULL) { + OC_LOG_V(ERROR, TAG, "No Memory"); ret = OC_STACK_NO_MEMORY; + goto exit; } - else + + int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s%s%s", + AT_CMD_DOOR_LOCK, nodeId, + SEPARATOR, endpointId, + SEPARATOR, SENDMODE, + SEPARATOR, newState); + if(stringRet <= 0) + { + OC_LOG_V(ERROR, TAG, "Build command error."); + ret = OC_STACK_ERROR; + goto exit; + } + + twRet = TWIssueATCommand(g_plugin, cmdString); + if (twRet != TW_RESULT_OK) { - snprintf(cmdString, size, "%s%s%s%s%s%s%s%s", - AT_CMD_DOOR_LOCK, nodeId, - SEPARATOR, endpointId, - SEPARATOR, SENDMODE, - SEPARATOR, newState); + OC_LOG_V(ERROR, TAG, "Write %s", cmdString); + ret = OC_STACK_ERROR; + goto exit; + } - char* responseArray[ARRAY_LENGTH] = {}; - uint8_t responseCount = 0; + OC_LOG_V(INFO, TAG, "Write %s", cmdString); - char* promptArray[ARRAY_LENGTH] = {}; - uint8_t promptCount = 0; + TWEntry* entry = NULL; + twRet = TWDequeueEntry(g_plugin, &entry, TW_DFTREP); + if (twRet != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "TWDequeueEntry"); + ret = OC_STACK_ERROR; + goto exit; + } - uint64_t atErrorCode = 0; - twRet = IssueATCommand(cmdString, TIME_OUT_05_SECONDS, - &atErrorCode, - responseArray, promptArray, - &responseCount, &promptCount); + if (entry == NULL) + { + OC_LOG_V(ERROR, TAG, "TWEntry is NULL"); + ret = OC_STACK_ERROR; + goto exit; + } - if (twRet != TW_RESULT_OK) - { - OC_LOG_V(ERROR, TAG, "Write AT+DRLOCK - FAILED."); - ret = OC_STACK_ERROR; - } - else - { - if (atErrorCode == AT_ERROR_EVERYTHING_OK) - { - twRet = HandleATResponse(promptArray, promptCount); - if (twRet == TW_RESULT_OK) - { - ret = OC_STACK_OK; - } - else - { - ret = OC_STACK_ERROR; - } - } - else - { - if (atErrorCode == AT_ERROR_MESSAGE_NOT_SENT_TO_TARGET_SUCCESSFULLY) - { - OC_LOG_V(ERROR, TAG, - "Switch to ON/OFF - FAILED - Send to the target not succeeded."); - } - else - { - OC_LOG_V(ERROR, TAG, "Switch to ON/OFF - FAILED."); - } - ret = OC_STACK_ERROR; - } - } + twRet = processEntry(entry); + if (twRet != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString); + ret = OC_STACK_ERROR; + goto exit; + } + + ret = OC_STACK_OK; + +exit: + TWDeleteEntry(g_plugin, entry); + OICFree(cmdString); + OC_LOG_V(INFO, TAG, "Leave TWSwitchDoorLockState() with ret=%d", ret); + return ret; +} + +OCStackResult TWColorMoveToColorTemperature(char* nodeId, char* endpointId, + char* colorTemperature, char* transTime) +{ + + //AT+CCMVTOCT:
,,,, + // OK + // ERROR: + + OC_LOG_V(INFO, TAG, "Enter TWColorMoveToColorTemperature()"); + + OCStackResult ret = OC_STACK_ERROR; + TWResultCode twRet = TW_RESULT_UNKNOWN; + + int size = 0; + size = strlen(AT_CMD_COLOR_CTRL_MOVE_TO_COLOR_TEMPERATURE) + strlen(nodeId) + + SEPARATOR_LENGTH + strlen(endpointId) + + SEPARATOR_LENGTH + strlen(SENDMODE) + + SEPARATOR_LENGTH + strlen(colorTemperature) + + SEPARATOR_LENGTH + strlen(transTime) + 1; + + char* cmdString = (char*)OICMalloc(size * sizeof(char)); + if (cmdString == NULL) + { + OC_LOG_V(ERROR, TAG, "No Memory"); + ret = OC_STACK_NO_MEMORY; + goto exit; + } + + int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s", + AT_CMD_COLOR_CTRL_MOVE_TO_COLOR_TEMPERATURE, nodeId, + SEPARATOR, endpointId, + SEPARATOR, SENDMODE, + SEPARATOR, colorTemperature, + SEPARATOR, transTime); + if(stringRet <= 0) + { + OC_LOG_V(ERROR, TAG, "Build command error."); + ret = OC_STACK_ERROR; + goto exit; + } + twRet = TWIssueATCommand(g_plugin, cmdString); + if (twRet != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "Write %s", cmdString); + ret = OC_STACK_ERROR; + goto exit; + } + OC_LOG_V(INFO, TAG, "Write %s", cmdString); + + TWEntry* entry = NULL; + twRet = TWDequeueEntry(g_plugin, &entry, TW_DFTREP); + if (twRet != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "TWDequeueEntry - %s", cmdString); + ret = OC_STACK_ERROR; + goto exit; + } + if (entry == NULL) + { + OC_LOG_V(ERROR, TAG, "TWEntry is NULL - %s", cmdString); + ret = OC_STACK_ERROR; + goto exit; + } - CleanArray(responseArray, promptArray, responseCount, promptCount); - OICFree(cmdString); + twRet = processEntry(entry); + if (twRet != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString); + ret = OC_STACK_ERROR; + goto exit; } - OC_LOG_V(INFO, TAG, "Leave TWSwitchDoorLockState()."); + ret = OC_STACK_OK; + +exit: + TWDeleteEntry(g_plugin, entry); + OICFree(cmdString); + OC_LOG_V(INFO, TAG, "Leave TWColorMoveToColorTemperature() with ret=%d", ret); return ret; } OCStackResult TWSetDiscoveryCallback(const TWDeviceFoundCallback callback) { - OC_LOG_V(INFO, TAG, "Enter TWSetDiscoveryCallback()."); + OC_LOG_V(INFO, TAG, "Enter TWSetDiscoveryCallback()"); if (callback != NULL) { g_DeviceFoundCallback= callback; @@ -791,458 +764,423 @@ OCStackResult TWSetDiscoveryCallback(const TWDeviceFoundCallback callback) g_DeviceFoundCallback = NULL; } - OC_LOG_V(INFO, TAG, "Leave TWSetDiscoveryCallback()."); + OC_LOG_V(INFO, TAG, "Leave TWSetDiscoveryCallback() with ret=%d", OC_STACK_OK); return OC_STACK_OK; } -OCStackResult TWUninitialize() +OCStackResult TWSetStatusUpdateCallback(TWDeviceStatusUpdateCallback callback) { - OC_LOG_V(INFO, TAG, "Enter TWUninitializeZigBee()."); - - OCStackResult ret = OC_STACK_ERROR; - - TWResultCode twRet = ClosePort(g_fd); - if (twRet == TW_RESULT_OK) + OC_LOG_V(INFO, TAG, "Enter TWSetStatusUpdateCallback()"); + if (callback != NULL) { - ret = OC_STACK_OK; + g_DeviceStatusUpdateCallback= callback; } else { - ret = OC_STACK_ERROR; + g_DeviceStatusUpdateCallback = NULL; } - OC_LOG_V(INFO, TAG, "Leave TWUninitializeZigBee()."); - return ret; + OC_LOG_V(INFO, TAG, "Leave TWSetStatusUpdateCallback() with ret=%d", OC_STACK_OK); + return OC_STACK_OK; } -//----------------------------------------------------------------------------- -// Internal functions -//----------------------------------------------------------------------------- - -TWResultCode Reset() +OCStackResult TWListenForStatusUpdates(char* nodeId, char* endpointId) { - OC_LOG_V(INFO, TAG, "Enter Reset()."); + OC_LOG_V(INFO, TAG, "Enter TWListenForStatusUpdates()"); - TWResultCode ret = TW_RESULT_ERROR; + char* zoneClusterID = "0500"; + char* zoneAttributeID = "0010"; + char* attributeDateType = "F0"; - char* responseArray[ARRAY_LENGTH] = {}; - uint8_t responseCount = 0; - char* promptArray[ARRAY_LENGTH] = {}; - uint8_t promptCount = 0; - uint64_t atErrorCode = 0; + OCStackResult ret = TWSetAttribute(NULL, nodeId, endpointId, + zoneClusterID, zoneAttributeID, attributeDateType, + g_LocalEUI); - ret = IssueATCommand(AT_CMD_RESET, TIME_OUT_00_SECOND, - &atErrorCode, - responseArray, NULL, - &responseCount, NULL); + OC_LOG_V(INFO, TAG, "Leave TWListenForStatusUpdates() with ret=%d", ret); + return ret; +} - if (ret != TW_RESULT_OK) - { - OC_LOG_V(ERROR, TAG, "TWriting error on AT&F."); - ret = TW_RESULT_ERROR; - } - else +OCStackResult TWProcess() +{ + + TWResultCode ret = TW_RESULT_UNKNOWN; + + while (true) { - if (atErrorCode != AT_ERROR_EVERYTHING_OK) + TWEntry* entry = NULL; + ret = TWDequeueEntry(g_plugin, &entry, TW_NONE); + if (ret != TW_RESULT_OK) { - OC_LOG_V(ERROR, TAG, "Dongle Reset - FAILED - AT_ERROR: %" PRId64 "", atErrorCode); - ret = TW_RESULT_ERROR; + OC_LOG_V(ERROR, TAG, "TWDequeueEntry"); + ret = OC_STACK_ERROR; + break; } - else + if (entry == NULL) { - OC_LOG_V(INFO, TAG, "Dongle Reset - OK."); - ret = TW_RESULT_OK; + ret = OC_STACK_OK; + break; } + ret = processEntry(entry); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "processEntry"); + ret = TWDeleteEntry(g_plugin, entry); + if(ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "Failed to delete entry."); + ret = OC_STACK_ERROR; + break; + } + } + else + { + OC_LOG_V(INFO, TAG, "processEntry"); + ret = TWDeleteEntry(g_plugin, entry); + if(ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "Failed to delete entry."); + ret = OC_STACK_ERROR; + break; + } + } } - CleanArray(responseArray, promptArray, responseCount, promptCount); - - OC_LOG_V(INFO, TAG, "Leave Reset()."); return ret; } -TWResultCode GetLocalEUI() +OCStackResult TWUninitialize() { - OC_LOG_V(INFO, TAG, "Enter GetLocalEUI()."); - TWResultCode ret = TW_RESULT_UNKNOWN; - - char* responseArray[ARRAY_LENGTH] = {}; - uint8_t responseCount = 0; - - char* promptArray[ARRAY_LENGTH] = {}; - uint8_t promptCount = 0; - - uint64_t atErrorCode = 0; - - OC_LOG_V(INFO, TAG, "Issued Command: %s.", AT_CMD_GET_LOCAL_EUI); - ret = IssueATCommand(AT_CMD_GET_LOCAL_EUI, TIME_OUT_05_SECONDS, - &atErrorCode, - responseArray, promptArray, - &responseCount, &promptCount); + OC_LOG_V(INFO, TAG, "Enter TWUninitializeZigBee()"); + OCStackResult ret = OC_STACK_ERROR; - if (ret != TW_RESULT_OK) + TWResultCode twRet = TWStopSock(g_plugin); + if (twRet == TW_RESULT_OK) { - OC_LOG_V(ERROR, TAG, "Write %s", AT_CMD_GET_LOCAL_EUI); - ret = TW_RESULT_ERROR; + OC_LOG_V(INFO, TAG, "TWStopSock"); + ret = OC_STACK_OK; } else { - if (atErrorCode != AT_ERROR_EVERYTHING_OK) - { - OC_LOG_V(ERROR, TAG, - "Get Local EUI Failed - AT_ERROR: %" PRId64 "", atErrorCode); - ret = TW_RESULT_ERROR; - } - else - { - OICStrcpy(g_LocalEUI, SIZE_EUI, responseArray[0]); - OC_LOG_V(INFO, TAG, "Local EUI: %s ", g_LocalEUI); - ret = TW_RESULT_OK; - } + OC_LOG_V(ERROR, TAG, "TWStopSock"); + ret = OC_STACK_ERROR; } - CleanArray(responseArray, promptArray, responseCount, promptCount); + DeallocateTWDeviceList(); - OC_LOG_V(INFO, TAG, "Leave GetLocalEUI()."); + OC_LOG_V(INFO, TAG, "Leave TWUninitializeZigBee() with ret=%d", ret); return ret; } -TWResultCode CreatePAN() -{ - /* - //at+n - // +N=NoPAN - // OK - - //at+n - // +N=COO,26,-6,7306,133F04EA669C6B24 - // OK +//----------------------------------------------------------------------------- +// Internal functions +//----------------------------------------------------------------------------- - //at+en - // OK - // JPAN:26,7306,133F04EA669C6B24 +TWResultCode processEntry(TWEntry *entry) +{ + OC_LOG_V(INFO, TAG, "Enter processEntry()"); - //at+en - // ERROR:28 - */ + TWResultCode ret = TW_RESULT_UNKNOWN; + switch(entry->type) + { + /* + TW_OK, TODO: Joey to return an TWEntry for OK + TW_ERROR, TODO: Joey to return an TWEntry for ERROR - OC_LOG_V(INFO, TAG, "Enter CreatePAN()"); + TW_INCLUSTER, - TWResultCode ret = TW_RESULT_ERROR; + TW_ACK, + TW_NACK, + TW_SEQ, + TW_MAX_ENTRY + */ - uint8_t responseCount1 = 0; - uint8_t promptCount1 = 0; - char* responseArray1[ARRAY_LENGTH] = {}; - char* promptArray1[ARRAY_LENGTH] = {}; + /* + TODO: Joey? + //Ask: AT+PJOIN + //Response: OK - uint8_t responseCount2 = 0; - uint8_t promptCount2 = 0; - char* responseArray2[ARRAY_LENGTH] = {}; - char* promptArray2[ARRAY_LENGTH] = {}; + //Ask: AT+PJOIN + //Response: ERROR:70 - uint64_t atErrorCode = 0; + */ - ret = IssueATCommand(AT_CMD_GET_NETWORK_INFO, TIME_OUT_00_SECOND, - &atErrorCode, - responseArray1, promptArray1, - &responseCount1, &promptCount1); - if (ret != TW_RESULT_OK) - { - OC_LOG_V(ERROR, TAG, "Write AT+N - FAILED."); - ret = TW_RESULT_ERROR; - } - else - { - if (atErrorCode != AT_ERROR_EVERYTHING_OK) - { - OC_LOG_V(ERROR, TAG, "Get network info - FAILED."); - ret = TW_RESULT_ERROR; - } - else - { - //Handle +N - ret = HandleATResponse(responseArray1, responseCount1); - if (ret == TW_RESULT_NO_LOCAL_PAN) + case TW_NETWORK_INFO: + ret = processEntryNETWORK_INFO(entry); + if ((ret != TW_RESULT_NO_LOCAL_PAN) && + (ret != TW_RESULT_HAS_LOCAL_PAN)) { - OC_LOG_V(INFO, TAG, "Attempt to write AT+EN. "); - ret = IssueATCommand(AT_CMD_ESTABLISH_NETWORK, TIME_OUT_01_SECOND, - &atErrorCode, - responseArray2, promptArray2, - &responseCount2, &promptCount2); - - if (ret != TW_RESULT_OK) - { - OC_LOG_V(ERROR, TAG, "Write AT+EN - FAILED."); - ret = TW_RESULT_ERROR; - } - else - { - if (atErrorCode == AT_ERROR_EVERYTHING_OK) //OK - { - //IMPORTANT: Special case for JPAN prompt: - //JPAN prompts are stored in responseArray instead of promptArray - //Handle JPAN:26,7306,133F04EA669C6B24 - ret = HandleATResponse(responseArray2, responseCount2); - if (ret == TW_RESULT_NEW_LOCAL_PAN_ESTABLISHED) - { - OC_LOG_V(INFO, TAG, "New Local PAN established - OK."); - ret = TW_RESULT_OK; - } - else - { - OC_LOG_V(ERROR, TAG, "Handling AT+EN."); - ret = TW_RESULT_ERROR; - } - } - else if (atErrorCode == AT_ERROR_NODE_IS_PART_OF_PAN) - { - OC_LOG_V(INFO, TAG, "Already Established PAN - OK."); - ret = TW_RESULT_OK; - } - else - { - OC_LOG_V(ERROR, TAG, "Couldn't establish PAN."); - ret = TW_RESULT_ERROR; - } - } + OC_LOG_V(ERROR, TAG, "processEntryNETWORK_INFO."); } - else if (ret == TW_RESULT_HAS_LOCAL_PAN) + break; + case TW_JPAN: + ret = processEntryJPAN(entry); + if (ret != TW_RESULT_OK) { - OC_LOG_V(INFO, TAG, "Already established PAN - OK."); - ret = TW_RESULT_OK; + OC_LOG_V(ERROR, TAG, "processEntryJPAN."); } - else if (atErrorCode != 0) + break; + case TW_SED: + ret = processEntryEndDevice(entry); + if (ret != TW_RESULT_OK) { - OC_LOG_V(ERROR, TAG, - "CreatePAN() FAILED with AT_ERROR: %" PRId64 "", atErrorCode); - ret = TW_RESULT_ERROR; + OC_LOG_V(ERROR, TAG, "processEntrySED."); } - } - } - - CleanArray(responseArray1, promptArray1, responseCount1, promptCount1); - CleanArray(responseArray2, promptArray2, responseCount2, promptCount2); - - OC_LOG_V(INFO, TAG, "Leave CreatePAN()."); - return ret; -} - -TWResultCode EnableJoin(bool isKeyEncrypted, uint8_t* outDeviceJoinedCount) -{ - //Ask: AT+PJOIN - //Response: OK + break; + case TW_RFD: + ret = processEntryEndDevice(entry); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "processEntryRFD."); + } + break; + case TW_FFD: + ret = processEntryEndDevice(entry); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "processEntryFFD."); + } + break; + case TW_ZED: + ret = processEntryEndDevice(entry); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "processEntryZED."); + } + break; + case TW_MATCHDESC: + ret = processEntryMatchDesc(entry); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "processEntryMatchDesc."); + } + break; + case TW_SIMPLEDESC: + ret = processEntrySimpleDesc(entry); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "processEntrySimpleDesc."); + } + break; + case TW_WRITEATTR: + ret = processEntryWriteAttr(entry); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "processEntryWriteAttr."); + } + break; + case TW_RESPATTR: + ret = processEntryReadAttr(entry); + if (ret != TW_RESULT_REMOTE_ATTR_HAS_VALUE) + { + OC_LOG_V(ERROR, TAG, "processEntryReadAttr."); + } + break; + case TW_TEMPERATURE: + ret = processEntryTemperature(entry); + if (ret != TW_RESULT_REMOTE_ATTR_HAS_VALUE) + { + OC_LOG_V(ERROR, TAG, "processEntryTemperature."); + } + break; + case TW_DRLOCRSP: + ret = processEntrySwitchDoorLockState(entry); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "processEntrySwitchDoorLockState."); + } + break; + case TW_DRUNLOCKRSP: + ret = processEntrySwitchDoorLockState(entry); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "processEntrySwitchDoorLockState."); + } + break; + case TW_DFTREP: + ret = processEntryZCLDefaultResponse(entry); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "processEntryZCLDefaultResponse."); + } + break; + case TW_ZENROLLREQ: + ret = processEntryZoneEnrollRequest(entry); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "processEntryZoneEnrollRequest."); + } + break; + case TW_ENROLLED: + ret = processEntryEnrolled(entry); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "processEntryEnrolled."); + } + break; + case TW_ZONESTATUS: + ret = processEntryZoneStatus(entry); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "processEntryZoneStatus."); + } + break; + case TW_ADDRESS_RESPONSE: + ret = processEntryAddressResponse(entry); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "processEntryAddressResponse."); + } + break; + default: + OC_LOG_V(ERROR, TAG, "processEntry() doesn't receive an valid entry."); + ret = TW_RESULT_ERROR; + break; + } - //Ask: AT+PJOIN - //Response: ERROR:70 + OC_LOG_V(INFO, TAG, "Leave processEntry() with ret=%d", ret); + return ret; +} - OC_LOG_V(INFO, TAG, "Enter Enabling Join()."); +TWResultCode processEntryNETWORK_INFO(TWEntry* entry) +{ + /* + //at+n + // +N=NoPAN + // OK - (void)isKeyEncrypted; + //at+n + // +N=COO,26,-6,7306,133F04EA669C6B24 + // OK + */ - TWResultCode ret = TW_RESULT_ERROR; + OC_LOG_V(INFO, TAG, "Enter processEntryNETWORK_INFO()"); + + TWResultCode ret = TW_RESULT_UNKNOWN; - if (outDeviceJoinedCount != NULL) + if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0) { - *outDeviceJoinedCount = 0; + OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode); + ret = TW_RESULT_ERROR; + goto exit; + } - isKeyEncrypted = false; //TODO: for now - don't encrypt + ret = HandleATResponse(entry); + +exit: + OC_LOG_V(INFO, TAG, "Leave processEntryNETWORK_INFO() with ret=%d", ret); + return ret; +} - char* joinTimeHex = "0F"; //TODO: for now - 15 seconds - uint8_t joinTimeDecimal = 15; //TODO: for now - 15 seconds +TWResultCode processEntryJPAN(TWEntry* entry) +{ + /* + //at+en + // OK + // JPAN:26,7306,133F04EA669C6B24 - char* broadcast = "FFFC"; + //at+en + // ERROR:28 + */ - int size = strlen(AT_CMD_PERMIT_JOIN) + strlen(joinTimeHex) + - SEPARATOR_LENGTH + strlen(broadcast) + 1; + OC_LOG_V(INFO, TAG, "Enter processEntryJPAN()"); - char* cmdString = (char*)OICMalloc(size * sizeof(char)); - if (cmdString == NULL) + TWResultCode ret = TW_RESULT_UNKNOWN; + if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) == 0) + { + ret = HandleATResponse(entry); + if (ret == TW_RESULT_NEW_LOCAL_PAN_ESTABLISHED) { - ret = TW_RESULT_ERROR_NO_MEMORY; + OC_LOG_V(INFO, TAG, "New Local PAN established."); + ret = TW_RESULT_OK; } else { - snprintf(cmdString, size, "%s%s%s%s", - AT_CMD_PERMIT_JOIN, joinTimeHex, SEPARATOR, broadcast); - - char* responseArray[ARRAY_LENGTH] = {}; - uint8_t responseCount = 0; - - char* promptArray[ARRAY_LENGTH] = {}; - uint8_t promptCount = 0; - - uint64_t atErrorCode = 0; - - OC_LOG_V(INFO, TAG, "Attempt to allow joining..."); - - OC_LOG_V(INFO, TAG, "Issued Command: %s.", cmdString); - ret = IssueATCommand(cmdString, joinTimeDecimal, - &atErrorCode, - responseArray, promptArray, - &responseCount, &promptCount); - - if (ret != TW_RESULT_OK) - { - OC_LOG_V(ERROR, TAG, "Write AT+PJOIN - AT_ERROR = %" PRId64 "", atErrorCode); - ret = TW_RESULT_ERROR; - } - else - { - if (atErrorCode == AT_ERROR_EVERYTHING_OK) - { - OC_LOG_V(INFO, TAG, "Enable joining - OK."); - OC_LOG_V(INFO, TAG, - "Joining has been allowed for %d seconds. Time's up!", - joinTimeDecimal); - if (promptCount > 0) // some devices joined. - { - OC_LOG_V(INFO, TAG, "Number of devices joined:%d.", promptCount); - *outDeviceJoinedCount = promptCount; - - //Handle SED, FFD, RFD,... - ret = HandleATResponse(promptArray, promptCount); - } - else - { - ret = TW_RESULT_OK; - } - } - else if (atErrorCode == AT_ERROR_INVALID_OPERATION) - { - OC_LOG_V(ERROR, TAG, "Enable joining - FAILED - because there was no PAN."); - ret = TW_RESULT_ERROR; - } - else - { - OC_LOG_V(ERROR, TAG, "Enable joining - FAILED."); - ret = TW_RESULT_ERROR; - } - } - CleanArray(responseArray, promptArray, responseCount, promptCount); + ret = TW_RESULT_ERROR; } } + else if (strcmp(entry->atErrorCode, AT_STR_ERROR_NODE_IS_PART_OF_PAN) == 0) + { + OC_LOG_V(INFO, TAG, "Already Established PAN."); + ret = TW_RESULT_OK; + } + else + { + OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode); + ret = TW_RESULT_ERROR; + } - OC_LOG_V(INFO, TAG, "Leave Enabling Join()"); + OC_LOG_V(INFO, TAG, "Leave processEntryJPAN() with ret=%d", ret); return ret; } -TWResultCode FindMatchNodes(uint8_t* outDeviceMatchedCount) +TWResultCode processEntryEndDevice(TWEntry* entry) { - //AT+MATCHREQ:0104,03,0003,0006,0402,00 - // OK - // MatchDesc:0B4A,00,01 - - //AT+MATCHREQ:0104,03,0999,0999,0999,00 - // OK - - OC_LOG_V(INFO, TAG, "Enter FindMatchNodes()."); + OC_LOG_V(INFO, TAG, "Enter processEntryEndDevice()"); TWResultCode ret = TW_RESULT_UNKNOWN; + ret = HandleATResponse(entry); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "HandleATResponse"); + } - char* profileHomeAutomation = "0104"; - char* inClusterCount = "04"; - char* outClusterCount = "00"; + OC_LOG_V(INFO, TAG, "Leave processEntryEndDevice() with ret=%d", ret); + return ret; +} - //TODO: add more clusters - char* clusterIdentify = "0003"; - char* clusterOnOff = "0006"; - char* clusterTemperatureMeasurement = "0402"; - char* clusterIASZone = "0500"; +TWResultCode processEntryMatchDesc(TWEntry* entry) +{ + //MatchDesc:0B4A,00,01 - int size = strlen(AT_CMD_MATCH_REQUEST) + strlen(profileHomeAutomation) + - SEPARATOR_LENGTH + strlen(inClusterCount) + - SEPARATOR_LENGTH + strlen(clusterIdentify) + - SEPARATOR_LENGTH + strlen(clusterOnOff) + - SEPARATOR_LENGTH + strlen(clusterTemperatureMeasurement) + - SEPARATOR_LENGTH + strlen(clusterIASZone) + - SEPARATOR_LENGTH + strlen(outClusterCount) + 1; + OC_LOG_V(INFO, TAG, "Enter processEntryMatchDesc()"); + TWResultCode ret = TW_RESULT_UNKNOWN; - char* cmdString = (char*)OICMalloc(size * sizeof(char)); - if (cmdString == NULL) + if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0) { - ret = TW_RESULT_ERROR_NO_MEMORY; + OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode); + ret = TW_RESULT_ERROR; } else { - snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s", - AT_CMD_MATCH_REQUEST, profileHomeAutomation, - SEPARATOR, inClusterCount, - SEPARATOR, clusterIdentify, - SEPARATOR, clusterOnOff, - SEPARATOR, clusterTemperatureMeasurement, - SEPARATOR, clusterIASZone, - SEPARATOR, outClusterCount); - - char* responseArray[ARRAY_LENGTH] = {}; - uint8_t responseCount = 0; - - char* promptArray[ARRAY_LENGTH] = {}; - uint8_t promptCount = 0; - - uint64_t atErrorCode = 0; - - OC_LOG_V(INFO, TAG, "Issued Command: %s.", cmdString); - ret = IssueATCommand(cmdString, TIME_OUT_10_SECONDS, - &atErrorCode, - responseArray, promptArray, - &responseCount, &promptCount); - - if (ret != TW_RESULT_OK) - { - OC_LOG_V(ERROR, TAG, "Write %s - AT_ERROR = %" PRId64 ".", cmdString, atErrorCode); - ret = TW_RESULT_ERROR; - } - else + ret = HandleATResponse(entry); + if (ret == TW_RESULT_OK) { - if (atErrorCode != AT_ERROR_EVERYTHING_OK) + OC_LOG_V(INFO, TAG, "HandleATResponse"); + ret = FindClusters(g_WIPDevice->nodeId, + g_WIPDevice->endpointOfInterest->endpointId); + if (ret == TW_RESULT_OK) { - OC_LOG_V(ERROR, TAG, - "AT_ERROR %" PRId64 " returned from %s", atErrorCode, cmdString); - ret = TW_RESULT_ERROR; + OC_LOG_V(INFO, TAG, "FindClusters - Found a match node"); + if (g_DeviceFoundCallback != NULL) + { + OC_LOG_V(INFO, TAG, "Found a match node -- invoke callback"); + g_DeviceFoundCallback(g_WIPDevice); + } + ret = TW_RESULT_OK; } else { - OC_LOG_V(INFO, TAG, "Number of found matched nodes:%d.", promptCount); - if (promptCount > 0) - { - //Handle all received MatchDesc:0B4A,00,01 - ret = HandleATResponse(promptArray, promptCount); - if (ret == TW_RESULT_OK) - { - OC_LOG_V(INFO, TAG, "Handle matched nodes - SUCCEED."); - *outDeviceMatchedCount = promptCount; - ret = TW_RESULT_FOUND_MATCHED_DEVICES; - } - else - { - OC_LOG_V(ERROR, TAG, "Handle matched nodes."); - ret = TW_RESULT_ERROR; - } - } - else - { - ret = TW_RESULT_FOUND_NO_MATCHED_DEVICE; - } + OC_LOG_V(ERROR, TAG, "FindClusters"); + ret = TW_RESULT_ERROR; } } - - OICFree(cmdString); - CleanArray(responseArray, promptArray, responseCount, promptCount); - - if (g_FoundMatchedDeviceList != NULL) + else { - OC_LOG_V(INFO, TAG, "Found these devices via match request."); - PrintTWDeviceList(g_FoundMatchedDeviceList); + OC_LOG_V(ERROR, TAG, "HandleATResponse"); + ret = TW_RESULT_ERROR; } + + g_WIPDevice = NULL; //reset and do not deallocate it } - OC_LOG_V(INFO, TAG, "Leave FindMatchNodes()."); + OC_LOG_V(INFO, TAG, "Leave processEntryMatchDesc() with ret=%d", ret); return ret; } -TWResultCode FindClusters(char nodeId[], char endpoint[]) +TWResultCode processEntrySimpleDesc(TWEntry* entry) { + /* //AT+SIMPLEDESC:3746,3746,01 // SEQ:97 // OK @@ -1255,1415 +1193,1512 @@ TWResultCode FindClusters(char nodeId[], char endpoint[]) // OutCluster:0019 // // ACK:97 - - OC_LOG_V(INFO, TAG, "Enter FindClusters()."); + */ + OC_LOG_V(INFO, TAG, "Enter processEntrySimpleDesc()"); TWResultCode ret = TW_RESULT_UNKNOWN; - int size = strlen(AT_CMD_SIMPLE_DESC) + strlen(nodeId) + - SEPARATOR_LENGTH + strlen(nodeId) + - SEPARATOR_LENGTH + strlen(endpoint) + 1; - - char* cmdString = (char*)OICMalloc(size * sizeof(char)); - if (cmdString == NULL) + if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0) { - ret = TW_RESULT_ERROR_NO_MEMORY; + OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", (entry->atErrorCode)); + ret = TW_RESULT_ERROR; } else { - snprintf(cmdString, size, "%s%s%s%s%s%s", - AT_CMD_SIMPLE_DESC, nodeId, - SEPARATOR, nodeId, - SEPARATOR, endpoint); - - char* responseArray[ARRAY_LENGTH] = {}; - uint8_t responseCount = 0; - - char* promptArray[ARRAY_LENGTH] = {}; - uint8_t promptCount = 0; - - uint64_t atErrorCode = 0; - - OC_LOG_V(INFO, TAG, "Issued Command: %s.", cmdString); - ret = IssueATCommand(cmdString, TIME_OUT_07_SECONDS, - &atErrorCode, - responseArray, promptArray, - &responseCount, &promptCount); - - if (ret != TW_RESULT_OK) + if (entry->count == 6) //must be 6 as it is the number of lines to expect { - OC_LOG_V(ERROR, TAG, "Write %s", cmdString); - ret = TW_RESULT_ERROR; + ret = HandleATResponse(entry); + if (ret == TW_RESULT_HAS_CLUSTERS) + { + OC_LOG_V(INFO, TAG, "has clusters."); + ret = TW_RESULT_OK; + } } else { - if (atErrorCode != AT_ERROR_EVERYTHING_OK) - { - OC_LOG_V(ERROR, TAG, - "AT_ERROR %" PRId64 " returned from %s", atErrorCode, cmdString); - ret = TW_RESULT_ERROR; - } - else - { - if (promptCount == SIMPLEDESC_RESPONSE_EXPECTED_LINES) - { - //Handle - SimpleDesc... - ret = HandleATResponse(promptArray, promptCount); - if (ret == TW_RESULT_OK) - { - OC_LOG_V(INFO, TAG, - "Succeed handling clusters for nodeid %s.", nodeId); - ret = TW_RESULT_HAS_CLUSTERS; - } - else - { - OC_LOG_V(ERROR, TAG, "Error handling clusters for nodeid %s.", nodeId); - ret = TW_RESULT_ERROR; - } - } - else - { - OC_LOG_V(ERROR, TAG, "Received an invalid Simple Descriptor prompt."); - PrintArray(responseArray, promptArray, responseCount, promptCount); - ret = TW_RESULT_ERROR; - } - } + OC_LOG_V(INFO, TAG, "Received an invalid Simple Descriptor."); + ret = TW_RESULT_ERROR; } - CleanArray(responseArray, promptArray, responseCount, promptCount); - OICFree(cmdString); } - OC_LOG_V(INFO, TAG, "Leave FindClusters()."); - + OC_LOG_V(INFO, TAG, "Leave processEntrySimpleDesc() returns with ret=%d", ret); return ret; } -OCStackResult TWListenForStatusUpdates(char* nodeId, char* endpointId) +TWResultCode processEntryWriteAttr(TWEntry* entry) { - OC_LOG_V(INFO, TAG, "Enter TWListenForStatusUpdates()."); + //AT+WRITEATR:3A3D,01,0,0003,0000,21,00 + // OK + // WRITEATTR:3A3D,01,0003,,00 - char* zoneClusterID = "0500"; - char* zoneAttributeID = "0010"; - char* attributeDateType = "F0"; + OC_LOG_V(INFO, TAG, "Enter processEntryWriteAttr()"); - OCStackResult ret = TWSetAttribute(NULL, nodeId, endpointId, - zoneClusterID, zoneAttributeID, attributeDateType, - g_LocalEUI); + TWResultCode ret = TW_RESULT_UNKNOWN; - OC_LOG_V(INFO, TAG, "Leave TWListenForStatusUpdates()."); + if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0) + { + OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode); + ret = TW_RESULT_ERROR; + } + else + { + ret = HandleATResponse(entry); + } + OC_LOG_V(INFO, TAG, "Leave processEntryWriteAttr() returns with ret=%d", ret); return ret; } -TWResultCode HandleATResponse(char* responseArray[], int count) +TWResultCode processEntryReadAttr(TWEntry* entry) { - OC_LOG_V(INFO, TAG, "Enter HandleATResponse()."); + OC_LOG_V(INFO, TAG, "Enter processEntryWriteAttr()"); - TWResultCode ret = TW_RESULT_ERROR; + TWResultCode ret = TW_RESULT_UNKNOWN; - int32_t i = 0; - for (; i < count; i++) + if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0) { - uint32_t k = 0; - for (; k < sizeof(g_TWATResultHandlerPairArray)/sizeof(TWATResultHandlerPair); ++k) - { - if (strncmp(responseArray[i], - g_TWATResultHandlerPairArray[k].resultTxt, - strlen(g_TWATResultHandlerPairArray[k].resultTxt) - ) == 0) - { - char* tokens[ARRAY_LENGTH] = {}; - const char* delimiters = ",\r\n"; - int paramCount = Tokenize(responseArray[i] + - strlen(g_TWATResultHandlerPairArray[k].resultTxt), - delimiters, tokens); - if (paramCount > 0) - { - ret = g_TWATResultHandlerPairArray[k].handler(paramCount, tokens); - } - - int n = 0; - for (; n < paramCount; n++) - { - OICFree(tokens[n]); - } - - break; - } - } + OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode); + ret = TW_RESULT_ERROR; + } + else + { + ret = HandleATResponse(entry); } - OC_LOG_V(INFO, TAG, "Leave HandleATResponse()."); + OC_LOG_V(INFO, TAG, "Leave processEntryWriteAttr() returns with ret=%d", ret); return ret; } -//----------------------------------------------------------------------------- -// Internal functions - AT Response/Prompt Handlers -//----------------------------------------------------------------------------- - -TWResultCode TelAddressResponseHandler(int count, char* tokens[]) +TWResultCode processEntryTemperature(TWEntry* entry) { - //AddrResp:[,,] - //AddrResp:00,15ED,000D6F00040574B8 - - if(!tokens || count <= 3) - { - return TW_RESULT_ERROR_INVALID_PARAMS; - } - - OC_LOG_V(INFO, TAG, "Enter TelAddressResponseHandler()"); + OC_LOG_V(INFO, TAG, "Enter processEntryTemperature()"); - TWResultCode ret = TW_RESULT_ERROR; + TWResultCode ret = TW_RESULT_UNKNOWN; - if (strcmp(tokens[0], AT_STR_ERROR_OK) != 0) + if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0) { - OC_LOG_V(ERROR, TAG, "AddrResp prompt contained error status."); + OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode); + ret = TW_RESULT_ERROR; } else { - OICStrcpy(g_WIPRemoteNodeId, SIZE_NODEID, tokens[1]); - OICStrcpy(g_WIPRemoteEUI, SIZE_EUI, tokens[2]); - ret = TW_RESULT_OK; + ret = HandleATResponse(entry); } - OC_LOG_V(INFO, TAG, "Leave TelAddressResponseHandler()"); - + OC_LOG_V(INFO, TAG, "Leave processEntryTemperature() returns with ret=%d", ret); return ret; } -TWResultCode TelNetworkInfoHandler(int count, char* tokens[]) +TWResultCode processEntrySwitchDoorLockState(TWEntry* entry) { - // Ask: AT+N - // Response: +N=COO,24,-6,9726,12BB200F073AB573 - // or - // +N=NoPAN - // - // +N=,,,, + OC_LOG_V(INFO, TAG, "Enter processEntrySwitchDoorLockState()"); - OC_LOG_V(INFO, TAG, "Enter TelNetworkInfoHandler()"); - if(!tokens || count <= 4) - { - return TW_RESULT_ERROR_INVALID_PARAMS; - } TWResultCode ret = TW_RESULT_UNKNOWN; - int i = 0; - for (; i < count; ++i) - { - if (tokens[i] != NULL) - { - OC_LOG_V(INFO, TAG, "Token[%d] = %s", i, tokens[i]); - } - } - - char* temp = tokens[0]; - if (strcmp(temp, "NoPAN") == 0) + if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0) { - OC_LOG_V(INFO, TAG, "TelNetworkInfoHandler(): It is NoPan."); - ret = TW_RESULT_NO_LOCAL_PAN; + OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode); + ret = TW_RESULT_ERROR; } else { - OC_LOG_V(INFO, TAG, "TelNetworkInfoHandler(): already have an established network."); - ret = AsciiHexToValue(tokens[3], 2, &g_ZigBeeStatus.panId); - if(ret != TW_RESULT_OK) - { - return ret; - } - ret = AsciiHexToValue(tokens[4], 8, &g_ZigBeeStatus.extPanId); - if(ret != TW_RESULT_OK) - { - return ret; - } - OC_LOG_V(INFO, TAG, - "TelNetworkInfoHandler(): PanId=%" PRId64 "", g_ZigBeeStatus.panId); - OC_LOG_V(INFO, TAG, - "TelNetworkInfoHandler(): ExtPanId=%" PRId64 "", g_ZigBeeStatus.extPanId); - - OC_LOG_V(INFO, TAG, "TelNetworkInfoHandler(): PanId=%s", tokens[3]); - OC_LOG_V(INFO, TAG, "TelNetworkInfoHandler(): ExtPanId=%s", tokens[4]); - - OC_LOG_V(INFO, TAG, "TelNetworkInfoHandler set ExtPanId to %08X%08X", - (unsigned int)(g_ZigBeeStatus.extPanId >> 32), - (unsigned int)(g_ZigBeeStatus.extPanId & 0xFFFFFFFF)); - - ret = TW_RESULT_HAS_LOCAL_PAN; + ret = HandleATResponse(entry); } - OC_LOG_V(INFO, TAG, "Leave TelNetworkInfoHandler()"); + OC_LOG_V(INFO, TAG, "Leave processEntrySwitchDoorLockState() returns with ret=%d", ret); return ret; } -TWResultCode TelJpanHandler(int count, char* tokens[]) +TWResultCode processEntryZCLDefaultResponse(TWEntry* entry) { - //Ask: AT+EN:[],[],[] - //Response: JPAN:,, - - OC_LOG_V(INFO, TAG, "Enter TelJpanHandler()."); - if(!tokens || count <= 2) - { - return TW_RESULT_ERROR_INVALID_PARAMS; - } - (void)count; + OC_LOG_V(INFO, TAG, "Enter processEntryZCLDefaultResponse()"); TWResultCode ret = TW_RESULT_UNKNOWN; - ret = AsciiHexToValue(tokens[1], 2, &g_ZigBeeStatus.panId); - if(ret != TW_RESULT_OK) + if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0) { - return ret; + if (strcmp(entry->atErrorCode, AT_STR_ERROR_MESSAGE_NOT_SENT_TO_TARGET_SUCCESSFULLY) == 0) + { + OC_LOG_V(ERROR, TAG, "Send to the target not succeed."); + ret = TW_RESULT_ERROR; + } + else + { + OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode); + ret = TW_RESULT_ERROR; + } } - ret = AsciiHexToValue(tokens[2], 8, &g_ZigBeeStatus.extPanId); - if(ret != TW_RESULT_OK) + else { - return ret; + ret = HandleATResponse(entry); } - OC_LOG_V(INFO, TAG, "PanId = %" PRId64 "", g_ZigBeeStatus.panId); - OC_LOG_V(INFO, TAG, "ExtPanId = %" PRId64 "", g_ZigBeeStatus.extPanId); - ret = TW_RESULT_NEW_LOCAL_PAN_ESTABLISHED; - OC_LOG_V(INFO, TAG, "Leave TelJpanHandler()."); + OC_LOG_V(INFO, TAG, "Leave processEntryZCLDefaultResponse() returns with ret=%d", ret); return ret; } -TWResultCode TelEndDeviceJoinHandler(int count, char* tokens[]) +TWResultCode processEntryZoneEnrollRequest(TWEntry* entry) { - //Ask: AT+PJOIN - // - //Prompt: RFD:, - //Prompt: FFD:, - //Prompt: SED:, - //Prompt: ZED:, - - OC_LOG_V(INFO, TAG, "Enter TelEndDeviceJoinHandler()."); - if(!tokens || count <= 1) - { - return TW_RESULT_ERROR_INVALID_PARAMS; - } - (void)count; + OC_LOG_V(INFO, TAG, "Enter processEntryZoneEnrollRequest()"); TWResultCode ret = TW_RESULT_UNKNOWN; - - //TODO: Might need to add into the list if needed - log it for now. - OC_LOG_V(INFO, TAG, "Just Joined - EUI:%s; NodeID:%s.", tokens[0], tokens[1]); - - ret = TW_RESULT_OK; - - OC_LOG_V(INFO, TAG, "Leave TelEndDeviceJoinHandler()."); - return ret; -} - -TWResultCode TelMatchDescHandler(int count, char* tokens[]) -{ - //Prompt: MatchDesc:0B4A,00,01 - - OC_LOG_V(INFO, TAG, "Enter TelMatchDescHandler()."); - if(!tokens || count <= 2) - { - return TW_RESULT_ERROR_INVALID_PARAMS; - } - (void)count; - - TWResultCode ret = TW_RESULT_ERROR; - - if (strcmp(tokens[1], AT_STR_ERROR_OK) != 0) + if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0) { - OC_LOG_V(ERROR, TAG, "MatchDesc prompt contained error status."); + OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode); + ret = TW_RESULT_ERROR; } else { - //Create TWDevice - TWDevice* device = (TWDevice*)OICCalloc(1, sizeof(TWDevice)); - if (device == NULL) - { - ret = TW_RESULT_ERROR_NO_MEMORY; - } - else - { - device->endpointOfInterest = (TWEndpoint*)OICCalloc(1, sizeof(TWEndpoint)); - if (device->endpointOfInterest == NULL) - { - OICFree(device); - ret = TW_RESULT_ERROR_NO_MEMORY; - } - else - { - //OICStrcpy(device->eui, SIZE_EUI, remoteEUI); - OICStrcpy(device->nodeId, SIZE_NODEID, tokens[0]); - OICStrcpy(device->endpointOfInterest->endpointId, SIZE_ENDPOINTID, tokens[2]); - - if (g_FoundMatchedDeviceList == NULL) - { - //Create a list of promptCount entries - g_FoundMatchedDeviceList = (TWDeviceList*)OICMalloc(sizeof(TWDeviceList)); - if (g_FoundMatchedDeviceList == NULL) - { - OICFree(device->endpointOfInterest); - OICFree(device); - ret = TW_RESULT_ERROR_NO_MEMORY; - } - else - { - g_FoundMatchedDeviceList->count = 1; - g_FoundMatchedDeviceList->deviceList = - (TWDevice*)OICMalloc(sizeof(TWDevice)); - if (g_FoundMatchedDeviceList->deviceList == NULL) - { - OICFree(device->endpointOfInterest); - OICFree(device); - ret = TW_RESULT_ERROR_NO_MEMORY; - } - else - { - memcpy(g_FoundMatchedDeviceList->deviceList, - device, - sizeof(TWDevice)); - ret = TW_RESULT_OK; - } - } - } - else - { - //Expand the list - int newSize = sizeof(TWDevice) * (g_FoundMatchedDeviceList->count + 1); - TWDevice* temp = (TWDevice*)realloc(g_FoundMatchedDeviceList->deviceList, - newSize); - if (temp == NULL) - { - OICFree(device->endpointOfInterest); - OICFree(device); - ret =TW_RESULT_ERROR_NO_MEMORY; - } - else - { - g_FoundMatchedDeviceList->deviceList = temp; - - //Add to the end of list - int count = g_FoundMatchedDeviceList->count; - memcpy(&g_FoundMatchedDeviceList->deviceList[count], - device, - sizeof(TWDevice)); - - //Increase the count - g_FoundMatchedDeviceList->count++; - - ret = TW_RESULT_OK; - } - } - } - } + ret = HandleATResponse(entry); } - OC_LOG_V(INFO, TAG, "Leave TelMatchDescHandler()."); + OC_LOG_V(INFO, TAG, "Leave processEntryZoneEnrollRequest() with ret=%d", ret); return ret; } -TWResultCode TelSimpleDescHandler(int count, char* tokens[]) +TWResultCode processEntryEnrolled(TWEntry* entry) { - //AT+SIMPLEDESC:3746,3746,01 - // SEQ:97 - // OK - // - // SimpleDesc:3746,00 <<<<<<<--------------------- - // EP:01 - // ProfileID:0104 - // DeviceID:0402v00 - // InCluster:0000,0001,0003,0402,0500,0020,0B05 - // OutCluster:0019 - // ACK:97 - - OC_LOG_V(INFO, TAG, "Enter TelSimpleDescHandler()."); - if(!tokens || count <= 1) - { - return TW_RESULT_ERROR_INVALID_PARAMS; - } - (void)count; + OC_LOG_V(INFO, TAG, "Enter processEntryEnrolled()"); TWResultCode ret = TW_RESULT_UNKNOWN; - - if (strcmp(tokens[1], AT_STR_ERROR_OK) != 0) + if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0) { - OC_LOG_V(ERROR, TAG, "SimpleDesc: prompt contained error status %s.", tokens[1]); + OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode); ret = TW_RESULT_ERROR; } else { - if (strcmp(tokens[0], g_WIPDevice->nodeId) == 0) - { - OC_LOG_V(INFO, TAG, "Got simple descriptor for nodeid %s", tokens[0]); - ret = TW_RESULT_OK; - } - else - { - OC_LOG_V(ERROR, TAG, - "Finding simple descriptor for non existing nodeid %s.", tokens[0]); - ret = TW_RESULT_ERROR; - } + ret = HandleATResponse(entry); } - OC_LOG_V(INFO, TAG, "Leave TelSimpleDescHandler()."); + OC_LOG_V(INFO, TAG, "Leave processEntryEnrolled() with ret=%d", ret); return ret; } -TWResultCode TelSimpleDescInClusterHandler(int count, char* tokens[]) +TWResultCode processEntryZoneStatus(TWEntry* entry) { - //AT+SIMPLEDESC:3746,3746,01 - // SEQ:97 - // OK - // - // SimpleDesc:3746,00 - // EP:01 - // ProfileID:0104 - // DeviceID:0402v00 - // InCluster:0000,0001,0003,0402,0500,0020,0B05 <<<<<<<<-------------- - // OutCluster:0019 - // ACK:97 - - OC_LOG_V(INFO, TAG, "Enter TelSimpleDescInClusterHandler()."); - TWResultCode ret = TW_RESULT_ERROR; + OC_LOG_V(INFO, TAG, "Enter processEntryZoneStatus()"); - //Add found clusters for the node. - if (g_WIPDevice->endpointOfInterest->clusterList == NULL) + TWResultCode ret = TW_RESULT_UNKNOWN; + if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0) { - g_WIPDevice->endpointOfInterest->clusterList = - (TWClusterList*)OICCalloc(sizeof(TWClusterList), 1); - if (g_WIPDevice->endpointOfInterest->clusterList == NULL) - { - ret = TW_RESULT_ERROR_NO_MEMORY; - } - else - { - g_WIPDevice->endpointOfInterest->clusterList->clusterIds = - (TWClusterId*)OICCalloc(sizeof(TWClusterId) * count, 1); - if (g_WIPDevice->endpointOfInterest->clusterList->clusterIds == NULL) - { - OICFree(g_WIPDevice->endpointOfInterest->clusterList); - ret = TW_RESULT_ERROR_NO_MEMORY; - } - else - { - int i = 0; - for (; i < count; i++) - { - OICStrcpy(g_WIPDevice->endpointOfInterest->clusterList-> - clusterIds[i].clusterId, - SIZE_CLUSTERID, - tokens[i]); - - OC_LOG_V(INFO, TAG, "ClusterIds[%d]=%s", - i, - g_WIPDevice->endpointOfInterest-> - clusterList->clusterIds[i].clusterId); - } - g_WIPDevice->endpointOfInterest->clusterList->count = count; - ret = TW_RESULT_OK; - } - } + OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode); + ret = TW_RESULT_ERROR; } else { - OC_LOG_V(ERROR, TAG, "Expected an empty cluster list."); + ret = HandleATResponse(entry); } - OC_LOG_V(INFO, TAG, "Leave TelSimpleDescInClusterHandler()."); + OC_LOG_V(INFO, TAG, "Leave processEntryZoneStatus() with ret=%d", ret); return ret; } -TWResultCode TelWriteAttrHandler(int count, char* tokens[]) +TWResultCode processEntryAddressResponse(TWEntry* entry) { - //AT+WRITEATR:3A3D,01,0,0003,0000,21,00 - // OK - // WRITEATTR:3A3D,01,0003,,00 - - OC_LOG_V(INFO, TAG, "Enter TelWriteAttrHandler()."); - if(!tokens || count <= 3) - { - return TW_RESULT_ERROR_INVALID_PARAMS; - } - (void)count; + OC_LOG_V(INFO, TAG, "Enter processEntryAddressResponse()"); TWResultCode ret = TW_RESULT_UNKNOWN; - - if (strcmp(tokens[3], AT_STR_ERROR_OK) == 0) + if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0) { - ret = TW_RESULT_OK; + OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode); + ret = TW_RESULT_ERROR; } else { - ret = TW_RESULT_ERROR; + ret = HandleATResponse(entry); } - OC_LOG_V(INFO, TAG, "Leave TelWriteAttrHandler()."); + OC_LOG_V(INFO, TAG, "Leave processEntryAddressResponse() with ret=%d", ret); return ret; } -TWResultCode TelReadAttrHandlerTemperature(int count, char* tokens[]) +TWResultCode Reset() { - //AT+READATR:F2D7,01,0,0402,0002 - // OK - // TEMPERATURE:F2D7,01,0002,00,1770 - // - //AT+READATR:F2D7,01,0,0402,0002 - // OK - // ERROR:66 - - OC_LOG_V(INFO, TAG, "Enter TelReadAttrHandlerTemperature()."); - if(!tokens || count <= 4) - { - return TW_RESULT_ERROR_INVALID_PARAMS; - } - (void)count; + OC_LOG_V(INFO, TAG, "Enter Reset()"); TWResultCode ret = TW_RESULT_ERROR; - - if (strcmp(tokens[3], AT_STR_ERROR_OK) != 0) + ret = TWIssueATCommand(g_plugin, AT_CMD_RESET); + if (ret == TW_RESULT_OK) { - OC_LOG_V(ERROR, TAG, "TEMPERATURE prompt contained error status."); + OC_LOG_V(INFO, TAG, "Write %s", AT_CMD_RESET); } else { - // AttrInfo is 16-bit value representing (100 * Degrees Celsius) - // so 0x812 = 20.66 C = 69.188 F - if (g_ZigBeeStatus.remoteAttributeValueRead != NULL) - { - OICFree(g_ZigBeeStatus.remoteAttributeValueRead); - } - OC_LOG_V(INFO, TAG, "Read Attribute Value: %s.", tokens[4]); - g_ZigBeeStatus.remoteAttributeValueRead = - (char*)OICMalloc(sizeof(char) * strlen(tokens[4])); - if (g_ZigBeeStatus.remoteAttributeValueRead == NULL) - { - ret = TW_RESULT_ERROR_NO_MEMORY; - } - else - { - strcpy(g_ZigBeeStatus.remoteAttributeValueRead, tokens[4]); - g_ZigBeeStatus.remoteAtrributeValueReadLength = strlen(tokens[4]); - ret = TW_RESULT_REMOTE_ATTR_HAS_VALUE; - } + OC_LOG_V(ERROR, TAG, "Write %s", AT_CMD_RESET); } - - OC_LOG_V(INFO, TAG, "Leave TelReadAttrHandlerTemperature()."); - + OC_LOG_V(INFO, TAG, "Leave Reset() with ret=%d", ret); return ret; } -TWResultCode TelReadAttrHandler(int count, char* tokens[]) +TWResultCode CreatePAN() { - //AT+READATR:F2D7,01,0,0402,0002 - // OK - // RESPATTR:,,,,, - // - //AT+READATR:F2D7,01,0,0402,0002 + /* + //at+n + // +N=NoPAN // OK - // ERROR:66 - OC_LOG_V(INFO, TAG, "Enter TelReadAttrHandler()."); - if(!tokens || count <= 5) - { - return TW_RESULT_ERROR_INVALID_PARAMS; - } - (void)count; + //at+n + // +N=COO,26,-6,7306,133F04EA669C6B24 + // OK - TWResultCode ret = TW_RESULT_ERROR; + //at+en + // OK + // JPAN:26,7306,133F04EA669C6B24 - if (strcmp(tokens[4], AT_STR_ERROR_OK) != 0) + //at+en + // ERROR:28 + */ + + OC_LOG_V(INFO, TAG, "Enter CreatePAN()"); + + TWResultCode twRet1 = TW_RESULT_UNKNOWN; + TWResultCode twRet2 = TW_RESULT_UNKNOWN; + TWResultCode ret = TW_RESULT_UNKNOWN; + ret = TWIssueATCommand(g_plugin, AT_CMD_GET_NETWORK_INFO); + if (ret != TW_RESULT_OK) { - OC_LOG_V(ERROR, TAG, "READATTR prompt contained error status."); + OC_LOG_V(ERROR, TAG, "Write %s", AT_CMD_GET_NETWORK_INFO); + goto exit; + } + OC_LOG_V(INFO, TAG, "Write %s", AT_CMD_GET_NETWORK_INFO); + TWEntry* entry = NULL; + TWEntry* entry2 = NULL; + ret = TWDequeueEntry(g_plugin, &entry, TW_NETWORK_INFO); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "TWDequeueEntry - %s", AT_CMD_GET_NETWORK_INFO); + goto exit; + } + if (entry == NULL) + { + OC_LOG_V(ERROR, TAG, "TWEntry is NULL - %s", AT_CMD_GET_NETWORK_INFO); + ret = TW_RESULT_ERROR; + goto exit; + } + ret = processEntry(entry); + if (ret == TW_RESULT_HAS_LOCAL_PAN) + { + OC_LOG_V(INFO, TAG, "Has local PAN."); + ret = TW_RESULT_OK; + } + else if (ret == TW_RESULT_NO_LOCAL_PAN) + { + OC_LOG_V(INFO, TAG, "Has no local PAN."); + ret = TWIssueATCommand(g_plugin, AT_CMD_ESTABLISH_NETWORK); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "Write %s", AT_CMD_ESTABLISH_NETWORK); + goto exit; + } + OC_LOG_V(INFO, TAG, "Write %s", AT_CMD_ESTABLISH_NETWORK); + + ret = TWDequeueEntry(g_plugin, &entry2, TW_JPAN); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "TWDequeueEntry - %s", AT_CMD_ESTABLISH_NETWORK); + goto exit; + } + if (entry2 == NULL) + { + OC_LOG_V(ERROR, TAG, "TWEntry is NULL - %s", AT_CMD_ESTABLISH_NETWORK); + ret = TW_RESULT_ERROR; + goto exit; + } + ret = processEntry(entry2); + if (ret == TW_RESULT_OK) + { + OC_LOG_V(INFO, TAG, "processEntry - %s", AT_CMD_ESTABLISH_NETWORK); + g_ZigBeeStatus.state = ZB_STATE_INIT; + ret = TW_RESULT_OK; + } + else + { + OC_LOG_V(ERROR, TAG, "processEntry - %s", AT_CMD_ESTABLISH_NETWORK); + ret = TW_RESULT_ERROR; + } } else { - if (g_ZigBeeStatus.remoteAttributeValueRead != NULL) + OC_LOG_V(ERROR, TAG, "processEntry - unexpected return code: %d", ret); + ret = TW_RESULT_ERROR; + } + +exit: + if (entry) + { + twRet1 = TWDeleteEntry(g_plugin, entry); + if(twRet1 != TW_RESULT_OK) { - OICFree(g_ZigBeeStatus.remoteAttributeValueRead); + OC_LOG_V(ERROR, TAG, "TWDeleteEntry 1 - ret=%d", twRet1); } - OC_LOG_V(INFO, TAG, "Read Attribute Value: %s.", tokens[5]); - g_ZigBeeStatus.remoteAttributeValueRead = - (char*)OICMalloc(sizeof(char) * strlen(tokens[5])); - if (g_ZigBeeStatus.remoteAttributeValueRead != NULL) + } + if (entry2) + { + twRet2 = TWDeleteEntry(g_plugin, entry2); + if(twRet2 != TW_RESULT_OK) { - strcpy(g_ZigBeeStatus.remoteAttributeValueRead, tokens[5]); - g_ZigBeeStatus.remoteAtrributeValueReadLength = strlen(tokens[5]); - ret = TW_RESULT_REMOTE_ATTR_HAS_VALUE; + OC_LOG_V(ERROR, TAG, "TWDeleteEntry 2 - ret=%d", twRet2); } } - OC_LOG_V(INFO, TAG, "Leave TelReadAttrHandler()."); + OC_LOG_V(INFO, TAG, "Leave CreatePan with ret=%d", ret); + return ret; +} +TWResultCode EnableJoin(bool isKeyEncrypted) +{ + //Ask: AT+PJOIN + //Response: OK + + //Ask: AT+PJOIN + //Response: ERROR:70 + + (void)isKeyEncrypted; + isKeyEncrypted = false; //TODO: for now - don't encrypt + + TWResultCode ret = TW_RESULT_ERROR; + char* joinTimeHex = "0F"; //TODO: for now - 15 seconds + char* broadcast = "FFFC"; + + int size = strlen(AT_CMD_PERMIT_JOIN) + strlen(joinTimeHex) + + SEPARATOR_LENGTH + strlen(broadcast) + 1; + char* cmdString = (char*)OICMalloc(size * sizeof(char)); + if (cmdString == NULL) + { + OC_LOG_V(ERROR, TAG, "No Memory"); + ret = TW_RESULT_ERROR_NO_MEMORY; + goto exit; + } + snprintf(cmdString, size, "%s%s%s%s", + AT_CMD_PERMIT_JOIN, joinTimeHex, SEPARATOR, broadcast); + ret = TWIssueATCommand(g_plugin, cmdString); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "Write %s", cmdString); + ret = TW_RESULT_ERROR; + goto exit; + } + OC_LOG_V(INFO, TAG, "Write %s", cmdString); + + sleep(15); //must sleep here to permit joining for 15 seconds + +exit: + OICFree(cmdString); + OC_LOG_V(INFO, TAG, "Leave EnableJoin() with ret=%d", ret); return ret; } -TWResultCode TelZCLDefaultResponseHandler(int count, char* tokens[]) +TWResultCode FindMatchNodes() { - //AT+RONOFF:
,,[,] - // DFTREP:,,,, + //AT+MATCHREQ:0104,03,0003,0006,0402,00 + // OK + // MatchDesc:0B4A,00,01 + + //AT+MATCHREQ:0104,03,0999,0999,0999,00 + // OK + + OC_LOG_V(INFO, TAG, "Enter FindMatchNodes()"); + + TWResultCode ret = TW_RESULT_UNKNOWN; + + char* profileHomeAutomation = "0104"; + char* inClusterCount = "04"; + char* outClusterCount = "00"; + + //TODO: add more clusters + char* clusterIdentify = "0003"; + char* clusterOnOff = "0006"; + char* clusterTemperatureMeasurement = "0402"; + char* clusterIASZone = "0500"; + + int size = strlen(AT_CMD_MATCH_REQUEST) + strlen(profileHomeAutomation) + + SEPARATOR_LENGTH + strlen(inClusterCount) + + SEPARATOR_LENGTH + strlen(clusterIdentify) + + SEPARATOR_LENGTH + strlen(clusterOnOff) + + SEPARATOR_LENGTH + strlen(clusterTemperatureMeasurement) + + SEPARATOR_LENGTH + strlen(clusterIASZone) + + SEPARATOR_LENGTH + strlen(outClusterCount) + 1; + + char* cmdString = (char*)OICMalloc(size * sizeof(char)); + if (cmdString == NULL) + { + OC_LOG_V(INFO, TAG, "No Memory"); + ret = TW_RESULT_ERROR_NO_MEMORY; + goto exit; + } + + int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + AT_CMD_MATCH_REQUEST, profileHomeAutomation, + SEPARATOR, inClusterCount, + SEPARATOR, clusterIdentify, + SEPARATOR, clusterOnOff, + SEPARATOR, clusterTemperatureMeasurement, + SEPARATOR, clusterIASZone, + SEPARATOR, outClusterCount); + if(stringRet <= 0) + { + OC_LOG_V(ERROR, TAG, "Build command error."); + ret = OC_STACK_ERROR; + goto exit; + } + ret = TWIssueATCommand(g_plugin, cmdString); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "Write %s.", cmdString); + goto exit; + } + OC_LOG_V(INFO, TAG, "Write %s.", cmdString); + +exit: + OICFree(cmdString); + OC_LOG_V(INFO, TAG, "Leave FindMatchNodes() with ret=%d", ret); + return ret; +} + +TWResultCode FindClusters(char nodeId[], char endpoint[]) +{ + /* + //AT+SIMPLEDESC:3746,3746,01 + // SEQ:97 + // OK // - //AT+DRLOCK:
,,, - // DFTREP:,,,, + // SimpleDesc:3746,00 + // EP:01 + // ProfileID:0104 + // DeviceID:0402v00 + // InCluster:0000,0001,0003,0402,0500,0020,0B05 + // OutCluster:0019 // - //AT+LCMVTOLEV:
,,,,, - // DFTREP:,,,, + // ACK:97 + */ + + OC_LOG_V(INFO, TAG, "Enter FindClusters()"); + + TWResultCode ret = TW_RESULT_UNKNOWN; - OC_LOG_V(INFO, TAG, "Enter TelZCLDefaultResponseHandler()."); - if(!tokens || count <= 4) + int size = strlen(AT_CMD_SIMPLE_DESC) + strlen(nodeId) + + SEPARATOR_LENGTH + strlen(nodeId) + + SEPARATOR_LENGTH + strlen(endpoint) + 1; + + char* cmdString = (char*)OICMalloc(size * sizeof(char)); + if (cmdString == NULL) { - return TW_RESULT_ERROR_INVALID_PARAMS; + OC_LOG_V(ERROR, TAG, "No Memory"); + ret = TW_RESULT_ERROR_NO_MEMORY; + goto exit; } - (void)count; + int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s", + AT_CMD_SIMPLE_DESC, nodeId, + SEPARATOR, nodeId, + SEPARATOR, endpoint); + if(stringRet <= 0) + { + OC_LOG_V(ERROR, TAG, "Build command error."); + ret = OC_STACK_ERROR; + goto exit; + } + ret = TWIssueATCommand(g_plugin, cmdString); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "Write %s", cmdString); + ret = TW_RESULT_ERROR; + goto exit; + } + OC_LOG_V(INFO, TAG, "Write %s", cmdString); + + TWEntry* entry = NULL; + ret = TWDequeueEntry(g_plugin, &entry, TW_SIMPLEDESC); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "TWDequeueEntry - %s", cmdString); + goto exit; + } + if (entry == NULL) + { + OC_LOG_V(ERROR, TAG, "TWEntry is NULL - %s", cmdString); + ret = TW_RESULT_ERROR; + goto exit; + } + + ret = processEntry(entry); + if (ret == TW_RESULT_OK) + { + OC_LOG_V(INFO, TAG, "processEntry - %s", cmdString); + } + else + { + OC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString); + } + +exit: + TWDeleteEntry(g_plugin, entry); + OICFree(cmdString); + OC_LOG_V(INFO, TAG, "Leave FindClusters() with ret=%d", ret); + return ret; +} + +TWResultCode GetRemoteEUI(char *nodeId, char* outRemoteEUI) +{ + //AT+EUIREQ:< Address>,[,XX] + // AddrResp:[,,] + // AddrResp:00,15ED,000D6F00040574B8 + + OC_LOG_V(INFO, TAG, "Enter GetRemoteEUI()"); TWResultCode ret = TW_RESULT_UNKNOWN; - OC_LOG_V(INFO, TAG, - "DFTREP prompt succeed for NodeId:%s, EP:%s, ClusterId:%s, CMD:%s.", - tokens[0], tokens[1], tokens[2], tokens[3]); + int size = strlen(AT_CMD_REMOTE_EUI_REQUEST) + strlen(nodeId) + + SEPARATOR_LENGTH + strlen(nodeId) + 1; + char* cmdString = (char*)OICMalloc(size * sizeof(char)); + if (cmdString == NULL) + { + OC_LOG_V(ERROR, TAG, "No Memory"); + ret = TW_RESULT_ERROR_NO_MEMORY; + goto exit; + } - if (strcmp(tokens[4], AT_STR_ERROR_OK) != 0) + int stringRet = snprintf(cmdString, size, "%s%s%s%s", + AT_CMD_REMOTE_EUI_REQUEST, nodeId, + SEPARATOR, nodeId); + if(stringRet <= 0) { + OC_LOG_V(ERROR, TAG, "Build command error."); + ret = OC_STACK_ERROR; + goto exit; + } + ret = TWIssueATCommand(g_plugin, cmdString); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "Write %s", cmdString); ret = TW_RESULT_ERROR; + goto exit; } - else + OC_LOG_V(INFO, TAG, "Write %s", cmdString); + + TWEntry* entry = NULL; + ret = TWDequeueEntry(g_plugin, &entry, TW_ADDRESS_RESPONSE); + if (ret != TW_RESULT_OK) { - ret = TW_RESULT_OK; + OC_LOG_V(ERROR, TAG, "TWDequeueEntry - %s", cmdString); + ret = TW_RESULT_ERROR; + goto exit; + } + if (entry == NULL) + { + OC_LOG_V(ERROR, TAG, "TWEntry is NULL - %s", cmdString); + ret = TW_RESULT_ERROR; + goto exit; } - OC_LOG_V(INFO, TAG, "Leave TelZCLDefaultResponseHandler()."); + ret = processEntry(entry); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString); + ret = TW_RESULT_ERROR; + goto exit; + } + OC_LOG_V(INFO, TAG, "Wanted eui of NodeID=%s ", nodeId); + OC_LOG_V(INFO, TAG, "Received eui of g_WIPRemoteNodeId=%s ", g_WIPRemoteNodeId); + if (strcmp(nodeId, g_WIPRemoteNodeId) != 0) + { + OC_LOG_V(ERROR, TAG, "Received eui for an unexpected remote node id."); + ret = TW_RESULT_ERROR; + goto exit; + } + + OC_LOG_V(INFO, TAG, "Remote NodeId:%s has EUI: %s \n", + g_WIPRemoteNodeId, g_WIPRemoteEUI); + OICStrcpy(outRemoteEUI, SIZE_EUI, g_WIPRemoteEUI); + + ret = TW_RESULT_OK; +exit: + memset(g_WIPRemoteEUI, '\0', SIZE_EUI); + memset(g_WIPRemoteNodeId, '\0', SIZE_NODEID); + TWDeleteEntry(g_plugin, entry); + OICFree(cmdString); + OC_LOG_V(INFO, TAG, "Leave GetRemoteEUI() with ret=%d", ret); return ret; } -TWResultCode TelSwitchDoorLockStateHandler(int count, char* tokens[]) +TWResultCode HandleATResponse(TWEntry* entry) { - //AT+DRLOCK:
,,, - // DRLOCRSP:,, - // or - // DRUNLOCKRSP:,, + OC_LOG_V(INFO, TAG, "Enter HandleATResponse()"); + + TWResultCode ret = TW_RESULT_ERROR; - OC_LOG_V(INFO, TAG, "Enter TelSwitchDoorLockStateHandler()."); - if(!tokens || count <= 4) + int32_t i = 0; + for (; i < entry->count; i++) { - return TW_RESULT_ERROR_INVALID_PARAMS; + uint32_t k = 0; + for (; k < sizeof(g_TWATResultHandlerPairArray)/sizeof(TWATResultHandlerPair); ++k) + { + const char* line = (entry)->lines[i].line; + if (strncmp(line, + g_TWATResultHandlerPairArray[k].resultTxt, + strlen(g_TWATResultHandlerPairArray[k].resultTxt) + ) == 0) + { + char* tokens[ARRAY_LENGTH] = {}; + const char* delimiters = ",\r\n"; + int paramCount = Tokenize((entry)->lines[i].line + + strlen(g_TWATResultHandlerPairArray[k].resultTxt), + delimiters, tokens); + if (paramCount > 0) + { + ret = g_TWATResultHandlerPairArray[k].handler(paramCount, tokens); + } + + int n = 0; + for (; n < paramCount; n++) + { + OICFree(tokens[n]); + } + + break; + } + } } - (void)count; + + OC_LOG_V(INFO, TAG, "Leave HandleATResponse() with ret=%d", ret); + return ret; +} + +//----------------------------------------------------------------------------- +// Internal functions - AT Response/Prompt Handlers +//----------------------------------------------------------------------------- + +TWResultCode TelAddressResponseHandler(int count, char* tokens[]) +{ + //AT+EUIREQ:< Address>,[,XX] + // AddrResp:[,,] + // AddrResp:00,15ED,000D6F00040574B8 + + OC_LOG_V(INFO, TAG, "Enter TelAddressResponseHandler()"); TWResultCode ret = TW_RESULT_UNKNOWN; - if (strcmp(tokens[2], AT_STR_ERROR_OK) != 0) + + if(!tokens || count != RESPONSE_PARAMS_COUNT_ADDRESS_RESPONSE) { - OC_LOG_V(ERROR, TAG, - "DRLOCRSP/DRUNLOCKRSP prompt contained error status %s.", tokens[4]); - ret = TW_RESULT_ERROR; + ret = TW_RESULT_ERROR_INVALID_PARAMS; } else { - OC_LOG_V(INFO, TAG, "DRLOCRSP/DRUNLOCKRSP prompt succeed for nodeId:%s, ep:%s.", - tokens[0], tokens[1]); - ret = TW_RESULT_OK; + if (strcmp(tokens[0], AT_STR_ERROR_OK) != 0) + { + OC_LOG_V(ERROR, TAG, "AddrResp prompt contained error status."); + ret = TW_RESULT_ERROR; + } + else + { + OICStrcpy(g_WIPRemoteNodeId, SIZE_NODEID, tokens[1]); + OICStrcpy(g_WIPRemoteEUI, SIZE_EUI, tokens[2]); + OC_LOG_V(INFO, TAG, "Received eui %s for g_WIPRemoteNodeId=%s ", + g_WIPRemoteEUI, + g_WIPRemoteNodeId); + ret = TW_RESULT_OK; + } + } + + OC_LOG_V(INFO, TAG, "Leave TelAddressResponseHandler() with ret=%d", ret); + return ret; +} + +TWResultCode TelNetworkInfoHandler(int count, char* tokens[]) +{ + // Ask: AT+N + // Response: +N=COO,24,-6,9726,12BB200F073AB573 + // or + // +N=NoPAN + // + // +N=,,,, + + OC_LOG_V(INFO, TAG, "Enter TelNetworkInfoHandler()"); + + TWResultCode ret = TW_RESULT_UNKNOWN; + + if(!tokens || + ((count != RESPONSE_PARAMS_COUNT_NETWORK_INFO_1) && + (count != RESPONSE_PARAMS_COUNT_NETWORK_INFO_5))) + { + ret = TW_RESULT_ERROR_INVALID_PARAMS; + goto exit; + } + + int i = 0; + for (; i < count; ++i) + { + if (tokens[i] != NULL) + { + OC_LOG_V(INFO, TAG, "Token[%d] = %s", i, tokens[i]); + } + } + + char* temp = tokens[0]; + if (strcmp(temp, "NoPAN") == 0) + { + OC_LOG_V(INFO, TAG, "It is NoPan."); + ret = TW_RESULT_NO_LOCAL_PAN; + goto exit; + } + + OC_LOG_V(INFO, TAG, "Already have an established network."); + ret = AsciiHexToValue(tokens[3], strlen(tokens[3]), &g_ZigBeeStatus.panId); + if(ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "AsciiHexToValue - panId"); + goto exit; + } + ret = AsciiHexToValue(tokens[4], strlen(tokens[4]), &g_ZigBeeStatus.extPanId); + if(ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "AsciiHexToValue - extPanId"); + goto exit; } + OC_LOG_V(INFO, TAG, "PanId=%" PRId64 , g_ZigBeeStatus.panId); + OC_LOG_V(INFO, TAG, "ExtPanId=%" PRId64 , g_ZigBeeStatus.extPanId); + OC_LOG_V(INFO, TAG, "PanId=%s", tokens[3]); + OC_LOG_V(INFO, TAG, "ExtPanId=%s", tokens[4]); - OC_LOG_V(INFO, TAG, "Leave TelSwitchDoorLockStateHandler()."); + OC_LOG_V(INFO, TAG, "TelNetworkInfoHandler set ExtPanId to %08X%08X", + (unsigned int)(g_ZigBeeStatus.extPanId >> 32), + (unsigned int)(g_ZigBeeStatus.extPanId & 0xFFFFFFFF)); + ret = TW_RESULT_HAS_LOCAL_PAN; + +exit: + OC_LOG_V(INFO, TAG, "Leave TelNetworkInfoHandler() with ret=%d", ret); return ret; } -TWResultCode TelZoneEnrollRequestHandler(int count, char* tokens[]) +TWResultCode TelJpanHandler(int count, char* tokens[]) { - //ZENROLLREQ:,,, + //Ask: AT+EN:[],[],[] + //Response: JPAN:,, - OC_LOG_V(INFO, TAG, "Enter TelZoneEnrollRequestHandler()."); - if(!tokens || count <= 3) + OC_LOG_V(INFO, TAG, "Enter TelJpanHandler()"); + + TWResultCode ret = TW_RESULT_UNKNOWN; + + if(!tokens || count != RESPONSE_PARAMS_COUNT_JPAN) { - return TW_RESULT_ERROR_INVALID_PARAMS; + ret = TW_RESULT_ERROR_INVALID_PARAMS; + goto exit; } - (void)count; - TWResultCode ret = TW_RESULT_OK; + ret = AsciiHexToValue(tokens[1], strlen(tokens[1]), &g_ZigBeeStatus.panId); + if(ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "AsciiHexToValue - panId"); + goto exit; + } + ret = AsciiHexToValue(tokens[2], strlen(tokens[2]), &g_ZigBeeStatus.extPanId); + if(ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "AsciiHexToValue - extPanId"); + goto exit; + } + OC_LOG_V(INFO, TAG, "PanId = %" PRId64 "\n", g_ZigBeeStatus.panId); + OC_LOG_V(INFO, TAG, "ExtPanId = %" PRId64 "\n", g_ZigBeeStatus.extPanId); + ret = TW_RESULT_NEW_LOCAL_PAN_ESTABLISHED; - OC_LOG_V(INFO, TAG, "Received zone request from:"); - OC_LOG_V(INFO, TAG, "Node:%s", tokens[0]); - OC_LOG_V(INFO, TAG, "EP:%s", tokens[1]); - OC_LOG_V(INFO, TAG, "ZoneType:%s", tokens[2]); - OC_LOG_V(INFO, TAG, "ManufactureCode:%s", tokens[3]); +exit: + OC_LOG_V(INFO, TAG, "Leave TelJpanHandler() with ret=%d", ret); + return ret; +} + +TWResultCode TelEndDeviceJoinHandler(int count, char* tokens[]) +{ + //Ask: AT+PJOIN + // + //Prompt: RFD:, + //Prompt: FFD:, + //Prompt: SED:, + //Prompt: ZED:, + + OC_LOG_V(INFO, TAG, "Enter TelEndDeviceJoinHandler()"); + TWResultCode ret = TW_RESULT_UNKNOWN; + + if(!tokens || count != RESPONSE_PARAMS_COUNT_DEVICE_JOINED) + { + ret = TW_RESULT_ERROR_INVALID_PARAMS; + goto exit; + } + + //TODO: Might need to add into the list if needed - log it for now. + OC_LOG_V(INFO, TAG, "Just Joined - EUI:%s; NodeID:%s.\n", tokens[0], tokens[1]); + ret = TW_RESULT_OK; + +exit: + OC_LOG_V(INFO, TAG, "Leave TelEndDeviceJoinHandler() with ret=%d", ret); + return ret; +} + +TWResultCode TelMatchDescHandler(int count, char* tokens[]) +{ + //Prompt: MatchDesc:0B4A,00,01 + + OC_LOG_V(INFO, TAG, "Enter TelMatchDescHandler()"); + TWResultCode ret = TW_RESULT_ERROR; + + if(!tokens || count != RESPONSE_PARAMS_COUNT_MATCH_DESC) + { + ret = TW_RESULT_ERROR_INVALID_PARAMS; + goto exit; + } + + if (strcmp(tokens[1], AT_STR_ERROR_OK) != 0) + { + OC_LOG_V(INFO, TAG, "MatchDesc prompt contained error status."); + ret = TW_RESULT_ERROR; + goto exit; + } + else + { + char remoteEUI[SIZE_EUI]; + ret = GetRemoteEUI(tokens[0], remoteEUI); + if (ret != TW_RESULT_OK) + { + OC_LOG_V(ERROR, TAG, "GetRemoteEUI()"); + goto exit; + } + else + { + //Step 1: Create TWDevice + TWDevice* device = (TWDevice*)OICCalloc(1, sizeof(TWDevice)); + if (device == NULL) + { + ret = TW_RESULT_ERROR_NO_MEMORY; + goto exit; + } + else + { + device->endpointOfInterest = (TWEndpoint*)OICCalloc(1, sizeof(TWEndpoint)); + if (device->endpointOfInterest == NULL) + { + OICFree(device); + ret = TW_RESULT_ERROR_NO_MEMORY; + } + else + { + OICStrcpy(device->eui, SIZE_EUI, remoteEUI); + OICStrcpy(device->nodeId, SIZE_NODEID, tokens[0]); + OICStrcpy(device->endpointOfInterest->endpointId, SIZE_ENDPOINTID, tokens[2]); + g_WIPDevice = device; + + //Step 2: Add to list + if (g_FoundMatchedDeviceList == NULL) + { + //Create a list of promptCount entries + g_FoundMatchedDeviceList = (TWDeviceList*)OICMalloc(sizeof(TWDeviceList)); + if (g_FoundMatchedDeviceList == NULL) + { + OICFree(device->endpointOfInterest); + OICFree(device); + ret = TW_RESULT_ERROR_NO_MEMORY; + } + else + { + g_FoundMatchedDeviceList->count = 1; + g_FoundMatchedDeviceList->deviceList = + (TWDevice*)OICMalloc(sizeof(TWDevice)); + if (g_FoundMatchedDeviceList->deviceList == NULL) + { + OICFree(device->endpointOfInterest); + OICFree(device); + ret = TW_RESULT_ERROR_NO_MEMORY; + } + else + { + memcpy(g_FoundMatchedDeviceList->deviceList, + device, + sizeof(TWDevice)); + ret = TW_RESULT_OK; + } + } + } + else + { + //Expand the list + int newSize = sizeof(TWDevice) * (g_FoundMatchedDeviceList->count + 1); + TWDevice* temp = (TWDevice*)realloc(g_FoundMatchedDeviceList->deviceList, + newSize); + if (temp == NULL) + { + OICFree(device->endpointOfInterest); + OICFree(device); + ret =TW_RESULT_ERROR_NO_MEMORY; + } + else + { + g_FoundMatchedDeviceList->deviceList = temp; + + //Add to the end of list + int count = g_FoundMatchedDeviceList->count; + memcpy(&g_FoundMatchedDeviceList->deviceList[count], + device, + sizeof(TWDevice)); - OC_LOG_V(INFO, TAG, "Leave TelZoneEnrollRequestHandler()."); + //Increase the count + g_FoundMatchedDeviceList->count++; - return ret; + ret = TW_RESULT_OK; + } + } + } + } + } + } +exit: + OC_LOG_V(INFO, TAG, "Leave TelMatchDescHandler() with ret=%d", ret); + return ret; } -TWResultCode TelEnrolledHandler(int count, char* tokens[]) +TWResultCode TelSimpleDescHandler(int count, char* tokens[]) { - //ENROLLED:,, + //AT+SIMPLEDESC:3746,3746,01 + // SEQ:97 + // OK + // + // SimpleDesc:3746,00 <<<<<<<--------------------- + // EP:01 + // ProfileID:0104 + // DeviceID:0402v00 + // InCluster:0000,0001,0003,0402,0500,0020,0B05 + // OutCluster:0019 + // ACK:97 + + OC_LOG_V(INFO, TAG, "Enter TelSimpleDescHandler()."); + TWResultCode ret = TW_RESULT_UNKNOWN; - OC_LOG_V(INFO, TAG, "Enter TelEnrolledHandler()."); - if(!tokens || count <= 2) + if(!tokens || count != RESPONSE_PARAMS_COUNT_SIMPLE_DESC) { - return TW_RESULT_ERROR_INVALID_PARAMS; + ret = TW_RESULT_ERROR_INVALID_PARAMS; + goto exit; } - (void)count; - - TWResultCode ret = TW_RESULT_OK; - OC_LOG_V(INFO, TAG, "Received zone request from:"); - OC_LOG_V(INFO, TAG, "ZID:%s", tokens[0]); - OC_LOG_V(INFO, TAG, "ZoneType:%s", tokens[1]); - OC_LOG_V(INFO, TAG, "EUI:%s", tokens[2]); - - TWEnrollee enrollee; - OICStrcpy(enrollee.zoneId, SIZE_ZONEID, tokens[0]); - OICStrcpy(enrollee.zoneType, SIZE_ZONETYPE, tokens[1]); - OICStrcpy(enrollee.eui, SIZE_EUI, tokens[2]); - - if (g_EnrollmentSucceedCallback != NULL) + if (g_WIPDevice == NULL) { - g_EnrollmentSucceedCallback(&enrollee); + OC_LOG_V(ERROR, TAG, + "Receive simple descriptor unexpectedly - %s", tokens[0]); + ret = TW_RESULT_ERROR; + goto exit; } - OC_LOG_V(INFO, TAG, "Leave TelEnrolledHandler()."); + if (strcmp(tokens[1], AT_STR_ERROR_OK) != 0) + { + OC_LOG_V(ERROR, TAG, "SimpleDesc: prompt contained error status %s.", tokens[1]); + ret = TW_RESULT_ERROR; + } + else + { + if (strcmp(tokens[0], g_WIPDevice->nodeId) == 0) + { + OC_LOG_V(INFO, TAG, "Got simple descriptor for nodeid %s", tokens[0]); + ret = TW_RESULT_OK; + } + else + { + OC_LOG_V(ERROR, TAG, + "Finding simple descriptor for non existing nodeid %s.", tokens[0]); + ret = TW_RESULT_ERROR; + } + } +exit: + OC_LOG_V(INFO, TAG, "Leave TelSimpleDescHandler() with ret=%d", ret); return ret; } -TWResultCode TelZoneStatusHandler(int count, char* tokens[]) +TWResultCode TelSimpleDescInClusterHandler(int count, char* tokens[]) { - //ZONESTATUS:,,,[,,] - //ZONESTATUS:5FBA,01,0021,00,01,00AF + //AT+SIMPLEDESC:3746,3746,01 + // SEQ:97 + // OK + // + // SimpleDesc:3746,00 + // EP:01 + // ProfileID:0104 + // DeviceID:0402v00 + // InCluster:0000,0001,0003,0402,0500,0020,0B05 <<<<<<<<-------------- + // OutCluster:0019 + // ACK:97 + + OC_LOG_V(INFO, TAG, "Enter TelSimpleDescInClusterHandler()"); + TWResultCode ret = TW_RESULT_ERROR; - OC_LOG_V(INFO, TAG, "Enter TelZoneStatusHandler()."); - if(!tokens || count <= 3) + if (!tokens || count < RESPONSE_PARAMS_COUNT_SIMPLE_DESC_IN_CLUSTER_MIN ) { - return TW_RESULT_ERROR_INVALID_PARAMS; + OC_LOG_V(ERROR, TAG, "Invalid Params"); + ret = TW_RESULT_ERROR_INVALID_PARAMS; + goto exit; } - TWResultCode ret = TW_RESULT_OK; - - TWUpdate update; - OICStrcpy(update.nodeId, SIZE_NODEID, tokens[0]); - OICStrcpy(update.endpoint, SIZE_NODEID, tokens[1]); - OICStrcpy(update.status, SIZE_NODEID, tokens[2]); - OICStrcpy(update.extendedStatus, SIZE_NODEID, tokens[3]); - if (count == 6) + if (g_WIPDevice == NULL) { - OICStrcpy(update.zoneId, SIZE_NODEID, tokens[4]); - OICStrcpy(update.delay, SIZE_NODEID, tokens[5]); + OC_LOG_V(ERROR, TAG, + "Receive simple descriptor unexpectedly - %s", tokens[0]); + ret = TW_RESULT_ERROR; + goto exit; } - if (g_DeviceStatusUpdateCallback != NULL) + if (g_WIPDevice->endpointOfInterest->clusterList != NULL) { - g_DeviceStatusUpdateCallback(&update); + OC_LOG_V(ERROR, TAG, "Expected an empty cluster list."); + ret = TW_RESULT_ERROR; + goto exit; } - OC_LOG_V(INFO, TAG, "Leave TelZoneStatusHandler()."); - - return ret; -} - -//----------------------------------------------------------------------------- -// Internal functions - Helpers -//----------------------------------------------------------------------------- - -/** - * - * Tokenize 'input' parameter by 'delimiters' into 'output' array. - * - */ -int Tokenize(const char *input, const char* delimiters, char* output[]) -{ - OC_LOG_V(INFO, TAG, "Enter Tokenize()"); - - if (output == NULL) + //Add found clusters for the node. + g_WIPDevice->endpointOfInterest->clusterList = + (TWClusterList*)OICMalloc(sizeof(TWClusterList)); + if (g_WIPDevice->endpointOfInterest->clusterList == NULL) { - OC_LOG_V(INFO, TAG, "Invalid parameter."); - return -1; + OC_LOG_V(ERROR, TAG, "No Memory - clusterList"); + ret = TW_RESULT_ERROR_NO_MEMORY; + goto exit; } - int length = strlen(input); - char * str = (char *) OICCalloc(1, length + 1); - OICStrcpy(str, length+1, input); + g_WIPDevice->endpointOfInterest->clusterList->clusterIds = + (TWClusterId*)OICMalloc(sizeof(TWClusterId) * count); + if (g_WIPDevice->endpointOfInterest->clusterList->clusterIds == NULL) + { + OICFree(g_WIPDevice->endpointOfInterest->clusterList); + OC_LOG_V(ERROR, TAG, "No Memory - clusterIds"); + ret = TW_RESULT_ERROR_NO_MEMORY; + goto exit; + } - char* savePtr = NULL; - char* p = strtok_r(str, delimiters, &savePtr); - int index = 0; - while (p && index <= ARRAY_LENGTH) + int i = 0; + for (; i < count; i++) { - int size = strlen(p) + 1; //for null char - output[index] = (char*)OICCalloc(size, sizeof(char)); - OICStrcpy(output[index], size, p); + OICStrcpy(g_WIPDevice->endpointOfInterest->clusterList-> + clusterIds[i].clusterId, + SIZE_CLUSTERID, + tokens[i]); - p = strtok_r (NULL, delimiters, &savePtr); - index++; + OC_LOG_V(INFO, TAG, "ClusterIds[%d]=%s", + i, + g_WIPDevice->endpointOfInterest-> + clusterList->clusterIds[i].clusterId); } + g_WIPDevice->endpointOfInterest->clusterList->count = count; + ret = TW_RESULT_HAS_CLUSTERS; - OICFree(str); - OC_LOG_V(INFO, TAG, "Leave Tokenize()"); - return index; +exit: + OC_LOG_V(INFO, TAG, "Leave TelSimpleDescInClusterHandler() with ret=%d", ret); + return ret; } -int AsciiToHex(char c) +TWResultCode TelWriteAttrHandler(int count, char* tokens[]) { - int num = (int) c; - if(c >= '0' && c <= '9') - { - return num - '0'; - } + //AT+WRITEATR:3A3D,01,0,0003,0000,21,00 + // OK + // WRITEATTR:3A3D,01,0003,,00 + // + //AT+WRITEATR:B826,01,0,0500,0010,F0,000D6F0000D59E92 + // OK + // WRITEATTR:B826,01,0500,0010,70 - if(num >= 'A' && num <= 'F') - { - return num - 'A' + 10; - } - return -1; -} + OC_LOG_V(INFO, TAG, "Enter TelWriteAttrHandler()"); -TWResultCode AsciiHexToValue(char* hexString, int length, uint64_t* value) -{ - if(!hexString || !value || length < 0) + TWResultCode ret = TW_RESULT_ERROR; + + if(!tokens || + (count < RESPONSE_PARAMS_COUNT_WRITE_ATTR_4) || + (count > RESPONSE_PARAMS_COUNT_WRITE_ATTR_5)) { - return TW_RESULT_ERROR_INVALID_PARAMS; + ret = TW_RESULT_ERROR_INVALID_PARAMS; + goto exit; } - int retVal = AsciiToHex(hexString[0]); - if(retVal == -1) + + if (count == RESPONSE_PARAMS_COUNT_WRITE_ATTR_4) { - OC_LOG(ERROR, TAG, "Bad conversion from ASCII To Hex."); - return TW_RESULT_ERROR; + if (strcmp(tokens[3], AT_STR_ERROR_OK) == 0) + { + ret = TW_RESULT_OK; + } } - *value = (uint64_t)retVal; - for (int i = 1; i < length*2; ++i) + else if (count == RESPONSE_PARAMS_COUNT_WRITE_ATTR_5) { - if (sizeof(hexString) > (uint32_t)i) + if (strcmp(tokens[4], AT_STR_ERROR_INVALID_OP) == 0) { - *value <<= 4; - retVal = AsciiToHex(hexString[i]); - if(retVal == -1) - { - OC_LOG(ERROR, TAG, "Bad conversion from ASCII To Hex."); - return TW_RESULT_ERROR; - } - *value |= (uint64_t)retVal; + ret = TW_RESULT_ERROR_INVALID_OP; } } - return TW_RESULT_OK; + +exit: + OC_LOG_V(INFO, TAG, "Leave TelWriteAttrHandler() with ret=%d", ret); + return ret; } -/** - * - * Apply interface attribute values to terminal settings. - * - */ -int SetTerminalInfo(int fd, int speed, int parity, int shouldBlock) +TWResultCode TelReadAttrHandlerTemperature(int count, char* tokens[]) { - OC_LOG_V(INFO, TAG, "Enter SetTerminalInfo()"); + //AT+READATR:F2D7,01,0,0402,0002 + // OK + // TEMPERATURE:F2D7,01,0002,00,1770 + // + //AT+READATR:F2D7,01,0,0402,0002 + // OK + // ERROR:66 + + OC_LOG_V(INFO, TAG, "Enter TelReadAttrHandlerTemperature()."); + TWResultCode ret = TW_RESULT_UNKNOWN; - int ret = 0; - struct termios terminalInfo = {0, 0, 0, 0, 0, 0, 0}; - ret = tcgetattr(fd, &terminalInfo); - if (ret != 0) + if(!tokens || count != RESPONSE_PARAMS_COUNT_TEMPERATURE) { - OC_LOG_V(ERROR, TAG, "tcgetattr() - error=%d", ret); - ret = -1; + OC_LOG_V(ERROR, TAG, "Invalid Params"); + ret = TW_RESULT_ERROR_INVALID_PARAMS; goto exit; } - ret = cfsetispeed (&terminalInfo, speed); - if (ret != 0) + if (strcmp(tokens[3], AT_STR_ERROR_OK) != 0) { - OC_LOG_V(ERROR, TAG, "cfsetispeed() - error=%d", ret); - ret = -1; + OC_LOG_V(ERROR, TAG, "TEMPERATURE prompt contained error status."); + ret = TW_RESULT_ERROR; goto exit; } - ret = cfsetospeed (&terminalInfo, speed); - if (ret != 0) + // AttrInfo is 16-bit value representing (100 * Degrees Celsius) + // so 0x812 = 20.66 C = 69.188 F + if (g_ZigBeeStatus.remoteAttributeValueRead != NULL) { - OC_LOG_V(ERROR, TAG, "cfsetospeed() - error=%d", ret); - ret = -1; - goto exit; + OICFree(g_ZigBeeStatus.remoteAttributeValueRead); + g_ZigBeeStatus.remoteAttributeValueRead = NULL; } - - terminalInfo.c_cflag = (terminalInfo.c_cflag & ~CSIZE); //byte size - terminalInfo.c_cflag |= CS8; //byte size is 8 - - terminalInfo.c_cflag &= ~PARENB; //no parity - terminalInfo.c_cflag |= parity; //no parity - - terminalInfo.c_cflag &= ~CSTOPB; //1 stop bit - - terminalInfo.c_cflag |= CREAD; //enable the receiver - - //Input Control Settings - terminalInfo.c_iflag &= ~IGNBRK; //break condition - - //Local Mode Settings - terminalInfo.c_lflag = 0; - - // whether to block on read and read time-out - terminalInfo.c_cc[VMIN] = (shouldBlock >= 1) ? 1 : 0; - terminalInfo.c_cc[VTIME] = 5; - - //Input Control Settings - terminalInfo.c_oflag = 0; - - if (tcsetattr (fd, TCSANOW, &terminalInfo) != 0) + OC_LOG_V(INFO, TAG, "Read Attribute Value: %s", tokens[4]); + g_ZigBeeStatus.remoteAttributeValueRead = + (char*)OICMalloc(sizeof(char) * strlen(tokens[4])); + if (g_ZigBeeStatus.remoteAttributeValueRead == NULL) + { + OC_LOG_V(ERROR, TAG, "No Memory"); + ret = TW_RESULT_ERROR_NO_MEMORY; + } + else { - OC_LOG_V(ERROR, TAG, "tcsetattr"); - ret = -1; + strcpy(g_ZigBeeStatus.remoteAttributeValueRead, tokens[4]); + g_ZigBeeStatus.remoteAtrributeValueReadLength = strlen(tokens[4]); + ret = TW_RESULT_REMOTE_ATTR_HAS_VALUE; } exit: - OC_LOG_V(INFO, TAG, "Leave SetTerminalInfo() with ret=%d", ret); + OC_LOG_V(INFO, TAG, "Leave TelReadAttrHandlerTemperature() with ret=%d", ret); return ret; } -/** - * - * Issues an AT Command to the Telegesis Dongle. Waits for response unless - * a timeout is specified. Blocks until operation is completed. Responses are - * in placed responseArray, while prompts are placed in promptArray. - * - * @param[out] atErrorCode The AT Error code received as Hex. 0 on success, - * otherwise refer to Telegesis manual. - * @param[out] responseArray Array corresponding to response lines received in - * the buffer during a write/read. (ie. A synchronous - * AT result.) - * @param[out] promptArray Array corresponding to prompt lines received in - * the buffer post write/read. (ie. An asynchronous AT - * result.) - * @param[out] responseCount The number of responses in the response array. - * @param[out] promptCount The number of prompts in the prompt array. - * @param[in] command The AT Command you wish to issue. - * @param[in] timeout The allotted time (seconds) you expect the AT Command's - * prompt results to reach the buffer. - * - */ -TWResultCode IssueATCommand(const char * command, - uint8_t timeout, - uint64_t * atErrorCode, - char * responseArray[], - char * promptArray[], - uint8_t * responseCount, - uint8_t * promptCount) +TWResultCode TelReadAttrHandler(int count, char* tokens[]) { - TWResultCode ret = TW_RESULT_ERROR; + //AT+READATR:F2D7,01,0,0402,0002 + // OK + // RESPATTR:,,,,, + // + //AT+READATR:F2D7,01,0,0402,0002 + // OK + // ERROR:66 - ret = WriteBuffer(command); - if(ret != TW_RESULT_OK) - { - OC_LOG_V(ERROR, TAG, "Failed to write to buffer with result: %d", ret); - return ret; - } + OC_LOG_V(INFO, TAG, "Enter TelReadAttrHandler()"); + TWResultCode ret = TW_RESULT_UNKNOWN; - ret = ReadBuffer(atErrorCode, - responseArray, - responseCount, - command, - 0); - if(ret != TW_RESULT_OK) + if(!tokens || count != RESPONSE_PARAMS_COUNT_RESPATTR) { - OC_LOG_V(ERROR, TAG, "Failed to read from buffer with result: %d", ret); - return ret; + OC_LOG_V(ERROR, TAG, "Invalid Params"); + ret = TW_RESULT_ERROR_INVALID_PARAMS; + goto exit; } - if(timeout != 0) + + if (strcmp(tokens[4], AT_STR_ERROR_OK) != 0) { - sleep(timeout); - ret = ReadBuffer(atErrorCode, - promptArray, - promptCount, - NULL, - timeout); - if(ret != TW_RESULT_OK) - { - OC_LOG_V(ERROR, TAG, "Failed to read from buffer with result: %d", ret); - return ret; - } + OC_LOG_V(INFO, TAG, "READATTR prompt contained error status."); + ret = TW_RESULT_ERROR; + goto exit; } - return ret; -} -/** - * - * Returns file descriptor by reference based on the global comPort specified - * at the top of this file. - * - * @param[out] fd The file descriptor associated with the comport specified. - * - */ -TWResultCode OpenPort(int * fd) -{ - if(g_port == NULL) + if (g_ZigBeeStatus.remoteAttributeValueRead != NULL) { - OC_LOG_V(ERROR, TAG, "No port specified."); - return TW_RESULT_ERROR_INVALID_PORT; + OICFree(g_ZigBeeStatus.remoteAttributeValueRead); } - if(!fd) + OC_LOG_V(INFO, TAG, "Read Attribute Value: %s.", tokens[5]); + g_ZigBeeStatus.remoteAttributeValueRead = + (char*)OICMalloc(sizeof(char) * strlen(tokens[5])); + if (g_ZigBeeStatus.remoteAttributeValueRead != NULL) { - return TW_RESULT_ERROR_INVALID_PARAMS; + strcpy(g_ZigBeeStatus.remoteAttributeValueRead, tokens[5]); + g_ZigBeeStatus.remoteAtrributeValueReadLength = strlen(tokens[5]); + ret = TW_RESULT_REMOTE_ATTR_HAS_VALUE; } - int tw_fd = open(g_port, O_RDWR | O_NOCTTY | O_SYNC); - *fd = tw_fd; - if(tw_fd <= 0) + else { - OC_LOG_V(ERROR, TAG, "Could not open port. Errno is: %d", errno); - return TW_RESULT_ERROR; + OC_LOG_V(ERROR, TAG, "No Memory"); + ret = TW_RESULT_ERROR_NO_MEMORY; } - // set speed to 19,200 bps, 8n1 (no parity), no block - SetTerminalInfo(tw_fd, DEVICE_BAUDRATE, 0, 0); - - return TW_RESULT_OK; +exit: + OC_LOG_V(INFO, TAG, "Leave TelReadAttrHandler().\n"); + return ret; } -/** - * - * Closes port based on the specified file descriptor. - * - * Returns TW_RESULT_OK on success. - * - * @param[in] The file descriptor to be closed. - * - */ -TWResultCode ClosePort(int fd) +TWResultCode TelZCLDefaultResponseHandler(int count, char* tokens[]) { - int ret = close(fd); - if(ret != 0) + //AT+RONOFF:
,,[,] + // DFTREP:,,,, + // + //AT+DRLOCK:
,,, + // DFTREP:,,,, + // + //AT+LCMVTOLEV:
,,,,, + // DFTREP:,,,, + + OC_LOG_V(INFO, TAG, "Enter TelZCLDefaultResponseHandler()"); + TWResultCode ret = TW_RESULT_UNKNOWN; + + if(!tokens || count != RESPONSE_PARAMS_COUNT_DFTREP) { - OC_LOG_V(ERROR, TAG, "Could not close port. Errno is: %d", errno); - return TW_RESULT_ERROR; + OC_LOG_V(ERROR, TAG, "Invalid Params"); + ret = TW_RESULT_ERROR_INVALID_PARAMS; + goto exit; } - return TW_RESULT_OK; -} -bool IsThisAValidLine(char * singleLine, bool * endControlHit, uint64_t * atErrorCode) -{ - if(!singleLine || !endControlHit || !atErrorCode) + OC_LOG_V(INFO, TAG, + "DFTREP prompt succeed for NodeId:%s, EP:%s, ClusterId:%s, CMD:%s.\n", + tokens[0], tokens[1], tokens[2], tokens[3]); + + if (strcmp(tokens[4], AT_STR_ERROR_OK) != 0) { - return TW_RESULT_ERROR_INVALID_PARAMS; + ret = TW_RESULT_ERROR; } - size_t singleLineSize = strlen(singleLine); - int i = 0; - size_t endStrSize = 0; - size_t strSize = 0; - TWResultCode ret = TW_RESULT_ERROR; - for(; i= endStrSize ? endStrSize : singleLineSize; - // Found a single EndControl string. - if (strncmp(singleLine, g_TWEndMessageMap[i].endStr, strSize) == 0) - { - //endControlHit = true; - if (g_TWEndMessageMap[i].endControl == TW_ENDCONTROL_OK) - { - *atErrorCode = 0x0000; - *endControlHit = true; - } - else if (g_TWEndMessageMap[i].endControl == TW_ENDCONTROL_ERROR) - { - ret = AsciiHexToValue(&singleLine[strSize], - strlen(&singleLine[strSize])-1, - atErrorCode); - if(ret != TW_RESULT_OK) - { - return false; - } - *endControlHit = true; - } - else if (g_TWEndMessageMap[i].endControl == TW_ENDCONTROL_SEQ) - { - //endControlHit = false; - } - else if (g_TWEndMessageMap[i].endControl == TW_ENDCONTROL_ACK) - { - //endControlHit = false; - } - return false; - //break; - } + ret = TW_RESULT_OK; } - return true; +exit: + OC_LOG_V(INFO, TAG, "Leave TelZCLDefaultResponseHandler()"); + return ret; } -char * myStrTok(char* readData, const char* tokens, bool * endControlHit, - uint64_t * atErrorCode, char ** savePtr) +TWResultCode TelSwitchDoorLockStateHandler(int count, char* tokens[]) { - if(!tokens || !endControlHit || !atErrorCode || !savePtr) - { - return NULL; - } - char * buf = strtok_r(readData, tokens, savePtr); - if(!buf) + //AT+DRLOCK:
,,, + // DRLOCRSP:,, + // or + // DRUNLOCKRSP:,, + + OC_LOG_V(INFO, TAG, "Enter TelSwitchDoorLockStateHandler()"); + TWResultCode ret = TW_RESULT_UNKNOWN; + + if(!tokens || count != RESPONSE_PARAMS_COUNT_DRLOCKUNLOCKRSP) { - return NULL; + OC_LOG_V(ERROR, TAG, "Invalid Params"); + ret = TW_RESULT_ERROR_INVALID_PARAMS; + goto exit; } - bool valid = false; - valid = IsThisAValidLine(buf, endControlHit, atErrorCode); - if(valid == true) + + if (strcmp(tokens[2], AT_STR_ERROR_OK) != 0) { - return buf; + OC_LOG_V(INFO, TAG, + "DRLOCRSP/DRUNLOCKRSP prompt contained error status %s.", tokens[4]); + ret = TW_RESULT_ERROR; } else { - return myStrTok(NULL, tokens, endControlHit, atErrorCode, savePtr); + OC_LOG_V(INFO, TAG, "DRLOCRSP/DRUNLOCKRSP prompt succeed for nodeId:%s, ep:%s.", + tokens[0], tokens[1]); + ret = TW_RESULT_OK; } + +exit: + OC_LOG_V(INFO, TAG, "Leave TelSwitchDoorLockStateHandler() with ret=%d", ret); + return ret; } -/** - * - * Reads an entire buffer, parses the buffer into individual lines, and places - * these individual lines into the response array. - * - * The original command echo'd back is ignored. Any endControl items are also - * ignored. - * - * If a timeout is specified greater than zero, it means you expect prompts in - * the buffer. - * - * @param[out] atErrorCode The AT Error code received as Hex. 0 on success, - * otherwise refer to Telegesis manual. - * @param[out] responseArray Each individual line from read() is placed in this - array. - * @param[out] count The number of items in the response array. - * @param[in] command The AT command that was already issued. Used to ignore - * when it is echo'd back in the read buffer. - * @param[in] timeout If not zero, it is used as a flag to determine if - * blocking on read() should occur. - * - */ -TWResultCode ReadBuffer(uint64_t * atErrorCode, - char * responseArray[], - uint8_t * count, - const char * command, - uint8_t timeout) +TWResultCode TelZoneEnrollRequestHandler(int count, char* tokens[]) { + //ZENROLLREQ:,,, - TWResultCode ret = TW_RESULT_OK; - char readData[1000] = {}; - char itrData[200] = {}; + OC_LOG_V(INFO, TAG, "Enter TelZoneEnrollRequestHandler()"); + TWResultCode ret = TW_RESULT_UNKNOWN; - ssize_t readDataBytes = 0; - ssize_t itrDataBytes = 0; - bool endControlHit = false; - uint8_t responseArrayPos = 0; - while(itrDataBytes == 0) + if(!tokens || count != RESPONSE_PARAMS_COUNT_ZENROLLREQ) { - itrDataBytes += read(g_fd, itrData, sizeof(itrData)-1); - if(itrDataBytes < 0) - { - OC_LOG_V(ERROR, TAG, "Could not read from port. Errno is: %d", errno); - return TW_RESULT_ERROR; - } + OC_LOG_V(ERROR, TAG, "Invalid Params"); + ret = TW_RESULT_ERROR_INVALID_PARAMS; + goto exit; + } - if(command) - { - size_t itrDataIndexLength = (strlen(itrData) - 1); - if(strncmp(itrData, command, strlen(command)) == 0 && - itrData[itrDataIndexLength] == '\r') - { - memset(itrData, 0, sizeof(itrData)); - itrDataBytes = 0; // Ignore any single line which only echo'd - // the command. This allows us to block on read(). - } - } - if(itrDataBytes > 0 && - readDataBytes < (ssize_t)sizeof(readData) && - (readDataBytes + itrDataBytes) <= (ssize_t)sizeof(readData)) - { - readDataBytes += itrDataBytes; - OICStrcat(readData, sizeof(readData), itrData); - if(itrDataBytes == sizeof(itrData)) - { -reread: - memset(itrData, 0, sizeof(itrData)); - itrDataBytes = 0; - } - } + OC_LOG_V(INFO, TAG, "Received zone request from:"); + OC_LOG_V(INFO, TAG, "Node:%s", tokens[0]); + OC_LOG_V(INFO, TAG, "EP:%s", tokens[1]); + OC_LOG_V(INFO, TAG, "ZoneType:%s", tokens[2]); + OC_LOG_V(INFO, TAG, "ManufactureCode:%s", tokens[3]); + ret = TW_RESULT_OK; - if(timeout != 0) - { - break; // Don't block on read as there are no prompts waiting in the buffer. - } - } - if(readDataBytes > 0) - { - char * savePtr = NULL; - char * singleLine = myStrTok(readData, "\r\n", &endControlHit, atErrorCode, &savePtr); - while(singleLine) - { - // Stop on endControl items. Also leave function when an endControl is found. - //singleLine = myStrTok(NULL, "\r", &endControlHit, atErrorCode, &savePtr); - if(singleLine) - { - // Ignore the echo'd command line if it was passed in. - if(!command || (command && strcmp(singleLine, command) != 0)) - { - responseArray[responseArrayPos] = (char *) OICMalloc((strlen(singleLine)+1) * - sizeof(char)); - if(!responseArray[responseArrayPos]) - { - return TW_RESULT_ERROR_NO_MEMORY; - } - memset(responseArray[responseArrayPos], - 0, - (strlen(singleLine)+1) * sizeof(char)); - strcpy(responseArray[responseArrayPos], singleLine); - responseArrayPos++; - } - singleLine = myStrTok(NULL, "\r\n", &endControlHit, atErrorCode, &savePtr); - } - } - *count = responseArrayPos; - } - if(endControlHit == false && timeout == 0) - { - memset(readData, 0, sizeof(readData)); - readDataBytes = 0; - goto reread; - } +exit: + OC_LOG_V(INFO, TAG, "Leave TelZoneEnrollRequestHandler() with ret=%d", ret); return ret; } -/** - * - * Writes AT command to buffer. - * - * @param[in] command The command to be written to the buffer. - * - */ -TWResultCode WriteBuffer(const char * command) +TWResultCode TelEnrolledHandler(int count, char* tokens[]) { + //ENROLLED:,, + + OC_LOG_V(INFO, TAG, "Enter TelEnrolledHandler()"); TWResultCode ret = TW_RESULT_OK; - if(!command) - { - return TW_RESULT_ERROR_INVALID_PARAMS; - } - size_t sendCommandSize = (strlen(command) + 2) * sizeof(char); - char * sendCommand = (char *) OICMalloc(sendCommandSize); - if(!sendCommand) + if(!tokens || count != RESPONSE_PARAMS_COUNT_ENROLLED) { - return TW_RESULT_ERROR_NO_MEMORY; - } - memset(sendCommand, 0, sendCommandSize); - sprintf(sendCommand, "%s\r", command); - size_t expectedWrittenBytes = strlen(sendCommand); - size_t actualWrittenBytes = write(g_fd, sendCommand, expectedWrittenBytes); - if(actualWrittenBytes <= 0) - { - OC_LOG_V(ERROR, TAG, "Could not write to port. Errno is: %d", errno); - ret = TW_RESULT_ERROR; + OC_LOG_V(ERROR, TAG, "Invalid Params"); + ret = TW_RESULT_ERROR_INVALID_PARAMS; goto exit; } - if(actualWrittenBytes != expectedWrittenBytes) + + OC_LOG_V(INFO, TAG, "Received zone enrollment for:"); + OC_LOG_V(INFO, TAG, "ZID:%s", tokens[0]); + OC_LOG_V(INFO, TAG, "ZoneType:%s", tokens[1]); + OC_LOG_V(INFO, TAG, "EUI:%s", tokens[2]); + + TWEnrollee enrollee; + OICStrcpy(enrollee.zoneId, SIZE_ZONEID, tokens[0]); + OICStrcpy(enrollee.zoneType, SIZE_ZONETYPE, tokens[1]); + OICStrcpy(enrollee.eui, SIZE_EUI, tokens[2]); + + if (g_EnrollmentSucceedCallback != NULL) { - ret = TW_RESULT_ERROR; - goto exit; + OC_LOG_V(INFO, TAG, "Enrolled - Invoke callback"); + g_EnrollmentSucceedCallback(&enrollee); } + ret = TW_RESULT_OK; exit: - OICFree(sendCommand); + OC_LOG_V(INFO, TAG, "Leave TelEnrolledHandler() with ret=%d", ret); return ret; } -/** - * - * Deallocate items in the given arrays. - * - */ -void CleanArray(char* responseArray[], char* promptArray[], - uint8_t responseCount, uint8_t promptCount) +TWResultCode TelZoneStatusHandler(int count, char* tokens[]) { - OC_LOG_V(INFO, TAG, "Enter CleanArray()."); + //ZONESTATUS:,,,[,,] + //ZONESTATUS:5FBA,01,0021,00,01,00AF - if(responseCount > ARRAY_LENGTH || promptCount > ARRAY_LENGTH) + OC_LOG_V(INFO, TAG, "Enter TelZoneStatusHandler()"); + TWResultCode ret = TW_RESULT_UNKNOWN; + if(!tokens || + ((count != RESPONSE_PARAMS_COUNT_ZONESTATUS_4) && + (count != RESPONSE_PARAMS_COUNT_ZONESTATUS_6))) { - OC_LOG_V(ERROR, TAG, "Trying to access arrays out of bounds."); - return; + OC_LOG_V(ERROR, TAG, "Invalid Params"); + ret = TW_RESULT_ERROR_INVALID_PARAMS; + goto exit; } - OC_LOG_V(INFO, TAG, "Attempt to free responseArray and promptArray."); - int i = 0; - if (responseArray) + TWUpdate update; + OICStrcpy(update.nodeId, SIZE_NODEID, tokens[0]); + OICStrcpy(update.endpoint, SIZE_NODEID, tokens[1]); + OICStrcpy(update.status, SIZE_NODEID, tokens[2]); + OICStrcpy(update.extendedStatus, SIZE_NODEID, tokens[3]); + + if (count == RESPONSE_PARAMS_COUNT_ZONESTATUS_6) { - for (; i < responseCount; i++) - { - OC_LOG_V(INFO, TAG, "Free responseArray[%d]: %s", i, responseArray[i]); - OICFree(responseArray[i]); - } + OICStrcpy(update.zoneId, SIZE_NODEID, tokens[4]); + OICStrcpy(update.delay, SIZE_NODEID, tokens[5]); } - if (promptArray) + if (g_DeviceStatusUpdateCallback != NULL) { - i = 0; - for (; i < promptCount; i++) - { - OC_LOG_V(INFO, TAG, "Free promptArray[%d]: %s", i, promptArray[i]); - OICFree(promptArray[i]); - } + OC_LOG_V(INFO, TAG, "device status update - invoke callback"); + g_DeviceStatusUpdateCallback(&update); } + ret = TW_RESULT_OK; - OC_LOG_V(INFO, TAG, "Leave CleanArray()."); +exit: + OC_LOG_V(INFO, TAG, "Leave TelZoneStatusHandler() with ret=%d", ret); + return ret; } +//----------------------------------------------------------------------------- +// Internal functions - Helpers +//----------------------------------------------------------------------------- + /** * - * Print the given arrays. + * Tokenize 'input' parameter by 'delimiters' into 'output' array. * */ -void PrintArray(char* responseArray[], char* promptArray[], - uint8_t responseCount, uint8_t promptCount) +int Tokenize(const char *input, const char* delimiters, char* output[]) { - OC_LOG_V(INFO, TAG, "Enter PrintArray()."); + OC_LOG_V(INFO, TAG, "Enter Tokenize() - %s", input); - if(responseCount > ARRAY_LENGTH || promptCount > ARRAY_LENGTH) + if (output == NULL) { - OC_LOG_V(ERROR, TAG, "Trying to access arrays out of bounds."); - return; + OC_LOG_V(INFO, TAG, "Invalid parameter."); + return -1; } - int n = 0; - OC_LOG_V(INFO, TAG, "responseCount=%d", responseCount); - for (; n < responseCount; n++) - { - OC_LOG_V(INFO, TAG, "responseArray[%d]=%s", n, responseArray[n]); - } + int length = strlen(input); + char * str = (char *) OICCalloc(1, length + 1); + OICStrcpy(str, length+1, input); - OC_LOG_V(INFO, TAG, "promptCount=%d", promptCount); - for (n = 0; n < promptCount; n++) + char* savePtr = NULL; + char* p = strtok_r(str, delimiters, &savePtr); + int index = 0; + while (p && index <= ARRAY_LENGTH) { - OC_LOG_V(INFO, TAG, "promptArray[%d]=%s", n, promptArray[n]); + int size = strlen(p) + 1; //for null char + output[index] = (char*)OICCalloc(size, sizeof(char)); + OICStrcpy(output[index], size, p); + OC_LOG_V(INFO, TAG, "Token[%d]=%s", index, output[index]); + p = strtok_r (NULL, delimiters, &savePtr); + index++; } - OC_LOG_V(INFO, TAG, "Leave PrintArray()."); + OICFree(str); + OC_LOG_V(INFO, TAG, "Leave Tokenize()"); + return index; } - -/** - * - * Print the given device. - * - */ -void PrintTWDevice(TWDevice* device) +int AsciiToHex(char c) { - if (device != NULL) + int num = (int) c; + if(c >= '0' && c <= '9') { - OC_LOG_V(INFO, TAG, "Device - NodeID=%s", device->nodeId); - OC_LOG_V(INFO, TAG, "Device - EPID=%s", device->endpointOfInterest->endpointId); + return num - '0'; } - else + + if(num >= 'A' && num <= 'F') { - OC_LOG_V(ERROR, TAG, "Received a NULL device - CAN'T PRINT IT."); + return num - 'A' + 10; } + return -1; } -/** - * - * Print the given device list. - * - */ -void PrintTWDeviceList(TWDeviceList* list) +TWResultCode AsciiHexToValue(char* hexString, int length, uint64_t* value) { - int i = 0; - for (; i < list->count; i++) + if(!hexString || !value || length < 0) + { + return TW_RESULT_ERROR_INVALID_PARAMS; + } + int retVal = AsciiToHex(hexString[0]); + if(retVal == -1) + { + OC_LOG(ERROR, TAG, "Bad conversion from ASCII To Hex."); + return TW_RESULT_ERROR; + } + *value = (uint64_t)retVal; + for (int i = 1; i < length; ++i) { - PrintTWDevice(&list->deviceList[i]); + if (sizeof(hexString) > (uint32_t)i) + { + *value <<= 4; + retVal = AsciiToHex(hexString[i]); + if(retVal == -1) + { + OC_LOG(ERROR, TAG, "Bad conversion from ASCII To Hex."); + return TW_RESULT_ERROR; + } + *value |= (uint64_t)retVal; + } } + return TW_RESULT_OK; } /** @@ -2730,7 +2765,6 @@ void DeallocateTWDeviceList() OICFree(g_FoundMatchedDeviceList->deviceList->endpointOfInterest->clusterList); g_FoundMatchedDeviceList->deviceList->endpointOfInterest->clusterList = NULL; - OICFree(g_FoundMatchedDeviceList->deviceList->endpointOfInterest); g_FoundMatchedDeviceList->deviceList->endpointOfInterest = NULL; -- 2.7.4