Releases: arboeh/huABus
Release list
v1.11.0
This release upgrades the Huawei Solar communication stack and improves Modbus batching reliability.
Added
- Added
get_error_tracker()for tests and diagnostics. - Added tests covering tracker singleton behavior and reset state.
Changed
- Upgraded
huawei-solarfrom 2.5.0 to 3.0.7. - Migrated from
pyModbustotModbus. - Tightened
read_registers()error handling so programming errors now fail fast. - Introduced typed error categories in
error_tracker.py. - Refactored internal error-tracker and register-read code for better maintainability.
Fixed
- Fixed smart batching so requests never exceed the Modbus 125-register limit.
- Fixed storage-unit state-of-charge register mappings.
- Fixed register definition and
CallbackAPIVersionimport paths.
Dependencies
- Removed:
pymodbus,backoff,pyserial-asyncio,pyserial,pytz - Added:
tmodbus,serialx,tenacity
v1.10.4
🐛 Fixed
- Modbus connect timeout:
setup_modbus()now wrapsAsyncHuaweiSolar.create()inasyncio.wait_for()with a 15-second timeout. This prevents indefinite hanging if the TCP handshake stalls. Previously, only the slave-ID auto-detection path had a timeout — the final connection-create call was unbounded (HA-ASYNC-001).
🔧 Changed
- Narrowed exception handling in
run_main_cycle: The broadexcept Exceptioncatch-all was replaced with an explicitRECOVERABLE_EXCEPTIONStuple (TimeoutError,ConnectionRefusedError,ModbusException).ExceptionResponsefrom pymodbus 3.x is excluded at runtime, since it is a dataclass and not aBaseExceptionsubclass. Truly unexpected errors now propagate up to the top-level handler inmain()instead of being silently swallowed.asyncio.CancelledErroris explicitly re-raised (CC-CLEAN-002). - Typed error categories: Introduced a new
ErrorTypeLiteral ("timeout","connection_refused","modbus_exception") inerror_tracker.py. The previoustype(e).__name__.lower()stringification (which produced inconsistent names like"timeouterror") was replaced with explicit, canonical error-type mapping (PY-STYLE-003).
v1.10.3
🔧 v1.10.3 — Async Safety & Hotpath Fixes
This release eliminates blocking calls in the MQTT publish path and connection setup that could stall the event loop for up to several seconds per cycle.
What changed:
- MQTT hotpath:
publish_data()andpublish_status()no longer block on synchronouswait_for_publish(). The blocking paho-mqtt wait is now offloaded toloop.run_in_executor(). - Startup:
connect_mqtt()replaced itstime.sleep(0.1)busy-poll loop with athreading.Event+run_in_executor()pattern. This is the correct primitive since paho callbacks execute in their own thread. - Shutdown:
disconnect_mqtt()is now async;loop_stop()anddisconnect()run in an executor instead of blocking SIGTERM handling. - mypy: Added
# type: ignore[attr-defined]for paho-mqttCallbackAPIVersion.VERSION2to resolve a type-checker false positive. - Dependencies:
requirements.txtregenerated fromuv.lock(pymodbus==3.13.1,pytz==2026.2).
Impact:
- Cycle publish latency reduced from up to ~2s blocking to non-blocking async wait.
- Startup no longer wastes CPU in a busy-poll loop.
- Shutdown is cleaner under SIGTERM/SIGINT.
No breaking changes. All existing configurations and behaviors remain identical.
v1.10.2
[v1.10.2] - 2026-06-18
Fixed
- Runtime state encapsulation: Replaced scattered globals (
LAST_SUCCESS,BATCH_MODE_AVAILABLE) with a_BridgeStatedataclass and a dedicatedreset_state()helper — no runtime behavior change, significantly cleaner test isolation - Poll interval enforcement: Moved cycle wait handling into the main loop path, preserving existing
poll_intervaltiming behavior - Modbus auto-detection cleanup:
client.stop()during failed slave-ID attempts is now bounded byasyncio.wait_for(..., timeout=2.0); cleanup failures are logged instead of silently swallowed - Filter reset behavior:
reset_filter()now resets the singleton state in-place instead of destroying the instance, closing a brief unprotected window during error recovery where a zero-drop could reach Home Assistant - TRACE logger typing: Replaced dynamic monkey-patching of
logging.Loggerwith a dedicated_TraceLoggersubclass
Changed
- Default
batch_max_gapremains at 50: Keeps Batch 3 below the inverter's internal 125-register limit after the 1.10.1 adjustment — if you havebatch_max_gap: 100in your config, update it to50 - Runtime dependency export:
requirements.txtis now generated byuv export --no-dev --no-hashes --no-emit-projectand includes all transitive runtime dependencies - Development dependency management: Dev dependencies migrated from optional dependencies to PEP 735
[dependency-groups] - CI dependency resolution: CI uses
uv sync --dev; Docker generation uses--no-emit-project - CI actions: Updated GitHub Actions and
astral-sh/setup-uvto latest versions - Production push script: Removed dev-only local/update-test scripts from the production push summary; added a
requirements.txtguard
Tests
- Added
tests/test_version.pyto verify the bridge version constant - Expanded BATS coverage for
enable_batchingandbatch_max_gapenvironment variable handling - Refactored test suite around the new
_BridgeStatehelpers and[dependency-groups]setup
v1.10.1
v1.10.1 - Fix default batch_max_gap
Fixed
- Default
batch_max_gapreduced from 100 to 50 (#XX)- The previous default caused Batch 3 to exceed the inverter's internal
register span limit, triggering a sequential fallback on every cycle - With 50, batches stay within the inverter's limits out of the box
- Users with
batch_max_gap: 100in their config should update to50
- The previous default caused Batch 3 to exceed the inverter's internal
Improved
- Clearer log message when a batch exceeds the inverter limit, with a hint
to reducebatch_max_gap - Updated config descriptions (EN/DE) to reflect new default
v1.10.0
[1.10.0] - 2026-06-02
Added
- Added smart batch register grouping with new configuration options:
enable_batching(default:true)batch_max_gap(default:100)
- Added intelligent register grouping by Modbus address proximity
- Added graceful fallback to sequential reads when batch reads fail
- Added
batch_builder.pywith a dedicatedBatchBuilderclass for batch construction - Added an extensible foundation for future Modbus batching optimizations
- Added batch timing integration into existing DEBUG performance statistics
Fixed
- Improved handling of optional and unsupported registers during batch reads
- Fixed the known DEV-branch limitation where optional storage-related registers could break batch requests
- Expected to resolve #25
Tests
- Added
test_batch_builder.pywith 15 tests for batch building logic - Added
test_read_registers_smart_batching_enabled - Extended
test_main.pyfor the new tuple-based batching API - Extended configuration loading tests for
enable_batchingandbatch_max_gap
Performance
- Reduced TCP calls from 67 individual reads to typically 3-5 batch requests
- Improved typical cycle time from
17.4sto3.9-6.7s(~77% reduction) - Improved optimized cycle time from
15.1sto4.4sduring warm-up, then3.9ssteady-state (~74% reduction) - Preserved partial performance benefits even when fallback to single reads is required
v1.9.0
[1.9.0] - 2026-05-03
Added
-
Performance Diagnostics: Detailed per-register timing measurements are now available when
log_level: DEBUGis enabled -
Individual register read times with automatic warnings for slow registers (>200ms)
-
Statistical summary per cycle: average, min, max, and median read times across all registers
-
Top 5 slowest registers are listed in the logs to help identify performance bottlenecks
-
Connection establishment time is now logged with detailed host/port/slave information
-
Aids in diagnosing network latency issues and SDongle firmware performance variations
-
Documentation: Expanded Performance Troubleshooting section in
DOCS.mdincluding:- Step-by-step guide for diagnosing slow cycle times
- Network latency testing instructions (ping, traceroute)
- Reference values for expected vs. problematic performance metrics
- Firmware update recommendations and known caveats
Tests
- Added
test_read_registers_timing_and_statisticsto verify timing measurement functionality - Added
test_read_registers_no_slow_register_warning_when_fastto ensure no false positives for slow register warnings
v1.8.5
[1.8.5] - 2026-04-28
Fixed
- aarch64 / ARM installation failure (Issue #22): Add-on failed to build
on Raspberry Pi 4 and other ARM-based systems due to a hardcodedamd64
base image in the Dockerfile- Root cause:
ARG BUILD_FROM=ghcr.io/home-assistant/amd64-base:latest
was used as default, causing Docker to pull an amd64-only image when
building foraarch64 - Removed hardcoded default —
BUILD_FROMis now fully controlled by
Home Assistant Supervisor viabuild.yaml - Added missing
build.yamlwith correct architecture-specific base images
for all supported architectures (aarch64,amd64,armhf,armv7,i386)
- Root cause:
CI
- Fixed
test-dockerjob: added--build-arg BUILD_FROM=...andload: true
todocker/build-push-actionso the built image is available for subsequent
test steps - Removed redundant second
docker buildcall intest-dockerjob