Repository navigation
feat: surface locally-pushed chemistry dose events, water quality, energy (incl. heater gas BTU) and heater egg timer - #8
Draft
kingbear2 wants to merge 13 commits into
Conversation
added 13 commits
October 21, 2026 19:51
…timer entities The controller's Device.setStatus local push stream already delivers several status items the integration drops at the entity layer: - Last chemical dose per dosing system (CurrentAcidMixEvent / CurrentLiquidChlorineMixEvent / CurrentSaltChlorinatorMixEvent): a measurement of the dose amount with duration, timestamps, mix minutes, probe reading before, interruption, and origin as attributes. The item's JSON document parses tolerantly and the last dose is preserved when the item goes null between doses. - Water quality (WaterQualityState): enum sensor over the raw GOOD/OK/LOW-style values with a tolerant mapper. - Last-minute energy consumption (LastMinuteOfEnergyConsumption): an electric power sensor (TotalWattsUsed) and a gas sensor (TotalNaturalGasBtuUsed, with TotalLiquidPropaneBtuUsed as an attribute) - giving gas-heated pools a gas-usage sensor. - Heater timed-session end (OnUntil): a timestamp sensor per temperature control that reports the item. All new entities follow the existing patterns: added on first report (the equipment behind them is optional), availability gated on the client connection, and null-safe against missing or malformed items. Includes unit tests for the JSON-string parsing helpers.
…pytest.ini TOML-style lists
…ns (disabled by default) - Dose sensors (+ salt-gate kept), energy sensors, and heater egg-timer sensors are created at setup instead of waiting for their first push, so installs see them immediately as no data. - New per-chemical 'dosed since last reset' running-total sensors (disabled by default, restored across restarts, UUID-deduped). - New matching reset buttons (disabled by default) on a new button platform; pressing zeroes the paired counter for refill tracking.
…er to heater device - Dose sensing trio attaches to the chemical pump device matched via the pump's ChemicalType model, falling back to the body group device when a site reports no matching pump. - Gas consumption attaches to the heater device; watts stays on the body group device (whole-body aggregate). - Heater egg-timer sensor attaches to the heater device when present. - Icons: totals get flask/tonic icons, reset gets restart-alert.
…ty); via_device_id deprecation
…model); heater by device_type/name
…pers recipe - Counters record the reset timestamp (persisted with the total). - New TANK_TRACKING.md documents the tank-level pattern: number helper + counter-triggered decrement automation (positive-delta filter so resets are ignored) + low-tank alert; README links to it.
The controller carries LastMinuteOfEnergyConsumption on its site status item; reading the body uuid left power consumption (and heater gas) unknown forever on installs that stream it site-side. The lookup now prefers the body and falls back to the client's site_uuid, and the sensor subscribes to both keys.
…(pumps already expose watts)
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.
Motivation
The controller's
Device.setStatuslocal push stream already delivers several status items that the integration receives but currently drops at the entity layer — no polling, no cloud, no new API surface needed. This PR surfaces them as sensors:Real payload sample
A real dose-event payload captured from a controller push (keyed under the body-of-water UUID):
{ "UUID": "9d5365d1-d267-49f2-afa4-a44a09bd7943", "StartDateTime": "2026-08-31T13:58:16.8837444-05:00", "EndDateTime": "2026-08-31T14:24:24.8837657-05:00", "DoseSeconds": 68, "DoseAmount": 5.0, "DosingUnit": "OZ", "MixMinutes": 25, "ChemicalType": "CHLORINE", "ChemicalPumpUUID": "Universal-Chemical-Pump", "InterruptedAt": null, "Before": 597.0, "After": null, "IgnoreBadEvent": false, "PumpMinimumPowerLevelWhileMixing": 25, "PumpMinimumPowerLevelWhileDosing": 100, "ManuallyInitiatedEvent": false, "DosingCutShort": false }The item's value arrives as this document JSON-encoded inside the string value (double-encoded, like the InformationFields documents the integration already parses); the item goes null between doses, so the sensors keep the last known dose rather than flapping to unknown.
New entities
Dose events (per body of water, per dosing system that reports;
Last acid dose,Last chlorine dose,Last salt chlorinator dosefromCurrentAcidMixEvent/CurrentLiquidChlorineMixEvent/CurrentSaltChlorinatorMixEvent):DoseAmount—state_class: measurement, unitfl. oz.duration_seconds(DoseSeconds),started/ended(Start/EndDateTime),mix_minutes(MixMinutes),probe_before(Before),interrupted(InterruptedAt),cut_short(DosingCutShort),manually_initiated(ManuallyInitiatedEvent),unit(DosingUnit); null-valued keys are omittedWater quality (
WaterQualityState): enum sensor (good/ok/low/alert/noneoptions) with a tolerant mapper — unrecognized raw values render as unknown instead of crashing.Energy (from
LastMinuteOfEnergyConsumption, JSON string):Power consumption:TotalWattsUsed— device_classpower, unitW, state_class measurementGas consumption:TotalNaturalGasBtuUsed— unitBtu, state_class measurement, withTotalLiquidPropaneBtuUsedas aliquid_propane_btuattribute (keeping the entity count lean). No device class on the gas sensor: the value is thermal energy (Btu), and HA'sgasdevice class is for metered fuel volume, which this isn't.Heater egg timer (
OnUntil, per temperature control that reports it): timestamp sensor with the ISO end time of the timed session, null-safe when no session runs.Implementation notes
Device.setStatussubscription channel the integration already consumes; each new entity follows the codebase's existing patterns (entity-description dataclasses,_status_keyssubscription,controller_uuid+ item-UUID + key unique_ids,DeviceInfovia the group entity, availability gated on the client connection).tests/test_sensor_parsing.py— pure functions, 6 passing.pytest.inisetspythonpath = ["."]for the import. No test framework was previously configured in the repo; happy to drop or restructure these if you'd rather not carry tests here.manifest.jsonunchanged; no new dependencies, no cloud/API access anywhere.Happy to adjust entity shapes to maintainer preference — names, units, attributes, or which items deserve their own entity vs. an attribute.