Nov 6, 2019
 in 
Tutorials

What to Wear

A

m I the only one who sometimes don't know what to wear because the weather outside is so flaky? Add a need for some outfit guidance and BINGO - it me! So I decided to build a bot that could help me out with that. Since training algorithms isn't my thing, I'm taking this project in small strides. It'll be something that I iterate on overtime as I learn more machine learning concepts.

In this tutorial, I'll show you how to deploy a SMS based app that tells you the current weather for a given zip code. In addition, we'll apply conditional logic that will tell you what to wear based on a series of temperature ranges. Since I live in Los Angeles, I'll have the app send me a text with the current weather and then tell me if I should wear shorts, a light jacket or a coat. The logic will be as such:

  • If the weather is 80 degrees or warmer, I should wear shorts
  • If the weather is 60 - 79 degrees, I should wear a light jacket
  • If the weather is 59 degrees or less, I should wear a coat

Language: Python

Product(s)Twilio SMS and OpenWeatherMap API

Prerequisites

Sign Up for Twilio and Get a Phone Number

In order to work with Twilio’s products, you’ll need to sign up and purchase a voice enabled phone number. If you’re new to Twilio, you can start with a free trial. For further assistance on signing up and purchasing a phone number, visit Twilio.

Create an Account on OpenWeatherMap

You'll need an API Key to use the OpenWeather API. It's FREE if you're just doing 60 calls per minute.

GitHub Repository

Visit my GitHub repository to access the code that will be used throughout the tutorial.

Tutorial

Get Data from the API

Before we pull the API into anything, we should see how the data is returned to us - and more important get the data into our desired format. In your IDE of choice, create a new Python file. We'll use the requests module so that we can use the API. You can import the requests module using import requests.

We'll use the Current Weather Data API to get the weather data for one location. The By Zip Code parameters will get us just what we need since we want to get current weather for whatever zip code we place into the API call. The API call looks as such: 

api.openweathermap.org/data/2.5/weather?zip={zip code},{country code}&appid={API Key}

USA is the default, however, if you need to pull weather for a different country, be sure to insert the respective country code. Here's an example of how the API call should look once you pass in your parameters:

http://api.openweathermap.org/data/2.5/weather?zip=90028,us&appid=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Note: Replaces all the x's with your own API Key!

Before we grab some data, we'll make life easier by using f-Strings to embed the zip code, country code and app id into the API call. When we create f-Strings, we'll define variables for each of the items I just mentioned and assign the values to their respective variables. This will help clean up our API call and make it easier to change out values as needed.

CODE: https://gist.github.com/aprilspeight/ffbb63f2e39fbc732db0b007bed277ff.js

Now, grab some data! We can use the requests module and get to see the API in action. We'll assign everything to a variable r and assign the API call to the variable. Let's also add a print() function and pass through r.text so that we can see the content of the response printed to the console.

CODE: https://gist.github.com/aprilspeight/cb8ac08b9d54e452efb8d518a463ed32.js

Convert to Json

So the result could be cleaner - don'tcha think? We can use handy dandy json to clean things up a bit. We can comment out the print() statement that we currently have in our code and start our json conversion on the next line.

The json class will convert the result for request to json. First, create a new variable weather for the conversion and assign the value r.json() to the variable. Similar to the prior step, we'll use the print() function to get the response content printed to the console by passing through the new variable weather.

CODE: https://gist.github.com/aprilspeight/3b4ec2c00ac09c11c7a86eda1e3b0cbd.js

After you save and run your Python script, the result should look cleaner and easier to read.

Get Weather in Fahrenheit

The problem now is that we're pulling in the entire API response. However, we just need the value for temp and more important, the weather in Fahrenheit. Right now, the weather isn't in Fahrenheit so we'll need to do some more conversion. The Units Format section of the documentation states that when we do not specify the unit parameter, the standard (what we currently see) is the default. Since I'm in the US, I'll need to set units to imperial. However, if metric is more so your thing, then use metric instead.

In either case, we'll need to append the units=imperial parameter to the API call. Create a new variable for units at the top of your code, assign it your preferred unit of measurement and append units={unit} to the API call.

CODE: https://gist.github.com/aprilspeight/ff9623a73c33c2eb096ead7646dc6c78.js

Save and run the Python script to view the unit conversion for temp.

To isolate the value for temp, we'll need to modify our print() function by just asking for temp. Rather than pass everything through the print() function, we'll create a variable in our code above the print() function for temperature and assign ['main']['temp'] to the variable. We can then modify the print() function by passing through the variable temperature. Be sure to convert temperature from a float to an int by wrapping the variable value around int().

CODE: https://gist.github.com/aprilspeight/0f49419f17a43a26fbb0952674600684.js

Save and run the Python script again. Only the temperature for your chosen zip code should display in your preferred units.

Add Conditional Logic

As a reminder, we're going to have the app/bot suggest what to wear based on 3 temperature ranges:

  • If the weather is 80 degrees or warmer, I should wear shorts
  • If the weather is 60 - 79 degrees, I should wear a light jacket
  • If the weather is 59 degrees or cooler, I should wear a coat

We can use an if, elif, else statement to do so. For each statement, we'll need to evaluate if the value for temperature meets the conditions.

CODE: https://gist.github.com/aprilspeight/b9a7df172484d5bbfdb7e1bbb13ff1c9.js

The result for running the script will vary based on the zip code you passed into the API call. Save and run the script to test out each conditional statement. Enter different zip codes into the API call to get each statement to print at least once to the console. For example, I used Los Angeles (90028) for 80 degrees or warmer, San Francisco (94103) for 60 - 70 degrees, and D.C. (20002) for 59 degrees or cooler.

Add Twilio Helper Library and Variables

We're now going to setup things with Twilio. Make sure you already setup everything with your Twilio phone number before moving forward with this step. We'll need to import the Twilio helper library at the top of our code using from twilio.rest import Client. Let's also add in some more variables to our code - this time we'll add Twilio variables for our account_sid and auth_token. These variables will be used when we later use the client to setup our text message.

CODE: https://gist.github.com/aprilspeight/8cfe6ef5fd27f8f1a1a2f2140676853d.js

Create the Message

We already setup the logic we need in a previous step, so all that's left to do now is setup the text message. We'll use some handy dandy f-Strings to help simplify our code. You can get as creative as you want for the text message. I'm going to give my message some personality that closely resembles my own personality. I want the text messages to say one of the following:

  • Girl, it's hot outside in {city}- it's {temperature} degrees! Definitely wear some shorts, otherwise, you'll get too hot!
  • Eh, so the weather doesn't completely suck today in {city}. However, it's only {temperature} degrees outside. Grab a light jacket if you decide to head out.
  • Why is it so cold in {city}?! It's only {temperature} degrees outside and if I were you, I'd just stay at home. However, if you do leave the house, wear a coat.

We'll also need to add a variable to our code for {city} by grabbing weather['name'] from the API call response.

Note: Don't forget to use an escape character (\') if your message includes apostrophes!

CODE: https://gist.github.com/aprilspeight/62701c34eb28e0ade06d1fbc68603209.js

You can test everything out by saving and running the script. The response should return your new message including the city and temperature.

Create a Method for the Conditional Logic

We'll wrap our conditional logic from earlier into a method which we'll then assign to a variable for the message. Let's name the method advice and pass the parameter temperature into the method. We can then finish up the method with the if, elif, else statement we wrote earlier. Since we're creating a method, swap out all the print() functions for return since we need to return a value to the console. To

CODE: https://gist.github.com/aprilspeight/b6116605816ed7c5755719c614e6a530.js

Now that our advice method is complete, let's create a variable for the text message body and name it text_message. We can assign our method to the text_message variable. To test our code, add a print() function and pass through the new variable text_message. This will run the method we created to get the proper response based on the current temperature.

CODE: https://gist.github.com/aprilspeight/2db4bcee0441b4f049e817d3de3bc651.js

Replace Message Values

Twilio provides us with a template that we can use to replace values so that we can send the message via SMS. The code from the template is below in the code block. Replace the to and from fields with the number that'll receive the text message (your personal number) and the number sending the message (your Twilio number) respectively. Be sure to include the country code at the beginning of the number (for ex: U.S. is +1) You'll also replace the value for body with the variable text_message as that's the message that we'll have the app send via SMS.

Before we move forward with testing, comment out the two prior print() statements from the code. Be sure to leave the one for print(message.sid)!

CODE: https://gist.github.com/aprilspeight/522e70d617ec3743d3a63e488c8f7ab6.js

Test the Code

To test everything out, we'll need to save and run the Python script. You'll instantly know if a message was sent if a message.sid is printed to the console. It'll be a series of letters and numbers starting with SMS. If you see the message.sid, check your phone for the text message!

I'll be adding onto this app overtime as I plan out all the fine details for how I'd like my bot to interact with users. For now, feel free to modify the script to your liking and even deploy as a real service!

Until next time, happy coding!