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.
ManuelV
(Manuel Vasco)
March 26, 2024, 10:31am
21
Absolutely. I have upload both files in this folder:
https://file.io/gUVpAPRNvR2L
It somehow sumed 2.177.719,9 liters in a week, so it is not only reading the variables but suming like a crazy.
I think that is due to something being wrong with the meter itself. There are a couple of entries like 'Medidor pulsos agua': Sending state 2162.94165 litros/min with 2 decimals of accuracy
, so over the course of a week that would sum up quite rapidly. Also keep in mind it does not have any filters applied yet (see the documentation: Pulse Meter Sensor — ESPHome )
Aside from that, I found this thread: ESPHome total meter - #7 by danielw
What’s mainly important is that the way we’re currently trying to solve it would likely result in your ESP needing replacement relatively soon.
So, less than ideal, but I think taking a few steps back is best, and configuring the solution mainly using an automation in Home Assistant.
My idea would be having an automation that triggers on a new value of the total water sensor, and writes that to an input number, only if the new value is higher than the previous one (using trigger templates, that’s not too hard. Let me know if you’d need help with that). And on the ESP, you’d want a service that can set the total water value. If the new value of the sensor is lower (i.e. 0, meaning a restart of the ESP), Home Assistant should call the service with the retained value of the input number.
ManuelV
(Manuel Vasco)
March 26, 2024, 5:40pm
23
Sounds good to me, but my initial approach was taken of a tutorial, so the latter modifications were thanks to some ideas and mainly by yours, I’m not sure if I would know how to do it (more than asking for help to chatgpt and then by depuring mistakes).
Besides, you have used a lot of your time in helping me and I don’t want to bother you more. I’m gonna take a read to your links, try with chatgpt and then, if I can’t success, will come here again, if you please.
Thanks!!
1 Like
Alright, good luck! And of course you’re free to come back here if you run into new problems you can’t solve!
ManuelV
(Manuel Vasco)
March 27, 2024, 1:35pm
25
Well, I created an input_number.total_consumo_agua_global in which I entered the real consumption in this moment.
Then I created an automation in home assistant:
alias: Actualizar consumo total de agua
description: ""
trigger:
- platform: state
entity_id:
- sensor.esphome_web_71afe8_total_agua
condition:
- condition: template
value_template: >-
"{{ trigger.to_state.state | float >
states('input_number.total_consumo_agua_global') | float }}"
action:
- service: input_number.set_value
target:
entity_id: input_number.total_consumo_agua_global
data:
value: "{{ trigger.to_state.state }}"
mode: single
And then added this in espHome:
api:
services:
- service: set_total_agua
variables:
value: float
then:
- lambda: |-
id(total_agua).publish_state(value);
Still doesn’t update the input number in HA and doesn’t take it at boot. It booted with 734 l., I wasted water for ten seconds and it went up to 1261 l.
ManuelV
(Manuel Vasco)
March 27, 2024, 6:39pm
26
I’m trying a different approach. This is my new configuration:
substitutions:
name: esphome-web-71afe8
friendly_name: ESPHome Pantalla
packages:
esphome.bluetooth-proxy: github://esphome/firmware/bluetooth-proxy/esp32-generic.yaml@main
esphome:
name: ${name}
name_add_mac_suffix: false
friendly_name: ${friendly_name}
on_boot:
priority: -10
then:
- while:
condition:
not:
api.connected:
then:
- delay: 1s
- script.execute: get_ha_var
script:
- id: get_ha_var
then:
- lambda: |-
int new_total = round(id(ha_total_consumo_agua_global).state);
id(total_agua_meter).set_total_pulses(new_total);
esp32:
board: esp32dev
framework:
type: arduino
logger:
level: VERBOSE
# Enable Home Assistant
api:
encryption:
key: ***
services:
- service: set_total_agua
variables:
value: int
then:
- lambda: |-
id(total_agua).publish_state(value);
- service: set_total
variables:
new_total: int
then:
- pulse_meter.set_total_pulses:
id: total_agua_meter
value: !lambda 'return new_total;'
ota:
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
manual_ip:
static_ip: 192.168.0.208
gateway: 192.168.0.1
subnet: 255.255.255.0
ap:
ssid: "Esphome-Web-71Afe8"
password: "***"
captive_portal:
sensor:
- platform: homeassistant
id: ha_total_consumo_agua_global
entity_id: input_number.total_consumo_agua_global
- platform: pulse_counter
pin:
number: 19
allow_other_uses: true
update_interval : 6s
name: "pulso agua"
id: pulso_agua
filters:
- multiply: 1
- platform: pulse_meter
pin:
number: 19
allow_other_uses: true
name: "Medidor pulsos agua"
unit_of_measurement: "decilitros/min"
icon: "mdi:water"
id: total_agua_meter
total:
id: total_agua
name: "Total Agua"
unit_of_measurement: "decilitros"
filters:
- multiply: 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: 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
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), "%.1f", 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), "I");
it.print(35 + i * 10, 55, id(robotofont_small), "I");
}
}
Besides, it always start with a value of 2147483647 which, according to chatgpt, is the maximum value for a 32 bit number. Any help here?
I think that would have something to do with the on_boot automation, however I am not fully sure why.
My best guess would be it having to do with how you declare the int new_total
. It could be that esphome imports it as a float, for example.
You can use ESP_LOGD("DEBUG", "new_total is %i", new_total);
after that line to print the value in your logs, that way we could at least see if that’s where the incorrect value happens.
ManuelV
(Manuel Vasco)
March 29, 2024, 10:48am
28
Ok, seems to have gone a little further, I attach my lattest config and the log. It now starts the script, and takes the value from ha, but I think it may be in a wrong order and this is why it doesn’t pass the value to the variable?
The config:
https://justpaste.it/d97y5
The log:
https://justpaste.it/efkvg