2018-10-22: This is a temporary repository to fix issue mbed OS issue 8344. I'm reverting to an earlier mbed revision that isn't messed up. Expect mbed to fix the linker issue in the next release and I'll remove this repository. I havne't tested the code at this revision - sorry!

Dependencies:   BLE_API mbed mbedtls nRF51822

Revision:
11:d5edb6e3edab
Parent:
10:9db2ac7e1eea
Child:
12:30c6e83f0fe5
--- a/main.cpp	Mon Jul 10 04:20:46 2017 +0000
+++ b/main.cpp	Sat Jul 29 21:49:32 2017 +0000
@@ -1,26 +1,9 @@
-/* 
-
- 
+/*  
  Eric Tsai
-BLE Gateway to bridge sensor data.  Works.
-Scans for advertisements and captures the ones identified as mine
-Takes UUID fields and injects the MAC and RSSI data.  Assumes UUID JSON data.
-
-
-
-----------------------------------------------
+ 
+ 7/29/2017:  Added spoof checking using clock algorithm.  
 
-
-Example output:
-{"mac":"c56e806d7cfb","rssi":-54,"volt":3.01,"mag/p":2}
-added timer
-{"mac":"c56e806d7cfb","rssi":-54,"tmr":3232,"volt":3.01,"mag/p":2}
-{"mac":"c2f154bb0af9","rssi":-76,"tmr":250,"volt":3.14,"mag/p":1}
-
-todo:  hash MAC to create unique identifiers for sensors seen as "mine"
-todo:  create search for ensure gateway only accepts tmr values that match, else
-        are consecutive transmits in case we miss power up transmit.
- */
+*/
 
 #include "mbed.h"
 #include "ble/BLE.h"
@@ -31,26 +14,337 @@
 #define MyDebugEnb 0
 
 
+
 //DigitalOut led1(LED1, 1);
 Ticker     ticker;
 
+const uint16_t Periodicity = 180;   //clock periodicity used for spoof checking, should be 1800 seconds for 30minutes
+
 //aes stuff
 uint8_t src_buf[16] = {0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4};
 uint8_t des_buf[16] = {0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4};
-
 mbedtls_aes_context aes;
-
 unsigned char iv[16] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x1, 0x2};       //16-byte key
 size_t input_len = 16;
 size_t output_len = 0;
 
 Serial device(p9, p11);  //nRF51822 uart :  TX=p9.  RX=p11
 
-void periodicCallback(void)
+//data structures for tracking wake time of BLE end nodes, for to prevent spoofing
+struct MAC_Birth_Record
+{
+    uint8_t MAC_Addr[6]; //mac[0] is low order byte in mac address
+    uint16_t MAC_Time;  //The time of birth for this end node
+    uint16_t Attempt_MAC_Time;
+    uint8_t Attempt_Cnt;
+    uint8_t Xmit_Cnt;
+};
+const uint8_t sizeOfSpoof = 50;
+MAC_Birth_Record Spoof_Check[sizeOfSpoof];   //array tracking end node birth times
+uint8_t Spoof_Ray_Tail = 0;         //array index for next record
+uint8_t Received_MAC_Addr[6]; //mac[0] is low order byte in mac address
+uint16_t Received_MAC_Time;
+static Timer Gateway_Time;
+static uint16_t Expected_MAC_Time;
+uint8_t Received_Xmit_Cnt;
+
+
+const uint8_t ADVisUnknown = 0;
+const uint8_t ADVisNew = 1;
+const uint8_t ADVisDuplicate = 2;
+const uint8_t ADVisSpoof = 3;
+
+//********************
+// Takes into account 30-minute clock, wrap arounds and edge cases
+// returns:
+//      TRUE:  if sensor's reported time lines up to gateway's recorded time
+//  Expected_MAC_Time
+//*******************
+bool Is_Birth_Time_Correct (uint16_t gateway_mac_time, uint16_t sensor_mac_time, uint8_t margin)
+{
+    bool return_val = 0;
+    uint16_t current_time = (uint16_t)(Gateway_Time.read_ms()/1000);
+    int16_t gateway_time_zone = current_time - sensor_mac_time;
+    
+    if (current_time >= sensor_mac_time)
+    {
+        Expected_MAC_Time = current_time - sensor_mac_time;
+    }
+    else
+    {
+        Expected_MAC_Time = (Periodicity - sensor_mac_time + current_time);
+    }
+    
+    if (1)  //check for count==0 situations
+    {
+        if ( (gateway_mac_time < (Expected_MAC_Time + margin)) && (gateway_mac_time > (Expected_MAC_Time - margin)) )
+        {
+            return_val = 1;
+        }
+        else
+        {
+            return_val = 0;
+            
+        }  
+    }
+    
+    /*
+    //if positive, not a wrap around edge case
+    //todo:  take into account low count, indicates reset?
+    if ((gateway_time_zone >= 0) && (1))
+    {
+        Expected_MAC_Time = gateway_time_zone;
+        if ( (gateway_mac_time < (Expected_MAC_Time + margin)) && (gateway_mac_time > (Expected_MAC_Time - margin)) )
+        {
+            return_val = 1;  //valid birth time
+        }
+        
+    }
+    else    //wrap around edge case, gateway_time_zone is negative
+    {
+        gateway_time_zone = (Periodicity - sensor_mac_time + current_time);
+        Expected_MAC_Time = gateway_time_zone;                  //todo:  2 declarations??
+        //if ( (Periodicity-gateway_mac_time)+current_time == sensor_mac_time) //wrong, need bands
+        if ( (gateway_mac_time < (Expected_MAC_Time + margin)) && (gateway_mac_time > (Expected_MAC_Time - margin)) )
+        {
+            return_val = 1;
+        }
+        else
+        {
+            return_val = 0;
+            
+        }
+        
+    }
+    */
+    return return_val;
+    
+}//end Is_Birth_Time_Correct
+
+
+
+/* **************************************
+check adv against birth records to detect spoofing
+add device to birth records if new
+returns
+    TRUE:   if device reported birth time matches real birth time
+            if device is first encountered
+            if X consecutive birth time matches
+    FALSE:  if device reported birth time does not match
+    
+ToDo:  add attempts
+ToDo:  wrap around of gateway clock not accounted for.  Like if Gateway_Time.read_ms() - Received_MAC_Time < 0
+*/
+uint8_t Is_Not_Spoofed ()
 {
+    uint8_t return_val = ADVisUnknown;
+    //iterate through all of birth records looking for one that matches MAC address
+    for (int i=0; i<sizeOfSpoof; i++)
+    {
+        //Search for matching MAC address
+        if (Spoof_Check[i].MAC_Addr[0] == Received_MAC_Addr[0] &&
+            Spoof_Check[i].MAC_Addr[1] == Received_MAC_Addr[1] &&
+            Spoof_Check[i].MAC_Addr[2] == Received_MAC_Addr[2] &&
+            Spoof_Check[i].MAC_Addr[3] == Received_MAC_Addr[3] &&
+            Spoof_Check[i].MAC_Addr[4] == Received_MAC_Addr[4] &&
+            Spoof_Check[i].MAC_Addr[5] == Received_MAC_Addr[5])
+        {
+            
+            
+            
+            #if MyDebugEnb
+            device.printf("found MAC address in array\r\n");
+            device.printf("   Index = %d \r\n", i);
+            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]);
+            device.printf("   Received MAC Time =  %d \r\n", Received_MAC_Time);
+            device.printf("   Gateway time = %d \r\n", (uint16_t)(Gateway_Time.read_ms()/1000));
+            device.printf("   Array.MAC_Time =  %d \r\n", Spoof_Check[i].MAC_Time);
+            device.printf("   Array.Attempt_MAC_Time =  %d \r\n", Spoof_Check[i].Attempt_MAC_Time);
+            device.printf("   Array.Attempt_Cnt =  %d \r\n", Spoof_Check[i].Attempt_Cnt);
+            device.printf("   Array.Xmit_Cnt =  %d \r\n", Spoof_Check[i].Xmit_Cnt);
+            device.printf("   expected time =  %d \r\n", ((uint16_t)(Gateway_Time.read_ms()/1000)) - Received_MAC_Time);
+            #endif
+            
+            //calcuate the time of birth of this bluetooth module @ gateway time zone relative to received MAC_Time.
+            //int16_t expected_mac_time = ((uint16_t)(Gateway_Time.read_ms()/1000)) - Received_MAC_Time;
+            //uint16_t expected_mac_time = 0;
+            
+            
+            //todo:  this needs to be a POSITIVE VALUE, calculated by Is_MAC_Time_Correct();
+            
+            
+            // ToDo:  there's a bug here.  Need to use count to figure out when it's a first-powered on device.  Can't use time?
+            
+            //*****
+            // check primary Mac_Time
+            //****
+            if 
+            (
+                Is_Birth_Time_Correct(Spoof_Check[i].MAC_Time, Received_MAC_Time, 3)
+            )
+            {
+                if (Spoof_Check[i].Xmit_Cnt != Received_Xmit_Cnt)
+                {
+                    return_val = ADVisNew; //MAC Time checks out and not duplicate
+                    Spoof_Check[i].MAC_Time = Expected_MAC_Time;    //update birth time for this device.
+                    Spoof_Check[i].Xmit_Cnt = Received_Xmit_Cnt;
+                    //i = sizeOfSpoof;    //exit for loop, we've found the MAC address.  But can't do it this way.
+                    //ToDo:  hey, what happens if the array holds entries w/ same MAC?  Is that possible?
+                    #if MyDebugEnb
+                    device.printf("Pirmary MAC Time as expected...expected=%d...Spoof_mac_tmr=%d \r\n", Expected_MAC_Time, Spoof_Check[i].MAC_Time);
+                    #endif
+                }
+                else
+                {
+                    return_val = ADVisDuplicate; //MAC Time checks out and is duplicate
+                }
+            }//if primary MAC_time match
+            else
+            {
+                //*****
+                // check secondary Mac_Time
+                //****
+                #if MyDebugEnb
+                device.printf("    MAC Time No Match!!...expected=%d...Spoof_mac_tmr=%d \r\n", Expected_MAC_Time, Spoof_Check[i].MAC_Time);
+                
+                #endif 
+                
+                //increment count if matches secondary
+                //if ( (Spoof_Check[i].Attempt_MAC_Time < (expected_mac_time + 5)) && (Spoof_Check[i].Attempt_MAC_Time > (expected_mac_time - 5)) )
+                if (Is_Birth_Time_Correct(Spoof_Check[i].Attempt_MAC_Time, Received_MAC_Time, 3))
+                {
+                    if (Spoof_Check[i].Xmit_Cnt != Received_Xmit_Cnt)
+                    {
+
+                        //Spoof_Check[i].Attempt_MAC_Time = expected_mac_time;
+                        Spoof_Check[i].Attempt_Cnt++;
+                        Spoof_Check[i].Xmit_Cnt = Received_Xmit_Cnt;
+                        #if MyDebugEnb
+                        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);
+                        #endif
+                        //this takes care of usecase where a module is reset after it's already been seen by gateway
+                        //after 3 consecutive correlated MAC_Time attempts we assume is our long lost friend and not a spoof.
+                        if (Spoof_Check[i].Attempt_Cnt >= 3)
+                        {
+                            return_val = ADVisNew;
+                            
+                            //promote this MAC_Time to primary and start accepting data @ this MAC_Time
+                            Spoof_Check[i].MAC_Time = Expected_MAC_Time;
+                            Spoof_Check[i].Xmit_Cnt = Received_Xmit_Cnt;
+                            Spoof_Check[i].Attempt_Cnt = 0;
+                        }
+                        else    //Received_MAC_Time matches Attempt, but not enough times to be considered as valid.
+                        {
+                            return_val = ADVisSpoof;
+                            
+                        }
+                        
+                        
+                    }//is not duplicate, and transmit count matches
+                    else
+                    {
+                        #if MyDebugEnb
+                        device.printf("    is Duplicate , but matches Attempt_MAC_Time matches\r\n");
+                        #endif 
+                        return_val = ADVisDuplicate;
+                    }
+                } //Recevied MAC_Time matches secondary MAC_Time
+                else
+                {
+                    #if MyDebugEnb
+                    device.printf("    No Match on secondary either, ===setting return_val = Spoof ===\r\n");
+                    #endif 
+                    return_val = ADVisSpoof;  //it should still be zero, so this is just for clarification
+                    //at this point:  MAC matches, MAC_Time doesn't match primary nor secondary.
+                    Spoof_Check[i].Attempt_Cnt = 0;  //reset secondary count
+
+                }
+                //update second backup regardless whether it matches exptected_mac_time matches secondary or not.
+                Spoof_Check[i].Attempt_MAC_Time = Expected_MAC_Time;
+                Spoof_Check[i].Xmit_Cnt = Received_Xmit_Cnt;
+            }//if Primary MAC_Time doesn't match
+            
+            break;  //return_val tells us if this is a valid or not.  Don't need to search through remainder of array
+        }//if matching MAC address
+        else //MAC doesn't match
+        {
+            //MAC doesn't match and we've searched through entire record
+            //let's add this MAC as new, an initialze records to match this sensor
+            if (i >= (sizeOfSpoof - 1))   //we've searched through entire array and didn't find this MAC
+            {
+                //we've searched through the entire array and didn't find this MAC address
+                //add this MAC to array, and report this as valid MAC_Time
+                #if MyDebugEnb
+                device.printf("MAC not found, creating new at %d \r\n", Spoof_Ray_Tail);
+                device.printf("  sizeOfSpoof=%d ... and i=%d \r\n", sizeOfSpoof, i);  
+                #endif
+                
+                return_val = ADVisNew;
+
+                //create new entry for newly seen MAC @ tail
+                // why refigure??  Spoof_Check[Spoof_Ray_Tail].MAC_Time = ((uint16_t)(Gateway_Time.read_ms()/1000)) - Received_MAC_Time;
+                Spoof_Check[Spoof_Ray_Tail].MAC_Addr[0] = Received_MAC_Addr[0];
+                Spoof_Check[Spoof_Ray_Tail].MAC_Addr[1] = Received_MAC_Addr[1];
+                Spoof_Check[Spoof_Ray_Tail].MAC_Addr[2] = Received_MAC_Addr[2];
+                Spoof_Check[Spoof_Ray_Tail].MAC_Addr[3] = Received_MAC_Addr[3];
+                Spoof_Check[Spoof_Ray_Tail].MAC_Addr[4] = Received_MAC_Addr[4];
+                Spoof_Check[Spoof_Ray_Tail].MAC_Addr[5] = Received_MAC_Addr[5];
+                Spoof_Check[Spoof_Ray_Tail].Xmit_Cnt = Received_Xmit_Cnt;
+
+                //calculate Expected_MAC_Time
+                Is_Birth_Time_Correct (0, Received_MAC_Time, 3);
+                #if MyDebugEnb
+                device.printf("Expected_MAC_Time should be %d \r\n", Expected_MAC_Time);
+
+                #endif
+                Spoof_Check[Spoof_Ray_Tail].MAC_Time = Expected_MAC_Time;    //wrong!!!
+                Spoof_Check[Spoof_Ray_Tail].Xmit_Cnt = Received_Xmit_Cnt;
+                Spoof_Check[Spoof_Ray_Tail].Attempt_Cnt = 0;
+                
+                //increment tail pointer to next position or wrap around
+                //todo:  might not be using the last index position of this array, not sure.  Doesn't matter IDK.
+                if (Spoof_Ray_Tail >= (sizeOfSpoof-1) ) //FIFO at end of array, return to beginning
+                {
+                    Spoof_Ray_Tail = 0;
+                }
+                else
+                {
+                    Spoof_Ray_Tail++;
+                }
+                
+            }//end if loop at end of array
+        }//end else not maching MAC
+        
+    }//loop through Spoof_Check array
+
+    
+    return return_val;
+}//end Is_Not_Spoofed()
+
+
+
+
+void periodicCallback(void) //every 1800 seconds = 30 minutes, max for ticker.
+{
+#if MyDebugEnb
+    device.printf("===== reset timer ===== \r\n");
+#endif
     //led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
     //device.printf("periodic 5...");
     //device.printf("\r\n");
+    Gateway_Time.reset();
+}
+
+
+//with the current beacon, I see 3 valid advertisements per wake period with ambient other beacons.  sometimes 4.
+//even with 2 phones broadcasting at 10Hz, still see 3 adv's.
+bool is_ours(const uint8_t * adv_data, const uint8_t * adv_address)
+{
+    //if ((adv_data[5] == adv_address[3]) && (adv_data[6] == adv_address[2]) && (adv_data[7] == adv_address[1]) && (adv_data[8] == adv_address[0]))
+    if ((adv_data[5] == adv_address[3]) && (adv_data[6] == adv_address[2]))
+        return 1;
+    else
+        return 0;
 }
 
 void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) {
@@ -74,9 +368,65 @@
     if ( (params->advertisingDataLen) >= 8)
     {
         //if one of "ours", these UUID fields will be this value.  Arbitrary " 
-        //todo:  use MAC to make a hash of what these 3 bytes should be.
-        if ( (params->advertisingData[5] == 0x44) && (params->advertisingData[6] == 0x45) && (params->advertisingData[7]==0x43) )
+        
+        //if ( (params->advertisingData[5] == 0x44) && (params->advertisingData[6] == 0x45) && (params->advertisingData[7]==0x43) )
+        //if (is_ours(params->advertisingData[5],params->advertisingData[6],params->advertisingData[7], params->advertisingData[8], params->peerAddr[3], params->peerAddr[2], params->peerAddr[1], params->peerAddr[0] ))
+        if (is_ours(params->advertisingData, params->peerAddr))
         {
+            #if MyDebugEnb
+            device.printf("----------- ADV CAll Back -----------------\r\n  ");
+            #endif 
+            //**************
+            // Decrypt data
+            //**************
+            //prep array for deciphering the encrypted portion of advertisement
+            //device.printf("\r\n copy adv length:  %d \r\n", params->advertisingDataLen);  //always 31
+            for (int i = 0; i<16; i++)
+            {
+                src_buf[i]=params->advertisingData[i+15];
+                #if MyDebugEnb
+                //device.printf("%x ", src_buf[i]);
+                #endif
+            }
+            #if MyDebugEnb
+            //device.printf("...\r\n  ");
+            #endif 
+
+            
+            mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_DECRYPT, src_buf, des_buf );   //execution time not an issue
+            
+            
+            #if MyDebugEnb
+            
+            //device.printf("decoded first 16 bytes \r\n");
+            for (int i = 0; i<16; i++)
+            {
+                //device.printf("%02x", params->advertisingData[index]);
+                if (i < 2)
+                {
+                   //device.printf("%x ", des_buf[i]); 
+                }
+                else
+                {
+                    //device.printf("%c ", des_buf[i]);
+                }
+            }
+            //device.printf("done----- \r\n");
+            #endif
+            //save MAC address
+            Received_MAC_Addr[0] = params->peerAddr[0];
+            Received_MAC_Addr[1] = params->peerAddr[1];
+            Received_MAC_Addr[2] = params->peerAddr[2];
+            Received_MAC_Addr[3] = params->peerAddr[3];
+            Received_MAC_Addr[4] = params->peerAddr[4];
+            Received_MAC_Addr[5] = params->peerAddr[5];
+            
+            uint16_t beacon_timer = des_buf[0] | (des_buf[1] << 8);  //it's a 2 byte uint little endian
+            Received_MAC_Time = beacon_timer;
+            Received_Xmit_Cnt = des_buf[2];
+            
+            
+            
             /*
             BLE Received from MAC C2F154BB0AF9
             volt:3.11,mag:1
@@ -94,95 +444,125 @@
               params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2], params->peerAddr[1], params->peerAddr[0],
               params->rssi, params->isScanResponse, params->type);
             */
-            device.printf("{\"mac\":\"%02x%02x%02x%02x%02x%02x\",\"rssi\":%d,",
-                params->peerAddr[5], 
-                params->peerAddr[4], 
-                params->peerAddr[3], 
-                params->peerAddr[2], 
-                params->peerAddr[1], 
-                params->peerAddr[0],
-                params->rssi
-                );
-            //mac:"c2f154bb0af9"
             
-            //device.printf("\r\n copy adv length:  %d \r\n", params->advertisingDataLen);
-            for (int i = 0; i<16; i++)
-            {
-                
-                src_buf[i]=params->advertisingData[i+8];
-#if MyDebugEnb
-                device.printf("%x ", src_buf[i]);
-#endif
-            }
-#if MyDebugEnb
-            device.printf("...\r\n  ");
-#endif    
-            mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_DECRYPT, src_buf, des_buf );
-#if MyDebugEnb
-            
-            device.printf("decoded first 16 bytes \r\n");
-            for (int i = 0; i<16; i++)
+            // punch out the data as json
+            //---------------------------------------
+            // 1.  MAC and RSSI
+            // "mac":xxxxxxxx,rssi:xx,
+            //---------------------------------------
+            uint8_t ADV_Result = Is_Not_Spoofed();
+            #if MyDebugEnb
+            device.printf("--------ADV_Result = %d", ADV_Result);
+            #endif
+
+
+            if (ADV_Result == ADVisNew)
             {
-                //device.printf("%02x", params->advertisingData[index]);
-                if (i < 2)
+                device.printf("{\"mac\":\"%02x%02x%02x%02x%02x%02x\",\"rssi\":%d,",
+                    params->peerAddr[5], 
+                    params->peerAddr[4], 
+                    params->peerAddr[3], 
+                    params->peerAddr[2], 
+                    params->peerAddr[1], 
+                    params->peerAddr[0],
+                    params->rssi
+                    );
+                //mac:"c2f154bb0af9"
+    
+                //---------------------------------------
+                // 2.  Volt
+                // "volt":3.03,
+                //---------------------------------------
+                device.printf("\"volt\":%c%c%c%c,",
+                    params->advertisingData[9],
+                    params->advertisingData[10],
+                    params->advertisingData[11],
+                    params->advertisingData[12]);
+                
+    
+    
+    
+                //---------------------------------------
+                // 3.  clock
+                // "tmr":xxx,
+                //---------------------------------------
+                //print clock
+                //     "tmr":3232,
+                //---------------------------------------
+                
+                device.printf("\"tmr\":%d,", beacon_timer);
+                //device.printf("\"tmr\":%d,", des_buf[0]);
+                device.printf("\"xmit_cnt\":%d,", Received_Xmit_Cnt);
+                
+                //---------------------------------------
+                // 4.  rest of payload as json
+                // "tmr":xxx,
+                //---------------------------------------
+                for (int i = 3; i< 16; i++)
                 {
-                   device.printf("%x ", des_buf[i]); 
-                }
-                else
-                {
-                    device.printf("%c ", des_buf[i]);
+                    //device.printf("%02x", params->advertisingData[index]);
+                    device.printf("%c", des_buf[i]);    //print as character
                 }
-            }
-            device.printf("done----- \r\n");
-#endif
-
-            //print clock
-            //     "tmr":3232,
-            //des_buf[0] = lower byte, des_buf[1] = higher byte
-            uint16_t beacon_timer = des_buf[0] | (des_buf[1] << 8);
-            device.printf("\"tmr\":%d,", beacon_timer);
-            //device.printf("\"tmr\":%d,", des_buf[0]);
-            
-            for (int i = 2; i< 16; i++)
-            {
-                //device.printf("%02x", params->advertisingData[index]);
-                device.printf("%c", des_buf[i]);
-            }
-
-            if (params->advertisingDataLen > 24)
-            {
-                for (unsigned index = 24; index < params->advertisingDataLen; index++)
+    
+    
+    
+                /*
+                for (unsigned index = 8; index < params->advertisingDataLen; index++)
                 {
                     //device.printf("%02x", params->advertisingData[index]);
                     device.printf("%c", params->advertisingData[index]);
-                }   
+                }
+                */
+                
+                device.printf("}");
+                device.printf("\r\n");
+                
+                /*
+                mac:c2f154bb0af9,rssi:-55,volt:3.05,mag:1
+                mac:c2f154bb0af9,rssi:-67,volt:3.05,mag:1
+                mac:c2f154bb0af9,rssi:-60,volt:3.07,mag:0
+                */
             }
-
-            /*
-            for (unsigned index = 8; index < params->advertisingDataLen; index++)
+            if (ADV_Result == ADVisDuplicate)
             {
-                //device.printf("%02x", params->advertisingData[index]);
-                device.printf("%c", params->advertisingData[index]);
+                device.printf("{\"mac\":\"%02x%02x%02x%02x%02x%02x\",\"duplicate\": %d}\r\n",
+                    params->peerAddr[5], 
+                    params->peerAddr[4], 
+                    params->peerAddr[3], 
+                    params->peerAddr[2], 
+                    params->peerAddr[1], 
+                    params->peerAddr[0],
+                    ADV_Result);
             }
-            */
-            
-            device.printf("}");
-            device.printf("\r\n");
-            
-            /*
-            mac:c2f154bb0af9,rssi:-55,volt:3.05,mag:1
-            mac:c2f154bb0af9,rssi:-67,volt:3.05,mag:1
-            mac:c2f154bb0af9,rssi:-60,volt:3.07,mag:0
-            */
-            
+            if (ADV_Result == ADVisSpoof)
+            {
+                device.printf("{\"mac\":\"%02x%02x%02x%02x%02x%02x\",\"spoof\": %d}\r\n",
+                    params->peerAddr[5], 
+                    params->peerAddr[4], 
+                    params->peerAddr[3], 
+                    params->peerAddr[2], 
+                    params->peerAddr[1], 
+                    params->peerAddr[0],
+                    ADV_Result);
+            }
+            if (ADV_Result == ADVisUnknown)
+            {
+                device.printf("{\"mac\":\"%02x%02x%02x%02x%02x%02x\",\"unknown\": %d}\r\n",
+                    params->peerAddr[5], 
+                    params->peerAddr[4], 
+                    params->peerAddr[3], 
+                    params->peerAddr[2], 
+                    params->peerAddr[1], 
+                    params->peerAddr[0],
+                    ADV_Result);            
+            }
         }//end if it's our adv
     }//end if advertisingDataLen
 
+}//end advertisementCallback
 
 
 
-}//end advertisementCallback
-
 /**
  * This function is called when the ble initialization process has failed
  */
@@ -219,10 +599,23 @@
 
 int main(void)
 {
+    for (int i=0; i<sizeOfSpoof; i++)
+    {
+        Spoof_Check[i].MAC_Addr[0]= 0;
+        Spoof_Check[i].MAC_Addr[1]= 0;
+        Spoof_Check[i].MAC_Addr[2]= 0;
+        Spoof_Check[i].MAC_Time = 0;
+        Spoof_Check[i].Attempt_MAC_Time = 0;
+        Spoof_Check[i].Attempt_Cnt = 0;
+        Spoof_Check[i].Attempt_Cnt = 0;
+        Spoof_Check[i].Xmit_Cnt = 0;
+    }
+    
+    Gateway_Time.start();
     device.baud(9600);
-    device.printf("started main 04... ");
+    device.printf("started main 06 hashed observer... ");
     device.printf("\r\n");
-    ticker.attach(periodicCallback, 5);
+    ticker.attach(periodicCallback, Periodicity);
     
     //mbedtls_aes_init(&aes);
     mbedtls_aes_setkey_dec( &aes, iv, 128 );