Sonoff PowR2 with ESPHome: Energy Utility Meter drops to "0" after reboot

Hi,

I have recently flashed a Sonoff PowR2 with ESPHome. It seems to work fine, except the energy sensor drops to “0” and starts from there after reboot or disconnecting/reconnecting power.

I have created 2 utility meters (-> daily/monthly reset). Those drop to “0” with the underlying energy sensor. How can I prevent this?

Utility Meter settings:


As fare as I understand, those settings should prevent a unexpected reset to “0”?

ESPHome yaml

# Variablen
substitutions:
  device_name: "bautrockner"
  friendly_name: "Bautrockner"
  node_name: "bautrockner"
  device_description: "Sonoff POW R2 mit ESPHome; Strommessung des Bautrockners"
  update_interval: 10s


# ESPHome Core Configuration
esphome:
  name: '${device_name}'
  friendly_name: '${friendly_name}'
  comment: '${device_description}'



esp8266:
  board: esp01_1m
  restore_from_flash: true
  early_pin_init: false


[...]



binary_sensor:
  - platform: gpio
    pin:
      number: GPIO0
      mode: INPUT_PULLUP
      inverted: True
    name: Button
    internal: true
    on_press:
      - switch.toggle: relay

switch:
  - platform: gpio
    id: relay
    name: '${device_name}'
    pin: GPIO12
    restore_mode: RESTORE_DEFAULT_OFF  # Letzter Zustand, default AUS




# the device has two LEDs: a red LED wired to the relay state and a blue 'wifi status' LED
# status LED is active-low so will be lit when status is a-ok; invert to darken
status_led:
  pin:
    number: GPIO13
    #inverted: true

# the CSE7766 voltage/current and power sensor is connected to the ESP via the ESP's UART (the
# ESP8266 has only one)
#  - this precludes logging via serial, so disable that
#  - the CSE7766 emits data more frequently than desired (which in turn would be passed on by
#    esphome); use a filter to slow down updates

logger:
  baud_rate: 0

uart:
  rx_pin: RX
  baud_rate: 4800
  parity: EVEN

sensor:
  - platform: cse7766
    current:
      name: "Current"
      filters:
        - throttle_average: ${update_interval}
    voltage:
      name: "Voltage"
      filters:
        - throttle_average: ${update_interval}
    power:
      name: "Power"
      filters:
        - throttle_average: ${update_interval}
    energy:
      name: "Energy"
      state_class: total_increasing
      device_class: energy
      filters:
        - throttle: ${update_interval}
    apparent_power:
      name: "Apparent Power"
      filters:
        - throttle_average: ${update_interval}
    power_factor:
      name: "Power Factor"
      filters:
        - throttle_average: ${update_interval}


Anybody?

the sensor is defined like this:

state_class: total_increasing
unit_of_measurement: Wh
device_class: energy
friendly_name: Bautrockner Energy

The utility meter is defined like this:

state_class: total_increasing
status: collecting
last_period: 2620.28613237850368023
last_valid_state: 3904.1201171875
last_reset: 2026-03-18T23:00:00.006089+00:00
next_reset: 2026-03-20T00:00:00+01:00
unit_of_measurement: kWh
device_class: energy
friendly_name: Bautrockner Utility Meter heute

I would simply use esphome integration sensor with restore option enabled.

Hi @Karosm

I read the energy values every 10s. Wouldn’t that result in too many flash writing cycles and lead to damage of the flash in no time?

Chris

Your update interval is not flash_write_interval. Esphome default is 60s.
And even if you set flash write interval to 10s, your “in no time” is likely something >10 years.
Few years ago i calculated that for esp32, I don’t remember anymore the numbers, but saving 4bytes variable to flash at 1s interval was something I could consider still an option if I need to (several years).

I have changed my yaml, so that my utility meters do not drop to zero after reboot. The issue was that during reboot, ESPHome sends a zero to HomeAssistant and that resets the Utility Meter. (I still don’t understand, why it is like this, as the Utility Meter is state_class: total_increasing and should not drop to zero…)

For completness, I have asked my artificial friend to provide a summary on my changes.


1. Added: preferences Component (Top-Level)

A new top-level preferences block was introduced to explicitly configure the flash write interval. This controls how frequently buffered global variable changes are committed to flash memory.

preferences:
  flash_write_interval: 1min

The default value is already 1min; the block was added for documentation clarity and to allow easy future adjustment.


2. Added: globals Section

Two global variables were introduced to enable energy accumulation across device reboots:

globals:
  - id: energy_total_wh
    type: float
    restore_value: true      # Persisted to flash; survives power loss
    initial_value: '0.0'

  - id: energy_raw_last
    type: float
    restore_value: false     # Intentionally not persisted; resets to 0 on every boot
    initial_value: '0.0'
  • energy_total_wh holds the cumulative lifetime energy value and is restored from flash on boot.
  • energy_raw_last tracks the last raw CSE7766 register value within the current session only.

3. Modified: energy Sensor — Lambda Filter Added

The energy sub-sensor of the cse7766 platform received a delta-accumulation lambda filter.

energy:
  name: "Energy"
  state_class: total_increasing
  device_class: energy
  accuracy_decimals: 0
  filters:
    - throttle: ${update_interval}
    - lambda: |-
        float delta = x - id(energy_raw_last);
        id(energy_raw_last) = x;
        if (delta < 0) return id(energy_total_wh);  // Reboot detected → no deduction
        id(energy_total_wh) = id(energy_total_wh) + delta;
        return id(energy_total_wh);

The lambda computes the incremental delta between consecutive raw readings and accumulates it into energy_total_wh. A negative delta (indicating a chip reset after reboot) is silently ignored, preventing the published value from ever dropping to zero.