4ce011a5ee63d5fd2d30dd3acecc586321a25981
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)
280 {
281 MUTEX_lock(all_connections_mutex, -1);
282 }
284 /* See lock() above */
285 static void unlock_connection_list(void)
286 {
287 MUTEX_unLock(all_connections_mutex);
288 }
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)
295 {
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;
320 }
322 /*!
323 * @brief send a join confirm to the gateway
324 */
325 static void send_AppSrvJoinPermitCnf(int status)
326 {
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;
351 }
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)
362 {
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);
411 }
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)
420 {
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 }
445 }
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)
454 {
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);
469 }
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)
476 {
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;
538 }
540 /*!
541 * @brief Process incoming getDeviceArrayReq message
542 *
543 * @param pConn - the connection
544 */
545 static void appsrv_processGetDeviceArrayReq(struct appsrv_connection *pCONN)
546 {
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++)
572 {
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);
591 }
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 }
605 }
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)
616 {
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();
687 }
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)
696 {
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;
753 }
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)
762 {
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;
801 }
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)
816 {
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;
1036 }
1039 /*!
1040 * @brief send the remove device response to gateway
1041 */
1042 void appsrv_send_removeDeviceRsp(void)
1043 {
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;
1058 }
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)
1068 {
1069 appsrv_deviceSensorData_common(pSrcAddr, rssi, NULL, pRspMsg);
1070 }
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)
1079 {
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;
1113 }
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)
1124 {
1125 appsrv_deviceSensorData_common(pSrcAddr, rssi, pSensorMsg, NULL);
1126 }
1128 void appsrv_stateChangeUpdate(Cllc_states_t state)
1129 {
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;
1145 }
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 )
1158 {
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 }
1205 }
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)
1216 {
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;
1353 }
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)
1363 {
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;
1457 }
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)
1468 {
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
1481 }
1483 /*
1484 This is the main application, "linux_main.c" calls this.
1485 */
1486 void APP_main(void)
1487 {
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 */
1593 }
1595 /*!
1596 * Set default items for the application.
1597 * These are set before the ini file is read.
1598 */
1599 void APP_defaults(void)
1600 {
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;
1616 }
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 */