user java script

User Spezifischer Java Script Code

Um eine einfache Möglichkeit zu bieten, AvNav an seine Bedürfnisse anzupassen, kann man mit ein wenig Java Script Code AvNav relativ einfach erweitern.

Dabei ist es zunächst einmal möglich, neue Anzeigen zu definieren, die dann im Layout Editor ausgewählt werden können. Prinzipiell kann man dort natürlich beliebigen Java Script Code ausführen - muss dabei aber natürlich zusehen, die Funktionen von AvNav nicht zu stören.

Der Java Script Code liegt in der Datei user.js im Verzeichnis BASEDIR/user/viewer.
BASEDIR ist z.B. auf dem pi /home/pi/avnav/data.

Bearbeitung

Um die Bearbeitung zu erleichtern, kann man über die Files/Download Seite und die Unterseite auf die Dateien in diesem Verzeichnis zugreifen.

Wie im Bild zu sehen, existiert dort bereits eine Datei user.js. Diese wird beim erstmaligen Start aus einem Template erzeugt.

Durch einen Klick auf die Datei und die Auswahl von "Edit" kann man die Datei direkt bearbeiten.

In der Datei sind bereits Beispiele vorhanden für die Möglichkeiten der Anpassung. Nach dem Bearbeiten die Datei speichern und AvNav neu laden.

Es empfiehlt sich, die Datei in regelmäßigen Abständen nach dem Bearbeiten herunterzuladen und noch einmal irgenwo zu speichern - es gibt keine Versionsverwaltung in AvNav.

Das aktuelle Template kann man auch auf github finden.

Anzeigen (Widgets)

Man kann im Wesentlichen die folgenden Arten von Anzeigen hinzufügen:

  • Widgets mit eigenem Formatter (und ggf. festen Werten) basierend auf dem Default Widget (Beispiel 1 - user.js: rpmWidget, testPlugin: testPluing_simpleWidget )
  • Anpassung/Erweiterung der Grafik Widgets mit canvas gauges (Beispiel 2 - user.js: rpmGauge)
    Hiermit ist es auch möglich, Parameter zugänglich zu machen, die in den bisher vorhandenen Widgets nicht enthalten sind
  • Widgets mit eigenem HTML code (Beispiel 3 - user.js: userSpecialRpm, TestPlugin: testPlugin_courseWidget)
  • Widgets mit Grafik in einem Canvas Element (Beispiel im TestPlugin: testPlugin_courseWidget)
  • Widgets mit eigenem HTML, die mit dem Server Teil eines Plugins interagieren (TestPlugin: testPlugin_serverWidget)

Das Interface, über das mit AvNav kommuniziert wird, findet sich auf github bzw. im Template Code.

Für ein selbst geschriebenes Widget können die folgenden Funktionen/Eigenschaften implementiert werden:

Name Typ Nutzbar bei Typ Beschreibung
name String alle der Name des Widgets
type String
(optional)
alle Bestimmt, welches Widget erzeugt werden soll.
Werte: radialGauge, linearGauge
Wenn der Typ nicht gesetzt ist, wird entweder das default widget genutzt (keine Funktion renderHtml und keine Funktion renderCanvas angegeben) - oder ein nutzer definiertes Widget (userWidget)
renderHtml Funktion
(optional)
userWidget Diese Methode muss einen String zurückgeben, der dann als HTML code in das Widget eingebaut wird.
Falls eventHandler für Elemente genutzt werden sollen, müssen diese vorher registriert werden (siehe initFunction) und werden im HTML code einfach mit
<button onclick="myHandler">Click!</button>
angegeben (das ist keine exakte HTML Syntax, da nur der Name des event handlers angegeben wird, kein java script code).

Die "this" variable innerhalb von renderHtml zeigt auf ein Objekt, das spezifisch für das Widget ist (Kontext).
Wenn der EventHandler aufgerufen wird, zeigt this ebenfalls auf diesen Kontext.

Das als Parameter an renderHtml übergebene Objekt enthält die unter storeKeys definierten Werte.
Die Funktion wird jedesmal erneut aufgerufen, wenn sich die Werte geändert haben.
renderCanvas
Funktion
(optional)
userWidget Mit dieser Funktion kann in das übergebene Canvas Objekt gezeichnet werden.
Das als zweiter Parameter an renderCanvas übergebene Objekt enthält die unter storeKeys definierten Werte.
Die Funktion wird jedesmal erneut aufgerufen, wenn sich die Werte geändert haben.
Die "this" variable innerhalb von renderCanvas zeigt auf ein Objekt, das spezifisch für das Widget ist (Kontext).
storeKeys
Object alle Hier müssen die Daten angegeben werden, die aus dem zentralen Speicher gelesen und als Parameter den renderXXX Funktionen mitgegeben werden sollen
caption String
(optional)
alle Eine default Beschriftung
unit String
(optional)
alle Eine default Einheit
formatter Funktion
(optional)
defaultWidget,
radialGauge, linearGauge
Ein Formatierer für den Wert. Für das defaultWidget muss diese Funktion angegeben werden.
translateFunction Funktion
(optional)
alle Diese Funktion wird mit den aktuellen Werten als Parameter aufgerufen (so wie bei storeKeys angegeben) und muss die daraus berechneten Werte zurückgeben.
Falls keine eigene renderXXX Funktion genutzt werden soll, kann hier vor dem Rendern eine Umrechnung von Werten erfolgen - siehe Beispiel.
initFunction Funktion
(optional)
userWidget Falls vorhanden, wird diese Funktion einmalig aufgerufen, wenn das Widget erzeugt wird. Als Parameter (und als this) ist der Widget Context vorhanden.
Dieses Objekt hat eine eventHandler Eigenschaft - hier müssen die im renderHTML genutzten eventHandler eingetragen werden.
Mit der Funktion triggerRedraw am Widget Kontext kann ein erneuter Aufruf der renderXXX Funktionen erzwungen werden,
Ab Version 20210422 erhält die initFunction einen 2. Parameter, der die Eigenschaften des Widgets enthält. Das sind insbesondere auch alle editierbaren Widget Parameter, die definiert wurden.
finalizeFunktion Funktion
(optional)
userWidget Falls vorhanden, wird diese Funktion aufgerufen, bevor das Widget nicht mehr genutzt wird. Die "this" Variable zeigt wieder auf den Widget Kontext.
Ausserdem ist der Kontext auch als erster Parameter vorhanden - wie bei der initFunction.
Ab Version 20210422 erhält die initFunction einen 2. Parameter, der die Eigenschaften des Widgets enthält. Das sind insbesondere auch alle editierbaren Widget Parameter, die definiert wurden.

Der java script code erhält folgende globale Variablen:

Name plugin.js/user.js Beschreibung
AVNAV_BASE_URL beide die URL zum Verzeichnis, aus dem die Java script Datei geladen wurde. Diese kann z.B. verwendet werden, um weitere Elemente von dort zu laden. Für die user.js können Dateien aus dem images Verzeichnis über AVNAV_BASE_URL+"../images" erreicht werden.
Für plugins kann über AVNAV_BASE_URL+"/api" die Kommunikation mit dem Python Anteil erreicht werden.
AVNAV_PLUGIN_NAME plugin.js Der Name des Plugins.

Nach der Definition muss das Widget bei AvNav bekannt gemacht werden (avnav.registerWidget).

Widget Parameter

Neben der Widget Definition können hier noch Parameter angegeben werden, die dann im Layout Editor für das Widget angezeigt werden.

Beispiele sind im user.js Template zu finden. Die Werte, die im Layout Editor für diese Parameter angegeben werden, stehen später in den renderHtml und renderCanvas Funktionen zur Verfügung (Ausnahme: Typ KEY, hier wird der  aus dem Speicher gelesene Wert zur Verfügung gestellt).
Für jeden Parameter kann man die folgenden Werte angeben:

Name Type Beschreibung

key Der Name des Parameters so wie er im Layout Editor angezeigt werden soll, und wie er den renderXXX Funktionen zur Verfügung stehen soll.
type String STRING, NUMBER, KEY, SELECT, ARRAY, BOOLEAN, COLOR
Der Typ für den Parameter. Je nach Typ wird er dem Nutzer unterschiedlich angezeigt.
Für COLOR eine Farb-Auswahl, für SELECT eine AuswahlListe und für KEY die Liste der momentan verfügbaren Werte im Store.
Für ein Array kann eine durch Komma getrennte Liste angegeben werden.
default je nach type Der default Wert.
Für COLOR eine color css Property - also z.B. "rgba(200, 50, 50, .75)"
list Array
(nur für type SELECT)
Ein Array von Strings oder von Objekten {name:'xxx',value:'yyy'} - diese Werte werden  zur Auswahl angezeigt.

Es gibt eine Reihe von vordefinierten Parametern für den Layout Editor. Bei diesen wird zur Beschreibung kein Objekt mit Eigenschaften angegeben, sonder nur true oder false (das zeigt, ob sie zum Ändern angeboten werden sollen oder nicht).

Das sind:

  • caption (STRING)
  • unit (STRING)
  • formatter (SELECT)
  • formatterParameters (ARRAY)
  • value (KEY)
  • className (STRING)

Ein Beispiel für eine Definition:

var exampleUserParameters = { //formatterParameters is already well known to avnav, so no need for any definition //just tell avnav that the user should be able to set this formatterParameters: true, //we would like to get a value from the internal data store //if we name it "value" avnav already knows how to ask the user about it value: true, //we allow the user to define a minValue and a maxValue minValue: {type: 'NUMBER', default: 0}, maxValue: {type: 'NUMBER', default: 4000}, };

Formatierer (Formatter)

Neben den eigentlichen Anzeigen können auch eigene Formatierer geschrieben werden, die die Werte für die Anzeige aufbereiten.
Im System sind bereits eine Reihe von Formatierern vorhanden - siehe Layout Editor.

Ab Version 20210106 können eigene Formatierer bei AvNav registriert werden und stehen dann allen Widgets zur Verfügung. Ein Formatierer ist eine Funktion, die als ersten Parameter den zu formatierenden Wert übergeben bekommt und als Ergebnis einen String zurück liefern muss.
Der String sollte dabei unabhänging vom momentanen Wert immer die gleiche Länge haben (ggf. Leerzeichen voranstellen) um die Größenanpassung auf den Dashboard-Seiten nicht zu stören.

Eine Formatierer-Funktion kann zusätzliche Parameter akzeptieren, um die Umwandlung zu steuern. Diese werden über die Widget Eigenschaft formatterParameters typischerweise im Layout Editor gesetzt.

Beispiel:

const formatTemperature=function(data,opt_unit){ try{ if (! opt_unit || opt_unit.toLowerCase().match(/^k/)){ return formatDecimal(data,3,1); } if (opt_unit.toLowerCase().match(/^c/)){ return formatDecimal(parseFloat(data)-273.15,3,1) } }catch(e){ return "-----" } } formatTemperature.parameters=[ {name:'unit',type:'SELECT',list:['celsius','kelvin'],default:'celsius'} ]
avnav.api.registerFormatter("mySpecialTemperature",formatTemperature);

Falls ein Formatierer mit dem gleichen Namen schon existiert, wirft registerFormatter eine Exception.

Jede Formatter Funktion sollte eine Property "parameters" bekommen. Diese beschreibt die im Layout-Editor sichtbaren Parameter für die Funktion. Die Werte in dieser Definition haben die gleiche Syntax wie die editierbaren Widget-Parameter.

Bibliotheken und Bilder

Falls der eigene Java Script code auf libraries oder images zugreifen soll, können diese in das gleiche Verzeichnis hochgeladen werden - Images auch in das Images Verzeichnis.

Das Einbinden von Bibliotheken kann z.B. so erfolgen

var fileref=document.createElement('script'); fileref.setAttribute("type","text/javascript"); fileref.setAttribute("src", AVNAV_BASE_URL+"/my_nice_lib.js"); document.getElementsByTagName("head")[0].appendChild(fileref)

Es empfiehlt sich, für alle Widgets css Klassen zu vergeben, damit man diese dann mit nutzerspezifischem CSS anpassen kann. IDs sollten nicht verwendet werden, da die Elemente potentiell mehrfach auf der Seite auftauchen können.

Falls Daten vom Server geladen werden sollen, empfiehlt sich die Verwendung von fetch. Alle Dateien im user Verzeichnis (oder im plugin Verzeichnis für plugin.js)  sind nach dem Schema AVNAV_BASE_URL+"/"+name abrufbar.

Falls im User-Verzeichnis z.B. eine weitere Text-, Html- oder andere Datei angelegt werden soll (ohne eine hochzuladen), kann man das auch direkt mit dem "+" Button unten rechts erledigen - die Datei kann dann natürlich ebenfalls direkt bearbeitet werden.

Feature Formatierer (featureFormatter)

Ab Version 20210114 gibt es die Möglichkeit, eigene Funktionen zu registrieren, die die Anzeige von Daten aus Overlays aufbereiten.
Solche Funktionen können in der user.js oder in Plugins implementiert werden.

Mit

avnav.api.registerFeatureFormatter('myHtmlInfo',myHtmlInfoFunction);

werden sie registriert. Für Details siehe Overlays.