Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: LMiC-10secs SX1276Lib X_NUCLEO_IKS01A1 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 #include "x_nucleo_iks01a1.h" 00024 #include "rtos.h" 00025 00026 #include "lmic.h" 00027 #include "debug.h" 00028 00029 /* Instantiate the expansion board */ 00030 static X_NUCLEO_IKS01A1 *mems_expansion_board = X_NUCLEO_IKS01A1::Instance(D14, D15); 00031 00032 /* Retrieve the composing elements of the expansion board */ 00033 static GyroSensor *gyroscope = mems_expansion_board->GetGyroscope(); 00034 static MotionSensor *accelerometer = mems_expansion_board->GetAccelerometer(); 00035 static MagneticSensor *magnetometer = mems_expansion_board->magnetometer; 00036 static HumiditySensor *humidity_sensor = mems_expansion_board->ht_sensor; 00037 static PressureSensor *pressure_sensor = mems_expansion_board->pt_sensor; 00038 static TempSensor *temp_sensor1 = mems_expansion_board->ht_sensor; 00039 static TempSensor *temp_sensor2 = mems_expansion_board->pt_sensor; 00040 00041 uint8_t id; 00042 float value1, value2; 00043 char buffer1[32], buffer2[32], buffer3[32]; 00044 int32_t axes[3]; 00045 00046 static bool temp_sent = false; 00047 static bool hum_sent = false; 00048 static bool press_sent = false; 00049 static bool gyro_sent = false; 00050 static bool motion_sent = false; 00051 static bool magn_sent = false; 00052 00053 const std::string REGISTRATION_SEGMENT ="/rd"; 00054 const std::string ENDPOINT_SEGMENT = "?ep="; 00055 const std::string LIFETIME ="<="; 00056 const std::string BINDING ="&b="; 00057 00058 const std::string REGISTRATION_OPEN = "<"; 00059 const std::string REGISTRATION_CLOSE = ">"; 00060 const std::string REGISTRATION_SEPARATOR ="/"; 00061 00062 int _node_Id=0; 00063 00064 const std::string endPoint_Name = "loraDevice"; 00065 const int lifeTime = 300; 00066 const std::string binding = "U"; 00067 00068 unsigned char * _payload; 00069 long _payload_size; 00070 00071 /*! 00072 * When set to 1 the application uses the Over-the-Air activation procedure 00073 * When set to 0 the application uses the Personalization activation procedure 00074 */ 00075 #define OVER_THE_AIR_ACTIVATION 0 00076 00077 #if( OVER_THE_AIR_ACTIVATION == 0 ) 00078 00079 /*! 00080 * Defines the network ID when using personalization activation procedure 00081 */ 00082 #define LORAWAN_NET_ID ( uint32_t )0x00000000 00083 00084 /*! 00085 * Defines the device address when using personalization activation procedure 00086 */ 00087 //To be changed when switching from one to another 00088 #define LORAWAN_DEV_ADDR ( uint32_t )0x12342222 00089 00090 #endif 00091 00092 /*! 00093 * Defines the application data transmission duty cycle 00094 */ 00095 //#define APP_TX_DUTYCYCLE 5000 // 5 [s] value in ms 00096 //PANY 00097 #define APP_TX_DUTYCYCLE 1000 // 1 [s] value in ms 00098 //PANY 00099 #define APP_TX_DUTYCYCLE_RND 1000 // 1 [s] value in ms 00100 00101 /*! 00102 * LoRaWAN Adaptative Data Rate 00103 */ 00104 #define LORAWAN_ADR_ON 1 00105 00106 /*! 00107 * LoRaWAN confirmed messages 00108 */ 00109 #define LORAWAN_CONFIRMED_MSG_ON 0 00110 00111 /*! 00112 * LoRaWAN application port 00113 */ 00114 #define LORAWAN_APP_PORT 15 00115 00116 /*! 00117 * User application data buffer size 00118 */ 00119 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 ) 00120 #define LORAWAN_APP_DATA_SIZE 6 00121 00122 #else 00123 #define LORAWAN_APP_DATA_SIZE 1 00124 00125 #endif 00126 00127 #define UINT16_MAX (65535U) 00128 #define UINT64_MAX (18446744073709551615ULL) 00129 00130 //Node lwm2mNode("LR-test0");; 00131 unsigned int LoRaWAN_data_size = 0; 00132 00133 /* Helper function for printing floats & doubles */ 00134 static char *printDouble(char* str, double v, int decimalDigits=2) 00135 { 00136 int i = 1; 00137 int intPart, fractPart; 00138 int len; 00139 char *ptr; 00140 00141 /* prepare decimal digits multiplicator */ 00142 for (;decimalDigits!=0; i*=10, decimalDigits--); 00143 00144 /* calculate integer & fractinal parts */ 00145 intPart = (int)v; 00146 fractPart = (int)((v-(double)(int)v)*i); 00147 00148 /* fill in integer part */ 00149 sprintf(str, "%i.", intPart); 00150 00151 /* prepare fill in of fractional part */ 00152 len = strlen(str); 00153 ptr = &str[len]; 00154 00155 /* fill in leading fractional zeros */ 00156 for (i/=10;i>1; i/=10, ptr++) { 00157 if(fractPart >= i) break; 00158 *ptr = '0'; 00159 } 00160 00161 /* fill in (rest of) fractional part */ 00162 sprintf(ptr, "%i", fractPart); 00163 00164 return str; 00165 } 00166 00167 /* Helper function for printing integers */ 00168 static char *printInt(char* str, int v) 00169 { 00170 /* fill in integer part */ 00171 sprintf(str, "%i", v); 00172 00173 return str; 00174 } 00175 00176 /* Thread for calling libNsdl exec function (cleanup, resendings etc..) */ 00177 /* Node updates accelerometer every 60 seconds. Notification sending is done here. */ 00178 static void exec_call_thread(void const *args) 00179 { 00180 uint8_t id; 00181 float value1, value2; 00182 char buffer1[32], buffer2[32]; 00183 int32_t axes[3]; 00184 00185 debug_str("--- Starting new run ---\r\n"); 00186 00187 humidity_sensor->ReadID(&id); 00188 debug_str("HTS221 humidity & temperature = "); 00189 debug_uint(id); 00190 debug_str("\r\n"); 00191 pressure_sensor->ReadID(&id); 00192 debug_str("LPS25H pressure & temperature = "); 00193 debug_uint(id); 00194 debug_str("\r\n"); 00195 magnetometer->ReadID(&id); 00196 debug_str("LIS3MDL magnetometer = "); 00197 debug_uint(id); 00198 debug_str("\r\n"); 00199 gyroscope->ReadID(&id); 00200 debug_str("LSM6DS0 accelerometer & gyroscope = "); 00201 debug_uint(id); 00202 debug_str("\r\n"); 00203 00204 wait(3); 00205 00206 while(1) { 00207 debug_str("\r\n"); 00208 00209 temp_sensor1->GetTemperature(&value1); 00210 humidity_sensor->GetHumidity(&value2); 00211 debug_str("HTS221: [temp] "); 00212 debug_str(printDouble(buffer1, value1)); 00213 debug_str("°C, [hum] "); 00214 debug_str(printDouble(buffer2, value2)); 00215 debug_str("%\r\n"); 00216 //pc.printf("HTS221: [temp] %7s°C, [hum] %s%%\r\n", printDouble(buffer1, value1), printDouble(buffer2, value2)); 00217 00218 temp_sensor2->GetFahrenheit(&value1); 00219 pressure_sensor->GetPressure(&value2); 00220 debug_str("LPS25H: [temp] "); 00221 debug_str(printDouble(buffer1, value1)); 00222 debug_str("°F, [press] "); 00223 debug_str(printDouble(buffer2, value2)); 00224 debug_str("mbar\r\n"); 00225 //pc.printf("LPS25H: [temp] %7s°F, [press] %smbar\r\n", printDouble(buffer1, value1), printDouble(buffer2, value2)); 00226 00227 debug_str("---\r\n"); 00228 00229 magnetometer->Get_M_Axes(axes); 00230 debug_str("LIS3MDL [mag/mgauss]: "); 00231 debug_uint(axes[0]); 00232 debug_str(", "); 00233 debug_uint(axes[1]); 00234 debug_str(", "); 00235 debug_uint(axes[2]); 00236 debug_str("\r\n"); 00237 //pc.printf("LIS3MDL [mag/mgauss]: %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]); 00238 00239 accelerometer->Get_X_Axes(axes); 00240 debug_str("LSM6DS0 [acc/mg]: "); 00241 debug_uint(axes[0]); 00242 debug_str(", "); 00243 debug_uint(axes[1]); 00244 debug_str(", "); 00245 debug_uint(axes[2]); 00246 debug_str("\r\n"); 00247 //pc.printf("LSM6DS0 [acc/mg]: %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]); 00248 00249 gyroscope->Get_G_Axes(axes); 00250 debug_str("LSM6DS0 [gyro/mdps]: "); 00251 debug_uint(axes[0]); 00252 debug_str(", "); 00253 debug_uint(axes[1]); 00254 debug_str(", "); 00255 debug_uint(axes[2]); 00256 debug_str("\r\n"); 00257 //pc.printf("LSM6DS0 [gyro/mdps]: %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]); 00258 00259 wait(1.5); 00260 } 00261 } 00262 00263 std::string to_string( int x ) { 00264 int length = snprintf( NULL, 0, "%d", x ); 00265 assert( length >= 0 ); 00266 char* buf = new char[length + 1]; 00267 snprintf( buf, length + 1, "%d", x ); 00268 std::string str( buf ); 00269 delete[] buf; 00270 return str; 00271 } 00272 00273 unsigned char * get_Registration_Payload(long *payload_size){ 00274 00275 string registration_Payload =""; 00276 00277 string s=""; 00278 00279 s.append(REGISTRATION_OPEN); 00280 s.append(REGISTRATION_SEPARATOR); 00281 s.append("3/0/0"); 00282 s.append(REGISTRATION_CLOSE); 00283 s.append(","); 00284 s.append(REGISTRATION_OPEN); 00285 s.append(REGISTRATION_SEPARATOR); 00286 s.append("3/0/1"); 00287 s.append(REGISTRATION_CLOSE); 00288 s.append(","); 00289 s.append(REGISTRATION_OPEN); 00290 s.append(REGISTRATION_SEPARATOR); 00291 s.append("3/0/2"); 00292 s.append(REGISTRATION_CLOSE); 00293 00294 registration_Payload.append(s); 00295 00296 unsigned char *c = new unsigned char[registration_Payload.size()+1]; 00297 copy(registration_Payload.begin(),registration_Payload.end(),c); 00298 c[registration_Payload.size()]='\0'; 00299 *payload_size=registration_Payload.size(); 00300 00301 return c; 00302 00303 } 00304 uint8_t * get_Token(int * size){ 00305 srand(time(0)+_node_Id); 00306 long test=0; 00307 bool exist=false; 00308 00309 do{ 00310 test=(rand() % UINT64_MAX); 00311 00312 }while (exist==true); 00313 uint8_t ones = 0xFF; 00314 *size=1; 00315 for (int i=0; i<8; ++i) { 00316 if ( (test>>8*i & ones) =='\0' || i==8) { 00317 *size=i; 00318 break; 00319 } 00320 } 00321 uint8_t * token =new uint8_t[*size]; 00322 for (int i=0; i<*size; ++i){ 00323 token[*size-1-i]=test>>8*i & ones; 00324 } 00325 return token; 00326 } 00327 00328 uint16_t get_Message_ID(){ 00329 srand(time(0)+_node_Id); 00330 int test=0; 00331 bool exist=false; 00332 do{ 00333 00334 exist=false; 00335 test=(rand() % UINT16_MAX); 00336 00337 }while (exist==true); 00338 00339 00340 return (uint16_t) test; 00341 00342 } 00343 00344 char * get_Registration_Query(){ 00345 00346 string buffer; 00347 buffer.append(REGISTRATION_SEGMENT); 00348 buffer.append(ENDPOINT_SEGMENT); 00349 buffer.append(endPoint_Name); 00350 buffer.append(LIFETIME); 00351 buffer.append(to_string(lifeTime)); 00352 buffer.append(BINDING); 00353 buffer.append(binding); 00354 00355 char *c = new char[buffer.size()+1]; 00356 copy(buffer.begin(),buffer.end(),c); 00357 c[buffer.size()]='\0'; 00358 return c; 00359 00360 00361 } 00362 00363 ////////////////////////////////////////////////// 00364 // CONFIGURATION (FOR APPLICATION CALLBACKS BELOW) 00365 ////////////////////////////////////////////////// 00366 00367 // application router ID (LSBF) 00368 //To be changed when switching from one to another 00369 static const uint8_t AppEui[8] = 00370 { 00371 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 00372 // 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 00373 }; 00374 00375 // unique device ID (LSBF) 00376 //To be changed when switching from one to another 00377 static const u1_t DevEui[8] = 00378 { 00379 0x33, 0x74, 0x73, 0x65, 0x74, 0x2D, 0x52, 0x4C // 4c522d7465737433 = "LR-test3" 00380 }; 00381 00382 // device-specific AES key (derived from device EUI) 00383 static const uint8_t DevKey[16] = 00384 { 00385 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 00386 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3E 00387 }; 00388 00389 #if( OVER_THE_AIR_ACTIVATION == 0 ) 00390 // network session key 00391 //To be changed when switching from one to another 00392 static uint8_t NwkSKey[] = 00393 { 00394 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 00395 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3E 00396 }; 00397 00398 // application session key 00399 //To be changed when switching from one to another 00400 static uint8_t ArtSKey[] = 00401 { 00402 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 00403 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3E 00404 }; 00405 00406 #endif 00407 00408 // LEDs and Frame jobs 00409 osjob_t rxLedJob; 00410 osjob_t txLedJob; 00411 osjob_t sendFrameJob; 00412 00413 // LED state 00414 static bool AppLedStateOn = false; 00415 00416 ////////////////////////////////////////////////// 00417 // Utility functions 00418 ////////////////////////////////////////////////// 00419 /*! 00420 * \brief Computes a random number between min and max 00421 * 00422 * \param [IN] min range minimum value 00423 * \param [IN] max range maximum value 00424 * \retval random random value in range min..max 00425 */ 00426 int32_t randr( int32_t min, int32_t max ) 00427 { 00428 return ( int32_t )rand( ) % ( max - min + 1 ) + min; 00429 } 00430 00431 ////////////////////////////////////////////////// 00432 // APPLICATION CALLBACKS 00433 ////////////////////////////////////////////////// 00434 00435 // provide application router ID (8 bytes, LSBF) 00436 void os_getArtEui( uint8_t *buf ) 00437 { 00438 memcpy( buf, AppEui, 8 ); 00439 } 00440 00441 // provide device ID (8 bytes, LSBF) 00442 void os_getDevEui( uint8_t *buf ) 00443 { 00444 memcpy( buf, DevEui, 8 ); 00445 } 00446 00447 // provide device key (16 bytes) 00448 void os_getDevKey( uint8_t *buf ) 00449 { 00450 memcpy( buf, DevKey, 16 ); 00451 } 00452 00453 ////////////////////////////////////////////////// 00454 // MAIN - INITIALIZATION AND STARTUP 00455 ////////////////////////////////////////////////// 00456 00457 static void onRxLed( osjob_t* j ) 00458 { 00459 // debug_val("LED2 = ", 0 ); 00460 } 00461 00462 static void onTxLed( osjob_t* j ) 00463 { 00464 // debug_val("LED1 = ", 0 ); 00465 } 00466 00467 static void prepareTxCoapFrame( void ) 00468 { 00469 // Create Registration PDU : 00470 00471 CoapPDU *pdu = new CoapPDU(); 00472 00473 pdu->setCode(CoapPDU::COAP_POST); 00474 pdu->setType(CoapPDU::COAP_CONFIRMABLE); 00475 int size; 00476 uint8_t * token = get_Token(&size); 00477 pdu->setToken(token,size); 00478 pdu->setMessageID(get_Message_ID()); 00479 pdu->setURI(get_Registration_Query()); 00480 00481 _payload=get_Registration_Payload(&_payload_size); 00482 pdu->setPayload(_payload, (int) _payload_size); 00483 int PDUlength = pdu->getPDULength(); 00484 00485 // strncpy((char*) LMIC.frame, (const char*)pdu->getPDUPointer(), PDUlength); 00486 memcpy(LMIC.frame, pdu->getPDUPointer(), PDUlength * sizeof(uint8_t)); 00487 00488 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 ) 00489 LMIC.frame[PDUlength] = LMIC.seqnoDn >> 8; 00490 LMIC.frame[PDUlength+1] = LMIC.seqnoDn; 00491 LMIC.frame[PDUlength+2] = LMIC.rssi >> 8; 00492 LMIC.frame[PDUlength+3] = LMIC.rssi; 00493 LMIC.frame[PDUlength+4] = LMIC.snr; 00494 #endif 00495 debug_str("Frame to be sent: "); 00496 debug_buf(LMIC.frame, PDUlength + 5); 00497 00498 LoRaWAN_data_size = PDUlength + 5; 00499 } 00500 00501 static void prepareTxLoraFrame( void ) 00502 { 00503 const char *frame = "LoRa"; 00504 // const char *frame = "Test"; 00505 00506 strncpy((char*) LMIC.frame, frame, strlen(frame)); 00507 00508 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 ) 00509 LMIC.frame[strlen(frame)] = LMIC.seqnoDn >> 8; 00510 LMIC.frame[strlen(frame)+1] = LMIC.seqnoDn; 00511 LMIC.frame[strlen(frame)+2] = LMIC.rssi >> 8; 00512 LMIC.frame[strlen(frame)+3] = LMIC.rssi; 00513 LMIC.frame[strlen(frame)+4] = LMIC.snr; 00514 #endif 00515 debug_str("Frame to be sent: "); 00516 // debug_buf(LMIC.frame, strlen(frame) + 5); 00517 debug_buf(LMIC.frame, strlen(frame)); 00518 00519 // LoRaWAN_data_size = strlen(frame) + 5; 00520 LoRaWAN_data_size = strlen(frame); 00521 } 00522 00523 static void prepareTxSensorsFrame( void ) 00524 { 00525 std::string frame = ""; 00526 std::string tmp; 00527 debug_str("\r\n"); 00528 00529 temp_sensor1->GetTemperature(&value1); 00530 humidity_sensor->GetHumidity(&value2); 00531 debug_str("HTS221: [temp] "); 00532 debug_str(printDouble(buffer1, value1)); 00533 tmp = "0,"; 00534 tmp += buffer1; 00535 tmp += ","; 00536 00537 if ((!temp_sent) && (frame.length() + tmp.length() < 50)) 00538 { 00539 temp_sent = true; 00540 frame += tmp; 00541 } 00542 00543 debug_str("Celsius, [hum] "); 00544 debug_str(printDouble(buffer2, value2)); 00545 tmp = "1,"; 00546 tmp += buffer2; 00547 tmp += ","; 00548 00549 if ((!hum_sent) && (frame.length() + tmp.length() < 50)) 00550 { 00551 hum_sent = true; 00552 frame += tmp; 00553 } 00554 00555 debug_str("%\r\n"); 00556 //pc.printf("HTS221: [temp] %7s°C, [hum] %s%%\r\n", printDouble(buffer1, value1), printDouble(buffer2, value2)); 00557 00558 temp_sensor2->GetFahrenheit(&value1); 00559 pressure_sensor->GetPressure(&value2); 00560 debug_str("LPS25H: [temp] "); 00561 debug_str(printDouble(buffer1, value1)); 00562 debug_str("Farenheit, [press] "); 00563 debug_str(printDouble(buffer2, value2)); 00564 tmp = "2,"; 00565 tmp += buffer2; 00566 tmp += ","; 00567 00568 if ((!press_sent) && (frame.length() + tmp.length() < 50)) 00569 { 00570 press_sent = true; 00571 frame += tmp; 00572 } 00573 00574 debug_str("mbar\r\n"); 00575 //pc.printf("LPS25H: [temp] %7s°F, [press] %smbar\r\n", printDouble(buffer1, value1), printDouble(buffer2, value2)); 00576 00577 debug_str("---\r\n"); 00578 00579 magnetometer->Get_M_Axes(axes); 00580 debug_str("LIS3MDL [mag/mgauss]: "); 00581 debug_str(printInt(buffer1, axes[0])); 00582 debug_str(", "); 00583 debug_str(printInt(buffer2, axes[1])); 00584 debug_str(", "); 00585 debug_str(printInt(buffer3, axes[2])); 00586 debug_str("\r\n"); 00587 tmp = "3,"; 00588 tmp += buffer1; 00589 tmp += ";"; 00590 tmp += buffer2; 00591 tmp += ";"; 00592 tmp += buffer3; 00593 tmp += ","; 00594 00595 if ((!magn_sent) && (frame.length() + tmp.length() < 50)) 00596 { 00597 magn_sent = true; 00598 frame += tmp; 00599 } 00600 00601 //pc.printf("LIS3MDL [mag/mgauss]: %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]); 00602 00603 accelerometer->Get_X_Axes(axes); 00604 debug_str("LSM6DS0 [acc/mg]: "); 00605 debug_str(printInt(buffer1, axes[0])); 00606 debug_str(", "); 00607 debug_str(printInt(buffer2, axes[1])); 00608 debug_str(", "); 00609 debug_str(printInt(buffer3, axes[2])); 00610 tmp = "4,"; 00611 tmp += buffer1; 00612 tmp += ";"; 00613 tmp += buffer2; 00614 tmp += ";"; 00615 tmp += buffer3; 00616 tmp += ","; 00617 00618 if ((!motion_sent) && (frame.length() + tmp.length() < 50)) 00619 { 00620 motion_sent = true; 00621 frame += tmp; 00622 } 00623 00624 debug_str("\r\n"); 00625 //pc.printf("LSM6DS0 [acc/mg]: %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]); 00626 00627 gyroscope->Get_G_Axes(axes); 00628 debug_str("LSM6DS0 [gyro/mdps]: "); 00629 debug_str(printInt(buffer1, axes[0])); 00630 debug_str(", "); 00631 debug_str(printInt(buffer2, axes[1])); 00632 debug_str(", "); 00633 debug_str(printInt(buffer3, axes[2])); 00634 tmp = "5,"; 00635 tmp += buffer1; 00636 tmp += ";"; 00637 tmp += buffer2; 00638 tmp += ";"; 00639 tmp += buffer3; 00640 00641 if ((!gyro_sent) && (frame.length() + tmp.length() < 50)) 00642 { 00643 gyro_sent = false; 00644 temp_sent = false; 00645 press_sent = false; 00646 motion_sent = false; 00647 magn_sent = false; 00648 hum_sent = false; 00649 00650 frame += tmp; 00651 } 00652 00653 debug_str("\r\n Frame: "); 00654 debug_str(frame.c_str()); 00655 debug_str("\r\n"); 00656 //pc.printf("LSM6DS0 [gyro/mdps]: %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]); 00657 00658 strncpy((char*) LMIC.frame, frame.c_str(), strlen(frame.c_str())); 00659 00660 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 ) 00661 LMIC.frame[strlen(frame.c_str())] = LMIC.seqnoDn >> 8; 00662 LMIC.frame[strlen(frame.c_str())+1] = LMIC.seqnoDn; 00663 LMIC.frame[strlen(frame.c_str())+2] = LMIC.rssi >> 8; 00664 LMIC.frame[strlen(frame.c_str())+3] = LMIC.rssi; 00665 LMIC.frame[strlen(frame.c_str())+4] = LMIC.snr; 00666 #endif 00667 debug_str("Frame to be sent: "); 00668 // debug_buf(LMIC.frame, strlen(frame) + 5); 00669 debug_buf(LMIC.frame, strlen(frame.c_str())); 00670 00671 // LoRaWAN_data_size = strlen(frame) + 5; 00672 LoRaWAN_data_size = strlen(frame.c_str()); 00673 } 00674 00675 static void prepareTxFrame( void ) 00676 { 00677 LMIC.frame[0] = AppLedStateOn; 00678 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 ) 00679 LMIC.frame[1] = LMIC.seqnoDn >> 8; 00680 LMIC.frame[2] = LMIC.seqnoDn; 00681 LMIC.frame[3] = LMIC.rssi >> 8; 00682 LMIC.frame[4] = LMIC.rssi; 00683 LMIC.frame[5] = LMIC.snr; 00684 #endif 00685 debug_str("Frame to be sent: "); 00686 debug_buf(LMIC.frame, LORAWAN_APP_DATA_SIZE); 00687 00688 LoRaWAN_data_size = LORAWAN_APP_DATA_SIZE; 00689 } 00690 00691 void processRxFrame( void ) 00692 { 00693 00694 char* frameToDisplay = (char*) (LMIC.frame + LMIC.dataBeg); 00695 frameToDisplay[LMIC.dataLen] = '\0'; 00696 00697 switch( LMIC.frame[LMIC.dataBeg - 1] ) // Check Rx port number 00698 { 00699 case 0: 00700 // debug_str("Port 0!!!\r\n"); 00701 // debug_val("Data Len: ", LMIC.dataLen); 00702 00703 case 1: // The application LED can be controlled on port 1 or 2 00704 debug_str("Data received on port 1: "); 00705 debug_str("Data in hexa: "); 00706 debug_buf( LMIC.frame + LMIC.dataBeg, LMIC.dataLen ); 00707 debug_str("Data in string: "); 00708 00709 debug_str( frameToDisplay ); 00710 debug_str("\r\n"); 00711 00712 break; 00713 case 2: 00714 debug_str("Data received on port 2: "); 00715 debug_str("Data in hexa: "); 00716 debug_buf( LMIC.frame + LMIC.dataBeg, LMIC.dataLen ); 00717 debug_str("Data in string: "); 00718 00719 debug_str( frameToDisplay ); 00720 debug_str("\r\n"); 00721 00722 if( LMIC.dataLen == 1 ) 00723 { 00724 debug_str("Data received on port 2: "); 00725 debug_hex(LMIC.frame[LMIC.dataBeg]); 00726 debug_str("\r\n"); 00727 AppLedStateOn = LMIC.frame[LMIC.dataBeg] & 0x01; 00728 //debug_val( "LED3 = ", AppLedStateOn ); 00729 } 00730 break; 00731 default: 00732 break; 00733 } 00734 } 00735 00736 static void onSendFrame( osjob_t* j ) 00737 { 00738 //prepareTxFrame( ); 00739 //prepareTxCoapFrame(); 00740 prepareTxSensorsFrame(); 00741 //prepareTxLoraFrame(); 00742 00743 LMIC_setTxData2( LORAWAN_APP_PORT, LMIC.frame, LoRaWAN_data_size, LORAWAN_CONFIRMED_MSG_ON ); 00744 00745 // Blink Tx LED 00746 //debug_val( "LED1 = ", 1 ); 00747 os_setTimedCallback( &txLedJob, os_getTime( ) + ms2osticks( 25 ), onTxLed ); 00748 /* os_setTimedCallback( &sendFrameJob, 00749 os_getTime( ) + ms2osticks( APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ) ), 00750 onSendFrame );*/ 00751 } 00752 00753 // Initialization job 00754 static void onInit( osjob_t* j ) 00755 { 00756 debug_str("--- Starting new run ---\r\n"); 00757 00758 humidity_sensor->ReadID(&id); 00759 debug_str("HTS221 humidity & temperature = "); 00760 debug_uint(id); 00761 debug_str("\r\n"); 00762 pressure_sensor->ReadID(&id); 00763 debug_str("LPS25H pressure & temperature = "); 00764 debug_uint(id); 00765 debug_str("\r\n"); 00766 magnetometer->ReadID(&id); 00767 debug_str("LIS3MDL magnetometer = "); 00768 debug_uint(id); 00769 debug_str("\r\n"); 00770 gyroscope->ReadID(&id); 00771 debug_str("LSM6DS0 accelerometer & gyroscope = "); 00772 debug_uint(id); 00773 debug_str("\r\n"); 00774 00775 // reset MAC state 00776 LMIC_reset( ); 00777 LMIC_setAdrMode( LORAWAN_ADR_ON ); 00778 LMIC_setDrTxpow( DR_SF12, 14 ); 00779 00780 // start joining 00781 #if( OVER_THE_AIR_ACTIVATION != 0 ) 00782 LMIC_startJoining( ); 00783 #else 00784 LMIC_setSession( LORAWAN_NET_ID, LORAWAN_DEV_ADDR, NwkSKey, ArtSKey ); 00785 onSendFrame( NULL ); 00786 #endif 00787 // init done - onEvent( ) callback will be invoked... 00788 } 00789 00790 int main( void ) 00791 { 00792 debug_init(); 00793 osjob_t initjob; 00794 00795 // initialize runtime env 00796 os_init( ); 00797 // setup initial job 00798 os_setCallback( &initjob, onInit ); 00799 // execute scheduled jobs and events 00800 00801 //static Thread exec_thread(exec_call_thread); 00802 00803 os_runloop( ); 00804 // (not reached) 00805 } 00806 00807 ////////////////////////////////////////////////// 00808 // LMIC EVENT CALLBACK 00809 ////////////////////////////////////////////////// 00810 void onEvent( ev_t ev ) 00811 { 00812 bool txOn = false; 00813 debug_event( ev ); 00814 00815 switch( ev ) 00816 { 00817 // network joined, session established 00818 case EV_JOINED: 00819 debug_val( "Net ID = ", LMIC.netid ); 00820 txOn = true; 00821 break; 00822 // scheduled data sent (optionally data received) 00823 case EV_TXCOMPLETE: 00824 debug_val( "Datarate = ", LMIC.datarate ); 00825 // Check if we have a downlink on either Rx1 or Rx2 windows 00826 if( ( LMIC.txrxFlags & ( TXRX_DNW1 | TXRX_DNW2 ) ) != 0 ) 00827 { 00828 // debug_val( "LED2 = ", 1 ); 00829 os_setTimedCallback( &rxLedJob, os_getTime( ) + ms2osticks( 25 ), onRxLed ); 00830 00831 if( LMIC.dataLen != 0 ) 00832 { // data received in rx slot after tx 00833 //debug_buf( LMIC.frame + LMIC.dataBeg, LMIC.dataLen ); 00834 processRxFrame( ); 00835 } 00836 } 00837 txOn = true; 00838 break; 00839 default: 00840 break; 00841 } 00842 if( txOn == true ) 00843 { 00844 //Sends frame every APP_TX_DUTYCYCLE +/- APP_TX_DUTYCYCLE_RND random time (if not duty cycle limited) 00845 os_setTimedCallback( &sendFrameJob, 00846 os_getTime( ) + ms2osticks( APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ) ), 00847 onSendFrame ); 00848 //os_setCallback( &sendFrameJob, onSendFrame ); 00849 ////Sends frame as soon as possible (duty cylce limitations) 00850 //onSendFrame( NULL ); 00851 } 00852 } 00853 00854
Generated on Sat Jul 16 2022 03:37:10 by
1.7.2
