Expressions
L'unique langage d'expression derrière les variables et les conditions d'alarme, ce qu'il peut référencer, la surface de lecture de chaque sorte de point, les règles que l'évaluateur impose, les messages que donne la validation, et le fonctionnement de l'éditeur de script et de son sélecteur Parcourir….
Un seul langage d'expression sert deux endroits de la page Logic : ce qu'une variable d'expression calcule et la condition qu'une alarme surveille. Les deux sont une seule expression JavaScript évaluée en mode strict dans un bac à sable sans accès à la machine, et les deux se modifient dans le même éditeur de script. Les scripts d'action emploient le même vocabulaire mais sont des blocs d'instructions; leurs différences sont sur Actions.
Ce qu'est une expression
Une expression est exactement une expression JavaScript : littéraux, arithmétique, comparaisons, opérateurs logiques, l'expression conditionnelle a ? b : c, opérations sur les chaînes, chaînes de gabarit, et appels aux objets natifs de JavaScript Math, Date et JSON. Les instructions (let, if, boucles) appartiennent aux actions : une deuxième instruction est refusée avec « Une variable contient une seule expression. Les instructions appartiennent aux actions. » Les affectations et ++/--, où qu'ils soient dans l'expression, sont refusés avec « Les expressions sont en lecture seule. Les écritures appartiennent aux actions. »
L'expression référence des points par leur adresse enracinée. Ce que chaque racine remet à l'expression :
| Racine | Ce qui entre dans l'expression |
|---|---|
Les tags de Connector, Variables, Alarms, les Channels d'une unité Process |
Un objet vivant avec la surface de lecture typée ci-dessous. Une référence nue (Connector.Simulated.Pump.Flow seul) s'évalue en la valeur du point; une alarme nue en son IsActive. |
System, Server, Assets, et l'état d'exécution, la production, les commandes et la préparation d'une unité Process |
La valeur courante elle-même : un nombre, un texte, un booléen ou un instant. Employez-la directement; il n'y a pas de membre à ajouter. |
System.Now est l'instant de l'évaluation : chaque référence à cet instant, dans une même évaluation, lit la même heure. Il entre comme une Date JavaScript, comme tout horodatage, si bien que les instants se comparent et se soustraient naturellement : (System.Now - Connector.Simulated.Pump.Run.SourceTimeStamp()) / 1000 donne des secondes.
Une variable d'expression peut référencer des tags, des variables mémoire, des alarmes, des points Process, des points Assets et les diagnostics System et Server, mais jamais une autre variable d'expression : l'éditeur le refuse (« « Variables.X » est une variable d'expression. Une expression ne peut pas référencer d'autres variables d'expression; référencez plutôt des variables mémoire ou les points sous-jacents. ») pour qu'un résultat ne dépende jamais de l'ordre d'évaluation. Une condition d'alarme peut tout référencer sauf Alarms.* (« Une condition d'alarme ne peut pas référencer d'autres alarmes. ») et doit produire un booléen.
La surface de lecture d'un point
Un tag vivant offre :
| Membre | Renvoie | Sens |
|---|---|---|
.Value |
valeur typée | La valeur physique, après toute la chaîne de conversion du tag |
.ValueRaw |
valeur typée | La valeur brute normalisée au type déclaré du tag, avant la mise à l'échelle |
.ValueObject |
n'importe quoi | La valeur exactement telle que le pilote l'a produite |
.ValueScaled, .ValueCalibrated, .ValueLimited, .ValueRounded |
nombre | La valeur après les étapes Mise à l'échelle, Étalonnage, Limites et Décimales |
.ValueToBool(), .ValueToInteger(), .ValueToReal(), .ValueToString(), .ValueToDateTime() |
valeur convertie | La valeur physique convertie vers cette catégorie; l'absence de valeur reste une absence de valeur |
.State() |
booléen | La qualité : vrai tant que la lecture est bonne |
.SourceTimeStamp() |
Date | Quand l'équipement a produit la lecture |
.ApplicationTimeStamp() |
Date | Quand le serveur intégré l'a reçue |
.Name, .EngineeringUnit |
texte | Le nom et l'unité du tag |
Une variable offre .Value, les cinq conversions .ValueTo*(), .State(), .ApplicationTimeStamp(), .Name et .EngineeringUnit. Une alarme offre .IsActive, .IsAcked, .CurrentState, .State() (si sa condition a pu être évaluée au dernier cycle), .ActiveSince(), .LastTransitionAt() et .Name. Une voie Process offre la surface d'un tag quand elle est liée à un tag et la surface d'une variable quand elle est liée à une variable; une voie sans liaison n'offre rien. Rien d'autre n'est atteignable sur un objet vivant : un membre hors de cette surface se lit comme indéfini, et en appeler un échoue à la validation. Le sélecteur Parcourir… liste ces mêmes membres sous chaque point; aucun n'a donc à être tapé de mémoire.
Les règles que l'évaluateur impose
Dans l'éditeur au fil de la frappe, et de nouveau à chaque cycle de 100 ms :
- La barrière de qualité. Avant d'évaluer, chaque point référencé est résolu et rafraîchi. Tout point manquant, de mauvaise qualité ou sans valeur rend le résultat un vide de mauvaise qualité sans exécuter l'expression : un tag hors ligne ne peut donc jamais fabriquer un échantillon, et
nulln'atteint jamais le moteur pour y devenir0. - Un résultat non fini est un vide. NaN ou l'infini (division par zéro, arithmétique indéfinie) ne devient jamais un échantillon.
- Protection contre l'emballement. Une évaluation est interrompue au-delà de 250 ms, de 5 000 instructions ou de 4 MB de mémoire de script, et compte comme un vide de mauvaise qualité. Un moteur est tenu par texte d'expression, si bien que rien ne fuit d'une expression à l'autre.
- Conversion. Un résultat réussi est converti vers le type de sortie de la variable; une condition d'alarme est convertie en booléen, et un résultat qui ne se convertit pas laisse l'alarme dans son état.
- Les erreurs sont des vides, pas des exceptions. Une erreur d'exécution au moment du cycle donne un vide et une entrée de journal (le premier échec, des résumés tant qu'il se répète, une ligne au rétablissement); le cycle continue avec la variable suivante.
Ce que la validation refuse
L'éditeur valide le brouillon toutes les demi-secondes et affiche le premier problème sous la valeur ou sous la condition :
| Message | Cause |
|---|---|
| Une expression est obligatoire. / Une condition est obligatoire. | L'éditeur est vide. |
| Erreur d'expression : … | Le texte ne s'analyse pas. |
| Une variable contient une seule expression. Les instructions appartiennent aux actions. | Plus d'une instruction, ou une instruction qui n'est pas une expression. |
| Les expressions sont en lecture seule. Les écritures appartiennent aux actions. | Une affectation ou ++/--. |
| Les adresses doivent être statiques : « Root » est atteint par un segment calculé. | Variables[name] ou tout segment qui n'est pas un littéral. |
| Adresse incomplète « Connector.Simulated ». | Une chaîne trop courte pour nommer un point sous sa racine. |
| « X » est introuvable. | L'adresse ne se résout vers rien. |
| « X » est une variable d'expression. … | Une référence à une autre variable d'expression. |
| Une condition d'alarme ne peut pas référencer d'autres alarmes. | Une référence Alarms.* dans une condition. |
| La condition doit s'évaluer en booléen, mais elle a produit « x ». | L'évaluation d'essai d'une condition a produit une valeur présente qui ne se convertit pas en booléen. |
| Erreur d'expression : un point en direct ne peut pas être utilisé tel quel ici. Lisez-le par son membre .Value (par exemple Connector.Driver.Device.Tag.Value). | Un objet vivant employé là où une valeur primitive est attendue (Tag + 1). |
Erreur d'expression : <message du moteur> |
L'évaluation d'essai a levé une erreur : un identifiant inconnu, un membre bloqué appelé comme fonction. |
L'évaluation d'essai s'exécute avec les valeurs courantes quelle qu'en soit la qualité : un message reflète donc l'expression, pas une entrée de mauvaise qualité; une entrée de mauvaise qualité se voit plutôt dans la carte POINTS RÉFÉRENCÉS.
L'éditeur de script
Chaque expression, condition et script de la page se modifie dans la même carte : un surtitre (EXPRESSION DE CALCUL, CONDITION SURVEILLÉE ou SCRIPT DE L'ACTION), un bouton Parcourir…, l'éditeur, une indication et le message de validation. L'éditeur est CodeMirror, avec la coloration JavaScript, un historique d'annulation, et l'autocomplétion des jetons d'adresse : les noms de racine pour un jeton nu, puis les enfants du chemin déjà tapé, membres compris dès que le jeton nomme un point (saisir une adresse). Le texte est poussé vers le brouillon avec un délai et enregistré automatiquement. Les zones d'expression et de condition font au moins 56 px de haut, la zone de script d'action 160 px. Quand le moteur de l'éditeur ne peut pas démarrer, la zone se réduit à une zone de texte simple qui lit et écrit toujours, sans coloration, sans complétion et sans historique; Parcourir… ajoute alors l'adresse choisie à la fin plutôt qu'au curseur.
Parcourir… ouvre une boîte de dialogue (« Parcourir : insérer dans EXPRESSION DE CALCUL ») avec l'arborescence de tout l'espace d'adressage jusqu'au niveau des membres; sélectionnez une ligne et pressez Insérer, ou double-cliquez dessus, pour poser son adresse au curseur. Chaque éditeur possède sa propre boîte de dialogue : deux éditeurs d'une même page ne partagent donc jamais une sélection.
Ce que les expressions ne font pas
Elles n'écrivent rien, n'appellent pas les commandes d'essai de Process, ne gardent aucun état d'une évaluation à l'autre, ne peuvent pas définir de fonctions partagées entre expressions, et ne sont pas évaluées à la demande : le cycle les publie toutes les 100 ms et l'éditeur montre un aperçu du brouillon deux fois par seconde.