[{"element_type":"text","content":"\n  \n  \n        \u003cp\u003eThis is the second chapter in the \"Finding an \u003cem\u003eopenweathermap\u003c/em\u003e Alternative,\" my latest choose-an-adventure saga exploring the weather API wilderness. The first chapter, \u0026nbsp;\u003ca href=\"https://adafruit-playground.com/u/CGrover/pages/weather-gov-a-truly-free-weather-api\" target=\"_blank\"\u003eweather.gov: A Truly Free Weather API\u003c/a\u003e, looked at the completely-free \u003ca href=\"https://www.weather.gov/documentation/services-web-api\" target=\"_blank\"\u003eNOAA NWS API Web Service\u003c/a\u003e\u0026nbsp;as a replacement for \u003cem\u003eopenweathermap.org\u003c/em\u003e's API. The next area in our search is the weather power-up module of the premium (not-free but affordable) \u003ca href=\"https://learn.adafruit.com/category/adafruit-io\" target=\"_blank\"\u003eAdafruit IO Plus\u003c/a\u003e (AIO+) service and its\u0026nbsp;\u003cem\u003e\u003cstrong\u003eCircuitPython\u003c/strong\u003e\u003c/em\u003e interface.\u003c/p\u003e\n\u003cp\u003e\u0026nbsp;\u003c/p\u003e\n      \n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/000/991/original/AIO_cloud.png?1720974320","metadata":{"caption":""}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003eWe all know about AIO's ability to collect and display sensor data as well as its integration with messaging and control protocols such as \u003cem\u003eMQTT\u003c/em\u003e, \u003cem\u003eIFTTT\u003c/em\u003e, and \u003cem\u003eZapier\u003c/em\u003e. But did you realize that, besides increasing throughput and feed limits, AIO+ also adds \u003cem\u003eSMS\u003c/em\u003e and \u003cem\u003eApple WeatherKit\u003c/em\u003e services to the mix?\u003c/p\u003e\n\u003cp\u003eMy Workshop Corrosion Monitor project needs 12 AIO feeds; 5 for locally connected sensors and 7 for external weather observations. The monitor can reliably detect a corrosion condition in real time by using its attached sensors. To predict when future corrosion events may happen, the monitor needs to know what's going on with the weather outside of the workshop. Rather than installing dedicated external weather sensors (requiring holes in the wall and reliable weather-proofing),\u0026nbsp;\u003cem\u003eopenweathermap.org\u003c/em\u003e's API was initially used to obtain the outside weather conditions and trends. The API was an excellent implementation up until they served notice that a credit card would be required for the \"free\" tier of the service. That's when I started looking for alternatives.\u003c/p\u003e\n\u003cp\u003eThe large number of AIO feeds for this project had already caused me to upgrade to AIO+. At the time, I didn't realize \u003cem\u003eApple WeatherKit\u003c/em\u003e was included in the premium service. Now I know. Replacing the\u0026nbsp;\u003cem\u003eopenweathermap.org\u003c/em\u003e API service with AIO+ weather was therefore a no-new-cost alternative for the monitor project. Besides, if I'm going to be paying for a premium service, I'd rather be sending the money to Adafruit who is committed to openly describing and supporting reliable service levels, providing tutorials, and other efforts to assure product longevity.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch2\u003eUsing MQTT to Query the Weather Service\u003c/h2\u003e\n\u003cp\u003eThe \u003cspan\u003e\u003ca href=\"https://en.wikipedia.org/wiki/MQTT\" target=\"_blank\"\u003eMessage Queuing Telemetry Transport\u003c/a\u003e \u003c/span\u003e(MQTT) protocol along with a CircuitPython library or two provide a mechanism to access the AIO+ weather observations data. An MQTT subscription to a \u003cem\u003etopic\u003c/em\u003e associated with the local weather data source produces a new \u003cem\u003ejson payload\u003c/em\u003e\u0026nbsp;whenever the observation changes, usually about once every 20 minutes.\u003c/p\u003e\n\u003cp\u003eAn added benefit of using MQTT with AIO is its support for publishing local sensor data to AIO feeds. The combination of retrieving information from and publishing to AIO is a perfect fit for projects like the corrosion monitor that need to integrate local and remote sensor data.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"text","content":"\n        \u003ch2\u003eAIO+ Apple WeatherKit json Data Structure\u003c/h2\u003e\n\u003cp\u003e\u003cspan\u003eThe \u003ca href=\"https://developer.apple.com/documentation/weatherkitrestapi/currentweather/currentweatherdata\" target=\"_blank\"\u003eApple WeatherKit json data structure\u003c/a\u003e is fairly flat; metadata is at the same level as the current observation values. Forecast data is also available as a part of the overall weather topic, but for the scope of the project and this example, we'll limit it to just the current observation data.\u003c/span\u003e\u003c/p\u003e\n      ","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/000/989/original/AIO_weather_json.png?1720927261","metadata":{"caption":"AIO+ Weather json Data Structure with Example Query Results"}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch2\u003eCreating a Local Weather Observation Topic\u003c/h2\u003e\n\u003cp\u003eAIO+ makes it very easy to create up to 5 weather location topics. For this example, we'll be looking at the Seattle-Tacoma International Airport (Sea-Tac) as our local weather station.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch4\u003eStep 1: Create a Weather Location and Feed Key\u003c/h4\u003e\n\u003cp\u003eAfter subscribing to the AIO+ service, navigate from your account's Adafruit IO page to the \u003cem\u003ePower-Ups/Weather\u003c/em\u003e page. Click on \u003cem\u003e\u003cstrong\u003eAdd Location\u003c/strong\u003e\u003c/em\u003e to begin.\u003c/p\u003e\n\u003cp\u003e\u0026nbsp;\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/000/990/original/AIO_plus-ups_page.png?1720973703","metadata":{"caption":"Power-Ups Page"}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003e\u0026nbsp;\u003c/p\u003e\n\u003cp\u003e\u0026nbsp;\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/000/982/original/AIO_add_weather_page.png?1720910758","metadata":{"caption":"Power-Ups / Apple WeatherKit Page"}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003e\u0026nbsp;\u003c/p\u003e\n\u003cp\u003eThe\u0026nbsp;\u003cem\u003eCreate a New Weather Service Integration\u003c/em\u003e window will appear. You may either type in the latitude/longitude pair or use the interactive map to pinpoint your location.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/000/985/original/Screenshot_2024-07-13_at_4.04.33%E2%80%AFPM.png?1720911907","metadata":{"caption":"Create a New Weather Service Integration Window"}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003eAfter clicking \u003cem\u003e\u003cstrong\u003eCreate\u003c/strong\u003e\u003c/em\u003e, the \u003cem\u003eWeather by Apple WeatherKit\u003c/em\u003e page with the list of defined locations will appear. Note the \u003cstrong\u003eID\u003c/strong\u003e integer value associated with the entered location -- you'll need that for CircuitPython to subscribe to the MQTT topic area with the current weather observations.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/000/986/original/AIO_add_weather_detail.png?1720912123","metadata":{"caption":"Weather by Apple WeatherKit Page Showing the Current Locations List"}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch4\u003eStep 2: Verify -- Check the Latest Observations\u003c/h4\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003eWhile still on the \u003cem\u003eWeather by Apple WeatherKit\u003c/em\u003e page, click on the \u003cem\u003e\u003cstrong\u003eView\u003c/strong\u003e\u003c/em\u003e button corresponding to the location of interest. A \u003cem\u003eWeather Record\u003c/em\u003e window will appear, showing the location and current observation values. Click on \u003cem\u003e\u003cstrong\u003eShow JSON\u003c/strong\u003e\u003c/em\u003e to see all of the data values (metadata, current, and forecasts) for the location.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/000/987/original/AIO_weather_verify.png?1720912449","metadata":{"caption":"Weather Record Window Displaying Current Observations and Query Response"}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch1\u003eUsing AIO+ Weather with CircuitPython\u003c/h1\u003e\n\u003cp\u003eIt's time to incorporate the AIO+ weather service into a CircuitPython project. We'll be using the Adafruit ESP32-S3 Feather in this case.\u003c/p\u003e\n\u003cp\u003eThe following code example defines two MQTT \"callback\" methods then connects the microcontroller board (MCU) to your Wi-Fi access point as specified in the\u0026nbsp;\u003ccode\u003esettings.toml\u003c/code\u003e file in the root directory of the MCU. After connecting, a socket pool and requests session are created. If the connection process encounters a Wi-Fi access error, the MCU will be reset in a minute to try again.\u003c/p\u003e\n\u003cp\u003eNext, the MQTT helper will be instantiated and associated with the MQTT client, \u003ccode\u003eaio\u003c/code\u003e followed by subscribing to the MQTT \u003cem\u003eweather\u003c/em\u003e topic's current observations.\u0026nbsp;\u003c/p\u003e\n\u003cp\u003eIn the main \u003ccode\u003ewhile True\u003c/code\u003e loop, an MQTT watcher is called. For the next 5 seconds, the watcher keeps an eye on all \u0026nbsp;subscribed topics to check for updates. If a topic had changed, the message callback method executes and the current observation json results are placed in an object for parsing into printable values.\u003c/p\u003e\n\u003cp\u003eFinally, after printing the observation data, the process sleeps for 55 seconds to control the AIO query rate to a single query per minute.\u003c/p\u003e\n\u003cp\u003e\u0026nbsp;\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"code","content":"# Retrieve and print Sea-Tac weather observations from AdafruitIO+\n# CircuitPython code for ESP32-S3 Feather\n\nimport os\nimport time\nimport json\nimport ssl\nimport supervisor\nimport adafruit_connection_manager\nimport wifi\nimport adafruit_requests\nimport adafruit_minimqtt.adafruit_minimqtt as mqtt\nfrom adafruit_io.adafruit_io import IO_MQTT\n\n# Get weather observations from the Sea-Tac station\nW_TOPIC_KEY = 2730  # Integer value\nW_TOPIC_DESC = \"Sea-Tac Airport\"\n\n\ndef subscribe(client, userdata, topic, granted_qos):\n    \"\"\"Callback method for when the client subscribes to a new feed.\"\"\"\n    print(f\"  ... subscribed to '{topic}' with QOS level {granted_qos}\")\n\n\ndef message(client, feed_id, payload):\n    \"\"\"Callback method for when a subscribed feed has a new value.\"\"\"\n    global weather_data\n    if feed_id == \"weather\":\n        weather_data = json.loads(payload)\n\n\ntry:\n    # Connect to Wi-Fi access point\n    print(f\"Connecting to {os.getenv('CIRCUITPY_WIFI_SSID')}\")\n    wifi.radio.connect(\n        os.getenv(\"CIRCUITPY_WIFI_SSID\"), os.getenv(\"CIRCUITPY_WIFI_PASSWORD\")\n    )\n    print(\"  ... SUCCESS: connected to WiFi access point\")\nexcept Exception as wifi_access_error:\n    print(f\"  ... FAILED to connect to WiFi. Error: {wifi_access_error}\")\n    print(\"      MCU will soft reset in 60 seconds.\")\n    time.sleep(60)\n    supervisor.reload()  # soft reset: keeps the terminal session alive\n\n# Initialize a requests session\npool = adafruit_connection_manager.get_radio_socketpool(wifi.radio)\nrequests = adafruit_requests.Session(pool, ssl.create_default_context())\n\n# Connect to AIO and MQTT\n# Initialize the MQTT Client object (keep_alive default is 300 sec)\nmqtt_client = mqtt.MQTT(\n    broker=\"io.adafruit.com\",\n    username=os.getenv(\"aio_username\"),\n    password=os.getenv(\"aio_key\"),\n    socket_pool=pool,\n    ssl_context=ssl.create_default_context(),\n)\n\n# Initialize AIO MQTT helper and connect to AIO\naio = IO_MQTT(mqtt_client)\nprint(\"  ... IO MQTT helper initialized\")\naio.connect()\nprint(f\"  ... IO MQTT connected: {mqtt_client.is_connected()}\")\n\n# Connect the callback methods to AIO\naio.on_subscribe = subscribe\naio.on_message = message\n\n# Subscribe to the AIO+ weather topic\naio.subscribe_to_weather(W_TOPIC_KEY, \"current\")\n\n# Initialize the weather_data and history variables\nweather_data = None\nweather_data_old = None\n\nwhile True:\n    # Fetch and update the weather conditions from AIO\n    aio.loop(5)\n\n    if weather_data:\n        _w_desc = weather_data[\"conditionCode\"]\n        _w_temp_c = weather_data[\"temperature\"]\n        _w_humid = weather_data[\"humidity\"]\n        _w_wind_speed = weather_data[\"windSpeed\"]\n        _w_wind_dir = weather_data[\"windDirection\"]\n        _w_wind_gusts = weather_data[\"windGust\"]\n        _w_timestamp = weather_data[\"metadata\"][\"readTime\"]\n\n        if weather_data != weather_data_old:\n            print(\"-\" * 13 + \" NEW \" + \"-\" * 13)\n        else:\n            print(\"-\" * 30)\n        print(_w_timestamp)\n        print(f\"Weather Temp: {_w_temp_c}˚C\")\n        print(f\"Weather Humidity: {_w_humid} %\")\n        print(f\"Weather Wind Speed: {_w_wind_speed}kph\")\n        print(f\"Weather Wind Gusts: {_w_wind_gusts}kph\")\n        print(f\"Weather Wind Direction: {_w_wind_dir}˚\")\n        print(f\"Weather Description: {_w_desc}\\n\")\n\n        weather_data_old = weather_data  # to watch for changes\n    else:\n        print(f\"  ... waiting for weather observations from {W_TOPIC_DESC}\")\n\n    # Throttle query rate to 1 per min\n    time.sleep(55)","metadata":{"language":"python","linenums":false}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/000/977/original/AIO_REPL_example.png?1720906677","metadata":{"caption":"Code Example REPL Output"}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch1\u003eResources\u003c/h1\u003e\n\u003cp\u003eIf you are just starting to use AIO or need a refresher, the\u0026nbsp;\u003ca href=\"https://learn.adafruit.com/welcome-to-adafruit-io\" target=\"_blank\"\u003eWelcome to Adafruit IO\u003c/a\u003e learning guide is very helpful.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch1\u003eSummary\u003c/h1\u003e\n\u003cp\u003eThe AIO+ Weather plus-up is very promising. It consists of a stable observation data source, \u003cem\u003eApple WeatherKit\u003c/em\u003e, and a mature collection of CircuitPython libraries. Being able to access reliable local weather data is essential for any weather project, especially since it also opens the door for AIO-based projects with a creative fusion of local sensors.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eApple WeatherKit\u003c/em\u003e\u0026nbsp;appears to aggregate weather data from multiple sources and doesn't depend on a single NWS observation station like \u003cem\u003eweather.gov\u003c/em\u003e. Aggregating weather observations improves reliability and adjusts as needed for observation station accuracy issues and outages. The aggregation method used must be similar to that of \u003cem\u003eopenweathermap.org\u003c/em\u003e, as the observation data is very close.\u003c/p\u003e\n\u003cp\u003eThe granularity of observation values in \u003cem\u003eApple WeatherKit\u003c/em\u003e is better than \u003cem\u003eweather.gov\u003c/em\u003e, a benefit of data aggregation. Note the smoother weather temperature (yellow) line in the graph. Both data sources were queried every 20 minutes. Wind speed and humidity also displayed similar granularity improvement.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/000/994/original/weather-gov_AIO_compare.png?1721144181","metadata":{"caption":"Data Source Granularity Comparison (yellow weather-temperature line)"}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003e\u0026nbsp;\u003c/p\u003e\n\u003ch1\u003eWish List\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003eIt's a challenge when first learning to use MQTT with the AIO+ weather service. It takes some effort to discover useful examples. Most examples are generally good, but coding tutorials specifically for the weather module were not easy to find and required quite a bit of sandbox play (experimentation) to achieve a working algorithm.\u003c/li\u003e\n\u003cli\u003eIt's been difficult to find examples for how to control AIO feed rates in order to stay under account limits, particularly for multiple projects that independently query and publish to the same AIO account's feeds. Some further research is needed -- knowing that there's a user-facing throttle management scheme in AIO that's supported by the CircuitPython AIO libraries.\u003c/li\u003e\n\u003cli\u003eAs noted in Chapter 1, a server-side implementation of selectable \u003cem\u003eApple WeatherKit\u003c/em\u003e data presented as AIO feeds would simplify the integration with projects -- and would be a welcome feature that could create a storm of new project innovation.\u003c/li\u003e\n\u003cli\u003eAn indexed library of day/night graphical icons linked to the description field, similar to\u0026nbsp;\u003cem\u003eopenweathermap.org\u003c/em\u003e or \u003ca href=\"https://api.weather.gov/icons/land/night/few?size=large\" target=\"_blank\"\u003e\u003cem\u003eweather.gov\u003c/em\u003e\u003c/a\u003e.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u0026nbsp;\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"product","content":"https://www.adafruit.com/product/3792","metadata":{}},{"element_type":"product","content":"https://www.adafruit.com/product/5483","metadata":{}}]