initialize

This commit is contained in:
2026-04-24 16:34:10 -04:00
commit 9aca623336
202 changed files with 6718 additions and 0 deletions

157
eg4battery/Install.md Normal file
View File

@@ -0,0 +1,157 @@
# 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
and polls each independently.
```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.

160
eg4battery/NOTES.md Normal file
View File

@@ -0,0 +1,160 @@
# EG4 LifePower4 v2 — architecture & protocol notes
## Modes — choose per deployment
`bus.mode` in the config picks one of three daemon modes:
| Mode | Wire protocol | Baud | Role | Status |
|------------------|----------------------|-------|----------------|------------------------------------------------------------|
| `modbus_per_pack`| Modbus RTU, fn 0x03 | 9600 | master (per pack)| **Primary path for LP4V2 Auto-Addressing.** One FTDI per pack's RS485 port, polls once per cycle, fully decodes into named HA entities. |
| `active` | EG4 7E/0D legacy | 9600 | master (shared) | **Legacy.** V1 firmware only. V2 packs don't respond to this protocol — kept for reference. |
| `passive` | Modbus RTU sniff | 19200 | listener | **Diagnostic.** Originally intended to listen on an LVX6048 BMS bus; the LVX6048 doesn't poll EG4 packs that way, so has no production use here. |
## How we got here (summary)
1. **Port matrix test** (2026-04-24). Established that the LP4V2 back panel's four RJ45s (CAN / RS485 / Comm1 / Comm2) carry three distinct electrical buses:
- Comm1 + Comm2 = inter-pack hub bus (19200 Modbus, master-to-slave coordination). Pin 1-2 and pin 7-8 both tap the same bus.
- RS485 = external monitor bus. Inactive until an external master drives it.
- CAN = separate bus, not in scope.
2. **EG4 BMS Tool capture.** User confirmed the stock Windows/macOS BMS Tool connects to the RS485 port at 9600 baud, Modbus slave ID **0x40**. Our first canonical Modbus probe at that address returned a clean 99-byte reply.
3. **`lv_host.app` reverse-engineering.** The BMS Tool is a Qt app. Its Mach-O binary contains:
- SQLite schema for the `total` table → complete list of 39 fields the BMS Tool stores per cycle.
- String-table names for warning / protection bit flags.
- C++ symbols `BmsDatalog::allFunctionModbusAnalysis`, `BmsMonitoring::allFunctionModbusAnalysis`, `usModbusAskRegBase` etc. → confirms Modbus RTU fn 0x03 read-holding-regs.
4. **Register map construction.** Correlated live register values (cell voltages, pack V) against the SQL field list to derive the 47-reg map below. High-confidence fields promoted to named HA entities; unknowns still emitted as `register_NN` for future correlation.
## Register map (Modbus fn 0x03, start 0x0000, count 47)
From live observation + lv_host.app schema:
| Reg | Observed | Field | Scale | Unit | HA entity suffix |
|-------|--------------|---------------------|---------|------|----------------------|
| 00 | 5256 | Total_Voltage | × 0.01 | V | `pack_voltage` |
| 01 | 0 (signed) | Current_I | × 0.01 | A | `pack_current` |
| 02-17 | ~3285 each | Vol_Cell01..16 | × 0.001 | V | `cell_01_voltage`..`cell_16_voltage` + `cell_voltage_min/max/delta_mv/lowest/highest` |
| 18 | 21 | Temp_01 | × 1 | °C | `temperature_01` |
| 19 | 21 | Temp_02 | × 1 | °C | `temperature_02` |
| 20 | 20 | Temp_03 | × 1 | °C | `temperature_03` |
| 21 | 54 | Temp_04 | × 1 | °C | `temperature_04` |
| 22 | 100 | SOC | × 1 | % | `soc` |
| 23 | 100 | SOH | × 1 | % | `soh` |
| 24 | 55 | Temp_PCB | × 1 | °C | `temperature_pcb` |
| 25-29 | 0 | reserved | | | (register_NN only) |
| 30 | 1 | Heater (bit 0) | | | `heater` (on/off) |
| 31 | 5493 | MAX_Curren | × 0.01 | A | `max_current_limit` |
| 32 | 10752 | *?* | | | (register_32) |
| 33 | ? | Warning bitfield | | | `warning_*` (14 bits)|
| 34 | ? | Protection bitfield | | | `protection_*` (14 bits)|
| 35 | 0 | Error_Code | | | `error_code` |
| 36 | 16 | Cell_Num | | | `cell_count` |
| 37 | 1000 | Capacity | × 0.1 | Ah | `capacity_ah` |
| 38 | 0 | Remaining | × 0.01 | Ah | `remaining_ah` |
| 39 | 0 | CycleNum | | | `cycle_count` |
| 40 | 7 | Battery_Mode (enum) | | | `battery_mode` |
| 41 | 0x0fff | BMS_Version (hi) | | | `bms_version_hi` |
| 42 | 0x07ff | BMS_Version (lo) | | | `bms_version_lo` |
| 43-45 | — | *?* | | | (register_NN only) |
| 46 | +1.25 Hz | runtime counter | × 0.1 s?| | `uptime_ds` |
**Confidence levels**: Bold-worthy certain (confirmed by live values + UI labels): pack_voltage, cells 01-16, SOC, SOH, cell_count, capacity_ah. Medium (fits data, unverified): temps, current, bitfields, Battery_Mode. Unknown: regs 32, 35 (probably Error_Code but value always 0 so far), 38-40, 43-45.
## Warning / protection bit maps
From the UI labels in lv_host.app (bit 0 = first listed):
| Bit | Warning (reg 33) | Protection (reg 34) |
|-----|-------------------|---------------------|
| 0 | pack_ov | pack_ov |
| 1 | cell_ov | cell_ov |
| 2 | pack_uv | pack_uv |
| 3 | cell_uv | cell_uv |
| 4 | charge_oc | charge_oc |
| 5 | discharge_oc | discharge_oc |
| 6 | temp_anomaly | temp_anomaly |
| 7 | mos_ot | mos_ot |
| 8 | charge_ot | charge_ot |
| 9 | discharge_ot | discharge_ot |
| 10 | charge_ut | charge_ut |
| 11 | discharge_ut | discharge_ut |
| 12 | low_capacity | float_stopped |
| 13 | other_error | discharge_sc |
Each bit becomes an HA sensor reporting `on` / `off`. Exact bit ordering is guessed from UI display order — adjust if the EG4 tool ever shows a flag we don't match.
## Hardware topology notes
### Critical: RS485 port only works when the pack is standalone
**Empirical finding** (2026-04-24): the LP4V2's external `RS485` port
only answers Modbus queries when the pack is **not** daisy-chained to
other packs via `Comm1`/`Comm2`. Specifically:
- With daisy chains intact (bat1 Comm2 → bat2 Comm1 etc.), one pack
elects as master and polls slaves over the internal hub bus
(19200 Modbus on Comm1/Comm2). Slave packs' RS485 ports go silent —
only the master responds externally.
- Remove the inter-pack Comm jumpers and each pack becomes a
self-contained master: its Comm1/Comm2 LEDs flash (it's trying to
poll slaves that aren't there), and its own RS485 port becomes fully
live for external queries.
**Implication**: `modbus_per_pack` mode requires **each pack standalone**
— one FTDI adapter per pack's RS485 port, no inter-pack Comm jumpers.
This is how we got bat1 responding cleanly. If the batteries later
need to be daisy-chained to an inverter, only the master pack's RS485
port will answer external queries; slave per-pack data would need to
come from decoding the Comm1/Comm2 hub bus instead (a future mode).
### Port roles on the LP4V2 pack (from the port matrix test)
| Port | Role | Pins carrying signal | Protocol / baud |
|-------|--------------------------------|-------------------------|-----------------------|
| CAN | Inverter CAN comms | (CAN-specific pinout) | CANbus (not RS-485) |
| RS485 | External monitor | 1-2 | Modbus RTU @ 9600 |
| Comm1 | Inter-pack hub bus (in/out) | 1-2 and 7-8 both tap it | Modbus RTU @ 19200 |
| Comm2 | Inter-pack hub bus (in/out) | 1-2 and 7-8 both tap it | Modbus RTU @ 19200 |
- The **stock USB-RS485 cable** ships wired to pins 1-2 — usable on either Comm or RS485.
- The **pin 7-8 modified cable** only gains us the Comm/Comm2 hub-bus tap; since pins 1-2 reach the same bus, it's not strictly necessary. Kept in the toolkit for diagnostic purposes.
- Factory inter-pack jumpers (between packs) are 8-conductor CAT5 — they carry both pin pairs.
### Adapters
On this host, three USB-FTDI adapters are plugged into the three packs' RS485 ports:
| Adapter ID | Pack | `/dev/serial/by-id/...` |
|------------------|----------------|--------------------------------------------------------|
| A994XMVK | bat1 (RS485) | `usb-FTDI_FT232R_USB_UART_A994XMVK-if00-port0` |
| A994XGUY | bat2 (RS485) | `usb-FTDI_FT232R_USB_UART_A994XGUY-if00-port0` |
| A994XMBR | bat3 (RS485) | `usb-FTDI_FT232R_USB_UART_A994XMBR-if00-port0` |
Each pack gets polled on its own bus → no shared-bus arbitration, no master/slave coordination needed, pack Modbus address is 0x40 for all of them.
## LVX6048 compatibility (still true)
LVX6048 BMS port protocols: `PYL` (Pylontech), `LIb` (MPP LIO), `WEC` (WECO), `SOL` (Soltaro), `VSC` (Pylontech-CAN), `USE` (voltage-only). **No native EG4 LP4V2 support.** For inverter↔battery comms, set `P05/P14 = USE` and manage charge profile via `lvx-flash`. See DIY Solar Forum threads 67496 & 96019, LVX6048WP manual §9-2.
## Bring-up checklist (when a new pack goes live)
1. Wire: plug USB-FTDI adapter (stock pin-1-2 cable) into the pack's **RS485** port.
2. Confirm the pack's BMS is powered (LEDs steady on Comm1 + Comm2, not dark).
3. Verify the `/dev/serial/by-id/...` symlink exists for the adapter.
4. Add a pack entry to the config:
```yaml
packs:
- name: lifepower4_N
address: 0x40
port: /dev/serial/by-id/usb-FTDI_...-if00-port0
baud: 9600
```
5. `sudo systemctl restart eg4-battery.service`. Watch journal — within ~10 s you should see the first MQTT publish, or `WARNING: no/bad response` if the pack isn't answering.
6. In HA: `EG4 LifePower4 lifepower4_N` device appears with ~65 auto-discovered entities.
## Sources / references
- `lv_host.app` (Qt) — Contents/MacOS/lv_host Mach-O binary + my1.db/my2.db SQLite schemas
- `../battery/eg4_lifepower.py` — V1 7E/0D decoder (Louisvdw/dbus-serialbattery port), historical reference
- `../battery/sweep.py` — protocol + baud scanner used for initial triage
- EG4 "Cables Needed for Updating" PDF
- EG4 Community Forum: "Specs for LifePower4 V2 BAT-COM ports"
- LVX6048WP manual §9-2 (BMS pinout), §Programs P03/P05

95
eg4battery/README.md Normal file
View File

@@ -0,0 +1,95 @@
# 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
As of 2026-04-24, `bat1` is live via `modbus_per_pack` mode on its RS485 port,
reporting all ~65 entities into HA:
```
lifepower4_1_pack_voltage 52.56 V (16 cells × 3.285 V)
lifepower4_1_cell_01_voltage 3.285 V
lifepower4_1_cell_16_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_01 21 °C
lifepower4_1_temperature_pcb 55 °C
... plus 14 warning bits, 14 protection bits, all 47 raw registers
```
`bat2` and `bat3` are wired but unpowered — the daemon logs one warning per
unreachable pack per startup and keeps retrying silently. They'll come online
automatically when the user powers them up.
## 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.

969
eg4battery/bin/eg4-battery Executable file
View File

@@ -0,0 +1,969 @@
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "pyserial>=3.5",
# "paho-mqtt>=2.0",
# "pyyaml>=6.0",
# ]
# ///
"""
eg4-battery — telemetry bridge from EG4 LifePower4 v2 BMSes to MQTT/HA.
Three modes, selected via `bus.mode` in the config:
modbus_per_pack — RECOMMENDED. One FTDI RS-485 adapter per pack. Each pack
has its own (port, address, baud) in the `packs:` list.
Uses Modbus RTU fn=0x03 read-47-regs at 0x0000. Decoder
extracts named fields (pack V, 16 cell voltages, temps,
SoC, SoH, Capacity, warnings, protections) — register
map reverse-engineered from the EG4 `lv_host.app` BMS
Tool's SQLite schema + UI labels.
active — LEGACY. Single FTDI adapter on a dedicated bus, EG4
7E/0D protocol at 9600 baud. Was ported from the V1
firmware via `battery/eg4_lifepower.py`; V2 hardware
doesn't speak this protocol in practice. Kept for
reference / possible V1 deployments.
passive — LEGACY. Listen-only Modbus-RTU sniffer at 19200 baud.
Originally targeted the LVX6048 BMS bus; LVX6048 doesn't
poll EG4 packs that way, so the mode is diagnostic only.
Usage:
eg4-battery -C <config.yaml>
eg4-battery -C <config.yaml> --dry-run # mock bus, print, exit
eg4-battery -C <config.yaml> --trace # log every frame
"""
from __future__ import annotations
import argparse
import asyncio
import dataclasses
import json
import logging
import random
import struct
import sys
import time
from pathlib import Path
from struct import unpack_from
from typing import Any, Iterator
import paho.mqtt.client as mqtt
import serial
import yaml
log = logging.getLogger("eg4-battery")
# =============================================================================
# === config ==================================================================
# =============================================================================
@dataclasses.dataclass
class PackConfig:
name: str # HA entity prefix / device identifier (e.g. "lifepower4_1")
address: int # protocol-level address (Modbus slave ID, or EG4 7E address)
port: str | None = None # per-pack port (modbus_per_pack mode only)
baud: int | None = None # per-pack baud override (modbus_per_pack mode only)
@dataclasses.dataclass
class BusConfig:
mode: str # "modbus_per_pack" | "active" | "passive"
transport: str = "serial" # "serial" | "mock"
port: str = "" # shared port (active / passive modes)
baud: int = 9600
read_chunk: int = 512
timeout_s: float = 1.5 # per-query timeout
poll_interval_s: float = 10.0 # full round-robin cycle target
@dataclasses.dataclass
class MQTTConfig:
host: str
port: int
username: str
password: str
discovery_prefix: str = "homeassistant"
@dataclasses.dataclass
class AppConfig:
bus: BusConfig
mqtt: MQTTConfig
packs: list[PackConfig]
cell_count: int = 16 # active mode only
def load_config(path: Path) -> AppConfig:
raw = yaml.safe_load(path.read_text())
return AppConfig(
bus=BusConfig(**raw["bus"]),
mqtt=MQTTConfig(**raw["mqtt"]),
packs=[PackConfig(**p) for p in raw["packs"]],
cell_count=raw.get("cell_count", 16),
)
# =============================================================================
# === active mode: EG4 7E/0D protocol =========================================
# =============================================================================
# Verified against `battery/eg4_lifepower.py`. Frame:
# request (6 bytes): 7E <addr> <cmd> 00 <chk> 0D
# chk = (0x100 - (addr + cmd + len)) & 0xFF
# reply (variable): 7E <addr> <cmd> <len> [10 groups] <chk> 0D
# each group: <type_byte> <count> <count × big-endian uint16>
CMD_GENERAL_STATUS = 0x01 # cells, V, I, SoC, cap, temps, cycles, alarms
CMD_FW_VER = 0x33
CMD_HW_VER = 0x42
def encode_eg4_request(address: int, cmd: int, length: int = 0) -> bytes:
chk = (0x100 - (address + cmd + length)) & 0xFF
return bytes([0x7E, address, cmd, length, chk, 0x0D])
def decode_eg4_general_status(data: bytes, cell_count: int) -> dict[str, Any]:
"""Decode a fn=0x01 reply into a flat dict keyed for HA. Mirrors
`battery/eg4_lifepower.py::parse_status`. Permissive framing check
(header/footer); upstream doesn't validate the reply CRC and neither
do we until we know the algorithm."""
if not data or len(data) < 6 or data[0] != 0x7E or data[-1] != 0x0D:
raise ValueError(f"bad framing: {data.hex(' ')[:120]}")
groups: list[list[int]] = []
i = 4 # skip 7E <addr> <cmd> <len>
for _ in range(10):
if i + 2 > len(data):
raise ValueError(f"truncated payload at group {len(groups)}")
group_len = data[i + 1]
end = i + 2 + group_len * 2
if end > len(data):
raise ValueError(f"group {len(groups)} overruns frame (end={end}, len={len(data)})")
payload = data[i + 2:end]
groups.append([unpack_from(">H", payload, k)[0] for k in range(0, len(payload), 2)])
i = end
out: dict[str, Any] = {}
# group 0 — cell voltages (mV; mask 0x7FFF per upstream — top bit is some flag)
cells = [(v & 0x7FFF) / 1000.0 for v in groups[0][:cell_count]]
for idx, cv in enumerate(cells, start=1):
out[f"cell_{idx:02d}_voltage"] = round(cv, 3)
if cells:
vmin, vmax = min(cells), max(cells)
out["cell_voltage_min"] = round(vmin, 3)
out["cell_voltage_max"] = round(vmax, 3)
out["cell_voltage_delta_mv"] = round((vmax - vmin) * 1000)
out["cell_lowest"] = cells.index(vmin) + 1
out["cell_highest"] = cells.index(vmax) + 1
# group 1 — current (signed; encoded as 30000 - A×100; positive = charge)
if groups[1]:
out["current"] = round((30000 - groups[1][0]) / 100.0, 2)
# group 2 — SoC × 100
if groups[2]:
out["soc"] = round(groups[2][0] / 100.0, 1)
# group 3 — capacity (Ah × 100)
if groups[3]:
out["capacity_ah"] = round(groups[3][0] / 100.0, 2)
# group 4 — temperatures (low byte 50 °C)
for idx, raw in enumerate(groups[4][:6], start=1):
out[f"temperature_{idx}"] = (raw & 0xFF) - 50
# group 5 — alarm bitfield (second word per upstream)
flags = groups[5][1] if len(groups[5]) > 1 else 0
out["alarm_current_over"] = "on" if flags & 0b00001000 else "off"
out["alarm_voltage_high"] = "on" if flags & 0b00010000 else "off"
out["alarm_voltage_low"] = "on" if flags & 0b00100000 else "off"
out["alarm_temp_high_chg"] = "on" if flags & 0b01000000 else "off"
out["alarm_temp_low_chg"] = "on" if flags & 0b10000000 else "off"
# group 6 — cycle count
if groups[6]:
out["cycle_count"] = groups[6][0]
# group 7 — pack voltage (V × 100)
if groups[7]:
out["pack_voltage"] = round(groups[7][0] / 100.0, 2)
# groups 8-9 — undecoded; leave as future work
return out
# =============================================================================
# === passive mode: Modbus RTU framing ========================================
# =============================================================================
def crc16_modbus(data: bytes) -> int:
crc = 0xFFFF
for b in data:
crc ^= b
for _ in range(8):
if crc & 1:
crc = (crc >> 1) ^ 0xA001
else:
crc >>= 1
return crc
def _crc_ok(buf: bytes, start: int, length: int) -> bool:
if start + length > len(buf):
return False
body = buf[start:start + length - 2]
expected = buf[start + length - 2] | (buf[start + length - 1] << 8)
return crc16_modbus(body) == expected
_MODBUS_FUNCS = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x0F, 0x10, 0x16, 0x17}
def parse_modbus_frame_at(buf: bytes, start: int) -> tuple[int, str] | None:
if start + 4 > len(buf):
return None
func = buf[start + 1]
# exception response (5 bytes), only for legitimate function codes
if func >= 0x80 and (func & 0x7F) in _MODBUS_FUNCS \
and start + 5 <= len(buf) and 1 <= buf[start + 2] <= 11 \
and _crc_ok(buf, start, 5):
return (5, "exception")
if func == 0x03:
# query: 8 bytes
if _crc_ok(buf, start, 8):
return (8, "query")
# response: 1 + 1 + 1 + byte_count + 2
if start + 3 <= len(buf):
byte_count = buf[start + 2]
if 2 <= byte_count <= 250 and byte_count % 2 == 0:
total = 3 + byte_count + 2
if _crc_ok(buf, start, total):
return (total, "response")
return None
@dataclasses.dataclass
class ModbusFrame:
address: int
function: int
kind: str
raw: bytes
@property
def registers(self) -> list[int]:
if self.kind != "response" or self.function != 0x03:
return []
bc = self.raw[2]
d = self.raw[3:3 + bc]
return [(d[i] << 8) | d[i + 1] for i in range(0, len(d), 2)]
def decode_modbus_response(frame: ModbusFrame) -> dict[str, Any]:
"""Raw-register dump; promote to named fields once we know the layout."""
return {f"register_{i:02d}": v for i, v in enumerate(frame.registers)}
# ---- modbus_per_pack active-poll decoder (EG4 LP4V2) -----------------------
# Register map derived from lv_host.app BMS Tool SQLite schema + UI labels +
# live probing of a single pack. See ../NOTES.md "Register map" section.
# High-confidence fields promoted to named entities; unknowns (reg 32, 35,
# 38-40, 43-45) still emitted as register_NN for correlation.
_WARNING_BITS = [
"pack_ov", "cell_ov", "pack_uv", "cell_uv",
"charge_oc", "discharge_oc", "temp_anomaly", "mos_ot",
"charge_ot", "discharge_ot", "charge_ut", "discharge_ut",
"low_capacity", "other_error",
]
_PROTECTION_BITS = [
"pack_ov", "cell_ov", "pack_uv", "cell_uv",
"charge_oc", "discharge_oc", "temp_anomaly", "mos_ot",
"charge_ot", "discharge_ot", "charge_ut", "discharge_ut",
"float_stopped", "discharge_sc",
]
def _signed16(v: int) -> int:
return v - 0x10000 if v & 0x8000 else v
def decode_eg4_modbus_regs(regs: list[int]) -> dict[str, Any]:
"""Decode the 47-reg read-holding-regs response from an LP4V2 BMS.
Emits named HA entities where meaning is known; raw register_NN
passthrough for the rest."""
out: dict[str, Any] = {}
# always emit raw registers — invaluable for future refinement
for i, v in enumerate(regs):
out[f"register_{i:02d}"] = v
if len(regs) < 47:
return out
# --- pack-level V / I (regs 0, 1) ---
out["pack_voltage"] = round(regs[0] / 100.0, 2)
out["pack_current"] = round(_signed16(regs[1]) / 100.0, 2)
# --- 16 cell voltages (regs 2-17), mV ---
cells_v = [regs[2 + i] / 1000.0 for i in range(16)]
for i, cv in enumerate(cells_v, start=1):
out[f"cell_{i:02d}_voltage"] = round(cv, 3)
vmin, vmax = min(cells_v), max(cells_v)
out["cell_voltage_min"] = round(vmin, 3)
out["cell_voltage_max"] = round(vmax, 3)
out["cell_voltage_delta_mv"] = round((vmax - vmin) * 1000)
out["cell_lowest"] = cells_v.index(vmin) + 1
out["cell_highest"] = cells_v.index(vmax) + 1
# --- temperatures (regs 18-21 = Temp_01..04, reg 24 = Temp_PCB) ---
out["temperature_01"] = regs[18]
out["temperature_02"] = regs[19]
out["temperature_03"] = regs[20]
out["temperature_04"] = regs[21]
out["temperature_pcb"] = regs[24]
# --- SoC / SoH (regs 22, 23) ---
out["soc"] = regs[22]
out["soh"] = regs[23]
# --- heater / status (regs 25-30) ---
# reg 30 has been observed = 1 on a healthy pack; treat as binary
out["heater"] = "on" if regs[30] & 0x01 else "off"
# --- max charge/discharge current limit (reg 31), A ---
out["max_current_limit"] = round(regs[31] / 100.0, 2)
# --- bitfields: warnings (reg 33), protections (reg 34), error code (reg 35) ---
warn = regs[33]
for i, name in enumerate(_WARNING_BITS):
out[f"warning_{name}"] = "on" if (warn >> i) & 1 else "off"
prot = regs[34]
for i, name in enumerate(_PROTECTION_BITS):
out[f"protection_{name}"] = "on" if (prot >> i) & 1 else "off"
out["error_code"] = regs[35]
# --- static-ish (regs 36, 37) ---
out["cell_count"] = regs[36]
out["capacity_ah"] = round(regs[37] / 10.0, 1)
out["remaining_ah"] = round(regs[38] / 100.0, 2)
out["cycle_count"] = regs[39]
out["battery_mode"] = regs[40]
# BMS firmware version — regs 41 & 42 appear to hold version codes; emit
# the raw u16s alongside a decimal representation for easier HA display
out["bms_version_hi"] = regs[41]
out["bms_version_lo"] = regs[42]
# reg 46 increments ~1.25 Hz on live bus — likely uptime in deciseconds
out["uptime_ds"] = regs[46]
return out
class ModbusActivePoller:
"""One instance per pack. Opens its own serial port, issues a single
read-holding-regs fn=0x03 on every `poll()` call, returns raw registers
(or raises). Graceful: a pack whose port doesn't exist or whose BMS is
off will raise on poll, and main loop catches + rate-limits the noise."""
READ_START = 0x0000
READ_COUNT = 47
def __init__(self, port: str, baud: int, address: int, timeout_s: float = 1.0):
self._port_path = port
self._baud = baud
self._address = address
self._timeout_s = timeout_s
self._ser: serial.Serial | None = None
def _open(self) -> None:
if self._ser is None or not self._ser.is_open:
self._ser = serial.Serial(
port=self._port_path, baudrate=self._baud, timeout=0.2,
bytesize=8, parity="N", stopbits=1,
)
def poll(self) -> list[int]:
self._open()
body = bytes([self._address, 0x03,
self.READ_START >> 8, self.READ_START & 0xFF,
self.READ_COUNT >> 8, self.READ_COUNT & 0xFF])
crc = crc16_modbus(body)
frame = body + bytes([crc & 0xFF, crc >> 8])
assert self._ser is not None
self._ser.reset_input_buffer()
self._ser.write(frame)
expected = 3 + self.READ_COUNT * 2 + 2 # addr + func + bc + data + crc
buf = bytearray()
deadline = time.monotonic() + self._timeout_s
while time.monotonic() < deadline and len(buf) < expected:
chunk = self._ser.read(expected - len(buf))
if chunk:
buf.extend(chunk)
raw = bytes(buf)
log.debug("pack 0x%02x tx=%s rx=%s", self._address, frame.hex(" "), raw.hex(" "))
if len(raw) < 5 or raw[0] != self._address or raw[1] != 0x03:
raise RuntimeError(f"no/bad response ({len(raw)} B)")
bc = raw[2]
if len(raw) < 3 + bc + 2:
raise RuntimeError(f"truncated response ({len(raw)} B, expected {3 + bc + 2})")
if not _crc_ok(raw, 0, 3 + bc + 2):
raise RuntimeError("CRC mismatch")
data = raw[3:3 + bc]
return [(data[i] << 8) | data[i + 1] for i in range(0, len(data), 2)]
def close(self) -> None:
if self._ser is not None and self._ser.is_open:
self._ser.close()
# =============================================================================
# === transports ==============================================================
# =============================================================================
# Two abstractions; main loop picks the right one based on bus.mode.
class ActiveTransport:
"""Request-response transport for active mode."""
def query_general(self, address: int) -> bytes:
raise NotImplementedError
def close(self) -> None:
pass
class PassiveListener:
"""Continuous frame-iterator for passive mode."""
def frames(self) -> Iterator[ModbusFrame]:
raise NotImplementedError
def close(self) -> None:
pass
# --- active: serial + mock --------------------------------------------------
class SerialActiveTransport(ActiveTransport):
def __init__(self, port: str, baud: int, timeout_s: float):
self._timeout_s = timeout_s
self._ser = serial.Serial(port=port, baudrate=baud, timeout=0.25,
bytesize=8, parity="N", stopbits=1)
def query_general(self, address: int) -> bytes:
frame = encode_eg4_request(address, CMD_GENERAL_STATUS)
log.debug("TX addr=0x%02x: %s", address, frame.hex())
self._ser.reset_input_buffer()
self._ser.write(frame)
buf = bytearray()
deadline = time.monotonic() + self._timeout_s
while time.monotonic() < deadline:
chunk = self._ser.read(256)
if chunk:
buf.extend(chunk)
if buf[0:1] == b"\x7E" and buf.endswith(b"\x0D"):
break
log.debug("RX addr=0x%02x: %s", address, bytes(buf).hex())
return bytes(buf)
def close(self) -> None:
self._ser.close()
class MockActiveTransport(ActiveTransport):
"""Synthesise EG4 7E/0D replies. Values drift per call so HA dashboards
look alive in dry-run mode."""
def __init__(self, cell_count: int = 16):
self._cell_count = cell_count
self._call = 0
def query_general(self, address: int) -> bytes:
self._call += 1
rng = random.Random(address * 1000 + self._call)
base_mv = 3280 + rng.randint(-5, 5)
cells_mv = [max(0, min(0x7FFF, base_mv + rng.randint(-8, 8)))
for _ in range(self._cell_count)]
current_x100 = rng.randint(-500, 2000)
current_raw = 30000 - current_x100
soc_x100 = (50 + rng.randint(-2, 2)) * 100
cap_ah_x100 = 5000 + rng.randint(-10, 10)
temps_raw = [50 + 25 + rng.randint(-3, 3) for _ in range(4)]
cycles = 42 + address
pack_v_x100 = round(sum(cells_mv) / 10)
def grp(gid: int, values: list[int]) -> bytes:
return bytes([gid, len(values)]) + b"".join(
struct.pack(">H", v & 0xFFFF) for v in values
)
body = b"".join([
grp(0x01, cells_mv),
grp(0x02, [current_raw]),
grp(0x03, [soc_x100]),
grp(0x04, [cap_ah_x100]),
grp(0x05, temps_raw),
grp(0x06, [0, 0]), # alarms = clear
grp(0x07, [cycles]),
grp(0x08, [pack_v_x100]),
grp(0x09, []),
grp(0x0A, []),
])
# checksum byte tolerated as 0x00 by the upstream parser
return bytes([0x7E, address, CMD_GENERAL_STATUS, len(body) & 0xFF]) \
+ body + bytes([0x00, 0x0D])
# --- passive: serial + mock -------------------------------------------------
class SerialPassiveListener(PassiveListener):
_BUF_MAX = 4096
def __init__(self, port: str, baud: int, read_chunk: int = 512):
self._read_chunk = read_chunk
self._ser = serial.Serial(port=port, baudrate=baud, timeout=0.1,
bytesize=8, parity="N", stopbits=1)
self._buf = bytearray()
def frames(self) -> Iterator[ModbusFrame]:
while True:
chunk = self._ser.read(self._read_chunk)
if chunk:
self._buf.extend(chunk)
if len(self._buf) > self._BUF_MAX:
del self._buf[:self._BUF_MAX // 2]
yield from self._extract()
def _extract(self) -> Iterator[ModbusFrame]:
i = 0
while i < len(self._buf) - 4:
r = parse_modbus_frame_at(self._buf, i)
if r is None:
i += 1
continue
length, kind = r
raw = bytes(self._buf[i:i + length])
yield ModbusFrame(address=raw[0], function=raw[1], kind=kind, raw=raw)
del self._buf[:i + length]
i = 0
def close(self) -> None:
self._ser.close()
class MockPassiveListener(PassiveListener):
def __init__(self, packs: list[PackConfig], gap_s: float = 0.5):
self._packs = packs
self._gap_s = gap_s
self._tick = 0
def frames(self) -> Iterator[ModbusFrame]:
while True:
for pack in self._packs:
self._tick += 1
q = self._build_query(pack.address)
yield ModbusFrame(address=pack.address, function=0x03, kind="query", raw=q)
time.sleep(0.05)
r = self._build_response(pack.address)
yield ModbusFrame(address=pack.address, function=0x03, kind="response", raw=r)
time.sleep(self._gap_s)
def _build_query(self, addr: int) -> bytes:
body = bytes([addr, 0x03, 0x00, 0x00, 0x00, 0x2F])
crc = crc16_modbus(body)
return body + bytes([crc & 0xFF, crc >> 8])
def _build_response(self, addr: int) -> bytes:
rng = random.Random(addr * 1000 + self._tick)
regs = [3280 + rng.randint(-5, 5) for _ in range(16)]
regs += [round(52.48 * 100), 50_00, rng.randint(0, 100)]
while len(regs) < 47:
regs.append(rng.randint(0, 100))
body = bytes([addr, 0x03, len(regs) * 2]) + b"".join(
struct.pack(">H", r & 0xFFFF) for r in regs
)
crc = crc16_modbus(body)
return body + bytes([crc & 0xFF, crc >> 8])
# =============================================================================
# === MQTT publisher (HA auto-discovery) ======================================
# =============================================================================
# Field metadata. Active and passive modes emit different keys; both sets
# coexist here without overlap.
_FIELD_META: dict[str, tuple[str | None, str | None, str | None, str | None]] = {
# active mode (EG4 7E/0D decoded)
"pack_voltage": ("V", "voltage", "measurement", "mdi:battery-outline"),
"current": ("A", "current", "measurement", "mdi:current-dc"),
"soc": ("%", "battery", "measurement", "mdi:battery-70"),
"capacity_ah": ("Ah", None, "measurement", "mdi:battery-clock"),
"cycle_count": (None, None, "total", "mdi:counter"),
"cell_voltage_min": ("V", "voltage", "measurement", "mdi:arrow-down-bold"),
"cell_voltage_max": ("V", "voltage", "measurement", "mdi:arrow-up-bold"),
"cell_voltage_delta_mv": ("mV", None, "measurement", "mdi:sine-wave"),
"cell_lowest": (None, None, "measurement", "mdi:numeric"),
"cell_highest": (None, None, "measurement", "mdi:numeric"),
"alarm_current_over": (None, None, None, "mdi:alert-octagon"),
"alarm_voltage_high": (None, None, None, "mdi:alert"),
"alarm_voltage_low": (None, None, None, "mdi:alert"),
"alarm_temp_high_chg": (None, None, None, "mdi:thermometer-alert"),
"alarm_temp_low_chg": (None, None, None, "mdi:thermometer-alert"),
}
for _i in range(1, 33):
_FIELD_META[f"cell_{_i:02d}_voltage"] = ("V", "voltage", "measurement", "mdi:battery-outline")
for _i in range(1, 7):
_FIELD_META[f"temperature_{_i}"] = ("°C", "temperature", "measurement", "mdi:thermometer")
# modbus_per_pack named fields (EG4 register map)
_FIELD_META.update({
"pack_current": ("A", "current", "measurement", "mdi:current-dc"),
"temperature_01": ("°C", "temperature", "measurement", "mdi:thermometer"),
"temperature_02": ("°C", "temperature", "measurement", "mdi:thermometer"),
"temperature_03": ("°C", "temperature", "measurement", "mdi:thermometer"),
"temperature_04": ("°C", "temperature", "measurement", "mdi:thermometer"),
"temperature_pcb": ("°C", "temperature", "measurement", "mdi:chip"),
"heater": (None, None, None, "mdi:heating-coil"),
"max_current_limit": ("A", "current", "measurement", "mdi:current-dc"),
"error_code": (None, None, None, "mdi:alert-octagon"),
"cell_count": (None, None, "measurement", "mdi:numeric"),
"remaining_ah": ("Ah", None, "measurement", "mdi:battery-clock"),
"battery_mode": (None, None, None, "mdi:state-machine"),
"bms_version_hi": (None, None, None, "mdi:chip"),
"bms_version_lo": (None, None, None, "mdi:chip"),
"uptime_ds": (None, None, "total_increasing", "mdi:timer-outline"),
})
for _name in _WARNING_BITS:
_FIELD_META[f"warning_{_name}"] = (None, None, None, "mdi:alert")
for _name in _PROTECTION_BITS:
_FIELD_META[f"protection_{_name}"] = (None, None, None, "mdi:shield-alert")
def field_meta(key: str) -> tuple[str | None, str | None, str | None, str | None]:
if key.startswith("register_"):
return (None, None, "measurement", "mdi:numeric")
return _FIELD_META.get(key, (None, None, None, None))
class MQTTPublisher:
def __init__(self, cfg: MQTTConfig, dry_run: bool = False):
self._cfg = cfg
self._dry_run = dry_run
self._client: mqtt.Client | None = None
self._discovered: set[tuple[str, str]] = set()
if not dry_run:
c = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="eg4-battery")
c.username_pw_set(cfg.username, cfg.password)
c.connect(cfg.host, cfg.port, keepalive=60)
c.loop_start()
self._client = c
log.info("connected to MQTT %s:%d", cfg.host, cfg.port)
def publish_pack(self, pack_name: str, readings: dict[str, Any]) -> None:
for key, value in readings.items():
self._publish_one(pack_name, key, value)
def _publish_one(self, pack_name: str, key: str, value: Any) -> None:
entity_id = f"{pack_name}_{key}"
state_topic = f"{self._cfg.discovery_prefix}/sensor/{entity_id}/state"
disco_key = (pack_name, key)
if disco_key not in self._discovered:
self._publish_discovery(pack_name, key, state_topic)
self._discovered.add(disco_key)
payload = json.dumps(value) if isinstance(value, (dict, list)) else str(value)
if self._dry_run:
print(f" {state_topic} {payload}")
else:
self._client.publish(state_topic, payload, qos=0, retain=False)
def _publish_discovery(self, pack_name: str, key: str, state_topic: str) -> None:
unit, device_class, state_class, icon = field_meta(key)
cfg = {
"name": f"{pack_name} {key}",
"state_topic": state_topic,
"unique_id": f"{pack_name}_{key}_eg4",
"device": {
"name": f"EG4 LifePower4 {pack_name}",
"identifiers": [pack_name],
"model": "LifePower4 48V 100Ah v2 Auto-Addressing",
"manufacturer": "EG4 Electronics",
},
}
if unit is not None: cfg["unit_of_measurement"] = unit
if device_class is not None: cfg["device_class"] = device_class
if state_class is not None: cfg["state_class"] = state_class
if icon is not None: cfg["icon"] = icon
topic = f"{self._cfg.discovery_prefix}/sensor/{pack_name}_{key}/config"
payload = json.dumps(cfg)
if self._dry_run:
print(f" [discovery] {topic} {payload}")
else:
self._client.publish(topic, payload, qos=0, retain=True)
def close(self) -> None:
if self._client is not None:
self._client.loop_stop()
self._client.disconnect()
# =============================================================================
# === per-pack state & rate-limited logging ===================================
# =============================================================================
@dataclasses.dataclass
class _PackState:
ok: bool = False
last_error_category: str = ""
consecutive_errors: int = 0
response_count: int = 0
first_seen_logged: bool = False
_FAIL_HEARTBEAT_CYCLES = 360 # re-log a stuck failure every ~hour at 10 s cadence
def _resolve_pack_name(addr: int, packs: list[PackConfig]) -> str:
for p in packs:
if p.address == addr:
return p.name
return f"lifepower4_addr_{addr:02x}"
# =============================================================================
# === main loops ==============================================================
# =============================================================================
def run_active(transport: ActiveTransport, publisher: MQTTPublisher, cfg: AppConfig,
states: dict[str, _PackState], one_cycle: bool = False) -> None:
"""Round-robin poll every configured pack; rate-limit error noise."""
while True:
cycle_start = time.monotonic()
for pack in cfg.packs:
st = states.setdefault(pack.name, _PackState())
try:
raw = transport.query_general(pack.address)
if not raw:
raise RuntimeError(f"empty response from addr=0x{pack.address:02x}")
readings = decode_eg4_general_status(raw, cell_count=cfg.cell_count)
publisher.publish_pack(pack.name, readings)
st.response_count += 1
if not st.ok and st.consecutive_errors > 0:
log.info("pack %s (0x%02x): recovered after %d failed cycle(s)",
pack.name, pack.address, st.consecutive_errors)
st.ok = True
st.consecutive_errors = 0
except Exception as e:
category = f"{type(e).__name__}:{str(e).split(':', 1)[0]}"
if st.ok or category != st.last_error_category:
log.warning("pack %s (0x%02x): %s", pack.name, pack.address, e)
elif st.consecutive_errors > 0 and st.consecutive_errors % _FAIL_HEARTBEAT_CYCLES == 0:
log.warning("pack %s (0x%02x): still failing (%d cycles): %s",
pack.name, pack.address, st.consecutive_errors, e)
st.ok = False
st.last_error_category = category
st.consecutive_errors += 1
if one_cycle:
return
elapsed = time.monotonic() - cycle_start
time.sleep(max(0.0, cfg.bus.poll_interval_s - elapsed))
def run_passive(listener: PassiveListener, publisher: MQTTPublisher, cfg: AppConfig,
trace: bool, max_frames: int | None = None) -> None:
"""Consume frames as they arrive; publish on every fn=0x03 response."""
states: dict[int, _PackState] = {}
seen_unconfigured: set[int] = set()
configured = {p.address for p in cfg.packs}
n = 0
for frame in listener.frames():
n += 1
if trace:
log.debug("%r raw=%s", frame, frame.raw.hex(" "))
if frame.kind != "response" or frame.function != 0x03:
if max_frames is not None and n >= max_frames:
return
continue
st = states.setdefault(frame.address, _PackState())
st.response_count += 1
if not st.first_seen_logged:
if frame.address in configured:
log.info("first response from configured pack 0x%02x (%s)",
frame.address, _resolve_pack_name(frame.address, cfg.packs))
elif frame.address not in seen_unconfigured:
log.warning("response from unconfigured slave 0x%02x — auto-naming as %s",
frame.address, _resolve_pack_name(frame.address, cfg.packs))
seen_unconfigured.add(frame.address)
st.first_seen_logged = True
try:
readings = decode_modbus_response(frame)
except Exception as e:
log.warning("decode failed for addr 0x%02x: %s (raw=%s)",
frame.address, e, frame.raw.hex(" "))
continue
publisher.publish_pack(_resolve_pack_name(frame.address, cfg.packs), readings)
if max_frames is not None and n >= max_frames:
return
def run_modbus_per_pack(cfg: AppConfig, publisher: MQTTPublisher,
states: dict[str, _PackState], one_cycle: bool = False,
dry_run: bool = False) -> None:
"""One adapter per pack. Each `PackConfig` must have `port` and `baud`
set. Round-robin poll every pack on its own serial port; decode
Modbus response into named HA entities + raw register_NN dump."""
pollers: dict[str, ModbusActivePoller] = {}
mock_regs_call: dict[str, int] = {}
def make_poller(p: PackConfig) -> ModbusActivePoller | None:
if dry_run:
return None # mock path, no real poller
if not p.port:
log.warning("pack %s: no `port` set in config; skipping", p.name)
return None
baud = p.baud or cfg.bus.baud
try:
return ModbusActivePoller(p.port, baud, p.address, cfg.bus.timeout_s)
except Exception as e:
log.warning("pack %s: could not open %s: %s", p.name, p.port, e)
return None
for p in cfg.packs:
pl = make_poller(p)
if pl is not None:
pollers[p.name] = pl
try:
while True:
cycle_start = time.monotonic()
for p in cfg.packs:
st = states.setdefault(p.name, _PackState())
try:
if dry_run:
mock_regs_call[p.name] = mock_regs_call.get(p.name, 0) + 1
regs = _mock_modbus_regs(p.address, mock_regs_call[p.name])
else:
if p.name not in pollers:
raise RuntimeError(f"no poller configured for {p.name}")
regs = pollers[p.name].poll()
readings = decode_eg4_modbus_regs(regs)
publisher.publish_pack(p.name, readings)
st.response_count += 1
if not st.ok and st.consecutive_errors > 0:
log.info("pack %s: recovered after %d failed cycle(s)",
p.name, st.consecutive_errors)
st.ok = True
st.consecutive_errors = 0
except Exception as e:
category = f"{type(e).__name__}:{str(e).split(':', 1)[0]}"
if st.ok or category != st.last_error_category:
log.warning("pack %s (0x%02x): %s", p.name, p.address, e)
elif st.consecutive_errors > 0 \
and st.consecutive_errors % _FAIL_HEARTBEAT_CYCLES == 0:
log.warning("pack %s (0x%02x): still failing (%d cycles): %s",
p.name, p.address, st.consecutive_errors, e)
st.ok = False
st.last_error_category = category
st.consecutive_errors += 1
if one_cycle:
return
elapsed = time.monotonic() - cycle_start
time.sleep(max(0.0, cfg.bus.poll_interval_s - elapsed))
finally:
for pl in pollers.values():
pl.close()
def _mock_modbus_regs(address: int, tick: int) -> list[int]:
"""Synthesise 47 realistic-looking registers for dry-run mode."""
rng = random.Random(address * 1000 + tick)
base_mv = 3280 + rng.randint(-3, 3)
cells_mv = [base_mv + rng.randint(-8, 8) for _ in range(16)]
regs: list[int] = [0] * 47
regs[0] = sum(cells_mv) // 10 # pack voltage × 100
regs[1] = (30000 - rng.randint(-500, 2000)) & 0xFFFF # current (×100 biased)
for i, mv in enumerate(cells_mv, start=2):
regs[i] = mv
regs[18] = 21 + rng.randint(-1, 1)
regs[19] = 21 + rng.randint(-1, 1)
regs[20] = 20 + rng.randint(-1, 1)
regs[21] = 54 + rng.randint(-1, 1)
regs[22] = 100
regs[23] = 100
regs[24] = 55
regs[30] = 1
regs[31] = 5493
regs[32] = 10752
regs[33] = 0 # no warnings
regs[34] = 0 # no protections
regs[35] = 0 # error code
regs[36] = 16 # cell count
regs[37] = 1000 # 100.0 Ah
regs[46] = (tick * 5) & 0xFFFF # runtime counter
return regs
def main() -> int:
ap = argparse.ArgumentParser(
description="EG4 LifePower4 v2 → MQTT bridge.")
ap.add_argument("-C", "--config", required=True, type=Path)
ap.add_argument("--dry-run", action="store_true",
help="Mock-bus smoke test — one cycle, print, exit.")
ap.add_argument("--trace", action="store_true", help="Log every frame.")
args = ap.parse_args()
logging.basicConfig(
level=logging.DEBUG if args.trace else logging.INFO,
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
)
cfg = load_config(args.config)
valid_modes = {"modbus_per_pack", "active", "passive"}
if cfg.bus.mode not in valid_modes:
raise SystemExit(f"bus.mode must be one of {valid_modes}, got {cfg.bus.mode!r}")
if cfg.bus.transport not in {"serial", "mock"}:
raise SystemExit(f"bus.transport must be 'serial' or 'mock', got {cfg.bus.transport!r}")
publisher = MQTTPublisher(cfg.mqtt, dry_run=args.dry_run)
log.info("eg4-battery starting: mode=%s %d configured pack(s)",
cfg.bus.mode, len(cfg.packs))
use_mock = args.dry_run or cfg.bus.transport == "mock"
try:
if cfg.bus.mode == "modbus_per_pack":
run_modbus_per_pack(cfg, publisher, states={},
one_cycle=args.dry_run, dry_run=args.dry_run)
elif cfg.bus.mode == "active":
transport: ActiveTransport
transport = (MockActiveTransport(cell_count=cfg.cell_count) if use_mock
else SerialActiveTransport(cfg.bus.port, cfg.bus.baud, cfg.bus.timeout_s))
try:
run_active(transport, publisher, cfg, states={}, one_cycle=args.dry_run)
finally:
transport.close()
else: # passive
listener: PassiveListener
listener = (MockPassiveListener(cfg.packs) if use_mock
else SerialPassiveListener(cfg.bus.port, cfg.bus.baud, cfg.bus.read_chunk))
try:
run_passive(listener, publisher, cfg, trace=args.trace,
max_frames=(2 * len(cfg.packs) if args.dry_run else None))
finally:
listener.close()
return 0
except KeyboardInterrupt:
return 0
finally:
publisher.close()
if __name__ == "__main__":
sys.exit(main())

View File

@@ -0,0 +1,48 @@
# eg4-battery config — deploys to ~/.config/eg4-battery/eg4-battery.yaml (mode 600)
bus:
# ---- mode: pick one ----
# active ← RECOMMENDED. We are the master on a dedicated bus to the
# battery's pin-1/2 external monitor port. Speaks the EG4
# 7E/0D protocol at 9600 baud. Returns named, decoded HA
# entities (pack V, cell voltages, SoC, temps, alarms).
#
# passive ← Listen-only Modbus-RTU sniffer at 19200 baud. Use only when
# the FTDI is on a bus that already has a Modbus master
# (e.g. the LVX6048 parallel-comm bus — although see NOTES.md:
# the LVX6048 doesn't poll EG4 packs that way, so this mode
# is mostly diagnostic). Publishes raw `register_NN` per slave.
mode: active
transport: serial # serial | mock (--dry-run on the CLI forces mock)
# Stable /dev/serial/by-id symlink survives USB reshuffles. Find yours with
# ls -l /dev/serial/by-id/
port: /dev/serial/by-id/usb-FTDI_<YOUR_ADAPTER_ID>-if00-port0
# Default 9600 (active EG4 protocol). Set 19200 for passive Modbus mode.
baud: 9600
# Active mode only:
timeout_s: 1.5 # per-query response wait
poll_interval_s: 10.0 # round-robin cycle target
mqtt:
host: <MQTT_BROKER_IP> # e.g. 10.0.0.41 (HA Mosquitto broker)
port: 1883
username: <MQTT_USER>
password: <MQTT_PASSWORD>
discovery_prefix: homeassistant
# One entry per pack. `name` is the HA entity prefix and device identifier.
# `address` is the EG4 7E protocol address in active mode (master = 1, slaves
# typically 2, 3, ...) or the Modbus slave ID in passive mode.
packs:
- name: lifepower4_1
address: 1
- name: lifepower4_2
address: 2
- name: lifepower4_3
address: 3
cell_count: 16 # 16S for 48V LFP — active mode only

View File

@@ -0,0 +1,19 @@
[Unit]
Description=EG4 LifePower4 RS485 -> MQTT bridge
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=noise
Group=dialout
# Systemd's default PATH does not include ~/.local/bin where `uv` is installed.
# The script's `#!/usr/bin/env -S uv run --script` shebang needs to find uv.
Environment=PATH=/home/noise/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# uv manages the ephemeral venv per the PEP-723 inline deps in the script
ExecStart=/usr/local/bin/eg4-battery -C /home/noise/.config/eg4-battery/eg4-battery.yaml
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,5 @@
# EG4 LifePower4 RS485 bus via USB-serial adapter.
# Grants dialout group access; /dev/serial/by-id/ symlink survives USB moves.
# Adjust idVendor/idProduct if you use a CP210x (0x10c4:0xea60) or CH340
# (0x1a86:0x7523) adapter instead of the reference FTDI FT232R.
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="0660", GROUP="dialout"

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

View 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

View 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

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

93
eg4battery/install.sh Executable file
View File

@@ -0,0 +1,93 @@
#!/usr/bin/env bash
# EG4 LifePower4 → Home Assistant monitoring — reproducible installer.
#
# Installs the eg4-battery daemon onto /usr/local/bin (uv handles deps via the
# script's PEP-723 inline metadata), drops in the udev rule + systemd unit,
# and seeds the config template. Idempotent: safe to re-run.
#
# Assumptions:
# - Debian-family Linux with systemd
# - `uv` on $PATH (https://docs.astral.sh/uv/)
# - User has sudo
#
# After install, finish by editing:
# ~/.config/eg4-battery/eg4-battery.yaml — bus.port, MQTT creds, pack addresses
# then:
# ./install.sh --dry-run — end-to-end smoke test (no HW needed)
# sudo systemctl enable --now eg4-battery.service
# journalctl -u eg4-battery.service -f
set -euo pipefail
BASE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DRY_RUN=0
for arg in "$@"; do
[ "$arg" = "--dry-run" ] && DRY_RUN=1
done
msg() { printf '\n\033[1;36m== %s ==\033[0m\n' "$*"; }
# --- 1. dependency check ---------------------------------------------------
msg "Checking prerequisites"
command -v uv >/dev/null || { echo "uv not found — install from https://docs.astral.sh/uv/"; exit 1; }
# --- 2. entry point --------------------------------------------------------
msg "Installing /usr/local/bin/eg4-battery"
sudo install -m 755 "${BASE}/bin/eg4-battery" /usr/local/bin/eg4-battery
# --- 3. udev rule ----------------------------------------------------------
msg "Installing udev rule (FTDI/CH340/CP210x → dialout)"
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
# --- 4. systemd unit -------------------------------------------------------
msg "Installing systemd unit"
sudo install -m 644 "${BASE}/etc/systemd/system/eg4-battery.service" /etc/systemd/system/eg4-battery.service
sudo systemctl daemon-reload
# --- 5. user config (only if not already present) --------------------------
msg "Installing config template"
mkdir -p "${HOME}/.config/eg4-battery"
dest="${HOME}/.config/eg4-battery/eg4-battery.yaml"
if [ -e "$dest" ]; then
echo " $dest already exists — not overwriting"
else
install -m 600 "${BASE}/config/eg4-battery.yaml.example" "$dest"
echo " wrote $dest (mode 600) — edit bus.port, MQTT creds, pack addresses"
fi
# --- 6. smoke test ---------------------------------------------------------
if [ "$DRY_RUN" = "1" ]; then
msg "Dry-run: running one mock-bus cycle (no MQTT publish)"
/usr/local/bin/eg4-battery -C "$dest" --dry-run
echo
echo "(above output is what would be published to MQTT under real run)"
fi
# --- 7. enable -------------------------------------------------------------
if grep -q '<MQTT_PASSWORD>' "$dest" 2>/dev/null; then
cat <<EOF
Credentials in $dest still contain a placeholder.
Edit the file, verify with: eg4-battery -C $dest --dry-run
Then enable the daemon:
sudo systemctl enable --now eg4-battery.service
journalctl -u eg4-battery.service -f
EOF
else
msg "Enabling eg4-battery.service"
sudo systemctl enable --now eg4-battery.service
sleep 3
systemctl --no-pager status eg4-battery.service | head -15
fi
msg "Done"
echo "Next steps:"
echo " - While batteries are still in the mail: ./install.sh --dry-run"
echo " - Once one pack is wired: edit ~/.config/eg4-battery/eg4-battery.yaml,"
echo " set bus.transport: serial + address: 1 only,"
echo " validate per ../NOTES.md"
echo " - Full three-pack bring-up: uncomment addresses 2 and 3"

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtCore</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtCore</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = corelib.pro
QMAKE_PRL_TARGET = QtCore
QMAKE_PRL_CONFIG = lex yacc exceptions depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs testcase_exceptions explicitlib testcase_no_bundle warning_clean exceptions qt_tracepoints moc resources simd optimize_full pcre2 generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle arch_haswell avx512common avx512core thread
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtCore</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtCore</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = corelib.pro
QMAKE_PRL_TARGET = QtCore
QMAKE_PRL_CONFIG = lex yacc exceptions depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs testcase_exceptions explicitlib testcase_no_bundle warning_clean exceptions qt_tracepoints moc resources simd optimize_full pcre2 generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle arch_haswell avx512common avx512core thread
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtCore</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtCore</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = corelib.pro
QMAKE_PRL_TARGET = QtCore
QMAKE_PRL_CONFIG = lex yacc exceptions depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs testcase_exceptions explicitlib testcase_no_bundle warning_clean exceptions qt_tracepoints moc resources simd optimize_full pcre2 generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle arch_haswell avx512common avx512core thread
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtDBus</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtDBus</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = dbus.pro
QMAKE_PRL_TARGET = QtDBus
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtDBus</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtDBus</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = dbus.pro
QMAKE_PRL_TARGET = QtDBus
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtDBus</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtDBus</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = dbus.pro
QMAKE_PRL_TARGET = QtDBus
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtGui</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtGui</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = gui.pro
QMAKE_PRL_TARGET = QtGui
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean simd optimize_full opengl generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc qt_tracepoints have_target dll debug_info objective_c any_bundle arch_haswell avx512common avx512core thread moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -framework AppKit -framework Metal -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-framework;AppKit;-framework;Metal;-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtGui</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtGui</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = gui.pro
QMAKE_PRL_TARGET = QtGui
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean simd optimize_full opengl generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc qt_tracepoints have_target dll debug_info objective_c any_bundle arch_haswell avx512common avx512core thread moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -framework AppKit -framework Metal -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-framework;AppKit;-framework;Metal;-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtGui</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtGui</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = gui.pro
QMAKE_PRL_TARGET = QtGui
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean simd optimize_full opengl generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc qt_tracepoints have_target dll debug_info objective_c any_bundle arch_haswell avx512common avx512core thread moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -framework AppKit -framework Metal -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-framework;AppKit;-framework;Metal;-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtNetwork</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtNetwork</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = network.pro
QMAKE_PRL_TARGET = QtNetwork
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtNetwork</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtNetwork</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = network.pro
QMAKE_PRL_TARGET = QtNetwork
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtNetwork</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtNetwork</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = network.pro
QMAKE_PRL_TARGET = QtNetwork
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtPrintSupport</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtPrintSupport</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = printsupport.pro
QMAKE_PRL_TARGET = QtPrintSupport
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread uic opengl moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -framework QtWidgets -framework QtGui -framework AppKit -framework Metal -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-framework;QtWidgets;-framework;QtGui;-framework;AppKit;-framework;Metal;-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtPrintSupport</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtPrintSupport</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = printsupport.pro
QMAKE_PRL_TARGET = QtPrintSupport
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread uic opengl moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -framework QtWidgets -framework QtGui -framework AppKit -framework Metal -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-framework;QtWidgets;-framework;QtGui;-framework;AppKit;-framework;Metal;-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtPrintSupport</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtPrintSupport</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = printsupport.pro
QMAKE_PRL_TARGET = QtPrintSupport
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread uic opengl moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -framework QtWidgets -framework QtGui -framework AppKit -framework Metal -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-framework;QtWidgets;-framework;QtGui;-framework;AppKit;-framework;Metal;-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtQml</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtQml</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = qml.pro
QMAKE_PRL_TARGET = QtQml
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean python_available qt_tracepoints qlalr generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -framework QtNetwork -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-framework;QtNetwork;-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtQml</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtQml</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = qml.pro
QMAKE_PRL_TARGET = QtQml
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean python_available qt_tracepoints qlalr generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -framework QtNetwork -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-framework;QtNetwork;-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtQml</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtQml</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = qml.pro
QMAKE_PRL_TARGET = QtQml
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean python_available qt_tracepoints qlalr generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -framework QtNetwork -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-framework;QtNetwork;-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtQmlModels</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtQmlModels</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = qmlmodels.pro
QMAKE_PRL_TARGET = QtQmlModels
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean python_available generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -F$$[QT_INSTALL_LIBS] -framework QtQml -framework QtNetwork -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-F$$[QT_INSTALL_LIBS];-framework;QtQml;-framework;QtNetwork;-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtQmlModels</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtQmlModels</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = qmlmodels.pro
QMAKE_PRL_TARGET = QtQmlModels
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean python_available generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -F$$[QT_INSTALL_LIBS] -framework QtQml -framework QtNetwork -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-F$$[QT_INSTALL_LIBS];-framework;QtQml;-framework;QtNetwork;-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtQmlModels</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtQmlModels</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = qmlmodels.pro
QMAKE_PRL_TARGET = QtQmlModels
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean python_available generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -F$$[QT_INSTALL_LIBS] -framework QtQml -framework QtNetwork -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-F$$[QT_INSTALL_LIBS];-framework;QtQml;-framework;QtNetwork;-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtQuick</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtQuick</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = quick.pro
QMAKE_PRL_TARGET = QtQuick
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean python_available generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread opengl moc resources moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -F$$[QT_INSTALL_LIBS] -framework QtQmlModels -framework QtQml -framework QtGui -framework AppKit -framework Metal -framework QtNetwork -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-F$$[QT_INSTALL_LIBS];-framework;QtQmlModels;-framework;QtQml;-framework;QtGui;-framework;AppKit;-framework;Metal;-framework;QtNetwork;-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtQuick</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtQuick</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = quick.pro
QMAKE_PRL_TARGET = QtQuick
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean python_available generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread opengl moc resources moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -F$$[QT_INSTALL_LIBS] -framework QtQmlModels -framework QtQml -framework QtGui -framework AppKit -framework Metal -framework QtNetwork -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-F$$[QT_INSTALL_LIBS];-framework;QtQmlModels;-framework;QtQml;-framework;QtGui;-framework;AppKit;-framework;Metal;-framework;QtNetwork;-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtQuick</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtQuick</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = quick.pro
QMAKE_PRL_TARGET = QtQuick
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean python_available generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread opengl moc resources moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -F$$[QT_INSTALL_LIBS] -framework QtQmlModels -framework QtQml -framework QtGui -framework AppKit -framework Metal -framework QtNetwork -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-F$$[QT_INSTALL_LIBS];-framework;QtQmlModels;-framework;QtQml;-framework;QtGui;-framework;AppKit;-framework;Metal;-framework;QtNetwork;-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtSerialPort</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtSerialPort</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = serialport.pro
QMAKE_PRL_TARGET = QtSerialPort
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle done_config_ntddmodm generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtSerialPort</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtSerialPort</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = serialport.pro
QMAKE_PRL_TARGET = QtSerialPort
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle done_config_ntddmodm generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtSerialPort</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtSerialPort</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = serialport.pro
QMAKE_PRL_TARGET = QtSerialPort
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle done_config_ntddmodm generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtSql</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtSql</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = sql.pro
QMAKE_PRL_TARGET = QtSql
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>QtSql</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.QtSql</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.14</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.14.2</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
QMAKE_PRO_INPUT = sql.pro
QMAKE_PRL_TARGET = QtSql
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin asset_catalogs rez prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl app_bundle incremental global_init_link_order lib_version_first sdk clang_pch_style shared shared qt_framework release macos osx macx mac darwin unix posix gcc clang llvm sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent no_warn_empty_obj_files utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions explicitlib testcase_no_bundle warning_clean generated_privates module_frameworks lib_bundle relative_qt_rpath app_extension_api_only git_build target_qt c++11 strict_c++ c++14 c99 c11 hide_symbols separate_debug_info need_fwd_pri qt_install_module create_cmake sliced_bundle compiler_supports_fpmath create_pc have_target dll debug_info objective_c any_bundle thread moc resources
QMAKE_PRL_VERSION = 5.14.2
QMAKE_PRL_LIBS = -F$$[QT_INSTALL_LIBS] -framework QtCore -framework DiskArbitration -framework IOKit
QMAKE_PRL_LIBS_FOR_CMAKE = -F$$[QT_INSTALL_LIBS];-framework;QtCore;-framework;DiskArbitration;-framework;IOKit;

Some files were not shown because too many files have changed in this diff Show More