Le serveur HttpWebSocket
1. Description
Il est possible d'activer un serveur Http permettant de publier des pages statiques ainsi qu'un serveur WebSocket permettant de publier les changements des données du serveur. L'activation se fait au niveau du fichier <VKServer.ini> dans la section [Http]. Le mot clef Enabled=1 doit être défini. Il faut également que la licence permette cette option. Le serveur WebSocket transmet les modifications des données du serveur sous la forme de messages JSON. Il peut également recevoir des commandes sous le même format.
2. Les mots clef
Dans la section [http], les mots clef suivants sont disponibles:
Mot clef
Type
Description
Enabled
Boolean
Vrai si la fonctionnalité est activée.
BaseHttpURL
String
Adresse de base du serveur http
HttpPort
Integer
Numéro du port http
BaseWSURL
String
Adresse de base du serveur Websocket. Par défaut, l'adresse de base est /websocket
WSPort
Integer
Numéro du port WebSocket. Par défaut, le port du WebSocket sera le même que le port http
RootPath
String
Adresse du répertoire dans lequel les fichiers des pages htlm sont sauvegardés. Par défaut, definitionpath+\www
DomainName
String
Nom du domain. Par défaut, +
Exemple de définition:
[HTTP]
Enabled=1
httpPort=8484
3. Le protocole de communication
Un protocole de communication spécialement conçu pour QuickView est implémenté. Les messages JSON sont formés comme suit:
Exemple de message:
Les clients doivent se connecter sur le serveur à l'aide d'un websocket. Avant d'ouvrir le websocket, les clients devront s'identifier sur le serveur Web en effectuant un POST à l'adresse /auth avec comme paramètres "?username=xxx&pass=yyy". Les "userName" et "Password" correspondant aux identifiants de QuickView. Si l'identification est correct, le serveur renvoie un jwt ( JSon Web Token) enregistré dans un Cookie (jwtoken=.....). Lorsque le client ouvre le websocket, le serveur vérifie le contenu du token et accepte ou non son ouverture. Le token est valable 24 heures après quoi il est nécessaire de renouveler son identification si le websocket est fermé.
Il est aussi possible d'utiliser le mode d'authentification basic des websocket pour se connecter. En utilisant ce schéma, le serveur attend le token Authorization: Basic xxxx dans l'entête de la requête de connexion (voir https://developer.mozilla.org/fr/docs/Web/HTTP/Headers/Authorization ).
3.1 Les commandes possibles
Pour pouvoir lire, écrire, etc... le protocole demande l'utilisation de commandes. Les commandes possibles sont décrit dans le tableau suivant:
Commandes
Description
read
Lecture du contenu d'un registre.
Format de la commande "read" :
{"function":"read", "register":n }
{"function":"read", "databank":n }
n étant un entier et correspond au numéro de registre désiré.
write
Écriture de données dans un registre.
Format de la commande "write":
{"function":"write", "register":n, "data": {json object}}
{"function":"write", "databank":n, "reg":m, "bit":b, "value":true or false}
{"function":"write", "databank":n, "reg":m, "value": number or "string"}
n étant un entier correspondant au numéro de registre. data correspond à un objet JSOn qui est spécifique pour chaque registre.Lors de l'écriture dans un registre d'un databank, il faut spécifier le databand, le registre et la valeur pour une donnée complète du registre ou alors spécifier le bit et l'état de ce bit pour une valeur boolean.
readall
Demande le rafraîchissement de tous les registres du système. Le serveur renvoie tous les registres disponibles.
Format de la commande "refreshall":
{"function":"readall"}
subscribe
Souscrit au rafraîchissement d'un ou de plusieurs registres. Le serveur renvoie chaque changement d'un registre à tous les clients ayant souscrit à ce registre.
Format de la commande "subscribe":
{"function":"subscribe", "register":[x,y,z,...]} => souscrit aux changements de registres {"function":"subscribe", "databank":[x,y,z,...]} => souscrit aux changements des databanks {"function":"subscribe"} => souscrit à tous les changements
unsubscribe
Annule la souscription à un ou plusieurs registres.
Format de la commande "unsubscribe":
{"function":"unsubscribe", "register":[x,y,z,...]} => annule les souscriptions aux changements de registres
{"function":"unsubscribe", "databank":[x,y,z,...]} => annule les souscriptions aux changements de databank
{"function":"unsubscribe"} => annule toutes les souscriptions
3.2 Les registres
Les registres suivants sont disponibles:
Registre
Data
Description
10
"modeprogram":boolean Statut du mode programme
"modebuffer":boolean Statut du mode gare
"simulation":boolean Vrai si en mode simulation
"endofcycle":boolean Vrai si en fin de cycle
"workingmode":integer Mode de fonctionnement (0:DIA/OPI, 1:Priority, 2:OSCILine)
"timesynch":integer Nombre de secondes depuis le 01/01/1980. Permet de synchroniser les horloges
Statuts de la machine
32
"DateOfData" : string Date des données au format yyyymmdd
"Date" : string Date des données au format du PC
"BatchesIn" : Integer Nombre de chargements
"BatchesOut" : Integer Nombre de déchargements
"IdleTime" : Integer Nombre de minutes avec poste de charge vide
"ErrorStopTime" : Integer Nombre de minutess en stop causé par une alarme
"ErrorWarningTime" : Integer Nombre de minutes en stop causé par une alarme système en Auto
"ManuModeTime" : Integer Nombre de minutes en mode manuel
"SafetyDoorTime" : Integer Nombre de minutes pendant lesquelles les portes sont ouvertes
"PowerOnTime" : Integer Nombre de minute pendant lesquelles la machine est en marche
"Utilization-RPT" : Integer (PowerOnTime-Idle Time)/Power On Time = % d'utilisation
"Reliability" : Integer (Power On Time-Error Stop Time)/Power on Time = %
Données journalières
33
"labels" : Array 0..23 of strings Heures
"BatchsIn": Array 0..23 of integer Nombre de chargements par heure
"BatchesOut": Array 0..23 of integer Nombre de déchargements par heure
... Comme registre 32
Données journalières sur 24 heures
40
"alarmcount":integer Nombre d'alarme en cours
"alarms": array of alarm
[
"evt":integer Type d'événement: 1=Rtn, 2=Ack, 3=Ala, 4=Wrn
"num":integer Numéro de l'alarme
"time":Time Heure de l'alarme
"type":string Type de l'alarme
"group":string Groupe de l'alarme
"mess":string Message de l'alarme
"val":float Valeur associée à l'alarme
]
Liste des alarmes actives
42
"messagecount":integer Nombre de messages en cours
"messages": array of message
[
"evt":integer Type d'événement: 1=Rtn, 2=Ack, 3=Ala, 4=Wrn
"num":integer Numéro du message
"time":Time Heure du message
"type":string Type du message
"group":string Groupe du message
"mess":string Texte du message
"val":float Valeur associée au message
]
Liste des messages actifs
2000
"positioncount":integer Nombre de positions dans la machine
"hoistcount":integer Nombre de transporteurs dans la machine
"positions":array of position
[
"pos":integer Numéro de la position
"name": string Nom de la position
"flag":integer Flag de la position
"addr":integer Adresse de la position
"group":integer Numéro du groupe de la position
"tank": integer Numéro de la cuve
"disable":boolean Vrai si la position peut être mise hors service
"width":integer Largeur de la position
"process":integer Numéro de la page graphique
"dist":integer Distance entre position précédente et centre de la position
"branch";integer Numéro de la branche de la machine
"num":integer Numéro de la position à afficher
"layout":integer Layout de la position (0=standard, 1=en avant, 2=en arrière)
]
"hoists":array of hoist
[
"hoist":integer Numéro du transporteur
"type":integer Type de transporteur
"driptray":Boolean True si un bac d'égouttage est défini
"halfup":Boolean True si le transporteur peut faire un up demi
"pmin":integer Position minimale du transporteur
"pmax":integer Position maximale du transporteur
]
Définition de la machine
3000
"rectifiercount":integer Nombre de redresseur défini
"rectifiers": array of rectifier
[
"rectifier":integer numéro du redresseur
"position":integer position dans laquelle se trouve le redresseur
"name":string Nom du redresseur
"status":integer Statut du redresseur
"step":integer Step actuel du profil de courant
"ahamn":boolean True si Ah
"surface":float surface exposée
"density":float densité de courant
"current":float courant actuel
"voltage":float tension actuelle
"Q":float compteur Ah
"QTheo:float quantité d'Ah théorique
"QTheoAct:float écart actuel des Ah
"QTotal":float totalisateur des Ah
"setpoint":float consigne actuelle
"reverse":float consigne actuelle inverse
"maxU":float tension maximale
"maxI":float courant maximum
"minU":float tension à vide
"minI":float courant max lorsque la tension min est appliquée
"pcsetpoint":integer pourcentage de la consigne lorsque plusieurs redresseurs sont utilisés sur la même position
"alternation":integer temps entre chaque alternance
"surfaceflag":integer partie de la surface prise en considération
"currentform":integer numéro du profil de courant
"flag0":integer
"flag1:integer
"flag2:integer
]
Les redresseurs
5001..5100
"device":integer Numéro du device utilisé dans QuickView (0=interne)
"channel":integer Numéro du canal
"db":integer Numéro du db de l'automate
"regstart":integer Numéro du premier registre
"regend":integer Numéro du dernier registre
"registers": array of registre
[
"reg":integer Numéro du registre
"type":string Type de registre (byte,word,dword,real,string,int)
"value": string | number | float Valeur du registre
]
Contenu des databanks du serveur
12000
"ios" : array of IO
[
"io" : Integer Numéro de l'I/O
"Name" : string Nom de l'I/O
"unit" : string Unité de l'I/O
"type" : Integer Type d'I/O
"db" : Integer Numéro du DB
"reg" : Integer Numéro du registre
"bit" : Integer Numéro du bit
"mask" : Integer Mask à appliquer
"flags" : Integer Flags de l'I/O
"position" : Integer Position associée
"min" : Integer Valeur minimum
"max" : Integer valeur maximum
"value" : Integer|boolean|string selon le type de variable
]
Définition de toutes les I/O
12001..12999
"io" : Integer Numéro de l'I/O
"Name" : string Nom de l'I/O
"unit" : string Unité de l'I/O
"type" : Integer Type d'I/O
"db" : Integer Numéro du DB
"reg" : Integer Numéro du registre
"bit" : Integer Numéro du bit
"mask" : Integer Mask à appliquer
"flags" : Integer Flags de l'I/O
"position" : Integer Position associée
"min" : Integer Valeur minimum
"max" : Integer valeur maximum
"value" : Integer|boolean|string selon le type de variable
I/O individuelle
14000
"io1" : Integer|Boolean|String Donnée de l'I/O 1
"io2": Integer|Boolean|String Donnée de l'I/O 2
...
"io999": Integer|Boolean|String Donnée de l'I/O 999
Données de toutes les I/O sans définition
14100
"hoistsdata" : array hoistType
[
"hoist" : Integer Numéro du bras
"ready" : Boolean Vrai si le transporteur est prêt
"blockingalarms" : Integer Alarmes bloquantes
"height" : Integer Hauteur actuelle
"destheight" : Integer Hauteur de destination
"position" : Integer Position actuelle
"destination" : Integer Position de destination
"mode" : Integer Mode du robot
"movingleft" : Boolean Vrai si le robot se déplace à gauche
"movingright" : Boolean Vrai si le robot se déplace à droite
"movingup" : Boolean Vrai si le robot se déplace en haut
"movingdown" : Boolean Vrai si le robot se déplace en bas
"racknum" : Integer numéro de rack si présent sinon pas dans le record
"rackstatus" : Integer statut du rack si présent sinon pas dans le record
"rackprog" : Integer N° de programme du rack si présent sinon pas dans le record
]
Données de tous les robots
14101
"positionsdist" : array PositionDist
[
"position":integer numéro de position
"dist":integer distance depuis le début de la machine
]
"hoistsdist" : array HoistDist
[
"hoist":integer numéro du transporteur
"dist":integer distance actuelle depuis le début de la machine
]
14200
"positiondata" : array PositionDataType
[
"position" : Integer Numéro de la position
"racknum" : Integer numéro de rack si présent sinon pas dans le record
"rackstatus" : Integer statut du rack si présent sinon pas dans le record
"rackprog" : Integer N° de programme du rack si présent sinon pas dans le record
"program": String Nom du programme du rack
"ref": String Nom de la référence de la charge sur le rack
"tmin": Integer Temps minimum défini
"tmax": Integer Temps maximum défini
"teff": Integer Temps d'entrée dans la position (temps en secondes)
"disable" : Boolean Etat de la position si la position peut être mise hors service
"inalarm" : Boolean Etat d'alarme de la position
"ready" : Boolean Etat des équipements de la position par rapport au "Mode machine ready"
]
Données d'état des positions
14300
json de la page graphique
Données du dessin d'une page graphique
14301
"Registers" : array RegisterData
[
"db":integer numéro du databank
"reg":integer numéro du registre
"type":string type du registre (integer, real, string)
"value": integer or real or string valeur du registre
]
4. Utilisation en tant que API
Il est possible de faire des requêtes API sur le serveur. Pour obtenir les registres ci-dessus dans un GET HTTP, il faut effectuer les requêtes comme l'exemple suivant:
La réponse est un objet JSON comme suit:
{ "function":"write", "register":10, "Data": { "modeprogram": true, "modebuffer": true,..... }}
5. Utilisation comme serveur Web
Il est possible de fonctionner en tant que serveur web. Les fichiers doivent se trouver dans le répertoire RootPath .
6. Dashboard
Il est possible de faire fonctionner le site web avec Freeboard.

Pour fonctionner, il faut décompresser le fichier www.zip ci-dessous et le placer dans le répertoire défini dans rootPath.
Pour le lancer, il faut soit taper l'adresse web du site pour avoir l'éditeur de freeboard ou soit http://localhost:8484/index.html#source=dashboard.json pour lancer directement un dashboard prédéfini.
Dans le fichier index.html, le bouton donnant l'accès aux modification du dashboard a été commenté. Pour permettre des modifications, il faut dé-commenter les lignes 48 à 96 et 110 à 111
Mis à jour
Ce contenu vous a-t-il été utile ?