Informe - Escuela de Ingeniería Eléctrica

Anuncio
Universidad de Costa Rica
Facultad de Ingeniería
Escuela de Ingeniería Eléctrica
IE – 0502 Proyecto Eléctrico
Diseño e implementación de un sistema de registro
de personas mediante la identificación a partir de
la huella dactilar
Por:
Luis Alfonso Castro Leiva
Ciudad Universitaria Rodrigo Facio
Noviembre del 2009
Diseño e implementación de un sistema de registro
de personas mediante la identificación a partir de
la huella digital
Por:
Luis Alfonso Castro Leiva
Sometido a la Escuela de Ingeniería Eléctrica
de la Facultad de Ingeniería
de la Universidad de Costa Rica
como requisito parcial para optar por el grado de:
BACHILLER EN INGENIERÍA ELÉCTRICA
Aprobado por el Tribunal:
_________________________________
Ing. Rodrigo García León
Profesor Guía
_________________________________
Ing. Lucky Lochi Yu Lo
Profesor lector
_________________________________
Ing. Teodoro Willink Castro
Profesor lector
ii
DEDICATORIA
A Dios,
A mi familia y amigos,
que me han acompañado
en el largo camino
iii
RECONOCIMIENTOS
Un reconocimiento especial a mis padres por su gran ayuda durante toda mi vida.
iv
ÍNDICE GENERAL
ÍNDICE GENERAL ........................................................................................... v
ÍNDICE DE FIGURAS ...................................................................................viii
NOMENCLATURA .......................................................................................... ix
RESUMEN ........................................................................................................... x
CAPÍTULO 1: Introducción ............................................................................. 1
1.1
Introducción ................................................................................................................ 1
1.2
Justificación ................................................................................................................ 2
1.3
Presentación del problema a resolver........................................................................ 3
1.4
Objetivos ..................................................................................................................... 4
1.1.1
Objetivo general ................................................................................................. 4
1.1.2
Objetivos específicos ......................................................................................... 4
1.5
Metodología ................................................................................................................ 5
CAPÍTULO 2: Desarrollo teórico .................................................................... 6
2.1
Principios de reconocimiento biométrico mediante huellas dactilares ................... 6
2.1.1
Características Globales..................................................................................... 6
2.1.2
Características 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
v
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
CAPÍTULO 3: Trabajo previo al desarrollo del software ......................... 18
3.1
El lector de huellas dactilares U.Are.U 4500 de DigitalPersona...........................18
3.2
Elección la plataforma de Desarrollo......................................................................19
3.3
Elección del entorno integrado de desarrollo .........................................................20
3.4
Visión general del CRB ...........................................................................................21
3.5
Estructura de la base de datos..................................................................................23
CAPÍTULO 4: Cliente de comunicación 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
CAPÍTULO 5: Interfaz para la administración de bases de datos CRB. 32
CAPÍTULO 6: Conclusiones y recomendaciones ........................................ 37
6.1
Conclusiones.............................................................................................................37
6.2
Recomendaciones .....................................................................................................38
BIBLIOGRAFÍA............................................................................................... 40
APÉNDICE A: Código del cliente de comunicación 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
vi
A.5.
Archivo enroll.h........................................................................................................58
A.6.
Archivo enroll.cpp....................................................................................................66
APÉNDICE B: Código de la interfaz para administración 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
Apéndice C: Sentencia de SQL para la creación de la base de datos
crb_db1. .............................................................................................................. 84
Apéndice D: Funciones del Dispositivo utilizas. ........................................... 85
2.7.1
Funciones de extracción...................................................................................89
2.7.2
Funciones de comparación ..............................................................................91
ANEXOS............................................................................................................. 93
vii
ÍNDICE DE FIGURAS
Figura 2.1 Ejemplo de área patrón [3]................................................................................... 7
Figura 2.2 Ejemplo de Delta [3]............................................................................................. 7
Figura 2.3 Patrones básicos 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 abstracción del programa CRB. .....................................................28
Figura 4.5. Diagrama de flujo del almacenamiento de información. ................................29
Figura 4.6. Ventana del modo de control de acceso ...........................................................30
Figura 5.1. Módulos de la Interfaz Web..............................................................................32
Figura 5.2. Resultado mostrado por el navegador Web......................................................33
Figura 5.3. Resultados de búsqueda.....................................................................................34
Figura 5.4. Resultados del Registro de marcas de personal ...............................................35
Figura 5.5. Eliminación de un usuario.................................................................................36
viii
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.
ix
RESUMEN
En el presente proyecto se aborda la creación de un sistema que registra las entradas
y salidas de personal en alguna empresa o institución mediante la identificación de su
huella dactilar, siguiendo una metodología de búsqueda de soluciones y elección de la de
mejor ajuste a las necesidades y una programación modular. El resultado obtenido es un
sistema funcional en sus aspectos más básicos, con los suficientes requerimientos para ser
una versión alfa y con la necesidad de darle seguimiento para obtener un producto con
mejor acabado. En conclusión, se logró alcanzar la totalidad de los objetivos planteados y
se recomienda seguir con un proceso de mejoramiento de los resultados obtenidos.
x
1
CAPÍTULO 1: Introducción
1.1
Introducción
Cuando los seres humanos interactúan con otras personas, la identificación se
realiza por características como su apariencia física. En caso de que una prueba de la
identidad de la persona sea requerida, se recurre a algún tipo de tarjeta de identificación,
como la cédula de identidad, el pasaporte o incluso la firma. Sin embargo, técnicas de
identificación pueden ser fácilmente falsificables. Por este motivo se desarrolló la
biometría, ciencia que estudia la identificación de personas por medio de características
anatómicas. La gran ventaja de la identificación biométrica radica en que las características
analizadas son prácticamente irrepetibles en diferentes seres humanos y la falsificación de
las mismas es extremadamente difícil.
Por este motivo, el desarrollo de soluciones biométricas en el área digital ha tenido
un enorme desarrollo, especialmente en la identificación 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, además del control de asistencia de
personal.
1.2
Justificación
Cuando una empresa es de gran tamaño y sus empleados son muchos, la pérdida 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 pérdidas económicas. Además 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 país se sustenta en su capacidad para producir y dar respaldo a esta
producción, por esto es importante que se motive la creación de soluciones para las
necesidades del sector productivo del país 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 diseño e implementación de un
sistema de registro de personas mediante huellas dactilares y dar cabida a la elaboración de
este proyecto.
2
1.3
Presentación del problema a resolver
El problema que se aborda en este trabajo es la creación de un programa de
computadora que permita el control de entradas y salidas de personal a una institución 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 información sobre las huellas digitales del personal y
guardarlo junto con la información pertinente dentro de una base de datos. También debe
ser capaz de realizar la comparación 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 fácil de accesar a toda la información 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 vía de Internet.
Por este motivo, se busca que el programa tenga una orientación modular, y de esta
forma poder enfocarse en sectores específicos del programa por separado, siguiendo el
viejo adagio “divide y vencerás”.
3
1.4
Objetivos
1.1.1
Objetivo general

Conformar un sistema de registro de personas mediante la identificación a partir de
la huella dactilar.
1.1.2

Objetivos específicos
Realizar un estudio acerca de las tecnologías existentes en la identificación de
personas mediante huella dactilar.

Estructurar una solución persiguiendo la versatilidad y fácil adopción de empresas o
individuos interesados.

Programar una aplicación multiplataforma que interactúe con el hardware
especializado para la identificación mediante huella dactilar.

Implementar una interfaz Web para la administración y consulta del registro de
personas.

Elaborar manuales e instructivos de capacitación para el uso del sistema.
4
1.5
Metodología

Se indagará sobre las opciones que existen en el mercado para soluciones
biométricas y el hardware existente para tales fines, en miras de la elección de la
mejor opción. Tomando en cuenta precio, factibilidad de uso del hardware para
crear nuevas aplicaciones desde código fuente y disponibilidad de compra desde
Costa Rica.

Se seleccionará y adquirirá el hardware requerido junto con las herramientas de
programación necesarias para la creación de nuevas aplicaciones.

Se seleccionará la plataforma de operación (sistema operativo) en la cual se creará
la aplicación y el IDE sobre el cual se desarrollará la aplicación.

Se creará una la aplicación mediante un proceso de pruebas y depuración de errores
del código elaborado, que cumpla con necesidades planteadas

Se formulará un manual del usuario para la aplicación desarrollada.
5
6
CAPÍTULO 2: Desarrollo teórico
2.1
Principios
de
reconocimiento
biométrico
mediante
huellas
dactilares
Los dedos tienen superficies rugosas que permiten a los seres humanos tener más
fricción para tomar objetos y sostenerse de superficies sin deslizamientos. Estas
rugosidades forman patrones que son prácticamente únicos e irrepetibles en los seres
humanos. La identificación de personas se realiza por medio de dos características en estos
patrones: características globales y características locales.
Las características globales en las huellas dactilares son aquellas que se pueden
observar a simple vista, mientras que las características locales son llamadas puntos de
minutia. El arreglo bidimensional de la posición de los puntos de minutia es utilizado en los
algoritmos de reconocimiento debido a que diferentes personas pueden tener características
globales similares, mientras que es muy poco probable que dos personas tengan arreglos de
puntos de minutia similares, además de tener la ventaja de que un patrón de este tipo puede
ser cuantificable, lo cual hace esta técnica candidata ideal para ser implementada de forma
digital.
2.1.1
Características Globales
Algunos tipos de características globales son el área patrón, la delta y el patrón
básico, aunque existen muchas otras que ayudan a la clasificación manual de las huellas
digitales. El área patrón es el área principal donde se incluyen la mayoría de las
características globales, un ejemplo de esta área se muestra en la figura 2.1.
Figura 2.1 Ejemplo de área patrón [3]
La delta es un punto de bifurcación abrupta o encuentro de líneas digitales donde se
pueden formar puntos o fragmentos cortos de línea, un ejemplo de una delta se muestra en
la figura 2.2.
Figura 2.2 Ejemplo de Delta [3]
El patrón básico de las huellas es por así decirlo, la forma adoptan las líneas. Entre
las más comunes están el arco, el lazo, y el remolino, los cuales se muestran en la figura 2.3
en ese orden respectivo.
7
Figura 2.3 Patrones básicos de huellas.[3]
2.1.2
Características locales.
Las líneas que conforman una huella digital no son continuas ni rectas, éstas
generalmente se rompen, dividen, interrumpen y cambian de dirección. Los puntos donde
las líneas sufren esa clase de cambios y que proveen información distinguible, perdurable y,
más importante aún, cuantificable, son los puntos de minutia. Estos puntos tan importantes
para el reconocimiento digital se clasifican según su tipo, su orientación, su frecuencia
espacial, su curvatura y su posición.
Según su tipo los puntos de minutia pueden ser clasificados como:

Fin de línea

Bifurcación de línea en dos.

Isla o punto. Es una línea que empieza y acaba en un trayecto muy corto.

Encapsulamiento. Se produce cuando una línea se divide y rápidamente se
vuelve a juntar.
8
2.2
One Touch® for Windows® SDK C/C++ Edition
A continuación 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 después del estudio de tecnologías y
posibilidad de implementación en el trabajo.
El paquete de desarrollo de software SDK, One Touch® para Windows® C/C++
Edition, versión 1.4, es el paquete que contiene todos los elementos necesarios para el
desarrollo de una aplicación que interactúe con los lectores de huellas digitales de
DigitalPersona, incluida la interfaz de programación de aplicaciones o API, las librerías
estáticas y dinámicas requeridas para comunicarse con el hardware desde un nivel de
abstracción más alto (como lo es el lenguaje C++) y los controladores requeridos por el
sistema operativo para el control del hardware. La instalación de este paquete se encuentra
explicada detalladamente en la guía 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 programación de aplicaciones de DigitalPersona es la que realmente
facilita la interacción 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.
9
Para hacer uso del API se deben agregar librerías estáticas en el linker del
compilador a utilizar, para que las llamadas a estas librerías que se encuentran en los
archivos de encabezado, que también deben ser agregados, sean comprendidas por el
compilador
El API se encuentra dividido en dos: el núcleo 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
información sobre la huella digital y realizar una verificación de una huella contra una
plantilla existente. Además, el encapsulamiento incluye una enumeración utilizada en las
dos funciones y dos funciones callback. Una función callback consiste en un código
ejecutable que es pasado como argumento a otro código, esto permite a una capa inferior de
software llamar una subrutina definida en una capa superior.
Dependiendo del tipo de aplicación, puede resultar más fácil 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 comparación. En la comparación se debe realizar esta
operación interactuando con todo un conjunto de elementos presentes en la base de datos a
utilizar y además tomar decisiones que dependen del tiempo, pues se deben registrar
entradas o salidas. Por este motivo el núcleo del API fue la herramienta utilizada.
10
El núcleo contiene funciones, estructuras, enumeraciones, definiciones de tipos de
variables y constantes. Las funciones contenidas dentro del API pueden ser clasificadas en
las siguientes tres categorías:

Funciones del dispositivo: Son utilizadas para comunicarse establecer y
terminar la comunicación con el lector de huellas dactilares

Funciones de extracción: Son utilizadas en el proceso de captura y
procesamiento digital de las imágenes, tanto para el proceso de formación de
nuevas plantillas como en el proceso de comparación. Forman el llamado módulo
de extracción.

Funciones de comparación: son las funciones requeridas para la comparación
de plantillas y determinación de concordancia entre huellas. Forman el llamado
módulo de comparación.
En el apéndice D se presenta una explicación breve de algunas estas funciones,
especialmente las más relevantes para la creación de la solución propuesta.
11
2.4
El IDE de desarrollo Visual C++ 2005
Por motivos que se explican más 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 básicos necesarios que se necesitan conocer. Este entorno de
desarrollo permite la rápida creación de aplicaciones generando grandes cantidades de
código de forma que libera trabajo al programador y le permite centrarse en las necesidades
particulares de su aplicación. El punto más 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 creación 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 código de C++ estándar, o como lo
llaman en la plataforma de desarrollo .Net, código no manejado o nativo. El código CLR es
llamado código manejado y tiene grandes dificultades con la interacción de código 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 código 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 código nativo.
12
2.5
El Software WampServer.
Para implementar la parte Web del proyecto de requiere una estructura que dé
soporte a la página web, después de una búsqueda 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. Además 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 código abierto, con licencia GPL. La versión 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 fundación 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 estándares de HTTP.
A través de la interfaz de WampServer se puede iniciar y detener Apache Server, e
incluso cambiar algunas de sus características, pero para una configuración más profunda
se puede modificar el archivo de configuración de Apache, httpd.conf y manejarlo desde
línea de comandos.
13
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
también es posible comprar una versión licenciada. MySQL permite estructurar bases de
datos y realizar consultas a través 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 código a lenguaje máquina cada vez que se desea ejecutar. Esto trae
consigo una problemática para las aplicaciones Web: que el código debe ser ejecutado del
lado del servidor, en el caso de que el código PHP deba ser ejecutado solo bajo ciertas
condiciones o con ciertos parámetros acrecenta la problemática, por la necesidad de una
comunicación asincrónica 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
comunicación con MySQL a través 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 también sobre la estructura que da soporte a la base de datos y la
mejor opción para esto es MySQL por esto se dedica un apartado para hablar sobre el API
de MySQL, pues es la herramienta de conexión entre el software y la base de datos usada.
14
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 librerías estáticas al Linker del compilador a utilizar y los encabezados
que hacen los llamados a estas librerías estáticas. Dentro de las funciones más 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 conexión con la base de datos.
2.7

mysql_real_query(query): envía 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
AJAX
AJAX no es una tecnología, es un conglomerado de tecnologías existentes que ha
permitido lograr grandes avances en el mundo del Internet. La idea detrás de AJAX es
evitar la necesidad de tener que estar cargando una página Web cada vez que el usuario
interactúa con ella y se deben generar cambios. Una vez cargada y renderizada la página,
AJAX permite una comunicación asincrónica con el servidor, para traer datos que serán
usados solo en una nueva re-renderización del sitio, evitando la necesidad de tener que
15
cargar toda la página. 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 página. Esto no es de extrañar pues Google ha sido uno de los
más fuertes impulsores de AJAX.
“AJAX es realmente muchas tecnologías, cada una floreciendo por su propio
mérito, uniéndose en poderosas nuevas formas. AJAX incorpora:

presentación basada en estándares usando XHTML y CSS;

exhibición e interacción dinámicas usando el Document Object Model;

Intercambio y manipulación de datos usando XML and XSLT;

Recuperación de datos asincrónica usando XMLHttpRequest;

y JavaScript poniendo todo junto.” [2]
El modelo de transmisión de información queda ejemplificado en la figura 2.4. Aquí
se puede ver claramente las enormes ventajas de AJAX respecto a las nuevas posibilidades
que brinda.
16
Figura 2.4 Modelo de diseño Web con AJAX. [2]
Como se aprecia, en el antiguo modelo cada vez que el cliente requiere nueva
información debe realizar una llamada al servidor Web el cual le reenviará toda la
información y se deberá volver a cargar toda la página. En contraposición utilizando AJAX
se pueden enviar datos sin la necesidad de cargar toda la página, esto se traduce en un
aumento de la velocidad pues la cantidad de datos que se transmiten en ambos sentidos se
reduce considerablemente.
17
CAPÍTULO 3: Trabajo previo al desarrollo del software
3.1
El lector de huellas dactilares U.Are.U 4500 de DigitalPersona.
Para la elaboración de este proyecto fue sumamente importante la elección
adecuada del hardware encargado del escaneo de las huellas digitales. Los parámetros de
selección son principalmente las posibilidades reales de desarrollo de nuevas aplicaciones
con él, el factor económico y la disponibilidad de adquisición. Existen una gran variedad de
componentes para escaneo de huellas digitales, inclusive muchos incorporan teclados
numéricos y módulos para lectura de tarjetas de tecnología magnética. Estas capacidades
incrementan en gran medida la seguridad y se usan principalmente en el caso de restricción
de acceso físico a algún lugar, pero debido a la inclusión 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 características similares era muy
parecido al momento de la elección, en donde el factor económico fue de peso fue en los
paquetes de desarrollo de software para cada uno de los dispositivos. Para muchos de ellos
el costo podía alcanzar hasta los 600 USD.
Por este motivo la opción 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 página de
DigitalPersona se pueden descargar paquetes de desarrollo de software de versiones más
18
antiguas que la que se comercializa en este momento, lo cual permitió el desarrollo del
proyecto a un bajo costo. El contra que poseía la elección 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 Apéndice A de este documento.
Figura 3.1. Lector de huellas digitales U.are.U 4500
3.2
Elección 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 máximo las opciones de
código abierto para la elaboración de las aplicaciones, por lo cual en un primer momento se
19
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 código 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 técnicos, 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
Elección 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 extensión de Dev-C++ utilizando wxWidgets. Este último es un
Framework que permite la creación de aplicaciones de Windows basadas en formularios.
Esta primera opción fue descartada por ser un proyecto de software libre con poco
seguimiento y desarrollo, que contiene algunas pulgas aún.
La segunda opción 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
20
cual es un puerto del compilador de GCC de GNU, aunque si se encuentran instalados se
puede seleccionar otros compiladores. Esta opción 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 librerías estáticas
y dinámicas. Por este motivo se decidió seguir trabajando con la tercera opción 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
Visión general del CRB
La aplicación que se desarrolló es llamada Control de Registro Biométrico (CRB) y
la misma sigue una concepción modular por lo que está organizada en cuatro bloques
principales:

Un cliente de registro de nuevo personal, y confirmación 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
específicas de la aplicación CRB.

Un servidor Web Apache que incluye un interpretador PHP y todas las
prerrogativas de comunicación entre el interpretador PHP y la base de datos.
21

Y por último la interfaz Web por la cual el usuario tiene acceso a la información de
la base de datos.
Los bloques anteriormente mencionados se muestran en el diagrama esquemático de la
figura 3.2.
APACHE y
PHP
Base de Datos
MySQL
Cliente de
comunicación
con el lector
de huellas
Interfaz Web
Usuario
Figura 3.2. Diagrama modular de CRB.
Los usuarios finales solo tienen acceso a la interfaz Web y al cliente de
comunicación con el lector de huellas dactilares, el resto de partes son transparentes al
usuario.
22
3.5
Estructura de la base de datos.
Debido a que el sistema desarrollado todavía es una versión alfa, se decidió incluir dentro
de la base de datos la información básica 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 número de cédula 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 información
elemental del empleado. El espacio DataTemplate no es usado en la versión que ha sido
desarrollada, pero ha sido incluido como una prevista importante, pues en este momento la
información sobre las huellas digitales de los usuarios se guarda de forma independiente en
un archivo extensión crbt, aunque lo óptimo sería almacenar la información dentro de la
misma base de datos de forma binaria, es por esto que el espacio DataTemplate es tipo
23
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 generación de la tabla se encuentra en el apéndice C.
24
CAPÍTULO 4: Cliente de comunicación con el lector de huellas
digitales CRB.
El software encargado de comunicarse con el lector de huellas digitales y almacenar
nueva información sobre el registro de personas en la base de datos fue desarrollado en el
lenguaje C++. El código de este software se encuentra en el apéndice 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 operación del
software. En la figura 4.1 se muestra la ventana principal. Además permite al usuario ver la
información básica sobre el software CRB y salir del programa, ya sea mediante la
secuencia Archivo -> Salir o dando click en el botón cerrar de Windows.
Figura 4.1. Ventana principal del CRB.
25
Los dos modos de operación 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 más fácilmente lo que está haciendo y además se
facilita la labor de programación, pues se independizan las tareas de almacenamiento de
plantillas de huellas dactilares y la comparación de plantillas almacenadas.
Desde el punto de vista de programación 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. Además el programa inicia con la ejecución
de CRB.cpp, que es el archivo principal donde se inicializa el U.are.U 4500, se establece la
conexión 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
26
Inicio
Error
Inicializar el
hardware.
DPFPInit
Exitoso
Error
Crear un
contexto de
extracción
FX_init
Exitoso
Crear un
contexto de
comparación
MC_init
Error
Exitoso
Establecer conexión con MySQL
mysql_real_connect.
Abrir la ventana principal
Continuar con la ejecución desde ahí
Liberar recursos, y cerrar la
conexión con MySQL.
mysql_close, MC_terminate,
FX_terminate, DPFPTerm.
Figura 4.3. Diagrama de flujo de CRB.cpp.
27
Return 0
En general el programa puede ser analizado desde sus diferentes niveles de abstracción,
(ver figura 4.4), este enfoque permite identificar donde están los problemas, si son a nivel
de código del programa, a nivel de dependencias de la funciones (encabezados) o a nivel de
librerías dinámicas (problemas en el linker).
Aplicación desarrollada en C++
API accesado mediante los encabezado
Librerias dinámicas agregadas al linker
OS y controladores se comunican con el hardware
Figura 4.4. Niveles de abstracción 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
líneas de texto sobre el estado actual, espacios para introducir información necesaria para el
registro de personal nuevo y dos botones: uno para guardar la información 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 información sobre la huella digital de la persona en una plantilla. Este
proceso tiene la secuencia que se muestra en la figura 4.5, después de haberse creado los
contextos de extracción y comparación requeridos por el API de DigitalPersona.
28
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 características y
guardarlas en una plantilla de pre-registro en memoria.
¿Existen suficientes
plantillas de pre-registro?
No
Si
Guardar las características en una plantilla definitiva y
almacenar la información en forma externa al programa
Figura 4.5. Diagrama de flujo del almacenamiento de información.
Una vez almacenada la información solo queda generar un stream binario para
almacenarla en un archivo con extensión crbt codificado con la huella digital de la persona
y guardar la información personal en la base de datos. Por este motivo al dar click en
guardar se revisa que la información 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 interacción 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
29
4.6. La misma posee tres líneas de información, 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 programación lo más importante es el algoritmo de búsqueda
que se emplea. Por el momento el algoritmo empleado es muy simple y consiste en una
comparación uno a uno, principalmente por dos motivos. Primero, se necesita un
conocimiento mucho más profundo sobre la forma en que opera el lector de huellas
dactilares, aun más allá del manejo del API, para implementar algún tipo de algoritmo más
complejo y segundo, el corto tiempo que se tiene para desarrolla un proyecto de forma
individual dificulta el concentrar esfuerzos en un punto específico del sistema como este.
Es claro que el algoritmo es funcional y eficiente para alguna empresa pequeña, pero
30
conforme va creciendo la cantidad de usuarios del sistema, el algoritmo se va convirtiendo
cada vez más ineficiente.
31
CAPÍTULO 5: Interfaz para la administración de bases de datos
CRB.
Para ver la información sobre entradas y salidas del personal se desarrollo una
interfaz Web. Esta interfaz tiene una estructura modular la cual le permite establecer una
comunicación asincrónica entre el un servidor Apache y un navegador Web. Los módulos
tienen la estructura que se muestra en la figura 5.1
query_name
query_apellido1
Código
HTML
cliente.php
query_apellido2
Código
JavaScript
ajax.js
query_cedula
Base de
datos
crb_db1
query_marcas
query_eliminar
Figura 5.1. Módulos de la Interfaz Web
El primer bloque está formado por el archivo cliente.php. Aunque está conformado
casi completamente por código html, éste debe ser un archivo de extensión php. Esto se
debe a que debe ser preprocesado por el interpretador PHP antes de ser enviado al cliente
que lo está accediendo desde algún navegador Web desde cualquier lugar del mundo para
32
que pueda comunicarse adecuadamente con los otros módulos. 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 información de una
persona, por cuatro criterios de búsqueda diferentes: Nombre, Primer Apellido, Segundo
Apellido y Número de Cédula. Los resultados se muestran en el mismo espacio de la tabla
por debajo de los criterios de búsqueda como se muestra en la figura 3.3.
La operación realizada es la siguiente: un objeto AJAX creado mediante el script
ajax.js es usado a través de una función Consulta que se encuentra también en el mismo
script. Esta función envía información a cuatro diferentes códigos PHP dependiendo de qué
33
tipo de búsqueda se vaya a realizar. Es por esto que existen cuatro bloques query_,
correspondientes a cada una de las búsquedas. Los bloques query_ sea query_name,
query_apellido1, query_apellido2 o query_cedula, son ejecutados del lado del servidor,
debido a que están escritos en PHP y requieren del interpretador. Una vez procesados, éstos
devuelven la información 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 información de regreso a código en JavaScript.
Posteriormente la función Consulta se encarga de colocar los resultados en el código
HTML y decirle al navegador Web que debe re-renderizar la página.
Figura 5.3. Resultados de búsqueda
Otra de las operaciones que puede realizar el usuario, y tal vez la más importante, es
ver el registro de entradas y salidas del personal. Para ver los datos de una persona se
necesita conocer el número de cédula de ella. La búsqueda, al igual que en el modo
anterior, se realiza mediante un objeto AJAX, pero este se comunicará esta vez con el
bloque de código query_marcas escrito en PHP. La solución utilizada es la misma y la
34
forma en que se presentan lo resultados se muestra en la figura 3.4. Es en este punto de la
interfaz donde más se puede avanzar. Deben agregarse bloques que permitan filtrar las
marcas de algún usuario o ver los datos de un día en específico. 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 eliminación
de usuarios vía su número de cédula. Esta operación se ha agregado solamente aquí en esta
35
versión alfa, pero en versiones posteriores debe ser agregada también en la aplicación de
escritorio mediante código C++. Se ha agregado aquí principalmente porque la interfaz
Web puede ser accesada prácticamente desde cualquier lugar del mundo y no requiere de
una presencia física en el sitio de trabajo, como sí sucede con la aplicación de escritorio. En
lo que a programación se refiere, se realiza a través del bloque query_eliminar escrito en
PHP. Este bloque de código 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 número de cédula de la persona como la fila respectiva en la
tabla empleados. Como resultado este enviará solamente una línea de texto indicando que la
operación fue realiza con éxito, y el código ajax.js en JavaScript se encarga de que la
página sea re-renderizada y mostrar un resultado como el que se aprecia en la figura 3.5.
Figura 5.5. Eliminación 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.
36
CAPÍTULO 6: Conclusiones y recomendaciones
6.1
Conclusiones
Una búsqueda concienzuda y comparativa fue la que permitió realizar una elección
adecuada del hardware a utilizar, lo que a la postre vino a significar facilidades en el
proceso de programación y el satisfactorio fin de este trabajo.
El seguimiento de una estrategia clara de división 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 aplicación de escritorio y una interfaz Web.
De no ser este el enfoque no sería posible manipular la información desde rutas tan
diferentes como lo son el Internet y una aplicación de escritorio.
Durante la elaboración de este proyecto siempre se buscó que la solución
desarrollada tuviera un enfoque abierto el cual pudiera fácilmente ser adoptado en la gran
mayoría de casos donde se requiera una aplicación similar, y que a partir de la solución
planteada se pueda seguir trabajando para satisfacer las necesidades específicas del usuario
final. Esto se concretó, aunque aún se debe seguir trabajando en esta aplicación,
especialmente en los puntos que se abordan en las recomendaciones.
La interfaz Web desarrollada puede ser accesada desde los múltiples sistemas
operativos existentes, e incluso el código está hecho para preveer diferencias entre los
navegadores Web más populares del mercado lo cual hace que esta parte del sistema sea
multiplataforma. La aplicación de escritorio solo pudo ser desarrollada para Windows por
los problemas mencionados en el Capítulo 4. A pesar de esto si se pudiera contar
37
principalmente con los manejadores de hardware actualizados, partes importantes del
código desarrollado podría ser exportadas a una aplicación 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 solución deseada fueron conseguidos, pero es importante recalcar que
en esta clase de aplicaciones siempre debe existir una idea de mejoramiento continuo y aún
queda trabajo para obtener un producto final de alta calidad.
6.2
Recomendaciones
La aplicación desarrollada tiene mucho trabajo por delante antes de poder ser un
versión candidata a definitiva, entre los puntos en los que se debe trabajar para mejor el
sistema CRB se encuentran los siguientes.
Incluir la información 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 además facilita enormemente la tarea de respaldar la información.

Incluir el manejo de excepciones en el código de programa CRB hecho en C++,
para evitar comportamientos inesperados que podrían dañar valiosa información de
la base de datos.

Estandarizar la interfaz Web de manejo de bases de datos CRB, conforme lo
establece la W3C.
38

Buscar una mejor forma de enviar los resultados de la búsqueda en la base de datos
del código PHP a la interfaz Web para presentar la información de forma más
agradable.

Tomar en cuenta todos los posibles fallos del usuario en el ingreso de información.
En número de cédula, por ejemplo, se debe tomar medidas en caso de que el usuario
del programa no dé el número completo o incluya letras o espacios dentro de la caja
de texto establecida para ingresar tal número.

Mejorar el algoritmo de búsqueda del modo de control de acceso pues resulta
ineficiente conforme crece la cantidad de personal registrado.

Crear un programa instalador para la aplicación que pueda dejar el programa
funcional sin la intervención de un programador.

Incluir seguridad en el sistema, principalmente la implementación de usuarios y la
autenticación para el uso del programa, y posteriormente la encriptación de la
información que deberá viajar por Internet en la interfaz Web.

Debido a que la solución elaborada representa una versión alfa, el manual del
usuario elaborado deben ser puesto bajo revisión pues apenas cuentan con la
información necesaria para explicar al usuario como manejarse en el sistema pero
no prevén los problemas de desarrollo que hayan sido pasados por alto o que
todavía no son del conocimiento del desarrollador del sistema CRB.
39
BIBLIOGRAFÍA
Artículos de revistas:
1. Jiménez, J.M. Marín J.G. “Sistema de reconocimiento de huellas dactilares”,
Mundo Electrónico, España, 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++ Cómo programar” Segunda edición, Prentice Hall,
México, 1999.
Páginas Web:
5. “PHP Manual”, http://www.php.net/manual/en/
6. “Versión 2.2 de la documentación del Servidor de HTTP Apache”,
http://httpd.apache.org/docs/2.2/
7. Garretr,
J.J.
“AJAX:
A
New
Approach
to
http://adaptivepath.com/ideas/essays/archives/000385.php.
40
Web
Application”,
APÉNDICE A: Código del cliente de comunicación 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 <Winsock.h>
#include <mysql.h>
using namespace CRB;
#define
#define
#define
#define
host "localhost"
username "admin"
password "crb"
database "crb_db1"
[STAThreadAttribute]
int main(array<System::String ^> ^args){
//Localiza e inicializa los recursos necesarios para el funcionamiento
del API
if(FAILED(DPFPInit())==TRUE);
else{
// Inicializa el módulo de extracción del SDK
if (FT_OK == FX_init())
{
// Inicializa el módulo de comparación del SDK
if (FT_OK == MC_init())
{
41
// 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 conexión 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 módulo de comparación del SDK
MC_terminate();
}
else {
MC_terminate();
FX_terminate();
DPFPTerm ();
return 0;
}
// Libera recursos del módulo de extracción del SDK
FX_terminate();
}
else {
FX_terminate();
DPFPTerm ();
return 0;
}
}
DPFPTerm ();
return 0;
}
42
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 declaración como el contenido de las
funciones de la ventana principal, la cual se encarga de llamar los
dos diferentes modos de operación y distribuir información de
conexión a MySQL.
******************************************************************/
#pragma once
//Encabezados de los modos de operación
#include "enrrol.h"
#include "Verform.h"
//Encabezados necesarios para la conexion la base de datos de MySQL
#include <Winsock.h>
#include <mysql.h>
//Encabezados para la manipulacion de caracteres
#include <iostream>
#include <fstream>
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()
43
{
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
MYSQL*
m_RegTemplate;
conn;
#pragma region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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);
44
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
45
//
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<System::Drawing::Icon^
>(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^
System::EventArgs^ e) {
this->Hide();
enrrol ^form2 = gcnew enrrol();
form2->GetConnetionLinker(conn);
form2->ShowDialog(this);
this->Show();
46
sender,
}
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 aplicación?",
"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
Biométrico\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"
47
#include "dpFtrEx.h"
#include "dpMatch.h"
#include "DpUIApi.h"
//Encabezados necesarios para la manipulacion de caracteres
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
//Encabezados para la conexion con la base de datos
#include <Winsock.h>
#include <mysql.h>
using
using
using
using
using
using
using
using
using
using
namespace
namespace
namespace
namespace
namespace
namespace
namespace
namespace
namespace
namespace
std;
System;
System::ComponentModel;
System::Collections;
System::Windows::Forms;
System::Data;
System::Drawing;
System::Globalization;
System::IO;
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
48
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:
private:
private:
private:
private:
System::Windows::Forms::Label^ label1;
System::Windows::Forms::Button^ button1;
System::Windows::Forms::Label^ label2;
System::Windows::Forms::Label^ label3;
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;
49
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<System::Drawing::Icon^
>(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";
50
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<DATA_BLOB*>((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:
51
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;
}
52
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<FT_HANDLE> 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<FT_HANDLE> 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<HDPOPERATION> 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^
System::EventArgs^ e) {
53
sender,
//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 tamaño 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,
extraccion
iFingerprintImageSize,
imagen escaneada
pFingerprintImage,
buffer para contener la imagen
FT_VER_FTR,
Verification Features
iRecommendedVerFtrLen,
que recibe la informacion de la plantilla
54
// Contexto para la
// Tamaño de la
// Puntero a algun
// Requested
// Tamaño del buffer
pVerTemplate,
donde se almacena la plantilla
&imgQuality,
calidad de la imagen
&ftrQuality,
calidad de las caracteristicas
&bEextractOK);
extracción
// Puntero al buffer
// Retorna la
// Retorna la
// Resultado de la
if (FT_OK <= rc && bEextractOK == FT_TRUE) {
// Plantilla generada exitosamente
// Ahora se comparan la plantilla generada y la proveniente de
las plantillas almacenadas
double dFalseAcceptProbability = 0.0;
FT_BOOL bVerified = FT_FALSE;
rc = MC_verifyFeaturesEx(m_mcContext,
comparación
m_RegTemplate.cbData,
la plantilla almacenada
m_RegTemplate.pbData,
la plantilla almacenada
iRecommendedVerFtrLen,
la plantilla a ser verificada
pVerTemplate,
la plantilla a ser verificada
0,
debe ser 0
NULL,
debe ser NULL
NULL,
debe ser NULL
NULL,
debe ser NULL
&dFalseAcceptProbability,
Probabilidad de concordancia falsa
&bVerified);
de la comparación
if (FT_OK <= rc) {
if (FT_OK != rc) {
WCHAR buffer[101] = {0};
ULONG uSize = 100;
}
if (bVerified == FT_TRUE) {
match_flag = true;
this->label3->Text = L"Scan another finger
verification again.";
WCHAR buffer[101] = {0};
ULONG uSize = 100;
}
else {
55
// Contexto de
// puntero a
// tamaño de
// tamaño de
// Puntero a
// Obsoleto,
// Reservado,
// Reservado,
// Reservado,
//
// resultado
to run
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-MMdd",myDTFI));
char* Hora =
(char*)(void*)Marshal::StringToHGlobalAnsi(Marca.ToString("HH:mm::ss",myD
TFI));
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;
56
char*
MYSQL_ROW
sql;
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);
57
this->label1->Text
this->label2->Text
exitosamente";
}
else{
this->label1->Text
this->label2->Text
}
}
= L"Puede proceder a realizar otra marca";
= L"Bienvenido. Su marca ha sido registrada
= L"Su huella no se encuentra registrada";
= L"Intente nuevamente por favor";
System::Void Verform::Verform_FormClosing(System::Object^
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;
}
}
sender,
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: enrroll.cpp
Este archivo contiene las declaraciones funciones que correponden
a la ventana de registro de nuevo personal, (ver enrrol.cpp)
y forma parte del cliente de comunicacion con el lector de huellas
digitales U.are.U 4500
******************************************************************/
#pragma warning( disable : 4368)
58
#pragma once
//Encabezados para la conexion con la base de datos
#include <Winsock.h>
#include <mysql.h>
//Encabezados de DigitalPersona
#include "resource.h"
#include "dpRCodes.h"
#include "dpDefs.h"
#include "DPDevClt.h"
#include "dpFtrEx.h"
#include "dpMatch.h"
#include "DpUIApi.h"
//Encabezados manejo de cadenas de caracteres
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
using
using
using
using
using
using
using
using
using
namespace
namespace
namespace
namespace
namespace
namespace
namespace
namespace
namespace
std;
System;
System::ComponentModel;
System::Collections;
System::Windows::Forms;
System::Data;
System::Runtime::InteropServices;
System::Globalization;
System::IO;
namespace CRB {
public ref class enrrol : public System::Windows::Forms::Form{
public:
enrrol(void){
InitializeComponent();
::ZeroMemory(&m_RegTemplate, sizeof(m_RegTemplate));
}
protected:
~enrrol(){
if (components){
delete components;
}
delete [] m_RegTemplate.pbData;
m_RegTemplate.cbData = 0;
m_RegTemplate.pbData = NULL;
}
private: static const UINT FP_EVENT = (WM_USER+1);
59
private:
// Contexto de extraccion
FT_HANDLE
m_fxContext;
// Contexto de comparacion
FT_HANDLE
m_mcContext;
// Handle de la operacion
HDPOPERATION
m_hOperationEnroll;
// Numero de plantillas de pre-registro
int
m_NumberOfPreRegFeatures;
// Arreglo que contiene las pantillas de pre-registro
FT_BYTE**
m_TemplateArray;
// Indice de la plantilla de pre-registro
int
m_nRegFingerprint;
// Objeto binario donde se almacen las plantillas de huellas
dactilares
DATA_BLOB
m_RegTemplate;
// Link a la conexion con MySQL
MYSQL*
conn;
// Puntero a un objeto encargado de almacenar resultados de una
consulta
MYSQL_RES*
mysql_res;
// cadena de caracteres con una sentencia SQL
CHAR*
sql;
private:
private:
private:
private:
private:
private:
private:
private:
private:
private:
private:
private:
private:
private:
private:
private:
System::Windows::Forms::Label^
System::Windows::Forms::TextBox^
System::Windows::Forms::Label^
System::Windows::Forms::Label^
System::Windows::Forms::TextBox^
System::Windows::Forms::Label^
System::Windows::Forms::TextBox^
System::Windows::Forms::Label^
System::Windows::Forms::Label^
System::Windows::Forms::Button^
System::Windows::Forms::Button^
System::Windows::Forms::TextBox^
System::Windows::Forms::TextBox^
System::Windows::Forms::Label^
System::Windows::Forms::Label^
System::Windows::Forms::GroupBox^
label1;
textBox1;
label2;
label3;
textBox2;
label4;
textBox3;
label5;
label6;
button1;
Guar_button;
textBox4;
textBox5;
label7;
label8;
groupBox1;
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
void InitializeComponent(void){
System::ComponentModel::ComponentResourceManager^
resources
= (gcnew
System::ComponentModel::ComponentResourceManager(enrrol::typeid));
this->label1 = (gcnew System::Windows::Forms::Label());
this->textBox1 = (gcnew System::Windows::Forms::TextBox());
this->label2 = (gcnew System::Windows::Forms::Label());
60
this->label3 = (gcnew System::Windows::Forms::Label());
this->textBox2 = (gcnew System::Windows::Forms::TextBox());
this->label4 = (gcnew System::Windows::Forms::Label());
this->textBox3 = (gcnew System::Windows::Forms::TextBox());
this->label5 = (gcnew System::Windows::Forms::Label());
this->label6 = (gcnew System::Windows::Forms::Label());
this->button1 = (gcnew System::Windows::Forms::Button());
this->Guar_button = (gcnew System::Windows::Forms::Button());
this->textBox4 = (gcnew System::Windows::Forms::TextBox());
this->textBox5 = (gcnew System::Windows::Forms::TextBox());
this->label7 = (gcnew System::Windows::Forms::Label());
this->label8 = (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(21, 25);
this->label1->Name = L"label1";
this->label1->Size = System::Drawing::Size(35, 13);
this->label1->TabIndex = 0;
this->label1->Text = L"label1";
//
// textBox1
//
this->textBox1->Location = System::Drawing::Point(54, 193);
this->textBox1->Name = L"textBox1";
this->textBox1->Size = System::Drawing::Size(376, 20);
this->textBox1->TabIndex = 1;
//
// label2
//
this->label2->AutoSize = true;
this->label2->Location = System::Drawing::Point(51, 177);
this->label2->Name = L"label2";
this->label2->Size = System::Drawing::Size(44, 13);
this->label2->TabIndex = 2;
this->label2->Text = L"Nombre";
//
// label3
//
this->label3->AutoSize = true;
this->label3->Location = System::Drawing::Point(51, 340);
this->label3->Name = L"label3";
this->label3->Size = System::Drawing::Size(95, 13);
this->label3->TabIndex = 3;
this->label3->Text = L"Numero de Cédula";
//
// textBox2
//
61
this->textBox2->Location = System::Drawing::Point(54, 248);
this->textBox2->Name = L"textBox2";
this->textBox2->Size = System::Drawing::Size(376, 20);
this->textBox2->TabIndex = 4;
//
// label4
//
this->label4->AutoSize = true;
this->label4->Location = System::Drawing::Point(51, 391);
this->label4->Name = L"label4";
this->label4->Size = System::Drawing::Size(74, 13);
this->label4->TabIndex = 5;
this->label4->Text = L"Departamento";
//
// textBox3
//
this->textBox3->Location = System::Drawing::Point(54, 303);
this->textBox3->Name = L"textBox3";
this->textBox3->Size = System::Drawing::Size(376, 20);
this->textBox3->TabIndex = 6;
//
// label5
//
this->label5->AutoSize = true;
this->label5->Location = System::Drawing::Point(21, 57);
this->label5->Name = L"label5";
this->label5->Size = System::Drawing::Size(35, 13);
this->label5->TabIndex = 7;
this->label5->Text = L"label5";
//
// label6
//
this->label6->AutoSize = true;
this->label6->Location = System::Drawing::Point(21, 89);
this->label6->Name = L"label6";
this->label6->Size = System::Drawing::Size(35, 13);
this->label6->TabIndex = 8;
this->label6->Text = L"label6";
//
// button1
//
this->button1->Location = System::Drawing::Point(336, 471);
this->button1->Name = L"button1";
this->button1->Size = System::Drawing::Size(94, 28);
this->button1->TabIndex = 9;
this->button1->Text = L"Cerrar";
this->button1->UseVisualStyleBackColor = true;
this->button1->Click += gcnew System::EventHandler(this,
&enrrol::button1_Click);
//
// Guar_button
//
62
this->Guar_button->Location = System::Drawing::Point(231,
472);
this->Guar_button->Name = L"Guar_button";
this->Guar_button->Size = System::Drawing::Size(94, 27);
this->Guar_button->TabIndex = 10;
this->Guar_button->Text = L"Guardar";
this->Guar_button->UseVisualStyleBackColor = true;
this->Guar_button->Click += gcnew System::EventHandler(this,
&enrrol::button2_Click);
//
// textBox4
//
this->textBox4->Location = System::Drawing::Point(54, 356);
this->textBox4->Name = L"textBox4";
this->textBox4->Size = System::Drawing::Size(376, 20);
this->textBox4->TabIndex = 11;
//
// textBox5
//
this->textBox5->Location = System::Drawing::Point(54, 407);
this->textBox5->Name = L"textBox5";
this->textBox5->Size = System::Drawing::Size(376, 20);
this->textBox5->TabIndex = 12;
//
// label7
//
this->label7->AutoSize = true;
this->label7->Location = System::Drawing::Point(54, 232);
this->label7->Name = L"label7";
this->label7->Size = System::Drawing::Size(76, 13);
this->label7->TabIndex = 13;
this->label7->Text = L"Primer Apellido";
//
// label8
//
this->label8->AutoSize = true;
this->label8->Location = System::Drawing::Point(51, 287);
this->label8->Name = L"label8";
this->label8->Size = System::Drawing::Size(90, 13);
this->label8->TabIndex = 14;
this->label8->Text = L"Segundo Apellido";
//
// groupBox1
//
this->groupBox1->Controls->Add(this->label1);
this->groupBox1->Controls->Add(this->label5);
this->groupBox1->Controls->Add(this->label6);
this->groupBox1->Location = System::Drawing::Point(54, 36);
this->groupBox1->Name = L"groupBox1";
this->groupBox1->Size = System::Drawing::Size(376, 122);
this->groupBox1->TabIndex = 15;
this->groupBox1->TabStop = false;
63
this->groupBox1->Text = L"Estado";
//
// enrrol
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode =
System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(473, 541);
this->Controls->Add(this->groupBox1);
this->Controls->Add(this->label8);
this->Controls->Add(this->label7);
this->Controls->Add(this->textBox5);
this->Controls->Add(this->textBox4);
this->Controls->Add(this->Guar_button);
this->Controls->Add(this->button1);
this->Controls->Add(this->textBox3);
this->Controls->Add(this->label4);
this->Controls->Add(this->textBox2);
this->Controls->Add(this->label3);
this->Controls->Add(this->label2);
this->Controls->Add(this->textBox1);
this->Icon = (cli::safe_cast<System::Drawing::Icon^
>(resources->GetObject(L"$this.Icon")));
this->MaximizeBox = false;
this->MaximumSize = System::Drawing::Size(481, 575);
this->MinimumSize = System::Drawing::Size(481, 575);
this->Name = L"enrrol";
this->StartPosition =
System::Windows::Forms::FormStartPosition::CenterScreen;
this->Text = L"Registro de Personal";
this->Load += gcnew System::EventHandler(this,
&enrrol::enrrol_Load);
this->FormClosing += gcnew
System::Windows::Forms::FormClosingEventHandler(this,
&enrrol::enrrol_FormClosing);
this->groupBox1->ResumeLayout(false);
this->groupBox1->PerformLayout();
this->ResumeLayout(false);
this->PerformLayout();
}
#pragma endregion
public: System::Void
private: System::Void
System::EventArgs^ e);
private: System::Void
iFingerprintImageSize);
private: System::Void
FT_BYTE* pRegTemplate);
private: System::Void
System::EventArgs^ e);
GetConnetionLinker(MYSQL* connlink);
enrrol_Load(System::Object^ sender,
AddToEnroll(FT_IMAGE_PT pFingerprintImage, int
GuardarArchivo(int iRecommendedRegFtrLen,
button1_Click(System::Object^
64
sender,
private: System::Void enrrol_FormClosing(System::Object^ sender,
System::Windows::Forms::FormClosingEventArgs^ e);
private: System::Void button2_Click(System::Object^ sender,
System::EventArgs^ e);
protected:
virtual void WndProc(Message %m) override{
if (m.Msg == FP_EVENT){
switch((int)m.WParam) {
case WN_COMPLETED: {
this->label5->Text = L"Imagen de la huella
capturada";
DATA_BLOB* pImageBlob =
reinterpret_cast<DATA_BLOB*>((int)m.LParam);
AddToEnroll(pImageBlob->pbData, pImageBlob>cbData);
break;
}
case WN_ERROR: {
MessageBox::Show( "Existio un error interno del
lector", "Error");
break;
}
case WN_DISCONNECT:
this->label6->Text = L"Lector de huellas
digitales desconectado";
break;
case WN_RECONNECT:
this->label6->Text = L"Lector de huellas
digitales conectado";
break;
case WN_FINGER_TOUCHED:
this->label5->Text = L"Huella dactilar
detectada";
break;
case WN_FINGER_GONE:
this->label5->Text = L"Dedo separado del
lector";
break;
case WN_IMAGE_READY:
this->label5->Text = L"Imagen de la huella
dactilar lista";
break;
case WN_OPERATION_STOPPED:
this->label5->Text = L"Fingerprint Enrollment
Operation stopped";
break;
}
}
Form::WndProc(m);
}
};
}
65
A.6. Archivo enroll.cpp
/*****************************************************************
Universidad de Costa Rica
Escuela de Ingenieria Electrica
II Semestre 2009
IE-0502
Proyeto Electrico
Elaborado por: Luis Castro Leiva
A61368
Resumen: enrrol.cpp
Este archivo contiene las funciones que correponden a
la ventana de registro de nuevo personal, (ver enrrol.h)
y forma parte del cliente de comunicacion con el lector de
huellas digitales U.are.U 4500
******************************************************************/
#include "StdAfx.h"
#include "enrrol.h"
using namespace CRB;
System::Void enrrol::GetConnetionLinker(MYSQL* connlink){
//Almacena el link a la conexion establecida con MySQL
conn = connlink;
}
System::Void enrrol::enrrol_Load(System::Object^
System::EventArgs^ e) {
sender,
FT_RETCODE rc = FT_OK;
HRESULT hr = S_OK;
// Se crea un contexto para realizar una extraccion
pin_ptr<FT_HANDLE> pm_fxContext = &m_fxContext;
if (FT_OK != (rc = FX_createContext(pm_fxContext))) {
MessageBox::Show( "Error en FX_createContext", "Error");
}
// Se crea un contexto para la comparacion
pin_ptr<FT_HANDLE> pm_mcContext = &m_mcContext;
if (FT_OK != (rc = MC_createContext(pm_mcContext))) {
MessageBox::Show( "Error en MC_createContext", "Error");
}
// Se obtiene el numero de pre-plantillas necesarias para la creacion
de una plantilla de huella
// Se asigna memoria a un arreglo que almacena estas pre-plantillas
MC_SETTINGS mcSettings = {0};
if (FT_OK != (rc = MC_getSettings(&mcSettings)))
66
MessageBox::Show( "Error en MC_getSettings", "Error");
m_NumberOfPreRegFeatures = mcSettings.numPreRegFeatures;
if (NULL == (m_TemplateArray = new
FT_BYTE*[m_NumberOfPreRegFeatures]))
MessageBox::Show( "Error en m_TemplateArray", "Error");
::ZeroMemory(m_TemplateArray,
sizeof(FT_BYTE**)*m_NumberOfPreRegFeatures);
// Pone el indice del arreglo en cero, donde sera guardada la primera
pre-plantilla.
m_nRegFingerprint = 0;
// Se usa prioridad Normal para que solo se lean huellas cuando la
// ventana se encuentra activa
DP_ACQUISITION_PRIORITY ePriority = DP_PRIORITY_NORMAL;
HWND pHandle = (HWND)this->Handle.ToPointer();
pin_ptr<HDPOPERATION> pm_hOperationEnroll = &m_hOperationEnroll;
if(S_OK == DPFPCreateAcquisition(ePriority,
GUID_NULL,DP_SAMPLE_TYPE_IMAGE,pHandle,FP_EVENT,pm_hOperationEnroll)){
if(S_OK == DPFPStartAcquisition(m_hOperationEnroll)){
this->label5->Text = L"Inicializacion concluida";
this->label1->Text = L"Coloque el dedo indice derecho para
ser escaneado";
}
}
}
System::Void enrrol::AddToEnroll(FT_IMAGE_PT pFingerprintImage, int
iFingerprintImageSize){
HRESULT hr = S_OK;
FT_BYTE* pPreRegTemplate = NULL;
FT_BYTE* pRegTemplate = NULL;
// No se generan mas pre-plantillas de las necesarias
if (m_nRegFingerprint < m_NumberOfPreRegFeatures) {
FT_RETCODE rc = FT_OK;
// Se obtiene la cantidad recomendada de las plantillas de
pre-registro
int iRecommendedPreRegFtrLen = 0;
rc = FX_getFeaturesLen(FT_PRE_REG_FTR,
&iRecommendedPreRegFtrLen,
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;
67
if (NULL == (pPreRegTemplate = new
FT_BYTE[iRecommendedPreRegFtrLen]))
MessageBox::Show( "Error en pPreRegTemplate", "Error");
rc = FX_extractFeatures(m_fxContext,
// Contexto
de extraccion
iFingerprintImageSize,
// tamaño de la imagen de huella digital
pFingerprintImage,
// Puntero al buffer de imagen
FT_PRE_REG_FTR,
// Solicitud de extraccion de características
iRecommendedPreRegFtrLen,
// tamaño de la plantilla de pre-registro
pPreRegTemplate,
// puntero al buffer que almacena la plantilla de pre-registro
&imgQuality,
// retorna la calidad de imagen
&ftrQuality,
// retorna la calidad de las características
&bEextractOK);
// retorna el resultado de la extraccion
// Si la extracción es exitosa se crea una plantilla de preregistro
if (FT_OK <= rc && bEextractOK == FT_TRUE) {
this->label1->Text = L"Pre-Enrollment feature set
generated successfully";
m_TemplateArray[m_nRegFingerprint++] = pPreRegTemplate;
pPreRegTemplate = NULL;
// Se verifica si existen suficientes plantillas de
pre-registro
if (m_nRegFingerprint == m_NumberOfPreRegFeatures) {
int iRecommendedRegFtrLen = 0;
rc = MC_getFeaturesLen(FT_REG_FTR,
0,
&iRecommendedRegFtrLen,
NULL);
if (FT_OK != rc)
MessageBox::Show( "Error en MC_getFeaturesLen",
"Error");
if (NULL == (pRegTemplate = new
FT_BYTE[iRecommendedRegFtrLen]))
MessageBox::Show( "pRegTemplate", "Error");
FT_BOOL bRegSucceeded = FT_FALSE;
rc = MC_generateRegFeatures(m_mcContext,
// Contexto de comparacion
0,
// debe ser 0
68
m_NumberOfPreRegFeatures, // numero de plantillas de pre-registro
iRecommendedPreRegFtrLen, // tamaño de una plantilla de preregistro
m_TemplateArray,
// arreglo de plantillas de pre-registro
iRecommendedRegFtrLen,
// tamaño de la plantilla
pRegTemplate,
// Pointer to the buffer where the
Enrollment template to be stored
NULL,
// Reservado, debe ser NULL.
&bRegSucceeded);
plantilla
// Resultado de la creacion de la
if (FT_OK <= rc && bRegSucceeded == FT_TRUE) {
// Plantilla generada exitosamente
m_RegTemplate.pbData = pRegTemplate;
m_RegTemplate.cbData =
iRecommendedRegFtrLen;
pRegTemplate = NULL;
this->label1->Text = L"Plantilla de
registro generada exitosamente";
this->label5->Text = L"Close this dialog
and run Verification to verify fingerprint";
}
else {
this->label1->Text = L"La creacion de la
plantilla de registro fallo";
// Existio un error en la creacion de la
plantilla
// entonces se borran las prematriculas realizadas
m_nRegFingerprint = 0;
for (int i=0; i<m_NumberOfPreRegFeatures;
++i)
if(m_TemplateArray[i]) delete []
m_TemplateArray[i], m_TemplateArray[i] = NULL;
}
}
else {
// Continua ejecutandose si no se han terminado
la cantidad de plantilla de
// pre-matricula requeridas
this->label1->Text = L"Coloque el indice derecho
nuevamente";
}
}
else {
69
MessageBox::Show( "Error en la creación de la plantilla
de pre-registro.", "Error");
}
}
else {
MessageBox::Show( "Una plantilla de registro ya ha sido
creada", "Error");
}
}
System::Void enrrol::GuardarArchivo(int iRecommendedRegFtrLen, FT_BYTE*
pRegTemplate){
if (m_RegTemplate.cbData == 0 || m_RegTemplate.pbData == NULL) {
MessageBox::Show( "Debe crearse una plantilla de huella digital
antes de registrar una persona", "Error");
}
else{
if(this->textBox1->Text != L"" && this->textBox2->Text != L"" &&
this->textBox3->Text != L"" && this->textBox4->Text != L""&& this>textBox5->Text != L""){
//Almacenamiento en el archivo temporal
char archivo[40];
strcpy_s(archivo, 40, "d:\\CRB\\CRB\\Templates\\");
char* cod_ced = new char[9];
cod_ced = (char*)(void*)Marshal::StringToHGlobalAnsi(this>textBox4->Text);
strcat_s(archivo,40,cod_ced);
strcat_s(archivo,40,".crbt");
ofstream out(archivo,ios::binary);
out.write((char*)pRegTemplate,iRecommendedRegFtrLen);
out.close();
//Almacenamiento de la informacio del nuevo empleado en la
base de datos
String^ solicitud =
String::Format(CultureInfo::CurrentCulture,\
"INSERT INTO `crb_db1`.`empleados` (`Nombre` ,`Apellido1`
,`Apellido2` ,`Cedula`,`Departamento` ,`DataTemplate`,`cbData`)VALUES
('{0}', '{1}', '{2}', '{3}' ,'{4}','','{5}');"\
,textBox1->Text,textBox2->Text,textBox3->Text,textBox4>Text,textBox5->Text,iRecommendedRegFtrLen);
sql = (char*)(void*)Marshal::StringToHGlobalAnsi(solicitud);
int len = 0;
len = strlen(sql);
if(!mysql_real_query(conn, sql ,len)){
this->label5->Text = L"Informacion guardada
exitosamente";
}
else{
this->label5->Text = L"Error en la consulta";
}
mysql_res = mysql_store_result(conn);
70
mysql_free_result(mysql_res);
//Creacion de una Tabla en la base de datos para el nuevo
empleado
char nueva_tabla[122];
strcpy_s(nueva_tabla, 122, "CREATE TABLE `crb_db1`.`");
strcat_s(nueva_tabla,122,cod_ced);
strcat_s(nueva_tabla,122,"` (`Fecha` DATE NOT NULL ,`Hora`
TIME NOT NULL ,`Tipo` BOOL NOT NULL) ENGINE = MYISAM ;");
len = strlen(nueva_tabla);
mysql_real_query(conn, nueva_tabla ,len);
mysql_res = mysql_store_result(conn);
mysql_free_result(mysql_res);
}
else{
MessageBox::Show( "Ninguno de los campos de informacion puede
estar vacio", "Error");
}
}
}
System::Void enrrol::button1_Click(System::Object^
System::EventArgs^ e) {
this->Close();
}
sender,
System::Void enrrol::enrrol_FormClosing(System::Object^ sender,
System::Windows::Forms::FormClosingEventArgs^ e) {
//Se detienen los procesos de acquisicion y se eliminan los contextos
//de comparacion y extraccion
if (m_hOperationEnroll) {
DPFPStopAcquisition(m_hOperationEnroll);
DPFPDestroyAcquisition(m_hOperationEnroll);
m_hOperationEnroll = 0;
}
if (m_fxContext) {
FX_closeContext(m_fxContext);
m_fxContext = 0;
}
if (m_mcContext) {
MC_closeContext(m_mcContext);
m_mcContext = 0;
}
if(m_TemplateArray){
//Se eliminan las plantillas de pre-registro
for (int i=0; i<m_NumberOfPreRegFeatures; ++i)
if(m_TemplateArray[i]) delete [] m_TemplateArray[i],
m_TemplateArray[i] = NULL;
delete [] m_TemplateArray;
71
}
}
System::Void enrrol::button2_Click(System::Object^ sender,
System::EventArgs^ e) {
this->GuardarArchivo(m_RegTemplate.cbData, m_RegTemplate.pbData);
}
72
APÉNDICE B: Código de la interfaz para administración de
bases de datos CRB
B.1. Archivo cliente.php
<!---------------------------------------------------------Universidad de Costa Rica
Escuela de Ingenieria Electrica
II Semestre 2009
IE-0529
Proyecto Electrico
Elaborado por: Luis Castro Leiva A61368
Resumen: cliente.php
Este archivo contiene el codigo HTML de la interfaz de
administracion de Bases de Datos CRB.
----------------------------------------------------------->
<html>
<head>
<script language="JavaScript" type="text/javascript" src="ajax.js"></script>
<title>CRB Data Base Administrator</title>
<style type="text/css">
body {
font-family: Arial, "Times New Roman",
Times, serif;
color: #0174DF;
background-color: #FFFFFF }
h1 {
font-family: Helvetica, Geneva, Arial,
SunSans-Regular, sans-serif }
</style>
</head>
<body>
<h1>Interfaz para administracion de Bases de Datos CRB</h1>
<table align = "center" Border = 0 Cellpadding=4>
<td>
<p>Por medio de esta interfaz se pueden realizar busquedas
de sobre la informacion al almacenada en la base de datos
de CRB</p>
</td>
<td>
<object
type="application/x-shockwave-flash"
data="reloj1.swf"
height="100">
<param name="movie" value="reloj1.swf"></param>
<param name="quality" value="High"></param>
<param name="scale" value="ExactFit"></param>
<param name="wmode" value="transparent"></param>
<param name="loop" value="false"></param>
<param name="menu" value="false"></param>
</object>
73
width="100"
</td>
</table>
<Table align = "center" Border = 1 Cellpadding=4>
<tr>
<td>
<p>Busqueda de personal por Nombre, Primer y Segundo Apellido y Numero de
Cedula</p>
<Form Name="crb_form_busqueda" Action="" Methot="GET">
<Table align = "center" Border Cellpadding=4>
<tr>
<td>Nombre: <INPUT Type="text" Name="nombre" VALUE="" Size=25></td>
<td><Input
Type=button
OnClick="Consultar('query_name.php',this.form);
return
false" Value="Buscar"></td>
</tr>
<tr>
<td>Primer Apellido: <Input Name="apellido1" Value="" Size=16></td>
<td><Input
Type=button
OnClick="Consultar('query_apellido1.php',this.form);
return false" Value="Buscar"></td>
</tr>
<tr>
<td>Segundo Apellido: <Input Name="apellido2" Size=15></td>
<td><Input
Type=button
OnClick="Consultar('query_apellido2.php',this.form);
return false" Value="Buscar"></td>
</tr>
<tr>
<td>Cedula: <Input Name="cedula" Size=27></td>
<td><Input Type=button OnClick="Consultar('query_cedula.php',this.form); return
false" Value="Buscar"></td>
</tr>
</Table>
<p
Align
=
"center"><Input
OnClick="document.getElementById('resultado').innerHTML
=
resultados" Size=27></p>
<div id="resultado"></div>
''"
Type=button
Value="Limpiar
</Form>
</td>
<td rowspan="2">
<p Align = "center">Registro de Marcas de personal por Numero de Cedula</p>
<Form Name="crb_form_marcas" Action="" Methot="GET">
<Table align = "center" Border Cellpadding=4>
<tr>
<td>Cedula: <INPUT Type="text" Name="cedula" VALUE="" Size=25></td>
<td><Input
Type=button
OnClick="ConsultarMarcas('query_marcas.php',this.form);
return false" Value="Buscar"></td>
</tr>
</Table>
</Form>
<p
Align
=
"center"><Input
Type=button
OnClick="document.getElementById('marcas').innerHTML
=
''"
Value="Limpiar
resultados" Size=27></p>
<div id="marcas"></div>
</td>
</tr>
74
<tr>
<td>
<Form>
<p align = "center">Eliminacion de Usuarios por numero de Cedula</p>
<Table align = "center" Border Cellpadding=4>
<tr>
<td>Cedula: <Input Name="cedula_eliminar" Size=27></td>
<td><Input Type=button OnClick="Eliminar('query_eliminar.php',this.form); return
false" Value="Eliminar"></td>
</tr>
</Table>
<p
Align
=
"center"><Input
Type=button
OnClick="document.getElementById('resultado_eliminar').innerHTML
=
''"
Value="Limpiar resultados" Size=27></p>
<div id="resultado_eliminar"></div>
</Form>
</td>
</tr>
</table>
<p Align = "center">2009, Sistema CRB</p>
</body>
</html>
B.2. Archivo ajax.js
/***********************************************************************
Universidad de Costa Rica
Escuela de Ingenieria Electrica
II Semestre 2009
IE-0529
Proyecto Electrico
Elaborado por: Luis Castro Leiva A61368
Resumen: ajax.js
Este archivo contiene el codigo JAVASCRIPT necesario por la de la
interfaz de administracion de Bases de Datos CRB. En el se crea un objeto
Ajax para establecer comunicacion asincronica con PHP y este en ultimo
enlaza con MySQL
***********************************************************************/
//La funcion objetoAjax hace que la aplicación sea transparente al
navegador
//utilizado debido a que independientemente de cual sea, se crea un
objeto ajax
function objetoAjax(){
var xmlhttp=false;
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
75
} catch (e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (E) {
xmlhttp = false;
}
}
if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
xmlhttp = new XMLHttpRequest();
}
return xmlhttp;
}
//La función Consultar se encarga de llamar el script de PHP por medio
//del objeto ajax creado al llamar la funcion objetoAjax
function Consultar(datos,form){
var nombre = form.nombre.value;
var apellido1 = form.apellido1.value;
var apellido2 = form.apellido2.value;
var cedula = form.cedula.value;
divResultado = document.getElementById('resultado');
ajax=objetoAjax();
ajax.open("GET",
datos+"?nombre="+nombre+"&apellido1="+apellido1+"&apellido2="+apellido2+"
&cedula="+cedula);
ajax.onreadystatechange=function() {
if (ajax.readyState==4) {
divResultado.innerHTML = ajax.responseText
}
}
ajax.send(null)
}
function Eliminar(datos,form){
var cedula_eliminar = form.cedula_eliminar.value;
divResultado = document.getElementById('resultado_eliminar');
ajax=objetoAjax();
ajax.open("GET", datos+"?cedula="+cedula_eliminar);
ajax.onreadystatechange=function() {
if (ajax.readyState==4) {
divResultado.innerHTML = ajax.responseText
}
}
ajax.send(null)
}
function ConsultarMarcas(datos,form){
var cedula = form.cedula.value;
76
divResultado = document.getElementById('marcas');
ajax=objetoAjax();
ajax.open("GET", datos+"?cedula="+cedula);
ajax.onreadystatechange=function() {
if (ajax.readyState==4) {
divResultado.innerHTML = ajax.responseText
}
}
ajax.send(null)
}
B.3. Archivo query_name.php
<!--------------------------------------------------------Universidad de Costa Rica
Escuela de Ingenieria Electrica
II Semestre 2009
IE-0529
Proyecto Electrico
Elaborado por: Luis Castro Leiva A61368
Resumen: query_name.php
Este archivo contine el codigo en PHP que realiza busquedas
en la base de datos de CRB por el campo nombre y retorna los
resultados de la busqueda.
----------------------------------------------------------->
<?php
//Configuracion de la conexion a base de datos
$host = "localhost";
$usuario = "admin";
$password = "crb";
$base = "crb_db1";
$link = mysql_connect($host, $usuario, $password);
//Selección de la base de datos a usar
mysql_select_db($base, $link);
//consulta todos los empleados
if($_GET["nombre"]){
$sql=mysql_query("SELECT * FROM `empleados` WHERE Nombre =
'".$_GET['nombre']."'",$link);
$num_rows = mysql_num_rows($sql);
if($num_rows == NULL)
echo "<p align =\"center\">No hay resultados de la busqueda por
nombre</p>\n";
else
echo "<p align =\"center\">Nombre | Primer Apellido | Cedula </p>
\n";
while($row = mysql_fetch_array($sql)){
77
echo "<p align =\"center\">".$row['Nombre']." |
".$row['Apellido1']." | ".$row['Cedula']."</p> \n";
}
mysql_free_result($sql);
}
else{
echo "<p align =\"center\">No hay nombre elegido para realizar la
busqueda</p>";
}
?>
B.4. Archivo query_apellido1.php
<!--------------------------------------------------------Universidad de Costa Rica
Escuela de Ingenieria Electrica
II Semestre 2009
IE-0529
Proyecto Electrico
Elaborado por: Luis Castro Leiva A61368
Resumen: query_apellido1.php
Este archivo contine el codigo en PHP que realiza busquedas
en la base de datos de CRB por el campo apellido1 y retorna
los resultados de la busqueda.
----------------------------------------------------------->
<?php
//Configuracion de la conexion a base de datos
$host = "localhost";
$usuario = "admin";
$password = "crb";
$base = "crb_db1";
$link = mysql_connect($host, $usuario, $password);
//Selección de la base de datos a usar
mysql_select_db($base, $link);
//consulta todos los empleados
if($_GET["apellido1"]){
$sql=mysql_query("SELECT * FROM `empleados` WHERE Apellido1 =
'".$_GET['apellido1']."'",$link);
$num_rows = mysql_num_rows($sql);
if($num_rows == NULL)
echo "<p align =\"center\">No hay resultados de la busqueda por
primer apellido</p>\n";
else
echo "<p align =\"center\">Nombre | Primer Apellido | Segundo
Apellido | Cedula </p> \n";
while($row = mysql_fetch_array($sql)){
78
echo "<p align =\"center\">".$row['Nombre']." |
".$row['Apellido1']." | ".$row['Apellido2']." | ".$row['Cedula']."</p> \n";
}
mysql_free_result($sql);
}
else{
echo "<p align =\"center\">No hay un apellido elegido para realizar la
busqueda</p>";
}
?>
B.5. Archivo query_apellido2.php
<!--------------------------------------------------------Universidad de Costa Rica
Escuela de Ingenieria Electrica
II Semestre 2009
IE-0529
Proyecto Electrico
Elaborado por: Luis Castro Leiva A61368
Resumen: query_apellido2.php
Este archivo contine el codigo en PHP que realiza busquedas
en la base de datos de CRB por el campo Apellido2 y retorna
los resultados de la busqueda.
----------------------------------------------------------->
<?php
//Configuracion de la conexion a base de datos
$host = "localhost";
$usuario = "admin";
$password = "crb";
$base = "crb_db1";
//Establece la conexion con MySQL
$link = mysql_connect($host, $usuario, $password);
//Selección de la base de datos a usar
mysql_select_db($base, $link);
//consulta en la tabla empleados el campo Apellido2
if($_GET["apellido2"]){
$sql=mysql_query("SELECT * FROM `empleados` WHERE Apellido2 =
'".$_GET['apellido2']."'",$link);
$num_rows = mysql_num_rows($sql);
if($num_rows == NULL)
echo "<p align =\"center\">No hay resultados de la busqueda por
segundo apellido</p>\n";
else
79
echo "<p align =\"center\">Nombre | Primer Apellido | Segundo
Apellido | Cedula </p> \n";
while($row = mysql_fetch_array($sql)){
echo "<p align =\"center\">".$row['Nombre']." |
".$row['Apellido1']." | ".$row['Apellido2']." | ".$row['Cedula']."</p> \n";
}
mysql_free_result($sql);
}
else{
echo "<p align =\"center\">No hay un apellido elegido para realizar la
busqueda</p>";
}
?>
B.6. Archivo query_cedula.php
<!--------------------------------------------------------Universidad de Costa Rica
Escuela de Ingenieria Electrica
II Semestre 2009
IE-0529
Proyecto Electrico
Elaborado por: Luis Castro Leiva A61368
Resumen: query_cedula.php
Este archivo contine el codigo en PHP que realiza busquedas
en la base de datos de CRB por el campo Cedula y retorna
los resultados de la busqueda.
----------------------------------------------------------->
<?php
//Configuracion de la conexion a base de datos
$host = "localhost";
$usuario = "admin";
$password = "crb";
$base = "crb_db1";
$link = mysql_connect($host, $usuario, $password);
//Selección de la base de datos a usar
mysql_select_db($base, $link);
//consulta todos los empleados
if($_GET["cedula"]){
$sql=mysql_query("SELECT * FROM `empleados` WHERE Cedula =
'".$_GET['cedula']."'",$link);
$num_rows = mysql_num_rows($sql);
if($num_rows == NULL)
echo "<p align =\"center\">No hay resultados de la busqueda por
cedula</p>\n";
else
80
echo "<p align =\"center\">Nombre | Primer Apellido | Segundo
Apellido | Cedula </p> \n";
while($row = mysql_fetch_array($sql)){
echo "<p align =\"center\">".$row['Nombre']." |
".$row['Apellido1']." | ".$row['Apellido2']." | ".$row['Cedula']."</p> \n";
}
mysql_free_result($sql);
}
else{
echo "<p align =\"center\">No hay un numero de cedula elegido para realizar
la busqueda</p>";
}
?>
B.7. Archivo query_marcas.php
<!--------------------------------------------------------Universidad de Costa Rica
Escuela de Ingenieria Electrica
II Semestre 2009
IE-0529
Proyecto Electrico
Elaborado por: Luis Castro Leiva A61368
Resumen: query_marcas.php
Este archivo contine el codigo en PHP que realiza busquedas
en la base de datos de CRB de las marcas de acceso de personal
y retorna los resultados de la busqueda.
----------------------------------------------------------->
<?php
//Configuracion de la conexion a base de datos
$host = "localhost";
$usuario = "admin";
$password = "crb";
$base = "crb_db1";
$link = mysql_connect($host, $usuario, $password);
//Selección de la base de datos a usar
mysql_select_db($base, $link);
//consulta todos los empleados
if($_GET["cedula"]){
$sql=mysql_query("SELECT * FROM `".$_GET['cedula']."`",$link);
if($sql != 0){
$num_rows = mysql_num_rows($sql);
if($num_rows == NULL)
echo "<p align =\"center\">No hay marcas para esta
persona</p>\n";
81
else
echo "<p align =\"center\">Fecha | Hora </p> \n";
while($row = mysql_fetch_array($sql)){
echo "<p align =\"center\">".$row['Fecha']." |
".$row['Hora']."</p> \n";
}
mysql_free_result($sql);
}
else{
echo "<p align =\"center\">No se encuentra registrada una persona
con esta cedula</p>";
}
}
else{
echo "<p align =\"center\">Debe llenar el espacio dado para realizar la
busqueda</p>";
}
?>
B.8. Archivo query_eliminar.php
<!--------------------------------------------------------Universidad de Costa Rica
Escuela de Ingenieria Electrica
II Semestre 2009
IE-0529
Proyecto Electrico
Elaborado por: Luis Castro Leiva A61368
Resumen: query_eliminar.php
Este archivo contine el codigo en PHP que elimina una fila
correspondiente a un numero de cedula suministrado via GET
en la base de datos crb_db1 y la tabla de registro de accesos
correspondiente a ese numero de cedula
----------------------------------------------------------->
<?php
//Configuracion de la conexion a base de datos
$host = "localhost";
$usuario = "admin";
$password = "crb";
$base = "crb_db1";
//establece conexion con la base de datos MySQL
$link = mysql_connect($host, $usuario, $password);
//Selección de la base de datos a usar
mysql_select_db($base, $link);
82
if($_GET["cedula"]){
$sql1=mysql_query("DELETE FROM `crb_db1`.`empleados` WHERE
Cedula=".$_GET['cedula'],$link);
$sql2=mysql_query("DROP TABLE `".$_GET['cedula']."`",$link);
if (($sql1 == 1) && ($sql2 == 1)){
echo "<p align =\"center\">Se ha eliminado la persona
adecuadamente</p";
}
}
else{
echo "<p align =\"center\">No se encuentra registrada una persona con esta
cedula</p>";
}
?>
83
Apéndice C: Sentencia de SQL para la creación de la base de
datos crb_db1.
CREATE TABLE `crb_db1`.`empleados` (
`Nombre` CHAR( 20 ) NOT NULL ,
`Apellido1` CHAR( 20 ) NOT NULL ,
`Apellido2` CHAR( 20 ) NOT NULL ,
`Cedula` INT NOT NULL ,
`Departamento` CHAR( 20 ) NOT NULL ,
`DataTemplate` BLOB NOT NULL ,
`cbData` INT NOT NULL
) ENGINE = MYISAM ;
84
Apéndice D: Funciones del Dispositivo utilizas.
o HRESULT DPFPInit();
Valores de Retorno

S_OK
operación exitosa

S_FALSE
librería ya inicializada.

0x800706B3
el servidor RPC no está escuchando, lo que significa que el
Servicio Biométrico de Inicialización no ha sido iniciado.
Descripción: Inicializa los recursos necesarios y hace las asignaciones de memoria
necesarias para empezar la comunicación con el lector de huellas digitales. Debe ser
llamado antes de cualquier función del API, con excepción de DPFPBufferFree.
o HRESULT DPFPTerm();
Valores de Retorno

S_OK
operación exitosa
Descripción: Libera recursos asignados por DPFPInit().
o HRESULT DPFPCreateAcquisition(
DP_ACQUISITION_PRIORITY eAcquisitionPriority,
REFGUID DevUID,
ULONG uSampleType,
85
HWND hWnd,
ULONG uMsg,
HDPOPERATION * phOperation);
Parametros

eAcquisitionPriority: las aplicaciones que se conectan con el lector de huellas digitales
pueden elegir entre tres niveles de prioridad: alto, normal y bajo. En el nivel alto de
prioridad todos los eventos generados por el U.are.U 4500 serán enviados al cliente
suscrito y solo puede existir uno de este tipo. En nivel normal pueden haber varios
clientes suscritos pero la información será enviado a que esté como ventana activa. En
el nivel más bajo toda la información será enviada a él aunque no se encuentre activo.

DevUID: numero de serie del lector a utilizar, GUID_NULL si cualquier lector puede
ser utilizado.

uSampleType: Este parámetro debe ser DP_SAMPLE_TYPE_IMAGE.

hWnd: Handle de la ventana a ser notificada de los eventos.

uMsg: Mensaje a ser enviado como la notificación del evento

phOperation: puntero al handle de la operación a ser llenado si la operación es creada
exitosamente.
Valores de Retorno

S_OK
operación exitosa

E_ACCESSDENIED
se intenta suscribir una aplicación como cliente pero
no se tiene permisos para esto
86

E_INVALIDARG
ya existe una aplicación cliente suscrita con prioridad
alta.
Descripción: Crea una operación de adquisición.
o HRESULT DPFPStartAcquisition(HDPOPERATION hOperation);
Parametros
hOperation: Handle de la operación.
Valores de Retorno

S_OK
operación exitosa
Descripción: Suscribe una aplicación cliente para recibir notificación de eventos del
hardware.
o HRESULT DPFPStopAcquisition(HDPOPERATION hOperation);
Parametros
hOperation: Handle de la operación.
Valores de Retorno

S_OK
operación exitosa
Descripción: Se elimina la suscripción de alguna aplicación cliente para y se liberan
recursos asignados para esto.
o HRESULT DPFPDestroyAcquisition(HDPOPERATION hOperation);
87
Parametros
hOperation: Handle de la operación.
Valores de Retorno

S_OK
operación exitosa
Descripción: Elimina la operación creada por DPFPCreateAcquisition y libera los
recursos asociados.
88
2.7.1
Funciones de extracción
o FX_DLL_INTERFACE FT_RETCODE FX_init(void);
Valores de Retorno

S_OK
operación exitosa

FT_ERR_NO_MEMORY
no se encontró suficiente memoria para iniciar
el módulo de extracción

FT_ERR_BAD_INI_SETTING
la configuración de inicialización ha sido
corrompida.
Descripción: Inicializa el módulo de extracción de huellas digitales, inicializa la estructura
MC_SETTINGS y las tablas de búsqueda para comparación. Debe ser ejecutada antes que
cualquier función del módulo de extracción.
o FX_DLL_INTERFACE FT_RETCODE FX_Terminate(void);
Valores de Retorno

FT_OK

FT_WRN_NO_INIT
operación exitosa
el modulo de extracción no ha sido inicializado.
Descripción: Cierra el módulo de extracción y libera los recursos asociados
89
o FX_DLL_INTERFACE FT_RETCODE FX_createContext(
OUT FT_HANDLE *fxContext);
Parametros
fxContext: Puntero a la dirección de memoria donde se localiza el handle del contexto.
Valores de Retorno

FT_OK
operación exitosa

FT_ERR_NO_INIT
FX_INIT no ha sido llamada

FT_ERR_INVALID_CONTEXT
no hay suficiente memoria para crear el
contexto.
Descripción: Crea un contexto de extracción, si la operación es exitosa retorna un
HANDLE que apunta al contexto creado.
o FX_DLL_INTERFACE FT_RETCODE FX_closeContext(
OUT FT_HANDLE* fxContext);
Parametros
fxContext: handle del contexto a cerrar.
Valores de Retorno

operación exitosa
FT_OK
Descripción: Cierra un contexto de extracción.
90
2.7.2
Funciones de comparación
o FX_DLL_INTERFACE FT_RETCODE MC_init(void);
Valores de Retorno

S_OK
operación exitosa

FT_ERR_NO_MEMORY
no se encontró suficiente memoria para iniciar
el módulo de comparación

FT_ERR_BAD_INI_SETTING
la configuración de inicialización ha sido
corrompida.
Descripción: Inicializa el módulo de comparación extracción de huellas digitales,
inicializa. Debe ser ejecutada antes que cualquier función del módulo de extracción.
o FX_DLL_INTERFACE FT_RETCODE MC_Terminate(void);
Valores de Retorno

FT_OK

FT_WRN_NO_INIT
operación exitosa
el modulo de comparación no ha sido inicializado.
Descripción: Cierra el módulo de comparación y libera los recursos asociados.
91
o FX_DLL_INTERFACE FT_RETCODE MC_createContext(
OUT FT_HANDLE* mcContext);
Parametros
mcContext: Puntero a la dirección de memoria donde se localiza el handle del contexto.
Valores de Retorno

FT_OK
operación exitosa
Descripción: Crea un contexto de comparación, si la operación es exitosa retorna un
HANDLE que apunta al contexto creado.
o FX_DLL_INTERFACE FT_RETCODE MC_closeContext(
OUT FT_HANDLE* mcContext);
Parametros
mcContext: handle del contexto a cerrar.
Valores de Retorno

FT_OK
operación exitosa
Descripción: Cierra un contexto de comparación.
92
ANEXOS
Sistema CRB
Versión Alfa
MANUAL DEL USUARIO
93
Bienvenido a CRB
Bienvenido. Este documento pretende ser una guía para el manejo de la versión
Alfa del sistema CRB. Aquí encontrará toda la información sobre las capacidades del
programa y podrá adquirir los elementos necesarios para hacer uso del mismo.
CRB es una aplicación que le permitirá estar al tanto de las horas de entrada y salida
del personal a su empresa. Este software cuenta con dos partes fundamentales: una interfaz
Web y el programa CRB que registra las marcas del personal y le permite registrar nuevos
usuarios.
Proceso de Instalación
Por el momento, por ser esta una versión alfa, el proceso de instalación no está
automatizado por lo cual se requiere la instalación de personal capacitado en el tema.
Manejo del Sistema.
El programa CRB.
Para iniciar con el registro de entradas y salidas abra la aplicación CRB. Una vez
abierta podrá ver la ventana principal del programa como se muestra a continuación. En
esta ventana puede elegir uno de los dos modos de operación de la aplicación CRB según lo
que desee hacer.
94
Figura 1. Ventana principal
Si desea registrar un nuevo empleado en la base de datos del programa haga click en
“Registrar nuevo personal”, si desea registrar las salidas y entradas de personal a la
empresa haga click en “Registrar marcas de personal”.
Cómo agregar un nuevo usuario
Una vez que dio click en “Registrar nuevo personal” verá la siguiente ventana.
95
Figura 2. Ventana de Registro de nuevo personal.
Siga lo siguientes pasos:

Introduzca todos los datos solicitados de la persona

Solicite a la persona a registrar que coloque el dedo sobre el lector y luego lo retire.

Repita el procedimiento anterior tres veces más o hasta que aparezca en la línea
superior del área de estado la sentencia: “La plantilla de registro ha sido generada
exitosamente”

Haga click en el botón Guardar.
96

Revise que en la segunda línea del área de estado se encuentre la sentencia “La
información ha sido guardada exitosamente”, en caso de no ser así salga y vuelva a
intentar todo el procedimiento.

Haga click en el botón salir y vuelva a entrar si se desea registrar un nuevo usuario.
Cómo registrar marcas de personal
Desde la ventana principal, entre al modo de control de acceso haciendo click sobre
el botón “Registrar marcas de personal”. Podrá observar entonces la ventana que se muestra
en la siguiente figura:
Figura 3. Ventana de control de acceso.
Aquí los empleados nada más deben colocar el dedo que fue registrado y asegurarse
de que en el área de estado se informe del resultado de la marca. En caso de que se
97
informara de algún error, se debe volver a colocar el dedo hasta que el área de estado
notifique lo contrario
Interfaz para la administración de bases de datos CRB
Aquí el encargado de recursos humanos puede realizar las siguientes tres
operaciones:

Realizar búsqueda de la información del personal por nombre, apellidos o cédula.

Revisar las marcas de alguna persona.

Eliminar usuario registrado.
Figura 4. Interfaz Web.
98
Solamente se debe acceder al sitio Web habilitado por la empresa para tal fin y llenar
los espacios requeridos para realizar las búsquedas, las consultas o la eliminación.
Para realizar consultas de las marcas o eliminar usuarios debe conocerse el número de
cédula de la persona que se desea sacar del registro principal, y este es el dato que se debe
introducir en los espacios asignados para este fin.
99
100
Descargar