Take a variable from HA on ESP32 boot and start working from it

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.

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!

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.

image

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.

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

I think so too. Could you try the following for the automation:

  on_boot:
    priority: -100
    then:
      - lambda: |-
          ESP_LOGD("main", "Inicio de on_boot");
      - wait_until:
          condition:
              api.connected:
      - wait_until:
          condition:
            not:
              lambda: |-
                return isnan(id(ha_total_consumo_agua_global).state);
      - script.execute: get_ha_var

The idea is to have the ESP first wait until it connects to HA, and then also wait until it actually got a value from the helper (i.e., the sensor inside the ESP is not NaN anymore, but an actual number). I also changed the priority to -100, which according to the documentation means that basically everything is setup? Although -10 also should have worked. It may need a bit of tinkering in compile, although the lambda function should compile (It does on my pc at least).

Wow, I couldn’t figure out it was so dificult to achieve. Made your changes and it compiles without problembs, but I get:

INFO Successful handshake with esphome-web-71afe8 @ 192.168.0.208 in 0.812s
[18:47:22][V][sensor:043]: 'Total Agua': Received new state 4.000000
[18:47:22][D][sensor:094]: 'Total Agua': Sending state 4.00000 decilitros with 0 decimals of accuracy
[18:47:22][V][sensor:043]: 'Medidor pulsos agua': Received new state 106.795105
[18:47:23][D][sensor:094]: 'Medidor pulsos agua': Sending state 106.79510 decilitros/min with 2 decimals of accuracy
[18:47:23][W][component:232]: Component display took a long time for an operation (266 ms).
[18:47:23][W][component:233]: Components should block for at most 30 ms.
[18:47:23][V][sensor:043]: 'Flujo de agua': Received new state 0.000000
[18:47:23][D][sensor:094]: 'Flujo de agua': Sending state 0.00000 l/min with 1 decimals of accuracy
[18:47:23][V][bluetooth_proxy:097]: [0] Free connection
[18:47:23][V][bluetooth_proxy:097]: [1] Free connection
[18:47:23][V][bluetooth_proxy:097]: [2] Free connection
[18:47:23][D][homeassistant.sensor:024]: 'input_number.total_consumo_agua_global': Got state 2852978.00
[18:47:23][V][sensor:043]: 'ha_total_consumo_agua_global': Received new state 2852978.000000
[18:47:23][D][sensor:094]: 'ha_total_consumo_agua_global': Sending state 2852978.00000  with 1 decimals of accuracy
[18:47:23][D][main:029]: Inicio del script get_ha_var
[18:47:23][D][main:031]: new_total antes de set_total: 2852978.000000
[18:47:23][V][sensor:043]: 'Total Agua': Received new state 2852978.000000
[18:47:24][D][sensor:094]: 'Total Agua': Sending state 2852978.00000 decilitros with 0 decimals of accuracy
[18:47:24][D][main:033]: new_total después de set_total: 2852978.000000
[18:47:24][D][DEBUG:034]: new_total is 0
[18:47:24][V][sensor:043]: 'Total Agua': Received new state 6.000000
[18:47:24][D][sensor:094]: 'Total Agua': Sending state 6.00000 decilitros with 0 decimals of accuracy
[18:47:24][V][sensor:043]: 'Medidor pulsos agua': Received new state 111.886024
[18:47:24][D][sensor:094]: 'Medidor pulsos agua': Sending state 111.88602 decilitros/min with 2 decimals of accuracy
[18:49:41][D][main:041]: Valor de total_agua: 2852978.000000
[18:49:57][V][sensor:043]: 'pulso agua': Received new state 0.000000
[18:49:57][D][sensor:094]: 'pulso agua': Sending state 0.00000 pulses/min with 2 decimals of accuracy
[18:49:57][V][sensor:043]: 'Total Agua': Received new state 9.000000
[18:49:57][D][sensor:094]: 'Total Agua': Sending state 9.00000 decilitros with 0 decimals of accuracy
[18:50:01][D][main:041]: Valor de total_agua: 9.000000

So maybe there is a little residual compsuntion in my house (i.e. decalcifier) but it starts counting pulses before starting the script, then reads correctly the number, and now it writes it to “total_agua”, but as soon as there is another compsuntion, it keeps counting from the value before reading the input_number instead of suming the value to it.

Maybe it is the way it should be, and I should create a new sensor which takes the value of the input_number and sums all the pulses of the pulse_counter.

Maybe another option is to keep the total value in HA and sum all the pulses from ESP, so even if it restarts, the last value is kept and it starts growing from this number. It’s not the ideal solution (I would like the ESP to keep the value) but mayte it would be a workaround.

It could be that the lambda call that is being inside the script does not play well with the total component. It may work when using the documented way to do it:

script:
  - id: get_ha_var
    then:
        - pulse_meter.set_total_pulses:
            id: total_agua_meter
            value: !lambda 'return id(ha_total_consumo_agua_global).state;'

Saving it on the ESP will only be possible when using the global variable, like previously tried. I think it is possible to do that as well by extending the current script/logic, however it has to be update a bit more continuously, but perhaps not on every sensor update. An idea would be to update it only when the total value has increased by a certain amount, or to make a timed automation out of it. I’m not quite sure if it’s possible to get the value of the total water meter inside the ESP without calling the input_number, however, which would mean in the end it would still rely upon Home Assistant. I’ll give it a bit to think it over and see if I can think of anything.

Ok, two brains better than one. Anyway, maybe I should try to go the way way: let the ESP start as it wants, and let HA sum every pulse so the total goes in it.

Maybe the I could send this HA variable to a global variable in the ESP just to show it in the screen.

That’s possible too. I believe home assistant has a consumption meter, or otherwise there is the integration helper which should also be able to that.

It works!! Now it takes the value from the input.number and it starts suming from it. Finally it meters liters and not deciliters.

I attach the yaml file just in case anybody may use it.

https://justpaste.it/bougm

The only problem is that the pulse counter is not exactly. When the needle is near to a full round, it starts and stops metering for ms, so instead of a pulse it meters like 30-40. I think I will have to play with the filter a little so it only counts one.

1 Like

Great to hear :smiley: The other thing indeed sounds like a filter thing. Getting those parameters right usually requires some fiddling.

Just one a little help more: If I read it fine here I can fiddle with the us, so if it’s being so sensitive, it means I should increase the value or lower it?

For the internal_filter, you should increase the time to make it less sensitive. Basically, it means it should receive an on signal for longer before it counts it as water going through it.

It may be worth trying out the internal_filter_mode alongside of increasing the time too. I think PULSE would be the correct setting to apply, though I am not 100% sure, so I’d advice also trying out EDGE mode.