Recently a 200,000 ton container ship named the Ever Given has become stuck in the Suez Canal, halting one of the world's busiest waterways and disrupting global supply chains. And it looks like it might take weeks to move it. Luckily for those on the edge of their seats, with the Marine Traffic API we can access the location of marine vessels programmatically.
My coworker Kelley Robinson used this to create a Twilio phone number that you can text to see if the Ever Given is still stuck. Try it out by texting +1 (586) 800-BOAT, which is +1 (586) 800-2628, to get the status of the situation.
Let's walk through how you could build your own version of this, using Twilio Programmable Messaging, Flask, and the Marine Traffic API.
Setting up your environment
Make sure to have your Python environment set up before we get started. Getting everything working correctly, especially with respect to virtual environments is important for isolating your dependencies if you have multiple projects running on the same machine.
You can also run through this guide to make sure you’re good to go before moving on.
Now that your environment is set up, you’re going to need to install some third party libraries. We’re going to use:
- The Marine Traffic API Python library for determining the location of the Ever Given
- Flask for our web framework
- Twilio’s Python library to interact with the Twilio API for responding to text messages
Navigate to the directory where you want this code to live and run the following command in your terminal with your virtual environment activated to install these dependencies:
pip install Marine-Traffic-API==0.20.1 Flask==1.1.2 twilio==6.55.0
Retrieving data from the Marine Traffic API
First you need to sign up for an API key here. Sign up for an account and fill out the form with your information.
Now that you have an account, head to where you can sign up for API services for vessel information and click to get an API key.
Now set your API key set to an environment variable named
MARINE_TRAFFIC_API_KEY, and run the following code in a Python shell to get the location and speed of the Ever Given:
import os from marinetrafficapi import MarineTrafficApi api_key = os.environ['MARINE_TRAFFIC_API_KEY'] api = MarineTrafficApi(api_key=api_key) vessel = api.single_vessel_positions(time_span=240, mmsi=353136000) vessel = vessel.models latitude = vessel.latitude.value longitude = vessel.longitude.value speed = vessel.speed.value print(latitude, longitude, speed)
Now we can move on to putting this behind a phone number for users to text for updates.
Setting up your Twilio account
Before being able to respond to messages, you’ll need a Twilio phone number. You can buy a phone number here.
Your Flask app will need to be visible from the Internet in order for Twilio to send requests to it. We will use ngrok for this, which you’ll need to install if you don’t have it. In your terminal run the following command:
ngrok http 5000
This provides us with a publicly accessible URL to the Flask app. Configure your phone number as seen in this image so that when a text message is received, Twilio will send a
POST request to the
/sms route on the app we are going to build, which will sit behind your Ngrok URL:
It's time to actually build the app.
Building the Flask app
Now that you have a Twilio number and are able to grab the data you need from the Marine Traffic API, you want to allow users to text a phone number to view this data.
Let’s create our Flask app. Create a file called
app.py and add the following code to it:
import os from flask import Flask from marinetrafficapi import MarineTrafficApi from twilio.twiml.messaging_response import MessagingResponse api_key = os.environ['MARINE_TRAFFIC_API_KEY'] api = MarineTrafficApi(api_key=api_key) app = Flask(__name__) @app.route('/sms', methods=["GET","POST"]) def boat(): resp = MessagingResponse() vessel = api.single_vessel_positions(time_span=240, mmsi=353136000) vessel = vessel.models latitude = vessel.latitude.value longitude = vessel.longitude.value speed = vessel.speed.value stuck_latitude = 30.01765 stuck_longitude = 32.5802 stuck_speed = 0 if speed != stuck_speed and latitude != stuck_latitude and longitude != stuck_longitude: resp.message("It's moving!") else: resp.message("Still stuck 😔") return str(resp)
We only need one route on this app:
/sms to handle incoming text messages.
Run your code with the following terminal command:
Text your Twilio number to see the results. The
time_span threshold used here is 240 minutes, and as things change you might need to increase that depending on how long it's been since the Marine Traffic API has had an update on this particular vessel.
Staying up to date
Unfortunately, this dog is not nearby to mitigate the situation, so it looks like the Ever Given will be stuck for a bit longer.
If you're looking for something fun to do in the meantime, try playing TwilioQuest, our documentation video game. It has a really awesome Python mission! You can also work on other fun Python projects like generating Nintendo music through phone calls.
Feel free to reach out if you have any questions or comments or just want to show off the cool stuff you’ve built.