# Version History ## 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` 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