Skip to main content

Async protocol library for Huawei ESM-48100 batteries

Project description

huawei-esm48100

Huawei ESM-48100 电池的异步 Python 通信库,实时传输默认严格只读。

当前仓库已根据两台 ESM-48100B1 的实机抓包实现:

  • Modbus RTU CRC16、读保持寄存器请求和响应解析;
  • USB/本地串口传输(基于 serialx),按通信参数计算 Modbus RTU 3.5 字符静默时间,并为 USB 转向保留至少 10 ms;
  • TCP 透明串口服务器传输;
  • 多个从站共享同一传输连接的异步客户端;
  • 长时间空闲后的只读唤醒、CRC/超时重试和异常尾随数据清理;
  • 电压、电流、SOC、SOH、统计量、告警和 1–24 节单体数据解码;
  • 设置寄存器的只读回读;
  • 华为电子标签 0x41/0x06 只读分块采集与 ASCII 档案解析;
  • 支持扫描、连续读取、原始帧和完整性摘要的命令行工具。

[!WARNING] 实时传输默认只允许功能码 0x03,以及严格匹配格式的只读电子标签 0x41/0x05/0x04 元数据查询和 0x41/0x06/0x04 分块读取。0x060x10 和其他厂商私有功能默认拒绝发送。只有调用方显式启用不安全请求后, 库才允许五个经过抓包确认、带范围检查及写后读回的高级设置。不同型号或 固件仍需独立抓包验证。

完整的证据、寄存器表、私有电子标签帧和安全说明见 PROTOCOL.md

开发安装

虚拟环境只用于开发和独立硬件测试,不能复制到另一台机器,也不参与 Home Assistant 生产部署。每台机器应从本机 Python 重新创建环境。

Windows PowerShell:

.\scripts\setup-venv.ps1
.\.venv\Scripts\python.exe -m pytest

如果本机执行策略禁止直接运行 .ps1,可以只对这一次启动绕过策略:

powershell.exe -NoProfile -ExecutionPolicy Bypass `
  -File ".\scripts\setup-venv.ps1"

自动发现失败时可指定 Python:

.\scripts\setup-venv.ps1 `
  -Python "C:\Program Files\Python313\python.exe"

若已有环境来自另一台机器,脚本会把它移动到 .venv-stale-<时间戳> 后重建。只有明确使用 -Recreate 时才直接删除旧环境。

普通 Linux 开发环境:

bash scripts/setup-venv.sh
.venv/bin/python -m pytest

只安装运行依赖:

.\scripts\setup-venv.ps1 -RuntimeOnly
bash scripts/setup-venv.sh --runtime-only

两个脚本都要求 Python 3.12 或更高版本,并在结束前验证包可以导入。

Home Assistant 生产安装

HACS 只安装 custom_components/huawei_esm48100。Home Assistant 随后读取 集成的 manifest.json,自动安装固定版本的 huawei-esm48100 包。HA OS、 Supervised 和 Container 生产环境都不运行本仓库的 setup-venv 脚本。

因此正式 HACS 发布前,必须先把与 manifest.json 对应的协议库版本发布到 PyPI。

CI 与 PyPI 发布

.github/workflows/tests.yml 在 Ubuntu 上测试 Python 3.12、3.13 和 3.14, 并构建 wheel/sdist 后执行 twine check

.github/workflows/publish.yml 在 GitHub Release 发布时:

  1. 检查 Release tag(允许 v 前缀)与 pyproject.toml 版本一致;
  2. 构建并检查 wheel 和 source distribution;
  3. 使用 PyPI Trusted Publishing 的短期 OIDC 凭据发布,不使用仓库 API Token。

首次发布前,需要在 PyPI 创建 Pending Trusted Publisher:

PyPI project: huawei-esm48100
GitHub owner: 实际仓库所有者
GitHub repository: https://github.com/GImDX/huawei-esm48100
Workflow: publish.yml
Environment: pypi

同时在 GitHub 仓库创建名为 pypi 的 Environment,并建议为它启用人工审批。 之后将 pyproject.toml 版本更新为目标版本,创建相同版本的 Release tag, 例如 v0.1.0,即可触发发布。

读取原始寄存器

本地串口:

esm48100 read \
  --transport serial \
  --port /dev/serial/by-id/usb-... \
  --baudrate 9600 \
  --slave 0xd6 \
  --register 0x0000 \
  --count 7 \
  --raw

TCP 透明串口服务器:

esm48100 read \
  --transport tcp \
  --host 192.0.2.10 \
  --tcp-port 5020 \
  --slave 0xd6 \
  --register 0x0000 \
  --count 6

TCP 模式发送和接收的仍然是带 CRC 的 Modbus RTU 帧。它不是带 MBAP 头的 Modbus TCP。

串口首次打开默认等待 2 秒,然后用安全的 0x0000 × 1 读取唤醒设备。 read 单次响应超时默认 3 秒,初始恢复窗口默认 60 秒。连续测试示例:

esm48100 read `
  --transport serial --port COM4 --baudrate 9600 --parity N `
  --slave 0xD6 --register 0x0000 --count 7 `
  --repeat 20 --interval 3 --raw

扫描华为上位机使用的默认地址集合:

esm48100 scan --transport serial --port COM4 --raw

扫描不是对每个地址只读取一次,而是在 60 秒恢复窗口内轮询尚未响应的地址。 扫描的单次响应超时默认 0.5 秒,正常在线设备的实测响应为 45–90 ms;如透明 串口服务器延迟较高,可显式增大 --timeout。同一地址的重试轮次默认至少 间隔 3 秒;候选地址较多且一轮本身超过 3 秒时不会额外等待。

PowerShell 中需要手工等待总线空闲时,应使用:

Start-Sleep -Seconds 600

read 每轮都会打印 requested_countreceived_count、地址范围和连续性。 使用 --json 可生成一行一个完整结果的 JSON,避免依赖终端文本复制。

只读实机探针

仓库内的探针支持本地串口和透明 TCP 串口服务器。它保持同一个传输连接, 先静置,再测试安全唤醒并连续读取完整快照。探针不会启用危险请求,输出 JSONL 结果和逐帧调试日志。

本地串口:

.\.venv\Scripts\python.exe .\scripts\hardware_probe.py `
  --transport serial `
  --port COM4 `
  --addresses 0xD6,0xD7 `
  --idle-seconds 600 `
  --rounds 20 `
  --interval 3

透明 TCP 串口服务器:

.\.venv\Scripts\python.exe .\scripts\hardware_probe.py `
  --transport tcp `
  --host 192.0.2.10 `
  --tcp-port 1145 `
  --addresses 0xD6,0xD7 `
  --idle-seconds 0 `
  --rounds 10 `
  --interval 3

未指定 --transport 时仍默认使用 serial,因此旧的串口探针命令保持兼容。 TCP 模式下,波特率、校验位和停止位由串口服务器自身配置。

JSONL 是判断轮次和字段是否完整的依据;终端文本只用于观察进度,复制时缺行 不会被误判为协议解析缺失。

离线解析 Device Monitoring Studio 抓包

esm48100 decode-capture C:\path\to\Data_view_writes.txt --direction request
esm48100 decode-capture C:\path\to\Data_view_reads.txt --direction response

每个输入记录输出一行 JSON,并列出 CRC 有效的 RTU 帧与无法识别的剩余字节。 此命令不打开串口。

Python API

from huawei_esm48100 import EsmClient
from huawei_esm48100.transports import TcpRtuTransport

transport = TcpRtuTransport("192.0.2.10", 5020)
client = EsmClient(transport, slave_address=0xD6)

snapshot = await client.read_snapshot()
print(snapshot.bus_voltage_v)
print(snapshot.pack_voltage_v)
print(snapshot.state_of_charge)
print(snapshot.cell_voltages_v)
await transport.close()

项目边界

  • 一个 transport 代表一条物理或透明转发的 RS485 总线。
  • 多个 EsmClient 可以共享同一个 transport,并由 transport 串行化请求。
  • 一条 RS485 总线只支持一个主站;不支持同时运行华为上位机、串口助手或 另一个轮询程序。传输层仍会丢弃完整的无关 RTU 帧,并在畸形帧后恢复边界, 避免一次残留数据持续污染后续事务。
  • 默认传输只允许功能码 0x03;HACS 只有在用户显式启用高级控制实体后才会 打开危险请求开关。
  • 高级设置只发送一次写请求,不会因响应异常盲目重发。标准 0x06 回显会被 校验;若回显缺失或损坏,则恢复输入流并以目标寄存器读回作为最终确认。
  • 电子标签只放行已验证的 0x41/0x05/0x04 元数据查询和 0x41/0x06/0x04 分块读取请求,并读取索引 0x0000–0x000A;不会复现 上位机的隐式时钟写入、结束帧或其他私有操作。

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

huawei_esm48100-0.1.0.tar.gz (49.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

huawei_esm48100-0.1.0-py3-none-any.whl (31.4 kB view details)

Uploaded Python 3

File details

Details for the file huawei_esm48100-0.1.0.tar.gz.

File metadata

  • Download URL: huawei_esm48100-0.1.0.tar.gz
  • Upload date:
  • Size: 49.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for huawei_esm48100-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d48c20c76ffc82ba6823faafa6a9afa1f29ce07d88996ea20896abd48cc88767
MD5 bf067dd1297a4825f7b8cf97f10cc243
BLAKE2b-256 76de9c389cb2efbaf3e4d267228e5dfb19f2dcad58f34a1585eb04c731c1c256

See more details on using hashes here.

Provenance

The following attestation bundles were made for huawei_esm48100-0.1.0.tar.gz:

Publisher: publish.yml on GImDX/huawei-esm48100

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file huawei_esm48100-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: huawei_esm48100-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 31.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for huawei_esm48100-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ebcd3ade77709f8aa274f4ee04caf33c79590302cee889ec827b10eacb6f3296
MD5 2e8dbd10df943ac3f59b2048b6e26681
BLAKE2b-256 7d87fa79e8e4ff3b40638960830f692200f933a1dd2b3d572bb4152da8690f31

See more details on using hashes here.

Provenance

The following attestation bundles were made for huawei_esm48100-0.1.0-py3-none-any.whl:

Publisher: publish.yml on GImDX/huawei-esm48100

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page