aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortcave2013-03-20 09:14:17 -0500
committertcave2013-03-20 09:14:17 -0500
commit5e920e84ebbf20213e906a7518803b7740227a7e (patch)
tree2a339c113f23b20a46b7feb8a9a5be88b603cbc5
downloadzllhostinterfaceexample-5e920e84ebbf20213e906a7518803b7740227a7e.tar.gz
zllhostinterfaceexample-5e920e84ebbf20213e906a7518803b7740227a7e.tar.xz
zllhostinterfaceexample-5e920e84ebbf20213e906a7518803b7740227a7e.zip
Initial check in
-rw-r--r--Makefile24
-rw-r--r--Manifest.pdfbin0 -> 123749 bytes
-rw-r--r--readme.txt1
-rw-r--r--zllSocCmd.c1190
-rw-r--r--zllSocCmd.h113
-rw-r--r--zll_controller.c448
6 files changed, 1776 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..abb5d6d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,24 @@
1
2SBU_REV= "0.1"
3
4GCC = gcc
5
6CFLAGS = -Wall -DVERSION_NUMBER=${SBU_REV}
7OBJECTS = zll_controller.o zllSocCmd.o
8
9DEFS += -D_GNU_SOURCE
10
11APP_NAME=zllController.bin
12
13.PHONY: all, clean
14
15${APP_NAME}: ${OBJECTS}
16 $(GCC) $(CFLAGS) $(OBJECTS) -o ${APP_NAME}
17
18%.o: %.c
19 ${GCC} ${CFLAGS} ${INCLUDE} ${DEFS} -c -o $@ $<
20
21all: ${APP_NAME}
22
23clean:
24 rm -rf *.o ${APP_NAME}
diff --git a/Manifest.pdf b/Manifest.pdf
new file mode 100644
index 0000000..ba02bab
--- /dev/null
+++ b/Manifest.pdf
Binary files differ
diff --git a/readme.txt b/readme.txt
new file mode 100644
index 0000000..1d3178f
--- /dev/null
+++ b/readme.txt
@@ -0,0 +1 @@
documentation for this example can be found at http://processors.wiki.ti.com/index.php/ZStack-Lighting-1.0.1_Host_Interface_C_Examples
diff --git a/zllSocCmd.c b/zllSocCmd.c
new file mode 100644
index 0000000..1908662
--- /dev/null
+++ b/zllSocCmd.c
@@ -0,0 +1,1190 @@
1/*
2 * zllSocCmd.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 */
38
39
40/*********************************************************************
41 * INCLUDES
42 */
43#include <termios.h>
44#include <string.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <unistd.h>
48#include <fcntl.h>
49#include <sys/ioctl.h>
50
51#include <errno.h>
52#include <string.h>
53
54#include "zllSocCmd.h"
55
56
57/*********************************************************************
58 * MACROS
59 */
60
61#define APPCMDHEADER(len) \
620xFE, \
63len, /*RPC payload Len */ \
640x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */ \
650x00, /*MT_APP_MSG */ \
660x0B, /*Application Endpoint */ \
670x02, /*short Addr 0x0002 */ \
680x00, /*short Addr 0x0002 */ \
690x0B, /*Dst EP */ \
700xFF, /*Cluster ID 0xFFFF invalid, used for key */ \
710xFF, /*Cluster ID 0xFFFF invalid, used for key */ \
72
73#define BUILD_UINT16(loByte, hiByte) \
74 ((uint16_t)(((loByte) & 0x00FF) + (((hiByte) & 0x00FF) << 8)))
75
76/*********************************************************************
77 * CONSTANTS
78 */
79#define ZLL_MT_APP_RPC_CMD_TOUCHLINK 0x01
80#define ZLL_MT_APP_RPC_CMD_RESET_TO_FN 0x02
81#define ZLL_MT_APP_RPC_CMD_CH_CHANNEL 0x03
82#define ZLL_MT_APP_RPC_CMD_JOIN_HA 0x04
83#define ZLL_MT_APP_RPC_CMD_PERMIT_JOIN 0x05
84#define ZLL_MT_APP_RPC_CMD_SEND_RESET_TO_FN 0x06
85
86#define MT_APP_RSP 0x80
87#define MT_APP_ZLL_TL_IND 0x81
88#define MT_APP_ZLL_NEW_DEV_IND 0x82
89
90#define MT_DEBUG_MSG 0x80
91
92#define COMMAND_LIGHTING_MOVE_TO_HUE 0x00
93#define COMMAND_LIGHTING_MOVE_TO_SATURATION 0x03
94#define COMMAND_LEVEL_MOVE_TO_LEVEL 0x00
95
96/*** Foundation Command IDs ***/
97#define ZCL_CMD_READ 0x00
98#define ZCL_CMD_READ_RSP 0x01
99#define ZCL_CMD_WRITE 0x02
100#define ZCL_CMD_WRITE_UNDIVIDED 0x03
101#define ZCL_CMD_WRITE_RSP 0x04
102
103// General Clusters
104#define ZCL_CLUSTER_ID_GEN_IDENTIFY 0x0003
105#define ZCL_CLUSTER_ID_GEN_GROUPS 0x0004
106#define ZCL_CLUSTER_ID_GEN_SCENES 0x0005
107#define ZCL_CLUSTER_ID_GEN_ON_OFF 0x0006
108#define ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL 0x0008
109// Lighting Clusters
110#define ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL 0x0300
111
112/*******************************/
113/*** Scenes Cluster Commands ***/
114/*******************************/
115#define COMMAND_SCENE_STORE 0x04
116#define COMMAND_SCENE_RECALL 0x05
117
118/*******************************/
119/*** Groups Cluster Commands ***/
120/*******************************/
121#define COMMAND_GROUP_ADD 0x00
122
123#define ATTRID_ON_OFF 0x0000
124#define ATTRID_LEVEL_CURRENT_LEVEL 0x0000
125#define ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_HUE 0x0000
126#define ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_SATURATION 0x0001
127
128/* The 3 MSB's of the 1st command field byte are for command type. */
129#define MT_RPC_CMD_TYPE_MASK 0xE0
130
131/* The 5 LSB's of the 1st command field byte are for the subsystem. */
132#define MT_RPC_SUBSYSTEM_MASK 0x1F
133
134#define MT_RPC_SOF 0xFE
135
136typedef enum {
137 MT_RPC_CMD_POLL = 0x00,
138 MT_RPC_CMD_SREQ = 0x20,
139 MT_RPC_CMD_AREQ = 0x40,
140 MT_RPC_CMD_SRSP = 0x60,
141 MT_RPC_CMD_RES4 = 0x80,
142 MT_RPC_CMD_RES5 = 0xA0,
143 MT_RPC_CMD_RES6 = 0xC0,
144 MT_RPC_CMD_RES7 = 0xE0
145} mtRpcCmdType_t;
146
147typedef enum {
148 MT_RPC_SYS_RES0, /* Reserved. */
149 MT_RPC_SYS_SYS,
150 MT_RPC_SYS_MAC,
151 MT_RPC_SYS_NWK,
152 MT_RPC_SYS_AF,
153 MT_RPC_SYS_ZDO,
154 MT_RPC_SYS_SAPI, /* Simple API. */
155 MT_RPC_SYS_UTIL,
156 MT_RPC_SYS_DBG,
157 MT_RPC_SYS_APP,
158 MT_RPC_SYS_OTA,
159 MT_RPC_SYS_ZNP,
160 MT_RPC_SYS_SPARE_12,
161 MT_RPC_SYS_UBL = 13, // 13 to be compatible with existing RemoTI.
162 MT_RPC_SYS_MAX // Maximum value, must be last (so 14-32 available, not yet assigned).
163} mtRpcSysType_t;
164
165/************************************************************
166 * TYPEDEFS
167 */
168
169/*********************************************************************
170 * GLOBAL VARIABLES
171 */
172
173/*********************************************************************
174 * LOCAL VARIABLES
175 */
176int serialPortFd = 0;
177uint8_t transSeqNumber = 0;
178
179zllSocCallbacks_t zllSocCb;
180
181/*********************************************************************
182 * LOCAL FUNCTIONS
183 */
184void calcFcs(uint8_t *msg, int size);
185
186/*********************************************************************
187 * @fn calcFcs
188 *
189 * @brief populates the Frame Check Sequence of the RPC payload.
190 *
191 * @param msg - pointer to the RPC message
192 *
193 * @return none
194 */
195void calcFcs(uint8_t *msg, int size)
196{
197 uint8_t result = 0;
198 int idx = 1; //skip SOF
199 int len = (size - 1); // skip FCS
200
201 while ((len--) != 0) {
202 result ^= msg[idx++];
203 }
204
205 msg[(size-1)] = result;
206}
207
208/*********************************************************************
209 * API FUNCTIONS
210 */
211
212/*********************************************************************
213 * @fn zllSocOpen
214 *
215 * @brief opens the serial port to the CC253x.
216 *
217 * @param devicePath - path to the UART device
218 *
219 * @return status
220 */
221int32_t zllSocOpen( char *devicePath )
222{
223 struct termios tio;
224
225 /* open the device to be non-blocking (read will return immediatly) */
226 serialPortFd = open(devicePath, O_RDWR | O_NOCTTY | O_NONBLOCK);
227 if (serialPortFd <0)
228 {
229 perror(devicePath);
230 printf("%s open failed\n",devicePath);
231 return(-1);
232 }
233
234 /* c-iflags
235 B115200 : set board rate to 115200
236 CRTSCTS : HW flow control (disabled below)
237 CS8 : 8n1 (8bit,no parity,1 stopbit)
238 CLOCAL : local connection, no modem contol
239 CREAD : enable receiving characters*/
240 tio.c_cflag = B38400 | /*CRTSCTS |*/ CS8 | CLOCAL | CREAD;
241 /* c-iflags
242 ICRNL : maps 0xD (CR) to 0x10 (LR), we do not want this.
243 IGNPAR : ignore bits with parity erros, I guess it is
244 better to ignStateore an erronious bit then interprit it incorrectly. */
245 tio.c_iflag = IGNPAR & ~ICRNL;
246 tio.c_oflag = 0;
247 tio.c_lflag = 0;
248
249 tcflush(serialPortFd, TCIFLUSH);
250 tcsetattr(serialPortFd,TCSANOW,&tio);
251
252 return serialPortFd;
253}
254
255void zllSocClose( void )
256{
257 tcflush(serialPortFd, TCOFLUSH);
258 close(serialPortFd);
259
260 return;
261}
262
263/*********************************************************************
264 * @fn zllSocRegisterCallbacks
265 *
266 * @brief opens the serial port to the CC253x.
267 *
268 * @param devicePath - path to the UART device
269 *
270 * @return status
271 */
272void zllSocRegisterCallbacks( zllSocCallbacks_t zllSocCallbacks)
273{
274 //copy the callback function pointers
275 memcpy(&zllSocCb, &zllSocCallbacks, sizeof(zllSocCallbacks_t));
276 return;
277}
278
279
280/*********************************************************************
281 * @fn zllSocTouchLink
282 *
283 * @brief Send the touchLink command to the CC253x.
284 *
285 * @param none
286 *
287 * @return none
288 */
289void zllSocTouchLink(void)
290{
291 uint8_t tlCmd[] = {
292 APPCMDHEADER(13)
293 0x06, //Data Len
294 0x02, //Address Mode
295 0x00, //2dummy bytes
296 0x00,
297 ZLL_MT_APP_RPC_CMD_TOUCHLINK,
298 0x00, //
299 0x00, //
300 0x00 //FCS - fill in later
301 };
302
303 calcFcs(tlCmd, sizeof(tlCmd));
304 write(serialPortFd,tlCmd, sizeof(tlCmd));
305 tcflush(serialPortFd, TCOFLUSH);
306}
307
308
309/*********************************************************************
310 * @fn zllSocResetToFn
311 *
312 * @brief Send the reset to factory new command to the CC253x.
313 *
314 * @param none
315 *
316 * @return none
317 */
318void zllSocResetToFn(void)
319{
320 uint8_t tlCmd[] = {
321 APPCMDHEADER(13)
322 0x06, //Data Len
323 0x02, //Address Mode
324 0x00, //2dummy bytes
325 0x00,
326 ZLL_MT_APP_RPC_CMD_RESET_TO_FN,
327 0x00, //
328 0x00, //
329 0x00 //FCS - fill in later
330 };
331
332 calcFcs(tlCmd, sizeof(tlCmd));
333 write(serialPortFd,tlCmd, sizeof(tlCmd));
334 tcflush(serialPortFd, TCOFLUSH);
335}
336
337/*********************************************************************
338 * @fn zllSocSendResetToFn
339 *
340 * @brief Send the reset to factory new command to a ZLL device.
341 *
342 * @param none
343 *
344 * @return none
345 */
346void zllSocSendResetToFn(void)
347{
348 uint8_t tlCmd[] = {
349 APPCMDHEADER(13)
350 0x06, //Data Len
351 0x02, //Address Mode
352 0x00, //2dummy bytes
353 0x00,
354 ZLL_MT_APP_RPC_CMD_SEND_RESET_TO_FN,
355 0x00, //
356 0x00, //
357 0x00 //FCS - fill in later
358 };
359
360 calcFcs(tlCmd, sizeof(tlCmd));
361 write(serialPortFd,tlCmd, sizeof(tlCmd));
362 tcflush(serialPortFd, TCOFLUSH);
363}
364
365/*********************************************************************
366 * @fn zllSocSetState
367 *
368 * @brief Send the on/off command to a ZLL light.
369 *
370 * @param state - 0: Off, 1: On.
371 * @param dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
372 * @param endpoint - endpoint of the Light.
373 * @param addrMode - Unicast or Group cast.
374 *
375 * @return none
376 */
377void zllSocSetState(uint8_t state, uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
378{
379 uint8_t cmd[] = {
380 0xFE,
381 11, /*RPC payload Len */
382 0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
383 0x00, /*MT_APP_MSG */
384 0x0B, /*Application Endpoint */
385 (dstAddr & 0x00ff),
386 (dstAddr & 0xff00) >> 8,
387 endpoint, /*Dst EP */
388 (ZCL_CLUSTER_ID_GEN_ON_OFF & 0x00ff),
389 (ZCL_CLUSTER_ID_GEN_ON_OFF & 0xff00) >> 8,
390 0x04, //Data Len
391 addrMode,
392 0x01, //0x01 ZCL frame control field. (send to the light cluster only)
393 transSeqNumber++,
394 (state ? 1:0),
395 0x00 //FCS - fill in later
396 };
397
398 calcFcs(cmd, sizeof(cmd));
399
400 write(serialPortFd,cmd,sizeof(cmd));
401 tcflush(serialPortFd, TCOFLUSH);
402}
403
404/*********************************************************************
405 * @fn zllSocSetLevel
406 *
407 * @brief Send the level command to a ZLL light.
408 *
409 * @param level - 0-128 = 0-100%
410 * @param dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
411 * @param endpoint - endpoint of the Light.
412 * @param addrMode - Unicast or Group cast.
413 *
414 * @return none
415 */
416void zllSocSetLevel(uint8_t level, uint16_t time, uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
417{
418 uint8_t cmd[] = {
419 0xFE,
420 14, //RPC payload Len
421 0x29, //MT_RPC_CMD_AREQ + MT_RPC_SYS_APP
422 0x00, //MT_APP_MSG
423 0x0B, //Application Endpoint
424 (dstAddr & 0x00ff),
425 (dstAddr & 0xff00) >> 8,
426 endpoint, //Dst EP
427 (ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL & 0x00ff),
428 (ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL & 0xff00) >> 8,
429 0x07, //Data Len
430 addrMode,
431 0x01, //0x01 ZCL frame control field. (send to the light cluster only)
432 transSeqNumber++,
433 COMMAND_LEVEL_MOVE_TO_LEVEL,
434 (level & 0xff),
435 (time & 0xff),
436 (time & 0xff00) >> 8,
437 0x00 //FCS - fill in later
438 };
439
440 calcFcs(cmd, sizeof(cmd));
441
442 write(serialPortFd,cmd,sizeof(cmd));
443 tcflush(serialPortFd, TCOFLUSH);
444}
445
446/*********************************************************************
447 * @fn zllSocSetHue
448 *
449 * @brief Send the hue command to a ZLL light.
450 *
451 * @param hue - 0-128 represent the 360Deg hue color wheel : 0=red, 42=blue, 85=green
452 * @param dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
453 * @param endpoint - endpoint of the Light.
454 * @param addrMode - Unicast or Group cast.
455 *
456 * @return none
457 */
458void zllSocSetHue(uint8_t hue, uint16_t time, uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
459{
460 uint8_t cmd[] = {
461 0xFE,
462 15, //RPC payload Len
463 0x29, //MT_RPC_CMD_AREQ + MT_RPC_SYS_APP
464 0x00, //MT_APP_MSG
465 0x0B, //Application Endpoint
466 (dstAddr & 0x00ff),
467 (dstAddr & 0xff00) >> 8,
468 endpoint, //Dst EP
469 (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0x00ff),
470 (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0xff00) >> 8,
471 0x08, //Data Len
472 addrMode,
473 0x01, //0x01 ZCL frame control field. (send to the light cluster only)
474 transSeqNumber++,
475 COMMAND_LIGHTING_MOVE_TO_HUE,
476 (hue & 0xff),
477 0x00, //Move with shortest distance
478 (time & 0xff),
479 (time & 0xff00) >> 8,
480 0x00 //FCS - fill in later
481 };
482
483 calcFcs(cmd, sizeof(cmd));
484 write(serialPortFd,cmd,sizeof(cmd));
485 tcflush(serialPortFd, TCOFLUSH);
486}
487
488/*********************************************************************
489 * @fn zllSocSetSat
490 *
491 * @brief Send the satuartion command to a ZLL light.
492 *
493 * @param sat - 0-128 : 0=white, 128: fully saturated color
494 * @param dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
495 * @param endpoint - endpoint of the Light.
496 * @param addrMode - Unicast or Group cast.
497 *
498 * @return none
499 */
500void zllSocSetSat(uint8_t sat, uint16_t time, uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
501{
502 uint8_t cmd[] = {
503 0xFE,
504 14, //RPC payload Len
505 0x29, //MT_RPC_CMD_AREQ + MT_RPC_SYS_APP
506 0x00, //MT_APP_MSG
507 0x0B, //Application Endpoint
508 (dstAddr & 0x00ff),
509 (dstAddr & 0xff00) >> 8,
510 endpoint, //Dst EP
511 (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0x00ff),
512 (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0xff00) >> 8,
513 0x07, //Data Len
514 addrMode,
515 0x01, //0x01 ZCL frame control field. (send to the light cluster only)
516 transSeqNumber++,
517 COMMAND_LIGHTING_MOVE_TO_SATURATION,
518 (sat & 0xff),
519 (time & 0xff),
520 (time & 0xff00) >> 8,
521 0x00 //FCS - fill in later
522 };
523
524 calcFcs(cmd, sizeof(cmd));
525 write(serialPortFd,cmd,sizeof(cmd));
526 tcflush(serialPortFd, TCOFLUSH);
527}
528
529/*********************************************************************
530 * @fn zllSocSetHueSat
531 *
532 * @brief Send the hue and satuartion command to a ZLL light.
533 *
534 * @param hue - 0-128 represent the 360Deg hue color wheel : 0=red, 42=blue, 85=green
535 * @param sat - 0-128 : 0=white, 128: fully saturated color
536 * @param dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
537 * @param endpoint - endpoint of the Light.
538 * @param addrMode - Unicast or Group cast.
539 *
540 * @return none
541 */
542void zllSocSetHueSat(uint8_t hue, uint8_t sat, uint16_t time, uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
543{
544 uint8_t cmd[] = {
545 0xFE,
546 15, //RPC payload Len
547 0x29, //MT_RPC_CMD_AREQ + MT_RPC_SYS_APP
548 0x00, //MT_APP_MSG
549 0x0B, //Application Endpoint
550 (dstAddr & 0x00ff),
551 (dstAddr & 0xff00) >> 8,
552 endpoint, //Dst EP
553 (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0x00ff),
554 (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0xff00) >> 8,
555 0x08, //Data Len
556 addrMode,
557 0x01, //ZCL Header Frame Control
558 transSeqNumber++,
559 0x06, //ZCL Header Frame Command (COMMAND_LEVEL_MOVE_TO_HUE_AND_SAT)
560 hue, //HUE - fill it in later
561 sat, //SAT - fill it in later
562 (time & 0xff),
563 (time & 0xff00) >> 8,
564 0x00 //fcs
565 };
566
567 calcFcs(cmd, sizeof(cmd));
568 write(serialPortFd,cmd,sizeof(cmd));
569 tcflush(serialPortFd, TCOFLUSH);
570}
571
572/*********************************************************************
573 * @fn zllSocAddGroup
574 *
575 * @brief Add Group.
576 *
577 * @param groupId - Group ID of the Scene.
578 * @param dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
579 * @param endpoint - endpoint of the Light.
580 * @param addrMode - Unicast or Group cast.
581 *
582 * @return none
583 */
584void zllSocAddGroup(uint16_t groupId, uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
585{
586 uint8_t cmd[] = {
587 0xFE,
588 14, /*RPC payload Len */
589 0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
590 0x00, /*MT_APP_MSG */
591 0x0B, /*Application Endpoint */
592 (dstAddr & 0x00ff),
593 (dstAddr & 0xff00) >> 8,
594 endpoint, /*Dst EP */
595 (ZCL_CLUSTER_ID_GEN_GROUPS & 0x00ff),
596 (ZCL_CLUSTER_ID_GEN_GROUPS & 0xff00) >> 8,
597 0x07, //Data Len
598 addrMode,
599 0x01, //0x01 ZCL frame control field. (send to the light cluster only)
600 transSeqNumber++,
601 COMMAND_GROUP_ADD,
602 (groupId & 0x00ff),
603 (groupId & 0xff00) >> 8,
604 0, //Null group name - Group Name not pushed to the devices
605 0x00 //FCS - fill in later
606 };
607
608 printf("zllSocAddGroup: dstAddr 0x%x\n", dstAddr);
609
610 calcFcs(cmd, sizeof(cmd));
611
612 write(serialPortFd,cmd,sizeof(cmd));
613 tcflush(serialPortFd, TCOFLUSH);
614}
615
616/*********************************************************************
617 * @fn zllSocStoreScene
618 *
619 * @brief Store Scene.
620 *
621 * @param groupId - Group ID of the Scene.
622 * @param sceneId - Scene ID of the Scene.
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 */
629void zllSocStoreScene(uint16_t groupId, uint8_t sceneId, uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
630{
631 uint8_t cmd[] = {
632 0xFE,
633 14, /*RPC payload Len */
634 0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
635 0x00, /*MT_APP_MSG */
636 0x0B, /*Application Endpoint */
637 (dstAddr & 0x00ff),
638 (dstAddr & 0xff00) >> 8,
639 endpoint, /*Dst EP */
640 (ZCL_CLUSTER_ID_GEN_SCENES & 0x00ff),
641 (ZCL_CLUSTER_ID_GEN_SCENES & 0xff00) >> 8,
642 0x07, //Data Len
643 addrMode,
644 0x01, //0x01 ZCL frame control field. (send to the light cluster only)
645 transSeqNumber++,
646 COMMAND_SCENE_STORE,
647 (groupId & 0x00ff),
648 (groupId & 0xff00) >> 8,
649 sceneId++,
650 0x00 //FCS - fill in later
651 };
652
653 calcFcs(cmd, sizeof(cmd));
654
655 write(serialPortFd,cmd,sizeof(cmd));
656 tcflush(serialPortFd, TCOFLUSH);
657}
658
659/*********************************************************************
660 * @fn zllSocRecallScene
661 *
662 * @brief Recall Scene.
663 *
664 * @param groupId - Group ID of the Scene.
665 * @param sceneId - Scene ID of the Scene.
666 * @param dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
667 * @param endpoint - endpoint of the Light.
668 * @param addrMode - Unicast or Group cast.
669
670 * @return none
671 */
672void zllSocRecallScene(uint16_t groupId, uint8_t sceneId, uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
673{
674 uint8_t cmd[] = {
675 0xFE,
676 14, /*RPC payload Len */
677 0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
678 0x00, /*MT_APP_MSG */
679 0x0B, /*Application Endpoint */
680 (dstAddr & 0x00ff),
681 (dstAddr & 0xff00) >> 8,
682 endpoint, /*Dst EP */
683 (ZCL_CLUSTER_ID_GEN_SCENES & 0x00ff),
684 (ZCL_CLUSTER_ID_GEN_SCENES & 0xff00) >> 8,
685 0x07, //Data Len
686 addrMode,
687 0x01, //0x01 ZCL frame control field. (send to the light cluster only)
688 transSeqNumber++,
689 COMMAND_SCENE_RECALL,
690 (groupId & 0x00ff),
691 (groupId & 0xff00) >> 8,
692 sceneId++,
693 0x00 //FCS - fill in later
694 };
695
696 calcFcs(cmd, sizeof(cmd));
697
698 write(serialPortFd,cmd,sizeof(cmd));
699 tcflush(serialPortFd, TCOFLUSH);
700}
701
702/*********************************************************************
703 * @fn zllSocGetState
704 *
705 * @brief Send the get state command to a ZLL light.
706 *
707 * @param dstAddr - Nwk Addr or Group ID of the Light(s) to be sent the command.
708 * @param endpoint - endpoint of the Light.
709 * @param addrMode - Unicast or Group cast.
710 *
711 * @return none
712 */
713void zllSocGetState(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
714{
715 uint8_t cmd[] = {
716 0xFE,
717 13, /*RPC payload Len */
718 0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
719 0x00, /*MT_APP_MSG */
720 0x0B, /*Application Endpoint */
721 (dstAddr & 0x00ff),
722 (dstAddr & 0xff00) >> 8,
723 endpoint, /*Dst EP */
724 (ZCL_CLUSTER_ID_GEN_ON_OFF & 0x00ff),
725 (ZCL_CLUSTER_ID_GEN_ON_OFF & 0xff00) >> 8,
726 0x06, //Data Len
727 addrMode,
728 0x00, //0x00 ZCL frame control field. not specific to a cluster (i.e. a SCL founadation command)
729 transSeqNumber++,
730 ZCL_CMD_READ,
731 (ATTRID_ON_OFF & 0x00ff),
732 (ATTRID_ON_OFF & 0xff00) >> 8,
733 0x00 //FCS - fill in later
734 };
735
736 calcFcs(cmd, sizeof(cmd));
737
738 write(serialPortFd,cmd,sizeof(cmd));
739 tcflush(serialPortFd, TCOFLUSH);
740}
741
742/*********************************************************************
743 * @fn zllSocGetLevel
744 *
745 * @brief Send the get level command to a ZLL light.
746 *
747 * @param dstAddr - Nwk Addr or Group ID of the Light(s) to be sent the command.
748 * @param endpoint - endpoint of the Light.
749 * @param addrMode - Unicast or Group cast.
750 *
751 * @return none
752 */
753void zllSocGetLevel(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
754{
755 uint8_t cmd[] = {
756 0xFE,
757 13, /*RPC payload Len */
758 0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
759 0x00, /*MT_APP_MSG */
760 0x0B, /*Application Endpoint */
761 (dstAddr & 0x00ff),
762 (dstAddr & 0xff00) >> 8,
763 endpoint, /*Dst EP */
764 (ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL & 0x00ff),
765 (ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL & 0xff00) >> 8,
766 0x06, //Data Len
767 addrMode,
768 0x00, //0x00 ZCL frame control field. not specific to a cluster (i.e. a SCL founadation command)
769 transSeqNumber++,
770 ZCL_CMD_READ,
771 (ATTRID_LEVEL_CURRENT_LEVEL & 0x00ff),
772 (ATTRID_LEVEL_CURRENT_LEVEL & 0xff00) >> 8,
773 0x00 //FCS - fill in later
774 };
775
776 calcFcs(cmd, sizeof(cmd));
777
778 write(serialPortFd,cmd,sizeof(cmd));
779 tcflush(serialPortFd, TCOFLUSH);
780}
781
782/*********************************************************************
783 * @fn zllSocGetHue
784 *
785 * @brief Send the get hue command to a ZLL light.
786 *
787 * @param dstAddr - Nwk Addr or Group ID of the Light(s) to be sent the command.
788 * @param endpoint - endpoint of the Light.
789 * @param addrMode - Unicast or Group cast.
790 *
791 * @return none
792 */
793void zllSocGetHue(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
794{
795 uint8_t cmd[] = {
796 0xFE,
797 13, /*RPC payload Len */
798 0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
799 0x00, /*MT_APP_MSG */
800 0x0B, /*Application Endpoint */
801 (dstAddr & 0x00ff),
802 (dstAddr & 0xff00) >> 8,
803 endpoint, /*Dst EP */
804 (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0x00ff),
805 (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0xff00) >> 8,
806 0x06, //Data Len
807 addrMode,
808 0x00, //0x00 ZCL frame control field. not specific to a cluster (i.e. a SCL founadation command)
809 transSeqNumber++,
810 ZCL_CMD_READ,
811 (ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_HUE & 0x00ff),
812 (ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_HUE & 0xff00) >> 8,
813 0x00 //FCS - fill in later
814 };
815
816 calcFcs(cmd, sizeof(cmd));
817
818 write(serialPortFd,cmd,sizeof(cmd));
819 tcflush(serialPortFd, TCOFLUSH);
820}
821
822/*********************************************************************
823 * @fn zllSocGetSat
824 *
825 * @brief Send the get saturation command to a ZLL light.
826 *
827 * @param dstAddr - Nwk Addr or Group ID of the Light(s) to be sent the command.
828 * @param endpoint - endpoint of the Light.
829 * @param addrMode - Unicast or Group cast.
830 *
831 * @return none
832 */
833void zllSocGetSat(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
834{
835 uint8_t cmd[] = {
836 0xFE,
837 13, /*RPC payload Len */
838 0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
839 0x00, /*MT_APP_MSG */
840 0x0B, /*Application Endpoint */
841 (dstAddr & 0x00ff),
842 (dstAddr & 0xff00) >> 8,
843 endpoint, /*Dst EP */
844 (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0x00ff),
845 (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0xff00) >> 8,
846 0x06, //Data Len
847 addrMode,
848 0x00, //0x00 ZCL frame control field. not specific to a cluster (i.e. a SCL founadation command)
849 transSeqNumber++,
850 ZCL_CMD_READ,
851 (ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_SATURATION & 0x00ff),
852 (ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_SATURATION & 0xff00) >> 8,
853 0x00 //FCS - fill in later
854 };
855
856 calcFcs(cmd, sizeof(cmd));
857
858 write(serialPortFd,cmd,sizeof(cmd));
859 tcflush(serialPortFd, TCOFLUSH);
860}
861
862/*************************************************************************************************
863 * @fn processRpcSysAppTlInd()
864 *
865 * @brief process the TL Indication from the ZLL controller
866 *
867 * @param none
868 *
869 * @return length of current Rx Buffer
870 *************************************************************************************************/
871void processRpcSysAppTlInd(uint8_t *TlIndBuff)
872{
873 epInfo_t epInfo;
874
875 epInfo.nwkAddr = BUILD_UINT16(TlIndBuff[0], TlIndBuff[1]);
876 TlIndBuff+=2;
877 epInfo.endpoint = *TlIndBuff++;
878 epInfo.profileID = BUILD_UINT16(TlIndBuff[0], TlIndBuff[1]);
879 TlIndBuff+=2;
880 epInfo.deviceID = BUILD_UINT16(TlIndBuff[0], TlIndBuff[1]);
881 TlIndBuff+=2;
882 epInfo.version = *TlIndBuff++;
883 epInfo.status = *TlIndBuff++;
884
885 if(zllSocCb.pfnTlIndicationCb)
886 {
887 zllSocCb.pfnTlIndicationCb(&epInfo);
888 }
889}
890
891/*************************************************************************************************
892 * @fn processRpcSysAppNewDevInd()
893 *
894 * @brief process the New Device Indication from the ZLL controller
895 *
896 * @param none
897 *
898 * @return length of current Rx Buffer
899 *************************************************************************************************/
900void processRpcSysAppNewDevInd(uint8_t *TlIndBuff)
901{
902 epInfo_t epInfo;
903
904
905 epInfo.nwkAddr = BUILD_UINT16(TlIndBuff[0], TlIndBuff[1]);
906 TlIndBuff+=2;
907 epInfo.endpoint = *TlIndBuff++;
908 epInfo.profileID = BUILD_UINT16(TlIndBuff[0], TlIndBuff[1]);
909 TlIndBuff+=2;
910 epInfo.deviceID = BUILD_UINT16(TlIndBuff[0], TlIndBuff[1]);
911 TlIndBuff+=2;
912 epInfo.version = *TlIndBuff++;
913 epInfo.status = *TlIndBuff++;
914
915 printf("processRpcSysAppNewDevInd: %x:%x\n", epInfo.nwkAddr, epInfo.endpoint);
916 if(zllSocCb.pfnNewDevIndicationCb)
917 {
918 zllSocCb.pfnNewDevIndicationCb(&epInfo);
919 }
920}
921
922/*************************************************************************************************
923 * @fn processRpcSysAppZclRsp()
924 *
925 * @brief process the ZCL Rsp from the ZLL controller
926 *
927 * @param none
928 *
929 * @return length of current Rx Buffer
930 *************************************************************************************************/
931void processRpcSysAppZclRsp(uint8_t *zclRspBuff)
932{
933 uint8_t zclHdrLen = 3;
934 uint16_t nwkAddr, clusterID;
935 uint8_t endpoint, appEP, zclFrameLen, transSeqNum, commandID, zclFrameFrameControl;
936
937 //This is a ZCL response
938 appEP = *zclRspBuff++;
939 nwkAddr = BUILD_UINT16(zclRspBuff[0], zclRspBuff[1]);
940 zclRspBuff+=2;
941
942 endpoint = *zclRspBuff++;
943 clusterID = BUILD_UINT16(zclRspBuff[0], zclRspBuff[1]);
944 zclRspBuff+=2;
945
946 zclFrameLen = *zclRspBuff++;
947 zclFrameFrameControl = *zclRspBuff++;
948 //is it manufacturer specific
949 if ( zclFrameFrameControl & (1 <<2) )
950 {
951 //currently not supported shown for reference
952 uint16_t ManSpecCode;
953 //manu spec code
954 ManSpecCode = BUILD_UINT16(zclRspBuff[0], zclRspBuff[1]);
955 zclRspBuff+=2;
956 //Manufacturer specif commands have 2 extra byte in te header
957 zclHdrLen+=2;
958 }
959
960 transSeqNum = *zclRspBuff++;
961 commandID = *zclRspBuff++;
962
963 if(commandID == ZCL_CMD_READ_RSP)
964 {
965 uint16_t attrID;
966 uint8_t status;
967
968 attrID = BUILD_UINT16(zclRspBuff[0], zclRspBuff[1]);
969 zclRspBuff+=2;
970 status = *zclRspBuff++;
971 //skip over data type;
972 zclRspBuff++;
973
974 if( (clusterID == ZCL_CLUSTER_ID_GEN_ON_OFF) && (attrID == ATTRID_ON_OFF) )
975 {
976 if(zllSocCb.pfnZclGetStateCb)
977 {
978 uint8_t state = zclRspBuff[0];
979 zllSocCb.pfnZclGetStateCb(state, nwkAddr, endpoint);
980 }
981 }
982 else if( (clusterID == ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL) && (attrID == ATTRID_LEVEL_CURRENT_LEVEL) )
983 {
984 if(zllSocCb.pfnZclGetLevelCb)
985 {
986 uint8_t level = zclRspBuff[0];
987 zllSocCb.pfnZclGetLevelCb(level, nwkAddr, endpoint);
988 }
989 }
990 else if( (clusterID == ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL) && (attrID == ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_HUE) )
991 {
992 if(zllSocCb.pfnZclGetHueCb)
993 {
994 uint8_t hue = zclRspBuff[0];
995 zllSocCb.pfnZclGetHueCb(hue, nwkAddr, endpoint);
996 }
997 }
998 else if( (clusterID == ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL) && (attrID == ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_SATURATION) )
999 {
1000 if(zllSocCb.pfnZclGetSatCb)
1001 {
1002 uint8_t sat = zclRspBuff[0];
1003 zllSocCb.pfnZclGetSatCb(sat, nwkAddr, endpoint);
1004 }
1005 }
1006 else
1007 {
1008 //unsupported ZCL Read Rsp
1009 printf("processRpcSysAppZclRsp: Unsupported ZCL Rsp");
1010 }
1011 }
1012 else
1013 {
1014 //unsupported ZCL Rsp
1015 printf("processRpcSysAppZclRsp: Unsupported ZCL Rsp");;
1016 }
1017
1018 return;
1019}
1020
1021/*************************************************************************************************
1022 * @fn processRpcSysApp()
1023 *
1024 * @brief read and process the RPC App message from the ZLL controller
1025 *
1026 * @param none
1027 *
1028 * @return length of current Rx Buffer
1029 *************************************************************************************************/
1030void processRpcSysApp(uint8_t *rpcBuff)
1031{
1032 if( rpcBuff[1] == MT_APP_ZLL_TL_IND )
1033 {
1034 processRpcSysAppTlInd(&rpcBuff[2]);
1035 }
1036 else if( rpcBuff[1] == MT_APP_ZLL_NEW_DEV_IND )
1037 {
1038 processRpcSysAppNewDevInd(&rpcBuff[2]);
1039 }
1040 else if( rpcBuff[1] == MT_APP_RSP )
1041 {
1042 processRpcSysAppZclRsp(&rpcBuff[2]);
1043 }
1044 else if( rpcBuff[1] == 0 )
1045 {
1046 if( rpcBuff[2] == 0)
1047 {
1048 printf("processRpcSysApp: Command Received Successfully\n\n");
1049 }
1050 else
1051 {
1052 printf("processRpcSysApp: Command Error\n\n");
1053 }
1054 }
1055 else
1056 {
1057 printf("processRpcSysApp: Unsupported MT App Msg\n");
1058 }
1059
1060 return;
1061
1062}
1063
1064/*************************************************************************************************
1065 * @fn processRpcSysDbg()
1066 *
1067 * @brief read and process the RPC debug message from the ZLL controller
1068 *
1069 * @param none
1070 *
1071 * @return length of current Rx Buffer
1072 *************************************************************************************************/
1073void processRpcSysDbg(uint8_t *rpcBuff)
1074{
1075 if( rpcBuff[1] == MT_DEBUG_MSG )
1076 {
1077 //we got a debug string
1078 printf("lcd_debug message from zll controller: %s\n", (char*) &(rpcBuff[2]));
1079 }
1080 else if( rpcBuff[1] == 0 )
1081 {
1082 if( rpcBuff[2] == 0)
1083 {
1084 printf("processRpcSysDbg: Command Received Successfully\n\n");
1085 }
1086 else
1087 {
1088 printf("processRpcSysDbg: Command Error\n\n");
1089 }
1090 }
1091 else
1092 {
1093 printf("processRpcSysDbg: Unsupported MT App Msg\n");
1094 }
1095}
1096
1097
1098/*************************************************************************************************
1099 * @fn zllSocProcessRpc()
1100 *
1101 * @brief read and process the RPC from the ZLL controller
1102 *
1103 * @param none
1104 *
1105 * @return length of current Rx Buffer
1106 *************************************************************************************************/
1107void zllSocProcessRpc (void)
1108{
1109 uint8_t rpcLen, bytesRead, sofByte, *rpcBuff, rpcBuffIdx;
1110 static uint8_t retryAttempts = 0;
1111
1112 //read first byte and check it is a SOF
1113 read(serialPortFd, &sofByte, 1);
1114 if ( sofByte == MT_RPC_SOF )
1115 {
1116 retryAttempts = 0;
1117
1118 //read len
1119 bytesRead = read(serialPortFd, &rpcLen, 1);
1120
1121 if( bytesRead == 1)
1122 {
1123 //allocating RPC payload (+ cmd0, cmd1 and fcs)
1124 rpcLen += 3;
1125
1126 rpcBuff = malloc(rpcLen);
1127
1128 //non blocking read, so we need to wait for the rpc to be read
1129 rpcBuffIdx = 0;
1130 while(rpcLen > 0)
1131 {
1132 //read rpc
1133 bytesRead = read(serialPortFd, &(rpcBuff[rpcBuffIdx]), rpcLen);
1134
1135 //check for error
1136 if( bytesRead > rpcLen)
1137 {
1138 //there was an error
1139 //printf("zllSocProcessRpc: read of %d bytes failed - %s\n", rpcLen, strerror(errno) );
1140
1141 if( retryAttempts++ < 5 )
1142 {
1143 //sleep for 10ms
1144 usleep(10000);
1145 //try again
1146 bytesRead = 0;
1147 }
1148 else
1149 {
1150 //something went wrong.
1151 printf("zllSocProcessRpc: failed\n");
1152 return;
1153 }
1154 }
1155
1156 rpcLen -= bytesRead;
1157 rpcBuffIdx += bytesRead;
1158 }
1159
1160 //Read CMD0
1161 switch (rpcBuff[0] & MT_RPC_SUBSYSTEM_MASK)
1162 {
1163 case MT_RPC_SYS_DBG:
1164 {
1165 processRpcSysDbg(rpcBuff);
1166 break;
1167 }
1168 case MT_RPC_SYS_APP:
1169 {
1170 processRpcSysApp(rpcBuff);
1171 break;
1172 }
1173 default:
1174 {
1175 printf("zllSocProcessRpc: CMD0:%x, CMD1:%x, not handled\n", rpcBuff[0], rpcBuff[1] );
1176 break;
1177 }
1178 }
1179
1180 free(rpcBuff);
1181 }
1182 else
1183 {
1184 printf("zllSocProcessRpc: No valid Start Of Frame found\n");
1185 }
1186 }
1187
1188 return;
1189}
1190
diff --git a/zllSocCmd.h b/zllSocCmd.h
new file mode 100644
index 0000000..3b370b0
--- /dev/null
+++ b/zllSocCmd.h
@@ -0,0 +1,113 @@
1/*
2 * zllSocCmd.h
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 */
38
39#ifndef ZLLSOCCMD_H
40#define ZLLSOCCMD_H
41
42#ifdef __cplusplus
43extern "C"
44{
45#endif
46
47#include <stdint.h>
48
49/********************************************************************/
50// ZLL Soc Types
51
52// Endpoint information record entry
53typedef struct
54{
55 uint16_t nwkAddr; // Network address
56 uint8_t endpoint; // Endpoint identifier
57 uint16_t profileID; // Profile identifier
58 uint16_t deviceID; // Device identifier
59 uint8_t version; // Version
60 char* deviceName;
61 uint8_t status;
62} epInfo_t;
63
64typedef uint8_t (*zllSocTlIndicationCb_t)(epInfo_t *epInfo);
65typedef uint8_t (*zllNewDevIndicationCb_t)(epInfo_t *epInfo);
66typedef uint8_t (*zllSocZclGetStateCb_t)(uint8_t state, uint16_t nwkAddr, uint8_t endpoint);
67typedef uint8_t (*zllSocZclGetLevelCb_t)(uint8_t level, uint16_t nwkAddr, uint8_t endpoint);
68typedef uint8_t (*zllSocZclGetHueCb_t)(uint8_t hue, uint16_t nwkAddr, uint8_t endpoint);
69typedef uint8_t (*zllSocZclGetSatCb_t)(uint8_t sat, uint16_t nwkAddr, uint8_t endpoint);
70
71
72typedef struct
73{
74 zllSocTlIndicationCb_t pfnTlIndicationCb; // TouchLink Indication callback
75 zllNewDevIndicationCb_t pfnNewDevIndicationCb; // New device Indication callback
76 zllSocZclGetStateCb_t pfnZclGetStateCb; // ZCL response callback for get State
77 zllSocZclGetLevelCb_t pfnZclGetLevelCb; // ZCL response callback for get Level
78 zllSocZclGetHueCb_t pfnZclGetHueCb; // ZCL response callback for get Hue
79 zllSocZclGetSatCb_t pfnZclGetSatCb; // ZCL response callback for get Sat
80} zllSocCallbacks_t;
81
82/********************************************************************/
83// ZLL Soc API
84
85//configuration API's
86int32_t zllSocOpen( char *devicePath );
87void zllSocRegisterCallbacks( zllSocCallbacks_t zllSocCallbacks);
88void zllSocClose( void );
89void zllSocProcessRpc (void);
90
91//ZLL API's
92void zllSocTouchLink(void);
93void zllSocResetToFn(void);
94void zllSocSendResetToFn(void);
95//ZCL Set API's
96void zllSocSetState(uint8_t state, uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode);
97void zllSocSetLevel(uint8_t level, uint16_t time, uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode);
98void zllSocSetHue(uint8_t hue, uint16_t time, uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode);
99void zllSocSetSat(uint8_t sat, uint16_t time, uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode);
100void zllSocSetHueSat(uint8_t hue, uint8_t sat, uint16_t time, uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode);
101void zllSocAddGroup(uint16_t groupId, uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode);
102void zllSocStoreScene(uint16_t groupId, uint8_t sceneId, uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode);
103void zllSocRecallScene(uint16_t groupId, uint8_t sceneId, uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode);
104//ZCL Get API's
105void zllSocGetState(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode);
106void zllSocGetLevel(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode);
107void zllSocGetHue(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode);
108void zllSocGetSat(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode);
109#ifdef __cplusplus
110}
111#endif
112
113#endif /* ZLLSOCCMD_H */
diff --git a/zll_controller.c b/zll_controller.c
new file mode 100644
index 0000000..3b91873
--- /dev/null
+++ b/zll_controller.c
@@ -0,0 +1,448 @@
1/*
2 * zll_controller.c
3 *
4 * This module demonstrates how to use the API for the zll SoC
5 * Host Interface.
6 *
7 * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
8 *
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 *
17 * Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the
20 * distribution.
21 *
22 * Neither the name of Texas Instruments Incorporated nor the names of
23 * its contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 *
38 */
39#include <termios.h>
40#include <string.h>
41#include <stdio.h>
42#include <unistd.h>
43#include <fcntl.h>
44#include <stdlib.h>
45#include <poll.h>
46
47#include "zllSocCmd.h"
48
49#define MAX_CONSOLE_CMD_LEN 128
50
51void usage( char* exeName );
52void commandUsage( void );
53void processConsoleCommand( void );
54void getConsoleCommandParams(char* cmdBuff, uint16_t *nwkAddr, uint8_t *addrMode, uint8_t *ep, uint8_t *value, uint16_t *transitionTime);
55uint32_t getParam( char *cmdBuff, char *paramId, uint32_t *paramInt);
56uint8_t tlIndicationCb(epInfo_t *epInfo);
57uint8_t zclGetStateCb(uint8_t state, uint16_t nwkAddr, uint8_t endpoint);
58uint8_t zclGetLevelCb(uint8_t level, uint16_t nwkAddr, uint8_t endpoint);
59uint8_t zclGetHueCb(uint8_t hue, uint16_t nwkAddr, uint8_t endpoint);
60uint8_t zclGetSatCb(uint8_t sat, uint16_t nwkAddr, uint8_t endpoint);
61
62static zllSocCallbacks_t zllSocCbs =
63{
64 tlIndicationCb, // pfnTlIndicationCb - TouchLink Indication callback
65 NULL, // pfnNewDevIndicationCb - New Device Indication callback
66 zclGetStateCb, // pfnZclGetHueCb - ZCL response callback for get Hue
67 zclGetLevelCb, //pfnZclGetSatCb - ZCL response callback for get Sat
68 zclGetHueCb, //pfnZclGetLevelCb_t - ZCL response callback for get Level
69 zclGetSatCb //pfnZclGetStateCb - ZCL response callback for get State
70};
71
72static uint16_t savedNwkAddr;
73static uint8_t savedAddrMode;
74static uint8_t savedEp;
75static uint8_t savedValue;
76static uint16_t savedTransitionTime;
77
78void usage( char* exeName )
79{
80 printf("Usage: ./%s <port>\n", exeName);
81 printf("Eample: ./%s /dev/ttyACM0\n", exeName);
82}
83
84void commandUsage( void )
85{
86 printf("Commands:\n");
87 printf("touchlink\n");
88 printf("sendresettofn\n");
89 printf("resettofn\n");
90 printf("setstate\n");
91 printf("setlevel\n");
92 printf("sethue\n");
93 printf("setsat\n");
94 printf("getstate\n");
95 printf("getlevel\n");
96 printf("gethue\n");
97 printf("getsat\n\n");
98 printf("exit\n\n");
99
100 printf("Parameters:\n");
101 printf("-n<network address>\n");
102 printf("-e<end point>\n");
103 printf("-m<address mode 1=groupcast, 2=unicast>\n");
104 printf("-v<value>\n");
105 printf("-t<transition time in 10ms>\n\n");
106
107 printf("A successful touchlink will set the network address and endpoint of the newly\n");
108 printf("paired device. so all the new Light can be turn on with the following command\n");
109 printf("setsat -v1\n\n");
110
111 printf("The below example will send a MoveToHue command to network address 0x0003\n");
112 printf("end point 0xb, which will cause the device to move to a red hue over 3s\n");
113 printf("(be sure that the saturation is set high to see the change):\n");
114 printf("sethue -n0x0003 -e0xb -m0x2 -v0 -t30\n\n");
115
116 printf("parameters are remembered, so the blow command directly after the above will\n");
117 printf("change to a blue hue:\n");
118 printf("sethue -v0xAA \n\n");
119
120 printf("The value of hue is a 0x0-0xFF representation of the 360Deg color wheel where:\n");
121 printf("0Deg or 0x0 is red\n");
122 printf("120Deg or 0x55 is a green hue\n");
123 printf("240Deg or 0xAA is a blue hue\n\n");
124
125 printf("The value of saturation is a 0x0-0xFE value where:\n");
126 printf("0x0 is white\n");
127 printf("0xFE is the fully saturated color specified by the hue value\n");
128}
129
130int main(int argc, char* argv[])
131{
132 int retval = 0;
133 int zllSoc_fd;
134
135 printf("%s -- %s %s\n", argv[0], __DATE__, __TIME__ );
136
137 // accept only 1
138 if( argc != 2 )
139 {
140 usage(argv[0]);
141 printf("attempting to use /dev/ttyACM0\n");
142 zllSoc_fd = zllSocOpen( "/dev/ttyACM0" );
143 }
144 else
145 {
146 zllSoc_fd = zllSocOpen( argv[1] );
147 }
148
149 if( zllSoc_fd == -1 )
150 {
151 exit(-1);
152 }
153
154 zllSocRegisterCallbacks( zllSocCbs );
155
156 //set some default values
157 savedNwkAddr = 0x0002;
158 savedAddrMode = 0x02;
159 savedEp = 0x0b;
160 savedValue = 0x0;
161 savedTransitionTime = 0x1;
162
163 while(1)
164 {
165 struct pollfd pollFds[2];
166
167 //set the zllSoC serial port FD in the poll file descriptors
168 pollFds[0].fd = zllSoc_fd;
169 pollFds[0].events = POLLIN;
170
171 //set the stdin FD in the poll file descriptors
172 pollFds[1].fd = 0; //stdin
173 pollFds[1].events = POLLIN;
174
175 poll(pollFds, 2, -1);
176
177 //did the poll unblock because of the zllSoC serial?
178 if(pollFds[0].revents)
179 {
180 zllSocProcessRpc();
181 //printf("main: zllSocProcessRpc - %x\n", pollFds[0].revents);
182 }
183 //did the poll unblock because of the stdin?
184 else if(pollFds[1].revents)
185 {
186 processConsoleCommand();
187 //printf("main: processConsoleCommand - %x\n", pollFds[1].revents);
188 }
189 else
190 {
191 printf("zllMain: unhandled poll\n");
192 }
193 }
194
195 return retval;
196}
197
198void processConsoleCommand( void )
199{
200 char cmdBuff[MAX_CONSOLE_CMD_LEN];
201 uint32_t bytesRead;
202 uint16_t nwkAddr;
203 uint8_t addrMode;
204 uint8_t endpoint;
205 uint8_t value;
206 uint16_t transitionTime;
207
208 //read stdin
209 bytesRead = read(0, cmdBuff, (MAX_CONSOLE_CMD_LEN-1));
210 cmdBuff[bytesRead] = '\0';
211
212 getConsoleCommandParams(cmdBuff, &nwkAddr, &addrMode, &endpoint, &value, &transitionTime);
213
214 if((strstr(cmdBuff, "touchlink")) != 0)
215 {
216 zllSocTouchLink();
217 printf("touchlink command executed\n\n");
218 }
219 else if((strstr(cmdBuff, "sendresettofn")) != 0)
220 {
221 //sending of reset to fn must happen within a touchlink
222 zllSocTouchLink();
223 printf("press a key when device identyfies\n");
224 getc(stdin);
225 zllSocSendResetToFn();
226 }
227 else if((strstr(cmdBuff, "resettofn")) != 0)
228 {
229 zllSocResetToFn();
230 printf("resettofn command executed\n\n");
231 }
232 else if((strstr(cmdBuff, "setstate")) != 0)
233 {
234 zllSocSetState(value, nwkAddr, endpoint, addrMode);
235 printf("setstate command executed with params: \n");
236 printf(" Network Addr :0x%04x\n End Point :0x%02x\n Addr Mode :0x%02x\n Value :0x%02x\n\n",
237 nwkAddr, endpoint, addrMode, value);
238 }
239 else if((strstr(cmdBuff, "setlevel")) != 0)
240 {
241 zllSocSetLevel(value, transitionTime, nwkAddr, endpoint, addrMode);
242 printf("setlevel command executed with params: \n");
243 printf(" Network Addr :0x%04x\n End Point :0x%02x\n Addr Mode :0x%02x\n Value :0x%02x\n Transition Time :0x%04x\n\n",
244 nwkAddr, endpoint, addrMode, value, transitionTime);
245 }
246 else if((strstr(cmdBuff, "sethue")) != 0)
247 {
248 zllSocSetHue(value, transitionTime, nwkAddr, endpoint, addrMode);
249 printf("sethue command executed with params: \n");
250 printf(" Network Addr :0x%04x\n End Point :0x%02x\n Addr Mode :0x%02x\n Value :0x%02x\n Transition Time :0x%04x\n\n",
251 nwkAddr, endpoint, addrMode, value, transitionTime);
252 }
253 else if((strstr(cmdBuff, "setsat")) != 0)
254 {
255 zllSocSetSat(value, transitionTime, nwkAddr, endpoint, addrMode);
256 printf("setsat command executed with params: \n");
257 printf(" Network Addr :0x%04x\n End Point :0x%02x\n Addr Mode :0x%02x\n Value :0x%02x\n Transition Time :0x%04x\n\n",
258 nwkAddr, endpoint, addrMode, value, transitionTime);
259 }
260 else if((strstr(cmdBuff, "getstate")) != 0)
261 {
262 zllSocGetState(nwkAddr, endpoint, addrMode);
263 printf("getstate command executed wtih params: \n");
264 printf(" Network Addr :0x%04x\n End Point :0x%02x\n Addr Mode :0x%02x\n\n",
265 nwkAddr, endpoint, addrMode);
266 }
267 else if((strstr(cmdBuff, "getlevel")) != 0)
268 {
269 zllSocGetLevel(nwkAddr, endpoint, addrMode);
270 printf("getlevel command executed with params: \n");
271 printf(" Network Addr :0x%04x\n End Point :0x%02x\n Addr Mode :0x%02x\n\n",
272 nwkAddr, endpoint, addrMode);
273 }
274 else if((strstr(cmdBuff, "gethue")) != 0)
275 {
276 zllSocGetHue(nwkAddr, endpoint, addrMode);
277 printf("gethue command executed with params: \n");
278 printf(" Network Addr :0x%04x\n End Point :0x%02x\n Addr Mode :0x%02x\n\n",
279 nwkAddr, endpoint, addrMode);
280 }
281 else if((strstr(cmdBuff, "getsat")) != 0)
282 {
283 zllSocGetSat(nwkAddr, endpoint, addrMode);
284 printf("getsat command executed with params: \n");
285 printf(" Network Addr :0x%04x\n End Point :0x%02x\n Addr Mode :0x%02x\n\n",
286 nwkAddr, endpoint, addrMode);
287 }
288 else if((strstr(cmdBuff, "exit")) != 0)
289 {
290 printf("Closing. \n");
291 zllSocClose();
292 exit(0);
293 }
294 else
295 {
296 printf("invalid command\n\n");
297 commandUsage();
298 }
299}
300
301void getConsoleCommandParams(char* cmdBuff, uint16_t *nwkAddr, uint8_t *addrMode, uint8_t *ep, uint8_t *value, uint16_t *transitionTime)
302{
303 //set some default values
304 uint32_t tmpInt;
305
306 if( getParam( cmdBuff, "-n", &tmpInt) )
307 {
308 savedNwkAddr = (uint16_t) tmpInt;
309 }
310 if( getParam( cmdBuff, "-m", &tmpInt) )
311 {
312 savedAddrMode = (uint8_t) tmpInt;
313 }
314 if( getParam( cmdBuff, "-e", &tmpInt) )
315 {
316 savedEp = (uint8_t) tmpInt;
317 }
318 if( getParam( cmdBuff, "-v", &tmpInt) )
319 {
320 savedValue = (uint8_t) tmpInt;
321 }
322 if( getParam( cmdBuff, "-t", &tmpInt) )
323 {
324 savedTransitionTime = (uint16_t) tmpInt;
325 }
326
327 *nwkAddr = savedNwkAddr;
328 *addrMode = savedAddrMode;
329 *ep = savedEp;
330 *value = savedValue;
331 *transitionTime = savedTransitionTime;
332
333 return;
334}
335
336uint32_t getParam( char *cmdBuff, char *paramId, uint32_t *paramInt)
337{
338 char* paramStrStart;
339 char* paramStrEnd;
340 //0x1234+null termination
341 char paramStr[7];
342 uint32_t rtn = 0;
343
344 memset(paramStr, 0, sizeof(paramStr));
345 paramStrStart = strstr(cmdBuff, paramId);
346
347 if( paramStrStart )
348 {
349 //index past the param idenentifier "-?"
350 paramStrStart+=2;
351 //find the the end of the param text
352 paramStrEnd = strstr(paramStrStart, " ");
353 if( paramStrEnd )
354 {
355 if(paramStrEnd-paramStrStart > (sizeof(paramStr)-1))
356 {
357 //we are not on the last param, but the param str is too long
358 strncpy( paramStr, paramStrStart, (sizeof(paramStr)-1));
359 paramStr[sizeof(paramStr)-1] = '\0';
360 }
361 else
362 {
363 //we are not on the last param so use the " " as the delimiter
364 strncpy( paramStr, paramStrStart, paramStrEnd-paramStrStart);
365 paramStr[paramStrEnd-paramStrStart] = '\0';
366 }
367 }
368
369 else
370 {
371 //we are on the last param so use the just go the the end of the string
372 //(which will be null terminate). But make sure that it is not bigger
373 //than our paramStr buffer.
374 if(strlen(paramStrStart) > (sizeof(paramStr)-1))
375 {
376 //command was entered wrong and paramStrStart will over flow the
377 //paramStr buffer.
378 strncpy( paramStr, paramStrStart, (sizeof(paramStr)-1));
379 paramStr[sizeof(paramStr)-1] = '\0';
380 }
381 else
382 {
383 //Param is the correct size so just copy it.
384 strcpy( paramStr, paramStrStart);
385 paramStr[strlen(paramStrStart)-1] = '\0';
386 }
387 }
388
389 //was the param in hex or dec?
390 if(strstr(paramStr, "0x"))
391 {
392 //convert the hex value to an int.
393 sscanf(paramStr, "0x%x", paramInt);
394 }
395 else
396 {
397 //assume that it ust be dec and convert to int.
398 sscanf(paramStr, "%d", paramInt);
399 }
400
401 //paramInt was set
402 rtn = 1;
403
404 }
405
406 return rtn;
407}
408
409uint8_t tlIndicationCb(epInfo_t *epInfo)
410{
411 printf("\ntlIndicationCb:\n Network Addr : 0x%04x\n End Point : 0x%02x\n Profile ID : 0x%04x\n",
412 epInfo->nwkAddr, epInfo->endpoint, epInfo->profileID);
413 printf(" Device ID : 0x%04x\n Version : 0x%02x\n Status : 0x%02x\n\n",
414 epInfo->deviceID, epInfo->version, epInfo->status);
415
416 //control this device by default
417 savedNwkAddr = epInfo->nwkAddr;
418 savedEp = epInfo->endpoint;
419
420 return 0;
421}
422
423uint8_t zclGetStateCb(uint8_t state, uint16_t nwkAddr, uint8_t endpoint)
424{
425 printf("\nzclGetStateCb:\n Network Addr : 0x%04x\n End Point : 0x%02x\n State : 0x%02x\n\n",
426 nwkAddr, endpoint, state);
427 return 0;
428}
429
430uint8_t zclGetLevelCb(uint8_t level, uint16_t nwkAddr, uint8_t endpoint)
431{
432 printf("\nzclGetLevelCb:\n Network Addr : 0x%04x\n End Point : 0x%02x\n Level : %02x\n\n",
433 nwkAddr, endpoint, level);
434 return 0;
435}
436
437uint8_t zclGetHueCb(uint8_t hue, uint16_t nwkAddr, uint8_t endpoint)
438{
439 printf("\nzclGetHueCb:\n Network Addr : 0x%04x\n End Point : 0x%02x\n Hue : %02x\n\n", nwkAddr, endpoint, hue);
440 return 0;
441}
442
443uint8_t zclGetSatCb(uint8_t sat, uint16_t nwkAddr, uint8_t endpoint)
444{
445 printf("\nzclGetSatCb:\n Network Addr : 0x%04x\n End Point : 0x%02x\n Saturation : %02x\n\n",
446 nwkAddr, endpoint, sat);
447 return 0;
448}