ManuelV
(Manuel Vasco)
March 20, 2024, 4:22pm
1
Hello. I have set a magnetic counter on my home water counter, connected to an ESP32 through ESPHome with the following setup:
esphome:
name: esphome-web-71afe8
friendly_name: ESPHome Pantalla
on_boot:
- homeassistant.service:
service: input_number.set
data:
entity_id: input_number.total_consumo_agua_global
value: !lambda 'return id(total_agua).state;'
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "*****"
ota:
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "****"
password: "****"
captive_portal:
sensor:
- platform: pulse_counter
pin:
number: 19
allow_other_uses: true
update_interval : 6s
name: "pulso agua"
id: pulso_agua
filters:
- multiply: 0.1
- platform: pulse_meter
pin:
number: 19
allow_other_uses: true
name: "Medidor pulsos agua"
unit_of_measurement: "litros/min"
icon: "mdi:water"
total:
name: "Total Agua"
unit_of_measurement: "litros"
filters:
- multiply: 0.1
- platform: template
name: "Flujo de agua"
id: flujo_agua
accuracy_decimals: 1
unit_of_measurement: "l/min"
icon: "mdi:water"
lambda: return (id(pulso_agua).state * 1);
update_interval: 6s
- platform: homeassistant
id: total_agua
entity_id: sensor.esphome_web_71afe8_total_agua
on_value:
then:
- homeassistant.service:
service: input_number.set
data:
entity_id: input_number.total_consumo_agua_global
value: !lambda 'return x;'
- platform: wifi_signal
name: "WiFi ESP"
update_interval: 60s
id: intensidad_wifi_esp
font:
- file: "fonts/roboto.ttf"
id: robotofont
size: 15
- file: "fonts/roboto.ttf"
id: robotofont_large
size: 25
- file: "fonts/roboto.ttf"
id: robotofont_small
size: 12
i2c:
sda: GPIO21
scl: GPIO22
# Añadir el componente de pantalla OLED
display:
- platform: ssd1306_i2c
model: "SSD1306 128x64"
address: 0x3C
reset_pin: GPIO0
lambda: |-
// Imprime "Consumo Total:"
it.print(0, 0, id(robotofont), "Consumo Total:");
// Imprime el valor del sensor "total_agua"
if (id(total_agua).has_state()) {
it.printf(0, 15, id(robotofont_large), "%.0f", id(total_agua).state);
}
// Imprime "Wifi:" un poco más arriba
it.print(0, 50, id(robotofont), "Wifi: ");
// Imprime la intensidad de la señal WiFi como una barra horizontal más gruesa
if (id(intensidad_wifi_esp).has_state()) {
float signal_strength = min(max(2 * (id(intensidad_wifi_esp).state + 100.0), 0.0), 100.0);
for (int i = 0; i < signal_strength / 10; i++) {
it.print(35 + i * 10, 50, id(robotofont_small), "|");
it.print(35 + i * 10, 55, id(robotofont_small), "|");
}
}
The problem is that, if I have a power outage, it starts from zero, so set an input.number in home assistant:
Every time the value of the counter changes, it updates this input number with its value.
If there is a power outage, on boot, the ESP32 should take this value from Home Assistant and start counting from this number.
Besides, it’s not working; the input number is not being updated and if I unplug the device and plug it again it starts from 0.
Could anybody please help me?
You should import the input number from Home Assistant into the device, using this component: Home Assistant Sensor — ESPHome
Then on boot of the esp you should publish the state of the input number to the water sensor. Essentially, exactly the other way around from what you’re doing now.
However, it may be worth taking a look at using a number component: Template Number — ESPHome
These have a restore value setting which should also allow for the esp to restore the state after booting.
1 Like
ManuelV
(Manuel Vasco)
March 21, 2024, 9:54am
3
So I should add a new sensor to esp32:
sensor:
platform: homeassistant
id: total_consumo_agua_global
entity_id: input_number.total_consumo_agua_global
and then modify the begining to:
esphome:
name: esphome-web-71afe8
on_boot:
priority: -10
then:
- lambda: |-
id(total_agua).publish_state(id(total_consumo_agua_global).state);
Is it right? Sorry but I know very little of esp32 and I’m getting help from AI
From what I can see, that should work yes. You should however remove the service call (homeassistant.service
) from your on_boot
automation.
A good way to test if it works is to set the input number to a random value in Home Assistant, and see if the esp indeed sets the sensor to that value at the start. I’d try setting the priority at -100 though.
If it doesn’t work, could you post the output of the logs?
ManuelV
(Manuel Vasco)
March 21, 2024, 10:25am
5
No. Doesn’t work. As soon as it boots, it starts adding pulses (but water is closed) until a random number and then stops, but doesn’t fit the number I set in the input number. I attach the log:
https://justpaste.it/fsgqf
hmm, that it would be weird that it’s already measuring pulses. Could you try putting the display reset pin to a different pin? Using gpio0 can lead to problems since it’s a strapping pin. This site has a handy overview of which pins do what: ESP32 Pinout Reference: Which GPIO pins should you use? | Random Nerd Tutorials
Another thing you could try is, instead of on_boot
, use the api_connected
trigger: Native API Component — ESPHome
And use an if statement to only update the sensor to the input number when the ip is equal to your homeassistant instance.
api:
# ...
on_client_connected:
- if:
condition:
lambda: 'return client_address.c_str() == "x.x.x.x";
then:
- lambda: |-
id(total_agua).publish_state(id(total_consumo_agua_global).state);
I freehanded this a bit, so keep in mind the indentation and stuff may not be fully correct.
ManuelV
(Manuel Vasco)
March 21, 2024, 11:05am
7
No, the screen was soldered so it has to be in PIN 0.
I tried your sugestion and didn’t get the value either:
https://justpaste.it/bu18a
Could you post your current yaml config? Maybe I can find something in that, I don’t currently have the time to test it out on a device of my own.
ManuelV
(Manuel Vasco)
March 21, 2024, 11:17am
9
Of course:
esphome:
name: esphome-web-71afe8
friendly_name: ESPHome Pantalla
# on_boot:
# priority: -100
# then:
# - lambda: |-
# id(total_agua).publish_state(id(total_consumo_agua_global).state);
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
level: DEBUG
# Enable Home Assistant API
api:
encryption:
key: "****"
services:
- service: set_total_agua
variables:
value: float
then:
- lambda: |-
id(total_agua).publish_state(value);
- service: update_total_agua
then:
- lambda: |-
id(total_agua).publish_state(id(total_agua).state);
on_client_connected:
- if:
condition:
lambda: 'return client_address.c_str() == "192.168.0.128";'
then:
- lambda: |-
id(total_agua).publish_state(id(total_consumo_agua_global).state);
ota:
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "****"
password: "****"
captive_portal:
sensor:
- platform: pulse_counter
pin:
number: 19
allow_other_uses: true
update_interval : 6s
name: "pulso agua"
id: pulso_agua
filters:
- multiply: 0.1
- platform: pulse_meter
pin:
number: 19
allow_other_uses: true
name: "Medidor pulsos agua"
unit_of_measurement: "litros/min"
icon: "mdi:water"
total:
name: "Total Agua"
unit_of_measurement: "litros"
filters:
- multiply: 0.1
- platform: template
name: "Flujo de agua"
id: flujo_agua
accuracy_decimals: 1
unit_of_measurement: "l/min"
icon: "mdi:water"
lambda: return (id(pulso_agua).state * 1);
update_interval: 6s
- platform: homeassistant
id: total_agua
entity_id: sensor.esphome_web_71afe8_total_agua
on_value:
then:
- homeassistant.service:
service: input_number.set
data:
entity_id: input_number.total_consumo_agua_global
value: !lambda 'return x;'
- platform: homeassistant
id: total_consumo_agua_global
entity_id: input_number.total_consumo_agua_global
- platform: wifi_signal
name: "WiFi ESP"
update_interval: 60s
id: intensidad_wifi_esp
font:
- file: "fonts/roboto.ttf"
id: robotofont
size: 15
- file: "fonts/roboto.ttf"
id: robotofont_large
size: 25
- file: "fonts/roboto.ttf"
id: robotofont_small
size: 12
i2c:
sda: GPIO21
scl: GPIO22
# Añadir el componente de pantalla OLED
display:
- platform: ssd1306_i2c
model: "SSD1306 128x64"
address: 0x3C
reset_pin: GPIO0
lambda: |-
// Imprime "Consumo Total:"
it.print(0, 0, id(robotofont), "Consumo Total:");
// Imprime el valor del sensor "total_agua"
if (id(total_agua).has_state()) {
it.printf(0, 15, id(robotofont_large), "%.0f", id(total_agua).state);
}
// Imprime "Wifi:" un poco más arriba
it.print(0, 50, id(robotofont), "Wifi: ");
// Imprime la intensidad de la señal WiFi como una barra horizontal más gruesa
if (id(intensidad_wifi_esp).has_state()) {
float signal_strength = min(max(2 * (id(intensidad_wifi_esp).state + 100.0), 0.0), 100.0);
for (int i = 0; i < signal_strength / 10; i++) {
it.print(35 + i * 10, 50, id(robotofont_small), "|");
it.print(35 + i * 10, 55, id(robotofont_small), "|");
}
}
Okay I think this part could be causing the problem. I’d try putting a condition on it that the API has to be connected to Home Assistant.
ManuelV
(Manuel Vasco)
March 21, 2024, 11:36am
11
Something like this?:
- platform: homeassistant
id: total_agua
entity_id: sensor.esphome_web_71afe8_total_agua
on_value:
then:
- if:
condition:
api.connected:
then:
- homeassistant.service:
service: input_number.set
data:
entity_id: input_number.total_consumo_agua_global
value: !lambda 'return x;'
Sorry if being too dumb but I don’t dominate this part at all.
Yeah I think that should work!
Also no worries, we all have to start somewhere with learning. We’ll get to a solution eventually:D
ManuelV
(Manuel Vasco)
March 21, 2024, 12:00pm
13
Thanks for your help. I entered it and doesn’t work either. It doesn’t get the number from the input number in home assistant at boot, but I don’t know why
hmm that’s odd indeed. This started boggling my mind more than I initially expected, but I think I found a thread that deals with a similar problem:
I have a template sensor in ESPhome which I use as counter of the times a button has been pushed:
sensor:
- platform: template
name: "count since reboot"
id: total_count
accuracy_decimals: 0
state_class: "total_increasing"
binary_sensor:
- platform: gpio
id: physical_button
on_click:
- sensor.template.publish:
id: total_count
state: !lambda |-
if (isnan(id(total_count).state)) {
return 1.0;
} else {
r…
So the idea is to use global variables, because those can be restored upon boot:
And I think then, if you want to show it in the front end, you can use a template sensor that simply returns the global, or you can use the on_boot
automation we discussed before, and publish the value of the global. I thought of something like this for the configuration of the global variable:
globals:
- id: total_agua_var
type: float
restore_value: yes
initial_value: '0'
And then use use the pulse sensor to update the global:
- platform: pulse_meter
pin:
number: 19
allow_other_uses: true
name: "Medidor pulsos agua"
unit_of_measurement: "litros/min"
icon: "mdi:water"
id: total_agua_meter
total:
id: total_agua
name: "Total Agua"
unit_of_measurement: "litros"
filters:
- multiply: 0.1
on_value:
then:
- lambda: |-
id(total_agua_var) = id(total_agua).state;
ESP_LOGD(DEBUG, "Updated water consumption global variable to %f", id(total_agua_var));
And the automation like:
on_boot:
then:
- pulse_meter.set_total_pulses:
id: total_agua_meter
value: !lambda 'return id(total_agua_var);'
I hope this works out of the box. It might take some playing around with the configuration though to get everything to play together nicely.
ManuelV
(Manuel Vasco)
March 21, 2024, 6:49pm
15
Well, I may be missing something. I cleaned the config and added what you suggested:
esphome:
name: esphome-web-71afe8
friendly_name: ESPHome Pantalla
on_boot:
then:
- pulse_meter.set_total_pulses:
id: total_agua_meter
value: !lambda 'return id(total_agua_var);'
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "***"
globals:
- id: total_agua_var
type: float
restore_value: yes
initial_value: '0'
ota:
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "***"
password: "***"
captive_portal:
sensor:
- platform: pulse_counter
pin:
number: 19
allow_other_uses: true
update_interval : 6s
name: "pulso agua"
id: pulso_agua
filters:
- multiply: 0.1
- platform: pulse_meter
pin:
number: 19
allow_other_uses: true
name: "Medidor pulsos agua"
unit_of_measurement: "litros/min"
icon: "mdi:water"
id: total_agua_meter
total:
id: total_agua
name: "Total Agua"
unit_of_measurement: "litros"
filters:
- multiply: 0.1
on_value:
then:
- lambda: |-
id(total_agua_var) = id(total_agua).state;
ESP_LOGD(DEBUG, "Updated water consumption global variable to %f", id(total_agua_var));
- platform: template
name: "Flujo de agua"
id: flujo_agua
accuracy_decimals: 1
unit_of_measurement: "l/min"
icon: "mdi:water"
lambda: return (id(pulso_agua).state * 1);
update_interval: 6s
- platform: homeassistant
id: total_agua_ha
entity_id: sensor.esphome_web_71afe8_total_agua
on_value:
then:
- homeassistant.service:
service: input_number.set
data:
entity_id: input_number.total_consumo_agua_global
value: !lambda 'return x;'
- platform: wifi_signal
name: "WiFi ESP"
update_interval: 60s
id: intensidad_wifi_esp
font:
- file: "fonts/roboto.ttf"
id: robotofont
size: 15
- file: "fonts/roboto.ttf"
id: robotofont_large
size: 25
- file: "fonts/roboto.ttf"
id: robotofont_small
size: 12
i2c:
sda: GPIO21
scl: GPIO22
# Añadir el componente de pantalla OLED
display:
- platform: ssd1306_i2c
model: "SSD1306 128x64"
address: 0x3C
reset_pin: GPIO0
lambda: |-
// Imprime "Consumo Total:"
it.print(0, 0, id(robotofont), "Consumo Total:");
// Imprime el valor del sensor "total_agua"
if (id(total_agua).has_state()) {
it.printf(0, 15, id(robotofont_large), "%.0f", id(total_agua).state);
}
// Imprime "Wifi:" un poco más arriba
it.print(0, 50, id(robotofont), "Wifi: ");
// Imprime la intensidad de la señal WiFi como una barra horizontal más gruesa
if (id(intensidad_wifi_esp).has_state()) {
float signal_strength = min(max(2 * (id(intensidad_wifi_esp).state + 100.0), 0.0), 100.0);
for (int i = 0; i < signal_strength / 10; i++) {
it.print(35 + i * 10, 50, id(robotofont_small), "|");
it.print(35 + i * 10, 55, id(robotofont_small), "|");
}
}
And got this error:
ERROR Circular dependency detected! Please run with -v option to see what functions failed to complete.
Edit: don’t know how to run with -v option as I’m using ESPHome in Home Assistant.
I ran it like that, and it seems like esphome treats total_agua
like a variable? I have no clue why however. The logs would simply print the following over and over again:
DEBUG Waiting for variable total_agua
DEBUG Running to_code in esphome.components.pulse_meter.sensor (num 11)
The sensor as defined below would compile. However logic wise you’d have to test if it works. I’m mainly not sure if it would follow the correct state, so you’d have to check that.
- platform: pulse_meter
pin:
number: 19
allow_other_uses: true
name: "Medidor pulsos agua"
unit_of_measurement: "litros/min"
icon: "mdi:water"
id: total_agua_meter
total:
#id: total_agua
name: "Total Agua"
unit_of_measurement: "litros"
filters:
- multiply: 0.1
on_value:
then:
- lambda: |-
if (id(total_agua_var) != id(total_agua_meter).state) {
id(total_agua_var) = id(total_agua_meter).state;
ESP_LOGD("DEBUG", "Updated water consumption global variable to %f", id(total_agua_var));
}
ManuelV
(Manuel Vasco)
March 22, 2024, 11:44am
17
Yes, this way it compiles but it keeps refusing to restore previous value of the global we set.
What’s more, if I try to use the service I set:
service: esphome.esphome_web_71afe8_set_total_agua
data:
value: 282648.9
it is sent but as long as I open the water, the value jumps to a number that I don’t know where it came.
Can you post the logs again? It may also be an idea to compile it with
logger:
level: VERBOSE
It may give more insights in what is going on. I assume somewhere an automation is working back on itself, perhaps. Also, I assume you mean the sensor value is the one that is jumping?
ManuelV
(Manuel Vasco)
March 24, 2024, 6:16pm
19
Of course, and thanks again for taking so much time in helping me:
https://justpaste.it/e7ti0
Could you post it again, but this time when opening the water? The pulse meter hasn’t updated here so it’s not possible to figure out what happens with it when it updates.
Best would be to post logs where you first call the service in home assistant, and then open the water so we can inspect the number and its origins.