/**
* \file enddevice_demo.c
*
* \brief Serial Provisioning of LoRaWAN Demo Application
*
* Copyright (c) 2020 Europalab Devices ApS
*
* \asf_license_start
*
* \page License
*
* This file is part of Sendcomm.
*
* Sendcomm is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Sendcomm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Sendcomm. If not, see .
*
* \asf_license_stop
*
*/
/**
* \mainpage
* \section preface Preface
* Serial Provisioning of LoRaWAN Demo Application available from Atmel Studio examples,
* this is used to send the temperature sensor data through the LoRaWAN network to the network server.
*
• 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.
* • User if chooses NA / AU band can choose the sub-band of operation depending on the LoRaWAN Gateway being used.
* • This example uses the commands sent over UART/TeraTerm to join/send data/sleep.
*/
/****************************** INCLUDES **************************************/
#include "asf.h"
#include "lorawan.h"
#include "system_task_manager.h"
#include "enddevice_demo.h"
#include "conf_app.h"
#include "sio2host.h"
#include "resources.h"
#include "delay.h"
#include "sw_timer.h"
#include "LED.h"
#include "pmm.h"
#include "radio_driver_hal.h"
#include "conf_pmm.h"
#include "conf_sio2host.h"
#include "pds_interface.h"
#if (EDBG_EUI_READ == 1)
#include "edbg_eui.h"
#endif
#include "atomic.h"
#include
/******************************** MACROS ***************************************/
/************************** GLOBAL VARIABLES ***********************************/
/************************** GLOBAL VARIABLES ***********************************/
static bool joinTypeSelection = false;
static bool keyConfigSelection = false;
static bool devEuiSelectionDone = false;
static bool joinEuiSelectionDone = false;
static bool appKeySelectionDone = false;
static bool devAddrSelectionDone = false;
static bool appSkeySelectionDone = false;
static bool nwkSkeySelectionDone = false;
static bool verifyDemoConfigSelection = false;
ActivationType_t demoJoinActivationType;
static bool joined = false;
static float cel_val;
static float fahren_val;
static char temp_sen_str[25];
static uint8_t data_len = 0;
bool certAppEnabled = false;
static uint8_t on = LON;
static uint8_t off = LOFF;
static uint8_t toggle = LTOGGLE;
static volatile uint8_t appTaskFlags = 0x00u;
/* Default Regional band start delay time */
volatile static uint8_t count = 5;
static uint8_t rxchar[11];
static bool startReceiving = false;
extern uint8_t demoTimerId;
extern uint8_t lTimerId;
static AppTaskState_t appTaskState;
static const char* bandStrings[] =
{
"FactoryDefaultReset",
#if (EU_BAND == 1)
"EU868",
#endif
#if (NA_BAND == 1)
"NA915",
#endif
#if (AU_BAND == 1)
"AU915",
#endif
#if (AS_BAND == 1)
"AS923",
#endif
#if (JPN_BAND == 1)
"JPN923",
#endif
#if (KR_BAND == 1)
"KR920",
#endif
#if (IND_BAND == 1)
"IND865",
#endif
"Clear PDS",
"Reset Board"
};
uint8_t bandTable[] =
{
0xFF,
#if (EU_BAND == 1)
ISM_EU868,
#endif
#if (NA_BAND == 1)
ISM_NA915,
#endif
#if (AU_BAND == 1)
ISM_AU915,
#endif
#if (AS_BAND == 1)
ISM_THAI923,
#endif
#if (JPN_BAND == 1)
ISM_JPN923,
#endif
#if (KR_BAND == 1)
ISM_KR920,
#endif
#if (IND_BAND == 1)
ISM_IND865,
#endif
0xFF,
0xFF
};
static uint8_t tempBuff[4];
#if (RANDOM_NW_ACQ == 0)
/*Band Selection for NA and AU region */
static uint8_t subBand = 2;
#endif
/*ABP Join Parameters */
static uint32_t demoDevAddr;
static uint8_t demoNwksKey[16];
static uint8_t demoAppsKey[16];
/* OTAA join parameters */
static uint8_t demoDevEui[8];
static uint8_t demoJoinEui[8];
static uint8_t demoAppKey[16];
static LorawanSendReq_t lorawanSendReq;
static char serialBuffer;
/* Muticast Parameters */
static bool demoMcastEnable = DEMO_APP_MCAST_ENABLE;
static uint32_t demoMcastDevAddr = DEMO_APP_MCAST_GROUP_ADDRESS;
static uint8_t demoMcastNwksKey[16] = DEMO_APP_MCAST_NWK_SESSION_KEY;
static uint8_t demoMcastAppsKey[16] = DEMO_APP_MCAST_APP_SESSION_KEY;
static uint8_t demoMcastGroupId = DEMO_APP_MCAST_GROUPID;
/************************** EXTERN VARIABLES ***********************************/
extern bool button_pressed;
extern bool factory_reset;
extern bool bandSelected;
extern uint32_t longPress;
static void demoAddr_keyconfig_handler(void);
static void sendData(void);
static void appPostTask(AppTaskIds_t id);
static void displaySelectedAppConfig(void);
static SYSTEM_TaskStatus_t (*appTaskHandlers[])(void);
static void demoTimerCb(void * cnt);
static void lTimerCb(void * data);
static SYSTEM_TaskStatus_t displayTask(void);
static SYSTEM_TaskStatus_t processTask(void);
static void processRunDemoCertApp(void);
static void processRunRestoreBand(void);
static void processJoinAndSend(void);
static void processAppConfig(void);
static void processRunDemoApp(void);
static void displayRunDemoCertApp(void);
static void displayRunRestoreBand(void);
static void displayAppConfigMenu(void);
static void displayJoinAndSend(void);
static void displayRunDemoApp(void);
#ifdef CONF_PMM_ENABLE
static void appWakeup(uint32_t sleptDuration);
static void app_resources_uninit(void);
#endif
/************************** FUNCTION PROTOTYPES ********************************/
SYSTEM_TaskStatus_t APP_TaskHandler(void);
static float convert_celsius_to_fahrenheit(float cel_val);
/*********************************************************************//*
\brief Function that processes the Rx data
\param[in] data - Rx data payload
\param[in] dataLen - The number of Rx bytes
************************************************************************/
static void demo_handle_evt_rx_data(void *appHandle, appCbParams_t *appdata);
/***************************** FUNCTIONS ***************************************/
static SYSTEM_TaskStatus_t (*appTaskHandlers[APP_TASKS_COUNT])(void) = {
/* In the order of descending priority */
displayTask,
processTask
};
/*********************************************************************//**
\brief Calls appropriate functions based on state variables
*************************************************************************/
static SYSTEM_TaskStatus_t displayTask(void)
{
switch(appTaskState)
{
case RESTORE_BAND_STATE:
displayRunRestoreBand();
break;
case DEMO_APP_CONFIG:
displayAppConfigMenu();
break;
case DEMO_CERT_APP_STATE:
displayRunDemoCertApp();
break;
case DEMO_APP_STATE:
displayRunDemoApp();
break;
case JOIN_SEND_STATE:
displayJoinAndSend();
break;
default:
printf("Error STATE Entered\r\n");
break;
}
return SYSTEM_TASK_SUCCESS;
}
/*********************************************************************//**
\brief Pulls the data from UART when activated
*************************************************************************/
void serial_data_handler(void)
{
int rxChar;
char serialData;
/* verify if there was any character received*/
if (startReceiving == true)
{
if((-1) != (rxChar = sio2host_getchar_nowait()))
{
serialData = (char)rxChar;
if((serialData != '\r') && (serialData != '\n') && (serialData != '\b'))
{
startReceiving = false;
serialBuffer = rxChar;
appPostTask(PROCESS_TASK_HANDLER);
printf("\r\n");
}
}
}
}
uint8_t asciiToDecConverter(uint8_t input)
{
uint8_t decVal = -1;
if (input >= 48 && input <= 57) decVal = input - 48; // decimal values between 1 and 9
else if (input >= 65 && input <= 70) decVal = input - 55; // hex values between A and F
else if (input >= 97 && input <= 102) decVal = input - 87; // hex values between a and f
return decVal;
}
void serial_read_appConfig(uint8_t *buffer, uint8_t noOfBytes)
{
uint8_t i = 0;
uint8_t temp = 0, rxDec;
while (i != noOfBytes*2)
{
rxDec = asciiToDecConverter(sio2host_getchar());
if (i%2 == 0) temp = rxDec << 4;
else if (i%2 != 0) buffer[i/2] = temp + rxDec;
if (rxDec != 255) i++; // increment count only when receiving a valid hex value from 0-F
}
}
static void displaySelectedAppConfig(void)
{
uint8_t i = 0;
if (demoJoinActivationType == OVER_THE_AIR_ACTIVATION)
{
printf("Activation Type: OVER THE AIR ACTIVATION (OTAA)\r\n");
printf("Device EUI: 0x");
for (i=0;i<8;i++) printf("%x",demoDevEui[i]);
printf("\r\n");
printf("Join EUI: 0x");
for (i=0;i<8;i++) printf("%x",demoJoinEui[i]);
printf("\r\n");
printf("Application Key: 0x");
for (i=0;i<16;i++) printf("%x",demoAppKey[i]);
printf("\r\n");
}
else if (demoJoinActivationType == ACTIVATION_BY_PERSONALIZATION)
{
printf("Activation Type: ACTIVATION BY PERSONALIZATION (ABP)\r\n");
printf("Device Address: 0x%lx\r\n",demoDevAddr);
printf("Application Session Key: 0x");
for (i=0;i<16;i++) printf("%x",demoAppsKey[i]);
printf("\r\n");
printf("Network Session Key: 0x");
for (i=0;i<16;i++) printf("%x",demoNwksKey[i]);
printf("\r\n");
}
}
/*********************************************************************//**
\brief Handle the Key / addresses based on Join Mechanism Chosen
*************************************************************************/
static void demoAddr_keyconfig_handler(void)
{
if (demoJoinActivationType == OVER_THE_AIR_ACTIVATION)
{
if (devEuiSelectionDone == false)
{
serial_read_appConfig(demoDevEui, 8);
devEuiSelectionDone = true;
}
else if (joinEuiSelectionDone == false)
{
serial_read_appConfig(demoJoinEui, 8);
joinEuiSelectionDone = true;
}
else if (appKeySelectionDone == false)
{
serial_read_appConfig(demoAppKey, 16);
appKeySelectionDone = true;
}
}
else if (demoJoinActivationType == ACTIVATION_BY_PERSONALIZATION)
{
if (devAddrSelectionDone == false)
{
serial_read_appConfig(tempBuff, 4);
demoDevAddr = (uint32_t)tempBuff[0] << 24 | (uint32_t)tempBuff[1] << 16 | (uint32_t)tempBuff[2] << 8 | (uint32_t)tempBuff[3];
devAddrSelectionDone = true;
}
else if (appSkeySelectionDone == false)
{
serial_read_appConfig(demoAppsKey, 16);
appSkeySelectionDone = true;
}
else if (nwkSkeySelectionDone == false)
{
serial_read_appConfig(demoNwksKey, 16);
nwkSkeySelectionDone = true;
}
}
}
/*********************************************************************//**
\brief Calls appropriate functions based on state variables
*************************************************************************/
static SYSTEM_TaskStatus_t processTask(void)
{
switch(appTaskState)
{
case RESTORE_BAND_STATE:
processRunRestoreBand();
break;
case DEMO_APP_CONFIG:
processAppConfig();
break;
case DEMO_CERT_APP_STATE:
processRunDemoCertApp();
break;
case DEMO_APP_STATE:
processRunDemoApp();
break;
case JOIN_SEND_STATE:
processJoinAndSend();
break;
default:
printf("Error STATE Entered\r\n");
break;
}
return SYSTEM_TASK_SUCCESS;
}
/*********************************************************************//**
\brief Activates demo application or certification application
*************************************************************************/
static void processRunDemoCertApp(void)
{
if(serialBuffer == '1')
{
appTaskState = DEMO_APP_STATE;
appPostTask(DISPLAY_TASK_HANDLER);
}
else
{
printf("Please enter a valid choice\r\n");
appTaskState = DEMO_CERT_APP_STATE;
appPostTask(DISPLAY_TASK_HANDLER);
}
}
/*********************************************************************//**
\brief Restores the previous band and runs
*************************************************************************/
static void processRunRestoreBand(void)
{
StackRetStatus_t status = LORAWAN_SUCCESS;
uint8_t prevBand = 0xff;
uint8_t choice = 0xff;
bool joinBackoffEnable = false;
PDS_RestoreAll();
LORAWAN_GetAttr(ISMBAND,NULL,&prevBand);
for (uint32_t i = 0; i < sizeof(bandTable)-1; i++)
{
if(bandTable[i] == prevBand)
{
choice = i;
break;
}
}
if(choice >0 && choice < sizeof(bandTable)-1)
{
status = LORAWAN_Reset(bandTable[choice]);
}
/*Disabled Join backoff in Demo application
Needs to be enabled in Production Environment Ref Section */
LORAWAN_SetAttr(JOIN_BACKOFF_ENABLE,&joinBackoffEnable);
if(status == LORAWAN_SUCCESS && choice < sizeof(bandTable)-1)
{
uint32_t joinStatus = 0;
PDS_RestoreAll();
LORAWAN_GetAttr(LORAWAN_STATUS,NULL, &joinStatus);
printf("\r\nPDS_RestorationStatus: Success\r\n" );
if(joinStatus & LORAWAN_NW_JOINED)
{
joined = true;
printf("joinStatus: Joined\r\n");
}
else
{
joined = false;
printf("JoinStatus : Denied\r\n");
set_LED_data(LED_AMBER,&on);
SYSTEM_PostTask(APP_TASK_ID);
}
printf("Band: %s\r\n",bandStrings[choice]);
print_application_config();
appTaskState = JOIN_SEND_STATE;
appPostTask(DISPLAY_TASK_HANDLER);
}
else
{
printf("Restoration failed\r\n");
appTaskState = DEMO_APP_STATE;
appPostTask(DISPLAY_TASK_HANDLER);
}
}
/*********************************************************************//**
\brief Sends Join request or Data to the network
*************************************************************************/
static void processJoinAndSend(void)
{
StackRetStatus_t status = LORAWAN_SUCCESS;
if(serialBuffer == '1')
{
status = LORAWAN_Join(demoJoinActivationType);
if (LORAWAN_SUCCESS == (StackRetStatus_t)status)
{
set_LED_data(LED_RED,&on);
printf("\nJoin Request Sent\n\r");
}
else
{
set_LED_data(LED_AMBER,&on);
print_stack_status(status);
appTaskState = JOIN_SEND_STATE;
appPostTask(DISPLAY_TASK_HANDLER);
}
}
else if(serialBuffer == '2' && joined == true)
{
sendData();
}
else if(serialBuffer == '2' && !joined)
{
set_LED_data(LED_AMBER,&on);
printf("Device not joined to the network\r\n");
appTaskState = JOIN_SEND_STATE;
appPostTask(DISPLAY_TASK_HANDLER);
}
#ifdef CONF_PMM_ENABLE
else if(serialBuffer == '3')
{
static bool deviceResetsForWakeup = false;
PMM_SleepReq_t sleepReq;
/* Put the application to sleep */
sleepReq.sleepTimeMs = DEMO_CONF_DEFAULT_APP_SLEEP_TIME_MS;
sleepReq.pmmWakeupCallback = appWakeup;
sleepReq.sleep_mode = CONF_PMM_SLEEPMODE_WHEN_IDLE;
if (CONF_PMM_SLEEPMODE_WHEN_IDLE == SLEEP_MODE_STANDBY)
{
deviceResetsForWakeup = false;
}
if (true == LORAWAN_ReadyToSleep(deviceResetsForWakeup))
{
app_resources_uninit();
if (PMM_SLEEP_REQ_DENIED == PMM_Sleep(&sleepReq))
{
HAL_Radio_resources_init();
sio2host_init();
appTaskState = JOIN_SEND_STATE;
appPostTask(DISPLAY_TASK_HANDLER);
printf("\r\nsleep_not_ok\r\n");
}
}
else
{
printf("\r\nsleep_not_ok\r\n");
appTaskState = JOIN_SEND_STATE;
appPostTask(DISPLAY_TASK_HANDLER);
}
}
else if(serialBuffer == '4')
#else
else if(serialBuffer == '3')
#endif
{
appTaskState = DEMO_APP_STATE;
appPostTask(DISPLAY_TASK_HANDLER);
}
else
{
set_LED_data(LED_AMBER,&on);
printf("Invalid choice entered\r\n");
appTaskState = JOIN_SEND_STATE;
appPostTask(DISPLAY_TASK_HANDLER);
}
}
/*********************************************************************//**
\brief Runs the Demo application
*************************************************************************/
static void processRunDemoApp(void)
{
uint8_t num = serialBuffer - '0';
if(num == sizeof(bandTable)-1)
{
NVIC_SystemReset();
}
else if(num == sizeof(bandTable)-2)
{
PDS_DeleteAll();
appTaskState = DEMO_APP_STATE;
appPostTask(DISPLAY_TASK_HANDLER);
}
else if(num >0 && num < sizeof(bandTable) -2)
{
LORAWAN_Reset(bandTable[num]);
#if (RANDOM_NW_ACQ == 0)
if (bandTable[num] == ISM_NA915 || bandTable[num] == ISM_AU915)
{
printf("\r\nEnter SUBBAND(1-8): ");
subBand = sio2host_getchar() - '0';
}
#endif
mote_set_parameters(bandTable[num],num);
set_LED_data(LED_RED,&on);
}
else
{
printf("Not a valid regional band choice\r\n");
appTaskState = DEMO_APP_STATE;
appPostTask(DISPLAY_TASK_HANDLER);
}
}
/*********************************************************************//**
\brief configures the configuration for Demo application
*************************************************************************/
static void processAppConfig(void)
{
uint8_t choice = serialBuffer - '0';
if(joinTypeSelection == false && choice >= 1 && choice <= 2)
{
if (choice == 1) demoJoinActivationType = OVER_THE_AIR_ACTIVATION;
else demoJoinActivationType = ACTIVATION_BY_PERSONALIZATION;
joinTypeSelection = true;
appPostTask(DISPLAY_TASK_HANDLER);
}
else if (joinTypeSelection == false && choice < 0 && choice > 2)
{
printf("Not a valid join type\r\n");
appPostTask(DISPLAY_TASK_HANDLER);
}
else if (joinTypeSelection == true && keyConfigSelection == false)
{
demoAddr_keyconfig_handler();
if ((devEuiSelectionDone && joinEuiSelectionDone && appKeySelectionDone) ||
(devAddrSelectionDone && appSkeySelectionDone && nwkSkeySelectionDone)) keyConfigSelection = true;
appPostTask(DISPLAY_TASK_HANDLER);
}
else if (joinTypeSelection == true && keyConfigSelection == true && verifyDemoConfigSelection == false)
{
if (choice == 1)
{
verifyDemoConfigSelection = true;
}
else if (choice == 2)
{
joinTypeSelection = false;
keyConfigSelection = false;
devEuiSelectionDone = false;
joinEuiSelectionDone = false;
appKeySelectionDone = false;
devAddrSelectionDone = false;
appSkeySelectionDone = false;
nwkSkeySelectionDone = false;
}
appPostTask(DISPLAY_TASK_HANDLER);
}
}
/*********************************************************************//**
\brief Displays and activates LED's to choose between Demo
and Certification application
*************************************************************************/
static void displayRunDemoCertApp(void)
{
//sio2host_rx(rxchar,10);
set_LED_data(LED_AMBER,&off);
set_LED_data(LED_RED,&off);
printf("\r\n--Choose Application Type--\r\n");
printf("1. Demo application\r\n");
printf("\r\n Select Application : ");
startReceiving = true;
}
/*********************************************************************//**
\brief Activates LED's to indicate restoring of band
*************************************************************************/
static void displayRunRestoreBand(void)
{
//sio2host_rx(rxchar,10);
set_LED_data(LED_AMBER,&off);
set_LED_data(LED_RED,&off);
appPostTask(PROCESS_TASK_HANDLER);
}
/*********************************************************************//**
\brief Display App Configuration Options Available
*************************************************************************/
static void displayAppConfigMenu(void)
{
if (joinTypeSelection == false)
{
printf("\r\n---Join Type Selection---\r\n");
printf("1. Over The Air Activation(OTAA)\r\n");
printf("2. Activation By Personalization(ABP)\r\n");
printf("\r\nEnter your choice: ");
startReceiving = true;
}
else if (joinTypeSelection == true && keyConfigSelection == false)
{
if (demoJoinActivationType == OVER_THE_AIR_ACTIVATION)
{
if (devEuiSelectionDone == false) printf("\r\nEnter Device EUI(hex 0-F): ");
else if (joinEuiSelectionDone == false) printf("\r\nEnter Join EUI(hex 0-F): ");
else if (appKeySelectionDone == false) printf("\r\nEnter Application Key(hex 0-F): ");
}
else if (demoJoinActivationType == ACTIVATION_BY_PERSONALIZATION)
{
if (devAddrSelectionDone == false) printf("\r\nEnter Device Address(hex 0-F): ");
else if (appSkeySelectionDone == false) printf("\r\nEnter Application Session Key(hex 0-F): ");
else if (nwkSkeySelectionDone == false) printf("\r\nEnter Network Session Key(hex 0-F): ");
}
appPostTask(PROCESS_TASK_HANDLER);
startReceiving = false;
}
else if (joinTypeSelection == true && keyConfigSelection == true && verifyDemoConfigSelection == false)
{
printf("\r\n\r\n---Configuration Selected ---\r\n");
displaySelectedAppConfig();
printf("\r\n1. Confirm App Configuration Selection\r\n");
printf("2. Modify Configuration \r\n");
printf("Enter your choice: ");
startReceiving = true;
}
else if (joinTypeSelection == true && keyConfigSelection == true && verifyDemoConfigSelection == true)
{
appTaskState = DEMO_CERT_APP_STATE;
appPostTask(DISPLAY_TASK_HANDLER);
}
}
/*********************************************************************//**
\brief Displays and activates LED's for joining to a network
and sending data to a network
*************************************************************************/
static void displayJoinAndSend(void)
{
printf("\r\n1. Send Join Request\r\n");
printf("2. Send Data\r\n");
#ifdef CONF_PMM_ENABLE
printf("3. Sleep\r\n");
printf("4. Select Band\r\n");
#else
printf("3. Select Band\r\n");
#endif /* CONF_PMM_ENABLE */
printf("\r\nEnter your choice: ");
set_LED_data(LED_AMBER,&off);
set_LED_data(LED_RED,&off);
startReceiving = true;
}
/*********************************************************************//**
\brief Displays and activates LED's for selecting Demo application
*************************************************************************/
static void displayRunDemoApp(void)
{
uint8_t i = 0;
set_LED_data(LED_AMBER,&off);
set_LED_data(LED_RED,&off);
printf("\r\nPlease select one of the band given below\r\n");
for(i = 1;i < sizeof(bandTable); i++)
{
printf("%d. %s\r\n",i,bandStrings[i]);
}
printf("Select Regional Band : ");
startReceiving = true;
}
/*********************************************************************//**
\brief Initialization the Demo application
*************************************************************************/
void mote_demo_init(void)
{
bool status = false;
/* Initialize the resources */
resource_init();
startReceiving = false;
/* Initialize the LORAWAN Stack */
LORAWAN_Init(demo_appdata_callback, demo_joindata_callback);
printf("\n\n\r*******************************************************\n\r");
printf("\n\rDemocratic SendComm 2020");
printf("\n\rLibrary: %s\r\n",STACK_VER);
printf("\r\nInit - Successful\r\n");
status = PDS_IsRestorable();
if(status)
{
static uint8_t prevBand = 0xFF;
uint8_t prevChoice = 0xFF;
PDS_RestoreAll();
LORAWAN_GetAttr(ISMBAND,NULL,&prevBand);
for (uint32_t i = 0; i < sizeof(bandTable) -1; i++)
{
if(bandTable[i] == prevBand)
{
prevChoice = i;
break;
}
}
memset(rxchar,0,sizeof(rxchar));
sio2host_rx(rxchar,10);
printf ("Last configured Regional band %s\r\n",bandStrings[prevChoice]);
printf("Press any key to change band\r\n Continuing in %s in ", bandStrings[prevChoice]);
SwTimerStart(demoTimerId,MS_TO_US(1000),SW_TIMEOUT_RELATIVE,(void *)demoTimerCb,NULL);
}
else
{
appTaskState = DEMO_APP_CONFIG;
appPostTask(DISPLAY_TASK_HANDLER);
}
}
/*********************************************************************//*
\brief Function that processes the Rx data
\param[in] data - Rx data payload
\param[in] dataLen - The number of Rx bytes
************************************************************************/
static void demo_handle_evt_rx_data(void *appHandle, appCbParams_t *appdata)
{
uint8_t *pData = appdata->param.rxData.pData;
uint8_t dataLength = appdata->param.rxData.dataLength;
uint32_t devAddress = appdata->param.rxData.devAddr;
//Successful transmission
if((dataLength > 0U) && (NULL != pData))
{
printf("*** Received DL Data ***\n\r");
printf("\nFrame Received at port %d\n\r",pData[0]);
printf("\nFrame Length - %d\n\r",dataLength);
printf("\nAddress - 0x%lx\n\r", devAddress);
printf ("\nPayload: ");
for (uint8_t i =0; ievt)
{
status = appdata->param.rxData.status;
switch(status)
{
case LORAWAN_SUCCESS:
{
demo_handle_evt_rx_data(appHandle, appdata);
}
break;
case LORAWAN_RADIO_NO_DATA:
{
printf("\n\rRADIO_NO_DATA \n\r");
}
break;
case LORAWAN_RADIO_DATA_SIZE:
printf("\n\rRADIO_DATA_SIZE \n\r");
break;
case LORAWAN_RADIO_INVALID_REQ:
printf("\n\rRADIO_INVALID_REQ \n\r");
break;
case LORAWAN_RADIO_BUSY:
printf("\n\rRADIO_BUSY \n\r");
break;
case LORAWAN_RADIO_OUT_OF_RANGE:
printf("\n\rRADIO_OUT_OF_RANGE \n\r");
break;
case LORAWAN_RADIO_UNSUPPORTED_ATTR:
printf("\n\rRADIO_UNSUPPORTED_ATTR \n\r");
break;
case LORAWAN_RADIO_CHANNEL_BUSY:
printf("\n\rRADIO_CHANNEL_BUSY \n\r");
break;
case LORAWAN_NWK_NOT_JOINED:
printf("\n\rNWK_NOT_JOINED \n\r");
break;
case LORAWAN_INVALID_PARAMETER:
printf("\n\rINVALID_PARAMETER \n\r");
break;
case LORAWAN_KEYS_NOT_INITIALIZED:
printf("\n\rKEYS_NOT_INITIALIZED \n\r");
break;
case LORAWAN_SILENT_IMMEDIATELY_ACTIVE:
printf("\n\rSILENT_IMMEDIATELY_ACTIVE\n\r");
break;
case LORAWAN_FCNTR_ERROR_REJOIN_NEEDED:
printf("\n\rFCNTR_ERROR_REJOIN_NEEDED \n\r");
break;
case LORAWAN_INVALID_BUFFER_LENGTH:
printf("\n\rINVALID_BUFFER_LENGTH \n\r");
break;
case LORAWAN_MAC_PAUSED :
printf("\n\rMAC_PAUSED \n\r");
break;
case LORAWAN_NO_CHANNELS_FOUND:
printf("\n\rNO_CHANNELS_FOUND \n\r");
break;
case LORAWAN_BUSY:
printf("\n\rBUSY\n\r");
break;
case LORAWAN_NO_ACK:
printf("\n\rNO_ACK \n\r");
break;
case LORAWAN_NWK_JOIN_IN_PROGRESS:
printf("\n\rALREADY JOINING IS IN PROGRESS \n\r");
break;
case LORAWAN_RESOURCE_UNAVAILABLE:
printf("\n\rRESOURCE_UNAVAILABLE \n\r");
break;
case LORAWAN_INVALID_REQUEST:
printf("\n\rINVALID_REQUEST \n\r");
break;
case LORAWAN_FCNTR_ERROR:
printf("\n\rFCNTR_ERROR \n\r");
break;
case LORAWAN_MIC_ERROR:
printf("\n\rMIC_ERROR \n\r");
break;
case LORAWAN_INVALID_MTYPE:
printf("\n\rINVALID_MTYPE \n\r");
break;
case LORAWAN_MCAST_HDR_INVALID:
printf("\n\rMCAST_HDR_INVALID \n\r");
break;
case LORAWAN_INVALID_PACKET:
printf("\n\rINVALID_PACKET \n\r");
break;
default:
printf("UNKNOWN ERROR\n\r");
break;
}
}
else if(LORAWAN_EVT_TRANSACTION_COMPLETE == appdata->evt)
{
switch(status = appdata->param.transCmpl.status)
{
case LORAWAN_SUCCESS:
{
printf("Transmission Success\r\n");
}
break;
case LORAWAN_RADIO_SUCCESS:
{
printf("Transmission Success\r\n");
}
break;
case LORAWAN_RADIO_NO_DATA:
{
printf("\n\rRADIO_NO_DATA \n\r");
}
break;
case LORAWAN_RADIO_DATA_SIZE:
printf("\n\rRADIO_DATA_SIZE \n\r");
break;
case LORAWAN_RADIO_INVALID_REQ:
printf("\n\rRADIO_INVALID_REQ \n\r");
break;
case LORAWAN_RADIO_BUSY:
printf("\n\rRADIO_BUSY \n\r");
break;
case LORAWAN_TX_TIMEOUT:
printf("\nTx Timeout\n\r");
break;
case LORAWAN_RADIO_OUT_OF_RANGE:
printf("\n\rRADIO_OUT_OF_RANGE \n\r");
break;
case LORAWAN_RADIO_UNSUPPORTED_ATTR:
printf("\n\rRADIO_UNSUPPORTED_ATTR \n\r");
break;
case LORAWAN_RADIO_CHANNEL_BUSY:
printf("\n\rRADIO_CHANNEL_BUSY \n\r");
break;
case LORAWAN_NWK_NOT_JOINED:
printf("\n\rNWK_NOT_JOINED \n\r");
break;
case LORAWAN_INVALID_PARAMETER:
printf("\n\rINVALID_PARAMETER \n\r");
break;
case LORAWAN_KEYS_NOT_INITIALIZED:
printf("\n\rKEYS_NOT_INITIALIZED \n\r");
break;
case LORAWAN_SILENT_IMMEDIATELY_ACTIVE:
printf("\n\rSILENT_IMMEDIATELY_ACTIVE\n\r");
break;
case LORAWAN_FCNTR_ERROR_REJOIN_NEEDED:
printf("\n\rFCNTR_ERROR_REJOIN_NEEDED \n\r");
break;
case LORAWAN_INVALID_BUFFER_LENGTH:
printf("\n\rINVALID_BUFFER_LENGTH \n\r");
break;
case LORAWAN_MAC_PAUSED :
printf("\n\rMAC_PAUSED \n\r");
break;
case LORAWAN_NO_CHANNELS_FOUND:
printf("\n\rNO_CHANNELS_FOUND \n\r");
break;
case LORAWAN_BUSY:
printf("\n\rBUSY\n\r");
break;
case LORAWAN_NO_ACK:
printf("\n\rNO_ACK \n\r");
break;
case LORAWAN_NWK_JOIN_IN_PROGRESS:
printf("\n\rALREADY JOINING IS IN PROGRESS \n\r");
break;
case LORAWAN_RESOURCE_UNAVAILABLE:
printf("\n\rRESOURCE_UNAVAILABLE \n\r");
break;
case LORAWAN_INVALID_REQUEST:
printf("\n\rINVALID_REQUEST \n\r");
break;
case LORAWAN_FCNTR_ERROR:
printf("\n\rFCNTR_ERROR \n\r");
break;
case LORAWAN_MIC_ERROR:
printf("\n\rMIC_ERROR \n\r");
break;
case LORAWAN_INVALID_MTYPE:
printf("\n\rINVALID_MTYPE \n\r");
break;
case LORAWAN_MCAST_HDR_INVALID:
printf("\n\rMCAST_HDR_INVALID \n\r");
break;
case LORAWAN_INVALID_PACKET:
printf("\n\rINVALID_PACKET \n\r");
break;
default:
printf("\n\rUNKNOWN ERROR\n\r");
break;
}
printf("\n\r*************************************************\n\r");
}
SwTimerStop(lTimerId);
set_LED_data(LED_RED,&off);
if(status != LORAWAN_SUCCESS)
{
set_LED_data(LED_AMBER,&on);
}
appTaskState = JOIN_SEND_STATE;
appPostTask(DISPLAY_TASK_HANDLER);
}
/*********************************************************************//*
\brief Callback function for the ending of Activation procedure
************************************************************************/
void demo_joindata_callback(StackRetStatus_t status)
{
/* This is called every time the join process is finished */
set_LED_data(LED_RED,&off);
if(LORAWAN_SUCCESS == status)
{
uint32_t devAddress;
bool mcastEnabled;
joined = true;
printf("\nJoining Successful\n\r");
LORAWAN_GetAttr(DEV_ADDR, NULL, &devAddress);
LORAWAN_GetAttr(MCAST_ENABLE, NULL, &mcastEnabled);
if (devAddress != DEMO_APP_MCAST_GROUP_ADDRESS)
{
printf("\nDevAddr: 0x%lx\n\r", devAddress);
}
else if ((devAddress == DEMO_APP_MCAST_GROUP_ADDRESS) && (true == mcastEnabled))
{
printf("\nAddress conflict between Device Address and Multicast group address\n\r");
}
print_application_config();
set_LED_data(LED_RED,&on);
}
else if(LORAWAN_NO_CHANNELS_FOUND == status)
{
joined = false;
set_LED_data(LED_AMBER,&on);
printf("\n No Free Channel found");
}
else if (LORAWAN_MIC_ERROR == status)
{
joined = false;
set_LED_data(LED_AMBER,&on);
printf("\n MIC Error");
}
else if (LORAWAN_TX_TIMEOUT == status)
{
joined = false;
set_LED_data(LED_AMBER,&on);
printf("\n Transmission Timeout");
}
else
{
joined = false;
set_LED_data(LED_AMBER,&on);
printf("\nJoining Denied\n\r");
}
printf("\n\r*******************************************************\n\r");
PDS_StoreAll();
appTaskState = JOIN_SEND_STATE;
appPostTask(DISPLAY_TASK_HANDLER);
}
void lTimerCb(void *data)
{
SwTimerStart(lTimerId,MS_TO_US(100),SW_TIMEOUT_RELATIVE,(void *)lTimerCb,NULL);
set_LED_data(LED_RED,&toggle);
}
/*********************************************************************//*
\brief Function to send data from end device to application server
************************************************************************/
void sendData(void)
{
int status = -1;
uint8_t avail_payload;
/* Read temperature sensor value */
get_resource_data(TEMP_SENSOR,(uint8_t *)&cel_val);
fahren_val = convert_celsius_to_fahrenheit(cel_val);
printf("\nTemperature:");
snprintf(temp_sen_str,sizeof(temp_sen_str),"%.1fC/%.1fF\n", cel_val, fahren_val);
printf("%.1f\xf8 C/%.1f\xf8 F\n\r", cel_val, fahren_val);
data_len = strlen(temp_sen_str);
lorawanSendReq.buffer = &temp_sen_str;
lorawanSendReq.bufferLength = data_len - 1;
lorawanSendReq.confirmed = DEMO_APP_TRANSMISSION_TYPE;
lorawanSendReq.port = DEMO_APP_FPORT;
LORAWAN_GetAttr(NEXT_PAYLOAD_SIZE, NULL, &avail_payload);
if (avail_payload < lorawanSendReq.bufferLength)
{
// At DR0 for NA and AU regions Max payload = 3 bytes or less, due to FHDR(7) and FPORT(1) byte
printf("\r\nSending %d bytes of payload - DR limitation\r\n", avail_payload);
lorawanSendReq.bufferLength = avail_payload;
}
status = LORAWAN_Send(&lorawanSendReq);
if (LORAWAN_SUCCESS == status)
{
printf("\nTx Data Sent \r\n");
set_LED_data(LED_RED,&on);
SwTimerStart(lTimerId,MS_TO_US(100),SW_TIMEOUT_RELATIVE,(void *)lTimerCb,NULL);
}
else
{
print_stack_status(status);
appTaskState = JOIN_SEND_STATE;
appPostTask(DISPLAY_TASK_HANDLER);
}
}
#ifdef CONF_PMM_ENABLE
static void appWakeup(uint32_t sleptDuration)
{
HAL_Radio_resources_init();
sio2host_init();
appTaskState = JOIN_SEND_STATE;
appPostTask(DISPLAY_TASK_HANDLER);
printf("\r\nsleep_ok %ld ms\r\n", sleptDuration);
}
#endif
#ifdef CONF_PMM_ENABLE
static void app_resources_uninit(void)
{
/* Disable USART TX and RX Pins */
struct port_config pin_conf;
port_get_config_defaults(&pin_conf);
pin_conf.powersave = true;
#ifdef HOST_SERCOM_PAD0_PIN
port_pin_set_config(HOST_SERCOM_PAD0_PIN, &pin_conf);
#endif
#ifdef HOST_SERCOM_PAD1_PIN
port_pin_set_config(HOST_SERCOM_PAD1_PIN, &pin_conf);
#endif
/* Disable UART module */
sio2host_deinit();
/* Disable Transceiver SPI Module */
HAL_RadioDeInit();
}
#endif
/*********************************************************************//*
\brief Timer callback for demo application.
Used during the initial 5 sec wait period.
\param[in] cnt - not used
************************************************************************/
void demoTimerCb(void * cnt)
{
uint8_t i = 10;
int8_t rxdata = 0;
printf("%d..",count);
count--;
startReceiving = false;
sio2host_rx(rxchar,10);
for(i = 0;i<=10;i++)
{
if(rxchar[i] != 13 && rxchar[i] != 10)
{
rxdata = rxchar[i];
break;
}
}
if(!count)
{
printf("\r\n");
}
/* No input so far. start timer till expiry */
if(count > 0 && (!rxdata))
{
SwTimerStart(demoTimerId,MS_TO_US(1000),SW_TIMEOUT_RELATIVE,(void *)demoTimerCb,NULL);
}
/* user did not press any input */
else if(count == 0 && (!rxdata))
{
appTaskState = RESTORE_BAND_STATE;
appPostTask(DISPLAY_TASK_HANDLER);
}
/* User pressed a key */
else if(rxdata)
{
printf("\r\n");
appTaskState = DEMO_APP_CONFIG;
appPostTask(DISPLAY_TASK_HANDLER);
}
}
/*********************************************************************//*
\brief App Post Task
\param[in] Id of the application to be posted
************************************************************************/
void appPostTask(AppTaskIds_t id)
{
ATOMIC_SECTION_ENTER
appTaskFlags |= (1 << id);
ATOMIC_SECTION_EXIT
/* Also post a APP task to the system */
SYSTEM_PostTask(APP_TASK_ID);
}
/*********************************************************************//*
\brief Application Task Handler
************************************************************************/
SYSTEM_TaskStatus_t APP_TaskHandler(void)
{
if (appTaskFlags)
{
for (uint16_t taskId = 0; taskId < APP_TASKS_COUNT; taskId++)
{
if ((1 << taskId) & (appTaskFlags))
{
ATOMIC_SECTION_ENTER
appTaskFlags &= ~(1 << taskId);
ATOMIC_SECTION_EXIT
appTaskHandlers[taskId]();
if (appTaskFlags)
{
SYSTEM_PostTask(APP_TASK_ID);
}
break;
}
}
}
return SYSTEM_TASK_SUCCESS;
}
/*********************************************************************//*
\brief Set join parameters function
\param[in] activation type - notifies the activation type (OTAA/ABP)
\return LORAWAN_SUCCESS, if successfully set the join parameters
LORAWAN_INVALID_PARAMETER, otherwise
************************************************************************/
StackRetStatus_t set_join_parameters(ActivationType_t activation_type)
{
StackRetStatus_t status;
printf("\n********************Join Parameters********************\n\r");
if(ACTIVATION_BY_PERSONALIZATION == activation_type)
{
status = LORAWAN_SetAttr (DEV_ADDR, &demoDevAddr);
if (LORAWAN_SUCCESS == status)
{
status = LORAWAN_SetAttr (APPS_KEY, demoAppsKey);
}
if (LORAWAN_SUCCESS == status)
{
printf("\nAppSessionKey : ");
print_array((uint8_t *)&demoAppsKey, sizeof(demoAppsKey));
status = LORAWAN_SetAttr (NWKS_KEY, demoNwksKey);
}
if (LORAWAN_SUCCESS == status)
{
printf("\nNwkSessionKey : ");
print_array((uint8_t *)&demoNwksKey, sizeof(demoNwksKey));
}
}
else
{
status = LORAWAN_SetAttr (DEV_EUI, demoDevEui);
if (LORAWAN_SUCCESS == status)
{
printf("\nDevEUI : ");
print_array((uint8_t *)&demoDevEui, sizeof(demoDevEui));
status = LORAWAN_SetAttr (JOIN_EUI, demoJoinEui);
}
if (LORAWAN_SUCCESS == status)
{
printf("\nJoinEUI : ");
print_array((uint8_t *)&demoJoinEui, sizeof(demoJoinEui));
status = LORAWAN_SetAttr (APP_KEY, demoAppKey);
}
if (LORAWAN_SUCCESS == status)
{
printf("\nAppKey : ");
print_array((uint8_t *)&demoAppKey, sizeof(demoAppKey));
}
}
return status;
}
/*********************************************************************//*
\brief Function to Initialize the device type
\param[in] ed_class - notifies the device class (CLASS_A/CLASS_B/CLASS_C)
\return LORAWAN_SUCCESS, if successfully set the device class
LORAWAN_INVALID_PARAMETER, otherwise
************************************************************************/
StackRetStatus_t set_device_type(EdClass_t ed_class)
{
StackRetStatus_t status = LORAWAN_SUCCESS;
status = LORAWAN_SetAttr(EDCLASS, &ed_class);
if((LORAWAN_SUCCESS == status) && ((CLASS_C | CLASS_B) & ed_class) && (true == DEMO_APP_MCAST_ENABLE))
{
set_multicast_params();
}
return status;
}
/*********************************************************************//*
\brief Function to Initialize the Multicast parameters
************************************************************************/
void set_multicast_params (void)
{
StackRetStatus_t status;
LorawanMcastDevAddr_t dMcastDevAddr;
LorawanMcastAppSkey_t mcastAppSKey;
LorawanMcastNwkSkey_t mcastNwkSKey;
LorawanMcastDlFreqeuncy_t mcastDlFreq;
LorawanMcastDatarate_t mcastDatarate;
LorawanMcastStatus_t mcastStatus;
ReceiveWindow2Params_t receivewindow2param;
printf("\n***************Multicast Parameters********************\n\r");
dMcastDevAddr.groupId = demoMcastGroupId;
mcastAppSKey.groupId = demoMcastGroupId;
mcastNwkSKey.groupId = demoMcastGroupId;
mcastDlFreq.groupId = demoMcastGroupId;
mcastDatarate.groupId = demoMcastGroupId;
mcastStatus.groupId = demoMcastGroupId;
memcpy(&(mcastAppSKey.mcastAppSKey), &demoMcastAppsKey,LORAWAN_SESSIONKEY_LENGTH);
dMcastDevAddr.mcast_dev_addr = demoMcastDevAddr;
memcpy(&(mcastNwkSKey.mcastNwkSKey), &demoMcastNwksKey,LORAWAN_SESSIONKEY_LENGTH);
memcpy(&(mcastStatus.status),&demoMcastEnable,sizeof(demoMcastEnable));
LORAWAN_GetAttr(RX2_WINDOW_PARAMS ,NULL, &receivewindow2param);
mcastDatarate.datarate = receivewindow2param.dataRate;
mcastDlFreq.dlFrequency = receivewindow2param.frequency;
status = LORAWAN_SetAttr(MCAST_APPS_KEY, &mcastAppSKey);
if (status == LORAWAN_SUCCESS)
{
printf("\nMcastAppSessionKey : ");
print_array((uint8_t *)&(mcastAppSKey.mcastAppSKey), LORAWAN_SESSIONKEY_LENGTH);
status = LORAWAN_SetAttr(MCAST_NWKS_KEY, &mcastNwkSKey);
}
if(status == LORAWAN_SUCCESS)
{
printf("\nMcastNwkSessionKey : ");
print_array((uint8_t *)&(mcastNwkSKey.mcastNwkSKey), LORAWAN_SESSIONKEY_LENGTH);
status = LORAWAN_SetAttr(MCAST_GROUP_ADDR, &dMcastDevAddr);
}
if (status == LORAWAN_SUCCESS)
{
printf("\nMcastGroupAddr : 0x%lx\n\r", dMcastDevAddr.mcast_dev_addr);
status = LORAWAN_SetAttr(MCAST_ENABLE, &mcastStatus);
}
if (status == LORAWAN_SUCCESS)
{
status = LORAWAN_SetMulticastParam(MCAST_DATARATE , &mcastDatarate);
}
if (status == LORAWAN_SUCCESS)
{
status = LORAWAN_SetMulticastParam(MCAST_FREQUENCY , &mcastDlFreq);
}
else
{
printf("\nMcastGroupAddrStatus : Failed\n\r");
}
if (status == LORAWAN_SUCCESS)
{
printf("\nMulticastStatus : Enabled\n\r");
}
else
{
printf("\nMulticastStatus : Failed\n\r");
}
printf("\n********************************************************\n\r");
}
/***********************************************************************
\brief Function to Initialize set default parameters
\param[in] void
\return LORAWAN_SUCCESS, if successfully set all the parameters
LORAWAN_INVALID_PARAMETER, otherwise
************************************************************************/
StackRetStatus_t mote_set_parameters(IsmBand_t ismBand, const uint16_t index)
{
StackRetStatus_t status;
bool joinBackoffEnable = false;
LORAWAN_Reset(ismBand);
#if (NA_BAND == 1 || AU_BAND == 1)
#if (RANDOM_NW_ACQ == 0)
if ((ismBand == ISM_NA915) || (ismBand == ISM_AU915))
{
#define MAX_NA_CHANNELS 72
#define MAX_SUBBAND_CHANNELS 8
ChannelParameters_t ch_params;
uint8_t allowed_min_125khz_ch,allowed_max_125khz_ch,allowed_500khz_channel;
allowed_min_125khz_ch = (subBand-1)*MAX_SUBBAND_CHANNELS;
allowed_max_125khz_ch = ((subBand-1)*MAX_SUBBAND_CHANNELS) + 7 ;
allowed_500khz_channel = subBand+63;
for (ch_params.channelId = 0; ch_params.channelId < MAX_NA_CHANNELS; ch_params.channelId++)
{
if((ch_params.channelId >= allowed_min_125khz_ch) && (ch_params.channelId <= allowed_max_125khz_ch))
{
ch_params.channelAttr.status = true;
}
else if(ch_params.channelId == allowed_500khz_channel)
{
ch_params.channelAttr.status = true;
}
else
{
ch_params.channelAttr.status = false;
}
LORAWAN_SetAttr(CH_PARAM_STATUS, &ch_params);
}
}
#endif
#endif
/*Disabled Join backoff in Demo application
Needs to be enabled in Production Environment Ref Section */
LORAWAN_SetAttr(JOIN_BACKOFF_ENABLE,&joinBackoffEnable);
/* Initialize the join parameters for Demo application */
status = set_join_parameters(demoJoinActivationType);
if (LORAWAN_SUCCESS != status)
{
printf("\nJoin parameters initialization failed\n\r");
return status;
}
/* Set the device type */
status = set_device_type(DEMO_APP_ENDDEVICE_CLASS);
if (LORAWAN_SUCCESS != status)
{
printf("\nUnsupported Device Type\n\r");
return status;
}
/* Send Join request for Demo application */
status = LORAWAN_Join(demoJoinActivationType);
if (LORAWAN_SUCCESS == status && index < sizeof(bandTable))
{
printf("\nJoin Request Sent for %s\n\r",bandStrings[index]);
}
else
{
print_stack_status(status);
appTaskState = JOIN_SEND_STATE;
appPostTask(DISPLAY_TASK_HANDLER);
}
return status;
}
/*********************************************************************//*
\brief Function to Print array of characters
\param[in] *array - Pointer of the array to be printed
\param[in] length - Length of the array
************************************************************************/
void print_array (uint8_t *array, uint8_t length)
{
printf("0x");
for (uint8_t i =0; i < length; i++)
{
printf("%02x", *array);
array++;
}
printf("\n\r");
}
/*********************************************************************//*
\brief Function to Print application configuration
************************************************************************/
void print_application_config (void)
{
EdClass_t edClass;
printf("\n***************Application Configuration***************\n\r");
LORAWAN_GetAttr(EDCLASS, NULL, &edClass);
printf("\nDevType : ");
if(edClass == CLASS_A)
{
printf("CLASS A\n\r");
}
else if(edClass == CLASS_C)
{
printf("CLASS C\n\r");
}
printf("\nActivationType : ");
if(demoJoinActivationType == OVER_THE_AIR_ACTIVATION)
{
printf("OTAA\n\r");
}
else if(demoJoinActivationType == ACTIVATION_BY_PERSONALIZATION)
{
printf("ABP\n\r");
}
printf("\nTransmission Type - ");
if(DEMO_APP_TRANSMISSION_TYPE == CONFIRMED)
{
printf("CONFIRMED\n\r");
}
else if(DEMO_APP_TRANSMISSION_TYPE == UNCONFIRMED)
{
printf("UNCONFIRMED\n\r");
}
printf("\nFPort - %d\n\r", DEMO_APP_FPORT);
printf("\n*******************************************************\n\r");
}
/*********************************************************************//*
\brief Function to Print stack return status
\param[in] status - Status from the stack
************************************************************************/
void print_stack_status(StackRetStatus_t status)
{
switch(status)
{
case LORAWAN_SUCCESS:
printf("\nlorawan_success\n\r");
break;
case LORAWAN_BUSY:
printf("\nlorawan_state : stack_Busy\n\r");
break;
case LORAWAN_NWK_NOT_JOINED:
printf("\ndevice_not_joined_to_network\n\r");
break;
case LORAWAN_INVALID_PARAMETER:
printf("\ninvalid_parameter\n\r");
break;
case LORAWAN_KEYS_NOT_INITIALIZED:
printf("\nkeys_not_initialized\n\r");
break;
case LORAWAN_SILENT_IMMEDIATELY_ACTIVE:
printf("\nsilent_immediately_active\n\r");
break;
case LORAWAN_FCNTR_ERROR_REJOIN_NEEDED:
printf("\nframecounter_error_rejoin_needed\n\r");
break;
case LORAWAN_INVALID_BUFFER_LENGTH:
printf("\ninvalid_buffer_length\n\r");
break;
case LORAWAN_MAC_PAUSED:
printf("\nMAC_paused\n\r");
break;
case LORAWAN_NO_CHANNELS_FOUND:
printf("\nno_free_channels_found\n\r");
break;
case LORAWAN_INVALID_REQUEST:
printf("\nrequest_invalid\n\r");
break;
case LORAWAN_NWK_JOIN_IN_PROGRESS:
printf("\nprev_join_request_in_progress\n\r");
break;
default:
printf("\nrequest_failed %d\n\r",status);
break;
}
}
/*********************************************************************//*
\brief Function to convert Celsius value to Fahrenheit
\param[in] cel_val - Temperature value in Celsius
\param[out] fauren_val- Temperature value in Fahrenheit
************************************************************************/
static float convert_celsius_to_fahrenheit(float celsius_val)
{
float fauren_val;
/* T(°F) = T(°C) × 9/5 + 32 */
fauren_val = (((celsius_val * 9)/5) + 32);
return fauren_val;
}
/* eof demo_app.c */