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.
- fastnet2ip-1.0.0/LICENSE +21 -0
- fastnet2ip-1.0.0/PKG-INFO +415 -0
- fastnet2ip-1.0.0/README.md +361 -0
- fastnet2ip-1.0.0/fastnet2ip/__init__.py +1 -0
- fastnet2ip-1.0.0/fastnet2ip/__main__.py +153 -0
- fastnet2ip-1.0.0/fastnet2ip/core/__init__.py +0 -0
- fastnet2ip-1.0.0/fastnet2ip/core/data_store.py +34 -0
- fastnet2ip-1.0.0/fastnet2ip/core/display.py +23 -0
- fastnet2ip-1.0.0/fastnet2ip/core/input.py +57 -0
- fastnet2ip-1.0.0/fastnet2ip/handlers/__init__.py +0 -0
- fastnet2ip-1.0.0/fastnet2ip/handlers/base.py +43 -0
- fastnet2ip-1.0.0/fastnet2ip/handlers/nmea0183.py +379 -0
- fastnet2ip-1.0.0/fastnet2ip/handlers/nmea2000.py +612 -0
- fastnet2ip-1.0.0/fastnet2ip.egg-info/PKG-INFO +415 -0
- fastnet2ip-1.0.0/fastnet2ip.egg-info/SOURCES.txt +21 -0
- fastnet2ip-1.0.0/fastnet2ip.egg-info/dependency_links.txt +1 -0
- fastnet2ip-1.0.0/fastnet2ip.egg-info/entry_points.txt +2 -0
- fastnet2ip-1.0.0/fastnet2ip.egg-info/requires.txt +6 -0
- fastnet2ip-1.0.0/fastnet2ip.egg-info/top_level.txt +1 -0
- fastnet2ip-1.0.0/pyproject.toml +50 -0
- fastnet2ip-1.0.0/setup.cfg +4 -0
- fastnet2ip-1.0.0/tests/test_nmea0183.py +240 -0
- fastnet2ip-1.0.0/tests/test_nmea2000.py +295 -0
fastnet2ip-1.0.0/LICENSE
ADDED
|
@@ -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
|
+

|
|
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).
|