From 2d29ee4524c99f3cc8c672a8b90cdda0d2ae0f1c Mon Sep 17 00:00:00 2001
From: Peter Lambrechtsen
Date: Thu, 7 Aug 2025 12:59:33 +1200
Subject: [PATCH] [BLE] Add support for decrypting PVVX, BTHome v2 and Victron
BLE frames (#2219)
* Changing WebUI to include display device name, and change it to select drop down rather than checkbox
* Fix mqttDiscovery to require WebUI and ESP32 for displayDeviceName
* Fix mqttDiscovery to require WebUI and ESP32 and ESP8266 for displayDeviceName and ForceDeviceName
* Changing WebUI to include display device name, and change it to select drop down rather than checkbox
* Fixes for WebUI and BT for supporting custom setting Display name
* Fixes for WebUI and BT for supporting custom setting Display name
* Move DISPLAY_DEVICE_NAME to User_config.h
* Update docs to include change for Display temperature
* Update docs to include change for Display temperature
* Fix minor cosmetic bug where devices were not linking in HA to the gateway using via_device as it should be the gateway mac address not name
* Add support for decrypting BTHome v2 frames
* Add support for decrypting BTHome v2 frames
* Add support for decrypting BTHome v2 frames
* BTHome fix issue with theengs-plug
* BTHome fix issue with theengs-plug
* Adding support for all BLE encrypted methods, support in UI and gatewayBT for specific MACAddress AES Keys
* Fix lint
* Fix build issue with theengs-bridge-v11 and esp32dev-all-test and revert the documentation to Units of measurement displayed
* Revert docs
* Revert displayDeviceName and Units of measurement
* Revert displayDeviceName and Units of measurement
* Revert displayDeviceName and Units of measurement
* Revert minor typo
* Revert minor typo
* Revert minor typo
* Bug in Victron as nonce should be 16 bytes
* Shortened the client side javascript for BLE key validation that is commented out due to image constrains on theengs-bridge-v11
---
docs/use/webui.md | 4 +
main/TheengsCommon.h | 5 +
main/User_config.h | 12 ++
main/config_WebContent.h | 15 ++-
main/gatewayBT.cpp | 232 +++++++++++++++++++++++++++++++++++++++
main/main.cpp | 39 +++++++
main/webUI.cpp | 93 ++++++++++++++++
7 files changed, 399 insertions(+), 1 deletion(-)
diff --git a/docs/use/webui.md b/docs/use/webui.md
index 24198c0..b3004a9 100644
--- a/docs/use/webui.md
+++ b/docs/use/webui.md
@@ -30,6 +30,10 @@ Ability to change the mqtt settings, if the change is unsuccessful it will rever
Ability to change the display of sensor to Metric or Imperial, and disable the WebUI Authentication
+## Bluetooth Low Energy - BLE
+
+Ability to add the default AES BLE decryption key, and multiple per-device `macaddress:aeskey` allowing for devices that cannot have their AES key changed.
+
## Logging
Ability to temporarily change the logging level.
diff --git a/main/TheengsCommon.h b/main/TheengsCommon.h
index 17a0fe8..f52cea6 100644
--- a/main/TheengsCommon.h
+++ b/main/TheengsCommon.h
@@ -63,6 +63,11 @@ extern char mqtt_topic[];
extern char gateway_name[];
extern unsigned long lastDiscovery; // Time of the last discovery to trigger automaticaly to off after DiscoveryAutoOffTimer
+#if BLEDecryptor
+extern char ble_aes[];
+extern StaticJsonDocument ble_aes_keys;
+#endif
+
extern bool enqueueJsonObject(const StaticJsonDocument& jsonDoc, int timeout);
extern bool enqueueJsonObject(const StaticJsonDocument& jsonDoc);
extern void buildTopicFromId(JsonObject& Jsondata, const char* origin);
diff --git a/main/User_config.h b/main/User_config.h
index ea5fcbf..e11e3a2 100644
--- a/main/User_config.h
+++ b/main/User_config.h
@@ -652,6 +652,18 @@ bool isAduplicateSignal(uint64_t);
void storeSignalValue(uint64_t);
#endif
+#ifdef ZgatewayBT
+# ifndef BLEDecryptor
+# define BLEDecryptor true //true if decrypt encrypted PVVX or BTHome v2 service data
+# endif
+# ifndef JSON_BLE_AES_CUSTOM_KEYS
+# define JSON_BLE_AES_CUSTOM_KEYS 256 // 42 byte BLE Custom Key * 6 rounded up to 256.
+# endif
+# ifndef BLE_AES
+# define BLE_AES "00112233445566778899001122334455"
+# endif
+#endif
+
#define convertTemp_CtoF(c) ((c * 1.8) + 32)
#define convertTemp_FtoC(f) ((f - 32) * 5 / 9)
diff --git a/main/config_WebContent.h b/main/config_WebContent.h
index 9215d0d..eccf82f 100644
--- a/main/config_WebContent.h
+++ b/main/config_WebContent.h
@@ -62,7 +62,11 @@
#else
# define configure_6
#endif
-#define configure_7
+#ifdef BLEDecryptor
+# define configure_7 "
"
+#else
+# define configure_7
+#endif
#define configure_8
/*------------------- ----------------------*/
@@ -219,6 +223,15 @@ const char config_lora_body[] = body_header
""
"" body_footer_config_menu;
+#ifdef BLEDecryptor
+const char config_ble_body[] = body_header "" body_footer_config_menu;
+
+// Client side javascript validation of the Default AES Key is hex, and the custom keys are in the correct format. This pushes the theengs-bridge-v11 way of the file size, so reudcing it now and leaving it commented out
+//const char ble_script[] = "function bkv(){let e=document.getElementById('bk'),t=document.getElementById('bke'),l=e.value.trim();0===l.length||/^[A-Fa-f0-9]{32}$/.test(l)?(t.textContent='',e.style.color=''):(t.textContent='Invalid key',e.style.color='red')}function kpv(){let e=document.getElementById('kp'),t=document.getElementById('kpe'),l=e.value.split(/ /),n=/^[A-Fa-f0-9]{12}:[A-Fa-f0-9]{32}$/,o=l.map((e,t)=>({line:e,index:t})).filter(e=>!n.test(e.line));if(0===e.value.trim().length||0===o.length)t.textContent='',e.style.color='';else{let i=o.map(e=>e.index+1).join(', ');t.textContent=`Invalid format on line(s): ${i}`,e.style.color='red'}}";
+
+const char ble_script[] = "";
+#endif
+
const char footer[] = "