Adapted to LoRa Semtech + Nucleo
Dependencies: LMiC SX1276Lib cantcoap lwip mbed-rtos mbed
Fork of LoRaWAN-lmic-app by
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 00016 #include <cstdio> 00017 #include <string> 00018 #include <cassert> 00019 00020 #include "mbed.h" 00021 //#include "Node.h" 00022 #include "cantcoap.h" 00023 00024 #include "lmic.h" 00025 #include "debug.h" 00026 00027 const std::string REGISTRATION_SEGMENT ="/rd"; 00028 const std::string ENDPOINT_SEGMENT = "?ep="; 00029 const std::string LIFETIME ="<="; 00030 const std::string BINDING ="&b="; 00031 00032 const std::string REGISTRATION_OPEN = "<"; 00033 const std::string REGISTRATION_CLOSE = ">"; 00034 const std::string REGISTRATION_SEPARATOR ="/"; 00035 00036 int _node_Id=0; 00037 00038 const std::string endPoint_Name = "loraDevice"; 00039 const int lifeTime = 300; 00040 const std::string binding = "U"; 00041 00042 unsigned char * _payload; 00043 long _payload_size; 00044 00045 /*! 00046 * When set to 1 the application uses the Over-the-Air activation procedure 00047 * When set to 0 the application uses the Personalization activation procedure 00048 */ 00049 #define OVER_THE_AIR_ACTIVATION 0 00050 00051 #if( OVER_THE_AIR_ACTIVATION == 0 ) 00052 00053 /*! 00054 * Defines the network ID when using personalization activation procedure 00055 */ 00056 #define LORAWAN_NET_ID ( uint32_t )0x00000000 00057 00058 /*! 00059 * Defines the device address when using personalization activation procedure 00060 */ 00061 #define LORAWAN_DEV_ADDR ( uint32_t )0x12345678 00062 //#define LORAWAN_DEV_ADDR ( uint32_t )0x12341111 00063 00064 #endif 00065 00066 /*! 00067 * Defines the application data transmission duty cycle 00068 */ 00069 #define APP_TX_DUTYCYCLE 5000 // 5 [s] value in ms 00070 #define APP_TX_DUTYCYCLE_RND 1000 // 1 [s] value in ms 00071 00072 /*! 00073 * LoRaWAN Adaptative Data Rate 00074 */ 00075 #define LORAWAN_ADR_ON 1 00076 00077 /*! 00078 * LoRaWAN confirmed messages 00079 */ 00080 #define LORAWAN_CONFIRMED_MSG_ON 1 00081 00082 /*! 00083 * LoRaWAN application port 00084 */ 00085 #define LORAWAN_APP_PORT 15 00086 00087 /*! 00088 * User application data buffer size 00089 */ 00090 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 ) 00091 #define LORAWAN_APP_DATA_SIZE 6 00092 00093 #else 00094 #define LORAWAN_APP_DATA_SIZE 1 00095 00096 #endif 00097 00098 #define UINT16_MAX (65535U) 00099 #define UINT64_MAX (18446744073709551615ULL) 00100 00101 //Node lwm2mNode("LR-test0");; 00102 unsigned int LoRaWAN_data_size = 0; 00103 00104 std::string to_string( int x ) { 00105 int length = snprintf( NULL, 0, "%d", x ); 00106 assert( length >= 0 ); 00107 char* buf = new char[length + 1]; 00108 snprintf( buf, length + 1, "%d", x ); 00109 std::string str( buf ); 00110 delete[] buf; 00111 return str; 00112 } 00113 unsigned char * get_Registration_Payload(long *payload_size){ 00114 00115 string registration_Payload =""; 00116 00117 string s=""; 00118 00119 s.append(REGISTRATION_OPEN); 00120 s.append(REGISTRATION_SEPARATOR); 00121 s.append("3/0/0"); 00122 s.append(REGISTRATION_CLOSE); 00123 s.append(","); 00124 s.append(REGISTRATION_OPEN); 00125 s.append(REGISTRATION_SEPARATOR); 00126 s.append("3/0/1"); 00127 s.append(REGISTRATION_CLOSE); 00128 s.append(","); 00129 s.append(REGISTRATION_OPEN); 00130 s.append(REGISTRATION_SEPARATOR); 00131 s.append("3/0/2"); 00132 s.append(REGISTRATION_CLOSE); 00133 00134 registration_Payload.append(s); 00135 00136 unsigned char *c = new unsigned char[registration_Payload.size()+1]; 00137 copy(registration_Payload.begin(),registration_Payload.end(),c); 00138 c[registration_Payload.size()]='\0'; 00139 *payload_size=registration_Payload.size(); 00140 00141 return c; 00142 00143 } 00144 uint8_t * get_Token(int * size){ 00145 srand(time(0)+_node_Id); 00146 long test=0; 00147 bool exist=false; 00148 00149 do{ 00150 test=(rand() % UINT64_MAX); 00151 00152 }while (exist==true); 00153 uint8_t ones = 0xFF; 00154 *size=1; 00155 for (int i=0; i<8; ++i) { 00156 if ( (test>>8*i & ones) =='\0' || i==8) { 00157 *size=i; 00158 break; 00159 } 00160 } 00161 uint8_t * token =new uint8_t[*size]; 00162 for (int i=0; i<*size; ++i){ 00163 token[*size-1-i]=test>>8*i & ones; 00164 } 00165 return token; 00166 } 00167 00168 uint16_t get_Message_ID(){ 00169 srand(time(0)+_node_Id); 00170 int test=0; 00171 bool exist=false; 00172 do{ 00173 00174 exist=false; 00175 test=(rand() % UINT16_MAX); 00176 00177 }while (exist==true); 00178 00179 00180 return (uint16_t) test; 00181 00182 } 00183 00184 char * get_Registration_Query(){ 00185 00186 string buffer; 00187 buffer.append(REGISTRATION_SEGMENT); 00188 buffer.append(ENDPOINT_SEGMENT); 00189 buffer.append(endPoint_Name); 00190 buffer.append(LIFETIME); 00191 buffer.append(to_string(lifeTime)); 00192 buffer.append(BINDING); 00193 buffer.append(binding); 00194 00195 char *c = new char[buffer.size()+1]; 00196 copy(buffer.begin(),buffer.end(),c); 00197 c[buffer.size()]='\0'; 00198 return c; 00199 00200 00201 } 00202 00203 ////////////////////////////////////////////////// 00204 // CONFIGURATION (FOR APPLICATION CALLBACKS BELOW) 00205 ////////////////////////////////////////////////// 00206 00207 // application router ID (LSBF) 00208 static const uint8_t AppEui[8] = 00209 { 00210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 00211 // 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 00212 }; 00213 00214 // unique device ID (LSBF) 00215 static const u1_t DevEui[8] = 00216 { 00217 // 0x00, 0x00, 0x00, 0x00, 0x08, 0x06, 0x02, 0x48 00218 00219 0x30, 0x74, 0x73, 0x65, 0x74, 0x2D, 0x52, 0x4C // 4c522d7465737430 = "LR-test0" 00220 // 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x99, 0xF7 00221 00222 00223 // 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF 00224 // 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x099, 0xF7 00225 }; 00226 00227 // device-specific AES key (derived from device EUI) 00228 static const uint8_t DevKey[16] = 00229 { 00230 // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00231 // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 00232 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 00233 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C 00234 }; 00235 00236 #if( OVER_THE_AIR_ACTIVATION == 0 ) 00237 // network session key 00238 static uint8_t NwkSKey[] = 00239 { 00240 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 00241 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C 00242 // 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3D 00243 }; 00244 00245 // application session key 00246 static uint8_t ArtSKey[] = 00247 { 00248 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 00249 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C 00250 // 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3D 00251 }; 00252 00253 #endif 00254 00255 // LEDs and Frame jobs 00256 osjob_t rxLedJob; 00257 osjob_t txLedJob; 00258 osjob_t sendFrameJob; 00259 00260 // LED state 00261 static bool AppLedStateOn = false; 00262 00263 ////////////////////////////////////////////////// 00264 // Utility functions 00265 ////////////////////////////////////////////////// 00266 /*! 00267 * \brief Computes a random number between min and max 00268 * 00269 * \param [IN] min range minimum value 00270 * \param [IN] max range maximum value 00271 * \retval random random value in range min..max 00272 */ 00273 int32_t randr( int32_t min, int32_t max ) 00274 { 00275 return ( int32_t )rand( ) % ( max - min + 1 ) + min; 00276 } 00277 00278 ////////////////////////////////////////////////// 00279 // APPLICATION CALLBACKS 00280 ////////////////////////////////////////////////// 00281 00282 // provide application router ID (8 bytes, LSBF) 00283 void os_getArtEui( uint8_t *buf ) 00284 { 00285 memcpy( buf, AppEui, 8 ); 00286 } 00287 00288 // provide device ID (8 bytes, LSBF) 00289 void os_getDevEui( uint8_t *buf ) 00290 { 00291 memcpy( buf, DevEui, 8 ); 00292 } 00293 00294 // provide device key (16 bytes) 00295 void os_getDevKey( uint8_t *buf ) 00296 { 00297 memcpy( buf, DevKey, 16 ); 00298 } 00299 00300 ////////////////////////////////////////////////// 00301 // MAIN - INITIALIZATION AND STARTUP 00302 ////////////////////////////////////////////////// 00303 00304 static void onRxLed( osjob_t* j ) 00305 { 00306 debug_val("LED2 = ", 0 ); 00307 } 00308 00309 static void onTxLed( osjob_t* j ) 00310 { 00311 debug_val("LED1 = ", 0 ); 00312 } 00313 00314 static void prepareTxCoapFrame( void ) 00315 { 00316 // Create Registration PDU : 00317 00318 CoapPDU *pdu = new CoapPDU(); 00319 00320 pdu->setCode(CoapPDU::COAP_POST); 00321 pdu->setType(CoapPDU::COAP_CONFIRMABLE); 00322 int size; 00323 uint8_t * token = get_Token(&size); 00324 pdu->setToken(token,size); 00325 pdu->setMessageID(get_Message_ID()); 00326 pdu->setURI(get_Registration_Query()); 00327 00328 _payload=get_Registration_Payload(&_payload_size); 00329 pdu->setPayload(_payload, (int) _payload_size); 00330 int PDUlength = pdu->getPDULength(); 00331 00332 // strncpy((char*) LMIC.frame, (const char*)pdu->getPDUPointer(), PDUlength); 00333 memcpy(LMIC.frame, pdu->getPDUPointer(), PDUlength * sizeof(uint8_t)); 00334 00335 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 ) 00336 LMIC.frame[PDUlength] = LMIC.seqnoDn >> 8; 00337 LMIC.frame[PDUlength+1] = LMIC.seqnoDn; 00338 LMIC.frame[PDUlength+2] = LMIC.rssi >> 8; 00339 LMIC.frame[PDUlength+3] = LMIC.rssi; 00340 LMIC.frame[PDUlength+4] = LMIC.snr; 00341 #endif 00342 debug_str("Frame to be sent: "); 00343 debug_buf(LMIC.frame, PDUlength + 5); 00344 00345 LoRaWAN_data_size = PDUlength + 5; 00346 } 00347 00348 static void prepareTxFrame( void ) 00349 { 00350 LMIC.frame[0] = AppLedStateOn; 00351 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 ) 00352 LMIC.frame[1] = LMIC.seqnoDn >> 8; 00353 LMIC.frame[2] = LMIC.seqnoDn; 00354 LMIC.frame[3] = LMIC.rssi >> 8; 00355 LMIC.frame[4] = LMIC.rssi; 00356 LMIC.frame[5] = LMIC.snr; 00357 #endif 00358 debug_str("Frame to be sent: "); 00359 debug_buf(LMIC.frame, LORAWAN_APP_DATA_SIZE); 00360 00361 LoRaWAN_data_size = LORAWAN_APP_DATA_SIZE; 00362 } 00363 00364 void processRxFrame( void ) 00365 { 00366 debug_str("Data: "); 00367 debug_buf( LMIC.frame + LMIC.dataBeg, LMIC.dataLen ); 00368 00369 switch( LMIC.frame[LMIC.dataBeg - 1] ) // Check Rx port number 00370 { 00371 case 0: 00372 // debug_str("Port 0!!!\r\n"); 00373 // debug_val("Data Len: ", LMIC.dataLen); 00374 00375 case 1: // The application LED can be controlled on port 1 or 2 00376 case 2: 00377 if( LMIC.dataLen == 1 ) 00378 { 00379 debug_str("Data received on port 2: "); 00380 debug_hex(LMIC.frame[LMIC.dataBeg]); 00381 debug_str("\r\n"); 00382 AppLedStateOn = LMIC.frame[LMIC.dataBeg] & 0x01; 00383 debug_val( "LED3 = ", AppLedStateOn ); 00384 } 00385 break; 00386 default: 00387 break; 00388 } 00389 } 00390 00391 static void onSendFrame( osjob_t* j ) 00392 { 00393 //prepareTxFrame( ); 00394 prepareTxCoapFrame(); 00395 00396 LMIC_setTxData2( LORAWAN_APP_PORT, LMIC.frame, LoRaWAN_data_size, LORAWAN_CONFIRMED_MSG_ON ); 00397 00398 // Blink Tx LED 00399 debug_val( "LED1 = ", 1 ); 00400 os_setTimedCallback( &txLedJob, os_getTime( ) + ms2osticks( 25 ), onTxLed ); 00401 } 00402 00403 // Initialization job 00404 static void onInit( osjob_t* j ) 00405 { 00406 // reset MAC state 00407 LMIC_reset( ); 00408 LMIC_setAdrMode( LORAWAN_ADR_ON ); 00409 LMIC_setDrTxpow( DR_SF12, 14 ); 00410 00411 // start joining 00412 #if( OVER_THE_AIR_ACTIVATION != 0 ) 00413 LMIC_startJoining( ); 00414 #else 00415 LMIC_setSession( LORAWAN_NET_ID, LORAWAN_DEV_ADDR, NwkSKey, ArtSKey ); 00416 onSendFrame( NULL ); 00417 #endif 00418 // init done - onEvent( ) callback will be invoked... 00419 } 00420 00421 int main( void ) 00422 { 00423 debug_init(); 00424 osjob_t initjob; 00425 00426 // initialize runtime env 00427 os_init( ); 00428 // setup initial job 00429 os_setCallback( &initjob, onInit ); 00430 // execute scheduled jobs and events 00431 os_runloop( ); 00432 // (not reached) 00433 } 00434 00435 ////////////////////////////////////////////////// 00436 // LMIC EVENT CALLBACK 00437 ////////////////////////////////////////////////// 00438 void onEvent( ev_t ev ) 00439 { 00440 bool txOn = false; 00441 debug_event( ev ); 00442 00443 switch( ev ) 00444 { 00445 // network joined, session established 00446 case EV_JOINED: 00447 debug_val( "Net ID = ", LMIC.netid ); 00448 txOn = true; 00449 break; 00450 // scheduled data sent (optionally data received) 00451 case EV_TXCOMPLETE: 00452 debug_val( "Datarate = ", LMIC.datarate ); 00453 // Check if we have a downlink on either Rx1 or Rx2 windows 00454 if( ( LMIC.txrxFlags & ( TXRX_DNW1 | TXRX_DNW2 ) ) != 0 ) 00455 { 00456 debug_val( "LED2 = ", 1 ); 00457 os_setTimedCallback( &rxLedJob, os_getTime( ) + ms2osticks( 25 ), onRxLed ); 00458 00459 if( LMIC.dataLen != 0 ) 00460 { // data received in rx slot after tx 00461 //debug_buf( LMIC.frame + LMIC.dataBeg, LMIC.dataLen ); 00462 processRxFrame( ); 00463 } 00464 } 00465 txOn = true; 00466 break; 00467 default: 00468 break; 00469 } 00470 if( txOn == true ) 00471 { 00472 //Sends frame every APP_TX_DUTYCYCLE +/- APP_TX_DUTYCYCLE_RND random time (if not duty cycle limited) 00473 os_setTimedCallback( &sendFrameJob, 00474 os_getTime( ) + ms2osticks( APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ) ), 00475 onSendFrame ); 00476 00477 ////Sends frame as soon as possible (duty cylce limitations) 00478 //onSendFrame( NULL ); 00479 } 00480 }
Generated on Tue Jul 12 2022 21:41:46 by 1.7.2