Aller au contenu principal

Directives du préprocesseur

Directives du préprocesseur​

Les directives du préprocesseur permettent d'influencer des fonctions du compilateur du module Math, le traitement des variables et l'exécution du code. Les directives du préprocesseur doivent se trouver en début de ligne dans le texte de formule et se terminent à la première fin de ligne qui n'est pas masquée dans un niveau de parenthèses. Des commentaires peuvent être insérés selon les règles connues.

Les directives sont identifiées par un caractère # suivi d'un identifiant. Les paramètres qui suivent la directive et leur format dépendent de la fonction. Des formats possibles sont par exemple :

#directiveA <parameter>
#directiveB <name>[<parameter>](<parameter>){<code>}
#directiveC <key>, <key>=<value>, …

Insérer du texte de formule "#include"​

Cette directive permet d'insérer du texte de formule provenant d'une ressource ou d'un fichier externe. La syntaxe utilisée détermine la source adressée.

#include "aRessource"
#include 'aRessource'
#include <aFile>

La ressource indiquée sous forme de chaîne est reprise dans le code source en tenant compte des decoder qui y sont indiqués, ou comme texte.

Le fichier indiqué dans <…> est repris dans le code source. Les chemins absolus et relatifs sont autorisés, les chemins relatifs étant recherchés à partir de répertoires fixement définis (chemins de recherche). Les éléments entre %...% sont remplacés par la valeur correspondante de la variable d'environnement.

Chemins de recherche sous WINDOWS :​

  • %USERPROFILE%/mm_lib/

  • %LOCALAPPDATA%/optimeas.osg.com/mm_lib/

  • %APPDATA%/optimeas.osg.com/mm_lib/

Chemins de recherche sous LINUX/YOCTO :​

  • /sdi/config/mm_lib/

  • /sdi/apps/smartcore/mm_lib/

  • /var/lib/mm_lib/

  • /usr/local/lib/mm_lib/

  • /usr/lib/mm_lib/

Supprimer la référence temporelle "#timeless"​

Pour supprimer la référence temporelle de certains canaux d'entrée du module Math, la directive #timeless peut être utilisée. Les noms de canaux peuvent être transmis à la directive dans une liste séparée par des virgules. Si les noms contiennent d'autres caractères que ceux autorisés pour un identifiant, ils doivent être placés entre '...' ou "...". L'utilisation de la syntaxe $'...' n'est pas autorisée, car seul un attribut du canal est défini ici.

#timeless <varName>, <varName2>, ...
remarque

La même fonction est activée ou désactivée via la macro #property avec la propriété timeout=<bool>.

remarque

Une fonctionnalité similaire est mise à disposition via la fonction value() pour une utilisation locale ciblée dans le texte de formule.

Principe : traitement des données à temps exact et timeout​

Comme décrit en introduction, le module Math traite toujours les données provenant des différentes sources du smartCORE à temps exact. On s'assure ainsi, par exemple, qu'un signal de courant et un signal de tension sont corrélés de manière cohérente pour le calcul d'une puissance.

Il existe toutefois aussi des sources de données qui ne fournissent de nouvelles valeurs que très rarement. Il peut s'agir, par exemple, de données de mesure d'une station météorologique, interrogée peut-être seulement toutes les 10 minutes et écrite dans les canaux smartCORE, ou de données d'un horaire, interrogé et mis à jour une seule fois par jour auprès d'un serveur.

Les données transmises du smartCORE au module Math passent en timeout après un intervalle de temps réglable ; elles continuent alors d'être utilisées avec ce même décalage temporel et la dernière valeur en attente, bien que leur validité ne soit pas confirmée par des mesures ou interrogations plus récentes. Il en résulte que tous les calculs qui en dépendent sont certes toujours exécutés à temps exact, mais retardés de cet intervalle de temps.

L'intervalle de temps du timeout est défini par le paramètre global inputTimeoutS et peut être remplacé individuellement pour un canal avec la macro #property et la propriété timeout.

Ce retard peut avoir des effets défavorables dans la représentation des données MQTT dans le cloud ou pour des tâches de commande.

Avec les fonctions

les différents états d'une variable d'entrée peuvent être interrogés. Dans le cas où aucun canal smartCORE n'a pu être connecté ou où ce canal ne fournit pas encore de données, une valeur default est affectée ; elle peut être réglée via la macro #property <channel>, default=<var>.

Que provoque l'attribut timeless ?​

Les canaux d'entrée marqués timeless sont toujours valides du début à la fin de l'intervalle de calcul respectif evaluationTimeMs, par rapport à l'heure système correspondante.

Schéma timeless

Dans l'exemple montré, le calcul du jeu de formules est exécuté aux instants t0,t_0, t1t_1 et t2t_2. Jusqu'à l'instant t0t_0, seule la valeur y0y_0 a été réglée sur le canal. Jusqu'à l'instant t1t_1, la source de signal fournit les points de données y1,y_1, y2y_2 et y3y_3. Les points de données y4y_4 et y5y_5 ne sont produits que jusqu'à l'instant t2t_2, bien que leur horodatage soit antérieur à t1t_1.

Pour le début de l'intervalle, c'est toujours le jeu de données du canal situé immédiatement avant qui est utilisé, quel que soit son âge. Pour l'intervalle ]t0,t1]]t_0,t_1], c'est donc le point de données y1,y_1, pour l'intervalle ]t1,t2]]t_1,t_2] le point de données y5y_5.

Si de nouvelles valeurs de données tombent par hasard dans l'intervalle de calcul courant et y sont déjà enregistrées à temps, elles sont prises en compte avec leurs instants. Pour l'intervalle ]t0,t1]]t_0,t_1], il s'agit des points de données y2y_2 et y3y_3.

La validité du jeu de données le plus récent disponible (ici y3y_3) est automatiquement prolongée jusqu'à la fin de l'intervalle (ici t1t_1), de sorte que ce canal ne peut finalement retenir aucun des calculs qui en dépendent.

attention

Le prix à payer est que de brèves variations de signal situées dans cette plage de validité prolongée n'entrent éventuellement plus dans les calculs. Dans l'exemple, le point de données y4y_4 est « manqué », car il se situe dans un intervalle de temps déjà complété par l'automatisme. En partant du principe et de la condition que ces canaux ne fournissent des données que rarement, cela ne devrait pas poser de problème.

Définir des propriétés d'une variable "#property" 1​

Cette directive du préprocesseur permet de définir des propriétés et des méta-informations d'une variable d'entrée ou de sortie.

#property <channel>, <key>=<value>, ...
ArgumentTypeDescription
channel<str>Le nom du canal doit être indiqué comme premier argument. S'il contient des caractères spéciaux tels que des espaces ou des virgules, il doit être placé entre guillemets. L'utilisation de la syntaxe $'...' n'est pas autorisée, car seules des propriétés du canal sont définies ici.
key<str>Le nom de la propriété, voir le tableau suivant
value<var>La nouvelle valeur de la propriété (Variant)

Le tableau suivant est un récapitulatif des propriétés possibles et autorisées et de leurs valeurs :

PropriétéTypeDescription
default<var>La valeur default affectée à une variable jusqu'à l'arrivée des premières valeurs de données du canal smartCORE. Cela permet de réagir, dans le module Math, à des flux de données qui démarrent avec retard.
timeout<dbl>Valeur de timeout individuelle pour ce canal, remplace inputTimeoutS
timeless<bool>Active ou désactive la fonctionnalité timeless pour ce canal. Cela correspond à la macro #timeless

Définir un fuseau horaire local "#timezone" 2​

Cette macro permet de régler un fuseau horaire local pour certaines fonctions de date et d'heure.

#timezone <tzIdentifier>
tzIdentifierAbréviations de fuseau horaireCodes de pays
Europe/Berlin
Europe/Stockholm
Europe/Oslo
Europe/Copenhagen
CET / CESTDE, DK, NO, SE, SJ
Europe/Brussels
Europe/Amsterdam
Europe/Luxembourg
CET / CESTBE, LU, NL
Europe/Paris
Europe/Vienna
Europe/Warsaw
Europe/Zurich
Europe/Rome
CET / CESTFR, MC, AT, PL, CH, IT
Europe/Kiev
Europe/Kyiv
EET / EESTUA
Asia/Singapore
Asia/Kuala_Lumpur
+08:00MY
...

Une liste des fuseaux horaires peut être consultée sur Wikipédia.

En arrière-plan, la bibliothèque usuelle sous Linux HowardHinnant/date: A date and time library based on the C++11/14/17 <chrono> header est utilisée ; elle repose sur la IANA Timezone Database. Celle-ci est déployée sur les systèmes dans son état actuel avec la distribution Yocto.

Un extrait de celle-ci est distribué avec le logiciel optiCONTROL, car la bibliothèque mathématique y est également intégrée dans l'éditeur du module Math.

Définition de fonctions "#define"​

Under Construction Cette fonction est en préparation.

#define <newFunction>(<argsList>)[<options>]{<code>}

Informations de débogage "#dump"​

attention

For Debugging Only Cette directive du préprocesseur est exclusivement destinée au diagnostic et au développement. Elle produit un très grand nombre de sorties informatives dans le fichier journal du smartCORE et ne doit donc être utilisée que sur de courtes périodes.

Le paramètre de la directive #dump est une liste de clés (key) ou de paires clé-valeur (key-value) séparées par des virgules et agit sur le texte de formule qui suit :

#dump <key>, <key>=<value>, ...
KeyValueDescription
treeAffiche l'arbre d'objets traduit. Pour l'interprétation, voir ci-dessous.
node<uint>Ajoute un nœud d'objet déterminé pour la surveillance continue (3, 4).
var<str>Ajoute une expression regex pour sélectionner des noms de canaux dont les accès doivent être consignés (3)
trace<enum>active la sortie du flux de données pour
- in les entrées,
- out les sorties ou
- io les deux sens de données.
clearSupprime tous les réglages de dump pour la section de code suivante.

Exemples :

#dump tree
#dump node=5, node=9
#dump var='Temp.*', trace=out

Sortie de l'arbre d'objets​

La sortie de l'arbre d'objets au moyen de #dump tree fournit des informations détaillées sur les relations fonctionnelles du jeu de formules défini. L'exploitation est réservée aux collaborateurs spécialisés d'optiMEAS.

+---o [0]: sequencer, bareImpl, op: ';' listOfArgs
> out: nullptr
+---o [1]: operatorNode, followInputs, op: '=' orderR2L
| > out: { n:'duration', s:[upLnk, wrVar], *rd[0], *wr[1], h:'=', empty}
| +---o [2]: operatorNode, followInputs, op: '*' orderL2R
| | > out: { n:'', s:[upLnk], *rd[1], *wr[2], h:'*', empty}
| | +---o [3]: varPoolSource, followInputs
| | | > var: { n:'wv2', s:[rdVar], *rd[3], empty}
| | | > out: { n:'', s:[upLnk], *rd[2], *wr[3], empty}
| | +---o [4]: constValueNode, constValue
| | | > out: { n:'', s:[upLnk, const], *rd[2], *wr[4], [1]={t: INF, d: TrustedTimestamp }, [0]={t: 0, d: (cScalar, cInt) 59}}}

Les sorties de trace pour un élément de liaison de flux de données (out: ou var:, canal ou TS_Stream) ont la structure compacte suivante :

{ n:'duration', s:[upLnk, wrVar], *rd[0], *wr[1], h:'=', [9]={t: 48, d: (cScalar, cDbl) 54.978065}, ... [0]={t: 20, d: (cScalar, cDbl) 0.000000}}}

Leur signification :

AbréviationFlagsDescription
n:'...'le nom du canal, s'il s'agit d'une variable
s:[]Flags d'état du canal
upLnkUp-Link, liaison d'un nœud enfant vers le nœud parent
rdVarRead Variable, variable d'entrée, fournie par le smartCORE et uniquement lue
wrVarWrite Variable, variable de sortie, peut être renvoyée dans le smartCORE
inzInitializer, possède un nœud d'initialisation
constConstant value, la valeur ne change pas pendant l'exécution.
discrDiscrete evaluation, ce canal est calculé par pas d'échantillonnage discrets
ev@0Evaluate at Start, le canal discret a été initialisé
evDTEvaluate Delta-T, un pas d'échantillonnage a été calculé pour le canal discret
explExplicit name, la variable a été définie avec la syntaxe $'…' et doit exister dans le smartCORE
fldEField-Element, le canal alimente un champ de données déterminé dans une structure multidimensionnelle (vecteur, matrice, …)
privPrivate, une variable créée par un bloc fonctionnel et utilisée exclusivement par celui-ci
propDes propriétés supplémentaires ont été définies sur la variable avec #property.
noTnoTime, ce canal a été marqué #timeless et est toujours valide jusqu'à la fin de l'intervalle de calcul.
+=dTLe canal a un décalage temporel constant issu de shiftT()
nRecNoRecursion, cette variable ne doit pas être utilisée dans une boucle de récursion.
toValPropriété timeout affectée
fdVal Propriété default affectée
noChCe canal n'a pas pu être connecté à un canal smartCORE comme entrée. => La valeur par défaut est affectée comme valeur constante. Voir aussi isConnected()
TOutTimeout pour les données d'entrée, si le canal est encore vide (noD) ou s'il n'a pas été marqué #timeless. Voir aussi isTimeout()
H1Interpolation linéaire explicitement autorisée (1st-order hold)
:=fdLa valeur default a été écrite dans le canal, voir aussi #property <channel>, default=<var>
*rd[]Les indices des nœuds d'objet qui accèdent en lecture au canal
*wr[]L'indice du nœud d'objet qui accède en écriture au canal
*@0[]L'indice du nœud d'objet qui exécute l'initialisation du canal discret.
h:'...'Indication de la fonction du nœud écrivant, p. ex. '*' ou 'sin(…)'
[n]={}l'échantillon enregistré à la position la plus récente n (correspond au nombre d'entrées - 1) avec...
t:Horodatage en ns depuis le 01.01.1970, INF (infini) ou NAV (non valide)
d:Valeur de données avec (structure, type) valeur ou TrustedTimestamp, c'est-à-dire que la valeur qui précède conserve sa validité jusqu'à cet instant. L'instant peut croître de façon monotone à chaque intervalle de calcul.
[0]={}l'échantillon enregistré à la position la plus ancienne (facultatif)

Suivre le déroulement du calcul "#monitor"​

For Debugging Only AVERTISSEMENT ! Cette directive du préprocesseur est exclusivement destinée au diagnostic et au développement. Elle produit un très grand nombre de sorties informatives dans le fichier journal du smartCORE et ne doit donc être utilisée que sur de courtes périodes.

Surveillance des tampons internes "#warn"​

For Debugging Only AVERTISSEMENT ! Cette directive du préprocesseur est exclusivement destinée au diagnostic et au développement. Elle produit un très grand nombre de sorties informatives dans le fichier journal du smartCORE et ne doit donc être utilisée que sur de courtes périodes. De plus, cette option génère une charge CPU supplémentaire et ne doit être utilisée que temporairement et sous surveillance !!!

Le paramètre de la directive #warn est une liste de clés (key) ou de paires clé-valeur (key-value) séparées par des virgules et agit sur le texte de formule qui suit :

KeyValueDescription
maxbuflen<uint>Surveille le nombre maximal d'enregistrements dans une file d'attente de données. Un avertissement est émis lorsque la limite est dépassée. La limite est relevée de 25 % de maxbuflen pour le message suivant.
timeout<dbl>Surveille l'écart de temps entre le premier échantillon de données et l'instant d'exécution. Un avertissement est émis lorsque ce temps est supérieur à la valeur définie en s.
clearSupprime tous les réglages d'avertissement pour la section de code suivante.

Exemples :

#warn maxBufLen=10, timeout=1000
// Formeltext zur Überwachung
#warn clear

Footnotes​

  1. Disponible à partir de la version 10 du catalogue. ↩

  2. Disponible à partir de la version 13 du catalogue. ↩

  3. L'option peut être citée plusieurs fois. ↩ ↩2

  4. Numéros de nœuds issus de l'arbre d'objets ↩