Plugins

Avnav Plugins

=== nicht für Android ===

Um die Funktionalität von AvNav erweitern zu können gibt es Plugins. Plugins können mit Python code den Server erweitern und sie können mit Java Script und Css die WebApp erweitern.

Jedes Plugin muss sich in einem eigenen Verzeichnis befinden. Dessen Name ist gleichzeitig der Plugin Name. Es gibt 2 Wurzelverzeichnisse, die AvNav nach Plugins durchsucht:

  • "systemdir" - ein Verzeichnis für Plugins, die für alle Nutzer auf einem System installiert werden (z.B. als Pakete). Dieses ist /usr/lib/avnav/plugins.
  • "userdir" - ein Verzeichnis für Plugins eines einzelnen Nutzers. Das befindet sich unterhalb des "datadir" - also auf dem pi /home/pi/avnav/data/plugins, sonst unter Linux $HOME/avnav/plugins.

Daneben gibt es noch ein internes Plugin Verzeichnis (builtin).

Grundsätzlich können die Server-Anteile an verschiedenen Stellen Daten aus AvNav lesen oder hineinschreiben. Die WebApp Anteile können im Allgemeinen dazu dienen, diese Daten dann z.B. anzuzeigen. Daneben können sie aber auch einfach weitere Anzeigen einbringen oder das Aussehen anpassen.

In einem Plugin Verzeichnis kann es bis zu 3 Dateien geben, die von AvNav beachtet werden (daneben natürlich weitere Dateien, die das Plugin selbst benötigt).

Diese sind:

  • plugin.py - die Serveranteile des Plugins, optional
  • plugin.js - die Java Script Anteile des Plugins, optional
  • plugin.css - die CSS Anteile des Plugins, optional

Ein Beispiel für ein Plugin findet man auf GitHub.

Liste von Plugins

plugin.js

Im Java script code sind genau die gleichen Funktionen verfügbar wie unter nutzerspezifischer Java Script code beschrieben.

plugin.css

Im CSS code sind die gleichen Möglichkeiten vorhanden wie unter nutzerspezifisches CSS beschrieben.

plugin.py

Die Zeichnung gibt einen groben Überblick über die interne Struktur des AvNav Servers und die Punkte, an denen ein Plugin Daten auslesen oder einspeisen kann.

Punkt Funktion Beispiel
A Einspeisen von NMEA Daten in die interne Liste. Diese stehen dann an allen Ausgängen zur Verfügung.
Hinweis: Solche Daten stehen zunächst nicht für die WebApp zur Verfügung, solange es keinen Dekoder für diesen Datensatz gibt.
Auslesen eines Sensors und Erzeugen des passenden NMEA0183 Datensatzes.
B Auslesen von empfangenen NMEA Daten. Hier können (ggf. mit einem Filter) alle in AvNav durchlaufenden NMEA Daten gelesen werden. In Zusammenspiel mit Punkt "C" Dekodieren von NMEA Datensätzen
C Einspeisen von Daten in den internen Speicher von AvNav. Die Daten im internen Speicher sind in einer Baumstruktur abgelegt. Jedes Element ist durch einen Schlüssel der Form "a.b.c...." adressiert. Beispiel: "gps.lat".
Alle Schlüsselwerte, die mit "gps." starten, werden automatisch an die WebApp übertragen und sind dann dort unter "nav.gps...." verfügbar. (siehe Layout Editor und nutzerspezifisches Java Script).
Schlüsselwerte müssen vorher durch das Plugin angemeldet werden, es ist nicht möglich, bereits im System genutzte Schlüssel zu überschreiben. Ausnahme: Der Nutzer konfiguriert für das Plugin den Wert "allowKeyOverride" auf true.
Einspeisen eines von einem Sensor gelesenen Wertes - z.B. gps.temperature.outside oder von dekodierten NMEA Daten.
D Auslesen von Daten aus dem internen Speicher. Berechnung neuer Daten und Einspeisung unter "C" - oder Weiterreichen an eine externe Verbindung.
E Bearbeiten von HTTP Requests Die Java script Anteile können einen HTTP request senden, der im python code bearbeitet werden kann.
Anworten typischerweise in Json


Ein Beispiel für eine plugin.py findet sich auf GitHub.

Damit das Plugin von AvNav erkannt wird, müssen folgende Voraussetzungen eingehalten werden:

  1. In plugin.py muss mindestens eine Klasse vorhanden sein (der Name sollte Plugin sein)
  2. Die Klasse muss eine statische Methode (@classmethod) mit dem Namen pluginInfo haben, die ein dictionary zurückgibt.
    * description (mandatory) * data: list of keys to be stored (optional) * path - the key - see AVNApi.addData, all pathes starting with "gps." will be sent to the GUI * description

    Ein Beispiel könnte so aussehen:
    @classmethod def pluginInfo(cls):
    return { 'description': 'a test plugins', 'data': [ { 'path': 'gps.test', 'description': 'output of testdecoder', } ] }
  3. Der Konstruktor der plugin Klasse muss einen Parameter erwarten.
    Beim Aufruf wird hier eine Instanz des API übergeben, über das die Kommunikation mit AvNav erfolgt.
  4. Die Klasse muss eine run Methode (ohne Parameter) besitzen.
    Diese wird in einem eigenen Thread aufgerufen, nachdem die Initialisierung abgeschlossen ist.
    Typischerweise wird diese Methode eine Endlosschleife enthalten, um die Plugin-Funktion zu realisieren.

Für das Plugin können in der avnav_server.xml Parameter konfiguriert werden, diese sind dann über das API (getConfigValue) abrufbar.

Am API stehen die folgenden Funktionen zur Verfügung

Funktion Beschreibung
log,debug,error Logging Funktionen. Es werden Zeilen in die AvNav log Datei geschrieben. Man sollte für log und error vermeiden, solche Einträge in grosser Zahl zu schreiben, da sonst im Log potentiell wichtige Informationen verloren gehen (also z.B. nicht jede Sekunde ein Fehlereintrag...)
getConfigValue lies einen config Wert aus der avnav_server.xml.
fetchFromQueue Interface B: lies Daten aus der internen NMEA Liste. Ein Beispiel ist im API code vorhanden. Der filter Parameter funktioniert wie in der avnav_server.xml.
addNMEA Interface A: schreibe einen NMEA Datensatz in die interne Liste. Man kann AvNav die Prüfsummenberechnung überlassen und man kann auch eine Dekodierung in AvNav verhindern. Der Parameter source ist ein Wert, der in blackList parametern genutzt werden kann.
addData Interface C: schreibe einen Wert in den internen Speicher. Es können nur Werte geschrieben werden, deren Schlüssel in der Rückgabe der pluginInfo Methode vorhanden waren.
getSingleValue Interface D: lies einen Datenwert aus dem internen Speicher. Zur Zusammenfassung mehrerer solcher Lesevorgänge existiert die Funktion getDataByPrefix
setStatus Hier sollte der aktuelle Zustand des Plugins gesetzt werden. Das ist der Wert, der auf der Statusseite angezeigt wird.
registerUserApp Ein Plugin kann eine User App registrieren. Dafür nötig ist eine URL und eine Icon Datei. Die Icon Datei sollte mit im Plugin Verzeichnis liegen. In der URL kann $HOST verwendet werden, das wird dann durch die korrekte IP Adresse des AvNav Servers ersetzt. Beispiel im signalk Plugin.
registerLayout Falls das Plugin z.B. eigene Widgets mitbringt, ist es u.U. hilfreich ein vorbereitetes Layout mitzuliefern, das der Nutzer dann auswählen kann. Das Layout dazu nach der Erstellung mit dem Layout Editor herunterladen und im Plugin Verzeichnis speichern. Beispiel wieder im signalk Plugin.
getDataDir Das Verzeichnis, in dem AvNav Daten ablegt
registerChartProvider Falls das Plugin Karten bereitstellt, wird hier ein callback registriert, der eine Liste der Karten zurückgibt.
registerRequestHandler Falls das Plugin HTTP requests bearbeiten soll (Interface E) muss hier ein callback registriert werden, der den Request behandelt. Die url für den Aufruf ist:
<pluginBase>/api
Dabei ist pluginBase der unter getBaseUrl zurückgegebene Wert.
Die java script Anteile können die API url mit der Variable AVNAV_BASE_URL bilden: AVNAV_BASE_URL+"/api"
Im einfachsten Fall kann die aufgerufene callback-Funktion ein dictionary zurückgeben, dieses wird als Json zurück gesendet.
getBaseUrl gib die Basis URL für das Plugin zurück
registerUsbHandler
(ab 20201227)
registriert einen Callback für ein USB Gerät. Mit dieser Registrierung wird AvNav mitgeteilt, dass es das USB Gerät nicht beachten soll. Der Callback wird mit dem Device-Pfad für das Gerät aufgerufen, wenn das Gerät erkannt wurde.
Die USB-Id kann am einfachsten durch Beobachten der Status-Seite beim Einstecken des Gerätes ermittelt werden. Siehe auch AVNUsbSerialReader. Damit kann ein Plugin selbst einfach das Handling für ein spezielles Gerät übernehmen, Ein Beispiel findet sich auf GitHub.
getAvNavVersion
(ab 20210115)
Aktuelle AvNav Version (int)
saveConfigValues
(ab 20210322)
Speichere config Werte für das Plugin in avnav_server.xml. Der Parameter muss ein dictionary mit den Werten sein. Das Plugin muss sicherstellen, dass es später mit diesen Werten wieder starten kann.
registerEditableParameters
(ab 20210322)
Registriert eine Liste mit config Werten, die zur Laufzeit geändert werden können. Der erste Parameter ist eine Liste von dictionaries mit den Parameter Beschreibungen, der zweite ein callback, der bei Änderungen mit den geänderten Werten aufgerufen wird (wird typischerweise saveConfigValues rufen).
Die Syntax für die Parameter-Liste ist im Source Code beschrieben.
registerRestart
(ab 20210322)
Registriere einen Stop Callback. Damit kann das Plugin disabled (deaktiviert) werden.
unregisterUserApp
(ab 20210322)
Deregistriere eine User App.
deregisterUsbHandler
(ab 20210322)
Deregistriere eine usb device id (siehe registerUsbHandler)
shouldStopMainThread
(ab 20210322)
Kann in der Hauptschleife genutzt werden, um zu prüfen, ob das Plugin gestoppt werden soll. In jedem anderen Thread wird immer True zurück gegeben.