Final version of the exercise on the Things Network

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 // Application helpers
00024 #include "trace_helper.h"
00025 #include "lora_radio_helper.h"
00026 
00027 // Extension Board library
00028 #include "XNucleoIKS01A2.h"
00029 
00030 
00031 using namespace events;
00032 
00033 // Max payload size can be LORAMAC_PHY_MAXPAYLOAD.
00034 // This example only communicates with much shorter messages (<30 bytes).
00035 // If longer messages are used, these buffers must be changed accordingly.
00036 uint8_t tx_buffer[60];
00037 uint8_t rx_buffer[30];
00038 
00039 /*
00040  * Sets up an application dependent transmission timer in ms. Used only when Duty Cycling is off for testing
00041  */
00042 #define TX_TIMER                        10000
00043 
00044 /**
00045  * Maximum number of events for the event queue.
00046  * 10 is the safe number for the stack events, however, if application
00047  * also uses the queue for whatever purposes, this number should be increased.
00048  */
00049 #define MAX_NUMBER_OF_EVENTS            10
00050 
00051 /**
00052  * Maximum number of retries for CONFIRMED messages before giving up
00053  */
00054 #define CONFIRMED_MSG_RETRY_COUNTER     3
00055 
00056 
00057 /**
00058 * This event queue is the global event queue for both the
00059 * application and stack. To conserve memory, the stack is designed to run
00060 * in the same thread as the application and the application is responsible for
00061 * providing an event queue to the stack that will be used for ISR deferment as
00062 * well as application information event queuing.
00063 */
00064 static EventQueue ev_queue(MAX_NUMBER_OF_EVENTS *EVENTS_EVENT_SIZE);
00065 
00066 /**
00067  * Event handler.
00068  *
00069  * This will be passed to the LoRaWAN stack to queue events for the
00070  * application which in turn drive the application.
00071  */
00072 static void lora_event_handler(lorawan_event_t event);
00073 
00074 /**
00075  * Constructing Mbed LoRaWANInterface and passing it the radio object from lora_radio_helper.
00076  */
00077 static LoRaWANInterface lorawan(radio);
00078 
00079 /**
00080  * Application specific callbacks
00081  */
00082 static lorawan_app_callbacks_t callbacks;
00083 
00084 /* Instantiate the expansion board */
00085 XNucleoIKS01A2 *mems_expansion_board = XNucleoIKS01A2::instance(D14, D15, D4, D5);
00086 
00087 /* Sensor initialization */
00088 HTS221Sensor *hum_temp = mems_expansion_board->ht_sensor;
00089 LSM6DSLSensor *acc_gyro = mems_expansion_board->acc_gyro;
00090 
00091 /**
00092  * Auxiliary functions
00093  */
00094 float get_temperature(){
00095     float value;
00096     hum_temp->get_temperature(&value);
00097     printf("\n\rTemperature %f\n\r", value);
00098     
00099     printf("%3.3f", value);
00100     return value;
00101 }
00102 
00103 /* Print the orientation. */
00104 bool send_orientation() {
00105   uint8_t xl = 0;
00106   uint8_t xh = 0;
00107   uint8_t yl = 0;
00108   uint8_t yh = 0;
00109   uint8_t zl = 0;
00110   uint8_t zh = 0;
00111   
00112   acc_gyro->get_6d_orientation_xl(&xl);
00113   acc_gyro->get_6d_orientation_xh(&xh);
00114   acc_gyro->get_6d_orientation_yl(&yl);
00115   acc_gyro->get_6d_orientation_yh(&yh);
00116   acc_gyro->get_6d_orientation_zl(&zl);
00117   acc_gyro->get_6d_orientation_zh(&zh);
00118   
00119   if ( xl == 0 && yl == 0 && zl == 0 && xh == 0 && yh == 0 && zh == 1 ) {
00120     return true;
00121   }
00122   
00123   else {
00124     return false;
00125   }
00126 }
00127 
00128 /**
00129  * Entry point for application
00130  */
00131 int main(void)
00132 {
00133     
00134     // SENSOR INIT
00135     hum_temp->enable();
00136     acc_gyro->enable_x();
00137     /* Enable 6D Orientation. */
00138     acc_gyro->enable_6d_orientation();
00139     
00140     // setup tracing
00141     setup_trace();
00142 
00143     // stores the status of a call to LoRaWAN protocol
00144     lorawan_status_t retcode;
00145 
00146     // Initialize LoRaWAN stack
00147     if (lorawan.initialize(&ev_queue) != LORAWAN_STATUS_OK) {
00148         printf("\r\n LoRa initialization failed! \r\n");
00149         return -1;
00150     }
00151 
00152     printf("\r\n Mbed LoRaWANStack initialized \r\n");
00153 
00154     // prepare application callbacks
00155     callbacks.events = mbed::callback(lora_event_handler);
00156     lorawan.add_app_callbacks(&callbacks);
00157 
00158     // Set number of retries in case of CONFIRMED messages
00159     if (lorawan.set_confirmed_msg_retries(CONFIRMED_MSG_RETRY_COUNTER)
00160             != LORAWAN_STATUS_OK) {
00161         printf("\r\n set_confirmed_msg_retries failed! \r\n\r\n");
00162         return -1;
00163     }
00164 
00165     printf("\r\n CONFIRMED message retries : %d \r\n",
00166            CONFIRMED_MSG_RETRY_COUNTER);
00167 
00168     // Enable adaptive data rate
00169     if (lorawan.enable_adaptive_datarate() != LORAWAN_STATUS_OK) {
00170         printf("\r\n enable_adaptive_datarate failed! \r\n");
00171         return -1;
00172     }
00173 
00174     printf("\r\n Adaptive data  rate (ADR) - Enabled \r\n");
00175 
00176     retcode = lorawan.connect();
00177 
00178     if (retcode == LORAWAN_STATUS_OK ||
00179             retcode == LORAWAN_STATUS_CONNECT_IN_PROGRESS) {
00180     } else {
00181         printf("\r\n Connection error, code = %d \r\n", retcode);
00182         return -1;
00183     }
00184 
00185     printf("\r\n Connection - In Progress ...\r\n");
00186 
00187     // make your event queue dispatching events forever
00188     ev_queue.dispatch_forever();
00189 
00190     return 0;
00191 }
00192 
00193 /**
00194  * Sends a message to the Network Server
00195  */
00196 static void send_message()
00197 {
00198     uint16_t packet_len;
00199     int16_t retcode;
00200     float temperature = 0.0;
00201     int correct = 0;
00202     
00203     temperature = get_temperature();
00204     correct = send_orientation();
00205     
00206     packet_len = sprintf((char *) tx_buffer, "%3.3f-%d", temperature, correct);
00207     
00208     
00209     retcode = lorawan.send(MBED_CONF_LORA_APP_PORT, tx_buffer, packet_len,
00210                            MSG_UNCONFIRMED_FLAG);
00211 
00212     if (retcode < 0) {
00213         retcode == LORAWAN_STATUS_WOULD_BLOCK ? printf("send - WOULD BLOCK\r\n")
00214         : printf("\r\n send() - Error code %d \r\n", retcode);
00215 
00216         if (retcode == LORAWAN_STATUS_WOULD_BLOCK) {
00217             //retry in 3 seconds
00218             if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
00219                 ev_queue.call_in(3000, send_message);
00220             }
00221         }
00222         return;
00223     }
00224 
00225     printf("\r\n %d bytes scheduled for transmission \r\n", retcode);
00226     memset(tx_buffer, 0, sizeof(tx_buffer));
00227 }
00228 
00229 
00230 /**
00231  * Event handler
00232  */
00233 static void lora_event_handler(lorawan_event_t event)
00234 {
00235     switch (event) {
00236         case CONNECTED:
00237             printf("\r\n Connection - Successful \r\n");
00238             if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
00239                 send_message();
00240             } else {
00241                 ev_queue.call_every(TX_TIMER, send_message);
00242             }
00243 
00244             break;
00245         case DISCONNECTED:
00246             ev_queue.break_dispatch();
00247             printf("\r\n Disconnected Successfully \r\n");
00248             break;
00249         case TX_DONE:
00250             printf("\r\n Message Sent to Network Server \r\n");
00251             if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
00252                 send_message();
00253             }
00254             break;
00255         case TX_TIMEOUT:
00256         case TX_ERROR:
00257         case TX_CRYPTO_ERROR:
00258         case TX_SCHEDULING_ERROR:
00259             printf("\r\n Transmission Error - EventCode = %d \r\n", event);
00260             // try again
00261             if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
00262                 send_message();
00263             }
00264             break;
00265         case RX_DONE:
00266             printf("\r\n Received message from Network Server \r\n");
00267             break;
00268         case RX_TIMEOUT:
00269         case RX_ERROR:
00270             printf("\r\n Error in reception - Code = %d \r\n", event);
00271             break;
00272         case JOIN_FAILURE:
00273             printf("\r\n OTAA Failed - Check Keys \r\n");
00274             break;
00275         case UPLINK_REQUIRED:
00276             printf("\r\n Uplink required by NS \r\n");
00277             if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
00278                 send_message();
00279             }
00280             break;
00281         default:
00282             MBED_ASSERT("Unknown Event");
00283     }
00284 }
00285 
00286 // EOF