Canboat and SignalK

Zusammenwirken mit Canboat und SignalK

Ab Release 20200204 kann AvNav mit canboat (NMEA2000) und SignalK zusammenarbeiten.

Wichtiger Hinweis: Ab Version 20220421 hat sich das Handling für SignalK start verändert.

Canboat (NMEA2000)

Mit canboat können an den Raspberry angeschlossene CAN Adapter (z.B. mit MCP2515 oder ein Waveshare RS485 CAN-HAT ) oder per USB angeschlossene Adapter (z.B. Actisene NGT-1) genutzt werden. Für die einfachen CAN-Adapter muss darauf geachtet werden, dass sie 2 Spannungsversorgungen haben (3,3V und 5V) - viele ganz einfache haben das nicht!

Im Bild ist das prinzipielle Setup zu sehen, so wie es von den headless Images bereitgestellt wird.

Für einen per SPI angeschlossenen CAN-Adapter muss meist noch ein Overlay in /boot/config.txt eingeschaltet werden. Für den MCP2515 sind entsprechende Einträge bereits vorbereitet, diese müssen auskommentiert und ggf. muss die Taktfrequenz und der für den Interrupt genutzte GPIO Pin geändert werden.

Dieser CAN-Adapter erscheint dann als Netzwerk-Interface (ggf. muss er noch entsprechend konfiguriert werden - in den Images ist das bereits vorbereitet).

Das Interface sollte mit

ifconfig can0

sichtbar sein.

Für einen per USB angeschlossenen Actisense NGT-1 siehe die Beschreibung bei canboat.

AvNav kommuniziert mit dem n2kd. Dieser konvertiert empfangene NMEA2000 Daten in NMEA0183 (nicht ganz vollständig). Die Konfiguration für n2kd erfolgt über die Datei

/etc/default/n2kd

In den Images ist hier eine Verbindung zu can0 vorbereitet, für einen per USB angeschlossenen Adapter muss diese Datei geändert werden. Falls ein solcher USB-Adapter für NMEA2000 angeschlossen wird, sollte er einen Eintrag in der avnav_server.xml bekommen, damit er dort nicht genutzt wird (bei Einstecken die Status-Seite beobachten und die USB-Id von dort kopieren), dann entsprechend eintragen:

<AVNUsbSerialReader .....>
<UsbDevice usbid="x:y.z" type="ignore"/>
....

Wenn alles korrekt konfiguriert ist, sollten auf den ports 2599 und 2598 NMEA-Daten bzw. json Daten zu sehen sein, wenn auf dem Bus NMEA2000 Datenverkehr vorhanden ist. Kontrolle z.B.

nc localhost 2599

Sonst den Zustand von canboat mit

sudo systemctl status canboat

prüfen.

Für AvNav sollten 2 Verbindungen zum n2kd konfiguriert werden. Über eine Verbindung (Port 2599) empfängt er die NMEA0183 Daten und über die andere Verbindung (Port 2598)  direkt einige JSON Daten. Das ist notwendig, da n2kd keinen NMEA-Datensatz mit Datum ausgibt (z.B. RMC). Um das Datum zu erhalten, kann AvNav direkt die pgns 126992,129029 lesen, um intern Datum und Zeit zu setzen und kann daraus auch einen RMC Datensatz generieren (wenn über NMEA gültige Positionsdaten empfangen werden).

Dazu sind in der avnav_server.xml einige Konfigurationen nötig. Diese werden bei einer Image Installation automatisch aufgesetzt, sonst sind sie im Template unter /usr/lib/avnav/raspberry/avnav_server.xml zu finden und können von dort kopiert werden.

<AVNSocketWriter port="34568" maxDevices="5"
filter=""read="true" minTime="50"
name="nmea0183tosignalk"
blackList="canboatnmea0183,canboatgen"/> <AVNSocketReader port="2599" host="localhost" filter="" name="canboatnmea0183"/> <AVNPluginHandler>
<builtin-canboat enabled="true" allowKeyOverwrite="true" autoSendRMC="30" sourceName="canboatgen"/>
</AVNPluginHandler>

Mit dem ersten Eintrag wird ein zusätzlicher Port erzeugt, auf dem AvNav seine NMEA-Daten ausgibt - aber ohne die per canboat empfangenen Daten. Das wird für die Integration mit SignalK genutzt, wenn SignalK die NMEA2000 Daten bereits selbst empfängt.

Der Socketreader localhost:2599 empfängt die konvertierten Daten vom n2kd.

Die direkte Abfrage der NMEA2000 Daten erfolgt über ein Plugin, daher muss ein Eintrag unter AVNPluginHandler gemacht werden. Mit den Settings im Beispiel wird das Plugin aktiviert, allowKeyOverwrite erlaubt das Überschreiben der internen Zeit durch das Plugin und autoSendRMC=30 sorgt dafür, das (wenn 30s kein RMC im NMEA Datenstrom aufgetaucht ist) im Intervall 1s ein RMC geschrieben wird. Für die Parameter des Plugins siehe den source code

Ein Senden von Daten über NMEA2000 ist bisher nicht vorgesehen, dass kann ggf. über SignalK konfiguriert werden.


SignalK

Mit der Version 20220421 ist die Integration von AvNav mit  SignalK stark erweitert worden.

SignalK

Für die Integration zwischen AvNav und SignalK ist es zunächst wichtig, zu entscheiden wie die Daten fliessen sollen.
Dabei gibt es 2 grundsätzliche Möglichkeiten:

  1. NMEA Daten landen zunächst in AvNav und werden von dort zu SignalK weiter geleitet. Dieses Set Up wird in den AvNav Headless Images genutzt. Die SignalK Daten können (per HTTP-Json und websocket) wieder zu AvNav geschickt werden und dann dort auch angezeigt werden.
    Die Daten die AvNav zur Navigation nutzt (inklusive der AIS Daten) werden hier direkt von AvNav aus den NMEA Daten dekodiert.
    Ausnahme: NMEA2000 Daten die über Canboat kommen müssen parallel auch zu SignalK geschickt werden.
  2. NMEA Daten landen zunächst in SignalK und können von dort per HTTP-Json und websocket zu AvNav weiter geleitet werden.
    Das ist das Set Up, was z.B. in OpenPlotter verwendet wird.

Für beide Varianten kann AvNav auch eigene Daten an SignalK schicken. Im Moment sind das die Routing Daten zum nächsten Wegepunkt (entweder als RMB/APB NMEA0183 Daten oder als SignalK update - s.u.).

Ausserdem können Notifications (Alarme) von SignalK gelesen und dort hin gesendet werden.

Mit der Version 20220421 wird das Handling nicht mehr durch ein Plugin von AvNav erledigt sonder durch einen eigenen "Handler" AVNSignalKHandler. Die Konfiguration muss daher an diesem erfolgen.

1. NMEA zu AvNav und von dort zu SignalK

Die Konfiguration ist in den AvNav Headless Images vorbereitet.

Für diese Konfiguration wird in AvNav ein AVNSocketWriter vorgesehen (Standard: port 34568) der empfangene NMEA Daten weiterleitet. Über blacklist Einträge werden Daten von canboat (NMEA2000) nicht mit ausgesendet.

<AVNSocketWriter port="34568" maxDevices="5" filter="" read="true" minTime="50" name="nmea0183tosignalk" blackList="canboatnmea0183,canboatgen"/>

In SignalK muss dazu eine entsprechende data connection für NMEA0183, TCP client angelegt werden.

Der AVNSignalKHandler ist per default so konfiguriert, das er SignalK über localhost:3000 erreicht und alle Daten von vessels.self liest. Diese werden dann unter gps.signalk,... in AvNav abgespeichert und können so in Anzeigen verwendet werden.
Dabei wird eine Mischung aus polling per HTTP-Json und einer Websocket Vebindung genutzt. Das Polling sorgt für eine sichere Aktualisierung, die Websocket-Verbindung für ein zeitnahes Update.

Auf der obigen SocketWriter Verbindung schickt AvNav auch seine Routing Daten als RMB bzw. APB Sätze zu SignalK.
Zusätzlich kann beim SignalKHandler noch die Integration von Alarmen (SignalK: Notifications) aktiviert werden.

Daten die über andere Wege direkt in SignalK ankommen, werden zwar wie beschrieben zu AvNav geleitet, sind dort jedoch nicht direkt für die Navigation nutzbar.

Wenn man möchte, das Daten zunächst in SignalK ankommen und von dort zu AvNav weiter gehen, sollte man überlegen, ob der andere Signalfluss (2) nicht besser geeignet ist.

Vorteil an Signalfluss 1 (NMEA erst zu AvNav) ist , das auch wenn SignalK nicht verfügbar ist oder Probleme macht, die Navigationsfunktionen von AvNav noch arbeiten können.

2. NMEA Daten zuerst zu SignalK

In diesem Fluss, der unter OpenPlotter der Default ist (ab AvNavInstaller Version xxxx) werden NMEA Daten zunächst in SignalK empfangen und gespeichert. Dazu müssen in SignalK die entsprechenden data connections konfiguriert werden.

In AvNav wird der AVNSignalKHandler so konfiguriert, das er die Daten von SignalK in einer Kombination von HTTP-Json und einer Websocket Verbindung abholt.
Es sind die Flags "decodeData" und "fetchAis" (siehe Konfiguration) gesetzt. Damit werden empfangene Daten intern in AvNav für die Navigation gespeichert. Zusätzlich werden sie wie bei (1) noch einmal unter gps.signalk.... gespeichert, damit die Anzeigen genauso funktionieren.
Für das Mapping der Daten siehe [Mapping].

Im AVNSignalKhandler ist ausserdem das Senden von Daten aktiviert ("sendData"). Es werden die Daten für den aktuellen Wegepunkt sowie Alarme zu SignalK gesendet.
Ausserdem werden Notifications von SignalK empfangen.
Für das Schreiben von Daten zu SignalK muss ein unter SignalK verfügbarer Nutzer mit Schreibrechten konfiguriert werden (siehe Konfiguration).

Die in früheren Versionen nötigen NMEA Verbindungen von SignalK (port 10110) zu AvNav und zurück sind mit dieser Version nicht mehr nötig. Es ist auf SignalK Seite auch kein Plugin zum Erzeugen von NMEA Daten erforderlich.

Wenn man ein update von einer älteren Version macht, kann man die NMEA Verbindungen zu SignalK einfach deaktivieren und am AVNSignalKHandler die neuen Einstellungen vornehmen.

Auswahl des Datenflusses

Für die Entscheidung ob der Datenfluss 1 (erst zu AvNav) oder der Datenfluss 2 (erst zu SignalK) genutzt werden soll, kann man zunächst von den defaults ausgehen, je nachdem auf welcher Basis man aufsetzt.

Man sollte nur dann davon abweichen, wenn es gute Gründe dafür gibt. Durch Konfiguration auf der  Status/Server Seite kann man jeden dieser Flüsse einstellen, es sind sogar Mischformen möglich.

Man muss dabei nur darauf achten, das man keine Schleifen erzeugt - also z.B. Daten von AvNav per NMEA0183 zu SignalK schickt und diese dann wieder von dort zurückholt.
AvNav versucht solche Probleme mit einer "sourcePriority" an jeder Verbindung zu vermeiden. Alle NMEA Verbindungen haben per default eine Priority von 50, der AVNSignalKHandler 40 - damit "gewinnen" direkt empfangene NMEA Daten immer gegenüber den von SignalK geholten Daten.

Konfiguration

Der AVNSignalK Handler hat die folgenden Konfigurationen.

Name Beschreibung Default
name Ein Name für den Handler. Wird auf der Status-Seite angezeigt und im Log verwendet. leer (signalk)
enabled Wenn ausgeschaltet, wird die SignalK Integration deaktiviert. Ggf. konfigurierte NMEA Verbindungen sind davon nicht betroffen. ein
decodeData Wenn eingeschaltet, werden die empfangenen Daten von SignalK auch für die Navigationsfunktionen in AvNav verwendet. Siehe Mapping. aus (ein auf OpenPlotter)
fetchAis Wenn eingeschaltet, werden alle 10s (aisQueryPeriod) die AIS Daten von SignalK geholt und in AvNav als AIS Daten gespeichert. aus (ein auf OpenPlotter)
priority Die Priorität der dekodierten SignalK Daten 40
port Der SignalK HTTP Port. 3000
host Der SignalK server hostname/die IP Adresse. localhost
aisQueryPeriod Intervall (in s) für die Abfrage der AIS Daten 10
period Periode in ms für die HTTP-Json Abfrage auf SignalK. Wenn die python websocket bibliotheken verfügbar sind (der Normalfall), wird dieses Intervall auf nahezu die expiryTime der Daten in AvNav vergrößert. 1000
fetchCharts Hole die Informationen über die bei SignalK installierten Karten. Dazu muss dort der signalk-chart-provider installiert sein. ein
chartQueryPeriod Intervall (in s) für die Abfrage der Karten. 10
chartProxyMode Wenn SignalK auf einem anderen Rechner läuft als AvNav, kann es sein, das der Browser diesen anderen Rechner nicht direkt erreichen kann. Daher besteht die Möglichkeit, das das Laden der Karten über einen Proxy in AvNav erfolgt. Das erzeugt allerdings etwas zusätzliche Last und kann daher abgeschaltet werden.
sameHost: nur Proxy wenn SignalK nicht auf dem gleichen Server läuft wie AvNav
never: kein Proxy (kann genutzt werden, wenn auch vom Browser aus der SignalK Server unter der hier eingetragenen Adresse erreicht werden kann)
always: Immer proxy. Kann genutzt werden, wenn der SignalK Port (3000) nicht direkt von ausserhalb erreichbar ist.
sameHost
ignoreTimestamp Im Normalfall wertet der Handler den Timestamp der SignalK Daten aus und ignoriert Daten, die zu alt sind (expiryPeriod in AVNConfig). Eine potentielle Zeitdifferenz zwischen dem eigenen Server und dem SignalK Server wird dabei berücksichtigt.
SignalK nutzt allerdings manchmal nicht seine lokale Zeit als Basis für diesen Zeitstempel sondern niimmt den Zeitstempel aus empfangegen Daten. Der kann insbesondere bei der Verwendung von Simulationsdaten weit in der Vergangenheit liegen - und AvNav würde solche Daten ignorieren.
Durch Setzen dieses Flags ignoriert AvNav diese Zeitstempel und trägt als Zeitstempel seine lokale Zeit der letzten Änderung eines Wertes ein.
Das ist natürlich nicht so genau, wie der originale Zeitstempel in SignalK, führt aber dazu, das auch ältere Simulationsdaten genutzt werden könen.
aus
sendData Sende Daten an SignalK.
Es kann jeweils noch konfiguriert werden, on Alarme oder/und Wegepunkt-Daten gesendet werden können. Diese Einstellungen werden aber erst sichtbar, wenn sendData aktiviert wurde.
Das steuert nicht das Senden von NMEA Daten zu SignalK!
aus (ein auf OpenPlotter)
userName Der Name eines SignalK Nutzers mit Schreibrechten auf dem SignalK server. Dieser Nutzer muss vorher mit den entsprechenden rechten bei SignalK angelegt worde sein.
Leider hat SignalK kein Interface um direkt prüfen zu können, ob ein bestimmter Nutzer die gewünschten Pfade schreiben kann, nur für "localhost" wird geprüft, ob Schreibrechte vorliegen.
admin
password Das Passwort für den konfigurierten Nutzer. Dieses Passwort ist im Normalfall für eine SignalK Installation auf dem gleichen Server nicht erfordelich (sofern die Konfiguration auf dem Standardpfad $HOME/.signalk/security.json liegt).
Wenn in der Status-Anzeige unter "authentication" ein Fehler auftritt, kann u.U. auch lokal das Setzen des Passwortes das Problem lösen.
Achtung: Das Passwort wird im Klartext in der avnav_server.xml gespeichert.
<leer>
sendWp Sende Wegepunkt-Daten zu SignalK. Siehe auch Mapping. ein
sendNotifications Sende AvNav Alarme als Notifications zu SignalK - siehe Mapping. ein
receiveNotifications Empfange Notifications von SignalK als Alarme. aus
notifyWhiteList Eine Komma-separierte Liste von SignalK notifications, die emfangen werden sollen. Anzugeben sind jeweils die Pfade ohne "notification." - als z.B. navigation.arrivalCircleEntered,mob,fire,sinking.
Wenn die Liste leer ist, werden alle Notifications empfangen - aber es wird noch die notificationBlacklist betrachtet,
<leer>
notifyBlackList Eine Komma-separierte Liste von SignalK notifications, die nicht empfangen werden sollen. server.newVersion
webSocketRetry Interval (in s) in dem versucht wird, eine erneute Websocket-Verbindung aufzubauen, wenn die vorige geschlossen wurde. 20

Einige der Parameter werden erst sichtbar, wenn der jeweils "übergeordnete" Parameter aktiviert wurde.


Mapping

Die SignalK Pfade werden wie folgt auf AvNav Datenpfade gemappt:

/vessels/self/... => gps.signalk....

Diese Pfade werden in AvNav intern nicht verwendet, können aber angezeigt werden.

Wenn "decodeData" aktiviert ist, wird wie folgt gemappt (siehe im code).

Anmerkung: Kurse/Winkel werden intern in AvNav in ° gespeichert, in SignalK in rad. Wenn mehrere SignalK Pfade angegebn sind, wird der jeweils erste bei SignalK vorhandene genutzt.

SignalK unter /vessels/self/ AvNav
navigation.headingMagnetic gps.headingMag
navigation.headingTrue gps.headingTrue
environment.water.temperature gps.waterTemp
navigation.speedThroughWater gps.waterSpeed
environment.wind.speedTrue oder environment.wind.speedOverGround gps.trueWindSpeed
environment.wind.speedApparent gps.windSpeed
environment.wind.directionTrue environment.wind.directionGround gps.trueWindAngle
environment.wind.angleApparent gps.windAngle
navigation.position.latitude gps.lat
navigation.position.longitude gps.lon
navigation.courseOverGroundTrue gps.track
navigation.speedOverGround gps.speed
environment.depth.belowTransducer gps.depthBelowTransducer
environment.depth.belowSurface gps.depthBelowWaterline
environment.depth.belowKeel gps.depthBelowKeel
navigation.datetime gps.time
navigation.gnss.satellitesInView.count gps.satInview
navigation.gnss.satellites gps.satUsed

AIS Daten werden wie folgt gemappt ("fetchAis" ein):

SignalK vessels/*/ AvNav ais Bemerkung
mmsi mmsi nur wenn mmsi gesetzt ist, werden die Daten übernommen
name shipname
navigation.speedOverGround speed
navigation.courseOverGroundTrue course
communication.callsignVhf callsign
design.aisShipType shiptype
navigation.position.longitude lon
navigation.position.latitude lat
navigation.destination destination
sensors.ais.class type class A -> type 1
class B -> type 18
other -> type other

Wenn "sendWp" aktiv ist, werden die Daten wie folgt gemappt:

AvNav SignalK vessels/self/
currentLeg.to.lon navigation.courseGreatCircle.nextPoint.position.longitude
currentLeg.to.lat navigation.courseGreatCircle.nextPoint.position.latitude
currentLeg.from.lon navigation.courseGreatCircle.previousPoint.position.longitude
currentLeg.from.lon navigation.courseGreatCircle.previousPoint.position.latitude
currentLeg.distance navigation.courseGreatCircle.nextPoint.distance
currentleg.dstBearing navigation.courseGreatCircle.nextPoint.bearingTrue
currentLeg.xte navigation.courseGreatCircle.crossTrackError
currentLeg.approachDistance navigation.courseGreatCircle.nextPoint.arrivalCircle
currentLeg.bearing navigation.courseGreatCircle.bearingTrackTrue

Für Notifications gibt es einige wenige Mappings, ungemappte Notifications werden in AvNav mit ihrem Name und "sk:" vorangestellt gehandelt. Also z.B. notifications.sinking wird zu sk:sinking.

AvNav SignalK vessels/self/notifications Value
mob mob  'state':'emergency',
 'method':['visual','sound'],
 'message':'man overboard'
waypoint arrivalCircleEntered 'state': 'normal',
'method': ['visual','sound'],
'message': 'arrival circle entered'
anchor navigation.anchor 'state':'emergency',
'method': ['visual','sound'],
'message': 'anchor drags'

SignalK Notifications ohne ein direktes Mapping werden basierend auf ihrem state einer Kategorie zugeordnet (darüber kann im AVNCommandHandler das auszuführende Kommand und der Sound definiert werden).

emergency -> critical
normal -> normal


SignalK - Karten

Ab Version 202011xx ist auch der SignalK chart provider integriert. Karten, die von dort angeboten werden, können auf der Einstiegsseite ebenfalls ausgewählt werden. Dazu muss natürlich innerhalb von SignalK das entsprechende Plugin installiert und aktiviert sein - und Karten müssen dort verfügbar sein.

Im Normalfall werden durch AvNav nur die Informationen über die Karten bereitgestellt, der Zugriff auf die Karten erfolgt direkt vom Browser zu SignalK.

Falls das z.B. durch Firewall Einstellungen verhindert wird, kann man auch alle Karten-Zugriffe über AvNav leiten (Proxy) - siehe Konfiguration.