2026-04-24 16:34:10 -04:00
|
|
|
|
# EG4 LifePower4 v2 → Home Assistant
|
|
|
|
|
|
|
|
|
|
|
|
Daemon that polls EG4 LifePower4 48V 100Ah v2 (Auto-Addressing) packs over
|
|
|
|
|
|
RS-485 and publishes per-pack telemetry to MQTT with HA auto-discovery.
|
|
|
|
|
|
|
|
|
|
|
|
## Status: live
|
|
|
|
|
|
|
2026-04-25 19:00:44 -04:00
|
|
|
|
All 3 packs publishing in `modbus_per_pack` mode, each on its own FTDI
|
|
|
|
|
|
RS-485 adapter. Per pack, ~70 named entities + 136 raw `register_NN` series:
|
2026-04-24 16:34:10 -04:00
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
lifepower4_1_pack_voltage 52.56 V (16 cells × 3.285 V)
|
|
|
|
|
|
lifepower4_1_cell_01_voltage 3.285 V
|
|
|
|
|
|
lifepower4_1_cell_voltage_delta_mv 2 (outstanding balance)
|
|
|
|
|
|
lifepower4_1_soc 100 %
|
|
|
|
|
|
lifepower4_1_capacity_ah 100.0 Ah
|
|
|
|
|
|
lifepower4_1_temperature_pcb 55 °C
|
2026-04-25 19:00:44 -04:00
|
|
|
|
lifepower4_1_model "LFP-51.2V100Ah-V1.0"
|
|
|
|
|
|
lifepower4_1_firmware_version "Z03T21"
|
|
|
|
|
|
lifepower4_1_firmware_date "20260206"
|
|
|
|
|
|
... plus 14 warning bits, 14 protection bits, all 136 raw registers
|
2026-04-24 16:34:10 -04:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-04-25 19:00:44 -04:00
|
|
|
|
The decoder maps registers to fields per a layout reverse-engineered from
|
|
|
|
|
|
the EG4 BMS Tool's Mach-O binary (see [`NOTES.md`](./NOTES.md) §"Modbus
|
|
|
|
|
|
polling" and §"Register map"). Each cycle, the daemon issues two Modbus
|
|
|
|
|
|
fn=0x03 reads per pack — block 1 (39 regs at 0x0000) for live status, and
|
|
|
|
|
|
block 2 (91 regs at 0x002D) for counters + model + firmware strings —
|
|
|
|
|
|
mirroring what the vendor BMS Tool itself does.
|
2026-04-24 16:34:10 -04:00
|
|
|
|
|
|
|
|
|
|
## Modes
|
|
|
|
|
|
|
|
|
|
|
|
Set by `bus.mode` in `~/.config/eg4-battery/eg4-battery.yaml`:
|
|
|
|
|
|
|
|
|
|
|
|
| Mode | When to use |
|
|
|
|
|
|
|-------------------|---------------------------------------------------------|
|
|
|
|
|
|
| `modbus_per_pack` | **Default.** One FTDI per pack's RS485 port. Fully decoded HA entities. |
|
|
|
|
|
|
| `active` | Legacy 7E/0D (V1 firmware only). Not used on V2 hardware. |
|
|
|
|
|
|
| `passive` | Listen-only Modbus sniff (19200). Diagnostic use. |
|
|
|
|
|
|
|
|
|
|
|
|
See [`NOTES.md`](./NOTES.md) for architecture, register map, LVX6048
|
|
|
|
|
|
compatibility findings, and bring-up checklist.
|
|
|
|
|
|
|
|
|
|
|
|
## What's in the box
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
eg4battery/
|
|
|
|
|
|
├── README.md ← start here
|
|
|
|
|
|
├── Install.md ← detailed walkthrough + mode-switch howto
|
|
|
|
|
|
├── NOTES.md ← architecture, register map, port matrix
|
|
|
|
|
|
├── install.sh ← idempotent installer (supports --dry-run)
|
|
|
|
|
|
│
|
|
|
|
|
|
├── bin/eg4-battery ← single-file daemon (uv PEP-723 inline deps)
|
|
|
|
|
|
│
|
|
|
|
|
|
├── config/eg4-battery.yaml.example ← template, multiple-pack config
|
|
|
|
|
|
│
|
|
|
|
|
|
├── etc/ mirror of target paths (Pi side)
|
|
|
|
|
|
│ ├── udev/rules.d/99-eg4-rs485.rules
|
|
|
|
|
|
│ └── systemd/system/eg4-battery.service
|
|
|
|
|
|
│
|
|
|
|
|
|
├── homeassistant/ ← drop into your HA config dir
|
|
|
|
|
|
│ ├── README.md (what goes where + retention tiers)
|
|
|
|
|
|
│ ├── recorder.yaml (exclude noisy / diagnostic entities)
|
|
|
|
|
|
│ ├── template_sensors.yaml (derived: power, temp_max, cell_imbalance, stack rollups)
|
|
|
|
|
|
│ └── lovelace_overview.yaml (3-pack stack dashboard)
|
|
|
|
|
|
│
|
|
|
|
|
|
└── tmp/ ad-hoc diagnostics
|
|
|
|
|
|
├── port-probe (single-cycle 9600/19200/7E probe)
|
|
|
|
|
|
├── eg4-snapshot (47-reg dump for BMS Tool cross-check)
|
|
|
|
|
|
└── bms-tool-ref/ (unpacked vendor BMS Tool for RE reference)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Quick start on a fresh host
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
cd ~/solar/eg4battery
|
|
|
|
|
|
./install.sh --dry-run # mock cycle, prints MQTT payloads, exits
|
|
|
|
|
|
|
|
|
|
|
|
# Edit ~/.config/eg4-battery/eg4-battery.yaml:
|
|
|
|
|
|
# - For modbus_per_pack: one 'packs:' entry per pack, each with port + address + baud
|
|
|
|
|
|
# - mqtt.host / username / password
|
|
|
|
|
|
|
|
|
|
|
|
./install.sh # real deploy; auto-starts once creds are filled
|
|
|
|
|
|
journalctl -u eg4-battery.service -f
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Related packages
|
|
|
|
|
|
|
|
|
|
|
|
- [`../LVX6048/`](../LVX6048/) — inverter-side monitoring via PI18 over USB-HID.
|
|
|
|
|
|
Same MQTT broker. Between the two packages, HA sees every useful number from
|
|
|
|
|
|
the stack.
|
|
|
|
|
|
|
|
|
|
|
|
## Acknowledgements
|
|
|
|
|
|
|
|
|
|
|
|
- `battery/eg4_lifepower.py` — V1 protocol decoder adapted from
|
|
|
|
|
|
[`Louisvdw/dbus-serialbattery`](https://github.com/Louisvdw/dbus-serialbattery).
|
|
|
|
|
|
Historical; V2 firmware moved to Modbus on a different port.
|
|
|
|
|
|
- EG4 Electronics `lv_host.app` — the vendor BMS Tool; its Qt binary's SQLite
|
|
|
|
|
|
schema and strings gave us the register-to-field mapping.
|