Initial work on BLE advertisement gateway for BLE-WiFI packet forwarding
Dependencies: BLE_API mbed nRF51822
main.cpp@0:4f2e461b0995, 2016-03-30 (annotated)
- Committer:
- petekmet
- Date:
- Wed Mar 30 07:17:33 2016 +0000
- Revision:
- 0:4f2e461b0995
initial commit
Who changed what in which revision?
User | Revision | Line number | New 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 |