III.2.2 Tâches effectuées sous MS Access
XP
Toutes les bases de données de l'application ont
été implémentées dans MS Access. Les contraintes
d'intégrité prises en compte ici sont :
· Les contraintes sur domaines de valeurs d'attributs :
elles contrôlent les valeurs entrées dans les tables. Il s'agit
des types de données, de la plage admissible et la possibilité ou
non d'avoir des valeurs NULL (inconnues) ;
· Les contraintes d'unicité de clés : elles
garantissent la non répétition de valeurs dans une clé
primaire de table ;
· Les contraintes référentielles : elles
agissent sur les tables liées (comme les tables de la figure II.7). Il
s'agit ici de savoir comment la suppression d'un enregistrement d'une des
tables influencera ses enregistrements liés dans l'autre table. Nous
n'avons effectué liaisons suivantes :
- Clients/Chambres, Profils climatiques/Villes et Villes/Pays
: ici, quand un enregistrement d'une table est supprimé de la base de
données, ses correspondants dans l'autre table ne sont pas
retirés automatiquement. C'est l'utilisateur qui, s'il le désire
pourra les supprimer ;
- Règles/Prémisses (Figure II.7) : ici, quand
une règle est supprimée, toutes ses prémisses le sont
aussi. Cette contrainte n'est pas gérée par MS Access, mais
plutôt par le code Visual Basic de l'éditeur de règles.
III.3 Implémentation sous Visual Basic 6
III.3.1 Présentation de Visual Basic 6
Visual Basic est un langage de 4ème
génération. Ses débuts remontent à plus de vingt
ans, avec le fameux BASIC (Beginners All purposes Symbolic Instructions Code)
de Bill Gates, qui était très populaire à cause de son
apprentissage facile. Avec l'ère des interfaces graphiques, Visual Basic
a conservé cette simplicité d'utilisation, qui fait de lui le
plus utilisé actuellement (KIRSTEIN, 1999) pour les
développements sous Windows.
La programmation sous Visual Basic est purement visuelle et
évènementielle. Elle permet de manipuler aisément
pratiquement tous les objets graphiques de Windows. En plus des
propriétés et des méthodes de la théorie classique
des objets, les objets graphiques ont des évènements auxquels ils
peuvent répondre (Click, Double click, Déplacement, ...). Il
s'agit d'objets COM (Component Object Model). COM est
modèle centré objet assurant l'interopérabilité au
niveau binaire entre des objets de technologie Microsoft (GARDARIN, 2000).
C'est par exemple à travers ce modèle que sous Windows Word et
Excel (deux composants COM) peuvent communiquer entre eux.
Les objets de base de la programmation sont les feuilles, sur
lesquelles peuvent être rajoutés d'autres objets COM (boutons de
commandes, libellés, ...), encore appelés « contrôles
». A chaque feuille, est associée un module de classe, où
sont définies les procédures (évènementielles ou
non) de manipulation de la feuille. Il existe deux types de feuilles :
· Les feuilles MDI (Multiple Documents Interface) : il
s'agit d'une zone de travail dans laquelle plusieurs feuilles filles peuvent
être affichées. On peut en mettre une seule par application ;
· Les feuilles standard : elles peuvent ou non
être considérées comme filles d'une MDI.
Il est aussi possible de créer des modules standard, non
liés à des feuilles.
III.3.2 Tâches effectuées sous Visual
Basic 6
Nous présentons ici quelques grandes lignes du
développement effectué sous Visual
Basic.
a) La feuille de bilan thermique
La feuille de bilan thermique est une fille de la MDI. Pour un
maximum de convivialité, les contrôles principaux utilisés
ici sont :
· Le contrôle TreeView : il permet d'afficher dans
une arborescence les éléments de la chambre froide
(façades, ouvertures, compartiments, évaporateur ...) ;
· Le contrôle PictureBox : il offre à
l'utilisateur une visualisation en temps réel de la chambre qu'il
décrit. Chaque fois qu'un élément graphique
(façade, ouverture et compartiment) est sélectionné dans
l'arborescence, se dernier prend une couleur particulière dans le
graphique, permettant ainsi de situer l'élément en question ;
· Des contrôles Frame : en les superposant, on
peut offrir de nombreuses fonctionnalités dans un espace restreint de la
feuille. C'est ainsi que les caractéristiques des éléments
de la chambre sont saisis dans une même zone, la configuration de cette
zone changeant automatiquement en fonction de l'élément en cours
d'utilisation ;
· Le contrôle ToolsBar : il offre à
l'utilisateur une barre d'outils renfermant des commandes utiles à la
réalisation du bilan thermique.
Pendant l'exécution, cette fenêtre est accessible
à partir du menu Exécution et se présente comme
suit :
Figure III.1 : Fenêtre principale de
calcul du bilan thermique
b) La feuille d'estimation de l'état interne
La feuille d'estimation de l'état interne (diagnostic)
est une fille de la MDI. Pour un maximum de convivialité, les
contrôles principaux utilisés ici sont :
· Le contrôle TreeView : il permet d'afficher dans
une arborescence les groupes frigorifiques de la chambre froide ;
· Le contrôle PictureBox : chaque Configuration de
Circuit Fluidique (CCF) a une image propre, qui est affichée dans ce
contrôle ;
· Le contrôle MSFlexGrid : il a l'apparence d'une
grille de données, et est utilisé pour afficher les mesures
à prendre sur un groupe frigorifique donné ;
· Le contrôle ToolsBar : il offre à
l'utilisateur une barre d'outils renfermant des commandes utiles à
l'estimation de l'état interne des groupes frigorifiques.
Pendant l'exécution, cette fenêtre est accessible
à partir du menu Exécution et se présente comme
suit :
Figure III.2 : Fenêtre principale du
diagnostic interne
c) L'éditeur de texte
L'éditeur de texte est construit autour du
contrôle RichTextBox, dont les propriétés et
méthodes offrent déjà pratiquement toutes les
fonctionnalités requises. Il est accessible à partir du menu
Edition et se présente comme suit :
Figure III.3 : Affichage de l'éditeur de
texte
d) L'éditeur de règles
Cet éditeur est accessible à partir du menu
Edition. Il permet à l'utilisateur d'ajouter, de modifier ou de
supprimer des règles de décision à la CCF de son choix. Il
se présente comme suit :
Figure III.4 : Affichage de l'éditeur de
règles
e) Les principes de connexion aux bases de données
Comme dans tout environnement Client-Serveur typique, la
connexion à une base de donnée demande un médiateur
compatible et un langage d'interrogation. Sous Windows, le médiateur le
plus utilisé pour accéder à des bases de données
Access locales est Microsoft Jet, et le langage d'interrogation est le SQL.
Mais quelque soit le médiateur utilisé, Visual Basic 6.0 propose
une interface de niveau application, composée d'un jeu d'objets (ADO :
Active X Data Objects) d'accès uniforme aux sources de données,
qu'il s'agisse de bases de données relationnelles ou non, les
systèmes de fichiers, de courrier électronique, les
données texte, ... . Les principaux objets ADO sont :
· Connection : il permet d'établir la connexion avec
le fournisseur de données ;
· Command : il définit les opérations
à éxécuter sur la source de données. Dans notre
cas, il s'agit de requêtes SQL ;
· RecordSet : il représente un jeu d'enregistrements
(résultat d'une requête), et offre des méthodes de
manipulation de ces enregistrements.
Le code suivant donne un exemple d'utilisation d'objets ADO pour
ouvrir la table MATERIAUX de la base de donnée principale :
'Chemin d'installation du logiciel sur le disque Public Const
strInstal$ = "
C:\FRONIX\"
'Chaîne de connexion à la base de données
principale
Public Const strConnec$ = "PROVIDER=Microsoft.Jet.OLEDB.4.0;Data
Source=" & strInstal & "SUPP0RT\Frxbd.mdb;"
'Déclaration des objets ADO
Dim WithEvents rsConst As Recordset Dim cnnADO As New
ADODB.Connection Dim cmdADO As New ADODB.Command
'Instancier le RecordSet
Set rsConst = New Recordset
'Etablir la connection cnnADO.ConnectionString = strConnec
cnnADO.Open
'Configurer la commande
cmdADO.ActiveConnection = cnnADO cmdADO.CommandText = "SELECT Nom
FROM MATERIAUX"
'Configurer et ouvrir le Recordset rsConst.CursorLocation =
adUseClient rsConst.CursorType = adOpenDynamic rsConst.LockType =
adLockReadOnly rsConst.Open cmdADO
Figure III.5 : Exemple de code de connexion
à la base de données
f) L'appel de procédures externes
Par procédures externes, nous entendons les fonctions
de l'interface de programmation de Windows (Windows API : Application
Programming Interface), l'API du compilateur de fichiers d'aide (HtmlHelp) et
les DLL de l'application. Sous Windows, il y a deux manières
d'accéder à une DLL lors de l'exécution d'une application
:
· La DLL peut être chargée automatiquement
lors du chargement en mémoire de l'application ou d'une portion de
l'application dont la portée contient la déclaration de la DLL.
On parle alors de liaison dynamique au chargement (load time dynamic linking).
C'est ce mode de liaison que nous avons utilisé pour la DLL de
l'algorithme génétique et les fonctions des l'API de Windows et
de HtmlHelp ;
· La DLL peut être chargée dans l'espace
d'adressage de l'application pendant l'exécution, au moment voulu. On
parle alors de liaison dynamique à l'exécution (run time dynamic
linking). Une fois chargée, la bibliothèque peut être
manipulée à partir de son handle. Les handles sont des
descripteurs utilisés par Windows pour identifier de façon unique
des objets ou des contextes de périphériques (liaisons entre
Windows et des périphériques de sortie). Le « run time
dynamic linking » est indispensable lorsque le nom de la DLL à
appeler ne sera connu que pendant l'exécution. C'est le cas en ce qui
nous concerne pour les DLL des CCF, car c'est l'utilisateur qui décide
avec quelle CCF travailler. Ce sont les fonctions LoadLibrary() et
FreeLibrary() de l'API de Windows qui permettent respectivement de
charger et de décharger une DLL pendant l'exécution. Après
avoir chargé la DLL dans l'espace
d'adressage de l'application, LoadLibrary() renvoie
le handle du module chargé. Après le chargement d'une DLL de CCF,
c'est ce handle qui est envoyé à la DLL de l'algorithme
génétique, qui saura alors où retrouver les points
d'entrée des fonctions dont il a besoin. La DLL des fluides
frigorigènes est aussi manipulée par ce même principe.
L'exemple de code suivant montre comment les fonctions
LoadLibrary() et FreeLibrary() sont déclarées
(load time dynamic linking), et utilisées pour charger puis
décharger la bibliothèque des fluides frigorigènes (run
time dynamic linking).
'Fonction de chargement de bibliothèque de l'API de
Windows
Public Declare Function LoadLibrary Lib "kernel32" Alias
"LoadLibraryA" _ (ByVal lpLibFileName As String) As Long
'Fonction de déchargement de bibliothèque de l'API
de Windows
Public Declare Function FreeLibrary Lib "kernel32" (ByVal
hLibModule As Long) As Long
'Handle de la dll des fluides Public RefDLL As Long
'Charger la bibliothèques des fluides
Dim strBuf$
strBuf = "
C:\FRONIX\BIBLIO\REF_CALC32.dll"
RefDLL = LoadLibrary(strBuf)
If RefDLL = 0 Then
Beep
MsgBox "Fronix n'arrive pas à charger le fichier
C:\FRONIX\BIBLIO\REF_CALC32.dll",
_ vbCritical
Exit Sub
End If
'Utilisation du pointeur RefDLL
'Décharger la bibliothèque des fluides
Dim lngBuf&
lngBuf = FreeLibrary(RefDLL)
If lngBuf = 0 Then
strBuf = "
C:\FRONIX\BIBLIO\REF_CALC32.dll"
Beep
MsgBox "Une erreur est survenue lors du déchargement du
fichier " & Chr(10) & _ "
C:\FRONIX\BIBLIO\REF_CALC32.DLL",
vbCritical
Exit Sub End If
|
|
Figure III.6 : Exemple de code de chargement de
DLL
III.4 Implémentation sous Visual C++
6
III.4.1 Présentation de Visual C++
6
Le langage C a été crée en 1972 dans les
laboratoires AT&T Bell par Denis Ritchie avec un objectif précis :
écrire un système d'exploitation (UNIX). Mais sa
simplicité d'expression et sa rapidité d'exécution l'ont
très vite fait adopter par une large communauté de programmeurs.
Toujours chez AT&T, Bjarne Stroustrup développa au début des
années 80 le C++, qui reprend le C en y apportant des évolutions.
L'amélioration la plus importante apportée par le C++ est la
possibilité de faire de la programmation orientée objet. Visual
C++
est le compilateur C++ de Microsoft, fournissant en plus des
facilités pour la programmation visuelle sous Windows.
III.4.2 Tâches effectuées sous Visual
C++ 6
Nous présentons ici quelques grandes lignes du
développement effectué sous Visual C++. Toutes les fonctions
présentées ici retournent un entier court (« short »)
valant 0 si le calcul s'est déroulé avec succès. Dans le
cas contraire, elles retournent un code d'erreur positif. Mais quand nous
parlerons de données retournées, il ne s'agira que de celles qui
sont indispensables à l'expertise, et transmises par adresse aux
fonctions correspondantes.
a) Les DLL de CCF
La DLL de chaque Configuration de Circuit Fluidique exporte les
fonctions suivantes :
· fnCCF1 : c'est la fonction d'adaptation
utilisée par l'algorithme génétique. Elle reçoit en
entrée les mesures prélevées sur un groupe frigorifique
donné, les paramètres de ce groupe, le fluide frigorigène
à utiliser, le handle de la bibliothèque des fluides
(chargée par le code de l'application principale écrit en Visual
Basic) et les variables d'état (individu transmis par l'algorithme
génétique, et dont on veut connaître le fitness). En
retour, cette fonction renvoie une valeur indiquant l'écart entre les
mesures prélevées et les mesures calculées à partir
des variables d'état entrées ;
· fnCCF2 : à la fin du diagnostic, quand
l'algorithme génétique a trouvé des variables
d'état acceptables, cette fonction permet d'avoir les grandeurs de
décision restantes (variables internes et toutes les mesures possibles,
qu'elles aient été prélevées ou pas) ;
· fnCCF3 : c'est la fonction de redimensionnement. Elle
reçoit en entrée toutes les grandeurs actuelles d'un groupe
frigorifique donné (paramètres, variables d'état,
variables internes et mesures calculées), les paramètres de
dimensionnement (surchauffes admissibles, efficacités types des
échangeurs, ...), le fluide frigorigène à utiliser et le
handle de la bibliothèque des fluides chargée. En retour, elle
fournit des valeurs nominales pour les grandeurs transmises et un rapport de
calcul.
Le code suivant montre les déclarations de ces
fonctions.
#define CCF_API __declspec(dllexport)
//Fitness de l'AG de détermination de l'état
actuel
CCF_API short fnCCF1(
LPSTR hRef, //Nom du fluide utilisé
HINSTANCE RefDLL, //Handle de la dll des fluide chargée
depuis Fronix
double *norme, //Norme de retour (fitness)
double *param, //Paramètres de la CCF
double *varetat, //Variables d'état
int *nmes, //Nombre de mesures prélevées
double *mesurem, //Mesures prises sur site
int *maskmes //Masque des mesures
);
//Fonction de retour des variables internes et des mesures
obtenues par simulation CCF_API short fnCCF2(
LPSTR hRef, //Nom du fluide utilisé
HINSTANCE RefDLL, //Handle de la dll des fluide chargée
depuis Fronix
double *param, //Paramètres de la CCF
double *varetat, //Variables d'état
double *varint, //Variables internes
double *mesurem, //Mesures prises sur site
double *mesurec //Mesures issues de la simulation
);
//Fonction de retour des variables type issues de la
reconception CCF_API short fnCCF3(
LPSTR hRef, //Nom du fluide utilisé
HINSTANCE RefDLL, //Handle de la dll des fluide chargée
depuis Fronix
double *varobj, //Variables objectif issues du bilan
thermique
double *param, //Paramètres de la CCF
double *paramre, //Paramètres de reconception de la
CCF
double *varetac, //Variables d'état actuelles
double *varinac, //Variables internes actuelles
double *mesac, //Mesures actuelles
double *varetre, //Variables d'état après
reconception (à retourner)
double *varinre, //Variables internes après reconception
(à retourner)
double *mesre, //Mesures après reconception (à
retourner)
LPSTR *rapport //Rapport de la reconception (à
retourner)
);
|
|
Figure III.7 : Déclaration des fonctions
des DLL de CCF
b) La DLL de l'algorithme génétique
Cette DLL exporte deux fonctions :
~ La fonction de diagnostic : c'est elle qui met en oeuvre le
diagnostic par algorithme génétique. Elle recoit les
paramètres de l'algorithme génétique, les mesures
prélevées, le fluide frigorigène à utiliser et les
handles de la DLL de la CCF à utiliser et celle des fluides
chargée. En sortie, cette fonction renvoie le fitness minimal de la
dernière génération, le paramètre
d'homogénéisation de cette génération, et toutes
les variables de décision nécessaire à la CCF (variables
d'état, variables internes et mesures) ;
~ La fonction de reconception : elle a une signature
identique à la fonction fnCCF3 précédemment
présentée, sauf qu'en plus ici le handle de la DLL de la CCF
concernée est aussi transmis en entrée.
Le code suivant montre les déclarations de ces fonctions
:
#define AG_API __declspec(dllexport)
AG_API short __stdcall AlgoGen(
int taille, //Taille de la population
int iter, //Nombre de génération à
simuler
double ps, //Probabilité de sélection après
tournoi
double pmin, //Probabilité de mutation minimale
double pmax, //Probabilité de mutation maximale
double *minve, //Bornes minimales des varialbles
d'état
double *maxve, //Bornes maximales des varialbles d'état
LPSTR hRef, //Nom du fluide utilisé
HINSTANCE RefDLL, //Handle de la dll des fluides,
chargée depuis Fronix
HINSTANCE hDLL, //Handle de la dll de la CCF, chargée
depuis Fronix
double *param, //Paramètres de la CCF
int nve, //Nombre de variables d'état
double *mesurec, //Mesures obtenues par simulation (à
retourner)
double *varint, //Variables internes (à retourner)
double *homo, //Paramètre
d'homogénéïté (à retourner)
double *opti, //Fitness minimal (à retourner)
int nmes, //Nombre de mesures prélévées
double *mesurem, //Mesures prises sur site
int *maskmes, //Masque des mesures
double *varetat //Vaiables d'état (à retourner)
);
AG_API short __stdcall Concep(
HINSTANCE hDLL, //Handle de la dll de la CCF, chargée
depuis Fronix
LPSTR hRef, //Nom du fluide utilisé
HINSTANCE RefDLL, //Handle de la dll des fluide chargée
depuis Fronix
double *varobj, //Variables objectif issues du bilan
thermique
double *param, //Paramètres de la CCF
double *paramre, //Paramètres de reconception de la
CCF
double *varetac, //Variables d'état actuelles
double *varinac, //Variables internes actuelles
double *mesac, //Mesures actuelles
double *varetre, //Variables d'état après
reconception (à retourner)
double *varinre, //Variables internes après reconception
(à retourner)
double *mesre, //Mesures après reconception (à
retourner)
LPSTR *rapport //Rapport de la reconception (à
retourner)
);
|
|
Figure III.8 : Déclaration des
fonctions de la DLL de l'algorithme génétique
Dans toutes ces fonctions de DLL, les tableaux sont transmis
par adresse pour gagner en temps (pas recopie inutile de variables en
mémoire). La convention d'appel (protocole de gestion du transfert
d'arguments) standard a été utilisée lorsque la
compatibilité avec Visual Basic était nécessaire. Dans ces
DLL, de nombreuses fonctions non exportées ont été
définies pour faciliter la programmation. Ces fonctions ont
été rendues les plus courtes possibles afin de les définir
comme « inline ». Les fonctions « inline » sont
expansées lors de la compilation dans le code, en leurs points d'appel.
Ce principe accélère l'exécution du code, car les
mécanismes d'appel de fonctions se trouvent supprimés. L'annexe 1
montre celles qui ont été définies pour l'algorithme
génétique.
Les fonctions de redimensionnement auraient pu être
implémentées et appelées directement à partir des
DLL de CCF. Nous ne l'avons pas fait à cause des limitations de Visual
Basic dans la manipulation de pointeurs sur fonctions. En effet, quand on a le
handle de la DLL d'une CCF (après chargement en « run time dynamic
linking »), la fonction GetProcAddress() de l'API de Windows
permet d'obtenir le pointeur vers une fonction donnée de la DLL. Les
appels de cette fonction se feront par la suite par l'intermédiaire de
ce pointeur. Si un appel incohérent est réalisé (erreur
dans le nombre ou les types
d'arguments), alors le compilateur ne s'en apercevra pas, et
les dégâts à l'exécution pourront être
néfastes : tentatives d'écriture dans des zones mémoires
non allouées à l'application (MICROSOFT, 2000). Ce n'est qu'avec
Visual C++ que nous avons trouvé une technique pour prévenir
cela. Elle consiste à définir un type de pointeur sur fonction
ayant un prototype donné (celui de la fonction à appeler). Lors
de appel de GetProcAddress() une conversion explicite vers ce type de
pointeur est réalisée. De cette façon, lors des appels de
la fonction le compilateur dispose de tous les renseignements pour un
contrôle strict des arguments transmis. Le même problème ne
se pose pas lors des appels de fonctions de la DLL de l'algorithme
génétique depuis Visual Basic, car cette DLL est chargée
en « load time dynamic linking ». Le code suivant montre comment ceci
est mis en oeuvre pour l'appel de la fonction de redimensionnement depuis la
DLL de l'algorithme génétique.
//Définition de synonyme de pointeur sur la fonction de
redimensionnement typedef short (*Fonct3)(
LPSTR, //Nom du fluide utilisé
HINSTANCE, //Handle de la dll des fluide chargée depuis
Fronix
double*, //Variables objectif issues du bilan thermique
double*, //Paramètres de la CCF
double*, //Paramètres de reconception de la CCF
double*, //Variables d'état actuelles
double*, //Variables internes actuelles
double*, //Mesures actuelles
double*, //Variables d'état après reconception
(à retourner)
double*, //Variables internes après reconception
(à retourner)
double*, //Mesures après reconception (à
retourner)
LPSTR* //Rapport de la reconception (à retourner)
);
// Déclaration du pointeur sur la fonction de
redimensionnement Fonct3 ReDim; //Fonction de redimensionnement de la CCF
//Extraction du pointeur sur la fonction de redimensionnement
//hDLL est le handle de la DLL de la CCF transmis en argument
à cette fonction ReDim = (Fonct3)GetProcAddress(hDLL,"fnCCF3");
if (!ReDim)
{
return 20;
// Le pointeur n'a pas pu être obtenu, on retourne un
code d'erreur
}
short erreur; //Variable de retour de la fonction ReDim
//Appel de la fonction de redimensionnement erreur = ReDim(
hRef, //Nom du fluide utilisé
RefDLL, //Handle de la dll des fluide chargée depuis
Fronix
varobj, //Variables objectif issues du bilan thermique
param, //Paramètres de la CCF
paramre, //Paramètres de reconception de la CCF
varetac, //Variables d'état actuelles
varinac, //Variables internes actuelles
mesac, //Mesures actuelles
varetre, //Variables d'état après reconception
(à retourner)
varinre, //Variables internes après reconception
(à retourner)
mesre, //Mesures après reconception (à
retourner)
rapport //Rapport de la reconception (à retourner)
);
if (erreur > 0)
{
return 30;
//La DLL de la CCF ne trouve pas de solution
réalisable
}
//Le calcul s'est déroulé avec succès
return 0;
|
|
Figure III.9 : Exemple de code de manipulation
de pointeurs sur fonctions en C++
|