Initial work on BLE advertisement gateway for BLE-WiFI packet forwarding
Dependencies: BLE_API mbed nRF51822
Diff: main.cpp
- 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);
+ }
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+