3 Commits

Author SHA1 Message Date
scottp 97e57b0306 Fix chips supported 2026-06-07 19:27:12 +10:00
scottp 05ee88cd31 Working across ESP32 S3, ESP32 C3 and nRF52 2026-06-07 19:23:13 +10:00
scottp ef50829c81 Cleanup READMED and release notes 2026-06-05 00:00:25 +10:00
8 changed files with 70 additions and 120 deletions
+28
View File
@@ -320,3 +320,31 @@ cd3b462 ignore local
- src/VictronBLE.h - src/VictronBLE.h
- src/crypto/vble_aes.c - src/crypto/vble_aes.c
### Session: 2026-06-04 23:58
**Commits:**
```
53fa6fa ignore pka file
de6607d Branch version ready for testing with nRF52
```
**Modified files:**
- .gitignore
- README.md
- UPGRADE_V0.4.md
- VERSIONS
- library.json
- library.properties
### Session: 2026-06-05 00:00
**Commits:**
```
53fa6fa ignore pka file
de6607d Branch version ready for testing with nRF52
```
**Modified files:**
- .claude/CLAUDE.md
- .gitignore
- README.md
- UPGRADE_V0.4.md
+1 -3
View File
@@ -2,9 +2,7 @@
A portable Arduino library for reading Victron Energy device data via Bluetooth Low Energy (BLE) advertisements — runs on both **ESP32** and **nRF52840**. A portable Arduino library for reading Victron Energy device data via Bluetooth Low Energy (BLE) advertisements — runs on both **ESP32** and **nRF52840**.
**⚠️ API CHANGE in v0.4 — not backwards compatible with v0.3.x** v0.6 adds **multi-platform support** (ESP32 + nRF52840) via a hardware-abstracted BLE backend and dependency-free bundled crypto. (v0.5 brought the decoding accuracy fixes and AC charger support; v0.4 reworked the internals — function-pointer callback API, reduced memory usage, non-blocking scanning.) See [VERSIONS](VERSIONS) for full details. A stable **v1.0** release with a consistent, long-term API is coming soon.
v0.4 is a major rework of the library internals: new callback API, reduced memory usage, non-blocking scanning. See [VERSIONS](VERSIONS) for full details. A stable **v1.0** release with a consistent, long-term API is coming soon.
--- ---
-106
View File
@@ -1,106 +0,0 @@
# Upgrading to VictronBLE v0.4
v0.4 is a breaking API change that simplifies the library significantly.
## Summary of Changes
- **Callback**: Virtual class → function pointer
- **Data access**: Inheritance → tagged union (`VictronDevice` with `solar`, `battery`, `inverter`, `dcdc` members)
- **Strings**: Arduino `String` → fixed `char[]` arrays
- **Memory**: `std::map` + heap allocation → fixed array, zero dynamic allocation
- **Removed**: `getLastError()`, `removeDevice()`, `getDevicesByType()`, per-type getter methods, `VictronDeviceConfig` struct, `VictronDeviceCallback` class
- **Removed field**: `panelVoltage` (was unreliably derived from `panelPower / batteryCurrent`)
## Migration Guide
### 1. Callback: class → function pointer
**Before (v0.3):**
```cpp
class MyCallback : public VictronDeviceCallback {
void onSolarChargerData(const SolarChargerData& data) override {
Serial.println(data.deviceName + ": " + String(data.panelPower) + "W");
}
void onBatteryMonitorData(const BatteryMonitorData& data) override {
Serial.println("SOC: " + String(data.soc) + "%");
}
};
MyCallback callback;
victron.setCallback(&callback);
```
**After (v0.4):**
```cpp
void onVictronData(const VictronDevice* dev) {
switch (dev->deviceType) {
case DEVICE_TYPE_SOLAR_CHARGER:
Serial.printf("%s: %.0fW\n", dev->name, dev->solar.panelPower);
break;
case DEVICE_TYPE_BATTERY_MONITOR:
Serial.printf("SOC: %.1f%%\n", dev->battery.soc);
break;
}
}
victron.setCallback(onVictronData);
```
### 2. Data field access
Fields moved from flat `SolarChargerData` etc. into the `VictronDevice` tagged union:
| Old (v0.3) | New (v0.4) |
|---|---|
| `data.deviceName` | `dev->name` (char[32]) |
| `data.macAddress` | `dev->mac` (char[13]) |
| `data.rssi` | `dev->rssi` |
| `data.lastUpdate` | `dev->lastUpdate` |
| `data.batteryVoltage` | `dev->solar.batteryVoltage` |
| `data.batteryCurrent` | `dev->solar.batteryCurrent` |
| `data.panelPower` | `dev->solar.panelPower` |
| `data.yieldToday` | `dev->solar.yieldToday` |
| `data.loadCurrent` | `dev->solar.loadCurrent` |
| `data.chargeState` | `dev->solar.chargeState` (uint8_t, was enum) |
| `data.panelVoltage` | **Removed** - see below |
### 3. panelVoltage removed
`panelVoltage` was a derived value (`panelPower / batteryCurrent`) that was unreliable (division by zero when no current, inaccurate due to MPPT conversion). It has been removed.
If you need an estimate:
```cpp
float panelVoltage = (dev->solar.batteryCurrent > 0.1f)
? dev->solar.panelPower / dev->solar.batteryCurrent
: 0.0f;
```
### 4. getLastError() removed
Debug output now goes directly to Serial when `setDebug(true)` is enabled. Remove any `getLastError()` calls.
**Before:**
```cpp
if (!victron.begin(2)) {
Serial.println(victron.getLastError());
}
```
**After:**
```cpp
if (!victron.begin(2)) {
Serial.println("Failed to initialize VictronBLE!");
}
```
### 5. String types
Device name and MAC are now `char[]` instead of Arduino `String`. Use `Serial.printf()` or `String(dev->name)` if you need a String object.
### 6. addDevice() parameters
Parameters changed from `String` to `const char*`. Existing string literals work unchanged. `VictronDeviceConfig` struct is no longer needed.
```cpp
// Both v0.3 and v0.4 - string literals work the same
victron.addDevice("MySolar", "f69dfcce55eb",
"bf25c098c156afd6a180157b8a3ab1fb", DEVICE_TYPE_SOLAR_CHARGER);
```
+1 -1
View File
@@ -160,7 +160,7 @@ void setup() {
while (1) delay(1000); while (1) delay(1000);
} }
victron.setDebug(false); victron.setDebug(true);
victron.setCallback(onVictronData); victron.setCallback(onVictronData);
// Replace with your own devices (MAC + 32-char hex key from VictronConnect) // Replace with your own devices (MAC + 32-char hex key from VictronConnect)
+2 -2
View File
@@ -1,8 +1,8 @@
{ {
"name": "victronble", "name": "victronble",
"version": "0.6.0", "version": "0.6.0",
"description": "Portable Arduino library for reading Victron Energy device data via Bluetooth Low Energy (BLE) advertisements. Runs on ESP32 and nRF52840. Supports SmartSolar MPPT, SmartShunt, BMV, MultiPlus, Orion, Blue Smart AC chargers and other Victron devices. No external crypto dependency.", "description": "Portable Arduino library for reading Victron Energy device data via Bluetooth Low Energy (BLE) advertisements. Runs on ESP32, ESP32-S3, ESP32-C3 and nRF52 (nRF52840, nRF52832). Supports SmartSolar MPPT, SmartShunt, BMV, MultiPlus, Orion, Blue Smart AC chargers and other Victron devices. No external crypto dependency.",
"keywords": "victron, ble, bluetooth, solar, mppt, battery, smartshunt, smartsolar, bmv, inverter, multiplus, esp32, nrf52, nrf52840, xiao, iot, energy, monitoring", "keywords": "victron, ble, bluetooth, solar, mppt, battery, smartshunt, smartsolar, bmv, inverter, multiplus, esp32, esp32-s3, esp32-c3, nrf52, nrf52840, nrf52832, xiao, iot, energy, monitoring",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://gitea.sh3d.com.au/Sh3d/VictronBLE.git" "url": "https://gitea.sh3d.com.au/Sh3d/VictronBLE.git"
+2 -2
View File
@@ -2,8 +2,8 @@ name=VictronBLE
version=0.6.0 version=0.6.0
author=Scott Penrose author=Scott Penrose
maintainer=Scott Penrose <scottp@dd.com.au> maintainer=Scott Penrose <scottp@dd.com.au>
sentence=Portable library for reading Victron Energy device data via BLE on ESP32 and nRF52840 sentence=Portable library for reading Victron Energy device data via BLE on ESP32/S3/C3 and nRF52 (nRF52840/nRF52832)
paragraph=Read data from Victron SmartSolar, SmartShunt, BMV, inverters, Blue Smart AC chargers and other devices using Bluetooth Low Energy advertisements. Runs on ESP32 and nRF52840 (Bluefruit) with no external crypto dependency. Supports multiple devices simultaneously with no pairing required. paragraph=Read data from Victron SmartSolar, SmartShunt, BMV, inverters, Blue Smart AC chargers and other devices using Bluetooth Low Energy advertisements. Runs on ESP32, ESP32-S3, ESP32-C3 and nRF52 (nRF52840, nRF52832 — Bluefruit or Seeed cores) with no external crypto dependency. Supports multiple devices simultaneously with no pairing required.
category=Communication category=Communication
url=https://gitea.sh3d.com.au/Sh3d/VictronBLE url=https://gitea.sh3d.com.au/Sh3d/VictronBLE
architectures=esp32,nrf52 architectures=esp32,nrf52
+9
View File
@@ -53,6 +53,15 @@ void VictronBLEAdvertisedDeviceCallbacks::onResult(BLEAdvertisedDevice advertise
} }
void VictronBLE::processDevice(BLEAdvertisedDevice& advertisedDevice) { void VictronBLE::processDevice(BLEAdvertisedDevice& advertisedDevice) {
// Debug: print every BLE device seen (before any filtering)
if (debugEnabled) {
Serial.printf("[VictronBLE] MAC=%-17s RSSI=%-4d Name=%-20s ManData=%s\n",
advertisedDevice.getAddress().toString().c_str(),
advertisedDevice.getRSSI(),
advertisedDevice.haveName() ? advertisedDevice.getName().c_str() : "(none)",
advertisedDevice.haveManufacturerData() ? "yes" : "no");
}
if (!advertisedDevice.haveManufacturerData()) return; if (!advertisedDevice.haveManufacturerData()) return;
// getManufacturerData() returns std::string on older ESP32 BLE libraries and // getManufacturerData() returns std::string on older ESP32 BLE libraries and
+27 -6
View File
@@ -43,18 +43,39 @@ void VictronBLE::loop() {
void VictronBLE::scanCallback(ble_gap_evt_adv_report_t* report) { void VictronBLE::scanCallback(ble_gap_evt_adv_report_t* report) {
if (s_instance) { if (s_instance) {
// Format MAC (little-endian to big-endian hex)
const uint8_t* a = report->peer_addr.addr;
char mac[18];
snprintf(mac, sizeof(mac), "%02x:%02x:%02x:%02x:%02x:%02x",
a[5], a[4], a[3], a[2], a[1], a[0]);
// Debug: print every BLE device seen (before any filtering)
if (s_instance->debugEnabled) {
// Manufacturer specific data (AD type 0xFF) — includes the 0x02E1 vendor ID
uint8_t mfgBuf[31];
uint8_t mfgLen = Bluefruit.Scanner.parseReportByType(
report, BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA, mfgBuf, sizeof(mfgBuf));
// Try to get device name
char nameBuf[32] = "(none)";
uint8_t nameLen = Bluefruit.Scanner.parseReportByType(
report, BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME, (uint8_t*)nameBuf, sizeof(nameBuf) - 1);
if (nameLen == 0) {
nameLen = Bluefruit.Scanner.parseReportByType(
report, BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME, (uint8_t*)nameBuf, sizeof(nameBuf) - 1);
}
if (nameLen > 0) nameBuf[nameLen] = '\0';
Serial.printf("[VictronBLE] MAC=%-17s RSSI=%-4d Name=%-20s ManData=%s\n",
mac, report->rssi, nameBuf, mfgLen >= 2 ? "yes" : "no");
}
// Manufacturer specific data (AD type 0xFF) — includes the 0x02E1 vendor ID // Manufacturer specific data (AD type 0xFF) — includes the 0x02E1 vendor ID
uint8_t buf[31]; uint8_t buf[31];
uint8_t len = Bluefruit.Scanner.parseReportByType( uint8_t len = Bluefruit.Scanner.parseReportByType(
report, BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA, buf, sizeof(buf)); report, BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA, buf, sizeof(buf));
if (len >= 2) { if (len >= 2) {
// peer_addr.addr is little-endian (LSB first); format big-endian to
// match the AA:BB:CC:DD:EE:FF MAC users copy from VictronConnect.
const uint8_t* a = report->peer_addr.addr;
char mac[18];
snprintf(mac, sizeof(mac), "%02x:%02x:%02x:%02x:%02x:%02x",
a[5], a[4], a[3], a[2], a[1], a[0]);
s_instance->onAdvertisement(buf, len, mac, report->rssi); s_instance->onAdvertisement(buf, len, mac, report->rssi);
} }
} }