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 theSystemInfo, where it used to hold the version string and hand that back regardless ofdetailsget_firmware_version(),get_components()andget_battery_block()now attemptconnect()when the DIN is unknown, like the other getters already did, instead of failing the fetch on aNonerecipient- Failure shapes are now pinned per getter:
get_status(),get_device_controller(),get_battery_block()andget_config()degrade to{}(logged) for the cache window;get_components()keeps its uncachedNone(_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/componentskeeps servingnullrather than{}on failure get_config()on v1r LAN gets the samebattery_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
Messageas anAuthEnvelopeto find the inner envelope (a wire-shape pun on field 1) —_post_tedapi()strips theMessage/Tailwrapper to bareMessageEnvelopebytes with one shared_envelope_bytes(), transport proto matched totedapi_api_versionso a V2026_06 signed-GraphQL request survives the round trip. The bare-envelope guard (protobuf parses it as an emptyMessagewithout raising) closes the silentb""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-watchdogdaemon thread pollspw.version()everyPW_FIRMWARE_CHECK_INTERVALseconds (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 topypowerwall==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