How to update a globals variable

I use globals variable to set the initial value of sensors.

globals:
  - id: z61count
    type: int
    restore_value: yes
    initial_value: "0"
  - id: z61counter
    type: float
    restore_value: yes
    initial_value: "0.000"
  - id: m3kw
    type: float
    restore_value: yes
    initial_value: "10.94"
  - id: gas_meter_displayvalue

binary_sensor:
  - platform: gpio
    pin code:
      number: GPIO12
      mode: INPUT_PULLUP
      inverted: false
    name: $ {friendly_name} gas meter Z-61 pulse
    id: gas sensor_state
    device_class: window
    filters:
      - delayed_off: 10ms
    on_release:
      then:
        - lambda: | -
            id (z61counter) + = $ {impulsfactor};
            id (z61count) + = 1;
            id (gas_meter_totalm3) + = $ {impulsfactor};
            id (gas_meter_displayvalue) + = $ {impulsfactor};
            id (daily_value) + = $ {impulsfactor};
            id (gas_meter_display) .update ();
            id (gas_meter_total_m3) .update ();
            id (gas_meter_total_kw) .update ();
            id (gas_meter_total_kw_day) .update ();

The disadvantage here is that if this value is no longer correct, then I would like to change it. A change before compiling is not accepted.

How could I reset this initial value via an MQTT command or via API?

So far I have not found a solution for this and would be happy if someone can give me a tip on how I could do it.

In HA you will need input helpers for your globals.

In your ESPHome file you can set up user defined api services for each of the globals you need to set:


api:
  services:
    - service: set_z61count
      variables:
        my_count: int
      then:
        - globals.set:
            id: z61count
            value: !lambda 'return my_count;'

Then in HA you can attach a call service to a button or whatever trigger method you want to use:

service: esphome.device_name_set_z61count
data:
  my_count: "{{ states('input_number.z61count_manual') }}"

@Didgeridrew
Thanks, this is working but:

If API is enabled i can not use MQTT, because the device has on start a lot of boot error and will restart every 5min.

But ESPHOME MQTT generally causes massive problems, because even without API it occasionally

  • reboots,
  • WIFI is also very unstable,
  • OTA updates do not always work …

Regardless of which device ESP32, ESP8266, … always the same problem.

If I don’t use MQTT, i.e. only API methods, then all devices work without problems.

It looks as if the MQTT implementation only causes problems and cannot be used for productive use with ESPHOME devices.

Testcase:

## #######################################################################################
## D! MINI - HEIZUNG 2021 - SENSOREN
## #######################################################################################

## DONOT USE MQTT AND API:
##   [W][ota:036]: Last Boot was an unhandled reset, will proceed to safe mode in 8 restarts
##   device will also reboot all 5min .... !!!!

## used PINS on D1 MINI
##
##   GPI012:  ✔︎ D6 - DS18B20 4 x Digital temperature sensor
##   GPIO14:  ✔︎ D7 - WATERMETER binary_sensor reed contact sensor
##   SCL,SDA  ✔︎ D1, D2  ADS1115
##              A0: MQ2 GAS SENSIR
##              A1: DFRobot SEN0257 Analog Water Pressure Sensor
##              A2: DFRobot SEN0257 Analog Water Pressure Sensor
##              A3: DFRobot SEN0257 Analog Water Pressure Sensor
##
## ----------------------------------------------------------------
substitutions:
  board: d1_mini
  platform: ESP8266
  device_name_short: "wmt" # used by esp-home config
  friendly_name: "Heizung" # label name
  update_interval: 60s
  impulsfactor: "0.250"
  appversion: "1.1.4"
  device_description: "Heizungssensoren Temperatur, Wasserdruck, Wasserzähler, Luftqualität"

esphome:
  name: ${device_name_short}
  comment: ${device_description}
  platform: ${platform}
  board: ${board}
  esp8266_restore_from_flash: true
  project:
    name: "OE9psj.d1MiniWmt"
    version: ${appversion}
  on_boot:
    priority: -100.0
    then:
      - logger.log: ${device_name_short} is connected!
      - globals.set:
          id: boot_counter
          value: !lambda "return id(boot_counter)+=1;"
  on_shutdown:
    then:
      - logger.log: ${device_name_short} is down!

# ----------------------------------------------------------------
# set wifi,ota,web_server, time
# ----------------------------------------------------------------
<<: !include common/wifi.yaml

# ----------------------------------------------------------------
# logger component
# ----------------------------------------------------------------
logger:
  level: DEBUG
  baud_rate: 19200

# ----------------------------------------------------------------
# all used globals variables
# ----------------------------------------------------------------
globals:
  - id: boot_counter
    type: int
    restore_value: yes
    initial_value: "0"
  - id: water_meter_impulse
    type: float
    restore_value: yes
    initial_value: "0.000"
  - id: water_meter_sum
    type: float
    restore_value: yes
    initial_value: "0.000"
  - id: water_meter_display
    type: float
    restore_value: yes
    initial_value: "8.249"
  - id: daily_value
    type: float
    restore_value: yes
    initial_value: "0.000"

# ----------------------------------------------------------------
# Homeassistant API calls
# ----------------------------------------------------------------
api:
  services:
    - service: set_water_meter_display
      variables:
        my_newdisplayvalue: int
      then:
        - globals.set:
            id: water_meter_display
            value: !lambda "return my_newdisplayvalue * 0.001;"
        - logger.log: gas_meter_displayvalue has now new value!

# ----------------------------------------------------------------
# Sun component
# ----------------------------------------------------------------
sun:
  id: sun_sun
  latitude: !secret home_latitude
  longitude: !secret home_longitude
  on_sunrise:
    - then:
        - logger.log: Good morning!
    - elevation: 5°
      then:
        - logger.log: Good morning 2!
  on_sunset:
    - then:
        - logger.log: Good evening!

# ----------------------------------------------------------------
# Switch to restart
# ----------------------------------------------------------------
switch:
  - platform: restart
    id: restart_device
    name: ${friendly_name} restart

# ----------------------------------------------------------------
# D7 Watermeter counter  GPI013
# Simple pulscounter
# ----------------------------------------------------------------
binary_sensor:
  - platform: gpio
    pin:
      number: D7
      mode: INPUT_PULLUP
      inverted: false
    name: ${friendly_name} Warmwasser Impuls
    id: heatingwater_meter_state
    device_class: window
    filters:
      - delayed_off: 10ms
    on_release:
      then:
        - lambda: |-
            id(water_meter_sum) += ${impulsfactor};
            id(water_meter_impulse) += 1;
            id(water_meter_display) += ${impulsfactor}/1000;
            id(daily_value) += ${impulsfactor};
            id(water_meterdisplay).update();
            id(water_meter_liter).update();
            id(water_meter_counter).update();
            id(water_meter_total_liter_day).update();

sensor:
  # ----------------------------------------------------------------
  # testcase pulscounter
  # ----------------------------------------------------------------
  - platform: pulse_meter
    id: water_pulse_meter
    pin:
      number: D7
      mode: INPUT_PULLUP
    internal_filter: 2s
    timeout: 30 sec
    unit_of_measurement: "m³"
    name: ${friendly_name} water
    state_class: measurement
    accuracy_decimals: 3
    filters:
      - multiply: 0.250
    total:
      name: ${friendly_name} water consumption
      unit_of_measurement: "m³"
      device_class: gas
      state_class: total_increasing
      accuracy_decimals: 3
      icon: mdi:gauge
      filters:
        - multiply: 0.250

  # ----------------------------------------------------------------
  #  watermeter data
  # ----------------------------------------------------------------
  - platform: template
    name: ${friendly_name} Warmwasser Anzeige
    id: water_meterdisplay
    accuracy_decimals: 3
    unit_of_measurement: "m³"
    update_interval: 30s
    lambda: |-
      return (id(water_meter_display));

  - platform: template
    name: ${friendly_name} Warmwasser Liter
    id: water_meter_liter
    accuracy_decimals: 3
    unit_of_measurement: "l"
    update_interval: 30s
    lambda: |-
      return (id(water_meter_sum));

  - platform: template
    name: ${friendly_name} Warmwasser Einheiten
    id: water_meter_counter
    accuracy_decimals: 0
    update_interval: 30s
    lambda: |-
      return (id(water_meter_impulse));

  - platform: template
    name: ${friendly_name} Warmwasser heute
    id: water_meter_total_liter_day
    unit_of_measurement: "l"
    lambda: |-
      return (id(daily_value));

  # -----------------------------------------------
  # sensor wifi_signal
  # -----------------------------------------------
  - platform: wifi_signal
    name: ${friendly_name} WiFi Signal
    id: heating_wifi_signal
    update_interval: 60s

  - platform: template
    name: ${friendly_name} Boot counter
    id: bootcounter
    accuracy_decimals: 0
    lambda: |-
      return (id(boot_counter));

  # -----------------------------------------------
  # sensor updtime and MQTT Publish task
  # -----------------------------------------------
  - platform: uptime
    name: ${friendly_name} Uptime
    id: uptime_sensor
    update_interval: ${update_interval}
    on_raw_value:
      then:
        - text_sensor.template.publish:
            id: uptime_human
            state: !lambda |-
              int seconds = round(id(uptime_sensor).raw_state);
              int days = seconds / (24 * 3600);
              seconds = seconds % (24 * 3600);
              int hours = seconds / 3600;
              seconds = seconds % 3600;
              int minutes = seconds /  60;
              seconds = seconds % 60;
              return (
                (days ? String(days) + "d " : "") +
                (hours ? String(hours) + "h " : "") +
                (minutes ? String(minutes) + "m " : "") +
                (String(seconds) + "s")
              ).c_str();

# -----------------------------------------------
# Text sensors...
# -----------------------------------------------
text_sensor:
  - platform: sun
    name: ${friendly_name} Nächster Sonnenaufgang
    id: sunup
    type: sunrise

  - platform: sun
    name: ${friendly_name} Nächster Sonnenuntergang
    id: sundown
    type: sunset

  - platform: version
    name: ${friendly_name} Version
    id: appver

  - platform: template
    name: ${friendly_name} Online seit
    id: uptime_human
    icon: mdi:clock-start

  - platform: wifi_info
    ip_address:
      name: ${friendly_name} IP
      id: wifiip
      icon: mdi:ip-network
    ssid:
      name: ${friendly_name} SSID
      id: wifissid
    bssid:
      id: wifibssid
      name: ${friendly_name} BSSID

  - platform: template
    name: ${friendly_name} Timestamp
    id: systime
    lambda: |-
      char str[20];
      time_t currTime = id(sntp_time).now().timestamp;
      strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S", localtime(&currTime));
      return (std::string) str;

It’s been a while since I did anything with MQTT (I moved all my Tasmota devices to ESPHome because I had so many issues with MQTT)… but if you need MQTT for you project, I think what you are looking for is the Subscribe Sensor. I can’t remember if payload is passed the same way as with the on_message action (as ‘x’), but try something like:

sensor:
  - platform: mqtt_subscribe
    name: "z61count Manual Set"
    id: set_z61count
    topic: the/topic
    on_value:
      then:
        - globals.set:
            id: z61count
            value: !lambda 'return x;'

From HA you just publish as usual:

service: mqtt.publish
data:
  topic: the/topic
  payload: 56

According to the docs, the subscribe sensor expects a float in the payload, so make sure you convert it as needed on the device before setting the global.

Hi,

Thanks.
Now i have moved alle my ESP Devices from MQTT to API and all works w/o any problems (crossing the fingers…). Tasmota works for me.

I am currently looking at the project “aioesphomeapi”.
see: https://github.com/esphome/aioesphomeapi

With this I could set up an MQTT service with python or set up processing without a home assistant (fallback solution). But I have not yet found out how I can set value via the aioesphomeapi API, reading all sensor data works perfectly.

The InfluxDBClient integration is also nice there.

I can only confirm that MQTT causes massive problems with ESPHome and therefore I cannot recommend its use with ESP devices.

Hi, I have a similar problem as petsie. Sometimes I need to set a correct value for my gas sensor. Using initial_value and restore_values in ESPHOME doesn’t allow me to re-initialise a value with “restore_values: yes”. I tried Didgeridrew’s approach, but how can I create a button on the Dashboard, where I get an input box to input the new value? I can create a button with a fixed value with this code:

show_name: true
show_icon: true
type: button
tap_action:
  action: call-service
  service: esphome.d1mini_1_set_zaehlerstand
  data:
    new_zaehlerstand: 10000
  target: {}
name: Neuer Zählerstand
view_layout:
  position: sidebar
icon: mdi:counter
show_state: false

But I want to get a popup where I can input the new value.

@patrick0815

see: How to update a globals variable - #2 by Didgeridrew

I use the developer tools - services:

based on:

# ----------------------------------------------------------------
# Native API Component
# ----------------------------------------------------------------
api:
  id: espapi
  port: 6053
  reboot_timeout: 5min
  services:
    - service: set_gasmeterdisplay
      variables:
        my_newdisplayvalue: float
      then:
        - logger.log:
            format: "Setting Gasmeter Display value: %.1f"
            args: [my_newdisplayvalue]
        - globals.set:
            id: gas_meter_displayvalue
            value: !lambda "return (my_newdisplayvalue);"
        - logger.log:
            format: "Gasmeter Display value: %.1f"
            args: [id(gas_meter_displayvalue)]

Thanks petsie! That’s a good way to do this. I already implemented the API on the ESP. Do you know, if it is possible with a button in the dashboard, which displays a popup dialog box to input the new value?

No, I don’t know - just the way via the service call or a Lovelace Card with an input field and button.