NuMaker mbed OS v5.x LoRaWAN

Committer:
cyliang
Date:
Tue Sep 01 21:06:51 2020 +0800
Revision:
0:895bbd4e6398
Mbed OS v5.x LoRaWAN example for NuMaker platforms based on https://github.com/ARMmbed/mbed-os-example-lorawan.git

Who changed what in which revision?

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