BLE ADV Gateway, converts advertisement to proper JSON serial output

Dependencies:   BLE_API mbed mbedtls nRF51822

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*  
00002  * Copyright (c) Eric Tsai 2017
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  * Credit:  I started with the basic BLE_Observer code from mbed Bluetooth Low Energy team
00018  * https://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_Observer/file/88f50499af9a/main.cpp
00019  *
00020  *
00021  *
00022  * This BLE advertisement observer looks for specific advertisements from intended bacons
00023  * and outputs beacon data as json over serial.  Compiled and tested for nRF51822 on mbed.
00024 */
00025 
00026 #include "mbed.h"   //revision 148
00027 #include "ble/BLE.h"
00028 #include "mbedtls/aes.h"    //derived from the standard mbedtls.  Modified for smaller build.  See project.
00029 
00030 
00031 #define MyDebugEnb 0    //change to 1 for debug out of the same serial as intended output
00032 
00033 
00034 Ticker     ticker;
00035 
00036 //clock periodicity used for spoof checking, should be 1800 seconds for 30minutes
00037 //make sure matches periodicity of beacons for correct operation
00038 const uint16_t Periodicity = 1800;   
00039 
00040 //aes
00041 uint8_t src_buf[16] = {0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4};
00042 uint8_t des_buf[16] = {0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4};
00043 mbedtls_aes_context aes;
00044 unsigned char iv[16] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x1, 0x2};       //16-byte aes key
00045 
00046 //Serial device(p9, p11);  //nRF51822 uart:  TX=p9.  RX=p11
00047 Serial device(p9, p11);  //nRF51822 uart:  TX=p9.  RX=p11
00048 DigitalIn pinHandShake(p0);  //handshake uart to prevent output before bridge MCU is ready.  Flow control.
00049 
00050 //data structures for tracking wake time of BLE end nodes, for to prevent spoofing
00051 struct MAC_Birth_Record
00052 {
00053     uint8_t MAC_Addr[6]; //mac[0] is low order byte in mac address
00054     uint16_t MAC_Time;  //The time of birth for this end node
00055     uint16_t Attempt_MAC_Time;
00056     uint8_t Attempt_Cnt;
00057     uint8_t Xmit_Cnt;
00058 };
00059 const uint8_t sizeOfSpoof = 50; //translates to the number of unique BLE modules this gateway should receive
00060 MAC_Birth_Record Spoof_Check[sizeOfSpoof];   //array tracking end node birth times
00061 uint8_t Spoof_Ray_Tail = 0;         //array index for next record
00062 uint8_t Received_MAC_Addr[6]; //mac[0] is low order byte in mac address
00063 uint16_t Received_MAC_Time;     //global var to hold MAC for processing the current ADV
00064 static Timer Gateway_Time;  //global for the # seconds within each "Periodicity" cycle, each 30 minute chunk.
00065 static uint16_t Expected_MAC_Time;  //holds Gateway Time Zone value for  Beacon's birth time indicated by ADV
00066 uint8_t Received_Xmit_Cnt;  //global var to hold xmit count for processing the current ADV
00067 const uint8_t Allowance = 5;  //number of seconds allowed for MAC Birthtime mismatch
00068 
00069 // possible return values for Is_Not_Spoofed()
00070 const uint8_t ADVisUnknown = 0;     //Unaccounted for advertisement type, should never happen
00071 const uint8_t ADVisNew = 1;             //first time seeing this MAC address
00072 const uint8_t ADVisDuplicate = 2;       //packet is one of the duplicate advertisement
00073 const uint8_t ADVisSpoof = 3;           //birth times do not match
00074 
00075 uint8_t MAC_gateway[6] = {0x0,0x0,0x0,0x0,0x0,0x0};  //mac address of this gateway BLE module
00076 
00077 //********************
00078 // Checks if Beacon's transmitted MAC birth time matches and gateway's recorded MAC birth time.
00079 // Takes into account 30-minute clock, takes care of edge cases for wrap around
00080 // returns:
00081 //      TRUE:  if sensor's reported time lines up to gateway's recorded time
00082 //********************
00083 bool Is_Birth_Time_Correct (uint16_t gateway_mac_time, uint16_t sensor_mac_time, uint8_t margin)
00084 {
00085     bool return_val = 0;
00086     uint16_t current_time = (uint16_t)(Gateway_Time.read_ms()/1000);
00087     int16_t gateway_time_zone = current_time - sensor_mac_time;
00088     
00089     if (current_time >= sensor_mac_time)        //simple time translation
00090     {
00091         Expected_MAC_Time = current_time - sensor_mac_time;
00092     }
00093     else        //wrap around time given periodicity
00094     {
00095         Expected_MAC_Time = (Periodicity - sensor_mac_time + current_time);
00096     }
00097     
00098     //todo:  perhaps return true if count is 0 to avoid 3-transmits needed to confirm devices that were reset?  Meh.
00099     if (1) 
00100     {
00101         //We can't be too stringent that beacon MAC time precisely matches recorded time, because we're advertising 
00102         // the same data over several seconds.  Not bothering to update the MAC time of each ADV within same event.
00103         // Pick margin time (in seconds) based on how many seconds the beacon is advertising, to give this alloweance
00104         // For example, you want to be more certain that beacon seen by gateway, and you increase the number of seconds
00105         // you advertise for from 2 to 4 seconds.  Then Margin has to be likewise increased to 4 seconds.
00106         // Increasing probably that Beacon is seen results in slightly compromised spoof-detection.
00107         if ( (gateway_mac_time < (Expected_MAC_Time + margin)) && (gateway_mac_time > (Expected_MAC_Time - margin)) )
00108         {
00109             return_val = 1;
00110         }
00111         else
00112         {
00113             return_val = 0;
00114             
00115         }  
00116     }
00117 
00118     return return_val;
00119 }//end Is_Birth_Time_Correct
00120 
00121 
00122 
00123 /* ****************************************
00124 iterates Beacon adv against all mac birth records to detect spoofing, repeats, and
00125 add device to birth records if new
00126 
00127 returns
00128     ADVisNew = 1                First time seeing this MAC address
00129     ADVisDuplicate = 2         Subsequent advertisements for same event
00130     ADVisSpoof = 3              MAC times do not match
00131     ADVisUnknown = 0        Shouldn't encounter this, debug
00132 *******************************************/
00133 uint8_t Is_Not_Spoofed ()
00134 {
00135     uint8_t return_val = ADVisUnknown;
00136     
00137     //iterate through all of birth records looking for one that matches MAC address
00138     for (int i=0; i<sizeOfSpoof; i++)
00139     {
00140         //Search for matching MAC address
00141         if (Spoof_Check[i].MAC_Addr[0] == Received_MAC_Addr[0] &&
00142             Spoof_Check[i].MAC_Addr[1] == Received_MAC_Addr[1] &&
00143             Spoof_Check[i].MAC_Addr[2] == Received_MAC_Addr[2] &&
00144             Spoof_Check[i].MAC_Addr[3] == Received_MAC_Addr[3] &&
00145             Spoof_Check[i].MAC_Addr[4] == Received_MAC_Addr[4] &&
00146             Spoof_Check[i].MAC_Addr[5] == Received_MAC_Addr[5])
00147         {
00148             #if MyDebugEnb
00149             device.printf("found MAC address in array\r\n");
00150             device.printf("   Index = %d \r\n", i);
00151             device.printf("   MAC = %02x:%02x:%02x:%02x:%02x:%02x \r\n", Received_MAC_Addr[5],Received_MAC_Addr[4],Received_MAC_Addr[3],Received_MAC_Addr[2],Received_MAC_Addr[1],Received_MAC_Addr[0]);
00152             device.printf("   Received MAC Time =  %d \r\n", Received_MAC_Time);
00153             device.printf("   Gateway time = %d \r\n", (uint16_t)(Gateway_Time.read_ms()/1000));
00154             device.printf("   Array.MAC_Time =  %d \r\n", Spoof_Check[i].MAC_Time);
00155             device.printf("   Array.Attempt_MAC_Time =  %d \r\n", Spoof_Check[i].Attempt_MAC_Time);
00156             device.printf("   Array.Attempt_Cnt =  %d \r\n", Spoof_Check[i].Attempt_Cnt);
00157             device.printf("   Array.Xmit_Cnt =  %d \r\n", Spoof_Check[i].Xmit_Cnt);
00158             device.printf("   expected time =  %d \r\n", ((uint16_t)(Gateway_Time.read_ms()/1000)) - Received_MAC_Time);
00159             #endif
00160             
00161             if 
00162             (
00163                 //check primary MAC time
00164                 //adjust margin=5 as needed to accomodate Beacon advertisement interval time
00165                 // if advertising for 3 seconds, then make margin 4.  4->5, etc...
00166                 Is_Birth_Time_Correct(Spoof_Check[i].MAC_Time, Received_MAC_Time, Allowance)
00167             )
00168             {
00169                 if (Spoof_Check[i].Xmit_Cnt != Received_Xmit_Cnt)   //check if this is duplicate
00170                 {
00171                     return_val = ADVisNew; //MAC Time checks out and not duplicate
00172                     Spoof_Check[i].MAC_Time = Expected_MAC_Time;    //update birth time for this device.
00173                     Spoof_Check[i].Xmit_Cnt = Received_Xmit_Cnt;
00174                     //i = sizeOfSpoof;    //exit for loop, we've found the MAC address.  But can't do it this way.
00175                     //ToDo:  hey, what happens if the array holds entries w/ same MAC?  Is that possible?
00176                     #if MyDebugEnb
00177                     device.printf("Pirmary MAC Time as expected...expected=%d...Spoof_mac_tmr=%d \r\n", Expected_MAC_Time, Spoof_Check[i].MAC_Time);
00178                     #endif
00179                 }
00180                 else
00181                 {
00182                     return_val = ADVisDuplicate; //MAC Time checks out and is duplicate
00183                 }
00184             }//if primary MAC_time match
00185             else
00186             {
00187                 
00188                 // check secondary Mac_Time
00189                 // allows for device to become registered if secondary matches multiple times
00190                 #if MyDebugEnb
00191                 device.printf("    MAC Time No Match!!...expected=%d...Spoof_mac_tmr=%d \r\n", Expected_MAC_Time, Spoof_Check[i].MAC_Time);
00192                 #endif 
00193                 
00194                 //increment count if matches secondary
00195                 if (Is_Birth_Time_Correct(Spoof_Check[i].Attempt_MAC_Time, Received_MAC_Time, Allowance))
00196                 {
00197                     if (Spoof_Check[i].Xmit_Cnt != Received_Xmit_Cnt)   //not a duplicate ADV
00198                     {
00199                         Spoof_Check[i].Attempt_Cnt++;
00200                         Spoof_Check[i].Xmit_Cnt = Received_Xmit_Cnt;
00201                         #if MyDebugEnb
00202                         device.printf("    Match on secondary, Attempt_Cnt= %d, Attempt_MAC_Time = %d, Expected_MAC_Time=%d \r\n", Spoof_Check[i].Attempt_Cnt, Spoof_Check[i].Attempt_MAC_Time, Expected_MAC_Time);
00203                         #endif
00204                         //this takes care of usecase where a module is reset after it's already been seen by gateway
00205                         //after 3 consecutive correlated MAC_Time attempts we assume is our long lost friend and not a spoof.
00206                         if (Spoof_Check[i].Attempt_Cnt >= 3)
00207                         {
00208                             return_val = ADVisNew;
00209                             
00210                             //promote this MAC_Time to primary and start accepting data @ this MAC_Time
00211                             Spoof_Check[i].MAC_Time = Expected_MAC_Time;
00212                             Spoof_Check[i].Xmit_Cnt = Received_Xmit_Cnt;
00213                             Spoof_Check[i].Attempt_Cnt = 0;
00214                         }
00215                         else    //Received_MAC_Time matches Attempt, but not enough times to be considered as valid.
00216                         {
00217                             return_val = ADVisSpoof;
00218                         }
00219                     }//is not duplicate, and transmit count matches
00220                     else
00221                     {
00222                         #if MyDebugEnb
00223                         device.printf("    is Duplicate , but matches Attempt_MAC_Time matches\r\n");
00224                         #endif 
00225                         return_val = ADVisDuplicate;
00226                     }
00227                 } //Recevied MAC_Time matches secondary MAC_Time
00228                 else
00229                 {
00230                     #if MyDebugEnb
00231                     device.printf("    No Match on secondary either, ===setting return_val = Spoof ===\r\n");
00232                     #endif 
00233                     return_val = ADVisSpoof;  //it should still be zero, so this is just for clarification
00234                     //at this point:  MAC matches, MAC_Time doesn't match primary nor secondary.
00235                     Spoof_Check[i].Attempt_Cnt = 0;  //reset secondary count
00236                 }
00237                 //update second backup regardless whether it matches exptected_mac_time matches secondary or not.
00238                 Spoof_Check[i].Attempt_MAC_Time = Expected_MAC_Time;
00239                 Spoof_Check[i].Xmit_Cnt = Received_Xmit_Cnt;
00240             }//if Primary MAC_Time doesn't match
00241             
00242             break;  //return_val tells us if this is a valid or not.  Don't need to search through remainder of array
00243         }//if matching MAC address
00244         else //MAC doesn't match
00245         {
00246             //MAC doesn't match and we've searched through entire record
00247             //let's add this MAC as new, and initialze records to match this sensor
00248             if (i >= (sizeOfSpoof - 1))   //we've searched through entire array and didn't find this MAC
00249             {
00250                 //we've searched through the entire array and didn't find this MAC address
00251                 //add this MAC to array, and report this as valid MAC_Time
00252                 #if MyDebugEnb
00253                 device.printf("MAC not found, creating new at %d \r\n", Spoof_Ray_Tail);
00254                 device.printf("  sizeOfSpoof=%d ... and i=%d \r\n", sizeOfSpoof, i);  
00255                 #endif
00256                 
00257                 return_val = ADVisNew;
00258 
00259                 //create new entry for newly seen MAC @ tail of FIFO
00260                 Spoof_Check[Spoof_Ray_Tail].MAC_Addr[0] = Received_MAC_Addr[0];
00261                 Spoof_Check[Spoof_Ray_Tail].MAC_Addr[1] = Received_MAC_Addr[1];
00262                 Spoof_Check[Spoof_Ray_Tail].MAC_Addr[2] = Received_MAC_Addr[2];
00263                 Spoof_Check[Spoof_Ray_Tail].MAC_Addr[3] = Received_MAC_Addr[3];
00264                 Spoof_Check[Spoof_Ray_Tail].MAC_Addr[4] = Received_MAC_Addr[4];
00265                 Spoof_Check[Spoof_Ray_Tail].MAC_Addr[5] = Received_MAC_Addr[5];
00266                 Spoof_Check[Spoof_Ray_Tail].Xmit_Cnt = Received_Xmit_Cnt;
00267 
00268                 //call this just to calculate Expected_MAC_Time...kinda ugly to do this.  todo:  don't do this
00269                 Is_Birth_Time_Correct (0, Received_MAC_Time, Allowance);
00270                 #if MyDebugEnb
00271                 device.printf("Expected_MAC_Time should be %d \r\n", Expected_MAC_Time);
00272                 #endif
00273                 Spoof_Check[Spoof_Ray_Tail].MAC_Time = Expected_MAC_Time;    //wrong!!!
00274                 Spoof_Check[Spoof_Ray_Tail].Xmit_Cnt = Received_Xmit_Cnt;
00275                 Spoof_Check[Spoof_Ray_Tail].Attempt_Cnt = 0;
00276                 
00277                 //increment tail pointer to next position or wrap around
00278                 if (Spoof_Ray_Tail >= (sizeOfSpoof-1) ) //FIFO at end of array, return to beginning
00279                 {
00280                     Spoof_Ray_Tail = 0;
00281                 }
00282                 else
00283                 {
00284                     Spoof_Ray_Tail++;
00285                 }
00286                 
00287             }//end if loop at end of array
00288         }//end else not maching MAC
00289     }//loop through Spoof_Check array
00290 
00291  
00292     return return_val;
00293 }//end Is_Not_Spoofed()
00294 
00295 
00296 void periodicCallback(void) //every Periodicity seconds, reset clock
00297 {
00298 #if MyDebugEnb
00299     device.printf("===== reset timer ===== \r\n");
00300 #endif
00301     Gateway_Time.reset();
00302 }
00303 
00304 
00305 
00306 //Scheme for recognizing our beacons and ignoring all other beacons
00307 //idea:  could use something like Pearson hash on parts of MAC address to make less obvious
00308 bool is_ours(const uint8_t * adv_data, const uint8_t * adv_address)
00309 {
00310     if ((adv_data[5] == adv_address[3]) && (adv_data[6] == adv_address[2]))
00311         return 1;
00312     else
00313         return 0;
00314 }
00315 
00316 
00317 // callback when BLE stack scans and finds a BLE ADV packet
00318 // Parse ADV and determine if it's one of ours, output data to serial if it is.
00319 void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) {
00320 
00321     if ( (params->advertisingDataLen) >= 8)
00322     {
00323         if (is_ours(params->advertisingData, params->peerAddr))
00324         {
00325             #if MyDebugEnb
00326             device.printf("----------- ADV CAll Back -----------------\r\n  ");
00327             #endif 
00328             
00329             //**************
00330             // Decrypt data
00331             //**************
00332             //prep array for deciphering the encrypted portion of advertisement
00333             for (int i = 0; i<16; i++)
00334             {
00335                 src_buf[i]=params->advertisingData[i+15];
00336                 #if MyDebugEnb
00337                 //device.printf("%x ", src_buf[i]);
00338                 #endif
00339             }
00340             mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_DECRYPT, src_buf, des_buf );   //execution time not an issue
00341             #if MyDebugEnb
00342             //device.printf("decoded first 16 bytes \r\n");
00343             for (int i = 0; i<16; i++)
00344             {
00345                 //device.printf("%02x", params->advertisingData[index]);
00346                 if (i < 2)
00347                 {
00348                    //device.printf("%x ", des_buf[i]); 
00349                 }
00350                 else
00351                 {
00352                     //device.printf("%c ", des_buf[i]);
00353                 }
00354             }
00355             //device.printf("done----- \r\n");
00356             #endif
00357             
00358             //save MAC address to global
00359             Received_MAC_Addr[0] = params->peerAddr[0];
00360             Received_MAC_Addr[1] = params->peerAddr[1];
00361             Received_MAC_Addr[2] = params->peerAddr[2];
00362             Received_MAC_Addr[3] = params->peerAddr[3];
00363             Received_MAC_Addr[4] = params->peerAddr[4];
00364             Received_MAC_Addr[5] = params->peerAddr[5];
00365             
00366             Received_MAC_Time = des_buf[0] | (des_buf[1] << 8);  //it's a 2 byte uint little endian
00367             Received_Xmit_Cnt = des_buf[2];
00368             
00369             
00370             
00371             
00372             // punch out the data over serial as json 
00373             //---------------------------------------
00374             // 1.  MAC and RSSI
00375             // "mac":xxxxxxxx,rssi:xx,
00376             //---------------------------------------
00377             uint8_t ADV_Result = Is_Not_Spoofed();
00378             #if MyDebugEnb
00379             device.printf("--------ADV_Result = %d", ADV_Result);
00380             #endif
00381 
00382             //decide wether or not duplicate ADV packets should be output as well.
00383             //if ((ADV_Result == ADVisNew) || (ADV_Result==ADVisDuplicate))  //output both first and duplicates
00384             if (ADV_Result == ADVisNew)  //only output first received ADV
00385             {
00386                 device.printf("{\"mac\":\"%02x%02x%02x%02x%02x%02x\",\"rssi\":%d,",
00387                     params->peerAddr[5], 
00388                     params->peerAddr[4], 
00389                     params->peerAddr[3], 
00390                     params->peerAddr[2], 
00391                     params->peerAddr[1], 
00392                     params->peerAddr[0],
00393                     params->rssi
00394                     );
00395     
00396                 //---------------------------------------
00397                 // 2.  Volt is always X.XX, per Beacon code
00398                 // "volt":3.03,
00399                 //---------------------------------------
00400                 device.printf("\"volt\":%c%c%c%c,",
00401                     params->advertisingData[9],
00402                     params->advertisingData[10],
00403                     params->advertisingData[11],
00404                     params->advertisingData[12]);
00405                 
00406     
00407                 //---------------------------------------
00408                 // 3.  Beacon time (# seconds since birth, clocked around Periodicity) 0-1800 seconds
00409                 // "tmr":xxxx,
00410                 //---------------------------------------
00411                 
00412                 device.printf("\"tmr\":%d,", Received_MAC_Time);
00413                 
00414                 //---------------------------------------
00415                 // 4.  Xmit Counter 0-255, incremented by Beacon with each new unique ADV event.
00416                 // "tmr":xxxx,
00417                 //---------------------------------------                
00418                 device.printf("\"xcnt\":%d,", Received_Xmit_Cnt);
00419                 
00420                 //---------------------------------------
00421                 // 5.  rest of sensor payload as json
00422                 // "tmr":xxx,
00423                 //---------------------------------------
00424                 for (int i = 3; i<16; i++)
00425                 {
00426                     device.printf("%c", des_buf[i]);    //print as character
00427                     //Note that sensor JSON payload most likely is not exactly 16 bytes long, so there's likely /0 in middle
00428                     // of this.  But JSON library on gateway handles this gracefully.
00429                 }
00430     
00431                 device.printf("}");
00432                 device.printf("\r\n");  //gateway looking for cariage return to indicate end
00433                 wait_ms(140);  //needed to give gateway time to assert flow control handshake pin
00434                 while (pinHandShake.read() == 1)    //normally pulled down, so loop when gateway processing;
00435                 {
00436                     //uart flow control
00437                     //blocking until gateway has processed ADV data from uart
00438                 }
00439             }
00440 
00441             if (ADV_Result == ADVisSpoof)  //If detected spoofed sensor data
00442             {
00443                 device.printf("{\"mac\":\"%02x%02x%02x%02x%02x%02x\",\"spoof\": %d}\r\n",
00444                     params->peerAddr[5], 
00445                     params->peerAddr[4], 
00446                     params->peerAddr[3], 
00447                     params->peerAddr[2], 
00448                     params->peerAddr[1], 
00449                     params->peerAddr[0],
00450                     ADV_Result);
00451             }
00452             
00453             if (ADV_Result == ADVisUnknown)  //catch all, should never occur
00454             {
00455                 device.printf("{\"mac\":\"%02x%02x%02x%02x%02x%02x\",\"unknown\": %d}\r\n",
00456                     params->peerAddr[5], 
00457                     params->peerAddr[4], 
00458                     params->peerAddr[3], 
00459                     params->peerAddr[2], 
00460                     params->peerAddr[1], 
00461                     params->peerAddr[0],
00462                     ADV_Result);            
00463             }
00464         }//end if it's our adv
00465     }//end if advertisingDataLen
00466 }//end advertisementCallback
00467 
00468 
00469 
00470 /**
00471  * This function is called when the ble initialization process has failed
00472  */
00473 void onBleInitError(BLE &ble, ble_error_t error)
00474 {
00475     /* Initialization error handling should go here */
00476     device.printf("periodic callback ");
00477     device.printf("\r\n");
00478 }
00479 
00480 /**
00481  * Callback triggered when the ble initialization process has finished
00482  */
00483 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
00484 {
00485     BLE&        ble   = params->ble;
00486     ble_error_t error = params->error;
00487 
00488     if (error != BLE_ERROR_NONE) {
00489         /* In case of error, forward the error handling to onBleInitError */
00490         onBleInitError(ble, error);
00491         return;
00492     }
00493 
00494     /* Ensure that it is the default instance of BLE */
00495     if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
00496         return;
00497     }
00498  
00499     //note:  defaults to scanning 3 channels.
00500     // Window and Interval in ms.  Duty cycle = (interval / window);  200ms/500ms = 40%;  Max is 10000
00501     //  |---window---|                          |---window---|                       |---window---|
00502     //  |---------- interval @ ch1 -----| |------- interval @ ch2--------||-----interval @ ch3-------|
00503     //  set window equal to interval for full duty cycle scanning
00504     //  set interval to hit all 3 channels of beacon advertising over advertising time duration
00505     ble.gap().setScanParams(500 /* scan interval */, 500 /* scan window */);
00506     ble.gap().startScan(advertisementCallback);
00507 }
00508 
00509 int main(void)
00510 {
00511     pinHandShake.mode(PullDown); //Expecting gateway to set pin high for flow control
00512     
00513     //intialize spoof checking data structure
00514     for (int i=0; i<sizeOfSpoof; i++)
00515     {
00516         Spoof_Check[i].MAC_Addr[0]= 0;
00517         Spoof_Check[i].MAC_Addr[1]= 0;
00518         Spoof_Check[i].MAC_Addr[2]= 0;
00519         Spoof_Check[i].MAC_Time = 0;
00520         Spoof_Check[i].Attempt_MAC_Time = 0;
00521         Spoof_Check[i].Attempt_Cnt = 0;
00522         Spoof_Check[i].Attempt_Cnt = 0;
00523         Spoof_Check[i].Xmit_Cnt = 0;
00524     }
00525         
00526     //maintains periodicity for spoof checking scheme
00527     Gateway_Time.start();
00528     ticker.attach(periodicCallback, Periodicity);
00529     
00530     device.baud(9600);  //p0.9 tx, p0.11 rx.  Use p0.9 to gateway
00531 
00532     mbedtls_aes_setkey_dec( &aes, iv, 128 );  //set AES key for decrypt
00533 
00534     BLE &ble = BLE::Instance();
00535     ble.init(bleInitComplete);
00536     
00537     ble.getAddress(0,MAC_gateway);  //get this gateway module's ble MAC
00538     device.printf("{\"mac\":\"%02x%02x%02x%02x%02x%02x\",\"gatewaystart\":\"now\"},",
00539         MAC_gateway[5], 
00540         MAC_gateway[4], 
00541         MAC_gateway[3], 
00542         MAC_gateway[2], 
00543         MAC_gateway[1], 
00544         MAC_gateway[0]
00545         );
00546     device.printf("\r\n");
00547     
00548     while (true) 
00549     {
00550         ble.waitForEvent();  //idle here until callback
00551     }
00552 }