Future Electronics / Mbed OS sequana-lorawan-lab2
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  * Copyright (c) 2019, Future Electronics.
00004  * SPDX-License-Identifier: Apache-2.0
00005  *
00006  * Licensed under the Apache License, Version 2.0 (the "License");
00007  * you may not use this file except in compliance with the License.
00008  * You may obtain a copy of the License at
00009  *
00010  *     http://www.apache.org/licenses/LICENSE-2.0
00011  *
00012  * Unless required by applicable law or agreed to in writing, software
00013  * distributed under the License is distributed on an "AS IS" BASIS,
00014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  * See the License for the specific language governing permissions and
00016  * limitations under the License.
00017  */
00018 #include <stdio.h>
00019 
00020 #include "lorawan/LoRaWANInterface.h"
00021 #include "lorawan/system/lorawan_data_structures.h"
00022 #include "events/EventQueue.h"
00023 #include "psoc6_utils.h"
00024 #include "mbed.h"
00025 
00026 // Application helpers
00027 #include "trace_helper.h"
00028 #include "lora_radio_helper.h"
00029 
00030 #include "BD2808.h"
00031 
00032 
00033 using namespace events;
00034 using namespace mbed;
00035 
00036 
00037 // Max payload size can be LORAMAC_PHY_MAXPAYLOAD.
00038 // This example only communicates with much shorter messages (<30 bytes).
00039 // If longer messages are used, these buffers must be changed accordingly.
00040 uint8_t tx_buffer[30];
00041 uint8_t rx_buffer[30];
00042 
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            20
00050 
00051 /**
00052  * Maximum number of retries for CONFIRMED messages before giving up
00053  */
00054 #define CONFIRMED_MSG_RETRY_COUNTER     3
00055 
00056 /**
00057 * This event queue is the global event queue for both the
00058 * application and stack. To conserve memory, the stack is designed to run
00059 * in the same thread as the application and the application is responsible for
00060 * providing an event queue to the stack that will be used for ISR deferment as
00061 * well as application information event queuing.
00062 */
00063 static EventQueue ev_queue(MAX_NUMBER_OF_EVENTS *EVENTS_EVENT_SIZE);
00064 
00065 /**
00066  * Event handler.
00067  *
00068  * This will be passed to the LoRaWAN stack to queue events for the
00069  * application which in turn drive the application.
00070  */
00071 static void lora_event_handler(lorawan_event_t event);
00072 
00073 /**
00074  * Constructing Mbed LoRaWANInterface and passing it the radio object from lora_radio_helper.
00075  */
00076 static LoRaWANInterface lorawan(radio);
00077 
00078 /**
00079  * Application specific callbacks
00080  */
00081 static lorawan_app_callbacks_t callbacks;
00082 
00083 
00084  typedef enum {
00085      DUMMY_MESSAGE,
00086      SWITCH_MESSAGE
00087  } message_type_t;
00088 
00089 /**
00090  * Button switch processing handler.
00091  */
00092  static void button_handler(void);
00093 
00094  static void send_message(message_type_t type);
00095 
00096 
00097 
00098 Timer g_timer;
00099 DigitalOut led(LED1);
00100 DigitalIn  button1(BUTTON1);
00101 BD2808 leds;
00102 
00103 bool frame_send = false;
00104 bool is_connected = false;
00105 bool tx_in_progress = false;
00106 uint8_t power_on = 0;
00107 uint8_t msg_id = 0;
00108 uint32_t delay_counter = 0;
00109 
00110 static uint32_t const INTER_FRAME_DELAY = 30;
00111 
00112 //static const uint8_t target_device_eui[] = MBED_CONF_APP_TARGET_DEVICE_EUI;
00113 static const uint8_t target_device_eui[] = { 0x00, 0xa0, 0x50, 0xff, 0xfe, 0x81, 0x27, 0x95 };
00114 
00115 /**
00116  * Helper routine to set RGB LEDs to specific color.
00117  */
00118 static void leds_set(uint8_t red, uint8_t green, uint8_t blue)
00119 {
00120     for (int i = 0; i < 8; ++i) {
00121         leds.set_color(i, BGR24_color_t(blue, green, red));
00122     }
00123     leds.refresh();
00124 }
00125 
00126 
00127 static void timer_one_sec(void)
00128 {
00129     if (is_connected) {
00130         if (!tx_in_progress) {
00131             led = 1;
00132             ThisThread::sleep_for(40);
00133             led = 0;
00134             --delay_counter;
00135             if (delay_counter == 0) {
00136                 delay_counter = INTER_FRAME_DELAY;
00137                 send_message(DUMMY_MESSAGE);
00138             }
00139         }
00140     } else {
00141     }
00142 }
00143 
00144 
00145 /**
00146  * Entry point for application
00147  */
00148 int main(void)
00149 {
00150     static uint8_t mac_address[6];
00151     static uint8_t device_eui[8] = {0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00};
00152     static const uint8_t application_eui[] = MBED_CONF_LORA_APPLICATION_EUI;
00153     static const uint8_t application_key[] = MBED_CONF_LORA_APPLICATION_KEY;
00154     static lorawan_connect_t connect_params = {
00155         .connect_type = LORAWAN_CONNECTION_OTAA,
00156     };
00157 
00158     leds.set_dma_usage(DMA_USAGE_ALWAYS);
00159 
00160     // setup tracing
00161     setup_trace();
00162 
00163     // stores the status of a call to LoRaWAN protocol
00164     lorawan_status_t retcode;
00165 
00166     // Create unique, hardware-dependent EUI.
00167     cy_get_bd_mac_address(mac_address);
00168     // MAC address is in reverse sequence.
00169     for (int i = 0; i < 3; ++i) {
00170         device_eui[i] = mac_address[5 - i];
00171         device_eui[i + 5] = mac_address[2 - i];
00172     }
00173     printf("\r\nDevice EUI is %02X", device_eui[0]);
00174     for (int i = 1; i < 8; ++i) {
00175         printf(":%02X", device_eui[i]);
00176     }
00177     printf("  [ ");
00178     for (int i = 0; i < 8; ++i) {
00179         printf("%02x", device_eui[i]);
00180     }
00181     printf(" ]\r\n");
00182 
00183     // Initialize LoRaWAN stack
00184     if (lorawan.initialize(&ev_queue) != LORAWAN_STATUS_OK) {
00185         printf("\r\n LoRa initialization failed! \r\n");
00186         return -1;
00187     }
00188 
00189     printf("\r\n Mbed LoRaWANStack initialized \r\n");
00190 
00191     // prepare application callbacks
00192     callbacks.events = mbed::callback(lora_event_handler);
00193     lorawan.add_app_callbacks(&callbacks);
00194 
00195     // Set number of retries in case of CONFIRMED messages
00196     if (lorawan.set_confirmed_msg_retries(CONFIRMED_MSG_RETRY_COUNTER)
00197             != LORAWAN_STATUS_OK) {
00198         printf("\r\n set_confirmed_msg_retries failed! \r\n\r\n");
00199         return -1;
00200     }
00201 
00202     printf("\r\n CONFIRMED message retries : %d \r\n",
00203            CONFIRMED_MSG_RETRY_COUNTER);
00204 
00205     // Enable adaptive data rate
00206     if (lorawan.enable_adaptive_datarate() != LORAWAN_STATUS_OK) {
00207         printf("\r\n enable_adaptive_datarate failed! \r\n");
00208         return -1;
00209     }
00210 
00211     printf("\r\n Adaptive data  rate (ADR) - Enabled \r\n");
00212 
00213     // Specify class C
00214     if (lorawan.set_device_class(CLASS_C) != LORAWAN_STATUS_OK) {
00215         printf("\r\n setting class C failed! \r\n");
00216         return -1;
00217     }
00218 
00219     printf("\r\n Class C - Enabled \r\n");
00220 
00221     connect_params.connection_u.otaa.dev_eui = device_eui;
00222     connect_params.connection_u.otaa.app_eui = const_cast<uint8_t *>(application_eui);
00223     connect_params.connection_u.otaa.app_key = const_cast<uint8_t *>(application_key);
00224     connect_params.connection_u.otaa.nb_trials = MBED_CONF_LORA_NB_TRIALS;
00225 
00226     g_timer.start();
00227 
00228     retcode = lorawan.connect(connect_params);
00229 
00230     if (retcode == LORAWAN_STATUS_OK ||
00231             retcode == LORAWAN_STATUS_CONNECT_IN_PROGRESS) {
00232     } else {
00233         printf("\r\n Connection error, code = %d \r\n", retcode);
00234         return -1;
00235     }
00236 
00237     printf("\r\n Connection - In Progress ...\r\n");
00238 
00239     // Start button handler; will check button switch every 100ms.
00240     ev_queue.call_every(100, button_handler);
00241 
00242     ev_queue.call_every(1000, timer_one_sec);
00243 
00244     // make your event queue dispatching events forever
00245     ev_queue.dispatch_forever();
00246 
00247     return 0;
00248 }
00249 
00250 
00251 /**
00252  * Sends a message to the Network Server
00253  */
00254 static void send_message(message_type_t type)
00255 {
00256     uint16_t packet_len;
00257     int16_t retcode;
00258     uint8_t port = MBED_CONF_LORA_APP_PORT;
00259 
00260     printf("\r\n[%8u] Sending message (%d) \r\n", g_timer.read_ms(), msg_id);
00261 
00262     switch (type) {
00263         case SWITCH_MESSAGE:
00264             memcpy(tx_buffer, target_device_eui, 8);
00265             for (int i = 8; i < 11; ++i) {
00266                 tx_buffer[8] = power_on? 0xf0 : 0x00;
00267             }
00268             packet_len = 11;
00269             break;
00270 
00271         case DUMMY_MESSAGE:
00272             tx_buffer[1] = msg_id;
00273             packet_len = 1;
00274             port += 1;
00275     }
00276 
00277     led = 1;
00278     tx_in_progress = true;
00279 
00280     retcode = lorawan.send(port, tx_buffer, packet_len, MSG_UNCONFIRMED_FLAG);
00281 
00282     if (retcode < 0) {
00283         retcode == LORAWAN_STATUS_WOULD_BLOCK ? printf("send - WOULD BLOCK\r\n")
00284         : printf("\r\n send() - Error code %d \r\n", retcode);
00285 
00286         if (retcode == LORAWAN_STATUS_WOULD_BLOCK) {
00287             lorawan.cancel_sending();
00288             led = 0;
00289             //retry in 3 seconds
00290             if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
00291                 ev_queue.call_in(3000, send_message, type);
00292             }
00293         }
00294         return;
00295     }
00296 
00297     frame_send = true;
00298     printf("\r\n[%8u] %d bytes scheduled for transmission \r\n", g_timer.read_ms(), retcode);
00299     memset(tx_buffer, 0, sizeof(tx_buffer));
00300 }
00301 
00302 /**
00303  * Receive a message from the Network Server
00304  */
00305 static void receive_message()
00306 {
00307     uint8_t port;
00308     int flags;
00309     int16_t retcode = lorawan.receive(rx_buffer, sizeof(rx_buffer), port, flags);
00310 
00311     if (retcode < 0) {
00312         printf("\r\n receive() - Error code %d \r\n", retcode);
00313         return;
00314     }
00315 
00316     printf("[%8u] RX Data on port %u (%d bytes): ", g_timer.read_ms(), port, retcode);
00317     for (uint8_t i = 0; i < retcode; i++) {
00318         printf("%02x ", rx_buffer[i]);
00319     }
00320     // Expecting exactly 3 bytes: red, green + blue color value.
00321     // Other messages are ignored.
00322     if ((retcode == 3) && (port == MBED_CONF_LORA_APP_PORT)) {
00323         leds_set(rx_buffer[0], rx_buffer[1], rx_buffer[2]);
00324     } else {
00325         printf(" - ignored (%d)", MBED_CONF_LORA_APP_PORT);
00326     }
00327     printf("\r\n");
00328 
00329     memset(rx_buffer, 0, sizeof(rx_buffer));
00330 }
00331 
00332 /**
00333  * Detects and processes button events.
00334  */
00335 static void button_handler(void)
00336 {
00337     static uint8_t prev_state = 1;
00338     static uint8_t stable_state = 1;
00339     static uint8_t count = 2;
00340 
00341     uint8_t curr_state = button1;
00342 
00343     if (curr_state != prev_state) {
00344         count = 2;
00345     } else {
00346         if (count > 0) {
00347             --count;
00348         } else {
00349             if ((stable_state == 0) && (curr_state != 0)) {
00350                 // we react on release of the button
00351                 if (is_connected) {
00352                     power_on = power_on? 0 : 1;
00353                     send_message(SWITCH_MESSAGE);
00354                 }
00355             }
00356             stable_state = curr_state;
00357         }
00358     }
00359     prev_state = curr_state;
00360 }
00361 
00362 
00363 /**
00364  * Event handler
00365  */
00366 static void lora_event_handler(lorawan_event_t event)
00367 {
00368     switch (event) {
00369         case CONNECTED:
00370             printf("\r\n[%8u] Connection - Successful \r\n", g_timer.read_ms());
00371             is_connected = true;
00372             msg_id = 0;
00373             delay_counter = INTER_FRAME_DELAY;
00374             send_message(DUMMY_MESSAGE);
00375             break;
00376         case DISCONNECTED:
00377             led = 0;
00378             frame_send = false;
00379             ev_queue.break_dispatch();
00380             printf("\r\n[%8u] Disconnected Successfully \r\n", g_timer.read_ms());
00381             break;
00382         case TX_DONE:
00383             led = 0;
00384             tx_in_progress = false;
00385             if (frame_send) {
00386                 frame_send = false;
00387                 delay_counter = INTER_FRAME_DELAY;
00388                 ++msg_id;
00389                 printf("\r\n[%8u] Message Sent to Network Server \r\n", g_timer.read_ms());
00390             } else {
00391             //    printf("\r\n[%8u] Duplicate TX_DONE !!! \r\n", g_timer.read_ms());
00392             }
00393             break;
00394         case TX_TIMEOUT:
00395         case TX_ERROR:
00396         case TX_CRYPTO_ERROR:
00397         case TX_SCHEDULING_ERROR:
00398             led = 0;
00399             frame_send = false;
00400             tx_in_progress = false;
00401             delay_counter = INTER_FRAME_DELAY;
00402             printf("\r\n[%8u] Transmission Error - EventCode = %d \r\n", g_timer.read_ms(), event);
00403             break;
00404         case RX_DONE:
00405             printf("\r\n[%8u] Received message from Network Server \r\n", g_timer.read_ms());
00406             receive_message();
00407             break;
00408         case RX_TIMEOUT:
00409         case RX_ERROR:
00410             printf("\r\n[%8u] Error in reception - Code = %d \r\n", g_timer.read_ms(), event);
00411             break;
00412         case JOIN_FAILURE:
00413             printf("\r\n OTAA Failed - Check Keys \r\n");
00414             break;
00415         case UPLINK_REQUIRED:
00416             printf("\r\n[%8u] Uplink required by NS \r\n", g_timer.read_ms());
00417             break;
00418         default:
00419             MBED_ASSERT("Unknown Event");
00420     }
00421 }
00422 
00423 // EOF