Files

160 lines
5.4 KiB
Markdown
Raw Permalink Normal View History

2026-04-24 16:34:10 -04:00
# EG4 LifePower4 v2 → HA Monitoring Install
Target: Debian-family Linux (developed on Raspberry Pi CM5), one USB-to-RS-485
adapter per pack's **RS485** socket, HA MQTT broker on the LAN.
> **Shortcut:** [`install.sh`](./install.sh) automates §3§7 and supports
> `--dry-run` for a no-hardware smoke test. This doc explains what it does
> and how to do it by hand.
Path conventions: `$BASE` = root of this package (e.g. `~/solar/eg4battery`).
## 1. Prerequisites
- `uv` on `$PATH` ([docs](https://docs.astral.sh/uv/))
- `sudo`
- **One USB-to-RS-485 adapter per pack**. FTDI-based is what we've tested
(FT232R + MAX485 combo, identified by the Linux kernel as `FT232R USB UART`
with a unique serial-number suffix). CH340 / CP210x also fine — adjust
the udev rule's vendor/product ID.
## 2. Cabling — read this before wiring
LP4V2 back panel has four RJ45 sockets: `CAN`, `RS485`, `Comm1`, `Comm2`.
Only `RS485` is relevant for our daemon:
| Socket | Use for monitoring? |
|--------|---------------------------------------------------------------------|
| CAN | No — separate bus, CAN signaling, for inverter BMS comms |
| RS485 | **Yes.** External monitor port. Pin 1-2 = B/A. Modbus RTU at 9600. |
| Comm1 | No — inter-pack hub bus (19200 Modbus). Leave for pack daisy-chain. |
| Comm2 | No — same internal bus as Comm1. |
The stock EG4 USB-RS-485 cable (included with each pack) is already wired
correctly for the RS485 socket (pins 1-2 / A-B).
**Topology**: each pack gets its own adapter plugged into its **RS485** socket.
No daisy chain required for monitoring — each pack is a dedicated bus. The
Comm1↔Comm2 daisy chain between packs is separate and carries the inter-pack
hub bus (not our concern).
## 3. udev rule
Grants `dialout` group access to FTDI USB-serial adapters.
```bash
sudo install -m 644 "$BASE/etc/udev/rules.d/99-eg4-rs485.rules" \
/etc/udev/rules.d/99-eg4-rs485.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --subsystem-match=tty
ls -l /dev/serial/by-id/ # expect one symlink per adapter
```
## 4. Daemon binary
```bash
sudo install -m 755 "$BASE/bin/eg4-battery" /usr/local/bin/eg4-battery
```
uv handles deps; no venv work on your side.
## 5. Config
Canonical template: [`config/eg4-battery.yaml.example`](./config/eg4-battery.yaml.example).
```bash
mkdir -p ~/.config/eg4-battery
install -m 600 "$BASE/config/eg4-battery.yaml.example" \
~/.config/eg4-battery/eg4-battery.yaml
# Edit — see "mode selection" below
```
### 5a. mode selection
- **`modbus_per_pack`** (default / recommended). Each pack listed with its own
`port:`, `address:` and `baud:` — the daemon opens one serial port per pack
2026-04-25 19:00:44 -04:00
and polls each independently. **Two Modbus reads per cycle per pack**:
block 1 (39 regs at 0x0000, live status) + block 2 (91 regs at 0x002D,
counters + model + firmware strings). ~150 ms per pack at 9600 baud.
2026-04-24 16:34:10 -04:00
```yaml
bus:
mode: modbus_per_pack
timeout_s: 1.0
poll_interval_s: 10.0
packs:
- name: lifepower4_1
address: 0x40
port: /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_<ID1>-if00-port0
baud: 9600
- name: lifepower4_2
address: 0x40
port: /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_<ID2>-if00-port0
baud: 9600
```
- **`active`** (legacy, V1 hardware only) — single shared bus, EG4 7E/0D
protocol at 9600. Not used on V2 Auto-Addressing hardware.
- **`passive`** (diagnostic) — listen-only Modbus sniff at 19200. See
[`NOTES.md`](./NOTES.md) "Modes" for details.
### 5b. MQTT creds
Replace `<MQTT_BROKER_IP>`, `<MQTT_USER>`, `<MQTT_PASSWORD>`. `install.sh`
will not auto-start the service while those placeholders remain.
## 6. Smoke test without hardware
```bash
eg4-battery -C ~/.config/eg4-battery/eg4-battery.yaml --dry-run
```
Mock transport, one cycle per pack, prints every discovery-config and
state-topic / payload to stdout. Confirms the pipeline end-to-end before
hardware is involved.
## 7. systemd
```bash
sudo install -m 644 "$BASE/etc/systemd/system/eg4-battery.service" \
/etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now eg4-battery.service
journalctl -u eg4-battery.service -f
```
Service includes `Environment=PATH=…` so uv is found under systemd.
## 8. Bring up additional packs
When a new pack comes online:
1. Plug its adapter into the pack's **RS485** socket and power the pack.
2. `ls -l /dev/serial/by-id/` — note the new symlink.
3. Add / update an entry in `~/.config/eg4-battery/eg4-battery.yaml`:
```yaml
- name: lifepower4_N
address: 0x40
port: /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_<ID>-if00-port0
baud: 9600
```
4. `sudo systemctl restart eg4-battery.service`. The journal shows
`pack lifepower4_N: recovered after N failed cycle(s)` within ~10 s when
the pack starts responding, and HA auto-discovers ~65 entities.
## 9. Verify MQTT flow
```bash
# modbus_per_pack: all named + raw register entities per pack
mosquitto_sub -h <broker> -u mqtt -P <pass> \
-t 'homeassistant/sensor/lifepower4_+_pack_voltage/state' \
-t 'homeassistant/sensor/lifepower4_+_soc/state' \
-t 'homeassistant/sensor/lifepower4_+_cell_voltage_delta_mv/state' \
-v
```
## 10. Swapping modes later
Change `bus.mode` in the config, restart the service. Config reshape varies
per mode — see §5a. No binary redeploy needed.