initialize
This commit is contained in:
58
eg4battery/homeassistant/README.md
Normal file
58
eg4battery/homeassistant/README.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# HA-side configuration for the eg4-battery daemon
|
||||
|
||||
Reference configs that go into your Home Assistant instance — they aren't
|
||||
installed by `install.sh` (HA typically lives on a different host / in an
|
||||
HA OS appliance), but they're tracked here so the full stack is reproducible.
|
||||
|
||||
## What's in here
|
||||
|
||||
| File | Where it goes in HA |
|
||||
|---------------------------|-----------------------------------------------------|
|
||||
| `recorder.yaml` | `configuration.yaml` → under a `recorder:` key, or merge into existing |
|
||||
| `template_sensors.yaml` | `configuration.yaml` → under a top-level `template:` list, or include via `!include` |
|
||||
| `lovelace_overview.yaml` | Raw Lovelace card config — paste into a new dashboard view |
|
||||
|
||||
All of it assumes pack names `lifepower4_1`, `lifepower4_2`, `lifepower4_3`
|
||||
matching the daemon's default config. If you renamed your packs, do a
|
||||
`sed -i 's/lifepower4_/your_prefix_/' *.yaml` first.
|
||||
|
||||
## Recommended retention tiers
|
||||
|
||||
Full rationale in [`../NOTES.md`](../NOTES.md) and the architecture thread,
|
||||
but the short version:
|
||||
|
||||
- **Tier 1 — keep forever**: `pack_voltage`, `pack_current`, `soc`, `soh`,
|
||||
`cycle_count`, `cell_voltage_min/max/delta_mv`, `capacity_ah`.
|
||||
- **Tier 2 — keep short**: all 14 `warning_*` + 14 `protection_*`,
|
||||
`error_code`, `remaining_ah`, `heater`, the derived `temperature_max`
|
||||
and `pack_power`.
|
||||
- **Tier 3 — exclude** (the `recorder.yaml` here does this): all 47 raw
|
||||
`register_NN` entities, the 16 individual `cell_NN_voltage` series,
|
||||
static metadata (`bms_version_*`, `battery_mode`, `cell_count`, etc.),
|
||||
and the `uptime_ds` counter that increments every second.
|
||||
|
||||
## Enabling in HA
|
||||
|
||||
Easiest path:
|
||||
|
||||
```yaml
|
||||
# configuration.yaml
|
||||
|
||||
# merge our recorder exclusions with your existing recorder config
|
||||
recorder: !include eg4_battery/recorder.yaml
|
||||
|
||||
# include the template sensors (creates a new `template:` list block)
|
||||
template: !include eg4_battery/template_sensors.yaml
|
||||
```
|
||||
|
||||
And drop the two YAMLs into `~/homeassistant/eg4_battery/`.
|
||||
|
||||
If you already have `recorder:` or `template:` keys elsewhere, merge by
|
||||
hand — HA doesn't allow two definitions of the same top-level key.
|
||||
|
||||
## Energy dashboard wiring (optional)
|
||||
|
||||
Once the derived `pack_power` template sensors exist, add them to the
|
||||
Energy dashboard via **Settings → Dashboards → Energy → Home battery
|
||||
storage** — each pack's `pack_power` integrates to `pack_energy_in_kwh`
|
||||
and `pack_energy_out_kwh` automatically, with per-pack bars.
|
||||
116
eg4battery/homeassistant/lovelace_overview.yaml
Normal file
116
eg4battery/homeassistant/lovelace_overview.yaml
Normal file
@@ -0,0 +1,116 @@
|
||||
# Lovelace card config for a 3-pack LifePower4 stack overview.
|
||||
# Paste into a dashboard view's raw-config editor, or drop in as a YAML-mode
|
||||
# dashboard. Assumes the template sensors in template_sensors.yaml exist.
|
||||
|
||||
views:
|
||||
- title: Battery Stack
|
||||
icon: mdi:battery
|
||||
path: batteries
|
||||
cards:
|
||||
# ---- stack summary row ----
|
||||
- type: horizontal-stack
|
||||
cards:
|
||||
- type: gauge
|
||||
name: Stack SoC
|
||||
entity: sensor.lifepower4_stack_soc_avg
|
||||
min: 0
|
||||
max: 100
|
||||
severity:
|
||||
green: 40
|
||||
yellow: 20
|
||||
red: 0
|
||||
- type: entity
|
||||
name: Stack Power
|
||||
entity: sensor.lifepower4_stack_pack_power_total
|
||||
icon: mdi:flash
|
||||
- type: entity
|
||||
name: Hottest Point
|
||||
entity: sensor.lifepower4_stack_temperature_max
|
||||
icon: mdi:thermometer
|
||||
|
||||
# ---- per-pack summary cards ----
|
||||
- type: horizontal-stack
|
||||
cards:
|
||||
- !include_named pack_summary_pack1.yaml
|
||||
- !include_named pack_summary_pack2.yaml
|
||||
- !include_named pack_summary_pack3.yaml
|
||||
|
||||
# ---- pack voltage time series ----
|
||||
- type: history-graph
|
||||
title: Pack voltage (24 h)
|
||||
hours_to_show: 24
|
||||
entities:
|
||||
- sensor.lifepower4_1_pack_voltage
|
||||
- sensor.lifepower4_2_pack_voltage
|
||||
- sensor.lifepower4_3_pack_voltage
|
||||
|
||||
# ---- SoC + SoH trend ----
|
||||
- type: history-graph
|
||||
title: SoC / SoH
|
||||
hours_to_show: 168 # 1 week
|
||||
entities:
|
||||
- sensor.lifepower4_1_soc
|
||||
- sensor.lifepower4_2_soc
|
||||
- sensor.lifepower4_3_soc
|
||||
- sensor.lifepower4_1_soh
|
||||
- sensor.lifepower4_2_soh
|
||||
- sensor.lifepower4_3_soh
|
||||
|
||||
# ---- cell balance health (the crucial long-term metric) ----
|
||||
- type: history-graph
|
||||
title: Cell voltage delta (mV) — rising = balance degrading
|
||||
hours_to_show: 168
|
||||
entities:
|
||||
- sensor.lifepower4_1_cell_voltage_delta_mv
|
||||
- sensor.lifepower4_2_cell_voltage_delta_mv
|
||||
- sensor.lifepower4_3_cell_voltage_delta_mv
|
||||
|
||||
# ---- any active warnings/protections — glance card, visible red when on ----
|
||||
- type: entities
|
||||
title: Alarms (should all be "off" on a healthy stack)
|
||||
show_header_toggle: false
|
||||
entities:
|
||||
- type: section
|
||||
label: Pack 1
|
||||
- entity: sensor.lifepower4_1_warning_cell_ov
|
||||
name: Cell OV
|
||||
- entity: sensor.lifepower4_1_warning_cell_uv
|
||||
name: Cell UV
|
||||
- entity: sensor.lifepower4_1_warning_charge_oc
|
||||
name: Charge OC
|
||||
- entity: sensor.lifepower4_1_warning_discharge_oc
|
||||
name: Discharge OC
|
||||
- entity: sensor.lifepower4_1_warning_mos_ot
|
||||
name: MOSFET OT
|
||||
- entity: sensor.lifepower4_1_warning_low_capacity
|
||||
name: Low Capacity
|
||||
- entity: sensor.lifepower4_1_protection_cell_ov
|
||||
name: PROT Cell OV
|
||||
- entity: sensor.lifepower4_1_protection_cell_uv
|
||||
name: PROT Cell UV
|
||||
# (repeat structure for pack_2 and pack_3, omitted for brevity)
|
||||
|
||||
# Per-pack summary card template — save as three copies named
|
||||
# pack_summary_pack1.yaml, pack_summary_pack2.yaml, pack_summary_pack3.yaml
|
||||
# with only the N suffix different.
|
||||
#
|
||||
# type: entities
|
||||
# title: Pack 1
|
||||
# show_header_toggle: false
|
||||
# entities:
|
||||
# - entity: sensor.lifepower4_1_pack_voltage
|
||||
# name: Voltage
|
||||
# - entity: sensor.lifepower4_1_pack_current
|
||||
# name: Current
|
||||
# - entity: sensor.lifepower4_1_pack_power
|
||||
# name: Power
|
||||
# - entity: sensor.lifepower4_1_soc
|
||||
# name: SoC
|
||||
# - entity: sensor.lifepower4_1_soh
|
||||
# name: SoH
|
||||
# - entity: sensor.lifepower4_1_temperature_max
|
||||
# name: Hottest
|
||||
# - entity: sensor.lifepower4_1_cell_voltage_delta_mv
|
||||
# name: Cell Δ
|
||||
# - entity: sensor.lifepower4_1_cycle_count
|
||||
# name: Cycles
|
||||
51
eg4battery/homeassistant/recorder.yaml
Normal file
51
eg4battery/homeassistant/recorder.yaml
Normal file
@@ -0,0 +1,51 @@
|
||||
# HA recorder exclusions for the eg4-battery daemon's MQTT entities.
|
||||
#
|
||||
# Merge with your existing recorder config; if you don't have one, this whole
|
||||
# file can be referenced as `recorder: !include eg4_battery/recorder.yaml`.
|
||||
#
|
||||
# Rationale:
|
||||
# - register_NN entities are raw Modbus registers, diagnostic only
|
||||
# - individual cell voltages are redundant once you have min/max/delta
|
||||
# - uptime / version / static config values are pure noise in a timeseries
|
||||
#
|
||||
# Everything NOT in `entity_globs` below keeps recording normally, including
|
||||
# the Tier-1 (pack_voltage / soc / soh / cycle_count / cell_voltage_min/max/
|
||||
# delta_mv / capacity_ah) and Tier-2 (warnings / protections / error_code)
|
||||
# entities. See ../NOTES.md for the retention-tier breakdown.
|
||||
|
||||
exclude:
|
||||
entity_globs:
|
||||
# raw Modbus register dump — diagnostic only
|
||||
- sensor.lifepower4_*_register_*
|
||||
|
||||
# 16 individual cells per pack = 48 noisy series.
|
||||
# cell_voltage_min / _max / _delta_mv already capture 95% of the info.
|
||||
# Comment this out if you're debugging a specific drifting cell.
|
||||
- sensor.lifepower4_*_cell_01_voltage
|
||||
- sensor.lifepower4_*_cell_02_voltage
|
||||
- sensor.lifepower4_*_cell_03_voltage
|
||||
- sensor.lifepower4_*_cell_04_voltage
|
||||
- sensor.lifepower4_*_cell_05_voltage
|
||||
- sensor.lifepower4_*_cell_06_voltage
|
||||
- sensor.lifepower4_*_cell_07_voltage
|
||||
- sensor.lifepower4_*_cell_08_voltage
|
||||
- sensor.lifepower4_*_cell_09_voltage
|
||||
- sensor.lifepower4_*_cell_10_voltage
|
||||
- sensor.lifepower4_*_cell_11_voltage
|
||||
- sensor.lifepower4_*_cell_12_voltage
|
||||
- sensor.lifepower4_*_cell_13_voltage
|
||||
- sensor.lifepower4_*_cell_14_voltage
|
||||
- sensor.lifepower4_*_cell_15_voltage
|
||||
- sensor.lifepower4_*_cell_16_voltage
|
||||
|
||||
# static metadata (doesn't change, no reason to keep history)
|
||||
- sensor.lifepower4_*_bms_version_hi
|
||||
- sensor.lifepower4_*_bms_version_lo
|
||||
- sensor.lifepower4_*_cell_count
|
||||
- sensor.lifepower4_*_cell_highest
|
||||
- sensor.lifepower4_*_cell_lowest
|
||||
- sensor.lifepower4_*_battery_mode
|
||||
- sensor.lifepower4_*_max_current_limit
|
||||
|
||||
# uptime counter — increments every second, kills the recorder's write cache
|
||||
- sensor.lifepower4_*_uptime_ds
|
||||
174
eg4battery/homeassistant/template_sensors.yaml
Normal file
174
eg4battery/homeassistant/template_sensors.yaml
Normal file
@@ -0,0 +1,174 @@
|
||||
# Derived template sensors for the eg4-battery daemon's 3-pack stack.
|
||||
# Include into configuration.yaml as:
|
||||
# template: !include eg4_battery/template_sensors.yaml
|
||||
#
|
||||
# Per-pack entities created:
|
||||
# sensor.lifepower4_N_pack_power W (V × I, signed; + = charging)
|
||||
# sensor.lifepower4_N_temperature_max °C (max of 5 temp sensors)
|
||||
# sensor.lifepower4_N_cell_imbalance_pct % (delta / min_cell) × 100
|
||||
#
|
||||
# Stack-wide rollups:
|
||||
# sensor.lifepower4_stack_pack_power_total W (sum of all 3 pack_powers)
|
||||
# sensor.lifepower4_stack_soc_avg % (average SoC across packs)
|
||||
# sensor.lifepower4_stack_temperature_max °C (hottest point anywhere)
|
||||
|
||||
- sensor:
|
||||
# ---- pack 1 ----
|
||||
- name: "lifepower4_1 pack_power"
|
||||
unique_id: lifepower4_1_pack_power
|
||||
unit_of_measurement: "W"
|
||||
device_class: power
|
||||
state_class: measurement
|
||||
state: >
|
||||
{% set v = states('sensor.lifepower4_1_pack_voltage') | float(0) %}
|
||||
{% set i = states('sensor.lifepower4_1_pack_current') | float(0) %}
|
||||
{{ (v * i) | round(1) }}
|
||||
|
||||
- name: "lifepower4_1 temperature_max"
|
||||
unique_id: lifepower4_1_temperature_max
|
||||
unit_of_measurement: "°C"
|
||||
device_class: temperature
|
||||
state_class: measurement
|
||||
state: >
|
||||
{% set t = [
|
||||
states('sensor.lifepower4_1_temperature_01') | int(0),
|
||||
states('sensor.lifepower4_1_temperature_02') | int(0),
|
||||
states('sensor.lifepower4_1_temperature_03') | int(0),
|
||||
states('sensor.lifepower4_1_temperature_04') | int(0),
|
||||
states('sensor.lifepower4_1_temperature_pcb') | int(0),
|
||||
] %}
|
||||
{{ t | max }}
|
||||
|
||||
- name: "lifepower4_1 cell_imbalance_pct"
|
||||
unique_id: lifepower4_1_cell_imbalance_pct
|
||||
unit_of_measurement: "%"
|
||||
state_class: measurement
|
||||
state: >
|
||||
{% set d = states('sensor.lifepower4_1_cell_voltage_delta_mv') | float(0) %}
|
||||
{% set mn = states('sensor.lifepower4_1_cell_voltage_min') | float(0) %}
|
||||
{{ (d / (mn * 1000) * 100) | round(3) if mn > 0 else 0 }}
|
||||
|
||||
# ---- pack 2 ----
|
||||
- name: "lifepower4_2 pack_power"
|
||||
unique_id: lifepower4_2_pack_power
|
||||
unit_of_measurement: "W"
|
||||
device_class: power
|
||||
state_class: measurement
|
||||
state: >
|
||||
{% set v = states('sensor.lifepower4_2_pack_voltage') | float(0) %}
|
||||
{% set i = states('sensor.lifepower4_2_pack_current') | float(0) %}
|
||||
{{ (v * i) | round(1) }}
|
||||
|
||||
- name: "lifepower4_2 temperature_max"
|
||||
unique_id: lifepower4_2_temperature_max
|
||||
unit_of_measurement: "°C"
|
||||
device_class: temperature
|
||||
state_class: measurement
|
||||
state: >
|
||||
{% set t = [
|
||||
states('sensor.lifepower4_2_temperature_01') | int(0),
|
||||
states('sensor.lifepower4_2_temperature_02') | int(0),
|
||||
states('sensor.lifepower4_2_temperature_03') | int(0),
|
||||
states('sensor.lifepower4_2_temperature_04') | int(0),
|
||||
states('sensor.lifepower4_2_temperature_pcb') | int(0),
|
||||
] %}
|
||||
{{ t | max }}
|
||||
|
||||
- name: "lifepower4_2 cell_imbalance_pct"
|
||||
unique_id: lifepower4_2_cell_imbalance_pct
|
||||
unit_of_measurement: "%"
|
||||
state_class: measurement
|
||||
state: >
|
||||
{% set d = states('sensor.lifepower4_2_cell_voltage_delta_mv') | float(0) %}
|
||||
{% set mn = states('sensor.lifepower4_2_cell_voltage_min') | float(0) %}
|
||||
{{ (d / (mn * 1000) * 100) | round(3) if mn > 0 else 0 }}
|
||||
|
||||
# ---- pack 3 ----
|
||||
- name: "lifepower4_3 pack_power"
|
||||
unique_id: lifepower4_3_pack_power
|
||||
unit_of_measurement: "W"
|
||||
device_class: power
|
||||
state_class: measurement
|
||||
state: >
|
||||
{% set v = states('sensor.lifepower4_3_pack_voltage') | float(0) %}
|
||||
{% set i = states('sensor.lifepower4_3_pack_current') | float(0) %}
|
||||
{{ (v * i) | round(1) }}
|
||||
|
||||
- name: "lifepower4_3 temperature_max"
|
||||
unique_id: lifepower4_3_temperature_max
|
||||
unit_of_measurement: "°C"
|
||||
device_class: temperature
|
||||
state_class: measurement
|
||||
state: >
|
||||
{% set t = [
|
||||
states('sensor.lifepower4_3_temperature_01') | int(0),
|
||||
states('sensor.lifepower4_3_temperature_02') | int(0),
|
||||
states('sensor.lifepower4_3_temperature_03') | int(0),
|
||||
states('sensor.lifepower4_3_temperature_04') | int(0),
|
||||
states('sensor.lifepower4_3_temperature_pcb') | int(0),
|
||||
] %}
|
||||
{{ t | max }}
|
||||
|
||||
- name: "lifepower4_3 cell_imbalance_pct"
|
||||
unique_id: lifepower4_3_cell_imbalance_pct
|
||||
unit_of_measurement: "%"
|
||||
state_class: measurement
|
||||
state: >
|
||||
{% set d = states('sensor.lifepower4_3_cell_voltage_delta_mv') | float(0) %}
|
||||
{% set mn = states('sensor.lifepower4_3_cell_voltage_min') | float(0) %}
|
||||
{{ (d / (mn * 1000) * 100) | round(3) if mn > 0 else 0 }}
|
||||
|
||||
# ---- stack-wide rollups ----
|
||||
- name: "lifepower4_stack pack_power_total"
|
||||
unique_id: lifepower4_stack_pack_power_total
|
||||
unit_of_measurement: "W"
|
||||
device_class: power
|
||||
state_class: measurement
|
||||
state: >
|
||||
{% set p = [
|
||||
states('sensor.lifepower4_1_pack_power') | float(0),
|
||||
states('sensor.lifepower4_2_pack_power') | float(0),
|
||||
states('sensor.lifepower4_3_pack_power') | float(0),
|
||||
] %}
|
||||
{{ p | sum | round(1) }}
|
||||
|
||||
- name: "lifepower4_stack soc_avg"
|
||||
unique_id: lifepower4_stack_soc_avg
|
||||
unit_of_measurement: "%"
|
||||
device_class: battery
|
||||
state_class: measurement
|
||||
state: >
|
||||
{% set s = [
|
||||
states('sensor.lifepower4_1_soc') | float(0),
|
||||
states('sensor.lifepower4_2_soc') | float(0),
|
||||
states('sensor.lifepower4_3_soc') | float(0),
|
||||
] %}
|
||||
{{ (s | sum / s | length) | round(1) }}
|
||||
|
||||
- name: "lifepower4_stack temperature_max"
|
||||
unique_id: lifepower4_stack_temperature_max
|
||||
unit_of_measurement: "°C"
|
||||
device_class: temperature
|
||||
state_class: measurement
|
||||
state: >
|
||||
{% set t = [
|
||||
states('sensor.lifepower4_1_temperature_max') | int(0),
|
||||
states('sensor.lifepower4_2_temperature_max') | int(0),
|
||||
states('sensor.lifepower4_3_temperature_max') | int(0),
|
||||
] %}
|
||||
{{ t | max }}
|
||||
|
||||
# --- integration → energy (pack_power integrated to Wh) ---
|
||||
# Paste this at the top level of configuration.yaml, NOT inside `template:`:
|
||||
#
|
||||
# sensor:
|
||||
# - platform: integration
|
||||
# source: sensor.lifepower4_1_pack_power
|
||||
# name: lifepower4_1_pack_energy
|
||||
# unit_prefix: k
|
||||
# round: 3
|
||||
# method: left
|
||||
# # ... repeat for pack 2 and 3 ...
|
||||
#
|
||||
# Then wire the resulting sensor.lifepower4_N_pack_energy into the HA
|
||||
# Energy dashboard → Home battery storage → one entry per pack.
|
||||
Reference in New Issue
Block a user