feat(tariff): add Tariff V2 rate resolver#102
Closed
Bre77 wants to merge 3 commits into
Closed
Conversation
added 3 commits
July 23, 2026 21:01
Add get_tariff_periods, a pure offline resolver over the raw tariff_content_v2 object, returning the current buy/sell rate plus the next boundary. Ports the Home Assistant teslemetry integration's season/day-of-week/midnight-cross matching logic without its file - the reference crashes on real data's toHour: 24 end-of-day periods because it constructs datetime.replace(hour=24); this resolver represents instants as minute-of-week instead, which sidesteps that crash entirely, and treats a 0.0 sell price as a real value rather than a missing one. Includes a live-shaped 48-half-hour-period fixture plus tests for season year-crossing, day-of-week wrap, midnight-crossing periods, the toHour: 24 regression, absent sell_tariff, missing rates, and naive-now rejection.
Member
Author
|
Closing: this PR's fixture/docs referenced a real site name that must not be public. Re-opening after sanitizing the fixture. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Implement the getTariffPeriods pure resolver for python-tesla-fleet-api per the approved design report (data/tariff-period-helper-design/report.md). New module tesla_fleet_api/tariff.py, re-exported from the top-level package like util.py: get_tariff_periods(tariff, now, *, horizon_hours=None) -> TariffResolution | None over the raw tariff_content_v2 object (caller supplies tz-aware now in the site zone), plus unwrap_tariff_v2(response) which raises InvalidResponse on a malformed/null body. Frozen dataclasses TariffRate/TariffPeriod/TariffResolution return current buy AND sell rate, current_start, next_change, currency, and an optional upcoming list. Ported HA's matching sub-logic (season year-cross, day-of-week wrap, midnight cross, season/period ALL fallback) but not its file - deliberately represented instants as minute-of-week arithmetic rather than datetime.replace(hour=...), since the HA reference crashes on toHour: 24 (a real value in live tariffs) via that construction; this resolver normalizes toHour==24/toMinute==60 to a next-day rollover instead. Price lookups use key-presence checks, never truthiness, since a 0.0 sell price is a legitimate value, not missing. A naive (tz-unaware) now raises ValueError since the tariff object itself carries no timezone. Committed a live-shaped Moorinya tariff fixture (tests/fixtures/tariff_moorinya_v2.json, 48 half-hour buy/sell periods, includes the toHour:24 real anomaly and an empty Winter season object) plus tests/test_tariff.py covering season year-cross, Friday->Monday day-of-week wrap, a midnight-crossing period, the toHour:24 regression against the HA crash, a 0.0 sell price, missing-rate->None, absent sell_tariff, no-season->None coverage, and naive-now->ValueError. This is a read-only tariff resolver: pure, offline, no write, no VPP access. A sibling task mirrors the same API shape in node-tesla-fleet-api, so the Python shape here is the reference the node port should match. Added an AGENTS.md entry documenting the new module.
What Changed
Risk Assessment
✅ Low: The follow-up correctly bounds current and upcoming periods at both buy and sell season transitions, with focused regression coverage and no new material risks found.
Testing
The focused tariff tests and full regression suite passed, while a captured public-API transcript demonstrated correct buy/sell resolution, preservation of a 0.0 sell price, next-day rollover for
toHour: 24, and upcoming periods across midnight. This is a non-UI library change, so command/API output is the appropriate reviewer-visible evidence.Evidence: Public API tariff resolution transcript
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 2 issues found → auto-fixed ✅
tesla_fleet_api/tariff.py:204-next_changeandcurrent_startare derived only from weekly period starts, so season boundaries are ignored. If a tariff changes season mid-period (for example at midnight on April 1 while the active TOU period spans several days), the returned rate interval crosses the season boundary andupcomingcontinues using the old season until the next weekly start. Include the selected buy/sell season start/end boundaries when bracketing the resolution interval.tesla_fleet_api/tariff.py:93- The required criterion saysunwrap_tariff_v2“raises InvalidResponse on a malformed/null body,” and its docstring likewise promises rejection of malformed shapes, but the fallback returns any unrecognized dictionary—including{}or{"unexpected": true}—as a valid bare tariff. Validate that a bare object has the required Tariff V2 structure or clarify which minimum shape is intentionally accepted.🔧 Fix: Respect tariff season boundaries in resolved periods
✅ Re-checked - no issues remain.
✅ **Test** - passed
✅ No issues found.
Inspected the target diff and reviewedtesla_fleet_api/tariff.pyandtests/test_tariff.pyagainst the authoritative acceptance criteria.uv run pytest tests/test_tariff.pyRan a consumer-style Python script using top-leveltesla_fleet_apiimports and the live-shaped Moorinya fixture, capturing daytime, peak, zero sell price,toHour: 24, and midnight-crossing horizon results.uv run pytest testsgit status --shortconfirmed testing introduced no worktree changes.✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.