Scripts et Formules
L'application Serveur dispose d'un moteur intégré pour exécuter des scripts utilisateurs. Les scripts sont utilisés pour calculer les valeurs et statuts des canaux, ainsi que pour calculer les valeurs des commandes.
Les scripts sont écrits dans la table Scripts de la base de données de configuration. Un projet créé à l'aide d'un modèle contient déjà un ensemble initial de scripts qui peuvent être utilisés comme exemples pour développer vos propres scripts. Les variables et fonctions implémentées dans la table Scripts sont ensuite appelées dans les colonnes Formule d'Entrée et Formule de Sortie de la table Canaux. Pour effectuer des calculs de formule pour un canal, sélectionnez la case dans la colonne Formule Activée.
Règles de Création de Scripts
Règles générales pour écrire et utiliser des scripts :
- Les scripts sont écrits selon la syntaxe du langage C#. Diverses classes du framework .NET sont disponibles, telles que Math, DateTime et File.
- De nouvelles constantes, champs, propriétés et méthodes sont ajoutés à la table Scripts et deviennent disponibles dans les formules des canaux.
- Si au moins un script ou une formule contient une erreur, le fonctionnement du Serveur est impossible. Les informations sur les erreurs dans les scripts sont écrites dans le journal d'application du Serveur.
Règles pour le calcul des formules des canaux :
- Une formule d'entrée pour les canaux des types Entrée et Entrée/Sortie est calculée uniquement lorsque le Serveur reçoit de nouvelles données pour ces canaux. Utilisez ces types de canaux si les données proviennent de dispositifs.
- Une formule d'entrée pour les canaux des types Calculé et Calculé/Sortie est calculée en continu à chaque itération de la boucle principale du Serveur. La séquence de calcul va du numéro de canal le plus petit au plus grand.
- Une formule de sortie pour les canaux des types Entrée/Sortie, Calculé/Sortie et Sortie est calculée lorsqu'une commande est envoyée au canal correspondant.
- Un statut de canal après le calcul d'une formule d'entrée pour les types Entrée et Entrée/Sortie est égal au statut des données transférées au Serveur, sauf si le calcul du statut est explicitement spécifié dans la formule.
- Pour les canaux des types Calculé et Calculé/Sortie, le statut est défini sur Défini si le calcul du statut n'est pas explicitement spécifié dans la formule.
- Si une formule d'entrée contient le symbole ";", elle est divisée en deux parties : la première calcule la valeur du canal, et la seconde calcule le statut du canal.
- Si un canal a des limites spécifiées, le statut du canal est recalculé en tenant compte des limites après le calcul de la formule d'entrée du canal.
- Les formules doivent retourner des valeurs de types de données spécifiques, décrits ci-dessous.
Les formules d'entrée des canaux retournent des données des types suivants :
Type de Données | Description |
---|---|
double | Valeur du canal |
CnlData | Valeur et statut du canal |
long | Valeur entière 64 bits d'un canal dont le type de données est défini sur Entier dans la table Canaux |
string | Valeur texte d'un canal dont le type de données est défini sur Chaîne ASCII ou Chaîne Unicode dans la table Canaux |
Si une formule d'entrée retourne un type de données autre que ceux listés ci-dessus, la valeur retournée par la formule est convertie au type approprié basé sur le type de données du canal. La partie de la formule d'entrée du canal qui calcule le statut du canal doit retourner une valeur entière de type int
.
Les formules de sortie des canaux retournent des données des types suivants :
Type de Données | Description |
---|---|
double | Valeur de commande. Pour annuler une commande, la formule doit retourner double.NaN |
CnlData | Valeur de commande. Pour annuler une commande, la formule doit retourner CnlData.Empty |
byte[] | Données binaires de commande. Pour annuler une commande, la formule doit retourner null |
string | Données de commande sous forme de chaîne. Converties par le Serveur en un tableau de bytes |
Variables Disponibles
Le moteur de script fournit les variables intégrées suivantes :
Variable | Type de Données | Description |
---|---|---|
Timestamp | DateTime | Horodatage des données traitées (UTC) |
IsCurrent | bool | Indique si les données traitées sont des données actuelles |
CnlNum | int | Numéro du canal pour lequel la formule est calculée |
Channel | Cnl | Propriétés du canal pour lequel la formule est calculée |
ArrIdx | int | Index de l'élément du tableau traité |
Cnl, CnlVal | double | Valeur du canal transmise au Serveur avant le calcul |
CnlStat | int | Statut du canal transmis au Serveur avant le calcul |
CnlData | CnlData | Données du canal transmises au Serveur avant le calcul |
Cmd, CmdVal | double | Valeur de commande transmise au Serveur avant le calcul |
CmdData | byte[] | Données de commande transmises au Serveur |
CmdDataStr | string | Données de commande sous forme de chaîne |
Fonctions Disponibles
Le moteur de script fournit les fonctions intégrées suivantes :
Fonction | Type de Données | Description |
---|---|---|
N(n) | int | Retourne le numéro du canal n. Utilisé dans le clonage de canaux |
Val() | double | Valeur actuelle du canal pour la formule |
Val(n) | double | Valeur actuelle du canal n |
SetVal(n, val) | double | Définit la valeur actuelle du canal n |
Stat() | int | Statut actuel du canal pour la formule |
Stat(n) | int | Statut actuel du canal n |
SetStat(n, stat) | int | Définit le statut actuel du canal n |
Data() | CnlData | Données actuelles du canal pour la formule |
Data(n) | CnlData | Données actuelles du canal n |
SetData(n, val, stat) | double | Définit la valeur et le statut actuels du canal n |
SetData(n, cnlData) | double | Définit les données actuelles du canal n |
NewData(val, stat) | CnlData | Crée une nouvelle instance de données de canal |
PrevVal() | double | Valeur précédente du canal pour la formule |
PrevVal(n) | double | Valeur précédente du canal n |
PrevStat() | int | Statut précédent du canal pour la formule |
PrevStat(n) | int | Statut précédent du canal n |
PrevData() | CnlData | Données précédentes du canal pour la formule |
PrevData(n) | CnlData | Données précédentes du canal n |
Time() | DateTime | Horodatage actuel du canal pour la formule |
Time(n) | DateTime | Horodatage actuel du canal n |
PrevTime() | DateTime | Horodatage précédent du canal pour la formule |
PrevTime(n) | DateTime | Horodatage précédent du canal n |
Deriv(n) | double | Dérivée temporelle du canal n |
Fonctions du Modèle de Projet
Dans un projet créé à partir d'un modèle standard, la table Scripts contient les fonctions suivantes :
Fonction | Type de Données | Description |
---|---|---|
GetBit(val, n) | double | Retourne le nème bit de la valeur spécifiée |
GetBit(cnlData, val) | CnlData | Retourne les données du canal composées du nème bit de la valeur et du statut du canal |
SetBit(val, n, isOn) | double | Définit le nème bit de la valeur spécifiée |
SetBit(cnlData, n, isOn) | CnlData | Définit le nème bit de la valeur du canal, tout en conservant le statut du canal |
GetByte(val, n) | double | Retourne le nème octet de la valeur spécifiée |
DataRel(offset) | CnlData | Données du canal relatives au canal actuel |
SetData() | double | Définit les données actuelles du canal en fonction de la valeur de commande |
Now() | double | La date et l'heure actuelles sous forme de nombre à virgule flottante. Utilise le fuseau horaire du serveur |
UtcNow() | double | La date et l'heure actuelles sous forme de nombre à virgule flottante. Utilise le fuseau horaire universel (UTC) |
UnixTime() | long | Heure Unix actuelle en secondes |
EncodeDate(dateTime) | double | Convertit la date et l'heure spécifiées en une valeur de canal de type Double |
DecodeDate(val) | DateTime | Convertit la valeur du canal en une date et une heure |
EncodeAscii(s) | double | Convertit une chaîne ASCII de 8 caractères maximum en un nombre à virgule flottante |
EncodeUnicode(s) | double | Convertit une chaîne Unicode de 4 caractères maximum en un nombre à virgule flottante |
DecodeAscii(val) | string | Convertit la valeur spécifiée en une chaîne ASCII de 8 caractères maximum |
DecodeUnicode(val) | string | Convertit la valeur spécifiée en une chaîne Unicode de 4 caractères maximum |
Substring(s, startIndex, length) | string | Extrait une sous-chaîne de la chaîne avec vérification des limites |
SplitAscii(getStringFunc) | string | Divise une chaîne ASCII pour être stockée dans plusieurs canaux |
SplitUnicode(getStringFunc) | string | Divise une chaîne Unicode pour être stockée dans plusieurs canaux |
EverySec(getDataFunc) | CnlData | Exécute la fonction spécifiée toutes les secondes |
EveryMin(getDataFunc) | CnlData | Exécute la fonction spécifiée toutes les minutes |
EveryHour(getDataFunc) | CnlData | Exécute la fonction spécifiée toutes les heures |
CountPulse(cnlNum) | double | Compte les impulsions du canal spécifié |
HourStarted() | bool | Indique qu'une nouvelle heure a commencé. Le résultat est vrai une fois pour chaque canal |
DayStarted() | bool | Indique qu'un nouveau jour a commencé. Le résultat est vrai une fois pour chaque canal |
MonthStarted() | bool | Indique qu'un nouveau mois a commencé. Le résultat est vrai une fois pour chaque canal |
Des scripts supplémentaires, notamment pour le calcul de moyennes, sont disponibles sur GitHub.
Débogage des Scripts
Lors du développement de vos propres scripts, suivez les règles de syntaxe et vérifiez que les scripts fonctionnent correctement. Si le service Serveur ne parvient pas à compiler les scripts au démarrage, les informations sur les erreurs s'affichent dans le journal des opérations du Serveur ScadaServer.log
, et le code source compilé est disponible dans le fichier CalcEngine.cs
, situé dans le répertoire des journaux du Serveur. Pour développer des formules complexes, nous recommandons d'utiliser Microsoft Visual Studio ou Visual Studio Code.
Exemples de Formules
Exemple 1 : Transformation linéaire de la valeur d'un canal reçue d'un dispositif. La formule est utilisée pour un canal de type Entrée.
10 * Cnl + 1
Exemple 2 : La somme des valeurs des canaux 101 et 102. Le statut est extrait du canal 101. La formule est utilisée pour un canal de type Calculé.
Val(101) + Val(102); Stat(101)
Exemple 3 : La formule utilisée pour un canal de type calcul extrait le 0ème bit des données du canal 105.
GetBit(Data(105), 0)
Exemple 4 : La formule incrémente le compteur d'une unité chaque minute, en réinitialisant le compteur au début de chaque heure.
EveryMin(() => HourStarted() ? 0 : Val() + 1)