Forest fire prediction using sensors and LoRa communications

Dependencies:   X_NUCLEO_IKS01A2

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /**
00002  * Copyright (c) 2017, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 #include <stdio.h>
00018 
00019 #include "lorawan/LoRaWANInterface.h"
00020 #include "lorawan/system/lorawan_data_structures.h"
00021 #include "events/EventQueue.h"
00022 
00023 // Sensor headers
00024 #include "mbed.h"
00025 #include "XNucleoIKS01A2.h"
00026 
00027 // Application helpers
00028 #include "trace_helper.h"
00029 #include "lora_radio_helper.h"
00030 
00031 using namespace events;
00032 
00033 //#define WITH_SENSORS
00034 
00035 #ifdef WITH_SENSORS
00036 // Instantiate the expansion board
00037 static XNucleoIKS01A2 *mems_expansion_board = XNucleoIKS01A2::instance(D14, D15, D4, D5);
00038 
00039 // Retrieve the composing elements of the expansion board
00040 static HTS221Sensor *hum_temp = mems_expansion_board->ht_sensor;
00041 static LPS22HBSensor *press_temp = mems_expansion_board->pt_sensor;
00042 #endif
00043 
00044 // Max payload size can be LORAMAC_PHY_MAXPAYLOAD.
00045 // This example only communicates with much shorter messages (<30 bytes).
00046 // If longer messages are used, these buffers must be changed accordingly.
00047 uint8_t tx_buffer[100];
00048 uint8_t rx_buffer[100];
00049 
00050 // Buffers needed to read values from the sensors
00051 float value_temp, value_hum;
00052 #define SENSOR_BUFFER_SIZE 32
00053 char buffer_temp[SENSOR_BUFFER_SIZE], buffer_hum[SENSOR_BUFFER_SIZE];
00054 
00055 /*
00056  * Sets up an application dependent transmission timer in ms. Used only when Duty Cycling is off for testing
00057  */
00058 #define TX_TIMER                        11000
00059 
00060 /**
00061  * Maximum number of events for the event queue.
00062  * 10 is the safe number for the stack events, however, if application
00063  * also uses the queue for whatever purposes, this number should be increased.
00064  */
00065 #define MAX_NUMBER_OF_EVENTS            10
00066 
00067 /**
00068  * Maximum number of retries for CONFIRMED messages before giving up
00069  */
00070 #define CONFIRMED_MSG_RETRY_COUNTER     3
00071 
00072 
00073 /**
00074 * This event queue is the global event queue for both the
00075 * application and stack. To conserve memory, the stack is designed to run
00076 * in the same thread as the application and the application is responsible for
00077 * providing an event queue to the stack that will be used for ISR deferment as
00078 * well as application information event queuing.
00079 */
00080 static EventQueue ev_queue(MAX_NUMBER_OF_EVENTS *EVENTS_EVENT_SIZE);
00081 
00082 /**
00083  * Event handler.
00084  *
00085  * This will be passed to the LoRaWAN stack to queue events for the
00086  * application which in turn drive the application.
00087  */
00088 static void lora_event_handler(lorawan_event_t event);
00089 
00090 /**
00091  * Constructing Mbed LoRaWANInterface and passing it the radio object from lora_radio_helper.
00092  */
00093 static LoRaWANInterface lorawan(radio);
00094 
00095 /**
00096  * Application specific callbacks
00097  */
00098 static lorawan_app_callbacks_t callbacks;
00099 
00100 
00101 static char *print_double(char* str, double v);
00102 
00103 /**
00104  * Entry point for application
00105  */
00106 int main(void)
00107 {
00108     printf("\r\n Hello, starting...");
00109     
00110     #ifdef WITH_SENSORS
00111     // setup sensor stack
00112     hum_temp->enable();
00113     press_temp->enable();
00114     
00115     // testing sensors
00116     hum_temp->get_temperature(&value_temp);
00117     hum_temp->get_humidity(&value_hum);
00118     printf("\r\n Sensors test:\r\n HTS221: [temp] %7s C,   [hum] %s%%\r\n", print_double(buffer_temp, value_temp), print_double(buffer_hum, value_hum));
00119     #endif
00120     
00121     // setup tracing
00122     setup_trace();
00123 
00124     // stores the status of a call to LoRaWAN protocol
00125     lorawan_status_t retcode;
00126 
00127     // Initialize LoRaWAN stack
00128     if (lorawan.initialize(&ev_queue) != LORAWAN_STATUS_OK) {
00129         printf("\r\n LoRa initialization failed! \r\n");
00130         return -1;
00131     }
00132 
00133     printf("\r\n Mbed LoRaWANStack initialized \r\n");
00134 
00135     // prepare application callbacks
00136     callbacks.events = mbed::callback(lora_event_handler);
00137     lorawan.add_app_callbacks(&callbacks);
00138 
00139     // Set number of retries in case of CONFIRMED messages
00140     if (lorawan.set_confirmed_msg_retries(CONFIRMED_MSG_RETRY_COUNTER)
00141             != LORAWAN_STATUS_OK) {
00142         printf("\r\n set_confirmed_msg_retries failed! \r\n\r\n");
00143         return -1;
00144     }
00145 
00146     printf("\r\n CONFIRMED message retries : %d \r\n",
00147            CONFIRMED_MSG_RETRY_COUNTER);
00148 
00149     // Enable adaptive data rate
00150     if (lorawan.enable_adaptive_datarate() != LORAWAN_STATUS_OK) {
00151         printf("\r\n enable_adaptive_datarate failed! \r\n");
00152         return -1;
00153     }
00154 
00155     printf("\r\n Adaptive data  rate (ADR) - Enabled \r\n");
00156 
00157     retcode = lorawan.connect();
00158 
00159     if (retcode == LORAWAN_STATUS_OK ||
00160             retcode == LORAWAN_STATUS_CONNECT_IN_PROGRESS) {
00161     } else {
00162         printf("\r\n Connection error, code = %d \r\n", retcode);
00163         return -1;
00164     }
00165 
00166     printf("\r\n Connection - In Progress ...\r\n");
00167 
00168     // make your event queue dispatching events forever
00169     ev_queue.dispatch_forever();
00170 
00171     return 0;
00172 }
00173 
00174 #ifndef WITH_SENSORS
00175 
00176 /*
00177  * Sends a message to the Network Server
00178  */
00179 static void send_message()
00180 {
00181     uint16_t packet_len;
00182     int16_t retcode;
00183     printf("\n\rSending message");    
00184 
00185     packet_len = sprintf((char *) tx_buffer, "This is a test. LoRa Works! <3");
00186 
00187     retcode = lorawan.send(MBED_CONF_LORA_APP_PORT, tx_buffer, packet_len,
00188                            MSG_UNCONFIRMED_FLAG);
00189 
00190     if (retcode < 0) {
00191         printf("retcode < 0 in send\r\n");
00192         
00193         retcode == LORAWAN_STATUS_WOULD_BLOCK ? printf("send - WOULD BLOCK\r\n")
00194         : printf("\r\n send() - Error code %d \r\n", retcode);
00195 
00196         if (retcode == LORAWAN_STATUS_WOULD_BLOCK) {
00197             //retry in 3 seconds
00198             printf("LORAWAN_STATUS_WOULD_BLOCK verified, retrying");
00199             if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
00200                 ev_queue.call_in(3000, send_message);
00201             }
00202         }
00203         return;
00204     }
00205 
00206     printf("\r\n %d bytes scheduled for transmission \r\n", retcode);
00207     memset(tx_buffer, 0, sizeof(tx_buffer));
00208 }
00209 
00210 #else
00211 
00212 
00213 static void send_message()
00214 {
00215     printf("\n\rSending message");
00216     uint16_t packet_len;
00217     int16_t retcode;
00218     
00219     // reading from sensors
00220     memset(buffer_temp, 0, sizeof(buffer_temp));
00221     memset(buffer_hum, 0, sizeof(buffer_hum));
00222     hum_temp->get_temperature(&value_temp);
00223     hum_temp->get_humidity(&value_hum);
00224     printf("\r\nSensors reading: [temp] %7s C, [hum] %s%%\r\n", 
00225         print_double(buffer_temp, value_temp), print_double(buffer_hum, value_hum));
00226 
00227     // format data
00228     uint16_t temp_len = sprintf((char *) tx_buffer, buffer_temp);
00229     tx_buffer[temp_len] = ':';
00230     uint16_t hum_len = sprintf((char *) &tx_buffer[temp_len+1], buffer_hum);
00231     
00232     // set final payload and send
00233     packet_len = temp_len + hum_len + 1;    
00234     
00235     printf("\r\n Sending to server %s", tx_buffer);
00236     
00237     retcode = lorawan.send(MBED_CONF_LORA_APP_PORT, tx_buffer, packet_len,
00238                            MSG_UNCONFIRMED_FLAG);
00239                            
00240     
00241 
00242     if (retcode < 0) {
00243         printf("retcode < 0 in send\r\n");
00244         
00245         retcode == LORAWAN_STATUS_WOULD_BLOCK ? printf("send - WOULD BLOCK\r\n")
00246         : printf("\r\n send() - Error code %d \r\n", retcode);
00247 
00248         if (retcode == LORAWAN_STATUS_WOULD_BLOCK) {
00249             //retry in 3 seconds
00250             printf("LORAWAN_STATUS_WOULD_BLOCK verified, retrying");
00251             if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
00252                 ev_queue.call_in(3000, send_message);
00253             }
00254         }
00255         return;
00256     }
00257 
00258     printf("\r\n %d bytes scheduled for transmission \r\n", retcode);
00259     memset(tx_buffer, 0, sizeof(tx_buffer));
00260 }
00261 
00262 #endif
00263 
00264 /* Helper function for printing floats & doubles */
00265 static char *print_double(char* str, double v)
00266 {
00267   int decimalDigits=2;
00268   int i = 1;
00269   int intPart, fractPart;
00270   int len;
00271   char *ptr;
00272 
00273   /* prepare decimal digits multiplicator */
00274   for (;decimalDigits!=0; i*=10, decimalDigits--);
00275 
00276   /* calculate integer & fractinal parts */
00277   intPart = (int)v;
00278   fractPart = (int)((v-(double)(int)v)*i);
00279 
00280   /* fill in integer part */
00281   sprintf(str, "%i.", intPart);
00282 
00283   /* prepare fill in of fractional part */
00284   len = strlen(str);
00285   ptr = &str[len];
00286 
00287   /* fill in leading fractional zeros */
00288   for (i/=10;i>1; i/=10, ptr++) {
00289     if (fractPart >= i) {
00290       break;
00291     }
00292     *ptr = '0';
00293   }
00294 
00295   /* fill in (rest of) fractional part */
00296   sprintf(ptr, "%i", fractPart);
00297 
00298   return str;
00299 }
00300 
00301 /**
00302  * Event handler
00303  */
00304 static void lora_event_handler(lorawan_event_t event)
00305 {
00306     switch (event) {
00307         case CONNECTED:
00308             printf("\r\n Connection - Successful \r\n");
00309             if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
00310                 send_message();
00311             } else {
00312                 ev_queue.call_every(TX_TIMER, send_message);
00313             }
00314 
00315             break;
00316         case DISCONNECTED:
00317             ev_queue.break_dispatch();
00318             printf("\r\n Disconnected Successfully \r\n");
00319             break;
00320         case TX_DONE:
00321             printf("\r\n Message Sent to Network Server \r\n");
00322             if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
00323                 send_message();
00324             }
00325             break;
00326         case TX_TIMEOUT:
00327         case TX_ERROR:
00328         case TX_CRYPTO_ERROR:
00329         case TX_SCHEDULING_ERROR:
00330             printf("\r\n Transmission Error - EventCode = %d \r\n", event);
00331             // try again
00332             if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
00333                 send_message();
00334             }
00335             break;
00336         case RX_DONE:
00337             printf("\r\n Received message from Network Server \r\n");
00338             break;
00339         case RX_TIMEOUT:
00340         case RX_ERROR:
00341             printf("\r\n Error in reception - Code = %d \r\n", event);
00342             break;
00343         case JOIN_FAILURE:
00344             printf("\r\n OTAA Failed - Check Keys \r\n");
00345             break;
00346         case UPLINK_REQUIRED:
00347             printf("\r\n Uplink required by NS \r\n");
00348             if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
00349                 send_message();
00350             }
00351             break;
00352         default:
00353             MBED_ASSERT("Unknown Event");
00354     }
00355 }
00356 
00357 // EOF