A few months ago I built a stupid Slack command to use in the offtopic chat channel at work. It's actually pretty simple but fun to use; basically each time you request "the weather" the following things happens:
- The Slack command triggers a custom script on my remote host (check the Slack API and the custom slash commands for more info about registering an app and working with it).
- The script picks a random location id from the OpenWeather API (they have a full list of their valid id's here, so I made a small file with all the valid numbers and then make some random alchemy to choose one).
- Then it asks for the current weather on that location.
- The result is parsed and sent back to the Slack channel with some information about the place name, country, temperature, humidity, wind speed, etc. etc. (featuring a Google Maps link with the provided coordinates to help discover new places with the Street View option - discovering new cities and taking a quick look it's actually kinda addictive...)
After tinkering around with it for a while I realized I had a ESP8266 Thing Dev Board I always wanted to try, so I thought: "What if I port this slack command idea into an external device connected to the Internet?".
And I did it! This is a small weekend project I like to call The Weather (because it prompts The Weather but not The Weather From A Specific Place)!
The ESP8266 Thing Dev is a SparkFun board built around the ESP8266, a small microcontroller with some wifi capabilities. It's, more or less, an easy-to-use micro you can connect to the Internet (among other things, of course, but here I only used it as a "generic board with wifi libraries to parse some json and print some text" - you can even work with the classic Arduino IDE).
Around this board there's a button (for user interaction!) and one of those small I2C OLED screen to show the info (Adafruit have an awesome library to work with it).
So, each time the user hits the big red button (I also designed and printed the box with the button! :D - still working on my cad skills...) the micro does the following:
- If not already connected, it connects to a specific wireless network (with some hardcoded credentials inside) using the ESP8266Wifi library.
- Fetch the content from (again) a script I had in my server that picks a random id and then returns the OpenWeather data for that place (first I tried - succesfully! : D - to use OpenWeather instead of my script "as a proxy", but since the id list was too big and I cannot save it inside the micro memory I decided to get both the id and the weather info from a remote place also controlled by me).
- Display the info in a fancy way (a.k.a. "using the Adafruit library to print some cool pixels on the OLED screen").
The code itself is a small state machine that iterates between idle, some connecting-and-fetching states and a display mode that parses a json string and puts the content in the screen. Check it out on my github page!
The Weather uses:
- The ESP8266Wifi library for the connect-to-the-outside-world thing
- The Adafruit SSD1306 library for the OLED Screen
- The ArduinoJson library for decoding the OpenWeather info
- An MD5 library to hash some params when sending the request
- An external custom script that gets the OpenWeather info (if you just wanna ask OpenWeather itself - without all the random id stuff - you won't need this, just aim for their API and then parse that data).
Cool features (or things I like about the device)
- The state machine tries to connect only if there's no connection, avoiding unnecessary reconnections (I really like the state handling I made :D)
- Both the micro and the external script uses a secret key to hash the params. This prevents anyone without that secret to remotely execute the script (well, the hash function is an MD5 and """maybe""" it's not the best idea for this kind of stuff; but as a simple "extra guard" to prevent multiple calls to my OpenWeather API quota it'll do the job).
- The box and the big...