Replace Poetry with uv

Use standard project metadata, dependency groups, and the uv build backend. The new lock preserves the previous dependency versions. Documentation and services use uv, and services leave their shared environment unchanged at startup.

Remove the entry point for the empty USB HID prototype. Exclude local prototypes, captures, and the external Type 7 lookup table from version control and distributions.
This commit is contained in:
tim
2026-10-08 14:03:09 +02:00
parent 79f9ebf0c7
commit bac953bf48
9 changed files with 849 additions and 1103 deletions
+121 -54
View File
@@ -1,75 +1,63 @@
# bmspy
bmspy is a tool to get information from a [xiaoxiang-type](https://www.lithiumbatterypcb.com/product/4s-or-3s-12v-li-ion-or-lifepo4-battery-smart-bms-with-bluetooth-function-uart-and-rs485-communication-with-60a-to-120a-constant-current/?attribute_specification-selection=4S+Lifepo4+120A+with+UART+and+RS485) BMS system, using some sort of serial connection.
bmspy is a tool to get information from battery management systems and UPS devices. It supports:
- [Xiaoxiang-type](https://www.lithiumbatterypcb.com/product/4s-or-3s-12v-li-ion-or-lifepo4-battery-smart-bms-with-bluetooth-function-uart-and-rs485-communication-with-60a-to-120a-constant-current/?attribute_specification-selection=4S+Lifepo4+120A+with+UART+and+RS485) BMS devices via serial (USB)
- EcoFlow power stations via Bluetooth LE
It can display the information as text, in JSON, or export the data continuously to InfluxDB or a Prometheus exporter.
Multiple BMS/UPS devices can be connected at once. Each is identified by a name, and data from all of them (or just one) can be pushed to InfluxDB or Prometheus in the same connection, with each measurement tagged with the UPS name.
Multiple devices can be connected at once. Each is identified by a name, and data from all of them (or just one) can be pushed to InfluxDB or Prometheus in the same connection, with each measurement tagged with the device name.
To install:
git clone https://git.treehouse.org.za/tim/bmspy
cd bmspy
poetry install
Install [uv](https://docs.astral.sh/uv/getting-started/installation/) and use Python 3.12 or later, below Python 4.
Then create the local environment:
Or, to install with influxdb and/or prometheus support:
poetry install -E influxdb -E prometheus
```bash
git clone https://git.treehouse.org.za/tim/bmspy
cd bmspy
uv sync --locked
```
To install with EcoFlow Bluetooth LE support:
```bash
uv sync --locked --extra ecoflow-bt
```
To install with InfluxDB and Prometheus support:
```bash
uv sync --locked --extra influxdb --extra prometheus
```
These optional dependency sets are called extras. Select the required extras
with each `uv run` command, or use `--all-extras` to enable all of them.
`uv sync` also installs development dependencies by default. Use `--no-dev`
for a deployment that does not need the test tools.
## Running the server
The server daemon reads from one or more serial devices and makes the data available over a Unix socket.
The server daemon reads from one or more devices and makes the data available over a Unix socket.
Single device (defaults to `/dev/ttyUSB0`):
Single JBD BMS device (defaults to `/dev/ttyUSB0`):
poetry run bmspy-server
uv run bmspy-server
Multiple devices, with optional names (default name is derived from the device path, e.g. `ttyUSB0`):
Multiple JBD BMS devices, with optional names (default name is derived from the device path, e.g. `ttyUSB0`):
poetry run bmspy-server -d network:/dev/ttyUSB0 -d nas:/dev/ttyUSB1
uv run bmspy-server -d network:/dev/ttyUSB0 -d nas:/dev/ttyUSB1
To run via systemd, copy `bmspy-server.service` to `/etc/systemd/system`, adjust `WorkingDirectory` and the `ExecStart` line as needed, then enable and start it:
### EcoFlow Bluetooth LE devices
cp bmspy-server.service /etc/systemd/system
$EDITOR /etc/systemd/system/bmspy-server.service
systemctl daemon-reload
systemctl enable bmspy-server
systemctl start bmspy-server
Install the `ecoflow-bt` extra as shown above. Close the EcoFlow app and stop other
Bluetooth collectors before connecting to a device.
## Running a client
To print a summary of all connected UPSes:
poetry run bmspy
To show only a specific UPS:
poetry run bmspy --ups network
To push data for all UPSes to InfluxDB (each measurement is tagged `ups=<name>`):
poetry run bmspy-influxdb --url https://influx.example.com --org myorg --token mytoken
To push data for a single UPS only:
poetry run bmspy-influxdb --ups network --url ...
InfluxDB connection details can also be supplied via environment variables (`INFLUXDB_V2_URL`, `INFLUXDB_V2_ORG`, `INFLUXDB_V2_TOKEN`) instead of command-line flags.
## EcoFlow Bluetooth LE devices
Install the Bluetooth dependencies:
```bash
poetry install -E ecoflow-bt
```
Close the EcoFlow app and stop other Bluetooth collectors before connecting.
### Setup
#### Setup
Get your EcoFlow account user ID:
```bash
poetry run bmspy-ecoflow-login you@example.com
uv run bmspy-ecoflow-login you@example.com
```
The command prompts for your password. Add `--region EU` or `--region US` if needed.
@@ -85,12 +73,35 @@ curl --fail --location --output bmspy/ecoflow_keydata.py \
This file is ignored by Git and excluded from packages. Type 1 devices do not need it.
### Diagnostics
#### Dump a River 2
Scan and collect reports from nearby supported devices:
Device arguments use `name@ADDRESS/SERIAL/USERID`. Replace the placeholders below
with the device's Bluetooth address, serial number, and your account user ID:
```bash
poetry run python -u tools/ecoflow-bt.py --user-id YOUR_USER_ID --scan --timeout 30
uv run --extra ecoflow-bt bmspy-server --socket /tmp/bmspy-rivers.sock \
-d 'river2@RIVER2_MAC/RIVER2_SERIAL/YOUR_USER_ID'
```
Leave the server running. In another terminal, print its snapshot:
```bash
uv run bmspy --socket /tmp/bmspy-rivers.sock
```
Omit `--ups` for all devices. Add `--ups river2` to select one. `--ups all` means a
device named `all`, not all devices. To include a serial BMS, add a server argument
such as `-d network:/dev/ttyUSB0`.
The server caches Bluetooth data for 60 seconds. Failed reads wait 60 seconds
before retrying. Unavailable devices are omitted from the response.
#### Diagnostics
Stop the server before connecting directly. Scan and collect reports from nearby supported devices:
```bash
uv run --extra ecoflow-bt python -u tools/ecoflow-bt.py --user-id YOUR_USER_ID --scan --timeout 30
```
Add `--watch` to print every packet until Ctrl+C. Watch mode ignores the telemetry
@@ -115,3 +126,59 @@ Client snapshots include all complete River 2 heartbeat fields under
Partial reports retain earlier field values. See the
[River 2 field reference](docs/ecoflow-river2-fields.md#reported-fields-available-to-clients)
for names, units, and limits.
### Running via systemd
Before you start a service, install its dependencies in the service's working
directory with `uv sync --locked --no-dev`. Add `--extra ecoflow-bt` for Bluetooth,
`--extra influxdb` for InfluxDB, or both if needed.
The service files use `uv run --no-sync`. This keeps services from changing
the shared environment when they start. Set the `uv` executable to an absolute
path if it is not on systemd's search path.
Copy `bmspy-server.service` to `/etc/systemd/system`, adjust `WorkingDirectory` and the `ExecStart` line as needed, then enable and start it:
cp bmspy-server.service /etc/systemd/system
$EDITOR /etc/systemd/system/bmspy-server.service
systemctl daemon-reload
systemctl enable bmspy-server
systemctl start bmspy-server
## Running a client
To print a summary of all connected devices:
uv run bmspy
To show only a specific device:
uv run bmspy --ups network
To push data for all devices to InfluxDB (each measurement is tagged `ups=<name>`):
uv run --extra influxdb bmspy-influxdb --url https://influx.example.com --org myorg --token mytoken
To push data for a single device only:
uv run --extra influxdb bmspy-influxdb --ups network --url ...
InfluxDB connection details can also be supplied via environment variables (`INFLUXDB_V2_URL`, `INFLUXDB_V2_ORG`, `INFLUXDB_V2_TOKEN`) instead of command-line flags.
## Development
Install all extras and run the tests:
```bash
uv sync --locked --all-extras
uv run --locked --all-extras pytest
```
To build a source archive and a wheel, which is an installable Python package:
```bash
uv build
```
`uv.lock` records the resolved dependency versions. After you change dependencies
in `pyproject.toml`, run `uv lock` and include the updated lock file with the change.