How to pass a variable from Home Assistant front end to ESPHome?

I have an ESP32 controlling all aspects of my koi pond.

I have a few timers and variables to manage water changes, water levels etc.

Changing these will be much faster and more user friendly if I could pass a value from a HA slider to a global variable in ESPHome.

My thinking is to:

  1. Create an input_number in HA.
  2. Convert the integer to text.
  3. Receive it into ESPHome using HomeAssistant text sensor.
  4. Convert text to integer.
  5. Set ESPHome global variable to integer value.

(2.) and (4.) are the ones I’m struggling with.

Is there a way to go straight from (1.) to (5.), avoiding the conversions?

Can this be done? If so how?

Any suggestions?

It’s amazing how posting the problem changes my thinking and solves the problem. Here’s the solution below for anyone else with this issue.

In HA, define your input numbers:



koi_water_change:
  name: Water change litres
  icon: mdi:water
  initial: 1000
  min: 0
  max: 1200
  step: 100

drum_wash_timer:
  name: Drum wash time
  icon: mdi:timer
  initial: 5
  min: 0
  max: 20
  step: 1

spindrifter_off_timer:
  name: Spindrifter off timer
  icon: mdi:timer
  initial: 5
  min: 0
  max: 20
  step: 1

Next, define sensor template using the input_numbers:

- platform: template
  sensors:
    koi_water_change:
      value_template: '{{ states.input_number.koi_water_change.state | int }}'
    drum_wash_timer:
      value_template: '{{ states.input_number.drum_wash_timer.state | int }}'
    spindrifter_off_timer:
      value_template: '{{ states.input_number.spindrifter_off_timer.state | int }}'

Lastly, in ESPHome, define the homeassistant sensors:

  - platform: homeassistant
    name: "Water change litres"
    entity_id: sensor.koi_water_change
  
  - platform: homeassistant
    name: "Drum wash timer"
    entity_id: sensor.drum_wash_timer
  
  - platform: homeassistant
    name: "Spindrifter off timer"
    entity_id: sensor.spindrifter_off_timer

Then use the sensor in your ESPHome automation:

        - lambda: |-        
            delay(id("Spindrifter off timer")*60);
6 Likes

Seems I was a little hasty:

The following compiles fine but when called has a delay of 0 seconds. When called again, the device stops responding.

The “Spindrifter off timer” sensor has the correct value (it can be seen in the webserver.

Any ideas?

because you’ve put delay in a lambda, you’re actually calling the C++ delay function, which takes milliseconds as a parameter. That’s probably why it seems so short. I’m not sure this is a good idea in ESPHome code. You may actually be crashing your ESP32 as delays interfere with ESP watchdog timers and WiFi processing.

Maybe try coding it in yaml, i.e. using an ESPHome delay. Note the ESPHome delay is a non-blocking, i.e. other code will run in the background.

Thanks. Yes, you’re correct there. It is crashing it.

I was using the delay in initial testing and all is fine, but I need to be able to adjust the length of the delay from HA, and that is where I am stuck.

The values are being passed from HA to ESPhome OK, I just can’t find a way to assign them as variables to use in the delay.

Any ideas?

Just give your home assistant sensors an ID, e.g. for your drum wash timer

sensor:
  - platform: homeassistant
    name: "Drum wash timer"
    entity_id: sensor.drum_wash_timer
    id: my_drum_wash_timer

then you can refer to it in an action

on_...:
  then:
    - switch.turn_on: relay_1
    - delay: !lambda 'return id(my_drum_wash_timer).state;'
    - switch.turn_off: relay_1
2 Likes

Thank you, Pat. I tried that already with no success. I’ll certainly give it another go.

With the delay like that, does it evaluate as seconds?

The docs say it has to have units like - delay: 2s, - delay: 2m. I think that is where it is failing.

oh yeah, sorry, when delay is templated like this, it assumes milliseconds, so assuming your delays are in seconds, multiply by 1000 as per the example in the docs, so

on_...:
  then:
    - switch.turn_on: relay_1
    - delay: !lambda 'return id(my_drum_wash_timer).state * 1000;'
    - switch.turn_off: relay_1
4 Likes

Brilliant! That’s the piece of info I’ve been missing all along.

I’ll give it a try now.

Genius! It works. Thank you so much.

1 Like

that’s great. Please mark as solution!

1 Like

@ashscott Hi, could you send new config?
I have same issue. I need set one variable from both sides - HA and ESP.

Sure.

What specifically, do you need?

I still don’t know how to pass value to ESP and back to HA when i change value in ESP.

You just use:

delay: !lambda ‘return id(my_drum_wash_timer).state * 1000;’

to get it into ESPHome.

A value coming back the other way is just reading the sensor or counter etc in HA.

I use values for different purpose. I don’t need delay. I need set temperature on both sides (HA & ESP).
It’s not general thermostat. It’s solar panel controller (hot water system).
I need set remotely and localy difference temperature for turn on the pump.
Could you refresh your second post in this thread?

Apart from the delay, it’s all identical.

Is this the sort of thing you are looking for:

  - platform: template
    name: "Boiler running"
    id: boiler_running
    lambda: |-
      if (id(boiler_output_temperature).state > 30) {
        return true;
      } else {
        return false;
      }
    on_press:
      then:
        switch.turn_on: boiler_on_led

You could substitute the ‘30’ for a sensor value derived from an input_number, as in my post #2.

Have a read of this. You can then see the template sensor you publish to in HA.

1 Like

@ ashscott Thank you! That is excactly what I was struggling with.

Heya
Wrote a little instructable with a little project I done passing variables from home aasistant to esphomehttps://www.instructables.com/id/ESPHOME-SONOF-S26-Timed-Light/

1 Like

Can you pass a value from one esphome node to another?
I want to set the value of a binary_sensor on esphome node1 based on a value from esphome node2

Thanks in advance for your help