esphome:
  name: pool
  friendly_name: "Pool"
  area: "Backyard"

  project:
    name: dasfoo.pool
    version: "1.0"

  on_boot:
    - priority: 600
      then:
        - output.turn_on: water_sensor_power
        - output.turn_off: water_sensor_com

globals:
  - id: temperature_published
    type: bool
    restore_value: false
    initial_value: "false"
  - id: water_presence_published
    type: bool
    restore_value: false
    initial_value: "false"

script:
  - id: check_and_sleep
    then:
      - if:
          condition:
            - lambda: "return id(temperature_published);"
            - lambda: "return id(water_presence_published);"
            - switch.is_off: stay_awake
          then:
            - deep_sleep.enter: chip_deep_sleep

esp32:
  # ESP32 has lower power consumption during deep sleep, which is the mode
  # we spend most time in.
  #
  # This board has an LED on GPIO16.
  board: esp32doit-devkit-v1
  framework:
    type: esp-idf

packages:
  wifi: !include templates/wifi.yaml
  ota: !include templates/ota.yaml
  mqtt: !include templates/mqtt.yaml

switch:
  - platform: template
    name: "Stay awake"
    id: stay_awake
    optimistic: true
    entity_category: diagnostic

    turn_on_action:
      - deep_sleep.prevent: chip_deep_sleep
    turn_off_action:
      # Sleep once we reach run_duration uptime, or immediately if already did.
      - deep_sleep.allow: chip_deep_sleep

    # Do not want any turn_on/turn_off actions on boot, only MQTT *commands*.
    restore_mode: DISABLED
    retain: false
    # Disable availability to make switch available even when chip is asleep.
    availability: null
    # Enable retention so that chip gets the value once it is online again.
    command_retain: true
    # State in MQTT will be confusing because esphome won't update it until it
    # is online. This will be confusing in HA, so we drop this.
    assumed_state: true

ota:
  - platform: esphome
    on_end:
      then:
        # If we did an OTA, likely don't need to stay awake anymore.
        - switch.turn_off: stay_awake

logger:
  # Higher log level to reduce power consumption and awake duration.
  level: INFO

# If you have to reflash, do one of the following:
# - set "Keep awake" to ON (lightning) and wait until next wake up, then OTA.
# - reset (EN) 10 times to trigger SAFE MODE, then OTA or flash.
# - hold BOOT and press EN, then release BOOT to enter bootloader mode, then
#   flash. If using web.esphome.io, just hold the BOOT button before INSTALL.
deep_sleep:
  id: chip_deep_sleep
  # Keep in sync with expire_after of important sensors.
  sleep_duration: 10min
  # If we couldn't send data within this interval, sleep anyway.
  run_duration: 30s
  # Sleep even if WiFi or MQTT never became ready. Also means that run_duration
  # starts at boot.
  setup_priority: 799

one_wire:
  - platform: gpio
    pin: GPIO27

sensor:
  - platform: dallas_temp
    # We only have one sensor, but maybe it's faster when addr is known.
    address: 0x4c0000006a0a5d28
    resolution: 10 # 0.25C accuracy, <200ms wait time.
    # We update manually, this is a backup in case a measurement fails.
    update_interval: 5s
    id: temperature
    name: "Temperature" # remember to update MQTT topic below
    # DS18B20 datasheet indicates 85C as an error reading. In general it makes
    # little sense to yield values out of reasonable range.
    filters:
      - clamp:
          min_value: 10
          max_value: 40
          ignore_out_of_range: true
    # Keep the latest value available in HA.
    availability: null
    # But not in MQTT (we subscribe to this topic to know update is delivered).
    retain: false
    expire_after: 11min

  - platform: uptime
    type: seconds
    name: "Wakeup time"
    id: wakeup_time
    accuracy_decimals: 3
    # Keep the latest value available in HA.
    availability: null
    # We call for update manually.
    update_interval: never
    expire_after: 11min

wifi:
  fast_connect: true
  manual_ip: # For faster connection.
    static_ip: 10.26.160.236
    gateway: 10.26.160.1
    subnet: 255.255.255.0

binary_sensor:
  - platform: gpio
    pin: GPIO18 # yellow
    name: "Water level dropped" # remember to update MQTT topic below
    device_class: problem
    filters:
      # XKC-Y25 datasheet: 500ms response time.
      - delayed_on_off: 500ms
    # Keep the latest value available in HA.
    availability: null
    # But not in MQTT (we subscribe to this topic to know update is delivered).
    retain: false

output:
  - platform: gpio
    pin: GPIO19 # black
    id: water_sensor_com
  - platform: gpio
    pin: GPIO5 # brown
    id: water_sensor_power

mqtt:
  on_connect:
    # Not on_boot: if we update before MQTT is ready, that message is lost.
    - component.update: wakeup_time
    - component.update: temperature
  on_message:
    # This is a reflect subscription to our own sensors - when we get a message,
    # it means that we're done with measurement.
    #
    # You can look up the topic in "MQTT INFO" of HA device page.
    - topic: pool/sensor/temperature/state
      then:
        - globals.set:
            id: temperature_published
            value: "true"
        - script.execute: check_and_sleep
    - topic: pool/binary_sensor/water_level_dropped/state
      then:
        - globals.set:
            id: water_presence_published
            value: "true"
        - script.execute: check_and_sleep
