Updated TI Linux Sensor To Cloud to the latest TI 15.4-Stack v2.4, now with CC13x2...
[apps/tidep0084.git] / example / collector / appsrv.c
1 /******************************************************************************
2  @file appsrv.c
4  @brief TIMAC 2.0 API User Interface Collector API
6  Group: WCS LPC
7  $Target Devices: Linux: AM335x, Embedded Devices: CC1310, CC1350, CC1352$
9  ******************************************************************************
10  $License: BSD3 2016 $
11   
12    Copyright (c) 2015, Texas Instruments Incorporated
13    All rights reserved.
14   
15    Redistribution and use in source and binary forms, with or without
16    modification, are permitted provided that the following conditions
17    are met:
18   
19    *  Redistributions of source code must retain the above copyright
20       notice, this list of conditions and the following disclaimer.
21   
22    *  Redistributions in binary form must reproduce the above copyright
23       notice, this list of conditions and the following disclaimer in the
24       documentation and/or other materials provided with the distribution.
25   
26    *  Neither the name of Texas Instruments Incorporated nor the names of
27       its contributors may be used to endorse or promote products derived
28       from this software without specific prior written permission.
29   
30    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
31    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
32    THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
33    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
35    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
36    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
37    OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
38    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
39    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
40    EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41  ******************************************************************************
42  $Release Name: TI-15.4Stack Linux x64 SDK$
43  $Release Date: Sept 27, 2017 (2.04.00.13)$
44 *****************************************************************************/
46 /******************************************************************************
47   Includes
48 *****************************************************************************/
49 #include "compiler.h"
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <errno.h>
53 #include <string.h>
54 #include <time.h>
55 #include <stdint.h>
56 #include <inttypes.h>
58 #include "debug_helpers.h"
60 #include "collector.h"
62 #include "api_mac.h"
63 #include "api_mac_linux.h"
64 #include "llc.h"
65 #include "cllc.h"
66 #include "smsgs.h"
67 #include "log.h"
68 #include "fatal.h"
70 #include "appsrv.h"
71 #include "csf_linux.h"
72 #include "mutex.h"
73 #include "threads.h"
74 #include "timer.h"
76 #include "stream.h"
77 #include "stream_socket.h"
78 #include "stream_uart.h"
80 /******************************************************************************
81  Typedefs
82 *****************************************************************************/
85 struct appsrv_connection {
86     /*! Is this item busy (broadcasting) */
87     bool is_busy;
88     /*! If something has gone wrong this is set to true */
89     bool is_dead;
90     /*! Name for us in debug logs */
91     char *dbg_name;
93     /* What connection number is this? */
94     int  connection_id;
96     /*! The socket interface to the gateway */
97     struct mt_msg_interface socket_interface;
99     /*! Thread id for the socket interface */
100     intptr_t thread_id_s2appsrv;
102     /*! Next connection in the list */
103     struct appsrv_connection *pNext;
104 };
106 /******************************************************************************
107  GLOBAL Variables
108 *****************************************************************************/
110 /*! The interface the API mac uses, points to either the socket or the uart */
111 struct mt_msg_interface *API_MAC_msg_interface;
112 /*! Generic template for all gateway connections */
113 struct socket_cfg appClient_socket_cfg;
114 /*! Configuration for apimac if using a socket (ie: npi server) */
115 struct socket_cfg npi_socket_cfg;
116 /*! UART configuration for apimac if talking to UART instead of npi */
117 struct uart_cfg   uart_cfg;
119 /*! Generic template for all gateway interfaces
120   Note: These parameters can be modified via the ini file
121 */
122 struct mt_msg_interface appClient_mt_interface_template = {
123     .dbg_name                  = "appClient",
124     .is_NPI                    = false,
125     .frame_sync                = false,
126     .include_chksum            = false,
127     .hndl                      = 0,
128     .s_cfg                     = NULL,
129     .u_cfg                     = NULL,
130     .rx_thread                 = 0,
131     .tx_frag_size              = 0,
132     .retry_max                 = 0,
133     .frag_timeout_mSecs        = 10000,
134     .intermsg_timeout_mSecs    = 10000,
135     .intersymbol_timeout_mSecs = 100,
136     .srsp_timeout_mSecs        = 300,
137     .stack_id                  = 0,
138     .len_2bytes                = true,
139     .rx_handler_cookie         = 0,
140     .is_dead                   = false,
141     .flush_timeout_mSecs       = 100
142 };
144 /*! Generic template for uart interface
145   Note: These parameters can be modified via the ini file
146 */
147 struct mt_msg_interface uart_mt_interface = {
148     .dbg_name                  = "uart",
149     .is_NPI                    = false,
150     .frame_sync                = true,
151     .include_chksum            = true,
152     .hndl                      = 0,
153     .s_cfg                     = NULL,
154     .u_cfg                     = &uart_cfg,
155     .rx_thread                 = 0,
156     .tx_frag_size              = 0,
157     .retry_max                 = 0,
158     .frag_timeout_mSecs        = 10000,
159     .intermsg_timeout_mSecs    = 10000,
160     .intersymbol_timeout_mSecs = 100,
161     .srsp_timeout_mSecs        = 300,
162     .stack_id                  = 0,
163     .len_2bytes                = true,
164     .rx_handler_cookie         = 0,
165     .is_dead                   = false,
166     .flush_timeout_mSecs       = 100
167 };
169 /*! Template for apimac connection to npi server
170   Note: These parameters can be modified via the ini file
171 */
172 struct mt_msg_interface npi_mt_interface = {
173     .dbg_name                  = "npi",
174     .is_NPI                    = false,
175     .frame_sync                = true,
176     .include_chksum            = true,
177     .hndl                      = 0,
178     .s_cfg                     = &npi_socket_cfg,
179     .u_cfg                     = NULL,
180     .rx_thread                 = 0,
181     .tx_frag_size              = 0,
182     .retry_max                 = 0,
183     .frag_timeout_mSecs        = 10000,
184     .intermsg_timeout_mSecs    = 10000,
185     .intersymbol_timeout_mSecs = 100,
186     .srsp_timeout_mSecs        = 300,
187     .stack_id                  = 0,
188     .len_2bytes                = true,
189     .rx_handler_cookie         = 0,
190     .is_dead                   = false,
191     .flush_timeout_mSecs       = 100
192 };
194 /*******************************************************************
195  * LOCAL VARIABLES
196  ********************************************************************/
198 static intptr_t all_connections_mutex;
199 static struct appsrv_connection *all_connections;
200 static intptr_t all_connections_mutex;
202 /*******************************************************************
203  * LOCAL FUNCTIONS
204  ********************************************************************/
206 /*! Lock the list of gateway connections
207   Often used when modifying the list
208 */
209 static void lock_connection_list(void)
211     MUTEX_lock(all_connections_mutex, -1);
214 /* See lock() above */
215 static void unlock_connection_list(void)
217     MUTEX_unLock(all_connections_mutex);
220 /*!
221  * @brief send a data confirm to the gateway
222  * @param status - the status value to send
223  */
224 static void send_AppsrvTxDataCnf(int status)
226     int len = TX_DATA_CNF_LEN;
227     uint8_t *pBuff;
229     struct mt_msg *pMsg;
230     pMsg = MT_MSG_alloc(
231         len,
232         MT_MSG_cmd0_areq(APPSRV_SYS_ID_RPC),
233         APPSRV_TX_DATA_CNF);
235     /* Create duplicate pointer to msg buffer for building */
236     pBuff = pMsg->iobuf + HEADER_LEN;
238     /* Put status in the msg buffer */
239     *pBuff++ = (uint8_t)(status & 0xFF);
240     *pBuff++ = (uint8_t)((status >> 8) & 0xFF);
241     *pBuff++ = (uint8_t)((status >> 16) & 0xFF);
242     *pBuff++ = (uint8_t)((status >> 24) & 0xFF);
244     /* Send msg  */
245     MT_MSG_setDestIface(pMsg, &appClient_mt_interface_template);
246     MT_MSG_wrBuf(pMsg, NULL, len);
247     appsrv_broadcast(pMsg);
248     MT_MSG_free(pMsg);
249     pMsg = NULL;
252 /*!
253  * @brief send a join confirm to the gateway
254  */
255 static void send_AppSrvJoinPermitCnf(int status)
257     int len = JOIN_PERMIT_CNF_LEN;
258     uint8_t *pBuff;
260     struct mt_msg *pMsg;
261     pMsg = MT_MSG_alloc(
262         len,
263         MT_MSG_cmd0_areq(APPSRV_SYS_ID_RPC),
264         APPSRV_SET_JOIN_PERMIT_CNF);
266     /* Create duplicate pointer to msg buffer for building */
267     pBuff = pMsg->iobuf + HEADER_LEN;
269     /* Put status in the msg buffer */
270     *pBuff++ = (uint8_t)(status & 0xFF);
271     *pBuff++ = (uint8_t)((status >> 8) & 0xFF);
272     *pBuff++ = (uint8_t)((status >> 16) & 0xFF);
273     *pBuff++ = (uint8_t)((status >> 24) & 0xFF);
275     /* Send msg */
276     MT_MSG_setDestIface(pMsg, &appClient_mt_interface_template);
277     MT_MSG_wrBuf(pMsg, NULL, len);
278     appsrv_broadcast(pMsg);
279     MT_MSG_free(pMsg);
280     pMsg = NULL;
283 /*!
284  * @brief handle a data request from the gateway
285  * @param pCONN - where the request came from
286  * @param pIncommingMsg - the msg from the gateway
287  */
288 static void appsrv_processTxDataReq(struct appsrv_connection *pCONN,
289                                     struct mt_msg *pIncomingMsg)
291     int status;
292     int ind = HEADER_LEN;
293     uint8_t msgId;
294     uint16_t shortAddr;
296     /* Parse msg */
297     msgId = (uint8_t)pIncomingMsg->iobuf[ind];
298     ind += 1;
300     shortAddr = (uint16_t)(pIncomingMsg->iobuf[ind]) |
301                 (pIncomingMsg->iobuf[ind + 1] << 8);
302     ind += 2;
304     ApiMac_sAddr_t pDstAddr;
305     pDstAddr.addrMode = ApiMac_addrType_short;
306     pDstAddr.addr.shortAddr = shortAddr;
308     if (msgId == Smsgs_cmdIds_configReq)
309     {
310         uint16_t framecontrol;
311         uint32_t pollingInterval;
312         uint32_t reportingInterval;
313         uint8_t configStatus;
315         pollingInterval = (uint32_t)(pIncomingMsg->iobuf[ind]) |
316                           (pIncomingMsg->iobuf[ind + 1] << 8);
317         ind += 2;
319         reportingInterval = (uint32_t)(pIncomingMsg->iobuf[ind]) |
320                             (pIncomingMsg->iobuf[ind + 1] << 8);
321         ind += 2;
323         framecontrol = (uint16_t)(pIncomingMsg->iobuf[ind]) |
324                        (pIncomingMsg->iobuf[ind + 1] << 8);
326         configStatus = Csf_sendConfigRequest(&pDstAddr, framecontrol, reportingInterval, pollingInterval);
327         LOG_printf(LOG_APPSRV_MSG_CONTENT, " Config-req sent\n");
328         LOG_printf(LOG_APPSRV_MSG_CONTENT, "Config status: %x\n", configStatus);
329     }
331     else if (msgId == Smsgs_cmdIds_toggleLedReq)
332     {
333         LOG_printf(LOG_APPSRV_MSG_CONTENT, " Toggle-req received\n");
334         Csf_sendToggleLedRequest(&pDstAddr);
335     }
337     else if (msgId == Smsgs_cmdIds_buzzerCtrlReq)
338     {
339         LOG_printf(LOG_APPSRV_MSG_CONTENT, " Buzzer-Ctrl Req received\n");
340         Csf_sendBuzzerCtrlRequest(&pDstAddr);
341     }
343     status = ApiMac_status_success;
344     send_AppsrvTxDataCnf(status);
347 static void appsrv_processRemoveDeviceReq(struct appsrv_connection *pCONN,
348                                           struct mt_msg *pIncomingMsg)
350     int ind = HEADER_LEN;
351     uint16_t shortAddr;
352     ApiMac_sAddr_t dstAddr;
353     Llc_deviceListItem_t devListItem;
354     ApiMac_status_t status;
356     shortAddr = (uint16_t)(pIncomingMsg->iobuf[ind]) |
357                 (pIncomingMsg->iobuf[ind + 1] << 8);
359     dstAddr.addrMode = ApiMac_addrType_short;
360     dstAddr.addr.shortAddr = shortAddr;
362     if (Csf_getDevice(&dstAddr, &devListItem))
363     {
364         /* Send disassociation request to specified sensor */
365         ApiMac_mlmeDisassociateReq_t disassocReq;
366         memset(&disassocReq, 0, sizeof(ApiMac_mlmeDisassociateReq_t));
367         disassocReq.deviceAddress.addrMode = ApiMac_addrType_short;
368         disassocReq.deviceAddress.addr.shortAddr = devListItem.devInfo.shortAddress;
369         disassocReq.devicePanId = devListItem.devInfo.panID;
370         disassocReq.disassociateReason = ApiMac_disassocateReason_coord;
371         disassocReq.txIndirect = true;
372         status = ApiMac_mlmeDisassociateReq(&disassocReq);
373         LOG_printf(LOG_APPSRV_MSG_CONTENT, "Disassociate Sent, status: %x\n", status);
374     }
377 /*!
378  * @brief handle a join permit request from the gateway
379  * @param pCONN - where the request came from
380  * @param pIncommingMsg - the msg from the gateway
381  */
382 static void appsrv_processSetJoinPermitReq(struct appsrv_connection *pCONN,
383                                            struct mt_msg *pIncomingMsg)
385     int status;
386     uint32_t duration;
387     duration = (uint32_t)(pIncomingMsg->iobuf[HEADER_LEN]) |
388                (pIncomingMsg->iobuf[HEADER_LEN + 1] << 8) |
389                (pIncomingMsg->iobuf[HEADER_LEN + 2] << 16) |
390                (pIncomingMsg->iobuf[HEADER_LEN + 3] << 24);
392     /* Set the join permit */
393     LOG_printf(LOG_APPSRV_MSG_CONTENT, "\nSending duration: 0x%x\n\n", duration);
394     status = Cllc_setJoinPermit(duration);
396     /* Send cnf msg  */
397     LOG_printf(LOG_APPSRV_MSG_CONTENT, "\nSending permitCnf message\n\n");
398     send_AppSrvJoinPermitCnf(status);
401 /*!
402  * @brief handle a getnetwork info request from the gateway
403  * @param pCONN - where the request came from
404  */
405 static void appsrv_processGetNwkInfoReq(struct appsrv_connection *pCONN)
407     Llc_netInfo_t networkInfo;
408     uint8_t *pBuff;
409     int len = NWK_INFO_REQ_LEN;
411     uint8_t status = (uint8_t)Csf_getNetworkInformation(&networkInfo);
412     uint8_t securityEnabled = CONFIG_SECURE;
413     uint8_t networkMode;
414     uint8_t state = Csf_getCllcState();
416     LOG_printf(LOG_APPSRV_MSG_CONTENT, "\nSending NwkCnf STATE = %x\n\n", state);
418     if (CONFIG_FH_ENABLE == true)
419     {
420         networkMode = FREQUENCY_HOPPING;
421     }
423     else
424     {
425         if ((CONFIG_MAC_SUPERFRAME_ORDER == 15) && (CONFIG_MAC_BEACON_ORDER == 15))
426         {
427             networkMode = NON_BEACON;
428         }
429         else
430         {
431             networkMode = BEACON_ENABLED;
432         }
433     }
435     struct mt_msg *pMsg;
436     pMsg = MT_MSG_alloc(
437         len,
438         MT_MSG_cmd0_areq(APPSRV_SYS_ID_RPC),
439         APPSRV_GET_NWK_INFO_CNF);
441     /* Create duplicate pointer to msg buffer for building */
442     pBuff = pMsg->iobuf + HEADER_LEN;
444     /* Build msg */
445     *pBuff++ = status;
446     *pBuff++ = (uint8_t)(networkInfo.devInfo.panID & 0xFF);
447     *pBuff++ = (uint8_t)((networkInfo.devInfo.panID >> 8) & 0xFF);
448     *pBuff++ = (uint8_t)(networkInfo.devInfo.shortAddress & 0xFF);
449     *pBuff++ = (uint8_t)((networkInfo.devInfo.shortAddress >> 8) & 0xFF);
450     *pBuff++ = (uint8_t)(networkInfo.devInfo.extAddress[0]);
451     *pBuff++ = (uint8_t)(networkInfo.devInfo.extAddress[1]);
452     *pBuff++ = (uint8_t)(networkInfo.devInfo.extAddress[2]);
453     *pBuff++ = (uint8_t)(networkInfo.devInfo.extAddress[3]);
454     *pBuff++ = (uint8_t)(networkInfo.devInfo.extAddress[4]);
455     *pBuff++ = (uint8_t)(networkInfo.devInfo.extAddress[5]);
456     *pBuff++ = (uint8_t)(networkInfo.devInfo.extAddress[6]);
457     *pBuff++ = (uint8_t)(networkInfo.devInfo.extAddress[7]);
458     *pBuff++ = (uint8_t)(networkInfo.channel);
459     *pBuff++ = (uint8_t)(networkInfo.fh);
460     *pBuff++ = securityEnabled;
461     *pBuff++ = networkMode;
462     *pBuff++ = state;
464     /* Send msg */
465     MT_MSG_setDestIface(pMsg, &(pCONN->socket_interface));
466     MT_MSG_wrBuf(pMsg, NULL, len);
467     MT_MSG_txrx(pMsg);
468     MT_MSG_free(pMsg);
469     pMsg = NULL;
472 /*!
473  * @brief  Process incoming getDeviceArrayReq message
474  *
475  * @param pConn - the connection
476  */
477 static void appsrv_processGetDeviceArrayReq(struct appsrv_connection *pCONN)
479     uint16_t n = 0;
480     uint8_t *pBuff;
481     Csf_deviceInformation_t *pDeviceInfo;
483     uint8_t status = ApiMac_status_success;
484     n = (uint16_t)Csf_getDeviceInformationList(&pDeviceInfo);
486     int len = DEV_ARRAY_HEAD_LEN + (DEV_ARRAY_INFO_LEN * n);
488     struct mt_msg *pMsg;
489     pMsg = MT_MSG_alloc(
490         len,
491         MT_MSG_cmd0_areq(APPSRV_SYS_ID_RPC),
492         APPSRV_GET_DEVICE_ARRAY_CNF);
494     /* Create duplicate pointer to msg buffer for building */
495     pBuff = pMsg->iobuf + HEADER_LEN;
497     /* Build msg */
498     *pBuff++ = status;
499     *pBuff++ = (uint8_t)(n & 0xFF);
500     *pBuff++ = (uint8_t)((n >> 8) & 0xFF);
502     uint16_t x;
503     for (x = 0; x < n; x++)
504     {
505         *pBuff++ = (uint8_t)(pDeviceInfo[x].devInfo.panID & 0xFF);
506         *pBuff++ = (uint8_t)((pDeviceInfo[x].devInfo.panID >> 8) & 0xFF);
507         *pBuff++ = (uint8_t)(pDeviceInfo[x].devInfo.shortAddress & 0xFF);
508         *pBuff++ = (uint8_t)((pDeviceInfo[x].devInfo.shortAddress >> 8) & 0xFF);
509         *pBuff++ = (uint8_t)(pDeviceInfo[x].devInfo.extAddress[0]);
510         *pBuff++ = (uint8_t)(pDeviceInfo[x].devInfo.extAddress[1]);
511         *pBuff++ = (uint8_t)(pDeviceInfo[x].devInfo.extAddress[2]);
512         *pBuff++ = (uint8_t)(pDeviceInfo[x].devInfo.extAddress[3]);
513         *pBuff++ = (uint8_t)(pDeviceInfo[x].devInfo.extAddress[4]);
514         *pBuff++ = (uint8_t)(pDeviceInfo[x].devInfo.extAddress[5]);
515         *pBuff++ = (uint8_t)(pDeviceInfo[x].devInfo.extAddress[6]);
516         *pBuff++ = (uint8_t)(pDeviceInfo[x].devInfo.extAddress[7]);
517         *pBuff++ = (uint8_t)(pDeviceInfo[x].capInfo.panCoord);
518         *pBuff++ = (uint8_t)(pDeviceInfo[x].capInfo.ffd);
519         *pBuff++ = (uint8_t)(pDeviceInfo[x].capInfo.mainsPower);
520         *pBuff++ = (uint8_t)(pDeviceInfo[x].capInfo.rxOnWhenIdle);
521         *pBuff++ = (uint8_t)(pDeviceInfo[x].capInfo.security);
522         *pBuff++ = (uint8_t)(pDeviceInfo[x].capInfo.allocAddr);
523     }
525     /* Send msg */
526     MT_MSG_setDestIface(pMsg, &(pCONN->socket_interface));
527     MT_MSG_wrBuf(pMsg, NULL, len);
528     MT_MSG_txrx(pMsg);
529     MT_MSG_free(pMsg);
530     pMsg = NULL;
532     if (pDeviceInfo)
533     {
534         Csf_freeDeviceInformationList(n, pDeviceInfo);
535         pDeviceInfo = NULL;
536     }
539 /******************************************************************************
540  Function Implementation
541 *****************************************************************************/
543 /*
544   Broadcast a message to all connections.
545   Public function in appsrv.h
546 */
547 void appsrv_broadcast(struct mt_msg *pMsg)
549     struct appsrv_connection *pCONN;
550     struct mt_msg *pClone;
552     /* mark all connections as "ready to broadcast" */
553     lock_connection_list();
555     for(pCONN = all_connections ; pCONN ; pCONN = pCONN->pNext)
556     {
557         pCONN->is_busy = false;
558     }
560     unlock_connection_list();
562 next_connection:
563     /* find first connection in "ready-state"
564      * NOTE: this loop is funny we goto the top
565      * and we restart scanning from the head
566      * because ... while broadcasting a new
567      * connection may appear, or one may go away
568      */
569     lock_connection_list();
570     for(pCONN = all_connections ; pCONN ; pCONN = pCONN->pNext)
571     {
572         /* this one is dead */
573         if(pCONN->is_dead)
574         {
575             continue;
576         }
577         /* is this one ready? */
579         if(pCONN->is_busy == false)
580         {
581             /* Yes we have found one */
582             pCONN->is_busy = true;
583             break;
584         }
585     }
586     unlock_connection_list();
588     /* Did we find a connection? */
589     if(pCONN)
590     {
591         /* we have a connection we can send */
592         pClone = MT_MSG_clone(pMsg);
593         if(pClone)
594         {
595             MT_MSG_setDestIface(pClone, &(pCONN->socket_interface));
596             MT_MSG_txrx(pClone);
597             MT_MSG_free(pClone);
598         }
599         /* leave this connection as 'busy'
600          * busy really means: "done"
601          * so that we do not repeat this connection
602          * we clean up the list later
603          *---
604          * Go back to the *FIRST* connection
605          * And search again.... from the top..
606          * Why? Because connections may have died...
607          */
608         goto next_connection;
609     }
611     /* if we get here - we have no more connections to broadcast to */
612     /* mark all items as idle */
613     lock_connection_list();
614     for(pCONN = all_connections ; pCONN ; pCONN = pCONN->pNext)
615     {
616         pCONN->is_busy = false;
617     }
618     unlock_connection_list();
621 /*!
622   Csf module calls this function to inform the user/appClient
623   that the application has either started/restored the network
625   Public function defined in appsrv_Collector.h
626 */
627 void appsrv_networkUpdate(bool restored, Llc_netInfo_t *networkInfo)
629     int len = NWK_INFO_IND_LEN;
630     uint8_t *pBuff;
632     uint8_t securityEnabled = CONFIG_SECURE;
633     uint8_t networkMode;
634     uint8_t state = Csf_getCllcState();
636     if (CONFIG_FH_ENABLE == true)
637     {
638         networkMode = FREQUENCY_HOPPING;
639     }
641     else
642     {
643         if ((CONFIG_MAC_SUPERFRAME_ORDER == 15) && (CONFIG_MAC_BEACON_ORDER == 15))
644         {
645             networkMode = NON_BEACON;
646         }
647         else
648         {
649             networkMode = BEACON_ENABLED;
650         }
651     }
653     struct mt_msg *pMsg;
654     pMsg = MT_MSG_alloc(
655         len,
656         MT_MSG_cmd0_areq(APPSRV_SYS_ID_RPC),
657         APPSRV_NWK_INFO_IND);
659     /* Create duplicate pointer to msg buffer for building purposes */
660     pBuff = pMsg->iobuf + HEADER_LEN;
662     /* Build msg */
663     *pBuff++ = (uint8_t)(networkInfo->devInfo.panID & 0xFF);
664     *pBuff++ = (uint8_t)((networkInfo->devInfo.panID >> 8) & 0xFF);
665     *pBuff++ = (uint8_t)(networkInfo->devInfo.shortAddress & 0xFF);
666     *pBuff++ = (uint8_t)((networkInfo->devInfo.shortAddress >> 8) & 0xFF);
667     *pBuff++ = (uint8_t)(networkInfo->devInfo.extAddress[0]);
668     *pBuff++ = (uint8_t)(networkInfo->devInfo.extAddress[1]);
669     *pBuff++ = (uint8_t)(networkInfo->devInfo.extAddress[2]);
670     *pBuff++ = (uint8_t)(networkInfo->devInfo.extAddress[3]);
671     *pBuff++ = (uint8_t)(networkInfo->devInfo.extAddress[4]);
672     *pBuff++ = (uint8_t)(networkInfo->devInfo.extAddress[5]);
673     *pBuff++ = (uint8_t)(networkInfo->devInfo.extAddress[6]);
674     *pBuff++ = (uint8_t)(networkInfo->devInfo.extAddress[7]);
675     *pBuff++ = (uint8_t)(networkInfo->channel);
676     *pBuff++ = (uint8_t)(networkInfo->fh);
677     *pBuff++ = securityEnabled;
678     *pBuff++ = networkMode;
679     *pBuff++ = state;
681     /* Send msg */
682     MT_MSG_setDestIface(pMsg, &appClient_mt_interface_template);
683     MT_MSG_wrBuf(pMsg, NULL, len);
684     appsrv_broadcast(pMsg);
685     MT_MSG_free(pMsg);
686     pMsg = NULL;
689 /*!
691   Csf module calls this function to inform the user/appClient
692   that a device has joined the network
694   Public function defined in appsrv_Collector.h
695 */
696 void appsrv_deviceUpdate(Llc_deviceListItem_t *pDevListItem)
698     int len = DEVICE_JOINED_IND_LEN;
699     uint8_t *pBuff;
701     struct mt_msg *pMsg;
702     pMsg = MT_MSG_alloc(
703         len,
704         MT_MSG_cmd0_areq(APPSRV_SYS_ID_RPC),
705         APPSRV_DEVICE_JOINED_IND);
707     /* Create duplicate pointer to msg buffer for building purposes */
708     pBuff = pMsg->iobuf + HEADER_LEN;
710     /* Build msg */
711     *pBuff++ = (uint8_t)(pDevListItem->devInfo.panID & 0xFF);
712     *pBuff++ = (uint8_t)((pDevListItem->devInfo.panID >> 8) & 0xFF);
713     *pBuff++ = (uint8_t)(pDevListItem->devInfo.shortAddress & 0xFF);
714     *pBuff++ = (uint8_t)((pDevListItem->devInfo.shortAddress >> 8) & 0xFF);
715     *pBuff++ = (uint8_t)(pDevListItem->devInfo.extAddress[0]);
716     *pBuff++ = (uint8_t)(pDevListItem->devInfo.extAddress[1]);
717     *pBuff++ = (uint8_t)(pDevListItem->devInfo.extAddress[2]);
718     *pBuff++ = (uint8_t)(pDevListItem->devInfo.extAddress[3]);
719     *pBuff++ = (uint8_t)(pDevListItem->devInfo.extAddress[4]);
720     *pBuff++ = (uint8_t)(pDevListItem->devInfo.extAddress[5]);
721     *pBuff++ = (uint8_t)(pDevListItem->devInfo.extAddress[6]);
722     *pBuff++ = (uint8_t)(pDevListItem->devInfo.extAddress[7]);
723     *pBuff++ = (uint8_t)(pDevListItem->capInfo.panCoord);
724     *pBuff++ = (uint8_t)(pDevListItem->capInfo.ffd);
725     *pBuff++ = (uint8_t)(pDevListItem->capInfo.mainsPower);
726     *pBuff++ = (uint8_t)(pDevListItem->capInfo.rxOnWhenIdle);
727     *pBuff++ = (uint8_t)(pDevListItem->capInfo.security);
728     *pBuff++ = (uint8_t)(pDevListItem->capInfo.allocAddr);
730     /* Send msg */
731     MT_MSG_setDestIface(pMsg, &appClient_mt_interface_template);
732     MT_MSG_wrBuf(pMsg, NULL, len);
733     appsrv_broadcast(pMsg);
734     MT_MSG_free(pMsg);
735     pMsg = NULL;
738 #ifndef PROCESS_JS
739 /*
740  * @brief common code to handle sensor data messages
741  * @param pSrcAddr - address related to this message
742  * @param rssi - signal strength from device
743  * @param pDataMsg - the sensor message
744  * @param pRspMsg - the response
745  *
746  * In the end, the message is sent to the gateway
747  */
748 static void appsrv_deviceSensorData_common(ApiMac_sAddr_t *pSrcAddr,
749                                            int8_t rssi,
750                                            Smsgs_sensorMsg_t *pDataMsg,
751                                            Smsgs_configRspMsg_t *pRspMsg)
753     /*TODO: This function should be split into two functions, one function that
754             sends the dataMsg, and one function that sends the rspMsg. This would
755             eliminate the need for the msgContent field that is needed to build
756             and parse. */
758     /* Because the sensor data msg can can be different lengths depending
759     on what information is being sent, the msg is built differently.
760     Instead of creating the msg structure initially, a dummy buffer is
761     created first, then the contents are copied into the msg's iobuf. */
763     int len = 0;
764     uint8_t *buffer;
765     uint8_t *pBuff;
766     buffer = (uint8_t *)calloc(MAX_SENSOR_DATA_LEN, sizeof(uint8_t));
767     pBuff = buffer;
769     len += 1;
770     *pBuff++ = (uint8_t)pSrcAddr->addrMode;
771     if (pSrcAddr->addrMode == ApiMac_addrType_short)
772     {
773         len += 2;
774         *pBuff++ = (uint8_t)(pSrcAddr->addr.shortAddr & 0xFF);
775         *pBuff++ = (uint8_t)((pSrcAddr->addr.shortAddr >> 8) & 0xFF);
776     }
777     else if (pSrcAddr->addrMode == ApiMac_addrType_extended)
778     {
779         len += 8;
780         *pBuff++ = (uint8_t)(pSrcAddr->addr.extAddr[0]);
781         *pBuff++ = (uint8_t)(pSrcAddr->addr.extAddr[1]);
782         *pBuff++ = (uint8_t)(pSrcAddr->addr.extAddr[2]);
783         *pBuff++ = (uint8_t)(pSrcAddr->addr.extAddr[3]);
784         *pBuff++ = (uint8_t)(pSrcAddr->addr.extAddr[4]);
785         *pBuff++ = (uint8_t)(pSrcAddr->addr.extAddr[5]);
786         *pBuff++ = (uint8_t)(pSrcAddr->addr.extAddr[6]);
787         *pBuff++ = (uint8_t)(pSrcAddr->addr.extAddr[7]);
788     }
790     len += 1;
791     *pBuff++ = (uint8_t)rssi;
793     /* Msg type flag */
794     uint8_t msgContent = 0;
795     if (pDataMsg != NULL)
796     {
797         msgContent |= SENSOR_DATA_MSG;
798     }
799     if (pRspMsg != NULL)
800     {
801         msgContent |= CONFIG_RSP_MSG;
802     }
804     len += 1;
805     *pBuff++ = msgContent;
807     if (pDataMsg != NULL)
808     {
809         len += 11;
810         *pBuff++ = (uint8_t)(pDataMsg->cmdId);
811         *pBuff++ = (uint8_t)(pDataMsg->frameControl & 0xFF);
812         *pBuff++ = (uint8_t)((pDataMsg->frameControl >> 8) & 0xFF);
813         *pBuff++ = (uint8_t)(pDataMsg->extAddress[0]);
814         *pBuff++ = (uint8_t)(pDataMsg->extAddress[1]);
815         *pBuff++ = (uint8_t)(pDataMsg->extAddress[2]);
816         *pBuff++ = (uint8_t)(pDataMsg->extAddress[3]);
817         *pBuff++ = (uint8_t)(pDataMsg->extAddress[4]);
818         *pBuff++ = (uint8_t)(pDataMsg->extAddress[5]);
819         *pBuff++ = (uint8_t)(pDataMsg->extAddress[6]);
820         *pBuff++ = (uint8_t)(pDataMsg->extAddress[7]);
821         if (pDataMsg->frameControl & Smsgs_dataFields_tempSensor)
822         {
823             len += 4;
824             *pBuff++ = (uint8_t)(pDataMsg->tempSensor.ambienceTemp & 0xFF);
825             *pBuff++ = (uint8_t)((pDataMsg->tempSensor.ambienceTemp >> 8) & 0xFF);
826             *pBuff++ = (uint8_t)(pDataMsg->tempSensor.objectTemp & 0xFF);
827             *pBuff++ = (uint8_t)((pDataMsg->tempSensor.objectTemp >> 8) & 0xFF);
828         }
829         if (pDataMsg->frameControl & Smsgs_dataFields_lightSensor)
830         {
831             len += 2;
832             *pBuff++ = (uint8_t)(pDataMsg->lightSensor.rawData & 0xFF);
833             *pBuff++ = (uint8_t)((pDataMsg->lightSensor.rawData >> 8) & 0xFF);
834         }
835         if (pDataMsg->frameControl & Smsgs_dataFields_humiditySensor)
836         {
837             len += 4;
838             *pBuff++ = (uint8_t)(pDataMsg->humiditySensor.temp & 0xFF);
839             *pBuff++ = (uint8_t)((pDataMsg->humiditySensor.temp >> 8) & 0xFF);
840             *pBuff++ = (uint8_t)(pDataMsg->humiditySensor.humidity & 0xFF);
841             *pBuff++ = (uint8_t)((pDataMsg->humiditySensor.humidity >> 8) & 0xFF);
842         }
843         if (pDataMsg->frameControl & Smsgs_dataFields_msgStats)
844         {
845             len += 40;
846             *pBuff++ = (uint8_t)(pDataMsg->msgStats.joinAttempts & 0xFF);
847             *pBuff++ = (uint8_t)((pDataMsg->msgStats.joinAttempts >> 8) & 0xFF);
848             *pBuff++ = (uint8_t)(pDataMsg->msgStats.joinFails & 0xFF);
849             *pBuff++ = (uint8_t)((pDataMsg->msgStats.joinFails >> 8) & 0xFF);
850             *pBuff++ = (uint8_t)(pDataMsg->msgStats.msgsAttempted & 0xFF);
851             *pBuff++ = (uint8_t)((pDataMsg->msgStats.msgsAttempted >> 8) & 0xFF);
852             *pBuff++ = (uint8_t)(pDataMsg->msgStats.msgsSent & 0xFF);
853             *pBuff++ = (uint8_t)((pDataMsg->msgStats.msgsSent >> 8) & 0xFF);
854             *pBuff++ = (uint8_t)(pDataMsg->msgStats.trackingRequests & 0xFF);
855             *pBuff++ = (uint8_t)((pDataMsg->msgStats.trackingRequests >> 8) & 0xFF);
856             *pBuff++ = (uint8_t)(pDataMsg->msgStats.trackingResponseAttempts & 0xFF);
857             *pBuff++ = (uint8_t)((pDataMsg->msgStats.trackingResponseAttempts >> 8) & 0xFF);
858             *pBuff++ = (uint8_t)(pDataMsg->msgStats.trackingResponseSent & 0xFF);
859             *pBuff++ = (uint8_t)((pDataMsg->msgStats.trackingResponseSent >> 8) & 0xFF);
860             *pBuff++ = (uint8_t)(pDataMsg->msgStats.configRequests & 0xFF);
861             *pBuff++ = (uint8_t)((pDataMsg->msgStats.configRequests >> 8) & 0xFF);
862             *pBuff++ = (uint8_t)(pDataMsg->msgStats.configResponseAttempts & 0xFF);
863             *pBuff++ = (uint8_t)((pDataMsg->msgStats.configResponseAttempts >> 8) & 0xFF);
864             *pBuff++ = (uint8_t)(pDataMsg->msgStats.configResponseSent & 0xFF);
865             *pBuff++ = (uint8_t)((pDataMsg->msgStats.configResponseSent >> 8) & 0xFF);
866             *pBuff++ = (uint8_t)(pDataMsg->msgStats.channelAccessFailures & 0xFF);
867             *pBuff++ = (uint8_t)((pDataMsg->msgStats.channelAccessFailures >> 8) & 0xFF);
868             *pBuff++ = (uint8_t)(pDataMsg->msgStats.macAckFailures & 0xFF);
869             *pBuff++ = (uint8_t)((pDataMsg->msgStats.macAckFailures >> 8) & 0xFF);
870             *pBuff++ = (uint8_t)(pDataMsg->msgStats.otherDataRequestFailures & 0xFF);
871             *pBuff++ = (uint8_t)((pDataMsg->msgStats.otherDataRequestFailures >> 8) & 0xFF);
872             *pBuff++ = (uint8_t)(pDataMsg->msgStats.syncLossIndications & 0xFF);
873             *pBuff++ = (uint8_t)((pDataMsg->msgStats.syncLossIndications >> 8) & 0xFF);
874             *pBuff++ = (uint8_t)(pDataMsg->msgStats.rxDecryptFailures & 0xFF);
875             *pBuff++ = (uint8_t)((pDataMsg->msgStats.rxDecryptFailures >> 8) & 0xFF);
876             *pBuff++ = (uint8_t)(pDataMsg->msgStats.txEncryptFailures & 0xFF);
877             *pBuff++ = (uint8_t)((pDataMsg->msgStats.txEncryptFailures >> 8) & 0xFF);
878             *pBuff++ = (uint8_t)(pDataMsg->msgStats.resetCount & 0xFF);
879             *pBuff++ = (uint8_t)((pDataMsg->msgStats.resetCount >> 8) & 0xFF);
880             *pBuff++ = (uint8_t)(pDataMsg->msgStats.lastResetReason & 0xFF);
881             *pBuff++ = (uint8_t)((pDataMsg->msgStats.lastResetReason >> 8) & 0xFF);
882             *pBuff++ = (uint8_t)(pDataMsg->msgStats.joinTime & 0xFF);
883             *pBuff++ = (uint8_t)((pDataMsg->msgStats.joinTime >> 8) & 0xFF);
884             *pBuff++ = (uint8_t)(pDataMsg->msgStats.interimDelay & 0xFF);
885             *pBuff++ = (uint8_t)((pDataMsg->msgStats.interimDelay >> 8) & 0xFF);
886         }
887         if (pDataMsg->frameControl & Smsgs_dataFields_configSettings)
888         {
889             len += 8;
890             *pBuff++ = (uint8_t)(pDataMsg->configSettings.reportingInterval & 0xFF);
891             *pBuff++ = (uint8_t)((pDataMsg->configSettings.reportingInterval >> 8) & 0xFF);
892             *pBuff++ = (uint8_t)((pDataMsg->configSettings.reportingInterval >> 16) & 0xFF);
893             *pBuff++ = (uint8_t)((pDataMsg->configSettings.reportingInterval >> 24) & 0xFF);
894             *pBuff++ = (uint8_t)(pDataMsg->configSettings.pollingInterval & 0xFF);
895             *pBuff++ = (uint8_t)((pDataMsg->configSettings.pollingInterval >> 8) & 0xFF);
896             *pBuff++ = (uint8_t)((pDataMsg->configSettings.pollingInterval >> 16) & 0xFF);
897             *pBuff++ = (uint8_t)((pDataMsg->configSettings.pollingInterval >> 24) & 0xFF);
898         }
899         if (pDataMsg->frameControl & Smsgs_dataFields_pressureSensor)
900         {
901             len += 4;
902             *pBuff++ = (uint8_t)(pDataMsg->pressureSensor.tempValue & 0xFF);
903             *pBuff++ = (uint8_t)((pDataMsg->pressureSensor.tempValue >> 8) & 0xFF);
904             *pBuff++ = (uint8_t)(pDataMsg->pressureSensor.pressureValue & 0xFF);
905             *pBuff++ = (uint8_t)((pDataMsg->pressureSensor.pressureValue >> 8) & 0xFF);
906         }
907         if (pDataMsg->frameControl & Smsgs_dataFields_motionSensor)
908         {
909             len += 1;
910             *pBuff++ = (uint8_t)(pDataMsg->motionSensor.isMotion);
911         }
912         if (pDataMsg->frameControl & Smsgs_dataFields_batterySensor)
913         {
914             len += 4;
915             *pBuff++ = (uint8_t)(pDataMsg->batterySensor.voltageValue & 0xFF);
916             *pBuff++ = (uint8_t)((pDataMsg->batterySensor.voltageValue >> 8) & 0xFF);
917             *pBuff++ = (uint8_t)((pDataMsg->batterySensor.voltageValue >> 16) & 0xFF);
918             *pBuff++ = (uint8_t)((pDataMsg->batterySensor.voltageValue >> 24) & 0xFF);
919         }
920         if (pDataMsg->frameControl & Smsgs_dataFields_hallEffectSensor)
921         {
922             len += 2;
923             *pBuff++ = (uint8_t)(pDataMsg->hallEffectSensor.isOpen);
924             *pBuff++ = (uint8_t)(pDataMsg->hallEffectSensor.isTampered);
925         }
926         if (pDataMsg->frameControl & Smsgs_dataFields_fanSensor)
927         {
928             len += 1;
929             *pBuff++ = (uint8_t)(pDataMsg->fanSensor.fanSpeed);
930         }
931         if (pDataMsg->frameControl & Smsgs_dataFields_doorLockSensor)
932         {
933             len += 1;
934             *pBuff++ = (uint8_t)(pDataMsg->doorLockSensor.isLocked);
935         }
936         if (pDataMsg->frameControl & Smsgs_dataFields_waterleakSensor)
937         {
938             len += 2;
939             *pBuff++ = (uint8_t)(pDataMsg->waterleakSensor.status);
940             *pBuff++ = (uint8_t)((pDataMsg->waterleakSensor.status >> 8) & 0xFF);
941         }
942     }
944     if (pRspMsg != NULL)
945     {
946         len += 13;
947         *pBuff++ = (uint8_t)pRspMsg->cmdId;
948         *pBuff++ = (uint8_t)(pRspMsg->status & 0xFF);
949         *pBuff++ = (uint8_t)((pRspMsg->status >> 8) & 0xFF);
950         *pBuff++ = (uint8_t)(pRspMsg->frameControl & 0xFF);
951         *pBuff++ = (uint8_t)((pRspMsg->frameControl >> 8) & 0xFF);
952         *pBuff++ = (uint8_t)(pRspMsg->reportingInterval & 0xFF);
953         *pBuff++ = (uint8_t)((pRspMsg->reportingInterval >> 8) & 0xFF);
954         *pBuff++ = (uint8_t)((pRspMsg->reportingInterval >> 16) & 0xFF);
955         *pBuff++ = (uint8_t)((pRspMsg->reportingInterval >> 24) & 0xFF);
956         *pBuff++ = (uint8_t)(pRspMsg->pollingInterval & 0xFF);
957         *pBuff++ = (uint8_t)((pRspMsg->pollingInterval >> 8) & 0xFF);
958         *pBuff++ = (uint8_t)((pRspMsg->pollingInterval >> 16) & 0xFF);
959         *pBuff++ = (uint8_t)((pRspMsg->pollingInterval >> 24) & 0xFF);
960     }
962     struct mt_msg *pMsg;
963     pMsg = MT_MSG_alloc(
964         len,
965         MT_MSG_cmd0_areq(APPSRV_SYS_ID_RPC),
966         APPSRV_DEVICE_DATA_RX_IND);
968     uint16_t i;
969     for (i = 0; i < len; i++)
970     {
971         pMsg->iobuf[i + HEADER_LEN] = buffer[i];
972     }
973     free(buffer);
975     MT_MSG_setDestIface(pMsg, &appClient_mt_interface_template);
976     MT_MSG_wrBuf(pMsg, NULL, len);
977     appsrv_broadcast(pMsg);
978     MT_MSG_free(pMsg);
979     pMsg = NULL;
982 /*!
983   Csf module calls this function to inform the user/appClient
984   that the device has responded to the configuration request
986   Public function defined in appsrv_Collector.h
987 */
988 void appsrv_deviceConfigUpdate(ApiMac_sAddr_t *pSrcAddr, int8_t rssi,
989                                Smsgs_configRspMsg_t *pRspMsg)
991     appsrv_deviceSensorData_common(pSrcAddr, rssi, NULL, pRspMsg);
993 #else
994 /*
995  * @brief common code to handle sensor data messages
996  * @param pSrcAddr - address related to this message
997  *
998  * In the end, the message is sent to the gateway
999  */
1000 void appsrv_deviceRawDataUpdate(ApiMac_mcpsDataInd_t *pDataInd)
1002     // Get the length (srcAddr + rssi + msdu.len)
1003     uint16_t bufferLength = pDataInd->msdu.len + sizeof(pDataInd->rssi) + sizeof(ApiMac_sAddr_t);
1004     uint8_t buffer[bufferLength];
1005     memset(buffer, 0, bufferLength);
1006     uint16_t idx = 0;
1007     buffer[idx++] = pDataInd->srcAddr.addrMode;
1008     if (pDataInd->srcAddr.addrMode == ApiMac_addrType_short)
1009     {
1010         buffer[idx++] = (uint8_t)(pDataInd->srcAddr.addr.shortAddr & 0xFF);
1011         buffer[idx++] = (uint8_t)((pDataInd->srcAddr.addr.shortAddr >> 8) & 0xFF);
1012     }
1013     else if (pDataInd->srcAddr.addrMode == ApiMac_addrType_extended)
1014     {
1015         memcpy((buffer + idx), pDataInd->srcAddr.addr.extAddr, APIMAC_SADDR_EXT_LEN);
1016         idx += APIMAC_SADDR_EXT_LEN;
1017     }
1018     buffer[idx++] = pDataInd->rssi;
1019     memcpy((buffer + idx), pDataInd->msdu.p, pDataInd->msdu.len);
1021     // initalize the message struct
1022     struct mt_msg *pMsg;
1023     pMsg = MT_MSG_alloc(
1024         bufferLength,
1025         MT_MSG_cmd0_areq(APPSRV_SYS_ID_RPC),
1026         APPSRV_DEVICE_DATA_RX_IND);
1028     //add the ApiMac data to the message iobuf
1029     uint16_t i;
1030     for (i = 0; i < bufferLength; i++)
1031     {
1032         pMsg->iobuf[i + HEADER_LEN] = buffer[i];
1033     }
1035     // send the message buffer over a socket to the appclient
1036     MT_MSG_setDestIface(pMsg, &appClient_mt_interface_template);
1037     MT_MSG_wrBuf(pMsg, NULL, bufferLength);
1038     appsrv_broadcast(pMsg);
1039     MT_MSG_free(pMsg);
1040     pMsg = NULL;
1042 #endif
1044 void appsrv_send_removeDeviceRsp(void)
1046     int len = REMOVE_DEVICE_RSP_LEN;
1048     struct mt_msg *pMsg;
1049     pMsg = MT_MSG_alloc(
1050         len,
1051         MT_MSG_cmd0_areq(APPSRV_SYS_ID_RPC),
1052         APPSRV_RMV_DEVICE_RSP);
1054     /* Send msg */
1055     MT_MSG_setDestIface(pMsg, &appClient_mt_interface_template);
1056     MT_MSG_wrBuf(pMsg, NULL, len);
1057     appsrv_broadcast(pMsg);
1058     MT_MSG_free(pMsg);
1059     pMsg = NULL;
1062 /*!
1063   Csf module calls this function to inform the user/appClient
1064   that a device is no longer active in the network
1066   Public function defined in appsrv_Collector.h
1067 */
1068 void appsrv_deviceNotActiveUpdate(ApiMac_deviceDescriptor_t *pDevInfo,
1069                                   bool timeout)
1071     int len = DEVICE_NOT_ACTIVE_LEN;
1072     uint8_t *pBuff;
1074     struct mt_msg *pMsg;
1075     pMsg = MT_MSG_alloc(
1076         len,
1077         MT_MSG_cmd0_areq(APPSRV_SYS_ID_RPC),
1078         APPSRV_DEVICE_NOTACTIVE_UPDATE_IND);
1080     /* Create duplicate pointer to msg buffer for building purposes */
1081     pBuff = pMsg->iobuf + HEADER_LEN;
1083     /* Build msg */
1084     *pBuff++ = (uint8_t)(pDevInfo->panID & 0xFF);
1085     *pBuff++ = (uint8_t)((pDevInfo->panID >> 8) & 0xFF);
1086     *pBuff++ = (uint8_t)(pDevInfo->shortAddress & 0xFF);
1087     *pBuff++ = (uint8_t)((pDevInfo->shortAddress >> 8) & 0xFF);
1088     *pBuff++ = (uint8_t)(pDevInfo->extAddress[0]);
1089     *pBuff++ = (uint8_t)(pDevInfo->extAddress[1]);
1090     *pBuff++ = (uint8_t)(pDevInfo->extAddress[2]);
1091     *pBuff++ = (uint8_t)(pDevInfo->extAddress[3]);
1092     *pBuff++ = (uint8_t)(pDevInfo->extAddress[4]);
1093     *pBuff++ = (uint8_t)(pDevInfo->extAddress[5]);
1094     *pBuff++ = (uint8_t)(pDevInfo->extAddress[6]);
1095     *pBuff++ = (uint8_t)(pDevInfo->extAddress[7]);
1096     *pBuff++ = (uint8_t)timeout;
1098     /* Send msg */
1099     MT_MSG_setDestIface(pMsg, &appClient_mt_interface_template);
1100     MT_MSG_wrBuf(pMsg, NULL, len);
1101     appsrv_broadcast(pMsg);
1102     MT_MSG_free(pMsg);
1103     pMsg = NULL;
1106 #ifndef PROCESS_JS
1107 /*!
1108   Csf module calls this function to inform the user/appClient
1109   of the reported sensor data from a network device
1111   Public function defined in appsrv_Collector.h
1112 */
1113 void appsrv_deviceSensorDataUpdate(ApiMac_sAddr_t *pSrcAddr, int8_t rssi,
1114                                    Smsgs_sensorMsg_t *pSensorMsg)
1116     appsrv_deviceSensorData_common(pSrcAddr, rssi, pSensorMsg, NULL);
1118 #endif
1120 /*!
1121   TBD
1123   Public function defined in appsrv_Collector.h
1124 */
1125 void appsrv_stateChangeUpdate(Cllc_states_t state)
1127     int len = STATE_CHG_IND_LEN;
1128     struct mt_msg *pMsg;
1129     pMsg = MT_MSG_alloc(
1130         len,
1131         MT_MSG_cmd0_areq(APPSRV_SYS_ID_RPC),
1132         APPSRV_COLLECTOR_STATE_CNG_IND);
1134     /* Build msg, no need for duplicate pointer*/
1135     pMsg->iobuf[HEADER_LEN] = (uint8_t)(state & 0xFF);
1137     MT_MSG_setDestIface(pMsg, &appClient_mt_interface_template);
1138     MT_MSG_wrBuf(pMsg, NULL, len);
1139     appsrv_broadcast(pMsg);
1140     MT_MSG_free(pMsg);
1141     pMsg = NULL;
1144 /*********************************************************************
1145  * Local Functions
1146  *********************************************************************/
1148 /*!
1149  * @brief handle a request from a client.
1150  * @param pCONN - the client connection details
1151  * @param pMsg  - the message we received.
1152  */
1153 static void appsrv_handle_appClient_request( struct appsrv_connection *pCONN,
1154                                              struct mt_msg *pMsg )
1156     int subsys = _bitsXYof(pMsg->cmd0 , 4, 0);
1157     int handled = true;
1158     if (subsys != APPSRV_SYS_ID_RPC)
1159     {
1160         handled = false;
1161     }
1162     else
1163     {
1164         switch(pMsg->cmd1)
1165         {
1166         default:
1167             handled = false;
1168             break;
1169             /*
1170              * NOTE: ADD MORE ITEMS HERE TO EXTEND THE EXAMPLE
1171              */
1172         case APPSRV_GET_DEVICE_ARRAY_REQ:
1173             /* Rcvd data from Client */
1174             LOG_printf(LOG_APPSRV_MSG_CONTENT, "______________________________\n");
1175             LOG_printf(LOG_APPSRV_MSG_CONTENT, "rcvd get device array msg\n");
1176             LOG_printf(LOG_APPSRV_MSG_CONTENT, "______________________________\n");
1177             appsrv_processGetDeviceArrayReq(pCONN);
1178             break;
1180         case APPSRV_GET_NWK_INFO_REQ:
1181             LOG_printf(LOG_APPSRV_MSG_CONTENT, "______________________________\n");
1182             LOG_printf(LOG_APPSRV_MSG_CONTENT, "getnwkinfo req message\n");
1183             LOG_printf(LOG_APPSRV_MSG_CONTENT, "______________________________\n");
1184             appsrv_processGetNwkInfoReq(pCONN);
1185             break;
1187         case APPSRV_SET_JOIN_PERMIT_REQ:
1188             LOG_printf(LOG_APPSRV_MSG_CONTENT, "______________________________\n");
1189             LOG_printf(LOG_APPSRV_MSG_CONTENT, "rcvd join premit message\n ");
1190             LOG_printf(LOG_APPSRV_MSG_CONTENT, "______________________________\n");
1191             appsrv_processSetJoinPermitReq(pCONN, pMsg);
1192             break;
1194         case APPSRV_TX_DATA_REQ:
1195             LOG_printf(LOG_APPSRV_MSG_CONTENT, "______________________________\n");
1196             LOG_printf(LOG_APPSRV_MSG_CONTENT, "rcvd req to send message to a device\n ");
1197             LOG_printf(LOG_APPSRV_MSG_CONTENT, "______________________________\n");
1198             appsrv_processTxDataReq(pCONN, pMsg);
1199             break;
1200         case APPSRV_RMV_DEVICE_REQ:
1201             LOG_printf(LOG_APPSRV_MSG_CONTENT, "______________________________\n");
1202             LOG_printf(LOG_APPSRV_MSG_CONTENT, "rcvd req to remove a device\n ");
1203             LOG_printf(LOG_APPSRV_MSG_CONTENT, "______________________________\n");
1204             appsrv_processRemoveDeviceReq(pCONN, pMsg);
1205             break;
1206         }
1207     }
1208     if(!handled)
1209     {
1210         MT_MSG_log(LOG_ERROR, pMsg, "unknown msg\n");
1211     }
1214 /*
1215  * @brief specific connection thread
1216  * @param cookie - opaque parameter that is the connection details.
1217  *
1218  * The server thread creates these as needed
1219  *
1220  * This thread lives until the connection dies.
1221  */
1222 static intptr_t s2appsrv_thread(intptr_t cookie)
1224     struct appsrv_connection *pCONN;
1225     struct mt_msg *pMsg;
1226     int r;
1227     char iface_name[30];
1228     char star_line[30];
1229     int star_line_char;
1231     pCONN = (struct appsrv_connection *)(cookie);
1232     if( pCONN == NULL )
1233     {
1234         BUG_HERE("pCONN is null?\n");
1235     }
1237     /* create our upstream interface */
1238     (void)snprintf(iface_name,
1239                    sizeof(iface_name),
1240                    "s2u-%d-iface",
1241                    pCONN->connection_id);
1242     pCONN->socket_interface.dbg_name = iface_name;
1244     /* Create our interface */
1245     r = MT_MSG_interfaceCreate(&(pCONN->socket_interface));
1246     if(r != 0)
1247     {
1248         BUG_HERE("Cannot create socket interface?\n");
1249     }
1251     /* Add this connection to the list. */
1252     lock_connection_list();
1253     pCONN->pNext = all_connections;
1254     pCONN->is_busy = false;
1255     all_connections = pCONN;
1256     unlock_connection_list();
1258     star_line_char = 0;
1259     /* Wait for messages to come in from the socket.. */
1260     for(;;)
1261     {
1262         /* Did the other guy die? */
1263         if(pCONN->is_dead)
1264         {
1265             break;
1266         }
1268         /* did the socket die? */
1269         if(pCONN->socket_interface.is_dead)
1270         {
1271             pCONN->is_dead = true;
1272             continue;
1273         }
1275         /* get our message */
1276         pMsg = MT_MSG_LIST_remove(&(pCONN->socket_interface),
1277                                   &(pCONN->socket_interface.rx_list), 1000);
1278         if(pMsg == NULL)
1279         {
1280             /* must have timed out. */
1281             continue;
1282         }
1284         pMsg->pLogPrefix = "web-request";
1286         /* Print a *MARKER* line in the log to help trace this message */
1287         star_line_char++;
1288         /* Cycle through the letters AAAA, BBBB, CCCC .... */
1289         star_line_char = star_line_char % 26;
1290         memset((void *)(star_line),
1291                star_line_char + 'A',
1292                sizeof(star_line) - 1);
1293         star_line[sizeof(star_line) - 1] = 0;
1294         LOG_printf(LOG_DBG_MT_MSG_traffic, "START MSG: %s\n", star_line);
1296         /* Actually process the request */
1297         appsrv_handle_appClient_request(pCONN, pMsg);
1299         /* Same *MARKER* line at the end of the message */
1300         LOG_printf(LOG_DBG_MT_MSG_traffic, "END MSG: %s\n", star_line);
1301         MT_MSG_free(pMsg);
1302         pMsg = NULL;
1303     }
1305     /* There is an interock here.
1306      * FIRST: We set "is_dead"
1307      *   The broadcast code will skip this item.
1308      *   if and only if it is dead.
1309      * HOWEVER
1310      *   Q: What happens if we die in the middle of broadcasting?
1311      *   A: We must wait until the broad cast is complete
1312      *      We know this by checking the bcast_state.
1313      */
1314     while(pCONN->is_busy)
1315     {
1316         /* we must wait ... a broadcast is active. */
1317         /* so sleep alittle and try again */
1318         TIMER_sleep(10);
1319     }
1321     /* we can now remove this DEAD connection from the list. */
1322     lock_connection_list();
1323     {
1324         struct appsrv_connection **ppTHIS;
1326         /* find our self in the list of connections. */
1327         for(ppTHIS = &all_connections ;
1328             (*ppTHIS) != NULL ;
1329             ppTHIS = &((*ppTHIS)->pNext))
1330         {
1331             /* found? */
1332             if((*ppTHIS) == pCONN)
1333             {
1334                 /* yes we are done */
1335                 break;
1336             }
1337         }
1339         /* did we find this one? */
1340         if(*ppTHIS)
1341         {
1342             /* remove this one from the list */
1343             (*ppTHIS) = pCONN->pNext;
1344             pCONN->pNext = NULL;
1345         }
1346     }
1347     unlock_connection_list();
1348     /* socket is dead */
1349     /* we need to destroy the interface */
1350     MT_MSG_interfaceDestroy(&(pCONN->socket_interface));
1352     /* destroy the socket. */
1353     SOCKET_ACCEPT_destroy(pCONN->socket_interface.hndl);
1355     /* we can free this now */
1356     free((void *)pCONN);
1358     /* we do not destroy free the connection */
1359     /* this is done in the uart thread */
1360     return 0;
1363 /*
1364  * @brief This thread handles all connections from the nodeJS/gateway client.
1365  *
1366  * This server thread spawns off threads that handle
1367  * each connection from each gateway app.
1368  */
1370 static intptr_t appsrv_server_thread(intptr_t _notused)
1372     (void)(_notused);
1374     int r;
1375     intptr_t server_handle;
1376     struct appsrv_connection *pCONN;
1377     int connection_id;
1378     char buf[30];
1380     pCONN = NULL;
1381     connection_id = 0;
1383     server_handle = SOCKET_SERVER_create(&appClient_socket_cfg);
1384     if(server_handle == 0)
1385     {
1386         BUG_HERE("cannot create socket to listen\n");
1387     }
1389     r = SOCKET_SERVER_listen(server_handle);
1390     if(r != 0)
1391     {
1392         BUG_HERE("cannot set listen mode\n");
1393     }
1395     /* Wait for connections :-) */
1396     for(;;)
1397     {
1398         if(STREAM_isError(server_handle))
1399         {
1400             LOG_printf(LOG_ERROR, "server (accept) socket is dead\n");
1401             break;
1402         }
1403         if(pCONN == NULL)
1404         {
1405             pCONN = calloc(1, sizeof(*pCONN));
1406             if(pCONN == NULL)
1407             {
1408                 BUG_HERE("No memory\n");
1409             }
1410             pCONN->connection_id = connection_id++;
1412             /* clone the connection details */
1413             pCONN->socket_interface = appClient_mt_interface_template;
1415             (void)snprintf(buf,sizeof(buf),
1416                            "connection-%d",
1417                            pCONN->connection_id);
1418             pCONN->dbg_name = strdup(buf);
1419             if(pCONN->dbg_name == NULL)
1420             {
1421                 BUG_HERE("no memory\n");
1422             }
1423         }
1425         /* wait for a connection.. */
1426         r = SOCKET_SERVER_accept(&(pCONN->socket_interface.hndl),
1427                                  server_handle,
1428                                  appClient_socket_cfg.connect_timeout_mSecs);
1429         if(r < 0)
1430         {
1431             BUG_HERE("cannot accept!\n");
1432         }
1433         if(r == 0)
1434         {
1435             LOG_printf(LOG_APPSRV_CONNECTIONS, "no connection yet\n");
1436             continue;
1437         }
1438         /* we have a connection */
1439         pCONN->is_dead = false;
1441         /* create our connection threads */
1443         /* set name final use */
1444         (void)snprintf(buf, sizeof(buf),
1445                        "connection-%d",
1446                        pCONN->connection_id);
1447         pCONN->dbg_name = strdup(buf);
1448         if(pCONN->dbg_name == NULL)
1449         {
1450             BUG_HERE("no memory\n");
1451         }
1453         (void)snprintf(buf, sizeof(buf),
1454                        "thread-u2s-%d",
1455                        pCONN->connection_id);
1456         pCONN->thread_id_s2appsrv = THREAD_create(buf,
1457                                                   s2appsrv_thread,
1458                                                   (intptr_t)(pCONN),
1459                                                   THREAD_FLAGS_DEFAULT);
1461         pCONN = NULL;
1463     }
1464     return 0;
1468 /*
1469  * @brief the primary "collector thread"
1470  *
1471  * This thread never exists and performs all of
1472  * the 'collector' application tasks.
1473  */
1475 static intptr_t collector_thread(intptr_t dummy)
1477     (void)(dummy);
1478     for(;;)
1479     {
1480         /* this will "pend" on a semaphore */
1481         /* waiting for messages to come */
1482         Collector_process();
1483     }
1484 #if defined(__linux__)
1485     /* gcc complains, unreachable.. */
1486     /* other analisys tools do not .. Grrr. */
1487     return 0;
1488 #endif
1491 /*
1492   This is the main application, "linux_main.c" calls this.
1493 */
1494 void APP_main(void)
1496     int r;
1497     intptr_t server_thread_id;
1498     intptr_t collector_thread_id;
1499     struct appsrv_connection *pCONN;
1501     all_connections_mutex = MUTEX_create("all-connections");
1503     if(all_connections_mutex == 0)
1504     {
1505         BUG_HERE("cannot create connection list mutex\n");
1506     }
1508     Collector_init();
1509     r = MT_DEVICE_version_info.transport |
1510         MT_DEVICE_version_info.product |
1511         MT_DEVICE_version_info.major |
1512         MT_DEVICE_version_info.minor |
1513         MT_DEVICE_version_info.maint;
1514     if( r == 0 )
1515     {
1516         FATAL_printf( "Did not get device version info at startup - Bailing out\n");
1517     }
1520     LOG_printf( LOG_ALWAYS, "Found Mac Co-Processor Version info is:\n");
1521     LOG_printf( LOG_ALWAYS, "Transport: %d\n", MT_DEVICE_version_info.transport );
1522     LOG_printf( LOG_ALWAYS, "  Product: %d\n", MT_DEVICE_version_info.product   );
1523     LOG_printf( LOG_ALWAYS, "    Major: %d\n", MT_DEVICE_version_info.major     );
1524     LOG_printf( LOG_ALWAYS, "    Minor: %d\n", MT_DEVICE_version_info.minor     );
1525     LOG_printf( LOG_ALWAYS, "    Maint: %d\n", MT_DEVICE_version_info.maint     );
1527 #ifdef IS_HEADLESS
1528     fprintf( stdout, "Found Mac Co-Processor Version info is:\n");
1529     fprintf( stdout, "Transport: %d\n", MT_DEVICE_version_info.transport );
1530     fprintf( stdout, "  Product: %d\n", MT_DEVICE_version_info.product   );
1531     fprintf( stdout, "    Major: %d\n", MT_DEVICE_version_info.major     );
1532     fprintf( stdout, "    Minor: %d\n", MT_DEVICE_version_info.minor     );
1533     fprintf( stdout, "    Maint: %d\n", MT_DEVICE_version_info.maint     );
1534     fprintf( stdout, "----------------------------------------\n");
1535     fprintf( stdout, "Start the gateway application\n");
1536 #endif //IS_HEADLESS
1538     server_thread_id = THREAD_create("server-thread",
1539                                      appsrv_server_thread, 0,
1540                                      THREAD_FLAGS_DEFAULT);
1542     collector_thread_id = THREAD_create("collector-thread",
1543                                         collector_thread, 0, THREAD_FLAGS_DEFAULT);
1546     for(;;)
1547     {
1548         /* every 10 seconds.. */
1549         /* 10 seconds is an arbitrary value */
1550         TIMER_sleep(10 * 1000);
1551         r = 0;
1553         if(THREAD_isAlive(collector_thread_id))
1554         {
1555             r += 1;
1556         }
1558         if(THREAD_isAlive(server_thread_id))
1559         {
1560             r += 1;
1561         }
1562         /* we stay here while both *2* threads are alive */
1563         if(r != 2)
1564         {
1565             break;
1566         }
1567     }
1569     /* wait at most (N) seconds then we just 'die' */
1570     r = 0;
1571     while(r < 10)
1572     {
1574         lock_connection_list();
1575         pCONN = all_connections;
1576         /* mark them all as dead */
1577         while(pCONN)
1578         {
1579             pCONN->is_dead = true;
1580             LOG_printf(LOG_APPSRV_CONNECTIONS,
1581                        "Connection: %s is still alive\n",
1582                        pCONN->dbg_name);
1583             pCONN = pCONN->pNext;
1584         }
1585         unlock_connection_list();
1587         /* still have connections? */
1588         if(all_connections)
1589         {
1590             /* wait a second.. */
1591             TIMER_sleep(10000);
1592             /* and try again */
1593             r++;
1594             continue;
1595         }
1596         else
1597         {
1598             break;
1599         }
1600     }
1601     /* thread exit */
1604 /*!
1605  * Set default items for the application.
1606  * These are set before the ini file is read.
1607  */
1608 void APP_defaults(void)
1610     memset( (void *)(&appClient_socket_cfg), 0, sizeof(appClient_socket_cfg) );
1611     /*
1612       NOTE: All of these settings can be modified by ini file.
1613     */
1614     appClient_socket_cfg.inet_4or6 = 4;
1615     /*! this is a 's'=server, not a 'c'client */
1616     appClient_socket_cfg.ascp = 's';
1617     appClient_socket_cfg.host = NULL;
1618     /*! we listen on port 5000 */
1619     appClient_socket_cfg.service = strdup( "5000" );
1620     /*! and only allow one connection */
1621     appClient_socket_cfg.server_backlog = 1;
1622     appClient_socket_cfg.device_binding = NULL;
1623     /*! print a 'non-connect' every minute */
1624     appClient_socket_cfg.connect_timeout_mSecs = 60 * 1000;
1627 /*
1628  *  ========================================
1629  *  Texas Instruments Micro Controller Style
1630  *  ========================================
1631  *  Local Variables:
1632  *  mode: c
1633  *  c-file-style: "bsd"
1634  *  tab-width: 4
1635  *  c-basic-offset: 4
1636  *  indent-tabs-mode: nil
1637  *  End:
1638  *  vim:set  filetype=c tabstop=4 shiftwidth=4 expandtab=true
1639  */