Your antenna can hear ships

· feeders · ais · ships · network

Earlier today a feeder on the Lower Mississippi flew over his own house in the simulator and saw empty water. There is a towboat moored twenty metres from his door. He asked, reasonably, what firehose we were ingesting.

The answer was AISStream, a free network of volunteer coastal receivers, and it has no listener anywhere near him. We checked that from three directions and it held up. Our daily city sweep had probed New Orleans twice and found nothing both times, while Houston and Corpus Christi, sampled in the same message on the same day, came back with 175 and 67 ships.

Then we checked a second source and the towboat was there. Two of them: MISS DANIELLE and SOMMER S, both tugs, both sitting three kilometres from his pin, both transmitting perfectly well. The gap was never in his river. It was in our supplier.

Buying a bigger firehose only moves the hole

We could have subscribed to another aggregator. That would have fixed New Brunswick, or Louisiana, or the Baltic, until the next stretch of coast nobody happens to cover. All of these networks are volunteers with antennas, and their maps have the same shape: dense where hobbyists live, blank where they aren't.

We already have people with antennas. That is the whole ADS-B side of this project, pointed at the sky from windowsills in six countries. AIS is the same hobby on a different frequency, an RTL-SDR listening at 162 MHz instead of 1090, and the feeder who started this conversation already had one running. He just had nowhere to send it.

Now he does.

One flag

If you run AIS-catcher, your station page on /feed shows a second line next to your Beast connector:

AIS-catcher -H https://<your-station-id>@skydex.online/api/ais/feed gzip on interval 15

That is the whole setup. No config file, no second registration, no new account. It is the same station, the same roof, the same page, the same name in the network, and it now feeds two bands. The page says which bands are actually arriving, because a station that promises AIS and delivers nothing is a lie printed on a public page.

Ships your antenna hears go straight into the world. The sea around you fills in whether or not a pilot happens to be flying overhead, the vessels show on the public map, and they count on your station's numbers.

What we kept

The privacy line doesn't move, and it matters more here than upstream, because a local receiver hears far more small craft than a distant one. Sailing and pleasure boats are drawn but never named, never written down, never collectible. A small vessel that hasn't said what it is stays anonymous until it does.

One thing did change while we were building this. A boat that declares itself a pilot vessel, a port tender or a search-and-rescue craft was being treated as unidentified: anonymised forever because we had no model for it, not because we didn't know what it was. Those are working boats and they carry their names again. Declaring what you are is different from saying nothing.

Update, the same evening: any decoder now

The paragraph below used to say the universal door was coming next. It's open. Alongside the AIS-catcher command, every station page now shows a host and a port:

feed.skydex.online 10110

That is plain NMEA over UDP, on the port the marine world has used for it since before any of this existed. Whatever your receiver runs (rtl-ais, dAISy, OpenCPN, shipfeeder, a chartplotter with a spare output), if it can forward sentences to a host, it can feed the network. We wrote our own decoder for it, reading the message types that matter: position reports from both equipment classes, and the static reports that turn a contact into a named ship with a length and a destination.

Two things about that door. It accepts anonymous senders, so your ships reach the map whether or not we know whose antenna heard them; the alternative is turning a two-minute contribution into a signup. And if you do want the credit, a tag block with your station id in front of the sentences claims them, which is the mechanism the NMEA standard already has for exactly this.

It also cannot verify anyone. UDP has no handshake and a forgeable return address, so a station id there is a hint we accept, not a password we check. The number that decides rankings still comes from what your station delivers over the authenticated path.

What this does not fix

It doesn't conjure coverage out of nothing. The Bay of Fundy, where our Canadian feeder flies, is dark in every source we can reach, including the ones we don't use. Nobody is listening there. The difference is that now, when somebody decides to, there is somewhere to send it.

Two ladders, not one table

The station leaderboard has two now. Sky lists ADS-B receivers, Water lists AIS ones, and each is ranked and numbered inside itself.

An antenna hearing four thousand airframes in a month and one hearing two hundred hulls are not doing the same job badly and well. They are different hardware listening to different things over different distances. Put them in one column and the ranking stops meaning anything: "#3 of 12" would be a sentence about nothing, and the water would sit permanently at the bottom of a competition it was never in.

So each band carries its own numbers and never the other band's. A ships station shows vessels heard and messages delivered. It doesn't show a column of zeroes labelled "aircraft", because a zero about work nobody signed up for reads as a broken receiver. The same in reverse: an aircraft station is not scored on hulls. Signal, the score both ladders sort by, uses the same formula on both, against ceilings set for what each band can actually hear.

We fixed two bugs on the way, both the same kind: the system knew something and never wrote it down. A receiver feeding over UDP was putting ships on the map while its own page said it had never fed, because only the HTTP door recorded daily rows. And an AIS station's uptime was structurally zero, because the minute-by-minute presence figure came from the sweep that watches aircraft receivers, and nothing watched the water. Both now go through one path, so a station's numbers no longer depend on which door its decoder speaks through.

If your section is empty, that's honest too. Water has no receivers yet. It says so, and it says how to be the first.

What the station page shows now

A ships receiver's page had one thing to say about itself: how many hulls it heard and how many messages it delivered. Its ADS-B neighbour has had a wall of aircraft models since early September, with per-model counts. So we built the water's version.

The grouping key has to be different. An aircraft announces its model designator in almost every message; a hull announces its type only in the static message, which arrives about once every six minutes. So the wall groups by the coarse AIS category (cargo, tankers, tugs and workboats, passenger ships, fishing vessels, high-speed craft) and puts two numbers against each. Hulls is how many different ships of that kind the antenna heard. Sightings is how often any of them turned up, one per hull per UTC day. Sixty different cargo ships once each is a shipping lane; one tug sixty times is a working harbour, and a single "seen 60 times" would throw away the thing that makes one station different from another.

They are not voyages. An antenna can't see where one passage ends and the next begins, and we would rather print a number we can stand behind.

Underneath is a row of flags, which came free: the first three digits of an MMSI are the flag state, so every hull the station hears is counted there, including the ones no static message has classified yet.

The page also prints its own denominator. It says how many of the hulls heard have actually declared a ship type, rather than quietly showing you the smaller, tidier sea. The remainder is two things: hulls whose static message this antenna hasn't caught yet, and private craft, which we never classify or store. The second group isn't an omission we're working on. It's the privacy line the whole AIS side is built on.

No MMSIs appear on the wall, and nothing links to an individual vessel page. Those pages exist only where somebody has caught that ship, and a link into a dead end is worse than no link.

Two pieces of the station page are still missing on the water. A reception rose needs a bearing to each hull that the ingest doesn't compute yet, and "ships nobody else in the network heard" has no equivalent at all: ADS-B deduplicates a position to the receiver that reported it first, and AIS doesn't.

More from Skydex

Play Skydex free →