Experimenting with a claude file and created new logging example

This commit is contained in:
2026-02-12 18:04:02 +11:00
parent 30c93af18b
commit 5a210fb88f
6 changed files with 373 additions and 5 deletions

View File

@@ -21,3 +21,36 @@ Arduino/ESP32 library for reading Victron Energy devices via Bluetooth Low Energ
**Modified files:** **Modified files:**
- TODO - 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

4
TODO
View File

@@ -25,3 +25,7 @@ Seems mbedTLS is better choice as auotmatic hardware support even on ESP32 - whe
* Example scan anything * Example scan anything
* With and without Callback * With and without Callback
* Platformio.ini files into example data * Platformio.ini files into example data
# Logging and Debugging
* The debugging is very verbose and hard to read - maybe group the messages together for repeats

View File

@@ -0,0 +1,143 @@
[env]
lib_extra_dirs = ../..
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
; Serial monitor settings
monitor_speed = 115200
monitor_filters = esp32_exception_decoder
; Build flags
build_flags =
-DCORE_DEBUG_LEVEL=3
; Library dependencies
lib_deps =
; VictronBLE library will be automatically included from parent directory
; Optional: Specify partition scheme if needed
; board_build.partitions = default.csv
[env:esp32-s3]
platform = espressif32
board = esp32-s3-devkitc-1
framework = arduino
monitor_speed = 115200
monitor_filters = esp32_exception_decoder
build_flags =
-D ARDUINO_USB_MODE=1
-D ARDUINO_USB_CDC_ON_BOOT=1
# -DCORE_DEBUG_LEVEL=3
[env:esp32-s3-debug]
platform = espressif32
board = esp32-s3-devkitc-1
framework = arduino
#monitor_speed = 115200
#monitor_filters = esp32_exception_decoder
upload_protocol = esp-builtin
; Debug configuration for GDB
debug_tool = esp-builtin
debug_init_break = tbreak setup
debug_speed = 5000
debug_load_mode = always
; Build flags for debugging
build_flags =
-DCORE_DEBUG_LEVEL=5 ; Maximum ESP32 debug level
-O0 ; Disable optimization for debugging
-g3 ; Maximum debug information
build_type = debug
[env:esp32-c3]
platform = espressif32
framework = arduino
board = esp32-c3-devkitm-1
board_build.mcu = esp32c3
board_build.f_cpu = 160000000L
board_build.flash_mode = dio
board_build.partitions = default.csv
monitor_speed = 115200
monitor_filters = time, default, esp32_exception_decoder
upload_speed = 921600
# NOTE: Need these two ARDUIO_USB modes to work with serial
build_flags =
-Os
-I src
-D ARDUINO_ESP32C3_DEV
-D CONFIG_IDF_TARGET_ESP32C3
-D ARDUINO_USB_MODE=1
-D ARDUINO_USB_CDC_ON_BOOT=1
lib_deps =
elapsedMillis
[env:esp32-c3-debug]
platform = espressif32
board = esp32-c3-devkitc-02
framework = arduino
monitor_speed = 115200
; Upload configuration
upload_protocol = esp-builtin
; Debug configuration for GDB
debug_tool = esp-builtin
debug_init_break = tbreak setup
debug_speed = 5000
debug_load_mode = always
; Build flags for debugging
build_flags =
-DCORE_DEBUG_LEVEL=5 ; Maximum ESP32 debug level
-O0 ; Disable optimization for debugging
-g3 ; Maximum debug information
build_type = debug
[env:m5stick]
platform = espressif32
board = m5stick-c
framework = arduino
board_build.mcu = esp32
board_build.f_cpu = 240000000L
board_build.partitions = no_ota.csv
#upload_protocol = espota
#upload_port = Button.local
monitor_speed = 115200
monitor_filters = esp32_exception_decoder
#debug_tool = esp-prog ; esp-bridge, esp-prog ; or ftdi, esp-builtin, jlink, etc.
# debug_speed = 5000 ; optional: JTAG speed in kHz
#build_flags =
# -DCORE_DEBUG_LEVEL=5 ; ESP32 debug level
# -O0 ; no optimization
# -g3 ; max debug info
build_flags =
-Os
lib_deps =
M5StickC
elapsedMillis
[env:tough]
board = m5stack-core2
board_build.mcu = esp32
platform = espressif32
framework = arduino
monitor_speed = 115200
monitor_filters = esp32_exception_decoder
debug_tool = esp-bridge ; esp-bridge, esp-prog ; or ftdi, esp-builtin, jlink, etc.
# debug_speed = 5000 ; optional: JTAG speed in kHz
build_flags =
-DCORE_DEBUG_LEVEL=5 ; ESP32 debug level
-O0 ; no optimization
-g3 ; max debug info
-DARDUINO_M5STACK_TOUGH
-DDISPLAY_WIDTH=320
-DDISPLAY_HEIGHT=240
-DHAS_TOUCH=1
-DBUFFER_LINES=10
lib_deps =
M5Unified
elapsedMillis

View File

@@ -0,0 +1,167 @@
/**
* VictronBLE Logger Example
*
* Demonstrates change-detection logging for Solar Charger data.
* Only logs to serial when a value changes (ignoring RSSI), or once
* per minute if nothing has changed. This keeps serial output quiet
* and is useful for long-running monitoring / data logging.
*
* Setup:
* 1. Get your device encryption keys from the VictronConnect app
* 2. Update the device configurations below with your MAC and key
*/
#include <Arduino.h>
#include "VictronBLE.h"
VictronBLE victron;
// Tracks last-logged values per device for change detection
struct SolarChargerSnapshot {
bool valid = false;
SolarChargerState chargeState;
float batteryVoltage;
float batteryCurrent;
float panelVoltage;
float panelPower;
uint16_t yieldToday;
float loadCurrent;
unsigned long lastLogTime = 0;
uint32_t packetsSinceLastLog = 0;
};
// Store a snapshot per device (index by MAC string)
static const int MAX_DEVICES = 4;
static String deviceMACs[MAX_DEVICES];
static SolarChargerSnapshot snapshots[MAX_DEVICES];
static int deviceCount = 0;
static const unsigned long LOG_INTERVAL_MS = 60000; // 1 minute
static int findOrAddDevice(const String& mac) {
for (int i = 0; i < deviceCount; i++) {
if (deviceMACs[i] == mac) return i;
}
if (deviceCount < MAX_DEVICES) {
deviceMACs[deviceCount] = mac;
return deviceCount++;
}
return -1;
}
static String chargeStateName(SolarChargerState state) {
switch (state) {
case CHARGER_OFF: return "Off";
case CHARGER_LOW_POWER: return "Low Power";
case CHARGER_FAULT: return "Fault";
case CHARGER_BULK: return "Bulk";
case CHARGER_ABSORPTION: return "Absorption";
case CHARGER_FLOAT: return "Float";
case CHARGER_STORAGE: return "Storage";
case CHARGER_EQUALIZE: return "Equalize";
case CHARGER_INVERTING: return "Inverting";
case CHARGER_POWER_SUPPLY: return "Power Supply";
case CHARGER_EXTERNAL_CONTROL: return "External Control";
default: return "Unknown";
}
}
static void logData(const SolarChargerData& data, const char* reason, uint32_t packets) {
Serial.println("[" + data.deviceName + "] " + reason +
" pkts:" + String(packets) +
" | State:" + chargeStateName(data.chargeState) +
" Batt:" + String(data.batteryVoltage, 2) + "V" +
" " + String(data.batteryCurrent, 2) + "A" +
" PV:" + String(data.panelVoltage, 1) + "V" +
" " + String(data.panelPower, 0) + "W" +
" Yield:" + String(data.yieldToday) + "Wh" +
(data.loadCurrent > 0 ? " Load:" + String(data.loadCurrent, 2) + "A" : ""));
}
class LoggerCallback : public VictronDeviceCallback {
public:
void onSolarChargerData(const SolarChargerData& data) override {
int idx = findOrAddDevice(data.macAddress);
if (idx < 0) return;
SolarChargerSnapshot& prev = snapshots[idx];
unsigned long now = millis();
prev.packetsSinceLastLog++;
if (!prev.valid) {
// First reading - always log
logData(data, "INIT", prev.packetsSinceLastLog);
} else {
// Check for changes (everything except RSSI)
bool changed = false;
if (prev.chargeState != data.chargeState) changed = true;
if (prev.batteryVoltage != data.batteryVoltage) changed = true;
if (prev.batteryCurrent != data.batteryCurrent) changed = true;
if (prev.panelVoltage != data.panelVoltage) changed = true;
if (prev.panelPower != data.panelPower) changed = true;
if (prev.yieldToday != data.yieldToday) changed = true;
if (prev.loadCurrent != data.loadCurrent) changed = true;
if (changed) {
logData(data, "CHG", prev.packetsSinceLastLog);
} else if (now - prev.lastLogTime >= LOG_INTERVAL_MS) {
logData(data, "HEARTBEAT", prev.packetsSinceLastLog);
} else {
return; // Nothing to log
}
}
// Update snapshot
prev.packetsSinceLastLog = 0;
prev.valid = true;
prev.chargeState = data.chargeState;
prev.batteryVoltage = data.batteryVoltage;
prev.batteryCurrent = data.batteryCurrent;
prev.panelVoltage = data.panelVoltage;
prev.panelPower = data.panelPower;
prev.yieldToday = data.yieldToday;
prev.loadCurrent = data.loadCurrent;
prev.lastLogTime = now;
}
};
LoggerCallback callback;
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("\n=== VictronBLE Logger Example ===\n");
if (!victron.begin(5)) {
Serial.println("ERROR: Failed to initialize VictronBLE!");
Serial.println(victron.getLastError());
while (1) delay(1000);
}
victron.setDebug(false);
victron.setCallback(&callback);
// Add your devices here
victron.addDevice(
"Rainbow48V",
"E4:05:42:34:14:F3",
"0ec3adf7433dd61793ff2f3b8ad32ed8",
DEVICE_TYPE_SOLAR_CHARGER
);
victron.addDevice(
"ScottTrailer",
"e64559783cfb",
"3fa658aded4f309b9bc17a2318cb1f56",
DEVICE_TYPE_SOLAR_CHARGER
);
Serial.println("Configured " + String(victron.getDeviceCount()) + " devices");
Serial.println("Logging on change, or every 60s heartbeat\n");
}
void loop() {
victron.loop();
delay(100);
}

View File

@@ -30,8 +30,14 @@ VictronBLE victron;
// Device callback class - gets called when new data arrives // Device callback class - gets called when new data arrives
class MyVictronCallback : public VictronDeviceCallback { class MyVictronCallback : public VictronDeviceCallback {
public: public:
uint32_t solarChargerCount = 0;
uint32_t batteryMonitorCount = 0;
uint32_t inverterCount = 0;
uint32_t dcdcConverterCount = 0;
void onSolarChargerData(const SolarChargerData& data) override { void onSolarChargerData(const SolarChargerData& data) override {
Serial.println("\n=== Solar Charger: " + data.deviceName + " ==="); solarChargerCount++;
Serial.println("\n=== Solar Charger: " + data.deviceName + " (#" + String(solarChargerCount) + ") ===");
Serial.println("MAC: " + data.macAddress); Serial.println("MAC: " + data.macAddress);
Serial.println("RSSI: " + String(data.rssi) + " dBm"); Serial.println("RSSI: " + String(data.rssi) + " dBm");
Serial.println("State: " + getChargeStateName(data.chargeState)); Serial.println("State: " + getChargeStateName(data.chargeState));
@@ -47,7 +53,8 @@ public:
} }
void onBatteryMonitorData(const BatteryMonitorData& data) override { void onBatteryMonitorData(const BatteryMonitorData& data) override {
Serial.println("\n=== Battery Monitor: " + data.deviceName + " ==="); batteryMonitorCount++;
Serial.println("\n=== Battery Monitor: " + data.deviceName + " (#" + String(batteryMonitorCount) + ") ===");
Serial.println("MAC: " + data.macAddress); Serial.println("MAC: " + data.macAddress);
Serial.println("RSSI: " + String(data.rssi) + " dBm"); Serial.println("RSSI: " + String(data.rssi) + " dBm");
Serial.println("Voltage: " + String(data.voltage, 2) + " V"); Serial.println("Voltage: " + String(data.voltage, 2) + " V");
@@ -84,7 +91,8 @@ public:
} }
void onInverterData(const InverterData& data) override { void onInverterData(const InverterData& data) override {
Serial.println("\n=== Inverter/Charger: " + data.deviceName + " ==="); inverterCount++;
Serial.println("\n=== Inverter/Charger: " + data.deviceName + " (#" + String(inverterCount) + ") ===");
Serial.println("MAC: " + data.macAddress); Serial.println("MAC: " + data.macAddress);
Serial.println("RSSI: " + String(data.rssi) + " dBm"); Serial.println("RSSI: " + String(data.rssi) + " dBm");
Serial.println("Battery: " + String(data.batteryVoltage, 2) + " V"); Serial.println("Battery: " + String(data.batteryVoltage, 2) + " V");
@@ -107,7 +115,8 @@ public:
} }
void onDCDCConverterData(const DCDCConverterData& data) override { void onDCDCConverterData(const DCDCConverterData& data) override {
Serial.println("\n=== DC-DC Converter: " + data.deviceName + " ==="); dcdcConverterCount++;
Serial.println("\n=== DC-DC Converter: " + data.deviceName + " (#" + String(dcdcConverterCount) + ") ===");
Serial.println("MAC: " + data.macAddress); Serial.println("MAC: " + data.macAddress);
Serial.println("RSSI: " + String(data.rssi) + " dBm"); Serial.println("RSSI: " + String(data.rssi) + " dBm");
Serial.println("Input: " + String(data.inputVoltage, 2) + " V"); Serial.println("Input: " + String(data.inputVoltage, 2) + " V");
@@ -157,7 +166,7 @@ void setup() {
} }
// Enable debug output (optional) // Enable debug output (optional)
victron.setDebug(true); victron.setDebug(false);
// Set callback for data updates // Set callback for data updates
victron.setCallback(&callback); victron.setCallback(&callback);
@@ -176,6 +185,13 @@ void setup() {
DEVICE_TYPE_SOLAR_CHARGER // Device type DEVICE_TYPE_SOLAR_CHARGER // Device type
); );
victron.addDevice(
"ScottTrailer", // Device name
"e64559783cfb",
"3fa658aded4f309b9bc17a2318cb1f56",
DEVICE_TYPE_SOLAR_CHARGER // Device type
);
// Example: Solar Charger #1 // Example: Solar Charger #1
/* /*
victron.addDevice( victron.addDevice(

View File

@@ -26,6 +26,11 @@
"name": "MultiDevice", "name": "MultiDevice",
"base": "examples/MultiDevice", "base": "examples/MultiDevice",
"files": ["src/main.cpp"] "files": ["src/main.cpp"]
},
{
"name": "Logger",
"base": "examples/Logger",
"files": ["src/main.cpp"]
} }
], ],
"export": { "export": {