You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

268 lines
7.6 KiB

#include "CayenneLPP.h"
8 years ago
#include "events/EventQueue.h"
#include "lora_radio_helper.h"
#include "lorawan/LoRaWANInterface.h"
#include "lorawan/system/lorawan_data_structures.h"
#include "mbed.h"
#include "nvstore.h"
#if MBED_CONF_APP_DHT_ENABLED
8 years ago
#include "DHT.h"
#endif
8 years ago
#if MBED_CONF_APP_HX711_ENABLED
#include "HX711.h"
#endif
8 years ago
using namespace events;
uint8_t rx_buffer[LORAMAC_PHY_MAXPAYLOAD];
/**
* 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 10
8 years ago
/**
* Maximum number of retries for CONFIRMED messages before giving up
*/
#define CONFIRMED_MSG_RETRY_COUNTER 3
8 years ago
static EventQueue ev_queue(MAX_NUMBER_OF_EVENTS* EVENTS_EVENT_SIZE);
8 years ago
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);
AnalogIn vrefint(ADC_VREF);
static float battery_voltage() {
float vbat = bat.read();
double vdd = (1.224f) / vrefint.read();
return vbat * MBED_CONF_APP_BATTERY_RATIO * vdd;
}
static uint8_t battery_level() {
float vbat = battery_voltage();
double ratio = 253.0f / (4.2f - 3.3f);
int value = ratio * (vbat - 3.4f) + 1.0f;
return value < 1 ? 1 : (value > 254 ? 254 : value);
}
#endif
#if MBED_CONF_APP_DHT_ENABLED
DHT dht(MBED_CONF_APP_DHT_DATA, MBED_CONF_APP_DHT_TYPE);
#endif
#if MBED_CONF_APP_HX711_ENABLED
HX711 loadcell(MBED_CONF_APP_HX711_DATA, MBED_CONF_APP_HX711_CLK);
#endif
8 years ago
int main(void) {
lorawan_status_t retcode;
#if NVSTORE_ENABLED
NVStore &nvstore = NVStore::get_instance();
int rc;
uint16_t key;
// Values read or written by NVStore need to be aligned to a uint32_t address (even if their sizes
// aren't)
uint32_t value;
// Initialize NVstore. Note that it can be skipped, as it is lazily called by all other APIs
rc = nvstore.init();
printf("Init NVStore. \n");
// Show NVStore size, maximum number of keys and area addresses and sizes
printf("NVStore size is %d.\n", nvstore.size());
printf("NVStore max number of keys is %d (out of %d possible ones in this flash configuration).\n",
nvstore.get_max_keys(), nvstore.get_max_possible_keys());
printf("NVStore areas:\n");
for (uint8_t area = 0; area < NVSTORE_NUM_AREAS; area++) {
uint32_t area_address;
size_t area_size;
nvstore.get_area_params(area, area_address, area_size);
printf("Area %d: address 0x%08lx, size %d (0x%x).\n", area, area_address, area_size, area_size);
}
#else
printf("NVStore is disabled for this board\n");
#endif
while(1) {
wait(1);
}
#if MBED_CONF_APP_HX711_ENABLED
loadcell.powerDown();
loadcell.setScale(MBED_CONF_APP_HX711_SCALE);
loadcell.setOffset(MBED_CONF_APP_HX711_OFFSET);
#endif
8 years ago
// Initialize LoRaWAN stack
if(lorawan.initialize(&ev_queue) != LORAWAN_STATUS_OK) {
debug("\r\n LoRa initialization failed! \r\n");
8 years ago
return -1;
}
debug("\r\n Mbed LoRaWANStack initialized \r\n");
8 years ago
callbacks.events = mbed::callback(lora_event_handler);
#if MBED_CONF_APP_BATTERY_ENABLED
callbacks.battery_level = mbed::callback(battery_level);
#endif
8 years ago
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) {
debug("\r\n set_confirmed_msg_retries failed! \r\n\r\n");
8 years ago
return -1;
}
debug("\r\n CONFIRMED message retries : %d \r\n", CONFIRMED_MSG_RETRY_COUNTER);
8 years ago
// Enable adaptive data rate
if(lorawan.enable_adaptive_datarate() != LORAWAN_STATUS_OK) {
debug("\r\n enable_adaptive_datarate failed! \r\n");
8 years ago
return -1;
}
debug("\r\n Adaptive data rate (ADR) - Enabled \r\n");
8 years ago
retcode = lorawan.connect();
if(retcode == LORAWAN_STATUS_OK || retcode == LORAWAN_STATUS_CONNECT_IN_PROGRESS) {
8 years ago
} else {
debug("\r\n Connection error, code = %d \r\n", retcode);
8 years ago
return -1;
}
debug("\r\n Connection - In Progress ...\r\n");
8 years ago
// make your event queue dispatching events forever
ev_queue.dispatch_forever();
return 0;
}
/**
* Sends a message to the Network Server
*/
static void send_message() {
8 years ago
int16_t retcode;
#if MBED_CONF_APP_BATTERY_ENABLED && MBED_CONF_APP_BATTERY_IN_LPP
cayenne.addAnalogInput(1, battery_voltage());
#endif
8 years ago
#if MBED_CONF_APP_DHT_ENABLED
8 years ago
int err = dht.read();
if(err == DHT::SUCCESS) {
8 years ago
cayenne.addTemperature(1, dht.getTemperature());
cayenne.addRelativeHumidity(1, dht.getHumidity());
8 years ago
} else {
debug("Error code : %d\r\n", err);
8 years ago
}
#endif
#if MBED_CONF_APP_HX711_ENABLED
loadcell.powerUp();
if(loadcell.waitReadyRetry(20, 100)) {
cayenne.addAnalogInput(2, loadcell.getUnits(5));
}
loadcell.powerDown();
#endif
// No data to send
if(cayenne.getSize() == 0) {
return;
}
8 years ago
retcode = lorawan.send(MBED_CONF_LORA_APP_PORT, cayenne.getBuffer(), cayenne.getSize(),
MSG_UNCONFIRMED_FLAG);
if(retcode < 0) {
retcode == LORAWAN_STATUS_WOULD_BLOCK ? debug("send - WOULD BLOCK\r\n")
: debug("\r\n send() - Error code %d \r\n", retcode);
8 years ago
return;
}
debug("\r\n %d bytes scheduled for transmission \r\n", retcode);
8 years ago
cayenne.reset();
}
/**
* Receive a message from the Network Server
*/
static void receive_message() {
8 years ago
int16_t retcode;
retcode = lorawan.receive(MBED_CONF_LORA_APP_PORT, rx_buffer, LORAMAC_PHY_MAXPAYLOAD,
MSG_CONFIRMED_FLAG | MSG_UNCONFIRMED_FLAG);
8 years ago
if(retcode < 0) {
debug("\r\n receive() - Error code %d \r\n", retcode);
8 years ago
return;
}
debug(" Data:");
8 years ago
for(uint8_t i = 0; i < retcode; i++) {
debug("%x", rx_buffer[i]);
8 years ago
}
debug("\r\n Data Length: %d\r\n", retcode);
8 years ago
memset(rx_buffer, 0, LORAMAC_PHY_MAXPAYLOAD);
}
static void lora_event_handler(lorawan_event_t event) {
switch(event) {
8 years ago
case CONNECTED:
debug("\r\n Connection - Successful \r\n");
if(MBED_CONF_LORA_DUTY_CYCLE_ON) {
8 years ago
send_message();
} else {
send_message();
ev_queue.call_every(MBED_CONF_APP_TX_TIMER, send_message);
8 years ago
}
break;
case DISCONNECTED:
ev_queue.break_dispatch();
debug("\r\n Disconnected Successfully \r\n");
8 years ago
break;
case TX_DONE:
debug("\r\n Message Sent to Network Server \r\n");
if(MBED_CONF_LORA_DUTY_CYCLE_ON) {
8 years ago
send_message();
}
break;
case TX_TIMEOUT:
case TX_ERROR:
case TX_CRYPTO_ERROR:
case TX_SCHEDULING_ERROR:
debug("\r\n Transmission Error - EventCode = %d \r\n", event);
8 years ago
// try again
if(MBED_CONF_LORA_DUTY_CYCLE_ON) {
8 years ago
send_message();
}
break;
case RX_DONE:
debug("\r\n Received message from Network Server \r\n");
8 years ago
receive_message();
break;
case RX_TIMEOUT:
case RX_ERROR:
debug("\r\n Error in reception - Code = %d \r\n", event);
8 years ago
break;
case JOIN_FAILURE:
debug("\r\n OTAA Failed - Check Keys \r\n");
8 years ago
break;
default:
MBED_ASSERT("Unknown Event");
}
}