Issue with a lambda using the value of a select

Hi all,

I have the following select with an action when the value changes:

  - platform: template
    name: Schedule 2 Program
    id: pump_schedule_2_program
    options:
     - "Standard - 2300 RPM"
     - "Solar Heating - 40 GPM"
     - "Cleaner - 2650 RPM"
     - "Freeze Protect - 1250 RPM"
    initial_option: "Standard - 2300 RPM"
    optimistic: true
    on_value:
      then:
      - lambda: |-
         auto program = i + 1;
         id(pentairpump).commandLocalProgram(program);

Now, this by itself works as defined.

However, I want to use the value (index) of this select elsewhere to run the same action and created the following lambda in a script (note: took out some parts

  - id: egg_timer_check
    then:
      lambda: |-
        if (id(egg_timer_enabled).state)
          {
            auto index = id(egg_timer_program).active_index();
            auto program = index + 1;
            id(pentairpump).run();
            id(pentairpump).commandLocalProgram(program);
          }  

That however gives me the following compiler error:

/config/esphome-pool-heater.yaml: In lambda function:
/config/esphome-pool-heater.yaml:810:32: error: no match for 'operator+' (operand types are 'esphome::optional<unsigned int>' and 'int')
             auto program = index + 1;
                          ~~~~~~^~~
In file included from src/esphome/core/entity_base.h:5,
                 from src/esphome/components/binary_sensor/binary_sensor.h:4,
                 from src/esphome/core/controller.h:5,
                 from src/esphome/components/api/api_server.h:11,
                 from src/esphome/components/api/api_connection.h:8,
                 from src/esphome.h:3,
                 from src/main.cpp:3:
src/esphome/core/string_ref.h:118:20: note: candidate: 'std::__cxx11::string esphome::operator+(const char*, const esphome::StringRef&)'
 inline std::string operator+(const char *lhs, const StringRef &rhs) {
                    ^~~~~~~~
src/esphome/core/string_ref.h:118:20: note:   no known conversion for argument 1 from 'esphome::optional<unsigned int>' to 'const char*'
src/esphome/core/string_ref.h:124:20: note: candidate: 'std::__cxx11::string esphome::operator+(const esphome::StringRef&, const char*)'
 inline std::string operator+(const StringRef &lhs, const char *rhs) {
                    ^~~~~~~~
src/esphome/core/string_ref.h:124:20: note:   no known conversion for argument 1 from 'esphome::optional<unsigned int>' to 'const esphome::StringRef&'
*** [.pioenvs/esphome-pool-heater/src/main.cpp.o] Error 1
========================== [FAILED] Took 4.56 seconds ==========================

Anybody who can help me out here?

Thanks,
B.

Maybe if you post all the yaml instead of just the bits you think are relevant…

1 Like

Hi Daryl,

as it’s a meaty piece of code, I thought of only adding the code that’s giving me problems… But here’s the entire bunch:

esphome:
  name: "esphome-pool-heater"

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:
  level: DEBUG
  logs:
    text_sensor: ERROR

# Enable Home Assistant API
api:

ota:
  platform: esphome

time:
  - platform: sntp
    id: sntp_time
    timezone: America/New_York
    servers:
      - pfsense.deprez.biz
      - 0.pool.ntp.org
      - 1.pool.ntp.org
    on_time_sync:
      - globals.set:
          id: time_synced
          value: "true"
    on_time:
      - seconds: /15
        then:
          - script.execute: ichlor_on_off_script
          - script.execute: pump_schedule_check

wifi:
  ssid: "REDACTED"
  password: "REDACTED"
  manual_ip:
    static_ip: 172.16.10.138
    gateway: 172.16.10.1
    subnet: 255.255.255.0
    dns1: 172.16.10.15
  domain: .REDACTED

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "REDACTED"
    password: "REDACTED"

captive_portal:

external_components:
  - source: github://bdeprez/Pool_Automation@main
    # https://github.com/bdeprez/Pool_Automation/tree/main
    components: [pentair_intelliflo]
    refresh: 0s

uart:
  tx_pin: GPIO17
  rx_pin: GPIO18
  baud_rate: 9600

pentair_intelliflo:
  id: pentairpump

web_server:
  port: 80
  version: 3
  auth:
    username: "REDACTED"
    password: "REDACTED"
  sorting_groups:
    - id: sorting_group_temperatures
      name: "Temperatures"
      sorting_weight: -10
    - id: sorting_group_heating
      name: "Heating"
      sorting_weight: -9
    - id: sorting_group_pump_status
      name: "Pump Status"
      sorting_weight: -20
    - id: sorting_group_pump_schedules
      name: "Pump Schedules"
      sorting_weight: -19
    - id: sorting_group_pump_eggtimer
      name: "Pump Egg Timer"
      sorting_weight: -18
    - id: sorting_group_pump_freezeprotect
      name: "Pump Freeze Protect"
      sorting_weight: -17
    - id: sorting_group_ichlor
      name: "iChlor"
      sorting_weight: -15
    - id: sorting_group_waterfall
      name: "Waterfall"
      sorting_weight: -5
    - id: sorting_group_light
      name: "Light"
      sorting_weight: -4

globals:
  - id: time_synced
    type: bool
    restore_value: no
    initial_value: "false"
  # pump mode: 0: inactive, 1: sched 1, 2: sched 2, 3: eggtimer, 4: freezeprotect, (9:always_on)
  - id: pump_mode
    type: int
    restore_value: yes
    initial_value: "0"
  # to count timestamp when the pump was started
  - id: pump_running_timestamp
    type: long int
    restore_value: no
    initial_value: "0"
  # to count timestamp when the pump has been stopped
  - id: pump_stopped_timestamp
    type: long int
    restore_value: no
    initial_value: "0"
  - id: egg_timer_start_timestamp
    type: long int
    restore_value: no
    initial_value: "0"
  - id: pump_running_for
    type: long int
    restore_value: no
    initial_value: "0"
  - id: pump_stopped_for
    type: long int
    restore_value: no
    initial_value: "0"
  - id: egg_timer_check_script_result
    type: bool
    restore_value: no
  - id: freeze_protect_check_script_result
    type: bool
    restore_value: no
  - id: schedule_1_check_script_result
    type: bool
    restore_value: no
  - id: schedule_2_check_script_result
    type: bool
    restore_value: no
  - id: schedule_1_current_program
    type: int
    restore_value: yes
    initial_value: "1"
  - id: schedule_1_new_program
    type: int
    restore_value: yes
    initial_value: "1"
  - id: schedule_2_current_program
    type: int
    restore_value: yes
    initial_value: "1"
  - id: schedule_2_new_program
    type: int
    restore_value: yes
    initial_value: "1"    
  - id: egg_timer_current_program
    type: int
    restore_value: yes
    initial_value: "3"
  - id: egg_timer_new_program
    type: int
    restore_value: yes
    initial_value: "3"
  - id: freeze_protect_current_program
    type: int
    restore_value: yes
    initial_value: "4"
  - id: freeze_protect_new_program
    type: int
    restore_value: yes
    initial_value: "4"

sensor:
  - platform: wifi_signal
    name: "WiFi Signal"
    id: wifi_signal_db
    update_interval: 60s
    entity_category: diagnostic

  # Reports the WiFi signal strength in %
  - platform: copy
    source_id: wifi_signal_db
    name: "WiFi Strength"
    filters:
      - lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
    unit_of_measurement: "%"
    entity_category: diagnostic

#  - platform: pentair_intelliflo
#    power:
#      id: pump_power
#      name: "Power"
#      web_server:
#        sorting_group_id: sorting_group_pump_status
#        sorting_weight: 4      
#    rpm:
#      id: pump_rpm
#      name: "RPM"
#      unit_of_measurement: 'RPM'
#      web_server:
#        sorting_group_id: sorting_group_pump_status
#        sorting_weight: 5
#    flow:
#      id: pump_gpm
#      name: "GPM"
#      unit_of_measurement: gal/min
#      web_server:
#        sorting_group_id: sorting_group_pump_status
#        sorting_weight: 6

# !!! TEMP !!! POOL & ROOF TEMP - removed for testing purposes
  #Pool sensor voltages
#  - platform: ads1115
#    multiplexer: 'A0_GND'
#    gain: 4.096
#    update_interval: 30s
#    id: pool_voltage
#    name: "Pool Sensor Voltage"
#  - platform: ads1115
#    multiplexer: 'A1_GND'
#    gain: 4.096
#    update_interval: 30s
#    id: roof_voltage
#    name: "Roof Sensor Voltage"

  #Pool sensor resistance
#  - platform: resistance
#    id: pool_resistance
#    sensor: pool_voltage
#    configuration: DOWNSTREAM
#    resistor: 9.6kOhm
#    name: Pool Resistance

#  - platform: resistance
#    id: roof_resistance
#    sensor: roof_voltage
#    configuration: DOWNSTREAM
#    resistor: 9.6kOhm
#    name: Roof Resistance

  #Pool sensor temperatures
  # https://esphome.io/components/sensor/ntc.html#ntc-sensor
# !!! TEMP !!! POOL & ROOF TEMP - removed for testing purposes
#  - platform: ntc
#    id: pool_temp_c
#    name: Pool Temperature C
#    sensor: pool_resistance
#    calibration:
#      - 10.0kOhm -> 25°C
#      - 32.648kOhm -> 0°C
#      - 15.711kOhm -> 15°C
#    web_server:
#      sorting_group_id: sorting_group_temperatures
#      sorting_weight: 10

#  - platform: copy
#    source_id: pool_temp_c
#    id: pool_temp_f
#    name: Pool Temperature F
#    filters:
#      - lambda: return (x * 9/5) + 32;
#    unit_of_measurement: °F
#    web_server:
#      sorting_group_id: sorting_group_temperatures
#      sorting_weight: 12

#  - platform: ntc
#    id: roof_temp_c
#    name: Roof Temperature C
#    sensor: roof_resistance
#    calibration:
#      - 10.0kOhm -> 25°C
#      - 32.648kOhm -> 0°C
#      - 15.711kOhm -> 15°C
#    web_server:
#      sorting_group_id: sorting_group_temperatures
#      sorting_weight: 11

#  - platform: copy
#    source_id: roof_temp_c
#    id: roof_temp_f
#    name: Roof Temperature F
#    filters: 
#       - lambda: return (x * 9/5) + 32;
#    web_server:
#      sorting_group_id: sorting_group_temperatures
#      sorting_weight: 13

number:
  # Pool Heating - target temperature
  - platform: template
    name: Target Temperature
    optimistic: True
    restore_value: True
    initial_value: 30
    id: target_temperature
    update_interval: never
    min_value: 25
    max_value: 35
    step: 1
    device_class: temperature
    unit_of_measurement: °C
    icon: mdi:coolant-temperature
    mode: SLIDER
    web_server:
      sorting_group_id: sorting_group_heating
      sorting_weight: 6    

  # Home Assistant - Outdoor Temperature
  - platform: homeassistant
    id: ha_outdoor_temp_feels_like
    entity_id: sensor.tempest_ws_feels_like
  - platform: homeassistant
    id: ha_outdoor_temp
    entity_id: sensor.tempest_ws_temperature

  # Freeze Protect  - Start temperature
  - platform: template
    name: Freeze Protect Temp
    optimistic: True
    restore_value: True
    initial_value: 30
    id: freeze_protect_temperature
    update_interval: never
    min_value: 0
    max_value: 5
    step: 0.1
    device_class: temperature
    unit_of_measurement: °C
    icon: mdi:coolant-temperature
    mode: SLIDER
    web_server:
      sorting_group_id: sorting_group_pump_freezeprotect
      sorting_weight: 2

  # EGG TIMER duration
  - platform: template
    name: Egg Timer Duration
    id: egg_timer_duration
    min_value: 15
    max_value: 300
    step: 30
    initial_value: 60
    optimistic: True
    unit_of_measurement: min
    mode: SLIDER
    web_server:
      sorting_group_id: sorting_group_pump_eggtimer
      sorting_weight: 2

  # !!! TEMP !!! POOL & ROOF TEMP - added for testing purposes
  - platform: template
    name: Pool Temperature C
    id: pool_temp_C
    min_value: 25
    max_value: 35
    step: 1
    initial_value: 25
    optimistic: True
    unit_of_measurement: °C
    mode: SLIDER
    web_server:
      sorting_group_id: sorting_group_heating
      sorting_weight: 1
  # !!! TEMP !!! POOL & ROOF TEMP
  - platform: template
    name: Roof Temperature C
    id: roof_temp_C
    min_value: 25
    max_value: 35
    step: 1
    initial_value: 25
    optimistic: True
    unit_of_measurement: °C
    mode: SLIDER
    web_server:
      sorting_group_id: sorting_group_heating
      sorting_weight: 2

###DATETIME TIMES###
datetime:
  - platform: template
    id: pump_sched_1_start
    type: time
    name: Schedule 1 Start Time
    optimistic: yes
    initial_value: "08:00:00"
    restore_value: true
    web_server:
      sorting_group_id: sorting_group_pump_schedules
      sorting_weight: 2    
  - platform: template
    id: pump_sched_1_end
    type: time
    name: Schedule 1 End Time
    optimistic: yes
    initial_value: "18:00:00"
    restore_value: true
    web_server:
      sorting_group_id: sorting_group_pump_schedules
      sorting_weight: 3
  - platform: template
    id: pump_sched_2_start
    type: time
    name: Schedule 2 Start Time
    optimistic: yes
    initial_value: "08:00:00"
    restore_value: true
    web_server:
      sorting_group_id: sorting_group_pump_schedules
      sorting_weight: 6
  - platform: template
    id: pump_sched_2_end
    type: time
    name: Schedule 2 End Time
    optimistic: yes
    initial_value: "18:00:00"
    restore_value: true
    web_server:
      sorting_group_id: sorting_group_pump_schedules
      sorting_weight: 7
  - platform: template
    id: waterfall_sched_start
    type: time
    name: Waterfall Start Time
    optimistic: yes
    initial_value: "08:00:00"
    restore_value: true
    web_server:
      sorting_group_id: sorting_group_waterfall
      sorting_weight: 4
  - platform: template
    id: waterfall_sched_end
    type: time
    name: Waterfall End Time
    optimistic: yes
    initial_value: "08:05:00"
    restore_value: true    
    web_server:
      sorting_group_id: sorting_group_waterfall
      sorting_weight: 5

button:
# !!! TEMP !!! added only for testing purposes
  - platform: template
    id: pump_run_button
    name: "Pump Run Button"
    on_press: 
      then:
        if:
          condition:
            - binary_sensor.is_on: pump_running_status
          then:
            lambda: |-
              id(pump_running_status).publish_state(false);
          else:
            lambda: |-
              id(pump_running_status).publish_state(true);

  - platform: restart
    name: "Restart"
    id: restart_button
    entity_category: config

binary_sensor:

#  - platform: pentair_intelliflo
#    running:
#      name: "Pump Running"
#      id: pump_running_status
#      web_server:
#        sorting_group_id: sorting_group_pump_status
#        sorting_weight: 2
  - platform: template ## replace with above on PRD ##
    id: pump_running_status
    name: "Pump Running"
    device_class: running
    on_state: 
      then:
        - if: 
            condition:
              - binary_sensor.is_on: pump_running_status
            then:
              lambda: |-
                id(pump_running_timestamp) = id(sntp_time).now().timestamp;
                ESP_LOGD("TEST", "Pump running timestamp set to: ", id(pump_running_timestamp));
            else:
              lambda: |-
                id(pump_stopped_timestamp) = id(sntp_time).now().timestamp;
                ESP_LOGD("TEST", "Pump stopped timestamp set to: ", id(pump_stopped_timestamp));
    web_server:
      sorting_group_id: sorting_group_pump_status
      sorting_weight: 2
  - platform: copy
    id: pump_running_status_copy
    source_id: pump_running_status

switch:
  # Pump enabled/disabled
  - platform: template
    id: pump_enabled
    name: "Pump Enabled"
    restore_mode: RESTORE_DEFAULT_ON
    optimistic: True
    web_server:
      sorting_group_id: sorting_group_pump_status
      sorting_weight: 1
    on_turn_on:
      then:
      - lambda: |-
          id(pentairpump).run();
#      - text_sensor.template.publish:
#          id: last_action
#          state: "Pump ON"
    on_turn_off:
      then:
      - lambda: |-
          id(pentairpump).stop();
#      - text_sensor.template.publish:
#          id: last_action
#          state: "Pump OFF"

  # Schedule 1 enabled
  - platform: template
    id: schedule_1_enabled
    name: "Schedule 1 Enabled"
    restore_mode: RESTORE_DEFAULT_ON
    optimistic: True
    web_server:
      sorting_group_id: sorting_group_pump_schedules
      sorting_weight: 1

  # Schedule 2 enabled
  - platform: template
    id: schedule_2_enabled
    name: "Schedule 2 Enabled"
    restore_mode: RESTORE_DEFAULT_OFF
    optimistic: True
    web_server:
      sorting_group_id: sorting_group_pump_schedules
      sorting_weight: 5

  # Egg Timer enabled
  - platform: template
    id: egg_timer_enabled
    name: "Egg Timer Enabled"
    restore_mode: RESTORE_DEFAULT_OFF
    optimistic: True
    web_server:
      sorting_group_id: sorting_group_pump_eggtimer
      sorting_weight: 1

  # Freeze Protect enabled
  - platform: template
    id: freeze_protect_enabled
    name: "Freeze Protect Enabled"
    restore_mode: RESTORE_DEFAULT_ON
    optimistic: True
    web_server:
      sorting_group_id: sorting_group_pump_freezeprotect
      sorting_weight: 11

  # iChlor switches
  # !!! TEMP !!! added for testing purposes
  - platform: template
    id: iChlor_enabled
    name: "iChlor enabled"
#    on_turn_on:
#      - text_sensor.template.publish:
#          id: last_action
#          state: "iChlor ON"
#    on_turn_off:
#      - text_sensor.template.publish:
#          id: last_action
#          state: "iChlor OFF"
    restore_mode: RESTORE_DEFAULT_OFF
    optimistic: True
    web_server:
      sorting_group_id: sorting_group_ichlor
      sorting_weight: 9
  # !!! TEMP !!! commented for testing purposes
#  - platform: gpio
#    pin:
#      number: GPIO45
#      ignore_strapping_warning: true
#    id: relay5
#    name: iChlor L2
#    internal: True
#  - platform: gpio
#    pin:
#      number: GPIO46
#      ignore_strapping_warning: true
#    id: relay6
#    name: iChlor L1
#    internal: True
  - platform: template
    id: iChlor_relay
    name: "iChlor"
#    on_turn_on:
#      - text_sensor.template.publish:
#          id: last_action
#          state: "iChlor ON"
#    on_turn_off:
#      - text_sensor.template.publish:
#          id: last_action
#          state: "iChlor OFF"
    restore_mode: RESTORE_DEFAULT_OFF
    optimistic: True
    web_server:
      sorting_group_id: sorting_group_ichlor
      sorting_weight: 10

  # Switch to enable / disable heating
  - platform: template
    id: heating_enabled
    name: "Heating Enabled"
    optimistic: True
    restore_mode: RESTORE_DEFAULT_ON
    web_server:
      sorting_group_id: sorting_group_heating
      sorting_weight: 5

  # Heater Relay Switch
  - platform: gpio
    pin: GPIO2
    id: heater_relay
    name: Heater Valve
    restore_mode: RESTORE_DEFAULT_OFF
#    on_turn_on: 
#      then:
#        - text_sensor.template.publish:
#            id: last_action
#            state: "Heater Valve OPENED"
#    on_turn_off: 
#      then:
#        - text_sensor.template.publish:
#            id: last_action
#            state: "Heater Valve CLOSED"
    web_server:
      sorting_group_id: sorting_group_heating
      sorting_weight: 7

  # Waterfall Relay Switch
  # !!! TEMP !!! removed for testing purposes
#  - platform: gpio
#    pin: GPIO41
  # !!! TEMP !!! added for testing purposes
  - platform: template
    id: waterfall_relay
    name: Waterfall valve
    restore_mode: RESTORE_DEFAULT_OFF
#    on_turn_on: 
#      then:
#        - text_sensor.template.publish:
#            id: last_action
#            state: "Waterfall Valve OPENED"
#    on_turn_off: 
#      then:
#        - text_sensor.template.publish:
#            id: last_action
#            state: "Waterfall Valve CLOSED"
    optimistic: True ### REMOVE ON PROD ###
    web_server:
      sorting_group_id: sorting_group_waterfall
      sorting_weight: 2

  # Switch to enable / disable waterfall
  - platform: template
    id: waterfall_enabled
    name: "Waterfall Enabled"
    optimistic: True
    restore_mode: RESTORE_DEFAULT_OFF
    web_server:
      sorting_group_id: sorting_group_waterfall
      sorting_weight: 1

  # Waterfall Schedule enabled
  - platform: template
    id: waterfall_schedule_enabled
    name: "Watefall Schedule Enabled"
    restore_mode: RESTORE_DEFAULT_OFF
    optimistic: True
    web_server:
      sorting_group_id: sorting_group_waterfall
      sorting_weight: 3

  # Waterfall Schedule enabled
  - platform: template
    id: waterfall_always_on
    name: "Watefall Always On"
    restore_mode: RESTORE_DEFAULT_OFF
    optimistic: True
    web_server:
      sorting_group_id: sorting_group_waterfall
      sorting_weight: 6

  # Light Relay Switch
#  - platform: gpio
#    pin: GPIO42
  - platform: template
    id: light_relay
    name: Light
    restore_mode: RESTORE_DEFAULT_OFF
    on_turn_on: 
      then:
        - text_sensor.template.publish:
            id: last_action
            state: "Light ON"
    on_turn_off: 
      then:
        - text_sensor.template.publish:
            id: last_action
            state: "Light OFF"
    optimistic: True ### REMOVE ON PROD ###
    web_server:
      sorting_group_id: sorting_group_light
      sorting_weight: 10

select:
  # To select Pump program
  - platform: template
    name: Schedule 1 Program
    id: pump_schedule_1_program
    options:
     - "Standard - 2300 RPM"
     - "Solar Heating - 40 GPM"
     - "Cleaner - 2650 RPM"
     - "Freeze Protect - 1000 RPM"
    initial_option: "Standard - 2300 RPM"
    restore_value: True
    optimistic: true
    on_value:
      then:
      - lambda: |-
         auto program = i + 1;
         id(pentairpump).commandLocalProgram(program);
    web_server:
      sorting_group_id: sorting_group_pump_schedules
      sorting_weight: 4

  - platform: template
    name: Schedule 2 Program
    id: pump_schedule_2_program
    options:
     - "Standard - 2300 RPM"
     - "Solar Heating - 40 GPM"
     - "Cleaner - 2650 RPM"
     - "Freeze Protect - 1000 RPM"
    initial_option: "Standard - 2300 RPM"
    restore_value: True
    optimistic: true
#    on_value:
#      then:
#      - lambda: |-
#         auto program = i + 1;
#         id(pentairpump).commandLocalProgram(program);
    web_server:
      sorting_group_id: sorting_group_pump_schedules
      sorting_weight: 8

  # To select Timer program
  - platform: template
    name: Egg Timer Program
    id: egg_timer_program
    options:
     - "Standard - 2300 RPM"
     - "Solar Heating - 40 GPM"
     - "Cleaner - 2650 RPM"
     - "Freeze Protect - 1250 RPM"
    initial_option: "Cleaner - 2650 RPM"
    restore_value: True
    optimistic: true
    web_server:
      sorting_group_id: sorting_group_pump_eggtimer
      sorting_weight: 3

  # To select Freeze protect program
  - platform: template
    name: Freeze Protect Program
    id: freeze_protect_program
    options:
     - "Standard - 2300 RPM"
     - "Solar Heating - 40 GPM"
     - "Cleaner - 2650 RPM"
     - "Freeze Protect - 1250 RPM"
    initial_option: "Freeze Protect - 1250 RPM"
    restore_value: True
    optimistic: true
    web_server:
      sorting_group_id: sorting_group_pump_eggtimer
      sorting_weight: 3

text_sensor:
  - platform: version
    name: "ESPHome Version"
  - platform: wifi_info
    ip_address:
      name: "IP Address"
      entity_category: diagnostic
    ssid:
      name: "Connected SSID"
      entity_category: diagnostic
    mac_address:
      name: "Mac Address"
      entity_category: diagnostic

  # https://esphome.io/components/text_sensor/template.html
  - platform: template
    id: last_action
    name: Last Action
    icon: mdi:message
    lambda: return {"System Started"};
    update_interval: never
  - platform: template
    id: pump_mode_text
    name: Pump Mode
    icon: mdi:message
    lambda: |-
      switch(id(pump_mode)) {
        case 0: return std::string("Inactive");
        case 1: return std::string("Schedule 1");
        case 2: return std::string("Schedule 2");
        case 3: return std::string("Egg Timer");
        case 4: return std::string("Freeze Protect");
        //case 9: return std::string("Always On");
        default: return std::string("No Known Mode");
      }
    update_interval: 1s
    web_server:
      sorting_group_id: sorting_group_pump_status
      sorting_weight: 3

script:
  - id: pump_schedule_check
    then:
      lambda: |-
        if (id(time_synced))
          {
            switch (id(pump_mode))
              {
                // (inactive)
                case 0:
                  if (id(pump_enabled).state)
                    {
                      id(egg_timer_check).execute();
                    }
                  else
                    {
                      
                    }
                //run  egg_timer_check
                //if schedule_1_enabled
                //  then run schedule_1_check  
              }
          }

  - id: egg_timer_check
    then:
      lambda: |-
        if (id(egg_timer_enabled).state)
          {
            auto index = id(egg_timer_program).active_index();
            auto program = index + 1;
            id(pentairpump).run();
            id(pentairpump).commandLocalProgram(program);
          }        

  - id: schedule_1_check
    then:
      lambda: |-
        if (id(schedule_1_enabled).state)
          {
            auto current_time = (id(sntp_time).now().hour * 3600) + (id(sntp_time).now().minute * 00) + (id(sntp_time).now().second);
            auto schedule_start_time_seconds = (id(pump_sched_1_start).hour * 3600) + (id(pump_sched_1_start).minute * 60) + id(pump_sched_1_start).second;
            auto schedule_end_time_seconds = (id(pump_sched_1_end).hour * 3600) + (id(pump_sched_1_end).minute * 60) + id(pump_sched_1_end).second;
            if (current_time >= schedule_start_time_seconds < schedule_end_time_seconds)
              {
                id(pump_mode) = 1;
              }
          } 

  - id: schedule_2_check
    then:
      lambda: |-
        if (id(schedule_2_enabled).state)
          {
            auto current_time = id(sntp_time).now().timestamp;
            auto schedule_start_time_seconds = (id(pump_sched_2_start).hour * 3600) + (id(pump_sched_2_start).minute * 60) + id(pump_sched_2_start).second;
            auto schedule_end_time_seconds = (id(pump_sched_2_end).hour * 3600) + (id(pump_sched_2_end).minute * 60) + id(pump_sched_2_end).second;
            if (current_time >= schedule_start_time_seconds < schedule_end_time_seconds)
              {
                id(pump_mode) = 2;
              }
          } 

#  - id: freeze_protect_script
#    then:
#      lambda: |-


  - id: ichlor_on_off_script # Triggered every minute from Time 
    then:
      lambda: |-
        //if (id(homeassistant_time).now().timestamp.is_valid())
        if (id(sntp_time).now().is_valid())
          {
            // get current time
            auto current_time = id(sntp_time).now().timestamp;
            // check if pump is running
            if (id(pump_running_status).state == true)
              // pump is running
              {
                if (id(iChlor_relay).state == false)
                  // iChlor is off
                  {
                    id(pump_running_for) = difftime((current_time), id(pump_running_timestamp));
                    ESP_LOGD("TEST", "Pump running for: %d", id(pump_running_for));
                    if (id(pump_running_for) >= 60) 
                      {
                        id(iChlor_relay).turn_on();
                        ESP_LOGD("TEST", "iChlor turned on");
                      }
                  }
              }
              // pump is not running
              else
              {
                if (id(iChlor_relay).state == true)
                  // iChlor is on
                  {
                    id(pump_stopped_for) = difftime((current_time), id(pump_stopped_timestamp));
                    ESP_LOGD("TEST", "Pump stopped for: %d", id(pump_stopped_for));
                    if (id(pump_stopped_for) >= 60) 
                      {
                        id(iChlor_relay).turn_off();
                        ESP_LOGD("TEST", "iChlor turned off");
                      }
                  }
              }
          }

Note: this version of the code is for testing purposes as I cannot use the target device without taking the current systems out without rewiring. So I’m simulating a number of sensors with manual workarounds for testing.

Thanks!
B.

because you need .active_index().value() + 1

Look at the documentation example:

auto index = id(my_select).active_index();
if (index.has_value()) {
  ESP_LOGI("main", "Option at index %d is active", index.value());
} else {
  ESP_LOGI("main", "No option is active");
}

Brilliant, I totally overlooked that - thank you @Karosm

Sorry for my delayed response - have been busy work-wise so hadn’t gotten around to work on this till now.

B.

1 Like

No problem. I’m pleased to get any response, sooner or later. Not always the case…

Sorry isnt going to cut it around here for me, sir!! Next time your going to be late, we expect you to show up with some breakfast sandwiches or some donuts because we can’t eat “sorry’s” “traffic was bad”, etc excuses!!! Dang rookies!! ; )

Jk dude… Did you happen to mention what it is your making? Im just curious.

As my recent pool controller (the Pentair Intelliconnect) which I installed in May of 2020 died, the pool guys’ only suggestion was to upgrade to the more expensive ones and I was not going to shell out 2.3K dollars for something that’s pretty simple, really.

So, with the experience of my previous adventure (see: How I added a Hayward solar pool control to HA via ESPhome) I decided to build one myself.
I’ve so far been able to create a setup that controls the pump, pool solar heating, waterfall and the light. Currently the chlorinator is only partially integrated in where I can power it on/off and it’s still relying on the RS485 connection to the pump to know if there’s flow. I am struggling massively to create the code to fully integrate so I can update the output percentage.

I’m working on a write-up of what I accomplished so far, hoping somebody may be interested in helping out with the chlorinator. Write-up now published New Pentair pool automation setup – full write-up

Well that’s no surprise! I bet he was kind enough to let you pay him to so it for you too lol.

FYI back when i worked in landscaping and construction in general, things like pools or luxury cars were signs to us that the price was gonna get jacked up when it didnt look like people would miss an extra 500$ or so. Thats capitalism for ya though…

In the future you shouod borrow someone’s hooptie Ford Taurus and park it in the driveway and pretend your just house sitting and need to fix something you messed up or some similar story if you dont want contractors to tack on an extra 25% just because they think you wont want to negotiate the difference, or do what what you want, its just a tip.

Im busy for a couple more hours but, ill check it out and see if i can help ya out! You’re still at the same address, right? Just want to verify where i need to send my bill for tech support!

; )

1 Like