Experimenting with a claude file and created new logging example
This commit is contained in:
@@ -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
4
TODO
@@ -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
|
||||||
|
|||||||
143
examples/Logger/platformio.ini
Normal file
143
examples/Logger/platformio.ini
Normal 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
|
||||||
167
examples/Logger/src/main.cpp
Normal file
167
examples/Logger/src/main.cpp
Normal 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);
|
||||||
|
}
|
||||||
@@ -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(
|
||||||
|
|||||||
@@ -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": {
|
||||||
|
|||||||
Reference in New Issue
Block a user