Alcatel-Lucent IoT Development / Mbed 2 deprecated LoRaWAN-test-10secs

Dependencies:   LMiC-10secs SX1276Lib X_NUCLEO_IKS01A1 cantcoap lwip mbed-rtos mbed

Fork of LoRaWAN-lmic-app by Alcatel-Lucent IoT Development

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

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             ="&lt=";
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