Lora OTA device for Everynet

Dependencies:   LMiCLibOTADeviceEverynet SX1276Lib X_NUCLEO_IKS01A1 cantcoap lwip mbed-rtos mbed

Fork of LoRaWAN-test-10secs by Alcatel-Lucent IoT Development

Committer:
pnysten
Date:
Fri Jan 08 09:58:07 2016 +0000
Revision:
9:84a69ca4d35a
Parent:
8:8d9a49aaa323
Child:
10:155dc60fce79
No confirmation on uplink messages

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sam_grove 3:ce28e3313a88 1 /*
mluis 0:a2929fa6e4f0 2 / _____) _ | |
mluis 0:a2929fa6e4f0 3 ( (____ _____ ____ _| |_ _____ ____| |__
mluis 0:a2929fa6e4f0 4 \____ \| ___ | (_ _) ___ |/ ___) _ \
mluis 0:a2929fa6e4f0 5 _____) ) ____| | | || |_| ____( (___| | | |
mluis 0:a2929fa6e4f0 6 (______/|_____)_|_|_| \__)_____)\____)_| |_|
mluis 1:60184eda0066 7 (C)2015 Semtech
mluis 0:a2929fa6e4f0 8
mluis 1:60184eda0066 9 Description: MBED LoRaWAN example application
mluis 0:a2929fa6e4f0 10
mluis 0:a2929fa6e4f0 11 License: Revised BSD License, see LICENSE.TXT file include in the project
mluis 0:a2929fa6e4f0 12
mluis 0:a2929fa6e4f0 13 Maintainer: Miguel Luis and Gregory Cristian
mluis 0:a2929fa6e4f0 14 */
pnysten 6:540c5d907c90 15
pnysten 4:5e274bf85bf0 16 #include <cstdio>
pnysten 4:5e274bf85bf0 17 #include <string>
pnysten 4:5e274bf85bf0 18 #include <cassert>
pnysten 4:5e274bf85bf0 19
mluis 1:60184eda0066 20 #include "mbed.h"
pnysten 6:540c5d907c90 21 //#include "Node.h"
pnysten 4:5e274bf85bf0 22 #include "cantcoap.h"
mluis 1:60184eda0066 23
mluis 0:a2929fa6e4f0 24 #include "lmic.h"
mluis 1:60184eda0066 25 #include "debug.h"
mluis 0:a2929fa6e4f0 26
pnysten 4:5e274bf85bf0 27 const std::string REGISTRATION_SEGMENT ="/rd";
pnysten 4:5e274bf85bf0 28 const std::string ENDPOINT_SEGMENT = "?ep=";
pnysten 4:5e274bf85bf0 29 const std::string LIFETIME ="&lt=";
pnysten 4:5e274bf85bf0 30 const std::string BINDING ="&b=";
pnysten 6:540c5d907c90 31
pnysten 4:5e274bf85bf0 32 const std::string REGISTRATION_OPEN = "<";
pnysten 4:5e274bf85bf0 33 const std::string REGISTRATION_CLOSE = ">";
pnysten 4:5e274bf85bf0 34 const std::string REGISTRATION_SEPARATOR ="/";
pnysten 6:540c5d907c90 35
pnysten 4:5e274bf85bf0 36 int _node_Id=0;
pnysten 6:540c5d907c90 37
pnysten 4:5e274bf85bf0 38 const std::string endPoint_Name = "loraDevice";
pnysten 4:5e274bf85bf0 39 const int lifeTime = 300;
pnysten 4:5e274bf85bf0 40 const std::string binding = "U";
pnysten 6:540c5d907c90 41
pnysten 4:5e274bf85bf0 42 unsigned char * _payload;
pnysten 4:5e274bf85bf0 43 long _payload_size;
pnysten 6:540c5d907c90 44
mluis 0:a2929fa6e4f0 45 /*!
mluis 0:a2929fa6e4f0 46 * When set to 1 the application uses the Over-the-Air activation procedure
mluis 0:a2929fa6e4f0 47 * When set to 0 the application uses the Personalization activation procedure
mluis 0:a2929fa6e4f0 48 */
mluis 0:a2929fa6e4f0 49 #define OVER_THE_AIR_ACTIVATION 0
mluis 0:a2929fa6e4f0 50
mluis 1:60184eda0066 51 #if( OVER_THE_AIR_ACTIVATION == 0 )
mluis 1:60184eda0066 52
mluis 1:60184eda0066 53 /*!
mluis 1:60184eda0066 54 * Defines the network ID when using personalization activation procedure
mluis 1:60184eda0066 55 */
mluis 1:60184eda0066 56 #define LORAWAN_NET_ID ( uint32_t )0x00000000
mluis 1:60184eda0066 57
mluis 1:60184eda0066 58 /*!
mluis 1:60184eda0066 59 * Defines the device address when using personalization activation procedure
mluis 1:60184eda0066 60 */
pnysten 9:84a69ca4d35a 61 //To be changed when switching from one to another
pnysten 7:f1521b0ecf08 62 #define LORAWAN_DEV_ADDR ( uint32_t )0x12345678
pnysten 6:540c5d907c90 63 //#define LORAWAN_DEV_ADDR ( uint32_t )0x12341111
mluis 1:60184eda0066 64
mluis 1:60184eda0066 65 #endif
mluis 1:60184eda0066 66
mluis 1:60184eda0066 67 /*!
mluis 1:60184eda0066 68 * Defines the application data transmission duty cycle
mluis 1:60184eda0066 69 */
mluis 1:60184eda0066 70 #define APP_TX_DUTYCYCLE 5000 // 5 [s] value in ms
mluis 1:60184eda0066 71 #define APP_TX_DUTYCYCLE_RND 1000 // 1 [s] value in ms
mluis 1:60184eda0066 72
mluis 1:60184eda0066 73 /*!
mluis 1:60184eda0066 74 * LoRaWAN Adaptative Data Rate
mluis 1:60184eda0066 75 */
mluis 1:60184eda0066 76 #define LORAWAN_ADR_ON 1
mluis 1:60184eda0066 77
mluis 1:60184eda0066 78 /*!
mluis 1:60184eda0066 79 * LoRaWAN confirmed messages
mluis 1:60184eda0066 80 */
pnysten 9:84a69ca4d35a 81 #define LORAWAN_CONFIRMED_MSG_ON 0
mluis 1:60184eda0066 82
mluis 1:60184eda0066 83 /*!
mluis 1:60184eda0066 84 * LoRaWAN application port
mluis 1:60184eda0066 85 */
mluis 1:60184eda0066 86 #define LORAWAN_APP_PORT 15
mluis 1:60184eda0066 87
mluis 1:60184eda0066 88 /*!
mluis 1:60184eda0066 89 * User application data buffer size
mluis 1:60184eda0066 90 */
mluis 1:60184eda0066 91 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
mluis 1:60184eda0066 92 #define LORAWAN_APP_DATA_SIZE 6
mluis 1:60184eda0066 93
mluis 1:60184eda0066 94 #else
mluis 1:60184eda0066 95 #define LORAWAN_APP_DATA_SIZE 1
mluis 1:60184eda0066 96
mluis 1:60184eda0066 97 #endif
mluis 0:a2929fa6e4f0 98
pnysten 4:5e274bf85bf0 99 #define UINT16_MAX (65535U)
pnysten 4:5e274bf85bf0 100 #define UINT64_MAX (18446744073709551615ULL)
pnysten 6:540c5d907c90 101
pnysten 6:540c5d907c90 102 //Node lwm2mNode("LR-test0");;
pnysten 6:540c5d907c90 103 unsigned int LoRaWAN_data_size = 0;
pnysten 4:5e274bf85bf0 104
pnysten 4:5e274bf85bf0 105 std::string to_string( int x ) {
pnysten 4:5e274bf85bf0 106 int length = snprintf( NULL, 0, "%d", x );
pnysten 4:5e274bf85bf0 107 assert( length >= 0 );
pnysten 4:5e274bf85bf0 108 char* buf = new char[length + 1];
pnysten 4:5e274bf85bf0 109 snprintf( buf, length + 1, "%d", x );
pnysten 4:5e274bf85bf0 110 std::string str( buf );
pnysten 4:5e274bf85bf0 111 delete[] buf;
pnysten 4:5e274bf85bf0 112 return str;
pnysten 4:5e274bf85bf0 113 }
pnysten 4:5e274bf85bf0 114 unsigned char * get_Registration_Payload(long *payload_size){
pnysten 6:540c5d907c90 115
pnysten 4:5e274bf85bf0 116 string registration_Payload ="";
pnysten 6:540c5d907c90 117
pnysten 4:5e274bf85bf0 118 string s="";
pnysten 6:540c5d907c90 119
pnysten 4:5e274bf85bf0 120 s.append(REGISTRATION_OPEN);
pnysten 4:5e274bf85bf0 121 s.append(REGISTRATION_SEPARATOR);
pnysten 4:5e274bf85bf0 122 s.append("3/0/0");
pnysten 4:5e274bf85bf0 123 s.append(REGISTRATION_CLOSE);
pnysten 4:5e274bf85bf0 124 s.append(",");
pnysten 4:5e274bf85bf0 125 s.append(REGISTRATION_OPEN);
pnysten 4:5e274bf85bf0 126 s.append(REGISTRATION_SEPARATOR);
pnysten 4:5e274bf85bf0 127 s.append("3/0/1");
pnysten 4:5e274bf85bf0 128 s.append(REGISTRATION_CLOSE);
pnysten 4:5e274bf85bf0 129 s.append(",");
pnysten 4:5e274bf85bf0 130 s.append(REGISTRATION_OPEN);
pnysten 4:5e274bf85bf0 131 s.append(REGISTRATION_SEPARATOR);
pnysten 4:5e274bf85bf0 132 s.append("3/0/2");
pnysten 4:5e274bf85bf0 133 s.append(REGISTRATION_CLOSE);
pnysten 6:540c5d907c90 134
pnysten 4:5e274bf85bf0 135 registration_Payload.append(s);
pnysten 4:5e274bf85bf0 136
pnysten 4:5e274bf85bf0 137 unsigned char *c = new unsigned char[registration_Payload.size()+1];
pnysten 4:5e274bf85bf0 138 copy(registration_Payload.begin(),registration_Payload.end(),c);
pnysten 4:5e274bf85bf0 139 c[registration_Payload.size()]='\0';
pnysten 4:5e274bf85bf0 140 *payload_size=registration_Payload.size();
pnysten 4:5e274bf85bf0 141
pnysten 4:5e274bf85bf0 142 return c;
pnysten 6:540c5d907c90 143
pnysten 4:5e274bf85bf0 144 }
pnysten 4:5e274bf85bf0 145 uint8_t * get_Token(int * size){
pnysten 4:5e274bf85bf0 146 srand(time(0)+_node_Id);
pnysten 4:5e274bf85bf0 147 long test=0;
pnysten 4:5e274bf85bf0 148 bool exist=false;
pnysten 4:5e274bf85bf0 149
pnysten 4:5e274bf85bf0 150 do{
pnysten 4:5e274bf85bf0 151 test=(rand() % UINT64_MAX);
pnysten 4:5e274bf85bf0 152
pnysten 4:5e274bf85bf0 153 }while (exist==true);
pnysten 4:5e274bf85bf0 154 uint8_t ones = 0xFF;
pnysten 4:5e274bf85bf0 155 *size=1;
pnysten 4:5e274bf85bf0 156 for (int i=0; i<8; ++i) {
pnysten 4:5e274bf85bf0 157 if ( (test>>8*i & ones) =='\0' || i==8) {
pnysten 4:5e274bf85bf0 158 *size=i;
pnysten 4:5e274bf85bf0 159 break;
pnysten 4:5e274bf85bf0 160 }
pnysten 4:5e274bf85bf0 161 }
pnysten 4:5e274bf85bf0 162 uint8_t * token =new uint8_t[*size];
pnysten 4:5e274bf85bf0 163 for (int i=0; i<*size; ++i){
pnysten 4:5e274bf85bf0 164 token[*size-1-i]=test>>8*i & ones;
pnysten 4:5e274bf85bf0 165 }
pnysten 4:5e274bf85bf0 166 return token;
pnysten 4:5e274bf85bf0 167 }
pnysten 6:540c5d907c90 168
pnysten 4:5e274bf85bf0 169 uint16_t get_Message_ID(){
pnysten 4:5e274bf85bf0 170 srand(time(0)+_node_Id);
pnysten 4:5e274bf85bf0 171 int test=0;
pnysten 4:5e274bf85bf0 172 bool exist=false;
pnysten 4:5e274bf85bf0 173 do{
pnysten 4:5e274bf85bf0 174
pnysten 4:5e274bf85bf0 175 exist=false;
pnysten 4:5e274bf85bf0 176 test=(rand() % UINT16_MAX);
pnysten 4:5e274bf85bf0 177
pnysten 4:5e274bf85bf0 178 }while (exist==true);
pnysten 4:5e274bf85bf0 179
pnysten 4:5e274bf85bf0 180
pnysten 4:5e274bf85bf0 181 return (uint16_t) test;
pnysten 4:5e274bf85bf0 182
pnysten 4:5e274bf85bf0 183 }
pnysten 6:540c5d907c90 184
pnysten 4:5e274bf85bf0 185 char * get_Registration_Query(){
pnysten 4:5e274bf85bf0 186
pnysten 4:5e274bf85bf0 187 string buffer;
pnysten 4:5e274bf85bf0 188 buffer.append(REGISTRATION_SEGMENT);
pnysten 4:5e274bf85bf0 189 buffer.append(ENDPOINT_SEGMENT);
pnysten 4:5e274bf85bf0 190 buffer.append(endPoint_Name);
pnysten 4:5e274bf85bf0 191 buffer.append(LIFETIME);
pnysten 4:5e274bf85bf0 192 buffer.append(to_string(lifeTime));
pnysten 4:5e274bf85bf0 193 buffer.append(BINDING);
pnysten 4:5e274bf85bf0 194 buffer.append(binding);
pnysten 4:5e274bf85bf0 195
pnysten 4:5e274bf85bf0 196 char *c = new char[buffer.size()+1];
pnysten 4:5e274bf85bf0 197 copy(buffer.begin(),buffer.end(),c);
pnysten 4:5e274bf85bf0 198 c[buffer.size()]='\0';
pnysten 4:5e274bf85bf0 199 return c;
pnysten 4:5e274bf85bf0 200
pnysten 6:540c5d907c90 201
pnysten 4:5e274bf85bf0 202 }
pnysten 6:540c5d907c90 203
mluis 0:a2929fa6e4f0 204 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 205 // CONFIGURATION (FOR APPLICATION CALLBACKS BELOW)
mluis 0:a2929fa6e4f0 206 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 207
mluis 0:a2929fa6e4f0 208 // application router ID (LSBF)
pnysten 9:84a69ca4d35a 209 //To be changed when switching from one to another
mluis 1:60184eda0066 210 static const uint8_t AppEui[8] =
mluis 0:a2929fa6e4f0 211 {
mluis 1:60184eda0066 212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
pnysten 6:540c5d907c90 213 // 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
mluis 0:a2929fa6e4f0 214 };
mluis 0:a2929fa6e4f0 215
mluis 0:a2929fa6e4f0 216 // unique device ID (LSBF)
pnysten 9:84a69ca4d35a 217 //To be changed when switching from one to another
mluis 0:a2929fa6e4f0 218 static const u1_t DevEui[8] =
mluis 0:a2929fa6e4f0 219 {
pnysten 6:540c5d907c90 220 // 0x00, 0x00, 0x00, 0x00, 0x08, 0x06, 0x02, 0x48
pnysten 6:540c5d907c90 221
pnysten 9:84a69ca4d35a 222 0x30, 0x74, 0x73, 0x65, 0x74, 0x2D, 0x52, 0x4C // 4c522d7465737430 = "LR-test0"
pnysten 6:540c5d907c90 223 // 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x99, 0xF7
pnysten 9:84a69ca4d35a 224 // 0x32, 0x74, 0x73, 0x65, 0x74, 0x2D, 0x52, 0x4C // 4c522d7465737430 = "LR-test2"
pnysten 6:540c5d907c90 225
pnysten 6:540c5d907c90 226
pnysten 4:5e274bf85bf0 227 // 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
pnysten 4:5e274bf85bf0 228 // 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x099, 0xF7
mluis 0:a2929fa6e4f0 229 };
mluis 0:a2929fa6e4f0 230
mluis 0:a2929fa6e4f0 231 // device-specific AES key (derived from device EUI)
mluis 1:60184eda0066 232 static const uint8_t DevKey[16] =
mluis 0:a2929fa6e4f0 233 {
pnysten 6:540c5d907c90 234 // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
pnysten 6:540c5d907c90 235 // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
mluis 1:60184eda0066 236 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
mluis 1:60184eda0066 237 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
mluis 0:a2929fa6e4f0 238 };
mluis 0:a2929fa6e4f0 239
mluis 1:60184eda0066 240 #if( OVER_THE_AIR_ACTIVATION == 0 )
mluis 1:60184eda0066 241 // network session key
pnysten 9:84a69ca4d35a 242 //To be changed when switching from one to another
mluis 0:a2929fa6e4f0 243 static uint8_t NwkSKey[] =
mluis 0:a2929fa6e4f0 244 {
mluis 0:a2929fa6e4f0 245 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
mluis 0:a2929fa6e4f0 246 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
pnysten 6:540c5d907c90 247 // 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3D
mluis 0:a2929fa6e4f0 248 };
mluis 0:a2929fa6e4f0 249
mluis 1:60184eda0066 250 // application session key
pnysten 9:84a69ca4d35a 251 //To be changed when switching from one to another
mluis 0:a2929fa6e4f0 252 static uint8_t ArtSKey[] =
mluis 0:a2929fa6e4f0 253 {
mluis 0:a2929fa6e4f0 254 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
mluis 0:a2929fa6e4f0 255 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
pnysten 6:540c5d907c90 256 // 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3D
mluis 0:a2929fa6e4f0 257 };
mluis 0:a2929fa6e4f0 258
mluis 1:60184eda0066 259 #endif
mluis 1:60184eda0066 260
mluis 0:a2929fa6e4f0 261 // LEDs and Frame jobs
mluis 0:a2929fa6e4f0 262 osjob_t rxLedJob;
mluis 0:a2929fa6e4f0 263 osjob_t txLedJob;
mluis 0:a2929fa6e4f0 264 osjob_t sendFrameJob;
mluis 0:a2929fa6e4f0 265
mluis 1:60184eda0066 266 // LED state
mluis 0:a2929fa6e4f0 267 static bool AppLedStateOn = false;
mluis 0:a2929fa6e4f0 268
mluis 0:a2929fa6e4f0 269 //////////////////////////////////////////////////
mluis 1:60184eda0066 270 // Utility functions
mluis 1:60184eda0066 271 //////////////////////////////////////////////////
mluis 1:60184eda0066 272 /*!
mluis 1:60184eda0066 273 * \brief Computes a random number between min and max
mluis 1:60184eda0066 274 *
mluis 1:60184eda0066 275 * \param [IN] min range minimum value
mluis 1:60184eda0066 276 * \param [IN] max range maximum value
mluis 1:60184eda0066 277 * \retval random random value in range min..max
mluis 1:60184eda0066 278 */
mluis 1:60184eda0066 279 int32_t randr( int32_t min, int32_t max )
mluis 1:60184eda0066 280 {
mluis 1:60184eda0066 281 return ( int32_t )rand( ) % ( max - min + 1 ) + min;
mluis 1:60184eda0066 282 }
mluis 1:60184eda0066 283
mluis 1:60184eda0066 284 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 285 // APPLICATION CALLBACKS
mluis 0:a2929fa6e4f0 286 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 287
mluis 0:a2929fa6e4f0 288 // provide application router ID (8 bytes, LSBF)
mluis 1:60184eda0066 289 void os_getArtEui( uint8_t *buf )
mluis 0:a2929fa6e4f0 290 {
mluis 0:a2929fa6e4f0 291 memcpy( buf, AppEui, 8 );
mluis 0:a2929fa6e4f0 292 }
mluis 0:a2929fa6e4f0 293
mluis 0:a2929fa6e4f0 294 // provide device ID (8 bytes, LSBF)
mluis 1:60184eda0066 295 void os_getDevEui( uint8_t *buf )
mluis 0:a2929fa6e4f0 296 {
mluis 0:a2929fa6e4f0 297 memcpy( buf, DevEui, 8 );
mluis 0:a2929fa6e4f0 298 }
mluis 0:a2929fa6e4f0 299
mluis 0:a2929fa6e4f0 300 // provide device key (16 bytes)
mluis 1:60184eda0066 301 void os_getDevKey( uint8_t *buf )
mluis 0:a2929fa6e4f0 302 {
mluis 0:a2929fa6e4f0 303 memcpy( buf, DevKey, 16 );
mluis 0:a2929fa6e4f0 304 }
mluis 0:a2929fa6e4f0 305
mluis 0:a2929fa6e4f0 306 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 307 // MAIN - INITIALIZATION AND STARTUP
mluis 0:a2929fa6e4f0 308 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 309
mluis 0:a2929fa6e4f0 310 static void onRxLed( osjob_t* j )
mluis 0:a2929fa6e4f0 311 {
mluis 1:60184eda0066 312 debug_val("LED2 = ", 0 );
mluis 0:a2929fa6e4f0 313 }
mluis 0:a2929fa6e4f0 314
mluis 0:a2929fa6e4f0 315 static void onTxLed( osjob_t* j )
mluis 0:a2929fa6e4f0 316 {
mluis 1:60184eda0066 317 debug_val("LED1 = ", 0 );
mluis 0:a2929fa6e4f0 318 }
mluis 0:a2929fa6e4f0 319
pnysten 6:540c5d907c90 320 static void prepareTxCoapFrame( void )
pnysten 6:540c5d907c90 321 {
pnysten 6:540c5d907c90 322 // Create Registration PDU :
pnysten 6:540c5d907c90 323
pnysten 6:540c5d907c90 324 CoapPDU *pdu = new CoapPDU();
pnysten 6:540c5d907c90 325
pnysten 6:540c5d907c90 326 pdu->setCode(CoapPDU::COAP_POST);
pnysten 6:540c5d907c90 327 pdu->setType(CoapPDU::COAP_CONFIRMABLE);
pnysten 6:540c5d907c90 328 int size;
pnysten 6:540c5d907c90 329 uint8_t * token = get_Token(&size);
pnysten 6:540c5d907c90 330 pdu->setToken(token,size);
pnysten 6:540c5d907c90 331 pdu->setMessageID(get_Message_ID());
pnysten 6:540c5d907c90 332 pdu->setURI(get_Registration_Query());
pnysten 6:540c5d907c90 333
pnysten 6:540c5d907c90 334 _payload=get_Registration_Payload(&_payload_size);
pnysten 6:540c5d907c90 335 pdu->setPayload(_payload, (int) _payload_size);
pnysten 6:540c5d907c90 336 int PDUlength = pdu->getPDULength();
pnysten 6:540c5d907c90 337
pnysten 6:540c5d907c90 338 // strncpy((char*) LMIC.frame, (const char*)pdu->getPDUPointer(), PDUlength);
pnysten 6:540c5d907c90 339 memcpy(LMIC.frame, pdu->getPDUPointer(), PDUlength * sizeof(uint8_t));
pnysten 6:540c5d907c90 340
pnysten 6:540c5d907c90 341 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
pnysten 6:540c5d907c90 342 LMIC.frame[PDUlength] = LMIC.seqnoDn >> 8;
pnysten 6:540c5d907c90 343 LMIC.frame[PDUlength+1] = LMIC.seqnoDn;
pnysten 6:540c5d907c90 344 LMIC.frame[PDUlength+2] = LMIC.rssi >> 8;
pnysten 6:540c5d907c90 345 LMIC.frame[PDUlength+3] = LMIC.rssi;
pnysten 6:540c5d907c90 346 LMIC.frame[PDUlength+4] = LMIC.snr;
pnysten 6:540c5d907c90 347 #endif
pnysten 6:540c5d907c90 348 debug_str("Frame to be sent: ");
pnysten 6:540c5d907c90 349 debug_buf(LMIC.frame, PDUlength + 5);
pnysten 6:540c5d907c90 350
pnysten 6:540c5d907c90 351 LoRaWAN_data_size = PDUlength + 5;
pnysten 6:540c5d907c90 352 }
pnysten 6:540c5d907c90 353
pnysten 8:8d9a49aaa323 354 static void prepareTxLoraFrame( void )
pnysten 8:8d9a49aaa323 355 {
pnysten 8:8d9a49aaa323 356 const char *frame = "LoRa";
pnysten 9:84a69ca4d35a 357 // const char *frame = "Test";
pnysten 8:8d9a49aaa323 358
pnysten 8:8d9a49aaa323 359 strncpy((char*) LMIC.frame, frame, strlen(frame));
pnysten 8:8d9a49aaa323 360
pnysten 8:8d9a49aaa323 361 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
pnysten 8:8d9a49aaa323 362 LMIC.frame[strlen(frame)] = LMIC.seqnoDn >> 8;
pnysten 8:8d9a49aaa323 363 LMIC.frame[strlen(frame)+1] = LMIC.seqnoDn;
pnysten 8:8d9a49aaa323 364 LMIC.frame[strlen(frame)+2] = LMIC.rssi >> 8;
pnysten 8:8d9a49aaa323 365 LMIC.frame[strlen(frame)+3] = LMIC.rssi;
pnysten 8:8d9a49aaa323 366 LMIC.frame[strlen(frame)+4] = LMIC.snr;
pnysten 8:8d9a49aaa323 367 #endif
pnysten 8:8d9a49aaa323 368 debug_str("Frame to be sent: ");
pnysten 9:84a69ca4d35a 369 // debug_buf(LMIC.frame, strlen(frame) + 5);
pnysten 9:84a69ca4d35a 370 debug_buf(LMIC.frame, strlen(frame));
pnysten 8:8d9a49aaa323 371
pnysten 9:84a69ca4d35a 372 // LoRaWAN_data_size = strlen(frame) + 5;
pnysten 9:84a69ca4d35a 373 LoRaWAN_data_size = strlen(frame);
pnysten 8:8d9a49aaa323 374 }
pnysten 8:8d9a49aaa323 375
mluis 0:a2929fa6e4f0 376 static void prepareTxFrame( void )
mluis 0:a2929fa6e4f0 377 {
mluis 0:a2929fa6e4f0 378 LMIC.frame[0] = AppLedStateOn;
mluis 1:60184eda0066 379 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
mluis 1:60184eda0066 380 LMIC.frame[1] = LMIC.seqnoDn >> 8;
mluis 1:60184eda0066 381 LMIC.frame[2] = LMIC.seqnoDn;
mluis 1:60184eda0066 382 LMIC.frame[3] = LMIC.rssi >> 8;
mluis 1:60184eda0066 383 LMIC.frame[4] = LMIC.rssi;
mluis 1:60184eda0066 384 LMIC.frame[5] = LMIC.snr;
mluis 1:60184eda0066 385 #endif
pnysten 6:540c5d907c90 386 debug_str("Frame to be sent: ");
pnysten 6:540c5d907c90 387 debug_buf(LMIC.frame, LORAWAN_APP_DATA_SIZE);
pnysten 6:540c5d907c90 388
pnysten 6:540c5d907c90 389 LoRaWAN_data_size = LORAWAN_APP_DATA_SIZE;
mluis 0:a2929fa6e4f0 390 }
mluis 0:a2929fa6e4f0 391
mluis 0:a2929fa6e4f0 392 void processRxFrame( void )
mluis 0:a2929fa6e4f0 393 {
pnysten 8:8d9a49aaa323 394
pnysten 8:8d9a49aaa323 395 char* frameToDisplay = (char*) (LMIC.frame + LMIC.dataBeg);
pnysten 8:8d9a49aaa323 396 frameToDisplay[LMIC.dataLen] = '\0';
pnysten 4:5e274bf85bf0 397
mluis 0:a2929fa6e4f0 398 switch( LMIC.frame[LMIC.dataBeg - 1] ) // Check Rx port number
mluis 0:a2929fa6e4f0 399 {
pnysten 4:5e274bf85bf0 400 case 0:
pnysten 4:5e274bf85bf0 401 // debug_str("Port 0!!!\r\n");
pnysten 4:5e274bf85bf0 402 // debug_val("Data Len: ", LMIC.dataLen);
pnysten 4:5e274bf85bf0 403
mluis 0:a2929fa6e4f0 404 case 1: // The application LED can be controlled on port 1 or 2
pnysten 8:8d9a49aaa323 405 debug_str("Data received on port 1: ");
pnysten 8:8d9a49aaa323 406 debug_str("Data in hexa: ");
pnysten 8:8d9a49aaa323 407 debug_buf( LMIC.frame + LMIC.dataBeg, LMIC.dataLen );
pnysten 8:8d9a49aaa323 408 debug_str("Data in string: ");
pnysten 8:8d9a49aaa323 409
pnysten 8:8d9a49aaa323 410 debug_str( frameToDisplay );
pnysten 8:8d9a49aaa323 411 debug_str("\r\n");
pnysten 8:8d9a49aaa323 412
pnysten 8:8d9a49aaa323 413 break;
mluis 0:a2929fa6e4f0 414 case 2:
pnysten 8:8d9a49aaa323 415 debug_str("Data received on port 2: ");
pnysten 8:8d9a49aaa323 416 debug_str("Data in hexa: ");
pnysten 8:8d9a49aaa323 417 debug_buf( LMIC.frame + LMIC.dataBeg, LMIC.dataLen );
pnysten 8:8d9a49aaa323 418 debug_str("Data in string: ");
pnysten 8:8d9a49aaa323 419
pnysten 8:8d9a49aaa323 420 debug_str( frameToDisplay );
pnysten 8:8d9a49aaa323 421 debug_str("\r\n");
pnysten 8:8d9a49aaa323 422
mluis 0:a2929fa6e4f0 423 if( LMIC.dataLen == 1 )
mluis 0:a2929fa6e4f0 424 {
pnysten 4:5e274bf85bf0 425 debug_str("Data received on port 2: ");
pnysten 4:5e274bf85bf0 426 debug_hex(LMIC.frame[LMIC.dataBeg]);
pnysten 4:5e274bf85bf0 427 debug_str("\r\n");
mluis 0:a2929fa6e4f0 428 AppLedStateOn = LMIC.frame[LMIC.dataBeg] & 0x01;
mluis 1:60184eda0066 429 debug_val( "LED3 = ", AppLedStateOn );
mluis 0:a2929fa6e4f0 430 }
mluis 0:a2929fa6e4f0 431 break;
mluis 0:a2929fa6e4f0 432 default:
mluis 0:a2929fa6e4f0 433 break;
mluis 0:a2929fa6e4f0 434 }
mluis 0:a2929fa6e4f0 435 }
mluis 0:a2929fa6e4f0 436
mluis 0:a2929fa6e4f0 437 static void onSendFrame( osjob_t* j )
mluis 0:a2929fa6e4f0 438 {
pnysten 6:540c5d907c90 439 //prepareTxFrame( );
pnysten 8:8d9a49aaa323 440 //prepareTxCoapFrame();
pnysten 8:8d9a49aaa323 441 prepareTxLoraFrame();
pnysten 4:5e274bf85bf0 442
pnysten 6:540c5d907c90 443 LMIC_setTxData2( LORAWAN_APP_PORT, LMIC.frame, LoRaWAN_data_size, LORAWAN_CONFIRMED_MSG_ON );
mluis 1:60184eda0066 444
mluis 1:60184eda0066 445 // Blink Tx LED
mluis 1:60184eda0066 446 debug_val( "LED1 = ", 1 );
mluis 1:60184eda0066 447 os_setTimedCallback( &txLedJob, os_getTime( ) + ms2osticks( 25 ), onTxLed );
mluis 0:a2929fa6e4f0 448 }
mluis 0:a2929fa6e4f0 449
mluis 1:60184eda0066 450 // Initialization job
mluis 1:60184eda0066 451 static void onInit( osjob_t* j )
mluis 1:60184eda0066 452 {
mluis 1:60184eda0066 453 // reset MAC state
mluis 1:60184eda0066 454 LMIC_reset( );
mluis 1:60184eda0066 455 LMIC_setAdrMode( LORAWAN_ADR_ON );
mluis 1:60184eda0066 456 LMIC_setDrTxpow( DR_SF12, 14 );
mluis 1:60184eda0066 457
mluis 1:60184eda0066 458 // start joining
mluis 1:60184eda0066 459 #if( OVER_THE_AIR_ACTIVATION != 0 )
mluis 1:60184eda0066 460 LMIC_startJoining( );
mluis 1:60184eda0066 461 #else
mluis 1:60184eda0066 462 LMIC_setSession( LORAWAN_NET_ID, LORAWAN_DEV_ADDR, NwkSKey, ArtSKey );
mluis 1:60184eda0066 463 onSendFrame( NULL );
mluis 1:60184eda0066 464 #endif
mluis 1:60184eda0066 465 // init done - onEvent( ) callback will be invoked...
mluis 1:60184eda0066 466 }
mluis 1:60184eda0066 467
mluis 1:60184eda0066 468 int main( void )
mluis 0:a2929fa6e4f0 469 {
pnysten 4:5e274bf85bf0 470 debug_init();
mluis 0:a2929fa6e4f0 471 osjob_t initjob;
pnysten 6:540c5d907c90 472
mluis 0:a2929fa6e4f0 473 // initialize runtime env
mluis 0:a2929fa6e4f0 474 os_init( );
mluis 0:a2929fa6e4f0 475 // setup initial job
mluis 0:a2929fa6e4f0 476 os_setCallback( &initjob, onInit );
mluis 0:a2929fa6e4f0 477 // execute scheduled jobs and events
mluis 0:a2929fa6e4f0 478 os_runloop( );
mluis 0:a2929fa6e4f0 479 // (not reached)
mluis 0:a2929fa6e4f0 480 }
mluis 0:a2929fa6e4f0 481
mluis 0:a2929fa6e4f0 482 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 483 // LMIC EVENT CALLBACK
mluis 0:a2929fa6e4f0 484 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 485 void onEvent( ev_t ev )
mluis 0:a2929fa6e4f0 486 {
mluis 0:a2929fa6e4f0 487 bool txOn = false;
mluis 1:60184eda0066 488 debug_event( ev );
mluis 0:a2929fa6e4f0 489
mluis 0:a2929fa6e4f0 490 switch( ev )
mluis 0:a2929fa6e4f0 491 {
mluis 0:a2929fa6e4f0 492 // network joined, session established
mluis 0:a2929fa6e4f0 493 case EV_JOINED:
mluis 1:60184eda0066 494 debug_val( "Net ID = ", LMIC.netid );
mluis 0:a2929fa6e4f0 495 txOn = true;
mluis 0:a2929fa6e4f0 496 break;
mluis 0:a2929fa6e4f0 497 // scheduled data sent (optionally data received)
mluis 0:a2929fa6e4f0 498 case EV_TXCOMPLETE:
mluis 1:60184eda0066 499 debug_val( "Datarate = ", LMIC.datarate );
mluis 0:a2929fa6e4f0 500 // Check if we have a downlink on either Rx1 or Rx2 windows
mluis 1:60184eda0066 501 if( ( LMIC.txrxFlags & ( TXRX_DNW1 | TXRX_DNW2 ) ) != 0 )
mluis 0:a2929fa6e4f0 502 {
mluis 1:60184eda0066 503 debug_val( "LED2 = ", 1 );
mluis 1:60184eda0066 504 os_setTimedCallback( &rxLedJob, os_getTime( ) + ms2osticks( 25 ), onRxLed );
mluis 0:a2929fa6e4f0 505
mluis 1:60184eda0066 506 if( LMIC.dataLen != 0 )
mluis 0:a2929fa6e4f0 507 { // data received in rx slot after tx
pnysten 4:5e274bf85bf0 508 //debug_buf( LMIC.frame + LMIC.dataBeg, LMIC.dataLen );
mluis 0:a2929fa6e4f0 509 processRxFrame( );
mluis 0:a2929fa6e4f0 510 }
mluis 0:a2929fa6e4f0 511 }
mluis 0:a2929fa6e4f0 512 txOn = true;
mluis 0:a2929fa6e4f0 513 break;
mluis 0:a2929fa6e4f0 514 default:
mluis 0:a2929fa6e4f0 515 break;
mluis 0:a2929fa6e4f0 516 }
mluis 0:a2929fa6e4f0 517 if( txOn == true )
mluis 0:a2929fa6e4f0 518 {
mluis 1:60184eda0066 519 //Sends frame every APP_TX_DUTYCYCLE +/- APP_TX_DUTYCYCLE_RND random time (if not duty cycle limited)
mluis 1:60184eda0066 520 os_setTimedCallback( &sendFrameJob,
mluis 1:60184eda0066 521 os_getTime( ) + ms2osticks( APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ) ),
mluis 1:60184eda0066 522 onSendFrame );
mluis 0:a2929fa6e4f0 523
mluis 1:60184eda0066 524 ////Sends frame as soon as possible (duty cylce limitations)
mluis 1:60184eda0066 525 //onSendFrame( NULL );
mluis 0:a2929fa6e4f0 526 }
mluis 0:a2929fa6e4f0 527 }