Initial work on BLE advertisement gateway for BLE-WiFI packet forwarding

Dependencies:   BLE_API mbed nRF51822

Revision:
0:4f2e461b0995
diff -r 000000000000 -r 4f2e461b0995 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Mar 30 07:17:33 2016 +0000
@@ -0,0 +1,204 @@
+#include "mbed.h"
+#include "BLE.h"
+#include "Gap.h"
+#include "stdio.h"
+
+typedef struct{
+    BLEProtocol::AddressBytes_t address;
+    uint8_t frameId;
+    uint16_t age;
+} DeviceEntry;
+
+typedef struct{
+    BLEProtocol::AddressBytes_t address;
+    uint8_t data[31];
+    uint8_t dataLen;
+} TransmitData;
+
+BLE  ble;
+Serial pc(USBTX, USBRX);
+DeviceEntry *deviceArray;
+TransmitData txData;
+bool txEnabled = false;
+uint8_t devicesCount = 0;
+char tmp[18];
+
+void dumpBytes(const uint8_t *data, uint8_t len){
+    for(uint8_t i=0;i<len; i++){
+        pc.printf("%02X ", data[i]);
+    }
+}
+
+bool isAddressEqual(const uint8_t *addr1, const uint8_t *addr2){
+    uint8_t n;
+    for(n=0;n<6;n++){
+        if(addr1[n] != addr2[n]){
+            return false;
+        }
+    }
+    return true;
+}
+
+void getAddressString(char* addressString, const uint8_t *address){
+    sprintf(addressString, "%02X%02X%02X%02X%02X%02X", address[5], address[4], address[3], address[2], address[1], address[0]);
+}
+
+void sendToWifi(BLEProtocol::AddressBytes_t *address, const uint8_t *data, uint8_t dataLen){
+    if(txEnabled==false){
+        txEnabled = true;
+        getAddressString(tmp, (uint8_t*)address);
+        memcpy(txData.address, address, sizeof(BLEProtocol::AddressBytes_t));
+        memcpy(txData.data, data, dataLen);
+        txData.dataLen = dataLen;
+    }
+}
+
+void sendToWifi(){
+    if(txData.data[3] == 0xFB){
+        //beescale
+    }else
+    if(txData.data[3] == 0xFA){
+        //weatherbeacon
+        float temp = (float)(txData.data[11]|txData.data[12]<<8)/100;
+        int16_t pressure = txData.data[14]|txData.data[15]<<8;
+        uint16_t battery = txData.data[16]|txData.data[17]<<8;
+        
+        pc.printf("\r\ntemperature is %.1f C\r\n", temp);
+        pc.printf("humidity %d%%\r\n", txData.data[13]);
+        if(pressure>0){
+            pc.printf("pressure %d hPa\r\n", pressure);
+        }
+        pc.printf("battery %dmV\r\n", battery);
+    }else
+    if(txData.data[3] == 0xFC){
+        //weatherbeacon
+        float temp = (float)(txData.data[11]|txData.data[12]<<8)/10;
+        int16_t pressure = txData.data[14]|txData.data[15]<<8;
+        uint16_t battery = txData.data[16]|txData.data[17]<<8;
+        /*
+        pc.printf("\r\ntemperature is %.1f C\r\n", temp);
+        pc.printf("humidity %d%%\r\n", txData.data[13]);
+        if(pressure>0){
+            pc.printf("pressure %d hPa\r\n", pressure);
+        }
+        */
+        pc.printf("START\r\n");
+        pc.printf("api.thingspeak.com\r\n");
+        pc.printf("/update.json\r\n");
+        pc.printf("key=WL5U725HQ30KWELM&field1=%.1f&field2=%d&field3=%d&field4=%d\r\n", temp, txData.data[13], pressure, battery);
+        pc.printf("END\r\n");
+        //START
+        //HOST
+        //QUERY
+        //POST DATA
+        //END
+    }
+    
+    getAddressString(tmp, (uint8_t*)txData.address);
+    dumpBytes(txData.data, txData.dataLen);
+    pc.printf("\r\nuploading %d bytes, frame type %02X from %s to the cloud...", txData.dataLen, txData.data[3], tmp);
+    wait(2);
+    pc.printf(" OK\r\n");
+} 
+
+void updateDevice(const uint8_t *address, uint8_t frameId, const uint8_t *data, uint8_t dataLen){
+    
+        //search if there are some devices, find if this already exists
+        DeviceEntry *_devArr = deviceArray;
+        for(uint8_t n=0;n<devicesCount;n++){
+            if(isAddressEqual(_devArr->address, address)){
+                if(_devArr->frameId == frameId){
+                    //check if frameId is equal
+                    //pc.printf("frameId is equal, skipping\r\n");
+                }else{
+                    _devArr->frameId = frameId;
+                    getAddressString(tmp, address);
+                    pc.printf("\r\nnew frameId %d on %s\r\n", frameId, tmp);
+                    sendToWifi((BLEProtocol::AddressBytes_t*)address, data, dataLen);
+                }
+                return;
+            } 
+            _devArr+=sizeof(DeviceEntry);
+        }
+        
+        //create new device (existing device not found or no devices yet)
+        DeviceEntry *_newDevArr = (DeviceEntry *)malloc(sizeof(DeviceEntry)*(devicesCount+1));
+        if(_newDevArr!=NULL){
+            if(deviceArray!=NULL){ //resizing
+                pc.printf("\r\nextending devices array, now size %d, old %d, new %d\r\n", devicesCount+1, deviceArray, _newDevArr);
+                memcpy(_newDevArr, deviceArray, sizeof(DeviceEntry)*devicesCount);
+                free(deviceArray); //release old array
+                
+            }else{
+                //initializing
+                pc.printf("\r\ninitializing dev array\r\n");
+            }
+            
+            devicesCount++;
+            deviceArray = _newDevArr; //remember new resized array
+            
+            //put to array
+            DeviceEntry *newDevEntry = deviceArray + ((devicesCount-1)*sizeof(DeviceEntry)); 
+            memcpy(newDevEntry->address, address, sizeof(BLEProtocol::AddressBytes_t));
+            newDevEntry->frameId = frameId;
+            getAddressString(tmp, address);
+            pc.printf("address %s and frameId %d registered\r\n", tmp, frameId);
+            sendToWifi((BLEProtocol::AddressBytes_t*)address, data, dataLen);
+            
+        }else{
+            pc.printf("\r\nmalloc failed\r\n");
+        }
+}
+
+void onScanResult(const Gap::AdvertisementCallbackParams_t *params){
+    uint8_t n;
+    const uint8_t *data = params->advertisingData;
+    for(n=0;n<params->advertisingDataLen-1;n++){
+        const uint8_t len = data[n];
+        const uint8_t tpe = data[n+1];
+        //printf("Type %02X, l=%d\r\n", tpe, len);
+        if(tpe==0xFF){//search for manufacturer-data
+            if(data[n+2] == 0xFF && data[n+3] == 0xFF && (data[n+4] == 0xFA || data[n+4] == 0xFC || data[n+4] == 0xFC)){
+                updateDevice(params->peerAddr, data[n+5], data+n+1, len);
+            }
+        }
+        n+=len;
+    }
+}
+
+int main(void)
+{
+    pc.baud(9600);
+    ble.init();
+    while (ble.hasInitialized()  == false) { /* spin loop */ }
+    ble.gap().setScanParams(1000 /* scan interval */, 1000 /* scan window */);
+    ble.gap().startScan(onScanResult);
+    
+    pc.printf("Scan Start \r\n");
+    while(1){
+        ble.waitForEvent();
+        
+        if(txEnabled){
+            ble.gap().stopScan();
+            sendToWifi();
+            txEnabled = false;
+            ble.gap().startScan(onScanResult);
+        } 
+    }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+