Mode orchestration excerpt
main.py
py / 97 lines
Sanitized firmware excerpt showing how alarm, status and feedback modes are coordinated.
"""Public excerpt from the Pico door alarm firmware.
The full operating sequence, exact timings and wiring details are omitted from
the portfolio. This excerpt shows the parts that are useful to discuss: mode
priority, local feedback and rate-limited REST notifications.
"""
import gc
import time
from lib.buzzer import AlarmBuzzer
from lib.connection import ApiClient
from lib.led import BlinkLed, PauseLed
from lib.mode import Mode
from lib.switch import Switch
door_contact = Switch("DOOR_CONTACT_PIN")
green_led = PauseLed("GREEN_LED_PIN", blink_time=0.1, pause_time=1.5)
blue_led = PauseLed("BLUE_LED_PIN", blink_time=0.2, pause_time=1.0)
red_led = BlinkLed("RED_LED_PIN", blink_time=0.08)
buzzer = AlarmBuzzer("BUZZER_PIN")
api_client = ApiClient()
sleep_mode = Mode("sleep")
check_mode = Mode("check")
safety_mode = Mode("safety", duration=20.0)
alarm_mode = Mode("alarm", init_duration=5.0)
alarm_was_active = False
loop_count = 0
def update_modes(sleep_enabled: bool, safety_button_pressed: bool) -> None:
sleep_mode.set_active(sleep_enabled)
if sleep_mode.is_active():
check_mode.set_active(False)
safety_mode.set_active(False)
alarm_mode.cancel_pending()
return
if safety_button_pressed:
safety_mode.start()
alarm_mode.cancel_pending()
safety_mode.update()
check_mode.set_active(not safety_mode.is_active() and not alarm_mode.is_active())
if safety_mode.is_active():
alarm_mode.cancel_pending()
elif door_contact.is_opened() and not alarm_mode.is_init_active():
alarm_mode.start_pending()
alarm_mode.update_init()
def update_feedback(silent_enabled: bool) -> None:
green_led.paused_blink() if check_mode.is_active() else green_led.on(False)
blue_led.on(safety_mode.is_active())
red_led.blink() if alarm_mode.is_active() else red_led.on(False)
if silent_enabled:
buzzer.stop_alarm()
elif alarm_mode.is_active():
buzzer.start_or_update_alarm()
else:
buzzer.stop_alarm()
def send_notifications() -> None:
global alarm_was_active
if alarm_mode.is_active():
alarm_was_active = True
api_client.timed_post("Door alarm state changed", "DANGER")
if safety_mode.is_active() and alarm_was_active:
alarm_was_active = False
api_client.post("Door alarm acknowledged by safety mode", "INFO")
def loop_once(inputs: dict[str, bool]) -> None:
global loop_count
loop_count += 1
if loop_count >= 100000:
loop_count = 0
gc.collect()
update_modes(
sleep_enabled=inputs["sleep_enabled"],
safety_button_pressed=inputs["safety_button_pressed"],
)
update_feedback(silent_enabled=inputs["silent_enabled"])
send_notifications()
time.sleep(0.005)