wayne roberts / Mbed OS mbed-os-lorawan-gps

Dependencies:   lib_gps

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 #include "mbed.h"
00024 // Application helpers
00025 #include "gps.h"
00026 #include "trace_helper.h"
00027 #include "lora_radio_helper.h"
00028 
00029 using namespace events;
00030 
00031 // Max payload size can be LORAMAC_PHY_MAXPAYLOAD.
00032 // This example only communicates with much shorter messages (<30 bytes).
00033 // If longer messages are used, these buffers must be changed accordingly.
00034 uint8_t tx_buffer[30];
00035 uint8_t rx_buffer[30];
00036 
00037 /*
00038  * Sets up an application dependent transmission timer in ms. Used only when Duty Cycling is off for testing
00039  */
00040 #define TX_TIMER                        10000
00041 
00042 /**
00043  * Maximum number of events for the event queue.
00044  * 10 is the safe number for the stack events, however, if application
00045  * also uses the queue for whatever purposes, this number should be increased.
00046  */
00047 #define MAX_NUMBER_OF_EVENTS            10
00048 
00049 /**
00050  * Maximum number of retries for CONFIRMED messages before giving up
00051  */
00052 #define CONFIRMED_MSG_RETRY_COUNTER     3
00053 
00054 /**
00055  * Dummy pin for dummy sensor
00056  */
00057 #define PC_9                            0
00058 
00059 /**
00060  * Dummy sensor class object
00061  */
00062 //DS1820  ds1820(PC_9);
00063 
00064 /**
00065 * This event queue is the global event queue for both the
00066 * application and stack. To conserve memory, the stack is designed to run
00067 * in the same thread as the application and the application is responsible for
00068 * providing an event queue to the stack that will be used for ISR deferment as
00069 * well as application information event queuing.
00070 */
00071 static EventQueue ev_queue(MAX_NUMBER_OF_EVENTS * EVENTS_EVENT_SIZE);
00072 
00073 /**
00074  * Event handler.
00075  *
00076  * This will be passed to the LoRaWAN stack to queue events for the
00077  * application which in turn drive the application.
00078  */
00079 static void lora_event_handler(lorawan_event_t event);
00080 
00081 /**
00082  * Constructing Mbed LoRaWANInterface and passing it down the radio object.
00083  */
00084 static LoRaWANInterface lorawan(radio);
00085 
00086 /**
00087  * Application specific callbacks
00088  */
00089 static lorawan_app_callbacks_t callbacks;
00090 
00091 #ifdef TARGET_MOTE_L152RC
00092     GPS gps(PB_6, PB_7, PB_11);    // on-board GPS pins (tx, rx, en)
00093 #elif defined(TARGET_FF_MORPHO)
00094     /*    https://www.sparkfun.com/products/13740   */
00095     #ifdef TARGET_DISCO_L072CZ_LRWAN1
00096         GPS gps(PA_9, PA_10, NC);
00097     #else
00098         GPS gps(PC_10, PC_11, NC);
00099     #endif
00100 #endif
00101 
00102 void gps_service()
00103 {
00104     //int alt;
00105 
00106     gps.service();
00107 
00108     //alt = atoi( gps.NmeaGpsData.NmeaAltitude );
00109     //printf("lat:%f lon:%f alt:%d\r\n", gps.Latitude, gps.Longitude, alt);
00110 }
00111 
00112 #ifdef TARGET_MOTE_L152RC
00113 typedef enum
00114 {
00115     BOARD_VERSION_NONE = 0,
00116     BOARD_VERSION_2,
00117     BOARD_VERSION_3,
00118 }BoardVersion_t;
00119 
00120 DigitalOut Pc7( PC_7 );
00121 DigitalIn Pc1( PC_1 );
00122 BoardVersion_t BoardGetVersion( void )
00123 {
00124     Pc7 = 1;
00125     char first = Pc1;
00126     Pc7 = 0;
00127 
00128     if( first && !Pc1 )
00129     {
00130         return BOARD_VERSION_2;
00131     }
00132     else
00133     {
00134         return BOARD_VERSION_3;
00135     }
00136 }
00137 AnalogIn *Battery;
00138 #endif /* TARGET_MOTE_L152RC */
00139 
00140 /**
00141  * Entry point for application
00142  */
00143 int main (void)
00144 {
00145     // setup tracing
00146     setup_trace();
00147 
00148     // stores the status of a call to LoRaWAN protocol
00149     lorawan_status_t retcode;
00150 
00151 #ifdef TARGET_MOTE_L152RC
00152     switch( BoardGetVersion( ) )
00153     {
00154         case BOARD_VERSION_2:
00155             Battery = new AnalogIn( PA_0 );
00156             gps.en_invert = true;
00157             printf("v2-mote\r\n");
00158             break;
00159         case BOARD_VERSION_3:
00160             Battery = new AnalogIn( PA_1 );
00161             gps.en_invert = false;
00162             printf("v3-mote\r\n");
00163             break;
00164         default:
00165             break;
00166     }
00167 #endif /* TARGET_MOTE_L152RC */
00168     gps.init();
00169     gps.enable(1);
00170     gps.m_uart.baud(9600);  // override platform serial baud rate
00171 
00172     // Initialize LoRaWAN stack
00173     if (lorawan.initialize(&ev_queue) != LORAWAN_STATUS_OK) {
00174         printf("\r\n LoRa initialization failed! \r\n");
00175         return -1;
00176     }
00177 
00178     printf("\r\n Mbed LoRaWANStack initialized \r\n");
00179 
00180     // prepare application callbacks
00181     callbacks.events = mbed::callback(lora_event_handler);
00182     lorawan.add_app_callbacks(&callbacks);
00183 
00184     // Set number of retries in case of CONFIRMED messages
00185     if (lorawan.set_confirmed_msg_retries(CONFIRMED_MSG_RETRY_COUNTER)
00186                                           != LORAWAN_STATUS_OK) {
00187         printf("\r\n set_confirmed_msg_retries failed! \r\n\r\n");
00188         return -1;
00189     }
00190 
00191     printf("\r\n CONFIRMED message retries : %d \r\n",
00192            CONFIRMED_MSG_RETRY_COUNTER);
00193 
00194     // Enable adaptive data rate
00195     if (lorawan.enable_adaptive_datarate() != LORAWAN_STATUS_OK) {
00196         printf("\r\n enable_adaptive_datarate failed! \r\n");
00197         return -1;
00198     }
00199 
00200     printf("\r\n Adaptive data  rate (ADR) - Enabled \r\n");
00201 
00202     retcode = lorawan.connect();
00203 
00204     if (retcode == LORAWAN_STATUS_OK ||
00205         retcode == LORAWAN_STATUS_CONNECT_IN_PROGRESS) {
00206     } else {
00207         printf("\r\n Connection error, code = %d \r\n", retcode);
00208         return -1;
00209     }
00210 
00211     printf("\r\n Connection - In Progress ...\r\n");
00212 
00213     // make your event queue dispatching events forever
00214     ev_queue.dispatch_forever();
00215 
00216     return 0;
00217 }
00218 
00219 #define LPP_DIGITAL_INPUT       0       // 1 byte
00220 #define LPP_DIGITAL_OUTPUT      1       // 1 byte
00221 #define LPP_ANALOG_INPUT        2       // 2 bytes, 0.01 signed
00222 #define LPP_ANALOG_OUTPUT       3       // 2 bytes, 0.01 signed
00223 #define LPP_LUMINOSITY          101     // 2 bytes, 1 lux unsigned
00224 #define LPP_PRESENCE            102     // 1 byte, 1
00225 #define LPP_TEMPERATURE         103     // 2 bytes, 0.1°C signed
00226 #define LPP_RELATIVE_HUMIDITY   104     // 1 byte, 0.5% unsigned
00227 #define LPP_ACCELEROMETER       113     // 2 bytes per axis, 0.001G
00228 #define LPP_BAROMETRIC_PRESSURE 115     // 2 bytes 0.1 hPa Unsigned
00229 #define LPP_GYROMETER           134     // 2 bytes per axis, 0.01 °/s
00230 #define LPP_GPS                 136     // 3 byte lon/lat 0.0001 °, 3 bytes alt 0.01m
00231 
00232 
00233 // Data ID + Data Type + Data Size
00234 #define LPP_DIGITAL_INPUT_SIZE       3
00235 #define LPP_DIGITAL_OUTPUT_SIZE      3
00236 #define LPP_ANALOG_INPUT_SIZE        4
00237 #define LPP_ANALOG_OUTPUT_SIZE       4
00238 #define LPP_LUMINOSITY_SIZE          4
00239 #define LPP_PRESENCE_SIZE            3
00240 #define LPP_TEMPERATURE_SIZE         4
00241 #define LPP_RELATIVE_HUMIDITY_SIZE   3
00242 #define LPP_ACCELEROMETER_SIZE       8
00243 #define LPP_BAROMETRIC_PRESSURE_SIZE 4
00244 #define LPP_GYROMETER_SIZE           8
00245 #define LPP_GPS_SIZE                 11
00246 
00247 #define CAYENNE_CH_GPS      5
00248 
00249 
00250 /**
00251  * Sends a message to the Network Server
00252  */
00253 static void send_message()
00254 {
00255     int32_t lat, lon, alt;
00256     uint16_t packet_len;
00257     int16_t retcode;
00258 
00259     lat = gps.Latitude * 10000;
00260     lon = gps.Longitude * 10000;
00261     alt = atoi(gps.NmeaGpsData.NmeaAltitude) * 100;
00262 
00263     packet_len = 0;
00264     tx_buffer[packet_len++] = CAYENNE_CH_GPS;
00265     tx_buffer[packet_len++] = LPP_GPS;
00266     tx_buffer[packet_len++] = lat >> 16;
00267     tx_buffer[packet_len++] = lat >> 8;
00268     tx_buffer[packet_len++] = lat;
00269     tx_buffer[packet_len++] = lon >> 16;
00270     tx_buffer[packet_len++] = lon >> 8;
00271     tx_buffer[packet_len++] = lon;
00272     tx_buffer[packet_len++] = alt >> 16;
00273     tx_buffer[packet_len++] = alt >> 8;
00274     tx_buffer[packet_len++] = alt;
00275 
00276     retcode = lorawan.send(MBED_CONF_LORA_APP_PORT, tx_buffer, packet_len,
00277                            MSG_CONFIRMED_FLAG);
00278 
00279     if (retcode < 0) {
00280         retcode == LORAWAN_STATUS_WOULD_BLOCK ? printf("send - WOULD BLOCK\r\n")
00281                 : printf("\r\n send() - Error code %d \r\n", retcode);
00282 
00283         if (retcode == LORAWAN_STATUS_WOULD_BLOCK) {
00284             //retry in 3 seconds
00285             if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
00286                 ev_queue.call_in(3000, send_message);
00287             }
00288         }
00289         return;
00290     }
00291     for (alt = 0; alt < packet_len; alt++) {
00292         printf("%02x", tx_buffer[alt]);
00293     }
00294 
00295     alt = atoi( gps.NmeaGpsData.NmeaAltitude );
00296     printf("\r\n %d bytes scheduled for tx\tlat:%f lon:%f alt:%d\r\n", retcode, gps.Latitude, gps.Longitude, (int)alt);
00297     memset(tx_buffer, 0, sizeof(tx_buffer));
00298 }
00299 
00300 /**
00301  * Receive a message from the Network Server
00302  */
00303 static void receive_message()
00304 {
00305     int16_t retcode;
00306     retcode = lorawan.receive(MBED_CONF_LORA_APP_PORT, rx_buffer,
00307                               sizeof(rx_buffer),
00308                               MSG_CONFIRMED_FLAG|MSG_UNCONFIRMED_FLAG);
00309 
00310     if (retcode < 0) {
00311         printf("\r\n receive() - Error code %d \r\n", retcode);
00312         return;
00313     }
00314 
00315     printf(" Data:");
00316 
00317     for (uint8_t i = 0; i < retcode; i++) {
00318         printf("%x", rx_buffer[i]);
00319     }
00320 
00321     printf("\r\n Data Length: %d\r\n", retcode);
00322 
00323     memset(rx_buffer, 0, sizeof(rx_buffer));
00324 }
00325 
00326 /**
00327  * Event handler
00328  */
00329 static void lora_event_handler(lorawan_event_t event)
00330 {
00331 
00332     switch (event) {
00333         case CONNECTED:
00334             printf("\r\n Connection - Successful ");
00335             ev_queue.call_every(1000, gps_service);
00336             if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
00337                 printf("DUTY_ON\r\n");
00338                 send_message();
00339             } else {
00340                 printf("(duty off)\r\n");
00341                 ev_queue.call_every(TX_TIMER, send_message);
00342             }
00343 
00344             break;
00345         case DISCONNECTED:
00346             ev_queue.break_dispatch();
00347             printf("\r\n Disconnected Successfully \r\n");
00348             break;
00349         case TX_DONE:
00350             printf("\r\n Message Sent to Network Server \r\n");
00351             /*if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
00352                 send_message();
00353             }*/
00354             break;
00355         case TX_TIMEOUT:
00356             printf("\r\nTX_TIMEOUT\r\n");
00357             // try again
00358             /*if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
00359                 send_message();
00360             }*/
00361             break;
00362         case TX_ERROR:
00363             // no ack was received after enough retries
00364             printf("\r\nTX_ERROR\r\n");
00365             // try again
00366             /*if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
00367                 send_message();
00368             }*/
00369             break;
00370         case TX_CRYPTO_ERROR:
00371             printf("\r\nTX_CRYPTO_ERROR\r\n");
00372             // try again
00373             /*if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
00374                 send_message();
00375             }*/
00376             break;
00377         case TX_SCHEDULING_ERROR:
00378             printf("\r\nTX_SCHEDULING_ERROR\r\n");
00379             // try again
00380             /*if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
00381                 send_message();
00382             }*/
00383             break;
00384         case RX_DONE:
00385             printf("\r\n Received message from Network Server \r\n");
00386             receive_message();
00387             break;
00388         case RX_TIMEOUT:
00389         case RX_ERROR:
00390             printf("\r\n Error in reception - Code = %d \r\n", event);
00391             break;
00392         case JOIN_FAILURE:
00393             printf("\r\n OTAA Failed - Check Keys \r\n");
00394             break;
00395         case UPLINK_REQUIRED:
00396             printf("\r\n Uplink required by NS \r\n");
00397             if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
00398                 send_message();
00399             }
00400             break;
00401         default:
00402             MBED_ASSERT("Unknown Event");
00403     }
00404 }
00405 
00406 // EOF