LoRaWAN Class A node example based on IBM LoRa MAC in C (LMiC) implementation
Dependencies: LMiC SX1276Lib mbed
main.cpp
00001 /* 00002 / _____) _ | | 00003 ( (____ _____ ____ _| |_ _____ ____| |__ 00004 \____ \| ___ | (_ _) ___ |/ ___) _ \ 00005 _____) ) ____| | | || |_| ____( (___| | | | 00006 (______/|_____)_|_|_| \__)_____)\____)_| |_| 00007 (C)2015 Semtech 00008 00009 Description: MBED LoRaWAN example application 00010 00011 License: Revised BSD License, see LICENSE.TXT file include in the project 00012 00013 Maintainer: Miguel Luis and Gregory Cristian 00014 */ 00015 #include "mbed.h" 00016 00017 #include "lmic.h" 00018 #include "debug.h" 00019 00020 /*! 00021 * When set to 1 the application uses the Over-the-Air activation procedure 00022 * When set to 0 the application uses the Personalization activation procedure 00023 */ 00024 #define OVER_THE_AIR_ACTIVATION 0 00025 00026 #if( OVER_THE_AIR_ACTIVATION == 0 ) 00027 00028 /*! 00029 * Defines the network ID when using personalization activation procedure 00030 */ 00031 #define LORAWAN_NET_ID ( uint32_t )0x00000000 00032 00033 /*! 00034 * Defines the device address when using personalization activation procedure 00035 */ 00036 #define LORAWAN_DEV_ADDR ( uint32_t )0x12345678 00037 00038 #endif 00039 00040 /*! 00041 * Defines the application data transmission duty cycle 00042 */ 00043 #define APP_TX_DUTYCYCLE 5000 // 5 [s] value in ms 00044 #define APP_TX_DUTYCYCLE_RND 1000 // 1 [s] value in ms 00045 00046 /*! 00047 * LoRaWAN Adaptative Data Rate 00048 */ 00049 #define LORAWAN_ADR_ON 1 00050 00051 /*! 00052 * LoRaWAN confirmed messages 00053 */ 00054 #define LORAWAN_CONFIRMED_MSG_ON 1 00055 00056 /*! 00057 * LoRaWAN application port 00058 */ 00059 #define LORAWAN_APP_PORT 15 00060 00061 /*! 00062 * User application data buffer size 00063 */ 00064 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 ) 00065 #define LORAWAN_APP_DATA_SIZE 6 00066 00067 #else 00068 #define LORAWAN_APP_DATA_SIZE 1 00069 00070 #endif 00071 00072 ////////////////////////////////////////////////// 00073 // CONFIGURATION (FOR APPLICATION CALLBACKS BELOW) 00074 ////////////////////////////////////////////////// 00075 00076 // application router ID (LSBF) 00077 static const uint8_t AppEui[8] = 00078 { 00079 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 00080 }; 00081 00082 // unique device ID (LSBF) 00083 static const u1_t DevEui[8] = 00084 { 00085 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF 00086 }; 00087 00088 // device-specific AES key (derived from device EUI) 00089 static const uint8_t DevKey[16] = 00090 { 00091 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 00092 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C 00093 }; 00094 00095 #if( OVER_THE_AIR_ACTIVATION == 0 ) 00096 // network session key 00097 static uint8_t NwkSKey[] = 00098 { 00099 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 00100 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C 00101 }; 00102 00103 // application session key 00104 static uint8_t ArtSKey[] = 00105 { 00106 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 00107 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C 00108 }; 00109 00110 #endif 00111 00112 // LEDs and Frame jobs 00113 osjob_t rxLedJob; 00114 osjob_t txLedJob; 00115 osjob_t sendFrameJob; 00116 00117 // LED state 00118 static bool AppLedStateOn = false; 00119 00120 ////////////////////////////////////////////////// 00121 // Utility functions 00122 ////////////////////////////////////////////////// 00123 /*! 00124 * \brief Computes a random number between min and max 00125 * 00126 * \param [IN] min range minimum value 00127 * \param [IN] max range maximum value 00128 * \retval random random value in range min..max 00129 */ 00130 int32_t randr( int32_t min, int32_t max ) 00131 { 00132 return ( int32_t )rand( ) % ( max - min + 1 ) + min; 00133 } 00134 00135 ////////////////////////////////////////////////// 00136 // APPLICATION CALLBACKS 00137 ////////////////////////////////////////////////// 00138 00139 // provide application router ID (8 bytes, LSBF) 00140 void os_getArtEui( uint8_t *buf ) 00141 { 00142 memcpy( buf, AppEui, 8 ); 00143 } 00144 00145 // provide device ID (8 bytes, LSBF) 00146 void os_getDevEui( uint8_t *buf ) 00147 { 00148 memcpy( buf, DevEui, 8 ); 00149 } 00150 00151 // provide device key (16 bytes) 00152 void os_getDevKey( uint8_t *buf ) 00153 { 00154 memcpy( buf, DevKey, 16 ); 00155 } 00156 00157 ////////////////////////////////////////////////// 00158 // MAIN - INITIALIZATION AND STARTUP 00159 ////////////////////////////////////////////////// 00160 00161 static void onRxLed( osjob_t* j ) 00162 { 00163 debug_val("LED2 = ", 0 ); 00164 } 00165 00166 static void onTxLed( osjob_t* j ) 00167 { 00168 debug_val("LED1 = ", 0 ); 00169 } 00170 00171 static void prepareTxFrame( void ) 00172 { 00173 LMIC.frame[0] = AppLedStateOn; 00174 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 ) 00175 LMIC.frame[1] = LMIC.seqnoDn >> 8; 00176 LMIC.frame[2] = LMIC.seqnoDn; 00177 LMIC.frame[3] = LMIC.rssi >> 8; 00178 LMIC.frame[4] = LMIC.rssi; 00179 LMIC.frame[5] = LMIC.snr; 00180 #endif 00181 } 00182 00183 void processRxFrame( void ) 00184 { 00185 switch( LMIC.frame[LMIC.dataBeg - 1] ) // Check Rx port number 00186 { 00187 case 1: // The application LED can be controlled on port 1 or 2 00188 case 2: 00189 if( LMIC.dataLen == 1 ) 00190 { 00191 AppLedStateOn = LMIC.frame[LMIC.dataBeg] & 0x01; 00192 debug_val( "LED3 = ", AppLedStateOn ); 00193 } 00194 break; 00195 default: 00196 break; 00197 } 00198 } 00199 00200 static void onSendFrame( osjob_t* j ) 00201 { 00202 prepareTxFrame( ); 00203 LMIC_setTxData2( LORAWAN_APP_PORT, LMIC.frame, LORAWAN_APP_DATA_SIZE, LORAWAN_CONFIRMED_MSG_ON ); 00204 00205 // Blink Tx LED 00206 debug_val( "LED1 = ", 1 ); 00207 os_setTimedCallback( &txLedJob, os_getTime( ) + ms2osticks( 25 ), onTxLed ); 00208 } 00209 00210 // Initialization job 00211 static void onInit( osjob_t* j ) 00212 { 00213 // reset MAC state 00214 LMIC_reset( ); 00215 LMIC_setAdrMode( LORAWAN_ADR_ON ); 00216 #if defined(CFG_eu868) 00217 LMIC_setDrTxpow( DR_SF12, 14 ); 00218 #elif defined(CFG_us915) 00219 LMIC_setDrTxpow( DR_SF10, 14 ); 00220 #endif 00221 00222 // start joining 00223 #if( OVER_THE_AIR_ACTIVATION != 0 ) 00224 LMIC_startJoining( ); 00225 #else 00226 LMIC_setSession( LORAWAN_NET_ID, LORAWAN_DEV_ADDR, NwkSKey, ArtSKey ); 00227 onSendFrame( NULL ); 00228 #endif 00229 // init done - onEvent( ) callback will be invoked... 00230 } 00231 00232 int main( void ) 00233 { 00234 osjob_t initjob; 00235 00236 // initialize runtime env 00237 os_init( ); 00238 // setup initial job 00239 os_setCallback( &initjob, onInit ); 00240 // execute scheduled jobs and events 00241 os_runloop( ); 00242 // (not reached) 00243 } 00244 00245 ////////////////////////////////////////////////// 00246 // LMIC EVENT CALLBACK 00247 ////////////////////////////////////////////////// 00248 void onEvent( ev_t ev ) 00249 { 00250 bool txOn = false; 00251 debug_event( ev ); 00252 00253 switch( ev ) 00254 { 00255 // network joined, session established 00256 case EV_JOINED: 00257 debug_val( "Net ID = ", LMIC.netid ); 00258 txOn = true; 00259 break; 00260 // scheduled data sent (optionally data received) 00261 case EV_TXCOMPLETE: 00262 debug_val( "Datarate = ", LMIC.datarate ); 00263 // Check if we have a downlink on either Rx1 or Rx2 windows 00264 if( ( LMIC.txrxFlags & ( TXRX_DNW1 | TXRX_DNW2 ) ) != 0 ) 00265 { 00266 debug_val( "LED2 = ", 1 ); 00267 os_setTimedCallback( &rxLedJob, os_getTime( ) + ms2osticks( 25 ), onRxLed ); 00268 00269 if( LMIC.dataLen != 0 ) 00270 { // data received in rx slot after tx 00271 debug_buf( LMIC.frame + LMIC.dataBeg, LMIC.dataLen ); 00272 processRxFrame( ); 00273 } 00274 } 00275 txOn = true; 00276 break; 00277 default: 00278 break; 00279 } 00280 if( txOn == true ) 00281 { 00282 //Sends frame every APP_TX_DUTYCYCLE +/- APP_TX_DUTYCYCLE_RND random time (if not duty cycle limited) 00283 os_setTimedCallback( &sendFrameJob, 00284 os_getTime( ) + ms2osticks( APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ) ), 00285 onSendFrame ); 00286 00287 ////Sends frame as soon as possible (duty cylce limitations) 00288 //onSendFrame( NULL ); 00289 } 00290 }
Generated on Sat Jul 16 2022 07:20:36 by 1.7.2