Do you live near an active water way? Have you ever wondered what kind of ships are off in the distance? You could find out using a standard called AIS, or Automatic Identification System. It's a worldwide radio system used by larger ships to broadcast their name, position, speed and more. These messages can be decoded using simple Python code and is a cool weekend project if you have some extra CPU resources.
To do this project, you will need a Software Defined Radio or SDR. The easiest way to get this is to buy a cheap RTL-SDR device on Amazon and plug it into a Raspberry Pi. Once you have those two pieces of hardware, simply connect the SDR into one of the USB ports and place the included antenna near a window with a good view of the harbor.
The first step to actual capture these packets is to download a package called RTL_AIS. You can follow these steps:
apt-get install rtl-sdr
apt-get install librtlsdr-dev
git clone https://github.com/dgiardini/rtl-ais
Once you have it, simply start the binary using this command:
./rtl_ais -r162.016M -l161.965M -n
The tricky part here is to find the proper offsets to use. Try it without the -r and -l flags first, and then try various values around the 162.016 and 161.965 MHz respectively. If you have your Raspberry Pi setup to boot into graphical interface mode, you can use an app called GNU Radio to scan these frequencies and see what the precise offsets are. Once you find the proper values, you should start seeing the AIS messages appear on your screen. They look like this:
If you see these, then success! Your SDR is working properly. The only step remaining is decoding the messages. Fortunately, there's a Python library that can do that for you. So let's run the RTL_AIS process in the background and have it go to an output file first and install the library:
./rtl_ais -r162.016M -l161.965M -n >> /tmp/rtl_ais.txt 2>&1 &
pip3 install pyais
And now let's write a Python script that will parse it and output the information:
from pyais.stream import FileReaderStream
for entry in FileReaderStream("/tmp/rtl_ais.txt"):
msg = entry.decode()
And there you go, ship information! Depending on the message type, you will get more or less information, but you can access the ship name with msg.shipname, its longitude with msg.lon, latitude with msg.lat, etc. From here you could go further and lookup the ships using their MMSI number, or plot their position on Google Maps, and so on.