Technical note

How Seabearing talks to your boat and your crew

Updated 26 October 2026.

Contents
  1. The boat network
  2. Reading the instruments
    1. Protocols and ports
    2. NMEA 0183 over TCP
    3. NMEA 2000 as text
    4. Signal K
    5. What is decoded
    6. Choosing between sources
  3. Finding the plotter
    1. The subnet
    2. Three ways to find a host
    3. When it searches
    4. Picking one
  4. The crew link
    1. A mesh, no leader
    2. The LAN line
    3. The relay
    4. LAN or relay
    5. What is sent, and when
  5. Keys and encryption
    1. Primitives
    2. Pairing
    3. Removing a member
    4. Sequence numbers and delivery
  6. Calls
  7. What Android has to be told
  8. Bandwidth

1 The boat network

The boat's Wi-Fi, from the plotter or a gateway, often has no internet, so the phone keeps mobile data as its default route.

Four kinds of traffic, kept apart:

  • InstrumentsPlotter or gateway to phone, on the boat Wi-Fi. Received only.
  • Crew LAN linePhone to phone, on the boat Wi-Fi. One TCP connection per pair of devices, carrying encrypted lines.
  • Crew relayPhone to phone through a server on the internet. One WebSocket per device, live messages only.
  • CallsWebRTC audio between crew devices. Setup travels over the crew link; the audio goes direct if it can.
The boat network A plotter or gateway on the boat Wi-Fi sends instrument data to two crew devices. The devices talk to each other on the Wi-Fi, and each also keeps a WebSocket to a relay on the internet. Relay live messages only Boat Wi-Fi, one subnet Phone Seabearing app Tablet Seabearing app crew LAN line TCP Plotter or gateway instrument data instruments read only instruments read only WSS, TLS WSS, TLS
Figure 1. Solid lines stay on the boat's Wi-Fi. Dashed lines cross the internet.

The web app cannot open TCP or UDP sockets: it reads no instruments and its crew link uses the relay only.

2 Reading the instruments

The sockets live in the app's foreground service, so they stay open with the screen off and can be bound to one network.

2.1 Protocols and ports

SourceTransportDefault portRole of the app
NMEA 0183TCP, the app is the client10110Receive
NMEA 0183UDP datagrams, unicast or broadcast10110Receive
NMEA 2000, as textTCP, the app is the client1456Receive
Signal KHTTP, then WebSocket3000Receive
NMEA 0183 over BLE UARTGATT notificationsn/aReceive

Nothing here transmits, except Signal K's subscription request and the one Bluetooth write that turns notifications on.

2.2 NMEA 0183 over TCP

Most Wi-Fi gateways accept one client, so a change of target closes the live socket at once.

SettingValueNotes
Connect timeout1200 ms
Read timeout3000 ms
Stale20 sNo data
Longest line1024 bytesBounds a misbehaving gateway.
TCP keepaliveonSO_KEEPALIVE
Reconnect backoff1, 2, 4, 8, 16, 30 sThen every 30 s. Resets on a good connection. A Wi-Fi change skips the wait.
NetworkWi-FiThe socket is bound to the Wi-Fi network when the host is an IPv4 address on that subnet.

Without that binding, a socket on the default (mobile data) route never reaches 192.168.1.x. A host given as a name, or an address elsewhere, keeps normal routing.

UDP binds 0.0.0.0 on the configured port (default 10110) with address reuse and broadcast on, so one socket takes a gateway's broadcast and a unicast stream. Same 3 s read timeout and 20 s staleness as TCP.

2.3 NMEA 2000 as text

The app reads no CAN bus itself: a gateway sends CAN frames as text lines over TCP, in four framings detected line by line: Yacht Devices RAW, Actisense ASCII, $PCDIN and $MXPGN.

Yacht Devices RAW   time  dir  CAN id    data
19:58:53.469 R 09F8017F 50 C3 B8 13 47 D8 2B C6

Actisense ASCII     A+time  src  dst+pgn  data
A173321.107 23FF7 1F513 012F3070002F30709F

An Actisense USB gateway plugged into the device goes through the same decoder.

Fast-packet messages are reassembled. These 16 PGNs are decoded; any other is ignored.

GroupPGNs
Heading, attitude127250 heading, 127257 attitude (pitch, roll)
Speed, depth128259 speed through water, 128267 water depth
Position129025 position rapid update, 129029 GNSS position data
AIS129038 and 129039 position reports (Class A, B), 129794 Class A static, 129809 and 129810 Class B static (parts A, B)
Wind130306
Environment130310 and 130311 environmental parameters, 130312 temperature, 130316 temperature extended range

2.4 Signal K

The app asks GET http://host:3000/signalk (1.5 s timeout) for the stream's address, and otherwise uses:

ws://host:3000/signalk/v1/stream?subscribe=self

subscribe=self: the boat's own data, not every vessel the server knows. Reconnects wait 1, 2, 4, 8, 16, then 30 s.

2.5 What is decoded

A sentence with a wrong checksum is dropped; a source that has never sent a checksum is accepted without one.

GroupSentences
DepthDBT DPT DBS DBK
HeadingHDG HDT HDM
WindMWV MWD VWR VWT
Speed, water temperature, transducersVHW MTW XDR
Position and GNSS qualityGGA RMC GLL GNS GSA GST PGRME
AISVDM and VDO, message types 1, 2, 3, 5, 18, 19, 21 and 24
$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A
$SDDBT,12.4,f,3.8,M,2.1,F*39
$WIMWV,214.8,R,12.4,N,A*1B
$IIHDT,274.07,T*14
!AIVDM,1,1,,B,15M67FC000G?ufbE`FepT@3n00Sa,0*5C

Multi-sentence AIS messages are reassembled.

2.6 Choosing between sources

Per reading:

  • A reading is current for 5 s; an older one is ignored.
  • For depth, the shallowest current reading wins. A current "no bottom" report beats a numeric one only if it is at least as new.
  • For wind angle, MWV is preferred over the other wind sentences.
  • The source in use stays unless a better-ranked one appears, so the display does not flicker between equals.
  • The device's own instruments beat readings relayed by crew. A crew reading is used only when this device has no current one, and two crew sources are not switched on a gap under 1.5 s.

3 Finding the plotter

Android only. The app looks for hosts that answer on a known port and checks that they send NMEA, so nobody types an IP address.

Plotter discovery A search starts, picks the Wi-Fi subnet, gathers candidates by mDNS, by the Navico beacon and by a TCP sweep, checks that each sends valid NMEA, chooses one, and connects. A search is due no plotter set, failing 20 s, every 120 s, or a Wi-Fi change (now, +10 s, +30 s) 1 · Pick the subnet first Wi-Fi network with an IPv4 address up to /22 as is; wider: the /24 around us 2a · mDNS 3 types 400 ms each 1.2 s total 2b · Beacon Navico GoFree 239.2.1.1:2052 listen 2.5 s 2c · Sweep each port 4 at a time 150 ms each 3 · Check what answers wait up to 900 ms for a sentence with a valid checksum; mark hosts that send position or heading 4 · Choose the unit whose serial we remember, else the only host found, else the only host with boat data, else ask the person 5 · Connect a live connection is never replaced
Figure 2. The plotter in use is left out of the sweep: probing it would take its only client slot.

3.1 The subnet

The Wi-Fi network with an IPv4 address, not the default network (section 2.2). A prefix of /22 or narrower is swept whole; a wider one, only the /24 around the phone. A subnet of more than 1022 hosts is never swept.

The sweep also skips the phone's own address. A plotter set by name is matched by its resolved address.

3.2 Three ways to find a host

MethodWhat it doesTime
mDNS / DNS-SDBrowses _nmea-0183._tcp, _signalk-ws._tcp and _signalk-http._tcp, one after another.about 400 ms each
Navico GoFree beaconJoins multicast group 239.2.1.1, port 2052, under a multicast lock. Each plotter announces a JSON datagram with its address, model, name and serial number. The serial is the unit's identity: its DHCP address changes, and Android 10 and later hide other devices' MAC addresses.2.5 s
TCP sweepConnects to every address on the subnet, each port in turn, 4 at a time, then reads each open port for a sentence with a valid checksum.connect 150 ms, read 900 ms

Ports, in order: the configured one, then 10110, 2000, 1456, 39150, 10111, 5000 and 8888. The first four are known gateway families (Navico and similar, Digital Yacht and Quark-elec, Yacht Devices, Garmin and Vesper); the last three, common serial-to-Wi-Fi boxes. Signal K mode tries 3000. NMEA 2000 mode tries 1456 and 2000.

A host is marked "boat data" if it sends position or heading (RMC, GGA, GLL, HDG, HDT, HDM or THS); the check stops reading as soon as it sees one.

Worst case. On a /24 where every address silently drops packets, the sweep makes 253 attempts, 4 at a time, each ending at the 150 ms timeout: 64 rounds, about 9.6 s per port. All eight ports, about 77 s. In practice hosts answer or refuse in milliseconds; the search runs in the background.

3.3 When it searches

  • Never while connected, and never on the first connection attempt.
  • When instruments are off or no plotter address is set.
  • When the configured plotter has been failing for 20 s.
  • Then at most every 120 s while that holds.
  • When the Wi-Fi changes: at once, then 10 s and 30 s later, while DHCP and routes settle. What was offered or declined on the earlier network is forgotten.

A configured plotter coming back is the TCP client's reconnect, not a search.

3.4 Picking one

A search connects by itself only to the unit whose serial was remembered from the beacon, else the only host found, else the only host sending position or heading. Otherwise the app shows the list and asks. A unit announcing a different serial from the remembered one is never taken.

4 The crew link

Crew devices share positions, instrument readings, nearby AIS targets, alarms and a shared document holding the crew list.

4.1 A mesh, no leader

Every device sends every message to every other device. No leader, no forwarding: a device never repeats another's message. "Captain" is a role in the shared document, not on the network.

4.2 The LAN line

Devices on the same Wi-Fi find each other by Android network service discovery, advertising _seabearing._tcp on an ephemeral TCP port, and keep a TCP connection to each peer, up to 16. Each message is one line.

{"s":"Qk3xT_9aL2c","c":"7be1…(32 hex)","m":{"v":3,"n":"…","x":"…"}}\n

s  salt: 8 random bytes, base64url, new on every line
c  tag: first 128 bits of SHA-256 over the crew's channel name and the salt
m  the sealed message: version, 12-byte nonce, AES-GCM ciphertext (section 5)

A device finds which of its crews a line is for by hashing each of its channel names with the line's salt. A bystander on the Wi-Fi sees neither which crew is talking nor whether two lines are the same crew's. A salt seen before is dropped (the last 1024 are kept), so a replayed line does nothing.

LimitValue
Line length16 KiB
Peers sent to16 (crew devices first, then the newest others)
Connect timeout1500 ms
Keepalive lineevery 10 s
Idle close45 s without a line or keepalive
Connections held8 in all, 2 per address
Rate limit, per sending address40 lines per 10 s
Rate limit, all addresses not known to be crew120 lines per 10 s

Connections are duplex: a line travels either way on whichever socket exists. The keepalive is a fixed line, not a message. Sockets are made on the network that owns the peer's subnet, with TCP_NODELAY and keepalive on.

Plain TCP, no TLS: the lines are already ciphertext (section 5).

4.3 The relay

Off the same network, or with the LAN line down, messages go through a relay server on the internet. Each device opens one WebSocket over TLS and joins a private channel for its crew.

SettingValue
Heartbeatevery 25 s
Unanswered heartbeatsocket closed and reopened
Open timeout20 s
Reconnect backoff1 s, doubling, capped at 60 s
Acknowledgementsnone (ack: false)
Echo to sendernone (self: false)

The relay stores nothing: a message not heard is gone. The socket opens only while pairing or when the crew has other members, and carries only ciphertext.

4.4 LAN or relay

Every message is sent on the LAN line. It is also sent on the relay when the LAN line is not running, or some other member has not been heard on the LAN within the last 4 s. Leaving the crew, and the pairing envelopes of section 5.2, always go on both paths.

When everyone is heard on the LAN, the relay stays joined but carries nothing from this device.

The path-choice rule Every message is sent on the LAN line. The relay is added if the LAN line is down, the device is leaving, or any member has not been heard on the LAN for 4 seconds. A message to send Send on the LAN line whenever the line is started Add the relay? LAN line down, or leaving, or a member not heard on the LAN for 4 s no yes LAN only relay joined, silent LAN and relay same sealed message the receiver takes the first copy and drops the second
Figure 3. When a message goes both ways, the first copy to arrive wins.

The crew screen's link icon: LAN if a LAN message arrived from the member in the last 15 s, otherwise relay if a relay message did. After 2 minutes of hearing nothing from a member the screen says "Not heard for" and how long.

4.5 What is sent, and when

MessageCadenceNotes
Position1 HzOnly a fix up to 3 s old is sent.
Instrument readings1 HzThe readings chosen in section 2.6.
Heartbeatafter 2 s of silenceAlso what lets each side judge a path (the 4 s rule).
AIS targetsevery 10 sA snapshot of up to 512 targets, nearest first.
AIS static dataevery 10 minNames and dimensions, repeated for devices that joined late.
Document digestevery 60 sA digest of the shared crew document, so a device that missed a change can see it differs.
Raise, Silence3 times: 0, 5, 10 sSee section 5.4.
Track historycatch-upSent in chunks.

5 Keys and encryption

Encryption is end to end between the crew's devices, above both paths: the network, the relay operator and anyone on the marina Wi-Fi see only ciphertext.

5.1 Primitives

PurposeConstruction
Crew key32 random bytes, one per epoch. Every other key is derived from it, with a different label per use.
Key derivationHKDF-SHA-256
Message sealingAES-256-GCM, a fresh random 12-byte nonce per message, the crew id and epoch bound in as associated data
Device identityA P-256 key pair per device. The private key never leaves the device. A short device tag is the first 8 bytes of SHA-256 of the public key.
Key hand-overA "box": ECDH on P-256, HKDF, then AES-256-GCM. Used to give the crew key to one device.
On the LANPlain TCP carrying ciphertext
On the relayTLS to the server, and the same ciphertext inside
CallsWebRTC's DTLS-SRTP

Inside a sealed message is a small record: the crew and epoch, the sender and its device tag, a sequence number, a timestamp, a kind (position, heartbeat, alarm and so on), the body, and optionally the one member it is addressed to.

5.2 Pairing

One QR scan. The code is a one-time pairing secret, not the crew key.

  1. Invite. The inviter makes a 16-byte random secret and a one-time P-256 key. The QR carries the inviter's device id, the secret, a hash of the one-time public key (a commitment), an expiry 5 minutes ahead, and the inviter's name.
  2. Scan. Both sides derive a pairing channel name and an AES key from the secret with HKDF. Everything in the pairing is sealed with that key and sent on both paths.
  3. Join. The joiner sends its id, name, device public key and a one-time public key, every 5 s until answered.
  4. Crew. The inviter adds the joiner to the crew document and answers with the crew id, epoch, crew key and document, in a box sealed to the joiner's one-time key: only that joiner can open it, and, the code having committed to the inviter's key, only the inviter can have made it. A used code, or a joiner claiming an existing member's id with a different device key, gets "used" or "refused" instead, authenticated by an HMAC under the secret the two one-time keys share.
  5. Joined. The joiner takes the crew, replacing any it had, and says so at 0, 1 and 3 s.
The pairing sequence The inviter shows a QR code. The joiner scans it, sends a join message, receives the crew sealed to its one-time key, and confirms three times. Inviter Joiner 1 · make a 16-byte secret and a one-time P-256 key; show the QR (5 min, once) 2 · the QR is scanned secret, key hash, expiry both sides derive the pairing channel and AES key (HKDF) 3 · join id, name, two public keys repeated every 5 s until answered 4 · crew crew id, epoch, key, document sealed to the joiner’s one-time key 5 · joined sent three times: 0 s, 1 s, 3 s instead of 4: “used” or “refused”, tied to this joiner by an HMAC
Figure 4. Pairing works whether or not the two devices share a Wi-Fi network.

5.3 Removing a member

Removing a device starts a new epoch: a new random crew key, sealed to each remaining member's device key, so the removed device never gets it, and with it new derived keys and a new channel name.

The old epoch is accepted for 24 hours, for a phone asleep during the change and frames in flight, then dropped.

5.4 Sequence numbers and delivery

Each message carries a sequence number unique per sending device, accepted once, which is what makes sending on two paths safe.

  • Allocation. Numbers are reserved in recorded blocks of 1000, so a restart can skip numbers but never reuse one.
  • Acceptance. Per sender, a receiver keeps the highest number seen and the recent ones, and drops a number already seen or more than 1024 behind the highest: modest reordering passes, a replay does not. The highest numbers are saved once a minute.
  • No acknowledgements. Position and instrument data are replaced a second later.
  • Alarm presses. A Raise or a Silence is sent three times, at 0, 5 and 10 s. Each press is acted on once and ignored if it is more than 30 s old when it arrives.

6 Calls

WebRTC audio. The offer, answer, ICE candidates, hang-up and busy signals are ordinary crew messages, addressed to one member and sealed like any other. An offer rings for up to 60 s.

  • Topology. One RTCPeerConnection per pair: a mesh of up to 6 people. Full duplex; mute turns off the local track. Echo cancellation, noise suppression and automatic gain are on.
  • ICE servers. From a cloud function, with the user's account session, limited to 120 requests per user per hour: a STUN server on port 443 and TURN credentials from Amazon's managed service, valid for at most 300 s. TURN is used only when the devices cannot reach each other directly.
  • Fallback. No answer in 4 s: public STUN (stun.l.google.com:19302 and global.stun.twilio.com:3478) and no TURN.
  • Camera share. WebRTC on the LAN only, with no ICE servers, so only between devices that reach each other directly. Offered to members heard in the last minute, retried every 10 s backing off to 10 minutes, and abandoned if not open within 30 s.

7 What Android has to be told

With the screen off, Android stops an app's networking unless it holds these.

ResourceHeld whenWhy
Foreground serviceAn anchor watch, an instrument connection or a crew link is activeKeeps the process, its sockets and its timers alive with the screen off.
Wi-Fi lockA network instrument is in use, or the crew link is onKeeps the radio at full power; low-latency mode on Android 10 and later, high-performance before.
Multicast lockCrew LAN discovery; the Navico beacon listenWithout it the Wi-Fi chip discards multicast packets to save power.
Partial wake lockThe crew link is onKeeps the crew link's timers running with the screen off.
Location updatesThe crew link is on, where location is allowedThis device's position goes to the crew every second.
Sockets bound to the Wi-Fi NetworkInstrument connections and probes; crew LAN sockets bound to the network that owns the peer's subnetMobile data stays the default route, and the boat's LAN still works.

A change of Wi-Fi network wakes the instrument client out of its backoff and starts the search of section 3.3.

8 Bandwidth

Estimates, not yet measured on a boat: sizes on the wire (a LAN line with its salt and tag, or a relay message with its framing) times the cadences above. MB are 106 bytes.

Flow, per deviceCadenceLAN lineRelay
Position (own GPS)1 Hz~440 B/s~540 B/s
Instruments frame (the device reading the boat's instruments)1 Hz~910 B/s~1,010 B/s
Shared-state digestevery 60 s~6 B/s~8 B/s
Heartbeatafter 2 s of silence0 while positions flow0
AIS, 50 targetsevery 10 s1.20 MB/h1.24 MB/h
AIS, 300 targets (sent in two parts)every 10 s6.72 MB/h6.80 MB/h

On the LAN each frame is written once per other device; on the relay it goes up once and comes down to each of the others. For a crew of four with one device reading the instruments, in MB an hour, up / down:

AIS targetsInstrument device,
LAN
Instrument device,
relay
Phone,
LAN
Phone,
relay
014.7 / 4.85.6 / 5.94.8 / 8.12.0 / 9.6
5018.3 / 4.86.9 / 5.94.8 / 9.32.0 / 10.8
30034.8 / 4.812.4 / 5.94.8 / 14.82.0 / 16.4

A phone ashore on mobile data in a crew of four uses roughly 100–165 MB down and 20 MB up over a ten-hour night. The AIS snapshot is the largest flow. Track history catch-up is a one-off: about 36 KB per device per hour of track, paced at about one message a second, packed so it fits a LAN line.

Corrections and questions: write to us.