The Things Network 0.9 example for the Intel IoT Hackathon 2016 in Amsterdam

Dependencies:   LMiC SX1276Lib mbed

Fork of LoRaWAN-lmic-app by Semtech

Committer:
KarlNL
Date:
Sun Apr 24 08:10:41 2016 +0000
Revision:
4:2ab955d77be2
Parent:
3:ce28e3313a88
The Things Network based example

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 */
mluis 1:60184eda0066 15 #include "mbed.h"
mluis 1:60184eda0066 16
mluis 0:a2929fa6e4f0 17 #include "lmic.h"
mluis 1:60184eda0066 18 #include "debug.h"
mluis 0:a2929fa6e4f0 19
KarlNL 4:2ab955d77be2 20 AnalogIn analog_value(A1); //A0 is also the reset line
KarlNL 4:2ab955d77be2 21
mluis 0:a2929fa6e4f0 22 /*!
mluis 0:a2929fa6e4f0 23 * When set to 1 the application uses the Over-the-Air activation procedure
mluis 0:a2929fa6e4f0 24 * When set to 0 the application uses the Personalization activation procedure
mluis 0:a2929fa6e4f0 25 */
KarlNL 4:2ab955d77be2 26 #define OVER_THE_AIR_ACTIVATION 0
mluis 0:a2929fa6e4f0 27
mluis 1:60184eda0066 28 #if( OVER_THE_AIR_ACTIVATION == 0 )
mluis 1:60184eda0066 29
mluis 1:60184eda0066 30 /*!
mluis 1:60184eda0066 31 * Defines the network ID when using personalization activation procedure
mluis 1:60184eda0066 32 */
mluis 1:60184eda0066 33 #define LORAWAN_NET_ID ( uint32_t )0x00000000
mluis 1:60184eda0066 34
mluis 1:60184eda0066 35 /*!
mluis 1:60184eda0066 36 * Defines the device address when using personalization activation procedure
mluis 1:60184eda0066 37 */
KarlNL 4:2ab955d77be2 38 #define LORAWAN_DEV_ADDR ( uint32_t )0x07091970
mluis 1:60184eda0066 39
mluis 1:60184eda0066 40 #endif
mluis 1:60184eda0066 41
mluis 1:60184eda0066 42 /*!
mluis 1:60184eda0066 43 * Defines the application data transmission duty cycle
mluis 1:60184eda0066 44 */
mluis 1:60184eda0066 45 #define APP_TX_DUTYCYCLE 5000 // 5 [s] value in ms
mluis 1:60184eda0066 46 #define APP_TX_DUTYCYCLE_RND 1000 // 1 [s] value in ms
mluis 1:60184eda0066 47
mluis 1:60184eda0066 48 /*!
mluis 1:60184eda0066 49 * LoRaWAN Adaptative Data Rate
mluis 1:60184eda0066 50 */
mluis 1:60184eda0066 51 #define LORAWAN_ADR_ON 1
mluis 1:60184eda0066 52
mluis 1:60184eda0066 53 /*!
mluis 1:60184eda0066 54 * LoRaWAN confirmed messages
mluis 1:60184eda0066 55 */
mluis 1:60184eda0066 56 #define LORAWAN_CONFIRMED_MSG_ON 1
mluis 1:60184eda0066 57
mluis 1:60184eda0066 58 /*!
mluis 1:60184eda0066 59 * LoRaWAN application port
mluis 1:60184eda0066 60 */
mluis 1:60184eda0066 61 #define LORAWAN_APP_PORT 15
mluis 1:60184eda0066 62
mluis 1:60184eda0066 63 /*!
mluis 1:60184eda0066 64 * User application data buffer size
mluis 1:60184eda0066 65 */
mluis 1:60184eda0066 66 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
mluis 1:60184eda0066 67 #define LORAWAN_APP_DATA_SIZE 6
mluis 1:60184eda0066 68
mluis 1:60184eda0066 69 #else
mluis 1:60184eda0066 70 #define LORAWAN_APP_DATA_SIZE 1
mluis 1:60184eda0066 71
mluis 1:60184eda0066 72 #endif
mluis 0:a2929fa6e4f0 73
mluis 0:a2929fa6e4f0 74 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 75 // CONFIGURATION (FOR APPLICATION CALLBACKS BELOW)
mluis 0:a2929fa6e4f0 76 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 77
mluis 0:a2929fa6e4f0 78 // application router ID (LSBF)
mluis 1:60184eda0066 79 static const uint8_t AppEui[8] =
mluis 0:a2929fa6e4f0 80 {
KarlNL 4:2ab955d77be2 81 0x07, 0x09, 0x19, 0x70, 0x07, 0x09, 0x19, 0x70
mluis 0:a2929fa6e4f0 82 };
mluis 0:a2929fa6e4f0 83
mluis 0:a2929fa6e4f0 84 // unique device ID (LSBF)
mluis 0:a2929fa6e4f0 85 static const u1_t DevEui[8] =
mluis 0:a2929fa6e4f0 86 {
KarlNL 4:2ab955d77be2 87 0x07, 0x09, 0x19, 0x70, 0x07, 0x09, 0x19, 0x70
mluis 0:a2929fa6e4f0 88 };
mluis 0:a2929fa6e4f0 89
mluis 0:a2929fa6e4f0 90 // device-specific AES key (derived from device EUI)
mluis 1:60184eda0066 91 static const uint8_t DevKey[16] =
mluis 0:a2929fa6e4f0 92 {
mluis 1:60184eda0066 93 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
mluis 1:60184eda0066 94 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
mluis 0:a2929fa6e4f0 95 };
mluis 0:a2929fa6e4f0 96
mluis 1:60184eda0066 97 #if( OVER_THE_AIR_ACTIVATION == 0 )
mluis 1:60184eda0066 98 // network session key
mluis 0:a2929fa6e4f0 99 static uint8_t NwkSKey[] =
mluis 0:a2929fa6e4f0 100 {
mluis 0:a2929fa6e4f0 101 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
mluis 0:a2929fa6e4f0 102 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
mluis 0:a2929fa6e4f0 103 };
mluis 0:a2929fa6e4f0 104
mluis 1:60184eda0066 105 // application session key
mluis 0:a2929fa6e4f0 106 static uint8_t ArtSKey[] =
mluis 0:a2929fa6e4f0 107 {
mluis 0:a2929fa6e4f0 108 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
mluis 0:a2929fa6e4f0 109 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
mluis 0:a2929fa6e4f0 110 };
mluis 0:a2929fa6e4f0 111
mluis 1:60184eda0066 112 #endif
mluis 1:60184eda0066 113
mluis 0:a2929fa6e4f0 114 // LEDs and Frame jobs
mluis 0:a2929fa6e4f0 115 osjob_t rxLedJob;
mluis 0:a2929fa6e4f0 116 osjob_t txLedJob;
mluis 0:a2929fa6e4f0 117 osjob_t sendFrameJob;
mluis 0:a2929fa6e4f0 118
mluis 1:60184eda0066 119 // LED state
mluis 0:a2929fa6e4f0 120 static bool AppLedStateOn = false;
mluis 0:a2929fa6e4f0 121
mluis 0:a2929fa6e4f0 122 //////////////////////////////////////////////////
mluis 1:60184eda0066 123 // Utility functions
mluis 1:60184eda0066 124 //////////////////////////////////////////////////
mluis 1:60184eda0066 125 /*!
mluis 1:60184eda0066 126 * \brief Computes a random number between min and max
mluis 1:60184eda0066 127 *
mluis 1:60184eda0066 128 * \param [IN] min range minimum value
mluis 1:60184eda0066 129 * \param [IN] max range maximum value
mluis 1:60184eda0066 130 * \retval random random value in range min..max
mluis 1:60184eda0066 131 */
mluis 1:60184eda0066 132 int32_t randr( int32_t min, int32_t max )
mluis 1:60184eda0066 133 {
mluis 1:60184eda0066 134 return ( int32_t )rand( ) % ( max - min + 1 ) + min;
mluis 1:60184eda0066 135 }
mluis 1:60184eda0066 136
mluis 1:60184eda0066 137 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 138 // APPLICATION CALLBACKS
mluis 0:a2929fa6e4f0 139 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 140
mluis 0:a2929fa6e4f0 141 // provide application router ID (8 bytes, LSBF)
mluis 1:60184eda0066 142 void os_getArtEui( uint8_t *buf )
mluis 0:a2929fa6e4f0 143 {
mluis 0:a2929fa6e4f0 144 memcpy( buf, AppEui, 8 );
mluis 0:a2929fa6e4f0 145 }
mluis 0:a2929fa6e4f0 146
mluis 0:a2929fa6e4f0 147 // provide device ID (8 bytes, LSBF)
mluis 1:60184eda0066 148 void os_getDevEui( uint8_t *buf )
mluis 0:a2929fa6e4f0 149 {
mluis 0:a2929fa6e4f0 150 memcpy( buf, DevEui, 8 );
mluis 0:a2929fa6e4f0 151 }
mluis 0:a2929fa6e4f0 152
mluis 0:a2929fa6e4f0 153 // provide device key (16 bytes)
mluis 1:60184eda0066 154 void os_getDevKey( uint8_t *buf )
mluis 0:a2929fa6e4f0 155 {
mluis 0:a2929fa6e4f0 156 memcpy( buf, DevKey, 16 );
mluis 0:a2929fa6e4f0 157 }
mluis 0:a2929fa6e4f0 158
mluis 0:a2929fa6e4f0 159 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 160 // MAIN - INITIALIZATION AND STARTUP
mluis 0:a2929fa6e4f0 161 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 162
mluis 0:a2929fa6e4f0 163 static void onRxLed( osjob_t* j )
mluis 0:a2929fa6e4f0 164 {
mluis 1:60184eda0066 165 debug_val("LED2 = ", 0 );
mluis 0:a2929fa6e4f0 166 }
mluis 0:a2929fa6e4f0 167
mluis 0:a2929fa6e4f0 168 static void onTxLed( osjob_t* j )
mluis 0:a2929fa6e4f0 169 {
mluis 1:60184eda0066 170 debug_val("LED1 = ", 0 );
KarlNL 4:2ab955d77be2 171
mluis 0:a2929fa6e4f0 172 }
mluis 0:a2929fa6e4f0 173
mluis 0:a2929fa6e4f0 174 static void prepareTxFrame( void )
mluis 0:a2929fa6e4f0 175 {
KarlNL 4:2ab955d77be2 176 float meas;
KarlNL 4:2ab955d77be2 177 meas = analog_value.read(); // Converts and read the analog input value (value from 0.0 to 1.0)
KarlNL 4:2ab955d77be2 178 meas = meas * 18100; // Change the value to be roughly in the 0 to 15V range using a 4.7k/1k divider
KarlNL 4:2ab955d77be2 179 printf("measure = %.0f mV\n\r", meas);
KarlNL 4:2ab955d77be2 180 printf("measure fixed point = %u mV\n\r", (short) meas);
KarlNL 4:2ab955d77be2 181
KarlNL 4:2ab955d77be2 182 snprintf((char *)LMIC.frame, 7, "%.1f Volt", meas/1000.0);
KarlNL 4:2ab955d77be2 183
KarlNL 4:2ab955d77be2 184 // LMIC.frame[0] = (int) meas; //This is were the data of the measures value should go KB
KarlNL 4:2ab955d77be2 185 // LMIC.frame[1] = (int) meas >> 8;
KarlNL 4:2ab955d77be2 186 //#if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
KarlNL 4:2ab955d77be2 187 // LMIC.frame[2] = LMIC.seqnoDn >> 8;
KarlNL 4:2ab955d77be2 188 // LMIC.frame[3] = LMIC.seqnoDn;
KarlNL 4:2ab955d77be2 189 // LMIC.frame[4] = LMIC.rssi >> 8;
KarlNL 4:2ab955d77be2 190 // LMIC.frame[5] = LMIC.rssi;
KarlNL 4:2ab955d77be2 191 // LMIC.frame[6] = LMIC.snr;
KarlNL 4:2ab955d77be2 192 //LMIC.frame[0] = 0;
KarlNL 4:2ab955d77be2 193 //LMIC.frame[1] = 0;
KarlNL 4:2ab955d77be2 194 // LMIC.frame[2] = 0;
KarlNL 4:2ab955d77be2 195 // LMIC.frame[3] = 0;
KarlNL 4:2ab955d77be2 196 // LMIC.frame[4] = 0;
KarlNL 4:2ab955d77be2 197 // LMIC.frame[5] = 0;
KarlNL 4:2ab955d77be2 198 LMIC.frame[6] = 0;
KarlNL 4:2ab955d77be2 199
KarlNL 4:2ab955d77be2 200 printf("prepareTxFrame %02x %02x\r\n", LMIC.frame[0], LMIC.frame[1]);
KarlNL 4:2ab955d77be2 201
KarlNL 4:2ab955d77be2 202 //#endif
mluis 0:a2929fa6e4f0 203 }
mluis 0:a2929fa6e4f0 204
mluis 0:a2929fa6e4f0 205 void processRxFrame( void )
mluis 0:a2929fa6e4f0 206 {
mluis 0:a2929fa6e4f0 207 switch( LMIC.frame[LMIC.dataBeg - 1] ) // Check Rx port number
mluis 0:a2929fa6e4f0 208 {
mluis 0:a2929fa6e4f0 209 case 1: // The application LED can be controlled on port 1 or 2
mluis 0:a2929fa6e4f0 210 case 2:
mluis 0:a2929fa6e4f0 211 if( LMIC.dataLen == 1 )
mluis 0:a2929fa6e4f0 212 {
mluis 0:a2929fa6e4f0 213 AppLedStateOn = LMIC.frame[LMIC.dataBeg] & 0x01;
mluis 1:60184eda0066 214 debug_val( "LED3 = ", AppLedStateOn );
mluis 0:a2929fa6e4f0 215 }
mluis 0:a2929fa6e4f0 216 break;
mluis 0:a2929fa6e4f0 217 default:
mluis 0:a2929fa6e4f0 218 break;
mluis 0:a2929fa6e4f0 219 }
mluis 0:a2929fa6e4f0 220 }
mluis 0:a2929fa6e4f0 221
mluis 0:a2929fa6e4f0 222 static void onSendFrame( osjob_t* j )
mluis 0:a2929fa6e4f0 223 {
mluis 0:a2929fa6e4f0 224 prepareTxFrame( );
mluis 1:60184eda0066 225 LMIC_setTxData2( LORAWAN_APP_PORT, LMIC.frame, LORAWAN_APP_DATA_SIZE, LORAWAN_CONFIRMED_MSG_ON );
mluis 1:60184eda0066 226
mluis 1:60184eda0066 227 // Blink Tx LED
mluis 1:60184eda0066 228 debug_val( "LED1 = ", 1 );
mluis 1:60184eda0066 229 os_setTimedCallback( &txLedJob, os_getTime( ) + ms2osticks( 25 ), onTxLed );
mluis 0:a2929fa6e4f0 230 }
mluis 0:a2929fa6e4f0 231
mluis 1:60184eda0066 232 // Initialization job
mluis 1:60184eda0066 233 static void onInit( osjob_t* j )
mluis 1:60184eda0066 234 {
mluis 1:60184eda0066 235 // reset MAC state
mluis 1:60184eda0066 236 LMIC_reset( );
mluis 1:60184eda0066 237 LMIC_setAdrMode( LORAWAN_ADR_ON );
mluis 1:60184eda0066 238 LMIC_setDrTxpow( DR_SF12, 14 );
mluis 1:60184eda0066 239
mluis 1:60184eda0066 240 // start joining
mluis 1:60184eda0066 241 #if( OVER_THE_AIR_ACTIVATION != 0 )
mluis 1:60184eda0066 242 LMIC_startJoining( );
mluis 1:60184eda0066 243 #else
mluis 1:60184eda0066 244 LMIC_setSession( LORAWAN_NET_ID, LORAWAN_DEV_ADDR, NwkSKey, ArtSKey );
mluis 1:60184eda0066 245 onSendFrame( NULL );
mluis 1:60184eda0066 246 #endif
mluis 1:60184eda0066 247 // init done - onEvent( ) callback will be invoked...
mluis 1:60184eda0066 248 }
mluis 1:60184eda0066 249
mluis 1:60184eda0066 250 int main( void )
mluis 0:a2929fa6e4f0 251 {
mluis 0:a2929fa6e4f0 252 osjob_t initjob;
mluis 0:a2929fa6e4f0 253
mluis 0:a2929fa6e4f0 254 // initialize runtime env
mluis 0:a2929fa6e4f0 255 os_init( );
mluis 0:a2929fa6e4f0 256 // setup initial job
mluis 0:a2929fa6e4f0 257 os_setCallback( &initjob, onInit );
mluis 0:a2929fa6e4f0 258 // execute scheduled jobs and events
mluis 0:a2929fa6e4f0 259 os_runloop( );
mluis 0:a2929fa6e4f0 260 // (not reached)
mluis 0:a2929fa6e4f0 261 }
mluis 0:a2929fa6e4f0 262
mluis 0:a2929fa6e4f0 263 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 264 // LMIC EVENT CALLBACK
mluis 0:a2929fa6e4f0 265 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 266 void onEvent( ev_t ev )
mluis 0:a2929fa6e4f0 267 {
mluis 0:a2929fa6e4f0 268 bool txOn = false;
mluis 1:60184eda0066 269 debug_event( ev );
mluis 0:a2929fa6e4f0 270
mluis 0:a2929fa6e4f0 271 switch( ev )
mluis 0:a2929fa6e4f0 272 {
mluis 0:a2929fa6e4f0 273 // network joined, session established
mluis 0:a2929fa6e4f0 274 case EV_JOINED:
mluis 1:60184eda0066 275 debug_val( "Net ID = ", LMIC.netid );
mluis 0:a2929fa6e4f0 276 txOn = true;
mluis 0:a2929fa6e4f0 277 break;
mluis 0:a2929fa6e4f0 278 // scheduled data sent (optionally data received)
mluis 0:a2929fa6e4f0 279 case EV_TXCOMPLETE:
mluis 1:60184eda0066 280 debug_val( "Datarate = ", LMIC.datarate );
mluis 0:a2929fa6e4f0 281 // Check if we have a downlink on either Rx1 or Rx2 windows
mluis 1:60184eda0066 282 if( ( LMIC.txrxFlags & ( TXRX_DNW1 | TXRX_DNW2 ) ) != 0 )
mluis 0:a2929fa6e4f0 283 {
mluis 1:60184eda0066 284 debug_val( "LED2 = ", 1 );
mluis 1:60184eda0066 285 os_setTimedCallback( &rxLedJob, os_getTime( ) + ms2osticks( 25 ), onRxLed );
mluis 0:a2929fa6e4f0 286
mluis 1:60184eda0066 287 if( LMIC.dataLen != 0 )
mluis 0:a2929fa6e4f0 288 { // data received in rx slot after tx
mluis 1:60184eda0066 289 debug_buf( LMIC.frame + LMIC.dataBeg, LMIC.dataLen );
mluis 0:a2929fa6e4f0 290 processRxFrame( );
mluis 0:a2929fa6e4f0 291 }
mluis 0:a2929fa6e4f0 292 }
mluis 0:a2929fa6e4f0 293 txOn = true;
mluis 0:a2929fa6e4f0 294 break;
mluis 0:a2929fa6e4f0 295 default:
mluis 0:a2929fa6e4f0 296 break;
mluis 0:a2929fa6e4f0 297 }
mluis 0:a2929fa6e4f0 298 if( txOn == true )
mluis 0:a2929fa6e4f0 299 {
mluis 1:60184eda0066 300 //Sends frame every APP_TX_DUTYCYCLE +/- APP_TX_DUTYCYCLE_RND random time (if not duty cycle limited)
mluis 1:60184eda0066 301 os_setTimedCallback( &sendFrameJob,
mluis 1:60184eda0066 302 os_getTime( ) + ms2osticks( APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ) ),
mluis 1:60184eda0066 303 onSendFrame );
mluis 0:a2929fa6e4f0 304
mluis 1:60184eda0066 305 ////Sends frame as soon as possible (duty cylce limitations)
mluis 1:60184eda0066 306 //onSendFrame( NULL );
mluis 0:a2929fa6e4f0 307 }
mluis 0:a2929fa6e4f0 308 }