Interfaçage OpenFlyers et armoire à clés: Difference between revisions

From Documentation de la solution web de gestion OpenFlyers
Jump to navigation Jump to search
imported>Claratte
m (Text replacement - "Fichier:" to "File:")
 
(77 intermediate revisions by 7 users not shown)
Line 2: Line 2:


=Présentation=
=Présentation=
L'objet de cette page est de décrire le protocole d'interfaçage avec toute solution d'armoire à clé.
L'objet de cette page est de décrire le protocole d'interfaçage avec toute solution d'armoire à clés tiers. Pour les armoires à clés commercialisées par OpenFlyers, il faut se référer à la [[Contrôle des accès|documentation sur le contrôle d'accès]].


Le protocole repose sur le principe que l'interfaçage est piloté par un logiciel installé sur un PC ou une solution embarquée et qui dispose d'un accès à internet lui permettant de communiquer avec OpenFlyers.
Le protocole repose sur le principe que l'interfaçage est réalisé par un logiciel de contrôle de l'armoire à clé sur un PC ou une solution embarquée et qui dispose d'un accès à internet lui permettant de communiquer avec OpenFlyers. La communication est synchrone.


=Interface utilisateur OpenFlyers=
=Interface utilisateur OpenFlyers=
L'utilisateur ouvre un vol dans OpenFlyers :
L'utilisateur ouvre un vol dans OpenFlyers :


[[Fichier:Menu-contextuel-ouverture-de-vol.png]]
[[File:Menu-contextuel-ouverture-de-vol.png]]




Il se retrouve sur le formulaire de saisie du vol :
Il se retrouve sur le formulaire de saisie du vol en mode Départ en vol:


[[Fichier:Formulaire-ouverture-de-vol.png]]
[[File:Formulaire-ouverture-de-vol.png]]




Line 20: Line 20:
*Une alerte ou plusieurs alertes rouges (bloquantes), s'affichent : l'utilisateur n'a pas la possibilité de surpasser ses alertes, il ne peut alors récupérer la clé :
*Une alerte ou plusieurs alertes rouges (bloquantes), s'affichent : l'utilisateur n'a pas la possibilité de surpasser ses alertes, il ne peut alors récupérer la clé :


[[Fichier:Alertes-bloquantes-en-ouverture-vol.png]]
[[File:Alertes-bloquantes-en-ouverture-vol.png]]


*Une alerte ou plusieurs alertes oranges (non-bloquantes), s'affichent : l'utilisateur a la possibilité de surpasser ses alertes, et ainsi de récupérer la clé :
*Une alerte ou plusieurs alertes oranges (non-bloquantes), s'affichent : l'utilisateur a la possibilité de surpasser ses alertes, et ainsi de récupérer la clé :


[[Fichier:Alertes-non-bloquantes-en-ouverture-vol.png]]
[[File:Alertes-non-bloquantes-en-ouverture-vol.png]]


*Aucune alerte ne s'affiche, l'utilisateur se retrouve alors directement sur la page lui indiquant :
*Aucune alerte ne s'affiche, l'utilisateur se retrouve alors directement sur la page lui indiquant :


[[Fichier:Message autorisation libération clé.png]]
[[File:Message_autorisation_libération_clé.png]]


Une fois qu'il a cliqué sur '''LIBERER LA CLE''', il dispose de X secondes. Cette durée est paramétrable par OpenFlyers dans le cas du protocole piloté par OpenKeys.exe sur Windows ou est programmé en dur dans PyOpenKeys sous Linux.
Une fois qu'il a cliqué sur '''LIBÉRER LA CLÉ''', il dispose de X secondes. Cette durée est paramétrable par OpenFlyers.


*Lorsqu'il rentre de vol, l'utilisateur n'a plus qu'a retourner sur le formulaire de saisie de vol et à fermer son vol. Après la fermeture, il lui est demandé de remettre sa clé sur l'armoire s'il ne l'a pas fait avant.
*Lorsqu'il rentre de vol, l'utilisateur n'a plus qu'a retourner sur le formulaire de saisie de vol et à fermer son vol. La clé doit etre remise en place sur l'armoire pour fermer le vol.


=Interface administrateur OpenFlyers=
=Interface administrateur OpenFlyers=
==Activation et configuration de la gestion des armoires à clé==
==Activation et configuration de la gestion des armoires à clé==
*'''Admin'''
*'''Admin > Structure > Structure > Paramétrage'''
*'''Configuration > Paramétrage'''
*Dans la section du formulaire '''Contrôle d'accès''', sélectionner '''Activé(e)''' pour les champs '''Contrôle d'accès''' et '''Gestion armoire à clés'''.
*Dans le formulaire '''Gestion des vols''', sélectionner '''Activé(e)''' pour le champ '''Gestion armoire à clé'''
[[File:Config_parametres_OF_controle_acces 1.jpg]]
*Cliquer sur le bouton '''Valider''' lié au formulaire
*Cliquer sur le bouton '''Enregistrer'''  
*Le formulaire apparait alors comme suit :
*Un nouveau champ s'affich
*Sélectionner le '''Logiciel de contrôle de l'armoire à clés''' selon votre armoire à clés
[[File:Config_parametres_OF_controle_acces 4.jpg]]


[[Fichier:Paramétrage armoire à clé.png]]
Les Logiciels OpenKey et PyOpenKey sont des protocoles propriétaires d'OF, pour les configurer voir  [[Interfaçage-OpenFlyers-et-armoire-à-clés#Interface-administrateur-OpenFlyers | Interfaçage armoire à clés OF]]
 
*Signification des paramètres :
**'''Gestion des clés''' : Gestion par OpenFlyers des clés de l'armoire ('''Désactivé(e)''' ou '''Activé(e)''')
**'''Nombre de clés''' : nombre de clés possibles dans l'armoire
**'''Temporisation''' : temps en secondes pendant lequel la clé peut être retirée après autorisation (la configuration de la temporisation n'est effective qu'avec le logiciel de pilotage OpenKey sous Windows).
**'''IP du PC avec le driver du tableau de clés''' : adresse IP du PC sur lequel se trouve le logiciel de pilotage de l'armoire à clé.
**'''Port du driver du tableau de clés''' : port sur lequel écoute le logiciel de pilotage de l'armoire à clé.
**'''Type de serveur''' : PyOpenKey (sous Linux) ou OpenKey (sous Windows). Il s'agit du nom du logiciel de pilotage de l'armoire à clé.
**'''Fermeture automatique des vols au retour de la clé''' : permet de programmer la fermeture automatique des vols au retour de la clé.
**'''Phrase mot de passe''' : phrase permettant d'authentifier la source de la transmission dans le cas d'une requête XML-RPC '''notify'''.
'''Attention :''' dans le cas où le logiciel de pilotage se trouve sur le même PC que pour la saisie des vols dans OpenFlyers, il peut y avoir des problèmes de loopback au niveau du routeur.


==Attribution des clés aux ressources/aéronefs==
==Attribution des clés aux ressources/aéronefs==
''Dans le cas où c'est le logiciel OpenFlyers qui gère les clés.''
''Dans le cas où c'est le logiciel OpenFlyers qui gère les clés.''
*'''Admin'''
*'''Admin > Types de ressources > Actives'''
*'''Ressources > Ressources > Actives''' ou '''Flotte > Aéronefs > Aéronefs actifs''' sous version OF 2.1
[[File:Liste_des_aéronefs.png]]
 
[[Fichier:Liste des aéronefs.png]]


Pour chaque aéronef concerné, il suffit d'attribuer un numéro et un nom de clé dans les champs correspondants. La validation de la saisie se fait automatiquement en cliquant hors du champ de saisie.
Pour chaque aéronef concerné, il suffit d'attribuer un numéro et un nom de clé dans les champs correspondants. La validation de la saisie se fait automatiquement en cliquant hors du champ de saisie.


=Protocole de dialogue XML-RPC entre OpenFlyers et le logiciel de gestion de l'armoire à clé=
=Protocole de dialogue XML-RPC entre OpenFlyers et le logiciel de gestion de l'armoire à clé=
Le dialogue avec le serveur XML-RPC d'OpenFlyers doit s'effectuer en '''HTTPS'''.
Le dialogue avec le serveur XML-RPC d'OpenFlyers doit s'effectuer en '''HTTPS'''. Les commandes accessibles sont listées par un appel à ActionOnDemand.php
https://openflyers.com/yourURL/actionOnDemand.php


==Demande de libération d'une clé==
==Demande de libération d'une clé==
*Lorsque qu'une clé doit être libérée, le navigateur envoie un message au logiciel de pilotage par le protocole HTTP sous la forme suivante :
http://127.0.0.1:4080/?sessid=e5f01p2oqh2vb36arisr8k5j87&key=1&resource=2&person=12


:*L'adresse IP (ici 127.0.0.1) et le port (ici 4080) sont fonction de la [[#Activation_et_configuration_de_la_gestion_des_armoires_.C3.A0_cl.C3.A9|configuration de l'armoire à clé dans OpenFlyers]].
===Cas avec gestion des clés par OpenFlyers===
 
*Lorsque qu'une clé doit être libérée, le navigateur envoie un message au logiciel de contrôle de l'armoire à clé par le protocole HTTPS sous la forme suivante :
https://127.0.0.1:4080/?sessid=e5f01p2oqh2vb36arisr8k5j87&timeOut=10000&key=1&resource=2&person=12;action='releaseKey'
 
:*L'adresse IP (ici 127.0.0.1) et le port (ici 4080) sont fonction de la [[#Activation_et_configuration_de_la_gestion_des_armoires_à_clé|configuration de l'armoire à clé dans OpenFlyers]].
:*sessid contient le numéro de session en cours
:*sessid contient le numéro de session en cours
:*timeout correspond au temps d'attente pour la prise d'une clé en millisecondes
:*key contient le numéro de la clé concernée
:*key contient le numéro de la clé concernée
:*resource contient le numéro de la ressource concernée
:*resource contient le numéro de la ressource concernée
:*person contient le numéro de l'utilisateur qui fait la demande
:*person contient le numéro de l'utilisateur qui fait la demande
*Le logiciel de pilotage doit alors envoyer une demande d'ordre au serveur OpenFlyers à l'adresse suivante https://structure.openflyers.tld/actionOnDemand.php où il faut remplacer structure.openflyers.tld par l'adresse de la plateforme OpenFlyers concernée. avec comme commande XML_RPC '''checkCommand ("e5f01p2oqh2vb36arisr8k5j87",int(key))'''.
:*action est un mot clé désignant l'objet de la commande
:**release_key: ordre de libérer la clé
:**open_door: ordre d'ouvrir la porte
:**init_tags: ordre de lire les tags des clés
*Le logiciel de contrôle de l'armoire à clé doit alors envoyer une demande d'ordre au serveur OpenFlyers à l'adresse suivante https://openflyers.com/structure/ où il faut remplacer openflyers.com/structure par l'adresse de la plateforme OpenFlyers concernée, avec comme commande XML_RPC '''checkCommand ("e5f01p2oqh2vb36arisr8k5j87",int(key))'''.
 
*Le serveur OpenFlyers vérifie alors l'action demandée :
Pour release_key, il est vérifié :
#Que la clé est au bon format et existe. Lorsque la clé est validée, on passe à l'étape suivante sinon on retourne 0
#Que l'utilisateur faisant la demande est bien celui qui est connecté. Lorsque c'est le cas, on passe à l'étape suivante sinon on retourne 0
#Ensuite si l'utilisateur qui a passé la demande :
#*A le droit '''Gestion des clés''' (administrateur) alors on libère la clé sans condition (cela permet de libérer la clé sans contrôle) et on retourne 1
#*N'a pas le droit '''Gestion des clés''' (pilote) alors on vérifie s'il existe un vol ouvert qui remplit la double condition :
#**Vol attribué à l'utilisateur
#**Aéronef du vol associé à la demande de libération de la clé
#**Lorsque la double condition est remplie, on retourne 1 sinon 0
 
*Le serveur retourne ensuite la réponse :
**1 dans le cas d'autorisation de libération de clé
**0 dans le cas contraire
 
====Exemple de script en Python d'utilisation de la commande checkCommand avec gestion des clés====
<python># load library
from twisted.web.xmlrpc import Proxy
from twisted.internet import reactor, ssl
def printValue(value):
    print repr(value)
    reactor.stop()
def printError(error):
    print 'error', error
    reactor.stop()
# URL of the XML-RPC server
proxy = Proxy('https://yourURL.xx/actionOnDemand.php')
# init array to send
sessid = ""
key_num = 1
# send to the XML-RPC server
proxy.callRemote('checkCommand', sessid, key_num).addCallbacks(printValue, printError)
reactor.run()</python>
 
Ce test peut être complété (pour obtenir une réponse "1") en simulant une armoire à clé à l'aide d'un script PHP de la façon suivante :
*Installer un serveur local (par exemple [https://www.wampserver.com/ wampserver] sous Windows) de façon à avoir le port 127.0.0.1 qui lui est attribué
*Configurer la plateforme OpenFlyers de manière à gérer l'armoire à clé avec les éléments suivants :
**'''IP du PC contenant le logiciel de contrôle''' : 127.0.0.1
**'''Port du PC contenant le logiciel de contrôle''' : 80
*Configurer la plateforme OpenFlyers de manière à gérer les clés
*A la racine du répertoire www, mettre le script index.php suivant (on suppose que ce script est appelé par défaut lorsqu'on utilise l'URL https://127.0.0.1 ) :
<php><?php
file_put_contents('test.txt', 'TEST', FILE_APPEND );
file_put_contents('test.txt', print_r($_REQUEST, true), FILE_APPEND );
?></php>
*Toujours à la racine du répertoire www, créer un fichier test.txt
Le script PHP écrira dans le fichier test.txt les variables transmises lors de la demande d'ouverture de l'armoire à clé :
<pre>TESTArray
(
    [sessid] => j2eo92215nbef09borb74jftm1
    [key] => 1
    [resource] => 1
    [person] => 1
)</pre>
*Il suffit alors de recopier la valeur de '''sessid''' et de '''key''' dans le script python de ce début de paragraphe et de le tester : il devrait renvoyer 1.
 
===Cas sans gestion des clés par OpenFlyers===
 
*Lorsque qu'une demande de vérification doit être réalisée, le navigateur envoie un message au logiciel de contrôle de l'armoire à clé par le protocole HTTPS sous la forme suivante :
https://127.0.0.1:4080/?sessid=e5f01p2oqh2vb36arisr8k5j87&amp;resource=2&amp;person=12
 
:*L'adresse IP (ici 127.0.0.1) et le port (ici 4080) sont fonction de la [[#Activation_et_configuration_de_la_gestion_des_armoires_à_clé|configuration de l'armoire à clé dans OpenFlyers]].
:*sessid contient le numéro de session en cours
:*resource contient le numéro de la ressource concernée
:*person contient le numéro de l'utilisateur qui fait la demande
*Le logiciel de contrôle de l'armoire à clé doit alors envoyer une demande d'ordre au serveur OpenFlyers à l'adresse suivante https://openflyers.com/structure/actionOnDemand.php où il faut remplacer openflyers.com/structure par l'adresse de la plateforme OpenFlyers concernée, avec comme commande XML_RPC '''checkCommand ("e5f01p2oqh2vb36arisr8k5j87")'''.


*Le serveur OpenFlyers vérifie alors :
*Le serveur OpenFlyers vérifie alors :
**Si l'utilisateur qui a passé la demande a le droit '''Gestion des clés''' (administrateur), il libère la clé sans condition (cela permet de libérer la clé sans contrôle)
#Que l'utilisateur faisant la demande est bien celui qui est connecté. Lorsque c'est le cas, on passe à l'étape suivante sinon on retourne 0
**Si l'utilisateur qui a passé la demande n'a le droit '''Gestion des clés''' (pilote), alors il vérifie s'il existe un vol ouvert qui remplit la double condition :
#On vérifie s'il existe un vol ouvert qui remplit la double condition :
***Vol attribué à l'utilisateur
#*Vol attribué à l'utilisateur
***Aéronef du vol associé à la demande de libération de la clé
#*Aéronef du vol associé à la demande de libération de la clé
#*Lorsque la double condition est remplie, on retourne 1 sinon 0


*Le serveur retourne ensuite la réponse :
*Le serveur retourne ensuite la réponse :
*1 dans le cas d'autorisation de libération de clé  
**1 dans le cas d'autorisation
*0 dans le cas contraire
**0 dans le cas contraire
 
====Exemple de script en Python d'utilisation de la commande checkCommand sans gestion des clés====
 
<python># load library
from twisted.web.xmlrpc import Proxy
from twisted.internet import reactor, ssl
def printValue(value):
    print repr(value)
    reactor.stop()
def printError(error):
    print 'error', error
    reactor.stop()
# URL of the XML-RPC server
proxy = Proxy('https://yourURL.xx/actionOnDemand.php')
# init array to send
sessid = ""
# send to the XML-RPC server
proxy.callRemote('checkCommand', sessid).addCallbacks(printValue, printError)
reactor.run()</python>
 
Ce test peut être complété (pour obtenir une réponse "1") en simulant une armoire à clé à l'aide d'un script PHP de la façon suivante :
*Installer un serveur local (par exemple [https://www.wampserver.com/ wampserver] sous Windows) de façon à avoir le port 127.0.0.1 qui lui est attribué
*Configurer la plateforme OpenFlyers de manière à gérer l'armoire à clé avec les éléments suivants :
**'''IP du PC contenant le logiciel de contrôle''' : 127.0.0.1
**'''Port du PC contenant le logiciel de contrôle''' : 80
*Configurer la plateforme OpenFlyers de manière à ne pas gérer les clés
*A la racine du répertoire www, mettre le script index.php suivant (on suppose que ce script est appelé par défaut lorsqu'on utilise l'URL https://127.0.0.1 ) :
<php><?php
file_put_contents('test.txt', 'TEST', FILE_APPEND );
file_put_contents('test.txt', print_r($_REQUEST, true), FILE_APPEND );
?></php>
*Toujours à la racine du répertoire www, créer un fichier test.txt
Le script PHP écrira dans le fichier test.txt les variables transmises lors de la demande d'ouverture de l'armoire à clé :
<pre>TESTArray
(
    [sessid] => j2eo92215nbef09borb74jftm1
    [resource] => 1
    [person] => 1
)</pre>
*Il suffit alors de recopier la valeur de '''sessid''' dans le script python de ce début de paragraphe et de le tester : il devrait renvoyer 1.


==Modification de l'état d'une clé==
==Modification de l'état d'une clé==
''Applicable uniquement dans le cas où le logiciel OpenFlyers gère les clés.''
''Applicable dans le cas où le protocole PyOpenKeys2 gère les clés.''
*Le logiciel de pilotage doit envoyer un ordre '''notify([1,0,1,1,1,1,0,0], "passphrase")''' avec comme paramètre un tableau chronologique des clés ayant pour valeur leur état (1 = interrupteur de présence de clé fermé = clé absente de l'armoire, 0 = interrupteur de présence de clé ouvert = clé présente dans l'armoire)
*Le logiciel de contrôle de l'armoire à clés doit envoyer un ordre '''notify([1,0,1,1,1,1,0,0], "passphrase")''' avec comme paramètre un tableau chronologique des clés ayant pour valeur leur état  
''Applicable dans le cas où le protocole PyOpenKeys3 gère les clés.''
*Le logiciel de contrôle de l'armoire à clés doit envoyer un ordre '''notify2([[1,1],[2,0],[3,1],[4,1],[5,1],[6,1],[7,0],[8,0]], "passphrase")''' avec comme paramètre un tableau de tableau avec le numéro de la clé suivi de son état
**1 = interrupteur de présence de clé fermé = clé absente de l'armoire
**0 = interrupteur de présence de clé ouvert = clé présente dans l'armoire


===Exemple de script en Python pour la commande notify===
===Exemple de script en Python pour la commande notify===
Nécessite les librairies Twisted et pyOpenSSL
Nécessite les librairies Twisted et OpenSSL


<python># load library
<python># load library
Line 113: Line 234:
# init passphrase
# init passphrase
passphrase = 'SDjklsdiuQSIPO23879ZERK2098ZL2908DFZLK'
passphrase = 'SDjklsdiuQSIPO23879ZERK2098ZL2908DFZLK'
# Initiate number of key
KEY_NUMBER = 16


# init array to send
# init array to send
status = []
state = random.randint(0,1)
state = random.randint(0,1)
# Alternate 0 and 1 for test
 
for i in range(0,10):
if KEY_NUMBER > 8:
    # Test notify2
    status = [[d+1,0] for d in range(KEY_NUMBER)]
    for i in range(KEY_NUMBER):
        status[i] = [i+1,state]
        # Alternate 0 and 1 for test
        state = 0 if state == 1 else 1
else:
    # Test notify
    for i in range(KEY_NUMBER):
         status.append(state)
         status.append(state)
        # Alternate 0 and 1 for test
         state = 0 if state == 1 else 1
         state = 0 if state == 1 else 1
#print status


# send to the XML-RPC server
# send to the XML-RPC server
proxy.callRemote('notify', status, passphrase).addCallbacks(printValue, printError)
print "Status sequence : %s" % status
reactor.run()</python>
if KEY_NUMBER<9:
    proxy.callRemote('notify', status, passphrase).addCallbacks(printValue, printError)
else:
    proxy.callRemote('notify2', status, passphrase).addCallbacks(printValue, printError)
reactor.run()
</python>
''Nota : to test change the number of key : up to 8 the software use '''notify()''', beyond it uses '''notify2()'''
 
Cela retournera 0 en cas d'anomalie ou si la passphase transmise n'est pas correcte, 1 si la table des clés a été correctement mise à jour.
 
==Fermeture automatique d'un vol==
 
Le logiciel de contrôle de l'armoire à clé doit envoyer un ordre '''closeFlight("passphrase", "id de ressource")''' avec comme paramètre un passphrase et l'id qui va entraîner la fermeture du vol effectué sur cette ressource si un vol avait été ouvert et que la "Fermeture automatique des
vols au retour de la clé" soit activée. La commande retournera comme réponse une structure JSON pour déterminer si la fermeture du vol s'est bien réalisée ou non et qu'il n'y a pas eu d'erreur.


Ces scripts nécessitent les librairies Twisted et pyOpenSSL.
Réponse quand la vérification du passphrase est incorrecte, ce qui a entraîné la non-fermeture du vol :
<javascript>{[
    ack : 0
]}</javascript>


Ils recevront (et afficheront) comme réponse 0 du fait que le numéro de session transmis n'est pas correct (et laissé à une chaine vide).
Réponse quand la vérification du passphrase est correcte et que la demande de fermeture du vol s'est bien réalisée :
<javascript>{[
    ack : 1
]}</javascript>


==Fermeture automatique d'un vol==
Réponse quand la vérification du passphrase est correcte et que la demande de fermeture du vol ne s'est pas bien réalisée suite à une erreur :
La commande '''closeFlight''' permet d'envoyer l'ordre de fermer un vol. Il nécessite le passage de l'id d'une ressource en paramètre et entraîne la fermeture du vol effectué sur cette ressource si un vol avait été ouvert. La commande retournera un entier pour déterminer si la fermeture du vol s'est bien réalisée ou non.
<javascript>{[
    ack : 1,
    error : 'Message d\'erreur ...'
]}</javascript>


===Script d'exemple pour closeFlight===
===Script d'exemple pour closeFlight===
Line 151: Line 305:
proxy = Proxy('https://yourURL.xx/actionOnDemand.php')
proxy = Proxy('https://yourURL.xx/actionOnDemand.php')


$resource_id = 1
# Id of resource which needs a flight closing
resource_id = 1
 
# init passphrase
passphrase = 'SDjklsdiuQSIPO23879ZERK2098ZL2908DFZLK'


# send to the XML-RPC server
# send to the XML-RPC server
proxy.callRemote('closeFlight', $resource_id).addCallbacks(printValue, printError)
proxy.callRemote('closeFlight', resource_id, passphrase).addCallbacks(printValue, printError)
reactor.run()</python>
reactor.run()</python>


Cela affichera 1 en cas de fermeture de vol ou 0 si ça ne s'est pas réalisé.
==Exemple de script en Python de logiciel de contrôle d'une armoire==
 
==Exemple 1 de script en Python de logiciel de pilotage d'une armoire==
<python>#!/usr/bin/python
<python>#!/usr/bin/python
import xmlrpclib, time, dummy_proto, hashlib
import xmlrpclib, time, dummy_proto, hashlib
Line 167: Line 323:
from twisted.web import resource, server
from twisted.web import resource, server


# HTTP Port from which the OF client contact OpenKeys service
# Port from which the OF client contact OpenKeys service
SERVICE_PORT=4080  
SERVICE_PORT=4080  
SERVICE_HOST="127.0.0.1"
# IP address of the OpenKeys service
SERVICE_HOST="192.168.0.200"


KEYS_ADDR='192.168.23.118'
# IP address of the key cabinet
KEYS_ADDR='192.168.0.201'
# Port from which OpenKeys service contacts the key cabinet
KEYS_PORT=6002
KEYS_PORT=6002
#Time to release the key
KEY_RELEASE_DURATION=15
KEY_RELEASE_DURATION=15


Line 181: Line 341:
passphrase = 'SDjklsdiuQSIPO23879ZERK2098ZL2908DFZLK'
passphrase = 'SDjklsdiuQSIPO23879ZERK2098ZL2908DFZLK'


OF_XMLRPC_URL="https://structure.openflyers.tld/actionOnDemand.php"
OF_XMLRPC_URL="https://openflyers.com/structure/actionOnDemand.php"


DEBUG=False
DEBUG=False
Line 231: Line 391:


# blocking method ! must be run in a new thread
# blocking method ! must be run in a new thread
def release_key(self, key_num):
def release_key(self, key_num, timeOur):
m = dummy_proto.dummy_ONOFF_Control()
m = dummy_proto.dummy_ONOFF_Control()
m.setON(key_num)
m.setON(key_num)
self.protocol.send(m)
self.protocol.send(m)
time.sleep(KEY_RELEASE_DURATION)
time.sleep(timeOut)
m.setOFF(key_num)
m.setOFF(key_num)
self.protocol.send(m)
self.protocol.send(m)
Line 250: Line 410:
return self
return self


def render_GET(self, request):
def render(self, request):
reponse = 0 # NOK par defaut
reponse = 0 # NOK par defaut
key_num = 0
key_num = 0
if len(request.args) == 0:
# no GET args.
# return javascript code
return """
var handleSuccess = function(o){
if(o.responseText !== undefined){
/* TODO : regarder si on a OK ou NOK */
    }
}
var handleFailure = function(o){
    if(o.responseText !== undefined){
alert("Erreur lors de la liberation de la clef : "+o.status+" -- "+o.statusText);
    }
}
var callback = {
  success:handleSuccess,
  failure: handleFailure,
  argument: {}
};
function releasekey(sessid, keynum) {
YAHOO.util.Connect.asyncRequest('GET', "http://%s:%i/?sessid="+sessid+"&key="+keynum, callback);
document.getElementById('keybutton').enabled=false;
setTimeout ("document.getElementById('keybutton').enabled=true;", 10000);
}
""" % (SERVICE_HOST,SERVICE_PORT)
try:
try:
sessid = request.args.get('sessid', [""])[0]
sessid = request.args.get('sessid', [""])[0]
Line 285: Line 419:
response = 0
response = 0
if password:
if password:
if hashlib.sha224(password).hexdigest() in PASSWORDS:
                                if hashlib.sha224(password).hexdigest() in PASSWORDS:
response = 1
                                        timeOut  = KEY_RELEASE_DURATION
else:
                                        response_XMLRPC = 1
response = self.rpc_server.checkCommand(sessid, key_num)
                        else:
                                timeOut  = int(request.args.get('timeout', ["0"])[0])
                                response = self.rpc_server.checkCommand(sessid, key_num)
except Exception, err:
except Exception, err:
if DEBUG: print "error: ", err
if DEBUG: print "error: ", err
Line 297: Line 433:
if self.keys_webcontrol_state[key_num-1]: return "OK:already released"
if self.keys_webcontrol_state[key_num-1]: return "OK:already released"
self.keys_webcontrol_state[key_num-1] = 1
self.keys_webcontrol_state[key_num-1] = 1
d = threads.deferToThread(self.dummy_client_factory.release_key, key_num)
d = threads.deferToThread(self.dummy_client_factory.release_key, key_num, timeOut)
d.addCallback(self.unset_webcontrol_state)
d.addCallback(self.unset_webcontrol_state)
return "OK:releasing key..."
return "OK:releasing key..."
Line 326: Line 462:
  ).setServiceParent(serviceCollection)</python>
  ).setServiceParent(serviceCollection)</python>


==Exemple 3 de script en Python permettant de vérifier une demande de libération de clé (commande checkCommand)==
==Maquette de script actionOnDemand.php côté serveur recevant les appels du logiciel de contrôle de l'armoire==
 
<python># load library
from twisted.web.xmlrpc import Proxy
from twisted.internet import reactor, ssl
def printValue(value):
    print repr(value)
    reactor.stop()
def printError(error):
    print 'error', error
    reactor.stop()
# URL of the XML-RPC server
proxy = Proxy('https://yourURL.xx/actionOnDemand.php')
# init array to send
sessid = ""
key_num = 1
# send to the XML-RPC server
proxy.callRemote('checkCommand', sessid, key_num).addCallbacks(printValue, printError)
reactor.run()</python>
 
Ce test peut être complété (pour obtenir une réponse "1") en simulant une armoire à clé à l'aide d'un script PHP de la façon suivante :
*Installer un serveur local (par exemple [http://www.wampserver.com/ wampserver] sous Windows) de façon à avoir le port 127.0.0.1 qui lui est attribué
*Configurer la plateforme OpenFlyers de manière à gérer l'armoire à clé avec les éléments suivants :
**'''IP du PC avec le driver du tableau de clés :''' 127.0.0.1
**'''Port du driver du tableau de clés :''' 80
*A la racine du répertoire www, mettre le script index.php suivant (on suppose que ce script est appelé par défaut lorsqu'on utilise l'URL http://127.0.0.1 ) :
<php><?php
file_put_contents('test.txt', 'TEST', FILE_APPEND );
file_put_contents('test.txt', print_r($_REQUEST, true), FILE_APPEND );
?></php>
*Toujours à la racine du répertoire www, créer un fichier test.txt
Le script PHP écrira dans le fichier test.txt les variables transmises lors de la demande d'ouverture de l'armoire à clé :
<pre>TESTArray
(
    [sessid] => j2eo92215nbef09borb74jftm1
    [key] => 1
    [resource] => 1
    [person] => 1
)</pre>
*Il suffit alors de recopier la valeur de '''sessid''' et de '''key''' dans le script python de ce début de paragraphe et de le tester : il devrait renvoyer 1.
*Configurer la gestion de l'armoire à clé de la façon suivante
 
===Sans gestion des clés===
 
<python># load library
from twisted.web.xmlrpc import Proxy
from twisted.internet import reactor, ssl
def printValue(value):
    print repr(value)
    reactor.stop()
def printError(error):
    print 'error', error
    reactor.stop()
# URL of the XML-RPC server
proxy = Proxy('https://yourURL.xx/actionOnDemand.php')
# init array to send
sessid = ""
# send to the XML-RPC server
proxy.callRemote('checkCommand', sessid).addCallbacks(printValue, printError)
reactor.run()</python>
 
Ce test peut être complété (pour obtenir une réponse "1") en simulant une armoire à clé à l'aide d'un script PHP de la façon suivante :
*Installer un serveur local (par exemple [http://www.wampserver.com/ wampserver] sous Windows) de façon à avoir le port 127.0.0.1 qui lui est attribué
*Configurer la plateforme OpenFlyers de manière à gérer l'armoire à clé avec les éléments suivants :
**'''IP du PC avec le driver du tableau de clés :''' 127.0.0.1
**'''Port du driver du tableau de clés :''' 80
*A la racine du répertoire www, mettre le script index.php suivant (on suppose que ce script est appelé par défaut lorsqu'on utilise l'URL http://127.0.0.1 ) :
<php><?php
file_put_contents('test.txt', 'TEST', FILE_APPEND );
file_put_contents('test.txt', print_r($_REQUEST, true), FILE_APPEND );
?></php>
*Toujours à la racine du répertoire www, créer un fichier test.txt
Le script PHP écrira dans le fichier test.txt les variables transmises lors de la demande d'ouverture de l'armoire à clé :
<pre>TESTArray
(
    [sessid] => j2eo92215nbef09borb74jftm1
    [resource] => 1
    [person] => 1
)</pre>
*Il suffit alors de recopier la valeur de '''sessid''' dans le script python de ce début de paragraphe et de le tester : il devrait renvoyer 1.
 
==Maquette de script actionOnDemand.php côté serveur recevant les appels du logiciel de pilotage de l'armoire==
Ce script nécessite la bibliothèque PEAR [http://pear.php.net/package/XML_RPC2 XML_RPC2].
Ce script nécessite la bibliothèque PEAR [http://pear.php.net/package/XML_RPC2 XML_RPC2].



Latest revision as of 18:27, 2 October 2024

Présentation

L'objet de cette page est de décrire le protocole d'interfaçage avec toute solution d'armoire à clés tiers. Pour les armoires à clés commercialisées par OpenFlyers, il faut se référer à la documentation sur le contrôle d'accès.

Le protocole repose sur le principe que l'interfaçage est réalisé par un logiciel de contrôle de l'armoire à clé sur un PC ou une solution embarquée et qui dispose d'un accès à internet lui permettant de communiquer avec OpenFlyers. La communication est synchrone.

Interface utilisateur OpenFlyers

L'utilisateur ouvre un vol dans OpenFlyers :

Menu contextuel ouverture de vol.png


Il se retrouve sur le formulaire de saisie du vol en mode Départ en vol:

Formulaire ouverture de vol.png


Lorsqu'il clique sur le bouton de validation, 3 cas peuvent se présenter :

  • Une alerte ou plusieurs alertes rouges (bloquantes), s'affichent : l'utilisateur n'a pas la possibilité de surpasser ses alertes, il ne peut alors récupérer la clé :

Alertes bloquantes en ouverture vol.png

  • Une alerte ou plusieurs alertes oranges (non-bloquantes), s'affichent : l'utilisateur a la possibilité de surpasser ses alertes, et ainsi de récupérer la clé :

Alertes non bloquantes en ouverture vol.png

  • Aucune alerte ne s'affiche, l'utilisateur se retrouve alors directement sur la page lui indiquant :

Message_autorisation_libération_clé.png

Une fois qu'il a cliqué sur LIBÉRER LA CLÉ, il dispose de X secondes. Cette durée est paramétrable par OpenFlyers.

  • Lorsqu'il rentre de vol, l'utilisateur n'a plus qu'a retourner sur le formulaire de saisie de vol et à fermer son vol. La clé doit etre remise en place sur l'armoire pour fermer le vol.

Interface administrateur OpenFlyers

Activation et configuration de la gestion des armoires à clé

  • Admin > Structure > Structure > Paramétrage
  • Dans la section du formulaire Contrôle d'accès, sélectionner Activé(e) pour les champs Contrôle d'accès et Gestion armoire à clés.

Config_parametres_OF_controle_acces 1.jpg

  • Cliquer sur le bouton Enregistrer
  • Un nouveau champ s'affich
  • Sélectionner le Logiciel de contrôle de l'armoire à clés selon votre armoire à clés

Config_parametres_OF_controle_acces 4.jpg

Les Logiciels OpenKey et PyOpenKey sont des protocoles propriétaires d'OF, pour les configurer voir Interfaçage armoire à clés OF

Attribution des clés aux ressources/aéronefs

Dans le cas où c'est le logiciel OpenFlyers qui gère les clés.

  • Admin > Types de ressources > Actives

Liste_des_aéronefs.png

Pour chaque aéronef concerné, il suffit d'attribuer un numéro et un nom de clé dans les champs correspondants. La validation de la saisie se fait automatiquement en cliquant hors du champ de saisie.

Protocole de dialogue XML-RPC entre OpenFlyers et le logiciel de gestion de l'armoire à clé

Le dialogue avec le serveur XML-RPC d'OpenFlyers doit s'effectuer en HTTPS. Les commandes accessibles sont listées par un appel à ActionOnDemand.php https://openflyers.com/yourURL/actionOnDemand.php

Demande de libération d'une clé

Cas avec gestion des clés par OpenFlyers

  • Lorsque qu'une clé doit être libérée, le navigateur envoie un message au logiciel de contrôle de l'armoire à clé par le protocole HTTPS sous la forme suivante :

https://127.0.0.1:4080/?sessid=e5f01p2oqh2vb36arisr8k5j87&timeOut=10000&key=1&resource=2&person=12;action='releaseKey'

  • L'adresse IP (ici 127.0.0.1) et le port (ici 4080) sont fonction de la configuration de l'armoire à clé dans OpenFlyers.
  • sessid contient le numéro de session en cours
  • timeout correspond au temps d'attente pour la prise d'une clé en millisecondes
  • key contient le numéro de la clé concernée
  • resource contient le numéro de la ressource concernée
  • person contient le numéro de l'utilisateur qui fait la demande
  • action est un mot clé désignant l'objet de la commande
    • release_key: ordre de libérer la clé
    • open_door: ordre d'ouvrir la porte
    • init_tags: ordre de lire les tags des clés
  • Le logiciel de contrôle de l'armoire à clé doit alors envoyer une demande d'ordre au serveur OpenFlyers à l'adresse suivante https://openflyers.com/structure/ où il faut remplacer openflyers.com/structure par l'adresse de la plateforme OpenFlyers concernée, avec comme commande XML_RPC checkCommand ("e5f01p2oqh2vb36arisr8k5j87",int(key)).
  • Le serveur OpenFlyers vérifie alors l'action demandée :

Pour release_key, il est vérifié :

  1. Que la clé est au bon format et existe. Lorsque la clé est validée, on passe à l'étape suivante sinon on retourne 0
  2. Que l'utilisateur faisant la demande est bien celui qui est connecté. Lorsque c'est le cas, on passe à l'étape suivante sinon on retourne 0
  3. Ensuite si l'utilisateur qui a passé la demande :
    • A le droit Gestion des clés (administrateur) alors on libère la clé sans condition (cela permet de libérer la clé sans contrôle) et on retourne 1
    • N'a pas le droit Gestion des clés (pilote) alors on vérifie s'il existe un vol ouvert qui remplit la double condition :
      • Vol attribué à l'utilisateur
      • Aéronef du vol associé à la demande de libération de la clé
      • Lorsque la double condition est remplie, on retourne 1 sinon 0
  • Le serveur retourne ensuite la réponse :
    • 1 dans le cas d'autorisation de libération de clé
    • 0 dans le cas contraire

Exemple de script en Python d'utilisation de la commande checkCommand avec gestion des clés

<python># load library from twisted.web.xmlrpc import Proxy from twisted.internet import reactor, ssl

def printValue(value):

   print repr(value)
   reactor.stop()

def printError(error):

   print 'error', error
   reactor.stop()

  1. URL of the XML-RPC server

proxy = Proxy('https://yourURL.xx/actionOnDemand.php')

  1. init array to send

sessid = "" key_num = 1

  1. send to the XML-RPC server

proxy.callRemote('checkCommand', sessid, key_num).addCallbacks(printValue, printError) reactor.run()</python>

Ce test peut être complété (pour obtenir une réponse "1") en simulant une armoire à clé à l'aide d'un script PHP de la façon suivante :

  • Installer un serveur local (par exemple wampserver sous Windows) de façon à avoir le port 127.0.0.1 qui lui est attribué
  • Configurer la plateforme OpenFlyers de manière à gérer l'armoire à clé avec les éléments suivants :
    • IP du PC contenant le logiciel de contrôle : 127.0.0.1
    • Port du PC contenant le logiciel de contrôle : 80
  • Configurer la plateforme OpenFlyers de manière à gérer les clés
  • A la racine du répertoire www, mettre le script index.php suivant (on suppose que ce script est appelé par défaut lorsqu'on utilise l'URL https://127.0.0.1 ) :

<php><?php file_put_contents('test.txt', 'TEST', FILE_APPEND ); file_put_contents('test.txt', print_r($_REQUEST, true), FILE_APPEND ); ?></php>

  • Toujours à la racine du répertoire www, créer un fichier test.txt

Le script PHP écrira dans le fichier test.txt les variables transmises lors de la demande d'ouverture de l'armoire à clé :

TESTArray
(
    [sessid] => j2eo92215nbef09borb74jftm1
    [key] => 1
    [resource] => 1
    [person] => 1
)
  • Il suffit alors de recopier la valeur de sessid et de key dans le script python de ce début de paragraphe et de le tester : il devrait renvoyer 1.

Cas sans gestion des clés par OpenFlyers

  • Lorsque qu'une demande de vérification doit être réalisée, le navigateur envoie un message au logiciel de contrôle de l'armoire à clé par le protocole HTTPS sous la forme suivante :

https://127.0.0.1:4080/?sessid=e5f01p2oqh2vb36arisr8k5j87&resource=2&person=12

  • L'adresse IP (ici 127.0.0.1) et le port (ici 4080) sont fonction de la configuration de l'armoire à clé dans OpenFlyers.
  • sessid contient le numéro de session en cours
  • resource contient le numéro de la ressource concernée
  • person contient le numéro de l'utilisateur qui fait la demande
  • Le logiciel de contrôle de l'armoire à clé doit alors envoyer une demande d'ordre au serveur OpenFlyers à l'adresse suivante https://openflyers.com/structure/actionOnDemand.php où il faut remplacer openflyers.com/structure par l'adresse de la plateforme OpenFlyers concernée, avec comme commande XML_RPC checkCommand ("e5f01p2oqh2vb36arisr8k5j87").
  • Le serveur OpenFlyers vérifie alors :
  1. Que l'utilisateur faisant la demande est bien celui qui est connecté. Lorsque c'est le cas, on passe à l'étape suivante sinon on retourne 0
  2. On vérifie s'il existe un vol ouvert qui remplit la double condition :
    • Vol attribué à l'utilisateur
    • Aéronef du vol associé à la demande de libération de la clé
    • Lorsque la double condition est remplie, on retourne 1 sinon 0
  • Le serveur retourne ensuite la réponse :
    • 1 dans le cas d'autorisation
    • 0 dans le cas contraire

Exemple de script en Python d'utilisation de la commande checkCommand sans gestion des clés

<python># load library from twisted.web.xmlrpc import Proxy from twisted.internet import reactor, ssl

def printValue(value):

   print repr(value)
   reactor.stop()

def printError(error):

   print 'error', error
   reactor.stop()

  1. URL of the XML-RPC server

proxy = Proxy('https://yourURL.xx/actionOnDemand.php')

  1. init array to send

sessid = ""

  1. send to the XML-RPC server

proxy.callRemote('checkCommand', sessid).addCallbacks(printValue, printError) reactor.run()</python>

Ce test peut être complété (pour obtenir une réponse "1") en simulant une armoire à clé à l'aide d'un script PHP de la façon suivante :

  • Installer un serveur local (par exemple wampserver sous Windows) de façon à avoir le port 127.0.0.1 qui lui est attribué
  • Configurer la plateforme OpenFlyers de manière à gérer l'armoire à clé avec les éléments suivants :
    • IP du PC contenant le logiciel de contrôle : 127.0.0.1
    • Port du PC contenant le logiciel de contrôle : 80
  • Configurer la plateforme OpenFlyers de manière à ne pas gérer les clés
  • A la racine du répertoire www, mettre le script index.php suivant (on suppose que ce script est appelé par défaut lorsqu'on utilise l'URL https://127.0.0.1 ) :

<php><?php file_put_contents('test.txt', 'TEST', FILE_APPEND ); file_put_contents('test.txt', print_r($_REQUEST, true), FILE_APPEND ); ?></php>

  • Toujours à la racine du répertoire www, créer un fichier test.txt

Le script PHP écrira dans le fichier test.txt les variables transmises lors de la demande d'ouverture de l'armoire à clé :

TESTArray
(
    [sessid] => j2eo92215nbef09borb74jftm1
    [resource] => 1
    [person] => 1
)
  • Il suffit alors de recopier la valeur de sessid dans le script python de ce début de paragraphe et de le tester : il devrait renvoyer 1.

Modification de l'état d'une clé

Applicable dans le cas où le protocole PyOpenKeys2 gère les clés.

  • Le logiciel de contrôle de l'armoire à clés doit envoyer un ordre notify([1,0,1,1,1,1,0,0], "passphrase") avec comme paramètre un tableau chronologique des clés ayant pour valeur leur état

Applicable dans le cas où le protocole PyOpenKeys3 gère les clés.

  • Le logiciel de contrôle de l'armoire à clés doit envoyer un ordre notify2([[1,1],[2,0],[3,1],[4,1],[5,1],[6,1],[7,0],[8,0]], "passphrase") avec comme paramètre un tableau de tableau avec le numéro de la clé suivi de son état
    • 1 = interrupteur de présence de clé fermé = clé absente de l'armoire
    • 0 = interrupteur de présence de clé ouvert = clé présente dans l'armoire


Exemple de script en Python pour la commande notify

Nécessite les librairies Twisted et OpenSSL

<python># load library from twisted.web.xmlrpc import Proxy from twisted.internet import reactor, ssl import random

def printValue(value):

   print repr(value)
   reactor.stop()

def printError(error):

   print 'error', error
   reactor.stop()
  1. URL of the XML-RPC server

proxy = Proxy('https://yourURL.xx/actionOnDemand.php')

  1. init passphrase

passphrase = 'SDjklsdiuQSIPO23879ZERK2098ZL2908DFZLK'

  1. Initiate number of key

KEY_NUMBER = 16

  1. init array to send

state = random.randint(0,1)

if KEY_NUMBER > 8:

   # Test notify2
   status = [[d+1,0] for d in range(KEY_NUMBER)]
   for i in range(KEY_NUMBER):
       status[i] = [i+1,state]
       # Alternate 0 and 1 for test
       state = 0 if state == 1 else 1

else:

   # Test notify
   for i in range(KEY_NUMBER):
       status.append(state)
       # Alternate 0 and 1 for test
       state = 0 if state == 1 else 1
  1. send to the XML-RPC server

print "Status sequence : %s" % status if KEY_NUMBER<9:

   proxy.callRemote('notify', status, passphrase).addCallbacks(printValue, printError)

else:

   proxy.callRemote('notify2', status, passphrase).addCallbacks(printValue, printError)

reactor.run() </python> Nota : to test change the number of key : up to 8 the software use notify(), beyond it uses notify2()

Cela retournera 0 en cas d'anomalie ou si la passphase transmise n'est pas correcte, 1 si la table des clés a été correctement mise à jour.

Fermeture automatique d'un vol

Le logiciel de contrôle de l'armoire à clé doit envoyer un ordre closeFlight("passphrase", "id de ressource") avec comme paramètre un passphrase et l'id qui va entraîner la fermeture du vol effectué sur cette ressource si un vol avait été ouvert et que la "Fermeture automatique des vols au retour de la clé" soit activée. La commande retournera comme réponse une structure JSON pour déterminer si la fermeture du vol s'est bien réalisée ou non et qu'il n'y a pas eu d'erreur.

Réponse quand la vérification du passphrase est incorrecte, ce qui a entraîné la non-fermeture du vol : <javascript>{[

   ack : 0

]}</javascript>

Réponse quand la vérification du passphrase est correcte et que la demande de fermeture du vol s'est bien réalisée : <javascript>{[

   ack : 1

]}</javascript>

Réponse quand la vérification du passphrase est correcte et que la demande de fermeture du vol ne s'est pas bien réalisée suite à une erreur : <javascript>{[

   ack : 1,
   error : 'Message d\'erreur ...'

]}</javascript>

Script d'exemple pour closeFlight

<python># load library from twisted.web.xmlrpc import Proxy from twisted.internet import reactor, ssl import random

def printValue(value):

   print repr(value)
   reactor.stop()

def printError(error):

   print 'error', error
   reactor.stop()
  1. URL of the XML-RPC server

proxy = Proxy('https://yourURL.xx/actionOnDemand.php')

  1. Id of resource which needs a flight closing

resource_id = 1

  1. init passphrase

passphrase = 'SDjklsdiuQSIPO23879ZERK2098ZL2908DFZLK'

  1. send to the XML-RPC server

proxy.callRemote('closeFlight', resource_id, passphrase).addCallbacks(printValue, printError) reactor.run()</python>

Exemple de script en Python de logiciel de contrôle d'une armoire

<python>#!/usr/bin/python import xmlrpclib, time, dummy_proto, hashlib from twisted.internet import reactor, task, threads, ssl from twisted.application import internet, service from twisted.internet.protocol import Protocol, ClientCreator, ReconnectingClientFactory from twisted.web import resource, server

  1. Port from which the OF client contact OpenKeys service

SERVICE_PORT=4080

  1. IP address of the OpenKeys service

SERVICE_HOST="192.168.0.200"

  1. IP address of the key cabinet

KEYS_ADDR='192.168.0.201'

  1. Port from which OpenKeys service contacts the key cabinet

KEYS_PORT=6002

  1. Time to release the key

KEY_RELEASE_DURATION=15

  1. sha224 passwords

PASSWORDS=('847bed9bc354e7e47bc5350a3b3aaf6124f5748224a3c7ad79586c3c')

  1. init passphrase

passphrase = 'SDjklsdiuQSIPO23879ZERK2098ZL2908DFZLK'

OF_XMLRPC_URL="https://openflyers.com/structure/actionOnDemand.php"

DEBUG=False

class dummyProtocol(Protocol): def __init__(self, rpc_server): self.rpc_server=rpc_server self.lc = None

def connectionMade(self): if not self.lc: # update status every 10 minutes self.lc = task.LoopingCall(self.updateStatus) self.lc.start(600)

def dataReceived(self, data): msg=dummy_proto.dummy_message.newFromData(data) if DEBUG: msg.display() try: if type(msg)==dummyproto.dummy_ONOFF_Control_Response: response = self.rpc_server.notify(msg.getKeysStatus(),passphrase) except Exception, err: if DEBUG: print "error: ", err pass # ignore

def updateStatus(self): msg = dummy_proto.dummy_State_Request() self.transport.write(msg.build_message())

def send(self, dummy_data): self.transport.write(dummy_data.build_message())

class dummyClientFactory(ReconnectingClientFactory): def __init__(self, rpc_server): self.rpc_server = rpc_server

def buildProtocol(self, addr): self.resetDelay() self.protocol = dummyProtocol(self.rpc_server) return self.protocol

def clientConnectionLost(self, connector, reason): ReconnectingClientFactory.clientConnectionLost(self, connector, reason) connector.connect()

def clientConnectionFailed(self, connector, reason): if DEBUG: print 'Connection failed. Reason:', reason ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)

# blocking method ! must be run in a new thread def release_key(self, key_num, timeOur): m = dummy_proto.dummy_ONOFF_Control() m.setON(key_num) self.protocol.send(m) time.sleep(timeOut) m.setOFF(key_num) self.protocol.send(m) return key_num

class WebResource(resource.Resource): def __init__(self, rpc_server, dummy_client_factory): self.rpc_server = rpc_server self.dummy_client_factory = dummy_client_factory resource.Resource.__init__(self) self.keys_webcontrol_state = [0,0,0,0,0,0,0,0,0,0]

def getChild(self, name, request): return self

def render(self, request): reponse = 0 # NOK par defaut key_num = 0 try: sessid = request.args.get('sessid', [""])[0] password = request.args.get('password', [""])[0] key_num = int(request.args.get('key', ["0"])[0]) response = 0 if password:

                               if hashlib.sha224(password).hexdigest() in PASSWORDS:
                                       timeOut   = KEY_RELEASE_DURATION
                                       response_XMLRPC = 1
                       else:
                               timeOut   = int(request.args.get('timeout', ["0"])[0])
                               response = self.rpc_server.checkCommand(sessid, key_num)

except Exception, err: if DEBUG: print "error: ", err return "NOK:bad request"

if response == 1: # Don't try to release a key that is being released if self.keys_webcontrol_state[key_num-1]: return "OK:already released" self.keys_webcontrol_state[key_num-1] = 1 d = threads.deferToThread(self.dummy_client_factory.release_key, key_num, timeOut) d.addCallback(self.unset_webcontrol_state) return "OK:releasing key..." else: return "NOK:permission refused"

def unset_webcontrol_state(self, key_num): self.keys_webcontrol_state[key_num-1] = 0

class OpenKeysService(service.Service): def __init__(self): rpc_server=xmlrpclib.Server(OF_XMLRPC_URL); self.dummy_client_factory = dummyClientFactory(rpc_server) self.web_resource = WebResource(rpc_server, self.dummy_client_factory)

def getdummyClientFactory(self): return self.dummy_client_factory

def getWebResource(self): return self.web_resource

application = service.Application('openkeys') f = OpenKeysService() serviceCollection = service.IServiceCollection(application) internet.TCPClient(KEYS_ADDR, KEYS_PORT, f.getdummyClientFactory() ).setServiceParent(serviceCollection) internet.TCPServer(SERVICE_PORT, server.Site(f.getWebResource()) ).setServiceParent(serviceCollection)</python>

Maquette de script actionOnDemand.php côté serveur recevant les appels du logiciel de contrôle de l'armoire

Ce script nécessite la bibliothèque PEAR XML_RPC2.

Pour les tests, il suffit de modifier la valeur de la variable $weDontWant.

<php><?php include 'XML/RPC2/Server.php';

class OpenKeysGateway {

   /**
    * Update the status of the keys
    *
    * @param array $status Status of keys
    * @return integer 1 if ok, 0 else
    */
   public static function notify($status) {
       $logmsg = "";
       foreach ($status as $key_num_from_zero => $key_pres) {
           if (!is_numeric($key_pres) || intval($key_pres)!=$key_pres || $key_pres < 0 || $key_pres > 1) continue;
           if (!is_numeric($key_num_from_zero) || intval($key_num_from_zero)!=$key_num_from_zero 
               || $key_num_from_zero < 0 || $key_num_from_zero > 9) continue;
           $logmsg .= "".($key_num_from_zero+1).":".$key_pres.",";
       }
       file_put_contents('test.txt', "key notify :".$logmsg, FILE_APPEND );
       return 1;
   }
   /**
    * Check if user is able to release the key 'key_num'
    *
    * @param string $sessid PHPSESSID of a connected user
    * @param integer $key_num number of the key to release
    * @return integer 0:NOK, 1:OK
    */
   public static function checkCommand($sessid, $key_num) {
       /* sanitize input */
       if (!is_numeric($key_num) || intval($key_num)!=$key_num || $key_num < 1 || $key_num > 10) {
           return 0;
       }
       $weDontWant = 1;
       if ($weDontWant) {
           file_put_contents('test.txt', "$key_num has no associated airborne aircraft", FILE_APPEND );
           return 0;
       }
       else {
           file_put_contents('test.txt', "granted key: ".$key_num.":permission granted", FILE_APPEND );
           return 1;
       }
   }

}

$options = array(

   'autoDocument' => true,

);

// dirty hack to get things work ! $GLOBALS['HTTP_RAW_POST_DATA'] = file_get_contents('php://input');

$server = XML_RPC2_Server::create('OpenKeysGateway', $options); $server->handleCall();

?></php>