tesis 1 de proyecto de grado biometrico
Post on 08-Jan-2016
36 Views
Preview:
DESCRIPTION
TRANSCRIPT
-
Universidad de Costa Rica Facultad de Ingeniera
Escuela de Ingeniera Elctrica
IE 0502 Proyecto Elctrico
Diseo e implementacin de un sistema de registro de personas mediante la identificacin a partir de
la huella dactilar
Por:
Luis Alfonso Castro Leiva
Ciudad Universitaria Rodrigo Facio Noviembre del 2009
-
ii
Diseo e implementacin de un sistema de registro de personas mediante la identificacin a partir de
la huella digital
Por:
Luis Alfonso Castro Leiva
Sometido a la Escuela de Ingeniera Elctrica de la Facultad de Ingeniera
de la Universidad de Costa Rica como requisito parcial para optar por el grado de:
BACHILLER EN INGENIERA ELCTRICA
Aprobado por el Tribunal:
_________________________________ Ing. Rodrigo Garca Len
Profesor Gua
_________________________________ _________________________________ Ing. Lucky Lochi Yu Lo Ing. Teodoro Willink Castro Profesor lector Profesor lector
-
iii
DEDICATORIA
A Dios, A mi familia y amigos,
que me han acompaado en el largo camino
-
iv
RECONOCIMIENTOS
Un reconocimiento especial a mis padres por su gran ayuda durante toda mi vida.
-
v
NDICE GENERAL
NDICE GENERAL ........................................................................................... v
NDICE DE FIGURAS ...................................................................................viii
NOMENCLATURA .......................................................................................... ix
RESUMEN ........................................................................................................... x
CAPTULO 1: Introduccin ............................................................................. 1
1.1 Introduccin ................................................................................................................1
1.2 Justificacin ................................................................................................................2
1.3 Presentacin del problema a resolver........................................................................ 3
1.4 Objetivos .....................................................................................................................4
1.1.1 Objetivo general ................................................................................................. 4
1.1.2 Objetivos especficos ......................................................................................... 4
1.5 Metodologa ................................................................................................................5
CAPTULO 2: Desarrollo terico .................................................................... 6
2.1 Principios de reconocimiento biomtrico mediante huellas dactilares ...................6
2.1.1 Caractersticas Globales..................................................................................... 6
2.1.2 Caractersticas locales........................................................................................ 8
2.2 One Touch for Windows SDK C/C++ Edition ..................................................9
2.3 El API de DigitalPersona. ..........................................................................................9
2.4 El IDE de desarrollo Visual C++ 2005 ...................................................................12
2.5 El Software WampServer.........................................................................................13
2.5.1 El servidor HTTP, Apache ..............................................................................13
-
vi
2.5.2 El servidor de Bases de datos, MySQL ..........................................................14
2.5.3 El interpretador PHP ........................................................................................14
2.6 El API C de MySQL ................................................................................................14
2.7 AJAX.........................................................................................................................15
CAPTULO 3: Trabajo previo al desarrollo del software ......................... 18
3.1 El lector de huellas dactilares U.Are.U 4500 de DigitalPersona...........................18
3.2 Eleccin la plataforma de Desarrollo. .....................................................................19
3.3 Eleccin del entorno integrado de desarrollo .........................................................20
3.4 Visin general del CRB ...........................................................................................21
3.5 Estructura de la base de datos..................................................................................23
CAPTULO 4: Cliente de comunicacin con el lector de huellas digitales
CRB. .................................................................................................................... 25
4.1 Modo de registro de nuevo personal .......................................................................28
4.2 Modo de control de acceso ......................................................................................29
CAPTULO 5: Interfaz para la administracin de bases de datos CRB. 32
CAPTULO 6: Conclusiones y recomendaciones ........................................ 37
6.1 Conclusiones.............................................................................................................37
6.2 Recomendaciones .....................................................................................................38
BIBLIOGRAFA............................................................................................... 40
APNDICE A: Cdigo del cliente de comunicacin con el lector de
huellas dactilares. .............................................................................................. 41
A.1. Archivo CRB.cpp .....................................................................................................41
A.2. Archivo Form1.h ......................................................................................................43
A.3. Archivo Verform.h ...................................................................................................47
A.4. Archivo Verform.cpp ...............................................................................................52
-
vii
A.5. Archivo enroll.h........................................................................................................58
A.6. Archivo enroll.cpp....................................................................................................66
APNDICE B: Cdigo de la interfaz para administracin de bases de
datos CRB........................................................................................................... 73
B.1. Archivo cliente.php ..................................................................................................73
B.2. Archivo ajax.js..........................................................................................................75
B.3. Archivo query_name.php.........................................................................................77
B.4. Archivo query_apellido1.php ..................................................................................78
B.5. Archivo query_apellido2.php ..................................................................................79
B.6. Archivo query_cedula.php.......................................................................................80
B.7. Archivo query_marcas.php ......................................................................................81
B.8. Archivo query_eliminar.php....................................................................................82
Apndice C: Sentencia de SQL para la creacin de la base de datos
crb_db1. .............................................................................................................. 84
Apndice D: Funciones del Dispositivo utilizas. ........................................... 85
2.7.1 Funciones de extraccin...................................................................................89
2.7.2 Funciones de comparacin ..............................................................................91
ANEXOS............................................................................................................. 93
-
viii
NDICE DE FIGURAS
Figura 2.1 Ejemplo de rea patrn [3] ................................................................................... 7
Figura 2.2 Ejemplo de Delta [3]............................................................................................. 7
Figura 2.3 Patrones bsicos de huellas.[3] ............................................................................ 8
Figura 3.1. Lector de huellas digitales U.are.U 4500 .........................................................19
Figura 3.2. Diagrama modular de CRB...............................................................................22
Figura 4.1. Ventana principal del CRB. ..............................................................................25
Figura 4.2. Ventana del modo de registro de nuevo personal ............................................26
Figura 4.3. Diagrama de flujo de CRB.cpp.........................................................................27
Figura 4.4. Niveles de abstraccin del programa CRB. .....................................................28
Figura 4.5. Diagrama de flujo del almacenamiento de informacin. ................................29
Figura 4.6. Ventana del modo de control de acceso ...........................................................30
Figura 5.1. Mdulos de la Interfaz Web..............................................................................32
Figura 5.2. Resultado mostrado por el navegador Web......................................................33
Figura 5.3. Resultados de bsqueda.....................................................................................34
Figura 5.4. Resultados del Registro de marcas de personal ...............................................35
Figura 5.5. Eliminacin de un usuario.................................................................................36
-
ix
NOMENCLATURA
IDE Integrated development environment.
SDK Software developmet ki.t
API Aplication programming interface.
HTTP Hypertext Tranfer protocol.
PHP PHP: Hypertext preprocessor.
GPL General Public License.
AJAX Asynchronous JavaSript + XML.
RAD Rapid Application development.
MingW Minimalist GNU for Windows
GCC GNU Compiler Collection.
-
x
RESUMEN
En el presente proyecto se aborda la creacin de un sistema que registra las entradas
y salidas de personal en alguna empresa o institucin mediante la identificacin de su
huella dactilar, siguiendo una metodologa de bsqueda de soluciones y eleccin de la de
mejor ajuste a las necesidades y una programacin modular. El resultado obtenido es un
sistema funcional en sus aspectos ms bsicos, con los suficientes requerimientos para ser
una versin alfa y con la necesidad de darle seguimiento para obtener un producto con
mejor acabado. En conclusin, se logr alcanzar la totalidad de los objetivos planteados y
se recomienda seguir con un proceso de mejoramiento de los resultados obtenidos.
-
1
CAPTULO 1: Introduccin
1.1 Introduccin
Cuando los seres humanos interactan con otras personas, la identificacin se
realiza por caractersticas como su apariencia fsica. En caso de que una prueba de la
identidad de la persona sea requerida, se recurre a algn tipo de tarjeta de identificacin,
como la cdula de identidad, el pasaporte o incluso la firma. Sin embargo, tcnicas de
identificacin pueden ser fcilmente falsificables. Por este motivo se desarroll la
biometra, ciencia que estudia la identificacin de personas por medio de caractersticas
anatmicas. La gran ventaja de la identificacin biomtrica radica en que las caractersticas
analizadas son prcticamente irrepetibles en diferentes seres humanos y la falsificacin de
las mismas es extremadamente difcil.
Por este motivo, el desarrollo de soluciones biomtricas en el rea digital ha tenido
un enorme desarrollo, especialmente en la identificacin mediante huellas dactilares, palma
de la mano y el iris. Esto trae consigo grandes ventajas en especial en el rea de control de
acceso y seguridad en empresas e instituciones, adems del control de asistencia de
personal.
-
2
1.2 Justificacin
Cuando una empresa es de gran tamao y sus empleados son muchos, la prdida de
diez o quince minutos en la hora de entrada de varios de sus empleados puede
contabilizarse en gran cantidad de horas perdidas y retrasos en el inicio de las operaciones
de la empresa, lo cual se traduce al final en grandes prdidas econmicas. Adems la
existencia de ciertos puestos de trabajo que no pueden estar vacantes, ni siquiera por
algunos minutos, motiva al control de entradas y salidas de personal a los puestos de
trabajo.
El desarrollo del pas se sustenta en su capacidad para producir y dar respaldo a esta
produccin, por esto es importante que se motive la creacin de soluciones para las
necesidades del sector productivo del pas por parte del personal calificado existente en
nuestro propio territorio. Las soluciones que se pretenden construir en este proyecto buscan
potencializar las capacidades de las empresas nacionales y contribuir al desarrollo.
Estos motivos son suficientes para justificar el diseo e implementacin de un
sistema de registro de personas mediante huellas dactilares y dar cabida a la elaboracin de
este proyecto.
-
3
1.3 Presentacin del problema a resolver
El problema que se aborda en este trabajo es la creacin de un programa de
computadora que permita el control de entradas y salidas de personal a una institucin o
empresa. Este control se realiza por medio de un hardware especializado capaz de registrar
huellas dactilares y realizar comparaciones para determinar si existe concordancia entre
huellas guardadas en una base de datos y el personal que pretende hacer ingreso a las
instalaciones. Por este motivo el programa desarrollado debe ser capaz de interactuar con
este hardware para adquirir la informacin sobre las huellas digitales del personal y
guardarlo junto con la informacin pertinente dentro de una base de datos. Tambin debe
ser capaz de realizar la comparacin y tomar decisiones sobre su resultado, ya sea registrar
la entrada o salida del personal o no. Por ltimo se busca que el personal encargado de los
recursos humanos tenga una forma fcil de accesar a toda la informacin personal, como
nombre o departamento de los trabajadores o de la entrada y salida de los mismos a las
instalaciones, y que la forma en que el personal de recursos humanos pueda realizar estas
consultas sea por la va de Internet.
Por este motivo, se busca que el programa tenga una orientacin modular, y de esta
forma poder enfocarse en sectores especficos del programa por separado, siguiendo el
viejo adagio divide y vencers.
-
4
1.4 Objetivos
1.1.1 Objetivo general
Conformar un sistema de registro de personas mediante la identificacin a partir de
la huella dactilar.
1.1.2 Objetivos especficos
Realizar un estudio acerca de las tecnologas existentes en la identificacin de
personas mediante huella dactilar.
Estructurar una solucin persiguiendo la versatilidad y fcil adopcin de empresas o
individuos interesados.
Programar una aplicacin multiplataforma que interacte con el hardware
especializado para la identificacin mediante huella dactilar.
Implementar una interfaz Web para la administracin y consulta del registro de
personas.
Elaborar manuales e instructivos de capacitacin para el uso del sistema.
-
5
1.5 Metodologa
Se indagar sobre las opciones que existen en el mercado para soluciones
biomtricas y el hardware existente para tales fines, en miras de la eleccin de la
mejor opcin. Tomando en cuenta precio, factibilidad de uso del hardware para
crear nuevas aplicaciones desde cdigo fuente y disponibilidad de compra desde
Costa Rica.
Se seleccionar y adquirir el hardware requerido junto con las herramientas de
programacin necesarias para la creacin de nuevas aplicaciones.
Se seleccionar la plataforma de operacin (sistema operativo) en la cual se crear
la aplicacin y el IDE sobre el cual se desarrollar la aplicacin.
Se crear una la aplicacin mediante un proceso de pruebas y depuracin de errores
del cdigo elaborado, que cumpla con necesidades planteadas
Se formular un manual del usuario para la aplicacin desarrollada.
-
6
CAPTULO 2: Desarrollo terico
2.1 Principios de reconocimiento biomtrico mediante huellas
dactilares
Los dedos tienen superficies rugosas que permiten a los seres humanos tener ms
friccin para tomar objetos y sostenerse de superficies sin deslizamientos. Estas
rugosidades forman patrones que son prcticamente nicos e irrepetibles en los seres
humanos. La identificacin de personas se realiza por medio de dos caractersticas en estos
patrones: caractersticas globales y caractersticas locales.
Las caractersticas globales en las huellas dactilares son aquellas que se pueden
observar a simple vista, mientras que las caractersticas locales son llamadas puntos de
minutia. El arreglo bidimensional de la posicin de los puntos de minutia es utilizado en los
algoritmos de reconocimiento debido a que diferentes personas pueden tener caractersticas
globales similares, mientras que es muy poco probable que dos personas tengan arreglos de
puntos de minutia similares, adems de tener la ventaja de que un patrn de este tipo puede
ser cuantificable, lo cual hace esta tcnica candidata ideal para ser implementada de forma
digital.
2.1.1 Caractersticas Globales
Algunos tipos de caractersticas globales son el rea patrn, la delta y el patrn
bsico, aunque existen muchas otras que ayudan a la clasificacin manual de las huellas
digitales. El rea patrn es el rea principal donde se incluyen la mayora de las
caractersticas globales, un ejemplo de esta rea se muestra en la figura 2.1.
-
7
Figura 2.1 Ejemplo de rea patrn [3]
La delta es un punto de bifurcacin abrupta o encuentro de lneas digitales donde se
pueden formar puntos o fragmentos cortos de lnea, un ejemplo de una delta se muestra en
la figura 2.2.
Figura 2.2 Ejemplo de Delta [3]
El patrn bsico de las huellas es por as decirlo, la forma adoptan las lneas. Entre
las ms comunes estn el arco, el lazo, y el remolino, los cuales se muestran en la figura 2.3
en ese orden respectivo.
-
8
Figura 2.3 Patrones bsicos de huellas.[3]
2.1.2 Caractersticas locales.
Las lneas que conforman una huella digital no son continuas ni rectas, stas
generalmente se rompen, dividen, interrumpen y cambian de direccin. Los puntos donde
las lneas sufren esa clase de cambios y que proveen informacin distinguible, perdurable y,
ms importante an, cuantificable, son los puntos de minutia. Estos puntos tan importantes
para el reconocimiento digital se clasifican segn su tipo, su orientacin, su frecuencia
espacial, su curvatura y su posicin.
Segn su tipo los puntos de minutia pueden ser clasificados como:
Fin de lnea
Bifurcacin de lnea en dos.
Isla o punto. Es una lnea que empieza y acaba en un trayecto muy corto.
Encapsulamiento. Se produce cuando una lnea se divide y rpidamente se
vuelve a juntar.
-
9
2.2 One Touch for Windows SDK C/C++ Edition
A continuacin se har un breve resumen del SDK utilizado para el desarrollo del
trabajo, el cual fue escogido por ser la herramienta de software que permite el desarrollo de
aplicaciones con el lector de huellas seleccionado despus del estudio de tecnologas y
posibilidad de implementacin en el trabajo.
El paquete de desarrollo de software SDK, One Touch para Windows C/C++
Edition, versin 1.4, es el paquete que contiene todos los elementos necesarios para el
desarrollo de una aplicacin que interacte con los lectores de huellas digitales de
DigitalPersona, incluida la interfaz de programacin de aplicaciones o API, las libreras
estticas y dinmicas requeridas para comunicarse con el hardware desde un nivel de
abstraccin ms alto (como lo es el lenguaje C++) y los controladores requeridos por el
sistema operativo para el control del hardware. La instalacin de este paquete se encuentra
explicada detalladamente en la gua del desarrollador incluida en el mismo paquete, y es en
este mismo documento donde se explica el manejo de las funciones del API y su adecuado
uso.
2.3 El API de DigitalPersona.
La interfaz de programacin de aplicaciones de DigitalPersona es la que realmente
facilita la interaccin del programador con los lectores de huellas digitales de
DigitalPersona. Est constituida por un conjunto de funciones que, de ser llamadas
adecuadamente, permiten obtener resultados tangibles en el programa desarrollado.
-
10
Para hacer uso del API se deben agregar libreras estticas en el linker del
compilador a utilizar, para que las llamadas a estas libreras que se encuentran en los
archivos de encabezado, que tambin deben ser agregados, sean comprendidas por el
compilador
El API se encuentra dividido en dos: el ncleo y un encapsulamiento que crea una
interfaz de usuario del API. Este encapsulamiento (wrapper) consiste en dos funciones
DPEnrollUI y DPVerifyUI. Estas dos funciones son usadas para crear una plantilla con
informacin sobre la huella digital y realizar una verificacin de una huella contra una
plantilla existente. Adems, el encapsulamiento incluye una enumeracin utilizada en las
dos funciones y dos funciones callback. Una funcin callback consiste en un cdigo
ejecutable que es pasado como argumento a otro cdigo, esto permite a una capa inferior de
software llamar una subrutina definida en una capa superior.
Dependiendo del tipo de aplicacin, puede resultar ms fcil hacer uso de este
encapsulamiento. En soluciones como la elaborada en este proyecto no es ese el caso
debido a que se desea tener un alto grado de control sobre el funcionamiento del lector de
huellas digitales, en especial para la comparacin. En la comparacin se debe realizar esta
operacin interactuando con todo un conjunto de elementos presentes en la base de datos a
utilizar y adems tomar decisiones que dependen del tiempo, pues se deben registrar
entradas o salidas. Por este motivo el ncleo del API fue la herramienta utilizada.
-
11
El ncleo contiene funciones, estructuras, enumeraciones, definiciones de tipos de
variables y constantes. Las funciones contenidas dentro del API pueden ser clasificadas en
las siguientes tres categoras:
Funciones del dispositivo: Son utilizadas para comunicarse establecer y
terminar la comunicacin con el lector de huellas dactilares
Funciones de extraccin: Son utilizadas en el proceso de captura y
procesamiento digital de las imgenes, tanto para el proceso de formacin de
nuevas plantillas como en el proceso de comparacin. Forman el llamado mdulo
de extraccin.
Funciones de comparacin: son las funciones requeridas para la comparacin
de plantillas y determinacin de concordancia entre huellas. Forman el llamado
mdulo de comparacin.
En el apndice D se presenta una explicacin breve de algunas estas funciones,
especialmente las ms relevantes para la creacin de la solucin propuesta.
-
12
2.4 El IDE de desarrollo Visual C++ 2005
Por motivos que se explican ms adelante en este documento el IDE elegido fue
Visual C++ 2005 es por esto que en este apartado se habla brevemente sobre l, y se
comentan los aspecto bsicos necesarios que se necesitan conocer. Este entorno de
desarrollo permite la rpida creacin de aplicaciones generando grandes cantidades de
cdigo de forma que libera trabajo al programador y le permite centrarse en las necesidades
particulares de su aplicacin. El punto ms importante de mencionar sobre este IDE es el
manejo de Common Language Runtime (CLR), el cual es el motor de la plataforma de
trabajo (Framework) .NET de Microsoft. Esta plataforma es la responsable de acelerar y
simplificar la creacin y el manejo de formularios con los cuales se desarrollan aplicaciones
para Windows. Esto es una gran ventaja pero a la vez genera un problema con el uso del
API de DigitalPersona. Este API est desarrollo en cdigo de C++ estndar, o como lo
llaman en la plataforma de desarrollo .Net, cdigo no manejado o nativo. El cdigo CLR es
llamado cdigo manejado y tiene grandes dificultades con la interaccin de cdigo no
manejado, especialmente por el uso de un componente de Visual C++ 2005, llamado el
recolector de basura (Garbage Collector), este bloque genera dificultades en especial con el
manejo de punteros y pasos por referencia del cdigo nativo. Esto obliga a recurrir a
estrategias que han sido desarrolladas para tal fin como colocar pines a los punteros. Estos
pines fijan los punteros en direcciones de memoria de forma tal que el colector de basura no
generar problemas con el cdigo nativo.
-
13
2.5 El Software WampServer.
Para implementar la parte Web del proyecto de requiere una estructura que d
soporte a la pgina web, despus de una bsqueda de opciones se seleccion WampServer
y es por esto que en este apartado se habla de forma breve sobre l.
WampServer es un ambiente de desarrollo Web en Windows que permite crear
aplicaciones Web con Apache, PHP y MySQL. Adems incluye phpMyAdmin, un software
para el manejo de bases de datos. Al igual que cada una de las partes que lo conforma
WampServer es un proyecto de cdigo abierto, con licencia GPL. La versin WampServer
2.0i incluye las versiones Apache 2.2.11, MySQL 5.1.36 y PHP 5.3.0.
2.5.1 El servidor HTTP, Apache
Apache es una fundacin de software libre que da cabida a una gran cantidad de
proyectos, entre ellos se encuentra el servidor HTTP Apache. Este proyecto busca el
desarrollo y mantenimiento de un servidor HTTP para sistemas operativos modernos como
UNIX y Windows NT. El objetivo del proyecto es proveer de una alternativa de servidor,
segura, eficiente y extensible que est acorde con los estndares de HTTP.
A travs de la interfaz de WampServer se puede iniciar y detener Apache Server, e
incluso cambiar algunas de sus caractersticas, pero para una configuracin ms profunda
se puede modificar el archivo de configuracin de Apache, httpd.conf y manejarlo desde
lnea de comandos.
-
14
2.5.2 El servidor de Bases de datos, MySQL
MySQL es un gestor de bases de datos, que se encuentra bajo licencia GPL, aunque
tambin es posible comprar una versin licenciada. MySQL permite estructurar bases de
datos y realizar consultas a travs de lenguaje SQL
2.5.3 El interpretador PHP
PHP es un lenguaje interpretado, por lo cual se requiere un programa interpretador
que convierta el cdigo a lenguaje mquina cada vez que se desea ejecutar. Esto trae
consigo una problemtica para las aplicaciones Web: que el cdigo debe ser ejecutado del
lado del servidor, en el caso de que el cdigo PHP deba ser ejecutado solo bajo ciertas
condiciones o con ciertos parmetros acrecenta la problemtica, por la necesidad de una
comunicacin asincrnica entre cliente y servidor. Para solucionar este problema se ha
desarrollado AJAX.
Se ha decidido utilizar PHP por la enorme facilidad que tiene para establecer
comunicacin con MySQL a travs de un API para tal fin. Este API ya se encuentra
incluido y configurado dentro del paquete WampServer lo cual facilita en gran medida el
trabajo.
2.6 El API C de MySQL
Se debe comentar tambin sobre la estructura que da soporte a la base de datos y la
mejor opcin para esto es MySQL por esto se dedica un apartado para hablar sobre el API
de MySQL, pues es la herramienta de conexin entre el software y la base de datos usada.
-
15
El API C de MySQL es el encargado de dar conectividad entre aplicaciones escritas
en C o C++ y una base de datos implementada en MySQL. Para hacer uso de ella se deben
incluir un grupo de libreras estticas al Linker del compilador a utilizar y los encabezados
que hacen los llamados a estas libreras estticas. Dentro de las funciones ms relevantes
para este trabajo se encuentran:
mysql_init(NULL); : inicializa el API
mysql_close(connection); : cierra y libera recursos del API
mysql_real_connect(connection,host,username,password,dat
abase,port, NULL,0): establece la conexin con la base de datos.
mysql_real_query(query): enva una consulta a la base de datos.
mysql_store_result(connection): guarda el resultado de una consulta
mysql_free_result(result): libera el resultado de una consulta
2.7 AJAX
AJAX no es una tecnologa, es un conglomerado de tecnologas existentes que ha
permitido lograr grandes avances en el mundo del Internet. La idea detrs de AJAX es
evitar la necesidad de tener que estar cargando una pgina Web cada vez que el usuario
interacta con ella y se deben generar cambios. Una vez cargada y renderizada la pgina,
AJAX permite una comunicacin asincrnica con el servidor, para traer datos que sern
usados solo en una nueva re-renderizacin del sitio, evitando la necesidad de tener que
-
16
cargar toda la pgina. El mejor ejemplo que se puede dar del uso de AJAX es Google
Maps, donde es claro como es posible dar zoom y ver diferentes puntos de todo el mapa sin
la necesidad de refrescar la pgina. Esto no es de extraar pues Google ha sido uno de los
ms fuertes impulsores de AJAX.
AJAX es realmente muchas tecnologas, cada una floreciendo por su propio
mrito, unindose en poderosas nuevas formas. AJAX incorpora:
presentacin basada en estndares usando XHTML y CSS;
exhibicin e interaccin dinmicas usando el Document Object Model;
Intercambio y manipulacin de datos usando XML and XSLT;
Recuperacin de datos asincrnica usando XMLHttpRequest;
y JavaScript poniendo todo junto. [2]
El modelo de transmisin de informacin queda ejemplificado en la figura 2.4. Aqu
se puede ver claramente las enormes ventajas de AJAX respecto a las nuevas posibilidades
que brinda.
-
17
Figura 2.4 Modelo de diseo Web con AJAX. [2]
Como se aprecia, en el antiguo modelo cada vez que el cliente requiere nueva
informacin debe realizar una llamada al servidor Web el cual le reenviar toda la
informacin y se deber volver a cargar toda la pgina. En contraposicin utilizando AJAX
se pueden enviar datos sin la necesidad de cargar toda la pgina, esto se traduce en un
aumento de la velocidad pues la cantidad de datos que se transmiten en ambos sentidos se
reduce considerablemente.
-
18
CAPTULO 3: Trabajo previo al desarrollo del software
3.1 El lector de huellas dactilares U.Are.U 4500 de DigitalPersona.
Para la elaboracin de este proyecto fue sumamente importante la eleccin
adecuada del hardware encargado del escaneo de las huellas digitales. Los parmetros de
seleccin son principalmente las posibilidades reales de desarrollo de nuevas aplicaciones
con l, el factor econmico y la disponibilidad de adquisicin. Existen una gran variedad de
componentes para escaneo de huellas digitales, inclusive muchos incorporan teclados
numricos y mdulos para lectura de tarjetas de tecnologa magntica. Estas capacidades
incrementan en gran medida la seguridad y se usan principalmente en el caso de restriccin
de acceso fsico a algn lugar, pero debido a la inclusin de mayores capacidades, su precio
aumenta en gran medida si se compara con respecto a las soluciones que no incluyen estas
opciones. Entre las empresas que venden soluciones de hardware de este tipo se encuentra:
Microsoft con el DG2-00002, Zvetco con gran variedad de modelos, M2SYS y por
supuesto DigitalPersona. El costo de estos equipos con caractersticas similares era muy
parecido al momento de la eleccin, en donde el factor econmico fue de peso fue en los
paquetes de desarrollo de software para cada uno de los dispositivos. Para muchos de ellos
el costo poda alcanzar hasta los 600 USD.
Por este motivo la opcin del lector U.are.U 4500, mostrado en la figura 3.1, de
DigitalPersona fue elegida sobre gran cantidad de otras opciones. De la misma pgina de
DigitalPersona se pueden descargar paquetes de desarrollo de software de versiones ms
-
19
antiguas que la que se comercializa en este momento, lo cual permiti el desarrollo del
proyecto a un bajo costo. El contra que posea la eleccin de este dispositivo fue su
disponibilidad, aunque DigitalPersona tiene un socio comercial en Costa Rica, este ya no
comercializa sus productos por lo que tuvo que importarse desde los Estados Unidos, con
todas las implicaciones que esto conlleva. La hoja de datos del U.are.U 4500 se encuentra
en el Apndice A de este documento.
Figura 3.1. Lector de huellas digitales U.are.U 4500
3.2 Eleccin la plataforma de Desarrollo.
Dentro de las opciones de paquetes de desarrollo que se pueden descargar
gratuitamente del sitio Web de DigitalPersona se encuentran un paquete para Linux y otro
para Windows. Las aspiraciones de este proyecto son utilizar al mximo las opciones de
cdigo abierto para la elaboracin de las aplicaciones, por lo cual en un primer momento se
-
20
trat de utilizar las herramientas orientadas para Linux. A pesar de los intentos de utilizar
los paquetes de desarrollo para Linux, esto no se pudo concretar debido a que a pesar de
haberse logrado actualizar el cdigo fuente de los manejadores de hardware cambiando
funciones obsoleta que se encontraban en los mismos, estos controladores solo funcionan
para modelos de lectores de huellas digitales iguales o anteriores al U.are.U 4000B, que es
anterior al U.are.U 4500 adquirido. Debido a esto se debi utilizar el paquete de desarrollo
para Windows XP, el cual contiene manejadores de hardware actualizados para el U.are.U
4500.
Fuera de los motivos tcnicos, otro fuerte motivo es el mercado meta del software
desarrollado. Este posiblemente utilice Windows a pesar del fuerte crecimiento que han
venido experimentando el uso de Linux en Costa Rica.
3.3 Eleccin del entorno integrado de desarrollo
Para desarrollar el software se probaron tres opciones de RADs, el primero de ellos
wxDev-C++, el cual es una extensin de Dev-C++ utilizando wxWidgets. Este ltimo es un
Framework que permite la creacin de aplicaciones de Windows basadas en formularios.
Esta primera opcin fue descartada por ser un proyecto de software libre con poco
seguimiento y desarrollo, que contiene algunas pulgas an.
La segunda opcin fue CodeBlocks integrado con wxPack. wxPack contiene el
Framework wxWidgets anteriormente mencionado, y con este extra CodeBlocks puede
desarrollar aplicaciones de Windows, orientadas a formularios. Este IDE incluye Mingo, el
-
21
cual es un puerto del compilador de GCC de GNU, aunque si se encuentran instalados se
puede seleccionar otros compiladores. Esta opcin de IDE fue descartada, porque su
funcionamiento cuando se llaman funciones del API de DigitalPersona no era el adecuado.
Esto se debe a que el API de DigitalPersona fue escrito para el compilador Visual C++ y
hace uso de palabras reservadas para este, cuando se llaman funciones de libreras estticas
y dinmicas. Por este motivo se decidi seguir trabajando con la tercera opcin Visual C++
2005, a pesar de que en CodeBlock uno puede elegir utilizar el compilador Visual C++. Es
preferible usar el compilador desde el entorno de desarrollo para el cual fue creado y no
desde CodeBlocks.
3.4 Visin general del CRB
La aplicacin que se desarroll es llamada Control de Registro Biomtrico (CRB) y
la misma sigue una concepcin modular por lo que est organizada en cuatro bloques
principales:
Un cliente de registro de nuevo personal, y confirmacin de las entradas y salidas de
personal, que se comunica con el lector de huellas digitales.
Un servidor MySQL y una base de datos que cuenta con las tablas y columnas
especficas de la aplicacin CRB.
Un servidor Web Apache que incluye un interpretador PHP y todas las
prerrogativas de comunicacin entre el interpretador PHP y la base de datos.
-
22
Y por ltimo la interfaz Web por la cual el usuario tiene acceso a la informacin de
la base de datos.
Los bloques anteriormente mencionados se muestran en el diagrama esquemtico de la
figura 3.2.
Figura 3.2. Diagrama modular de CRB.
Los usuarios finales solo tienen acceso a la interfaz Web y al cliente de
comunicacin con el lector de huellas dactilares, el resto de partes son transparentes al
usuario.
Base de Datos
MySQL
APACHE y
PHP
Cliente de comunicacin con el lector de huellas
Interfaz Web
Usuario
-
23
3.5 Estructura de la base de datos.
Debido a que el sistema desarrollado todava es una versin alfa, se decidi incluir dentro
de la base de datos la informacin bsica que puede necesitar una empresa. As la base de
datos, llamada crb_db1, incluye un tabla principal llamada empleados y una tabla por cada
empleado que lleva como nombre el nmero de cdula correspondiente a cada empleado.
Dentro de la tabla empleados se han creado las siguientes columnas:
Nombre: un espacio tipo char(20).
Apellido1: un espacio tipo char(20).
Apellido2: un espacio tipo char(20).
Cedula: un espacio tipo int.
Departamento: un espacio tipo char(20).
DataTemplate: un espacio tipo BLOB.
cbData: un espacio tipo int.
Los primeros cinco espacios contienen como su nombre lo indica la informacin
elemental del empleado. El espacio DataTemplate no es usado en la versin que ha sido
desarrollada, pero ha sido incluido como una prevista importante, pues en este momento la
informacin sobre las huellas digitales de los usuarios se guarda de forma independiente en
un archivo extensin crbt, aunque lo ptimo sera almacenar la informacin dentro de la
misma base de datos de forma binaria, es por esto que el espacio DataTemplate es tipo
-
24
BLOB. Por ltimo, el espacio cbData contiene la longitud recomendada para la plantilla de
huella dactilar, este valor es generado por una de las funciones del API de DigitalPersona y
debe ser usado cuando se lee la plantilla, es por esto que fue almacenado en la base de
datos. La sentencia SQL para la generacin de la tabla se encuentra en el apndice C.
-
25
CAPTULO 4: Cliente de comunicacin con el lector de huellas
digitales CRB.
El software encargado de comunicarse con el lector de huellas digitales y almacenar
nueva informacin sobre el registro de personas en la base de datos fue desarrollado en el
lenguaje C++. El cdigo de este software se encuentra en el apndice A de este documento.
El software se divide en tres ventanas. La ventana principal permite al usuario cambiar
entre accesar a las otras dos ventanas que corresponden a los dos modos de operacin del
software. En la figura 4.1 se muestra la ventana principal. Adems permite al usuario ver la
informacin bsica sobre el software CRB y salir del programa, ya sea mediante la
secuencia Archivo -> Salir o dando click en el botn cerrar de Windows.
Figura 4.1. Ventana principal del CRB.
-
26
Los dos modos de operacin antes mencionados son el modo de registro de control
de acceso (ver figura 4.6) y el modo de registro de nuevo personal (ver figura 4.2).
Solamente se puede tener uno de ellos activo en un momento dado, esto para independizar
ambos procesos. As el usuario percibe ms fcilmente lo que est haciendo y adems se
facilita la labor de programacin, pues se independizan las tareas de almacenamiento de
plantillas de huellas dactilares y la comparacin de plantillas almacenadas.
Desde el punto de vista de programacin existen 3 clases, una para cada formulario:
la clase Form1 para la ventana principal, la clase Verform para el registro de marcas y la
clase enrrol para el registro de personal nuevo. Adems el programa inicia con la ejecucin
de CRB.cpp, que es el archivo principal donde se inicializa el U.are.U 4500, se establece la
conexin con la base de datos crb_db1 y se llama a la ventana principal. En la figura 4.3 se
muestra el diagrama de flujo que sigue el CRB.cpp.
Figura 4.2. Ventana del modo de registro de nuevo personal
-
27
Figura 4.3. Diagrama de flujo de CRB.cpp.
Inicializar el hardware. DPFPInit
Crear un contexto de extraccin FX_init
Crear un contexto de
comparacin MC_init
Exitoso
Exitoso
Return 0
Error
Error
Error
Liberar recursos, y cerrar la conexin con MySQL.
mysql_close, MC_terminate, FX_terminate, DPFPTerm.
Establecer conexin con MySQL mysql_real_connect.
Abrir la ventana principal Continuar con la ejecucin desde ah
Exitoso
Inicio
-
28
En general el programa puede ser analizado desde sus diferentes niveles de abstraccin,
(ver figura 4.4), este enfoque permite identificar donde estn los problemas, si son a nivel
de cdigo del programa, a nivel de dependencias de la funciones (encabezados) o a nivel de
libreras dinmicas (problemas en el linker).
Figura 4.4. Niveles de abstraccin del programa CRB.
4.1 Modo de registro de nuevo personal
En el modo de registro de nuevo personal posee una ventana que contiene tres
lneas de texto sobre el estado actual, espacios para introducir informacin necesaria para el
registro de personal nuevo y dos botones: uno para guardar la informacin y otro para salir
del modo de registro de nuevo personal. La figura 4.1 muestra esta ventana. Es aqu donde
se debe almacenar la informacin sobre la huella digital de la persona en una plantilla. Este
proceso tiene la secuencia que se muestra en la figura 4.5, despus de haberse creado los
contextos de extraccin y comparacin requeridos por el API de DigitalPersona.
Aplicacin desarrollada en C++
API accesado mediante los encabezado
Librerias dinmicas agregadas al linker
OS y controladores se comunican con el hardware
-
29
Figura 4.5. Diagrama de flujo del almacenamiento de informacin.
Una vez almacenada la informacin solo queda generar un stream binario para
almacenarla en un archivo con extensin crbt codificado con la huella digital de la persona
y guardar la informacin personal en la base de datos. Por este motivo al dar click en
guardar se revisa que la informacin est completa antes de proceder a guardar todo en
memoria externa al programa.
4.2 Modo de control de acceso
Este es el modo que tiene interaccin directa con todo el personal, aqu deben realizarse
las marcas de entrada o salida a la empresa. La ventana de este modo aparece en la figura
Obtener una muestra de huella digital a causa del toque de un dedo en el lector. Este evento es lanzado por el hardware
Procesar la muestra para extraer las caractersticas y guardarlas en una plantilla de pre-registro en memoria.
Existen suficientes plantillas de pre-registro?
Guardar las caractersticas en una plantilla definitiva y almacenar la informacin en forma externa al programa
No
Si
-
30
4.6. La misma posee tres lneas de informacin, donde se puede ver si el lector de huellas
digitales se encuentra conectado o no, si la marca fue realizada exitosamente y si es posible
realizar marca en el presente momento.
Figura 4.6. Ventana del modo de control de acceso
En lo que respecta a programacin lo ms importante es el algoritmo de bsqueda
que se emplea. Por el momento el algoritmo empleado es muy simple y consiste en una
comparacin uno a uno, principalmente por dos motivos. Primero, se necesita un
conocimiento mucho ms profundo sobre la forma en que opera el lector de huellas
dactilares, aun ms all del manejo del API, para implementar algn tipo de algoritmo ms
complejo y segundo, el corto tiempo que se tiene para desarrolla un proyecto de forma
individual dificulta el concentrar esfuerzos en un punto especfico del sistema como este.
Es claro que el algoritmo es funcional y eficiente para alguna empresa pequea, pero
-
31
conforme va creciendo la cantidad de usuarios del sistema, el algoritmo se va convirtiendo
cada vez ms ineficiente.
-
32
CAPTULO 5: Interfaz para la administracin de bases de datos
CRB.
Para ver la informacin sobre entradas y salidas del personal se desarrollo una
interfaz Web. Esta interfaz tiene una estructura modular la cual le permite establecer una
comunicacin asincrnica entre el un servidor Apache y un navegador Web. Los mdulos
tienen la estructura que se muestra en la figura 5.1
Figura 5.1. Mdulos de la Interfaz Web
El primer bloque est formado por el archivo cliente.php. Aunque est conformado
casi completamente por cdigo html, ste debe ser un archivo de extensin php. Esto se
debe a que debe ser preprocesado por el interpretador PHP antes de ser enviado al cliente
que lo est accediendo desde algn navegador Web desde cualquier lugar del mundo para
Cdigo HTML
cliente.php
Cdigo JavaScript
ajax.js
query_name
query_apellido1
query_apellido2
query_cedula
query_marcas
query_eliminar
Base de datos
crb_db1
-
33
que pueda comunicarse adecuadamente con los otros mdulos. Una vez recibido el
navegador Web lo procesar y se mostrar un resultado como el de la figura 3.2.
Figura 5.2. Resultado mostrado por el navegador Web
Aqu el usuario puede realizar tres acciones diferentes, buscar la informacin de una
persona, por cuatro criterios de bsqueda diferentes: Nombre, Primer Apellido, Segundo
Apellido y Nmero de Cdula. Los resultados se muestran en el mismo espacio de la tabla
por debajo de los criterios de bsqueda como se muestra en la figura 3.3.
La operacin realizada es la siguiente: un objeto AJAX creado mediante el script
ajax.js es usado a travs de una funcin Consulta que se encuentra tambin en el mismo
script. Esta funcin enva informacin a cuatro diferentes cdigos PHP dependiendo de qu
-
34
tipo de bsqueda se vaya a realizar. Es por esto que existen cuatro bloques query_,
correspondientes a cada una de las bsquedas. Los bloques query_ sea query_name,
query_apellido1, query_apellido2 o query_cedula, son ejecutados del lado del servidor,
debido a que estn escritos en PHP y requieren del interpretador. Una vez procesados, stos
devuelven la informacin mediante la sentencia echo de PHP y son mostrados como se ve
en la figura 3.3. Es importante decir que para versiones posteriores del sistema CRB debe
buscarse otra forma de enviar informacin de regreso a cdigo en JavaScript.
Posteriormente la funcin Consulta se encarga de colocar los resultados en el cdigo
HTML y decirle al navegador Web que debe re-renderizar la pgina.
Figura 5.3. Resultados de bsqueda
Otra de las operaciones que puede realizar el usuario, y tal vez la ms importante, es
ver el registro de entradas y salidas del personal. Para ver los datos de una persona se
necesita conocer el nmero de cdula de ella. La bsqueda, al igual que en el modo
anterior, se realiza mediante un objeto AJAX, pero este se comunicar esta vez con el
bloque de cdigo query_marcas escrito en PHP. La solucin utilizada es la misma y la
-
35
forma en que se presentan lo resultados se muestra en la figura 3.4. Es en este punto de la
interfaz donde ms se puede avanzar. Deben agregarse bloques que permitan filtrar las
marcas de algn usuario o ver los datos de un da en especfico. Nuevamente, el corto
tiempo de desarrollo fue la principal dificultad.
Figura 5.4. Resultados del Registro de marcas de personal
La ltima de las operaciones que puede realizar la interfaz Web, es la eliminacin
de usuarios va su nmero de cdula. Esta operacin se ha agregado solamente aqu en esta
-
36
versin alfa, pero en versiones posteriores debe ser agregada tambin en la aplicacin de
escritorio mediante cdigo C++. Se ha agregado aqu principalmente porque la interfaz
Web puede ser accesada prcticamente desde cualquier lugar del mundo y no requiere de
una presencia fsica en el sitio de trabajo, como s sucede con la aplicacin de escritorio. En
lo que a programacin se refiere, se realiza a travs del bloque query_eliminar escrito en
PHP. Este bloque de cdigo difiere en que realiza dos consultas a la base de datos y no
solamente una, como es el caso de todo el resto de bloques query_, pues se debe eliminar
tanto la tabla codificada con el nmero de cdula de la persona como la fila respectiva en la
tabla empleados. Como resultado este enviar solamente una lnea de texto indicando que la
operacin fue realiza con xito, y el cdigo ajax.js en JavaScript se encarga de que la
pgina sea re-renderizada y mostrar un resultado como el que se aprecia en la figura 3.5.
Figura 5.5. Eliminacin de un usuario
El manejo del sistema, en su totalidad por parte del usuario final est documentado
en el manual del usuario.Este manual se encuentra en el Anexo de este documento.
-
37
CAPTULO 6: Conclusiones y recomendaciones
6.1 Conclusiones
Una bsqueda concienzuda y comparativa fue la que permiti realizar una eleccin
adecuada del hardware a utilizar, lo que a la postre vino a significar facilidades en el
proceso de programacin y el satisfactorio fin de este trabajo.
El seguimiento de una estrategia clara de divisin modular del problema a resolver
fue exitoso y es el responsable del funcionamiento adecuado de un sistema que integra
diferentes frentes de trabajo como lo son una aplicacin de escritorio y una interfaz Web.
De no ser este el enfoque no sera posible manipular la informacin desde rutas tan
diferentes como lo son el Internet y una aplicacin de escritorio.
Durante la elaboracin de este proyecto siempre se busc que la solucin
desarrollada tuviera un enfoque abierto el cual pudiera fcilmente ser adoptado en la gran
mayora de casos donde se requiera una aplicacin similar, y que a partir de la solucin
planteada se pueda seguir trabajando para satisfacer las necesidades especficas del usuario
final. Esto se concret, aunque an se debe seguir trabajando en esta aplicacin,
especialmente en los puntos que se abordan en las recomendaciones.
La interfaz Web desarrollada puede ser accesada desde los mltiples sistemas
operativos existentes, e incluso el cdigo est hecho para preveer diferencias entre los
navegadores Web ms populares del mercado lo cual hace que esta parte del sistema sea
multiplataforma. La aplicacin de escritorio solo pudo ser desarrollada para Windows por
los problemas mencionados en el Captulo 4. A pesar de esto si se pudiera contar
-
38
principalmente con los manejadores de hardware actualizados, partes importantes del
cdigo desarrollado podra ser exportadas a una aplicacin de Linux, pero mientras no se
cuente con estos manejadores se tendr que esperar.
Por ltimo la meta general planteada se concret y todos los requisitos puestos
inicialmente para la solucin deseada fueron conseguidos, pero es importante recalcar que
en esta clase de aplicaciones siempre debe existir una idea de mejoramiento continuo y an
queda trabajo para obtener un producto final de alta calidad.
6.2 Recomendaciones
La aplicacin desarrollada tiene mucho trabajo por delante antes de poder ser un
versin candidata a definitiva, entre los puntos en los que se debe trabajar para mejor el
sistema CRB se encuentran los siguientes.
Incluir la informacin de las plantillas de huella digital correspondiente a cada
persona dentro de la base de datos como un elemento tipo BLOB pues mejora en gran
medida la portabilidad y adems facilita enormemente la tarea de respaldar la informacin.
Incluir el manejo de excepciones en el cdigo de programa CRB hecho en C++,
para evitar comportamientos inesperados que podran daar valiosa informacin de
la base de datos.
Estandarizar la interfaz Web de manejo de bases de datos CRB, conforme lo
establece la W3C.
-
39
Buscar una mejor forma de enviar los resultados de la bsqueda en la base de datos
del cdigo PHP a la interfaz Web para presentar la informacin de forma ms
agradable.
Tomar en cuenta todos los posibles fallos del usuario en el ingreso de informacin.
En nmero de cdula, por ejemplo, se debe tomar medidas en caso de que el usuario
del programa no d el nmero completo o incluya letras o espacios dentro de la caja
de texto establecida para ingresar tal nmero.
Mejorar el algoritmo de bsqueda del modo de control de acceso pues resulta
ineficiente conforme crece la cantidad de personal registrado.
Crear un programa instalador para la aplicacin que pueda dejar el programa
funcional sin la intervencin de un programador.
Incluir seguridad en el sistema, principalmente la implementacin de usuarios y la
autenticacin para el uso del programa, y posteriormente la encriptacin de la
informacin que deber viajar por Internet en la interfaz Web.
Debido a que la solucin elaborada representa una versin alfa, el manual del
usuario elaborado deben ser puesto bajo revisin pues apenas cuentan con la
informacin necesaria para explicar al usuario como manejarse en el sistema pero
no prevn los problemas de desarrollo que hayan sido pasados por alto o que
todava no son del conocimiento del desarrollador del sistema CRB.
-
40
BIBLIOGRAFA
Artculos de revistas:
1. Jimnez, J.M. Marn J.G. Sistema de reconocimiento de huellas dactilares,
Mundo Electrnico, Espaa, N 380, 2006.
2. Zucker, D.F. What does AJAX mean for you?, Interactions, Estados Unidos,
Volumen 14 N 5, 2007.
Libros:
3. DigitalPersona, Inc.. One Touch for Window SDK C/C++ Edition. Developer
Guide, Estados Unidos, 2009.
4. Deitel, H.M. Deitel, P.J. C++ Cmo programar Segunda edicin, Prentice Hall,
Mxico, 1999.
Pginas Web:
5. PHP Manual, http://www.php.net/manual/en/
6. Versin 2.2 de la documentacin del Servidor de HTTP Apache,
http://httpd.apache.org/docs/2.2/
7. Garretr, J.J. AJAX: A New Approach to Web Application,
http://adaptivepath.com/ideas/essays/archives/000385.php.
-
41
APNDICE A: Cdigo del cliente de comunicacin con el lector
de huellas dactilares.
A.1. Archivo CRB.cpp /***************************************************************** Universidad de Costa Rica Escuela de Ingenieria Electrica II Semestre 2009 IE-0502 Proyeto Electrico Elaborado por: Luis Castro Leiva A61368 Resumen: CRB.cpp Este archivo contiene el arranque de CRB, se llama la base de datos se inicializa el lector U.are.U 4500 y se llama la ventana principal en caso de error se da aviso y se cierra el programa. ******************************************************************/ #include "stdafx.h" #include "Form1.h" #include "enrrol.h" //Encabezados necesarios para la conexion la base de datos de MySQL #include #include using namespace CRB; #define host "localhost" #define username "admin" #define password "crb" #define database "crb_db1" [STAThreadAttribute] int main(array ^args){ //Localiza e inicializa los recursos necesarios para el funcionamiento del API if(FAILED(DPFPInit())==TRUE); else{ // Inicializa el mdulo de extraccin del SDK if (FT_OK == FX_init()) { // Inicializa el mdulo de comparacin del SDK if (FT_OK == MC_init()) {
-
42
// Habilita los efectos visuales de XP antes de que los controles sean creados Application::EnableVisualStyles(); Application::SetCompatibleTextRenderingDefault(false); MYSQL *conn = mysql_init(NULL); int code = 0; int port = 3306; //Establece una conexion con MySQL if (mysql_real_connect(conn,host,username,password,database,port,NULL,0) == NULL){ //En caso de falta de conectividad con crb_db1 se cierra el programa MessageBox::Show( "Error en la conexin con la base de datos\nEl programa se cerrar", "Error"); mysql_close(conn); MC_terminate(); FX_terminate(); DPFPTerm (); return 0; } // Se crea la ventana principal y se ejecuta Application::Run(gcnew Form1(conn)); // Libera recursos de la conexion con la base de datos mysql_close(conn); // Libera recursos del mdulo de comparacin del SDK MC_terminate(); } else { MC_terminate(); FX_terminate(); DPFPTerm (); return 0; } // Libera recursos del mdulo de extraccin del SDK FX_terminate(); } else { FX_terminate(); DPFPTerm (); return 0; } } DPFPTerm (); return 0; }
-
43
A.2. Archivo Form1.h /***************************************************************** Universidad de Costa Rica Escuela de Ingenieria Electrica II Semestre 2009 IE-0502 Proyeto Electrico Elaborado por: Luis Castro Leiva A61368 Resumen: Form1.h Este archivo contiene tanto la declaracin como el contenido de las funciones de la ventana principal, la cual se encarga de llamar los dos diferentes modos de operacin y distribuir informacin de conexin a MySQL. ******************************************************************/ #pragma once //Encabezados de los modos de operacin #include "enrrol.h" #include "Verform.h" //Encabezados necesarios para la conexion la base de datos de MySQL #include #include //Encabezados para la manipulacion de caracteres #include #include namespace CRB { using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::IO; public ref class Form1 : public System::Windows::Forms::Form { public: Form1(MYSQL* connlink) { InitializeComponent(); ZeroMemory(&m_RegTemplate, sizeof(m_RegTemplate)); conn = connlink; } protected: ~Form1()
-
44
{ if (components) { delete components; } } private: System::Windows::Forms::Button^ button1; private: System::Windows::Forms::MenuStrip^ menuStrip1; private: System::Windows::Forms::ToolStripMenuItem^ archivoToolStripMenuItem; private: System::Windows::Forms::ToolStripMenuItem^ salirToolStripMenuItem; private: System::Windows::Forms::ToolStripMenuItem^ toolStripMenuItem1; private: System::Windows::Forms::ToolStripMenuItem^ cRBToolStripMenuItem; private: System::Windows::Forms::Button^ button2; private: System::ComponentModel::IContainer^ components; private: DATA_BLOB m_RegTemplate; MYSQL* conn; #pragma region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// void InitializeComponent(void) { System::ComponentModel::ComponentResourceManager^ resources = (gcnew System::ComponentModel::ComponentResourceManager(Form1::typeid)); this->button1 = (gcnew System::Windows::Forms::Button()); this->menuStrip1 = (gcnew System::Windows::Forms::MenuStrip()); this->archivoToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem()); this->salirToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem()); this->toolStripMenuItem1 = (gcnew System::Windows::Forms::ToolStripMenuItem()); this->cRBToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem()); this->button2 = (gcnew System::Windows::Forms::Button()); this->menuStrip1->SuspendLayout(); this->SuspendLayout(); // // button1 // this->button1->Location = System::Drawing::Point(53, 77);
-
45
this->button1->Name = L"button1"; this->button1->Size = System::Drawing::Size(184, 26); this->button1->TabIndex = 0; this->button1->Text = L"Registrar nuevo personal"; this->button1->UseVisualStyleBackColor = true; this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click); // // menuStrip1 // this->menuStrip1->Items->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^ >(2) {this->archivoToolStripMenuItem, this->toolStripMenuItem1}); this->menuStrip1->Location = System::Drawing::Point(0, 0); this->menuStrip1->Name = L"menuStrip1"; this->menuStrip1->Size = System::Drawing::Size(292, 24); this->menuStrip1->TabIndex = 1; this->menuStrip1->Text = L"menuStrip1"; // // archivoToolStripMenuItem // this->archivoToolStripMenuItem->DropDownItems->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^ >(1) {this->salirToolStripMenuItem}); this->archivoToolStripMenuItem->Name = L"archivoToolStripMenuItem"; this->archivoToolStripMenuItem->Size = System::Drawing::Size(55, 20); this->archivoToolStripMenuItem->Text = L"Archivo"; // // salirToolStripMenuItem // this->salirToolStripMenuItem->Name = L"salirToolStripMenuItem"; this->salirToolStripMenuItem->Size = System::Drawing::Size(105, 22); this->salirToolStripMenuItem->Text = L"Salir"; this->salirToolStripMenuItem->Click += gcnew System::EventHandler(this, &Form1::salirToolStripMenuItem_Click); // // toolStripMenuItem1 // this->toolStripMenuItem1->DropDownItems->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^ >(1) {this->cRBToolStripMenuItem}); this->toolStripMenuItem1->Name = L"toolStripMenuItem1"; this->toolStripMenuItem1->Size = System::Drawing::Size(67, 20); this->toolStripMenuItem1->Text = L"Acerca de"; // // cRBToolStripMenuItem
-
46
// this->cRBToolStripMenuItem->Name = L"cRBToolStripMenuItem"; this->cRBToolStripMenuItem->Size = System::Drawing::Size(105, 22); this->cRBToolStripMenuItem->Text = L"CRB"; this->cRBToolStripMenuItem->Click += gcnew System::EventHandler(this, &Form1::cRBToolStripMenuItem_Click); // // button2 // this->button2->Location = System::Drawing::Point(53, 141); this->button2->Name = L"button2"; this->button2->Size = System::Drawing::Size(184, 26); this->button2->TabIndex = 2; this->button2->Text = L"Registrar marcas de personal"; this->button2->UseVisualStyleBackColor = true; this->button2->Click += gcnew System::EventHandler(this, &Form1::button2_Click); // // Form1 // this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(292, 266); this->Controls->Add(this->button2); this->Controls->Add(this->button1); this->Controls->Add(this->menuStrip1); this->Icon = (cli::safe_cast(resources->GetObject(L"$this.Icon"))); this->MaximizeBox = false; this->MaximumSize = System::Drawing::Size(300, 300); this->MinimumSize = System::Drawing::Size(300, 300); this->Name = L"Form1"; this->StartPosition = System::Windows::Forms::FormStartPosition::CenterScreen; this->Text = L"Control de Registro Biometrico"; this->menuStrip1->ResumeLayout(false); this->menuStrip1->PerformLayout(); this->ResumeLayout(false); this->PerformLayout(); } #pragma endregion private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { this->Hide(); enrrol ^form2 = gcnew enrrol(); form2->GetConnetionLinker(conn); form2->ShowDialog(this); this->Show();
-
47
} private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { this->Hide(); Verform ^form3 = gcnew Verform(); form3->GetConnetionLinker(conn); form3->ShowDialog(this); this->Show(); } private: System::Void salirToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) { if(MessageBox::Show( "Desea salir de la aplicacin?", "Salir", MessageBoxButtons::YesNo ) == System::Windows::Forms::DialogResult::Yes) Application::Exit(); } private: System::Void cRBToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) { MessageBox::Show( "CRB: Control de Registro Biomtrico\n2009\nElaborado por: Luis Castro Leiva", "Acerca de CRB"); } }; }
A.3. Archivo Verform.h /***************************************************************** Universidad de Costa Rica Escuela de Ingenieria Electrica II Semestre 2009 IE-0502 Proyeto Electrico Elaborado por: Luis Castro Leiva A61368 Resumen: Verform.h Este archivo contiene declaraciones de las funciones que correponden a la ventana de registro de control de acceso, (ver Verform.cpp) y forma parte del cliente de comunicacion con el lector de huellas digitales U.are.U 4500 ******************************************************************/ #pragma once #pragma warning( disable : 4368) #include "dpRCodes.h" #include "dpDefs.h" #include "DPDevClt.h"
-
48
#include "dpFtrEx.h" #include "dpMatch.h" #include "DpUIApi.h" //Encabezados necesarios para la manipulacion de caracteres #include #include #include #include //Encabezados para la conexion con la base de datos #include #include using namespace std; using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; using namespace System::Globalization; using namespace System::IO; using namespace System::Runtime::InteropServices; namespace CRB { public ref class Verform : public System::Windows::Forms::Form { public: Verform(void){ InitializeComponent(); } protected: ~Verform(){ if (components){ delete components; } delete [] m_RegTemplate.pbData; m_RegTemplate.cbData = 0; m_RegTemplate.pbData = NULL; } //codificacion para los eventos generados por el lector private: static const UINT FP_EVENT = (WM_USER+1); // Variables globales necesarias en el proceso de Verificacion private: // Contexto de extraccion FT_HANDLE m_fxContext; // Contexto de comparacion
-
49
FT_HANDLE m_mcContext; // Handle de la operacion HDPOPERATION m_hOperationVerify; // Objetos binarios donde se almacen las plantillas de huellas dactilares DATA_BLOB m_RegTemplate,r_RegTemplate; // identificador de la comunicacion establecidad con MySQL MYSQL* conn; // Objeto para almacenar los resultados de una consulta a MySQL MYSQL_RES* mysql_res; // Bandera de resultado de comparacion TRUE == huellas concuerdan. FALSE == no concuerdan bool match_flag; private: System::Windows::Forms::Label^ label1; private: System::Windows::Forms::Button^ button1; private: System::Windows::Forms::Label^ label2; private: System::Windows::Forms::Label^ label3; private: System::Windows::Forms::GroupBox^ groupBox1; System::ComponentModel::Container ^components; #pragma region Windows Form Designer generated code void InitializeComponent(void) { System::ComponentModel::ComponentResourceManager^ resources = (gcnew System::ComponentModel::ComponentResourceManager(Verform::typeid)); this->label1 = (gcnew System::Windows::Forms::Label()); this->button1 = (gcnew System::Windows::Forms::Button()); this->label2 = (gcnew System::Windows::Forms::Label()); this->label3 = (gcnew System::Windows::Forms::Label()); this->groupBox1 = (gcnew System::Windows::Forms::GroupBox()); this->groupBox1->SuspendLayout(); this->SuspendLayout(); // // label1 // this->label1->AutoSize = true; this->label1->Location = System::Drawing::Point(46, 54); this->label1->Name = L"label1"; this->label1->Size = System::Drawing::Size(35, 13); this->label1->TabIndex = 0; this->label1->Text = L"label1"; // // button1 // this->button1->Location = System::Drawing::Point(314, 255); this->button1->Name = L"button1"; this->button1->Size = System::Drawing::Size(92, 28); this->button1->TabIndex = 1;
-
50
this->button1->Text = L"Cerrar"; this->button1->UseVisualStyleBackColor = true; this->button1->Click += gcnew System::EventHandler(this, &Verform::button1_Click); // // label2 // this->label2->AutoSize = true; this->label2->Location = System::Drawing::Point(46, 89); this->label2->Name = L"label2"; this->label2->Size = System::Drawing::Size(35, 13); this->label2->TabIndex = 2; this->label2->Text = L"label2"; // // label3 // this->label3->AutoSize = true; this->label3->Location = System::Drawing::Point(46, 125); this->label3->Name = L"label3"; this->label3->Size = System::Drawing::Size(35, 13); this->label3->TabIndex = 3; this->label3->Text = L"label3"; // // groupBox1 // this->groupBox1->Controls->Add(this->label2); this->groupBox1->Controls->Add(this->label1); this->groupBox1->Controls->Add(this->label3); this->groupBox1->Location = System::Drawing::Point(12, 37); this->groupBox1->Name = L"groupBox1"; this->groupBox1->Size = System::Drawing::Size(394, 212); this->groupBox1->TabIndex = 5; this->groupBox1->TabStop = false; this->groupBox1->Text = L"Estado"; // // Verform // this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(418, 295); this->Controls->Add(this->groupBox1); this->Controls->Add(this->button1); this->Icon = (cli::safe_cast(resources->GetObject(L"$this.Icon"))); this->MaximizeBox = false; this->MaximumSize = System::Drawing::Size(426, 329); this->MinimumSize = System::Drawing::Size(426, 329); this->Name = L"Verform"; this->StartPosition = System::Windows::Forms::FormStartPosition::CenterScreen; this->Text = L"Control de entradas y salidas";
-
51
this->Load += gcnew System::EventHandler(this, &Verform::Verform_Load); this->FormClosing += gcnew System::Windows::Forms::FormClosingEventHandler(this, &Verform::Verform_FormClosing); this->groupBox1->ResumeLayout(false); this->groupBox1->PerformLayout(); this->ResumeLayout(false); } #pragma endregion public: System::Void GetConnetionLinker(MYSQL* connlink); public: System::Void LoadRegTemplate(const DATA_BLOB% rRegTemplate); private: System::Void Verform_Load(System::Object^ sender, System::EventArgs^ e); private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e); private: System::Void Verificar(FT_IMAGE_PT pFingerprintImage, int iFingerprintImageSize); private: System::Void Marca_Personal(int match_cedula); private: System::Void Cargar_Templates(FT_IMAGE_PT pFingerprintImage, int iFingerprintImageSize ); private: System::Void Verform_FormClosing(System::Object^ sender, System::Windows::Forms::FormClosingEventArgs^ e); protected: virtual void WndProc(Message %m) override{ if (m.Msg == FP_EVENT){ switch((int)m.WParam) { case WN_COMPLETED: { this->label3->Text = L"Huella digital capturada"; DATA_BLOB* pImageBlob = reinterpret_cast((int)m.LParam); //Verificar si hay concordancia this->Cargar_Templates(pImageBlob->pbData, pImageBlob->cbData); break; } case WN_ERROR: { MessageBox::Show( "Existio un error interno del lector", "Error"); break; } case WN_DISCONNECT: this->label2->Text = L"Lector de huellas digitales desconectado"; break; case WN_RECONNECT: this->label2->Text = L"Lector de huellas digitales conectado"; break; case WN_FINGER_TOUCHED:
-
52
this->label3->Text = L"Huella digital detectada"; break; case WN_FINGER_GONE: this->label3->Text = L"Dedo alejado"; break; case WN_IMAGE_READY: this->label3->Text = L"Huella digital capturada"; break; case WN_OPERATION_STOPPED: this->label3->Text = L"Operacion detenida inadecuadamente"; break; } } Form::WndProc(m); } };//Fin de la clase Verform }//Fin del espacio CRB
A.4. Archivo Verform.cpp /***************************************************************** Universidad de Costa Rica Escuela de Ingenieria Electrica II Semestre 2009 IE-0502 Proyeto Electrico Elaborado por: Luis Castro Leiva A61368 Resumen: Verform.cpp Este archivo contiene las funciones que correponden a la ventana de registro de control de acceso, (ver Verform.h) y forma parte del cliente de comunicacion con el lector de huellas digitales U.are.U 4500 ******************************************************************/ #include "StdAfx.h" #include "Verform.h" using namespace CRB; System::Void Verform::GetConnetionLinker(MYSQL* connlink){ conn = connlink; }
-
53
System::Void Verform::LoadRegTemplate(const DATA_BLOB% rRegTemplate) { // Se eliminan los elementos antiguos que puedan estar en la plantilla. delete [] m_RegTemplate.pbData; m_RegTemplate.pbData = NULL; m_RegTemplate.cbData = 0; // Se copian los datos suministrados dentro de la plantilla de comparacion m_RegTemplate.pbData = new BYTE[rRegTemplate.cbData]; if (!m_RegTemplate.pbData) MessageBox::Show( "No hay una plantilla creada", "Error"); ::CopyMemory(m_RegTemplate.pbData, rRegTemplate.pbData, rRegTemplate.cbData); m_RegTemplate.cbData = rRegTemplate.cbData; } System::Void Verform::Verform_Load(System::Object^ sender, System::EventArgs^ e) { HRESULT hr = S_OK; FT_RETCODE rc = FT_OK; // Se crea un contexto para realizar una extraccion pin_ptr pm_fxContext = &m_fxContext; if (FT_OK != (rc = FX_createContext(pm_fxContext))) { MessageBox::Show( "Cannot create Feature Extraction Context.", "Error"); } // Se crea un contexto para realizar una comparacion pin_ptr pm_mcContext = &m_mcContext; if (FT_OK != (rc = MC_createContext(pm_mcContext))) { MessageBox::Show( "Error en MC_createContext", "Error"); } // Iniciar la verificacion // Se utiliza prioridad baja para que se registren las marcas // aun si la ventana no se encuentra activa. DP_ACQUISITION_PRIORITY ePriority = DP_PRIORITY_LOW; HWND pHandle = (HWND)this->Handle.ToPointer(); pin_ptr pm_hOperationVerify = &m_hOperationVerify; if(S_OK == DPFPCreateAcquisition(ePriority, GUID_NULL,DP_SAMPLE_TYPE_IMAGE,pHandle,FP_EVENT,pm_hOperationVerify)){ if(S_OK == DPFPStartAcquisition(m_hOperationVerify)){ this->label1->Text = L"Inicializacion concluida"; this->label3->Text = L"Puede realizar una marca"; } } } System::Void Verform::button1_Click(System::Object^ sender, System::EventArgs^ e) {
-
54
//Se detienen y destruyen los procesos de Adquisicion y se cierran los contextos de extraccion y comparacion if (m_hOperationVerify) { DPFPStopAcquisition(m_hOperationVerify); DPFPDestroyAcquisition(m_hOperationVerify); m_hOperationVerify = 0; } if (m_fxContext) { FX_closeContext(m_fxContext); m_fxContext = 0; } if (m_mcContext) { MC_closeContext(m_mcContext); m_mcContext = 0; } this->Close(); } System::Void Verform::Verificar(FT_IMAGE_PT pFingerprintImage, int iFingerprintImageSize) { HRESULT hr = S_OK; FT_BYTE* pVerTemplate = NULL; FT_RETCODE rc = FT_OK; // Se obtiene el tamao recomendado de las plantillas de prematricula. int iRecommendedVerFtrLen = 0; rc = FX_getFeaturesLen(FT_VER_FTR, &iRecommendedVerFtrLen, NULL); if (FT_OK != rc) MessageBox::Show( "Error en FX_getFeaturesLen", "Error"); FT_IMG_QUALITY imgQuality; FT_FTR_QUALITY ftrQuality; FT_BOOL bEextractOK = FT_FALSE; if (NULL == (pVerTemplate = new FT_BYTE[iRecommendedVerFtrLen])) MessageBox::Show( "Error en iRecommendedVerFtrLen", "Error"); rc = FX_extractFeatures(m_fxContext, // Contexto para la extraccion iFingerprintImageSize, // Tamao de la imagen escaneada pFingerprintImage, // Puntero a algun buffer para contener la imagen FT_VER_FTR, // Requested Verification Features iRecommendedVerFtrLen, // Tamao del buffer que recibe la informacion de la plantilla
-
55
pVerTemplate, // Puntero al buffer donde se almacena la plantilla &imgQuality, // Retorna la calidad de la imagen &ftrQuality, // Retorna la calidad de las caracteristicas &bEextractOK); // Resultado de la extraccin if (FT_OK Text = L"Scan another finger to run verification again."; WCHAR buffer[101] = {0}; ULONG uSize = 100; } else {
-
56
this->label3->Text = L"Scan another finger to run verification again."; WCHAR buffer[101] = {0}; ULONG uSize = 100; } } else { WCHAR buffer[101] = {0}; ULONG uSize = 100; MessageBox::Show( "Error en la operacion de verificacion", "Error"); this->label3->Text = L"Intente nuevamente"; } } } System::Void Verform::Marca_Personal(int match_cedula){ CultureInfo^ MyCI = gcnew CultureInfo( "en-US",false ); DateTimeFormatInfo^ myDTFI = MyCI->DateTimeFormat; char* cedula = new char[9]; _itoa_s(match_cedula,cedula,10,10); DateTime Marca = DateTime::Now; char* Fecha = (char*)(void*)Marshal::StringToHGlobalAnsi(Marca.Date.ToString("yyyy-MM-dd",myDTFI)); char* Hora = (char*)(void*)Marshal::StringToHGlobalAnsi(Marca.ToString("HH:mm::ss",myDTFI)); char sql[100]; strcpy_s(sql,100,"INSERT INTO `crb_db1`.`"); strcat_s(sql,100,cedula); strcat_s(sql,100,"` (`Fecha` ,`Hora` ,`Tipo`)VALUES ('"); strcat_s(sql,100,Fecha); strcat_s(sql,100,"', '"); strcat_s(sql,100,Hora); strcat_s(sql,100,"', '');"); if(!mysql_real_query(conn, sql ,strlen(sql))){ this->label2->Text = L"Marca realizada adecuadamente"; } else{ this->label2->Text = L"Error en la marca, no se pudo realizar"; } mysql_res = mysql_store_result(conn); mysql_free_result(mysql_res); } System::Void Verform::Cargar_Templates(FT_IMAGE_PT pFingerprintImage, int iFingerprintImageSize ){ FT_BYTE* pRegTemplate = NULL;
-
57
char* sql; MYSQL_ROW row; String^ solicitud = String::Format(CultureInfo::CurrentCulture,"SELECT * FROM empleados"); sql = (char*)(void*)Marshal::StringToHGlobalAnsi(solicitud); int len = 0; len = strlen(sql); if(!mysql_real_query(conn, sql ,len)){ this->label2->Text = L"Consulta exitosa"; } else{ this->label2->Text = L"Error en la consulta"; } mysql_res = mysql_store_result(conn); int match_cedula = 0; while (row = mysql_fetch_row(mysql_res)){ match_flag = false; int iRecommendedRegFtrLen = atoi(row[6]); char archivo[40]; strcpy_s(archivo,40,"d:\\CRB\\CRB\\Templates\\"); strcat_s(archivo,40,row[3]); strcat_s(archivo,40,".crbt"); char* templ = new char[iRecommendedRegFtrLen]; ifstream input(archivo, ios::binary); input.read(templ, iRecommendedRegFtrLen); input.close(); //Borrar la informacion antigua del template delete [] m_RegTemplate.pbData; m_RegTemplate.pbData = NULL; m_RegTemplate.cbData = 0; // Se copian los datos suministrados dentro de la plantilla de comparacion m_RegTemplate.pbData = new BYTE[iRecommendedRegFtrLen]; if (!m_RegTemplate.pbData) MessageBox::Show( "No hay una plantilla creada", "Error"); ::CopyMemory(m_RegTemplate.pbData, templ, iRecommendedRegFtrLen); m_RegTemplate.cbData = iRecommendedRegFtrLen; Verificar(pFingerprintImage, iFingerprintImageSize); if(match_flag == true) match_cedula = atoi(row[3]); } mysql_free_result(mysql_res); if(match_cedula != 0){ Marca_Personal(match_cedula);
-
58
this->label1->Text = L"Puede proceder a realizar otra marca"; this->label2->Text = L"Bienvenido. Su marca ha sido registrada exitosamente"; } else{ this->label1->Text = L"Su huella no se encuentra registrada"; this->label2->Text = L"Intente nuevamente por favor"; } } System::Void Verform::Verform_FormClosing(System::Object^ sender, System::Windows::Forms::FormClosingEventArgs^ e) { if (m_hOperationVerify) { DPFPStopAcquisition(m_hOperationVerify); DPFPDestroyAcquisition(m_hOperationVerify); m_hOperationVerify = 0; } if (m_fxContext) { FX_closeContext(m_fxContext); m_fxContext = 0; } if (m_mcContext) { MC_closeContext(m_mcContext); m_mcContext = 0; } }
A.5. Archivo enroll.h
/***************************************************************** Universidad de Costa Rica Escuela de Ingenieria Electrica II Semestre 2009 IE-0502 Proyeto Electrico Elaborado por: Luis Castro Leiva A61368 Resumen: e
top related