6 Commits

Author SHA1 Message Date
scottp cc8c4d36d5 check version before release 2026-06-08 17:14:39 +10:00
scottp 712259eec5 Remove claude entries from old session 2026-06-08 16:17:26 +10:00
scottp 57ae49fd09 Add a rak4631 board definition testing 2026-06-07 23:22:36 +10:00
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
12 changed files with 146 additions and 476 deletions
-322
View File
@@ -1,322 +0,0 @@
# VictronBLE Project Context
## Project Overview
Portable Arduino library for reading Victron Energy devices via Bluetooth Low Energy (BLE). Runs on ESP32 (Bluedroid) and nRF52840 (Bluefruit); BLE scanning is the only platform-specific code (src/esp32, src/nrf52), while decoding and AES-128-CTR crypto are common.
## Key Files
- `src/` - Main library source code
- `examples/` - Example sketches
- `experiment/` - Experimental code
- `library.json` / `library.properties` - PlatformIO/Arduino library config
## Build & Test
- This is an Arduino/PlatformIO library
- Test with PlatformIO: `pio run`
## Session Notes
<!-- Add learnings from each session below -->
### Session: 2026-01-29 18:41
**Modified files:**
- TODO
### Session: 2026-02-11 13:51
**Modified files:**
- .claude/CLAUDE.md
- .claude/scripts/update-claude-md.sh
- TODO
- examples/MultiDevice/src/main.cpp
### Session: 2026-02-11 15:57
**Modified files:**
- .claude/CLAUDE.md
- .claude/scripts/update-claude-md.sh
- TODO
- examples/MultiDevice/src/main.cpp
### Session: 2026-02-12 18:02
**Modified files:**
- .claude/CLAUDE.md
- .claude/scripts/update-claude-md.sh
- TODO
- examples/MultiDevice/src/main.cpp
### Session: 2026-02-12 18:02
**Modified files:**
- .claude/CLAUDE.md
- .claude/scripts/update-claude-md.sh
- TODO
- examples/MultiDevice/src/main.cpp
- library.json
### Session: 2026-02-12 18:06
**Commits:**
```
5a210fb Experimenting with a claude file and created new logging example
```
**Modified files:**
- .claude/CLAUDE.md
- TODO
- examples/Logger/platformio.ini
- examples/Logger/src/main.cpp
- examples/MultiDevice/src/main.cpp
- library.json
### Session: 2026-02-12 18:08
**Commits:**
```
5a210fb Experimenting with a claude file and created new logging example
```
**Modified files:**
- .claude/CLAUDE.md
- README.md
- TODO
- VERSIONS
- examples/Logger/platformio.ini
- examples/Logger/src/main.cpp
- examples/MultiDevice/src/main.cpp
- library.json
- library.properties
### Session: 2026-02-12 18:10
**Commits:**
```
5a210fb Experimenting with a claude file and created new logging example
```
**Modified files:**
- .claude/CLAUDE.md
- README.md
- TODO
- VERSIONS
- examples/Logger/platformio.ini
- examples/Logger/src/main.cpp
- examples/MultiDevice/src/main.cpp
- library.json
- library.properties
### Session: 2026-02-12 18:23
**Commits:**
```
a843eb9 Keep v0.3.1
5a210fb Experimenting with a claude file and created new logging example
```
**Modified files:**
- .claude/CLAUDE.md
- README.md
- VERSIONS
- library.json
- library.properties
- src/VictronBLE.cpp
- src/VictronBLE.h
### Session: 2026-02-12 18:35
**Commits:**
```
a64fef8 New version with smaller memory footprint etc
a843eb9 Keep v0.3.1
5a210fb Experimenting with a claude file and created new logging example
```
**Modified files:**
- .claude/CLAUDE.md
- src/VictronBLE.cpp
- src/VictronBLE.h
### Session: 2026-02-13 11:02
**Modified files:**
- .claude/CLAUDE.md
- src/VictronBLE.cpp
- src/VictronBLE.h
### Session: 2026-02-15 18:59
**Modified files:**
- .claude/CLAUDE.md
- library.json
- src/VictronBLE.cpp
- src/VictronBLE.h
### Session: 2026-02-15 19:06
**Modified files:**
- .claude/CLAUDE.md
- library.json
- src/VictronBLE.cpp
- src/VictronBLE.h
### Session: 2026-02-15 19:10
**Modified files:**
- .claude/CLAUDE.md
- library.json
- src/VictronBLE.cpp
- src/VictronBLE.h
### Session: 2026-02-15 19:18
**Commits:**
```
8a2402c Repeater and Test code for ESP Now
```
**Modified files:**
- .claude/CLAUDE.md
- examples/FakeRepeater/platformio.ini
- examples/FakeRepeater/src/main.cpp
- examples/Receiver/platformio.ini
- examples/Receiver/src/main.cpp
- examples/Repeater/platformio.ini
- examples/Repeater/src/main.cpp
- library.json
### Session: 2026-02-15 19:20
**Commits:**
```
24712c2 Work on receiver and sender
8a2402c Repeater and Test code for ESP Now
```
**Modified files:**
- .claude/CLAUDE.md
- examples/Receiver/platformio.ini
- examples/Receiver/src/main.cpp
- examples/Repeater/src/main.cpp
### Session: 2026-02-28 12:26
**Modified files:**
- .claude/CLAUDE.md
- examples/Receiver/src/main.cpp
- examples/Repeater/src/main.cpp
### Session: 2026-02-28 14:32
**Commits:**
```
4944757 Fix to be non blocking without tasks
31765c7 Update notes
84d153c Single callback version - vastly simplified.
```
**Modified files:**
- examples/Logger/src/main.cpp
- examples/MultiDevice/src/main.cpp
- examples/Repeater/src/main.cpp
- library.json
- library.properties
- src/VictronBLE.cpp
- src/VictronBLE.h
### Session: 2026-02-28 14:33
**Commits:**
```
4944757 Fix to be non blocking without tasks
31765c7 Update notes
84d153c Single callback version - vastly simplified.
```
**Modified files:**
- .claude/CLAUDE.md
- VERSIONS
- examples/Logger/src/main.cpp
- examples/MultiDevice/src/main.cpp
- examples/Repeater/src/main.cpp
- library.json
- library.properties
- src/VictronBLE.cpp
- src/VictronBLE.h
### Session: 2026-02-28 14:36
**Commits:**
```
4944757 Fix to be non blocking without tasks
31765c7 Update notes
```
**Modified files:**
- .claude/CLAUDE.md
- VERSIONS
- examples/Logger/src/main.cpp
- examples/MultiDevice/src/main.cpp
- examples/Repeater/src/main.cpp
- library.json
- library.properties
- src/VictronBLE.cpp
- src/VictronBLE.h
### Session: 2026-02-28 14:40
**Commits:**
```
39a89c8 Versions v0.4 ready for release
4944757 Fix to be non blocking without tasks
31765c7 Update notes
```
**Modified files:**
- .claude/CLAUDE.md
- README.md
- VERSIONS
- library.json
- library.properties
### Session: 2026-02-28 14:48
**Commits:**
```
261cc0d Improve readme ready for v0.4 release
39a89c8 Versions v0.4 ready for release
4944757 Fix to be non blocking without tasks
31765c7 Update notes
```
**Modified files:**
- .claude/CLAUDE.md
- README.md
- REVIEW.md
### Session: 2026-06-04 21:23
**Commits:**
```
cd3b462 ignore local
7706f88 Bug fixes for reported issues
```
**Modified files:**
- .gitignore
- README.md
### Session: 2026-06-04 22:59
**Commits:**
```
105d66b Update info
```
**Modified files:**
- .claude/CLAUDE.md
- README.md
### Session: 2026-06-04 23:46
**Commits:**
```
105d66b Update info
```
**Modified files:**
- .claude/CLAUDE.md
- README.md
- VERSIONS
- examples/MultiDevice/platformio.ini
- examples/MultiDevice/src/main.cpp
- library.json
- library.properties
- src/VictronBLE.cpp
- src/VictronBLE.h
- src/crypto/vble_aes.c
-31
View File
@@ -1,31 +0,0 @@
#!/bin/bash
# Auto-update CLAUDE.md at end of session
CLAUDE_MD="$(git rev-parse --show-toplevel)/.claude/CLAUDE.md"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M')
# Get recent git activity from this session (last hour)
RECENT_COMMITS=$(git log --oneline --since="1 hour ago" 2>/dev/null | head -5)
MODIFIED_FILES=$(git diff --name-only HEAD~1 2>/dev/null | head -10)
# Append session summary
{
echo ""
echo "### Session: $TIMESTAMP"
if [ -n "$RECENT_COMMITS" ]; then
echo "**Commits:**"
echo "\`\`\`"
echo "$RECENT_COMMITS"
echo "\`\`\`"
fi
if [ -n "$MODIFIED_FILES" ]; then
echo "**Modified files:**"
echo "$MODIFIED_FILES" | sed 's/^/- /'
fi
echo ""
} >> "$CLAUDE_MD"
echo "Updated CLAUDE.md with session summary"
+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**.
**⚠️ API CHANGE in v0.4 — not backwards compatible with v0.3.x**
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.
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.
---
-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);
```
+34
View File
@@ -0,0 +1,34 @@
#!/usr/bin/env bash
#
# check_version.sh -- verify the library version is consistent and released.
#
# Read-only: confirms the version matches in both manifests and that a matching
# git tag (vX.Y.Z) exists. Run it before tagging a release. Non-zero exit if the
# versions disagree or the tag is missing.
#
# SPDX-License-Identifier: MIT
set -u
cd "$(dirname "$0")" || exit 2
json=$(sed -nE 's/.*"version"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/p' library.json | head -1)
prop=$(sed -nE 's/^version=([^[:space:]]+).*/\1/p' library.properties | tr -d '\r' | head -1)
echo "library.json : ${json:-<none>}"
echo "library.properties : ${prop:-<none>}"
fail=0
if [ -n "$json" ] && [ "$json" = "$prop" ]; then
echo "ok versions match ($json)"
else
echo "FAIL versions differ (json=$json properties=$prop)"; fail=1
fi
if git rev-parse -q --verify "refs/tags/v$json" >/dev/null 2>&1; then
echo "ok git tag v$json exists"
else
echo "FAIL no git tag v$json -- create one to release: git tag v$json"; fail=1
fi
exit "$fail"
+52
View File
@@ -0,0 +1,52 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v6.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_WISCORE_RAK4631_BOARD -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x8029"],
["0x239A", "0x0029"],
["0x239A", "0x002A"],
["0x239A", "0x802A"]
],
"usb_product": "WisCore RAK4631 Board",
"mcu": "nrf52840",
"variant": "wiscore_rak4631",
"bsp": {
"name": "adafruit"
},
"softdevice": {
"sd_flags": "-DS140",
"sd_name": "s140",
"sd_version": "6.1.1",
"sd_fwid": "0x00B6"
},
"bootloader": {
"settings_addr": "0xFF000"
}
},
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52.cfg"
},
"frameworks": ["arduino"],
"name": "WisCore RAK4631 Board",
"upload": {
"maximum_ram_size": 235520,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",
"protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"],
"use_1200bps_touch": true,
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "https://www.rakwireless.com",
"vendor": "RAKwireless"
}
+15
View File
@@ -1,3 +1,7 @@
[platformio]
src_dir = src
boards_dir = boards
[env]
lib_extra_dirs = ../..
@@ -20,6 +24,17 @@ framework = arduino
monitor_speed = 115200
build_flags = -DCFG_DEBUG=0
; RAKwireless RAK4630 (WisBlock) — nRF52840 with Bluefruit backend.
; Board definition lives in boards/rak4631.json (always available).
[env:rak4630]
platform = nordicnrf52
platform_packages = framework-arduinoadafruitnrf52 @ 1.10700.0
framework = arduino
board = rak4631
monitor_speed = 115200
upload_protocol = nrfutil
build_flags = -DCFG_DEBUG=0
[env:esp32dev]
platform = espressif32
board = esp32dev
+1 -1
View File
@@ -160,7 +160,7 @@ void setup() {
while (1) delay(1000);
}
victron.setDebug(false);
victron.setDebug(true);
victron.setCallback(onVictronData);
// Replace with your own devices (MAC + 32-char hex key from VictronConnect)
+3 -3
View File
@@ -1,8 +1,8 @@
{
"name": "victronble",
"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.",
"keywords": "victron, ble, bluetooth, solar, mppt, battery, smartshunt, smartsolar, bmv, inverter, multiplus, esp32, nrf52, nrf52840, xiao, iot, energy, monitoring",
"version": "0.6.1",
"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, esp32-s3, esp32-c3, nrf52, nrf52840, nrf52832, xiao, iot, energy, monitoring",
"repository": {
"type": "git",
"url": "https://gitea.sh3d.com.au/Sh3d/VictronBLE.git"
+4 -4
View File
@@ -1,11 +1,11 @@
name=VictronBLE
version=0.6.0
version=0.6.1
author=Scott Penrose
maintainer=Scott Penrose <scottp@dd.com.au>
sentence=Portable library for reading Victron Energy device data via BLE on ESP32 and nRF52840
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.
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, 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
url=https://gitea.sh3d.com.au/Sh3d/VictronBLE
url=https://github.com/SH3D/VictronBLE
architectures=esp32,nrf52
depends=
includes=VictronBLE.h
+9
View File
@@ -53,6 +53,15 @@ void VictronBLEAdvertisedDeviceCallbacks::onResult(BLEAdvertisedDevice advertise
}
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;
// 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) {
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
uint8_t buf[31];
uint8_t len = Bluefruit.Scanner.parseReportByType(
report, BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA, buf, sizeof(buf));
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);
}
}