#include "CayenneLPP.h" #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 #include "DHT.h" #endif #if MBED_CONF_APP_HX711_ENABLED #include "HX711.h" #endif 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 /** * 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); 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 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 // Initialize LoRaWAN stack if(lorawan.initialize(&ev_queue) != LORAWAN_STATUS_OK) { debug("\r\n LoRa initialization failed! \r\n"); return -1; } debug("\r\n Mbed LoRaWANStack initialized \r\n"); callbacks.events = mbed::callback(lora_event_handler); #if MBED_CONF_APP_BATTERY_ENABLED callbacks.battery_level = mbed::callback(battery_level); #endif 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"); return -1; } debug("\r\n CONFIRMED message retries : %d \r\n", CONFIRMED_MSG_RETRY_COUNTER); // Enable adaptive data rate if(lorawan.enable_adaptive_datarate() != LORAWAN_STATUS_OK) { debug("\r\n enable_adaptive_datarate failed! \r\n"); return -1; } debug("\r\n Adaptive data rate (ADR) - Enabled \r\n"); retcode = lorawan.connect(); if(retcode == LORAWAN_STATUS_OK || retcode == LORAWAN_STATUS_CONNECT_IN_PROGRESS) { } else { debug("\r\n Connection error, code = %d \r\n", retcode); return -1; } debug("\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 && MBED_CONF_APP_BATTERY_IN_LPP cayenne.addAnalogInput(1, battery_voltage()); #endif #if MBED_CONF_APP_DHT_ENABLED int err = dht.read(); if(err == DHT::SUCCESS) { cayenne.addTemperature(1, dht.getTemperature()); cayenne.addRelativeHumidity(1, dht.getHumidity()); } else { debug("Error code : %d\r\n", err); } #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; } 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); return; } debug("\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) { debug("\r\n receive() - Error code %d \r\n", retcode); return; } debug(" Data:"); for(uint8_t i = 0; i < retcode; i++) { debug("%x", rx_buffer[i]); } debug("\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: debug("\r\n Connection - Successful \r\n"); if(MBED_CONF_LORA_DUTY_CYCLE_ON) { send_message(); } else { send_message(); ev_queue.call_every(MBED_CONF_APP_TX_TIMER, send_message); } break; case DISCONNECTED: ev_queue.break_dispatch(); debug("\r\n Disconnected Successfully \r\n"); break; case TX_DONE: debug("\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: debug("\r\n Transmission Error - EventCode = %d \r\n", event); // try again if(MBED_CONF_LORA_DUTY_CYCLE_ON) { send_message(); } break; case RX_DONE: debug("\r\n Received message from Network Server \r\n"); receive_message(); break; case RX_TIMEOUT: case RX_ERROR: debug("\r\n Error in reception - Code = %d \r\n", event); break; case JOIN_FAILURE: debug("\r\n OTAA Failed - Check Keys \r\n"); break; default: MBED_ASSERT("Unknown Event"); } }