209 lines
10 KiB
Plaintext
209 lines
10 KiB
Plaintext
# Version History
|
||
|
||
## 0.7.0 (2026-08-21)
|
||
|
||
Pure C core + Zephyr support. One repo now serves three ecosystems: Arduino
|
||
(unchanged public API), PlatformIO, and Zephyr west workspaces.
|
||
|
||
### Pure C99 core (`include/victronble.h`, `src/victronble_core.c`)
|
||
- All decoding and decryption extracted into a dependency-free, reentrant,
|
||
allocation-free C core: `victronble_decode(mfg, len, key, out)` plus the
|
||
cheap pre-filters `victronble_is_product_adv()` / `victronble_key_matches()`
|
||
and helpers (`victronble_parse_key`, `strerror`, `device_type_str`,
|
||
`state_str`). Explicit little-endian accessors — no packed-struct punning.
|
||
- Absent wire fields are now NAN in the core (test with `isnan()`); the
|
||
Arduino wrapper converts back to the legacy `0` convention, so existing
|
||
sketches see identical values.
|
||
- AES is behind a CTR-shaped hook (`victronble_aes_ctr_fn`): weak-symbol
|
||
default = the bundled tiny-AES (linker-droppable), runtime override via
|
||
`victronble_set_aes_ctr()` for PSA/mbedTLS/hardware backends.
|
||
- `VictronBLE` (Arduino) is now a thin wrapper over the core — registry,
|
||
nonce dedup and rate limiting only. Public C++ API unchanged.
|
||
|
||
### Host test vectors (`tests/vectors/`)
|
||
- Plain-gcc harness (`run.sh`), no framework. Positive vectors for all five
|
||
payload shapes are generated by `gen_vectors.py` and encrypted with the
|
||
openssl CLI — independent of the bundled AES, so the CTR/nonce semantics
|
||
are cross-checked — plus negative cases (truncated, wrong vendor, wrong
|
||
key, unsupported record type).
|
||
|
||
### Zephyr module (`zephyr/module.yml`, `Kconfig`, `CMakeLists.txt`)
|
||
- `CONFIG_VICTRONBLE` (needs `CONFIG_BT_OBSERVER`): passive-scan observer
|
||
(`include/victronble_zephyr.h`, `src/victronble_zephyr.c`). The scan
|
||
callback only pre-filters and queues; a dedicated thread decrypts, decodes,
|
||
nonce-dedups and fans out to registered listeners
|
||
(`victronble_device_add(addr, key)` / `victronble_cb_register()` /
|
||
`victronble_start()`), with `victronble_get_stats()` counters. Default scan
|
||
is slow/low-duty (1.28 s / 11.25 ms — Victron advertises ~1 Hz). Consume as
|
||
a west project or via `-DZEPHYR_EXTRA_MODULES=<path>`; see
|
||
`docs/ZEPHYR_PORT.md` for the porting plan this implements.
|
||
|
||
- Watch mode (`victronble_watch_set(true)`): logs every Victron product
|
||
advert heard, registered or not — MAC, RSSI, record type, length and
|
||
key-check byte. Reads only the plaintext header, so it needs no keys.
|
||
Discovery and key debugging; `samples/scan` is built around it.
|
||
|
||
### Samples and examples
|
||
- `samples/observer/` — Zephyr reference app: known devices from a table of
|
||
MAC + key, full field decode for every device type, and a 30-second stats
|
||
line for diagnosing a quiet console. Builds for `nrf52840dk/nrf52840` and
|
||
`rak4631/nrf52840`.
|
||
- `samples/scan/` — Zephyr discovery app: watch mode only, no keys or
|
||
addresses needed. Run it first to find what you have.
|
||
- Both carry a `sample.yaml`, so `west twister -T samples` build-tests them.
|
||
- `examples/NativeDecode/` — decode an advertisement on a PC with plain
|
||
`make`. No board, no BLE stack; exercises the pure C core directly, which
|
||
makes it useful for checking a key or a sniffer capture.
|
||
|
||
### Fixed
|
||
- `library.properties` URL now points at the real repo (gitea) instead of a
|
||
nonexistent GitHub mirror.
|
||
- `library.json` no longer claims the `espidf` framework. There is no ESP-IDF
|
||
BLE backend — `src/esp32/` is Arduino/Bluedroid only — so the claim was
|
||
never true. The pure C core works fine under ESP-IDF; scanning is the
|
||
missing piece, and a native backend is future work.
|
||
- `QUICK_START.md` pointed at `examples/MultiDevice/main.cpp`; the file is at
|
||
`examples/MultiDevice/src/main.cpp`.
|
||
|
||
## 0.6.0 (2026-06-04)
|
||
|
||
Multi-platform support. The library now runs on **nRF52840** (Adafruit/Seeed
|
||
Bluefruit core) in addition to ESP32, sharing all decoding and crypto code.
|
||
|
||
### Platform abstraction
|
||
- The BLE scanning layer is now the only platform-specific code, split into
|
||
backends under `src/esp32/` (ESP32 Bluedroid `BLEScan`) and `src/nrf52/`
|
||
(Bluefruit passive scan). Both extract manufacturer data + MAC + RSSI and feed
|
||
a shared `VictronBLE::onAdvertisement()`. The public API is unchanged.
|
||
- The correct backend is auto-selected at compile time; no user configuration
|
||
needed beyond picking the board.
|
||
|
||
### Portable crypto (no external dependency)
|
||
- Replaced the ESP32-only mbedTLS AES with a small bundled AES-128-CTR
|
||
implementation (`src/crypto/`, trimmed/prefixed tiny-AES, public domain,
|
||
NIST SP 800-38A verified). Decryption output is byte-identical to the previous
|
||
mbedTLS path; the library now has no external crypto dependency on any target.
|
||
|
||
### New
|
||
- The `MultiDevice` example now builds for both ESP32 and nRF52840 from a single
|
||
sketch — its `platformio.ini` adds `xiao_nrf52840` (Seeed XIAO nRF52840, board
|
||
`xiaoble_adafruit` via the maxgerhardt nRF52 platform fork) and
|
||
`adafruit_feather_nrf52840` environments alongside the ESP32 ones.
|
||
- `nrf52` added to the supported architectures / PlatformIO platforms.
|
||
|
||
## 0.5.0 (2026-06-04)
|
||
|
||
Decoding accuracy fixes (thanks to community bug reports from Karsten, Cory, Kevin and Dan)
|
||
plus new AC Charger support. Field layouts verified against the keshavdv/victron-ble
|
||
reference implementation and the Victron "Extra Manufacturer Data" specification.
|
||
|
||
### Bug fixes
|
||
- **Battery monitor decoding rewritten.** The `victronBatteryMonitorPayload` struct had
|
||
wrong field widths (8-bit alarm instead of 16, no 2-bit aux-mode field) which cascaded
|
||
and misaligned current, consumed Ah and SOC. `parseBatteryMonitor()` now decodes the
|
||
bit-packed payload directly by bit offset: signed voltage, 16-bit alarm, aux value +
|
||
2-bit aux mode (replacing the unreliable `< 3000` voltage/temperature heuristic),
|
||
22-bit signed current, 20-bit consumed Ah (×-0.1 Ah), 10-bit SOC (×0.1 %).
|
||
- **Solar charger battery current scale fixed.** Was multiplied by 0.01 (10× too small);
|
||
the field is in 0.1 A units. Load current is now read as the correct 9-bit field.
|
||
- **Compile error with newer ESP32 BLE library fixed.** `getManufacturerData()` now returns
|
||
an Arduino `String` on recent cores; `processDevice()` handles both `String` and
|
||
`std::string` while preserving the binary payload's embedded null bytes.
|
||
- **Device type IDs corrected.** The enum was off-by-one from 0x07 onward, mislabelling
|
||
AC chargers (0x08) as Lynx Smart BMS. Now matches the Victron protocol:
|
||
0x07 GX Device, 0x08 AC Charger, 0x09 Smart Battery Protect, 0x0A Lynx Smart BMS,
|
||
0x0B Multi RS, 0x0C VE.Bus, 0x0D DC Energy Meter, 0x0F Orion XS.
|
||
|
||
### New features
|
||
- **AC Charger support** (Blue Smart IP22/IP65/IP67, device type 0x08). New
|
||
`VictronACChargerData` struct (three output voltage/current banks, temperature, AC
|
||
current) and `DEVICE_TYPE_AC_CHARGER` handling.
|
||
|
||
## 0.4.1 (2026-02-28)
|
||
|
||
Major rework of library internals. Breaking API change — not backwards compatible with 0.3.x.
|
||
|
||
### Callback API rewrite
|
||
- Replaced virtual callback class (`VictronDeviceCallback` with 4 override methods) with a
|
||
single function pointer (`VictronCallback`). Users now provide a plain function instead of
|
||
subclassing. The callback receives a `VictronDevice*` and switches on `deviceType` to access
|
||
the appropriate data via a tagged union.
|
||
|
||
### Non-blocking BLE scanning
|
||
- `loop()` is now non-blocking — returns immediately if a scan is already running.
|
||
Previously it blocked for the entire scan duration (default 5 seconds).
|
||
- Scan restarts automatically when it completes.
|
||
|
||
### Callback throttling
|
||
- Nonce-based deduplication: skips decrypt/parse/callback when the device's data hasn't
|
||
changed (detected via the nonce field in the BLE advertisement header).
|
||
- Configurable minimum interval (`setMinInterval()`, default 1000ms) limits callback
|
||
frequency even when data is changing rapidly.
|
||
- Encryption key byte check before AES decryption for early rejection of mismatched keys.
|
||
|
||
### Memory and code reduction
|
||
- Replaced `std::map<String, DeviceInfo*>` with a fixed array (max 8 devices, linear search).
|
||
Eliminates heap allocation for device storage.
|
||
- Replaced Arduino `String` with fixed `char[]` arrays throughout (MAC: 12 chars, name: 32 chars).
|
||
Eliminates heap fragmentation from dynamic string operations.
|
||
- Replaced inheritance hierarchy (`VictronDeviceData` base + 4 derived classes) with a flat
|
||
`VictronDevice` struct using a tagged union. No more `new`/`delete` for device data.
|
||
- Removed `std::map` and `std::vector` includes entirely.
|
||
- Source reduced from ~970 lines to ~510 lines (48% reduction).
|
||
- Flash savings: ~11-14 KB across examples.
|
||
|
||
### Bug fixes
|
||
- Fixed undefined behavior: derived objects were deleted through a base pointer without a
|
||
virtual destructor. Now uses flat structs, no polymorphic delete.
|
||
- Removed incorrect `panelVoltage` calculation (was dividing PV power by battery current,
|
||
which is wrong for MPPT chargers). The BLE protocol does not transmit PV voltage.
|
||
- Removed spurious `nullPad` byte from manufacturer data struct.
|
||
- Device type is now auto-detected from the BLE advertisement record type. The type
|
||
parameter in `addDevice()` is optional.
|
||
|
||
### Removed features (commented out in header for reference)
|
||
- `VictronDeviceConfig` struct — use `addDevice(name, mac, key, type)` directly
|
||
- Per-type getter methods (`getSolarChargerData()`, etc.) — use callback instead
|
||
- `removeDevice()`, `getDevicesByType()`, `getLastError()`
|
||
|
||
### Examples updated
|
||
- All examples updated for new callback API
|
||
- Removed `panelVoltage` from ESPNow packet structs (Repeater, FakeRepeater, Receiver)
|
||
- Removed unnecessary `delay(100)` from loop functions
|
||
- Added ESPNow Repeater and Receiver examples
|
||
|
||
## 0.3.1 (2026-02-11)
|
||
|
||
### Changes
|
||
- Added Logger example: change-detection logging for Solar Charger data
|
||
- Added message type counters to MultiDevice example
|
||
- Tested with MPPT Solar Chargers on ESP32-S3 and ESP32-C3
|
||
|
||
## 0.1.1 (2025-12-18)
|
||
|
||
Initial release - not yet tested on hardware.
|
||
|
||
### Features
|
||
- Support for multiple Victron device types:
|
||
- Solar Chargers (MPPT)
|
||
- Battery Monitors (SmartShunt, BMV)
|
||
- Inverters (MultiPlus, Quattro, Phoenix with VE.Bus BLE)
|
||
- DC-DC Converters (Orion Smart, Orion XS)
|
||
- BLE advertisement decryption using AES-128-CTR
|
||
- Callback interface for real-time data updates
|
||
- Manual data polling API
|
||
- Support for multiple simultaneous devices
|
||
- Debug logging
|
||
- Framework agnostic (Arduino and ESP-IDF)
|
||
|
||
### Known Issues
|
||
- Not yet tested with real hardware
|
||
- No validation against actual Victron devices
|
||
|
||
### TODO
|
||
- Hardware testing with real Victron devices
|
||
- Add more device types (Smart Battery Protect, Lynx Smart BMS, etc.)
|
||
- Add more examples
|
||
- Performance optimization
|
||
- Add unit tests
|