Summary
Brings the Atlas EZO support in the repo up to the full state of the real atlas-hydro-monitor device, on a clean component-based architecture (the old prototype's per-feature YAML template-switches are pushed into the component).
- Migrates the advanced
ezo_types (pH/EC/RTD/ORP, cell-constant select, calibration + command-queue diagnostics, cross-sensor temp compensation) from the fork, self-contained against stock upstream ezo (AUTO_LOAD=["ezo"], no esphome-core patch). Ported to ESPHome 2026.5 (on_slope → add_slope_callback, const char* commands).
- EC secondary outputs:
ECSensor now publishes TDS / salinity / specific-gravity by enabling the matching O,<param> outputs and parsing the full R-response CSV (order EC,TDS,SAL,SG), plus a TDS,<factor> conversion-factor number. Plain single-value EC path is preserved when no secondaries are configured.
- New component-owned switch platform:
DataloggerSwitch (RTD D,<n>/D,0) and ExtendedScaleSwitch (ORP ORPext,1/0), mirroring the cell-constant select pattern.
configs/test-ezo-types.yaml is the validation/device config: sensor names match the live device (Water pH/EC/Temperature/ORP + EC TDS/salinity/SG), the diagnostics section (ESP version, WiFi info/signal, uptime, HA API status, status LED), and slot 4's enable named "Enable AUX Circuit" (the board's general-purpose port, currently hosting ORP).
Test plan
./docker/esphome compile configs/test-ezo-types.yaml — green on ESPHome 2026年5月1日.
- Hardware-verified on the Atlas hydro monitor (ESP32 Feather) via OTA. All four circuits read live (pH ≈ 6.1, EC 171 μS/cm, RTD 22.3 °C, ORP 314 mV); the EC CSV parse publishes TDS 92 ppm / salinity 0.00 PSU / SG 1.000 with no command-queue desync and pH/RTD/ORP unaffected; calibration-status decode, slope/asymmetry, cell-constant select, datalogger + extended-scale switches, and the full diagnostics panel all present and functioning. Confirmed via native-API logs and the
web_server UI.
## Summary
Brings the Atlas EZO support in the repo up to the full state of the real `atlas-hydro-monitor` device, on a clean component-based architecture (the old prototype's per-feature YAML template-switches are pushed into the component).
- **Migrates the advanced `ezo_types`** (pH/EC/RTD/ORP, cell-constant select, calibration + command-queue diagnostics, cross-sensor temp compensation) from the fork, self-contained against stock upstream `ezo` (`AUTO_LOAD=["ezo"]`, no esphome-core patch). Ported to ESPHome 2026.5 (`on_slope` → `add_slope_callback`, `const char*` commands).
- **EC secondary outputs:** `ECSensor` now publishes TDS / salinity / specific-gravity by enabling the matching `O,<param>` outputs and parsing the full R-response CSV (order EC,TDS,SAL,SG), plus a `TDS,<factor>` conversion-factor number. Plain single-value EC path is preserved when no secondaries are configured.
- **New component-owned switch platform:** `DataloggerSwitch` (RTD `D,<n>`/`D,0`) and `ExtendedScaleSwitch` (ORP `ORPext,1`/`0`), mirroring the cell-constant select pattern.
- **`configs/test-ezo-types.yaml`** is the validation/device config: sensor names match the live device (`Water pH/EC/Temperature/ORP` + EC TDS/salinity/SG), the diagnostics section (ESP version, WiFi info/signal, uptime, HA API status, status LED), and slot 4's enable named "Enable AUX Circuit" (the board's general-purpose port, currently hosting ORP).
## Test plan
- `./docker/esphome compile configs/test-ezo-types.yaml` — green on ESPHome 2026年5月1日.
- **Hardware-verified** on the Atlas hydro monitor (ESP32 Feather) via OTA. All four circuits read live (pH ≈ 6.1, EC 171 μS/cm, RTD 22.3 °C, ORP 314 mV); the EC CSV parse publishes TDS 92 ppm / salinity 0.00 PSU / SG 1.000 with no command-queue desync and pH/RTD/ORP unaffected; calibration-status decode, slope/asymmetry, cell-constant select, datalogger + extended-scale switches, and the full diagnostics panel all present and functioning. Confirmed via native-API logs and the `web_server` UI.
Replaces the older minimal ezo_types with the advanced version (pH/EC/RTD/ORP
circuits, cell-constant select, TDS conversion-factor number, calibration and
command-queue diagnostics) and ports it to ESPHome 2026.5.
The component is now self-contained against the STOCK upstream `ezo`, not a
patched fork of it:
- sensor.py binds the `ezo` codegen handle (EZOSensor) locally instead of
importing it from esphome.components.ezo, so no esphome-core patch is
needed. The C++ comes from stock ezo via AUTO_LOAD = ["ezo"] (a plain
DEPENDENCIES cannot be satisfied — stock ezo has no top-level schema).
- on_slope is wired through the base's add_slope_callback (the
CallbackAutomation pattern stock ezo itself uses); upstream replaced the
old SlopeTrigger with callbacks between 2025.7 and 2026.5.
- add_command_ takes a const char* in stock ezo, so the one std::string
call now passes .c_str().
Compiles green against configs/test-ezo-types.yaml on 2026年5月1日. Not yet
verified on hardware (needs the Atlas circuits attached).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Brings configs/test-ezo-types.yaml back from the fork as the dev/validation
config for ezo_types (pH/EC/RTD/ORP on a featheresp32 over I2C). Repointed
external_components to the local monorepo path and added a device_mac
substitution. Wi-Fi/API/OTA use !secret; secrets.yaml stays gitignored.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The recovered test-ezo-types.yaml used short sensor names
("pH"/"EC"/"Temperature"/"ORP"), which slugify to
sensor.atlas_hydro_monitor_{ph,ec,temperature,orp} in Home Assistant.
The live device's dashboard references the original _water_ entity IDs,
so the short names broke those references after the OTA.
Restore "Water pH"/"Water EC"/"Water Temperature"/"Water ORP" so the
entity IDs match the deployed device. Names only -- no component
behavior change; reflashed and verified on hardware.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Restore the advanced EZO features lost in the earlier upstreaming
attempt, implemented at the component level so device YAML stays clean:
- ECSensor publishes the conductivity circuit's secondary outputs (TDS,
salinity, specific gravity). setup() enables exactly the O,<param>
outputs whose sub-sensors are wired, and an ECSensor::loop() override
reads the full R-response CSV (order EC,TDS,SAL,SG) before the stock
ezo loop truncates it at the first comma, publishing each field. The
plain single-value EC path is untouched when no secondaries are set.
- TDSConversionFactorNumber drives the circuit's TDS,<factor> command.
- New component-owned switch platform: DataloggerSwitch (RTD D,<n>/D,0)
and ExtendedScaleSwitch (ORP ORPext,1/0), mirroring the cell-constant
select pattern.
Hardware-verified: all four EC outputs read with no command-queue
desync; pH/RTD/ORP unaffected.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bring test-ezo-types.yaml up to the real device's full feature set on
the clean component architecture:
- EC: TDS / salinity / specific-gravity sub-sensors + TDS conversion
factor number.
- RTD: datalogger switch; ORP: extended-scale switch.
- Re-add the diagnostics section (ESP version, wifi_info, wifi_signal,
uptime, Home Assistant API status, status LED on GPIO13) under a
"Diagnostic" sorting group.
- Name slot 4's enable "Enable AUX Circuit" (the board's general-purpose
port; currently hosts ORP) rather than labelling it ORP-specific.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The TDS conversion-factor number was write-only -- control() sent
TDS,<v> but nothing read TDS,? back, so the slider showed its own
default (min 0.01) instead of the circuit's actual factor, and a stray
state push could have clobbered the real value.
Mirror the cell-constant select's readback: TDSConversionFactorNumber::
setup() requests TDS,? via the EC sensor; the ?TDS,<n> response is parsed
and pushed to the number with publish_state (display only, no write-back).
Verified on hardware: the slider now reads 0.54 (the Atlas default it was
always at), and 170 uS/cm x 0.54 ~= 92 ppm matches the reported TDS.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The bench device runs freshwater, where salinity and specific gravity
read ~0 PSU / 1.000 and aren't useful. Removing the sub-keys disables
the O,S / O,SG outputs on the circuit and drops the entities, leaving
EC + TDS (ppm500, CF 0.50). Also exercises the declarative output model
(a sub-sensor's presence = its EZO output enabled).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>