# Retrieve and print Sea-Tac weather observations from AdafruitIO+
# CircuitPython code for ESP32-S3 Feather

import os
import time
import json
import ssl
import supervisor
import adafruit_connection_manager
import wifi
import adafruit_requests
import adafruit_minimqtt.adafruit_minimqtt as mqtt
from adafruit_io.adafruit_io import IO_MQTT

# Get weather observations from the Sea-Tac station
W_TOPIC_KEY = 2730  # Integer value
W_TOPIC_DESC = "Sea-Tac Airport"


def subscribe(client, userdata, topic, granted_qos):
    """Callback method for when the client subscribes to a new feed."""
    print(f"  ... subscribed to '{topic}' with QOS level {granted_qos}")


def message(client, feed_id, payload):
    """Callback method for when a subscribed feed has a new value."""
    global weather_data
    if feed_id == "weather":
        weather_data = json.loads(payload)


try:
    # Connect to Wi-Fi access point
    print(f"Connecting to {os.getenv('CIRCUITPY_WIFI_SSID')}")
    wifi.radio.connect(
        os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD")
    )
    print("  ... SUCCESS: connected to WiFi access point")
except Exception as wifi_access_error:
    print(f"  ... FAILED to connect to WiFi. Error: {wifi_access_error}")
    print("      MCU will soft reset in 60 seconds.")
    time.sleep(60)
    supervisor.reload()  # soft reset: keeps the terminal session alive

# Initialize a requests session
pool = adafruit_connection_manager.get_radio_socketpool(wifi.radio)
requests = adafruit_requests.Session(pool, ssl.create_default_context())

# Connect to AIO and MQTT
# Initialize the MQTT Client object (keep_alive default is 300 sec)
mqtt_client = mqtt.MQTT(
    broker="io.adafruit.com",
    username=os.getenv("aio_username"),
    password=os.getenv("aio_key"),
    socket_pool=pool,
    ssl_context=ssl.create_default_context(),
)

# Initialize AIO MQTT helper and connect to AIO
aio = IO_MQTT(mqtt_client)
print("  ... IO MQTT helper initialized")
aio.connect()
print(f"  ... IO MQTT connected: {mqtt_client.is_connected()}")

# Connect the callback methods to AIO
aio.on_subscribe = subscribe
aio.on_message = message

# Subscribe to the AIO+ weather topic
aio.subscribe_to_weather(W_TOPIC_KEY, "current")

# Initialize the weather_data and history variables
weather_data = None
weather_data_old = None

while True:
    # Fetch and update the weather conditions from AIO
    aio.loop(5)

    if weather_data:
        _w_desc = weather_data["conditionCode"]
        _w_temp_c = weather_data["temperature"]
        _w_humid = weather_data["humidity"]
        _w_wind_speed = weather_data["windSpeed"]
        _w_wind_dir = weather_data["windDirection"]
        _w_wind_gusts = weather_data["windGust"]
        _w_timestamp = weather_data["metadata"]["readTime"]

        if weather_data != weather_data_old:
            print("-" * 13 + " NEW " + "-" * 13)
        else:
            print("-" * 30)
        print(_w_timestamp)
        print(f"Weather Temp: {_w_temp_c}˚C")
        print(f"Weather Humidity: {_w_humid} %")
        print(f"Weather Wind Speed: {_w_wind_speed}kph")
        print(f"Weather Wind Gusts: {_w_wind_gusts}kph")
        print(f"Weather Wind Direction: {_w_wind_dir}˚")
        print(f"Weather Description: {_w_desc}\n")

        weather_data_old = weather_data  # to watch for changes
    else:
        print(f"  ... waiting for weather observations from {W_TOPIC_DESC}")

    # Throttle query rate to 1 per min
    time.sleep(55)