Files
shaggy-solar/eg4battery/Install.md
2026-04-25 19:00:44 -04:00

5.4 KiB
Raw Blame History

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 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)
  • 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.

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

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.

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 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.

    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 "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

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

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:
    - 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

# 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.