BLE ADV Gateway, converts advertisement to proper JSON serial output

Dependencies:   BLE_API mbed mbedtls nRF51822

main.cpp

Committer:
electronichamsters
Date:
2017-07-10
Revision:
10:9db2ac7e1eea
Parent:
9:1ea51b2048a8
Child:
11:d5edb6e3edab

File content as of revision 10:9db2ac7e1eea:

/* 

 
 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.



----------------------------------------------


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"
#include "mbedtls/aes.h"


//comment out when done with debug uart, else eats batteries
#define MyDebugEnb 0


//DigitalOut led1(LED1, 1);
Ticker     ticker;

//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)
{
    //led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
    //device.printf("periodic 5...");
    //device.printf("\r\n");
}

void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) {


    //BLE MAC Address (6 bytes):
    //      params->peerAddr[5]
    //      params->peerAddr[4]
    //      ...
    //      params->peerAddr[0]
    //RSSI = params->rssi
    //Payload
    //  params->advertisingData[#<advertisingDataLen]
    

    
    //              [<---MY DATA-->]
    //0x02      0x01    0x06    0x06    0xff    D   E   C   ?  ?
    //0         1       2       3       4       5   6   7   8   9

    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) )
        {
            /*
            BLE Received from MAC C2F154BB0AF9
            volt:3.11,mag:1
            
            uart-transmit:
            mac:C2F154BB0AF9,rssi:##,volt:3.11,mag:1
            
            /ble/C2F154BB0AF9/rssi
            /ble/C2F154BB0AF9/1st_token
            /ble/c2F153
            
            */
            /*
            device.printf("Adv peerAddr: [%02x%02x%02x%02x%02x%02x] rssi %d, ScanResp: %u, AdvType: %u\r\n",
              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++)
            {
                //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

            //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++)
                {
                    //device.printf("%02x", params->advertisingData[index]);
                    device.printf("%c", params->advertisingData[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
            */
            
        }//end if it's our adv
    }//end if advertisingDataLen




}//end advertisementCallback

/**
 * This function is called when the ble initialization process has failed
 */
void onBleInitError(BLE &ble, ble_error_t error)
{
    /* Initialization error handling should go here */
    device.printf("periodic callback ");
    device.printf("\r\n");
}

/**
 * Callback triggered when the ble initialization process has finished
 */
void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
{
    BLE&        ble   = params->ble;
    ble_error_t error = params->error;

    if (error != BLE_ERROR_NONE) {
        /* In case of error, forward the error handling to onBleInitError */
        onBleInitError(ble, error);
        return;
    }

    /* Ensure that it is the default instance of BLE */
    if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
        return;
    }
 
    // in ms.  Duty cycle = (interval / window);  200ms/500ms = 40%
    ble.gap().setScanParams(500 /* scan interval */, 200 /* scan window */);
    ble.gap().startScan(advertisementCallback);
}

int main(void)
{
    device.baud(9600);
    device.printf("started main 04... ");
    device.printf("\r\n");
    ticker.attach(periodicCallback, 5);
    
    //mbedtls_aes_init(&aes);
    mbedtls_aes_setkey_dec( &aes, iv, 128 );
    //mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_DECRYPT, input, output );

    BLE &ble = BLE::Instance();
    ble.init(bleInitComplete);

    while (true) {
        ble.waitForEvent();
    }
}