Skip to content

Debounce Sensor Changes

Sensors like temperature or humidity often emit bursts of near-identical readings. This recipe waits until a value has been stable for a set period before reacting, and only fires when the temperature has increased and crossed a threshold.

The Code

from hassette import App, AppConfig, C, D, states


THRESHOLD = 25.0
DEBOUNCE_SECONDS = 10.0


class DebounceSensorApp(App[AppConfig]):
    """React to stable temperature changes and log when a threshold is crossed."""

    async def on_initialize(self) -> None:
        await self.bus.on_state_change(
            "sensor.outdoor_temperature",
            changed=C.Increased(),
            handler=self.on_temperature_stable,
            debounce=DEBOUNCE_SECONDS,
            name="outdoor_temp_debounced",
        )

    async def on_temperature_stable(
        self,
        new_state: D.StateNew[states.SensorState],
        old_state: D.StateOld[states.SensorState],
    ) -> None:
        try:
            new_temp = float(str(new_state.value))
        except (TypeError, ValueError):
            return

        if new_temp >= THRESHOLD:
            self.logger.info(
                "Temperature crossed %.1f°C threshold: %s%.1f°C (stable for %ss)",
                THRESHOLD,
                old_state.value,
                new_temp,
                DEBOUNCE_SECONDS,
            )

How It Works

  • debounce=10.0 — the handler is not called until the sensor has been quiet for 10 seconds. Any new event during that window resets the timer, so rapid fluctuations are silently discarded.
  • changed=C.Increased() — the debounce timer only starts for events where the new value is numerically greater than the old one. Decreases and unchanged readings never queue the handler.
  • The handler uses dependency injection (D.StateNew[states.SensorState]) to receive the new state as a typed object. The value is converted to a float before comparing to THRESHOLD.
  • When the temperature is at or above the threshold after stabilising, a single log line is emitted.
  • Adjust THRESHOLD, DEBOUNCE_SECONDS, and the entity ID for your sensor.

Variations

Use throttle instead of debounce. If you want to log at most once every 30 seconds regardless of how many events arrive, replace debounce=10.0 with throttle=30.0. Throttle fires on the first event and then suppresses the rest for the window; debounce waits for a quiet period before firing.

Watch a different sensor. Swap "sensor.outdoor_temperature" for any numeric sensor — humidity (sensor.living_room_humidity), CO₂ (sensor.co2_level), or power draw (sensor.solar_inverter_power). Adjust THRESHOLD to match the units.

See Also