Repeater and Test code for ESP Now
This commit is contained in:
@@ -118,3 +118,47 @@ a843eb9 Keep v0.3.1
|
|||||||
- src/VictronBLE.cpp
|
- src/VictronBLE.cpp
|
||||||
- src/VictronBLE.h
|
- 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
|
||||||
|
|
||||||
|
|||||||
48
examples/FakeRepeater/platformio.ini
Normal file
48
examples/FakeRepeater/platformio.ini
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
[env:esp32dev]
|
||||||
|
platform = espressif32
|
||||||
|
board = esp32dev
|
||||||
|
framework = arduino
|
||||||
|
monitor_speed = 115200
|
||||||
|
monitor_filters = esp32_exception_decoder
|
||||||
|
|
||||||
|
[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
|
||||||
|
|
||||||
|
[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
|
||||||
|
build_flags =
|
||||||
|
-Os
|
||||||
|
-D ARDUINO_ESP32C3_DEV
|
||||||
|
-D CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
-D ARDUINO_USB_MODE=1
|
||||||
|
-D ARDUINO_USB_CDC_ON_BOOT=1
|
||||||
|
|
||||||
|
[env:m5stick]
|
||||||
|
platform = espressif32
|
||||||
|
board = m5stick-c
|
||||||
|
framework = arduino
|
||||||
|
board_build.mcu = esp32
|
||||||
|
board_build.f_cpu = 240000000L
|
||||||
|
board_build.partitions = no_ota.csv
|
||||||
|
monitor_speed = 115200
|
||||||
|
monitor_filters = esp32_exception_decoder
|
||||||
|
build_flags =
|
||||||
|
-Os
|
||||||
|
lib_deps =
|
||||||
|
M5StickC
|
||||||
102
examples/FakeRepeater/src/main.cpp
Normal file
102
examples/FakeRepeater/src/main.cpp
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
/**
|
||||||
|
* VictronBLE FakeRepeater Example
|
||||||
|
*
|
||||||
|
* Sends fake Solar Charger data over ESPNow every 10 seconds.
|
||||||
|
* Use with the Receiver example to test ESPNow without needing
|
||||||
|
* a real Victron device or the VictronBLE library.
|
||||||
|
*
|
||||||
|
* No VictronBLE dependency - just WiFi + ESPNow.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <esp_now.h>
|
||||||
|
|
||||||
|
// ESPNow packet structure - must match Receiver
|
||||||
|
struct __attribute__((packed)) SolarChargerPacket {
|
||||||
|
uint8_t chargeState;
|
||||||
|
float batteryVoltage; // V
|
||||||
|
float batteryCurrent; // A
|
||||||
|
float panelVoltage; // V
|
||||||
|
float panelPower; // W
|
||||||
|
uint16_t yieldToday; // Wh
|
||||||
|
float loadCurrent; // A
|
||||||
|
int8_t rssi; // BLE RSSI
|
||||||
|
char deviceName[16]; // Null-terminated, truncated
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t BROADCAST_ADDR[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||||
|
static uint32_t sendCount = 0;
|
||||||
|
static unsigned long lastSendTime = 0;
|
||||||
|
static const unsigned long SEND_INTERVAL_MS = 10000;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
Serial.println("\n=== VictronBLE FakeRepeater ===\n");
|
||||||
|
|
||||||
|
WiFi.mode(WIFI_STA);
|
||||||
|
WiFi.disconnect();
|
||||||
|
|
||||||
|
Serial.println("MAC: " + WiFi.macAddress());
|
||||||
|
|
||||||
|
if (esp_now_init() != ESP_OK) {
|
||||||
|
Serial.println("ERROR: ESPNow init failed!");
|
||||||
|
while (1) delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_now_peer_info_t peerInfo = {};
|
||||||
|
memcpy(peerInfo.peer_addr, BROADCAST_ADDR, 6);
|
||||||
|
peerInfo.channel = 0;
|
||||||
|
peerInfo.encrypt = false;
|
||||||
|
|
||||||
|
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
|
||||||
|
Serial.println("ERROR: Failed to add broadcast peer!");
|
||||||
|
while (1) delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println("ESPNow initialized, sending fake data every 10s");
|
||||||
|
Serial.println("Packet size: " + String(sizeof(SolarChargerPacket)) + " bytes\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
unsigned long now = millis();
|
||||||
|
if (now - lastSendTime < SEND_INTERVAL_MS) {
|
||||||
|
delay(100);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lastSendTime = now;
|
||||||
|
sendCount++;
|
||||||
|
|
||||||
|
// Generate varying fake data
|
||||||
|
SolarChargerPacket pkt;
|
||||||
|
pkt.chargeState = (sendCount % 4) + 3; // Cycle through Bulk(3), Absorption(4), Float(5), Storage(6)
|
||||||
|
pkt.batteryVoltage = 51.0f + (sendCount % 20) * 0.15f;
|
||||||
|
pkt.batteryCurrent = 2.0f + (sendCount % 10) * 0.5f;
|
||||||
|
pkt.panelVoltage = 65.0f + (sendCount % 15) * 0.8f;
|
||||||
|
pkt.panelPower = pkt.batteryCurrent * pkt.batteryVoltage;
|
||||||
|
pkt.yieldToday = 100 + sendCount * 10;
|
||||||
|
pkt.loadCurrent = 0;
|
||||||
|
pkt.rssi = -60 - (sendCount % 30);
|
||||||
|
|
||||||
|
memset(pkt.deviceName, 0, sizeof(pkt.deviceName));
|
||||||
|
strncpy(pkt.deviceName, "FakeMPPT", sizeof(pkt.deviceName) - 1);
|
||||||
|
|
||||||
|
esp_err_t result = esp_now_send(BROADCAST_ADDR,
|
||||||
|
reinterpret_cast<const uint8_t*>(&pkt),
|
||||||
|
sizeof(pkt));
|
||||||
|
|
||||||
|
if (result != ESP_OK) {
|
||||||
|
Serial.println("[TX FAIL] " + String(esp_err_to_name(result)));
|
||||||
|
} else {
|
||||||
|
Serial.printf("[TX #%lu] %s Batt:%.2fV %.2fA PV:%.0fW Yield:%uWh RSSI:%d\n",
|
||||||
|
sendCount,
|
||||||
|
pkt.deviceName,
|
||||||
|
pkt.batteryVoltage,
|
||||||
|
pkt.batteryCurrent,
|
||||||
|
pkt.panelPower,
|
||||||
|
pkt.yieldToday,
|
||||||
|
pkt.rssi);
|
||||||
|
}
|
||||||
|
}
|
||||||
48
examples/Receiver/platformio.ini
Normal file
48
examples/Receiver/platformio.ini
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
[env:esp32dev]
|
||||||
|
platform = espressif32
|
||||||
|
board = esp32dev
|
||||||
|
framework = arduino
|
||||||
|
monitor_speed = 115200
|
||||||
|
monitor_filters = esp32_exception_decoder
|
||||||
|
|
||||||
|
[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
|
||||||
|
|
||||||
|
[env:m5stick]
|
||||||
|
platform = espressif32
|
||||||
|
board = m5stick-c
|
||||||
|
framework = arduino
|
||||||
|
board_build.mcu = esp32
|
||||||
|
board_build.f_cpu = 240000000L
|
||||||
|
board_build.partitions = no_ota.csv
|
||||||
|
monitor_speed = 115200
|
||||||
|
monitor_filters = esp32_exception_decoder
|
||||||
|
build_flags =
|
||||||
|
-Os
|
||||||
|
lib_deps =
|
||||||
|
M5StickC
|
||||||
|
|
||||||
|
[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
|
||||||
|
build_flags =
|
||||||
|
-Os
|
||||||
|
-D ARDUINO_ESP32C3_DEV
|
||||||
|
-D CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
-D ARDUINO_USB_MODE=1
|
||||||
|
-D ARDUINO_USB_CDC_ON_BOOT=1
|
||||||
107
examples/Receiver/src/main.cpp
Normal file
107
examples/Receiver/src/main.cpp
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/**
|
||||||
|
* VictronBLE ESPNow Receiver
|
||||||
|
*
|
||||||
|
* Standalone receiver for data sent by the Repeater example.
|
||||||
|
* Does NOT depend on VictronBLE library - just ESPNow.
|
||||||
|
*
|
||||||
|
* Flash this on a second ESP32 and it will print Solar Charger
|
||||||
|
* data received over ESPNow from the Repeater.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <esp_now.h>
|
||||||
|
|
||||||
|
// ESPNow packet structure - must match Repeater
|
||||||
|
struct __attribute__((packed)) SolarChargerPacket {
|
||||||
|
uint8_t chargeState;
|
||||||
|
float batteryVoltage; // V
|
||||||
|
float batteryCurrent; // A
|
||||||
|
float panelVoltage; // V
|
||||||
|
float panelPower; // W
|
||||||
|
uint16_t yieldToday; // Wh
|
||||||
|
float loadCurrent; // A
|
||||||
|
int8_t rssi; // BLE RSSI
|
||||||
|
char deviceName[16]; // Null-terminated, truncated
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint32_t recvCount = 0;
|
||||||
|
|
||||||
|
static const char* chargeStateName(uint8_t state) {
|
||||||
|
switch (state) {
|
||||||
|
case 0: return "Off";
|
||||||
|
case 1: return "Low Power";
|
||||||
|
case 2: return "Fault";
|
||||||
|
case 3: return "Bulk";
|
||||||
|
case 4: return "Absorption";
|
||||||
|
case 5: return "Float";
|
||||||
|
case 6: return "Storage";
|
||||||
|
case 7: return "Equalize";
|
||||||
|
case 9: return "Inverting";
|
||||||
|
case 11: return "Power Supply";
|
||||||
|
case 252: return "External Control";
|
||||||
|
default: return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onDataRecv(const uint8_t* senderMac, const uint8_t* data, int len) {
|
||||||
|
if (len != sizeof(SolarChargerPacket)) {
|
||||||
|
Serial.println("Unexpected packet size: " + String(len));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto* pkt = reinterpret_cast<const SolarChargerPacket*>(data);
|
||||||
|
recvCount++;
|
||||||
|
|
||||||
|
// Ensure device name is null-terminated even if corrupted
|
||||||
|
char name[17];
|
||||||
|
memcpy(name, pkt->deviceName, 16);
|
||||||
|
name[16] = '\0';
|
||||||
|
|
||||||
|
Serial.printf("[RX #%lu] %s | State:%s Batt:%.2fV %.2fA PV:%.1fV %.0fW Yield:%uWh",
|
||||||
|
recvCount,
|
||||||
|
name,
|
||||||
|
chargeStateName(pkt->chargeState),
|
||||||
|
pkt->batteryVoltage,
|
||||||
|
pkt->batteryCurrent,
|
||||||
|
pkt->panelVoltage,
|
||||||
|
pkt->panelPower,
|
||||||
|
pkt->yieldToday);
|
||||||
|
|
||||||
|
if (pkt->loadCurrent > 0) {
|
||||||
|
Serial.printf(" Load:%.2fA", pkt->loadCurrent);
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.printf(" RSSI:%ddBm From:%02X:%02X:%02X:%02X:%02X:%02X\n",
|
||||||
|
pkt->rssi,
|
||||||
|
senderMac[0], senderMac[1], senderMac[2],
|
||||||
|
senderMac[3], senderMac[4], senderMac[5]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
Serial.println("\n=== VictronBLE ESPNow Receiver ===\n");
|
||||||
|
|
||||||
|
// Init WiFi in STA mode (required for ESPNow)
|
||||||
|
WiFi.mode(WIFI_STA);
|
||||||
|
WiFi.disconnect();
|
||||||
|
|
||||||
|
Serial.println("MAC: " + WiFi.macAddress());
|
||||||
|
|
||||||
|
// Init ESPNow
|
||||||
|
if (esp_now_init() != ESP_OK) {
|
||||||
|
Serial.println("ERROR: ESPNow init failed!");
|
||||||
|
while (1) delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_now_register_recv_cb(onDataRecv);
|
||||||
|
|
||||||
|
Serial.println("ESPNow initialized, waiting for packets...");
|
||||||
|
Serial.println("Expecting " + String(sizeof(SolarChargerPacket)) + " byte packets\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
57
examples/Repeater/platformio.ini
Normal file
57
examples/Repeater/platformio.ini
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
[env]
|
||||||
|
lib_extra_dirs = ../..
|
||||||
|
|
||||||
|
[env:esp32dev]
|
||||||
|
platform = espressif32
|
||||||
|
board = esp32dev
|
||||||
|
framework = arduino
|
||||||
|
monitor_speed = 115200
|
||||||
|
monitor_filters = esp32_exception_decoder
|
||||||
|
build_flags =
|
||||||
|
-DCORE_DEBUG_LEVEL=3
|
||||||
|
|
||||||
|
[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
|
||||||
|
|
||||||
|
[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 = huge_app.csv
|
||||||
|
monitor_speed = 115200
|
||||||
|
monitor_filters = time, default, esp32_exception_decoder
|
||||||
|
upload_speed = 921600
|
||||||
|
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:m5stick]
|
||||||
|
platform = espressif32
|
||||||
|
board = m5stick-c
|
||||||
|
framework = arduino
|
||||||
|
board_build.mcu = esp32
|
||||||
|
board_build.f_cpu = 240000000L
|
||||||
|
board_build.partitions = no_ota.csv
|
||||||
|
monitor_speed = 115200
|
||||||
|
monitor_filters = esp32_exception_decoder
|
||||||
|
build_flags =
|
||||||
|
-Os
|
||||||
|
lib_deps =
|
||||||
|
M5StickC
|
||||||
|
elapsedMillis
|
||||||
142
examples/Repeater/src/main.cpp
Normal file
142
examples/Repeater/src/main.cpp
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
/**
|
||||||
|
* VictronBLE Repeater Example
|
||||||
|
*
|
||||||
|
* Collects Solar Charger data via BLE and forwards every packet
|
||||||
|
* over ESPNow broadcast. Place this ESP32 near Victron devices and
|
||||||
|
* use a separate Receiver ESP32 at a distance.
|
||||||
|
*
|
||||||
|
* ESPNow range is typically much greater than BLE (~200m+ line of sight).
|
||||||
|
*
|
||||||
|
* Setup:
|
||||||
|
* 1. Get your device encryption keys from the VictronConnect app
|
||||||
|
* 2. Update the device configurations below with your MAC and key
|
||||||
|
* 3. Flash the Receiver example on a second ESP32
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <esp_now.h>
|
||||||
|
#include "VictronBLE.h"
|
||||||
|
|
||||||
|
// ESPNow packet structure - must match Receiver
|
||||||
|
struct __attribute__((packed)) SolarChargerPacket {
|
||||||
|
uint8_t chargeState;
|
||||||
|
float batteryVoltage; // V
|
||||||
|
float batteryCurrent; // A
|
||||||
|
float panelVoltage; // V
|
||||||
|
float panelPower; // W
|
||||||
|
uint16_t yieldToday; // Wh
|
||||||
|
float loadCurrent; // A
|
||||||
|
int8_t rssi; // BLE RSSI
|
||||||
|
char deviceName[16]; // Null-terminated, truncated
|
||||||
|
};
|
||||||
|
|
||||||
|
// Broadcast address
|
||||||
|
static const uint8_t BROADCAST_ADDR[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||||
|
|
||||||
|
static uint32_t sendCount = 0;
|
||||||
|
static uint32_t sendFailCount = 0;
|
||||||
|
|
||||||
|
VictronBLE victron;
|
||||||
|
|
||||||
|
class RepeaterCallback : public VictronDeviceCallback {
|
||||||
|
public:
|
||||||
|
void onSolarChargerData(const SolarChargerData& data) override {
|
||||||
|
SolarChargerPacket pkt;
|
||||||
|
pkt.chargeState = static_cast<uint8_t>(data.chargeState);
|
||||||
|
pkt.batteryVoltage = data.batteryVoltage;
|
||||||
|
pkt.batteryCurrent = data.batteryCurrent;
|
||||||
|
pkt.panelVoltage = data.panelVoltage;
|
||||||
|
pkt.panelPower = data.panelPower;
|
||||||
|
pkt.yieldToday = data.yieldToday;
|
||||||
|
pkt.loadCurrent = data.loadCurrent;
|
||||||
|
pkt.rssi = data.rssi;
|
||||||
|
|
||||||
|
// Copy device name, truncate to fit
|
||||||
|
memset(pkt.deviceName, 0, sizeof(pkt.deviceName));
|
||||||
|
strncpy(pkt.deviceName, data.deviceName.c_str(), sizeof(pkt.deviceName) - 1);
|
||||||
|
|
||||||
|
esp_err_t result = esp_now_send(BROADCAST_ADDR,
|
||||||
|
reinterpret_cast<const uint8_t*>(&pkt),
|
||||||
|
sizeof(pkt));
|
||||||
|
|
||||||
|
sendCount++;
|
||||||
|
if (result != ESP_OK) {
|
||||||
|
sendFailCount++;
|
||||||
|
Serial.println("ESPNow send failed: " + String(esp_err_to_name(result)));
|
||||||
|
} else {
|
||||||
|
Serial.println("[TX] " + String(pkt.deviceName) +
|
||||||
|
" Batt:" + String(pkt.batteryVoltage, 2) + "V" +
|
||||||
|
" PV:" + String(pkt.panelPower, 0) + "W" +
|
||||||
|
" (sent:" + String(sendCount) +
|
||||||
|
" fail:" + String(sendFailCount) + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
RepeaterCallback callback;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
Serial.println("\n=== VictronBLE ESPNow Repeater ===\n");
|
||||||
|
|
||||||
|
// Init WiFi in STA mode (required for ESPNow)
|
||||||
|
WiFi.mode(WIFI_STA);
|
||||||
|
WiFi.disconnect();
|
||||||
|
|
||||||
|
Serial.println("MAC: " + WiFi.macAddress());
|
||||||
|
|
||||||
|
// Init ESPNow
|
||||||
|
if (esp_now_init() != ESP_OK) {
|
||||||
|
Serial.println("ERROR: ESPNow init failed!");
|
||||||
|
while (1) delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add broadcast peer
|
||||||
|
esp_now_peer_info_t peerInfo = {};
|
||||||
|
memcpy(peerInfo.peer_addr, BROADCAST_ADDR, 6);
|
||||||
|
peerInfo.channel = 0; // Use current channel
|
||||||
|
peerInfo.encrypt = false;
|
||||||
|
|
||||||
|
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
|
||||||
|
Serial.println("ERROR: Failed to add broadcast peer!");
|
||||||
|
while (1) delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println("ESPNow initialized, broadcasting on all channels");
|
||||||
|
|
||||||
|
// Init VictronBLE
|
||||||
|
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()) + " BLE devices");
|
||||||
|
Serial.println("Packet size: " + String(sizeof(SolarChargerPacket)) + " bytes\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
victron.loop();
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
@@ -31,6 +31,11 @@
|
|||||||
"name": "Logger",
|
"name": "Logger",
|
||||||
"base": "examples/Logger",
|
"base": "examples/Logger",
|
||||||
"files": ["src/main.cpp"]
|
"files": ["src/main.cpp"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Repeater",
|
||||||
|
"base": "examples/Repeater",
|
||||||
|
"files": ["src/main.cpp"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"export": {
|
"export": {
|
||||||
|
|||||||
Reference in New Issue
Block a user