Raspberry Pi NMEA Wifi Multiplexer
Warning!
This page is based on an early (2015/Debian 7/Wheezy) version of Raspbian on a Raspberry pi 1 model B and may not be applicable to modern hardware or Raspberry pi OS.
This page describes how to use a Raspberry Pi to build a wireless access point which also acts as an NMEA-0183 router. I stress that what is described here is not necessarily the ideal way to do it. I've put this page up at the request of others as a starting point. Take some ideas from here and improve on them. If you search for "raspberry pi access point" you will find other ideas.
Some people will be wanting to build an access point which functions purely as an NMEA-0183 to wifi bridge, like some of the commercial offerings. Others will want to combine that functionality with a shared Internet connection. This page will start by describing how to use the pi to build an access point for an isolated network not connected to any other network. Later sections (not yet written) will develop the project, adding hardware (a GPS connected to the pi's console port) and an additional network connection to allow sharing a wifi or 3G connection.
Do be aware that in some cases open source linux drivers are written with incomplete information regarding the closed hardware they need to support. Although others will disagree, my experience with linux wireless over the past decade or so has been that it isn't always consistent or reliable. It goes without saying that this project is not recommended for safety critical systems. I have experienced numerous USB-related lockups when experimenting with the pi as an nmea server and access point.Assumed Knowledge
Basic knowledge of Linux including use of a text editor is assumed. There is a wealth of information available elsewhere on getting started with the Raspberry Pi that need not be replicated here. Different types of hardware (specifically, different wifi dongles) may require downloading and installing of firmware in order to get working. Because of the variety of different dongles that might be used it is not possible to give step by step instructions.
Required Hardware
Raspberry Pi
I was originally using one of the first generation model Bs with 256MB memory. The memory and processing power are fine for this application but I found the USB bus could be flaky with two wireless adapters connected. This was not a simple power problem as the same issue occurred with a powered hub. Not a problem when only using the pi for an access point but became an issue when also using it as a router to connect to the Internet. Reports from others suggest the B+ improved on this situation and my current Pi v2 is working fine.
SD card
For the Pi's OS. 4GB is sufficient, but 8 or more gives you room to add more software or store more logged data. Note that the newer Pis use a micro SD card.
Power supply
You want to convert the boat's 12v power supply to 5v and provide it to the pi via a micro usb. The easiest option is to use a phone charger designed for a lighter socket. I found a converter with a micro usb connector on one side and 1m of power cable on the other. Either solution should be less than €5 on ebay.
USB wifi dongle which supports master mode
This is the hard part. When acting as an access point, your wifi device operates in what is known as "master mode" (or "AP" mode). Not all devices or their software drivers support this mode. Support for this mode in Linux depends on the device's chipset (ie the electronics inside the device). Unfortunately manufacturers sometimes change the chipset they use in a device without changing the name of their product. You may read in someone's blog post that a particular dongle supports master mode on Linux, go out and buy the "same" thing only to discover you've bought the New! Improved! version with a different chipset which doesn't even work on Linux. The best way to select a dongle is to borrow someone else's, try it, and if it works, don't give it back. Offer to buy them another newer one if you are honest. Alternatively for any device you are thinking about buying, try and find out what chipset it uses then attempt to determine whether that chipset's driver supports master mode under Linux. A summary list of driver capabilities is available on the Linux Wireless web site, although this is not always up to date and accurate. Worst case, be prepared to give several of your friends wifi dongles as birthday presents this year.
I'm currently using an old D-Link DWA-110 (RaLink RT2571W chipset). It's an 802.11g device which is plenty fast enough for boat data, although may not be your best option if you want to push high definition video about.
UPDATE: For my latest re-work of this project I used an Edimax EW-7811un
adapter which is commonly sold for use with the Raspberry Pi. This uses the
RTL8188CUS chipset which at time of writing requires a custom version of
hostapd. The software can be downloaded from the realtek website.
I compiled and installed a replacement hostapd, added the declaration:
to /etc/default/hostapd in order to reference the custom binary, then replaced:
DAEMON_SBIN=/usr/local/bin/hostapd
with
driver=nl80211
I will updated this document with more detail at a later date.
driver=rtl871xdrv
ieee80211n=1
wmm_enabled=1
Serial to USB converter(s)
The easiest way to get NMEA-0183 data into your pi is via USB. If the device you want to hook up to the pi outputs NMEA-0183 over USB, happy days. If not you will need a serial to usb adapter. Ideally this should be opto-isolated, but the cost of such adapters tends to be more than replacing the pi several times over in the unlikely event of it being blown up by a power surge. If your NMEA-0183 device outputs data over an RS232 adapter, use an RS232 to serial adapter (~€13 delivered from ebay). If it is compliant with a version of NMEA-0183 prior to v2, use an rs232 to serial adapter. Older equipment and cheap GPS units fall into this category. The device's TX should be connected to the adapter's RX, RX to TX, GND to GND. More modern devices (NMEA-0183 v2 upwards) use RS 422, a differential protocol. You can buy rs422 to usb adapters, but these far harder to come by and generally more expensive than your average RS232 to USB adapters. For input only, many people will just use an RS232 to usb adapter, connecting TX+ to RX on the adapter and GND to GND. Tollerances are such that this will generally work although it is not guaranteed.
The pi only has two USB ports. If you use one for the wifi dongle that leaves you with one. In order to connect more than one serial device via usb we can use a dual serial-to-usb converter, or we can connect a usb hub to the pi, and connect other serial-to-usb adapters to that.Later we'll look at the alternative method of getting data into the pi via the serial i/o pins normally used for the pi's serial console.
Software
We will be using:
- An OS image. We will use the "standard" hard float Raspbian image from the Raspberry Pi Foundation
- hostapd for access point management
- isc dhcpd, our DHCP server
- kplex for NMEA-0183 multiplexing
hostapd and dhcpd are most easily installed with apt-get once the pi is up and running. Dhcpd is probably not the best choice of dhcp server: It is a full-fat enterprise-ready piece of software that is undoubtedly overkill for your purposes, but it's what I have used for many years and am familiar with.
Initial Setup
This section may be expanded but for now, follow the Instructions on the Pi foundation's web site to get the pi running a basic OS. For the rest of this guide we're going to be working with the command line.It is critical that you use an OS image which includes up to date firmware. Issues existed with USB handling code which could cause USB hangs when some serial to USB devices were opened. If your firmware is older than April 2013 and you experience such a problem, either use a more up to date image or upgrade the pi's firware. A popular way of doing that is with rpi-update.
Hardware Configuration
For now we're going to assume you are only connecting one NMEA-0183 connection which carries combined AIS and other data at 38400 baud. After the initial setup described above, plug in your wireless dongle to one USB port and plug in the serial to USB converter to the other. If you're going to use several serial to USB converters, you'll need to use a USB hub.
At this point it pays to check that the wireless dongle really is the device you think it is. Here's the output of the "lsusb" command on my pi:
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. Bus 001 Device 004: ID 07d1:3c07 D-Link System DWA-110 Wireless G Adapter(rev.A1) [Ralink RT2571W] Bus 001 Device 005: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) ICThe wireless dongle is obvious. If we have any questions about it, Internet searches on the chipset ("Ralink RT2571W") or vendor and product id ("07d1:3c07") are often more helpful than searches on the product name: Often several different manufacturers will base their products on the same underlying electronics, and linux may treat them all the same. Many types of wireless dongle require binary firmware to be loaded on them. Fortunately some of the more common firmwares are already available in the raspbian distribution (in the /lib/firmware directory) and others are available in packages which can be downloaded using normal dpkg tools. If your device doesn't give you a wireless interface, and error messages in your system log indicate a missing firmware file, check if there is a package available before finding instructions on the web for hacking the firmware out of Windows drivers.
Software Configuration
If you're ultimately going to use your pi on a boat without an Internet connection, set it up beforehand somewhere where you do have an Internet connection.
Installing Software
Our first task is to install all the additional software we're going to need. If your installation procedure involved a software update you don't need this next step, otherwise update your apt cache with "apt-get update" then update you software with "apt-cache upgrade".
Next install hostapd...
apt-get install hostapd...and dhcpd...
apt-get install isc-dhcp-serverNow follow the instructions for obtaining and installing kplex here. Don't worry about configuring it yet.
Configuring hostapd
My /etc/hostapd/hostapd.conf looks like this:
interface=wlan0 driver=nl80211 ssid=NMEA0183 channel=1 country_code=UK ieee80211d=1 hw_mode=g auth_algs=1 wpa=2 wpa_passphrase=changeme! wpa_key_mgmt=WPA-PSK wpa_pairwise=TKIP rsn_pairwise=CCMPDo take some time to read what these settings mean. I've stripped out the comments for brevity but the original prototype (with all comments present) is here. You will minimally have to change the SSID setting to some string of 32 characters or less (31 or less in some implementations) which you like, and the passphrase to some string between 8 and 63 characters long. Change the country code according to your location, and if your wifi dongle doesn't use the mac80211 driver, you may need to change the "driver" line.
To check if your device uses mac80211, type
lsmod | grep mac80211If there is no output, you will need to work out which driver to use, but if you see some output with "mac80211" somewhere in the left hand column, you're good to go. Here's what I see from the above command on my pi:
mac80211 273413 2 rt2x00lib,rt2x00usb cfg80211 184163 2 mac80211,rt2x00libIn some distributions you may need to tell startup scripts where to find the configuration file. This can be done by setting the DAEMON_CONF variable, either in /etc/default/hostapd or the startup script itself. If setting it in the startup script simply append "/etc/hostapd/hostapd.conf" to "DAEMON_CONF=":
DAEMON_CONF=/etc/hostapd/hostapd.conf
dhcpd
Here is a minimal /etc/dhcp/dhcpd.conf for a closed network (i.e. no gateway to the outside world) with no DNS.
ddns-update-style none; default-lease-time 600; max-lease-time 7200; authoritative; log-facility local7; subnet 192.168.129.0 netmask 255.255.255.0 { range 192.168.129.129 192.168.129.191; }You can use any of the private network address spaces specified in RFC 1918. Here we are using 192.168.129.0/24 and allowing our dhcp server to allocate from a pool of 62 address in that range. Later we'll see how to modify this to enable us to link up with a connection to the outside world.
kplex
You can do a lot with kplex but for now we are going to do something very simple: Plug in a serial to usb adaptor with the serial end attached to a 38400 bps (such as would be used for a connection carrying AIS and possibly other data) NMEA-0183 feed and create a tcp server which will allow us to connect to it from a wireless application. For the details of what kplex can do (including broadcasting data over UDP) the instructions are here but for now here's our basic /etc/kplex.conf, which essentially just requires uncommenting the configuration in the example that was installed with the .deb.
[serial] filename=/dev/ttyUSB0 direction=both baud=38400 [tcp] mode=server port=10110 direction=bothIf your NMEA feed is 4800 baud, change the "baud=" directive accordingly.
Iniialisation Script
We could start any of the software we've just configured automatically at boot time independently of the other services which start. However we may want to control the "access point" functionality as a unit: hostapd, dhcpd and (when we add it later) BIND. To achieve this, let's creat a trivial script and call it /usr/local/bin/apctl. We'll develop this script further later.
#!/bin/bash fname=${0##*/} usage() { echo "Usage: $fname start|stop|restart" >&2 exit 1 } do_start() { /etc/init.d/hostapd start /etc/init.d/isc-dhcp-server start /etc/init.d/kplex start } do_stop() { /etc/init.d/kplex stop /etc/init.d/isc-dhcp-server stop /etc/init.d/hostapd stop } if (( $# == 1)) ; then cmd=$1 else if [[ $fname == start* ]]; then cmd=start elif [[ $fname == stop* ]]; then cmd=stop else usage fi fi case $cmd in start) do_start ;; stop) do_stop ;; restart) do_start do_stop ;; *) usage esac exit $?Make it executable:
chmod 755 /usr/local/bin/apctlIn /usr/local/bin create two links to this file:
cd /usr/local/bin sudo ln apctl startap sudo ln apctl stopapNow let's configure /etc/network/interfaces:
auto lo iface lo inet loopback allow-hotplug wlan0 iface wlan0 inet static address 192.168.129.1 netmask 255.255.255.0 post-up /usr/local/bin/startap pre-down /usr/local/bin/stopapHere we've assigned the address 192.168.129.1 to our wireless interface. When logging in to the pi over ssh from another computer, this is the address we can go to. More importantly, this is the address we will use as the server for our wireless NMEA-0183 apps to connect to.
Firewall Rules
For our first cut, isolated from the Internet, we won't install any firewall rules. Out wireless network should be protected by WPA2 with only clients into which you have entered the passphrase should be able to connect. Ignoring firewall rules avoids us having to discuss variations in rules to accommodate different configurations of kplex. We will revist this when we discuss connecting the network to the Internet.
Disable Unnecessary Services
There are two good reasons to disable services you aren't using.
- Security: Any running program is a potential risk. Possibly a very small risk, but if you don't need it, why have it?
- Performance: Any running program you don't need is a waste of resources
Misc Configuration
If you're not using IPv6, you might as well disable it. If you have a file /etc/modprobe.d/ipv6.conf, ensure the following line is in it:
alias net-pf-10 offIf you don't, or there isn't, make a file of that name containing the line above. Later we'll discuss making proper use of IPv6 on your boat network.
Firing it up
Everything should start cleanly on boot. You should be able to:
- See the SSID you specified in hostapd.conf in your list of available networks on another wireless device (e.g. ipad)
- Connect to the access point using the passphrase you specified and obtain an IP address
- Connect an application which uses NMEA-0183-over TCP by telling it to use
the server at:
Address: 192.168.129.1 Port: 10110
Next Steps
If there is no link associated with the list items below, that page hasn't been written yet and is "Coming Soon..."
- Using the Pi's "Serial Port" for an NMEA-0183 connection
- Adding an Internet connection
- IPv6 connectivity