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

Dependencies:   BLE_API mbed nRF51822

Committer:
petekmet
Date:
Wed Mar 30 07:17:33 2016 +0000
Revision:
0:4f2e461b0995
initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
petekmet 0:4f2e461b0995 1 #include "mbed.h"
petekmet 0:4f2e461b0995 2 #include "BLE.h"
petekmet 0:4f2e461b0995 3 #include "Gap.h"
petekmet 0:4f2e461b0995 4 #include "stdio.h"
petekmet 0:4f2e461b0995 5
petekmet 0:4f2e461b0995 6 typedef struct{
petekmet 0:4f2e461b0995 7 BLEProtocol::AddressBytes_t address;
petekmet 0:4f2e461b0995 8 uint8_t frameId;
petekmet 0:4f2e461b0995 9 uint16_t age;
petekmet 0:4f2e461b0995 10 } DeviceEntry;
petekmet 0:4f2e461b0995 11
petekmet 0:4f2e461b0995 12 typedef struct{
petekmet 0:4f2e461b0995 13 BLEProtocol::AddressBytes_t address;
petekmet 0:4f2e461b0995 14 uint8_t data[31];
petekmet 0:4f2e461b0995 15 uint8_t dataLen;
petekmet 0:4f2e461b0995 16 } TransmitData;
petekmet 0:4f2e461b0995 17
petekmet 0:4f2e461b0995 18 BLE ble;
petekmet 0:4f2e461b0995 19 Serial pc(USBTX, USBRX);
petekmet 0:4f2e461b0995 20 DeviceEntry *deviceArray;
petekmet 0:4f2e461b0995 21 TransmitData txData;
petekmet 0:4f2e461b0995 22 bool txEnabled = false;
petekmet 0:4f2e461b0995 23 uint8_t devicesCount = 0;
petekmet 0:4f2e461b0995 24 char tmp[18];
petekmet 0:4f2e461b0995 25
petekmet 0:4f2e461b0995 26 void dumpBytes(const uint8_t *data, uint8_t len){
petekmet 0:4f2e461b0995 27 for(uint8_t i=0;i<len; i++){
petekmet 0:4f2e461b0995 28 pc.printf("%02X ", data[i]);
petekmet 0:4f2e461b0995 29 }
petekmet 0:4f2e461b0995 30 }
petekmet 0:4f2e461b0995 31
petekmet 0:4f2e461b0995 32 bool isAddressEqual(const uint8_t *addr1, const uint8_t *addr2){
petekmet 0:4f2e461b0995 33 uint8_t n;
petekmet 0:4f2e461b0995 34 for(n=0;n<6;n++){
petekmet 0:4f2e461b0995 35 if(addr1[n] != addr2[n]){
petekmet 0:4f2e461b0995 36 return false;
petekmet 0:4f2e461b0995 37 }
petekmet 0:4f2e461b0995 38 }
petekmet 0:4f2e461b0995 39 return true;
petekmet 0:4f2e461b0995 40 }
petekmet 0:4f2e461b0995 41
petekmet 0:4f2e461b0995 42 void getAddressString(char* addressString, const uint8_t *address){
petekmet 0:4f2e461b0995 43 sprintf(addressString, "%02X%02X%02X%02X%02X%02X", address[5], address[4], address[3], address[2], address[1], address[0]);
petekmet 0:4f2e461b0995 44 }
petekmet 0:4f2e461b0995 45
petekmet 0:4f2e461b0995 46 void sendToWifi(BLEProtocol::AddressBytes_t *address, const uint8_t *data, uint8_t dataLen){
petekmet 0:4f2e461b0995 47 if(txEnabled==false){
petekmet 0:4f2e461b0995 48 txEnabled = true;
petekmet 0:4f2e461b0995 49 getAddressString(tmp, (uint8_t*)address);
petekmet 0:4f2e461b0995 50 memcpy(txData.address, address, sizeof(BLEProtocol::AddressBytes_t));
petekmet 0:4f2e461b0995 51 memcpy(txData.data, data, dataLen);
petekmet 0:4f2e461b0995 52 txData.dataLen = dataLen;
petekmet 0:4f2e461b0995 53 }
petekmet 0:4f2e461b0995 54 }
petekmet 0:4f2e461b0995 55
petekmet 0:4f2e461b0995 56 void sendToWifi(){
petekmet 0:4f2e461b0995 57 if(txData.data[3] == 0xFB){
petekmet 0:4f2e461b0995 58 //beescale
petekmet 0:4f2e461b0995 59 }else
petekmet 0:4f2e461b0995 60 if(txData.data[3] == 0xFA){
petekmet 0:4f2e461b0995 61 //weatherbeacon
petekmet 0:4f2e461b0995 62 float temp = (float)(txData.data[11]|txData.data[12]<<8)/100;
petekmet 0:4f2e461b0995 63 int16_t pressure = txData.data[14]|txData.data[15]<<8;
petekmet 0:4f2e461b0995 64 uint16_t battery = txData.data[16]|txData.data[17]<<8;
petekmet 0:4f2e461b0995 65
petekmet 0:4f2e461b0995 66 pc.printf("\r\ntemperature is %.1f C\r\n", temp);
petekmet 0:4f2e461b0995 67 pc.printf("humidity %d%%\r\n", txData.data[13]);
petekmet 0:4f2e461b0995 68 if(pressure>0){
petekmet 0:4f2e461b0995 69 pc.printf("pressure %d hPa\r\n", pressure);
petekmet 0:4f2e461b0995 70 }
petekmet 0:4f2e461b0995 71 pc.printf("battery %dmV\r\n", battery);
petekmet 0:4f2e461b0995 72 }else
petekmet 0:4f2e461b0995 73 if(txData.data[3] == 0xFC){
petekmet 0:4f2e461b0995 74 //weatherbeacon
petekmet 0:4f2e461b0995 75 float temp = (float)(txData.data[11]|txData.data[12]<<8)/10;
petekmet 0:4f2e461b0995 76 int16_t pressure = txData.data[14]|txData.data[15]<<8;
petekmet 0:4f2e461b0995 77 uint16_t battery = txData.data[16]|txData.data[17]<<8;
petekmet 0:4f2e461b0995 78 /*
petekmet 0:4f2e461b0995 79 pc.printf("\r\ntemperature is %.1f C\r\n", temp);
petekmet 0:4f2e461b0995 80 pc.printf("humidity %d%%\r\n", txData.data[13]);
petekmet 0:4f2e461b0995 81 if(pressure>0){
petekmet 0:4f2e461b0995 82 pc.printf("pressure %d hPa\r\n", pressure);
petekmet 0:4f2e461b0995 83 }
petekmet 0:4f2e461b0995 84 */
petekmet 0:4f2e461b0995 85 pc.printf("START\r\n");
petekmet 0:4f2e461b0995 86 pc.printf("api.thingspeak.com\r\n");
petekmet 0:4f2e461b0995 87 pc.printf("/update.json\r\n");
petekmet 0:4f2e461b0995 88 pc.printf("key=WL5U725HQ30KWELM&field1=%.1f&field2=%d&field3=%d&field4=%d\r\n", temp, txData.data[13], pressure, battery);
petekmet 0:4f2e461b0995 89 pc.printf("END\r\n");
petekmet 0:4f2e461b0995 90 //START
petekmet 0:4f2e461b0995 91 //HOST
petekmet 0:4f2e461b0995 92 //QUERY
petekmet 0:4f2e461b0995 93 //POST DATA
petekmet 0:4f2e461b0995 94 //END
petekmet 0:4f2e461b0995 95 }
petekmet 0:4f2e461b0995 96
petekmet 0:4f2e461b0995 97 getAddressString(tmp, (uint8_t*)txData.address);
petekmet 0:4f2e461b0995 98 dumpBytes(txData.data, txData.dataLen);
petekmet 0:4f2e461b0995 99 pc.printf("\r\nuploading %d bytes, frame type %02X from %s to the cloud...", txData.dataLen, txData.data[3], tmp);
petekmet 0:4f2e461b0995 100 wait(2);
petekmet 0:4f2e461b0995 101 pc.printf(" OK\r\n");
petekmet 0:4f2e461b0995 102 }
petekmet 0:4f2e461b0995 103
petekmet 0:4f2e461b0995 104 void updateDevice(const uint8_t *address, uint8_t frameId, const uint8_t *data, uint8_t dataLen){
petekmet 0:4f2e461b0995 105
petekmet 0:4f2e461b0995 106 //search if there are some devices, find if this already exists
petekmet 0:4f2e461b0995 107 DeviceEntry *_devArr = deviceArray;
petekmet 0:4f2e461b0995 108 for(uint8_t n=0;n<devicesCount;n++){
petekmet 0:4f2e461b0995 109 if(isAddressEqual(_devArr->address, address)){
petekmet 0:4f2e461b0995 110 if(_devArr->frameId == frameId){
petekmet 0:4f2e461b0995 111 //check if frameId is equal
petekmet 0:4f2e461b0995 112 //pc.printf("frameId is equal, skipping\r\n");
petekmet 0:4f2e461b0995 113 }else{
petekmet 0:4f2e461b0995 114 _devArr->frameId = frameId;
petekmet 0:4f2e461b0995 115 getAddressString(tmp, address);
petekmet 0:4f2e461b0995 116 pc.printf("\r\nnew frameId %d on %s\r\n", frameId, tmp);
petekmet 0:4f2e461b0995 117 sendToWifi((BLEProtocol::AddressBytes_t*)address, data, dataLen);
petekmet 0:4f2e461b0995 118 }
petekmet 0:4f2e461b0995 119 return;
petekmet 0:4f2e461b0995 120 }
petekmet 0:4f2e461b0995 121 _devArr+=sizeof(DeviceEntry);
petekmet 0:4f2e461b0995 122 }
petekmet 0:4f2e461b0995 123
petekmet 0:4f2e461b0995 124 //create new device (existing device not found or no devices yet)
petekmet 0:4f2e461b0995 125 DeviceEntry *_newDevArr = (DeviceEntry *)malloc(sizeof(DeviceEntry)*(devicesCount+1));
petekmet 0:4f2e461b0995 126 if(_newDevArr!=NULL){
petekmet 0:4f2e461b0995 127 if(deviceArray!=NULL){ //resizing
petekmet 0:4f2e461b0995 128 pc.printf("\r\nextending devices array, now size %d, old %d, new %d\r\n", devicesCount+1, deviceArray, _newDevArr);
petekmet 0:4f2e461b0995 129 memcpy(_newDevArr, deviceArray, sizeof(DeviceEntry)*devicesCount);
petekmet 0:4f2e461b0995 130 free(deviceArray); //release old array
petekmet 0:4f2e461b0995 131
petekmet 0:4f2e461b0995 132 }else{
petekmet 0:4f2e461b0995 133 //initializing
petekmet 0:4f2e461b0995 134 pc.printf("\r\ninitializing dev array\r\n");
petekmet 0:4f2e461b0995 135 }
petekmet 0:4f2e461b0995 136
petekmet 0:4f2e461b0995 137 devicesCount++;
petekmet 0:4f2e461b0995 138 deviceArray = _newDevArr; //remember new resized array
petekmet 0:4f2e461b0995 139
petekmet 0:4f2e461b0995 140 //put to array
petekmet 0:4f2e461b0995 141 DeviceEntry *newDevEntry = deviceArray + ((devicesCount-1)*sizeof(DeviceEntry));
petekmet 0:4f2e461b0995 142 memcpy(newDevEntry->address, address, sizeof(BLEProtocol::AddressBytes_t));
petekmet 0:4f2e461b0995 143 newDevEntry->frameId = frameId;
petekmet 0:4f2e461b0995 144 getAddressString(tmp, address);
petekmet 0:4f2e461b0995 145 pc.printf("address %s and frameId %d registered\r\n", tmp, frameId);
petekmet 0:4f2e461b0995 146 sendToWifi((BLEProtocol::AddressBytes_t*)address, data, dataLen);
petekmet 0:4f2e461b0995 147
petekmet 0:4f2e461b0995 148 }else{
petekmet 0:4f2e461b0995 149 pc.printf("\r\nmalloc failed\r\n");
petekmet 0:4f2e461b0995 150 }
petekmet 0:4f2e461b0995 151 }
petekmet 0:4f2e461b0995 152
petekmet 0:4f2e461b0995 153 void onScanResult(const Gap::AdvertisementCallbackParams_t *params){
petekmet 0:4f2e461b0995 154 uint8_t n;
petekmet 0:4f2e461b0995 155 const uint8_t *data = params->advertisingData;
petekmet 0:4f2e461b0995 156 for(n=0;n<params->advertisingDataLen-1;n++){
petekmet 0:4f2e461b0995 157 const uint8_t len = data[n];
petekmet 0:4f2e461b0995 158 const uint8_t tpe = data[n+1];
petekmet 0:4f2e461b0995 159 //printf("Type %02X, l=%d\r\n", tpe, len);
petekmet 0:4f2e461b0995 160 if(tpe==0xFF){//search for manufacturer-data
petekmet 0:4f2e461b0995 161 if(data[n+2] == 0xFF && data[n+3] == 0xFF && (data[n+4] == 0xFA || data[n+4] == 0xFC || data[n+4] == 0xFC)){
petekmet 0:4f2e461b0995 162 updateDevice(params->peerAddr, data[n+5], data+n+1, len);
petekmet 0:4f2e461b0995 163 }
petekmet 0:4f2e461b0995 164 }
petekmet 0:4f2e461b0995 165 n+=len;
petekmet 0:4f2e461b0995 166 }
petekmet 0:4f2e461b0995 167 }
petekmet 0:4f2e461b0995 168
petekmet 0:4f2e461b0995 169 int main(void)
petekmet 0:4f2e461b0995 170 {
petekmet 0:4f2e461b0995 171 pc.baud(9600);
petekmet 0:4f2e461b0995 172 ble.init();
petekmet 0:4f2e461b0995 173 while (ble.hasInitialized() == false) { /* spin loop */ }
petekmet 0:4f2e461b0995 174 ble.gap().setScanParams(1000 /* scan interval */, 1000 /* scan window */);
petekmet 0:4f2e461b0995 175 ble.gap().startScan(onScanResult);
petekmet 0:4f2e461b0995 176
petekmet 0:4f2e461b0995 177 pc.printf("Scan Start \r\n");
petekmet 0:4f2e461b0995 178 while(1){
petekmet 0:4f2e461b0995 179 ble.waitForEvent();
petekmet 0:4f2e461b0995 180
petekmet 0:4f2e461b0995 181 if(txEnabled){
petekmet 0:4f2e461b0995 182 ble.gap().stopScan();
petekmet 0:4f2e461b0995 183 sendToWifi();
petekmet 0:4f2e461b0995 184 txEnabled = false;
petekmet 0:4f2e461b0995 185 ble.gap().startScan(onScanResult);
petekmet 0:4f2e461b0995 186 }
petekmet 0:4f2e461b0995 187 }
petekmet 0:4f2e461b0995 188 }
petekmet 0:4f2e461b0995 189
petekmet 0:4f2e461b0995 190
petekmet 0:4f2e461b0995 191
petekmet 0:4f2e461b0995 192
petekmet 0:4f2e461b0995 193
petekmet 0:4f2e461b0995 194
petekmet 0:4f2e461b0995 195
petekmet 0:4f2e461b0995 196
petekmet 0:4f2e461b0995 197
petekmet 0:4f2e461b0995 198
petekmet 0:4f2e461b0995 199
petekmet 0:4f2e461b0995 200
petekmet 0:4f2e461b0995 201
petekmet 0:4f2e461b0995 202
petekmet 0:4f2e461b0995 203
petekmet 0:4f2e461b0995 204