I'm running MicroPython on an ESP32 relaying sensor data to my MQTT server for Home Assistant. I only want it to emit a message when state has changed and a motion detected state to hold for a minute before returning to a clear state. I see a lot of examples using sleep, but I don't like the blocking nature of sleep as I will be adding more sensors. Instead I've been using ticks_ms() and ticks_diff() to keep the state from fluttering on/off too much, but I can't help but think there's a better/more elegant way to do this that I'm not seeing.
There's some repetition and nesting that sticks out to me
from umqtt.robust import MQTTClient
from machine import Pin, unique_id
from time import ticks_diff, ticks_ms
from ubinascii import hexlify
#Config
MQTT_SERVER = "X.X.X.X"
MQTT_PORT = 1883
MQTT_USER = b"USER"
MQTT_PASSWORD = b"PASSWORD"
MQTT_CLIENT_ID = hexlify(unique_id())
MQTT_TOPIC = b"esp/motion"
mqtt = MQTTClient(MQTT_CLIENT_ID, MQTT_SERVER, MQTT_PORT, MQTT_USER, MQTT_PASSWORD)
ledPin = Pin(2, Pin.OUT)
motPin = Pin(15, Pin.IN)
previousState = 0
delay_ms = 60000
clock = ticks_ms()
def main():
global clock, previousState, delay_ms
try:
mqtt.connect()
while True:
state = motPin.value()
if state == 1:
ledPin.on()
if previousState == 0:
if ticks_diff(ticks_ms(), clock) >= 0:
print('motion_start')
mqtt.publish(MQTT_TOPIC, 'motion_start')
clock = ticks_ms() + delay_ms
previousState = state
else:
clock = ticks_ms() + delay_ms
else:
ledPin.off()
if previousState == 1:
if ticks_diff(ticks_ms(), clock) >= 0:
print('motion_stop')
mqtt.publish(MQTT_TOPIC, 'motion_stop')
previousState = state
finally:
ledPin.off()
mqtt.publish(MQTT_TOPIC, 'motion_stop')
mqtt.disconnect()
if __name__ == "__main__":
main()