- 01Input pair
- 02Validation
- 03Previous state
- 04New state
Keep the rule independent of the sensor
The same function runs in CPython for tests and in MicroPython on the board. It takes a reading and the previous state; it does not import a pin driver or read a clock.
"""Shared CPython/MicroPython decision logic; temperatures are Celsius."""
def state_for(temperature, humidity, previous="unknown"):
for value in (temperature, humidity):
if isinstance(value, bool) or not isinstance(value, (int, float)) or value != value:
return "unknown"
if not (0 <= temperature <= 50 and 0 <= humidity <= 100):
return "unknown"
if temperature >= 28:
return "warm"
if temperature <= 26:
return "ok"
return previous if previous in ("ok", "warm") else "ok"A boolean is an integer subtype in Python, but it is not a temperature reading in this interface. The explicit boolean rejection matters when a record is accidentally shaped incorrectly. NaN is rejected before comparisons; infinities fail the range check.
Replay the important transition
from policy import state_for
state = "unknown"
for temperature in [25, 27, 28, 27, 26]:
state = state_for(temperature, 50, state)
print(temperature, state)Expect ok, ok, warm, warm, ok. Test the exact edges, not only a comfortable midpoint. After None, status should become unknown; the next 27 °C reading starts from that explicit state.
Try it
Change the warm threshold and return threshold together, keeping a gap between them. Add tests for the new exact boundaries before deploying. Avoid editing a separate copy of the policy in the firmware; copy the tested file to the board instead.