Francesc Gistau Queralt - deeea.urv.catdeeea.urv.cat/public/PROPOSTES/pub/pdf/2499pub.pdf ·...

70
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

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