Europalab Devices produces a LoRaWAN transmitting client node, specialised for higher research of actuator and sensor assisted IoT networks. https://dev.europalab.com/nlnet/20200000/
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

1661 Zeilen
51KB

  1. /**
  2. * \file enddevice_demo.c
  3. *
  4. * \brief Serial Provisioning of LoRaWAN Demo Application
  5. *
  6. * Copyright (c) 2020 Europalab Devices ApS
  7. *
  8. * \asf_license_start
  9. *
  10. * \page License
  11. *
  12. * This file is part of Sendcomm.
  13. *
  14. * Sendcomm is free software: you can redistribute it and/or modify
  15. * it under the terms of the GNU General Public License as published by
  16. * the Free Software Foundation, either version 3 of the License, or
  17. * (at your option) any later version.
  18. *
  19. * Sendcomm is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with Sendcomm. If not, see <https://www.gnu.org/licenses/>.
  26. *
  27. * \asf_license_stop
  28. *
  29. */
  30. /**
  31. * \mainpage
  32. * \section preface Preface
  33. * Serial Provisioning of LoRaWAN Demo Application available from Atmel Studio examples,
  34. * this is used to send the temperature sensor data through the LoRaWAN network to the network server.
  35. * <P>• This example provides an option for the user to configure the join types and provisioning paramters as per the join type chosen in run time.</P>
  36. * <P>• User if chooses NA / AU band can choose the sub-band of operation depending on the LoRaWAN Gateway being used.</P>
  37. * <P>• This example uses the commands sent over UART/TeraTerm to join/send data/sleep. </P>
  38. */
  39. /****************************** INCLUDES **************************************/
  40. #include "asf.h"
  41. #include "lorawan.h"
  42. #include "system_task_manager.h"
  43. #include "enddevice_demo.h"
  44. #include "conf_app.h"
  45. #include "sio2host.h"
  46. #include "resources.h"
  47. #include "delay.h"
  48. #include "sw_timer.h"
  49. #include "LED.h"
  50. #include "pmm.h"
  51. #include "radio_driver_hal.h"
  52. #include "conf_pmm.h"
  53. #include "conf_sio2host.h"
  54. #include "pds_interface.h"
  55. #if (EDBG_EUI_READ == 1)
  56. #include "edbg_eui.h"
  57. #endif
  58. #include "atomic.h"
  59. #include <stdint.h>
  60. /******************************** MACROS ***************************************/
  61. /************************** GLOBAL VARIABLES ***********************************/
  62. /************************** GLOBAL VARIABLES ***********************************/
  63. static bool joinTypeSelection = false;
  64. static bool keyConfigSelection = false;
  65. static bool devEuiSelectionDone = false;
  66. static bool joinEuiSelectionDone = false;
  67. static bool appKeySelectionDone = false;
  68. static bool devAddrSelectionDone = false;
  69. static bool appSkeySelectionDone = false;
  70. static bool nwkSkeySelectionDone = false;
  71. static bool verifyDemoConfigSelection = false;
  72. ActivationType_t demoJoinActivationType;
  73. static bool joined = false;
  74. static float cel_val;
  75. static float fahren_val;
  76. static char temp_sen_str[25];
  77. static uint8_t data_len = 0;
  78. bool certAppEnabled = false;
  79. static uint8_t on = LON;
  80. static uint8_t off = LOFF;
  81. static uint8_t toggle = LTOGGLE;
  82. static volatile uint8_t appTaskFlags = 0x00u;
  83. /* Default Regional band start delay time */
  84. volatile static uint8_t count = 5;
  85. static uint8_t rxchar[11];
  86. static bool startReceiving = false;
  87. extern uint8_t demoTimerId;
  88. extern uint8_t lTimerId;
  89. static AppTaskState_t appTaskState;
  90. static const char* bandStrings[] =
  91. {
  92. "FactoryDefaultReset",
  93. #if (EU_BAND == 1)
  94. "EU868",
  95. #endif
  96. #if (NA_BAND == 1)
  97. "NA915",
  98. #endif
  99. #if (AU_BAND == 1)
  100. "AU915",
  101. #endif
  102. #if (AS_BAND == 1)
  103. "AS923",
  104. #endif
  105. #if (JPN_BAND == 1)
  106. "JPN923",
  107. #endif
  108. #if (KR_BAND == 1)
  109. "KR920",
  110. #endif
  111. #if (IND_BAND == 1)
  112. "IND865",
  113. #endif
  114. "Clear PDS",
  115. "Reset Board"
  116. };
  117. uint8_t bandTable[] =
  118. {
  119. 0xFF,
  120. #if (EU_BAND == 1)
  121. ISM_EU868,
  122. #endif
  123. #if (NA_BAND == 1)
  124. ISM_NA915,
  125. #endif
  126. #if (AU_BAND == 1)
  127. ISM_AU915,
  128. #endif
  129. #if (AS_BAND == 1)
  130. ISM_THAI923,
  131. #endif
  132. #if (JPN_BAND == 1)
  133. ISM_JPN923,
  134. #endif
  135. #if (KR_BAND == 1)
  136. ISM_KR920,
  137. #endif
  138. #if (IND_BAND == 1)
  139. ISM_IND865,
  140. #endif
  141. 0xFF,
  142. 0xFF
  143. };
  144. static uint8_t tempBuff[4];
  145. #if (RANDOM_NW_ACQ == 0)
  146. /*Band Selection for NA and AU region */
  147. static uint8_t subBand = 2;
  148. #endif
  149. /*ABP Join Parameters */
  150. static uint32_t demoDevAddr;
  151. static uint8_t demoNwksKey[16];
  152. static uint8_t demoAppsKey[16];
  153. /* OTAA join parameters */
  154. static uint8_t demoDevEui[8];
  155. static uint8_t demoJoinEui[8];
  156. static uint8_t demoAppKey[16];
  157. static LorawanSendReq_t lorawanSendReq;
  158. static char serialBuffer;
  159. /* Muticast Parameters */
  160. static bool demoMcastEnable = DEMO_APP_MCAST_ENABLE;
  161. static uint32_t demoMcastDevAddr = DEMO_APP_MCAST_GROUP_ADDRESS;
  162. static uint8_t demoMcastNwksKey[16] = DEMO_APP_MCAST_NWK_SESSION_KEY;
  163. static uint8_t demoMcastAppsKey[16] = DEMO_APP_MCAST_APP_SESSION_KEY;
  164. static uint8_t demoMcastGroupId = DEMO_APP_MCAST_GROUPID;
  165. /************************** EXTERN VARIABLES ***********************************/
  166. extern bool button_pressed;
  167. extern bool factory_reset;
  168. extern bool bandSelected;
  169. extern uint32_t longPress;
  170. static void demoAddr_keyconfig_handler(void);
  171. static void sendData(void);
  172. static void appPostTask(AppTaskIds_t id);
  173. static void displaySelectedAppConfig(void);
  174. static SYSTEM_TaskStatus_t (*appTaskHandlers[])(void);
  175. static void demoTimerCb(void * cnt);
  176. static void lTimerCb(void * data);
  177. static SYSTEM_TaskStatus_t displayTask(void);
  178. static SYSTEM_TaskStatus_t processTask(void);
  179. static void processRunDemoCertApp(void);
  180. static void processRunRestoreBand(void);
  181. static void processJoinAndSend(void);
  182. static void processAppConfig(void);
  183. static void processRunDemoApp(void);
  184. static void displayRunDemoCertApp(void);
  185. static void displayRunRestoreBand(void);
  186. static void displayAppConfigMenu(void);
  187. static void displayJoinAndSend(void);
  188. static void displayRunDemoApp(void);
  189. #ifdef CONF_PMM_ENABLE
  190. static void appWakeup(uint32_t sleptDuration);
  191. static void app_resources_uninit(void);
  192. #endif
  193. /************************** FUNCTION PROTOTYPES ********************************/
  194. SYSTEM_TaskStatus_t APP_TaskHandler(void);
  195. static float convert_celsius_to_fahrenheit(float cel_val);
  196. /*********************************************************************//*
  197. \brief Function that processes the Rx data
  198. \param[in] data - Rx data payload
  199. \param[in] dataLen - The number of Rx bytes
  200. ************************************************************************/
  201. static void demo_handle_evt_rx_data(void *appHandle, appCbParams_t *appdata);
  202. /***************************** FUNCTIONS ***************************************/
  203. static SYSTEM_TaskStatus_t (*appTaskHandlers[APP_TASKS_COUNT])(void) = {
  204. /* In the order of descending priority */
  205. displayTask,
  206. processTask
  207. };
  208. /*********************************************************************//**
  209. \brief Calls appropriate functions based on state variables
  210. *************************************************************************/
  211. static SYSTEM_TaskStatus_t displayTask(void)
  212. {
  213. switch(appTaskState)
  214. {
  215. case RESTORE_BAND_STATE:
  216. displayRunRestoreBand();
  217. break;
  218. case DEMO_APP_CONFIG:
  219. displayAppConfigMenu();
  220. break;
  221. case DEMO_CERT_APP_STATE:
  222. displayRunDemoCertApp();
  223. break;
  224. case DEMO_APP_STATE:
  225. displayRunDemoApp();
  226. break;
  227. case JOIN_SEND_STATE:
  228. displayJoinAndSend();
  229. break;
  230. default:
  231. printf("Error STATE Entered\r\n");
  232. break;
  233. }
  234. return SYSTEM_TASK_SUCCESS;
  235. }
  236. /*********************************************************************//**
  237. \brief Pulls the data from UART when activated
  238. *************************************************************************/
  239. void serial_data_handler(void)
  240. {
  241. int rxChar;
  242. char serialData;
  243. /* verify if there was any character received*/
  244. if (startReceiving == true)
  245. {
  246. if((-1) != (rxChar = sio2host_getchar_nowait()))
  247. {
  248. serialData = (char)rxChar;
  249. if((serialData != '\r') && (serialData != '\n') && (serialData != '\b'))
  250. {
  251. startReceiving = false;
  252. serialBuffer = rxChar;
  253. appPostTask(PROCESS_TASK_HANDLER);
  254. printf("\r\n");
  255. }
  256. }
  257. }
  258. }
  259. uint8_t asciiToDecConverter(uint8_t input)
  260. {
  261. uint8_t decVal = -1;
  262. if (input >= 48 && input <= 57) decVal = input - 48; // decimal values between 1 and 9
  263. else if (input >= 65 && input <= 70) decVal = input - 55; // hex values between A and F
  264. else if (input >= 97 && input <= 102) decVal = input - 87; // hex values between a and f
  265. return decVal;
  266. }
  267. void serial_read_appConfig(uint8_t *buffer, uint8_t noOfBytes)
  268. {
  269. uint8_t i = 0;
  270. uint8_t temp = 0, rxDec;
  271. while (i != noOfBytes*2)
  272. {
  273. rxDec = asciiToDecConverter(sio2host_getchar());
  274. if (i%2 == 0) temp = rxDec << 4;
  275. else if (i%2 != 0) buffer[i/2] = temp + rxDec;
  276. if (rxDec != 255) i++; // increment count only when receiving a valid hex value from 0-F
  277. }
  278. }
  279. static void displaySelectedAppConfig(void)
  280. {
  281. uint8_t i = 0;
  282. if (demoJoinActivationType == OVER_THE_AIR_ACTIVATION)
  283. {
  284. printf("Activation Type: OVER THE AIR ACTIVATION (OTAA)\r\n");
  285. printf("Device EUI: 0x");
  286. for (i=0;i<8;i++) printf("%x",demoDevEui[i]);
  287. printf("\r\n");
  288. printf("Join EUI: 0x");
  289. for (i=0;i<8;i++) printf("%x",demoJoinEui[i]);
  290. printf("\r\n");
  291. printf("Application Key: 0x");
  292. for (i=0;i<16;i++) printf("%x",demoAppKey[i]);
  293. printf("\r\n");
  294. }
  295. else if (demoJoinActivationType == ACTIVATION_BY_PERSONALIZATION)
  296. {
  297. printf("Activation Type: ACTIVATION BY PERSONALIZATION (ABP)\r\n");
  298. printf("Device Address: 0x%lx\r\n",demoDevAddr);
  299. printf("Application Session Key: 0x");
  300. for (i=0;i<16;i++) printf("%x",demoAppsKey[i]);
  301. printf("\r\n");
  302. printf("Network Session Key: 0x");
  303. for (i=0;i<16;i++) printf("%x",demoNwksKey[i]);
  304. printf("\r\n");
  305. }
  306. }
  307. /*********************************************************************//**
  308. \brief Handle the Key / addresses based on Join Mechanism Chosen
  309. *************************************************************************/
  310. static void demoAddr_keyconfig_handler(void)
  311. {
  312. if (demoJoinActivationType == OVER_THE_AIR_ACTIVATION)
  313. {
  314. if (devEuiSelectionDone == false)
  315. {
  316. serial_read_appConfig(demoDevEui, 8);
  317. devEuiSelectionDone = true;
  318. }
  319. else if (joinEuiSelectionDone == false)
  320. {
  321. serial_read_appConfig(demoJoinEui, 8);
  322. joinEuiSelectionDone = true;
  323. }
  324. else if (appKeySelectionDone == false)
  325. {
  326. serial_read_appConfig(demoAppKey, 16);
  327. appKeySelectionDone = true;
  328. }
  329. }
  330. else if (demoJoinActivationType == ACTIVATION_BY_PERSONALIZATION)
  331. {
  332. if (devAddrSelectionDone == false)
  333. {
  334. serial_read_appConfig(tempBuff, 4);
  335. demoDevAddr = (uint32_t)tempBuff[0] << 24 | (uint32_t)tempBuff[1] << 16 | (uint32_t)tempBuff[2] << 8 | (uint32_t)tempBuff[3];
  336. devAddrSelectionDone = true;
  337. }
  338. else if (appSkeySelectionDone == false)
  339. {
  340. serial_read_appConfig(demoAppsKey, 16);
  341. appSkeySelectionDone = true;
  342. }
  343. else if (nwkSkeySelectionDone == false)
  344. {
  345. serial_read_appConfig(demoNwksKey, 16);
  346. nwkSkeySelectionDone = true;
  347. }
  348. }
  349. }
  350. /*********************************************************************//**
  351. \brief Calls appropriate functions based on state variables
  352. *************************************************************************/
  353. static SYSTEM_TaskStatus_t processTask(void)
  354. {
  355. switch(appTaskState)
  356. {
  357. case RESTORE_BAND_STATE:
  358. processRunRestoreBand();
  359. break;
  360. case DEMO_APP_CONFIG:
  361. processAppConfig();
  362. break;
  363. case DEMO_CERT_APP_STATE:
  364. processRunDemoCertApp();
  365. break;
  366. case DEMO_APP_STATE:
  367. processRunDemoApp();
  368. break;
  369. case JOIN_SEND_STATE:
  370. processJoinAndSend();
  371. break;
  372. default:
  373. printf("Error STATE Entered\r\n");
  374. break;
  375. }
  376. return SYSTEM_TASK_SUCCESS;
  377. }
  378. /*********************************************************************//**
  379. \brief Activates demo application or certification application
  380. *************************************************************************/
  381. static void processRunDemoCertApp(void)
  382. {
  383. if(serialBuffer == '1')
  384. {
  385. appTaskState = DEMO_APP_STATE;
  386. appPostTask(DISPLAY_TASK_HANDLER);
  387. }
  388. else
  389. {
  390. printf("Please enter a valid choice\r\n");
  391. appTaskState = DEMO_CERT_APP_STATE;
  392. appPostTask(DISPLAY_TASK_HANDLER);
  393. }
  394. }
  395. /*********************************************************************//**
  396. \brief Restores the previous band and runs
  397. *************************************************************************/
  398. static void processRunRestoreBand(void)
  399. {
  400. StackRetStatus_t status = LORAWAN_SUCCESS;
  401. uint8_t prevBand = 0xff;
  402. uint8_t choice = 0xff;
  403. bool joinBackoffEnable = false;
  404. PDS_RestoreAll();
  405. LORAWAN_GetAttr(ISMBAND,NULL,&prevBand);
  406. for (uint32_t i = 0; i < sizeof(bandTable)-1; i++)
  407. {
  408. if(bandTable[i] == prevBand)
  409. {
  410. choice = i;
  411. break;
  412. }
  413. }
  414. if(choice >0 && choice < sizeof(bandTable)-1)
  415. {
  416. status = LORAWAN_Reset(bandTable[choice]);
  417. }
  418. /*Disabled Join backoff in Demo application
  419. Needs to be enabled in Production Environment Ref Section */
  420. LORAWAN_SetAttr(JOIN_BACKOFF_ENABLE,&joinBackoffEnable);
  421. if(status == LORAWAN_SUCCESS && choice < sizeof(bandTable)-1)
  422. {
  423. uint32_t joinStatus = 0;
  424. PDS_RestoreAll();
  425. LORAWAN_GetAttr(LORAWAN_STATUS,NULL, &joinStatus);
  426. printf("\r\nPDS_RestorationStatus: Success\r\n" );
  427. if(joinStatus & LORAWAN_NW_JOINED)
  428. {
  429. joined = true;
  430. printf("joinStatus: Joined\r\n");
  431. }
  432. else
  433. {
  434. joined = false;
  435. printf("JoinStatus : Denied\r\n");
  436. set_LED_data(LED_AMBER,&on);
  437. SYSTEM_PostTask(APP_TASK_ID);
  438. }
  439. printf("Band: %s\r\n",bandStrings[choice]);
  440. print_application_config();
  441. appTaskState = JOIN_SEND_STATE;
  442. appPostTask(DISPLAY_TASK_HANDLER);
  443. }
  444. else
  445. {
  446. printf("Restoration failed\r\n");
  447. appTaskState = DEMO_APP_STATE;
  448. appPostTask(DISPLAY_TASK_HANDLER);
  449. }
  450. }
  451. /*********************************************************************//**
  452. \brief Sends Join request or Data to the network
  453. *************************************************************************/
  454. static void processJoinAndSend(void)
  455. {
  456. StackRetStatus_t status = LORAWAN_SUCCESS;
  457. if(serialBuffer == '1')
  458. {
  459. status = LORAWAN_Join(demoJoinActivationType);
  460. if (LORAWAN_SUCCESS == (StackRetStatus_t)status)
  461. {
  462. set_LED_data(LED_RED,&on);
  463. printf("\nJoin Request Sent\n\r");
  464. }
  465. else
  466. {
  467. set_LED_data(LED_AMBER,&on);
  468. print_stack_status(status);
  469. appTaskState = JOIN_SEND_STATE;
  470. appPostTask(DISPLAY_TASK_HANDLER);
  471. }
  472. }
  473. else if(serialBuffer == '2' && joined == true)
  474. {
  475. sendData();
  476. }
  477. else if(serialBuffer == '2' && !joined)
  478. {
  479. set_LED_data(LED_AMBER,&on);
  480. printf("Device not joined to the network\r\n");
  481. appTaskState = JOIN_SEND_STATE;
  482. appPostTask(DISPLAY_TASK_HANDLER);
  483. }
  484. #ifdef CONF_PMM_ENABLE
  485. else if(serialBuffer == '3')
  486. {
  487. static bool deviceResetsForWakeup = false;
  488. PMM_SleepReq_t sleepReq;
  489. /* Put the application to sleep */
  490. sleepReq.sleepTimeMs = DEMO_CONF_DEFAULT_APP_SLEEP_TIME_MS;
  491. sleepReq.pmmWakeupCallback = appWakeup;
  492. sleepReq.sleep_mode = CONF_PMM_SLEEPMODE_WHEN_IDLE;
  493. if (CONF_PMM_SLEEPMODE_WHEN_IDLE == SLEEP_MODE_STANDBY)
  494. {
  495. deviceResetsForWakeup = false;
  496. }
  497. if (true == LORAWAN_ReadyToSleep(deviceResetsForWakeup))
  498. {
  499. app_resources_uninit();
  500. if (PMM_SLEEP_REQ_DENIED == PMM_Sleep(&sleepReq))
  501. {
  502. HAL_Radio_resources_init();
  503. sio2host_init();
  504. appTaskState = JOIN_SEND_STATE;
  505. appPostTask(DISPLAY_TASK_HANDLER);
  506. printf("\r\nsleep_not_ok\r\n");
  507. }
  508. }
  509. else
  510. {
  511. printf("\r\nsleep_not_ok\r\n");
  512. appTaskState = JOIN_SEND_STATE;
  513. appPostTask(DISPLAY_TASK_HANDLER);
  514. }
  515. }
  516. else if(serialBuffer == '4')
  517. #else
  518. else if(serialBuffer == '3')
  519. #endif
  520. {
  521. appTaskState = DEMO_APP_STATE;
  522. appPostTask(DISPLAY_TASK_HANDLER);
  523. }
  524. else
  525. {
  526. set_LED_data(LED_AMBER,&on);
  527. printf("Invalid choice entered\r\n");
  528. appTaskState = JOIN_SEND_STATE;
  529. appPostTask(DISPLAY_TASK_HANDLER);
  530. }
  531. }
  532. /*********************************************************************//**
  533. \brief Runs the Demo application
  534. *************************************************************************/
  535. static void processRunDemoApp(void)
  536. {
  537. uint8_t num = serialBuffer - '0';
  538. if(num == sizeof(bandTable)-1)
  539. {
  540. NVIC_SystemReset();
  541. }
  542. else if(num == sizeof(bandTable)-2)
  543. {
  544. PDS_DeleteAll();
  545. appTaskState = DEMO_APP_STATE;
  546. appPostTask(DISPLAY_TASK_HANDLER);
  547. }
  548. else if(num >0 && num < sizeof(bandTable) -2)
  549. {
  550. LORAWAN_Reset(bandTable[num]);
  551. #if (RANDOM_NW_ACQ == 0)
  552. if (bandTable[num] == ISM_NA915 || bandTable[num] == ISM_AU915)
  553. {
  554. printf("\r\nEnter SUBBAND(1-8): ");
  555. subBand = sio2host_getchar() - '0';
  556. }
  557. #endif
  558. mote_set_parameters(bandTable[num],num);
  559. set_LED_data(LED_RED,&on);
  560. }
  561. else
  562. {
  563. printf("Not a valid regional band choice\r\n");
  564. appTaskState = DEMO_APP_STATE;
  565. appPostTask(DISPLAY_TASK_HANDLER);
  566. }
  567. }
  568. /*********************************************************************//**
  569. \brief configures the configuration for Demo application
  570. *************************************************************************/
  571. static void processAppConfig(void)
  572. {
  573. uint8_t choice = serialBuffer - '0';
  574. if(joinTypeSelection == false && choice >= 1 && choice <= 2)
  575. {
  576. if (choice == 1) demoJoinActivationType = OVER_THE_AIR_ACTIVATION;
  577. else demoJoinActivationType = ACTIVATION_BY_PERSONALIZATION;
  578. joinTypeSelection = true;
  579. appPostTask(DISPLAY_TASK_HANDLER);
  580. }
  581. else if (joinTypeSelection == false && choice < 0 && choice > 2)
  582. {
  583. printf("Not a valid join type\r\n");
  584. appPostTask(DISPLAY_TASK_HANDLER);
  585. }
  586. else if (joinTypeSelection == true && keyConfigSelection == false)
  587. {
  588. demoAddr_keyconfig_handler();
  589. if ((devEuiSelectionDone && joinEuiSelectionDone && appKeySelectionDone) ||
  590. (devAddrSelectionDone && appSkeySelectionDone && nwkSkeySelectionDone)) keyConfigSelection = true;
  591. appPostTask(DISPLAY_TASK_HANDLER);
  592. }
  593. else if (joinTypeSelection == true && keyConfigSelection == true && verifyDemoConfigSelection == false)
  594. {
  595. if (choice == 1)
  596. {
  597. verifyDemoConfigSelection = true;
  598. }
  599. else if (choice == 2)
  600. {
  601. joinTypeSelection = false;
  602. keyConfigSelection = false;
  603. devEuiSelectionDone = false;
  604. joinEuiSelectionDone = false;
  605. appKeySelectionDone = false;
  606. devAddrSelectionDone = false;
  607. appSkeySelectionDone = false;
  608. nwkSkeySelectionDone = false;
  609. }
  610. appPostTask(DISPLAY_TASK_HANDLER);
  611. }
  612. }
  613. /*********************************************************************//**
  614. \brief Displays and activates LED's to choose between Demo
  615. and Certification application
  616. *************************************************************************/
  617. static void displayRunDemoCertApp(void)
  618. {
  619. //sio2host_rx(rxchar,10);
  620. set_LED_data(LED_AMBER,&off);
  621. set_LED_data(LED_RED,&off);
  622. printf("\r\n--Choose Application Type--\r\n");
  623. printf("1. Demo application\r\n");
  624. printf("\r\n Select Application : ");
  625. startReceiving = true;
  626. }
  627. /*********************************************************************//**
  628. \brief Activates LED's to indicate restoring of band
  629. *************************************************************************/
  630. static void displayRunRestoreBand(void)
  631. {
  632. //sio2host_rx(rxchar,10);
  633. set_LED_data(LED_AMBER,&off);
  634. set_LED_data(LED_RED,&off);
  635. appPostTask(PROCESS_TASK_HANDLER);
  636. }
  637. /*********************************************************************//**
  638. \brief Display App Configuration Options Available
  639. *************************************************************************/
  640. static void displayAppConfigMenu(void)
  641. {
  642. if (joinTypeSelection == false)
  643. {
  644. printf("\r\n---Join Type Selection---\r\n");
  645. printf("1. Over The Air Activation(OTAA)\r\n");
  646. printf("2. Activation By Personalization(ABP)\r\n");
  647. printf("\r\nEnter your choice: ");
  648. startReceiving = true;
  649. }
  650. else if (joinTypeSelection == true && keyConfigSelection == false)
  651. {
  652. if (demoJoinActivationType == OVER_THE_AIR_ACTIVATION)
  653. {
  654. if (devEuiSelectionDone == false) printf("\r\nEnter Device EUI(hex 0-F): ");
  655. else if (joinEuiSelectionDone == false) printf("\r\nEnter Join EUI(hex 0-F): ");
  656. else if (appKeySelectionDone == false) printf("\r\nEnter Application Key(hex 0-F): ");
  657. }
  658. else if (demoJoinActivationType == ACTIVATION_BY_PERSONALIZATION)
  659. {
  660. if (devAddrSelectionDone == false) printf("\r\nEnter Device Address(hex 0-F): ");
  661. else if (appSkeySelectionDone == false) printf("\r\nEnter Application Session Key(hex 0-F): ");
  662. else if (nwkSkeySelectionDone == false) printf("\r\nEnter Network Session Key(hex 0-F): ");
  663. }
  664. appPostTask(PROCESS_TASK_HANDLER);
  665. startReceiving = false;
  666. }
  667. else if (joinTypeSelection == true && keyConfigSelection == true && verifyDemoConfigSelection == false)
  668. {
  669. printf("\r\n\r\n---Configuration Selected ---\r\n");
  670. displaySelectedAppConfig();
  671. printf("\r\n1. Confirm App Configuration Selection\r\n");
  672. printf("2. Modify Configuration \r\n");
  673. printf("Enter your choice: ");
  674. startReceiving = true;
  675. }
  676. else if (joinTypeSelection == true && keyConfigSelection == true && verifyDemoConfigSelection == true)
  677. {
  678. appTaskState = DEMO_CERT_APP_STATE;
  679. appPostTask(DISPLAY_TASK_HANDLER);
  680. }
  681. }
  682. /*********************************************************************//**
  683. \brief Displays and activates LED's for joining to a network
  684. and sending data to a network
  685. *************************************************************************/
  686. static void displayJoinAndSend(void)
  687. {
  688. printf("\r\n1. Send Join Request\r\n");
  689. printf("2. Send Data\r\n");
  690. #ifdef CONF_PMM_ENABLE
  691. printf("3. Sleep\r\n");
  692. printf("4. Select Band\r\n");
  693. #else
  694. printf("3. Select Band\r\n");
  695. #endif /* CONF_PMM_ENABLE */
  696. printf("\r\nEnter your choice: ");
  697. set_LED_data(LED_AMBER,&off);
  698. set_LED_data(LED_RED,&off);
  699. startReceiving = true;
  700. }
  701. /*********************************************************************//**
  702. \brief Displays and activates LED's for selecting Demo application
  703. *************************************************************************/
  704. static void displayRunDemoApp(void)
  705. {
  706. uint8_t i = 0;
  707. set_LED_data(LED_AMBER,&off);
  708. set_LED_data(LED_RED,&off);
  709. printf("\r\nPlease select one of the band given below\r\n");
  710. for(i = 1;i < sizeof(bandTable); i++)
  711. {
  712. printf("%d. %s\r\n",i,bandStrings[i]);
  713. }
  714. printf("Select Regional Band : ");
  715. startReceiving = true;
  716. }
  717. /*********************************************************************//**
  718. \brief Initialization the Demo application
  719. *************************************************************************/
  720. void mote_demo_init(void)
  721. {
  722. bool status = false;
  723. /* Initialize the resources */
  724. resource_init();
  725. startReceiving = false;
  726. /* Initialize the LORAWAN Stack */
  727. LORAWAN_Init(demo_appdata_callback, demo_joindata_callback);
  728. printf("\n\n\r*******************************************************\n\r");
  729. printf("\n\rDemocratic SendComm 2020");
  730. printf("\n\rLibrary: %s\r\n",STACK_VER);
  731. printf("\r\nInit - Successful\r\n");
  732. status = PDS_IsRestorable();
  733. if(status)
  734. {
  735. static uint8_t prevBand = 0xFF;
  736. uint8_t prevChoice = 0xFF;
  737. PDS_RestoreAll();
  738. LORAWAN_GetAttr(ISMBAND,NULL,&prevBand);
  739. for (uint32_t i = 0; i < sizeof(bandTable) -1; i++)
  740. {
  741. if(bandTable[i] == prevBand)
  742. {
  743. prevChoice = i;
  744. break;
  745. }
  746. }
  747. memset(rxchar,0,sizeof(rxchar));
  748. sio2host_rx(rxchar,10);
  749. printf ("Last configured Regional band %s\r\n",bandStrings[prevChoice]);
  750. printf("Press any key to change band\r\n Continuing in %s in ", bandStrings[prevChoice]);
  751. SwTimerStart(demoTimerId,MS_TO_US(1000),SW_TIMEOUT_RELATIVE,(void *)demoTimerCb,NULL);
  752. }
  753. else
  754. {
  755. appTaskState = DEMO_APP_CONFIG;
  756. appPostTask(DISPLAY_TASK_HANDLER);
  757. }
  758. }
  759. /*********************************************************************//*
  760. \brief Function that processes the Rx data
  761. \param[in] data - Rx data payload
  762. \param[in] dataLen - The number of Rx bytes
  763. ************************************************************************/
  764. static void demo_handle_evt_rx_data(void *appHandle, appCbParams_t *appdata)
  765. {
  766. uint8_t *pData = appdata->param.rxData.pData;
  767. uint8_t dataLength = appdata->param.rxData.dataLength;
  768. uint32_t devAddress = appdata->param.rxData.devAddr;
  769. //Successful transmission
  770. if((dataLength > 0U) && (NULL != pData))
  771. {
  772. printf("*** Received DL Data ***\n\r");
  773. printf("\nFrame Received at port %d\n\r",pData[0]);
  774. printf("\nFrame Length - %d\n\r",dataLength);
  775. printf("\nAddress - 0x%lx\n\r", devAddress);
  776. printf ("\nPayload: ");
  777. for (uint8_t i =0; i<dataLength - 1; i++)
  778. {
  779. printf("%x",pData[i+1]);
  780. }
  781. printf("\r\n*************************\r\n");
  782. }
  783. else
  784. {
  785. printf("Received ACK for Confirmed data\r\n");
  786. }
  787. }
  788. /*********************************************************************//**
  789. \brief Callback function for the ending of Bidirectional communication of
  790. Application data
  791. *************************************************************************/
  792. void demo_appdata_callback(void *appHandle, appCbParams_t *appdata)
  793. {
  794. StackRetStatus_t status = LORAWAN_INVALID_REQUEST;
  795. if (LORAWAN_EVT_RX_DATA_AVAILABLE == appdata->evt)
  796. {
  797. status = appdata->param.rxData.status;
  798. switch(status)
  799. {
  800. case LORAWAN_SUCCESS:
  801. {
  802. demo_handle_evt_rx_data(appHandle, appdata);
  803. }
  804. break;
  805. case LORAWAN_RADIO_NO_DATA:
  806. {
  807. printf("\n\rRADIO_NO_DATA \n\r");
  808. }
  809. break;
  810. case LORAWAN_RADIO_DATA_SIZE:
  811. printf("\n\rRADIO_DATA_SIZE \n\r");
  812. break;
  813. case LORAWAN_RADIO_INVALID_REQ:
  814. printf("\n\rRADIO_INVALID_REQ \n\r");
  815. break;
  816. case LORAWAN_RADIO_BUSY:
  817. printf("\n\rRADIO_BUSY \n\r");
  818. break;
  819. case LORAWAN_RADIO_OUT_OF_RANGE:
  820. printf("\n\rRADIO_OUT_OF_RANGE \n\r");
  821. break;
  822. case LORAWAN_RADIO_UNSUPPORTED_ATTR:
  823. printf("\n\rRADIO_UNSUPPORTED_ATTR \n\r");
  824. break;
  825. case LORAWAN_RADIO_CHANNEL_BUSY:
  826. printf("\n\rRADIO_CHANNEL_BUSY \n\r");
  827. break;
  828. case LORAWAN_NWK_NOT_JOINED:
  829. printf("\n\rNWK_NOT_JOINED \n\r");
  830. break;
  831. case LORAWAN_INVALID_PARAMETER:
  832. printf("\n\rINVALID_PARAMETER \n\r");
  833. break;
  834. case LORAWAN_KEYS_NOT_INITIALIZED:
  835. printf("\n\rKEYS_NOT_INITIALIZED \n\r");
  836. break;
  837. case LORAWAN_SILENT_IMMEDIATELY_ACTIVE:
  838. printf("\n\rSILENT_IMMEDIATELY_ACTIVE\n\r");
  839. break;
  840. case LORAWAN_FCNTR_ERROR_REJOIN_NEEDED:
  841. printf("\n\rFCNTR_ERROR_REJOIN_NEEDED \n\r");
  842. break;
  843. case LORAWAN_INVALID_BUFFER_LENGTH:
  844. printf("\n\rINVALID_BUFFER_LENGTH \n\r");
  845. break;
  846. case LORAWAN_MAC_PAUSED :
  847. printf("\n\rMAC_PAUSED \n\r");
  848. break;
  849. case LORAWAN_NO_CHANNELS_FOUND:
  850. printf("\n\rNO_CHANNELS_FOUND \n\r");
  851. break;
  852. case LORAWAN_BUSY:
  853. printf("\n\rBUSY\n\r");
  854. break;
  855. case LORAWAN_NO_ACK:
  856. printf("\n\rNO_ACK \n\r");
  857. break;
  858. case LORAWAN_NWK_JOIN_IN_PROGRESS:
  859. printf("\n\rALREADY JOINING IS IN PROGRESS \n\r");
  860. break;
  861. case LORAWAN_RESOURCE_UNAVAILABLE:
  862. printf("\n\rRESOURCE_UNAVAILABLE \n\r");
  863. break;
  864. case LORAWAN_INVALID_REQUEST:
  865. printf("\n\rINVALID_REQUEST \n\r");
  866. break;
  867. case LORAWAN_FCNTR_ERROR:
  868. printf("\n\rFCNTR_ERROR \n\r");
  869. break;
  870. case LORAWAN_MIC_ERROR:
  871. printf("\n\rMIC_ERROR \n\r");
  872. break;
  873. case LORAWAN_INVALID_MTYPE:
  874. printf("\n\rINVALID_MTYPE \n\r");
  875. break;
  876. case LORAWAN_MCAST_HDR_INVALID:
  877. printf("\n\rMCAST_HDR_INVALID \n\r");
  878. break;
  879. case LORAWAN_INVALID_PACKET:
  880. printf("\n\rINVALID_PACKET \n\r");
  881. break;
  882. default:
  883. printf("UNKNOWN ERROR\n\r");
  884. break;
  885. }
  886. }
  887. else if(LORAWAN_EVT_TRANSACTION_COMPLETE == appdata->evt)
  888. {
  889. switch(status = appdata->param.transCmpl.status)
  890. {
  891. case LORAWAN_SUCCESS:
  892. {
  893. printf("Transmission Success\r\n");
  894. }
  895. break;
  896. case LORAWAN_RADIO_SUCCESS:
  897. {
  898. printf("Transmission Success\r\n");
  899. }
  900. break;
  901. case LORAWAN_RADIO_NO_DATA:
  902. {
  903. printf("\n\rRADIO_NO_DATA \n\r");
  904. }
  905. break;
  906. case LORAWAN_RADIO_DATA_SIZE:
  907. printf("\n\rRADIO_DATA_SIZE \n\r");
  908. break;
  909. case LORAWAN_RADIO_INVALID_REQ:
  910. printf("\n\rRADIO_INVALID_REQ \n\r");
  911. break;
  912. case LORAWAN_RADIO_BUSY:
  913. printf("\n\rRADIO_BUSY \n\r");
  914. break;
  915. case LORAWAN_TX_TIMEOUT:
  916. printf("\nTx Timeout\n\r");
  917. break;
  918. case LORAWAN_RADIO_OUT_OF_RANGE:
  919. printf("\n\rRADIO_OUT_OF_RANGE \n\r");
  920. break;
  921. case LORAWAN_RADIO_UNSUPPORTED_ATTR:
  922. printf("\n\rRADIO_UNSUPPORTED_ATTR \n\r");
  923. break;
  924. case LORAWAN_RADIO_CHANNEL_BUSY:
  925. printf("\n\rRADIO_CHANNEL_BUSY \n\r");
  926. break;
  927. case LORAWAN_NWK_NOT_JOINED:
  928. printf("\n\rNWK_NOT_JOINED \n\r");
  929. break;
  930. case LORAWAN_INVALID_PARAMETER:
  931. printf("\n\rINVALID_PARAMETER \n\r");
  932. break;
  933. case LORAWAN_KEYS_NOT_INITIALIZED:
  934. printf("\n\rKEYS_NOT_INITIALIZED \n\r");
  935. break;
  936. case LORAWAN_SILENT_IMMEDIATELY_ACTIVE:
  937. printf("\n\rSILENT_IMMEDIATELY_ACTIVE\n\r");
  938. break;
  939. case LORAWAN_FCNTR_ERROR_REJOIN_NEEDED:
  940. printf("\n\rFCNTR_ERROR_REJOIN_NEEDED \n\r");
  941. break;
  942. case LORAWAN_INVALID_BUFFER_LENGTH:
  943. printf("\n\rINVALID_BUFFER_LENGTH \n\r");
  944. break;
  945. case LORAWAN_MAC_PAUSED :
  946. printf("\n\rMAC_PAUSED \n\r");
  947. break;
  948. case LORAWAN_NO_CHANNELS_FOUND:
  949. printf("\n\rNO_CHANNELS_FOUND \n\r");
  950. break;
  951. case LORAWAN_BUSY:
  952. printf("\n\rBUSY\n\r");
  953. break;
  954. case LORAWAN_NO_ACK:
  955. printf("\n\rNO_ACK \n\r");
  956. break;
  957. case LORAWAN_NWK_JOIN_IN_PROGRESS:
  958. printf("\n\rALREADY JOINING IS IN PROGRESS \n\r");
  959. break;
  960. case LORAWAN_RESOURCE_UNAVAILABLE:
  961. printf("\n\rRESOURCE_UNAVAILABLE \n\r");
  962. break;
  963. case LORAWAN_INVALID_REQUEST:
  964. printf("\n\rINVALID_REQUEST \n\r");
  965. break;
  966. case LORAWAN_FCNTR_ERROR:
  967. printf("\n\rFCNTR_ERROR \n\r");
  968. break;
  969. case LORAWAN_MIC_ERROR:
  970. printf("\n\rMIC_ERROR \n\r");
  971. break;
  972. case LORAWAN_INVALID_MTYPE:
  973. printf("\n\rINVALID_MTYPE \n\r");
  974. break;
  975. case LORAWAN_MCAST_HDR_INVALID:
  976. printf("\n\rMCAST_HDR_INVALID \n\r");
  977. break;
  978. case LORAWAN_INVALID_PACKET:
  979. printf("\n\rINVALID_PACKET \n\r");
  980. break;
  981. default:
  982. printf("\n\rUNKNOWN ERROR\n\r");
  983. break;
  984. }
  985. printf("\n\r*************************************************\n\r");
  986. }
  987. SwTimerStop(lTimerId);
  988. set_LED_data(LED_RED,&off);
  989. if(status != LORAWAN_SUCCESS)
  990. {
  991. set_LED_data(LED_AMBER,&on);
  992. }
  993. appTaskState = JOIN_SEND_STATE;
  994. appPostTask(DISPLAY_TASK_HANDLER);
  995. }
  996. /*********************************************************************//*
  997. \brief Callback function for the ending of Activation procedure
  998. ************************************************************************/
  999. void demo_joindata_callback(StackRetStatus_t status)
  1000. {
  1001. /* This is called every time the join process is finished */
  1002. set_LED_data(LED_RED,&off);
  1003. if(LORAWAN_SUCCESS == status)
  1004. {
  1005. uint32_t devAddress;
  1006. bool mcastEnabled;
  1007. joined = true;
  1008. printf("\nJoining Successful\n\r");
  1009. LORAWAN_GetAttr(DEV_ADDR, NULL, &devAddress);
  1010. LORAWAN_GetAttr(MCAST_ENABLE, NULL, &mcastEnabled);
  1011. if (devAddress != DEMO_APP_MCAST_GROUP_ADDRESS)
  1012. {
  1013. printf("\nDevAddr: 0x%lx\n\r", devAddress);
  1014. }
  1015. else if ((devAddress == DEMO_APP_MCAST_GROUP_ADDRESS) && (true == mcastEnabled))
  1016. {
  1017. printf("\nAddress conflict between Device Address and Multicast group address\n\r");
  1018. }
  1019. print_application_config();
  1020. set_LED_data(LED_RED,&on);
  1021. }
  1022. else if(LORAWAN_NO_CHANNELS_FOUND == status)
  1023. {
  1024. joined = false;
  1025. set_LED_data(LED_AMBER,&on);
  1026. printf("\n No Free Channel found");
  1027. }
  1028. else if (LORAWAN_MIC_ERROR == status)
  1029. {
  1030. joined = false;
  1031. set_LED_data(LED_AMBER,&on);
  1032. printf("\n MIC Error");
  1033. }
  1034. else if (LORAWAN_TX_TIMEOUT == status)
  1035. {
  1036. joined = false;
  1037. set_LED_data(LED_AMBER,&on);
  1038. printf("\n Transmission Timeout");
  1039. }
  1040. else
  1041. {
  1042. joined = false;
  1043. set_LED_data(LED_AMBER,&on);
  1044. printf("\nJoining Denied\n\r");
  1045. }
  1046. printf("\n\r*******************************************************\n\r");
  1047. PDS_StoreAll();
  1048. appTaskState = JOIN_SEND_STATE;
  1049. appPostTask(DISPLAY_TASK_HANDLER);
  1050. }
  1051. void lTimerCb(void *data)
  1052. {
  1053. SwTimerStart(lTimerId,MS_TO_US(100),SW_TIMEOUT_RELATIVE,(void *)lTimerCb,NULL);
  1054. set_LED_data(LED_RED,&toggle);
  1055. }
  1056. /*********************************************************************//*
  1057. \brief Function to send data from end device to application server
  1058. ************************************************************************/
  1059. void sendData(void)
  1060. {
  1061. int status = -1;
  1062. uint8_t avail_payload;
  1063. /* Read temperature sensor value */
  1064. get_resource_data(TEMP_SENSOR,(uint8_t *)&cel_val);
  1065. fahren_val = convert_celsius_to_fahrenheit(cel_val);
  1066. printf("\nTemperature:");
  1067. snprintf(temp_sen_str,sizeof(temp_sen_str),"%.1fC/%.1fF\n", cel_val, fahren_val);
  1068. printf("%.1f\xf8 C/%.1f\xf8 F\n\r", cel_val, fahren_val);
  1069. data_len = strlen(temp_sen_str);
  1070. lorawanSendReq.buffer = &temp_sen_str;
  1071. lorawanSendReq.bufferLength = data_len - 1;
  1072. lorawanSendReq.confirmed = DEMO_APP_TRANSMISSION_TYPE;
  1073. lorawanSendReq.port = DEMO_APP_FPORT;
  1074. LORAWAN_GetAttr(NEXT_PAYLOAD_SIZE, NULL, &avail_payload);
  1075. if (avail_payload < lorawanSendReq.bufferLength)
  1076. {
  1077. // At DR0 for NA and AU regions Max payload = 3 bytes or less, due to FHDR(7) and FPORT(1) byte
  1078. printf("\r\nSending %d bytes of payload - DR limitation\r\n", avail_payload);
  1079. lorawanSendReq.bufferLength = avail_payload;
  1080. }
  1081. status = LORAWAN_Send(&lorawanSendReq);
  1082. if (LORAWAN_SUCCESS == status)
  1083. {
  1084. printf("\nTx Data Sent \r\n");
  1085. set_LED_data(LED_RED,&on);
  1086. SwTimerStart(lTimerId,MS_TO_US(100),SW_TIMEOUT_RELATIVE,(void *)lTimerCb,NULL);
  1087. }
  1088. else
  1089. {
  1090. print_stack_status(status);
  1091. appTaskState = JOIN_SEND_STATE;
  1092. appPostTask(DISPLAY_TASK_HANDLER);
  1093. }
  1094. }
  1095. #ifdef CONF_PMM_ENABLE
  1096. static void appWakeup(uint32_t sleptDuration)
  1097. {
  1098. HAL_Radio_resources_init();
  1099. sio2host_init();
  1100. appTaskState = JOIN_SEND_STATE;
  1101. appPostTask(DISPLAY_TASK_HANDLER);
  1102. printf("\r\nsleep_ok %ld ms\r\n", sleptDuration);
  1103. }
  1104. #endif
  1105. #ifdef CONF_PMM_ENABLE
  1106. static void app_resources_uninit(void)
  1107. {
  1108. /* Disable USART TX and RX Pins */
  1109. struct port_config pin_conf;
  1110. port_get_config_defaults(&pin_conf);
  1111. pin_conf.powersave = true;
  1112. #ifdef HOST_SERCOM_PAD0_PIN
  1113. port_pin_set_config(HOST_SERCOM_PAD0_PIN, &pin_conf);
  1114. #endif
  1115. #ifdef HOST_SERCOM_PAD1_PIN
  1116. port_pin_set_config(HOST_SERCOM_PAD1_PIN, &pin_conf);
  1117. #endif
  1118. /* Disable UART module */
  1119. sio2host_deinit();
  1120. /* Disable Transceiver SPI Module */
  1121. HAL_RadioDeInit();
  1122. }
  1123. #endif
  1124. /*********************************************************************//*
  1125. \brief Timer callback for demo application.
  1126. Used during the initial 5 sec wait period.
  1127. \param[in] cnt - not used
  1128. ************************************************************************/
  1129. void demoTimerCb(void * cnt)
  1130. {
  1131. uint8_t i = 10;
  1132. int8_t rxdata = 0;
  1133. printf("%d..",count);
  1134. count--;
  1135. startReceiving = false;
  1136. sio2host_rx(rxchar,10);
  1137. for(i = 0;i<=10;i++)
  1138. {
  1139. if(rxchar[i] != 13 && rxchar[i] != 10)
  1140. {
  1141. rxdata = rxchar[i];
  1142. break;
  1143. }
  1144. }
  1145. if(!count)
  1146. {
  1147. printf("\r\n");
  1148. }
  1149. /* No input so far. start timer till expiry */
  1150. if(count > 0 && (!rxdata))
  1151. {
  1152. SwTimerStart(demoTimerId,MS_TO_US(1000),SW_TIMEOUT_RELATIVE,(void *)demoTimerCb,NULL);
  1153. }
  1154. /* user did not press any input */
  1155. else if(count == 0 && (!rxdata))
  1156. {
  1157. appTaskState = RESTORE_BAND_STATE;
  1158. appPostTask(DISPLAY_TASK_HANDLER);
  1159. }
  1160. /* User pressed a key */
  1161. else if(rxdata)
  1162. {
  1163. printf("\r\n");
  1164. appTaskState = DEMO_APP_CONFIG;
  1165. appPostTask(DISPLAY_TASK_HANDLER);
  1166. }
  1167. }
  1168. /*********************************************************************//*
  1169. \brief App Post Task
  1170. \param[in] Id of the application to be posted
  1171. ************************************************************************/
  1172. void appPostTask(AppTaskIds_t id)
  1173. {
  1174. ATOMIC_SECTION_ENTER
  1175. appTaskFlags |= (1 << id);
  1176. ATOMIC_SECTION_EXIT
  1177. /* Also post a APP task to the system */
  1178. SYSTEM_PostTask(APP_TASK_ID);
  1179. }
  1180. /*********************************************************************//*
  1181. \brief Application Task Handler
  1182. ************************************************************************/
  1183. SYSTEM_TaskStatus_t APP_TaskHandler(void)
  1184. {
  1185. if (appTaskFlags)
  1186. {
  1187. for (uint16_t taskId = 0; taskId < APP_TASKS_COUNT; taskId++)
  1188. {
  1189. if ((1 << taskId) & (appTaskFlags))
  1190. {
  1191. ATOMIC_SECTION_ENTER
  1192. appTaskFlags &= ~(1 << taskId);
  1193. ATOMIC_SECTION_EXIT
  1194. appTaskHandlers[taskId]();
  1195. if (appTaskFlags)
  1196. {
  1197. SYSTEM_PostTask(APP_TASK_ID);
  1198. }
  1199. break;
  1200. }
  1201. }
  1202. }
  1203. return SYSTEM_TASK_SUCCESS;
  1204. }
  1205. /*********************************************************************//*
  1206. \brief Set join parameters function
  1207. \param[in] activation type - notifies the activation type (OTAA/ABP)
  1208. \return LORAWAN_SUCCESS, if successfully set the join parameters
  1209. LORAWAN_INVALID_PARAMETER, otherwise
  1210. ************************************************************************/
  1211. StackRetStatus_t set_join_parameters(ActivationType_t activation_type)
  1212. {
  1213. StackRetStatus_t status;
  1214. printf("\n********************Join Parameters********************\n\r");
  1215. if(ACTIVATION_BY_PERSONALIZATION == activation_type)
  1216. {
  1217. status = LORAWAN_SetAttr (DEV_ADDR, &demoDevAddr);
  1218. if (LORAWAN_SUCCESS == status)
  1219. {
  1220. status = LORAWAN_SetAttr (APPS_KEY, demoAppsKey);
  1221. }
  1222. if (LORAWAN_SUCCESS == status)
  1223. {
  1224. printf("\nAppSessionKey : ");
  1225. print_array((uint8_t *)&demoAppsKey, sizeof(demoAppsKey));
  1226. status = LORAWAN_SetAttr (NWKS_KEY, demoNwksKey);
  1227. }
  1228. if (LORAWAN_SUCCESS == status)
  1229. {
  1230. printf("\nNwkSessionKey : ");
  1231. print_array((uint8_t *)&demoNwksKey, sizeof(demoNwksKey));
  1232. }
  1233. }
  1234. else
  1235. {
  1236. status = LORAWAN_SetAttr (DEV_EUI, demoDevEui);
  1237. if (LORAWAN_SUCCESS == status)
  1238. {
  1239. printf("\nDevEUI : ");
  1240. print_array((uint8_t *)&demoDevEui, sizeof(demoDevEui));
  1241. status = LORAWAN_SetAttr (JOIN_EUI, demoJoinEui);
  1242. }
  1243. if (LORAWAN_SUCCESS == status)
  1244. {
  1245. printf("\nJoinEUI : ");
  1246. print_array((uint8_t *)&demoJoinEui, sizeof(demoJoinEui));
  1247. status = LORAWAN_SetAttr (APP_KEY, demoAppKey);
  1248. }
  1249. if (LORAWAN_SUCCESS == status)
  1250. {
  1251. printf("\nAppKey : ");
  1252. print_array((uint8_t *)&demoAppKey, sizeof(demoAppKey));
  1253. }
  1254. }
  1255. return status;
  1256. }
  1257. /*********************************************************************//*
  1258. \brief Function to Initialize the device type
  1259. \param[in] ed_class - notifies the device class (CLASS_A/CLASS_B/CLASS_C)
  1260. \return LORAWAN_SUCCESS, if successfully set the device class
  1261. LORAWAN_INVALID_PARAMETER, otherwise
  1262. ************************************************************************/
  1263. StackRetStatus_t set_device_type(EdClass_t ed_class)
  1264. {
  1265. StackRetStatus_t status = LORAWAN_SUCCESS;
  1266. status = LORAWAN_SetAttr(EDCLASS, &ed_class);
  1267. if((LORAWAN_SUCCESS == status) && ((CLASS_C | CLASS_B) & ed_class) && (true == DEMO_APP_MCAST_ENABLE))
  1268. {
  1269. set_multicast_params();
  1270. }
  1271. return status;
  1272. }
  1273. /*********************************************************************//*
  1274. \brief Function to Initialize the Multicast parameters
  1275. ************************************************************************/
  1276. void set_multicast_params (void)
  1277. {
  1278. StackRetStatus_t status;
  1279. LorawanMcastDevAddr_t dMcastDevAddr;
  1280. LorawanMcastAppSkey_t mcastAppSKey;
  1281. LorawanMcastNwkSkey_t mcastNwkSKey;
  1282. LorawanMcastDlFreqeuncy_t mcastDlFreq;
  1283. LorawanMcastDatarate_t mcastDatarate;
  1284. LorawanMcastStatus_t mcastStatus;
  1285. ReceiveWindow2Params_t receivewindow2param;
  1286. printf("\n***************Multicast Parameters********************\n\r");
  1287. dMcastDevAddr.groupId = demoMcastGroupId;
  1288. mcastAppSKey.groupId = demoMcastGroupId;
  1289. mcastNwkSKey.groupId = demoMcastGroupId;
  1290. mcastDlFreq.groupId = demoMcastGroupId;
  1291. mcastDatarate.groupId = demoMcastGroupId;
  1292. mcastStatus.groupId = demoMcastGroupId;
  1293. memcpy(&(mcastAppSKey.mcastAppSKey), &demoMcastAppsKey,LORAWAN_SESSIONKEY_LENGTH);
  1294. dMcastDevAddr.mcast_dev_addr = demoMcastDevAddr;
  1295. memcpy(&(mcastNwkSKey.mcastNwkSKey), &demoMcastNwksKey,LORAWAN_SESSIONKEY_LENGTH);
  1296. memcpy(&(mcastStatus.status),&demoMcastEnable,sizeof(demoMcastEnable));
  1297. LORAWAN_GetAttr(RX2_WINDOW_PARAMS ,NULL, &receivewindow2param);
  1298. mcastDatarate.datarate = receivewindow2param.dataRate;
  1299. mcastDlFreq.dlFrequency = receivewindow2param.frequency;
  1300. status = LORAWAN_SetAttr(MCAST_APPS_KEY, &mcastAppSKey);
  1301. if (status == LORAWAN_SUCCESS)
  1302. {
  1303. printf("\nMcastAppSessionKey : ");
  1304. print_array((uint8_t *)&(mcastAppSKey.mcastAppSKey), LORAWAN_SESSIONKEY_LENGTH);
  1305. status = LORAWAN_SetAttr(MCAST_NWKS_KEY, &mcastNwkSKey);
  1306. }
  1307. if(status == LORAWAN_SUCCESS)
  1308. {
  1309. printf("\nMcastNwkSessionKey : ");
  1310. print_array((uint8_t *)&(mcastNwkSKey.mcastNwkSKey), LORAWAN_SESSIONKEY_LENGTH);
  1311. status = LORAWAN_SetAttr(MCAST_GROUP_ADDR, &dMcastDevAddr);
  1312. }
  1313. if (status == LORAWAN_SUCCESS)
  1314. {
  1315. printf("\nMcastGroupAddr : 0x%lx\n\r", dMcastDevAddr.mcast_dev_addr);
  1316. status = LORAWAN_SetAttr(MCAST_ENABLE, &mcastStatus);
  1317. }
  1318. if (status == LORAWAN_SUCCESS)
  1319. {
  1320. status = LORAWAN_SetMulticastParam(MCAST_DATARATE , &mcastDatarate);
  1321. }
  1322. if (status == LORAWAN_SUCCESS)
  1323. {
  1324. status = LORAWAN_SetMulticastParam(MCAST_FREQUENCY , &mcastDlFreq);
  1325. }
  1326. else
  1327. {
  1328. printf("\nMcastGroupAddrStatus : Failed\n\r");
  1329. }
  1330. if (status == LORAWAN_SUCCESS)
  1331. {
  1332. printf("\nMulticastStatus : Enabled\n\r");
  1333. }
  1334. else
  1335. {
  1336. printf("\nMulticastStatus : Failed\n\r");
  1337. }
  1338. printf("\n********************************************************\n\r");
  1339. }
  1340. /***********************************************************************
  1341. \brief Function to Initialize set default parameters
  1342. \param[in] void
  1343. \return LORAWAN_SUCCESS, if successfully set all the parameters
  1344. LORAWAN_INVALID_PARAMETER, otherwise
  1345. ************************************************************************/
  1346. StackRetStatus_t mote_set_parameters(IsmBand_t ismBand, const uint16_t index)
  1347. {
  1348. StackRetStatus_t status;
  1349. bool joinBackoffEnable = false;
  1350. LORAWAN_Reset(ismBand);
  1351. #if (NA_BAND == 1 || AU_BAND == 1)
  1352. #if (RANDOM_NW_ACQ == 0)
  1353. if ((ismBand == ISM_NA915) || (ismBand == ISM_AU915))
  1354. {
  1355. #define MAX_NA_CHANNELS 72
  1356. #define MAX_SUBBAND_CHANNELS 8
  1357. ChannelParameters_t ch_params;
  1358. uint8_t allowed_min_125khz_ch,allowed_max_125khz_ch,allowed_500khz_channel;
  1359. allowed_min_125khz_ch = (subBand-1)*MAX_SUBBAND_CHANNELS;
  1360. allowed_max_125khz_ch = ((subBand-1)*MAX_SUBBAND_CHANNELS) + 7 ;
  1361. allowed_500khz_channel = subBand+63;
  1362. for (ch_params.channelId = 0; ch_params.channelId < MAX_NA_CHANNELS; ch_params.channelId++)
  1363. {
  1364. if((ch_params.channelId >= allowed_min_125khz_ch) && (ch_params.channelId <= allowed_max_125khz_ch))
  1365. {
  1366. ch_params.channelAttr.status = true;
  1367. }
  1368. else if(ch_params.channelId == allowed_500khz_channel)
  1369. {
  1370. ch_params.channelAttr.status = true;
  1371. }
  1372. else
  1373. {
  1374. ch_params.channelAttr.status = false;
  1375. }
  1376. LORAWAN_SetAttr(CH_PARAM_STATUS, &ch_params);
  1377. }
  1378. }
  1379. #endif
  1380. #endif
  1381. /*Disabled Join backoff in Demo application
  1382. Needs to be enabled in Production Environment Ref Section */
  1383. LORAWAN_SetAttr(JOIN_BACKOFF_ENABLE,&joinBackoffEnable);
  1384. /* Initialize the join parameters for Demo application */
  1385. status = set_join_parameters(demoJoinActivationType);
  1386. if (LORAWAN_SUCCESS != status)
  1387. {
  1388. printf("\nJoin parameters initialization failed\n\r");
  1389. return status;
  1390. }
  1391. /* Set the device type */
  1392. status = set_device_type(DEMO_APP_ENDDEVICE_CLASS);
  1393. if (LORAWAN_SUCCESS != status)
  1394. {
  1395. printf("\nUnsupported Device Type\n\r");
  1396. return status;
  1397. }
  1398. /* Send Join request for Demo application */
  1399. status = LORAWAN_Join(demoJoinActivationType);
  1400. if (LORAWAN_SUCCESS == status && index < sizeof(bandTable))
  1401. {
  1402. printf("\nJoin Request Sent for %s\n\r",bandStrings[index]);
  1403. }
  1404. else
  1405. {
  1406. print_stack_status(status);
  1407. appTaskState = JOIN_SEND_STATE;
  1408. appPostTask(DISPLAY_TASK_HANDLER);
  1409. }
  1410. return status;
  1411. }
  1412. /*********************************************************************//*
  1413. \brief Function to Print array of characters
  1414. \param[in] *array - Pointer of the array to be printed
  1415. \param[in] length - Length of the array
  1416. ************************************************************************/
  1417. void print_array (uint8_t *array, uint8_t length)
  1418. {
  1419. printf("0x");
  1420. for (uint8_t i =0; i < length; i++)
  1421. {
  1422. printf("%02x", *array);
  1423. array++;
  1424. }
  1425. printf("\n\r");
  1426. }
  1427. /*********************************************************************//*
  1428. \brief Function to Print application configuration
  1429. ************************************************************************/
  1430. void print_application_config (void)
  1431. {
  1432. EdClass_t edClass;
  1433. printf("\n***************Application Configuration***************\n\r");
  1434. LORAWAN_GetAttr(EDCLASS, NULL, &edClass);
  1435. printf("\nDevType : ");
  1436. if(edClass == CLASS_A)
  1437. {
  1438. printf("CLASS A\n\r");
  1439. }
  1440. else if(edClass == CLASS_C)
  1441. {
  1442. printf("CLASS C\n\r");
  1443. }
  1444. printf("\nActivationType : ");
  1445. if(demoJoinActivationType == OVER_THE_AIR_ACTIVATION)
  1446. {
  1447. printf("OTAA\n\r");
  1448. }
  1449. else if(demoJoinActivationType == ACTIVATION_BY_PERSONALIZATION)
  1450. {
  1451. printf("ABP\n\r");
  1452. }
  1453. printf("\nTransmission Type - ");
  1454. if(DEMO_APP_TRANSMISSION_TYPE == CONFIRMED)
  1455. {
  1456. printf("CONFIRMED\n\r");
  1457. }
  1458. else if(DEMO_APP_TRANSMISSION_TYPE == UNCONFIRMED)
  1459. {
  1460. printf("UNCONFIRMED\n\r");
  1461. }
  1462. printf("\nFPort - %d\n\r", DEMO_APP_FPORT);
  1463. printf("\n*******************************************************\n\r");
  1464. }
  1465. /*********************************************************************//*
  1466. \brief Function to Print stack return status
  1467. \param[in] status - Status from the stack
  1468. ************************************************************************/
  1469. void print_stack_status(StackRetStatus_t status)
  1470. {
  1471. switch(status)
  1472. {
  1473. case LORAWAN_SUCCESS:
  1474. printf("\nlorawan_success\n\r");
  1475. break;
  1476. case LORAWAN_BUSY:
  1477. printf("\nlorawan_state : stack_Busy\n\r");
  1478. break;
  1479. case LORAWAN_NWK_NOT_JOINED:
  1480. printf("\ndevice_not_joined_to_network\n\r");
  1481. break;
  1482. case LORAWAN_INVALID_PARAMETER:
  1483. printf("\ninvalid_parameter\n\r");
  1484. break;
  1485. case LORAWAN_KEYS_NOT_INITIALIZED:
  1486. printf("\nkeys_not_initialized\n\r");
  1487. break;
  1488. case LORAWAN_SILENT_IMMEDIATELY_ACTIVE:
  1489. printf("\nsilent_immediately_active\n\r");
  1490. break;
  1491. case LORAWAN_FCNTR_ERROR_REJOIN_NEEDED:
  1492. printf("\nframecounter_error_rejoin_needed\n\r");
  1493. break;
  1494. case LORAWAN_INVALID_BUFFER_LENGTH:
  1495. printf("\ninvalid_buffer_length\n\r");
  1496. break;
  1497. case LORAWAN_MAC_PAUSED:
  1498. printf("\nMAC_paused\n\r");
  1499. break;
  1500. case LORAWAN_NO_CHANNELS_FOUND:
  1501. printf("\nno_free_channels_found\n\r");
  1502. break;
  1503. case LORAWAN_INVALID_REQUEST:
  1504. printf("\nrequest_invalid\n\r");
  1505. break;
  1506. case LORAWAN_NWK_JOIN_IN_PROGRESS:
  1507. printf("\nprev_join_request_in_progress\n\r");
  1508. break;
  1509. default:
  1510. printf("\nrequest_failed %d\n\r",status);
  1511. break;
  1512. }
  1513. }
  1514. /*********************************************************************//*
  1515. \brief Function to convert Celsius value to Fahrenheit
  1516. \param[in] cel_val - Temperature value in Celsius
  1517. \param[out] fauren_val- Temperature value in Fahrenheit
  1518. ************************************************************************/
  1519. static float convert_celsius_to_fahrenheit(float celsius_val)
  1520. {
  1521. float fauren_val;
  1522. /* T(°F) = T(°C) × 9/5 + 32 */
  1523. fauren_val = (((celsius_val * 9)/5) + 32);
  1524. return fauren_val;
  1525. }
  1526. /* eof demo_app.c */