A scanner framework that receives advertisements, filters them by MAC, and prints out some data as CSV over the serial port

Dependencies:   BLE_API mbed nRF51822

Fork of BasicScanner by Mobius IoT

Revision:
14:d8f4a49c9fb3
Parent:
13:8999c8b2e18e
--- a/main.cpp	Wed Jun 01 20:36:08 2016 +0000
+++ b/main.cpp	Tue Mar 28 19:05:45 2017 +0000
@@ -1,113 +1,137 @@
-
 #include "mbed.h"
 #include "ble/BLE.h"
-#include "TMP_nrf51/TMP_nrf51.h"
+
+// Compile time options
+#define BLINK_LED           1 // Whether to blink the LED
+#define CYCLE_CHANNELS      0 // Whether to scan cycling between
+                              // single channels or normally
+#define BAUD_RATE           115200 // baud
 
+// Experiment parameters
+#define CYCLE_INTERVAL      5000    // ms; see CYCLE_CHANNELS
+#define SCAN_INTERVAL       500     // ms
+#define SCAN_WINDOW         SCAN_INTERVAL   // ms; must be <= SCAN_INTERVAL
+#define BLINK_INTERVAL      1000    // ms
 
-#include "UARTService.h"
+// Constants
+#define NRF_RADIO_FREQUENCY (*(uint32_t*)(0x40001508UL))
+
+BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
+
+uint8_t channel = 37;
+
+Serial pc(p9, p11);
+Timer uptime;
 
 
-#define UART_TX     p9
-#define UART_RX     p11
-
-#define LOG(...)    { pc.printf(__VA_ARGS__); }
-
-#define SCAN_INTERVAL 500
-#define SCAN_WINDOW 500
-
- //Baud rate: for the TinyBLE use 115200 for term or 4000000 for internal energy monitoring
-#define BAUD_RATE 115200
-
-DigitalOut alivenessLED(LED1, 1);
-Ticker     ticker;
-
-Serial pc(UART_TX, UART_RX);
-
-UARTService *uartServicePtr;
-
-
-
-void periodicCallback(void)
+#if BLINK_LED
+void blinkCallback(void)
 {
-    alivenessLED = !alivenessLED; /* Do blinky on LED1 while we're waiting for BLE events. This is optional. */
+    static DigitalOut led(LED1, 1);
+    led = !led;
 }
+#endif
 
 /*
  * This function is called every time we scan an advertisement.
  */
 void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params)
 {
-    // Here is what we do when we receive a packet
-    
-    /* Search for the manufacturer specific data with matching application-ID */
-    int addr_length = 6;
-
-    if(params->peerAddr[addr_length-1] == 0xaa)
+    if (params->peerAddr[1] == 0xAA &&
+        params->peerAddr[2] == 0xAA &&
+        params->peerAddr[3] == 0xAA &&
+        params->peerAddr[4] == 0xAA &&
+        params->peerAddr[5] == 0xAA)
     {
-        LOG("\nFrom: ");
-        for(int i=0; i<addr_length; i++)
-             LOG("%02x:", params->peerAddr[addr_length-i-1]);
-        //print payload
-        LOG(" RSSI: %d", params->rssi);
-        LOG("\n          Payload:  ");
-        for(int i=0; i < params->advertisingDataLen; i++) 
-                LOG(" %02x", params->advertisingData[i]);
-        
-        //print close of round
-        LOG("\n\n");
+        printf("%d,%d,%d,%d,%d\n",
+            params->peerAddr[0],
+            params->advertisingData[2],
+            uptime.read_ms(),
+            params->rssi,
+//#if CYCLE_CHANNELS
+//            channel
+//#else
+            NRF_RADIO_FREQUENCY
+//            params->advertisingData[3] // Infer channel from packet data
+//#endif
+        );
     }
 }
 
-/**
- * This function is called when the ble initialization process has failed
- */
-void onBleInitError(BLE &ble, ble_error_t error)
+void setupScanning(uint8_t channel, uint16_t scanInterval, uint16_t scanWindow)
 {
-    /* Initialization error handling should go here */
-    LOG("Crap, the BLE radio is broken\n");
+#if CYCLE_CHANNELS
+    // TODO: make the frequency stick instead of letting softdevice overwrite it
+    switch (channel) {
+        case 37:
+            NRF_RADIO_FREQUENCY = 2; // 2402 MHz
+            break;
+        case 38:
+            NRF_RADIO_FREQUENCY = 26; // 2426 MHz
+            break;
+        case 39:
+            NRF_RADIO_FREQUENCY = 80; // 2480 MHz
+            break;
+        default:
+            break;
+    }
+#endif
+    ble.gap().setScanParams(scanInterval, scanWindow);
+    ble.gap().startScan(advertisementCallback);
 }
 
-/**
- * Callback triggered when the ble initialization process has finished
- */
-void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
+#if CYCLE_CHANNELS
+void cycleChannelCallback(void)
 {
-    BLE&        ble   = params->ble;
-    ble_error_t error = params->error;
+    switch (channel) {
+        case 37:
+            channel = 38;
+            break;
+        case 38:
+            channel = 39;
+            break;
+        case 39:
+            channel = 37;
+            break;
+        default:
+            channel = 0;
+            break;
+    }
+    setupScanning(channel, SCAN_INTERVAL, SCAN_WINDOW);
+}
+#endif
 
-    if (error != BLE_ERROR_NONE) {
-        /* In case of error, forward the error handling to onBleInitError */
-        onBleInitError(ble, error);
+void bleInitCallback(BLE::InitializationCompleteCallbackContext *params)
+{
+    static Ticker cycleChannelTicker;
+    
+    if (params->error != BLE_ERROR_NONE ||
+        params->ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
         return;
     }
 
-    /* Ensure that it is the default instance of BLE */
-    if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
-        return;
-    }
-
-    /* Setup and start scanning */
-    ble.gap().setScanParams(SCAN_INTERVAL /* scan interval */, SCAN_WINDOW /* scan window */);
-    ble.gap().startScan(advertisementCallback);
+#if CYCLE_CHANNELS
+    setupScanning(channel, SCAN_INTERVAL, SCAN_WINDOW);
+    cycleChannelTicker.attach(cycleChannelCallback, CYCLE_INTERVAL/1000.0);
+#else
+    setupScanning(channel, SCAN_INTERVAL, SCAN_WINDOW);
+#endif
 }
 
 int main(void)
 {
-   
-    pc.baud(BAUD_RATE);
+    static Ticker ledTicker, incSeqNumTicker;
+    uptime.start();
     
-    LOG("---- Basic Scanner ACTIVIZE ----\n");
-   
-    
-    ticker.attach(periodicCallback, 1);  /* flash the LED because reasons */
+    pc.baud(BAUD_RATE);
 
-    LOG("Bring up the BLE radio\n");
-    BLE &ble = BLE::Instance();
-    ble.init(bleInitComplete);
+#if BLINK_LED
+    ledTicker.attach(blinkCallback, BLINK_INTERVAL/1000.0);
+#endif
 
-    UARTService uartService(ble);
-    uartServicePtr = &uartService;
-    //uartService.retargetStdout();
+    printf("\nID,Sequence Number,Timestamp,RSSI,Channel\n");
+    BLE &ble = BLE::Instance();
+    ble.init(bleInitCallback);
 
     while (true) {
         ble.waitForEvent();