PIR + LoRa
Dependencies: BLE_API LMiC SX1276Lib mbed nRF51822 nrf51_rtc
Fork of BLE_PhysicalWeb by
main.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "mbed.h" 00018 #include "BLEDevice.h" 00019 #include "URIBeaconConfigService.h" 00020 #include "DFUService.h" 00021 #include "DeviceInformationService.h" 00022 #include "nrf51_rtc/nrf51_rtc.h" 00023 00024 #include "lmic.h" 00025 #include "oslmic.h" 00026 #include "debug.h" 00027 00028 /*! 00029 * When set to 1 the application uses the Over-the-Air activation procedure 00030 * When set to 0 the application uses the Personalization activation procedure 00031 */ 00032 #define OVER_THE_AIR_ACTIVATION 1 00033 00034 #if( OVER_THE_AIR_ACTIVATION == 0 ) 00035 00036 /*! 00037 * Defines the network ID when using personalization activation procedure 00038 */ 00039 #define LORAWAN_NET_ID ( uint32_t )0x00000000 00040 00041 /*! 00042 * Defines the device address when using personalization activation procedure 00043 */ 00044 #define LORAWAN_DEV_ADDR ( uint32_t )0x73318891 00045 00046 #endif 00047 00048 /*! 00049 * Defines the application data transmission duty cycle 00050 */ 00051 #define APP_TX_DUTYCYCLE 5000 // 5 [s] value in ms 00052 #define APP_TX_DUTYCYCLE_RND 1000 // 1 [s] value in ms 00053 00054 /*! 00055 * LoRaWAN Adaptative Data Rate 00056 */ 00057 #define LORAWAN_ADR_ON 1 00058 00059 /*! 00060 * LoRaWAN confirmed messages 00061 */ 00062 #define LORAWAN_CONFIRMED_MSG_ON 0 00063 00064 /*! 00065 * LoRaWAN application port 00066 */ 00067 #define LORAWAN_APP_PORT 2 00068 00069 /*! 00070 * User application data buffer size 00071 */ 00072 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 ) 00073 #define LORAWAN_APP_DATA_SIZE 9 00074 00075 #else 00076 #define LORAWAN_APP_DATA_SIZE 4 00077 00078 #endif 00079 00080 ////////////////////////////////////////////////// 00081 // CONFIGURATION (FOR APPLICATION CALLBACKS BELOW) 00082 ////////////////////////////////////////////////// 00083 00084 // application router ID (LSBF) 00085 static const uint8_t AppEui[8] = 00086 { // 13-37-aa-bb-cc-dd-ee-ff 00087 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x37, 0x13 00088 // so its read rtl in the NS so when creating need to flip it in server 00089 // compared to here. Really weird. 00090 }; 00091 00092 // unique device ID (LSBF) 00093 static const u1_t DevEui[8] = 00094 { 00095 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF 00096 }; 00097 00098 // device-specific AES key (derived from device EUI) 00099 static const uint8_t DevKey[16] = 00100 { 00101 0xC1, 0x20, 0x2B, 0xB0, 0xAE, 0x97, 0x20, 0xC8, 00102 0x18, 0xA3, 0x0F, 0xFA, 0x05, 0x14, 0xC5, 0x4F 00103 }; 00104 00105 #if( OVER_THE_AIR_ACTIVATION == 0 ) 00106 // network session key 00107 static uint8_t NwkSKey[] = 00108 { 00109 0x50, 0x12, 0x78, 0x26, 0x23, 0x9A, 0x5E, 0x39, 00110 0x86, 0x8A, 0xCA, 0x7B, 0xDE, 0x16, 0xE1, 0x32 00111 }; 00112 static uint8_t ArtSKey[] = 00113 { 00114 0x54, 0xEB, 0x54, 0x4B, 0x07, 0x0C, 0x10, 0x69, 00115 0xB1, 0x44, 0x94, 0x44, 0xF1, 0xCC, 0x13, 0xDA 00116 }; 00117 00118 #endif 00119 00120 Serial pc(USBTX, USBRX); // tx, rx 00121 00122 // LEDs and Frame jobs 00123 osjob_t rxLedJob; 00124 osjob_t txLedJob; 00125 osjob_t sendFrameJob; 00126 00127 // LED state 00128 static bool AppLedStateOn = false; 00129 00130 ////////////////////////////////////////////////// 00131 // Utility functions 00132 ////////////////////////////////////////////////// 00133 /*! 00134 * \brief Computes a random number between min and max 00135 * 00136 * \param [IN] min range minimum value 00137 * \param [IN] max range maximum value 00138 * \retval random random value in range min..max 00139 */ 00140 int32_t randr( int32_t min, int32_t max ) 00141 { 00142 return ( int32_t )rand( ) % ( max - min + 1 ) + min; 00143 } 00144 00145 ////////////////////////////////////////////////// 00146 // APPLICATION CALLBACKS 00147 ////////////////////////////////////////////////// 00148 00149 // provide application router ID (8 bytes, LSBF) 00150 void os_getArtEui( uint8_t *buf ) 00151 { 00152 memcpy( buf, AppEui, 8 ); 00153 } 00154 00155 // provide device ID (8 bytes, LSBF) 00156 void os_getDevEui( uint8_t *buf ) 00157 { 00158 memcpy( buf, DevEui, 8 ); 00159 } 00160 00161 // provide device key (16 bytes) 00162 void os_getDevKey( uint8_t *buf ) 00163 { 00164 memcpy( buf, DevKey, 16 ); 00165 } 00166 00167 ////////////////////////////////////////////////// 00168 // MAIN - INITIALIZATION AND STARTUP 00169 ////////////////////////////////////////////////// 00170 00171 static void onRxLed( osjob_t* j ) 00172 { 00173 debug_val("LED2 = ", 0 ); 00174 } 00175 00176 static void onTxLed( osjob_t* j ) 00177 { 00178 debug_val("LED1 = ", 0 ); 00179 } 00180 00181 bool rise_state = false; 00182 uint16_t last_rise = 0; 00183 00184 static void prepareTxFrame( void ) 00185 { 00186 uint16_t seconds_ago = rtc.time() - last_rise; 00187 00188 LMIC.frame[0] = 0x02; // PIR sensor 00189 LMIC.frame[1] = rise_state ? 1 : 0; 00190 LMIC.frame[2] = ( seconds_ago >> 8 ) & 0xFF; 00191 LMIC.frame[3] = seconds_ago & 0xFF; 00192 00193 printf("prepareTxFrame %02x %02x %02x %02x\r\n", 00194 LMIC.frame[0], LMIC.frame[1], LMIC.frame[2], LMIC.frame[3]); 00195 00196 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 ) 00197 LMIC.frame[4] = LMIC.seqnoDn >> 8; 00198 LMIC.frame[5] = LMIC.seqnoDn; 00199 LMIC.frame[6] = LMIC.rssi >> 8; 00200 LMIC.frame[7] = LMIC.rssi; 00201 LMIC.frame[8] = LMIC.snr; 00202 #endif 00203 } 00204 00205 static void prepareTxFrameLoRaMote( void ) 00206 { 00207 pc.printf("prepareTxFrameLoRaMote\r\n"); 00208 00209 uint16_t pressure = 0; 00210 int16_t altitudeBar = 0; 00211 int16_t temperature = 0; 00212 int32_t latitude, longitude = 0; 00213 uint16_t altitudeGps = 0xFFFF; 00214 uint8_t batteryLevel = 0; 00215 00216 pressure = 10132; // in hPa / 10 00217 temperature = 2300; // in °C * 100 00218 altitudeBar = 70; // in m * 10 00219 batteryLevel = 160; // 1 (very low) to 254 (fully charged) 00220 altitudeGps = 73; // in m 00221 00222 LMIC.frame[0] = AppLedStateOn; 00223 LMIC.frame[1] = ( pressure >> 8 ) & 0xFF; 00224 LMIC.frame[2] = pressure & 0xFF; 00225 LMIC.frame[3] = ( temperature >> 8 ) & 0xFF; 00226 LMIC.frame[4] = temperature & 0xFF; 00227 LMIC.frame[5] = ( altitudeBar >> 8 ) & 0xFF; 00228 LMIC.frame[6] = altitudeBar & 0xFF; 00229 LMIC.frame[7] = batteryLevel; 00230 LMIC.frame[8] = ( latitude >> 16 ) & 0xFF; 00231 LMIC.frame[9] = ( latitude >> 8 ) & 0xFF; 00232 LMIC.frame[10] = latitude & 0xFF; 00233 LMIC.frame[11] = ( longitude >> 16 ) & 0xFF; 00234 LMIC.frame[12] = ( longitude >> 8 ) & 0xFF; 00235 LMIC.frame[13] = longitude & 0xFF; 00236 LMIC.frame[14] = ( altitudeGps >> 8 ) & 0xFF; 00237 LMIC.frame[15] = altitudeGps & 0xFF; 00238 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 ) 00239 LMIC.frame[16] = LMIC.seqnoDn >> 8; 00240 LMIC.frame[17] = LMIC.seqnoDn; 00241 LMIC.frame[18] = LMIC.rssi >> 8; 00242 LMIC.frame[19] = LMIC.rssi; 00243 LMIC.frame[20] = LMIC.snr; 00244 #endif 00245 } 00246 00247 DigitalOut led2(LED2); 00248 00249 void processRxFrame( void ) 00250 { 00251 switch( LMIC.frame[LMIC.dataBeg - 1] ) // Check Rx port number 00252 { 00253 case 1: // The application LED can be controlled on port 1 or 2 00254 case 2: 00255 if( LMIC.dataLen == 1 ) 00256 { 00257 AppLedStateOn = LMIC.frame[LMIC.dataBeg] & 0x01; 00258 led2 = AppLedStateOn; 00259 debug_val( "LED3 = ", AppLedStateOn ); 00260 } 00261 break; 00262 default: 00263 break; 00264 } 00265 } 00266 00267 static void onSendFrame( osjob_t* j ) 00268 { 00269 prepareTxFrame( ); 00270 LMIC_setTxData2( LORAWAN_APP_PORT, LMIC.frame, LORAWAN_APP_DATA_SIZE, LORAWAN_CONFIRMED_MSG_ON ); 00271 00272 // Blink Tx LED 00273 debug_val( "LED1 = ", 1 ); 00274 os_setTimedCallback( &txLedJob, os_getTime( ) + ms2osticks( 25 ), onTxLed ); 00275 } 00276 00277 // Initialization job 00278 static void onInit( osjob_t* j ) 00279 { 00280 // reset MAC state 00281 LMIC_reset( ); 00282 LMIC_setAdrMode( LORAWAN_ADR_ON ); 00283 LMIC_setDrTxpow( DR_SF12, 14 ); 00284 00285 // start joining 00286 #if( OVER_THE_AIR_ACTIVATION != 0 ) 00287 pc.printf("startJoining\n"); 00288 LMIC_startJoining( ); 00289 #else 00290 pc.printf("gonne send a frame yo\n"); 00291 LMIC_setSession( LORAWAN_NET_ID, LORAWAN_DEV_ADDR, NwkSKey, ArtSKey ); 00292 onSendFrame( NULL ); 00293 #endif 00294 // init done - onEvent( ) callback will be invoked... 00295 } 00296 00297 //int main( void ) 00298 //{ 00299 // osjob_t initjob; 00300 // 00301 // // initialize runtime env 00302 // os_init( ); 00303 // // setup initial job 00304 // os_setCallback( &initjob, onInit ); 00305 // // execute scheduled jobs and events 00306 // os_runloop( ); 00307 // // (not reached) 00308 //} 00309 00310 ////////////////////////////////////////////////// 00311 // LMIC EVENT CALLBACK 00312 ////////////////////////////////////////////////// 00313 void onEvent( ev_t ev ) 00314 { 00315 pc.printf("onEvent\r\n"); 00316 bool txOn = false; 00317 debug_event( ev ); 00318 00319 switch( ev ) 00320 { 00321 // network joined, session established 00322 case EV_JOINED: 00323 pc.printf("Joined, ID=%d\n", LMIC.netid); 00324 debug_val( "Net ID = ", LMIC.netid ); 00325 txOn = true; 00326 break; 00327 // scheduled data sent (optionally data received) 00328 case EV_TXCOMPLETE: 00329 pc.printf("TXComplete, datarate=%d\n", LMIC.datarate); 00330 debug_val( "Datarate = ", LMIC.datarate ); 00331 // Check if we have a downlink on either Rx1 or Rx2 windows 00332 if( ( LMIC.txrxFlags & ( TXRX_DNW1 | TXRX_DNW2 ) ) != 0 ) 00333 { 00334 debug_val( "LED2 = ", 1 ); 00335 os_setTimedCallback( &rxLedJob, os_getTime( ) + ms2osticks( 25 ), onRxLed ); 00336 00337 if( LMIC.dataLen != 0 ) 00338 { // data received in rx slot after tx 00339 debug_buf( LMIC.frame + LMIC.dataBeg, LMIC.dataLen ); 00340 processRxFrame( ); 00341 } 00342 } 00343 txOn = true; 00344 break; 00345 default: 00346 break; 00347 } 00348 if( txOn == true ) 00349 { 00350 //Sends frame every APP_TX_DUTYCYCLE +/- APP_TX_DUTYCYCLE_RND random time (if not duty cycle limited) 00351 os_setTimedCallback( &sendFrameJob, 00352 os_getTime( ) + ms2osticks( APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ) ), 00353 onSendFrame ); 00354 00355 ////Sends frame as soon as possible (duty cylce limitations) 00356 //onSendFrame( NULL ); 00357 } 00358 } 00359 00360 00361 InterruptIn motion(p7); 00362 DigitalOut led(LED4); 00363 00364 BLEDevice ble; 00365 URIBeaconConfigService *uriBeaconConfig; 00366 00367 void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) 00368 { 00369 ble.startAdvertising(); 00370 } 00371 00372 void riseHandler(void) 00373 { 00374 led = 0; 00375 pc.printf("rise\r\n"); 00376 last_rise = rtc.time(); 00377 rise_state = true; 00378 } 00379 00380 void fallHandler(void) 00381 { 00382 led = 1; 00383 pc.printf("fall\r\n"); 00384 last_rise = rtc.time(); 00385 rise_state = false; 00386 } 00387 00388 void lastRiseCallback(void) 00389 { 00390 pc.printf("Current state %d, last_rise %d\r\n", rise_state, rtc.time() - last_rise); 00391 } 00392 00393 void run_ble() { 00394 ble.init(); 00395 ble.onDisconnection(disconnectionCallback); 00396 00397 uriBeaconConfig = new URIBeaconConfigService(ble, "http://goo.gl/H9YK6O"); 00398 if (!uriBeaconConfig->configuredSuccessfully()) { 00399 error("failed to accommodate URI"); 00400 } 00401 /* optional use of the API offered by URIBeaconConfigService */ 00402 const int8_t powerLevels[] = {-20, -4, 0, 10}; 00403 uriBeaconConfig->setTxPowerLevels(powerLevels); 00404 uriBeaconConfig->setTxPowerMode(URIBeaconConfigService::TX_POWER_MODE_HIGH); 00405 00406 static const uint8_t BEACON_UUID[] = {0xD8, 0xFE}; 00407 static const uint8_t urldata[] = { 00408 BEACON_UUID[0], 00409 BEACON_UUID[1], 00410 0x00, // flags 00411 0x20, // power 00412 0x00, // http://www. 00413 'g', 00414 'o', 00415 'o', 00416 '.', 00417 'g', 00418 'l', 00419 '/', 00420 'H', 00421 '9', 00422 'Y', 00423 'K', 00424 '6', 00425 'O', 00426 }; 00427 00428 ble.clearAdvertisingPayload(); 00429 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, BEACON_UUID, sizeof(BEACON_UUID)); 00430 ble.accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, urldata, sizeof(urldata)); 00431 00432 ble.setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED); 00433 ble.setAdvertisingInterval(800); /* .5s; in multiples of 0.625ms. */ 00434 ble.startAdvertising(); 00435 } 00436 00437 int main(void) 00438 { 00439 Ticker ticker; 00440 ticker.attach(&lastRiseCallback, 10); 00441 00442 motion.rise(&riseHandler); 00443 motion.fall(&fallHandler); 00444 00445 run_ble(); 00446 00447 // run_ble(); 00448 00449 // osjob_t initjob; 00450 //// 00451 // // initialize runtime env 00452 // os_init( ); 00453 // // setup initial job 00454 // os_setCallback( &initjob, onInit ); 00455 // 00456 // os_runloop(); 00457 00458 while (true) { 00459 // execute scheduled jobs and events 00460 // os_inner_loop(); 00461 ble.waitForEvent(); 00462 } 00463 00464 00465 00466 // os_runloop( ); 00467 // (not reached) 00468 }
Generated on Tue Jul 12 2022 12:34:27 by 1.7.2