Interfaçage OpenFlyers et armoire à clés and Utilisation des réservations internes sur l'appli mobile: Difference between pages

From Documentation de la solution web de gestion OpenFlyers
(Difference between pages)
Jump to navigation Jump to search
 
 
Line 1: Line 1:
[[Image:planning4-overview.png|right|thumb|200px|Planning4 overview]]
__TOC__
__TOC__
=Présentation=
=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 [[Contrôle des accès|documentation sur le contrôle d'accès]].
L'objet de cette page est de présenter l'utilisation du planning de réservation de l'[[Présentation-d'OpenFlyers-4#Interface-dynamique|interface dynamique]] de la [[Accueil|version 4 d'OpenFlyers]]. D'autres pages de la documentation traitent de l'aspect du planning de réservation et du [[panier de réservation]].
 
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 :
 
[[File:Menu-contextuel-ouverture-de-vol.png]]
 
 
Il se retrouve sur le formulaire de saisie du vol en mode Départ en vol:
 
[[File: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é :
 
[[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é :
 
[[File:Alertes-non-bloquantes-en-ouverture-vol.png]]
 
*Aucune alerte ne s'affiche, l'utilisateur se retrouve alors directement sur la page lui indiquant :
 
[[File: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é==
Les protocoles OpenKey et PyOpenKey sont propriétaires d'OF, pour les configurer voir
[[Installation-armoire-à-clés#Configuration-OpenFlyers]]
 
==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'''
[[File: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 [[#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
:*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é :
#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 :
#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
#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()
# 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 :
==Différences entre l'[[Présentation-d'OpenFlyers-4#Interface-dynamique|interface dynamique]] et l'[[Présentation-d'OpenFlyers-4#Appli-OpenFlyers|application mobile]]==
*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é==
=Tutoriel vidéo=
''Applicable dans le cas où le protocole PyOpenKeys2 gère les clés.''
<youtube>tzM6hyOIpnc</youtube>
*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===
=Utilisation générique=
Nécessite les librairies Twisted et OpenSSL


<python># load library
==Afficher les informations d'une activité==
from twisted.web.xmlrpc import Proxy
Après avoir activé l'affichage des activités dans le planning, il est possible de voir les informations des activités affichées.
from twisted.internet import reactor, ssl
import random


def printValue(value):
Il suffit de cliquer sur une activité du planning afin d'ouvrir la page de paramètre de l'activité.
    print repr(value)
    reactor.stop()


def printError(error):
Le type d'activité, la ressource et les utilisateurs sont alors visibles.
    print 'error', error
    reactor.stop()


# URL of the XML-RPC server
==Changer de jour==
proxy = Proxy('https://yourURL.xx/actionOnDemand.php')


# init passphrase
Sur l'[[Présentation-d'OpenFlyers-4#Interface-dynamique|interface dynamique]] :
passphrase = 'SDjklsdiuQSIPO23879ZERK2098ZL2908DFZLK'
*Depuis le [[Aspect-du-planning-de-réservation#Modes-d'affichage-du-planning|planning journalier]] :
**Cliquer sur les '''flèches simples''' pour avancer ou reculer d'un jour.
**Cliquer sur les '''doubles flèches''' pour avancer ou reculer d'une semaine.
*Depuis le [[Aspect-du-planning-de-réservation#Modes-d'affichage-du-planning|planning mensuel]] :
**Cliquer sur les '''flèches simples''' pour avancer ou reculer d'un mois.
**Cliquer sur les '''doubles flèches''' pour avancer ou reculer d'un an.


# Initiate number of key
Sur l'[[Présentation-d'OpenFlyers-4#Appli-OpenFlyers|application mobile]] :
KEY_NUMBER = 16
*Cliquer sur les '''fleches''' pour avancer ou reculer d'un jour.
*Cliquer sur le mois et l'année dans la barre supérieure pour afficher un calendrier, qui permettra de choisir une date.


# init array to send
==Créer une réservation==
state = random.randint(0,1)


if KEY_NUMBER > 8:
=== Depuis le planning ===
    # Test notify2
Sur l'[[Présentation-d'OpenFlyers-4#Interface-dynamique|interface dynamique]] :
    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


# send to the XML-RPC server
*Effectuer un '''clic long''' sur un créneau horaire d'une ligne du planning.
print "Status sequence : %s" % status
*La réservation se matérialise sur la ligne concernée :
if KEY_NUMBER<9:
**Elle est alors [[#Réservation_incomplète|incomplète]].
    proxy.callRemote('notify', status, passphrase).addCallbacks(printValue, printError)
**Elle s'affiche en [[#Mode_édition|mode édition]].
else:
*La [[#Page_paramètres|page paramètres]] de l'onglet édition de la palette d'outils s'ouvre. On y définit les paramètres de la réservation : l''''activité''' ainsi que les '''ressources''' mobilisées.
    proxy.callRemote('notify2', status, passphrase).addCallbacks(printValue, printError)
*Pour compléter un paramètre, cliquer sur le titre de celui-là. La liste des '''choix''' disponibles s'affiche alors dans la partie basse de la palette d'outils.
reactor.run()
[[File:Planning4-8.png]]
</python>
*Cliquer sur le choix souhaité.
''Nota : to test change the number of key : up to 8 the software use '''notify()''', beyond it uses '''notify2()'''
*Ce choix s'affiche désormais sous le nom du paramètre, dans la partie haute de la palette d'outils.
*Pour le supprimer, cliquer sur la '''croix''' à côté du nom.
*Lorsque tous les paramètres sont définis, se rendre sur la [[#Page_informations_complémentaires|page informations complémentaires]] de la palette d'outils, afin de voir si certains champs sont incomplets.
*Lorsque toutes les informations obligatoires sont saisies, la réservation est '''complète'''.


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.
Sur l'[[Présentation-d'OpenFlyers-4#Appli-OpenFlyers|application mobile]] :


==Fermeture automatique d'un vol==
*Effectuer un '''clic long''' sur un créneau horaire d'une ligne du planning.
*La réservation se matérialise sur la ligne concernée :
**Elle est alors [[#Réservation_incomplète|incomplète]].
*On ouvre ensuite le [[#Formulaire-de-réservation|formulaire de réservation]].


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
=== Depuis le bouton + (Mobile)===
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 :
* Effectuer un '''appui''' sur le [[Aspect-du-planning-de-réservation#Bouton-+-(Mobile)|bouton +]].
<javascript>{[
* L'application recherche le premier créneau horaire libre en prenant en compte l'heure actuelle : la réservation est créée sur la ligne de la première '''ressource''' disponible.
    ack : 0
** Si aucun créneau n'est disponible sur la journée, l'application demandera si elle doit en chercher un autre à une date ultérieure.
]}</javascript>
** Le planning se rafraichit pour correspondre à la date trouvée.
** Le formulaire de reservation s'ouvre pour permettre de personnaliser la réservation.


Réponse quand la vérification du passphrase est correcte et que la demande de fermeture du vol s'est bien réalisée :
==Créer automatiquement un utilisateur en créant une réservation==
<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 :
Cette fonctionnalité est disponible lorsque l'utilisateur connecté dispose du droit [[Gestion-des-profils#Accès-visiteur|Accès visiteur]].
<javascript>{[
    ack : 1,
    error : 'Message d\'erreur ...'
]}</javascript>


===Script d'exemple pour closeFlight===
La création automatique se fait au moment d'une [[#Créer-une-réservation|création d'une réservation]] où :
<python># load library
* On récupère les données de la réservation
from twisted.web.xmlrpc import Proxy
* On créé l'utilisateur en lui générant un identifiant et un mot de passe puis en lui remplissant ses données personnelles depuis celles de la réservation
from twisted.internet import reactor, ssl
* On envoie un [[Configuration#Email-type-de-création-d'utilisateur|email de création d'utilisateur]]
import random


def printValue(value):
Après, le planning va se reconnecter automatique sur cet nouvelle utilisateur et poursuivre normalement la [[#Créer-une-réservation|création de réservation]].
    print repr(value)
    reactor.stop()


def printError(error):
==Édition d'une réservation==
    print 'error', error
Une réservation déjà [[#Créer_une_réservation|créée]] sur le planning est '''activable'''. Lorsqu'une réservation est activée, on peut la [[#Redimensionnement|redimensionner]] ou la [[#Déplacement|déplacer]].  
    reactor.stop()


# URL of the XML-RPC server
* Sur '''l'interface dynamique'''
proxy = Proxy('https://yourURL.xx/actionOnDemand.php')
** un '''clic''' active la réservation.
* Sur '''l'application mobile'''
** un '''appui''' ouvre le [[#Formulaire-de-r%C3%A9servation-(Mobile)|formulaire de réservation]].
** un '''appui long''' active la réservation.


# Id of resource which needs a flight closing
===Options de réservation===
resource_id = 1
====Composition====
sur '''l'interface dynamique''' :


# init passphrase
Lorsqu'on clique sur une réservation, on fait apparaître une [[Boîtes de dialogue#Info-bulle|info-bulle]] contenant les boutons suivants :
passphrase = 'SDjklsdiuQSIPO23879ZERK2098ZL2908DFZLK'
*Accéder aux '''informations complémentaires''' : [[File:Planning4-picto-tooltip-detail.png]].
*'''Saisir l'activité''' : [[File:Planning4-picto-tooltip-activity.png]].
*'''Supprimer''' la réservation : [[File:Planning4-picto-tooltip-delete.png]].


# send to the XML-RPC server
====Emplacement====
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==
Sur '''l'interface dynamique''' :
<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


# Port from which the OF client contact OpenKeys service
*Sur une réservation de grande taille :
SERVICE_PORT=4080
[[File:Planning4-9.png]]
# IP address of the OpenKeys service
SERVICE_HOST="192.168.0.200"


# IP address of the key cabinet
*Sur une réservation de petite taille :
KEYS_ADDR='192.168.0.201'
[[File:Planning4-10.png]]
# Port from which OpenKeys service contacts the key cabinet
KEYS_PORT=6002
#Time to release the key
KEY_RELEASE_DURATION=15


# sha224 passwords
===Redimensionnement===
PASSWORDS=('847bed9bc354e7e47bc5350a3b3aaf6124f5748224a3c7ad79586c3c')
Lorsqu'une réservation est en '''mode édition''', ses extrêmités gauche et droite s'affichent d'une '''couleur plus foncée'''. En effectuant un '''glisser-déposer''' sur ces zones, on augmente ou on réduit la durée de la réservation.


# init passphrase
===Déplacement===
passphrase = 'SDjklsdiuQSIPO23879ZERK2098ZL2908DFZLK'
Une réservation en mode édition peut être déplacée. Pour cela, il faut effectuer un '''glisser-déposer''' n'importe où sur la réservation, sauf dans les zones de redimensionnement. Durant le déplacement, un fantôme indique si l'emplacement de destination est disponible (gris) ou non (rouge).


OF_XMLRPC_URL="https://openflyers.com/structure/actionOnDemand.php"
*Emplacement de destination '''disponible''' :
[[File:Planning4-12.png]]


DEBUG=False
*Emplacement de destination '''indisponible''' :
[[File:Planning4-11.png]]


class dummyProtocol(Protocol):
==Formulaire de réservation (Mobile)==
def __init__(self, rpc_server):
self.rpc_server=rpc_server
self.lc = None


def connectionMade(self):
Le formulaire de reservation permet de visualiser et d'éditer les informations d'une réservation du planning.
if not self.lc:
# update status every 10 minutes
self.lc = task.LoopingCall(self.updateStatus)
self.lc.start(600)


def dataReceived(self, data):
Il s'ouvre d'un '''appui court''' sur une réservation [[#Créer_une-réservation|créée]].
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):
Il possède deux modes d'affichage :
msg = dummy_proto.dummy_State_Request()
* [[#Mode-lecture|Lecture]] : visualisation des éléments et des paramètres.
self.transport.write(msg.build_message())
* [[#Mode-édition|Edition]] : mise à jour des champs.
def send(self, dummy_data):
self.transport.write(dummy_data.build_message())


class dummyClientFactory(ReconnectingClientFactory):
Il possède des champs obligatoires :
def __init__(self, rpc_server):
* '''Activités''' : la/les type(s) d'activité(s) de la réservation.
self.rpc_server = rpc_server
* '''Ressource''' : la ressource mobilisé.
* '''Personnes''' : la/les personne(s) mobilisé(s).
* '''Date de début'''
* '''Date de fin'''
et des champs additionnels qui seront dépendants du [[Bien-débuter-avec-OpenFlyers#Paramétrer-la-plateforme|paramétrage de la plateforme]].


def buildProtocol(self, addr):
Les minutes dans les dates de début et de fin seront arrondis en fonction de [[Configuration#Unité-de-temps|l'unité de temps]] choisi sur la plateforme.
self.resetDelay()
self.protocol = dummyProtocol(self.rpc_server)
return self.protocol


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


def clientConnectionFailed(self, connector, reason):
Le mode lecture permet de visualiser les informations déjà rempli de la réservation.
if DEBUG: print 'Connection failed. Reason:', reason
Les paramètres n'ayant pas encore de valeur ne s'afficheront pas dans ce mode.
ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)


# blocking method ! must be run in a new thread
la barre supérieure possède plusieurs boutons :
def release_key(self, key_num, timeOur):
* Fermer le formulaire et revenir au planning.
m = dummy_proto.dummy_ONOFF_Control()
* Ouvrir en [[#Mode-édition|mode édition]].
m.setON(key_num)
* Supprimer la réservation.
self.protocol.send(m)
time.sleep(timeOut)
m.setOFF(key_num)
self.protocol.send(m)
return key_num


class WebResource(resource.Resource):
Le formulaire s'ouvre par défaut dans ce mode lorsqu'on appuie sur une réservation du planning.
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):
===Mode édition===
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):
Le mode édition permet d'éditer les paramètres de la réservation.
self.keys_webcontrol_state[key_num-1] = 0
Tout les champs disponibles sont affichés.


class OpenKeysService(service.Service):
la barre superieure ne possède que deux boutons :
def __init__(self):
* Revenir au [[#Mode-lecture|mode lecture]].
rpc_server=xmlrpclib.Server(OF_XMLRPC_URL);
* Supprimer la réservation.
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):
Le formulaire s'ouvre dans ce mode lorsqu'on crée une réservation depuis le [[#Bouton-+-(Mobile)|bouton +]].
return self.web_resource


application = service.Application('openkeys')
==Réservation incomplète==
f = OpenKeysService()
*Une réservation est '''incomplète''' lorsque le créneau horaire est défini mais qu'il lui manque des paramètres requis.  
serviceCollection = service.IServiceCollection(application)
*Apparence :
internet.TCPClient(KEYS_ADDR, KEYS_PORT, f.getdummyClientFactory()
**Contour en '''pointillés'''.  
  ).setServiceParent(serviceCollection)
**Lorsque cette réservation n'est pas en [[#Mode_édition_d'une_réservation|mode édition]], elle est '''transparente'''.
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==
===Manque l'activité et les ressources===
Ce script nécessite la bibliothèque PEAR [http://pear.php.net/package/XML_RPC2 XML_RPC2].
*La réservation apparaît avec un '''fond grisé''' :
[[File:Planning4-17-resa-incomp-1.png]]


Pour les tests, il suffit de modifier la valeur de la variable $weDontWant.
*En [[#Mode_édition_d'une_réservation|mode édition]] :
[[File:Planning4-17-resa-incomp-3.png]]


<php><?php
===Manque des ressources===
include 'XML/RPC2/Server.php';
*La réservation apparaît avec la '''couleur de l'activité''' :
[[File:Planning4-17-resa-incomp-2.png]]


class OpenKeysGateway {
*En [[#Mode_édition_d'une_réservation|mode édition]] :
    /**
[[File:Planning4-17-resa-incomp-4.png]]
    * 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;
    }


    /**
==Lister les réservations==
    * Check if user is able to release the key 'key_num'
*La liste des réservations est accessible depuis: '''Planning > Planning > Réservations'''
    *
    * @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;
*La liste des réservations peut être affichée soit sur une période soit sur une journée selon la position de l'interrupteur :
**'''Afficher sur une période''' :
***'''Date de début''' : un calendrier permet de choisir la date du début de l'intervalle de temps des ensembles des réservations à afficher
***'''Période''' : une liste déroulante à auto-complétion permet de choisir la période de l'intervalle de temps à partir de la date de début sélectionnée des ensembles des réservations à afficher (1, 2, ..6 jours, 1 semaine, 2 semaines, ... 3 semaines, 1 mois, 2 mois, ..., 11 mois, 1 an, 2 ans...10 ans)
***'''NB''' : la liste des réservations affichées pour une période inclut toutes les réservations dont la date de fin est comprise entre minuit (00:00:00) du jour de début et 23h59m59s du jour de fin (date de fin étant égale à la date de début plus la durée de la période).


        if ($weDontWant) {
**'''Afficher sur une journée''' :
            file_put_contents('test.txt', "$key_num has no associated airborne aircraft", FILE_APPEND );
***'''Journée à afficher''' : un calendrier permet de choisir la date du jour de l'ensemble des réservations à afficher
            return 0;
***'''NB''' : la liste des réservations affichées pour une journée représente toutes les réservations dont la date de fin se situe entre minuit (00:00:00) et 23h59m59s du jour sélectionné.
        }
*'''Utilisateur''': une liste déroulante à auto-complétion permet de choisir l'utilisateur dont les réservations doivent être affichées, quelque soit la place occupée dans la réservation. Ce choix n'est affiché que si l'utilisateur connecté dispose de droits pour gérer les réservations des autres utilisateurs.
        else {
            file_put_contents('test.txt', "granted key: ".$key_num.":permission granted", FILE_APPEND );
            return 1;
        }
    }
}


$options = array(
*La liste des réservations synthétise les informations les plus importantes pour l'ensemble des réservations dans un intervalle de temps :
    'autoDocument' => true,
**'''Créneaux''' : contient la date de début et la date de fin
);
**'''Place gauche''' : contient le nom complète du pilote
**'''Ressource''' : contient le nom de la ressource
**'''Place droite''' : contient le nom complète d'instructeur
**'''Actions''' : L'utilisateur peut effectuer sur une réservation les actions suivantes:
***'''Suivi''' : L'utilisateur peut visualiser l'historique d'une réservation.
***'''Modifier''' : L'utilisateur peut modifier une réservation.
***'''Supprimer''' : L'utilisateur peut supprimer une réservation.


// dirty hack to get things work !
=Utilisations métiers=
$GLOBALS['HTTP_RAW_POST_DATA'] = file_get_contents('php://input');
==Indisponibilité==
*Une ressource est '''indisponible''' lorsqu'elle est immobilisée. Elle n'est pas utilisable pour la plupart des activités.
*Sur les [[#Créneaux_horaires|créneaux horaires]] des lignes du planning, cela se matérialise par des '''striures horizontales grises'''.


$server = XML_RPC2_Server::create('OpenKeysGateway', $options);
==Préparer un vol==
$server->handleCall();
OpenFlyers est couplé avec [[Airmate]] pour aider les pilotes à préparer leur vol. Ainsi, il est possible depuis l'interface dynamique de créer une préparation de vol à partir d'une réservation :
*Effectuer un clic simple sur la réservation concernée pour faire apparaître l’info-bulle
*Cliquer sur le bouton symbolisant un trajet.


?></php>
=FAQ=
==Disparition de réservation==
Si une réservation n'apparait plus sur le planning, il faut se poser les questions suivantes :
*Est-ce que cette réservation a réellement été faite ? En effet, il peut arriver qu'une personne pense avoir fait une réservation et qu'elle ait été interrompue dans son action et que finalement elle n'ait pas effectuée l'intégralité du processus. C'est notamment le cas lorsqu'une alerte avec une demande de confirmation s'affiche. L'email de confirmation de réservation est une preuve qui permet de confirmer que la réservation a bien été faite.
*Est-ce que la réservation a été faite sur la bonne plateforme OpenFlyers ? Il peut arriver qu'un utilisateur dispose d'accès sur plusieurs plateformes OpenFlyers et qu'il confonde les plateformes. De la même façon, il peut avoir effectué sa réservation sur une recopie de test de la plateforme de production. Là encore, pour le lever le doute, l'email de confirmation de réservation indique le nom de la plateforme utilisée pour la réservation.
*Un gestionnaire n'est-il pas intervenu pour supprimer/modifier la réservation ? Pour le savoir, il faut suivre la procédure qui permet de [[Logs#Retrouver-qui-a-supprimé-une-réservation|retrouver qui a supprimé une réservation]] à partir des logs.
*Les emails de confirmation/modification/suppression de réservations indiquent à chaque fois le nom de la personne qui intervient pour effectuer l'action. Cela permet, en interrogeant les personnes ayant agit, de recouper les informations et de comprendre la cause de la disparition d'une réservation.

Revision as of 10:28, 5 January 2025

Planning4 overview

Présentation

L'objet de cette page est de présenter l'utilisation du planning de réservation de l'interface dynamique de la version 4 d'OpenFlyers. D'autres pages de la documentation traitent de l'aspect du planning de réservation et du panier de réservation.

Différences entre l'interface dynamique et l'application mobile

Tutoriel vidéo

Utilisation générique

Afficher les informations d'une activité

Après avoir activé l'affichage des activités dans le planning, il est possible de voir les informations des activités affichées.

Il suffit de cliquer sur une activité du planning afin d'ouvrir la page de paramètre de l'activité.

Le type d'activité, la ressource et les utilisateurs sont alors visibles.

Changer de jour

Sur l'interface dynamique :

  • Depuis le planning journalier :
    • Cliquer sur les flèches simples pour avancer ou reculer d'un jour.
    • Cliquer sur les doubles flèches pour avancer ou reculer d'une semaine.
  • Depuis le planning mensuel :
    • Cliquer sur les flèches simples pour avancer ou reculer d'un mois.
    • Cliquer sur les doubles flèches pour avancer ou reculer d'un an.

Sur l'application mobile :

  • Cliquer sur les fleches pour avancer ou reculer d'un jour.
  • Cliquer sur le mois et l'année dans la barre supérieure pour afficher un calendrier, qui permettra de choisir une date.

Créer une réservation

Depuis le planning

Sur l'interface dynamique :

  • Effectuer un clic long sur un créneau horaire d'une ligne du planning.
  • La réservation se matérialise sur la ligne concernée :
  • La page paramètres de l'onglet édition de la palette d'outils s'ouvre. On y définit les paramètres de la réservation : l'activité ainsi que les ressources mobilisées.
  • Pour compléter un paramètre, cliquer sur le titre de celui-là. La liste des choix disponibles s'affiche alors dans la partie basse de la palette d'outils.

Planning4 8.png

  • Cliquer sur le choix souhaité.
  • Ce choix s'affiche désormais sous le nom du paramètre, dans la partie haute de la palette d'outils.
  • Pour le supprimer, cliquer sur la croix à côté du nom.
  • Lorsque tous les paramètres sont définis, se rendre sur la page informations complémentaires de la palette d'outils, afin de voir si certains champs sont incomplets.
  • Lorsque toutes les informations obligatoires sont saisies, la réservation est complète.

Sur l'application mobile :

  • Effectuer un clic long sur un créneau horaire d'une ligne du planning.
  • La réservation se matérialise sur la ligne concernée :
  • On ouvre ensuite le formulaire de réservation.

Depuis le bouton + (Mobile)

  • Effectuer un appui sur le bouton +.
  • L'application recherche le premier créneau horaire libre en prenant en compte l'heure actuelle : la réservation est créée sur la ligne de la première ressource disponible.
    • Si aucun créneau n'est disponible sur la journée, l'application demandera si elle doit en chercher un autre à une date ultérieure.
    • Le planning se rafraichit pour correspondre à la date trouvée.
    • Le formulaire de reservation s'ouvre pour permettre de personnaliser la réservation.

Créer automatiquement un utilisateur en créant une réservation

Cette fonctionnalité est disponible lorsque l'utilisateur connecté dispose du droit Accès visiteur.

La création automatique se fait au moment d'une création d'une réservation où :

  • On récupère les données de la réservation
  • On créé l'utilisateur en lui générant un identifiant et un mot de passe puis en lui remplissant ses données personnelles depuis celles de la réservation
  • On envoie un email de création d'utilisateur

Après, le planning va se reconnecter automatique sur cet nouvelle utilisateur et poursuivre normalement la création de réservation.

Édition d'une réservation

Une réservation déjà créée sur le planning est activable. Lorsqu'une réservation est activée, on peut la redimensionner ou la déplacer.

  • Sur l'interface dynamique
    • un clic active la réservation.
  • Sur l'application mobile

Options de réservation

Composition

sur l'interface dynamique :

Lorsqu'on clique sur une réservation, on fait apparaître une info-bulle contenant les boutons suivants :

  • Accéder aux informations complémentaires : Planning4 picto tooltip detail.png.
  • Saisir l'activité : Planning4 picto tooltip activity.png.
  • Supprimer la réservation : Planning4 picto tooltip delete.png.

Emplacement

Sur l'interface dynamique :

  • Sur une réservation de grande taille :

Planning4 9.png

  • Sur une réservation de petite taille :

Planning4 10.png

Redimensionnement

Lorsqu'une réservation est en mode édition, ses extrêmités gauche et droite s'affichent d'une couleur plus foncée. En effectuant un glisser-déposer sur ces zones, on augmente ou on réduit la durée de la réservation.

Déplacement

Une réservation en mode édition peut être déplacée. Pour cela, il faut effectuer un glisser-déposer n'importe où sur la réservation, sauf dans les zones de redimensionnement. Durant le déplacement, un fantôme indique si l'emplacement de destination est disponible (gris) ou non (rouge).

  • Emplacement de destination disponible :

Planning4 12.png

  • Emplacement de destination indisponible :

Planning4 11.png

Formulaire de réservation (Mobile)

Le formulaire de reservation permet de visualiser et d'éditer les informations d'une réservation du planning.

Il s'ouvre d'un appui court sur une réservation créée.

Il possède deux modes d'affichage :

  • Lecture : visualisation des éléments et des paramètres.
  • Edition : mise à jour des champs.

Il possède des champs obligatoires :

  • Activités : la/les type(s) d'activité(s) de la réservation.
  • Ressource : la ressource mobilisé.
  • Personnes : la/les personne(s) mobilisé(s).
  • Date de début
  • Date de fin

et des champs additionnels qui seront dépendants du paramétrage de la plateforme.

Les minutes dans les dates de début et de fin seront arrondis en fonction de l'unité de temps choisi sur la plateforme.

Mode lecture

Le mode lecture permet de visualiser les informations déjà rempli de la réservation. Les paramètres n'ayant pas encore de valeur ne s'afficheront pas dans ce mode.

la barre supérieure possède plusieurs boutons :

  • Fermer le formulaire et revenir au planning.
  • Ouvrir en mode édition.
  • Supprimer la réservation.

Le formulaire s'ouvre par défaut dans ce mode lorsqu'on appuie sur une réservation du planning.

Mode édition

Le mode édition permet d'éditer les paramètres de la réservation. Tout les champs disponibles sont affichés.

la barre superieure ne possède que deux boutons :

Le formulaire s'ouvre dans ce mode lorsqu'on crée une réservation depuis le bouton +.

Réservation incomplète

  • Une réservation est incomplète lorsque le créneau horaire est défini mais qu'il lui manque des paramètres requis.
  • Apparence :
    • Contour en pointillés.
    • Lorsque cette réservation n'est pas en mode édition, elle est transparente.

Manque l'activité et les ressources

  • La réservation apparaît avec un fond grisé :

Planning4 17 resa incomp 1.png

Planning4 17 resa incomp 3.png

Manque des ressources

  • La réservation apparaît avec la couleur de l'activité :

Planning4 17 resa incomp 2.png

Planning4 17 resa incomp 4.png

Lister les réservations

  • La liste des réservations est accessible depuis: Planning > Planning > Réservations
  • La liste des réservations peut être affichée soit sur une période soit sur une journée selon la position de l'interrupteur :
    • Afficher sur une période :
      • Date de début : un calendrier permet de choisir la date du début de l'intervalle de temps des ensembles des réservations à afficher
      • Période : une liste déroulante à auto-complétion permet de choisir la période de l'intervalle de temps à partir de la date de début sélectionnée des ensembles des réservations à afficher (1, 2, ..6 jours, 1 semaine, 2 semaines, ... 3 semaines, 1 mois, 2 mois, ..., 11 mois, 1 an, 2 ans...10 ans)
      • NB : la liste des réservations affichées pour une période inclut toutes les réservations dont la date de fin est comprise entre minuit (00:00:00) du jour de début et 23h59m59s du jour de fin (date de fin étant égale à la date de début plus la durée de la période).
    • Afficher sur une journée :
      • Journée à afficher : un calendrier permet de choisir la date du jour de l'ensemble des réservations à afficher
      • NB : la liste des réservations affichées pour une journée représente toutes les réservations dont la date de fin se situe entre minuit (00:00:00) et 23h59m59s du jour sélectionné.
  • Utilisateur: une liste déroulante à auto-complétion permet de choisir l'utilisateur dont les réservations doivent être affichées, quelque soit la place occupée dans la réservation. Ce choix n'est affiché que si l'utilisateur connecté dispose de droits pour gérer les réservations des autres utilisateurs.
  • La liste des réservations synthétise les informations les plus importantes pour l'ensemble des réservations dans un intervalle de temps :
    • Créneaux : contient la date de début et la date de fin
    • Place gauche : contient le nom complète du pilote
    • Ressource : contient le nom de la ressource
    • Place droite : contient le nom complète d'instructeur
    • Actions : L'utilisateur peut effectuer sur une réservation les actions suivantes:
      • Suivi : L'utilisateur peut visualiser l'historique d'une réservation.
      • Modifier : L'utilisateur peut modifier une réservation.
      • Supprimer : L'utilisateur peut supprimer une réservation.

Utilisations métiers

Indisponibilité

  • Une ressource est indisponible lorsqu'elle est immobilisée. Elle n'est pas utilisable pour la plupart des activités.
  • Sur les créneaux horaires des lignes du planning, cela se matérialise par des striures horizontales grises.

Préparer un vol

OpenFlyers est couplé avec Airmate pour aider les pilotes à préparer leur vol. Ainsi, il est possible depuis l'interface dynamique de créer une préparation de vol à partir d'une réservation :

  • Effectuer un clic simple sur la réservation concernée pour faire apparaître l’info-bulle
  • Cliquer sur le bouton symbolisant un trajet.

FAQ

Disparition de réservation

Si une réservation n'apparait plus sur le planning, il faut se poser les questions suivantes :

  • Est-ce que cette réservation a réellement été faite ? En effet, il peut arriver qu'une personne pense avoir fait une réservation et qu'elle ait été interrompue dans son action et que finalement elle n'ait pas effectuée l'intégralité du processus. C'est notamment le cas lorsqu'une alerte avec une demande de confirmation s'affiche. L'email de confirmation de réservation est une preuve qui permet de confirmer que la réservation a bien été faite.
  • Est-ce que la réservation a été faite sur la bonne plateforme OpenFlyers ? Il peut arriver qu'un utilisateur dispose d'accès sur plusieurs plateformes OpenFlyers et qu'il confonde les plateformes. De la même façon, il peut avoir effectué sa réservation sur une recopie de test de la plateforme de production. Là encore, pour le lever le doute, l'email de confirmation de réservation indique le nom de la plateforme utilisée pour la réservation.
  • Un gestionnaire n'est-il pas intervenu pour supprimer/modifier la réservation ? Pour le savoir, il faut suivre la procédure qui permet de retrouver qui a supprimé une réservation à partir des logs.
  • Les emails de confirmation/modification/suppression de réservations indiquent à chaque fois le nom de la personne qui intervient pour effectuer l'action. Cela permet, en interrogeant les personnes ayant agit, de recouper les informations et de comprendre la cause de la disparition d'une réservation.