Close

The double duty button

A project log for The Water Watcher

Monitoring the pilot light on my water heater.

wjcarpenterWJCarpenter 08/16/2023 at 02:120 Comments

I have a hot water recirculating pump tied into my home plumbing. On a schedule, it pumps hot water from the water heater through the hot water piping. A temperature sensitive valve located at the distant end allows that pumped water to flow back down through the cold water piping. The idea is that there is hot water at the ready, and you don't have to waste water running it down the drain until it gets hot.

The timer on the recirculating pump is the tried and true analog type. It's a round dial, representing a 24-hour day, that slowly spins. Around the edges are a series of pegs that control whether the pump is on or off during any particular short time segment. Since I run Home Assistant for many reasons, I decided to convert the timer on the recirculating pump to be controlled by Home Assistant automation. No, I didn't rewire the timer. Instead, I turned all of the little pegs to the "pump is on" position, for all times of day and night. Then I plugged the pump into a smart socket. (The smart socket is an Sonoff S31 reflashed with ESPHome, as described in this and subsequent project logs.)

To control the smart socket, I created a Home Assistant schedule helper object. The schedule helper is a list of times when the schedule is "on"; otherwise, it is "off", and you can use the state of the schedule as a trigger in Home Assistant automations. I created an automation triggered by any state change in the schedule. The resulting action is a "choose", which turns the smart socket off if the state of the schedule is off and on if the state of the schedule is on. It works as desired. In YAML form, it looks like this:

alias: Hot water recirculation SCHEDULED
description: ""
trigger:
  - platform: state
    entity_id:
      - schedule.hot_water_recirculation
condition: []
action:
  - type: turn_on
    device_id: e3bfbdb764cdef92f454e345ec3e1042
    entity_id: switch.s31_green_orange_relay
    domain: switch
  - choose:
      - conditions:
          - condition: state
            entity_id: schedule.hot_water_recirculation
            state: "on"
        sequence:
          - type: turn_on
            device_id: e3bfbdb764cdef92f454e345ec3e1042
            entity_id: switch.s31_green_orange_relay
            domain: switch
      - conditions:
          - condition: state
            entity_id: schedule.hot_water_recirculation
            state: "off"
        sequence:
          - type: turn_off
            device_id: e3bfbdb764cdef92f454e345ec3e1042
            entity_id: switch.s31_green_orange_relay
            domain: switch
mode: queued
max: 10

If I want to change the schedule, I can do it in the Home Assistant GUI (or by manually editing a config file), and everything else automatically flows from that. (Heh, flows. Get it?) 

For my own highly regulated self, that scheduling is enough. But there are others in the household who want hot water at various times that are not really suitable for predictable scheduling. I wanted to provide a way for them to summon the hot water without a lot of fuss. I decided to use the button already present on the M5Stack Atom Matrix device, the device that is already in use to display the hot water heater flame status. On the Atom Matrix, the entire front face is a GPIO button. I've been using it for a simple way to cycle through the display modes of the device. I'm now overloading that button to also signal the desire for hot water recirculation.

My first draft of the implementation was to create a Home Assistant input button helper. It's simple enough for an ESPHome device to call a service in Home Assistant, so it's pretty easy to have the physical button press on the Atom Matrix cause a logical press of the Home Assistant input button helper, and that in turn can be used to trigger an automation. I abandoned that scheme for a light-weight reason. The implementation of this project uses MQTT to communicate among the devices. The devices still show up in Home Assistant via the MQTT integration. To call the service to logically press the input button helper, I'd have to use the Home Assistant API integration. That all works fine, and the API and MQTT components in ESPHome co-exist just fine. I merely didn't want to add a new dependency.

Instead, I changed the visibility of the GPIO button (the "internal" attribute) from true to false. Even over the MQTT integration, the button then appears as an entity in Home Assistant. I created a new automation for ad hoc hot water recirculation. The automation is triggered by the transition of the GPIO button from off to on. (Along the way, I flashed a second Atom Matrix to place in another location. It's also a trigger, and the two triggers are ORed by Home Assistant.) The automation turns the recirculation pump on, waits for a delay of 15 minutes, and then turns it off.

How do the two automations work together? If either one of them has turned the pump on and the other one fires to turn it on, that's OK because there's no conflict. If the ad hoc automation tries to turn the pump off, we don't want to actually turn it off if the schedule is still "on". Someone might innocently press the button for ad hoc hot water, and we don't want to cancel the scheduled hot water. So, the ad hoc automation checks that the schedule is not "on" before turning the pump off. The scheduled automation doesn't bother to check if the ad hoc automation is running before turning the pump off because the scheduled "on" time is long relative to the ad hoc time.

The ad hoc automation looks like this:

alias: Hot water recirculation AD HOC
description: Press the button, get 15 minutes action.
trigger:
  - platform: state
    entity_id:
      - binary_sensor.waterwatcher55_button
    from: "off"
    to: "on"
  - platform: state
    entity_id:
      - binary_sensor.waterwatcherkb_button
    from: "off"
    to: "on"
action:
  - type: turn_on
    device_id: e3bfbdb764cdef92f454e345ec3e1042
    entity_id: switch.s31_green_orange_relay
    domain: switch
  - delay:
      hours: 0
      minutes: 15
      seconds: 0
      milliseconds: 0
  - choose:
      - conditions:
          - condition: not
            conditions:
              - condition: state
                entity_id: schedule.hot_water_recirculation
                state: "on"
        sequence:
          - type: turn_off
            device_id: e3bfbdb764cdef92f454e345ec3e1042
            entity_id: switch.s31_green_orange_relay
            domain: switch
mode: restart

Discussions