Ausdrücke
Die eine Sprache der Ausdrücke hinter Variablen und Alarmbedingungen, worauf sie verweisen darf, die Lesefläche jeder Art von Punkt, die Regeln, die der Auswerter erzwingt, die Meldungen der Prüfung und wie der Editor für Skripte und seine Auswahl Durchsuchen… arbeiten.
Eine Sprache der Ausdrücke bedient zwei Stellen auf der Seite Logic: das, was eine Variable der Art Ausdruck berechnet, und die Bedingung, die ein Alarm beobachtet. Beide sind ein einzelner JavaScript-Ausdruck, im strengen Modus in einem Sandkasten ohne Zugriff auf den Rechner ausgewertet, und beide werden im selben Editor für Skripte bearbeitet. Skripte von Aktionen verwenden denselben Wortschatz, sind aber Anweisungsblöcke; ihre Unterschiede stehen auf Aktionen.
Was ein Ausdruck ist
Ein Ausdruck ist genau ein JavaScript-Ausdruck: Literale, Arithmetik, Vergleiche, logische Operatoren, die Bedingung a ? b : c, Operationen auf Zeichenketten, Vorlagenzeichenketten und Aufrufe der eingebauten JavaScript-Objekte Math, Date und JSON. Anweisungen (let, if, Schleifen) gehören zu Aktionen: Eine zweite Anweisung wird abgelehnt mit "Eine Variable hält einen einzelnen Ausdruck. Anweisungen gehören zu Aktionen." Zuweisungen und ++/-- werden überall in einem Ausdruck abgelehnt mit "Ausdrücke sind nur lesend. Schreibvorgänge gehören zu Aktionen."
Der Ausdruck verweist über ihre verwurzelte Adresse auf Punkte. Was jede Wurzel dem Ausdruck reicht:
| Wurzel | Was in den Ausdruck übergeht |
|---|---|
Tags unter Connector, Variables, Alarms, die Channels einer Einheit von Process |
Ein lebendes Objekt mit der typisierten Lesefläche unten. Ein nackter Verweis (Connector.Simulated.Pump.Flow allein) wertet zum Wert des Punkts aus; ein nackter Alarm zu seinem IsActive. |
System, Server, Assets sowie Zustand des Laufs, Produktivität, Befehle und Vorbereitung einer Einheit von Process |
Der aktuelle Wert selbst: eine Zahl, ein Text, ein Wahrheitswert oder ein Zeitpunkt. Verwenden Sie ihn unmittelbar; es gibt kein Element zum Anhängen. |
System.Now ist der Zeitpunkt der Auswertung: Jeder Verweis darauf innerhalb einer Auswertung liest dieselbe Zeit. Es geht wie jeder Zeitstempel als JavaScript-Date über, Zeitpunkte lassen sich also natürlich vergleichen und voneinander abziehen: (System.Now - Connector.Simulated.Pump.Run.SourceTimeStamp()) / 1000 sind Sekunden.
Eine Variable der Art Ausdruck darf auf Tags, Variablen der Art Merker, Alarme, Punkte von Process, Punkte unter Assets und die Diagnosewerte von System und Server verweisen, aber nie auf eine andere Variable der Art Ausdruck: Der Editor lehnt das ab ("'Variables.X' ist eine Variable der Art Ausdruck. Ausdrücke dürfen nicht auf andere Variablen der Art Ausdruck verweisen; verweisen Sie stattdessen auf Variablen der Art Merker oder auf die darunterliegenden Punkte."), damit Ergebnisse nie von der Reihenfolge der Auswertung abhängen. Eine Alarmbedingung darf auf alles außer Alarms.* verweisen ("Alarmbedingungen dürfen nicht auf andere Alarme verweisen.") und muss einen Wahrheitswert ergeben.
Die Lesefläche eines Punkts
Ein lebender Tag bietet an:
| Element | Gibt zurück | Bedeutung |
|---|---|---|
.Value |
typisierter Wert | Der technische Wert, nach der ganzen Wertkette des Tags |
.ValueRaw |
typisierter Wert | Der Rohwert, auf den erklärten Typ des Tags gebracht, vor der Skalierung |
.ValueObject |
beliebig | Der Wert genau so, wie der Treiber ihn erzeugt hat |
.ValueScaled, .ValueCalibrated, .ValueLimited, .ValueRounded |
Zahl | Der Wert nach den Stufen Skalierung, Kalibrierung, Grenzen und Nachkommastellen |
.ValueToBool(), .ValueToInteger(), .ValueToReal(), .ValueToString(), .ValueToDateTime() |
gewandelter Wert | Der technische Wert, in diese Kategorie gewandelt; kein Wert bleibt kein Wert |
.State() |
Wahrheitswert | Qualität: wahr, solange der Messwert gut ist |
.SourceTimeStamp() |
Date | Wann das Gerät den Messwert erzeugt hat |
.ApplicationTimeStamp() |
Date | Wann der eingebettete Server ihn empfangen hat |
.Name, .EngineeringUnit |
Text | Name und Einheit des Tags |
Eine Variable bietet .Value, die fünf Wandlungen .ValueTo*(), .State(), .ApplicationTimeStamp(), .Name und .EngineeringUnit an. Ein Alarm bietet .IsActive, .IsAcked, .CurrentState, .State() (ob seine Bedingung im letzten Zyklus ausgewertet werden konnte), .ActiveSince(), .LastTransitionAt() und .Name an. Ein Kanal von Process bietet die Fläche eines Tags an, wenn er an einen Tag gebunden ist, und die Fläche einer Variablen, wenn er an eine Variable gebunden ist; ein ungebundener Kanal bietet nichts an. Sonst ist an einem lebenden Objekt nichts erreichbar: Ein Element außerhalb dieser Fläche liest als undefiniert, und eines aufzurufen scheitert bei der Prüfung. Die Auswahl Durchsuchen… führt unter jedem Punkt genau diese Elemente auf, sodass keines davon aus dem Gedächtnis getippt werden muss.
Die Regeln, die der Auswerter erzwingt
Sowohl im Editor beim Tippen als auch erneut in jedem Zyklus von 100 ms:
- Das Tor der Qualität. Vor der Auswertung wird jeder genannte Punkt aufgelöst und aufgefrischt. Jeder Punkt, der fehlt, schlecht ist oder keinen Wert hält, macht das Ergebnis zu einer Lücke schlechter Qualität, ohne den Ausdruck auszuführen, ein Tag, der offline ist, kann also nie eine Stichprobe erfinden, und
nullerreicht die Maschine nie, um dort zu0zu werden. - Nicht endliche Ergebnisse sind Lücken. NaN oder unendlich (Teilen durch null, undefinierte Arithmetik) wird nie zu einer Stichprobe.
- Schutz vor Ausreißern. Eine Auswertung wird jenseits von 250 ms, 5.000 Anweisungen oder 4 MB Skriptspeicher abgebrochen und zählt als Lücke schlechter Qualität. Je Text eines Ausdrucks wird eine Maschine gehalten, aus einem anderen Ausdruck dringt also nichts herüber.
- Wandlung. Ein erfolgreiches Ergebnis wird in den Ausgabetyp der Variablen gewandelt; eine Alarmbedingung wird in einen Wahrheitswert gewandelt, und ein Ergebnis, das sich nicht wandeln lässt, hält den Zustand des Alarms.
- Fehler sind Lücken, keine Ausnahmen. Ein Fehler zur Laufzeit im Zyklus ergibt eine Lücke und einen Eintrag im Journal (den ersten Fehlschlag, Zusammenfassungen, solange er sich wiederholt, eine Zeile bei der Erholung); der Zyklus macht mit der nächsten Variablen weiter.
Was die Prüfung ablehnt
Der Editor prüft den Entwurf jede halbe Sekunde und zeigt das erste Problem unter dem Wert oder der Bedingung:
| Meldung | Ursache |
|---|---|
| Ein Ausdruck ist erforderlich. / Eine Bedingung ist erforderlich. | Der Editor ist leer. |
| Fehler im Ausdruck: … | Der Text lässt sich nicht lesen. |
| Eine Variable hält einen einzelnen Ausdruck. Anweisungen gehören zu Aktionen. | Mehr als eine Anweisung oder eine Anweisung, die kein Ausdruck ist. |
| Ausdrücke sind nur lesend. Schreibvorgänge gehören zu Aktionen. | Eine Zuweisung oder ++/--. |
| Adressen müssen statisch sein: Auf 'Root' wird mit einem berechneten Segment zugegriffen. | Variables[name] oder irgendein Segment, das kein Literal ist. |
| Unvollständige Adresse 'Connector.Simulated'. | Eine Kette, die zu kurz ist, um unter ihrer Wurzel einen Punkt zu benennen. |
| 'X' wurde nicht gefunden. | Die Adresse löst auf nichts auf. |
| 'X' ist eine Variable der Art Ausdruck. … | Ein Verweis auf eine andere Variable der Art Ausdruck. |
| Alarmbedingungen dürfen nicht auf andere Alarme verweisen. | Ein Verweis auf Alarms.* in einer Bedingung. |
| Die Bedingung muss zu einem Bool auswerten, hat aber 'x' ergeben. | Die Probeauswertung einer Bedingung ergab einen vorhandenen Wert, der sich nicht in einen Wahrheitswert wandeln lässt. |
| Fehler im Ausdruck: Ein lebender Punkt lässt sich hier nicht unmittelbar verwenden. Lesen Sie ihn über sein Element .Value (z. B. Connector.Driver.Device.Tag.Value). | Ein lebendes Objekt dort verwendet, wo ein einfacher Wert nötig ist (Tag + 1). |
Fehler im Ausdruck: <Meldung der Maschine> |
Die Probeauswertung hat geworfen: ein unbekannter Bezeichner, ein gesperrtes Element als Funktion aufgerufen. |
Die Probeauswertung läuft mit den aktuellen Werten, ohne Rücksicht auf die Qualität, eine Meldung spiegelt also den Ausdruck und keine schlechte Eingabe; eine schlechte Eingabe zeigt sich stattdessen in der Karte GELESENE PUNKTE.
Der Editor für Skripte
Jeder Ausdruck, jede Bedingung und jedes Skript auf der Seite wird in derselben Karte bearbeitet: eine Augenbraue (AUSDRUCK, BEDINGUNG oder SKRIPT), eine Schaltfläche Durchsuchen…, der Editor, ein Hinweis und die Prüfmeldung. Der Editor ist CodeMirror mit Hervorhebung für JavaScript, einer Geschichte zum Rückgängigmachen und Vervollständigung für die Zeichen einer Adresse: Wurzelnamen bei einem nackten Zeichen, dann die Kinder des bisher getippten Pfades, Elemente eingeschlossen, sobald das Zeichen einen Punkt nennt (eine Adresse eingeben). Der Text wird verzögert in den Entwurf geschoben und automatisch gespeichert. Die Felder für Ausdruck und Bedingung sind mindestens 56 px hoch, das Feld für das Skript einer Aktion 160 px. Kann die Maschine des Editors nicht starten, fällt das Feld auf ein einfaches Textfeld zurück, das weiterhin liest und schreibt, ohne Hervorhebung, Vervollständigung und Geschichte; Durchsuchen… hängt die gewählte Adresse dann am Ende an statt an der Einfügemarke.
Durchsuchen… öffnet einen Dialog ("Durchsuchen: in AUSDRUCK einfügen") mit dem Baum des ganzen Adressraums bis auf die Ebene der Elemente; wählen Sie eine Zeile und drücken Sie Einfügen oder klicken Sie doppelt darauf, um ihre Adresse an die Einfügemarke zu setzen. Jeder Editor besitzt seinen eigenen Dialog, zwei Editoren auf einer Seite teilen sich also nie eine Auswahl.
Was Ausdrücke nicht tun
Sie schreiben nichts, rufen keine Befehle für Läufe von Process auf, halten zwischen zwei Auswertungen keinen Zustand, können keine Funktionen bilden, die sich mehrere Ausdrücke teilen, und werden nicht auf Anforderung ausgewertet: Der Zyklus veröffentlicht sie alle 100 ms, und der Editor zeigt den Entwurf zweimal je Sekunde vorab.