]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - apps/tidep0084.git/blob - example/collector/appsrv.c
4ce011a5ee63d5fd2d30dd3acecc586321a25981
[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$
9  ******************************************************************************
10  $License: BSD3 2016 $
12    Copyright (c) 2015, Texas Instruments Incorporated
13    All rights reserved.
15    Redistribution and use in source and binary forms, with or without
16    modification, are permitted provided that the following conditions
17    are met:
19    *  Redistributions of source code must retain the above copyright
20       notice, this list of conditions and the following disclaimer.
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.
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.
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: Jun 28, 2017 (2.02.00.03)$
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>
59 #include "debug_helpers.h"
61 #include "collector.h"
63 #include "api_mac.h"
64 #include "api_mac_linux.h"
65 #include "llc.h"
66 #include "cllc.h"
67 #include "smsgs.h"
68 #include "log.h"
69 #include "fatal.h"
71 #include "appsrv.h"
72 #include "csf_linux.h"
73 #include "mutex.h"
74 #include "threads.h"
75 #include "timer.h"
77 #include "stream.h"
78 #include "stream_socket.h"
79 #include "stream_uart.h"
81 /******************************************************************************
82  Typedefs
83 *****************************************************************************/
84 typedef enum cmdIds {
85     APPSRV_DEVICE_JOINED_IND = 0,
86     APPSRV_DEVICE_LEFT_IND = 1,
87     APPSRV_NWK_INFO_IND = 2,
88     APPSRV_GET_NWK_INFO_REQ = 3,
89     APPSRV_GET_NWK_INFO_RSP = 4,
90     APPSRV_GET_NWK_INFO_CNF = 5,
91     APPSRV_GET_DEVICE_ARRAY_REQ = 6,
92     APPSRV_GET_DEVICE_ARRAY_CNF = 7,
93     APPSRV_DEVICE_NOTACTIVE_UPDATE_IND = 8,
94     APPSRV_DEVICE_DATA_RX_IND = 9,
95     APPSRV_COLLECTOR_STATE_CNG_IND = 10,
96     APPSRV_SET_JOIN_PERMIT_REQ = 11,
97     APPSRV_SET_JOIN_PERMIT_CNF = 12,
98     APPSRV_TX_DATA_REQ = 13,
99     APPSRV_TX_DATA_CNF = 14,
100     APPSRV_RMV_DEVICE_REQ = 15,
101     APPSRV_RMV_DEVICE_RSP = 16
102 } Cmd_Ids_t;
104 typedef enum smgsCmdIds{
105     SMGS_CONFIG_REQ = 1,
106     SMGS_CONFIG_RSP = 2,
107     SMGS_TRACKING_REQ = 3,
108     SMGS_TRACKING_RSP = 4,
109     SMGS_SENSOR_DATA = 5,
110     SMGS_TOGGLE_REQ = 6,
111     SMGS_TOGGLE_RSP = 7
112 }Smgs_Cmd_Ids_t;
114 typedef enum msgComponents {
115     HEADER_LEN = 4,
116     TX_DATA_CNF_LEN = 4,
117     JOIN_PERMIT_CNF_LEN = 4,
118     NWK_INFO_REQ_LEN = 18,
119     NWK_INFO_IND_LEN = 17,
120     DEV_ARRAY_HEAD_LEN = 3,
121     DEV_ARRAY_INFO_LEN = 18,
122     DEVICE_JOINED_IND_LEN = 18,
123     MAX_SENSOR_DATA_LEN = 255,
124     DEVICE_NOT_ACTIVE_LEN = 13,
125     STATE_CHG_IND_LEN = 1,
126     REMOVE_DEVICE_RSP_LEN = 0
127 } Msg_Components_t;
129 typedef enum nwkModes {
130     BEACON_ENABLED = 1,
131     NON_BEACON = 2,
132     FREQUENCY_HOPPING = 3
133 } Nwk_Modes_t;
135 typedef enum rmvDeviceStatus {
136     RMV_STATUS_SUCCESS = 0,
137     RMV_STATUS_FAIL = 1
138 } Rmv_Device_Status_t;
140 typedef enum apiMacAssocStatus {
141     API_MAC_STATUS_SUCCESS = 0,
142     API_MAC_STATUS_PAN_AT_CAP = 1,
143     API_MAC_STATUS_ACCESS_DENIED = 2
144 } Api_Mac_Assoc_Status_t;
146 typedef enum {
147     APPSRV_SYS_ID_RPC = 10
148 } TimacAppSrvSysId_No_Pb_t;
150 typedef enum sDataMsgType{
151     SENSOR_DATA_MSG = 0x01,
152     CONFIG_RSP_MSG = 0x02
153 } S_Data_Msg_Type_t;
155 struct appsrv_connection {
156     /*! is this item busy (broadcasting) */
157     bool is_busy;
158     /*! has something gone wrong this is set to true */
159     bool is_dead;
160     /*! name for us in debug logs */
161     char *dbg_name;
163     /* what connection number is this? */
164     int  connection_id;
166     /*! The socket interface to the gateway */
167     struct mt_msg_interface socket_interface;
169     /*! Thread id for the socket interface */
170     intptr_t thread_id_s2appsrv;
172     /*! Next connection in the list */
173     struct appsrv_connection *pNext;
174 };
176 /******************************************************************************
177  GLOBAL Variables
178 *****************************************************************************/
180 /*! The interface the API mac uses, points to either the socket or the uart */
181 struct mt_msg_interface *API_MAC_msg_interface;
182 /*! generic template for all gateway connections */
183 struct socket_cfg appClient_socket_cfg;
184 /*! configuration for apimac if using a socket (ie: npi server) */
185 struct socket_cfg npi_socket_cfg;
186 /*! uart configuration for apimac if talking to UART instead of npi */
187 struct uart_cfg   uart_cfg;
189 /*! Generic template for all gateway interfaces
190   Note: These parameters can be modified via the ini file
191 */
192 struct mt_msg_interface appClient_mt_interface_template = {
193     .dbg_name                  = "appClient",
194     .is_NPI                    = false,
195     .frame_sync                = false,
196     .include_chksum            = false,
197     .hndl                      = 0,
198     .s_cfg                     = NULL,
199     .u_cfg                     = NULL,
200     .rx_thread                 = 0,
201     .tx_frag_size              = 0,
202     .retry_max                 = 0,
203     .frag_timeout_mSecs        = 10000,
204     .intermsg_timeout_mSecs    = 10000,
205     .intersymbol_timeout_mSecs = 100,
206     .srsp_timeout_mSecs        = 300,
207     .stack_id                  = 0,
208     .len_2bytes                = true,
209     .rx_handler_cookie         = 0,
210     .is_dead                   = false,
211     .flush_timeout_mSecs       = 100
212 };
214 /*! Generic template for uart interface
215   Note: These parameters can be modified via the ini file
216 */
217 struct mt_msg_interface uart_mt_interface = {
218     .dbg_name                  = "uart",
219     .is_NPI                    = false,
220     .frame_sync                = true,
221     .include_chksum            = true,
222     .hndl                      = 0,
223     .s_cfg                     = NULL,
224     .u_cfg                     = &uart_cfg,
225     .rx_thread                 = 0,
226     .tx_frag_size              = 0,
227     .retry_max                 = 0,
228     .frag_timeout_mSecs        = 10000,
229     .intermsg_timeout_mSecs    = 10000,
230     .intersymbol_timeout_mSecs = 100,
231     .srsp_timeout_mSecs        = 300,
232     .stack_id                  = 0,
233     .len_2bytes                = true,
234     .rx_handler_cookie         = 0,
235     .is_dead                   = false,
236     .flush_timeout_mSecs       = 100
237 };
239 /*! Template for apimac connection to npi server
240   Note: These parameters can be modified via the ini file
241 */
242 struct mt_msg_interface npi_mt_interface = {
243     .dbg_name                  = "npi",
244     .is_NPI                    = false,
245     .frame_sync                = true,
246     .include_chksum            = true,
247     .hndl                      = 0,
248     .s_cfg                     = &npi_socket_cfg,
249     .u_cfg                     = NULL,
250     .rx_thread                 = 0,
251     .tx_frag_size              = 0,
252     .retry_max                 = 0,
253     .frag_timeout_mSecs        = 10000,
254     .intermsg_timeout_mSecs    = 10000,
255     .intersymbol_timeout_mSecs = 100,
256     .srsp_timeout_mSecs        = 300,
257     .stack_id                  = 0,
258     .len_2bytes                = true,
259     .rx_handler_cookie         = 0,
260     .is_dead                   = false,
261     .flush_timeout_mSecs       = 100
262 };
264 /*******************************************************************
265  * LOCAL VARIABLES
266  ********************************************************************/
268 static intptr_t all_connections_mutex;
269 static struct appsrv_connection *all_connections;
270 static intptr_t all_connections_mutex;
272 /*******************************************************************
273  * LOCAL FUNCTIONS
274  ********************************************************************/
276 /*! Lock the list of gateway connections
277   Often used when modifying the list
278 */
279 static void lock_connection_list(void)
281     MUTEX_lock(all_connections_mutex, -1);
284 /* See lock() above */
285 static void unlock_connection_list(void)
287     MUTEX_unLock(all_connections_mutex);
290 /*!
291  * @brief send a data confirm to the gateway
292  * @param status - the status value to send
293  */
294 static void send_AppsrvTxDataCnf(int status)
296     int len = TX_DATA_CNF_LEN;
297     uint8_t *pBuff;
299     struct mt_msg *pMsg;
300     pMsg = MT_MSG_alloc(
301                 len,
302                 MT_MSG_cmd0_areq(APPSRV_SYS_ID_RPC),
303                 APPSRV_TX_DATA_CNF);
305     /* Create duplicate pointer to msg buffer for building */
306     pBuff = pMsg->iobuf + HEADER_LEN;
308     /* Put status in the msg buffer */
309     *pBuff++ = (uint8_t)(status & 0xFF);
310     *pBuff++ = (uint8_t)((status >> 8) & 0xFF);
311     *pBuff++ = (uint8_t)((status >> 16) & 0xFF);
312     *pBuff++ = (uint8_t)((status >> 24) & 0xFF);
314     /* Send msg  */
315     MT_MSG_setDestIface(pMsg, &appClient_mt_interface_template);
316     MT_MSG_wrBuf(pMsg, NULL, len);
317     appsrv_broadcast(pMsg);
318     MT_MSG_free(pMsg);
319     pMsg = NULL;
322 /*!
323  * @brief send a join confirm to the gateway
324  */
325 static void send_AppSrvJoinPermitCnf(int status)
327     int len = JOIN_PERMIT_CNF_LEN;
328     uint8_t *pBuff;
330     struct mt_msg *pMsg;
331     pMsg = MT_MSG_alloc(
332                 len,
333                 MT_MSG_cmd0_areq(APPSRV_SYS_ID_RPC),
334                 APPSRV_SET_JOIN_PERMIT_CNF);
336     /* Create duplicate pointer to msg buffer for building */
337     pBuff = pMsg->iobuf + HEADER_LEN;
339     /* Put status in the msg buffer */
340     *pBuff++ = (uint8_t)(status & 0xFF);
341     *pBuff++ = (uint8_t)((status >> 8) & 0xFF);
342     *pBuff++ = (uint8_t)((status >> 16) & 0xFF);
343     *pBuff++ = (uint8_t)((status >> 24) & 0xFF);
345     /* Send msg */
346     MT_MSG_setDestIface(pMsg, &appClient_mt_interface_template);
347     MT_MSG_wrBuf(pMsg, NULL, len);
348     appsrv_broadcast(pMsg);
349     MT_MSG_free(pMsg);
350     pMsg = NULL;
355 /*!
356  * @brief handle a data request from the gateway
357  * @param pCONN - where the request came from
358  * @param pIncommingMsg - the msg from the gateway
359  */
360 static void appsrv_processTxDataReq(struct appsrv_connection *pCONN,
361                                     struct mt_msg *pIncomingMsg)
363     int status;
364     int ind = HEADER_LEN;
365     uint8_t msgId;
366     uint16_t shortAddr;
368     /* Parse msg */
369     msgId = (uint8_t) pIncomingMsg->iobuf[ind];
370     ind += 1;
372     shortAddr = (uint16_t) (pIncomingMsg->iobuf[ind]) |
373                            (pIncomingMsg->iobuf[ind + 1] << 8);
374     ind += 2;
376     ApiMac_sAddr_t pDstAddr;
377     pDstAddr.addrMode = ApiMac_addrType_short;
378     pDstAddr.addr.shortAddr = shortAddr;
380     if(msgId == SMGS_CONFIG_REQ)
381     {
382         uint16_t framecontrol;
383         uint32_t pollingInterval;
384         uint32_t reportingInterval;
385         uint8_t configStatus;
387         pollingInterval = (uint32_t) (pIncomingMsg->iobuf[ind]) |
388                            (pIncomingMsg->iobuf[ind + 1] << 8);
389         ind += 2;
391         reportingInterval = (uint32_t) (pIncomingMsg->iobuf[ind]) |
392                            (pIncomingMsg->iobuf[ind + 1] << 8);
393         ind += 2;
395         framecontrol = (uint16_t) (pIncomingMsg->iobuf[ind]) |
396                            (pIncomingMsg->iobuf[ind + 1] << 8);
398         configStatus = Csf_sendConfigRequest(&pDstAddr, framecontrol, reportingInterval, pollingInterval);
399         LOG_printf(LOG_APPSRV_MSG_CONTENT, " Config-req sent\n");
400         LOG_printf(LOG_APPSRV_MSG_CONTENT, "Config status: %x\n", configStatus);
401     }
403     else if(msgId == SMGS_TOGGLE_REQ)
404     {
405         LOG_printf(LOG_APPSRV_MSG_CONTENT, " Toggle-req received\n");
406         Csf_sendToggleLedRequest(&pDstAddr);
407     }
409     status = ApiMac_status_success;
410     send_AppsrvTxDataCnf(status);
413 /*!
414  * @brief handle a remove device request from the gateway
415  * @param pCONN - where the request came from
416  * @param pIncommingMsg - the msg from the gateway
417  */
418 static void appsrv_processRemoveDeviceReq(struct appsrv_connection *pCONN,
419                                     struct mt_msg *pIncomingMsg)
421     int ind = HEADER_LEN;
422     uint16_t shortAddr;
423     ApiMac_sAddr_t dstAddr;
424     Llc_deviceListItem_t devListItem;
425     ApiMac_status_t status;
427     shortAddr = (uint16_t) (pIncomingMsg->iobuf[ind]) |
428                            (pIncomingMsg->iobuf[ind + 1] << 8);
430     dstAddr.addrMode = ApiMac_addrType_short;
431     dstAddr.addr.shortAddr = shortAddr;
433     if(Csf_getDevice(&dstAddr,&devListItem)){
434         /* Send disassociation request to specified sensor */
435         ApiMac_mlmeDisassociateReq_t disassocReq;
436         memset(&disassocReq, 0, sizeof(ApiMac_mlmeDisassociateReq_t));
437         disassocReq.deviceAddress.addrMode = ApiMac_addrType_short;
438         disassocReq.deviceAddress.addr.shortAddr = devListItem.devInfo.shortAddress;
439         disassocReq.devicePanId = devListItem.devInfo.panID;
440         disassocReq.disassociateReason = ApiMac_disassocateReason_coord;
441         disassocReq.txIndirect = true;
442         status = ApiMac_mlmeDisassociateReq(&disassocReq);
443         LOG_printf(LOG_APPSRV_MSG_CONTENT, "Disassociate Sent, status: %x\n", status);
444     }
447 /*!
448  * @brief handle a join permit request from the gateway
449  * @param pCONN - where the request came from
450  * @param pIncommingMsg - the msg from the gateway
451  */
452 static void appsrv_processSetJoinPermitReq(struct appsrv_connection *pCONN,
453                                            struct mt_msg *pIncomingMsg)
455     int status;
456     uint32_t duration;
457     duration = (uint32_t) (pIncomingMsg->iobuf[HEADER_LEN]) |
458                           (pIncomingMsg->iobuf[HEADER_LEN + 1] << 8) |
459                           (pIncomingMsg->iobuf[HEADER_LEN + 2] << 16) |
460                           (pIncomingMsg->iobuf[HEADER_LEN + 3] << 24);
462     /* Set the join permit */
463     LOG_printf(LOG_APPSRV_MSG_CONTENT, "\nSending duration: 0x%x\n\n",duration);
464     status = Cllc_setJoinPermit(duration);
466     /* Send cnf msg  */
467     LOG_printf(LOG_APPSRV_MSG_CONTENT, "\nSending permitCnf message\n\n");
468     send_AppSrvJoinPermitCnf(status);
471 /*!
472  * @brief handle a getnetwork info request from the gateway
473  * @param pCONN - where the request came from
474  */
475 static void appsrv_processGetNwkInfoReq(struct appsrv_connection *pCONN)
477     Llc_netInfo_t networkInfo;
478     uint8_t *pBuff;
479     int len = NWK_INFO_REQ_LEN;
481     uint8_t status = (uint8_t)Csf_getNetworkInformation(&networkInfo);
482     uint8_t securityEnabled = CONFIG_SECURE;
483     uint8_t networkMode;
484     uint8_t state = Csf_getCllcState();
486     LOG_printf(LOG_APPSRV_MSG_CONTENT, "\nSending NwkCnf STATE = %x\n\n",state);
488     if(CONFIG_FH_ENABLE == true){
489         networkMode = FREQUENCY_HOPPING;
490     }
492     else{
493         if((CONFIG_MAC_SUPERFRAME_ORDER == 15) && (CONFIG_MAC_BEACON_ORDER == 15))
494         {
495             networkMode = NON_BEACON;
496         }
497         else
498         {
499             networkMode = BEACON_ENABLED;
500         }
501     }
503     struct mt_msg *pMsg;
504     pMsg = MT_MSG_alloc(
505                 len,
506                 MT_MSG_cmd0_areq(APPSRV_SYS_ID_RPC),
507                 APPSRV_GET_NWK_INFO_CNF);
509     /* Create duplicate pointer to msg buffer for building */
510     pBuff = pMsg->iobuf + HEADER_LEN;
512     /* Build msg */
513     *pBuff++ = status;
514     *pBuff++ = (uint8_t)(networkInfo.devInfo.panID & 0xFF);
515     *pBuff++ = (uint8_t)((networkInfo.devInfo.panID >> 8) & 0xFF);
516     *pBuff++ = (uint8_t)(networkInfo.devInfo.shortAddress & 0xFF);
517     *pBuff++ = (uint8_t)((networkInfo.devInfo.shortAddress >> 8) & 0xFF);
518     *pBuff++ = (uint8_t)(networkInfo.devInfo.extAddress[0]);
519     *pBuff++ = (uint8_t)(networkInfo.devInfo.extAddress[1]);
520     *pBuff++ = (uint8_t)(networkInfo.devInfo.extAddress[2]);
521     *pBuff++ = (uint8_t)(networkInfo.devInfo.extAddress[3]);
522     *pBuff++ = (uint8_t)(networkInfo.devInfo.extAddress[4]);
523     *pBuff++ = (uint8_t)(networkInfo.devInfo.extAddress[5]);
524     *pBuff++ = (uint8_t)(networkInfo.devInfo.extAddress[6]);
525     *pBuff++ = (uint8_t)(networkInfo.devInfo.extAddress[7]);
526     *pBuff++ = (uint8_t)(networkInfo.channel);
527     *pBuff++ = (uint8_t)(networkInfo.fh);
528     *pBuff++ = securityEnabled;
529     *pBuff++ = networkMode;
530     *pBuff++ = state;
532     /* Send msg */
533     MT_MSG_setDestIface(pMsg, &(pCONN->socket_interface));
534     MT_MSG_wrBuf(pMsg, NULL, len);
535     MT_MSG_txrx(pMsg);
536     MT_MSG_free(pMsg);
537     pMsg = NULL;
540 /*!
541  * @brief  Process incoming getDeviceArrayReq message
542  *
543  * @param pConn - the connection
544  */
545 static void appsrv_processGetDeviceArrayReq(struct appsrv_connection *pCONN)
547 uint16_t n = 0;
548 uint8_t *pBuff;
549 Csf_deviceInformation_t *pDeviceInfo;
551 uint8_t status = API_MAC_STATUS_SUCCESS;
552 n = (uint16_t) Csf_getDeviceInformationList(&pDeviceInfo);
554 int len = DEV_ARRAY_HEAD_LEN + (DEV_ARRAY_INFO_LEN * n);
556 struct mt_msg *pMsg;
557     pMsg = MT_MSG_alloc(
558                 len,
559                 MT_MSG_cmd0_areq(APPSRV_SYS_ID_RPC),
560                 APPSRV_GET_DEVICE_ARRAY_CNF);
562 /* Create duplicate pointer to msg buffer for building */
563 pBuff = pMsg->iobuf + HEADER_LEN;
565 /* Build msg */
566 *pBuff++ = status;
567 *pBuff++ = (uint8_t)(n & 0xFF);
568 *pBuff++ = (uint8_t)((n >> 8) & 0xFF);
570 uint16_t x;
571 for(x = 0 ; x < n ; x++)
573     *pBuff++ = (uint8_t)(pDeviceInfo[x].devInfo.panID & 0xFF);
574     *pBuff++ = (uint8_t)((pDeviceInfo[x].devInfo.panID >> 8) & 0xFF);
575     *pBuff++ = (uint8_t)(pDeviceInfo[x].devInfo.shortAddress & 0xFF);
576     *pBuff++ = (uint8_t)((pDeviceInfo[x].devInfo.shortAddress >> 8) & 0xFF);
577     *pBuff++ = (uint8_t)(pDeviceInfo[x].devInfo.extAddress[0]);
578     *pBuff++ = (uint8_t)(pDeviceInfo[x].devInfo.extAddress[1]);
579     *pBuff++ = (uint8_t)(pDeviceInfo[x].devInfo.extAddress[2]);
580     *pBuff++ = (uint8_t)(pDeviceInfo[x].devInfo.extAddress[3]);
581     *pBuff++ = (uint8_t)(pDeviceInfo[x].devInfo.extAddress[4]);
582     *pBuff++ = (uint8_t)(pDeviceInfo[x].devInfo.extAddress[5]);
583     *pBuff++ = (uint8_t)(pDeviceInfo[x].devInfo.extAddress[6]);
584     *pBuff++ = (uint8_t)(pDeviceInfo[x].devInfo.extAddress[7]);
585     *pBuff++ = (uint8_t)(pDeviceInfo[x].capInfo.panCoord);
586     *pBuff++ = (uint8_t)(pDeviceInfo[x].capInfo.ffd);
587     *pBuff++ = (uint8_t)(pDeviceInfo[x].capInfo.mainsPower);
588     *pBuff++ = (uint8_t)(pDeviceInfo[x].capInfo.rxOnWhenIdle);
589     *pBuff++ = (uint8_t)(pDeviceInfo[x].capInfo.security);
590     *pBuff++ = (uint8_t)(pDeviceInfo[x].capInfo.allocAddr);
593 /* Send msg */
594 MT_MSG_setDestIface(pMsg, &(pCONN->socket_interface));
595 MT_MSG_wrBuf(pMsg, NULL, len);
596 MT_MSG_txrx(pMsg);
597 MT_MSG_free(pMsg);
598 pMsg = NULL;
600 if(pDeviceInfo)
601     {
602         Csf_freeDeviceInformationList(n, pDeviceInfo);
603         pDeviceInfo = NULL;
604     }
607 /******************************************************************************
608  Function Implementation
609 *****************************************************************************/
611 /*
612   Broadcast a message to all connections.
613   Public function in appsrv.h
614 */
615 void appsrv_broadcast(struct mt_msg *pMsg)
617     struct appsrv_connection *pCONN;
618     struct mt_msg *pClone;
620     /* mark all connections as "ready to broadcast" */
621     lock_connection_list();
623     for(pCONN = all_connections ; pCONN ; pCONN = pCONN->pNext)
624     {
625         pCONN->is_busy = false;
626     }
628     unlock_connection_list();
630 next_connection:
631     /* find first connection in "ready-state"
632      * NOTE: this loop is funny we goto the top
633      * and we restart scanning from the head
634      * because ... while broadcasting a new
635      * connection may appear, or one may go away
636      */
637     lock_connection_list();
638     for(pCONN = all_connections ; pCONN ; pCONN = pCONN->pNext)
639     {
640         /* this one is dead */
641         if(pCONN->is_dead)
642         {
643             continue;
644         }
645         /* is this one ready? */
647         if(pCONN->is_busy == false)
648         {
649             /* Yes we have found one */
650             pCONN->is_busy = true;
651             break;
652         }
653     }
654     unlock_connection_list();
656     /* Did we find a connection? */
657     if(pCONN)
658     {
659         /* we have a connection we can send */
660         pClone = MT_MSG_clone(pMsg);
661         if(pClone)
662         {
663             MT_MSG_setDestIface(pClone, &(pCONN->socket_interface));
664             MT_MSG_txrx(pClone);
665             MT_MSG_free(pClone);
666         }
667         /* leave this connection as 'busy'
668          * busy really means: "done"
669          * so that we do not repeat this connection
670          * we clean up the list later
671          *---
672          * Go back to the *FIRST* connection
673          * And search again.... from the top..
674          * Why? Because connections may have died...
675          */
676         goto next_connection;
677     }
679     /* if we get here - we have no more connections to broadcast to */
680     /* mark all items as idle */
681     lock_connection_list();
682     for(pCONN = all_connections ; pCONN ; pCONN = pCONN->pNext)
683     {
684         pCONN->is_busy = false;
685     }
686     unlock_connection_list();
689 /*!
690   Csf module calls this function to inform the user/appClient
691   that the application has either started/restored the network
693   Public function defined in appsrv_Collector.h
694 */
695 void appsrv_networkUpdate(bool restored, Llc_netInfo_t *networkInfo)
697     int len = NWK_INFO_IND_LEN;
698     uint8_t *pBuff;
700     uint8_t securityEnabled = CONFIG_SECURE;
701     uint8_t networkMode;
702     uint8_t state = Csf_getCllcState();
704     if(CONFIG_FH_ENABLE == true){
705         networkMode = FREQUENCY_HOPPING;
706     }
708     else{
709         if((CONFIG_MAC_SUPERFRAME_ORDER == 15) && (CONFIG_MAC_BEACON_ORDER == 15))
710         {
711             networkMode = NON_BEACON;
712         }
713         else
714         {
715             networkMode = BEACON_ENABLED;
716         }
717     }
719     struct mt_msg *pMsg;
720     pMsg = MT_MSG_alloc(
721                 len,
722                 MT_MSG_cmd0_areq(APPSRV_SYS_ID_RPC),
723                 APPSRV_NWK_INFO_IND);
725     /* Create duplicate pointer to msg buffer for building purposes */
726     pBuff = pMsg->iobuf + HEADER_LEN;
728     /* Build msg */
729     *pBuff++ = (uint8_t)(networkInfo->devInfo.panID & 0xFF);
730     *pBuff++ = (uint8_t)((networkInfo->devInfo.panID >> 8) & 0xFF);
731     *pBuff++ = (uint8_t)(networkInfo->devInfo.shortAddress & 0xFF);
732     *pBuff++ = (uint8_t)((networkInfo->devInfo.shortAddress >> 8) & 0xFF);
733     *pBuff++ = (uint8_t)(networkInfo->devInfo.extAddress[0]);
734     *pBuff++ = (uint8_t)(networkInfo->devInfo.extAddress[1]);
735     *pBuff++ = (uint8_t)(networkInfo->devInfo.extAddress[2]);
736     *pBuff++ = (uint8_t)(networkInfo->devInfo.extAddress[3]);
737     *pBuff++ = (uint8_t)(networkInfo->devInfo.extAddress[4]);
738     *pBuff++ = (uint8_t)(networkInfo->devInfo.extAddress[5]);
739     *pBuff++ = (uint8_t)(networkInfo->devInfo.extAddress[6]);
740     *pBuff++ = (uint8_t)(networkInfo->devInfo.extAddress[7]);
741     *pBuff++ = (uint8_t)(networkInfo->channel);
742     *pBuff++ = (uint8_t)(networkInfo->fh);
743     *pBuff++ = securityEnabled;
744     *pBuff++ = networkMode;
745     *pBuff++ = state;
747     /* Send msg */
748     MT_MSG_setDestIface(pMsg, &appClient_mt_interface_template);
749     MT_MSG_wrBuf(pMsg, NULL, len);
750     appsrv_broadcast(pMsg);
751     MT_MSG_free(pMsg);
752     pMsg = NULL;
755 /*!
756   Csf module calls this function to inform the user/appClient
757   that a device has joined the network
759   Public function defined in appsrv_Collector.h
760 */
761 void appsrv_deviceUpdate(Llc_deviceListItem_t *pDevListItem)
763     int len = DEVICE_JOINED_IND_LEN;
764     uint8_t *pBuff;
766     struct mt_msg *pMsg;
767     pMsg = MT_MSG_alloc(
768                 len,
769                 MT_MSG_cmd0_areq(APPSRV_SYS_ID_RPC),
770                 APPSRV_DEVICE_JOINED_IND);
772     /* Create duplicate pointer to msg buffer for building purposes */
773     pBuff = pMsg->iobuf + HEADER_LEN;
775     /* Build msg */
776     *pBuff++ = (uint8_t)(pDevListItem->devInfo.panID & 0xFF);
777     *pBuff++ = (uint8_t)((pDevListItem->devInfo.panID >> 8) & 0xFF);
778     *pBuff++ = (uint8_t)(pDevListItem->devInfo.shortAddress & 0xFF);
779     *pBuff++ = (uint8_t)((pDevListItem->devInfo.shortAddress >> 8) & 0xFF);
780     *pBuff++ = (uint8_t)(pDevListItem->devInfo.extAddress[0]);
781     *pBuff++ = (uint8_t)(pDevListItem->devInfo.extAddress[1]);
782     *pBuff++ = (uint8_t)(pDevListItem->devInfo.extAddress[2]);
783     *pBuff++ = (uint8_t)(pDevListItem->devInfo.extAddress[3]);
784     *pBuff++ = (uint8_t)(pDevListItem->devInfo.extAddress[4]);
785     *pBuff++ = (uint8_t)(pDevListItem->devInfo.extAddress[5]);
786     *pBuff++ = (uint8_t)(pDevListItem->devInfo.extAddress[6]);
787     *pBuff++ = (uint8_t)(pDevListItem->devInfo.extAddress[7]);
788     *pBuff++ = (uint8_t)(pDevListItem->capInfo.panCoord);
789     *pBuff++ = (uint8_t)(pDevListItem->capInfo.ffd);
790     *pBuff++ = (uint8_t)(pDevListItem->capInfo.mainsPower);
791     *pBuff++ = (uint8_t)(pDevListItem->capInfo.rxOnWhenIdle);
792     *pBuff++ = (uint8_t)(pDevListItem->capInfo.security);
793     *pBuff++ = (uint8_t)(pDevListItem->capInfo.allocAddr);
795     /* Send msg */
796     MT_MSG_setDestIface(pMsg, &appClient_mt_interface_template);
797     MT_MSG_wrBuf(pMsg, NULL, len);
798     appsrv_broadcast(pMsg);
799     MT_MSG_free(pMsg);
800     pMsg = NULL;
803 /*
804  * @brief common code to handle sensor data messages
805  * @param pSrcAddr - address related to this message
806  * @param rssi - signal strength from device
807  * @param pDataMsg - the sensor message
808  * @param pRspMsg - the response
809  *
810  * In the end, the message is sent to the gateway
811  */
812 static void appsrv_deviceSensorData_common(ApiMac_sAddr_t *pSrcAddr,
813                                            int8_t rssi,
814                                            Smsgs_sensorMsg_t *pDataMsg,
815                                            Smsgs_configRspMsg_t *pRspMsg)
817     /*TODO: This function should be split into two functions, one function that
818             sends the dataMsg, and one function that sends the rspMsg. This would
819             eliminate the need for the msgContent field that is needed to build
820             and parse. */
822     /* Because the sensor data msg can can be different lengths depending
823     on what information is being sent, the msg is built differently.
824     Instead of creating the msg structure initially, a dummy buffer is
825     created first, then the contents are copied into the msg's iobuf. */
827     int len = 0;
828     uint8_t *buffer;
829     uint8_t *pBuff;
830     buffer = (uint8_t*)calloc(MAX_SENSOR_DATA_LEN,sizeof(uint8_t));
831     pBuff = buffer;
833     len += 1;
834     *pBuff++ =  (uint8_t)pSrcAddr->addrMode;
835     if(pSrcAddr->addrMode == ApiMac_addrType_short)
836     {
837         len += 2;
838         *pBuff++ = (uint8_t)(pSrcAddr->addr.shortAddr & 0xFF);
839         *pBuff++ = (uint8_t)((pSrcAddr->addr.shortAddr >> 8) & 0xFF);
840     }
841     else if(pSrcAddr->addrMode == ApiMac_addrType_extended)
842     {
843         len += 8;
844         *pBuff++ = (uint8_t)(pSrcAddr->addr.extAddr[0]);
845         *pBuff++ = (uint8_t)(pSrcAddr->addr.extAddr[1]);
846         *pBuff++ = (uint8_t)(pSrcAddr->addr.extAddr[2]);
847         *pBuff++ = (uint8_t)(pSrcAddr->addr.extAddr[3]);
848         *pBuff++ = (uint8_t)(pSrcAddr->addr.extAddr[4]);
849         *pBuff++ = (uint8_t)(pSrcAddr->addr.extAddr[5]);
850         *pBuff++ = (uint8_t)(pSrcAddr->addr.extAddr[6]);
851         *pBuff++ = (uint8_t)(pSrcAddr->addr.extAddr[7]);
852     }
854     len += 1;
855     *pBuff++ = (uint8_t)rssi;
857     /* Msg type flag */
858     uint8_t msgContent = 0;
859     if(pDataMsg != NULL){
860         msgContent |= SENSOR_DATA_MSG;
861     }
862     if(pRspMsg != NULL){
863         msgContent |= CONFIG_RSP_MSG;
864     }
866     len += 1;
867     *pBuff++ = msgContent;
869     if(pDataMsg != NULL)
870     {
871         len += 11;
872         *pBuff++ = (uint8_t)(pDataMsg->cmdId);
873         *pBuff++ = (uint8_t)(pDataMsg->frameControl & 0xFF);
874         *pBuff++ = (uint8_t)((pDataMsg->frameControl >> 8) & 0xFF);
875         *pBuff++ = (uint8_t)(pDataMsg->extAddress[0]);
876         *pBuff++ = (uint8_t)(pDataMsg->extAddress[1]);
877         *pBuff++ = (uint8_t)(pDataMsg->extAddress[2]);
878         *pBuff++ = (uint8_t)(pDataMsg->extAddress[3]);
879         *pBuff++ = (uint8_t)(pDataMsg->extAddress[4]);
880         *pBuff++ = (uint8_t)(pDataMsg->extAddress[5]);
881         *pBuff++ = (uint8_t)(pDataMsg->extAddress[6]);
882         *pBuff++ = (uint8_t)(pDataMsg->extAddress[7]);
883         if(pDataMsg->frameControl & Smsgs_dataFields_tempSensor)
884         {
885             len += 4;
886             *pBuff++ = (uint8_t)(pDataMsg->tempSensor.ambienceTemp & 0xFF);
887             *pBuff++ = (uint8_t)((pDataMsg->tempSensor.ambienceTemp >> 8) & 0xFF);
888             *pBuff++ = (uint8_t)(pDataMsg->tempSensor.objectTemp & 0xFF);
889             *pBuff++ = (uint8_t)((pDataMsg->tempSensor.objectTemp >> 8) & 0xFF);
890         }
891         if(pDataMsg->frameControl & Smsgs_dataFields_lightSensor)
892         {
893             len += 2;
894             *pBuff++ = (uint8_t)(pDataMsg->lightSensor.rawData & 0xFF);
895             *pBuff++ = (uint8_t)((pDataMsg->lightSensor.rawData >> 8) & 0xFF);
896         }
897         if(pDataMsg->frameControl & Smsgs_dataFields_humiditySensor)
898         {
899             len += 4;
900             *pBuff++ = (uint8_t)(pDataMsg->humiditySensor.temp & 0xFF);
901             *pBuff++ = (uint8_t)((pDataMsg->humiditySensor.temp >> 8) & 0xFF);
902             *pBuff++ = (uint8_t)(pDataMsg->humiditySensor.humidity & 0xFF);
903             *pBuff++ = (uint8_t)((pDataMsg->humiditySensor.humidity >> 8) & 0xFF);
904         }
905         if(pDataMsg->frameControl & Smsgs_dataFields_msgStats)
906         {
907             len += 40;
908             *pBuff++ = (uint8_t)(pDataMsg->msgStats.joinAttempts & 0xFF);
909             *pBuff++ = (uint8_t)((pDataMsg->msgStats.joinAttempts >> 8) & 0xFF);
910             *pBuff++ = (uint8_t)(pDataMsg->msgStats.joinFails & 0xFF);
911             *pBuff++ = (uint8_t)((pDataMsg->msgStats.joinFails >> 8) & 0xFF);
912             *pBuff++ = (uint8_t)(pDataMsg->msgStats.msgsAttempted & 0xFF);
913             *pBuff++ = (uint8_t)((pDataMsg->msgStats.msgsAttempted >> 8) & 0xFF);
914             *pBuff++ = (uint8_t)(pDataMsg->msgStats.msgsSent & 0xFF);
915             *pBuff++ = (uint8_t)((pDataMsg->msgStats.msgsSent >> 8) & 0xFF);
916             *pBuff++ = (uint8_t)(pDataMsg->msgStats.trackingRequests & 0xFF);
917             *pBuff++ = (uint8_t)((pDataMsg->msgStats.trackingRequests >> 8) & 0xFF);
918             *pBuff++ = (uint8_t)(pDataMsg->msgStats.trackingResponseAttempts & 0xFF);
919             *pBuff++ = (uint8_t)((pDataMsg->msgStats.trackingResponseAttempts >> 8) & 0xFF);
920             *pBuff++ = (uint8_t)(pDataMsg->msgStats.trackingResponseSent & 0xFF);
921             *pBuff++ = (uint8_t)((pDataMsg->msgStats.trackingResponseSent >> 8) & 0xFF);
922             *pBuff++ = (uint8_t)(pDataMsg->msgStats.configRequests & 0xFF);
923             *pBuff++ = (uint8_t)((pDataMsg->msgStats.configRequests >> 8) & 0xFF);
924             *pBuff++ = (uint8_t)(pDataMsg->msgStats.configResponseAttempts & 0xFF);
925             *pBuff++ = (uint8_t)((pDataMsg->msgStats.configResponseAttempts >> 8) & 0xFF);
926             *pBuff++ = (uint8_t)(pDataMsg->msgStats.configResponseSent & 0xFF);
927             *pBuff++ = (uint8_t)((pDataMsg->msgStats.configResponseSent >> 8) & 0xFF);
928             *pBuff++ = (uint8_t)(pDataMsg->msgStats.channelAccessFailures & 0xFF);
929             *pBuff++ = (uint8_t)((pDataMsg->msgStats.channelAccessFailures >> 8) & 0xFF);
930             *pBuff++ = (uint8_t)(pDataMsg->msgStats.macAckFailures & 0xFF);
931             *pBuff++ = (uint8_t)((pDataMsg->msgStats.macAckFailures >> 8) & 0xFF);
932             *pBuff++ = (uint8_t)(pDataMsg->msgStats.otherDataRequestFailures & 0xFF);
933             *pBuff++ = (uint8_t)((pDataMsg->msgStats.otherDataRequestFailures >> 8) & 0xFF);
934             *pBuff++ = (uint8_t)(pDataMsg->msgStats.syncLossIndications & 0xFF);
935             *pBuff++ = (uint8_t)((pDataMsg->msgStats.syncLossIndications >> 8) & 0xFF);
936             *pBuff++ = (uint8_t)(pDataMsg->msgStats.rxDecryptFailures & 0xFF);
937             *pBuff++ = (uint8_t)((pDataMsg->msgStats.rxDecryptFailures >> 8) & 0xFF);
938             *pBuff++ = (uint8_t)(pDataMsg->msgStats.txEncryptFailures & 0xFF);
939             *pBuff++ = (uint8_t)((pDataMsg->msgStats.txEncryptFailures >> 8) & 0xFF);
940             *pBuff++ = (uint8_t)(pDataMsg->msgStats.resetCount & 0xFF);
941             *pBuff++ = (uint8_t)((pDataMsg->msgStats.resetCount >> 8) & 0xFF);
942             *pBuff++ = (uint8_t)(pDataMsg->msgStats.lastResetReason & 0xFF);
943             *pBuff++ = (uint8_t)((pDataMsg->msgStats.lastResetReason >> 8) & 0xFF);
944             *pBuff++ = (uint8_t)(pDataMsg->msgStats.joinTime & 0xFF);
945             *pBuff++ = (uint8_t)((pDataMsg->msgStats.joinTime >> 8) & 0xFF);
946             *pBuff++ = (uint8_t)(pDataMsg->msgStats.interimDelay & 0xFF);
947             *pBuff++ = (uint8_t)((pDataMsg->msgStats.interimDelay >> 8) & 0xFF);
948         }
949         if(pDataMsg->frameControl & Smsgs_dataFields_configSettings)
950         {
951             len += 8;
952             *pBuff++ = (uint8_t)(pDataMsg->configSettings.reportingInterval & 0xFF);
953             *pBuff++ = (uint8_t)((pDataMsg->configSettings.reportingInterval >> 8) & 0xFF);
954             *pBuff++ = (uint8_t)((pDataMsg->configSettings.reportingInterval >> 16) & 0xFF);
955             *pBuff++ = (uint8_t)((pDataMsg->configSettings.reportingInterval >> 24) & 0xFF);
956             *pBuff++ = (uint8_t)(pDataMsg->configSettings.pollingInterval & 0xFF);
957             *pBuff++ = (uint8_t)((pDataMsg->configSettings.pollingInterval >> 8) & 0xFF);
958             *pBuff++ = (uint8_t)((pDataMsg->configSettings.pollingInterval >> 16) & 0xFF);
959             *pBuff++ = (uint8_t)((pDataMsg->configSettings.pollingInterval >> 24) & 0xFF);
960         }
961         if(pDataMsg->frameControl & Smsgs_dataFields_pressureSensor)
962         {
963             len += 4;
964             *pBuff++ = (uint8_t)(pDataMsg->pressureSensor.tempValue & 0xFF);
965             *pBuff++ = (uint8_t)((pDataMsg->pressureSensor.tempValue >> 8) & 0xFF);
966             *pBuff++ = (uint8_t)(pDataMsg->pressureSensor.pressureValue & 0xFF);
967             *pBuff++ = (uint8_t)((pDataMsg->pressureSensor.pressureValue >> 8) & 0xFF);
968         }
969         if(pDataMsg->frameControl & Smsgs_dataFields_motionSensor)
970         {
971             len += 1;
972             *pBuff++ = (uint8_t)(pDataMsg->motionSensor.isMotion);
973         }
974         if(pDataMsg->frameControl & Smsgs_dataFields_batterySensor)
975         {
976             len += 4;
977             *pBuff++ = (uint8_t)(pDataMsg->batterySensor.voltageValue & 0xFF);
978             *pBuff++ = (uint8_t)((pDataMsg->batterySensor.voltageValue >> 8) & 0xFF);
979             *pBuff++ = (uint8_t)((pDataMsg->batterySensor.voltageValue >> 16) & 0xFF);
980             *pBuff++ = (uint8_t)((pDataMsg->batterySensor.voltageValue >> 24) & 0xFF);
981         }
982         if(pDataMsg->frameControl & Smsgs_dataFields_hallEffectSensor)
983         {
984             len += 2;
985             *pBuff++ = (uint8_t)(pDataMsg->hallEffectSensor.isOpen);
986             *pBuff++ = (uint8_t)(pDataMsg->hallEffectSensor.isTampered);
987         }
988         if(pDataMsg->frameControl & Smsgs_dataFields_fanSensor)
989         {
990             len += 1;
991             *pBuff++ = (uint8_t)(pDataMsg->fanSensor.fanSpeed);
992         }
993         if(pDataMsg->frameControl & Smsgs_dataFields_doorLockSensor)
994         {
995             len += 1;
996             *pBuff++ = (uint8_t)(pDataMsg->doorLockSensor.isLocked);
997         }
998     }
1000     if(pRspMsg != NULL)
1001     {
1002         len += 13;
1003         *pBuff++ = (uint8_t)pRspMsg->cmdId;
1004         *pBuff++ = (uint8_t)(pRspMsg->status & 0xFF);
1005         *pBuff++ = (uint8_t)((pRspMsg->status >> 8) & 0xFF);
1006         *pBuff++ = (uint8_t)(pRspMsg->frameControl & 0xFF);
1007         *pBuff++ = (uint8_t)((pRspMsg->frameControl >> 8) & 0xFF);
1008         *pBuff++ = (uint8_t)(pRspMsg->reportingInterval & 0xFF);
1009         *pBuff++ = (uint8_t)((pRspMsg->reportingInterval >> 8) & 0xFF);
1010         *pBuff++ = (uint8_t)((pRspMsg->reportingInterval >> 16) & 0xFF);
1011         *pBuff++ = (uint8_t)((pRspMsg->reportingInterval >> 24) & 0xFF);
1012         *pBuff++ = (uint8_t)(pRspMsg->pollingInterval & 0xFF);
1013         *pBuff++ = (uint8_t)((pRspMsg->pollingInterval >> 8) & 0xFF);
1014         *pBuff++ = (uint8_t)((pRspMsg->pollingInterval >> 16) & 0xFF);
1015         *pBuff++ = (uint8_t)((pRspMsg->pollingInterval >> 24) & 0xFF);
1016     }
1018     struct mt_msg *pMsg;
1019     pMsg = MT_MSG_alloc(
1020                 len,
1021                 MT_MSG_cmd0_areq(APPSRV_SYS_ID_RPC),
1022                 APPSRV_DEVICE_DATA_RX_IND);
1024     uint16_t i;
1025     for(i = 0; i < len; i++)
1026     {
1027         pMsg->iobuf[i + HEADER_LEN] = buffer[i];
1028     }
1029     free(buffer);
1031     MT_MSG_setDestIface(pMsg, &appClient_mt_interface_template);
1032     MT_MSG_wrBuf(pMsg, NULL, len);
1033     appsrv_broadcast(pMsg);
1034     MT_MSG_free(pMsg);
1035     pMsg = NULL;
1039 /*!
1040  * @brief send the remove device response to gateway
1041  */
1042 void appsrv_send_removeDeviceRsp(void)
1044     int len = REMOVE_DEVICE_RSP_LEN;
1046     struct mt_msg *pMsg;
1047     pMsg = MT_MSG_alloc(
1048                 len,
1049                 MT_MSG_cmd0_areq(APPSRV_SYS_ID_RPC),
1050                 APPSRV_RMV_DEVICE_RSP);
1052     /* Send msg */
1053     MT_MSG_setDestIface(pMsg, &appClient_mt_interface_template);
1054     MT_MSG_wrBuf(pMsg, NULL, len);
1055     appsrv_broadcast(pMsg);
1056     MT_MSG_free(pMsg);
1057     pMsg = NULL;
1060 /*!
1061   Csf module calls this function to inform the user/appClient
1062   that the device has responded to the configuration request
1064   Public function defined in appsrv_Collector.h
1065 */
1066 void appsrv_deviceConfigUpdate(ApiMac_sAddr_t *pSrcAddr, int8_t rssi,
1067                                Smsgs_configRspMsg_t *pRspMsg)
1069     appsrv_deviceSensorData_common(pSrcAddr, rssi, NULL, pRspMsg);
1071 /*!
1072   Csf module calls this function to inform the user/appClient
1073   that a device is no longer active in the network
1075   Public function defined in appsrv_Collector.h
1076 */
1077 void appsrv_deviceNotActiveUpdate(ApiMac_deviceDescriptor_t *pDevInfo,
1078                                   bool timeout)
1080     int len = DEVICE_NOT_ACTIVE_LEN;
1081     uint8_t *pBuff;
1083     struct mt_msg *pMsg;
1084     pMsg = MT_MSG_alloc(
1085                 len,
1086                 MT_MSG_cmd0_areq(APPSRV_SYS_ID_RPC),
1087                 APPSRV_DEVICE_NOTACTIVE_UPDATE_IND);
1089     /* Create duplicate pointer to msg buffer for building purposes */
1090     pBuff = pMsg->iobuf + HEADER_LEN;
1092     /* Build msg */
1093     *pBuff++ = (uint8_t)(pDevInfo->panID & 0xFF);
1094     *pBuff++ = (uint8_t)((pDevInfo->panID >> 8) & 0xFF);
1095     *pBuff++ = (uint8_t)(pDevInfo->shortAddress & 0xFF);
1096     *pBuff++ = (uint8_t)((pDevInfo->shortAddress >> 8) & 0xFF);
1097     *pBuff++ = (uint8_t)(pDevInfo->extAddress[0]);
1098     *pBuff++ = (uint8_t)(pDevInfo->extAddress[1]);
1099     *pBuff++ = (uint8_t)(pDevInfo->extAddress[2]);
1100     *pBuff++ = (uint8_t)(pDevInfo->extAddress[3]);
1101     *pBuff++ = (uint8_t)(pDevInfo->extAddress[4]);
1102     *pBuff++ = (uint8_t)(pDevInfo->extAddress[5]);
1103     *pBuff++ = (uint8_t)(pDevInfo->extAddress[6]);
1104     *pBuff++ = (uint8_t)(pDevInfo->extAddress[7]);
1105     *pBuff++ = (uint8_t)timeout;
1107     /* Send msg */
1108     MT_MSG_setDestIface(pMsg, &appClient_mt_interface_template);
1109     MT_MSG_wrBuf(pMsg, NULL, len);
1110     appsrv_broadcast(pMsg);
1111     MT_MSG_free(pMsg);
1112     pMsg = NULL;
1116 /*!
1117   Csf module calls this function to inform the user/appClient
1118   of the reported sensor data from a network device
1120   Public function defined in appsrv_Collector.h
1121 */
1122 void appsrv_deviceSensorDataUpdate(ApiMac_sAddr_t *pSrcAddr, int8_t rssi,
1123                                    Smsgs_sensorMsg_t *pSensorMsg)
1125     appsrv_deviceSensorData_common(pSrcAddr, rssi, pSensorMsg, NULL);
1128 void appsrv_stateChangeUpdate(Cllc_states_t state)
1130     int len = STATE_CHG_IND_LEN;
1131     struct mt_msg *pMsg;
1132     pMsg = MT_MSG_alloc(
1133                 len,
1134                 MT_MSG_cmd0_areq(APPSRV_SYS_ID_RPC),
1135                 APPSRV_COLLECTOR_STATE_CNG_IND);
1137     /* Build msg, no need for duplicate pointer*/
1138     pMsg->iobuf[HEADER_LEN] = (uint8_t)(state & 0xFF);
1140     MT_MSG_setDestIface(pMsg, &appClient_mt_interface_template);
1141     MT_MSG_wrBuf(pMsg, NULL, len);
1142     appsrv_broadcast(pMsg);
1143     MT_MSG_free(pMsg);
1144     pMsg = NULL;
1147 /*********************************************************************
1148  * Local Functions
1149  *********************************************************************/
1151 /*!
1152  * @brief handle a request from a client.
1153  * @param pCONN - the client connection details
1154  * @param pMsg  - the message we received.
1155  */
1156 static void appsrv_handle_appClient_request( struct appsrv_connection *pCONN,
1157                                              struct mt_msg *pMsg )
1159     int subsys = _bitsXYof(pMsg->cmd0 , 4, 0);
1160     int handled = true;
1161     if(subsys != APPSRV_SYS_ID_RPC)
1162     {
1163         handled = false;
1164     }
1165     else
1166     {
1167         switch(pMsg->cmd1)
1168         {
1169         default:
1170             handled = false;
1171             break;
1172             /*
1173              * NOTE: ADD MORE ITEMS HERE TO EXTEND THE EXAMPLE
1174              */
1175         case APPSRV_GET_DEVICE_ARRAY_REQ:
1176             /* Rcvd data from Client */
1177             LOG_printf(LOG_APPSRV_MSG_CONTENT, "\nrcvd get device array msg\n");
1178             appsrv_processGetDeviceArrayReq(pCONN);
1179             break;
1181         case APPSRV_GET_NWK_INFO_REQ:
1182             LOG_printf(LOG_APPSRV_MSG_CONTENT,"\ngetnwkinfo req message\n");
1183             appsrv_processGetNwkInfoReq(pCONN);
1184             break;
1186         case APPSRV_SET_JOIN_PERMIT_REQ:
1187             LOG_printf(LOG_APPSRV_MSG_CONTENT,"\nrcvd join premit message\n ");
1188             appsrv_processSetJoinPermitReq(pCONN, pMsg);
1189             break;
1191         case APPSRV_TX_DATA_REQ:
1192             LOG_printf(LOG_APPSRV_MSG_CONTENT,"\nrcvd req to send message to a device\n ");
1193             appsrv_processTxDataReq(pCONN, pMsg);
1194             break;
1196         case APPSRV_RMV_DEVICE_REQ:
1197             LOG_printf(LOG_APPSRV_MSG_CONTENT,"\nrcvd req to remove device\n ");
1198             appsrv_processRemoveDeviceReq(pCONN, pMsg);
1199         }
1200     }
1201     if(!handled)
1202     {
1203         MT_MSG_log(LOG_ERROR, pMsg, "unknown msg\n");
1204     }
1207 /*
1208  * @brief specific connection thread
1209  * @param cookie - opaque parameter that is the connection details.
1210  *
1211  * The server thread creates these as needed
1212  *
1213  * This thread lives until the connection dies.
1214  */
1215 static intptr_t s2appsrv_thread(intptr_t cookie)
1217     struct appsrv_connection *pCONN;
1218     struct mt_msg *pMsg;
1219     int r;
1220     char iface_name[30];
1221     char star_line[30];
1222     int star_line_char;
1224     pCONN = (struct appsrv_connection *)(cookie);
1225     if( pCONN == NULL )
1226     {
1227         BUG_HERE("pCONN is null?\n");
1228     }
1230     /* create our upstream interface */
1231     (void)snprintf(iface_name,
1232                    sizeof(iface_name),
1233                    "s2u-%d-iface",
1234                    pCONN->connection_id);
1235     pCONN->socket_interface.dbg_name = iface_name;
1237     /* Create our interface */
1238     r = MT_MSG_interfaceCreate(&(pCONN->socket_interface));
1239     if(r != 0)
1240     {
1241         BUG_HERE("Cannot create socket interface?\n");
1242     }
1244     /* Add this connection to the list. */
1245     lock_connection_list();
1246     pCONN->pNext = all_connections;
1247     pCONN->is_busy = false;
1248     all_connections = pCONN;
1249     unlock_connection_list();
1251     star_line_char = 0;
1252     /* Wait for messages to come in from the socket.. */
1253     for(;;)
1254     {
1255         /* Did the other guy die? */
1256         if(pCONN->is_dead)
1257         {
1258             break;
1259         }
1261         /* did the socket die? */
1262         if(pCONN->socket_interface.is_dead)
1263         {
1264             pCONN->is_dead = true;
1265             continue;
1266         }
1268         /* get our message */
1269         pMsg = MT_MSG_LIST_remove(&(pCONN->socket_interface),
1270                                   &(pCONN->socket_interface.rx_list), 1000);
1271         if(pMsg == NULL)
1272         {
1273             /* must have timed out. */
1274             continue;
1275         }
1277         pMsg->pLogPrefix = "web-request";
1279         /* Print a *MARKER* line in the log to help trace this message */
1280         star_line_char++;
1281         /* Cycle through the letters AAAA, BBBB, CCCC .... */
1282         star_line_char = star_line_char % 26;
1283         memset((void *)(star_line),
1284                star_line_char + 'A',
1285                sizeof(star_line) - 1);
1286         star_line[sizeof(star_line) - 1] = 0;
1287         LOG_printf(LOG_DBG_MT_MSG_traffic, "START MSG: %s\n", star_line);
1289         /* Actually process the request */
1290         appsrv_handle_appClient_request(pCONN, pMsg);
1292         /* Same *MARKER* line at the end of the message */
1293         LOG_printf(LOG_DBG_MT_MSG_traffic, "END MSG: %s\n", star_line);
1294         MT_MSG_free(pMsg);
1295     }
1297     /* There is an interock here.
1298      * FIRST: We set "is_dead"
1299      *   The broadcast code will skip this item.
1300      *   if and only if it is dead.
1301      * HOWEVER
1302      *   Q: What happens if we die in the middle of broadcasting?
1303      *   A: We must wait until the broad cast is complete
1304      *      We know this by checking the bcast_state.
1305      */
1306     while(pCONN->is_busy)
1307     {
1308         /* we must wait ... a broadcast is active. */
1309         /* so sleep alittle and try again */
1310         TIMER_sleep(10);
1311     }
1313     /* we can now remove this DEAD connection from the list. */
1314     lock_connection_list();
1315     {
1316         struct appsrv_connection **ppTHIS;
1318         /* find our self in the list of connections. */
1319         for(ppTHIS = &all_connections ;
1320             (*ppTHIS) != NULL ;
1321             ppTHIS = &((*ppTHIS)->pNext))
1322         {
1323             /* found? */
1324             if((*ppTHIS) == pCONN)
1325             {
1326                 /* yes we are done */
1327                 break;
1328             }
1329         }
1331         /* did we find this one? */
1332         if(*ppTHIS)
1333         {
1334             /* remove this one from the list */
1335             (*ppTHIS) = pCONN->pNext;
1336             pCONN->pNext = NULL;
1337         }
1338     }
1339     unlock_connection_list();
1340     /* socket is dead */
1341     /* we need to destroy the interface */
1342     MT_MSG_interfaceDestroy(&(pCONN->socket_interface));
1344     /* destroy the socket. */
1345     SOCKET_ACCEPT_destroy(pCONN->socket_interface.hndl);
1347     /* we can free this now */
1348     free((void *)pCONN);
1350     /* we do not destroy free the connection */
1351     /* this is done in the uart thread */
1352     return 0;
1355 /*
1356  * @brief This thread handles all connections from the nodeJS/gateway client.
1357  *
1358  * This server thread spawns off threads that handle
1359  * each connection from each gateway app.
1360  */
1362 static intptr_t appsrv_server_thread(intptr_t _notused)
1364     (void)(_notused);
1366     int r;
1367     intptr_t server_handle;
1368     struct appsrv_connection *pCONN;
1369     int connection_id;
1370     char buf[30];
1372     pCONN = NULL;
1373     connection_id = 0;
1375     server_handle = SOCKET_SERVER_create(&appClient_socket_cfg);
1376     if(server_handle == 0)
1377     {
1378         BUG_HERE("cannot create socket to listen\n");
1379     }
1381     r = SOCKET_SERVER_listen(server_handle);
1382     if(r != 0)
1383     {
1384         BUG_HERE("cannot set listen mode\n");
1385     }
1387     /* Wait for connections :-) */
1388     for(;;)
1389     {
1390         if(STREAM_isError(server_handle))
1391         {
1392             LOG_printf(LOG_ERROR, "server (accept) socket is dead\n");
1393             break;
1394         }
1395         if(pCONN == NULL)
1396         {
1397             pCONN = calloc(1, sizeof(*pCONN));
1398             if(pCONN == NULL)
1399             {
1400                 BUG_HERE("No memory\n");
1401             }
1402             pCONN->connection_id = connection_id++;
1404             /* clone the connection details */
1405             pCONN->socket_interface = appClient_mt_interface_template;
1407             (void)snprintf(buf,sizeof(buf),
1408                            "connection-%d",
1409                            pCONN->connection_id);
1410             pCONN->dbg_name = strdup(buf);
1411             if(pCONN->dbg_name == NULL)
1412             {
1413                 BUG_HERE("no memory\n");
1414             }
1415         }
1417         /* wait for a connection.. */
1418         r = SOCKET_SERVER_accept(&(pCONN->socket_interface.hndl),
1419                                  server_handle,
1420                                  appClient_socket_cfg.connect_timeout_mSecs);
1421         if(r < 0)
1422         {
1423             BUG_HERE("cannot accept!\n");
1424         }
1425         if(r == 0)
1426         {
1427             LOG_printf(LOG_APPSRV_CONNECTIONS, "no connection yet\n");
1428             continue;
1429         }
1430         /* we have a connection */
1431         pCONN->is_dead = false;
1433         /* create our connection threads */
1435         /* set name final use */
1436         (void)snprintf(buf, sizeof(buf),
1437                        "connection-%d",
1438                        pCONN->connection_id);
1439         pCONN->dbg_name = strdup(buf);
1440         if(pCONN->dbg_name == NULL)
1441         {
1442             BUG_HERE("no memory\n");
1443         }
1445         (void)snprintf(buf, sizeof(buf),
1446                        "thread-u2s-%d",
1447                        pCONN->connection_id);
1448         pCONN->thread_id_s2appsrv = THREAD_create(buf,
1449                                                   s2appsrv_thread,
1450                                                   (intptr_t)(pCONN),
1451                                                   THREAD_FLAGS_DEFAULT);
1453         pCONN = NULL;
1455     }
1456     return 0;
1460 /*
1461  * @brief the primary "collector thread"
1462  *
1463  * This thread never exists and performs all of
1464  * the 'collector' application tasks.
1465  */
1467 static intptr_t collector_thread(intptr_t dummy)
1469     (void)(dummy);
1470     for(;;)
1471     {
1472         /* this will "pend" on a semaphore */
1473         /* waiting for messages to come */
1474         Collector_process();
1475     }
1476 #if defined(__linux__)
1477     /* gcc complains, unreachable.. */
1478     /* other analisys tools do not .. Grrr. */
1479     return 0;
1480 #endif
1483 /*
1484   This is the main application, "linux_main.c" calls this.
1485 */
1486 void APP_main(void)
1488     int r;
1489     intptr_t server_thread_id;
1490     intptr_t collector_thread_id;
1491     struct appsrv_connection *pCONN;
1493     all_connections_mutex = MUTEX_create("all-connections");
1495     if(all_connections_mutex == 0)
1496     {
1497         BUG_HERE("cannot create connection list mutex\n");
1498     }
1500     Collector_init();
1501     r = MT_DEVICE_version_info.transport |
1502         MT_DEVICE_version_info.product |
1503         MT_DEVICE_version_info.major |
1504         MT_DEVICE_version_info.minor |
1505         MT_DEVICE_version_info.maint;
1506     if( r == 0 )
1507     {
1508         FATAL_printf( "Did not get device version info at startup - Bailing out\n");
1509     }
1511     LOG_printf( LOG_ALWAYS, "Found Mac Co-Processor Version info is:\n");
1512     LOG_printf( LOG_ALWAYS, "Transport: %d\n", MT_DEVICE_version_info.transport );
1513     LOG_printf( LOG_ALWAYS, "  Product: %d\n", MT_DEVICE_version_info.product   );
1514     LOG_printf( LOG_ALWAYS, "    Major: %d\n", MT_DEVICE_version_info.major     );
1515     LOG_printf( LOG_ALWAYS, "    Minor: %d\n", MT_DEVICE_version_info.minor     );
1516     LOG_printf( LOG_ALWAYS, "    Maint: %d\n", MT_DEVICE_version_info.maint     );
1518 #ifdef IS_HEADLESS
1519     fprintf( stdout, "Found Mac Co-Processor Version info is:\n");
1520     fprintf( stdout, "Transport: %d\n", MT_DEVICE_version_info.transport );
1521     fprintf( stdout, "  Product: %d\n", MT_DEVICE_version_info.product   );
1522     fprintf( stdout, "    Major: %d\n", MT_DEVICE_version_info.major     );
1523     fprintf( stdout, "    Minor: %d\n", MT_DEVICE_version_info.minor     );
1524     fprintf( stdout, "    Maint: %d\n", MT_DEVICE_version_info.maint     );
1525     fprintf( stdout, "----------------------------------------\n");
1526     fprintf( stdout, "Start the gateway application\n");
1527 #endif //IS_HEADLESS
1529     server_thread_id = THREAD_create("server-thread",
1530                                      appsrv_server_thread, 0,
1531                                      THREAD_FLAGS_DEFAULT);
1533     collector_thread_id = THREAD_create("collector-thread",
1534                                         collector_thread, 0, THREAD_FLAGS_DEFAULT);
1537     for(;;)
1538     {
1539         /* every 10 seconds.. */
1540         /* 10 seconds is an arbitrary value */
1541         TIMER_sleep(10 * 1000);
1542         r = 0;
1544         if(THREAD_isAlive(collector_thread_id))
1545         {
1546             r += 1;
1547         }
1549         if(THREAD_isAlive(server_thread_id))
1550         {
1551             r += 1;
1552         }
1553         /* we stay here while both *2* threads are alive */
1554         if(r != 2)
1555         {
1556             break;
1557         }
1558     }
1560     /* wait at most (N) seconds then we just 'die' */
1561     r = 0;
1562     while(r < 10)
1563     {
1565         lock_connection_list();
1566         pCONN = all_connections;
1567         /* mark them all as dead */
1568         while(pCONN)
1569         {
1570             pCONN->is_dead = true;
1571             LOG_printf(LOG_APPSRV_CONNECTIONS,
1572                        "Connection: %s is still alive\n",
1573                        pCONN->dbg_name);
1574             pCONN = pCONN->pNext;
1575         }
1576         unlock_connection_list();
1578         /* still have connections? */
1579         if(all_connections)
1580         {
1581             /* wait a second.. */
1582             TIMER_sleep(10000);
1583             /* and try again */
1584             r++;
1585             continue;
1586         }
1587         else
1588         {
1589             break;
1590         }
1591     }
1592     /* thread exit */
1595 /*!
1596  * Set default items for the application.
1597  * These are set before the ini file is read.
1598  */
1599 void APP_defaults(void)
1601     memset( (void *)(&appClient_socket_cfg), 0, sizeof(appClient_socket_cfg) );
1602     /*
1603       NOTE: All of these settings can be modified by ini file.
1604     */
1605     appClient_socket_cfg.inet_4or6 = 4;
1606     /*! this is a 's'=server, not a 'c'client */
1607     appClient_socket_cfg.ascp = 's';
1608     appClient_socket_cfg.host = NULL;
1609     /*! we listen on port 5000 */
1610     appClient_socket_cfg.service = strdup( "5000" );
1611     /*! and only allow one connection */
1612     appClient_socket_cfg.server_backlog = 1;
1613     appClient_socket_cfg.device_binding = NULL;
1614     /*! print a 'non-connect' every minute */
1615     appClient_socket_cfg.connect_timeout_mSecs = 60 * 1000;
1618 /*
1619  *  ========================================
1620  *  Texas Instruments Micro Controller Style
1621  *  ========================================
1622  *  Local Variables:
1623  *  mode: c
1624  *  c-file-style: "bsd"
1625  *  tab-width: 4
1626  *  c-basic-offset: 4
1627  *  indent-tabs-mode: nil
1628  *  End:
1629  *  vim:set  filetype=c tabstop=4 shiftwidth=4 expandtab=true
1630  */