# ================================================================
# firmware/main.py
# Raspberry Pi Pico W — Entry Point (MicroPython)
# ================================================================
import network
import time
import json
import machine
import config
from sensor import DHT11Sensor
from mqtt_client import PicoMQTTClient
# ── Onboard LED (visual feedback) ────────────────────────────
led = machine.Pin("LED", machine.Pin.OUT)
def blink(times: int = 1, delay_ms: int = 200):
"""Blink the onboard LED for visual feedback."""
for _ in range(times):
led.on()
time.sleep_ms(delay_ms)
led.off()
time.sleep_ms(delay_ms)
# ── Wi-Fi connection ─────────────────────────────────────────
def connect_wifi() -> bool:
"""Connect to Wi-Fi. Returns True on success."""
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if wlan.isconnected():
print(f"[WIFI] Already connected: {wlan.ifconfig()[0]}")
return True
print(f"[WIFI] Connecting to {config.WIFI_SSID}...")
wlan.connect(config.WIFI_SSID, config.WIFI_PASSWORD)
for attempt in range(config.WIFI_RETRY_COUNT):
if wlan.isconnected():
ip = wlan.ifconfig()[0]
print(f"[WIFI] Connected — IP: {ip}")
blink(3, 150) # 3 fast blinks = WiFi OK
return True
print(f"[WIFI] Waiting... ({attempt + 1}/{config.WIFI_RETRY_COUNT})")
time.sleep_ms(config.RETRY_DELAY_MS)
print("[WIFI] Connection failed!")
return False
# ── Main loop ─────────────────────────────────────────────────
def main():
print("=" * 50)
print(" IoT Cyberattack Detection — Pico W Firmware")
print(" Device ID:", config.DEVICE_ID)
print("=" * 50)
# ── Step 1: Connect to Wi-Fi ──────────────────────────────
if not connect_wifi():
print("[MAIN] Cannot continue without Wi-Fi. Halting.")
while True:
blink(10, 50) # rapid blinks = error
time.sleep(5)
# ── Step 2: Initialise sensor ─────────────────────────────
sensor = DHT11Sensor(pin=config.DHT_PIN, device_id=config.DEVICE_ID)
print(f"[SENSOR] DHT11 initialised on GPIO {config.DHT_PIN}")
# ── Step 3: Connect to MQTT broker ───────────────────────
mqtt = PicoMQTTClient()
retry = 0
while not mqtt.connect():
retry += 1
if retry > config.MQTT_RETRY_COUNT:
print("[MAIN] MQTT connection failed too many times. Rebooting...")
time.sleep(3)
machine.reset()
print(f"[MAIN] MQTT retry {retry}/{config.MQTT_RETRY_COUNT}...")
time.sleep_ms(config.RETRY_DELAY_MS)
# ── Step 4: Publish status message ───────────────────────
status_payload = json.dumps({
"device_id": config.DEVICE_ID,
"status": "online",
"timestamp": time.time()
})
mqtt.publish(config.TOPIC_STATUS, status_payload, qos=1)
blink(2, 300) # 2 slow blinks = MQTT connected
# ── Step 5: Sensor publish loop ───────────────────────────
print(f"[MAIN] Publishing every {config.PUBLISH_INTERVAL_MS // 1000}s...")
while True:
try:
payload = sensor.read_json()
if payload:
# Publish temperature reading
mqtt.publish(config.TOPIC_TEMP, payload, qos=0)
led.on()
time.sleep_ms(100)
led.off()
else:
print("[MAIN] Sensor read returned None — skipping.")
except Exception as e:
print(f"[MAIN] Loop error: {e}")
# Try to reconnect MQTT
mqtt.connect()
time.sleep_ms(config.PUBLISH_INTERVAL_MS)
# ── Boot ──────────────────────────────────────────────────────
if __name__ == "__main__":
main()