Final version of the exercise on the Things Network

Dependencies:   X_NUCLEO_IKS01A2

Committer:
marcozecchini
Date:
Thu Mar 14 19:44:07 2019 +0000
Revision:
51:9bb9a0374572
Parent:
47:b6d132f1079f
Final version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
marcozecchini 51:9bb9a0374572 1 /**
marcozecchini 51:9bb9a0374572 2 * Copyright (c) 2017, Arm Limited and affiliates.
marcozecchini 51:9bb9a0374572 3 * SPDX-License-Identifier: Apache-2.0
marcozecchini 51:9bb9a0374572 4 *
marcozecchini 51:9bb9a0374572 5 * Licensed under the Apache License, Version 2.0 (the "License");
marcozecchini 51:9bb9a0374572 6 * you may not use this file except in compliance with the License.
marcozecchini 51:9bb9a0374572 7 * You may obtain a copy of the License at
marcozecchini 51:9bb9a0374572 8 *
marcozecchini 51:9bb9a0374572 9 * http://www.apache.org/licenses/LICENSE-2.0
marcozecchini 51:9bb9a0374572 10 *
marcozecchini 51:9bb9a0374572 11 * Unless required by applicable law or agreed to in writing, software
marcozecchini 51:9bb9a0374572 12 * distributed under the License is distributed on an "AS IS" BASIS,
marcozecchini 51:9bb9a0374572 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
marcozecchini 51:9bb9a0374572 14 * See the License for the specific language governing permissions and
marcozecchini 51:9bb9a0374572 15 * limitations under the License.
marcozecchini 51:9bb9a0374572 16 */
marcozecchini 51:9bb9a0374572 17 #include <stdio.h>
marcozecchini 51:9bb9a0374572 18
marcozecchini 51:9bb9a0374572 19 #include "lorawan/LoRaWANInterface.h"
marcozecchini 51:9bb9a0374572 20 #include "lorawan/system/lorawan_data_structures.h"
marcozecchini 51:9bb9a0374572 21 #include "events/EventQueue.h"
marcozecchini 51:9bb9a0374572 22
marcozecchini 51:9bb9a0374572 23 // Application helpers
marcozecchini 51:9bb9a0374572 24 #include "trace_helper.h"
marcozecchini 51:9bb9a0374572 25 #include "lora_radio_helper.h"
marcozecchini 51:9bb9a0374572 26
marcozecchini 51:9bb9a0374572 27 // Extension Board library
marcozecchini 51:9bb9a0374572 28 #include "XNucleoIKS01A2.h"
marcozecchini 51:9bb9a0374572 29
marcozecchini 51:9bb9a0374572 30
marcozecchini 51:9bb9a0374572 31 using namespace events;
marcozecchini 51:9bb9a0374572 32
marcozecchini 51:9bb9a0374572 33 // Max payload size can be LORAMAC_PHY_MAXPAYLOAD.
marcozecchini 51:9bb9a0374572 34 // This example only communicates with much shorter messages (<30 bytes).
marcozecchini 51:9bb9a0374572 35 // If longer messages are used, these buffers must be changed accordingly.
marcozecchini 51:9bb9a0374572 36 uint8_t tx_buffer[60];
marcozecchini 51:9bb9a0374572 37 uint8_t rx_buffer[30];
marcozecchini 51:9bb9a0374572 38
marcozecchini 51:9bb9a0374572 39 /*
marcozecchini 51:9bb9a0374572 40 * Sets up an application dependent transmission timer in ms. Used only when Duty Cycling is off for testing
marcozecchini 51:9bb9a0374572 41 */
marcozecchini 51:9bb9a0374572 42 #define TX_TIMER 10000
marcozecchini 51:9bb9a0374572 43
marcozecchini 51:9bb9a0374572 44 /**
marcozecchini 51:9bb9a0374572 45 * Maximum number of events for the event queue.
marcozecchini 51:9bb9a0374572 46 * 10 is the safe number for the stack events, however, if application
marcozecchini 51:9bb9a0374572 47 * also uses the queue for whatever purposes, this number should be increased.
marcozecchini 51:9bb9a0374572 48 */
marcozecchini 51:9bb9a0374572 49 #define MAX_NUMBER_OF_EVENTS 10
marcozecchini 51:9bb9a0374572 50
marcozecchini 51:9bb9a0374572 51 /**
marcozecchini 51:9bb9a0374572 52 * Maximum number of retries for CONFIRMED messages before giving up
marcozecchini 51:9bb9a0374572 53 */
marcozecchini 51:9bb9a0374572 54 #define CONFIRMED_MSG_RETRY_COUNTER 3
marcozecchini 51:9bb9a0374572 55
marcozecchini 51:9bb9a0374572 56
marcozecchini 51:9bb9a0374572 57 /**
marcozecchini 51:9bb9a0374572 58 * This event queue is the global event queue for both the
marcozecchini 51:9bb9a0374572 59 * application and stack. To conserve memory, the stack is designed to run
marcozecchini 51:9bb9a0374572 60 * in the same thread as the application and the application is responsible for
marcozecchini 51:9bb9a0374572 61 * providing an event queue to the stack that will be used for ISR deferment as
marcozecchini 51:9bb9a0374572 62 * well as application information event queuing.
marcozecchini 51:9bb9a0374572 63 */
marcozecchini 51:9bb9a0374572 64 static EventQueue ev_queue(MAX_NUMBER_OF_EVENTS *EVENTS_EVENT_SIZE);
marcozecchini 51:9bb9a0374572 65
marcozecchini 51:9bb9a0374572 66 /**
marcozecchini 51:9bb9a0374572 67 * Event handler.
marcozecchini 51:9bb9a0374572 68 *
marcozecchini 51:9bb9a0374572 69 * This will be passed to the LoRaWAN stack to queue events for the
marcozecchini 51:9bb9a0374572 70 * application which in turn drive the application.
marcozecchini 51:9bb9a0374572 71 */
marcozecchini 51:9bb9a0374572 72 static void lora_event_handler(lorawan_event_t event);
marcozecchini 51:9bb9a0374572 73
marcozecchini 51:9bb9a0374572 74 /**
marcozecchini 51:9bb9a0374572 75 * Constructing Mbed LoRaWANInterface and passing it the radio object from lora_radio_helper.
marcozecchini 51:9bb9a0374572 76 */
marcozecchini 51:9bb9a0374572 77 static LoRaWANInterface lorawan(radio);
marcozecchini 51:9bb9a0374572 78
marcozecchini 51:9bb9a0374572 79 /**
marcozecchini 51:9bb9a0374572 80 * Application specific callbacks
marcozecchini 51:9bb9a0374572 81 */
marcozecchini 51:9bb9a0374572 82 static lorawan_app_callbacks_t callbacks;
marcozecchini 51:9bb9a0374572 83
marcozecchini 51:9bb9a0374572 84 /* Instantiate the expansion board */
marcozecchini 51:9bb9a0374572 85 XNucleoIKS01A2 *mems_expansion_board = XNucleoIKS01A2::instance(D14, D15, D4, D5);
marcozecchini 51:9bb9a0374572 86
marcozecchini 51:9bb9a0374572 87 /* Sensor initialization */
marcozecchini 51:9bb9a0374572 88 HTS221Sensor *hum_temp = mems_expansion_board->ht_sensor;
marcozecchini 51:9bb9a0374572 89 LSM6DSLSensor *acc_gyro = mems_expansion_board->acc_gyro;
marcozecchini 51:9bb9a0374572 90
marcozecchini 51:9bb9a0374572 91 /**
marcozecchini 51:9bb9a0374572 92 * Auxiliary functions
marcozecchini 51:9bb9a0374572 93 */
marcozecchini 51:9bb9a0374572 94 float get_temperature(){
marcozecchini 51:9bb9a0374572 95 float value;
marcozecchini 51:9bb9a0374572 96 hum_temp->get_temperature(&value);
marcozecchini 51:9bb9a0374572 97 printf("\n\rTemperature %f\n\r", value);
marcozecchini 51:9bb9a0374572 98
marcozecchini 51:9bb9a0374572 99 printf("%3.3f", value);
marcozecchini 51:9bb9a0374572 100 return value;
marcozecchini 51:9bb9a0374572 101 }
marcozecchini 51:9bb9a0374572 102
marcozecchini 51:9bb9a0374572 103 /* Print the orientation. */
marcozecchini 51:9bb9a0374572 104 bool send_orientation() {
marcozecchini 51:9bb9a0374572 105 uint8_t xl = 0;
marcozecchini 51:9bb9a0374572 106 uint8_t xh = 0;
marcozecchini 51:9bb9a0374572 107 uint8_t yl = 0;
marcozecchini 51:9bb9a0374572 108 uint8_t yh = 0;
marcozecchini 51:9bb9a0374572 109 uint8_t zl = 0;
marcozecchini 51:9bb9a0374572 110 uint8_t zh = 0;
marcozecchini 51:9bb9a0374572 111
marcozecchini 51:9bb9a0374572 112 acc_gyro->get_6d_orientation_xl(&xl);
marcozecchini 51:9bb9a0374572 113 acc_gyro->get_6d_orientation_xh(&xh);
marcozecchini 51:9bb9a0374572 114 acc_gyro->get_6d_orientation_yl(&yl);
marcozecchini 51:9bb9a0374572 115 acc_gyro->get_6d_orientation_yh(&yh);
marcozecchini 51:9bb9a0374572 116 acc_gyro->get_6d_orientation_zl(&zl);
marcozecchini 51:9bb9a0374572 117 acc_gyro->get_6d_orientation_zh(&zh);
marcozecchini 51:9bb9a0374572 118
marcozecchini 51:9bb9a0374572 119 if ( xl == 0 && yl == 0 && zl == 0 && xh == 0 && yh == 0 && zh == 1 ) {
marcozecchini 51:9bb9a0374572 120 return true;
marcozecchini 51:9bb9a0374572 121 }
marcozecchini 51:9bb9a0374572 122
marcozecchini 51:9bb9a0374572 123 else {
marcozecchini 51:9bb9a0374572 124 return false;
marcozecchini 51:9bb9a0374572 125 }
marcozecchini 51:9bb9a0374572 126 }
marcozecchini 51:9bb9a0374572 127
marcozecchini 51:9bb9a0374572 128 /**
marcozecchini 51:9bb9a0374572 129 * Entry point for application
marcozecchini 51:9bb9a0374572 130 */
marcozecchini 51:9bb9a0374572 131 int main(void)
marcozecchini 51:9bb9a0374572 132 {
marcozecchini 51:9bb9a0374572 133
marcozecchini 51:9bb9a0374572 134 // SENSOR INIT
marcozecchini 51:9bb9a0374572 135 hum_temp->enable();
marcozecchini 51:9bb9a0374572 136 acc_gyro->enable_x();
marcozecchini 51:9bb9a0374572 137 /* Enable 6D Orientation. */
marcozecchini 51:9bb9a0374572 138 acc_gyro->enable_6d_orientation();
marcozecchini 51:9bb9a0374572 139
marcozecchini 51:9bb9a0374572 140 // setup tracing
marcozecchini 51:9bb9a0374572 141 setup_trace();
marcozecchini 51:9bb9a0374572 142
marcozecchini 51:9bb9a0374572 143 // stores the status of a call to LoRaWAN protocol
marcozecchini 51:9bb9a0374572 144 lorawan_status_t retcode;
marcozecchini 51:9bb9a0374572 145
marcozecchini 51:9bb9a0374572 146 // Initialize LoRaWAN stack
marcozecchini 51:9bb9a0374572 147 if (lorawan.initialize(&ev_queue) != LORAWAN_STATUS_OK) {
marcozecchini 51:9bb9a0374572 148 printf("\r\n LoRa initialization failed! \r\n");
marcozecchini 51:9bb9a0374572 149 return -1;
marcozecchini 51:9bb9a0374572 150 }
marcozecchini 51:9bb9a0374572 151
marcozecchini 51:9bb9a0374572 152 printf("\r\n Mbed LoRaWANStack initialized \r\n");
marcozecchini 51:9bb9a0374572 153
marcozecchini 51:9bb9a0374572 154 // prepare application callbacks
marcozecchini 51:9bb9a0374572 155 callbacks.events = mbed::callback(lora_event_handler);
marcozecchini 51:9bb9a0374572 156 lorawan.add_app_callbacks(&callbacks);
marcozecchini 51:9bb9a0374572 157
marcozecchini 51:9bb9a0374572 158 // Set number of retries in case of CONFIRMED messages
marcozecchini 51:9bb9a0374572 159 if (lorawan.set_confirmed_msg_retries(CONFIRMED_MSG_RETRY_COUNTER)
marcozecchini 51:9bb9a0374572 160 != LORAWAN_STATUS_OK) {
marcozecchini 51:9bb9a0374572 161 printf("\r\n set_confirmed_msg_retries failed! \r\n\r\n");
marcozecchini 51:9bb9a0374572 162 return -1;
marcozecchini 51:9bb9a0374572 163 }
marcozecchini 51:9bb9a0374572 164
marcozecchini 51:9bb9a0374572 165 printf("\r\n CONFIRMED message retries : %d \r\n",
marcozecchini 51:9bb9a0374572 166 CONFIRMED_MSG_RETRY_COUNTER);
marcozecchini 51:9bb9a0374572 167
marcozecchini 51:9bb9a0374572 168 // Enable adaptive data rate
marcozecchini 51:9bb9a0374572 169 if (lorawan.enable_adaptive_datarate() != LORAWAN_STATUS_OK) {
marcozecchini 51:9bb9a0374572 170 printf("\r\n enable_adaptive_datarate failed! \r\n");
marcozecchini 51:9bb9a0374572 171 return -1;
marcozecchini 51:9bb9a0374572 172 }
marcozecchini 51:9bb9a0374572 173
marcozecchini 51:9bb9a0374572 174 printf("\r\n Adaptive data rate (ADR) - Enabled \r\n");
marcozecchini 51:9bb9a0374572 175
marcozecchini 51:9bb9a0374572 176 retcode = lorawan.connect();
marcozecchini 51:9bb9a0374572 177
marcozecchini 51:9bb9a0374572 178 if (retcode == LORAWAN_STATUS_OK ||
marcozecchini 51:9bb9a0374572 179 retcode == LORAWAN_STATUS_CONNECT_IN_PROGRESS) {
marcozecchini 51:9bb9a0374572 180 } else {
marcozecchini 51:9bb9a0374572 181 printf("\r\n Connection error, code = %d \r\n", retcode);
marcozecchini 51:9bb9a0374572 182 return -1;
marcozecchini 51:9bb9a0374572 183 }
marcozecchini 51:9bb9a0374572 184
marcozecchini 51:9bb9a0374572 185 printf("\r\n Connection - In Progress ...\r\n");
marcozecchini 51:9bb9a0374572 186
marcozecchini 51:9bb9a0374572 187 // make your event queue dispatching events forever
marcozecchini 51:9bb9a0374572 188 ev_queue.dispatch_forever();
marcozecchini 51:9bb9a0374572 189
marcozecchini 51:9bb9a0374572 190 return 0;
marcozecchini 51:9bb9a0374572 191 }
marcozecchini 51:9bb9a0374572 192
marcozecchini 51:9bb9a0374572 193 /**
marcozecchini 51:9bb9a0374572 194 * Sends a message to the Network Server
marcozecchini 51:9bb9a0374572 195 */
marcozecchini 51:9bb9a0374572 196 static void send_message()
marcozecchini 51:9bb9a0374572 197 {
marcozecchini 51:9bb9a0374572 198 uint16_t packet_len;
marcozecchini 51:9bb9a0374572 199 int16_t retcode;
marcozecchini 51:9bb9a0374572 200 float temperature = 0.0;
marcozecchini 51:9bb9a0374572 201 int correct = 0;
marcozecchini 51:9bb9a0374572 202
marcozecchini 51:9bb9a0374572 203 temperature = get_temperature();
marcozecchini 51:9bb9a0374572 204 correct = send_orientation();
marcozecchini 51:9bb9a0374572 205
marcozecchini 51:9bb9a0374572 206 packet_len = sprintf((char *) tx_buffer, "%3.3f-%d", temperature, correct);
marcozecchini 51:9bb9a0374572 207
marcozecchini 51:9bb9a0374572 208
marcozecchini 51:9bb9a0374572 209 retcode = lorawan.send(MBED_CONF_LORA_APP_PORT, tx_buffer, packet_len,
marcozecchini 51:9bb9a0374572 210 MSG_UNCONFIRMED_FLAG);
marcozecchini 51:9bb9a0374572 211
marcozecchini 51:9bb9a0374572 212 if (retcode < 0) {
marcozecchini 51:9bb9a0374572 213 retcode == LORAWAN_STATUS_WOULD_BLOCK ? printf("send - WOULD BLOCK\r\n")
marcozecchini 51:9bb9a0374572 214 : printf("\r\n send() - Error code %d \r\n", retcode);
marcozecchini 51:9bb9a0374572 215
marcozecchini 51:9bb9a0374572 216 if (retcode == LORAWAN_STATUS_WOULD_BLOCK) {
marcozecchini 51:9bb9a0374572 217 //retry in 3 seconds
marcozecchini 51:9bb9a0374572 218 if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
marcozecchini 51:9bb9a0374572 219 ev_queue.call_in(3000, send_message);
marcozecchini 51:9bb9a0374572 220 }
marcozecchini 51:9bb9a0374572 221 }
marcozecchini 51:9bb9a0374572 222 return;
marcozecchini 51:9bb9a0374572 223 }
marcozecchini 51:9bb9a0374572 224
marcozecchini 51:9bb9a0374572 225 printf("\r\n %d bytes scheduled for transmission \r\n", retcode);
marcozecchini 51:9bb9a0374572 226 memset(tx_buffer, 0, sizeof(tx_buffer));
marcozecchini 51:9bb9a0374572 227 }
marcozecchini 51:9bb9a0374572 228
marcozecchini 51:9bb9a0374572 229
marcozecchini 51:9bb9a0374572 230 /**
marcozecchini 51:9bb9a0374572 231 * Event handler
marcozecchini 51:9bb9a0374572 232 */
marcozecchini 51:9bb9a0374572 233 static void lora_event_handler(lorawan_event_t event)
marcozecchini 51:9bb9a0374572 234 {
marcozecchini 51:9bb9a0374572 235 switch (event) {
marcozecchini 51:9bb9a0374572 236 case CONNECTED:
marcozecchini 51:9bb9a0374572 237 printf("\r\n Connection - Successful \r\n");
marcozecchini 51:9bb9a0374572 238 if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
marcozecchini 51:9bb9a0374572 239 send_message();
marcozecchini 51:9bb9a0374572 240 } else {
marcozecchini 51:9bb9a0374572 241 ev_queue.call_every(TX_TIMER, send_message);
marcozecchini 51:9bb9a0374572 242 }
marcozecchini 51:9bb9a0374572 243
marcozecchini 51:9bb9a0374572 244 break;
marcozecchini 51:9bb9a0374572 245 case DISCONNECTED:
marcozecchini 51:9bb9a0374572 246 ev_queue.break_dispatch();
marcozecchini 51:9bb9a0374572 247 printf("\r\n Disconnected Successfully \r\n");
marcozecchini 51:9bb9a0374572 248 break;
marcozecchini 51:9bb9a0374572 249 case TX_DONE:
marcozecchini 51:9bb9a0374572 250 printf("\r\n Message Sent to Network Server \r\n");
marcozecchini 51:9bb9a0374572 251 if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
marcozecchini 51:9bb9a0374572 252 send_message();
marcozecchini 51:9bb9a0374572 253 }
marcozecchini 51:9bb9a0374572 254 break;
marcozecchini 51:9bb9a0374572 255 case TX_TIMEOUT:
marcozecchini 51:9bb9a0374572 256 case TX_ERROR:
marcozecchini 51:9bb9a0374572 257 case TX_CRYPTO_ERROR:
marcozecchini 51:9bb9a0374572 258 case TX_SCHEDULING_ERROR:
marcozecchini 51:9bb9a0374572 259 printf("\r\n Transmission Error - EventCode = %d \r\n", event);
marcozecchini 51:9bb9a0374572 260 // try again
marcozecchini 51:9bb9a0374572 261 if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
marcozecchini 51:9bb9a0374572 262 send_message();
marcozecchini 51:9bb9a0374572 263 }
marcozecchini 51:9bb9a0374572 264 break;
marcozecchini 51:9bb9a0374572 265 case RX_DONE:
marcozecchini 51:9bb9a0374572 266 printf("\r\n Received message from Network Server \r\n");
marcozecchini 51:9bb9a0374572 267 break;
marcozecchini 51:9bb9a0374572 268 case RX_TIMEOUT:
marcozecchini 51:9bb9a0374572 269 case RX_ERROR:
marcozecchini 51:9bb9a0374572 270 printf("\r\n Error in reception - Code = %d \r\n", event);
marcozecchini 51:9bb9a0374572 271 break;
marcozecchini 51:9bb9a0374572 272 case JOIN_FAILURE:
marcozecchini 51:9bb9a0374572 273 printf("\r\n OTAA Failed - Check Keys \r\n");
marcozecchini 51:9bb9a0374572 274 break;
marcozecchini 51:9bb9a0374572 275 case UPLINK_REQUIRED:
marcozecchini 51:9bb9a0374572 276 printf("\r\n Uplink required by NS \r\n");
marcozecchini 51:9bb9a0374572 277 if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
marcozecchini 51:9bb9a0374572 278 send_message();
marcozecchini 51:9bb9a0374572 279 }
marcozecchini 51:9bb9a0374572 280 break;
marcozecchini 51:9bb9a0374572 281 default:
marcozecchini 51:9bb9a0374572 282 MBED_ASSERT("Unknown Event");
marcozecchini 51:9bb9a0374572 283 }
marcozecchini 51:9bb9a0374572 284 }
marcozecchini 51:9bb9a0374572 285
marcozecchini 51:9bb9a0374572 286 // EOF