22d8fd1c05f5538bacc067265808c0d51b51154e
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)
240 {
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;
251 }
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)
267 {
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;
305 }
307 void zbSocClose(void)
308 {
309 tcflush(serialPortFd, TCOFLUSH);
310 close(serialPortFd);
312 return;
313 }
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)
325 {
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;
349 }
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)
361 {
362 //copy the callback function pointers
363 memcpy(&zbSocCb, &zbSocCallbacks, sizeof(zbSocCallbacks_t));
364 return;
365 }
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)
377 {
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));
389 }
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)
401 {
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));
413 }
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)
425 {
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));
437 }
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)
449 {
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));
461 }
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)
473 {
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));
508 }
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)
524 {
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);
546 }
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)
562 {
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);
584 }
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)
600 {
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));
615 }
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)
631 {
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);
653 }
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)
669 {
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));
687 }
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)
703 {
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));
721 }
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)
738 {
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));
758 }
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)
774 {
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));
795 }
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)
812 {
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));
828 }
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.
841 * @return none
842 */
843 void zbSocRecallScene(uint16_t groupId, uint8_t sceneId, uint16_t dstAddr,
844 uint8_t endpoint, uint8_t addrMode)
845 {
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));
861 }
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)
874 {
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));
911 }
913 void zbSocGetInfo(void)
914 {
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));
926 }
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)
940 {
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));
956 }
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)
970 {
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));
988 }
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)
1002 {
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));
1021 }
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)
1035 {
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));
1054 }
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)
1068 {
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));
1090 }
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)
1102 {
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 }
1119 }
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)
1131 {
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 }
1173 }
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)
1186 {
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;
1266 }
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)
1278 {
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 }
1303 }
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)
1315 {
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.
1327 }
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)
1339 {
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 }
1406 }
1408 void processRpcSysZdoLeaveInd(uint8_t *LeaveIndRspBuff)
1409 {
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 }
1421 }
1423 void processRpcUtilGetDevInfoRsp(uint8_t *GetDevInfoRsp)
1424 {
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 }
1452 }
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)
1464 {
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;
1491 }
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)
1503 {
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;
1527 }
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)
1539 {
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;
1551 }
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)
1562 {
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 }
1584 }
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)
1596 {
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;
1695 }