Fix backstream data for private producers and add consumption since last invoice sensor - #508
Merged
Merged
Conversation
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
…to Consumption Backstream detection for issue #507: normalize Hebrew/English meter kind inputs to the exact API casing ("Backstream", lowercase s — matching what the IEC web app sends) and default unknown values to "Consumption" instead of passing them through. Also accept the hyphenated "דו-כיווני" variant in _is_backstream_meter_kind. Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Fix issue #507: commit 808b967 hardcoded meter_kind="Consumption" for every device, so backstream/export data was never returned for private producers (cookie-less API requests only return backstream when meterKind is "Backstream"). Replace the hardcoded value with a meter kind derived from the contract's from_private_producer flag (fetched cookie-less via get_contracts, cached per refresh cycle, IECError falls back to "Consumption"). Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
DRY for issue #507: _is_backstream_meter_kind now delegates to _map_meter_kind_to_remote_reading_param, making the classification and the request parameter share a single source of truth. The mapping function learns the API's numeric meterKind values (1 = Consumption, 2 = Backstream) so int/enum inputs classify identically to strings. Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
The API's response meterKind is not a stable meter property: for the same meter it returns 2 when export data exists for the queried period and 1 when it does not (observed on contract 348435866: Backstream request for 2026-08-05 returned meterKind 2 with totalExport 39225, same request for 2026-08-06 returned meterKind 1 with totalExport 0). Classifying backstream_meters from that field made backstream sensors flicker between refreshes. Classify instead from the request-side device.meter_kind, derived from the contract's from_private_producer flag, which is deterministic. Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
The IEC API zeroes backstream (export) fields in the current period's aggregations even for bidirectional meters. _needs_future_consumption_fallback triggers a fallback when a backstream meter's monthly export came back empty; _future_consumption_candidate_dates lists the reading windows to probe, newest first: the last three days, the most recent completed week (last Sunday; two Sundays ago on Sunday), and the first of the current month (previous month on the 1st). Ref issue #507. Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
When the fallback is needed (missing future consumption, or a backstream meter whose monthly export is zeroed), walk the candidate reading windows via _probe_future_consumption instead of a single two-days-ago monthly fetch. Zero-export windows are skipped for backstream meters, the first window with real export wins, and the first valid window is kept as the bill-estimate baseline so consumption estimates are never lost. Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
IEC zeroes the current period's export (backstream) data unless lastInvoiceDate is the day after the last invoice. Always pass the invoice-derived last invoice date for monthly readings while keeping fromDate as the first of the month; the from_date override still applies on the first-of-month and Sunday paths. _get_invoice_reading_dates now derives the value from the most recent invoice's full_date plus one day instead of the lastDate field. Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Add a meter-level sensor reading FutureConsumptionInfo.future_consumption, mirroring the existing backstream production sensor, so consumption for the current period since the last invoice is available alongside production. Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
GuyKh
force-pushed
the
fix/backstream-meter-kind-from-contract
branch
from
August 10, 2026 06:13
f16d92a to
5a6107d
Compare
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.
Summary
Fixes #507 — backstream (energy production) data is no longer available or is zeroed in sensors. Also adds a new
Consumption since last invoicesensor.Root causes
Two separate problems caused backstream/export data to be missing or zeroed:
1. Meter kind was hardcoded to
"Consumption"Commit
808b967(#465) hardcodedmeter_kind="Consumption"for every device when working around the DeviceIn endpoint's recaptcha requirement. For cookie-less API clients like Home Assistant, the request'smeterKindis the gate that determines whether backstream/export data is returned:meterKind:"Consumption"→ response hasmeterKind:1, all backstream/export fields zeroedmeterKind:"Backstream"→ response hasmeterKind:2with real backstream/export data (byte-identical to what the IEC web app receives)2. Zeroed export data on monthly readings
Even with the correct meter kind, the IEC API returns zeroed export data for the current period unless
lastInvoiceDateis the day after the last invoice. The coordinator only sentlast_invoice_dateon the first-of-month/Sunday path, so the regular monthly "latest reading" request sent the period start aslastInvoiceDateand the API zeroed out all export fields.Changes
data_fetcher.py—_get_devices_by_contract_idno longer hardcodesmeter_kind="Consumption". New_get_meter_kind_for_contract()derives the meter kind from the contract'sfrom_private_producerflag, fetched cookie-less viaget_contracts()(cached per refresh cycle; onIECErrorfalls back to"Consumption"). The DeviceIn endpoint cannot be used here — that's exactly why #465 replaced it.bill.py—_map_meter_kind_to_remote_reading_paramnow normalizes Hebrew/English inputs to the exact API casing the IEC web app sends:"דו כיווני"/"דו-כיווני"→"Backstream"(was"BackStream"— capital S, which never matches the API),"צריכה"→"Consumption", numeric values (1 = Consumption, 2 = Backstream), and unknown values default to"Consumption"._get_invoice_reading_datesnow deriveslastInvoiceDatefrom the most recent invoice'sfullDate + 1 day(IEC's requirement for non-zeroed export data) instead of thelastDatefield._needs_future_consumption_fallbackand_future_consumption_candidate_dateshelpers.coordinator.py—device.meter_kind(the contract's private-producer flag). The responsemeterKindflips between 1 and 2 for the same meter depending on the queried period, so it is not a reliable indicator of a bidirectional meter.lastInvoiceDate, keepingfromDateas the first of the current month._probe_future_consumption) walks progressively older windows (last 3 days → last completed week → first of month), skipping zero-export windows for backstream meters, instead of a single two-days-ago monthly fetch.sensor.py— new meter-levelConsumption since last invoicesensor (elec_consumption_since_last_invoice) readingfuture_consumption, mirroring the existing backstream production sensor. Translations exist in bothen.jsonandhe.json.Tests — updated and extended (
tests/test_bill.py,tests/coordinator/test_invoice_reading_dates.py) for the new casing/defaults, thefullDate + 1contract, and the fallback helpers.Test plan
./scripts/lint)pytest tests/— 87 passed)lastInvoiceDate=2026-07-02andfromDate=2026-08-01returns real export data (futureBackStream3106.799,totalExport39225.556), matching the IEC web app's displayed "Production: 3107" and "Last read: 39226".