Quick and dirty ble advetiment

This commit is contained in:
rbaron 2021-02-12 18:21:11 +01:00
parent 850df22f1a
commit b96129a6e6
8 changed files with 80 additions and 28 deletions

View file

@ -1,5 +0,0 @@
#include "ble.h"
#include "ble_advdata.h"
#include "nrf_sdh.h"
#include "nrf_sdh_ble.h"

View file

@ -0,0 +1 @@
#include "ble.h"

View file

@ -8,7 +8,7 @@ namespace parasite {
class BLEAdvertiser {
public:
void Advertise(std::string name, double moisture) {}
}
};
} // namespace parasite
#endif // _PARASITE_BLE_H_

View file

@ -8,14 +8,12 @@
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[common]
lib_deps = sandeepmistry/BLEPeripheral@^0.4.0
[env:e73-tbb]
platform = nordicnrf52
board = adafruit_feather_nrf52832
framework = arduino
build_flags = -DNRF52 -DS132 -DNRF51_S132
; build_flags = -DNRF52 -DS132 -DNRF51_S132 -DNRF5
; Let's keep it simple for now and just use adafruit_feather_nrf52832.
; board = e73-tbb

View file

@ -1,9 +1,9 @@
#include <Arduino.h>
// #include "ble.h"
#include "pwm.h"
#include "parasite/pwm.h"
#include "parasite/ble.h"
#include "nrf_sdh_ble.h"
#include <bluefruit.h>
constexpr int kLED1Pin = 17;
constexpr int kLED2Pin = 18;
@ -12,22 +12,30 @@ constexpr int kSensAnalogPin = 4; // AIN2
constexpr int kDischargeEnablePin = 16;
constexpr double kPWMFrequency = 500000;
// static void ble_stack_init(void) {
// ret_code_t err_code;
char manufacturer_data[] = {
0x01,
0x02,
0x03,
};
// err_code = nrf_sdh_enable_request();
// APP_ERROR_CHECK(err_code);
constexpr int kManufacturerDataLen = 3;
// // Configure the BLE stack using the default settings.
// // Fetch the start address of the application RAM.
// uint32_t ram_start = 0;
// err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
// APP_ERROR_CHECK(err_code);
void setupAdvertising() {
Bluefruit.begin(1, 1);
Bluefruit.setName("Parasite");
}
// // Enable BLE stack.
// err_code = nrf_sdh_ble_enable(&ram_start);
// APP_ERROR_CHECK(err_code);
// }
void updateAdvertisingData(int moisture_level) {
manufacturer_data[2] = moisture_level & 0xff;
manufacturer_data[1] = 0xff;
Bluefruit.Advertising.stop();
Bluefruit.Advertising.clearData();
Bluefruit.Advertising.addName();
Bluefruit.Advertising.addManufacturerData(manufacturer_data, kManufacturerDataLen);
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
}
void setup() {
Serial.begin(9600);
@ -37,11 +45,18 @@ void setup() {
digitalWrite(kDischargeEnablePin, HIGH);
analogReference(AR_VDD4);
setupAdvertising();
// Bluefruit.Advertising.start();
// ble.setConnectable(false);
// ble.addLocalAttribute();
}
void loop() {
int sens_val = analogRead(kSensAnalogPin);
Serial.printf("Val: %d\n", sens_val);
digitalToggle(kLED1Pin);
updateAdvertisingData(sens_val);
delay(500);
}
}

View file

@ -142,7 +142,50 @@ I'm getting ~680 when in the air; ~65 while holding the sensor. The default reso
# BLE
* BLE examples for platformio with nordicnrf52 platform: [link](https://github.com/platformio/platform-nordicnrf52/tree/master/examples)
* [BLEPeripheral](https://github.com/sandeepmistry/arduino-BLEPeripheral) seems to be a popular library choice
* [nrf5 BLE examples](https://devzone.nordicsemi.com/nordic/short-range-guides/b/bluetooth-low-energy/posts/ble-advertising-a-beginners-tutorial) are way more complicated than I need for now
* How the alternative firmware for the xiaomi temp sensor works: [link](https://github.com/atc1441/ATC_MiThermometer)
* The MCU is a [Telink TLSR8251](http://wiki.telink-semi.cn/doc/ds/DS_TLSR8251-E_Datasheet%20for%20Telink%20BLE+IEEE802.15.4%20Multi-Standard%20Wireless%20SoC%20TLSR8251.pdf)
* Deep sleep current is 1-2uA
* It sends an _advertisement packet_ every 1 minute with the MAC, temperature, humidity and battery level
* [main](https://github.com/atc1441/ATC_MiThermometer/blob/master/ATC_Thermometer/main.c)
* [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
* 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:
* GAP role: broadcaster
* Advertisement type: legacy ADV_NONCONN_IND (non-connectable broadcast)
* Advertising data starts at 22:17
* The payload might contain 37 bytes in the classic/legacy protocol:
* addr (6 bytes) (either public or random)
* Public has privacy concerns
* Random can be static or private (resolvable or non-resolvable)
* data (31 bytes)
* The 31 bytes of advertisement data can be split into structures
* Each structure has a length (1 byte), a type (n bytes) and data (remaining bytes)
* Examples of structures are service UUID, local name, manufacturer specific data
* Manufacturer specific data is usually the way to transmit data in the advertisement packet
* Requires a company id. Check out the [list](https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers). Adafruit has the 0x0822.
* [BLEPeripheral](https://github.com/sandeepmistry/arduino-BLEPeripheral) seems to be a popular library choice
* [setManufacturerData](https://github.com/sandeepmistry/arduino-BLEPeripheral/blob/161a4163f565be3cd5b62bbc59f0c2b522d82b02/src/BLEPeripheral.h#L72) is probably what we want
* It seems to be highly geared towards nrf51 SOCs, although it mentions support for some nrf52 ones
* [Adafruit_nRF52_Arduino](https://github.com/adafruit/Adafruit_nRF52_Arduino)
* [BLEAdvertising guide](https://learn.adafruit.com/bluefruit-nrf52-feather-learning-guide/bleadvertising)
* [BLEAdvertising.h](https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/libraries/Bluefruit52Lib/src/BLEAdvertising.h#L87)
* 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)
# OTA
# Central BLE
The "central" BLE will be responsible for listening to parasite's BLE broadcasts and parsing its manufacturer's data.
One idea is to use ESPHome for this, for example like the xiaomi sensor does:
* [Xiaomi component's parse_device](https://github.com/esphome/esphome/blob/dev/esphome/components/xiaomi_lywsd03mmc/xiaomi_lywsd03mmc.cpp#L19)
* [esp32_ble_tracker calls all registered parse_devices()](https://github.com/esphome/esphome/blob/dev/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp#L68)
* [Setting up the development environment for ESPHome](https://esphome.io/guides/contributing.html#setting-up-development-environment)
Question: parasite will advertise a _lot_ of packets in short bursts. How is this data "deduplicated"? I imagine ESPHome won't parse all the packets and forward them to MQTT.
# OTA
# Measuring current consumption
* Good [issue](https://github.com/atc1441/ATC_MiThermometer/issues/134) on the xiaomi sensor tracker