ESPHome Replication Plan - jaas666/my-flo GitHub Wiki

ESPHome Replication Plan

Goal: reproduce the device's local behavior in ESPHome, using what is documented in Device Overview, Network Protocol, and Hardware GPIO Map.

What to skip entirely

  • Cloud registration/pairing (/device-api/v2/register, token flow) — the unit also has an offline mode, so it is not required for local operation.
  • Captive-portal onboarding — ESPHome's own WiFi provisioning (or Improv/dashboard import) replaces this.
  • TLS cert handling — the cloud uses a public CA bundle with no pinning, so there is nothing to replicate.

What to build

  1. Valve control — switch on GPIO9/GPIO10 (see Hardware GPIO Map) driven as a two-wire output, wrapped in a script that holds the valve open for the dose time, then returns to idle. The latching valve's feedback and retry is left out; the draft is a simple timed pulse.
  2. Dispense triggers:
    • a template button for a manual dose. The front button (GPIO6, pull-up, active low) is reported as a sensor only: on the factory unit it wakes the unit and keeps it awake rather than dispensing.
    • Scheduling (SCHEDULE DISPENSE) runs on the device (4 daily time slots, each with a dose count), so it keeps working with HA down. HA only edits the slots and views history.
    • REMOTE DISPENSE → just a Home Assistant service call to the same script.
  3. Battery monitoring — sensor.adc on GPIO8 (ADC1 channel 7, 11dB atten — see Hardware GPIO Map), mapped from 2200–3000 mV to a percentage, with binary_sensor thresholds at 20% (low) and 10% (critical) and dispensing blocked below 20%.
  4. Bottle/float sensor — if your unit has a float, a binary_sensor on GPIO7.
  5. Counters — ESPHome globals or number entities for the used-dose count and the dose limit, exposed to Home Assistant, replacing the cloud dashboard's role.

Design rule: standalone first

The unit must keep working with Home Assistant, and even WiFi, unavailable. HA is an optional controller and history/monitoring front end. In esphome/iflo.yaml this means:

  • Schedule, dose limits, counters, last-dose time and the valve failsafe live on the device and are saved to flash.
  • The clock comes from SNTP (HA also sets it when connected). Without any time source after a power loss, scheduled doses are skipped until the clock is valid again.
  • ESPHome's default reboot timers for "no API client" and "no WiFi" are disabled, so an HA or router outage doesn't reboot-loop the unit.
  • A local web UI (digest-auth) and the fallback AP allow control and WiFi changes with no HA.
  • While HA is down it only sees the persisted counters and last-dose time on reconnect, not each individual dose (an on-device event log is an open task).

Status: draft config

A first draft lives in the repo at esphome/iflo.yaml (core local function only: timed valve dose with a hard max-open failsafe, battery %, dose counters/limits, on-device 4-slot schedule, SNTP clock, local web UI). It passes esphome config and is not tested on hardware. Deliberately left out of this first build: deep sleep/wake (always-on WiFi drains the battery, so bench/USB power only), valve feedback/retry, and lost-dispense catch-up.

Safety gate: the config reads the hardware-model strap pins (GPIO18/19/20, see Hardware GPIO Map) and refuses to open the valve unless all three read low (the simple-valve model). See Flashing and Recovery before flashing a real unit.

Power model

The unit is battery powered and mostly asleep, so the target build needs deep sleep. The factory unit wakes on a timer, the front button (GPIO6), a bottle change (GPIO13), the float switch (GPIO7) and external power (GPIO16); see Power and Sleep. Plan: wake on the timer, the button (ext1) and the bottle eject (ext0, inverted level); the float switch and external power need a ULP program or timer polling, which ESPHome lacks. Wake on those plus a timer set to the earlier of the next schedule slot and a maximum sync interval, stay awake for a short window (about 60 s) so Home Assistant can connect, and offer a "stay awake" switch. While asleep the unit still runs its schedule on its own.

Development environment

The repo ships a VS Code dev container and a docker-compose.yml with ESPHome and esptool pinned, so nothing has to be installed locally except Docker. See the repo README. The container builds only; flash from the host.

Open items

  • GPIO40, 39, 41, 42 are probably the LEDs and GPIO15/GPIO2 the second driver IC; probe the PCB to confirm.
  • The float switch is GPIO7 and the bottle eject switch GPIO13 (see Hardware GPIO Map); both are pull-up inputs (active low) in the draft; confirm on a unit.
  • The latching/feedback valve (model 3, all straps high) is not implemented in the draft.
  • The dose-time units (probably tenths of a second) and the battery divider ratio are unverified; the draft exposes them as adjustable values.
  • How to get wired access for the first flash (see Flashing and Recovery).