work1
Dependencies: mbed MAX44009 mbed-os Si7021
app/AppLora.cpp
- Committer:
- danaeb
- Date:
- 2020-05-27
- Revision:
- 1:3656b45f17a8
- Parent:
- AppLora.cpp@ 0:d3e390d62607
File content as of revision 1:3656b45f17a8:
#include <stdio.h> #include "lorawan/LoRaWANInterface.h" #include "lorawan/system/lorawan_data_structures.h" #include "events/EventQueue.h" #include "mbed.h" #include "AppLora.h" #include "AppMain.h" #include "tools.h" // Application helpers //#include "trace_helper.h" #include "lora_radio_helper.h" #include "hal/pinmap.h" #include "PeripheralPins.h" #include "board/PowerManager.h" #include "mbed_trace.h" #define TRACE_GROUP "lora" #ifdef __cplusplus extern "C" { #endif #include "tools.h" #ifdef __cplusplus } #endif using namespace events; EventQueue * AppLora::_queue; Callback<void(AppLora::EVENT)> AppLora::_lora_callback; DigitalInOut AppLora::_txco(LORA_TXCO); // Max payload size can be LORAMAC_PHY_MAXPAYLOAD. // This example only communicates with much shorter messages (<30 bytes). // If longer messages are used, these buffers must be changed accordingly. uint8_t tx_buffer[30]; uint8_t rx_buffer[30]; /** * Maximum number of retries for CONFIRMED messages before giving up */ #define CONFIRMED_MSG_RETRY_COUNTER 3 /** * Constructing Mbed LoRaWANInterface and passing it down the radio object. */ static LoRaWANInterface lorawan(radio); /** * Application specific callbacks */ lorawan_app_callbacks_t AppLora::_callbacks; void AppLora::_pin_active_mode(void){ // enable MOSI pin pinmap_pinout(LORA_SPI_MOSI, PinMap_SPI_MOSI); pinmap_pinout(LORA_SPI_MISO, PinMap_SPI_MISO); pinmap_pinout(LORA_SPI_SCLK, PinMap_SPI_SCLK); // enable high precision oscillator (around 500uA) _txco.mode(PullNone); _txco = 1; _txco.output(); } void AppLora::_pin_lowpower_mode(void){ DigitalIn lora_spi_miso(LORA_SPI_MISO); DigitalIn lora_spi_mosi(LORA_SPI_MOSI); // That was a big mistake that consume 30µA // It must be corrected on tag //DigitalIn lora_spi_cs(SPI_MOSI); //lora_spi_cs.mode(PullNone); lora_spi_miso.mode(PullNone); lora_spi_mosi.mode(PullNone); #if 0 GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; // for whatever reason the mosi pin draw approximatly 300uA. // So it need to be disabled when loRa is not used // disable LORA_MOSI_SPI GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7 /* GPIO_PIN_7 | | GPIO_PIN_15*/; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_3; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); #endif // disable high precision oscillator _txco = 0; _txco.input(); } void AppLora::_enter_lowpower_mode(void){ _pin_lowpower_mode(); PowerManager *pm= PowerManager::get_instance(); pm->sleep_mode(); } void AppLora::_enter_active_mode(void){ PowerManager *pm= PowerManager::get_instance(); pm->run_mode(); _pin_active_mode(); } void AppLora::initialize(EventQueue *queue) { _queue = queue; _enter_active_mode(); tr_debug("setting voltage to 3V"); // setup tracing //setup_trace(); // Initialize LoRaWAN stack if (lorawan.initialize(_queue) != LORAWAN_STATUS_OK) { tr_err("LoRa initialization failed!"); //return -1; } tr_info("mbed LoRaWANStack initialized"); // prepare application callbacks _callbacks.events = mbed::callback(AppLora::_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) { tr_err("set_confirmed_msg_retries failed!"); //return -1; } tr_debug("confirmed message retries : %d", CONFIRMED_MSG_RETRY_COUNTER); // Enable adaptive data rate /* if (lorawan.enable_adaptive_datarate() != LORAWAN_STATUS_OK) { PRINT("\r\n enable_adaptive_datarate failed! \r\n"); //return -1; } */ //PRINT("\r\n Adaptive data rate (ADR) - Enabled \r\n"); _enter_lowpower_mode(); } u32 AppLora::get_random(void){ u32 rand; _enter_active_mode(); rand = radio.random(); _enter_lowpower_mode(); return rand; } u8 AppLora::get_next_transmission_max_size(void){ /* * find a better way to get the max payload size */ #if 0 lorawan_tx_metadata meta; lorawan.get_tx_metadata(meta); return meta.max_payload; #else return 51; // minimum payload size #endif } void AppLora::connect(void){ lorawan_status_t retcode; _enter_active_mode(); retcode = lorawan.connect(); if (retcode == LORAWAN_STATUS_OK || retcode == LORAWAN_STATUS_CONNECT_IN_PROGRESS) { } else { tr_err("connection error, code = %d", retcode); _enter_lowpower_mode(); _call_callback(AppLora::EVENT_CONNECTION_ERROR); //return -1; return; } tr_info("connection - in progress..."); } void AppLora::disconnect(void){ lorawan.cancel_sending(); lorawan.disconnect(); } /** * Sends a message to the Network Server */ s16 AppLora::send_message(u8 *data, u8 data_size, u8 app_port, bool confirmed) { s16 retcode; static u8 would_block_error_count = 0; int flags = MSG_UNCONFIRMED_FLAG; tr_info("sending message"); tr_debug("\t confirmed: %d", confirmed); tr_debug("\t port: 0x%02x", app_port); tr_debug("\t size: %d", data_size); tr_info("\t data: "); tools_print_to_hex(data, data_size); if(confirmed){ flags = MSG_CONFIRMED_FLAG; } _enter_active_mode(); retcode = lorawan.send(app_port, data, data_size, flags); if(retcode < 0){ /* * LoRa error code are between -1000 and -1024 * -(retcode+1000) convert the error in a number between * 1 and 24 * * Then the value 1 is saved @ the virtual address va between 1 and 24 */ tr_warn("\t error : %d", retcode); } if(retcode == LORAWAN_STATUS_WOULD_BLOCK){ ++would_block_error_count; // Reset only if this error appear three time in a row // Because in some case this error can appear during the join and this // is the expected behaviour if(would_block_error_count > 2){ NVIC_SystemReset(); } } else if(retcode >= 0){ would_block_error_count = 0; } return retcode; } /** * Receive a message from the Network Server */ s16 AppLora::get_rx_message(u8 *data, u16 data_size, u8 &app_port) { s16 received_size; int flags; received_size = lorawan.receive(data, data_size, app_port, flags); if (received_size < 0) { tr_err("receive() - Error code %d", received_size); // return; } else{ tr_info("received message"); tr_debug("\t flags: %d", flags); tr_debug("\t port: %d", app_port); tr_debug("\t max size: %d", data_size); tr_debug("\t received size: %d", received_size); tr_info("\t data: "); tools_print_to_hex(data, received_size); } return received_size; } void AppLora::_send_empty_uplink(void){ int retcode; _enter_active_mode(); //wait(0.05); wait_us(50000); // we could add more information in this frame retcode = lorawan.send(1, NULL, 0, MSG_CONFIRMED_FLAG); if (retcode < 0) { tr_err("uplink send() - Error code %d", retcode); _enter_lowpower_mode(); // return; } //_enter_lowpower_mode(); } void AppLora::set_lora_callback(Callback<void(AppLora::EVENT)> lora_callback){ _lora_callback = lora_callback; } void AppLora::_call_callback(AppLora::EVENT lora_event){ if(_lora_callback){ _lora_callback(lora_event); } } /** * Event handler */ void AppLora::_lora_event_handler(lorawan_event_t event) { switch (event) { case CONNECTED: tr_info("connection - successful"); _enter_lowpower_mode(); _call_callback(AppLora::EVENT_CONNECTED); break; case DISCONNECTED: //AppLora::_queue->break_dispatch(); tr_info("disconnected successfully"); _enter_lowpower_mode(); _call_callback(AppLora::EVENT_DISCONNECTED); break; case TX_DONE: tr_info("message sent to network server"); _enter_lowpower_mode(); _call_callback(AppLora::EVENT_TX_DONE); break; case UPLINK_REQUIRED: // Uplink are requested when the pending bit is set // or when more downlink messages are waiting // ACK seems to be handled directly by the stack tr_info("LoRaStack requesting uplink"); _send_empty_uplink(); _call_callback(AppLora::EVENT_UPLINK_REQUIERED); break; case TX_TIMEOUT: case TX_ERROR: case TX_CRYPTO_ERROR: case TX_SCHEDULING_ERROR: tr_err("transmission error - event code = %d", event); _enter_lowpower_mode(); _call_callback(AppLora::EVENT_TX_ERROR); break; case RX_DONE: tr_info("received message from network server"); AppMain::incoming_lora_message_callback(); _enter_lowpower_mode(); _call_callback(AppLora::EVENT_RX_DONE); //receive_message(); break; case RX_TIMEOUT: case RX_ERROR: tr_err("error in reception - code = %d", event); _enter_lowpower_mode(); _call_callback(AppLora::EVENT_RX_ERROR); break; case JOIN_FAILURE: tr_err("OTAA failed - check keys"); _enter_lowpower_mode(); _call_callback(AppLora::EVENT_JOIN_FAILURE); break; default: MBED_ASSERT("Unknown Event"); _enter_lowpower_mode(); } } // EOF