github jasonacox/pypowerwall v0.17.2
v0.17.2 - TEDAPI Getter and Bearer Transport Consolidation

3 hours ago

What's New

This release ships two changes since v0.17.1: the TEDAPI getter and bearer transport consolidation (#374) and proxy firmware change tracking (#378, proxy BUILD t101).

TEDAPI Getter and Bearer Transport Consolidation (#374)

The TEDAPI cached getters — get_config(), get_status(), get_device_controller(), get_firmware_version(), get_components(), get_battery_block() — were six hand-copied ~60-line variants of the same skeleton (cache check → cooldown → lock → re-check → connect → fetch → cache; lock timeout → stale cache). They now share one _cached_fetch() and contribute only their cache key, expiry and fetch; the query getters share one _fetch_query() (build → post, LAN or WiFi → parse → JSON). get_din() keeps its deliberately different contract (no lock, never reconnects, lets a transport exception reach connect() for its routing advice) but uses the same cache/cooldown helpers. Addresses #371.

Behavior deltas (all deliberate):

  • get_firmware_version(details=True) on a warm cache now returns the details dict — the cache holds the SystemInfo, where it used to hold the version string and hand that back regardless of details
  • get_firmware_version(), get_components() and get_battery_block() now attempt connect() when the DIN is unknown, like the other getters already did, instead of failing the fetch on a None recipient
  • Failure shapes are now pinned per getter: get_status(), get_device_controller(), get_battery_block() and get_config() degrade to {} (logged) for the cache window; get_components() keeps its uncached None (_fetch_query(..., strict=True)) so the next poll retries, get_pw3_vitals() sees "no components" rather than an empty set, and the proxy's /tedapi/components keeps serving null rather than {} on failure
  • get_config() on v1r LAN gets the same battery_blocks: [] default as the other transports; log lines are uniform

Transport unification:

  • get_config() now fetches config.json through the shared transport like every other query, instead of carrying its own inline bearer and basic branches — one copy of the transport logic to keep in sync (no behavior change)
  • The bearer transport no longer re-parses the request Message as an AuthEnvelope to find the inner envelope (a wire-shape pun on field 1) — _post_tedapi() strips the Message/Tail wrapper to bare MessageEnvelope bytes with one shared _envelope_bytes(), transport proto matched to tedapi_api_version so a V2026_06 signed-GraphQL request survives the round trip. The bare-envelope guard (protobuf parses it as an empty Message without raising) closes the silent b"" trap
  • _parse_response()'s legacy tier is split out as _parse_legacy_response(); config.json parses through it directly on every api version, including V2026_06 bearer mode
  • Net -176 lines in the module — one cache policy instead of six subtly different ones

Tests: new test_tedapi_cached_fetch.py (106 tests — the shared skeleton parametrized over all six getters, both sides of the failure-shape asymmetry pinned), test_bearer_auth.py reworked for the new contracts, test_api_version.py role-map guard extended. Full non-live suite: 639 passed, pylint 9.95/10 on the module.

Validation: differential audit (identical mocked scenarios against main and the branch — all 26 public TEDAPI signatures unchanged, every declared delta real, nothing undisclosed), plus two independent hardware validations — a bearer-mode run on live solar inverters and a v1r hardwire parity pass on a real dual-PW3 site, re-run on the final merge commit.

Proxy: Firmware Change Tracking (t101) (#378)

  • New firmware-watchdog daemon thread polls pw.version() every PW_FIRMWARE_CHECK_INTERVAL seconds (default 300, minimum 30) and logs a line whenever the gateway firmware changes — handy for correlating behavior shifts after Tesla OTA updates. Covers all modes (Cloud/FleetAPI/local/TEDAPI/v1r); version strings are sanitized against log forging, and the current version + interval are reported in /stats. Requested in Powerwall-Dashboard #854
  • New proxy/tests/test_firmware_tracking.py (9 tests)
  • Proxy container: jasonacox/pypowerwall:0.17.2t101
  • Library version bumped to 0.17.2; proxy requirement pin updated to pypowerwall==0.17.2

Full changelog: v0.17.1...v0.17.2


Contributors

Thanks to the community members who made this release possible:

  • @Nexarian — the TEDAPI getter and bearer transport consolidation refactor (#374), the issue that motivated it (#371), live bearer-mode hardware validation on his solar inverters, and opening the breaking-change policy discussion (#376). A genuinely load-bearing contribution — honest change accounting, 106 pinning tests, and patient iteration through the failure-shape review
  • @JonMurphy — requested firmware-change logging in Powerwall-Dashboard#854, which became the proxy firmware-watchdog (#378)
  • @jasonacox — empirical differential audit of the refactor, merge-conflict resolution, final review and merge, release packaging and PyPI publication

Don't miss a new pypowerwall release

NewReleases is sending notifications on new releases.