Lora Personalized device for Everynet

Dependencies:   LMiCPersonalizedforEverynet SX1276Lib X_NUCLEO_IKS01A1 cantcoap lwip mbed-rtos mbed

Fork of LoRaWAN-test-10secs 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     printDouble(buffer1, value1);
00532 //    debug_str("HTS221: [temp] ");
00533 //    debug_str(printDouble(buffer1, value1));
00534     tmp = "0,";
00535     tmp += buffer1;
00536     tmp += ",";
00537     
00538     if ((!temp_sent) && (frame.length() + tmp.length() < 50))
00539     {
00540         temp_sent = true;
00541         frame += tmp; 
00542     }
00543     printDouble(buffer2, value2);
00544 //    debug_str("Celsius,   [hum] ");
00545 //    debug_str(printDouble(buffer2, value2));
00546     tmp = "1,";
00547     tmp += buffer2;
00548     tmp += ",";
00549 
00550     if ((!hum_sent) && (frame.length() + tmp.length() < 50))
00551     {
00552         hum_sent = true;
00553         frame += tmp; 
00554     }
00555     
00556 //    debug_str("%\r\n");
00557     //pc.printf("HTS221: [temp] %7s°C,   [hum] %s%%\r\n", printDouble(buffer1, value1), printDouble(buffer2, value2));
00558     
00559     temp_sensor2->GetFahrenheit(&value1);
00560     pressure_sensor->GetPressure(&value2);
00561     printDouble(buffer1, value1);
00562     printDouble(buffer2, value2);
00563 /*    debug_str("LPS25H: [temp] ");
00564     debug_str(printDouble(buffer1, value1));
00565     debug_str("Farenheit, [press] ");
00566     debug_str(printDouble(buffer2, value2));*/
00567     tmp = "2,";
00568     tmp += buffer2;
00569     tmp += ",";
00570 
00571     if ((!press_sent) && (frame.length() + tmp.length() < 50))
00572     {
00573         press_sent = true;
00574         frame += tmp; 
00575     }
00576     
00577 //    debug_str("mbar\r\n");
00578     //pc.printf("LPS25H: [temp] %7s°F, [press] %smbar\r\n", printDouble(buffer1, value1), printDouble(buffer2, value2));
00579 
00580 //    debug_str("---\r\n");
00581 
00582     magnetometer->Get_M_Axes(axes);
00583     printInt(buffer1, axes[0]);
00584     printInt(buffer2, axes[1]);
00585     printInt(buffer3, axes[2]);
00586 /*    debug_str("LIS3MDL [mag/mgauss]:  ");
00587     debug_str(printInt(buffer1, axes[0]));
00588     debug_str(", ");
00589     debug_str(printInt(buffer2, axes[1]));
00590     debug_str(", ");
00591     debug_str(printInt(buffer3, axes[2]));
00592     debug_str("\r\n");*/
00593     tmp = "3,";
00594     tmp += buffer1;
00595     tmp += ";";
00596     tmp += buffer2;
00597     tmp += ";";
00598     tmp += buffer3;
00599     tmp += ",";
00600 
00601     if ((!magn_sent) && (frame.length() + tmp.length() < 50))
00602     {
00603         magn_sent = true;
00604         frame += tmp; 
00605     }
00606     
00607     //pc.printf("LIS3MDL [mag/mgauss]:  %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]);
00608 
00609     accelerometer->Get_X_Axes(axes);
00610     printInt(buffer1, axes[0]);
00611     printInt(buffer2, axes[1]);
00612     printInt(buffer3, axes[2]);
00613 /*   debug_str("LSM6DS0 [acc/mg]:      ");
00614 
00615     debug_str(printInt(buffer1, axes[0]));
00616     debug_str(", ");
00617     debug_str(printInt(buffer2, axes[1]));
00618     debug_str(", ");
00619     debug_str(printInt(buffer3, axes[2]));*/
00620     tmp = "4,";
00621     tmp += buffer1;
00622     tmp += ";";
00623     tmp += buffer2;
00624     tmp += ";";
00625     tmp += buffer3;
00626     tmp += ",";
00627 
00628     if ((!motion_sent) && (frame.length() + tmp.length() < 50))
00629     {
00630         motion_sent = true;
00631         frame += tmp; 
00632     }
00633     
00634     //debug_str("\r\n");
00635     //pc.printf("LSM6DS0 [acc/mg]:      %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]);
00636 
00637     gyroscope->Get_G_Axes(axes);
00638     printInt(buffer1, axes[0]);
00639     printInt(buffer2, axes[1]);
00640     printInt(buffer3, axes[2]);
00641 /*    debug_str("LSM6DS0 [gyro/mdps]:   ");
00642     debug_str(printInt(buffer1, axes[0]));
00643     debug_str(", ");
00644     debug_str(printInt(buffer2, axes[1]));
00645     debug_str(", ");
00646     debug_str(printInt(buffer3, axes[2]));*/
00647     tmp = "5,";
00648     tmp += buffer1;
00649     tmp += ";";
00650     tmp += buffer2;
00651     tmp += ";";
00652     tmp += buffer3;
00653 
00654     if ((!gyro_sent) && (frame.length() + tmp.length() < 50))
00655     {
00656         gyro_sent = false;
00657         temp_sent = false;
00658         press_sent = false;
00659         motion_sent = false;
00660         magn_sent = false;
00661         hum_sent = false;
00662         
00663         frame += tmp; 
00664     }
00665     
00666     //debug_str("\r\n Frame: ");
00667     //debug_str(frame.c_str());
00668     //debug_str("\r\n");
00669     //pc.printf("LSM6DS0 [gyro/mdps]:   %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]);
00670 
00671     strncpy((char*) LMIC.frame, frame.c_str(), strlen(frame.c_str()));
00672 
00673 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
00674     LMIC.frame[strlen(frame.c_str())] = LMIC.seqnoDn >> 8;
00675     LMIC.frame[strlen(frame.c_str())+1] = LMIC.seqnoDn;
00676     LMIC.frame[strlen(frame.c_str())+2] = LMIC.rssi >> 8;
00677     LMIC.frame[strlen(frame.c_str())+3] = LMIC.rssi;
00678     LMIC.frame[strlen(frame.c_str())+4] = LMIC.snr;
00679 #endif
00680     //debug_str("Frame to be sent: ");
00681 //    debug_buf(LMIC.frame, strlen(frame) + 5);
00682     //debug_buf(LMIC.frame, strlen(frame.c_str()));
00683     
00684 //    LoRaWAN_data_size = strlen(frame) + 5;
00685     LoRaWAN_data_size = strlen(frame.c_str());
00686 }
00687 
00688 static void prepareTxFrame( void )
00689 {
00690     LMIC.frame[0] = AppLedStateOn;
00691 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
00692     LMIC.frame[1] = LMIC.seqnoDn >> 8;
00693     LMIC.frame[2] = LMIC.seqnoDn;
00694     LMIC.frame[3] = LMIC.rssi >> 8;
00695     LMIC.frame[4] = LMIC.rssi;
00696     LMIC.frame[5] = LMIC.snr;
00697 #endif    
00698     //debug_str("Frame to be sent: ");
00699     //debug_buf(LMIC.frame, LORAWAN_APP_DATA_SIZE);
00700     
00701     LoRaWAN_data_size = LORAWAN_APP_DATA_SIZE;
00702 }
00703 
00704 void processRxFrame( void )
00705 {
00706 
00707     char* frameToDisplay = (char*) (LMIC.frame + LMIC.dataBeg);
00708     frameToDisplay[LMIC.dataLen] = '\0';
00709 
00710     switch( LMIC.frame[LMIC.dataBeg - 1] ) // Check Rx port number
00711     {
00712         case 0:
00713 //            debug_str("Port 0!!!\r\n");
00714 //            debug_val("Data Len: ", LMIC.dataLen);
00715             
00716         case 1: // The application LED can be controlled on port 1 or 2
00717             debug_str("Data received on port 1: ");
00718             debug_str("Data in hexa: ");
00719             debug_buf( LMIC.frame + LMIC.dataBeg, LMIC.dataLen );
00720             debug_str("Data in string: ");
00721             
00722             debug_str( frameToDisplay );
00723             debug_str("\r\n");
00724             
00725             break;
00726         case 2:
00727             debug_str("Data received on port 2: ");
00728             debug_str("Data in hexa: ");
00729             debug_buf( LMIC.frame + LMIC.dataBeg, LMIC.dataLen );
00730             debug_str("Data in string: ");
00731             
00732             debug_str( frameToDisplay );
00733             debug_str("\r\n");
00734         
00735             if( LMIC.dataLen == 1 )
00736             {
00737                 debug_str("Data received on port 2: ");
00738                 debug_hex(LMIC.frame[LMIC.dataBeg]);
00739                 debug_str("\r\n");
00740                 AppLedStateOn = LMIC.frame[LMIC.dataBeg] & 0x01;
00741                 //debug_val( "LED3 = ", AppLedStateOn );
00742             }
00743             break;
00744         default:
00745             break;
00746     }
00747 }
00748 
00749 static void onSendFrame( osjob_t* j )
00750 {
00751     //prepareTxFrame( );
00752     //prepareTxCoapFrame();
00753     prepareTxSensorsFrame();
00754     //prepareTxLoraFrame();
00755 
00756 #if( OVER_THE_AIR_ACTIVATION == 1 )
00757     LMIC_setTxData2( LORAWAN_APP_PORT, LMIC.frame, LoRaWAN_data_size, LORAWAN_CONFIRMED_MSG_ON, 1 );
00758 #endif  
00759 #if( OVER_THE_AIR_ACTIVATION == 0 )
00760     LMIC_setTxData2( LORAWAN_APP_PORT, LMIC.frame, LoRaWAN_data_size, LORAWAN_CONFIRMED_MSG_ON, 0 );
00761 #endif  
00762 
00763     // Blink Tx LED
00764     //debug_val( "LED1 = ", 1 );
00765     os_setTimedCallback( &txLedJob, os_getTime( ) + ms2osticks( 25 ), onTxLed );
00766     /*    os_setTimedCallback( &sendFrameJob,
00767                              os_getTime( ) + ms2osticks( APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ) ),
00768                              onSendFrame );*/
00769 }
00770 
00771 // Initialization job
00772 static void onInit( osjob_t* j )
00773 {
00774     debug_str("--- Starting new run ---\r\n");
00775 
00776     humidity_sensor->ReadID(&id);
00777     debug_str("HTS221  humidity & temperature    = ");
00778     debug_uint(id);
00779     debug_str("\r\n");
00780     pressure_sensor->ReadID(&id);
00781     debug_str("LPS25H  pressure & temperature    = ");
00782     debug_uint(id);
00783     debug_str("\r\n");
00784     magnetometer->ReadID(&id);
00785     debug_str("LIS3MDL magnetometer              = ");
00786     debug_uint(id);
00787     debug_str("\r\n");
00788     gyroscope->ReadID(&id);
00789     debug_str("LSM6DS0 accelerometer & gyroscope = ");
00790     debug_uint(id);
00791     debug_str("\r\n");
00792 
00793     // reset MAC state
00794     LMIC_reset( );
00795     LMIC_setAdrMode( LORAWAN_ADR_ON );
00796     LMIC_setDrTxpow( DR_SF12, 14 );
00797 
00798     // start joining
00799 #if( OVER_THE_AIR_ACTIVATION != 0 )
00800     LMIC_startJoining( );
00801 #else
00802     LMIC_setSession( LORAWAN_NET_ID, LORAWAN_DEV_ADDR, NwkSKey, ArtSKey );
00803     onSendFrame( NULL );
00804 #endif
00805     // init done - onEvent( ) callback will be invoked...
00806 }
00807 
00808 int main( void )
00809 {
00810     debug_init();
00811     osjob_t initjob;
00812     
00813     // initialize runtime env
00814     os_init( );
00815     // setup initial job
00816     os_setCallback( &initjob, onInit );
00817     // execute scheduled jobs and events
00818     
00819     //static Thread exec_thread(exec_call_thread);
00820     
00821     os_runloop( );
00822     // (not reached)
00823 }
00824 
00825 //////////////////////////////////////////////////
00826 // LMIC EVENT CALLBACK
00827 //////////////////////////////////////////////////
00828 void onEvent( ev_t ev )
00829 {
00830     bool txOn = false;
00831     debug_event( ev );
00832 
00833     switch( ev ) 
00834     {
00835     // network joined, session established
00836     case EV_JOINED:
00837         debug_val( "Net ID = ", LMIC.netid );
00838         txOn = true;
00839         break;
00840     // scheduled data sent (optionally data received)
00841     case EV_TXCOMPLETE:
00842         debug_val( "Datarate = ", LMIC.datarate );
00843         // Check if we have a downlink on either Rx1 or Rx2 windows
00844         if( ( LMIC.txrxFlags & ( TXRX_DNW1 | TXRX_DNW2 ) ) != 0 )
00845         {
00846 //            debug_val( "LED2 = ", 1 );
00847             os_setTimedCallback( &rxLedJob, os_getTime( ) + ms2osticks( 25 ), onRxLed );
00848 
00849             if( LMIC.dataLen != 0 )
00850             { // data received in rx slot after tx
00851                 //debug_buf( LMIC.frame + LMIC.dataBeg, LMIC.dataLen );
00852                 processRxFrame( );
00853             }
00854         }
00855         txOn = true;
00856         break;
00857     default:
00858         break;
00859     }
00860     if( txOn == true )
00861     {
00862         //Sends frame every APP_TX_DUTYCYCLE +/- APP_TX_DUTYCYCLE_RND random time (if not duty cycle limited)
00863         os_setTimedCallback( &sendFrameJob,
00864                              os_getTime( ) + ms2osticks( APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ) ),
00865                              onSendFrame );
00866         //os_setCallback( &sendFrameJob, onSendFrame );
00867         ////Sends frame as soon as possible (duty cylce limitations)
00868         //onSendFrame( NULL );
00869     }
00870 }
00871 
00872