The Automatic Identification System (AIS) is an automated transponder system for marine vessels, developed as a collision avoidance tool. This page shows how to set up a dual-channel AIS receiver using a Raspberry Pi 3 (Model B)  and any generic RTL-SDR USB stick.  We will forward the raw NMEA AIS feed via UDP to data.aishub.net from a static IP, using a DigitalOcean account.
The overall scheme will be as follows:
[UHF AIS signal to NMEA feed (Pi)] -> [UDP to TCP (Pi)] -> [SSH tunnel TCP (Pi) to TCP (DigitalOcean)] -> [TCP (DigitalOcean) to UDP (aishub.net)].
The SSH tunnel is kept alive by autossh, which runs as daemon in the background. You are free to choose different ports instead of the defaults 10110 and 1234 chosen here, just make sure to change the files below accordingly. We choose the Linux command line tool rtl_ais as decoder. UDP/TCP port forwarding is done by socat. Both of these programs also run as daemon processes and are automatically restarted if needed.
Prepare your Pi
Install a standard Raspbian system image on your SD card. Update the OS and install git, libusb, librtlsdr, rtl-sdr, socat, autossh using:
Install SSH keys
First, set up SSH keys for your Pi to access it via WLAN/LAN from a computer in your local network without entering a password. A tutorial can be found at DigitalOcean. After you are done with this step, you are able to configure your Pi via remote console. Remove the ability to log on via password for added security. In most of the cases, you will not have a static IP address with your residential internet. Once you register the cheapest DigitalOcean.com account (currently $5/month - link with my referral code), you will have a static IP for AIS sharing purposes. Lock down your digitalocean account with two-factor authorization. Set up SSH keys and disable password access for this account, too. You can use different keys for your work computer, and the Pi accessing the account.
Caveat: when you install the keys for DigitalOcean on your Pi, connect to DigitalOcean once as user pi on your Pi, and also once as root. SSH will otherwise fail to auto-connect on boot, because it will ask to add the host IP to the known_hosts file.
Set up the RTL-SDR USB stick
Plug the USB stick into the Pi. The output of lsusb should be similar to this:
pi@raspberrypi:~ $ lsusb Bus 001 Device 004: ID 0bda:2832 Realtek Semiconductor Corp. RTL2832U DVB-T Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Use git to download rtl-ais, follow the instructions on the github page, and copy the compiled rtl_ais executable to /usr/local/bin/.
There will be a small frequency offset for the USB stick, if it is a generic non-compensated one. This offset depends on temperature and your specific hardware. To determine the offset, let the USB stick warm up for 20 minutes first. The easiest way to proceed is to run SDR#, or any other SDR software which allows to display a waterfall plot, on your desktop. A typical AIS signal should look like this, using the correct parameters. The AIS frequencies A and B are at 161.975 MHz and 162.025 MHz. Other ways of determining the frequency offset (via tools that use GSM850 or GSM900 frequencies) turned out to be nonlinear/unreliable for my USB stick. These parameters work for my specific USB stick:
Tip: Just enter the two frequencies you see the signal at as parameters to rtl_ais like above, instead of giving a ppm offset. Don't forget to increase the gain if needed. You can check the output of rtl_ais to the default UDP port 10110 on localhost with ncat:
The output should be strings similar to !AIVDM,1,1,,A,403OwoQv2bBSDreTq0GEg6w02H;p,0*43, which is an encoded AIS message from channel A. If you are near a port and your antenna is good, you should see a few messages per minute or more. You can use ncat or socat to forward the UDP traffic to a local computer running e.g. OPENCPN to plot the ships your receiver sees on a map, and check your antenna range.
System configuration (Raspberry Pi)
Now we want to make the running system set-and-forget. We also will tunnel the UDP packets via forwarded TCP port via a persistent SSH connection to our server at DigitalOcean.
In /etc/systemd/system/, create a file ais.service with the following content (adjust your frequencies and gain values):
[Unit] Description=AIS [Service] Type=simple Restart=always RestartSec=30 UMask=022 ExecStart=/usr/local/bin/rtl_ais -l 161.966M -r 162.015M -g 48 -h 127.0.0.1 [Install] WantedBy=multi-user.target
A file autossh.service containing (adjust email@example.com according to your username and IP):
[Unit] Description=AutoSSH TCP tunnel from pi to digitalocean Wants=network-online.target After=network-online.target Before=multi-user.target [Service] User=pi ExecStart=/usr/bin/autossh -M 0 -N -q -o "ServerAliveInterval=30" -o "ServerAliveCountMax=3" -L 1234:127.0.0.1:1234 firstname.lastname@example.org -i /home/pi/.ssh/id$ Restart=always RestartSec=60 [Install] WantedBy=multi-user.target
And a file called udp-tcp.service:
[Unit] Description= forward UDP port 10110 to TCP port 1234 Wants=network-online.target After=network-online.target [Service] ExecStart=/usr/bin/socat -v UDP-LISTEN:10110,fork TCP:localhost:1234 Restart=always RestartSec=20 [Install] WantedBy=multi-user.target
Then start and enable-on-boot each one of the three services above, replacing **** the first part of the filename:
Check your setup on the Pi
sudo systemctl status udp-tcp.service -l should output something similar to:
● udp-tcp.service - forward UDP port 10110 to TCP port 1234 Loaded: loaded (/etc/systemd/system/udp-tcp.service; enabled) Active: active (running) since Thu 2016-10-13 17:17:04 EDT; 6 days ago Main PID: 570 (socat) CGroup: /system.slice/udp-tcp.service ├─ 570 /usr/bin/socat -v UDP-LISTEN:10110,fork TCP:localhost:1234 └─31282 /usr/bin/socat -v UDP-LISTEN:10110,fork TCP:localhost:1234 Oct 20 14:35:20 raspberrypi socat: > 2016/10/20 14:35:20.381938 length=49 from=5615126 to=5615174 Oct 20 14:35:20 raspberrypi socat: !AIVDM,1,1,,A,403OwoQv2bBSDreTq0GEg6w02H;p,0*43\r Oct 20 14:35:20 raspberrypi socat: > 2016/10/20 14:35:20.385932 length=49 from=5615175 to=5615223 Oct 20 14:35:20 raspberrypi socat: !AIVDM,1,1,,B,403OwoQv2bBSDreTq0GEg6w02H;r,0*42\r Oct 20 14:35:21 raspberrypi socat: > 2016/10/20 14:35:21.720172 length=49 from=5615224 to=5615272 Oct 20 14:35:21 raspberrypi socat: !AIVDM,1,1,,A,15NTHB001=reJ2nGFi`1J1<`0t1m,0*39\r Oct 20 14:35:26 raspberrypi socat: > 2016/10/20 14:35:26.318703 length=49 from=5615273 to=5615321 Oct 20 14:35:26 raspberrypi socat: !AIVDM,1,1,,B,15MwQn0P0iJeF@lGFErp3gvl0@?H,0*57\r Oct 20 14:35:32 raspberrypi socat: > 2016/10/20 14:35:32.588169 length=49 from=5615322 to=5615370 Oct 20 14:35:32 raspberrypi socat: !AIVDM,1,1,,B,15NTHB0017reJ8@GFjE1J1>v0PRT,0*58\r
The command iptraf lets you to see outgoing UDP packets. You can use ncat to quickly troubleshoot your port forwarding by sending simple text messages through the SSH tunnel. The load average on my Pi is 0.25 - there is plently of processing power left for other tasks.
System configuration (DigitalOcean)
Log into your DigitalOcean account and install socat and iptraf.
We again run socat as a daemon, it forwards the UDP packets to the AIS sharing service (change the site/port according to your needs). Put a file named tcp-udp.service in /etc/systemd/system/, changing ???? to your assigned port for data.aishub.net:
[Unit] Description= forward TCP port 1234 to UDP port data.aishub.net:???? Wants=network-online.target After=network-online.target [Service] ExecStart=/usr/bin/socat -v TCP-LISTEN:1234,fork UDP:data.aishub.net:???? Restart=always RestartSec=20 [Install] WantedBy=multi-user.target
Then start, and enable-on-boot the service:
You can check the forwarding service using systemctl status tcp-udp.service -l as before. Outgoing UDP packets will show up in iptraf.
That's all - your AIS receiver/forwarder system is up and running.
|||A good starter kit, including everything you need besides the USB dongle, is this one.|
|||I recommend the slightly more expensive version by RTL-SDR.com instead of a generic cheap dongle. It has <2 ppm frequency offset which should require no frequency adjustment, a metal case, and an SMA connector for the antenna - absolutely worth the extra $10.|