Skip to content

Releases: arboeh/huABus

v1.11.0

Choose a tag to compare

@arboeh arboeh released this 19 Aug 17:25
fe75d10

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-solar from 2.5.0 to 3.0.7.
  • Migrated from pyModbus to tModbus.
  • 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 CallbackAPIVersion import paths.

Dependencies

  • Removed: pymodbus, backoff, pyserial-asyncio, pyserial, pytz
  • Added: tmodbus, serialx, tenacity

v1.10.4

Choose a tag to compare

@arboeh arboeh released this 12 Aug 16:56
9c24d59

🐛 Fixed

  • Modbus connect timeout: setup_modbus() now wraps AsyncHuaweiSolar.create() in asyncio.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 broad except Exception catch-all was replaced with an explicit RECOVERABLE_EXCEPTIONS tuple (TimeoutError, ConnectionRefusedError, ModbusException). ExceptionResponse from pymodbus 3.x is excluded at runtime, since it is a dataclass and not a BaseException subclass. Truly unexpected errors now propagate up to the top-level handler in main() instead of being silently swallowed. asyncio.CancelledError is explicitly re-raised (CC-CLEAN-002).
  • Typed error categories: Introduced a new ErrorType Literal ("timeout", "connection_refused", "modbus_exception") in error_tracker.py. The previous type(e).__name__.lower() stringification (which produced inconsistent names like "timeouterror") was replaced with explicit, canonical error-type mapping (PY-STYLE-003).

v1.10.3

Choose a tag to compare

@arboeh arboeh released this 26 Jun 19:49
a3d9ae7

🔧 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() and publish_status() no longer block on synchronous wait_for_publish(). The blocking paho-mqtt wait is now offloaded to loop.run_in_executor().
  • Startup: connect_mqtt() replaced its time.sleep(0.1) busy-poll loop with a threading.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() and disconnect() run in an executor instead of blocking SIGTERM handling.
  • mypy: Added # type: ignore[attr-defined] for paho-mqtt CallbackAPIVersion.VERSION2 to resolve a type-checker false positive.
  • Dependencies: requirements.txt regenerated from uv.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

Choose a tag to compare

@arboeh arboeh released this 18 Jun 19:41
c7e93ed

[v1.10.2] - 2026-06-18

Fixed

  • Runtime state encapsulation: Replaced scattered globals (LAST_SUCCESS, BATCH_MODE_AVAILABLE) with a _BridgeState dataclass and a dedicated reset_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_interval timing behavior
  • Modbus auto-detection cleanup: client.stop() during failed slave-ID attempts is now bounded by asyncio.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.Logger with a dedicated _TraceLogger subclass

Changed

  • Default batch_max_gap remains at 50: Keeps Batch 3 below the inverter's internal 125-register limit after the 1.10.1 adjustment — if you have batch_max_gap: 100 in your config, update it to 50
  • Runtime dependency export: requirements.txt is now generated by uv export --no-dev --no-hashes --no-emit-project and 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-uv to latest versions
  • Production push script: Removed dev-only local/update-test scripts from the production push summary; added a requirements.txt guard

Tests

  • Added tests/test_version.py to verify the bridge version constant
  • Expanded BATS coverage for enable_batching and batch_max_gap environment variable handling
  • Refactored test suite around the new _BridgeState helpers and [dependency-groups] setup

v1.10.1

Choose a tag to compare

@arboeh arboeh released this 03 Jun 17:55
a53c0d5

v1.10.1 - Fix default batch_max_gap

Fixed

  • Default batch_max_gap reduced 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: 100 in their config should update to 50

Improved

  • Clearer log message when a batch exceeds the inverter limit, with a hint
    to reduce batch_max_gap
  • Updated config descriptions (EN/DE) to reflect new default

v1.10.0

Choose a tag to compare

@arboeh arboeh released this 02 Jun 16:44
11d4f33

[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.py with a dedicated BatchBuilder class 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.py with 15 tests for batch building logic
  • Added test_read_registers_smart_batching_enabled
  • Extended test_main.py for the new tuple-based batching API
  • Extended configuration loading tests for enable_batching and batch_max_gap

Performance

  • Reduced TCP calls from 67 individual reads to typically 3-5 batch requests
  • Improved typical cycle time from 17.4s to 3.9-6.7s (~77% reduction)
  • Improved optimized cycle time from 15.1s to 4.4s during warm-up, then 3.9s steady-state (~74% reduction)
  • Preserved partial performance benefits even when fallback to single reads is required

v1.9.0

Choose a tag to compare

@arboeh arboeh released this 06 May 16:56
b7f74c6

[1.9.0] - 2026-05-03

Added

  • Performance Diagnostics: Detailed per-register timing measurements are now available when log_level: DEBUG is 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.md including:

    • 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_statistics to verify timing measurement functionality
  • Added test_read_registers_no_slow_register_warning_when_fast to ensure no false positives for slow register warnings

v1.8.5

Choose a tag to compare

@arboeh arboeh released this 28 Apr 17:32
20b3df2

[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 hardcoded amd64
    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 for aarch64
    • Removed hardcoded default — BUILD_FROM is now fully controlled by
      Home Assistant Supervisor via build.yaml
    • Added missing build.yaml with correct architecture-specific base images
      for all supported architectures (aarch64, amd64, armhf, armv7, i386)

CI

  • Fixed test-docker job: added --build-arg BUILD_FROM=... and load: true
    to docker/build-push-action so the built image is available for subsequent
    test steps
  • Removed redundant second docker build call in test-docker job