diff --git a/code/parasite/src/main.cpp b/code/parasite/src/main.cpp index baea4b1..79e64f0 100644 --- a/code/parasite/src/main.cpp +++ b/code/parasite/src/main.cpp @@ -13,17 +13,26 @@ constexpr int kSensAnalogPin = 4; // AIN2 constexpr int kDischargeEnablePin = 16; constexpr double kPWMFrequency = 500000; -char manufacturer_data[] = { - 0x01, - 0x02, - 0x03, -}; - constexpr int kManufacturerDataLen = 3; +// We can have at most 31 bytes here. +uint8_t advertisement_data[] = { + 9, // Length of name. + BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME, + 'P', 'a', 'r', 'a', 's', 'i', 't', 'e', + 7, // Length of the service data. + BLE_GAP_AD_TYPE_SERVICE_DATA, + 0x1a, 0x18, // Environment sensor service UUID. + 0x00, 0x00, // Raw soil humidity. + 0x00, 0x00, // Percentage soil humidity. +}; +constexpr size_t kRawSoilMoistureOffset = 14; +constexpr size_t kPercentSoilMoistureOffset = kRawSoilMoistureOffset + 2; +constexpr size_t kTemperatureOfsset = kRawSoilMoistureOffset + 4; + ble_gap_addr_t kGAPAddr{ 1, - BLE_GAP_ADDR_TYPE_RANDOM_STATIC, + BLE_GAP_ADDR_TYPE_PUBLIC, // This is the "reverse" order in comparison that the colon-separated // human-readable MAC addresses. {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}, @@ -36,13 +45,16 @@ void setupAdvertising() { } void updateAdvertisingData(int moisture_level) { - manufacturer_data[2] = moisture_level & 0xff; - manufacturer_data[1] = 0xff; + uint16_t packed_raw_moisture = moisture_level; + advertisement_data[kRawSoilMoistureOffset] = packed_raw_moisture >> 1; + advertisement_data[kRawSoilMoistureOffset + 1] = packed_raw_moisture & 0xff; + // manufacturer_data[1] = 0xff; Bluefruit.Advertising.stop(); Bluefruit.Advertising.clearData(); - Bluefruit.Advertising.addName(); - Bluefruit.Advertising.addManufacturerData(manufacturer_data, - kManufacturerDataLen); + // Bluefruit.Advertising.addName(); + // Bluefruit.Advertising.addManufacturerData(manufacturer_data, + // kManufacturerDataLen); + Bluefruit.Advertising.setData(advertisement_data, sizeof(advertisement_data)); Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds @@ -58,6 +70,12 @@ void setup() { analogReference(AR_VDD4); setupAdvertising(); + + Serial.println("Will advertise with MAC:"); + for (const auto byte : kGAPAddr.addr) { + Serial.printf("0x%02x ", byte); + } + Serial.println(); } void loop() { diff --git a/resources.md b/resources.md index efa51d8..38a86dc 100644 --- a/resources.md +++ b/resources.md @@ -151,6 +151,11 @@ I'm getting ~680 when in the air; ~65 while holding the sensor. The default reso * [main_loop](https://github.com/atc1441/ATC_MiThermometer/blob/916cef7db24977ec187e68ab6e718b7b7a4988e6/ATC_Thermometer/app.c#L76) * [advertisement_data](https://github.com/atc1441/ATC_MiThermometer/blob/master/ATC_Thermometer/ble.c#L39) definition * [set_adv_data](https://github.com/atc1441/ATC_MiThermometer/blob/master/ATC_Thermometer/ble.c#L178) - where the temp, humidity and batt levels are encoded into the advertisement data + * They don't use manufacturer data. They use a custom UUID service (0x181a). + * Using the manufacturer data requires a SIG membership for getting the manufacturer ID (first two bytes in the manufacturer data) + * Using the service data also requires applying for a 16-bit (2 byte) ID from SIG ([link](https://www.bluetooth.com/specifications/assigned-numbers/)) + * Aha! I think we can use the 0x181a service UUID (the same one the alternative xiaomi firmware uses). This service is reserved for "Environmental Sensors". Check out the offical assigned numbers list [here](https://btprodspecificationrefs.blob.core.windows.net/assigned-values/16-bit%20UUID%20Numbers%20Document.pdf). + * We can use the SERVICE_DATA (int 16) in the BLE advertisement packet to pack service data for the UUID 0x181a. * How the xiaomi BLE temp sensor works in ESPHome: [link](https://github.com/esphome/esphome/blob/5c86f332b269fd3e4bffcbdf3359a021419effdd/esphome/components/xiaomi_lywsd03mmc/xiaomi_lywsd03mmc.cpp) * [How advertisement works YouTube video](https://www.youtube.com/watch?v=CJcLabp42b4) by nordic * In your case: @@ -176,8 +181,8 @@ I'm getting ~680 when in the air; ~65 while holding the sensor. The default reso * Can we update the manufaturer advertising data dynamically? * [Hint on devzone.nordicsemi.com](https://devzone.nordicsemi.com/f/nordic-q-a/11217/adc-values-in-advertising-data-dynamically-changing) * What MAC address to use? - * Public - * Random + * Public - might have some security implications, since BLE can be used for tracking + * Random - safer, since its random, but it "breaks" our MAC-addr based Hub config ## Packing values into the advertising packet ### Soil humidity