fastnet2ip 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 alex060
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,415 @@
1
+ Metadata-Version: 2.4
2
+ Name: fastnet2ip
3
+ Version: 1.0.0
4
+ Summary: Read B&G Fastnet serial data, decode it, and broadcast it over UDP as NMEA 0183 or NMEA 2000
5
+ Author: ghotihook
6
+ License: MIT License
7
+
8
+ Copyright (c) 2025 alex060
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/ghotihook/fastnet2ip
29
+ Project-URL: Repository, https://github.com/ghotihook/fastnet2ip
30
+ Project-URL: Issues, https://github.com/ghotihook/fastnet2ip/issues
31
+ Keywords: fastnet,bandg,nmea,nmea0183,nmea2000,marine,sailing,signalk
32
+ Classifier: Development Status :: 4 - Beta
33
+ Classifier: Environment :: Console
34
+ Classifier: Intended Audience :: End Users/Desktop
35
+ Classifier: License :: OSI Approved :: MIT License
36
+ Classifier: Operating System :: POSIX :: Linux
37
+ Classifier: Operating System :: MacOS
38
+ Classifier: Programming Language :: Python :: 3
39
+ Classifier: Programming Language :: Python :: 3.10
40
+ Classifier: Programming Language :: Python :: 3.11
41
+ Classifier: Programming Language :: Python :: 3.12
42
+ Classifier: Programming Language :: Python :: 3.13
43
+ Classifier: Topic :: Communications
44
+ Classifier: Topic :: System :: Networking
45
+ Requires-Python: >=3.10
46
+ Description-Content-Type: text/markdown
47
+ License-File: LICENSE
48
+ Requires-Dist: pyserial>=3.5
49
+ Requires-Dist: pyfastnet>=2.0.13
50
+ Requires-Dist: nmea2000>=2026.4.2
51
+ Provides-Extra: test
52
+ Requires-Dist: pytest>=7.0; extra == "test"
53
+ Dynamic: license-file
54
+
55
+ # fastnet2ip
56
+
57
+ Fastnet is the proprietary serial protocol used by B&G on older instruments (tested on Hydra/H2000). `fastnet2ip` reads raw Fastnet data from a serial port, decodes it using [pyfastnet](https://github.com/ghotihook/pyfastnet), and broadcasts it over UDP in your choice of output format:
58
+
59
+ | Output | Flag | Default port | Use with |
60
+ |---|---|---|---|
61
+ | NMEA 0183 | `--output nmea0183` | 2002 | Chart plotters, OpenCPN, most navigation software |
62
+ | NMEA 2000 | `--output nmea2000` | 2000 | Actisense, Yacht Devices, Signal K server (via UDP) |
63
+
64
+ `--output nmea0183` is the default.
65
+
66
+
67
+ ## Installation
68
+
69
+ `fastnet2ip` is a Python application (requires **Python 3.10+**). The easiest way to install it as a self-contained command is [pipx](https://pipx.pypa.io/):
70
+
71
+ ```bash
72
+ pipx install fastnet2ip
73
+ ```
74
+
75
+ This puts a `fastnet2ip` command on your PATH in an isolated environment. To upgrade later:
76
+
77
+ ```bash
78
+ pipx upgrade fastnet2ip
79
+ ```
80
+
81
+ <details>
82
+ <summary>Alternative: install with pip into a virtual environment</summary>
83
+
84
+ ```bash
85
+ python3 -m venv ~/fastnet2ip-venv
86
+ source ~/fastnet2ip-venv/bin/activate
87
+ pip install fastnet2ip
88
+ ```
89
+
90
+ Upgrade with `pip install --upgrade fastnet2ip`.
91
+ </details>
92
+
93
+ <details>
94
+ <summary>Alternative: install from source (for development)</summary>
95
+
96
+ ```bash
97
+ git clone https://github.com/ghotihook/fastnet2ip
98
+ cd fastnet2ip
99
+ python3 -m venv .venv
100
+ source .venv/bin/activate
101
+ pip install -e ".[test]"
102
+ ```
103
+
104
+ This installs the package in editable mode along with the test dependencies.
105
+ </details>
106
+
107
+
108
+ ## Hardware
109
+
110
+ Fastnet uses two-wire differential transmission. RS-485 adapters work well; the CAN Hat option includes 120 ohm termination which is recommended.
111
+
112
+ **Tested hardware**
113
+ - Raspberry Pi 4/5/Zero 2W
114
+ - Mac
115
+ - [M5Stack Core MP135](https://shop.m5stack.com/products/m5stack-coremp135-w-stm32mp135d) — has RS422/485 built in; a bit more fiddly to set up but good for a permanent install
116
+ - [DTECH USB RS422/RS485 dongle](https://www.amazon.com.au/DTECH-Converter-Adapter-Supports-Windows/dp/B076WVFXN8) — works out of the box
117
+ - [Waveshare RS485 CAN HAT](https://www.waveshare.com/wiki/RS485_CAN_HAT) — add to `/boot/firmware/config.txt`:
118
+ ```
119
+ dtoverlay=mcp2515-can0,oscillator=12000000,interrupt=25,spimaxfrequency=2000000
120
+ ```
121
+
122
+ **Wiring**
123
+
124
+ | Fastnet wire | RS-485 |
125
+ |---|---|
126
+ | White | Data + |
127
+ | Green | Data - |
128
+
129
+ **Serial settings**: 28,800 baud, 8 data bits, odd parity, 2 stop bits
130
+
131
+
132
+ ## Running
133
+
134
+ Once installed, run the `fastnet2ip` command directly.
135
+
136
+ **Live data from serial port**
137
+
138
+ ```bash
139
+ fastnet2ip --serial /dev/ttyUSB0 --output nmea0183 --live-data
140
+ fastnet2ip --serial /dev/ttyUSB0 --output nmea2000 --live-data
141
+ ```
142
+
143
+ **From a recorded hex file (testing)**
144
+
145
+ ```bash
146
+ fastnet2ip --file example1_fastnet_data.txt --output nmea0183 --live-data
147
+ ```
148
+
149
+ Sample recordings live in `tests/data/` in the source repository.
150
+
151
+ **Console output — `--live-data` flag**
152
+
153
+ ![Example console output](images/console_output.jpg "Fastnet live data console")
154
+
155
+ > The application can also be invoked as a module: `python3 -m fastnet2ip ...`. This is equivalent to the `fastnet2ip` command.
156
+
157
+
158
+ ## Command-line arguments
159
+
160
+ **Shared**
161
+
162
+ | Argument | Default | Description |
163
+ |---|---|---|
164
+ | `--output FORMAT` | `nmea0183` | `nmea0183` or `nmea2000` |
165
+ | `--serial PORT` | — | Serial port (e.g. `/dev/ttyUSB0`) |
166
+ | `--file PATH` | — | Path to a recorded hex file |
167
+ | `--log-level LEVEL` | `INFO` | `DEBUG`, `INFO`, `WARNING`, `ERROR` |
168
+ | `--live-data` | off | Print live channel table to console once per second |
169
+ | `--ignore-gps` | off | Suppress GPS channels — see below |
170
+ | `--ignore-heading` | off | Suppress heading channels — see below |
171
+ | `--host ADDR` | `255.255.255.255` | UDP destination host |
172
+ | `--udp-port N` | `2002` / `2000` | UDP port (default depends on output mode) |
173
+
174
+ **NMEA 2000** (`--output nmea2000`)
175
+
176
+ | Argument | Default | Description |
177
+ |---|---|---|
178
+ | `--n2k-src N` | `201` | N2K source address 0–253 (accepts hex: `0xC9`) |
179
+ | `--n2k-pri N` | `4` | Message priority 0 (highest) – 7 (lowest) |
180
+ | `--n2k-format FMT` | `ydwg` | Wire format: `ydwg` or `pcdin` (see below) |
181
+
182
+
183
+ ## Avoiding feedback loops: `--ignore-gps` and `--ignore-heading`
184
+
185
+ Most B&G systems receive GPS (and sometimes heading) from an external source and pass it through onto the Fastnet bus alongside the instrument data. If you also connect that same source directly to your network, re-broadcasting it from this bridge creates a **feedback loop** — downstream software sees the same data arriving twice, which can cause jumps, conflicts, or incorrect averaging.
186
+
187
+ Use `--ignore-gps` and/or `--ignore-heading` when that source is **already** on your network. Both flags work with `--output nmea0183` and `--output nmea2000`.
188
+
189
+ `--ignore-gps` suppresses:
190
+
191
+ | Fastnet channel | NMEA 0183 | NMEA 2000 |
192
+ |---|---|---|
193
+ | LatLon | GLL | PGN 129025 |
194
+ | Speed Over Ground | VTG | PGN 129026 |
195
+ | Course Over Ground (True) | VTG | PGN 129026 |
196
+ | Course Over Ground (Mag) | VTG | PGN 129026 |
197
+
198
+ `--ignore-heading` suppresses:
199
+
200
+ | Fastnet channel | NMEA 0183 | NMEA 2000 |
201
+ |---|---|---|
202
+ | Heading | HDM / HDT | PGN 127250 |
203
+ | Heading (Raw) | — | PGN 65281 |
204
+
205
+ If the bridge is the **only** source of that data on your network, omit these flags.
206
+
207
+
208
+ ## NMEA 0183 Output
209
+
210
+ | Sentence | Content |
211
+ |---|---|
212
+ | VHW | Boatspeed; heading in True or Magnetic field per instrument configuration |
213
+ | DBT | Depth below transducer |
214
+ | RSA | Rudder angle |
215
+ | HDM | Magnetic heading (emitted when instrument is configured for magnetic reference) |
216
+ | HDT | True heading (emitted when instrument is configured for true reference) |
217
+ | MWD | True wind direction and speed; direction True or Magnetic per instrument configuration |
218
+ | MWV | True wind angle/speed (ref T) |
219
+ | MWV | Apparent wind angle/speed (ref R) |
220
+ | MDA | Air temp, sea temp, barometric pressure |
221
+ | VTG | COG and SOG |
222
+ | VPW | Velocity made good |
223
+ | VDR | Tidal set and drift; set direction True or Magnetic per instrument configuration |
224
+ | GLL | Latitude/Longitude |
225
+
226
+ > **Note on True vs Magnetic:** The Fastnet data stream carries no magnetic variation or deviation. Whether a channel is labelled True or Magnetic reflects the reference configured in the B&G instrument — not a computed conversion. VHW, HDM/HDT, MWD, and VDR will each output whichever reference the instrument is set to.
227
+
228
+ XDR transducers:
229
+
230
+ | XDR name | Content |
231
+ |---|---|
232
+ | `BATTV` | Battery voltage |
233
+ | `ROLL` | Heel angle (degrees) |
234
+ | `PITCH` | Fore/aft trim (degrees) |
235
+ | `RAW_WIND_A` | Apparent wind angle raw sensor value |
236
+ | `RAW_WIND_S` | Apparent wind speed raw sensor value |
237
+ | `RAW_BSP` | Boatspeed raw sensor value |
238
+
239
+
240
+ ## NMEA 2000 Output
241
+
242
+ | PGN | Name |
243
+ |---|---|
244
+ | 127245 | Rudder |
245
+ | 127250 | Vessel Heading |
246
+ | 127251 | Rate of Turn |
247
+ | 127257 | Attitude (heel + trim) |
248
+ | 127508 | Battery Status |
249
+ | 128000 | Leeway |
250
+ | 128259 | Boat Speed |
251
+ | 128267 | Water Depth |
252
+ | 128275 | Distance Log |
253
+ | 129025 | Position |
254
+ | 129026 | COG & SOG |
255
+ | 129283 | Cross Track Error |
256
+ | 129291 | Set & Drift |
257
+ | 130306 | Wind Data (apparent, true boat-ref, true ground-ref) |
258
+ | 130312 | Temperature (sea + air) |
259
+ | 130314 | Pressure |
260
+ | 65280 | Proprietary: raw wind speed, wind angle |
261
+ | 65281 | Proprietary: raw heading |
262
+ | 65282 | Proprietary: raw boatspeed |
263
+
264
+ **Wire formats** (`--n2k-format`):
265
+ - `ydwg` — Yacht Devices RAW UDP: `HH:MM:SS.mmm R XXXXXXXX DD DD DD...`
266
+ - `pcdin` — PCDIN sentences for Signal K server UDP input: `$PCDIN,PPPPPP,TTTTTTTT,SS,DDDD...*CC`
267
+
268
+
269
+ ## Running as a systemd service
270
+
271
+ For an always-on bridge (e.g. a Raspberry Pi), run `fastnet2ip` under systemd so it starts on boot and restarts on failure.
272
+
273
+ > **Don't use the pipx install for the service.** pipx installs into a *user's* `~/.local/bin`, which a root-run service can't rely on. For a service, install into a dedicated system virtual environment instead.
274
+
275
+ **1. Install into a dedicated venv**
276
+
277
+ ```bash
278
+ sudo python3 -m venv /opt/fastnet2ip
279
+ sudo /opt/fastnet2ip/bin/pip install fastnet2ip
280
+ ```
281
+
282
+ This gives you `/opt/fastnet2ip/bin/fastnet2ip`, the path the service below uses.
283
+
284
+ **2. Create the unit file**
285
+
286
+ Paste the following into `/etc/systemd/system/fastnet2ip.service` (e.g. `sudo nano /etc/systemd/system/fastnet2ip.service`). The same template ships as `fastnet2ip.service` in the source repository if you'd rather copy it.
287
+
288
+ ```ini
289
+ [Unit]
290
+ Description=fastnet2ip Service
291
+ ####################################### CHANGE THIS IF PORT CHANGES
292
+ After=dev-ttyUSB0.device
293
+ BindsTo=dev-ttyUSB0.device
294
+
295
+ [Service]
296
+ Type=simple
297
+ User=root
298
+ WorkingDirectory=/opt/fastnet2ip
299
+ # Uncomment ONE ExecStart line for the output mode you want:
300
+ # NMEA 2000 output:
301
+ ExecStart=/opt/fastnet2ip/bin/fastnet2ip --output nmea2000 --serial /dev/ttyUSB0 --udp-port 2000 --n2k-format ydwg --n2k-src 201 --n2k-pri 4 --ignore-gps --log-level INFO
302
+ # NMEA 0183 output:
303
+ #ExecStart=/opt/fastnet2ip/bin/fastnet2ip --output nmea0183 --serial /dev/ttyUSB0 --udp-port 2002 --log-level INFO
304
+ Restart=always
305
+ RestartSec=10
306
+
307
+ # === RESOURCE LIMITS ===
308
+ OOMScoreAdjust=-700
309
+ OOMPolicy=continue
310
+ MemoryMax=128M
311
+ MemoryHigh=96M
312
+ TimeoutStopSec=30
313
+
314
+ # === LOGGING ===
315
+ StandardOutput=journal
316
+ StandardError=journal
317
+ SyslogIdentifier=fastnet2ip
318
+ Environment=PYTHONUNBUFFERED=1
319
+
320
+ [Install]
321
+ WantedBy=multi-user.target
322
+ ```
323
+
324
+ **Before enabling, edit it to match your setup:**
325
+ - `After=` / `BindsTo=` — your serial device, written in systemd's escaped form (`/dev/ttyUSB0` → `dev-ttyUSB0.device`)
326
+ - the active `ExecStart=` — pick **one** line (NMEA 0183 or NMEA 2000) and set the correct `--serial` port
327
+
328
+ **3. Enable and start it**
329
+
330
+ ```bash
331
+ sudo systemctl daemon-reload
332
+ sudo systemctl enable fastnet2ip
333
+ sudo systemctl start fastnet2ip
334
+ sudo journalctl -u fastnet2ip -f # follow the logs
335
+ ```
336
+
337
+ To upgrade later: `sudo /opt/fastnet2ip/bin/pip install --upgrade fastnet2ip && sudo systemctl restart fastnet2ip`.
338
+
339
+
340
+ ## Bench testing tools
341
+
342
+ Two helper scripts for capturing and replaying Fastnet data live in the `tools/` directory of the source repository (they are not installed by pip/pipx — clone the repo to use them):
343
+
344
+ **Record raw Fastnet data to file**
345
+
346
+ ```bash
347
+ python3 tools/record_fn.py --port /dev/ttyUSB0 --output my_capture.txt
348
+ ```
349
+
350
+ **Play back a recording to a serial port**
351
+
352
+ ```bash
353
+ python3 tools/playback_fn.py --port /dev/ttyUSB1 --input my_capture.txt
354
+ ```
355
+
356
+ Recordings can also be replayed through the main app with `fastnet2ip --file my_capture.txt`.
357
+
358
+
359
+ ## How it works
360
+
361
+ ```
362
+ Serial port / hex file
363
+
364
+
365
+ pyfastnet FrameBuffer ← byte sync, checksum, channel decoding
366
+
367
+
368
+ Live data store ← latest value per channel
369
+
370
+
371
+ Output handler ← nmea0183 or nmea2000, selected by --output
372
+
373
+
374
+ UDP broadcast
375
+ ```
376
+
377
+ A message is sent when a value changes, or after 5 seconds if unchanged (so downstream apps don't lose data during quiet periods).
378
+
379
+ To add a new output format, implement `OutputHandler` in `fastnet2ip/handlers/` and add it to `_HANDLERS` in `fastnet2ip/__main__.py`.
380
+
381
+
382
+ ## What this app does vs. pyfastnet
383
+
384
+ [pyfastnet](https://github.com/ghotihook/pyfastnet) handles the protocol layer: frame sync, checksums, and decoding raw bytes into named instrument channels. This app handles everything above that: reading the serial port, maintaining a live data store, mapping channels to output sentences/frames, rate limiting, and UDP broadcast.
385
+
386
+
387
+ ## Development
388
+
389
+ ```bash
390
+ git clone https://github.com/ghotihook/fastnet2ip
391
+ cd fastnet2ip
392
+ python3 -m venv .venv
393
+ source .venv/bin/activate
394
+ pip install -e ".[test]"
395
+ pytest
396
+ ```
397
+
398
+ To build distributable artifacts:
399
+
400
+ ```bash
401
+ pip install build
402
+ python -m build # writes sdist + wheel to dist/
403
+ ```
404
+
405
+
406
+ ## Acknowledgments
407
+
408
+ - [trlafleur](https://github.com/trlafleur) — collected significant background research
409
+ - [Oppedijk](https://www.oppedijk.com/bandg/fastnet.html) — protocol background
410
+ - [timmathews](https://github.com/timmathews/bg-fastnet-driver) — substantial C++ implementation
411
+
412
+
413
+ ## License
414
+
415
+ MIT — see [LICENSE](LICENSE).