npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

signalk-forward-watch

v0.2.0

Published

AI-powered forward watch obstacle detection for Signal K — detects boats, kayaks, buoys, logs, debris, docks and people using a bow-mounted IP camera

Readme

signalk-forward-watch

AI-powered forward watch obstacle detection for Signal K. Monitors a bow-mounted IP camera using a custom-trained YOLOv8 marine model and sends detections into the Signal K data stream as notifications and values.

Detects: ships, boats, debris, buoys, kayaks, logs


Requirements

  • Signal K server v2.22.1 or later recommended (Node.js ≥ 18)
    • Earlier Signal K versions have an unrelated AIS TCP provider memory leak that causes server instability when AIS is active alongside this plugin
  • A bow-mounted IP camera with RTSP stream (ONVIF cameras auto-discovered)
  • ffmpeg installed on the host (sudo apt install ffmpeg)
  • Raspberry Pi 4 or better (CPU inference, no GPU required)

Installation

Step 1 — Install the plugin

cd ~/.signalk
npm install signalk-forward-watch

Step 2 — Download the detection model

The YOLOv8 marine model is hosted on GitHub Releases (12MB — too large to bundle in the npm package).

mkdir -p ~/.signalk/node_modules/signalk-forward-watch/models
wget -O ~/.signalk/node_modules/signalk-forward-watch/models/forward-watch.onnx \
  https://github.com/SkipperDon/signalk-forward-watch/releases/download/v0.1.0/forward-watch.onnx

Or download it manually from the Releases page and place it at:

~/.signalk/node_modules/signalk-forward-watch/models/forward-watch.onnx

Step 3 — Enable the plugin

Restart Signal K and enable the plugin in Admin → Plugin Config → Forward Watch.


Configuration Fields

| Field | Default | Description | |-------|---------|-------------| | Camera IP Address | — | IP address of your bow camera (e.g. 192.168.1.100) | | Camera Username | admin | RTSP/ONVIF login username | | Camera Password | — | RTSP/ONVIF login password | | RTSP URL | auto | Full RTSP stream URL. If left blank, the plugin runs ONVIF discovery using the IP/user/pass above. Enter manually to skip discovery: rtsp://user:pass@ip:554/stream1 | | Detection interval (seconds) | 30 | How often to grab a frame and run detection. Lower = more CPU. 30s is recommended for Raspberry Pi 4. | | Alert cooldown (seconds) | 30 | Minimum time between repeat alerts for the same target type and quadrant. Prevents alarm flooding. | | Enable audio alarm | false | Plays a system beep on detection within 100m. Requires audio output on the host. | | Confidence threshold | 0.4 | Minimum detection confidence (0–1). Lower = more detections but more false positives. 0.4 is a good starting point. | | Show detections in OpenCPN | true | Sends detections to OpenCPN as AIS targets on the chart. Requires boat GPS. |


Chart Plotter Integration

When Show detections in OpenCPN is enabled, each detected object is written into Signal K as a vessel with a dedicated fake MMSI. Chart plotters that can read Signal K or NMEA 0183 AIS data will display them as AIS targets.

| Detection | Chart label | MMSI | |-----------|-------------|------| | ship | FW-SHIP (confidence%) | 800000001 | | boat | FW-BOAT (confidence%) | 800000002 | | debris | FW-DEBRIS (confidence%) | 800000003 | | buoy | FW-BUOY (confidence%) | 800000004 | | kayak | FW-KAYAK (confidence%) | 800000005 | | log | FW-LOG (confidence%) | 800000006 |

Each class uses a fixed MMSI so the same target updates in place on the chart rather than spawning new ones on every detection cycle.

OpenCPN (Signal K connection)

OpenPlotter users: No configuration needed. Signal K and OpenCPN are already connected — detections appear on the chart automatically.

Other setups: OpenCPN must have an active Signal K data connection (Admin → Connections → Signal K). If you can already see your boat's GPS position in OpenCPN via Signal K, detections will appear automatically.

Standalone chart plotters — Garmin, Raymarine, B&G, Furuno, Navionics

Standalone MFDs and chart plotter apps do not connect to Signal K directly. To see forward-watch detections on these devices, install the @signalk/signalk-to-nmea0183 plugin on your Signal K server.

Prerequisite: @signalk/signalk-to-nmea0183

Install it from the Signal K AppStore (Admin → AppStore → search "nmea0183"), then enable it. It converts all Signal K vessel data — including the fake AIS vessels written by forward-watch — into NMEA 0183 !AIVDM sentences and broadcasts them on a configurable TCP/UDP port or serial output.

Configure your chart plotter to receive NMEA 0183 from the Signal K server's IP address and port (default 10110). Once connected, forward-watch detections will appear as AIS targets labelled FW-SHIP, FW-BOAT, etc.

Note: Targets only appear when your boat has GPS active in Signal K. Without a GPS position, the plugin cannot calculate where the detected object is, so nothing is sent to the chart.


Signal K Data

environment.forwardWatch.detections

Updated every detection interval. Always present — empty array [] when nothing detected.

Example value (nothing detected):

[]

Example value (boat detected):

[
  {
    "class_id": 1,
    "class_name": "boat",
    "confidence": 0.72,
    "cx": 0.51,
    "cy": 0.63,
    "w": 0.18,
    "h": 0.24,
    "position": {
      "latitude": 43.1234,
      "longitude": -70.5678
    },
    "distance": 45,
    "bearing": 187,
    "quadrant": "starboard"
  }
]

Detection object fields:

| Field | Type | Description | |-------|------|-------------| | class_name | string | Detected object type: ship, boat, debris, buoy, kayak, log | | class_id | number | Numeric class index (0–5) | | confidence | number | Model confidence 0–1 (e.g. 0.72 = 72% confident) | | cx | number | Bounding box centre X, fraction of image width (0 = left, 1 = right) | | cy | number | Bounding box centre Y, fraction of image height (0 = top, 1 = bottom) | | w | number | Bounding box width as fraction of image width | | h | number | Bounding box height as fraction of image height | | distance | number | Estimated distance in metres (monocular estimate — larger object in frame = closer) | | bearing | number | Estimated bearing in degrees true | | quadrant | string | port (left half of frame) or starboard (right half of frame) | | position.latitude | number | Estimated GPS latitude of the object (requires boat GPS in Signal K) | | position.longitude | number | Estimated GPS longitude of the object (requires boat GPS in Signal K) |

Note on distance accuracy: Distance is estimated from bounding box height using a monocular depth formula. It assumes a ~60° horizontal field of view. Accuracy is ±50% — treat it as a rough range indicator, not a precise measurement. A proper rangefinder integration would improve this.


notifications.forwardWatch.<class_name>

A Signal K notification is sent for any detection within 100m. One notification path per class. Respects the alert cooldown setting.

Severity levels:

| Distance | Severity | Meaning | |----------|----------|---------| | ≤ 30m | emergency | Imminent collision risk | | ≤ 75m | warn | Close approach — take action | | > 75m | normal | Awareness only |

Example notification:

{
  "state": "alert",
  "severity": "warn",
  "message": "boat detected 45m ahead at bearing 187",
  "timestamp": "2026-03-06T13:02:42.484Z"
}

Detection Classes

| Class | Description | |-------|-------------| | ship | Large commercial vessel | | boat | Recreational or small vessel | | debris | Floating debris, garbage | | buoy | Navigation buoy | | kayak | Kayak or small paddle craft | | log | Floating log or deadhead |


Model

  • Architecture: YOLOv8n (nano) — optimised for edge CPU deployment
  • Training: 21,719 labelled marine images, 100 epochs
  • Input: 640×640 RGB
  • Format: ONNX (CPU inference via onnxruntime-node)
  • File: models/forward-watch.onnx (~12MB)

Performance

| Hardware | Inference time | Recommended interval | |----------|---------------|----------------------| | Raspberry Pi 4 (4GB) | ~1.6s | 300s (v0.1.x) · 60s (v0.2.0+) | | Raspberry Pi 5 | ~0.6s (estimated) | 60s | | x86 CPU (modern) | ~0.3s | 10s |

v0.1.x note: ONNX inference runs on the Signal K event loop thread. At short intervals this can cause GPS, AIS, and engine data to freeze during inference. The default interval of 300s avoids this. v0.2.0 moves inference to a worker thread — GPS/AIS/engine data will remain live at any detection interval.


Troubleshooting

No detections, camera not connecting

  • Check your RTSP URL is correct. Test it with VLC on another device.
  • Make sure ffmpeg is installed: ffmpeg -version
  • Check the camera IP is reachable from the Signal K host.

High CPU usage

  • Increase the detection interval. 30s is recommended for Pi 4.
  • The plugin guards against overlapping inference cycles — if one cycle takes longer than the interval, the next is skipped.

Distance estimates seem wrong

  • This is expected. Monocular depth estimation from a single camera is inherently imprecise. Use as a rough guide only.
  • Accuracy improves for larger objects that fill more of the frame.

No GPS position in detections

  • The plugin reads navigation.position and navigation.headingTrue from Signal K.
  • If your GPS isn't providing position data, detections will still appear but without position, distance, and bearing fields.

License

Apache 2.0 — see LICENSE

Author: SkipperDon Plugin ID: signalk-forward-watch npm: signalk-forward-watch