Work more on Bluetti

This commit is contained in:
2026-06-06 18:23:23 +10:00
parent d532c7da89
commit 8c7b28a82b
5 changed files with 235 additions and 21 deletions
+27 -4
View File
@@ -93,11 +93,15 @@ bool BluettiADV::begin(uint32_t scanDur) {
bool BluettiADV::addDevice(const char* name, const char* mac, const char* hexKey) {
if (deviceCount >= BLUETTI_ADV_MAX_DEVICES) return false;
if (!hexKey || strlen(hexKey) != 32) return false;
if (!mac || strlen(mac) == 0) return false;
char normMac[BLUETTI_ADV_MAC_LEN];
normalizeMAC(mac, normMac);
if (findDevice(normMac)) return false;
// MAC is optional: an empty MAC is a wildcard that matches (and then latches
// onto) the first Bluetti broadcaster seen — convenient for a single device.
char normMac[BLUETTI_ADV_MAC_LEN] = {0};
bool hasMac = (mac && strlen(mac) > 0);
if (hasMac) {
normalizeMAC(mac, normMac);
if (findDevice(normMac)) return false;
}
DeviceEntry* e = &devices[deviceCount];
memset(e, 0, sizeof(DeviceEntry));
@@ -150,6 +154,12 @@ void BluettiADV::processDevice(BLEAdvertisedDevice& adv) {
auto m = adv.getManufacturerData();
std::string r(m.c_str(), m.length());
for (size_t i = 0; i < r.length(); i++) Serial.printf("%02x", (uint8_t)r[i]);
uint16_t cid = r.length() >= 2 ? ((uint8_t)r[0] | ((uint16_t)(uint8_t)r[1] << 8)) : 0;
if (cid == BLUETTI_COMPANY_ID)
Serial.print(" <- BLUETTI TELEMETRY (0x0F06) — decoding");
else if (cid == BLUETTI_NAMEPLATE_ID)
Serial.print(" <- Bluetti nameplate only, NO telemetry "
"(enable Bluetooth broadcast in the app, or use the cloud API)");
} else {
Serial.print("(none)");
}
@@ -170,6 +180,19 @@ void BluettiADV::processDevice(BLEAdvertisedDevice& adv) {
char normMac[BLUETTI_ADV_MAC_LEN];
normalizeMAC(adv.getAddress().toString().c_str(), normMac);
DeviceEntry* e = findDevice(normMac);
if (!e) {
// No exact MAC match — adopt a wildcard entry (empty MAC) and latch it to
// this broadcaster so subsequent packets match by MAC normally.
for (size_t i = 0; i < deviceCount; i++) {
if (devices[i].active && devices[i].device.mac[0] == '\0') {
e = &devices[i];
memcpy(e->device.mac, normMac, BLUETTI_ADV_MAC_LEN);
if (debugEnabled) Serial.printf("[BluettiADV] latched %s onto wildcard device '%s'\n",
normMac, e->device.name);
break;
}
}
}
if (!e) {
// A Bluetti device that broadcasts but isn't registered. In debug mode,
// dump enough to confirm the broadcast exists and to set up addDevice():
+4 -1
View File
@@ -27,7 +27,10 @@
#include "mbedtls/aes.h"
// --- Constants ---
static constexpr uint16_t BLUETTI_COMPANY_ID = 0x0F06; // Poweroak / Bluetti
static constexpr uint16_t BLUETTI_COMPANY_ID = 0x0F06; // Poweroak: encrypted telemetry
// Newer Elite/V2 units advertise a static "BLUETT" nameplate (company id 0x4C42)
// instead of the 0x0F06 telemetry broadcast — i.e. no monitoring data over BLE ADV.
static constexpr uint16_t BLUETTI_NAMEPLATE_ID = 0x4C42;
static constexpr int BLUETTI_ADV_MAX_DEVICES = 4;
static constexpr int BLUETTI_ADV_MAC_LEN = 13; // 12 hex chars + null
static constexpr int BLUETTI_ADV_NAME_LEN = 32;