Forest fire prediction using sensors and LoRa communications
Dependencies: X_NUCLEO_IKS01A2
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
Generated on Thu Jul 14 2022 03:02:59 by 1.7.2