|
|
|
|
#include "mbed.h"
|
|
|
|
|
#include "lorawan/LoRaWANInterface.h"
|
|
|
|
|
#include "lorawan/system/lorawan_data_structures.h"
|
|
|
|
|
#include "events/EventQueue.h"
|
|
|
|
|
#include "lora_radio_helper.h"
|
|
|
|
|
#include "CayenneLPP.h"
|
|
|
|
|
|
|
|
|
|
#if MBED_CONF_APP_DHT_ENABLED
|
|
|
|
|
#include "DHT.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
using namespace events;
|
|
|
|
|
|
|
|
|
|
uint8_t rx_buffer[LORAMAC_PHY_MAXPAYLOAD];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Sets up an application dependent transmission timer in ms. Used only when Duty Cycling is off for testing
|
|
|
|
|
*/
|
|
|
|
|
#define TX_TIMER 600000
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Maximum number of events for the event queue.
|
|
|
|
|
* 16 is the safe number for the stack events, however, if application
|
|
|
|
|
* also uses the queue for whatever purposes, this number should be increased.c
|
|
|
|
|
*/
|
|
|
|
|
#define MAX_NUMBER_OF_EVENTS 16
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Maximum number of retries for CONFIRMED messages before giving up
|
|
|
|
|
*/
|
|
|
|
|
#define CONFIRMED_MSG_RETRY_COUNTER 3
|
|
|
|
|
|
|
|
|
|
static EventQueue ev_queue(MAX_NUMBER_OF_EVENTS * EVENTS_EVENT_SIZE);
|
|
|
|
|
static void lora_event_handler(lorawan_event_t event);
|
|
|
|
|
static LoRaWANInterface lorawan(radio);
|
|
|
|
|
static lorawan_app_callbacks_t callbacks;
|
|
|
|
|
static CayenneLPP cayenne(51);
|
|
|
|
|
|
|
|
|
|
#if MBED_CONF_APP_BATTERY_ENABLED
|
|
|
|
|
AnalogIn bat(MBED_CONF_APP_BATTERY_ADC);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if MBED_CONF_APP_DHT_ENABLED
|
|
|
|
|
DHT dht(MBED_CONF_APP_DHT_DATA, MBED_CONF_APP_DHT_TYPE);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
DigitalOut led(LED1);
|
|
|
|
|
|
|
|
|
|
int main(void) {
|
|
|
|
|
|
|
|
|
|
lorawan_status_t retcode;
|
|
|
|
|
// Initialize LoRaWAN stack
|
|
|
|
|
if (lorawan.initialize(&ev_queue) != LORAWAN_STATUS_OK) {
|
|
|
|
|
printf("\r\n LoRa initialization failed! \r\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("\r\n Mbed LoRaWANStack initialized \r\n");
|
|
|
|
|
|
|
|
|
|
callbacks.events = mbed::callback(lora_event_handler);
|
|
|
|
|
lorawan.add_app_callbacks(&callbacks);
|
|
|
|
|
|
|
|
|
|
// Set number of retries in case of CONFIRMED messages
|
|
|
|
|
if (lorawan.set_confirmed_msg_retries(CONFIRMED_MSG_RETRY_COUNTER)
|
|
|
|
|
!= LORAWAN_STATUS_OK) {
|
|
|
|
|
printf("\r\n set_confirmed_msg_retries failed! \r\n\r\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("\r\n CONFIRMED message retries : %d \r\n",
|
|
|
|
|
CONFIRMED_MSG_RETRY_COUNTER);
|
|
|
|
|
|
|
|
|
|
// Enable adaptive data rate
|
|
|
|
|
if (lorawan.enable_adaptive_datarate() != LORAWAN_STATUS_OK) {
|
|
|
|
|
printf("\r\n enable_adaptive_datarate failed! \r\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("\r\n Adaptive data rate (ADR) - Enabled \r\n");
|
|
|
|
|
|
|
|
|
|
retcode = lorawan.connect();
|
|
|
|
|
|
|
|
|
|
if (retcode == LORAWAN_STATUS_OK ||
|
|
|
|
|
retcode == LORAWAN_STATUS_CONNECT_IN_PROGRESS) {
|
|
|
|
|
} else {
|
|
|
|
|
printf("\r\n Connection error, code = %d \r\n", retcode);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("\r\n Connection - In Progress ...\r\n");
|
|
|
|
|
|
|
|
|
|
// make your event queue dispatching events forever
|
|
|
|
|
ev_queue.dispatch_forever();
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sends a message to the Network Server
|
|
|
|
|
*/
|
|
|
|
|
static void send_message()
|
|
|
|
|
{
|
|
|
|
|
int16_t retcode;
|
|
|
|
|
|
|
|
|
|
#if MBED_CONF_APP_BATTERY_ENABLED
|
|
|
|
|
float vbat = bat.read();
|
|
|
|
|
vbat = vbat*5/3*3.3f;
|
|
|
|
|
cayenne.addAnalogInput(1, vbat);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if MBED_CONF_APP_DHT_ENABLED
|
|
|
|
|
int err = dht.read();
|
|
|
|
|
if (err == DHT::SUCCESS) {
|
|
|
|
|
cayenne.addTemperature(1, dht.getTemperature());
|
|
|
|
|
cayenne.addRelativeHumidity(2, dht.getHumidity());
|
|
|
|
|
} else {
|
|
|
|
|
printf("Error code : %d\r\n", err);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// No data to send
|
|
|
|
|
if (cayenne.getSize() == 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
retcode = lorawan.send(MBED_CONF_LORA_APP_PORT, cayenne.getBuffer(), cayenne.getSize(),
|
|
|
|
|
MSG_UNCONFIRMED_FLAG);
|
|
|
|
|
|
|
|
|
|
if (retcode < 0) {
|
|
|
|
|
retcode == LORAWAN_STATUS_WOULD_BLOCK ? printf("send - WOULD BLOCK\r\n")
|
|
|
|
|
: printf("\r\n send() - Error code %d \r\n", retcode);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("\r\n %d bytes scheduled for transmission \r\n", retcode);
|
|
|
|
|
cayenne.reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Receive a message from the Network Server
|
|
|
|
|
*/
|
|
|
|
|
static void receive_message()
|
|
|
|
|
{
|
|
|
|
|
int16_t retcode;
|
|
|
|
|
retcode = lorawan.receive(MBED_CONF_LORA_APP_PORT, rx_buffer,
|
|
|
|
|
LORAMAC_PHY_MAXPAYLOAD,
|
|
|
|
|
MSG_CONFIRMED_FLAG|MSG_UNCONFIRMED_FLAG);
|
|
|
|
|
|
|
|
|
|
if (retcode < 0) {
|
|
|
|
|
printf("\r\n receive() - Error code %d \r\n", retcode);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf(" Data:");
|
|
|
|
|
|
|
|
|
|
for (uint8_t i = 0; i < retcode; i++) {
|
|
|
|
|
printf("%x", rx_buffer[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("\r\n Data Length: %d\r\n", retcode);
|
|
|
|
|
|
|
|
|
|
memset(rx_buffer, 0, LORAMAC_PHY_MAXPAYLOAD);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void lora_event_handler(lorawan_event_t event)
|
|
|
|
|
{
|
|
|
|
|
switch (event) {
|
|
|
|
|
case CONNECTED:
|
|
|
|
|
printf("\r\n Connection - Successful \r\n");
|
|
|
|
|
if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
|
|
|
|
|
send_message();
|
|
|
|
|
} else {
|
|
|
|
|
ev_queue.call_every(TX_TIMER, send_message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
case DISCONNECTED:
|
|
|
|
|
ev_queue.break_dispatch();
|
|
|
|
|
printf("\r\n Disconnected Successfully \r\n");
|
|
|
|
|
break;
|
|
|
|
|
case TX_DONE:
|
|
|
|
|
printf("\r\n Message Sent to Network Server \r\n");
|
|
|
|
|
if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
|
|
|
|
|
send_message();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case TX_TIMEOUT:
|
|
|
|
|
case TX_ERROR:
|
|
|
|
|
case TX_CRYPTO_ERROR:
|
|
|
|
|
case TX_SCHEDULING_ERROR:
|
|
|
|
|
printf("\r\n Transmission Error - EventCode = %d \r\n", event);
|
|
|
|
|
// try again
|
|
|
|
|
if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
|
|
|
|
|
send_message();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case RX_DONE:
|
|
|
|
|
printf("\r\n Received message from Network Server \r\n");
|
|
|
|
|
receive_message();
|
|
|
|
|
break;
|
|
|
|
|
case RX_TIMEOUT:
|
|
|
|
|
case RX_ERROR:
|
|
|
|
|
printf("\r\n Error in reception - Code = %d \r\n", event);
|
|
|
|
|
break;
|
|
|
|
|
case JOIN_FAILURE:
|
|
|
|
|
printf("\r\n OTAA Failed - Check Keys \r\n");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
MBED_ASSERT("Unknown Event");
|
|
|
|
|
}
|
|
|
|
|
}
|