Francesc Gistau Queralt - deeea.urv.catdeeea.urv.cat/public/PROPOSTES/pub/pdf/2499pub.pdf ·...
Transcript of Francesc Gistau Queralt - deeea.urv.catdeeea.urv.cat/public/PROPOSTES/pub/pdf/2499pub.pdf ·...
Francesc Gistau Queralt
Desenvolupament d’una Aplicació per a Validació de Hardware
TREBALL DE FI DE GRAU
dirigit pel Prof. Ernest Gil Dolcet
Grau d’Enginyeria Electrònica Industrial i Automàtica
Tarragona
2017
Memòria Descriptiva
2
Índex 2 Introducció .......................................................................................................................... 4
2.1 Visió Global ................................................................................................................. 4
2.2 Pràctiques d’Empresa................................................................................................... 4
2.3 Context ......................................................................................................................... 5
2.4 Objectiu ........................................................................................................................ 6
2.5 Resolució ..................................................................................................................... 6
3 Software Utilitzat ................................................................................................................ 7
3.1 Llenguatge i Entorn de Programació ........................................................................... 7
3.1.1 Comparativa de Llenguatges ................................................................................. 8
3.1.2 Mètode Reflection ................................................................................................. 8
3.2 Configuració de l’Excel ............................................................................................... 9
3.2.1 Fulla 1: Test Steps ................................................................................................. 9
3.2.2 Fulla 2: Dispositius ............................................................................................. 11
4 Estructura del Software .................................................................................................... 13
4.1 Model d’arquitectura .................................................................................................. 13
5 Software ............................................................................................................................ 14
5.1 Controlador ................................................................................................................ 14
5.1.1 Interfícies de Comunicació.................................................................................. 15
5.1.1.1 Port Sèrie ...................................................................................................... 15
5.1.1.2 CAN .............................................................................................................. 18
5.1.1.3 Servidor TCP Wifi ........................................................................................ 20
5.1.2 Controladors de Dispositius ................................................................................ 23
5.1.2.1 TEQ_System ................................................................................................. 26
5.1.2.2 IDM_8341 .................................................................................................... 28
5.1.2.3 Zebra_GK420t .............................................................................................. 30
5.1.2.4 KMTronic_USB_Relay ................................................................................ 32
5.1.2.5 MiniVNAPro ................................................................................................ 34
5.1.2.6 FlashMicrocontroller .................................................................................... 37
5.1.2.7 WIFI_TERTest ............................................................................................. 39
5.1.2.8 MessageBox_Class ....................................................................................... 41
5.2 Model ......................................................................................................................... 42
5.2.1 Importació dels Excels ........................................................................................ 42
Memòria Descriptiva
3
5.2.2 Execució del Test ................................................................................................ 46
5.2.2.1 Ús del mètode “Reflection” .......................................................................... 47
5.2.2.2 Interacció amb la Vista ................................................................................. 49
5.2.2.3 Salts de files .................................................................................................. 51
5.2.3 Resultats del Test ................................................................................................ 51
5.3 Vista ........................................................................................................................... 52
5.3.1 Interfície Gràfica ................................................................................................. 52
5.4 Comportament del Test ................................................................................................. 56
6 Hardware .......................................................................................................................... 57
6.1 Dispositius ................................................................................................................. 57
6.1.1 KMTronic USB Relay ......................................................................................... 57
6.1.2 IDM-8341 ............................................................................................................ 57
6.1.3 MiniVNA Pro ...................................................................................................... 57
6.1.4 ST-LINK V2 ....................................................................................................... 58
6.1.5 Zebra GK420t ...................................................................................................... 58
7 Conclusions ...................................................................................................................... 59
8 Taula de Figures ............................................................................................................... 60
9 Taula de Codis .................................................................................................................. 61
10 Annexes .......................................................................................................................... 62
10.1 Codi .......................................................................................................................... 62
11 Referències ..................................................................................................................... 70
Memòria Descriptiva
4
2 Introducció
2.1 Visió Global
En aquest document es descriu el projecte de l’Aplicació per Validació de Hardware,
juntament amb l’objectiu a assolir i tot el procés que s’ha seguit per aconseguir l’objectiu
proposat.
En els primers apartats, es descriu un resum introductori del projecte i es planteja un
objectiu a assolir, d’on sorgeix la idea del projecte i tot el procés definit per poder-lo
aconseguir.
A continuació, s’entra més en detall i es presenten les eines de software utilitzades en el
projecte, el llenguatge de programació i els mètodes utilitzats.
Amb una idea més clara de l’entorn del projecte, s’explica l’estructura de software que
s’ha seguit per estructurar el codi, i es destaquen els fitxers i les parts de codi més
importants a tenir en compte alhora d’entendre el funcionament del software.
Seguidament, es defineixen tots els dispositius hardware utilitzats i les proves necessàries
que s’han fet per poder validar correctament el funcionament del projecte.
Finalment, es presenta una demostració del projecte finalitzat per poder demostrar que s’ha
assolit l’objectiu plantejat al principi del document, juntament amb unes conclusions
extretes del projecte.
Al final del document, es troben els annexes i les referències del projecte.
2.2 Pràctiques d’Empresa
Vaig realitzar les pràctiques a l’empresa Generation RFID, S.L. durant 5 mesos, començant
al 4 de Febrer de 2016 i acabant al 23 de Juny de 2016, treballant a jornada completa de
8:30 del matí fins a les 17:30 de la tarda, amb una hora per dinar.
Generation RFID, S.L. és una Consultoria Electrònica situada a Reus, al Camí de Valls, 81.
Està enfocada principalment al sector de l’Automoció tot i que està oberta a molts altres
sectors. Està especialitzada en validació tan de Software com de Hardware.
Durant el període de pràctiques vaig col·laborar en diversos projectes, però no va ser fins
al Juny, el període final de pràctiques, quan vaig començar a treballar en aquesta
Aplicació. Al finalitzar el període de pràctiques em van oferir treballar per poder continuar
amb el projecte.
Figura 1. Logotip Generation RFID
Memòria Descriptiva
5
Usuari
Aplicació
Dispositiu Extern
Dispositiu Extern
Hardware
Configuració del Test
2.3 Context
Aquest projecte sorgeix de la principal necessitat de desenvolupar una forma de validar
Hardware de manera automàtica, ràpida i senzilla per poder-la implementar en una línia de
producció.
Part de la necessitat sorgeix d’una petició d’un client que va demanar una aplicació amb
una interfície gràfica on es mostrés el resultat dels passos del test, lògicament el resultat
final del test i el temps en realitzar el test. També es va demanar un SetUp amb un llit
d’agulles per facilitar el canvi entre plaques de Hardware. Per últim, i possiblement el
requisit més important, va demanar que el disseny del test fos configurable per l’usuari, a
través d’un fitxer d’Excel. Lògicament, per a validar Hardware, és necessari poder mesurar
corrent, tensió, continuïtats, etc, per tant, aquesta aplicació ha de controlar dispositius
externs.
Resumint, s’havia de dissenyar una aplicació amb els següents requeriments:
• Interfície gràfica on es mostressin els resultats dels test i els temps de realització
• Test configurable per l’usuari
• Aplicació ràpida i fàcil d’utilitzar
• Control de diversos dispositius externs
Amb els requeriments definits, es va començar a dissenyar el projecte.
Figura 2. Diagrama de l’estructura de l’Aplicació
Memòria Descriptiva
6
Vista
Model
Controlador
Figura 3. Diagrama de l’estructura del Software
2.4 Objectiu
L’objectiu del projecte és desenvolupar una aplicació que llegeix d’un document extern,
els diversos passos a realitzar durant el test i que controli diferents dispositius externs
necessaris per poder validar Hardware.
Per part de l’empresa es va comentar que en un futur, l’aplicació havia de tenir accés a una
base de dades i a una web on pujar les dades. Així que el llenguatge a utilitzar havia de
contemplar aquestes possibilitats.
Els passos ha seguir van ser els següents:
1. Investigació del llenguatge per a poder crear una aplicació amb tots els
requeriments presents i futurs contemplats.
2. Investigació i comprensió del mètode de lectura d’un fitxer extern en format Excel
tenint en compte el llenguatge de programació a utilitzar.
3. Desenvolupament de l’aplicació en el llenguatge escollit.
4. Documentació del procés de desenvolupament.
Cal destacar que per desenvolupar el projecte va ser necessària una comprensió notable del
llenguatge de programació i de les eines a utilitzar.
2.5 Resolució
Per complir l’objectiu del projecte, es va dedicar un cert temps a la investigació de mètodes
de lectura de documents externs i també a definir l’estructura i les parts del projecte.
En la part d’investigació es va trobar un mètode anomenat “Reflection” en llenguatge C#.
Aquest mètode permet instanciar objectes i cridar mètodes d’objectes a través d’un string.
Per l’estructura del software projecte es va seguir el model Vista – Model – Controlador
entenent com a Vista la part gràfica que interactua amb l’usuari, el Model la part de gestió
de la lectura de la configuració del test i el Controlador la part de comunicació i gestió amb
els dispositius externs.
Memòria Descriptiva
7
3 Software Utilitzat
3.1 Llenguatge i Entorn de Programació
El projecte s’ha desenvolupat amb el llenguatge de programació C#, un llenguatge d’alt
nivell orientat a objectes que permet crear aplicacions per “.NET Framework”. És un
llenguatge molt útil per crear aplicacions amb accés a base de dades, aplicacions web amb
serveis client-servidor (Restful, SOAP) i també molt útil alhora de crear aplicacions de
comunicació en general. Si parlem de la part gràfica, C# és compatible amb “Windows
Forms”, una API de “Microsoft .NET Framework” que conté components per la interfície
gràfica i que fa més senzill el desenvolupament de la part gràfica de l’aplicació.
“.NET Framework” és una plataforma de codi administrat de Microsoft que compila el
codi a CIL (Common Intermediate Language) i que consta de dos components principals:
• CLR (Common Language Runtime): entorn d’execució encarregat de compilar el
codi CIL a llenguatge màquina
• Classes .NET Framework: classes pròpies que faciliten l’ús de llenguatge
L’entorn de programació utilitzat va ser Visual Studio 2015, ja que suporta el llenguatge
C# i la plataforma “.NET” del Framework 2.0 fins al Framework 4.6.1. Això ens permet
crear aplicacions compatibles amb Windows XP fins a Windows 10.
El projecte s’ha desenvolupat amb Windows 7 i amb la versió “.NET Framework 4.5”.
C# •Compilador C#
CIL •Compilador CLR
Llenguatge Màquina
Figura 4. Estructura de compilació .NET Framework
Memòria Descriptiva
8
3.1.1 Comparativa de Llenguatges
La raó principal per la qual es va descartar el llenguatge JAVA, tot i les immenses
possibilitats que dona alhora de crear aplicacions, va ser la poca familiarització amb el
llenguatge, sobretot amb la sintaxis, ja que no havia programat mai en aquest llenguatge.
Tot i que en C# tampoc havia programat mai, la semblança amb C o C++ feia més fàcil la
programació.
La decisió final va ser entre els llenguatges C++ i C#. Els dos llenguatges disposen d’APIs
que faciliten la gestió de base de dades amb serveis web, també permeten comunicacions
amb dispositius a través de USB, Port Sèrie, Modbus, Wifi, Bluetooth, etc, i lògicament
permeten implementar una interfície gràfica. La decisió final es va decantar degut a la
forma de tractar la lectura de configuració del Test d’un fitxer extern. Investigant es va
trobar un mètode anomenat “Reflection” que permet cridar funcions d’una classe a través
d’un string. Això permetria crear un fitxer extern amb el nom de les funcions a executar de
cada classe.
Aquest mètode no està molt aconseguit en C++ i la forma d’utilitzar-lo es complica en
comparació en C# i per aquest motiu es va escollir el llenguatge C# com a llenguatge de
programació del projecte.
3.1.2 Mètode Reflection
Una de les parts més importants que va ser clau alhora d’escollir C# com a llenguatge de
programació d’aquest projecte va ser el mètode “Reflection”.
Com a idea general, aquest mètode permet obtenir la informació d’un objecte, cridar
mètodes d’una classe o modificar propietats en temps d’execució. Aquesta tècnica ens
permet escollir quines classes es volen instanciar i quins mètodes es volen cridar. A través
del document extern Excel on es configura el Test, s’escriuen les classes a utilitzar i les
funcions a cridar durant l’execució del Test. És a dir, a través d’un string llegit en un Excel
es poden instanciar objectes i cridar funcions escollits en temps d’execució.
El mètode “Reflection” fa més fàcil la configuració del Test en el document Excel, ja que
se li ha d’escriure el nom de la classe a instanciar i les funcions a cridar en cada pas del
Test. Una peculiaritat és que el nom de les classes i les funcions han de coincidir amb el
nom posat en el codi. Lògicament si les funciones necessiten paràmetres, també s’han de
configurar en l’Excel.
En “.NET Framework” les classes de “Reflection” es troben dins de la llibreria
“System.Reflection”[0].
Memòria Descriptiva
9
Test
Test Group 1
Test Case 1
Test Step 1
Test Step 2
Test Case 2
Test Step 1
Test Group 2
Test Case 1
Test Step 1
Test Step 2
Figura 5. Estructura de l’Excel
Figura 6. Estructura Excel Fulla 1
3.2 Configuració de l’Excel
Un dels requisits del projecte és la possibilitat de definir els passos d’un Test en un Excel.
Per tal de crear una Excel senzill i ordenat, es va dissenyar un patró per estructurar els
passos dels Tests on la primera fulla del Excel és per crear una estructura de Test i definir
tots els passos del Test. La segona fulla de l’Excel és per definir les classes dels dispositius
externs a utilitzar per instanciar.
3.2.1 Fulla 1: Test Steps
En la primera fulla de l’Excel es va decidir estructurar el Test en Grups(Test Groups),
Casos (Tests Cases) i Passos (Test Steps), on cada Test Group tindria els seus Test Cases i
cada Test Case tindria els seus Test Steps, de tal manera que el Test quedaria ordenat per
grups i casos en forma d’arbre.
Ordenar els passos del Test d’aquesta manera facilita la forma per guardar en classes els
paràmetres llegits en l’Excel. Així doncs si parlem de codi, tindrem una classe que
contindrà una llista d’objectes de la classe TestGroups que a la vegada contindrà una llista
d’objectes de la classe TestCases on cada objecte de la classe TestCases contindrà una
llista d’arrays de TestSteps.
Memòria Descriptiva
10
Figura 7. Exemple $START
La fulla 1 disposa de 14 columnes on cada una representa un paràmetre que influència en
el comportament del Test i sobretot en el mètode “Reflection”. Cal destacar, que un error
en l’Excel pot generar un mal funcionament del Test i per tant una validació errònia.
Columna Descripció
# Aquesta columna indica el número del Test
Step
Type/Device El nom de l’objecte instanciat de la classe
del controlador del dispositiu assignat a la
fulla 2 de l’Excel
Name/Function El nom de la funció a utilitzar de la classe
de l’objecte instanciat
Time Delay (s) Retard, en segons, després d’executar la
funció
Retries Reintents per si falla el test. Per simular
reintents infinits s’utilitza el zero.
Report Paràmetre per escollir quin tipus de report
es vol crear
• NONE
• HTML
• CSV
• BOTH
Param. 1 Primer paràmetre de la funció a cridar
Param. 2 Segon paràmetre de la funció a cridar
Param. 3 Tercer paràmetre de la funció a cridar
Param. 4 Quart paràmetre de la funció a cridar
Param. 5 Cinquè paràmetre de la funció a cridar
Param. 6 Sisè paràmetre de la funció a cridar
Description Descripció del Test Step
Line if Fail Línia del Excel on ha de saltar el test en cas
d’error
Totes les funcions cridades a través de “Reflection” se’ls hi passa una array de strings, on
cada posició és un paràmetre de l’Excel (Param. 1, Param. 2 ... Param. 6).
Existeixen funcions especials per a fer més fàcil la gestió del Test. Aquestes funcions tenen
la peculiaritat de començar amb el símbol “$” i les seves funcionalitats són les següents:
• $START: Aquesta funcionalitat es va implementar per a poder distingir el
començament del Test, de la preparació del Test. Abans de començar un Test és
recomanable crear un estat d’inici conegut, per exemple si s’utilitza una placa de
relés, és necessari comprovar que tots estan en un estat de repòs que no pugui
influenciar en la resta de passos del Test.
Memòria Descriptiva
11
Figura 8. Exemple $END
Figura 9. Exemple $WAITREFERENCE
• $END: De la mateixa manera que la funcionalitat $START, aquesta funcionalitat es
va implementar per distingir el final del Test de la preparació del pròxim Test o per
deixar tots els dispositius en estat de repòs.
• $WAITREFERENCE: Per aquells tests que requereixen un número de sèrie,
s’utilitza aquesta funcionalitat que simplement espera a que un número de sèrie 12
caràcters sigui introduït en la casella de Reference de la Vista.
Aquestes funcionalitats influeixen en el report final del Test. En cas de crear el report en
format CSV, només sortiran aquells passos del Test que estan definits entre $START i
$STOP. Això es va implementar d’aquesta manera per a poder distingir el report que conté
només informació del Test(CSV), amb el report complet tots els passos definits al
Excel(HTML).
3.2.2 Fulla 2: Dispositius
En la fulla 2 es defineixen els dispositius a utilitzar durant el Test. S’escull un nom per
l’objecte a instanciar de cada classe dels dispositius i a continuació s’escriuen els
paràmetres que se li passen al constructor per a poder instanciar l’objecte. Aquests
paràmetres són els necessaris per a la comunicació.
A través del mètode “Reflection”, es crida el constructor de la classe i se li passa com a
paràmetre un array amb els paràmetres de comunicació. Aquest objecte és guardat en una
llista d’objectes per fer-lo servir alhora de cridar les funcions a través de “Reflection”.
Figura 10. Estructura Excel Fulla 2
Memòria Descriptiva
12
Els paràmetres de la fulla 2 són els següents:
Columna Descripció
# Número de dispositiu
Class Name Nom de la classe interna del Codi
Device Name Nom de l’objecte de la classe
Param. 1 (*)
Param. 2 (*)
Param. 3 (*)
Param. 4 (*)
Param. 5 (*)
Param. 6 (*)
(*)Depèn de la comunicació
Els paràmetres de comunicació són els següents:
Comunicació Param.
1
Param.
2
Param.
3
Param.
4
Param.
5
Param. 6
Port Sèrie Baudrate Port (*) Parity Stop Bit DLC Número de Sèrie
CAN Baudrate ID _ _ _ _
Wifi Port _ _ _ _ _
(*)En el cas de Comunicació Sèrie, si al paràmetre 2 se li posa “AUTO”, l’aplicació
agafarà el número de sèrie del dispositiu, i automàticament obtindrà el port corresponent.
Aquesta funcionalitat és explicita dels dispositius amb comunicació Port Sèrie. La
implementació del codi per obtenir el port a través del número de sèrie està implementat al
constructor de cada classe que ho necessiti.
Memòria Descriptiva
13
Figura 11: Diagrama de flux MVC
4 Estructura del Software
4.1 Model d’arquitectura
L’estructura del projecte es pot dividir en tres grans blocs o capes, seguint les bases de
l’arquitectura MVC (Vista, Model i Controlador):
• Vista: Entenem com a Vista la part gràfica per interactuar amb l’usuari. És la capa
més alta del projecte i des d’on es gestiona el Test. Des de la Vista es crida el
Thread principal que va executant els passos del Test a través del Mètode
“Reflection”. En resum, des de la part gràfica l’usuari pot gestionar el
comportament de l’aplicació i del Test.
• Model: És la capa encarregada de llegir i obtenir la informació de l’Excel per
executar el Test. Conté el Thread principal que crida les funcions de les classes dels
controladors dels dispositius necessaris per executar el Test a través de
“Reflection”. També gestiona el report final del Test.
• Controlador: És la capa més baixa i des d’on es controlen els dispositius externs.
Conté les classes que controlen els dispositius juntament amb les funcions que es
criden a través de l’Excel i també conté les classes de comunicació necessàries per
als dispositius.
Figura 11. Diagrama de flux de l’Aplicació
Memòria Descriptiva
14
5 Software Per tal d’estructurar tot el que engloba el software del projecte, es dividirà en tres blocs:
Vista, Model i Controlador.
5.1 Controlador
La capa del Controlador és la de més baix nivell i engloba totes les classes de comunicació
a més de les classes individuals i especifiques per poder controlar els dispositius. En
aquestes classes és on estan definides les funcions que es criden a través de l’Excel amb el
mètode “Reflection”.
En aquesta capa es poden distingir dos blocs: el bloc de comunicacions i el bloc de
controladors.
• Bloc de les comunicacions: hi ha implementades totes les classes necessàries per a
poder comunicar l’aplicació amb els dispositius. Aquestes classes són utilitzades
per les classes del bloc de controladors.
• Bloc de controladors: hi ha implementades totes les classes necessàries per a
controlar els dispositius. Cada dispositiu té la seva pròpia classe implementada i el
seu objecte instanciat de les classes de comunicació per a poder-se comunicar si és
necessari.
Figura 12. Diagrama de Flux Capa Controlador
Memòria Descriptiva
15
5.1.1 Interfícies de Comunicació
Per poder controlar els dispositius externs del Test, són necessaris diferents tipus de
comunicacions. Per això es van crear diferents classes per a poder gestionar aquestes
comunicacions. Gràcies a les llibreries de la plataforma “.NET Framework”, la
configuració de les comunicacions va ser més senzilla.
Comunicació Llibreria
Port Sèrie[1] System.IO.Ports (System.dll)
CAN[2] PCANBasic.dll
WIFI[3] System.Net.Sockets (System.dll)
5.1.1.1 Port Sèrie
Es va implementar una classe per poder comunicar la aplicació amb els dispositius externs
que tinguessin Port Sèrie. Es van crear dos mètodes de comunicació per a la recepció de
trames:
• Caràcter de final de trama
• Timeout (ja que alguns dispositius no enviaven caràcter final de trama)
Aquesta classe conté un Thread per a poder llegir contínuament les dades rebudes. També
consta d’un Callback per a poder enviar les dades rebudes cap a la classe del Dispositiu
corresponent.
S’utilitza la classe “ComPort” de la llibreria “System.IO.Ports” (System.dll) per a poder
enviar dades a través del Port Sèrie amb la funció “Write(msg)”.
public CommResultCode SendFrame(byte[] msg)
string msg_converted = System.Text.Encoding.UTF8.GetString(msg);
try
serial_port.Write(msg_converted);
catch (Exception)
return CommResultCode.SEND_FRAME_ERROR;
return CommResultCode.OK;
Codi 1. Funció Port Sèrie Enviament de Trames
Memòria Descriptiva
16
Per la lectura, es crida la funció “ReadByte()” dins el Thread de lectura, que va llegint Byte
a Byte les dades del Port Sèrie i es va guardant en un buffer de Bytes fins que es llegeixen
la quantitat de Bytes indicada (mode TimeOut) o es llegeix el caràcter de final de trama
(mode Char).
//--- RECEIVE IN MODE TIMEOUT
//---------------------------------------------------------------------
if (Port_mode == (byte)Mode.TIMEOUT)
try
while (true)
Data = Convert.ToByte (serial_port.ReadByte ());
Data_Buffer [Counter] = Data;
Counter++;
if (Counter >= Data_Buffer.Length)
Counter = 0;
//--- RECEIVE IN MODE CHAR
//---------------------------------------------------------------------
if (Port_mode == (byte)Mode.CHAR)
Timeout_flag = false;
while ((Data != 0x0A) && (Data != 0x0D) && (Exception_flag ==
false))
try
Data = Convert.ToByte (serial_port.ReadByte ());
if ((Data == 0x11) || (Data == 0x0A) || (Data ==
0x0D) || (Timeout_flag == true))
else
if (Counter >= Data_Buffer.Length)
Counter = 0;
Data_Buffer [Counter] = Data;
Counter++;
Timeout_flag = false;
Codi 2. Codi de Recepció de Trames en Port Sèrie
Memòria Descriptiva
17
Figura 13. Diagrama de Flux Port Sèrie
El comportament de la comunicació Port Sèrie és el següent:
Memòria Descriptiva
18
5.1.1.2 CAN
També es va implementar una classe per a comunicacions CAN ja que algunes de les
plaques de relés utilitzades són de la pròpia empresa i funcionen amb aquesta comunicació.
En aquesta classe es va definir una funció per enviar les trames, i es va implementar un
Thread per la lectura del bus CAN.
Aquesta classe també consta d’un Callback per a poder passar el valor llegit cap a les
classes dels dispositius. Aquest Callback és cridat pel Thread de lectura cada cop que s’han
rebut dades del bus CAN.
Es fa ús de la classe “PCANBasic” de la llibreria “PCANBasic.dll” per a poder enviar i
rebre trames a través del bus CAN. Es crida la funció “Write(CANmsg)” per enviar les
trames a través del bus CAN. Se li passa com a paràmetre la trama completa. A
continuació es comprova que l’estat del bus és la correcte i que no hi ha error d’enviament.
Per a la lectura de trames del bus CAN, es crida la funció “Read()” dins el Thread de
lectura. Aquest Thread s’encarrega de gestionar les dades rebudes del bus i passar-les cap a
les classes de dispositius necessàries a través del Callback,
La funció ProcessMessage(CANMsg) és l’encarregada de cridar al Callback en cas de
rebre una trama sense error.
public CanCommResultCode SendFrame(CanFrame msg)
TPCANMsg CANMsg;
TPCANStatus stsResult;
CANMsg = new TPCANMsg();
CANMsg.DATA = new byte[8];
CANMsg.ID = (UInt32) msg.Id;
CANMsg.LEN = msg.DataLength;
CANMsg.MSGTYPE = PeakMsgTypes[(int)msg.MsgType];
for (int i = 0; i < 8; i++)
CANMsg.DATA[i] = msg.Data[i];
stsResult = PCANBasic.Write(ref CANMsg);
if (((stsResult & TPCANStatus.PCAN_ERROR_BUSHEAVY) > 0) ||
((stsResult & TPCANStatus.PCAN_ERROR_BUSOFF) > 0))
return CanCommResultCode.SEND_FRAME_ERROR;
return CanCommResultCode.OK;
Codi 3. Funció d’enviament de Trames CAN
Memòria Descriptiva
19
private void ReadMessages()
TPCANMsg CANMsg;
TPCANTimestamp CANTimeStamp;
TPCANStatus stsResult;
do
stsResult = PCANBasic.Read(out CANMsg, out CANTimeStamp);
if (stsResult == TPCANStatus.PCAN_ERROR_OK)
ProcessMessage(CANMsg);
while (!Convert.ToBoolean(stsResult &
TPCANStatus.PCAN_ERROR_QRCVEMPTY));
Codi 4. Funció de lectura de Trames CAN
El comportament de la comunicació és similar al comportament de la comunicació Port
Sèrie:
Figura 14. Diagrama de Flux CAN
Memòria Descriptiva
20
5.1.1.3 Servidor TCP Wifi
Es va implementar un servidor TCP per enviar i rebre trames Wifi per a la validació de la
comunicació Wifi. Aquest classe de comunicació sorgeix de la necessitat de validar el
hardware que controla el panys de les portes dels hotels que funcionen amb targetes RFID.
Aquests panys comptaven amb un mòdul Wifi per a poder validar el seu comportament un
cop programats.
Utilitzant les funcions de la classe “TCPListener” de la llibreria “System.Net.Sockets”
(System.dll) es va configurar la comunicació de l’aplicació amb el mòdul Wifi
corresponent.
public Boolean Init(int port, string IP)
//string IP = Get_Local_IP_Address ();
IPAddress myIp = IPAddress.Parse(IP);
//Creación listener
ListenTcpServer= new TcpListener(myIp, port);
try
ListenTcpServer.Start();
//Esperando la conexión del ciente...
Console.WriteLine("Esperando la conexion...");
catch (Exception e)
Console.WriteLine (e);
try
thread = new Thread(new ThreadStart(ReadThread));
thread.IsBackground = true;
thread.Start();
return true;
catch(Exception e)
Console.WriteLine (e.Message);
Console.Write("No se creado el thread.\n");
return false;
Codi 5. Configuració del Servidor TCP
Memòria Descriptiva
21
Amb les funcions de la classe “Socket” corresponents a la llibreria “System.Net.Sockets”
(System.dll) s’obre el socket, i es fa la lectura de trames cridant la funció “Receive()” dins
el Thread de lectura.
Com en les altres comunicacions, aquesta classe disposa d’un Thread de lectura i d’un
Callback que crida si ha llegit dades del socket.
(*) soc objecte instanciat de la classe Socket
public void ReadThread()
try
while(thread_enabled)
soc = ListenTcpServer.AcceptSocket(); //Open Socket
Console.Write("Connection accepted from " +
soc.RemoteEndPoint +"\n");
Process_IP_Address(Get_Remote_IP_Address());
while(SocketConnected(soc))
//string eth_frame_string = "";
byte[] eth_frame = new byte[100];
int num = soc.Receive(eth_frame);
//para verificar que no recibimos nada
if(num==0)
Console.WriteLine("EL CLIENTE HA CERRADO
COMUNICACIONES\n");
break;
// llamada al callback
Process_Ethernet_Frame(eth_frame);
soc.Close();
Console.Write("\n");
Console.Write("Connection closed\n");
catch (Exception e)
ListenTcpServer.Stop();
Console.WriteLine("Error..... " + e.StackTrace);
Codi 6. Thread de Lectura del Servido TCP
Memòria Descriptiva
22
Per enviar dades, s’utilitza la funció “Send(Msg)” de la classe “Socket”.
El comportament de la comunicació Wifi és el següent:
public CommResultCode SendFrame(byte[] msg)
try
Console.Write ("Enviando mensaje...\n");
soc.Send(msg);
catch (Exception)
return CommResultCode.SEND_FRAME_ERROR;
return CommResultCode.OK;
Figura 15. Diagrama de Flux Servidor TCP
Codi 7. Funció per enviar trames Wifi
Memòria Descriptiva
23
5.1.2 Controladors de Dispositius
Per tal de poder controlar els diferents dispositius externs per a poder realitzar el test, es
van crear classes per a cada un dels dispositius. Aquestes classes es van crear amb una
estructura similar per poder-les fer compatibles amb qualsevol canvi de futur.
·Constructor
A través del constructor es configura i es crea l’objecte de la classe de comunicació
corresponent. En cas de comunicació Port Sèrie, en el constructor també hi ha implementat
el mètode per a poder obtenir el Port del dispositiu a través del número de sèrie.
public KMTronic_USB_Relay(string[] Plist2)
try
if (Plist2[(int)ParamsComPort.port] != null)
configPuerto.com_baudRate =
Convert.ToInt32(Plist2[(int)ParamsComPort.baudrate]);
configPuerto.com_port =
Convert.ToString(Plist2[(int)ParamsComPort.port]);
Parity parity = new Parity();
configPuerto.com_parity =
GetParity(Convert.ToString(Plist2[(int)ParamsComPort.
parity]), parity);
StopBits stopbits = new StopBits();
configPuerto.com_stopBits =
GetStopBits(Convert.ToString(Plist2[(int)ParamsComPor
t.stopbit]), stopbits);
configPuerto.com_dataBits =
Convert.ToInt16(Plist2[(int)ParamsComPort.dlc]);
serialPort.Init(configPuerto);
serialPort.Port_Mode(ComPort.Mode.TIMEOUT,
COM_PORT_TIMEOUT);
serialPort.AddHandler(receivedDataCallback);
Console.WriteLine("Dispositivo KMTronic configurado
correctamente");
else
throw new Exception();
catch
Console.WriteLine("Error KMTronic: Null Port");
MessageBox.Show("Fallo en la conexión del dispositivo
KMTronic. Revise el número de serie.", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
Codi 8. Exemple Constructor amb Port Sèrie
Memòria Descriptiva
24
// Get Device Information //
private object GetDeviceInformation(string Excel_Serial, int length)
string DeviceID = "";
string QueryString = "SELECT * FROM Win32_PnPEntity WHERE Caption
like '%Serial Port%'";
object COM_PORT = null;
string PORT = "";
SelectQuery WMIquery = new SelectQuery(QueryString);
ManagementObjectSearcher WMIqueryResults = new
ManagementObjectSearcher(WMIquery);
try
if (WMIqueryResults != null && WMIqueryResults.Get().Count
> 0)
foreach (object cur in WMIqueryResults.Get())
ManagementObject mo = (ManagementObject)cur;
DeviceID = mo["PNPDeviceID"].ToString(); //Cogemos ID
string[] PNP = DeviceID.Split('\\'); //Separamos //
string[] ID = PNP[1].Split('+'); //Separamos por "+"
DeviceID = ID[2].Substring(0, length); //Cogemos ID
Excel
if (DeviceID == Excel_Serial)
this.Serial_Number = DeviceID;
object captionObject =
mo.GetPropertyValue("Caption"); //Caption ==
COMXX
Console.WriteLine(mo["Caption"].ToString());
PORT = mo["Caption"].ToString(); //Cogemos
Caption
PORT = PORT.Split('(', ')')[1]; //Cogemos solo
COMXX
COM_PORT = (object)PORT;
break;
else
COM_PORT = null;
catch
Console.WriteLine("KMTronic Error: Fallo en los parametros
de configuracion del puerto");
return COM_PORT;
Utilitzant les classes “ManagementObjectSearcher”[4] i “ManagementObject”[5] de la
llibreria “System.dll”, es busquen els dispositius que utilitzen algun port del PC, sigui
USB, Port Sèrie o LPT. A continuació s’obté el número de sèrie i es compara amb l’indicat
a l’Excel. Si són iguals, s’obté el port i s’utilitza per configurar la comunicació.
Codi 9. Algoritme de recerca del port a través del número de sèrie
Memòria Descriptiva
25
Amb el mètode “Reflection” s’instancia l’objecte de la classe del controlador especificada
en la fulla 2 de l’Excel i se li passa al constructor un array amb els 6 paràmetres de l’Excel.
D’aquesta manera, es crea l’objecte de cada dispositiu amb la comunicació ja establerta.
·Funcions
Les funcions que són cridades a través del mètode “Reflection” tenen dos peculiaritats:
• Tenen com a paràmetre un array de Strings amb els 6 paràmetres de l’Excel
• Retornen un Diccionari amb el següent format: o Dict = "Result": Result,
"Value": Value,
"MaxRange": MaxRange
"MinRange": Min Range
o Si la funció s’ha executat amb èxit el camp Result retornarà “True”, en cas
contrari “False”.
o Si els camps no tenen cap funcionalitat en la funció, es retorna “NA”.
o Tots els camps del diccionari retornen un String.
Totes les funcions de qualsevol controlador que es vulguin cridar a través de “Reflection”
han de seguir aquesta estructura. De no ser així, l’aplicació no les reconeixerà com a funció
correcte i el test fallarà. Lògicament, aquestes funcions han de ser públiques.
El nom de la funció que es crida a través de l’Excel, ha de coincidir amb el nom de la
funció definida en les classes dels controladors. Si el nom de la funció no correspon a cap
de les funcions de la classe corresponent, el test fallarà.
//--- ACTIVAR RELE
//---------------------------------------------------------------------
public Dictionary<string, string[]> activarRele (string[] Plist)
test = new Dictionary<string, string[]>();
.
.
.
test.Add("Result", mesureResult); test.Add("Value", value); test.Add("MaxRange", maxRange); test.Add("MinRange", minRange); return test;
Codi 10. Exemple de funció Reflection
Memòria Descriptiva
26
5.1.2.1 TEQ_System
La classe TEQ_System es va crear per controlar les plaqués de relés pròpies de l’empresa.
Per a comunicar-se amb aquestes plaques s’utilitza la classe de comunicació CAN.
El procediment per enviar les trames és el següent:
• Es prepara la trama amb el format següent
ID Frame Type Length Data
o ID: identificador de la placa de relés
o Frame Type: es poden enviar 4 tipus de trames
Trama Standard de CAN (0x00): trama amb 11 bits de identificador
pern enviar dades
Trama Remote Transfer Request (0x01): trama sense camp de dades
per a demanar dades a algun node
Trama Ampliada de CAN (0x02): trama amb 29 bits de identificador
per enviar dades
Trama d’estat de CAN (0x80): trama per saber l’estat de la
comunicació CAN
o Lenght: 8 bytes de dades
o Data: Codi de Trama + Nº de Relé + Acció
Codi de Trama:
• 1 – Activar/Desactivar Relé
• 2 – Activar/Desactivar tots els Relés
• 3 – Demanar el estat d’un Relé
Nº de Relé: el Relé que es vol commutar
Acció:
• 0xFF per tancar el Relé (Normally Close)
• 0x00 per obrir el Relé (Normally Open)
• A través de la llibreria PCANBasic es crida la funció “Write” i se li passa com a
paràmetre el Bus ha utilitzar (1...7) i tota la trama completa. Aquesta funció
s’encarrega d’enviar la trama al bus CAN per a que el dispositiu amb la mateixa ID
la pugui interpretar.
En el cas de la recepció de trames, la classe de comunicació CAN disposa d’un Thread que
va llegint el port CAN. Aquest Thread crida la referència al Callback definida en el
controlador TEQ_System si s’ha rebut una resposta. En el cas de rebre una resposta, se li
enviar el valor al controlador a través del Callback.
Aquesta classe disposa de dues funcions per a cridar des de l’Excel:
Funció Descripció activarRele() Funció per tancar el Relé (Normally Close). S’indica el
número del Relé en el Paràmetre 1. desactivarRele() Funció per obrir el Relé (Normally Open). S’indica el número
del Relé en el Paràmetre 1.
Memòria Descriptiva
27
public Dictionary<string, string[]> activarRele(string[] Plist)
//Dictionary Params//
string[] value = new string[5];
string[] mesureResult = new string[5];
string[] maxRange = new string[5];
string[] minRange = new string[5];
test = new Dictionary<string, string[]>();
RecvEvent.Reset();
send_frame.Data[0] = (byte)ControlFramesCodes.SetRelay;
send_frame.Data[1] = Convert.ToByte(Plist[(int)ParamsCAN.rele]);
send_frame.Data[2] = (byte)relayOperation.CLOSE_RELAY;
can_connection.SendFrame(send_frame);
bool result = RecvEvent.WaitOne(RESPONSE_TIMEOUT);
if (!result)
Console.WriteLine("ERROR\n\r");
mesureResult[0] = "false";
else
Console.WriteLine("Test --> Activar Rele OK");
mesureResult[0] = "true";
value[0] = "NA"; maxRange[0] = "NA"; minRange[0] = "NA";
test.Add("Result", mesureResult);
test.Add("Value", value);
test.Add("MaxRange", maxRange);
test.Add("MinRange", minRange);
return test;
void Received_Data_Callback(CanFrame received_data)
this.response_frame = received_data.Data;
RecvEvent.Set();
Codi 12. Callback CAN
Codi 11. Exemple Funció Activar Relé
Com es pot veure en el codi, no s’interpreta la resposta, ja que la placa de relés només
respon si ha pogut commutar el relé.
Memòria Descriptiva
28
5.1.2.2 IDM_8341
Aquesta classe s’utilitza per controlar el Multímetre IDM-8341 per a la mesura dels
diversos Test Points del Hardware a validar. S’envien diverses comandes en funció de la
mesura que es necessiti realitzar. Per comunicar-se amb aquest dispositiu s’utilitza la
classe de comunicació Port Sèrie amb caràcter final de trama.
Les funcions configurades del Multímetre per poder cridar des de l’Excel són les següents:
Funció Comanda Descripció measure_DC_voltages() "MEAS:VOLT:DC? " Mesura la Tensió Continua.
S’indica el màxim en el
Paràmetre 1 i el mínim en el
Paràmetre 2. measure_DC_current_range() "MEAS:CURR:DC? " Mesura la Corrent Continua.
S’indica el màxim en el
Paràmetre 1 i el mínim en el
Paràmetre 2. measure_resistance_range() "MEAS:RES?” Mesura els Ohms. S’indica el
màxim en el Paràmetre 1 i el
mínim en el Paràmetre 2. measure_frequency() "MEAS:FREQ? " Mesura la Freqüència. S’indica
el màxim en el Paràmetre 1 i el
mínim en el Paràmetre 2. measure_capacitance_range() "MEAS:CAP? " Mesura la Capacitat. S’indica
el màxim en el Paràmetre 1 i el
mínim en el Paràmetre 2.
Per enviar les comandes, simplement es crea un String amb la comanda adequada, es
codifica en cadena de caràcters amb format UTF-8 bits i a través de la funció “Write()” de
la classe SerialPort de la llibreria “System.IO.Ports”, s’envia la comanda pel Port Sèrie
corresponent al Multímetre.
Per obtenir la resposta, es va crear una funció Callback que és cridada pel Thread de
recepció de Trames de la classe de comunicació Serial Port quan s’ha rebut una resposta.
S’utilitza la classe “AutoResetEvent” per crear un Event que s’activa quan el Callback és
cridat. Si no es rep cap resposta abans que salti el TimeOut configurat del Event, la funció
interpreta la mesura com a errónea i retorna “False”.
Si la comanda és la correcte i el Multímetre ha pogut mesurar correctament, enviarà una
resposta amb el valor de la mesura. Es comprova que aquest valor estigui entre el màxim i
el mínim indicats en l’Excel.
Memòria Descriptiva
29
public Dictionary<string, string[]> measure_DC_voltages(string[] Plist)
//Dictionary Params//
string[] value = new string[5];
string[] mesureResult = new string[5];
string[] maxRange = new string[5];
string[] minRange = new string[5];
test = new Dictionary<string, string[]>();
bool TestResult = false;
RecvEvent.Reset();
Plist[(int)ParamsIDM_8341.MaxValue] =
Plist[(int)ParamsIDM_8341.MaxValue].Replace(",", ".");
send_string = "MEAS:VOLT:DC?" +
Plist[(int)ParamsIDM_8341.MaxValue] +"\n\r";
serialPort.SendFrame (Encoding.UTF8.GetBytes(send_string));
bool result = RecvEvent.WaitOne(RESPONSE_TIMEOUT);
if (!result)
if (serialPort.Get_Exception_flag () == true)
Console.WriteLine("Test Error IDM-8341: Flag Error");
mesureResult[0] = "false";
value[0] = "NA";
else
received_string = received_string.Replace (".", ",");
if (received_string == "")
Console.WriteLine ("\nEMPTY STRING -> NO VOLTAGE
VALUE READED\n");
mesureResult[0] = "false";
value[0] = "NA";
else
Console.WriteLine("TEST --> Measure DC Voltage:" +
received_string); // Test Print
value[0] = Convert.ToString(received_string);
//Comprobamos que el resultado este dentro del rango
TestResult = testValues(value[0],
Plist[(int)ParamsIDM_8341.MaxValue],
Plist[(int)ParamsIDM_8341.MinValue]);
value[0] = Value_Result_Handler(value[0]);
mesureResult[0] = TestResult ? "true":"false";
maxRange[0] = Plist[(int)ParamsIDM_8341.MaxValue];
minRange[0] = Plist[(int)ParamsIDM_8341.MinValue];
test.Add("Result", mesureResult);
test.Add("Value", value);
test.Add("MaxRange", maxRange);
test.Add("MinRange", minRange);
return test;
Codi 13. Exemple funció Mesura Voltatge DC
Memòria Descriptiva
30
5.1.2.3 Zebra_GK420t
Per tal de controlar la impressora Zebra GK420t es va crear una classe que enviar un string
a través de comunicació Port Sèrie, amb les comandes per crear l’etiqueta. Aquest string es
llegeix d’un fitxer “.txt”. i la seva ubicació s’indica en el paràmetre 1 de l’Excel. Degut a
que la impressora no retorna dades, no va fer falta implementar un Callback per obtenir
dades de recepció.
Aquesta classe disposa d’una única funció per cridar des de l’Excel:
Funció Descripció sendFileToPrint() Llegeix el fitxer .txt de la ubicació indicada en l’Excel i envia el
String pel Port Sèrie. S’indica el path del fitxer en el Paràmetre 1.
En aquesta classe també s’utilitza una funció que s’encarrega de substituir caràcters
especials que comencen en el símbol dollar ($). Es llegeix el fitxer “.txt” en un string, es
crida la funció “VariableStringHandle”, que fa un “Replace” (llibreria System.dll) de les
paraules. En aquesta versió només és possible substituir la paraula $DATE per la data
actual de l’execució de la funció.
Com es pot veure, està pensat per substituir també la paraula $SERIALNUM per un
número de sèrie, tot i que no està implementat.
public string VariableStringHandle(string var)
string escape = null;
string date = DateTime.Now.ToString("dd/MM/yyy");
try
var = var.Replace("$DATE", date); //Replace $DATE for
current date
catch
Console.WriteLine("\n$DATE has not been replaced.");
/*try
var = var.Replace("$SERIALNUM", "11111122");
catch
Console.WriteLine("\n$SERIALNUM has not been replaced.");
*/
escape = var;
return escape;
Codi 14. Funció VariableStringHandle per substituir paraules dollar ($)
Memòria Descriptiva
31
public Dictionary<string, string[]> sendFileToPrint(string[] Plist)
//Dictionary Params//
string[] value = new string[5];
string[] mesureResult = new string[5];
string[] maxRange = new string[5];
string[] minRange = new string[5];
test = new Dictionary<string, string[]>();
RecvEvent.Reset();
string path= System.IO.Directory.GetCurrentDirectory();
if (File.Exists(path +
Plist[(int)ParamsZebra_GK240t.escape_sequencences]))
string ZPLString = System.IO.File.ReadAllText(@path +
Plist[(int)ParamsZebra_GK240t.escape_sequencences]);
if (ZPLString.IndexOf("$") != -1)
ZPLString = handler.VariableStringHandle(ZPLString);
try
serialPort.SendFrame(Encoding.UTF8.GetBytes(ZPLString
));
Console.WriteLine("\nTest --> Print Test OK");
mesureResult[0] = "true";
value[0] = "NA";
catch (Exception e)
Console.WriteLine("Error: " + e);
mesureResult[0] = "false";
value[0] = "NA";
else
MessageBox.Show("Fichero de impresion no encontrado");
Console.WriteLine("Error: Print File doesn't exists");
mesureResult[0] = "false";
value[0] = "NA";
maxRange[0] = "NA"; minRange[0] = "NA";
test.Add("Result", mesureResult);
test.Add("Value", value);
test.Add("MaxRange", maxRange);
test.Add("MinRange", minRange);
return test;
Codi 15. Exemple funció per imprimir etiquetes
Memòria Descriptiva
32
public void receivedDataCallback(byte[] received_string, int
buffer_size)
Buffer.BlockCopy(received_string, 0, Received_Data, 0,
buffer_size);
Console.WriteLine("\nThread Callback KMTronic: " +
received_string.ToString());
RecvEvent.Set();
5.1.2.4 KMTronic_USB_Relay
Aquesta classe es va implementar per controlar les plaques de relés KMTronic. Utilitza la
classe de comunicació Port Sèrie amb final de trama per TimeOut, ja que les trames que
enviar el dispositiu KMTronic no tenen caràcter final de trama.
La trama que se li envia al dispositiu és una trama amb la següent estructura:
Inici de Trama Nº Relé Acció
• Inici de Trama: L’inici de la trama ha d’estar format per 0xFF
• Nº Relé: El número del Relé que es vol commutar
• Acció:
o 0 – Si es vol obrir el Relé
o 1 – Si es vol tancar el Relé
Trama per tancar el Relé 5 Trama per obrir el Relé 2
FF 05 1 FF 02 0
Com que el dispositiu no respon automàticament, per comprovar que el relé ha commutat
correctament, existeix una trama amb la qual el dispositiu et respon amb l’estat de tots els
relés.
Trama per saber els estats dels Relés
FF 09 0
Per rebre la trama, es fa servir el Thread de lectura de la classe de comunicació Port Sèrie,
que crida la funció de lectura, igual que amb el Multímetre IDM-8341. També es fa servir
un Event per controlar el TimeOut.
Les funcions que disposa aquesta classe per poder cridar des de l’Excel són les següents:
Funció Descripció activarRele() Funció per tancar el Relé (Normally Close). S’indica el
número del Relé en el Paràmetre 1. desactivarRele() Funció per obrir el Relé (Normally Open). S’indica el
número del Relé en el Paràmetre 1.
Codi 16. Callback Port Sèrie
Memòria Descriptiva
33
La funció “CheckResponse()” és l’encarregada d’enviar la trama per saber els estats dels
relés. Si l’estat és correcte retorna “True”.
public Dictionary<string, string[]> activarRele (string[] Plist)
//Dictionary Params//
string[] value = new string[5];
string[] mesureResult = new string[5];
string[] maxRange = new string[5];
string[] minRange = new string[5];
test = new Dictionary<string, string[]>();
RecvEvent.Reset();
send_data_KMTronic[0] = 0xFF;
send_data_KMTronic[1] =
Convert.ToByte(Plist[(int)ParamsKMTronic.rele]);
send_data_KMTronic[2] = (byte)relayAction.setRelay;
try
serialPort.SendByteFrame(send_data_KMTronic,
send_data_KMTronic.Length);
if (!Check_Response())
Console.WriteLine("KMTronic: No USB connection.");
mesureResult[0] = "false";
else
mesureResult[0] = "true";
catch
Console.WriteLine("Error: Activar Rele");
mesureResult[0] = "false";
value[0] = "NA"; maxRange[0] = "NA"; minRange[0] = "NA";
test.Add("Result", mesureResult);
test.Add("Value", value);
test.Add("MaxRange", maxRange);
test.Add("MinRange", minRange);
return test;
Codi 17. Funció per Activar Relé
Memòria Descriptiva
34
5.1.2.5 MiniVNAPro
La classe MiniVNAPro es va implementar per controlar el mesurador RFID MiniVNAPro.
Tot i que utilitza la comunicació Port Sèrie, des de la classe no es crear cap comunicació.
Per mesurar es crear un fitxer .bat, amb la classe “SteamWriter”[6] de la llibreria
“System.IO”, amb les comandes per executar les aplicacions Java “vnaJ-hl.3.1.5.jar” i
“vnaJ.3.1.9.jar”. Es crea un procés amb la classe “Process”[7] de la llibreria
“System.Diagnostics” que executa el fitxer .bat creat i s’espera a que el procés acabi.
Amb aquest seguit de passos, els executables Java creen un fitxer CSV amb tots els valors
mesurats. Aquests valors es llegeixen i es guarden en una estructura per més endavant
utilizar-los.
Les instruccions que s’escriuen en el fitxer .bat depenent del tipus de mesura són les
següents:
Tipus de Mesura Comanda
Reflection java -Dfstart= startFrequency Dfstop= stopFrequency -
Dfsteps= steps -Dcalfile= calibrationFile -
Dscanmode=REFL -Dexports=csv -jar \\vnaJ\\vnaJ-
hl.3.1.5.jar
Transmission java -Dfstart= startFrequency Dfstop= stopFrequency -
Dfsteps= steps -Dcalfile= calibrationFile -
Dscanmode=TRAN -Dexports=csv -jar \\vnaJ\\vnaJ-
hl.3.1.5.jar
• startFrequency: Freqüència d’inici de mesura
• stopFreqüency: Freqüència final de mesura
• steps: Número de mesures entre la freqüència incial i final
• calibrationFile: Nom del fitxer de calibratge creat amb l’executable Java
vnaJ.3.1.9.jar
Aquesta classe disposa de tres funcions per a poder cridar des de l’Excel:
Funció Descripció GetMeasuredValue() Funció que crea i executa el fitxer .bat per obtenir les
mesures. S’indica la freqüència màxima en el Paràmetre 1,
la freqüència mínima en el Paràmetre 2, el número de
mostres en el Paràmetre 3, el tipus de mesura
(REFL/TRAN) en el Paràmetre 4 i el fitxer de Calibratge
en el Paràmetre 5. GetFrequency() Funció per obtenir els valor mesurats d’una freqüència
concreta. S’indica la freqüència màxima en el Paràmetre 1,
la freqüència mínima en el Paràmetre 2 i la freqüència
exacte que vols agafar les mesures en el Paràmetre 3. Get_Measured_Parameter() Funció per obtenir qualsevol valor mesurat que existeixi
en l’Excel. S’indica el tipus de valor en el Paràmetre 1, el
màxim en el Paràmetre 2 i el mínim en el Paràmetre 3.
Memòria Descriptiva
35
public Dictionary<string, string[]> GetMeasuredValue(string[] Plist)
//Dictionary Params//
. . .
Process java = new Process();
int FrequencyOfParameterOfOut =
Convert.ToInt32(Plist[(int)ParamsVNA.FrequencyOfParameterOfOut]);
string Path = System.IO.Directory.GetCurrentDirectory();
string Dir = Path + "\\vnaJ\\vnaJ-hl.3.1.5.jar";
string Dir1 = Path + "\\vnaJ\\vnaJ.3.1.9.jar";
string Dir2 = Path + "\\vnaJ\\REFL_miniVNA-pro.cal";
mesureResult.SetValue("true", 0);
this.startFrequency = Plist[(int)ParamsVNA.startFrequency];
this.stopFrequency = Plist[(int)ParamsVNA.stopFrequency];
this.steps = Plist[(int)ParamsVNA.steps];
this.scanMode = Plist[(int)ParamsVNA.scanMode];
this.calibrationFile = Plist[(int)ParamsVNA.calibrationFile];
if ((File.Exists(Dir)) && (File.Exists(Dir1)) &&
(File.Exists(Dir2)))
if (scanMode == "REFL")
ejecutable = "java -Dfstart=" + startFrequency + " -
Dfstop=" + stopFrequency + " -Dfsteps=" + steps + " -
Dcalfile=" + calibrationFile + " -Dscanmode=REFL -
Dexports=csv -jar " + "\"" + Dir + "\"";
else if (scanMode == "TRAN")
ejecutable = "java -Dfstart=" + startFrequency + " -
Dfstop=" + stopFrequency + " -Dfsteps=" + steps + " -
Dcalfile=" + calibrationFile + " -Dscanmode=TRAN -
Dexports=csv -jar " + Dir;
try
if (File.Exists(Path + "\\vnaJ\\RFID.bat"))
File.Delete(Path + "\\vnaJ\\RFID.bat");
string[] Files = System.IO.Directory.GetFiles((Path +
"\\vnaJ\\"), "*.csv");
for (int i = 0; i < Files.Length; i++)
File.Delete(Files[i]);
// Creamos el fichero .bat //
StreamWriter sw = new StreamWriter(Path +
"\\vnaJ\\RFID.bat",false,Encoding.ASCII);
sw.WriteLine(ejecutable); sw.Close();
catch (Exception e)
mesureResult[0] = "false";
Console.WriteLine("Error Create BAT File: " + e);
goto salir;
Codi 18. Part 1 de la funció de mesura de Radiofreqüència
Memòria Descriptiva
36
Amb les mesures realitzades i guardades en un fitxer CSV, la funció “GetFrequency()”
llegeix del fitxer els valors corresponents a una freqüència i es guarden en una estructura
per posteriorment, amb la funció “Get_Measured_Parameter()” obtenir un valor concret.
try
java = Process.Start(Path + "\\vnaJ\\RFID.bat");
//Ejecutamos el fichero .bat
java.WaitForExit();
if (java.ExitCode != 0)
mesureResult.SetValue("false", 0);
java.Close();
goto salir;
else
java.Close();
mesureResult[0] = "true";
catch (Exception e)
Console.WriteLine("Test Error Exception: " + e);
mesureResult[0] = "false";
else
MessageBox.Show("Error: Archivos miniVNApro no
encontrados.", "Error", MessageBoxButtons.OK,
MessageBoxIcon.Error);
mesureResult[0] = "false";
goto salir;
salir:
maxRange[0] = "NA";
minRange[0] = "NA";
value[0] = "NA";
test.Add("Result", mesureResult);
test.Add("Value", value);
test.Add("MaxRange", maxRange);
test.Add("MinRange", minRange);
return test;
Codi 19. Part 2 de la funció de mesura de Radiofreqüència
Memòria Descriptiva
37
5.1.2.6 FlashMicrocontroller
Aquesta classe es va implementar per controlar els programadors de ST-Link i poder
programar Microcontroladors de la mateixa casa. Utilitza els drivers de ST-Link que
permeten enviar comandes al programador a través de comunicació VCP(Virtual Com
Port).
Es crea un procés per consola amb la classe “Process” de la llibreria “System.Diagnostics”
per executar una comanda que utilitza l’executable “ST-LINK_CLI.exe”. Al procés se li
passa el path de l’executable i la comanda a executar. Un cop es llença la comanda, es
criden les funcions “Wait_Finish_Erase” o “Wait_Finish_Programing” que van llegint per
consola el que printa el programador durant el procés de programació o borrat de memòria,
amb la funció “ReadLine()” de la classe “SteamReader”[8] (System.IO), fins a llegir el
string “Memory programmed in” en el cas de programar i “Flash memory erased.” en el
cas de borrat de memòria.
Les funcions que disposa la classe per cridar des de l’Excel són les següents:
Funció Descripció flashSTM32() Aquesta funció crea un procés i executa una comanda
per programar el Microcontrolador o fer un borrat de
memòria. S’indica el tipus de funció en el Paràmetre 1
(ME[Memori Erase]/P[Program]) i en cas de programar
(P), s’indica el fitxer .hex en el Paràmetre 2. Wait_Finish_Erase() Aquesta funció espera el final de borrat de memòria. Wait_Finish_Programing() Aquesta funció espera el final de programació del
Microcontrolador.
if (Plist[(int)MicroParam.ProgramMode] == "ME")
command = strCmdConnectToMicro + "FREQ=" +
Plist[(int)MicroParam.Frequency] + " -" +
Plist[(int)MicroParam.ProgramMode];
Console.WriteLine(path + command + "\n\r");
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = path;
startInfo.Arguments = command;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
cmd = Process.Start(startInfo);
mesureResult[0] = "true";
Console.WriteLine("Erase process has been launched
successfully");
Codi 20. Exemple de Procés per Borrat de Memòria del Microcontrolador
Memòria Descriptiva
38
else if (Plist[(int)MicroParam.ProgramMode] == "P")
if (File.Exists(Dir + Directory +
Plist[(int)MicroParam.FileName]))
command = strCmdConnectToMicro + "FREQ=" +
Plist[(int)MicroParam.Frequency] + " -" +
Plist[(int)MicroParam.ProgramMode] + " " + Directory +
Plist[(int)MicroParam.FileName] + " " +
Plist[(int)MicroParam.Address];
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = path;
startInfo.Arguments = command;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
cmd = Process.Start(startInfo);
mesureResult[0] = "true";
Console.WriteLine("Programming process has been launched
successfully");
StreamReader reader = cmd.StandardOutput;
bool Chip_Erased = false;
while (!reader.EndOfStream)
Line_Output = reader.ReadLine();
if (Line_Output == "Flash memory erased.")
Chip_Erased = true;
Full_Text_Output += Line_Output + ";";
StreamReader reader = cmd.StandardOutput;
while (!reader.EndOfStream)
Line_Output = reader.ReadLine();
Full_Text_Output += Line_Output + ";";
string[] FullText_String_Array = Full_Text_Output.Split(';'
bool Chip_Programmed = false;
//Escribimos el resultado del programador por consola a la vez
que analizamos si hay alguna anomalia al programar el micro
for (int i = 0; i < FullText_String_Array.Length; i++)
if ((FullText_String_Array[i].StartsWith("Memory programmed
in")))
Chip_Programmed = true;
Codi 21. Exemple de lectura del procés de Programació
Codi 23. Exemple de lectura del procés de Borrat de Memòria
Codi 22. Exemple Programació Microcontrolador
Memòria Descriptiva
39
5.1.2.7 WIFI_TERTest
Per gestionar les trames Wifi rebudes al servidor TCP, es va implementar una classe
anomenada WIFI_TERTest. Degut a temes de confidencialitat no es comentarà el codi de
la classe ja que és una classe específica que es va fer per a un client concret i que no forma
part de l’aplicació en sí.
Aquest classe és especifica per un tipus de trama Wifi composta per 11 camps:
ID VFW ER_CL_EN CLOSE_L OPEN_L_EN OPEN_L ERROR_L ERROR_L_READED REED REED_READED XOR
1 3 4 4 4 4 4 4 4 4 1
• ID: Identificador de la trama (1 byte)
• VFW: Versió de Firmware (3 bytes)
• ER_CL_EN: Bloc de dades 0 (4 bytes)
• CLOSE_L: Bloc de dades 1 (4 bytes)
• OPEN_L_EN: Bloc de dades 2 (4 bytes)
• OPEN_L: Bloc de dades 3 (4 bytes)
• ERROR_L: Bloc de dades 4 (4 bytes)
• ERROR_L_READED: Bloc de dades 5 (4 bytes)
• REED: Bloc de dades 6 (4 bytes)
• REED_READED: Bloc de dades 7 (4 bytes)
• XOR: CRC (1 byte)
Per obtenir les trames Wifi del servidor TCP, es va implementar una funció Callback per a
que el Thread del servidor TCP pogués cridar al rebre una trama Wifi. En aquest Callback
es guarda la trama Wifi en una estructura ordenada pels camps explicats anteriorment. En
cas de rebre més d’una trama, s’aniran guardant en l’estructura.
Per obtenir les dades d’una trama a través de l’Excel, s’utilitza una funció que se li passa
com a paràmetre 1, el ID corresponent a la trama que es vol obtenir les dades. Un cop es té
la trama seleccionada, es demanen per separat els diferents camps de la trama a través de
funcions que es criden en l’Excel. Aquestes funcions són les següents:
Funció Descripció Wifi_Data_Frame_Check() Aquesta funció serveix per comprovar si s’ha rebut una
trama amb el ID indicat en el Paràmetre 1. En el
Paràmetre 2 s’indica el temps màxim d’espera per a
rebre la trama. Measure_ID() Funció que retorna la ID de la trama. S’indica el valor
màxim de la ID en el Paràmetre 1 i el valor mínim de la
ID en el Paràmetre 2. Si el valor obtingut està entre els
límits, la funció retorna un True. En cas contrari, retorna
False. Measure_VFW() Funció que retorna el valor de la versió de Firmware.
S’indica el valor màxim de la versió en el Paràmetre 1 i
el valor mínim de la versió en el Paràmetre 2. Si el valor
obtingut està entre els límits, la funció retorna un True.
En cas contrari, retorna False. Measure_ER_CL_EN() Funció que retorna el valor del camp de dades 0.
Memòria Descriptiva
40
S’indica el valor màxim en el Paràmetre 1 i el valor
mínim en el Paràmetre 2. Si el valor obtingut està entre
els límits, la funció retorna un True. En cas contrari,
retorna False. Measure_CLOSE_L() Funció que retorna el valor del camp de dades 1.
S’indica el valor màxim en el Paràmetre 1 i el valor
mínim en el Paràmetre 2. Si el valor obtingut està entre
els límits, la funció retorna un True. En cas contrari,
retorna False. Measure_OPEN_L_EN() Funció que retorna el valor del camp de dades 2.
S’indica el valor màxim en el Paràmetre 1 i el valor
mínim en el Paràmetre 2. Si el valor obtingut està entre
els límits, la funció retorna un True. En cas contrari,
retorna False. Measure_OPEN_L() Funció que retorna el valor del camp de dades 3.
S’indica el valor màxim en el Paràmetre 1 i el valor
mínim en el Paràmetre 2. Si el valor obtingut està entre
els límits, la funció retorna un True. En cas contrari,
retorna False. Measure_ERROR_L() Funció que retorna el valor del camp de dades 4.
S’indica el valor màxim en el Paràmetre 1 i el valor
mínim en el Paràmetre 2. Si el valor obtingut està entre
els límits, la funció retorna un True. En cas contrari,
retorna False. Measure_ERROR_L_READED() Funció que retorna el valor del camp de dades 5.
S’indica el valor màxim en el Paràmetre 1 i el valor
mínim en el Paràmetre 2. Si el valor obtingut està entre
els límits, la funció retorna un True. En cas contrari,
retorna False. Measure_REED() Funció que retorna el valor del camp de dades 6.
S’indica el valor màxim en el Paràmetre 1 i el valor
mínim en el Paràmetre 2. Si el valor obtingut està entre
els límits, la funció retorna un True. En cas contrari,
retorna False. Measure_REED_READED() Funció que retorna el valor del camp de dades 7.
S’indica el valor màxim en el Paràmetre 1 i el valor
mínim en el Paràmetre 2. Si el valor obtingut està entre
els límits, la funció retorna un True. En cas contrari,
retorna False. Measure_XOR() Funció que retorna el valor del CRC. S’indica el valor
màxim en el Paràmetre 1 i el valor mínim en el
Paràmetre 2. Si el valor obtingut està entre els límits, la
funció retorna un True. En cas contrari, retorna False.
Memòria Descriptiva
41
5.1.2.8 MessageBox_Class
La classe MessageBox_Class és la última classe que es va implementar. Aquesta classe
serveix per generar finestres amb missatges per guiar al usuari durant tot el procés de
Validació. És molt útil en tests llargs o tests que no estan automatitzats i que és necessària
la interacció amb l’usuari en alguns passos.
Es va implementar una funció que crea una finestra de Windows amb una text instructiu
amb la classe “MessageBox”[9] i “AutoClosingMessageBox” de la llibreria
“System.Runtime”. Aquesta finestra es tanca un cop l’usuari ha premut la tecla OK, o salta
el TimeOut.
La funció que es pot cridar a través del Excel és la següent:
Funció Descripció Wait_Test_Instruction() Funció que crea una finestra de Windows amb dos butons
(YES/NO) que mostra un text instructiu amb pregunta.
S’indica en el Paràmetre 1 el missatge a mostrar i en el
Paràmetre 2 el TimeOut per mostrar el missatge.
public Dictionary<string, string[]> Wait_Test_Instruction(string[]
Plist)
//Dictionary Params//
. . .
DialogResult message;
string result = "";
Stopwatch sw = new Stopwatch();
int time = 0;
int TIMEOUT = Convert.ToInt32(Plist[(int)ParamsTer.TIMEOUT]);
try
message =
AnswerClosingMessageBox.Show(Plist[(int)ParamsTer.Function]
, "Information", TIMEOUT, MessageBoxButtons.YesNo);
if (message == DialogResult.Yes)
mesureResult[0] = "True";
else
mesureResult[0] = "False";
catch (Exception e)
Console.WriteLine("Test MessageBox_Class Error: " + e);
mesureResult[0] = "false";
. . .
return test;
Codi 24. Funció Wait_Test_Instruction() de la classe MessageBox_Class
Memòria Descriptiva
42
5.2 Model
La capa Model és l’encarregada de la lectura de l’Excel i de la crida de les funcions
necessàries per a realitzar el Test. En aquesta capa es fa ús del mètode “Reflection” per a
poder crear objectes de les classes dels dispositius configurats en l’Excel. Conté el Thread
principal que executa la funció que executa les funcions definides en l’Excel a través de
“Reflection”.
En aquesta capa també es gestiona el format del Report a extreure del Test i també tots els
paràmetres de l’Excel que influencien en el comportament del Test.
En aquesta capa es fa ús de diversos Callbacks per a enviar informació sobre l’estat del
Test a les classes de la capa superior (Vista).
5.2.1 Importació dels Excels
Per tal d’importar la informació dels Excels, es van utilitzar les classes de la llibreria
“Microsoft.Office.Interop.Excel”[10] que faciliten el procés de lectura d’un fitxer Excel.
Si parlem de la fulla 1, tal i com s’ha comentat anteriorment en l’apartat 3.2, es van
utilitzar 3 classes per guardar la informació de l’Excel:
• TestSequence: conté una llista d’objectes de la classe TestGroups
• TestGroups: conté una llista d’objectes de la classe TestCases
• TestCases: conté una llista d’arrays de Strings, on cada array és un Test Case i cada
posició de l’array és una columna de l’Excel.
D’aquesta manera, simplement accedint a la clase TestSequence és possible obtenir tota la
informació de la fulla 1 de l’Excel.
Memòria Descriptiva
43
public class TestSequence : DeviceList
public string String_CSV = ""; //Header CSV
public List<TestGroups> testGroup;
public TestSequence()
this.testGroup = new List<TestGroups>();
public void createNewTestGroup(string name)
testGroup.Add(new TestGroups(name));
public class TestGroups
public List<TestCases> testCase;
public string name;
public TestGroups(string name)
this.name = name;
this.testCase = new List<TestCases>();
public void createNewTestCase(string name)
testCase.Add(new TestCases(name));
public string getName()
return name;
public class TestCases
public List<Array> testStep;
public string name;
public TestCases(string name)
this.name = name;
testStep = new List<Array>();
public string getName()
return name;
Codi 25. Classes Fulla 1 Test Excel
Memòria Descriptiva
44
Per guardar els dispositius de la fulla 2 de l’Excel es van crear dues classes:
• Device: Classe que conté un array de strings de 20 posicions
• DeviceList: Classe que conté una llista d’objectes Device.
En un primer pas, es creen tants objectes Nulls com números de dispositius hi ha definits al
Excel i en cada objecte es guarda un array de Strings on les 9 primeres posicións de l’array
són els paràmetres de l’Excel. Es va crear un array de 20 posicions pensant en la
possibilitat futura de necessitar més paràmetres.
public class DeviceList
public List<Device> Devices;
public int frow; //Numero de filas
public DeviceList()
this.Devices = new List<Device>();
public void createNewDeviceList(object obj)
Devices.Add(new Device(obj));
public void setRows(int frow)
this.frow = frow;
public class Device
public object device;
public string[] paramArray = new string[20];
public Device(object obj)
this.device = obj;
public Device(string[] array)
this.paramArray = new string[20];
Codi 26. Classes Dispositius Fulla 2 Excel
Memòria Descriptiva
45
for (int i = 0; i < row; i++)
// ----- Get Constructor ----- //
Type testStep = Type.GetType("Test_TER.Controllers." +
devices.Devices[i].paramArray.GetValue(1).ToString());
//Ensamblado asociodo a la clase(namespace) + clase
ConstructorInfo ctor = testStep.GetConstructor(types);
// ----- Convert List to array ----- //
string[] aux = new string[20];
step = 0;
foreach (var value in devices.Devices[i].paramArray)
if (value == null)
break;
else
aux[step++] = value.ToString();
try
// ----- Invoke Constructor ----- //
object instance = ctor.Invoke(new object[] aux );
// ----- Save object ----- //
devices.Devices[i].device = instance;
catch(TargetInvocationException ex)
Console.WriteLine("Error al instanciar el constructor de la
clase " +
devices.Devices[i].paramArray.GetValue(1).ToString() + ex);
Codi 28. Mètode Reflection per a instanciar els objectes de l’Excel
Posteriorment, amb el mètode “Reflection” s’instancien els objectes. A partir del nom de la
classe s’obté el tipus de constructor. S’invoca el constructor i se li passen els paràmetres de
l’Excel per crear l’objecte de la classe amb la comunicació ja configurada, si el dispositiu
ho requereix.
// Devices classes Handler //
devices = new DeviceList();
devices.setRows(row); //Get number of rows
int step = 0;
object instance = null;
for (int i = 0; i < row; i++)
devices.createNewDeviceList(instance); // Creamos un objeto nullo
// ----- Save parameter into array ----- //
step = 0;
foreach (var value in auxValues[i])
devices.Devices[i].paramArray[step++] = value.ToString();
Codi 27. Exemple de creació d’objectes Nulls
Memòria Descriptiva
46
for (countTestGroup = 0; countTestGroup <
testSequence.testGroup.Count(); )
for (countTestCase = 0; countTestCase <
testSequence.testGroup[countTestGroup].testCase.Count(); )
jump_not_found = false;
for (countTestStep = 0; countTestStep <
testSequence.testGroup[countTestGroup].testCase[countTestCa
se].testStep.Count(); )
step = 0;
foreach (var value in
testSequence.testGroup[countTestGroup].testCase[count
TestCase].testStep[countTestStep])
updateParametersOfTheNextTestStepFunction(step+
+, value.ToString());
// Guardamos todos los parametros en Plist //
private void updateParametersOfTheNextTestStepFunction(int column,
string values)
Plist[column] = values.ToString();
if (column == (int)testStepSheet1.type_device)
GetDeviceClass(Plist[(int)testStepSheet1.type_device]);
Codi 29. Algoritme d’execució del Test
Aquests objectes es guarden en els objectes Nulls reservats en els passos anteriors.
D’aquesta manera, a través de la classe DeviceList tenim tots els objectes instanciats per
utilizar-los en el Test.
5.2.2 Execució del Test
Per tal d’executar el passos del Test es va crear una funció anomenada “TestTask()” que es
cridada a través d’un Thread des de la Vista, amb un bucle de 4 “for” que va cridant les
funcions a través del mètode “Reflection”. Aquest bucle recorre tots els objectes guardats a
la llista de la classe TestSequence fins a arribar al Test Step, és a dir, executa tots els Tests
Steps, de cada Test Case de cada Test Group.
La funció “updateParametersOfTheNextTestStepFunction” guarda els paràmetres de la
fulla 1 de l’Excel en un Array.
Codi 30. Funció updateParametersOfTheNextTestStepFunction
Memòria Descriptiva
47
5.2.2.1 Ús del mètode “Reflection”
Per cada Test Step guardat en la classe TestSequence, exceptuant les funcions amb símbol
dollar ($), es crida la funció “callingStepFunctionInProgress()” que és l’encarregada de
utilitzar el mètode “Reflection”.
Si el Test falla, es fa un salt a la fila indicada en la última columna de l’Excel.
else
testError = callingStepFunctionInProgress(GetParamArray(),
countTestGroup, countTestCase, countTestStep, testGroupFlag);
testGroupFlag = false;
if (testError)
jump_not_found = FindTestID(ref countTestGroup, ref
countTestCase, ref countTestStep,
Plist[(int)testStepSheet1.jump]);
if (jump_not_found)
break;
else
countTestStep++;
private bool FindTestID(ref int TestGroupCount, ref int TestCaseCount,
ref int TestStepCount, string jump_line)
for (int tg = 0; tg < testSequence.testGroup.Count(); tg++)
for (int tc = 0; tc <
testSequence.testGroup[tg].testCase.Count(); tc++)
for (int ts = 0; ts <
testSequence.testGroup[tg].testCase[tc].testStep.Coun
t(); ts++)
if (
testSequence.testGroup[tg].testCase[tc].testSte
p[ts].GetValue(1, 1).ToString() == jump_line)
TestGroupCount = tg; TestCaseCount = tc;
TestStepCount = ts; return false;
return true;
Codi 31. Crida a la funció callingStepFunctionInProgress
Codi 32. Funció per saltar de fila
Memòria Descriptiva
48
En la funció “callingStepFunctionInProgress()”, en primer lloc s’obté la informació i les
propietats de la classe a través del NameSpace de la classe i el nom de la classe.
A continuació, es busca en la llista ListDevices, l’objecte amb el mateix nom que l’indicat
en la columna B de la fulla 1 de l’Excel. Amb el Type de la classe, s’obtenen els atributs
de la classe juntament amb la funció indicada en la columna C de l’Excel, utilitzant la
classe “MethodInfo” de la llibreria “System.Reflection”.
Finalment amb l’objecte instanciat i els atributs de la classe, s’invoca la funció i se li
passen els 6 paràmetres de l’Excel.
Per poder tractar l’excepció del mètode “Reflection“ s’utilitza l’excepció
“TargetInvocationException”.
Com es pot veure, en la funció “callingStepFunctionInProgress()” també es gestionen els
reintents i el càlcul del temps d’execució amb la classe “StopWatch” (System.dll).
// ----- Get Constructor ----- //
Type testStep = Type.GetType("Test_TER.Controllers." + device_class);
//Ensamblado asociodo a la clase(namespace) + clase
ConstructorInfo ctor = testStep.GetConstructor(types);
var watch = System.Diagnostics.Stopwatch.StartNew(); //Start Time
if ( maxretries == 0 )
retries = -1;
while (retries < maxretries)
try
// ----- Get an instance ----- //
object inst =
GetObject(Plist[(int)testStepSheet1.type_device]); // inst
coge el valor del objeto ya instanciado y que estaba
guardado en la lista de objetos
//----- Get Method (function) ----- //
MethodInfo methodInfo =
testStep.GetMethod(Plist[(int)testStepSheet1.name_function]
);
// ----- Invoke with parameters ----- //
test = (Dictionary<string,
string[]>)methodInfo.Invoke(inst, new object[] ParamArray
); //Invoke method and return it as a Dictionary
Codi 33. Mètode Reflection per a la crida de funcions
Memòria Descriptiva
49
5.2.2.2 Interacció amb la Vista
Per a poder interactuar amb la capa de la Vista, es van crear funcions Callback que
modifiquen flags i retornen informació necessària per mostrar a l’usuari. Aquests
Callbacks són els següents:
Callback Descripció AddHandler_Reset_Control_Buttons() Reseteja els flags dels botons per habilitar-
los AddHandler_Reset_Final_Result_Test() Neteja la casella del resultat final del test
anterior AddHandler_Kill_Test_Process() Atura el Thread en cas d’acabar el Test o de
prémer el botó Stop AddHandler_Clear_Results() Neteja la finestra de passos del Test i el
temps AddHandler_Update_Final_Test() Retorna el resultat final del Test actual AddHandler_Update_Elapsed_TestTime() Retorna el temps d’execució del Test actual AddHandler_Update_Step_Values() Retorna el Test Group, Test Case, Test
Case, el número de la fila de l’Excel i tot el
Diccionari retornat per la funció cridada per
“Reflection” AddHandler_Enable_Test_Finalized() Activa el flag de final de Test AddHandler_Disable_Test_Finalized() Deshabilita el flag de final de Tets AddHandler_Get_Family() Retorna el nom de l’Excel AddHandler_Get_Reference() Retorna el valor de la Referència
5.2.2.3 Tractament de funcions dollar ($)
En la funció TestTask() també es gestionen les 3 funcionalitats amb símbol dolar ($):
• $START:
o Es reseteja el temps inicial del Test
o Es setegen els flags d’inici de Test
o Es criden els Callbacks referents a la capa de la Vista per netejar el resultat
final del Test
o Es crea el fitxer CSV
• $END:
o Es para el comptatge del temps d’execució del Test
o Es pinta el fitxer CSV
o S’activen els flags de final de Test
o Es criden els Callbacks referents a la capa de la vista per indicar el resultat
del Test i el temps.
• $WAITREFERENCE:
o Crida el Callback que retorna el valor de la casella “Reference”. Si conté un
string de 10 caràcters, continua el Test.
Memòria Descriptiva
50
if (Plist[(int)testStepSheet1.type_device] == "$START")
sw.Restart(); //Start Time
ResetFinalResultTest();
countTestStep++;
paintFlag = true;
CSV.Create(testSequence.String_CSV);
CSV.Add_Value(family); //Add family to CSV string
CSV.Add_Value(reference); //Add reference to CSV string
else if(Plist[(int)testStepSheet1.type_device] == "$END")
UpdateFinalTest();
sw.Stop(); //Stop Time
time =(double)sw.ElapsedMilliseconds; //Get Time
time = time / 1000;
ElapsedTime(time);
time = 0;
countTestStep++;
paintFlag = false;
if (testError == true)
Print_NOK_Report = true;
if (Stop_Test_Flag == false)
CSV.countRetries(reference);
CSV.Set_Values(FinalTestResult, testSequence.String_CSV,
family, reference); //Add values to CSV
Add_AfterEND_Value_HtmlReport = true;
FinalTestResult = true;
Stop_Test_Flag = false;//Resetamos el flag de detección pulsación
testError = false;
else if(Plist[(int)testStepSheet1.type_device] == "$WAITREFERENCE")
reference_value = false;
while (reference_value == false)
GetReference();
if ((reference != "") && (reference.Length == 10))
reference_value = true;
countTestStep++;
else
reference_value = false;
Codi 34. Tractament de les funcions especials dollar ($)
Memòria Descriptiva
51
5.2.2.3 Salts de files
Per fer més útil la gestió del Test, es va afegir la utilitat de salts de files. Aquesta
funcionalitat només s’executa quan el Test Step falla. Només és possible saltar cap
endavant, és a dir, no es pot tornar enrere en el Test. Per repetir els Tests Steps ja
existeixen els reintents que s’indiquen en la columna E de l’Excel. El número de la fila a
on es vol saltar s’indica en la columna N de l’Excel, i fa referència al número de la
columna A.
Si parlem de codi, tal i com es pot veure al quadre de text Codi 33, simplement
s’incrementen els comptadors de TestGroup, TestCase i TestStep en funció del salt de fila
indicat.
5.2.3 Resultats del Test
Al final de cada Test es poden generar dos tipus de Report segons ho haguem indicat en
l’Excel: HTML i CSV.
• HTML: Es genera un report en format HTML que incorpora el resultat de tots els
testos de l’Excel. Es crea el report al principi de la funció “TestTask()” i es tanca al
final de la funció, de tal manera que tot el que s’executa queda en el report sempre i
quan estigui indicat en el la columna F de l’Excel. Aquest report incorpora tota la
informació del Test per saber com i quan ha fallat, un report enfocat cap a
l’empresa Generation RFID.
• CSV: Es genera un report en format CSV amb només els resultats dels passos de
Tests que estiguin definits entre $START i $END, sempre i quan estigui indicat en
la columna F de l’Excel.
private void Report_Handler(string[] Plist, Dictionary<string,
string[]> test, int countretries, string[] time)
switch (Plist[(int)testStepSheet1.report])
case "BOTH":
terReport.fillReport(Plist, test, countretries,
time);
CSV.fillReport(Plist, test, countretries, time);
break;
case "HTML":
terReport.fillReport(Plist, test, countretries,
time); //Report
break;
case "CSV":
CSV.fillReport(Plist, test, countretries, time);
break;
case "NONE":
break;
Codi 35. Funció per generar el Report en funció del Paràmetre de la columna F de l’Excel
Memòria Descriptiva
52
Figura 16. Interfície Gràfica
5.3 Vista
La Vista és la capa més alta del projecte i és on es gestiona el Test. És la capa que conté la
interfície gràfica i on es produeix la interacció entre l’usuari i l’aplicació.
5.3.1 Interfície Gràfica
La interfície gràfica va ser aprofitada d’un altre projecte intern de l’empresa, així que no
l’he implementat jo personalment, però si que he tingut d’aprendre el seu funcionament i
comportament.
Es va utilitzar la API “Windows Forms”, de la plataforma “.NET Framework” que facilita
el disseny i la implementació. Aquesta API permet crear formularis amb controls(botons,
quadres de text, desplegables...) d’una manera molt senzilla. Cada control correspon a una
funció i quan l’usuari realitza una acció en el formulari, es crea un event que és gestionat
El disseny de la interfície és simple per tal de no carregar molt al usuari. S’ha de pensar
que aquesta aplicació està pensada per fer tests en una línia i per tant no sempre serà
utilitzada pel mateix usuari.
Memòria Descriptiva
53
Figura 20. Botó Play
Figura 21. Botó Stop
La interfície gràfica està composta per:
• Família: Quadre de text on es mostra el nom de l’Excel, que acostuma a ser el nom
del component a validar.
• Referència: Quadre de text on l’usuari escriu un valor de 10 caràcters en cas
d’haver definit en l’Excel la funció $WAITREFERENCE
• Control Automàtic/Manual: Botó per gestionar el funcionament del test. L’usuari
pot escollir si vol fer un sol test manual o vol llençar testos automàticament sense
parar.
• Play: Botó per començar el Test carregat.
• Stop: Botó per aturar el Test.
Figura 18. Quadre de Text Referència
Figura 17. Quadre de Text Família
Figura 19. Botó Manual/Autmàtic
Memòria Descriptiva
54
Figura 24. Comptadors
• Seqüència de Test: Quadre de Text on es mostren tots els passos de Test i el resultat
un cop executat. En cas de tenir Màxim i Mínim, també es mostren aquests valors.
En cas contrari, es mostra un “NA” (No Aplica).
• Resultat del Test: Quadre d’imatge on apareix una imatge de TestOK o TestNOK
en funció del resultat del Test.
• Número de DUTs Testejats: Quadre de Text on es mostra el número de Tests
realitzats.
• Número de DUTs OK: Quadre de Text on es mostra el número de Tests correctes
• Número de DUTs NOK: Quadre de Text on es mostra el número de Tests erronis
• RESET: Botó per resetejar els comptadors de Tests
Figura 22. Quadre de Seqüència de Test
Figura 23. Quadre Resultat del Test
Memòria Descriptiva
55
• Missatges d’Error/d’Estat: No té ús present però en una versió més nova del
projecte, es mostren estats i errors de l’aplicació. En la versió presentada, els errors
i excepcions es tracten en les capes inferiors enlloc de utilitzar “throws” i enviar els
errors i les excepcions cap a la Vista per poder-los mostrar en aquestes dues
finestres.
Per carregar l’Excel simplement s’ha d’obrir el desplegable “Archivo”, seleccionar “Abrir” i
buscar al directori del PC l’Excel corresponent.
Figura 25. Quadres de Missatges
Memòria Descriptiva
56
5.4 Comportament del Test
Per tal que sigui més senzill d’entendre tot el contingut explicat en l’apartat de Software,
s’ha definit un diagrama de flux del comportament del Test:
Figura 26. Diagrama de flux del funcionament del Test
Memòria Descriptiva
57
6 Hardware
6.1 Dispositius
Durant el desenvolupament del projecte van ser necessaris diversos dispositius Hardware
per tal de configurar les seves classes corresponents i per validar l’aplicació.
6.1.1 KMTronic USB Relay
El dispositiu KMTronic USB Relay és una placa de relés, que disposa de 2, 4 o 8 relés
segons el model. S’alimenta a 12V i utilitza relés RAS SERIES del fabricant Sun Hold de
dos posicions: Normalment Obert(NO) i Normalment Tancat(NC)
Es connecta al PC a través de USB utilitzant VCP (Virtual Com Port) per enviar comandes
que fan commutar els relés de la placa. Cada relé disposa d’un led per indicar el seu estat,
si està Normalment Obert el led està apagat, en cas d’estar Normalment Tancat el led està
encès.
6.1.2 IDM-8341
El IDM-8341 és un multímetre digital de precisió de la casa ISO-TECH. Permet
comunicar-se amb el PC utilitzant USB a través de VCP(Virtual Com Port). A través de
comandes, es pot controlar el dispositiu d’una manera ràpida i senzilla, per a poder fer
qualsevol tipus de mesura a l’abast d’un multímetre digital. A més, incorpora les
funcionalitats per a poder mesurar capacitats i temperatura.
Les característiques de mesura són les següents:
Funció Mesura Precisió Resolució
Màxima Corrent AC 10A ±0.5% 100nA
Màxim Voltatge AC 750V ±0.35% 100µV
Màxima Capacitat 50µF ±2% 0,001nF
Màxima Corrent DC 10A ±0.05% 100nA
Màxim Voltatge DC 1000V ±0.02% 100µV
Màxima Resistència 50MΩ ±0.1% 100mΩ
Freqüència màxima 100kHz _ _
6.1.3 MiniVNA Pro
El MiniVNA Pro és un mesurador de radiofreqüència (RF) de l’empresa Mini Radio
Solutions(MRS) que es connecta al PC via USB amb VCP(Virtual Com Port). Utilitza dos
executables JAVA( vnaJ-hl.3.1.5.jar i vnaJ.3.1.9.jar) que permeten controlar el mesurador
d’una manera més gràfica per l’usuari. També es pot controlar amb comandes a través de
Port Sèrie.
Memòria Descriptiva
58
Les característiques de mesura són les següents:
Funció Valor
Rang de freqüències 100kHz – 200MHz
Resolució 1Hz
Potència en mesures “Transmition” 90dB
Potència en mesures “Reflection” 50dB
6.1.4 ST-LINK V2
El ST-LINK V2 és un programador de la companyia STMicroelectronics per a
programació de Microcontroladors de la casa STM. Disposa de dos sortides de pins per a
poder programar Microcontroladors de 8 bits i 32 bits.
Es connecta amb USB i utilitza VCP(Virtual Com Port) per comunicar-se a través de Port
Sèrie.
6.1.5 Zebra GK420t
La zebra GK420t és una impressora d’etiquetes de la casa Zebra, amb impressió tèrmica.
Té una velocitat d’impressió de 5 pols/seg i una resolució de 203 dpi(punts per polsada).
Aquest impressora permet imprimir etiquetes simplement enviant les comandes a través de
Port Sèrie.
Es pot comunicar tan per USB com per Port Sèrie (RS232 directament). En l’aplicació
s’utilitza la comunicació Port Sèrie.
Memòria Descriptiva
59
7 Conclusions Si s’analitzen els objectius plantejats, es pot afirmar que el projecte s’ha aconseguit
satisfactòriament. S’ha creat una aplicació que llegeix d’un Excel els passos a realitzar en
un Test, controlant diferents dispositius que faciliten la validació. Aquesta aplicació és
senzilla i relativament ràpida per utilitzar-la en una línia. També s’han tingut en compte
millores futures alhora d’utilitzar el llenguatge i l’entorn de programació. Així doncs, de
cara a l’usuari el projecte ha contemplat tots els aspectes plantejats.
Si aprofundim en el codi, hi ha certs aspectes a millorar com per exemple el tracte de les
excepcions, que en aquesta versió es tracten en cada capa enlloc de tirar-les cap a la Vista a
través de “throw” i mostrar els errors en els quadres d’Estat/Error de la interfície gràfica.
En aquesta versió també hi ha un problema alhora de carregar Excels, ja que és necessari
tancar i obrir l’aplicació. Això és degut a que les comunicacions queden obertes i no es
tanquen fins que no es tanca l’aplicació. Aquests errors ja han sigut solucionats en noves
versions.
Si parlem d’aprenentatge, cal destacar que aquest projecte m’ha ajudat a entendre encara
millor la programació orientada a objectes i el funcionament de les diverses comunicacions
utilitzades. He descobert el potencial del llenguatge C# i les seves infinites possibilitats.
També he après com funciona el món de la validació i el funcionament de les eines
necessàries per a una bona validació de Hardware. Cal destacar que aquest projecte es va
fer en menys temps del previst i que l’esforç va ser gran, però tot i així l’aprenentatge ha
sigut molt extens.
En resum, aquest projecte ha sigut una oportunitat molt bona per millora i aprendre com a
enginyer i per entendre com funciona el món laboral. Dissenyar, implementar, validar i
solucionar errors ha sigut el dia a dia del projecte.
Memòria Descriptiva
60
8 Taula de Figures Figura 1. Logotip Generation RFID ...................................................................................... 4
Figura 2. Diagrama de l’estructura de l’Aplicació ................................................................ 5
Figura 3. Diagrama de l’estructura del Software ................................................................... 6
Figura 4. Estructura de compilació .NET Framework........................................................... 7
Figura 5. Estructura de l’Excel .............................................................................................. 9
Figura 6. Estructura Excel Fulla 1 ......................................................................................... 9
Figura 7. Exemple $START ................................................................................................ 10
Figura 8. Exemple $END .................................................................................................... 11
Figura 9. Exemple $WAITREFERENCE ........................................................................... 11
Figura 10. Estructura Excel Fulla 2 ..................................................................................... 11
Figura 11. Diagrama de flux de l’Aplicació ........................................................................ 13
Figura 12. Diagrama de Flux Capa Controlador ................................................................. 14
Figura 13. Diagrama de Flux Port Sèrie .............................................................................. 17
Figura 14. Diagrama de Flux CAN ..................................................................................... 19
Figura 15. Diagrama de Flux Servidor TCP ........................................................................ 22
Figura 16. Interfície Gràfica ................................................................................................ 52
Figura 17. Quadre de Text Família ...................................................................................... 53
Figura 18. Quadre de Text Referència................................................................................. 53
Figura 19. Botó Manual/Autmàtic ....................................................................................... 53
Figura 20. Botó Play ............................................................................................................ 53
Figura 21. Botó Stop ............................................................................................................ 53
Figura 22. Quadre de Seqüència de Test ............................................................................. 54
Figura 23. Quadre Resultat del Test .................................................................................... 54
Figura 24. Comptadors ........................................................................................................ 54
Figura 25. Quadres de Missatges ......................................................................................... 55
Figura 26. Diagrama de flux del funcionament del Test ..................................................... 56
Memòria Descriptiva
61
9 Taula de Codis Codi 1. Funció Port Sèrie Enviament de Trames ................................................................ 15
Codi 2. Codi de Recepció de Trames en Port Sèrie ............................................................. 16
Codi 3. Funció d’enviament de Trames CAN ..................................................................... 18
Codi 4. Funció de lectura de Trames CAN ......................................................................... 19
Codi 5. Configuració del Servidor TCP .............................................................................. 20
Codi 6. Thread de Lectura del Servido TCP ....................................................................... 21
Codi 7. Funció per enviar trames Wifi ................................................................................ 22
Codi 8. Exemple Constructor amb Port Sèrie ..................................................................... 23
Codi 9. Algoritme de recerca del port a través del número de sèrie.................................... 24
Codi 10. Exemple de funció Reflection .............................................................................. 25
Codi 11. Exemple Funció Activar Relé ............................................................................... 27
Codi 12. Callback CAN ....................................................................................................... 27
Codi 13. Exemple funció Mesura Voltatge DC ................................................................... 29
Codi 14. Funció VariableStringHandle per substituir paraules dollar ($) ........................... 30
Codi 15. Exemple funció per imprimir etiquetes ................................................................ 31
Codi 16. Callback Port Sèrie ............................................................................................... 32
Codi 17. Funció per Activar Relé ........................................................................................ 33
Codi 18. Part 1 de la funció de mesura de Radiofreqüència ................................................ 35
Codi 19. Part 2 de la funció de mesura de Radiofreqüència ................................................ 36
Codi 20. Exemple de Procés per Borrat de Memòria del Microcontrolador ....................... 37
Codi 21. Exemple de lectura del procés de Programació .................................................... 38
Codi 22. Exemple Programació Microcontrolador ............................................................. 38
Codi 23. Exemple de lectura del procés de Borrat de Memòria .......................................... 38
Codi 24. Funció Wait_Test_Instruction() de la classe MessageBox_Class ........................ 41
Codi 25. Classes Fulla 1 Test Excel .................................................................................... 43
Codi 26. Classes Dispositius Fulla 2 Excel ......................................................................... 44
Codi 27. Exemple de creació d’objectes Nulls .................................................................... 45
Codi 28. Mètode Reflection per a instanciar els objectes de l’Excel .................................. 45
Codi 29. Algoritme d’execució del Test .............................................................................. 46
Codi 30. Funció updateParametersOfTheNextTestStepFunction ....................................... 46
Codi 31. Crida a la funció callingStepFunctionInProgress ................................................. 47
Codi 32. Funció per saltar de fila ........................................................................................ 47
Codi 33. Mètode Reflection per a la crida de funcions ....................................................... 48
Codi 34. Tractament de les funcions especials dollar ($) .................................................... 50
Codi 35. Funció per generar el Report en funció del Paràmetre de la columna F de l’Excel
............................................................................................................................................. 51
Memòria Descriptiva
62
10 Annexes
10.1 Codi
Degut a que el codi del projecte és molt extens i per temes de confidencialitat, es farà
referència a les parts on es fa servir el mètode “Reflection”:
TestTask(); TestProcess.cs (Model)
public void TestTask()
int countTestGroup = 0;
int countTestCase = 0;
int countTestStep = 0;
int step=0;
bool testGroupFlag = false;
bool testError = false;
string SpecialSTR;
bool jump_not_found = false;
Stopwatch sw = new Stopwatch();
double time = 0;
bool reference_value = false;
DisableFinalTest();
ClearResult(); //Clear results of MainWindows
// Get Parameters for Reports //
GetFamily();
GetReference();
for (;;)
if (!readed_family)
try
CSV.getLastFamily(family);
readed_family = true;
catch
readed_family = false;
Console.WriteLine("No existe el CSV");
this.terReport = new TER_Report("TReport",
"Report\\TestOK\\", "Report\\TestNOK\\");
terReport.createReport(family, reference);
CSV.Create(testSequence.String_CSV);
testArray.Clear();
for (countTestGroup = 0; countTestGroup <
testSequence.testGroup.Count(); )
for (countTestCase = 0; countTestCase <
testSequence.testGroup[countTestGroup].testCase.Count()
; )
jump_not_found = false;
Memòria Descriptiva
63
for (countTestStep = 0; countTestStep <
testSequence.testGroup[countTestGroup].testCase[c
ountTestCase].testStep.Count(); )
step = 0;
foreach (var value in
testSequence.testGroup[countTestGroup].test
Case[countTestCase].testStep[countTestStep]
)
updateParametersOfTheNextTestStepFunc
tion(step++, SpecialSTR);
if (Plist[(int)testStepSheet1.type_device] ==
"$START")
sw.Restart(); //Start Time
ResetFinalResultTest();
countTestStep++;
paintFlag = true;
// Create CSV Report Table //
CSV.Create(testSequence.String_CSV);
CSV.Add_Value(family); //Add family to CSV
string
CSV.Add_Value(reference); //Add reference
to CSV
else if(Plist[(int)testStepSheet1.type_device] ==
"$END")
UpdateFinalTest();
sw.Stop(); //Stop Time
time =(double)sw.ElapsedMilliseconds; //Get
Time
time = time / 1000;
ElapsedTime(time);
time = 0;
countTestStep++;
paintFlag = false;
if (testError == true)
Print_NOK_Report = true;
if (Stop_Test_Flag == false)
CSV.countRetries(reference);
CSV.Set_Values(FinalTestResult,
testSequence.String_CSV, family,
reference); //Add values to CSV
Add_AfterEND_Value_HtmlReport = true;
FinalTestResult = true;
Memòria Descriptiva
64
//Resetamos el flag de detección pulsación
stop
Stop_Test_Flag = false;
//Resetamos el flag de detección pulsación
stop
testError = false;
else if(Plist[(int)testStepSheet1.type_device] ==
"$WAITREFERENCE")
reference_value = false;
while (reference_value == false)
GetReference();
if ((reference != "") &&
(reference.Length == 10))
reference_value = true;
countTestStep++;
else
reference_value = false;
else
testError =
callingStepFunctionInProgress(GetParamArray
(), countTestGroup, countTestCase,
countTestStep, testGroupFlag);
testGroupFlag = false;
if (testError)
jump_not_found = FindTestID(ref
countTestGroup, ref countTestCase,
ref countTestStep,
Plist[(int)testStepSheet1.jump]);
if (jump_not_found)
break;
else
countTestStep++;
if ( (jump_not_found) && (testError) )
break;
if (!testError)
countTestCase++;
Memòria Descriptiva
65
testGroupFlag = true;
if ((jump_not_found) && (testError))
break;
if (!testError)
countTestGroup++;
CSV.Clear_Values();
//Cerramos el Report HTML.
terReport.closeReport(Print_NOK_Report);
//Reseteamos el flag que nos mantiene el valor de si ha habido
error o no después del &END
Print_NOK_Report = false;
if (Mode) //Si esta en Automatico
ClearResult();
countTestGroup = 0;
testGroupFlag = false;
reference_value = false;
else //Si esta en manual o se aprieta el stop
readed_family = false;
EnableFinalTest();
UpdateControlButtons();
KillThread();
break;
Aquesta funció es cridada a través d’un Thread. Executa els tests i crida les funcions
definides en l’Excel a través del mètode “Reflection”. La funció
“callingStepFunctionInProgress” és l’encarregada d’executar el mètode “Reflection”.
Memòria Descriptiva
66
callingStepFunctionInProgress(); TestProcess.cs (Model)
private bool callingStepFunctionInProgress(string[] ParamArray, int
countTestGroup, int countTestCase, int countTestStep, bool testGroupFlag)
bool success = false;
int retries = 0;
int maxretries =
Convert.ToInt16(Plist[(int)testStepSheet1.retries]);
bool Tresult = false;
int countretries = 0;
string[] time = new string[5];
bool testError = false;
Type[] types = new Type[1];
types[0] = typeof(object[]);
// ----- Get Constructor ----- //
Type testStep = Type.GetType("Test_TER.Controllers." +
device_class); //Ensamblado asociodo a la clase(namespace) + clase
ConstructorInfo ctor = testStep.GetConstructor(types);
var watch = System.Diagnostics.Stopwatch.StartNew(); //Start Time
if ( maxretries == 0 )
retries = -1;
while (retries < maxretries)
try
// ----- Get an instance ----- //
object inst =
GetObject(Plist[(int)testStepSheet1.type_device]); //
inst coge el valor del objeto ya instanciado y que
estaba guardado en la lista de objetos
//----- Get Method (function) ----- //
MethodInfo methodInfo =
testStep.GetMethod(Plist[(int)testStepSheet1.name_funct
ion]);
// ----- Invoke with parameters ----- //
test = (Dictionary<string,
string[]>)methodInfo.Invoke(inst, new object[]
ParamArray ); //Invoke method and return it as a
Dictionary
testArray.Add(test);
string[] name = new string[5];
Tresult = testResult(test);
if (Tresult == true) //Comrpobamos el resultado del
test
Console.WriteLine("Test OK");
testError = false;
Memòria Descriptiva
67
// Si es nuevo TestGroup creamos otra tabla //
if (testGroupFlag)
terReport.newStepGroup();
testGroupFlag = false;
countretries = retries;
retries = maxretries;
else
if ((maxretries-1) == retries)
FinalTestResult = false;
Console.WriteLine("Test Error, reattempt " +
(retries + 1));
if (maxretries > 0)
retries++;
testError = true;
catch (Exception e)
Console.WriteLine("Error" + e + ", reattempt " +
(retries + 1));
if (maxretries > 0)
retries++;
testDelay(Plist[(int)testStepSheet1.timeDelay]); //Time Delay
entre test
watch.Stop(); //Stop Time
var elapsedMs = watch.ElapsedMilliseconds; //Get Time
time[0] = Convert.ToString(elapsedMs); //Convert time to
miliseconds
try
test.Add("Time", time);
// Comprobamos si tenemos que añadir valores al Report/CSV
if (Stop_Test_Flag == false)
Report_Handler(Plist, test, countretries, time);
else
if (Add_AfterEND_Value_HtmlReport == true)
Report_Handler(Plist, test, countretries, time);
Add_AfterEND_Value_HtmlReport = false;
Memòria Descriptiva
68
UpdateValues(countTestGroup, countTestCase, countTestStep,
Convert.ToInt16(Plist[(int)testStepSheet1.testStepIndex]) -
1, paintFlag, test);
catch
Console.WriteLine("Null Dictionary");
testError = true;
return testError;
Aquesta funció és cridada per cada fila del Test si no és cap funció dollar ($). En aquesta
funció es criden les funcions a través del mètode “Reflection”, es gestiona la comptabilitat
del temps i s’afegeix el resultat del pas del Test si es cau. Si el pas del Test ha passat la
validació satisfactòriament retorna un booleà True. En cas contrari, retorna un booleà
False.
Memòria Descriptiva
69
DevicesConfiguration(); DeviceConfig.cs (Model)
public DeviceList DevicesConfiguration()
int row = devices.frow;
int step = 0;
Console.WriteLine("Openning connections with devices. " +
row.ToString() + " devices found");
for (int i = 0; i < row; i++)
Type[] types = new Type[1];
types[0] = typeof(object[]);
// ----- Get Constructor ----- //
Console.WriteLine("Connecting to " +
devices.Devices[i].paramArray.GetValue(1).ToString());
Type testStep = Type.GetType("Test_TER.Controllers." +
devices.Devices[i].paramArray.GetValue(1).ToString());
//Ensamblado asociodo a la clase(namespace) + clase
ConstructorInfo ctor = testStep.GetConstructor(types);
// ----- Convert List to array ----- //
string[] aux = new string[20];
step = 0;
foreach (var value in devices.Devices[i].paramArray)
if (value == null)
break;
else
aux[step++] = value.ToString();
try
// ----- Invoke Constructor ----- //
object instance = ctor.Invoke(new object[] aux );
// ----- Save object ----- //
devices.Devices[i].device = instance;
catch(TargetInvocationException ex)
Console.WriteLine("Error al instanciar el constructor
de la clase " +
devices.Devices[i].paramArray.GetValue(1).ToString() +
ex);
return devices;
Aquesta és la funció que instancia els dispositius de la fulla 2 de l’Excel.
Memòria Descriptiva
70
11 Referències [0] https://msdn.microsoft.com/es-es/library/f7ykdhsy(v=vs.110).aspx
[1] https://msdn.microsoft.com/es-es/library/system.io.ports.serialport(v=vs.110).aspx
[2] http://www.peak-system.com/produktcd/Develop/PC%20interfaces/Windows/PCAN-
Basic%20API/Include/PCANBasic.cs
[3] https://msdn.microsoft.com/es-es/library/system.net.sockets.socket(v=vs.110).aspx
[4] https://msdn.microsoft.com/es-
es/library/system.management.managementobjectsearcher(v=vs.110).aspx
[5] https://msdn.microsoft.com/es-
es/library/system.management.managementobject(v=vs.110).aspx
[6] https://msdn.microsoft.com/es-es/library/system.io.streamwriter(v=vs.110).aspx
[7] https://msdn.microsoft.com/es-es/library/system.diagnostics.process(v=vs.110).aspx
[8 ] https://msdn.microsoft.com/es-es/library/system.io.streamreader(v=vs.110).aspx
[9] https://msdn.microsoft.com/es-es/library/system.windows.forms.messagebox(v=vs.110).aspx
[10] https://coderwall.com/p/app3ya/read-excel-file-in-c