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

Dependencies:   BLE_API mbed nRF51822

main.cpp

Committer:
petekmet
Date:
2016-03-30
Revision:
0:4f2e461b0995

File content as of revision 0:4f2e461b0995:

#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);
        } 
    }
}