]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - iot-gateway/lighting-gateway.git/blob - zbSocDriver/zbSocCmd.c
22d8fd1c05f5538bacc067265808c0d51b51154e
[iot-gateway/lighting-gateway.git] / zbSocDriver / zbSocCmd.c
1 /*
2  * zbSocCmd.c
3  *
4  * This module contains the API for the zll SoC Host Interface.
5  *
6  * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ 
7  * 
8  * 
9  *  Redistribution and use in source and binary forms, with or without 
10  *  modification, are permitted provided that the following conditions 
11  *  are met:
12  *
13  *    Redistributions of source code must retain the above copyright 
14  *    notice, this list of conditions and the following disclaimer.
15  *
16  *    Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the 
18  *    documentation and/or other materials provided with the   
19  *    distribution.
20  *
21  *    Neither the name of Texas Instruments Incorporated nor the names of
22  *    its contributors may be used to endorse or promote products derived
23  *    from this software without specific prior written permission.
24  *
25  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
26  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
27  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
29  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
30  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
31  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
34  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
35  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  *
37  */
39 /*********************************************************************
40  * INCLUDES
41  */
42 #include <termios.h>
43 #include <string.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <fcntl.h>
48 #include <sys/ioctl.h>
50 #include <errno.h>
51 #include <string.h>
53 #include "zbSocCmd.h"
55 /*********************************************************************
56  * MACROS
57  */
59 #define APPCMDHEADER(len) \
60 0xFE,                                                                             \
61 len,   /*RPC payload Len                                      */     \
62 0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP        */     \
63 0x00, /*MT_APP_MSG                                                   */     \
64 0x0B, /*Application Endpoint                                  */     \
65 0x02, /*short Addr 0x0002                                     */     \
66 0x00, /*short Addr 0x0002                                     */     \
67 0x0B, /*Dst EP                                                             */     \
68 0xFF, /*Cluster ID 0xFFFF invalid, used for key */     \
69 0xFF, /*Cluster ID 0xFFFF invalid, used for key */     \
71 #define BUILD_UINT16(loByte, hiByte) \
72           ((uint16_t)(((loByte) & 0x00FF) + (((hiByte) & 0x00FF) << 8)))
74 #define BUILD_UINT32(Byte0, Byte1, Byte2, Byte3) \
75           ((uint32_t)((uint32_t)((Byte0) & 0x00FF) \
76           + ((uint32_t)((Byte1) & 0x00FF) << 8) \
77           + ((uint32_t)((Byte2) & 0x00FF) << 16) \
78           + ((uint32_t)((Byte3) & 0x00FF) << 24)))
80 /*********************************************************************
81  * CONSTANTS
82  */
83 #define ZLL_MT_APP_RPC_CMD_TOUCHLINK          0x01
84 #define ZLL_MT_APP_RPC_CMD_RESET_TO_FN        0x02
85 #define ZLL_MT_APP_RPC_CMD_CH_CHANNEL         0x03
86 #define ZLL_MT_APP_RPC_CMD_JOIN_HA            0x04
87 #define ZLL_MT_APP_RPC_CMD_PERMIT_JOIN        0x05
88 #define ZLL_MT_APP_RPC_CMD_SEND_RESET_TO_FN   0x06
89 #define ZLL_MT_APP_RPC_CMD_START_DISTRIB_NWK  0x07
91 #define MT_APP_RSP                           0x80
92 #define MT_APP_ZLL_TL_IND                    0x81
93 #define MT_APP_ZLL_NEW_DEV_IND               0x82
95 #define MT_DEBUG_MSG                         0x80
97 #define COMMAND_LIGHTING_MOVE_TO_HUE                    0x00
98 #define COMMAND_LIGHTING_MOVE_TO_SATURATION 0x03
99 #define COMMAND_LEVEL_MOVE_TO_LEVEL                             0x00
100 #define COMMAND_IDENTIFY                    0x00
101 #define COMMAND_IDENTIFY_TRIGGER_EFFECT     0x40
103 /*** Foundation Command IDs ***/
104 #define ZCL_CMD_READ                                    0x00
105 #define ZCL_CMD_READ_RSP                                0x01
106 #define ZCL_CMD_WRITE                                   0x02
107 #define ZCL_CMD_WRITE_UNDIVIDED                         0x03
108 #define ZCL_CMD_WRITE_RSP                               0x04
109 //ZDO
110 #define MT_ZDO_SIMPLE_DESC_RSP             0x84 
111 #define MT_ZDO_ACTIVE_EP_RSP               0x85 
112 #define MT_ZDO_END_DEVICE_ANNCE_IND          0xC1
113 #define MT_ZDO_LEAVE_IND                     0xC9
115 //UTIL
116 #define MT_UTIL_GET_DEVICE_INFO              0x00
118 // General Clusters
119 #define ZCL_CLUSTER_ID_GEN_BASIC                             0x0000
120 #define ZCL_CLUSTER_ID_GEN_IDENTIFY                          0x0003
121 #define ZCL_CLUSTER_ID_GEN_GROUPS                            0x0004
122 #define ZCL_CLUSTER_ID_GEN_SCENES                            0x0005
123 #define ZCL_CLUSTER_ID_GEN_ON_OFF                            0x0006
124 #define ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL                     0x0008
125 // Lighting Clusters
126 #define ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL                0x0300
128 // Data Types
129 #define ZCL_DATATYPE_BOOLEAN                            0x10
130 #define ZCL_DATATYPE_UINT8                              0x20
131 #define ZCL_DATATYPE_INT16                              0x29
132 #define ZCL_DATATYPE_INT24                              0x2a
133 #define ZCL_DATATYPE_CHAR_STR                           0x42
135 /*******************************/
136 /*** Generic Cluster ATTR's  ***/
137 /*******************************/
138 #define ATTRID_BASIC_MODEL_ID                             0x0005
139 #define ATTRID_ON_OFF                                     0x0000
140 #define ATTRID_LEVEL_CURRENT_LEVEL                        0x0000
142 /*******************************/
143 /*** Lighting Cluster ATTR's  ***/
144 /*******************************/
145 #define ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_HUE         0x0000
146 #define ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_SATURATION  0x0001
148 /*******************************/
149 /*** Scenes Cluster Commands ***/
150 /*******************************/
151 #define COMMAND_SCENE_STORE                               0x04
152 #define COMMAND_SCENE_RECALL                              0x05
154 /*******************************/
155 /*** Groups Cluster Commands ***/
156 /*******************************/
157 #define COMMAND_GROUP_ADD                                 0x00
159 /* The 3 MSB's of the 1st command field byte are for command type. */
160 #define MT_RPC_CMD_TYPE_MASK  0xE0
162 /* The 5 LSB's of the 1st command field byte are for the subsystem. */
163 #define MT_RPC_SUBSYSTEM_MASK 0x1F
165 #define MT_RPC_SOF         0xFE
167 /*******************************/
168 /*** Bootloader Commands ***/
169 /*******************************/
170 #define SB_FORCE_BOOT               0xF8
171 #define SB_FORCE_RUN               (SB_FORCE_BOOT ^ 0xFF)
173 typedef enum {
174         MT_RPC_CMD_POLL = 0x00,
175         MT_RPC_CMD_SREQ = 0x20,
176         MT_RPC_CMD_AREQ = 0x40,
177         MT_RPC_CMD_SRSP = 0x60,
178         MT_RPC_CMD_RES4 = 0x80,
179         MT_RPC_CMD_RES5 = 0xA0,
180         MT_RPC_CMD_RES6 = 0xC0,
181         MT_RPC_CMD_RES7 = 0xE0
182 } mtRpcCmdType_t;
184 typedef enum {
185         MT_RPC_SYS_RES0, /* Reserved. */
186         MT_RPC_SYS_SYS,
187         MT_RPC_SYS_MAC,
188         MT_RPC_SYS_NWK,
189         MT_RPC_SYS_AF,
190         MT_RPC_SYS_ZDO,
191         MT_RPC_SYS_SAPI, /* Simple API. */
192         MT_RPC_SYS_UTIL,
193         MT_RPC_SYS_DBG,
194         MT_RPC_SYS_APP,
195         MT_RPC_SYS_OTA,
196         MT_RPC_SYS_ZNP,
197         MT_RPC_SYS_SPARE_12,
198         MT_RPC_SYS_UBL = 13, // 13 to be compatible with existing RemoTI.
199         MT_RPC_SYS_MAX // Maximum value, must be last (so 14-32 available, not yet assigned).
200 } mtRpcSysType_t;
202 /************************************************************
203  * TYPEDEFS
204  */
206 /*********************************************************************
207  * GLOBAL VARIABLES
208  */
210 /*********************************************************************
211  * LOCAL VARIABLES
212  */
213 int serialPortFd = 0;
214 uint8_t transSeqNumber = 0;
216 zbSocCallbacks_t zbSocCb;
218 /*********************************************************************
219  * LOCAL FUNCTIONS
220  */
221 void calcFcs(uint8_t *msg, int size);
222 static void processRpcSysAppTlInd(uint8_t *TlIndBuff);
223 static void processRpcSysAppZcl(uint8_t *zclRspBuff);
224 static void processRpcSysAppZclFoundation(uint8_t *zclRspBuff,
225                 uint8_t zclFrameLen, uint16_t clusterID, uint16_t nwkAddr, uint8_t endpoint);
226 static void processRpcSysApp(uint8_t *rpcBuff);
227 static void processRpcSysDbg(uint8_t *rpcBuff);
228 static void zbSocTransportWrite(uint8_t* buf, uint8_t len);
230 /*********************************************************************
231  * @fn      calcFcs
232  *
233  * @brief   populates the Frame Check Sequence of the RPC payload.
234  *
235  * @param   msg - pointer to the RPC message
236  *
237  * @return  none
238  */
239 void calcFcs(uint8_t *msg, int size)
241         uint8_t result = 0;
242         int idx = 1; //skip SOF
243         int len = (size - 1); // skip FCS
245         while ((len--) != 0)
246         {
247                 result ^= msg[idx++];
248         }
250         msg[(size - 1)] = result;
253 /*********************************************************************
254  * API FUNCTIONS
255  */
257 /*********************************************************************
258  * @fn      zbSocOpen
259  *
260  * @brief   opens the serial port to the CC253x.
261  *
262  * @param   devicePath - path to the UART device
263  *
264  * @return  status
265  */
266 int32_t zbSocOpen(char *devicePath)
268         struct termios tio;
270         /* open the device to be non-blocking (read will return immediatly) */
271         serialPortFd = open(devicePath, O_RDWR | O_NOCTTY | O_NONBLOCK);
272         if (serialPortFd < 0)
273         {
274                 perror(devicePath);
275                 printf("%s open failed\n", devicePath);
276                 return (-1);
277         }
279         //make the access exclusive so other instances will return -1 and exit
280         ioctl(serialPortFd, TIOCEXCL);
282         /* c-iflags
283          B115200 : set board rate to 115200
284          CRTSCTS : HW flow control (disabled below)
285          CS8     : 8n1 (8bit,no parity,1 stopbit)
286          CLOCAL  : local connection, no modem contol
287          CREAD   : enable receiving characters*/
288         tio.c_cflag = B38400 | CRTSCTS | CS8 | CLOCAL | CREAD;
289         /* c-iflags
290          ICRNL   : maps 0xD (CR) to 0x10 (LR), we do not want this.
291          IGNPAR  : ignore bits with parity erros, I guess it is
292          better to ignStateore an erronious bit then interprit it incorrectly. */
293         tio.c_iflag = IGNPAR & ~ICRNL;
294         tio.c_oflag = 0;
295         tio.c_lflag = 0;
297         tcflush(serialPortFd, TCIFLUSH);
298         tcsetattr(serialPortFd, TCSANOW, &tio);
300         //Send the bootloader force boot incase we have a bootloader that waits
301         uint8_t forceBoot = SB_FORCE_RUN;
302         zbSocTransportWrite(&forceBoot, 1);
304         return serialPortFd;
307 void zbSocClose(void)
309         tcflush(serialPortFd, TCOFLUSH);
310         close(serialPortFd);
312         return;
315 /*********************************************************************
316  * @fn      zbSocTransportWrite
317  *
318  * @brief   Write to the the serial port to the CC253x.
319  *
320  * @param   fd - file descriptor of the UART device
321  *
322  * @return  status
323  */
324 static void zbSocTransportWrite(uint8_t* buf, uint8_t len)
326         int remain = len;
327         int offset = 0;
328 #if 1
329         //printf("zbSocTransportWrite : len = %d\n", len);
331         while (remain > 0)
332         {
333                 int sub = (remain >= 8 ? 8 : remain);
334                 //printf("writing %d bytes (offset = %d, remain = %d)\n", sub, offset,
335                 //              remain);
336                 write(serialPortFd, buf + offset, sub);
338                 tcflush(serialPortFd, TCOFLUSH);
339                 usleep(5000);
340                 remain -= 8;
341                 offset += 8;
342         }
343 #else
344         write (serialPortFd, buf, len);
345         tcflush(serialPortFd, TCOFLUSH);
347 #endif
348         return;
351 /*********************************************************************
352  * @fn      zbSocRegisterCallbacks
353  *
354  * @brief   opens the serial port to the CC253x.
355  *
356  * @param   devicePath - path to the UART device
357  *
358  * @return  status
359  */
360 void zbSocRegisterCallbacks(zbSocCallbacks_t zbSocCallbacks)
362         //copy the callback function pointers
363         memcpy(&zbSocCb, &zbSocCallbacks, sizeof(zbSocCallbacks_t));
364         return;
367 /*********************************************************************
368  * @fn      zbSocTouchLink
369  *
370  * @brief   Send the touchLink command to the CC253x.
371  *
372  * @param   none
373  *
374  * @return  none
375  */
376 void zbSocTouchLink(void)
378         uint8_t cmd[] =
379         { APPCMDHEADER(13) 0x06, //Data Len
380                         0x02, //Address Mode
381                         0x00,//2dummy bytes
382                         0x00, ZLL_MT_APP_RPC_CMD_TOUCHLINK, 0x00, //
383                         0x00, //
384                         0x00 //FCS - fill in later
385                         };
387         calcFcs(cmd, sizeof(cmd));
388         zbSocTransportWrite(cmd, sizeof(cmd));
391 /*********************************************************************
392  * @fn      zbSocBridgeStartNwk
393  *
394  * @brief   Send the start network command to the CC253x.
395  *
396  * @param   none
397  *
398  * @return  none
399  */
400 void zbSocBridgeStartNwk(void)
402         uint8_t cmd[] =
403         { APPCMDHEADER(13) 0x06, //Data Len
404                         0x02, //Address Mode
405                         0x00,//2dummy bytes
406                         0x00, ZLL_MT_APP_RPC_CMD_START_DISTRIB_NWK, 0x00, //
407                         0x00, //
408                         0x00 //FCS - fill in later
409                         };
411         calcFcs(cmd, sizeof(cmd));
412         zbSocTransportWrite(cmd, sizeof(cmd));
415 /*********************************************************************
416  * @fn      zbSocResetToFn
417  *
418  * @brief   Send the reset to factory new command to the CC253x.
419  *
420  * @param   none
421  *
422  * @return  none
423  */
424 void zbSocResetToFn(void)
426         uint8_t cmd[] =
427         { APPCMDHEADER(13) 0x06, //Data Len
428                         0x02, //Address Mode
429                         0x00,//2dummy bytes
430                         0x00, ZLL_MT_APP_RPC_CMD_RESET_TO_FN, 0x00, //
431                         0x00, //
432                         0x00 //FCS - fill in later
433                         };
435         calcFcs(cmd, sizeof(cmd));
436         zbSocTransportWrite(cmd, sizeof(cmd));
439 /*********************************************************************
440  * @fn      zbSocSendResetToFn
441  *
442  * @brief   Send the reset to factory new command to a ZLL device.
443  *
444  * @param   none
445  *
446  * @return  none
447  */
448 void zbSocSendResetToFn(void)
450         uint8_t cmd[] =
451         { APPCMDHEADER(13) 0x06, //Data Len
452                         0x02, //Address Mode
453                         0x00,//2dummy bytes
454                         0x00, ZLL_MT_APP_RPC_CMD_SEND_RESET_TO_FN, 0x00, //
455                         0x00, //
456                         0x00 //FCS - fill in later
457                         };
459         calcFcs(cmd, sizeof(cmd));
460         zbSocTransportWrite(cmd, sizeof(cmd));
463 /*********************************************************************
464  * @fn      zbSocOpenNwk
465  *
466  * @brief   Send the open network command to a ZLL device.
467  *
468  * @param   none
469  *
470  * @return  none
471  */
472 void zbSocOpenNwk(uint8_t duration)
474         uint16_t srcNwkAddr = 0xFFFD; //Everyone with RxOnWhenIdle == TRUE
476         uint8_t mgmtPermit[] =
477         { 0xFE, 5, /*RPC payload Len */
478         MT_RPC_CMD_SREQ | MT_RPC_SYS_ZDO,
479         0x36, /*MT_ZDO_MGMT_PERMIT_JOIN_REQ*/
480         afAddrBroadcast, //addr mode
481         (srcNwkAddr & 0x00ff), /*Src Nwk Addr - To send the bind message to*/
482         (srcNwkAddr & 0xff00) >> 8, /*Src Nwk Addr - To send the bind message to*/
483         duration, /*Dst endpoint for the binding*/
484         1, /*trust center significance set*/
485         0x00 //FCS - fill in later
486         };
488         uint8_t localPermit[] =
489         { APPCMDHEADER(13) 0x06, //Data Len
490                         0x02, //Address Mode
491                         0x00,//2dummy bytes
492                         0x00, ZLL_MT_APP_RPC_CMD_PERMIT_JOIN,
493                         duration, //
494                         0x00, //
495                         0x00 //FCS - fill in later
496                         };
498         printf("zbSocOpenNwk: duration %ds\n", duration);
500         calcFcs(localPermit, sizeof(localPermit));
501         zbSocTransportWrite(localPermit, sizeof(localPermit));
503         //wait for message to be consumed
504         usleep(30);
506         calcFcs(mgmtPermit, sizeof(mgmtPermit));
507         zbSocTransportWrite(mgmtPermit, sizeof(mgmtPermit));
510 /*********************************************************************
511  * @fn      zbSocSendIdentify
512  *
513  * @brief   Send identify command to a ZLL light.
514  *
515  * @param   identifyTime - in s.
516  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
517  * @param   endpoint - endpoint of the Light.
518  * @param   addrMode - Unicast or Group cast.
519  *
520  * @return  none
521  */
522 void zbSocSendIdentify(uint16_t identifyTime, uint16_t dstAddr,
523                 uint8_t endpoint, uint8_t addrMode)
525         uint8_t cmd[] =
526         { 0xFE,
527                         13, //RPC payload Len
528                         0x29, //MT_RPC_CMD_AREQ + MT_RPC_SYS_APP
529                         0x00, //MT_APP_MSG
530                         0x0B, //Application Endpoint
531                         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8,
532                         endpoint, //Dst EP
533                         (ZCL_CLUSTER_ID_GEN_IDENTIFY & 0x00ff),
534                         (ZCL_CLUSTER_ID_GEN_IDENTIFY & 0xff00) >> 8, 0x06, //Data Len
535                         addrMode, 0x01, //0x01 ZCL frame control field.  (send to the light cluster only)
536                         transSeqNumber++, COMMAND_IDENTIFY, (identifyTime
537                                         & 0xff), (identifyTime & 0xff00) >> 8, 0x00 //FCS - fill in later
538                         };
540         calcFcs(cmd, sizeof(cmd));
542         zbSocTransportWrite(cmd, sizeof(cmd));
544         printf("zbSocSendIdentify: dstAddr=%x, endpoint=%x, addrMode=%x, identifyTime=%x\n",
545                         dstAddr, endpoint, addrMode, identifyTime);
548 /*********************************************************************
549  * @fn      COMMAND_IDENTIFY_TRIGGER_EFFECT
550  *
551  * @brief   Send identify command to a ZLL light.
552  *
553  * @param   effect - effect.
554  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
555  * @param   endpoint - endpoint of the Light.
556  * @param   addrMode - Unicast or Group cast.
557  *
558  * @return  none
559  */
560 void zbSocSendIdentifyEffect(uint8_t effect, uint8_t effectVarient, uint16_t dstAddr,
561                 uint8_t endpoint, uint8_t addrMode)
563         uint8_t cmd[] =
564         { 0xFE,
565                         13, //RPC payload Len
566                         0x29, //MT_RPC_CMD_AREQ + MT_RPC_SYS_APP
567                         0x00, //MT_APP_MSG
568                         0x0B, //Application Endpoint
569                         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8,
570                         endpoint, //Dst EP
571                         (ZCL_CLUSTER_ID_GEN_IDENTIFY & 0x00ff),
572                         (ZCL_CLUSTER_ID_GEN_IDENTIFY & 0xff00) >> 8, 0x06, //Data Len
573                         addrMode, 0x01, //0x01 ZCL frame control field.  (send to the light cluster only)
574                         transSeqNumber++, COMMAND_IDENTIFY_TRIGGER_EFFECT, effect,
575                         effectVarient, 0x00 //FCS - fill in later
576                         };
578         calcFcs(cmd, sizeof(cmd));
580         zbSocTransportWrite(cmd, sizeof(cmd));
582         printf("zbSocSendIdentify: dstAddr=%x, endpoint=%x, addrMode=%x, effect=%x\n",
583                         dstAddr, endpoint, addrMode, effect);
586 /*********************************************************************
587  * @fn      zbSocSetState
588  *
589  * @brief   Send the on/off command to a ZLL light.
590  *
591  * @param   state - 0: Off, 1: On.
592  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
593  * @param   endpoint - endpoint of the Light.
594  * @param   addrMode - Unicast or Group cast.
595  *
596  * @return  none
597  */
598 void zbSocSetState(uint8_t state, uint16_t dstAddr, uint8_t endpoint,
599                 uint8_t addrMode)
601         uint8_t cmd[] =
602         { 0xFE, 11, /*RPC payload Len */
603         0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
604         0x00, /*MT_APP_MSG  */
605         0x0B, /*Application Endpoint */
606         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8, endpoint, /*Dst EP */
607         (ZCL_CLUSTER_ID_GEN_ON_OFF & 0x00ff), (ZCL_CLUSTER_ID_GEN_ON_OFF & 0xff00)
608                         >> 8, 0x04, //Data Len
609                         addrMode, 0x01, //0x01 ZCL frame control field.  (send to the light cluster only)
610                         transSeqNumber++, (state ? 1 : 0), 0x00 //FCS - fill in later
611                         };
613         calcFcs(cmd, sizeof(cmd));
614         zbSocTransportWrite(cmd, sizeof(cmd));
617 /*********************************************************************
618  * @fn      zbSocSetLevel
619  *
620  * @brief   Send the level command to a ZLL light.
621  *
622  * @param   level - 0-128 = 0-100%
623  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
624  * @param   endpoint - endpoint of the Light.
625  * @param   addrMode - Unicast or Group cast.
626  *
627  * @return  none
628  */
629 void zbSocSetLevel(uint8_t level, uint16_t time, uint16_t dstAddr,
630                 uint8_t endpoint, uint8_t addrMode)
632         uint8_t cmd[] =
633         { 0xFE,
634                         14, //RPC payload Len
635                         0x29, //MT_RPC_CMD_AREQ + MT_RPC_SYS_APP
636                         0x00, //MT_APP_MSG
637                         0x0B, //Application Endpoint
638                         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8,
639                         endpoint, //Dst EP
640                         (ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL & 0x00ff),
641                         (ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL & 0xff00) >> 8, 0x07, //Data Len
642                         addrMode, 0x01, //0x01 ZCL frame control field.  (send to the light cluster only)
643                         transSeqNumber++, COMMAND_LEVEL_MOVE_TO_LEVEL, (level & 0xff), (time
644                                         & 0xff), (time & 0xff00) >> 8, 0x00 //FCS - fill in later
645                         };
647         calcFcs(cmd, sizeof(cmd));
649         zbSocTransportWrite(cmd, sizeof(cmd));
651         printf("zbSocSetLevel: dstAddr=%x, endpoint=%x, addrMode=%x, level=%x\n",
652                         dstAddr, endpoint, addrMode, level);
655 /*********************************************************************
656  * @fn      zbSocSetHue
657  *
658  * @brief   Send the hue command to a ZLL light.
659  *
660  * @param   hue - 0-128 represent the 360Deg hue color wheel : 0=red, 42=blue, 85=green  
661  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
662  * @param   endpoint - endpoint of the Light.
663  * @param   addrMode - Unicast or Group cast.
664  *
665  * @return  none
666  */
667 void zbSocSetHue(uint8_t hue, uint16_t time, uint16_t dstAddr, uint8_t endpoint,
668                 uint8_t addrMode)
670         uint8_t cmd[] =
671         { 0xFE,
672                         15, //RPC payload Len
673                         0x29, //MT_RPC_CMD_AREQ + MT_RPC_SYS_APP
674                         0x00, //MT_APP_MSG
675                         0x0B, //Application Endpoint
676                         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8,
677                         endpoint, //Dst EP
678                         (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0x00ff),
679                         (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0xff00) >> 8, 0x08, //Data Len
680                         addrMode, 0x01, //0x01 ZCL frame control field.  (send to the light cluster only)
681                         transSeqNumber++, COMMAND_LIGHTING_MOVE_TO_HUE, (hue & 0xff), 0x00, //Move with shortest distance
682                         (time & 0xff), (time & 0xff00) >> 8, 0x00 //FCS - fill in later
683                         };
685         calcFcs(cmd, sizeof(cmd));
686         zbSocTransportWrite(cmd, sizeof(cmd));
689 /*********************************************************************
690  * @fn      zbSocSetSat
691  *
692  * @brief   Send the satuartion command to a ZLL light.
693  *
694  * @param   sat - 0-128 : 0=white, 128: fully saturated color  
695  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
696  * @param   endpoint - endpoint of the Light.
697  * @param   addrMode - Unicast or Group cast.
698  *
699  * @return  none
700  */
701 void zbSocSetSat(uint8_t sat, uint16_t time, uint16_t dstAddr, uint8_t endpoint,
702                 uint8_t addrMode)
704         uint8_t cmd[] =
705         { 0xFE,
706                         14, //RPC payload Len
707                         0x29, //MT_RPC_CMD_AREQ + MT_RPC_SYS_APP
708                         0x00, //MT_APP_MSG
709                         0x0B, //Application Endpoint
710                         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8,
711                         endpoint, //Dst EP
712                         (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0x00ff),
713                         (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0xff00) >> 8, 0x07, //Data Len
714                         addrMode, 0x01, //0x01 ZCL frame control field.  (send to the light cluster only)
715                         transSeqNumber++, COMMAND_LIGHTING_MOVE_TO_SATURATION, (sat & 0xff), (time
716                                         & 0xff), (time & 0xff00) >> 8, 0x00 //FCS - fill in later
717                         };
719         calcFcs(cmd, sizeof(cmd));
720         zbSocTransportWrite(cmd, sizeof(cmd));
723 /*********************************************************************
724  * @fn      zbSocSetHueSat
725  *
726  * @brief   Send the hue and satuartion command to a ZLL light.
727  *
728  * @param   hue - 0-128 represent the 360Deg hue color wheel : 0=red, 42=blue, 85=green  
729  * @param   sat - 0-128 : 0=white, 128: fully saturated color  
730  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
731  * @param   endpoint - endpoint of the Light.
732  * @param   addrMode - Unicast or Group cast.
733  *
734  * @return  none
735  */
736 void zbSocSetHueSat(uint8_t hue, uint8_t sat, uint16_t time, uint16_t dstAddr,
737                 uint8_t endpoint, uint8_t addrMode)
739         uint8_t cmd[] =
740         { 0xFE,
741                         15, //RPC payload Len
742                         0x29, //MT_RPC_CMD_AREQ + MT_RPC_SYS_APP
743                         0x00, //MT_APP_MSG
744                         0x0B, //Application Endpoint
745                         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8,
746                         endpoint, //Dst EP
747                         (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0x00ff),
748                         (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0xff00) >> 8, 0x08, //Data Len
749                         addrMode, 0x01, //ZCL Header Frame Control
750                         transSeqNumber++, 0x06, //ZCL Header Frame Command (COMMAND_LEVEL_MOVE_TO_HUE_AND_SAT)
751                         hue, //HUE - fill it in later
752                         sat, //SAT - fill it in later
753                         (time & 0xff), (time & 0xff00) >> 8, 0x00 //fcs
754                         };
756         calcFcs(cmd, sizeof(cmd));
757         zbSocTransportWrite(cmd, sizeof(cmd));
760 /*********************************************************************
761  * @fn      zbSocAddGroup
762  *
763  * @brief   Add Group.
764  *
765  * @param   groupId - Group ID of the Scene.
766  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
767  * @param   endpoint - endpoint of the Light.
768  * @param   addrMode - Unicast or Group cast. 
769  *
770  * @return  none
771  */
772 void zbSocAddGroup(uint16_t groupId, uint16_t dstAddr, uint8_t endpoint,
773                 uint8_t addrMode)
775         uint8_t cmd[] =
776         { 0xFE, 14, /*RPC payload Len */
777         0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
778         0x00, /*MT_APP_MSG  */
779         0x0B, /*Application Endpoint */
780         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8, endpoint, /*Dst EP */
781         (ZCL_CLUSTER_ID_GEN_GROUPS & 0x00ff), (ZCL_CLUSTER_ID_GEN_GROUPS & 0xff00)
782                         >> 8,
783                         0x07, //Data Len
784                         addrMode,
785                         0x01, //0x01 ZCL frame control field.  (send to the light cluster only)
786                         transSeqNumber++, COMMAND_GROUP_ADD, (groupId & 0x00ff),
787                         (groupId & 0xff00) >> 8, 0, //Null group name - Group Name not pushed to the devices
788                         0x00 //FCS - fill in later
789                         };
791         printf("zbSocAddGroup: dstAddr 0x%x\n", dstAddr);
793         calcFcs(cmd, sizeof(cmd));
794         zbSocTransportWrite(cmd, sizeof(cmd));
797 /*********************************************************************
798  * @fn      zbSocStoreScene
799  *
800  * @brief   Store Scene.
801  * 
802  * @param   groupId - Group ID of the Scene.
803  * @param   sceneId - Scene ID of the Scene.
804  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
805  * @param   endpoint - endpoint of the Light.
806  * @param   addrMode - Unicast or Group cast. 
807  *
808  * @return  none
809  */
810 void zbSocStoreScene(uint16_t groupId, uint8_t sceneId, uint16_t dstAddr,
811                 uint8_t endpoint, uint8_t addrMode)
813         uint8_t cmd[] =
814         { 0xFE, 14, /*RPC payload Len */
815         0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
816         0x00, /*MT_APP_MSG  */
817         0x0B, /*Application Endpoint */
818         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8, endpoint, /*Dst EP */
819         (ZCL_CLUSTER_ID_GEN_SCENES & 0x00ff), (ZCL_CLUSTER_ID_GEN_SCENES & 0xff00)
820                         >> 8, 0x07, //Data Len
821                         addrMode, 0x01, //0x01 ZCL frame control field.  (send to the light cluster only)
822                         transSeqNumber++, COMMAND_SCENE_STORE, (groupId & 0x00ff), (groupId
823                                         & 0xff00) >> 8, sceneId++, 0x00 //FCS - fill in later
824                         };
826         calcFcs(cmd, sizeof(cmd));
827         zbSocTransportWrite(cmd, sizeof(cmd));
830 /*********************************************************************
831  * @fn      zbSocRecallScene
832  *
833  * @brief   Recall Scene.
834  *
835  * @param   groupId - Group ID of the Scene.
836  * @param   sceneId - Scene ID of the Scene.
837  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be controled. 
838  * @param   endpoint - endpoint of the Light.
839  * @param   addrMode - Unicast or Group cast. 
840  
841  * @return  none
842  */
843 void zbSocRecallScene(uint16_t groupId, uint8_t sceneId, uint16_t dstAddr,
844                 uint8_t endpoint, uint8_t addrMode)
846         uint8_t cmd[] =
847         { 0xFE, 14, /*RPC payload Len */
848         0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
849         0x00, /*MT_APP_MSG  */
850         0x0B, /*Application Endpoint */
851         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8, endpoint, /*Dst EP */
852         (ZCL_CLUSTER_ID_GEN_SCENES & 0x00ff), (ZCL_CLUSTER_ID_GEN_SCENES & 0xff00)
853                         >> 8, 0x07, //Data Len
854                         addrMode, 0x01, //0x01 ZCL frame control field.  (send to the light cluster only)
855                         transSeqNumber++, COMMAND_SCENE_RECALL, (groupId & 0x00ff), (groupId
856                                         & 0xff00) >> 8, sceneId++, 0x00 //FCS - fill in later
857                         };
859         calcFcs(cmd, sizeof(cmd));
860         zbSocTransportWrite(cmd, sizeof(cmd));
863 /*********************************************************************
864  * @fn      zbSocBind
865  *
866  * @brief   Recall Scene.
867  *
868  * @param   
869  *
870  * @return  none
871  */
872 void zbSocBind(uint16_t srcNwkAddr, uint8_t srcEndpoint, uint8_t srcIEEE[8],
873                 uint8_t dstEndpoint, uint8_t dstIEEE[8], uint16_t clusterID)
875         uint8_t cmd[] =
876         { 0xFE, 23, /*RPC payload Len */
877         MT_RPC_CMD_SREQ | MT_RPC_SYS_ZDO,
878         0x21, /*MT_ZDO_BIND_REQ*/
879         (srcNwkAddr & 0x00ff), /*Src Nwk Addr - To send the bind message to*/
880         (srcNwkAddr & 0xff00) >> 8, /*Src Nwk Addr - To send the bind message to*/
881         srcIEEE[0], /*Src IEEE Addr for the binding*/
882         srcIEEE[1], /*Src IEEE Addr for the binding*/
883         srcIEEE[2], /*Src IEEE Addr for the binding*/
884         srcIEEE[3], /*Src IEEE Addr for the binding*/
885         srcIEEE[4], /*Src IEEE Addr for the binding*/
886         srcIEEE[5], /*Src IEEE Addr for the binding*/
887         srcIEEE[6], /*Src IEEE Addr for the binding*/
888         srcIEEE[7], /*Src IEEE Addr for the binding*/
889         srcEndpoint, /*Src endpoint for the binding*/
890         (clusterID & 0x00ff), /*cluster ID to bind*/
891         (clusterID & 0xff00) >> 8, /*cluster ID to bind*/
892         afAddr64Bit, /*Addr mode of the dst to bind*/
893         dstIEEE[0], /*Dst IEEE Addr for the binding*/
894         dstIEEE[1], /*Dst IEEE Addr for the binding*/
895         dstIEEE[2], /*Dst IEEE Addr for the binding*/
896         dstIEEE[3], /*Dst IEEE Addr for the binding*/
897         dstIEEE[4], /*Dst IEEE Addr for the binding*/
898         dstIEEE[5], /*Dst IEEE Addr for the binding*/
899         dstIEEE[6], /*Dst IEEE Addr for the binding*/
900         dstIEEE[7], /*Dst IEEE Addr for the binding*/
901         dstEndpoint, /*Dst endpoint for the binding*/
902         0x00 //FCS - fill in later
903                         };
905         /*printf("zbSocBind: srcNwkAddr=0x%x, srcEndpoint=0x%x, srcIEEE=0x%x:%x:%x:%x:%x:%x:%x:%x, dstEndpoint=0x%x, dstIEEE=0x%x:%x:%x:%x:%x:%x:%x:%x, clusterID:%x\n",
906          srcNwkAddr, srcEndpoint, srcIEEE[0], srcIEEE[1], srcIEEE[2], srcIEEE[3], srcIEEE[4], srcIEEE[5], srcIEEE[6], srcIEEE[7],
907          srcEndpoint, dstIEEE[0], dstIEEE[1], dstIEEE[2], dstIEEE[3], dstIEEE[4], dstIEEE[5], dstIEEE[6], dstIEEE[7], clusterID);*/
909         calcFcs(cmd, sizeof(cmd));
910         zbSocTransportWrite(cmd, sizeof(cmd));
913 void zbSocGetInfo(void)
915         uint8_t cmd[] =
916         { 0xFE, 0, /*RPC payload Len */
917         MT_RPC_CMD_SREQ | MT_RPC_SYS_UTIL,
918         MT_UTIL_GET_DEVICE_INFO,
919         0x00 //FCS - fill in later
920         };
922         //printf("zbSocGetInfo++ \n");
924         calcFcs(cmd, sizeof(cmd));
925         zbSocTransportWrite(cmd, sizeof(cmd));
928 /*********************************************************************
929  * @fn      zbSocGetState
930  *
931  * @brief   Send the get state command to a ZLL light.
932  *
933  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be sent the command.
934  * @param   endpoint - endpoint of the Light.
935  * @param   addrMode - Unicast or Group cast.
936  *
937  * @return  none
938  */
939 void zbSocGetState(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
941         uint8_t cmd[] =
942         { 0xFE, 13, /*RPC payload Len */
943         0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
944         0x00, /*MT_APP_MSG  */
945         0x0B, /*Application Endpoint */
946         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8, endpoint, /*Dst EP */
947         (ZCL_CLUSTER_ID_GEN_ON_OFF & 0x00ff), (ZCL_CLUSTER_ID_GEN_ON_OFF & 0xff00)
948                         >> 8, 0x06, //Data Len
949                         addrMode, 0x00, //0x00 ZCL frame control field.  not specific to a cluster (i.e. a SCL founadation command)
950                         transSeqNumber++, ZCL_CMD_READ, (ATTRID_ON_OFF & 0x00ff), (ATTRID_ON_OFF
951                                         & 0xff00) >> 8, 0x00 //FCS - fill in later
952                         };
954         calcFcs(cmd, sizeof(cmd));
955         zbSocTransportWrite(cmd, sizeof(cmd));
958 /*********************************************************************
959  * @fn      zbSocGetLevel
960  *
961  * @brief   Send the get level command to a ZLL light.
962  *
963  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be sent the command.
964  * @param   endpoint - endpoint of the Light.
965  * @param   addrMode - Unicast or Group cast.
966  *
967  * @return  none
968  */
969 void zbSocGetLevel(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
971         uint8_t cmd[] =
972         { 0xFE, 13, /*RPC payload Len */
973         0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
974         0x00, /*MT_APP_MSG  */
975         0x0B, /*Application Endpoint */
976         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8, endpoint, /*Dst EP */
977         (ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL & 0x00ff), (ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL
978                         & 0xff00) >> 8,
979                         0x06, //Data Len
980                         addrMode,
981                         0x00, //0x00 ZCL frame control field.  not specific to a cluster (i.e. a SCL founadation command)
982                         transSeqNumber++, ZCL_CMD_READ, (ATTRID_LEVEL_CURRENT_LEVEL & 0x00ff),
983                         (ATTRID_LEVEL_CURRENT_LEVEL & 0xff00) >> 8, 0x00 //FCS - fill in later
984                         };
986         calcFcs(cmd, sizeof(cmd));
987         zbSocTransportWrite(cmd, sizeof(cmd));
990 /*********************************************************************
991  * @fn      zbSocGetHue
992  *
993  * @brief   Send the get hue command to a ZLL light.
994  *
995  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be sent the command.
996  * @param   endpoint - endpoint of the Light.
997  * @param   addrMode - Unicast or Group cast.
998  *
999  * @return  none
1000  */
1001 void zbSocGetHue(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
1003         uint8_t cmd[] =
1004         { 0xFE, 13, /*RPC payload Len */
1005         0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
1006         0x00, /*MT_APP_MSG  */
1007         0x0B, /*Application Endpoint */
1008         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8, endpoint, /*Dst EP */
1009         (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0x00ff),
1010                         (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0xff00) >> 8,
1011                         0x06, //Data Len
1012                         addrMode,
1013                         0x00, //0x00 ZCL frame control field.  not specific to a cluster (i.e. a SCL founadation command)
1014                         transSeqNumber++, ZCL_CMD_READ, (ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_HUE
1015                                         & 0x00ff), (ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_HUE & 0xff00) >> 8,
1016                         0x00 //FCS - fill in later
1017                         };
1019         calcFcs(cmd, sizeof(cmd));
1020         zbSocTransportWrite(cmd, sizeof(cmd));
1023 /*********************************************************************
1024  * @fn      zbSocGetSat
1025  *
1026  * @brief   Send the get saturation command to a ZLL light.
1027  *
1028  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be sent the command.
1029  * @param   endpoint - endpoint of the Light.
1030  * @param   addrMode - Unicast or Group cast.
1031  *
1032  * @return  none
1033  */
1034 void zbSocGetSat(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
1036         uint8_t cmd[] =
1037         { 0xFE, 13, /*RPC payload Len */
1038         0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
1039         0x00, /*MT_APP_MSG  */
1040         0x0B, /*Application Endpoint */
1041         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8, endpoint, /*Dst EP */
1042         (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0x00ff),
1043                         (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0xff00) >> 8,
1044                         0x06, //Data Len
1045                         addrMode,
1046                         0x00, //0x00 ZCL frame control field.  not specific to a cluster (i.e. a SCL founadation command)
1047                         transSeqNumber++, ZCL_CMD_READ,
1048                         (ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_SATURATION & 0x00ff),
1049                         (ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_SATURATION & 0xff00) >> 8, 0x00 //FCS - fill in later
1050                         };
1052         calcFcs(cmd, sizeof(cmd));
1053         zbSocTransportWrite(cmd, sizeof(cmd));
1056 /*********************************************************************
1057  * @fn      zbSocGetModel
1058  *
1059  * @brief   Send the get saturation command to a ZLL light.
1060  *
1061  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be sent the command.
1062  * @param   endpoint - endpoint of the Light.
1063  * @param   addrMode - Unicast or Group cast.
1064  *
1065  * @return  none
1066  */
1067 void zbSocGetModel(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
1069         uint8_t cmd[] =
1070         { 0xFE, 13, /*RPC payload Len */
1071         0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
1072         0x00, /*MT_APP_MSG  */
1073         0x0B, /*Application Endpoint */
1074         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8, endpoint, /*Dst EP */
1075         (ZCL_CLUSTER_ID_GEN_BASIC & 0x00ff),
1076                         (ZCL_CLUSTER_ID_GEN_BASIC & 0xff00) >> 8,
1077                         0x06, //Data Len
1078                         addrMode,
1079                         0x00, //0x00 ZCL frame control field.  not specific to a cluster (i.e. a SCL foundation command)
1080                         transSeqNumber++, ZCL_CMD_READ,
1081                         (ATTRID_BASIC_MODEL_ID & 0x00ff),
1082                         (ATTRID_BASIC_MODEL_ID & 0xff00) >> 8,
1083                         0x00 //FCS - fill in later
1084                         };
1086         //printf("zbSocGetModel: dstAddr:%x, endpoint:%x, addrMode:%x\n", dstAddr, endpoint, addrMode);
1088         calcFcs(cmd, sizeof(cmd));
1089         zbSocTransportWrite(cmd, sizeof(cmd));
1092 /*************************************************************************************************
1093  * @fn      processRpcSysAppTlInd()
1094  *
1095  * @brief  process the TL Indication from the ZLL controller
1096  *
1097  * @param   none
1098  *
1099  * @return  length of current Rx Buffer
1100  *************************************************************************************************/
1101 static void processRpcSysAppTlInd(uint8_t *TlIndBuff)
1103         epInfo_t epInfo;
1105         epInfo.nwkAddr = BUILD_UINT16(TlIndBuff[0], TlIndBuff[1]);
1106         TlIndBuff += 2;
1107         epInfo.endpoint = *TlIndBuff++;
1108         epInfo.profileID = BUILD_UINT16(TlIndBuff[0], TlIndBuff[1]);
1109         TlIndBuff += 2;
1110         epInfo.deviceID = BUILD_UINT16(TlIndBuff[0], TlIndBuff[1]);
1111         TlIndBuff += 2;
1112         epInfo.version = *TlIndBuff++;
1113         epInfo.status = *TlIndBuff++;
1115         if (zbSocCb.pfnTlIndicationCb)
1116         {
1117                 zbSocCb.pfnTlIndicationCb(&epInfo);
1118         }
1121 /*************************************************************************************************
1122  * @fn      processRpcSysAppZcl()
1123  *
1124  * @brief  process the ZCL Rsp from the ZLL controller
1125  *
1126  * @param   none
1127  *
1128  * @return  length of current Rx Buffer
1129  *************************************************************************************************/
1130 static void processRpcSysAppZcl(uint8_t *zclRspBuff)
1132         uint8_t zclHdrLen = 3;
1133         uint16_t nwkAddr, clusterID;
1134         uint8_t endpoint, zclFrameLen, zclFrameFrameControl;
1136         //printf("processRpcSysAppZcl++\n");
1138         //This is a ZCL response
1140         //Index past app EP
1141         zclRspBuff++;
1142         nwkAddr = BUILD_UINT16(zclRspBuff[0], zclRspBuff[1]);
1143         zclRspBuff += 2;
1145         endpoint = *zclRspBuff++;
1146         clusterID = BUILD_UINT16(zclRspBuff[0], zclRspBuff[1]);
1147         zclRspBuff += 2;
1149         zclFrameLen = *zclRspBuff++;
1150         zclFrameFrameControl = *zclRspBuff++;
1151         //is it manufacturer specific
1152         if (zclFrameFrameControl & (1 << 2))
1153         {
1154                 //currently not supported shown for reference
1155                 uint16_t ManSpecCode;
1156                 //manu spec code
1157                 ManSpecCode = BUILD_UINT16(zclRspBuff[0], zclRspBuff[1]);
1158                 zclRspBuff += 2;
1159                 //Manufacturer specif commands have 2 extra byte in te header
1160                 zclHdrLen += 2;
1162                 //supress warning
1163                 (void)ManSpecCode;
1164         }
1166         //is this a foundation command
1167         if ((zclFrameFrameControl & 0x3) == 0)
1168         {
1169                 //printf("processRpcSysAppZcl: Foundation messagex\n");
1170                 processRpcSysAppZclFoundation(zclRspBuff, zclFrameLen, clusterID, nwkAddr,
1171                                 endpoint);
1172         }
1175 /*************************************************************************************************
1176  * @fn      processRpcSysAppZclFoundation()
1177  *
1178  * @brief  process the ZCL Rsp from the ZLL controller
1179  *
1180  * @param   none
1181  *
1182  * @return  length of current Rx Buffer
1183  *************************************************************************************************/
1184 static void processRpcSysAppZclFoundation(uint8_t *zclRspBuff,
1185                 uint8_t zclFrameLen, uint16_t clusterID, uint16_t nwkAddr, uint8_t endpoint)
1187         uint8_t transSeqNum, commandID;
1189         transSeqNum = *zclRspBuff++;
1190         commandID = *zclRspBuff++;
1192         if (commandID == ZCL_CMD_READ_RSP)
1193         {
1194                 uint16_t attrID;
1195                 uint8_t status;
1196                 uint8_t dataType;
1198                 attrID = BUILD_UINT16(zclRspBuff[0], zclRspBuff[1]);
1199                 zclRspBuff += 2;
1200                 status = *zclRspBuff++;
1201                 //get data type;
1202                 dataType = *zclRspBuff++;
1204                 //printf("processRpcSysAppZclFoundation: clusterID:%x, attrID:%x, dataType=%x\n", clusterID, attrID, dataType);
1205                 if ((clusterID == ZCL_CLUSTER_ID_GEN_BASIC) && (attrID == ATTRID_BASIC_MODEL_ID)
1206                                 && (dataType == ZCL_DATATYPE_CHAR_STR))
1207                 {
1208                         if (zbSocCb.pfnZclGetModelCb)
1209                         {
1210                                 zbSocCb.pfnZclGetModelCb(&zclRspBuff[0]);
1211                         }
1212                 }
1213                 else if ((clusterID == ZCL_CLUSTER_ID_GEN_ON_OFF) && (attrID == ATTRID_ON_OFF)
1214                                 && (dataType == ZCL_DATATYPE_BOOLEAN))
1215                 {
1216                         if (zbSocCb.pfnZclGetStateCb)
1217                         {
1218                                 uint8_t state = zclRspBuff[0];
1219                                 zbSocCb.pfnZclGetStateCb(state, nwkAddr, endpoint);
1220                         }
1221                 }
1222                 else if ((clusterID == ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL)
1223                                 && (attrID == ATTRID_LEVEL_CURRENT_LEVEL)
1224                                 && (dataType == ZCL_DATATYPE_UINT8))
1225                 {
1226                         if (zbSocCb.pfnZclGetLevelCb)
1227                         {
1228                                 uint8_t level = zclRspBuff[0];
1229                                 zbSocCb.pfnZclGetLevelCb(level, nwkAddr, endpoint);
1230                         }
1231                 }
1232                 else if ((clusterID == ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL)
1233                                 && (attrID == ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_HUE)
1234                                 && (dataType == ZCL_DATATYPE_UINT8))
1235                 {
1236                         if (zbSocCb.pfnZclGetHueCb)
1237                         {
1238                                 uint8_t hue = zclRspBuff[0];
1239                                 zbSocCb.pfnZclGetHueCb(hue, nwkAddr, endpoint);
1240                         }
1241                 }
1242                 else if ((clusterID == ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL)
1243                                 && (attrID == ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_SATURATION)
1244                                 && (dataType == ZCL_DATATYPE_UINT8))
1245                 {
1246                         if (zbSocCb.pfnZclGetSatCb)
1247                         {
1248                                 uint8_t sat = zclRspBuff[0];
1249                                 zbSocCb.pfnZclGetSatCb(sat, nwkAddr, endpoint);
1250                         }
1251                 }
1252                 else
1253                 {
1254                         //unsupported ZCL Read Rsp
1255                         printf("processRpcSysAppZclFoundation: Unsupported ZCL Rsp\n");
1256                 }
1257         }
1258         else
1259         {
1260                 //unsupported ZCL Rsp
1261                 printf("processRpcSysAppZclFoundation: Unsupported ZCL Rsp");
1262                 ;
1263         }
1265         return;
1268 /*************************************************************************************************
1269  * @fn      processRpcSysZdoEndDeviceAnnceInd
1270  *
1271  * @brief   read and process the RPC ZDO message from the ZLL controller
1272  *
1273  * @param   none
1274  *
1275  * @return  length of current Rx Buffer
1276  *************************************************************************************************/
1277 void processRpcSysZdoEndDeviceAnnceInd(uint8_t *EndDeviceAnnceIndBuff)
1279         epInfo_t epInfo =       { 0 };
1280         uint8_t i;
1282         EndDeviceAnnceIndBuff += 2;
1283         epInfo.nwkAddr =
1284                         BUILD_UINT16(EndDeviceAnnceIndBuff[0], EndDeviceAnnceIndBuff[1]);
1285         EndDeviceAnnceIndBuff += 2;
1287         printf("processRpcSysZdoEndDeviceAnnceInd nwkAddr: %x, IEEE Addr: ",
1288                         epInfo.nwkAddr);
1290         for (i = 0; i < 8; i++)
1291         {
1292                 epInfo.IEEEAddr[i] = *EndDeviceAnnceIndBuff++;
1293                 printf("%x", epInfo.IEEEAddr[i]);
1294                 if (i < 7) printf(":");
1295         }
1296         printf("\n");
1298         if (zbSocCb.pfnNewDevIndicationCb)
1299         {
1300                 zbSocCb.pfnNewDevIndicationCb(&epInfo);
1301         }
1305 /*************************************************************************************************
1306  * @fn      processRpcSysZdoActiveEPRsp
1307  *
1308  * @brief   read and process the RPC ZDO message from the ZLL controller
1309  *
1310  * @param   none
1311  *
1312  * @return  length of current Rx Buffer
1313  *************************************************************************************************/
1314 void processRpcSysZdoActiveEPRsp(uint8_t *ActiveEPRspBuff)
1316         uint16_t nwkAddr;
1317         uint8_t epCount;
1319         nwkAddr = BUILD_UINT16(ActiveEPRspBuff[0], ActiveEPRspBuff[1]);
1320         ActiveEPRspBuff += 2;
1321         epCount = *ActiveEPRspBuff;
1323         printf("processRpcSysZdoActiveEPRsp nwkAddr: %x, Num Ep's: %d\n", nwkAddr,
1324                         epCount);
1326         //Can be used to check all Ep's have associated ZdoSimpleDesc.
1329 /*************************************************************************************************
1330  * @fn      processRpcSysZdoSimpleDescRsp
1331  *
1332  * @brief   read and process the RPC ZDO message from the ZLL controller
1333  *
1334  * @param   none
1335  *
1336  * @return  length of current Rx Buffer
1337  *************************************************************************************************/
1338 void processRpcSysZdoSimpleDescRsp(uint8_t *SimpleDescRspBuff)
1340         epInfo_t epInfo;
1341         uint8_t numInputClusters, numOutputClusters, clusterIdx;
1342         uint16_t  *inClusters, *outClusters;
1344         SimpleDescRspBuff += 2; //src address
1345         epInfo.status = *SimpleDescRspBuff++; //status..offset 2
1346         epInfo.nwkAddr = BUILD_UINT16(SimpleDescRspBuff[0], SimpleDescRspBuff[1]); //network address
1347         SimpleDescRspBuff += 2; //increment
1348         //printf("processRpcSysZdoSimpleDescRsp: Length:%x \n",SimpleDescRspBuff[0]  );
1349         SimpleDescRspBuff += 1;
1350         epInfo.endpoint = *SimpleDescRspBuff++; //end point
1351         epInfo.profileID = BUILD_UINT16(SimpleDescRspBuff[0], SimpleDescRspBuff[1]); //profile id
1352         SimpleDescRspBuff += 2;
1353         epInfo.deviceID = BUILD_UINT16(SimpleDescRspBuff[0], SimpleDescRspBuff[1]); //device id
1354         SimpleDescRspBuff += 2;
1355         epInfo.version = *SimpleDescRspBuff++;
1356         // epInfo.status = *TlIndBuff++;
1357         epInfo.deviceName = NULL;
1359         printf("processRpcSysZdoSimpleDescRsp: nwkAddr:%x endpoint:%x\n",  epInfo.nwkAddr, epInfo.endpoint);
1361         numInputClusters = *SimpleDescRspBuff++;
1362         inClusters = (uint16_t*) malloc(2*numInputClusters);
1363         if(inClusters)
1364         {
1365                 printf("processRpcSysZdoSimpleDescRsp: inClusters[%d]:\n",  numInputClusters);
1366                 for(clusterIdx = 0; clusterIdx < numInputClusters; clusterIdx++)
1367                 {
1368                         inClusters[clusterIdx] = BUILD_UINT16(SimpleDescRspBuff[0], SimpleDescRspBuff[1]); //profile id
1369                         SimpleDescRspBuff += 2;
1370                         printf("0x%x ", inClusters[clusterIdx]);
1371                 }
1372         }
1373         printf("\n");
1375         numOutputClusters = *SimpleDescRspBuff++;
1376         outClusters = (uint16_t*) malloc(2*numOutputClusters);
1377         if(outClusters)
1378         {
1379                 printf("processRpcSysZdoSimpleDescRsp: outClusters[%d]:\n",  numOutputClusters);
1380                 for(clusterIdx = 0; clusterIdx < numOutputClusters; clusterIdx++)
1381                 {
1382                         outClusters[clusterIdx] = BUILD_UINT16(SimpleDescRspBuff[0], SimpleDescRspBuff[1]); //profile id
1383                         SimpleDescRspBuff += 2;
1384                         printf("0x%x ", outClusters[clusterIdx]);
1385                 }
1386         }
1387         printf("\n");
1389         //if this is the TL endpoint then ignore it
1390         if( !((numInputClusters == 1) && (numOutputClusters == 1) && (epInfo.profileID) == (0xC05E)) )
1391         {
1392                 if (zbSocCb.pfnZdoSimpleDescRspCb)
1393                 {
1394                         zbSocCb.pfnZdoSimpleDescRspCb(&epInfo);
1395                 }
1396         }
1398         if(inClusters)
1399         {
1400                 free(inClusters);
1401         }
1402         if(outClusters)
1403         {
1404                 free(outClusters);
1405         }
1408 void processRpcSysZdoLeaveInd(uint8_t *LeaveIndRspBuff)
1410         uint16_t nwkAddr;
1412         nwkAddr = BUILD_UINT16(LeaveIndRspBuff[0], LeaveIndRspBuff[1]);
1413         LeaveIndRspBuff += 2;
1415         printf("processRpcSysZdoLeaveInd nwkAddr: %x\n", nwkAddr);
1417         if (zbSocCb.pfnZdoLeaveIndCb)
1418         {
1419                 zbSocCb.pfnZdoLeaveIndCb(nwkAddr);
1420         }
1423 void processRpcUtilGetDevInfoRsp(uint8_t *GetDevInfoRsp)
1425         uint8_t ieeeAddr[8], ieeeIdx, devType, devState, status;
1426         uint16_t nwkAddr;
1428         status = *GetDevInfoRsp++;
1430         if(status == 0)
1431         {
1432                 for(ieeeIdx = 0; ieeeIdx < 8; ieeeIdx++)
1433                 {
1434                         ieeeAddr[ieeeIdx] = *GetDevInfoRsp++;
1435                 }
1437                 nwkAddr = BUILD_UINT16(GetDevInfoRsp[0], GetDevInfoRsp[1]);
1438                 GetDevInfoRsp += 2;
1440                 devType = *GetDevInfoRsp++;
1442                 devState = *GetDevInfoRsp++;
1444                 //printf("processRpcUtilGetDevInfoRsp: status:%x devState:%x, nwkAddr:%x ieeeIdx:%x:%x:%x:%x:%x:%x:%x:%x\n", status, devState, nwkAddr,
1445                 //              ieeeAddr[7], ieeeAddr[6], ieeeAddr[5], ieeeAddr[4], ieeeAddr[3], ieeeAddr[2], ieeeAddr[1], ieeeAddr[0]);
1446         }
1448         if (zbSocCb.pfnUtilGetDevInfoRsp)
1449         {
1450                 zbSocCb.pfnUtilGetDevInfoRsp(status, nwkAddr, ieeeAddr, devType, devState);
1451         }
1454 /*************************************************************************************************
1455  * @fn      processRpcSysApp()
1456  *
1457  * @brief   read and process the RPC App message from the ZLL controller
1458  *
1459  * @param   none
1460  *
1461  * @return  length of current Rx Buffer
1462  *************************************************************************************************/
1463 static void processRpcSysApp(uint8_t *rpcBuff)
1465         if (rpcBuff[1] == MT_APP_ZLL_TL_IND)
1466         {
1467                 processRpcSysAppTlInd(&rpcBuff[2]);
1468         }
1470         else if (rpcBuff[1] == MT_APP_RSP)
1471         {
1472                 processRpcSysAppZcl(&rpcBuff[2]);
1473         }
1474         else if (rpcBuff[1] == 0)
1475         {
1476                 if (rpcBuff[2] == 0)
1477                 {
1478                         //printf("processRpcSysApp: Command Received Successfully\n\n");
1479                 }
1480                 else
1481                 {
1482                         printf("processRpcSysApp: Command Error\n\n");
1483                 }
1484         }
1485         else
1486         {
1487                 printf("processRpcSysApp: Unsupported MT App Msg\n");
1488         }
1490         return;
1493 /*************************************************************************************************
1494  * @fn      processRpcSysZdo()
1495  *
1496  * @brief   read and process the RPC ZDO messages from the ZLL controller
1497  *
1498  * @param   none
1499  *
1500  * @return  length of current Rx Buffer
1501  *************************************************************************************************/
1502 void processRpcSysZdo(uint8_t *rpcBuff)
1504         if (rpcBuff[1] == MT_ZDO_END_DEVICE_ANNCE_IND)
1505         {
1506                 processRpcSysZdoEndDeviceAnnceInd(&rpcBuff[2]);
1507         }
1508         else if (rpcBuff[1] == MT_ZDO_ACTIVE_EP_RSP)
1509         {
1510                 processRpcSysZdoActiveEPRsp(&rpcBuff[2]);
1511         }
1512         else if (rpcBuff[1] == MT_ZDO_SIMPLE_DESC_RSP)
1513         {
1514                 processRpcSysZdoSimpleDescRsp(&rpcBuff[2]);
1515         }
1516         else if (rpcBuff[1] == MT_ZDO_LEAVE_IND)
1517         {
1518                 processRpcSysZdoLeaveInd(&rpcBuff[2]);
1519         }
1520         else
1521         {
1522                 printf("processRpcSysZdo: Unsupported MT ZDO Msg\n");
1523         }
1525         return;
1529 /*************************************************************************************************
1530  * @fn      processRpcSysUtil()
1531  *
1532  * @brief   read and process the RPC UTIL messages from the ZLL controller
1533  *
1534  * @param   none
1535  *
1536  * @return  length of current Rx Buffer
1537  *************************************************************************************************/
1538 void processRpcSysUtil(uint8_t *rpcBuff)
1540         if (rpcBuff[1] == MT_UTIL_GET_DEVICE_INFO)
1541         {
1542                 processRpcUtilGetDevInfoRsp(&rpcBuff[2]);
1543         }
1544         else
1545         {
1546                 printf("processRpcSysUtil: Unsupported MT UTIL Msg\n");
1547         }
1549         return;
1553 /* @fn      processRpcSysDbg()
1554  *
1555  * @brief   read and process the RPC debug message from the ZLL controller
1556  *
1557  * @param   none
1558  *
1559  * @return  length of current Rx Buffer
1560  *************************************************************************************************/
1561 static void processRpcSysDbg(uint8_t *rpcBuff)
1563         if (rpcBuff[1] == MT_DEBUG_MSG)
1564         {
1565                 //we got a debug string
1566                 printf("lcd_debug message from zll controller: %s\n",
1567                                 (char*) &(rpcBuff[2]));
1568         }
1569         else if (rpcBuff[1] == 0)
1570         {
1571                 if (rpcBuff[2] == 0)
1572                 {
1573                         //printf("processRpcSysDbg: Command Received Successfully\n\n");
1574                 }
1575                 else
1576                 {
1577                         printf("processRpcSysDbg: Command Error\n\n");
1578                 }
1579         }
1580         else
1581         {
1582                 printf("processRpcSysDbg: Unsupported MT App Msg\n");
1583         }
1586 /*************************************************************************************************
1587  * @fn      zbSocProcessRpc()
1588  *
1589  * @brief   read and process the RPC from the ZLL controller
1590  *
1591  * @param   none
1592  *
1593  * @return  length of current Rx Buffer
1594  *************************************************************************************************/
1595 void zbSocProcessRpc(void)
1597         uint8_t rpcLen, bytesRead, sofByte, *rpcBuff, rpcBuffIdx;
1598         static uint8_t retryAttempts = 0;
1600         //read first byte and check it is a SOF
1601         read(serialPortFd, &sofByte, 1);
1602         if (sofByte == MT_RPC_SOF)
1603         {
1604                 retryAttempts = 0;
1606                 //read len
1607                 bytesRead = read(serialPortFd, &rpcLen, 1);
1609                 if (bytesRead == 1)
1610                 {
1611                         //allocating RPC payload (+ cmd0, cmd1 and fcs)
1612                         rpcLen += 3;
1614                         rpcBuff = malloc(rpcLen);
1616                         //non blocking read, so we need to wait for the rpc to be read
1617                         rpcBuffIdx = 0;
1618                         while (rpcLen > 0)
1619                         {
1620                                 //read rpc
1621                                 bytesRead = read(serialPortFd, &(rpcBuff[rpcBuffIdx]), rpcLen);
1623                                 //check for error
1624                                 if (bytesRead > rpcLen)
1625                                 {
1626                                         //there was an error
1627                                         printf("zbSocProcessRpc: read of %d bytes failed - %s\n", rpcLen,
1628                                                         strerror(errno));
1630                                         if (retryAttempts++ < 5)
1631                                         {
1632                                                 //sleep for 10ms
1633                                                 usleep(10000);
1634                                                 //try again
1635                                                 bytesRead = 0;
1636                                         }
1637                                         else
1638                                         {
1639                                                 //something went wrong.
1640                                                 printf("zbSocProcessRpc: failed\n");
1641                                                 free(rpcBuff);
1642                                                 return;
1643                                         }
1644                                 }
1646                                 rpcLen -= bytesRead;
1647                                 rpcBuffIdx += bytesRead;
1648                         }
1650                         //printf("zbSocProcessRpc: Processing CMD0:%x, CMD1:%x\n", rpcBuff[0],
1651                         //              rpcBuff[1]);
1652                         //Read CMD0
1653                         switch (rpcBuff[0] & MT_RPC_SUBSYSTEM_MASK)
1654                         {
1655                                 case MT_RPC_SYS_DBG:
1656                                 {
1657                                         processRpcSysDbg(rpcBuff);
1658                                         break;
1659                                 }
1660                                 case MT_RPC_SYS_APP:
1661                                 {
1662                                         processRpcSysApp(rpcBuff);
1663                                         break;
1664                                 }
1666                                 case MT_RPC_SYS_ZDO:
1667                                 {
1668                                         processRpcSysZdo(rpcBuff);
1669                                         break;
1670                                 }
1672                                 case MT_RPC_SYS_UTIL:
1673                                 {
1674                                         processRpcSysUtil(rpcBuff);
1675                                         break;
1676                                 }
1678                                 default:
1679                                 {
1680                                         printf("zbSocProcessRpc: CMD0:%x, CMD1:%x, not handled\n", rpcBuff[0],
1681                                                         rpcBuff[1]);
1682                                         break;
1683                                 }
1684                         }
1686                         free(rpcBuff);
1687                 }
1688                 else
1689                 {
1690                         printf("zbSocProcessRpc: No valid Start Of Frame found\n");
1691                 }
1692         }
1694         return;