{"id":5018,"date":"2022-05-06T18:39:45","date_gmt":"2022-05-06T16:39:45","guid":{"rendered":"https:\/\/blogs.etsii.urjc.es\/dseytr\/?p=5018"},"modified":"2022-06-03T09:56:56","modified_gmt":"2022-06-03T07:56:56","slug":"fichador-de-trabajo","status":"publish","type":"post","link":"https:\/\/blogs.etsii.urjc.es\/dseytr\/fichador-de-trabajo\/","title":{"rendered":"Fichador de trabajo"},"content":{"rendered":"\n<p>Trabajo realizado por el Grupo 1 del campus de M\u00f3stoles, formado por Sergio Carrascosa S\u00e1nchez, Francisco Daniel Fr\u00edas Quero, Jorge Garc\u00eda-Mauri\u00f1o Moll\u00e1 y Jose Manuel Soler Siles.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/kUcxMBYi9W951yU2I_pgI6UrBjVOV9Ps4BkfQQXCf4zIwFfOKlqXMS1_CdgEPq-e4AlKT-osnzD6vTKbZiWc5Z4DDng2vBDP217luclZnr2UO2R9oSFEBXz_PawVCtK1p-GIcCg6fzETuHHVkA\" alt=\"\" width=\"446\" height=\"281\"\/><\/figure>\n<\/div>\n\n\n<h1 class=\"wp-block-heading\"><strong>1.- INTRODUCCI\u00d3N AL PROYECTO Y OBJETIVOS PERSEGUIDOS<\/strong><\/h1>\n\n\n\n<p>En este proyecto se nos plante\u00f3 la posibilidad de desarrollar un proyecto en Arduino de forma totalmente libre, sin pautas ni gui\u00f3n alguno. Nuestra preferencia fue siempre desarrollar algo funcional, que tuviese utilidad en el mundo real y por lo tanto algo que los consumidores y otras empresas usar\u00edan.&nbsp;<\/p>\n\n\n\n<p>Dada la experiencia laboral de algunos de los miembros de nuestro grupo, se plante\u00f3 la idea desde el inicio de realizar un fichador. Un fichador es un dispositivo colocado en la entrada del puesto de trabajo que registra la jornada laboral de los trabajadores de la empresa. Al ver que era algo nuevo, que ning\u00fan grupo de a\u00f1os anteriores hab\u00eda hecho y su gran utilidad en el mundo real, que era lo que busc\u00e1bamos, nos decantamos por el mismo. Ten\u00eda la innovaci\u00f3n y la utilidad que quer\u00edamos.<\/p>\n\n\n\n<p>El objetivo principal de este proyecto era por tanto el desarrollo de un fichador funcional que registrase la entrada y salida de empleados en Arduino. Otro objetivos fueron la familiarizaci\u00f3n con el IDE de Arduino, aprendizaje m\u00e1s avanzado sobre el equipo hardware de Arduino (circuiter\u00eda, componentes electr\u00f3nicos &#8230; etc).<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<div class=\"video-container\"><iframe loading=\"lazy\" title=\"videoFichador\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/WJ1crARMoos?feature=oembed&#038;wmode=opaque\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe><\/div>\n<\/div><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>1.1.- REQUISITOS INICIALES<\/strong><\/h2>\n\n\n\n<p>Los requisitos iniciales del proyecto fueron:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Pantalla t\u00e1ctil con una interfaz simple y entendible para cualquier trabajador de la empresa.<\/li><li>Funcionalidad de fichar para entrar y salir de la empresa<\/li><li>Funcionalidad de registrar a un nuevo empleado (s\u00f3lo realizable por el administrador).<\/li><li>En caso de \u00e9xito o error en las funcionalidades previamente mencionadas, presencia de efecto sonoro y lum\u00ednico para acompa\u00f1ar al mensaje impreso por pantalla.<\/li><li>Implementaci\u00f3n de un sensor de huellas en el fichador de arduino.<\/li><li>Carcasa y aspecto f\u00edsico de fichador.<\/li><\/ul>\n\n\n\n<h1 class=\"wp-block-heading\"><strong>2.- CASOS DE USO<\/strong><\/h1>\n\n\n\n<p>El fichador arduino tiene 3 funcionalidades principalmente, llevadas a cabo por distintos actores:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Acciones realizadas por los trabajadores<ul><li>Fichar: acci\u00f3n que registra la entrada de un trabajador al puesto de trabajo.<\/li><li>Desfichar: acci\u00f3n que registra la salida de un trabajador del puesto de trabajo.<\/li><\/ul><\/li><\/ul>\n\n\n\n<ul class=\"wp-block-list\"><li>Acci\u00f3n realizada por el administrador:<ul><li>Alta empleado: acci\u00f3n que guarda un nuevo empleado en el fichero y le asigna una nueva clave \u00fanica.<\/li><\/ul><\/li><\/ul>\n\n\n\n<h1 class=\"wp-block-heading\"><strong>3.- ESTRUCTURA, CONSTRUCCI\u00d3N E IMPLEMENTACI\u00d3N<\/strong><\/h1>\n\n\n\n<p>Dada la naturaleza de nuestro proyecto, el pivote fundamental del mismo ser\u00eda el c\u00f3digo que nos permitiese realizar&nbsp; las distintas funciones requeridas del fichador. Debido a esto, el \u00e9nfasis inicial del proyecto se enfoc\u00f3 en el desarrollo del c\u00f3digo del fichador. El proceso de desarrollo del proyecto fue: c\u00f3digo, circuito y montaje f\u00edsico (apariencia).<\/p>\n\n\n\n<p>No fue necesario el montaje del circuito en un primer momento ya que la pantalla t\u00e1ctil nos permit\u00eda conectarla directamente a la placa Arduino Uno R3 y probar as\u00ed el c\u00f3digo que \u00edbamos desarrollando. Las funcionalidades de los LEDs y el buzzer se implementar\u00edan una vez terminada toda la parte software del proyecto.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>3.1.- C\u00d3DIGO ARDUINO<\/strong><\/h2>\n\n\n\n<p>En primer lugar, el c\u00f3digo comienza con la definici\u00f3n de todas las librer\u00edas necesarias para su ejecuci\u00f3n mediante las directivas <em>#include <\/em>y la declaraci\u00f3n de diversas macros a trav\u00e9s de <em>#define<\/em>.<\/p>\n\n\n\n<p>Posteriormente, se definen tambi\u00e9n todas las variables que necesitar\u00e1n ser de car\u00e1cter global, como son:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Relacionadas con la pantalla t\u00e1ctil:<ul><li><em>Adafruit_TFTLCD tft<\/em>: La variable de la propia pantalla<\/li><li><em>TouchScreen ts<\/em>: La variable para gestionar el aspecto t\u00e1ctil de la pantalla<\/li><li>Una serie de botones que se imprimir\u00e1n posteriormente en la pantalla<\/li><\/ul><\/li><li>Relacionadas con el c\u00f3digo:<ul><li><em>int touchXY[2]<\/em>: Array de dos posiciones en donde se guardan las coordenadas de la \u00faltima pulsaci\u00f3n realizada por el usuario en la pantalla t\u00e1ctil<\/li><li><em>int vista<\/em>: Almacena un n\u00famero con la vista que queremos mostrar<\/li><li><em>String clave<\/em>: Clave del usuario actual que est\u00e9 utilizando el fichador<\/li><li><em>int longString<\/em>: Longitud del <em>String clave<\/em><\/li><\/ul><\/li><\/ul>\n\n\n\n<p>Una vez dentro ya del setup(), se llama a la funci\u00f3n resetTouch() (cuyo funcionamiento es detallado con posterioridad), inicializamos el monitor serie y establecemos los pines de los LEDs y el buzzer como de salida. Tambi\u00e9n se llevan a cabo otras configuraciones b\u00e1sicas de la pantalla como un reseteo, inicializaci\u00f3n mediante su identificador el cu\u00e1l es proporcionado por el fabricante, se establece la rotaci\u00f3n de la misma y coloreamos de negro el fondo. Asimismo, a la variable vista se le otorga el valor 0, la pantalla inicial del fichador.<\/p>\n\n\n\n<p>Con respecto al loop(), aqu\u00ed nos encontramos con un c\u00f3digo que simplemente se encarga de, a trav\u00e9s de una gran estructura if-else, comprobar qu\u00e9 n\u00famero est\u00e1 almacenado en la variable vista para as\u00ed llamar a su m\u00e9todo correspondiente.<\/p>\n\n\n\n<p>A continuaci\u00f3n viene la implementaci\u00f3n de cada una de las 11 vistas que tenemos en el c\u00f3digo. Cada m\u00e9todo es bastante similar entre s\u00ed, empezando siempre con un resetTouch() en el caso de que en la vista se espere alguna pulsaci\u00f3n en la pantalla por parte del usuario. Luego se pasa a la impresi\u00f3n de todos los elementos de la vista (color de fondo, colocaci\u00f3n y tama\u00f1o del texto\u2026) para acabar finalmente con la funcionalidad que se espera que se realice en la propia vista: algunas esperan una pulsaci\u00f3n en la pantalla, otras simplemente realizan un delay() con el objetivo de que el usuario lea lo que hay en pantalla\u2026<\/p>\n\n\n\n<p>Algunos aspectos rese\u00f1ables de los m\u00e9todos de las vistas son:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><em>vista0():<\/em> El objetivo inicial era que esta vista mostrara en directo tanto la hora como el d\u00eda. No obstante, al no haber podido cumplir con este objetivo, simplemente las imprimimos a trav\u00e9s de las macros <em>__DATE__ <\/em>y <em>__TIME__, <\/em>almacenando ambas los datos correspondientes en el momento de la compilaci\u00f3n.<\/li><li><em>vista3()<\/em>: Esta es una de las vistas que requiere de la interacci\u00f3n con el script de Python que controla los ficheros. M\u00e1s concretamente, una vez que el usuario ha introducido su clave mediante el teclado, el c\u00f3digo escribe a trav\u00e9s del monitor serie al script el <em>String (\u201cpyc \u201c + clave)<\/em>, indicando con las tres primeras letras que es algo que debe ser le\u00eddo por el script Python (de ah\u00ed el \u201c<em>py\u201d<\/em>) y que es una clave (por eso la letra \u201c<em>c\u201d<\/em>), seguido todo ello por la propia clave. Posteriormente, en funci\u00f3n de la respuesta proporcionada por el script de Python, transitaremos a una vista u otra.<\/li><li><em>vista4(): <\/em>Al llegar a esta vista, la autentificaci\u00f3n con la clave ha sido exitosa, por lo que a parte de imprimir texto por pantalla, tambi\u00e9n se encarga de hacer sonar el buzzer y de encender el LED azul.<\/li><li><em>vista5()<\/em>: A esta vista se llega cuando la autentificaci\u00f3n con la clave ha sido exitosa, pero dicha clave ya se encontraba en el fichero de entradas, por lo que supone una salida de la empresa. Es por ello que, antes de todo, la vista tiene un bucle en el que espera a que el script Python le env\u00ede a trav\u00e9s del monitor serie los datos con el tiempo que ha pasado el trabajador dentro de la empresa en el d\u00eda. Tambi\u00e9n har\u00e1 sonar al buzzer y encender\u00e1 el LED azul<\/li><li><em>vista6()<\/em>: La vista 6 tiene un funcionamiento exactamente igual al de la vista 3, pero el <em>String<\/em> escrito <em>(\u201cpya \u201c + clave)<\/em>, difiere puesto que la clave enviada al script Python es una clave de administrador (de ah\u00ed la <em>\u201ca\u201d<\/em>)<\/li><li><em>vista8():<\/em> Si se llega a esta vista es porque el administrador est\u00e1 tratando de crear un nuevo usuario para que pueda acceder al sistema con su propia clave. El c\u00f3digo enviar\u00e1 ahora al script Python el <em>String (\u201cpyi \u201c + clave)<\/em>, siendo <em>clave<\/em> el identificador (de ah\u00ed la <em>\u201ci\u201d<\/em>) de 8 d\u00edgitos que el administrador le otorg\u00f3 en la vista anterior y que dar\u00e1 paso a que el sistema le devuelva su propia clave generada autom\u00e1ticamente<\/li><li><em>vista9(): <\/em>En esta vista se comunica que el registro del nuevo usuario ha sido un \u00e9xito y se muestra su nueva clave para identificarse en el fichador de la empresa. Es por esto por lo que antes de todo, se comienza con un bucle en el que el c\u00f3digo espera que el script Python le comunique a trav\u00e9s del monitor serie la clave que debe imprimir por pantalla<\/li><li><em>vista10()<\/em>: Comunica un error de cualquier tipo, haciendo sonar tambi\u00e9n al buzzer y encendiendo el LED rojo<\/li><\/ul>\n\n\n\n<p>Por \u00faltimo, tenemos la implementaci\u00f3n de otros cuatro m\u00e9todos. getTouch() es un m\u00e9todo cuya funci\u00f3n es entrar en un bucle hasta que el usuario realice una pulsaci\u00f3n en la pantalla. Para ello, comprobamos que la presi\u00f3n realizada por el usuario en la propia pantalla sea superior a <em>MINPRESSURE<\/em>, que en este caso es 1, y asignamos las coordenadas de la pulsaci\u00f3n al array touchXY<\/p>\n\n\n\n<p><em>resetTouch()<\/em> es el encargado de resetear cada vez que es llamado el array touchXY. Cada vez que se resetea, ponemos tanto el valor de la X como el de la Y a -1, para distinguir del caso en el que el usuario pulsara en las coordenadas 0,0.&nbsp;<\/p>\n\n\n\n<p><em>printHomeButton()<\/em>, como su nombre indica, es llamado cada vez que queremos imprimir el bot\u00f3n que da la posibilidad de volver al inicio en el caso de que el usuario se haya equivocado.<\/p>\n\n\n\n<p><em>printKeyBoard()<\/em> se ocupa de la impresi\u00f3n del teclado, con sus correspondientes n\u00fameros del 0 al 9 adem\u00e1s del bot\u00f3n de eliminar. Primeramente realiza la impresi\u00f3n de todos estos botones, para luego pasar a un bucle <em>while<\/em> en el que se permanece mientras la longitud del <em>String<\/em> que el usuario est\u00e1 introduciendo sea menor a la longitud buscada. Dentro del <em>while<\/em>, llamamos en cada iteraci\u00f3n a <em>getTouch()<\/em> y luego procedemos a distinguir en qu\u00e9 bot\u00f3n espec\u00edfico ha pulsado el usuario a trav\u00e9s del an\u00e1lisis de las coordenadas. Si es un bot\u00f3n del 0-9, se concatena al <em>String<\/em> introducido, mientras que si pulsa en el bot\u00f3n de eliminar, la clave introducida hasta ahora se borra y se resetea la vista.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>3.2.- C\u00d3DIGO PYTHON<\/strong><\/h2>\n\n\n\n<p>El siguiente problema que se nos planteaba era d\u00f3nde almacenar toda la informaci\u00f3n de usuario, claves y registros de salidas y entradas, por lo que decidimos guardar toda esa informaci\u00f3n en ficheros de texto que se puedan consultar f\u00e1cilmente.<\/p>\n\n\n\n<p>Por ello hemos programado un script en Python que se encarga de manejar y hacer comprobaciones sobre los ficheros del sistema. Para llevar a cabo la comunicaci\u00f3n entre el script y el programa de Arduino, donde se encuentra todo lo explicado hasta el momento, se emplea el monitor serie.<\/p>\n\n\n\n<p>Para iniciar esa comunicaci\u00f3n, creamos una nueva variable <em>serialArduino<\/em>. La instanciamos con los par\u00e1metros del puerto serie que estemos utilizando en Arduino.<\/p>\n\n\n\n<p>El script Python estar\u00e1 constantemente leyendo y decodificando la entrada del monitor serie en un bucle infinito hasta encontrar alg\u00fan input que comience con <em>py<\/em>, lo cual significa que le hemos enviado alg\u00fan mensaje para que lo procese.<\/p>\n\n\n\n<p>Dependiendo del caso, ejecutaremos unas funciones u otras. A esas funciones les pasaremos como argumento la entrada le\u00edda y decodificada, pero sin el prefijo que hemos utilizado para identificar el caso.<\/p>\n\n\n\n<p>Si el mensaje comenzaba con <em>pya<\/em>, significa que le hemos pasado una clave de administrador (ejecutaremos <em>comprobarAdmin<\/em>), si comienza con <em>pyc <\/em>es una clave de empleado (ejecutaremos <em>ficharUsuario<\/em> y <em>encontrarUsuario<\/em>), y si empieza con <em>pyi <\/em>la entrada es un nuevo identificador a registrar (ejecutaremos <em>guardarUsuario<\/em>).<\/p>\n\n\n\n<p><em>comprobarAdmin(clave)<\/em>: abriremos el fichero <em>admin.txt <\/em>y leeremos su primera l\u00ednea. Si la clave es igual que la primera l\u00ednea del fichero significa que es correcta, y escribimos <em>true<\/em> codificado en el monitor serie para que lo lea el Arduino. Si no era igual, escribimos <em>false<\/em>.<\/p>\n\n\n\n<p><em>encontrarUsuario(clave): <\/em>Este m\u00e9todo recorre el archivo <em>usuariosClaves.txt<\/em> linea a linea, leyendo y comparando la parte de las claves de cada usuario almacenado con la que introduce el empleado mediante la pantalla. De esta forma, si la clave le\u00edda es igual a la introducida, obtenemos el identificador correspondiente a esa clave y lo devolvemos.<\/p>\n\n\n\n<p>En caso de no estar asociada la clave introducida a ning\u00fan usuario, el m\u00e9todo devuelve el objeto <em>none<\/em>.<\/p>\n\n\n\n<p><em>ficharUsuario(identificador): <\/em>En primer lugar, se crea la carpeta del d\u00eda correspondiente en caso de no existir, as\u00ed como los ficheros de <em>entrada.txt<\/em> y <em>salida.txt<\/em> vac\u00edos.<\/p>\n\n\n\n<p>Este programa se usa junto al anterior, pues el identificador pasado es el valor de retorno de la ejecuci\u00f3n del m\u00e9todo <em>encontrarUsuario<\/em>. Por este motivo, si el identificador es igual a <em>none<\/em>, hacemos que el m\u00e9todo no se ejecute retornando un 0, ya que significa que la clave que meti\u00f3 el usuario no est\u00e1 en el fichero<em> usuariosClaves.txt<\/em>. A continuaci\u00f3n, almacenamos la hora actual para registrarla en el programa, y comprobamos cu\u00e1ntas veces aparece el identificador dado en los ficheros de entrada y salida. Esto lo hacemos para saber si lo que corresponde hacer con el usuario es fichar o desfichar:&nbsp;<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Si las veces que se ha entrado y salido son iguales, corresponde una entrada.&nbsp;<\/li><li>Si se ha entrado una vez m\u00e1s que salido, corresponde una salida.<\/li><\/ul>\n\n\n\n<p>En funci\u00f3n de esto abrimos el fichero correspondiente y registramos la entrada\/salida del usuario con la hora a la que se ha realizado. En caso de ser una salida, adem\u00e1s mostramos la duraci\u00f3n de la \u00faltima jornada laboral realizada, simplemente restando la hora de la salida actual con la \u00faltima hora de entrada que se registr\u00f3 para ese identificador.&nbsp;<\/p>\n\n\n\n<p><em>guardarUsuario(identificador)<\/em>: Abriremos los ficheros <em>usuariosClaves.txt<\/em> y <em>contadorClave.txt<\/em>. El primero contiene el listado de las claves junto con sus identificadores, mientras que el segundo la informaci\u00f3n de la \u00faltima clave de usuario asignada.<\/p>\n\n\n\n<p>Nos guardamos en una variable la \u00faltima clave asignada y le sumamos uno, para que en caso de que se registre con \u00e9xito el usuario podamos asign\u00e1rsela y guardarla de nuevo en el fichero. Ahora comprobaremos si el identificador que nos ha escrito el usuario ya exist\u00eda previamente en el listado de usuarios y claves. Si ya exist\u00eda enviamos <em>false<\/em> al monitor serie. Pero si no exist\u00eda, guardamos el identificador con su nueva clave en el fichero&nbsp; <em>usuariosClaves.txt<\/em>, la informaci\u00f3n de esa nueva clave en <em>contadorClave.txt<\/em> y comunicamos por el monitor serie que todo ha salido bien y la clave asignada (con un segundo y medio de diferencia para que el c\u00f3digo Arduino pueda recibirlo adecuadamente).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>3.3.- ESTRUCTURA FICHEROS<\/strong><\/h2>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/gFc_KRyHbRMzGO5tFo-W2-9-4_NTmdiK9CBUutENMgGMEFhpoO6AHgdC0OhbdCxgsmbNCINLh2-9XdZxR7agqXxoQCoZq4ItBc9qfoGHcOoUGZMaiMhdSMUp0PVS8pLpi9p_dbRYviEJYfArrA\" alt=\"\"\/><figcaption>Organizaci\u00f3n de los ficheros y carpetas<\/figcaption><\/figure>\n\n\n\n<p>El programa se ejecuta en la carpeta ra\u00edz del proyecto, donde encontramos los siguientes archivos:&nbsp;<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><em>admin.txt<\/em>: Se trata del fichero donde se almacena el identificador del administrador que est\u00e1 habilitado para registrar nuevos empleados mediante el fichador.&nbsp;<\/li><\/ul>\n\n\n\n<ul class=\"wp-block-list\"><li><em>contadorClave.txt<\/em>: Es el fichero en el que almacenamos la \u00faltima clave asignada para, a la hora de a\u00f1adir un nuevo empleado, asignarle una clave nueva incrementada.&nbsp;<\/li><\/ul>\n\n\n\n<ul class=\"wp-block-list\"><li><em>usuariosClaves.txt<\/em>: Es el fichero en el que se encuentra la lista de todos los empleados de la empresa. El formato en el que hemos decidido guardarlo es el siguiente:<\/li><\/ul>\n\n\n\n<ul class=\"wp-block-list\"><li>A cada empleado le corresponde una l\u00ednea del archivo.<\/li><li>De cada empleado se almacena el identificador (8 d\u00edgitos correspondiendo con los d\u00edgitos del DNI) y, separado por un espacio, la clave num\u00e9rica generada autom\u00e1ticamente de 4 d\u00edgitos.&nbsp;<\/li><li>Ejemplo: 12345678 1003<\/li><\/ul>\n\n\n\n<ul class=\"wp-block-list\"><li>Carpetas del d\u00eda : Las carpetas del d\u00eda tienen por nombre la fecha del d\u00eda del que se trata y en ellas se almacenan dos ficheros que son:&nbsp;<\/li><\/ul>\n\n\n\n<ul class=\"wp-block-list\"><li><em>entrada.txt<\/em>: Es el fichero donde se guardan las entradas de los usuarios. Se registra de cada empleado el identificador y, separado por un gui\u00f3n, la hora en la que se ha realizado la entrada.&nbsp;<\/li><\/ul>\n\n\n\n<p>Ejemplo: 12345678-09:31:22&nbsp;<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><em>salida.txt<\/em>: Es el fichero en el que guardamos las salidas de los usuarios. El formato es el mismo que el del archivo <em>entrada.txt.<\/em><\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>3.4.- CIRCUITO<\/strong><\/h2>\n\n\n\n<p>El montaje del circuito no fue complejo y se realiz\u00f3 una vez que todo el software del fichador estaba realizado. Los principales componentes utilizados son:&nbsp;<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Placa Arduino Uno R3<\/li><li>Protoboard<\/li><li>Dos resistencias de 5K\u03a9<\/li><li>Dos diodos LED<\/li><li>Buzzer<\/li><\/ul>\n\n\n\n<p>La principal caracter\u00edstica es que la pantalla t\u00e1ctil ocupa la mayor\u00eda de los puertos de la placa Arduino Uno R3, estos son: las entradas anal\u00f3gicas del A0 al A4, las salidas digitales de la D0 a la D10 y los puertos de GRND, 3.3V y 5V. A pesar de ello no hemos necesitado multiplexores para operar con m\u00e1s componentes.<\/p>\n\n\n\n<p>El circuito se compone de 4 subcircuitos:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>El subcircuito de la pantalla<\/li><li>Dos subcircuitos que encienden las LEDS: sus respectivas salidas digitales est\u00e1n situadas en los puertos 11 y 12. Su funcionamiento es el siguiente: cuando la placa Uno lo requiera, mandar\u00e1 una se\u00f1al a trav\u00e9s de sus puertos que activar\u00e1n las luces LED y dicha se\u00f1al se mandar\u00e1 a tierra, cerrando as\u00ed el circuito.<\/li><li>Subcircuito del buzzer: la salida digital se sit\u00faa en el puerto 13 y funciona igual que el caso de las LEDS.<\/li><\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter is-resized\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/2HDKwtyy8zTQZfwxoLyA2p8bM9Q-QBvysRBPeiGwAnU8IKj8xY_ibYzlmYHnjSVVx8JT0QKawAFFcMT9Ji7B-njQCHmiD-fJ10gZu12Yg-7re5uPQaXFkAeOJH46cR8nrqx053IXklRL-XNDQg\" alt=\"\" width=\"-389\" height=\"-268\"\/><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\"><strong>3.5.- MONTAJE F\u00cdSICO<\/strong><\/h2>\n\n\n\n<p>Para la apariencia del fichador comenzamos comprando y pintando la caja de plateado para darle una apariencia met\u00e1lica. Acto seguido, realizamos los cortes necesarios para las LEDs, pantalla t\u00e1ctil y para la entrada del cable USB que conecta la placa con el ordenador.<\/p>\n\n\n\n<p>Una vez realizado esto, el \u00faltimo paso fue meter la circuiter\u00eda dentro de la caja, colocar las luces LEDS, la pantalla y enchufar el cable USB y con eso tendr\u00edamos el proyecto finalizado.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter is-resized\"><img decoding=\"async\" src=\"https:\/\/lh6.googleusercontent.com\/M2OK52VXamG_mHxpRzb6YaQ6182ZP-hTrm5XY5V9qQ9OsVihzFnGSUF80yrBzONM-FL5wsDLkJBYQKIHUCKwqW_ejuhYzbOVzx0jQ30eK0mRKuTUmC4YLRA1bJWRB0ejp6W6NgsXtZDOMUp7WQ\" alt=\"\" width=\"-481\" height=\"-360\"\/><\/figure>\n<\/div>\n\n\n<h1 class=\"wp-block-heading\"><strong>4.- PROBLEMAS ENCONTRADOS Y SOLUCIONES<\/strong><\/h1>\n\n\n\n<p>El primer problema con el que nos encontramos fue el hecho de no poder implementar uno de los requisitos iniciales, el lector de huellas, que quer\u00edamos para el proyecto ya que dispon\u00edamos de un mes para realizarlo, y el lector de huellas m\u00e1s disponible en el mercado ten\u00eda un tiempo de entrega estimado de tres semanas. Esto nos dejaba un margen muy peque\u00f1o con el que trabajar, apenas una semana para implementarlo, quedando as\u00ed el lector fuera del proyecto final.<\/p>\n\n\n\n<p>Otro problema que surgi\u00f3, aunque menos importante, fue que en la vista inicial del fichador, que se encarga de dar la bienvenida y mostrar la fecha y hora, quer\u00edamos que tanto la fecha como la hora se mostrar\u00e1n a tiempo real. Al comprender que la tarea iba a demorar demasiado la realizaci\u00f3n de otras funciones, decidimos prescindir de ella, mostrando \u00fanicamente la fecha y hora del momento de la compilaci\u00f3n del programa, como se explic\u00f3 anteriormente.<\/p>\n\n\n\n<p>Con todo, el principal problema que tuvimos fue a la hora de trabajar con los ficheros. Originalmente programamos pr\u00e1cticamente toda la funcionalidad del sistema de carpetas y archivos en C, para poder integrarlo en el mismo c\u00f3digo que las funcionalidades de la pantalla. Sin embargo, al juntarlo todo empezaron a surgir gran cantidad de errores relacionados con la importaci\u00f3n de paquetes y funciones no soportadas por el compilador. Tras muchas horas intentando solucionarlo y buscando en Internet, nos dimos cuenta de que no era posible guardar los archivos en el ordenador tal y como nosotros quer\u00edamos en un principio. Al final, dimos con la soluci\u00f3n que hemos acabado implementando en el proyecto final, un peque\u00f1o script en Python que se comunicar\u00e1 con el programa Arduino a trav\u00e9s del monitor serie y se encargar\u00e1 de toda la gesti\u00f3n de los ficheros necesarios para que el fichador funcione.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\"><strong>5.- PRESUPUESTO<\/strong><\/h1>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong><em>Elemento<\/em><\/strong><\/td><td><strong><em>Coste<\/em><\/strong><\/td><\/tr><tr><td>Kit Arduino proporcionado por URJC<\/td><td>0\u20ac<\/td><\/tr><tr><td>Pantalla t\u00e1ctil ELEGOO TFT<\/td><td>15\u20ac<\/td><\/tr><tr><td>Cables extra Macho-Hembra<\/td><td>3\u20ac<\/td><\/tr><tr><td>Caja contenedor del circuito<\/td><td>3\u20ac<\/td><\/tr><tr><td><strong>Presupuesto total<\/strong><\/td><td><strong>21\u20ac<\/strong><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\"><strong>6.- Anexo de c\u00f3digo<\/strong><\/h1>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>6.1 C\u00f3digo Arduino<\/strong><\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;Arduino.h&gt;\n#include &lt;time.h&gt;\n#include &lt;TouchScreen.h&gt;\n#include &lt;Adafruit_GFX.h&gt;\n#include &lt;Adafruit_TFTLCD.h&gt;\n#include &lt;string.h&gt;\n#include &lt;stdio.h&gt;\n#include &lt;stdlib.h&gt;\n#include &lt;errno.h&gt;\n#include &lt;unistd.h&gt;\n#include &lt;sys\/types.h&gt;\n#include &lt;Fonts\/FreeSansBold18pt7b.h&gt;\n \n#define LCD_CS A3\n#define LCD_CD A2\n#define LCD_WR A1\n#define LCD_RD A0\n#define LCD_RESET A4\n#define _OPEN_SYS_ITOA_EXT\n#define LONGID 8\n#define LONGCLAVE 4\n \n#define YP A3  \/\/ must be an analog pin, use \"An\" notation!\n#define XM A2  \/\/ must be an analog pin, use \"An\" notation!\n#define YM 9   \/\/ can be a digital pin\n#define XP 8   \/\/ can be a digital pin\n \n#define BLACK   0x0000\n#define BLUE    0x001F\n#define RED     0xF800\n#define GREEN   0x07E0\n#define CYAN    0x07FF\n#define MAGENTA 0xF81F\n#define YELLOW  0xFFE0\n#define WHITE   0xFFFF\n \n#define MINPRESSURE 1\n#define MAXPRESSURE 1000\n \n#define AZUL 13\n#define ROJO 12\n#define BUZZER 11\n \n\/* Vistas de la aplicaci\u00f3n\n0 --&gt; Salvapantallas (hora y fecha)\n1 --&gt; Elecci\u00f3n opci\u00f3n (botones)\n2 --&gt; Introducir c\u00f3digo (texto temporal)\n3 --&gt; Introducir c\u00f3digo (teclado)\n4 --&gt; \u00c9xito c\u00f3digo entrada (bienvenido + hora)\n5 --&gt; \u00c9xito c\u00f3digo salida (adi\u00f3s + info duraci\u00f3n)\n6 --&gt; Registrar administrador (introducir su clave)\n7 --&gt; Introducir identificador registrar (texto)\n8 --&gt; Introducir identificador registrar (teclado)\n9 --&gt; Mostrar clave autom\u00e1tica\n10 --&gt; Error (texto) + vuelta a 1\n*\/\n \n\/\/Declaraci\u00f3n de variables globales - pantalla\nAdafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);\nAdafruit_GFX_Button botonRojo;\nAdafruit_GFX_Button botonAzul;\nAdafruit_GFX_Button botonInicio;\nAdafruit_GFX_Button boton0;\nAdafruit_GFX_Button boton1;\nAdafruit_GFX_Button boton2;\nAdafruit_GFX_Button boton3;\nAdafruit_GFX_Button boton4;\nAdafruit_GFX_Button boton5;\nAdafruit_GFX_Button boton6;\nAdafruit_GFX_Button boton7;\nAdafruit_GFX_Button boton8;\nAdafruit_GFX_Button boton9;\nAdafruit_GFX_Button botonCancelar;\nTouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);\n \n\/\/Declaraci\u00f3n de variables globales - c\u00f3digo\nint touchXY&#91;2];\nint vista;\nString clave;\nint longString;\n \nvoid setup() {\n  \n   \/\/Llamamos a resetTouch al inicio de todos los m\u00e9todos\n   resetTouch();\n \n   \/\/Inicializamos el monitor serie\n   Serial.begin(9600);\n \n   \/\/Establecemos como salida los pines de los LEDs y el buzzer\n   pinMode(AZUL, OUTPUT);\n   pinMode(ROJO, OUTPUT);\n   pinMode(BUZZER, OUTPUT);\n \n   \/\/Establecemos par\u00e1metros b\u00e1sicos de la pantalla\n   tft.reset();\n   uint16_t identifier = 0x9341;\n   tft.begin(identifier);\n   tft.setRotation(1);\n   tft.fillScreen(BLACK);\n \n   \/\/Establecemos la fuente\n   tft.setFont(&amp;FreeSansBold18pt7b);\n \n   \/\/Inicializamos la vista a la pantalla inicial\n   vista = 0;\n}\n \nvoid loop(){\n   if (vista == 0) {\n       vista0();\n   }\n   else if (vista == 1) {\n       vista1();\n   }\n   else if (vista == 2) {\n       vista2();\n   }\n   else if (vista == 3) {\n       vista3();\n   }\n   else if (vista == 4) {\n       vista4();\n   }\n   else if (vista == 5) {\n       vista5();\n   }\n   else if (vista == 6) {\n       vista6();\n   }\n   else if (vista == 7) {\n       vista7();\n   }\n   else if (vista == 8) {\n       vista8();\n   }\n   else if (vista == 9) {\n       vista9();\n   }\n   else if (vista == 10) {\n       vista10();\n   }\n}\n \nvoid vista0 (){\n \n   resetTouch();\n \n   \/\/Cada vez que se llega a la vista 0, el salvapantalla, el string de la clave o ident se reinicia\n   clave = \"\";\n \n   \/\/Impresi\u00f3n de la vista\n   tft.fillScreen(BLACK);\n   tft.setCursor(50, 70);\n   tft.setTextSize(1);\n   tft.setFont(&amp;FreeSansBold18pt7b);\n   tft.setTextColor(WHITE);\n   tft.println(\"Bienvenidos\");\n   tft.setCursor(55, 120);\n   tft.println(__DATE__); \n   tft.setCursor(85, 170); \n   tft.println(__TIME__);\n  \n   \/\/Esperar a un toque y avanzar\n   getTouch();\n   vista = 1;\n}\n \nvoid vista1() {\n \n   resetTouch();\n  \n   tft.fillScreen(BLACK);\n \n   \/\/L\u00edmites boton azul\n   \/\/845x750   545x750\n   \/\/845x250   545x250\n \n   tft.setFont();\n \n   botonAzul.initButton(&amp;tft, 80, 125, 115, 145, BLUE, BLUE, WHITE, \"FICHAR\", 2);\n   botonAzul.drawButton();\n \n   \/\/L\u00edmites bot\u00f3n rojo\n   \/\/445x750   145x750\n   \/\/445x250   145x250\n \n   botonRojo.initButton(&amp;tft, 235, 125, 115, 145, RED, RED, WHITE, \"REGISTRAR\", 2);\n   botonRojo.drawButton();\n \n   tft.setFont(&amp;FreeSansBold18pt7b);\n \n   \/\/Implementamos funcionalidad de la vista\n   while(vista == 1) {\n       getTouch();\n      \n       \/\/Detectamos si la pulsaci\u00f3n est\u00e1 dentro del rango del bot\u00f3n azul\n       if((touchXY&#91;0] &lt; 845) &amp;&amp; (touchXY&#91;0] &gt; 545) &amp;&amp; (touchXY&#91;1] &lt; 750) &amp;&amp; (touchXY&#91;1] &gt; 250)){\n           vista = 2;\n       }\n       \/\/Detectamos si la pulsaci\u00f3n est\u00e1 dentro del rango del bot\u00f3n rojo\n       else if ((touchXY&#91;0] &lt; 445) &amp;&amp; (touchXY&#91;0] &gt; 145) &amp;&amp; (touchXY&#91;1] &lt; 750) &amp;&amp; (touchXY&#91;1] &gt; 250)){\n           vista = 6;\n       }\n   }\n}\n \nvoid vista2() {\n \n   \/\/Impresi\u00f3n de la pantalla\n   tft.fillScreen(BLACK);\n   tft.setCursor(25,110);\n   tft.setTextSize(1);\n   tft.setTextColor(WHITE);\n   tft.println(\"Introduzca clave\");\n   tft.setCursor(50,150);\n   tft.println(\"de empleado\");\n \n   delay(2000);\n \n   \/\/Establecemos la vista 3\n   vista = 3;\n}\n \nvoid vista3() {\n \n   \/\/Como la vista va a analizar las pulsaciones, reiniciamos las variables\n   resetTouch();\n \n   tft.fillScreen(BLACK);\n  \n   \/\/Establecemos la longitud del string a detectar por el teclado y llamamos a su m\u00e9todo\n   longString = 4;\n   printKeyBoard(0);\n \n   \/\/Si se ha recogido exitosamente la clave, pasamos a la vista 4\n   if(clave != \"\"){\n       Serial.println(\"pyc \" + clave);\n       String inputRecibido = \"\";\n       while (!(inputRecibido.equals(\"trueE\") || inputRecibido.equals(\"trueS\") || inputRecibido.equals(\"false\"))) {\n           inputRecibido = Serial.readStringUntil('\\n');\n       }\n \n       if (inputRecibido.equals(\"trueE\")) {\n           vista = 4;\n       }\n       else if (inputRecibido.equals(\"trueS\")) {\n           vista = 5;\n       }\n       else if (inputRecibido.equals(\"false\")) {\n           vista = 10;\n       }\n   }\n}\n \nvoid vista4() {\n \n   digitalWrite(AZUL, HIGH);\n \n   tone(BUZZER, 3000, 720);\n   tone(BUZZER, 4000, 480);\n \n   \/\/Impresi\u00f3n de la vista\n   tft.fillScreen(BLACK);\n   tft.setCursor(90,80);\n   tft.setTextColor(WHITE);\n   tft.setTextSize(1);\n   tft.println(\"Entrada\");\n   tft.setCursor(73,130);\n   tft.println(\"registrada\");\n   tft.setCursor(80,180);\n   tft.println(\"con exito\");\n \n   delay(2000);\n \n   digitalWrite(AZUL, LOW);\n \n   vista = 0;\n}\n \nvoid vista5() {\n   String inputRecibido = \"\";\n   while (!((inputRecibido.length() == 8) || (inputRecibido.length() == 7))) {\n       inputRecibido = Serial.readStringUntil('\\n');\n   }\n \n   digitalWrite(AZUL, HIGH);\n \n   tone(BUZZER, 3000, 720);\n   tone(BUZZER, 4000, 480);\n \n   \/\/Impresi\u00f3n de la vista\n   tft.fillScreen(BLACK);\n   tft.setCursor(20,80);\n   tft.setTextColor(WHITE);\n   tft.setTextSize(1);\n   tft.println(\"Salida registrada\");\n   tft.setCursor(10, 130);\n   tft.println(\"Duracion jornada:\");\n   tft.setCursor(95, 180);\n   tft.println(inputRecibido);\n \n   delay(2000);\n \n   digitalWrite(AZUL, LOW);\n \n   vista = 0;\n  \n}\n \nvoid vista6() {\n  \n   \/\/Como la vista va a analizar las pulsaciones, reiniciamos las variables\n   resetTouch();\n \n   \/\/Impresi\u00f3n de la vista\n   tft.fillScreen(BLACK);\n \n   \/\/Establecemos la longitud del string a detectar por el teclado y llamamos a su m\u00e9todo\n   longString = 4;\n   printKeyBoard(0);\n \n   if(clave != \"\"){\n       Serial.println(\"pya \" + clave);\n       String inputRecibido = \"\";\n       while (!(inputRecibido.equals(\"true\") || inputRecibido.equals(\"false\"))) {\n           inputRecibido = Serial.readStringUntil('\\n');\n       }\n \n       if (inputRecibido.equals(\"true\")) {\n           vista = 7;\n       }\n       else if (inputRecibido.equals(\"false\")) {\n           vista = 10;\n       }\n   }\n}\n \nvoid vista7() {\n  \n   \/\/Impresi\u00f3n de la vista\n   tft.fillScreen(BLACK);\n   tft.setCursor(70,80);\n   tft.setTextSize(1);\n   tft.setTextColor(WHITE);\n   tft.println(\"Introduzca\");\n   tft.setCursor(55,130);\n   tft.println(\"identificador\");\n   tft.setCursor(70,180);\n   tft.println(\"a registrar\");\n \n   delay(2000);\n \n   \/\/Actualizamos a la vista 8\n   vista = 8;\n}\n \nvoid vista8() {\n \n   \/\/Como la vista va a analizar las pulsaciones, reiniciamos las variables\n   resetTouch();\n \n   \/\/Impresi\u00f3n de la vista\n   tft.fillScreen(BLACK);\n \n   \/\/Establecemos la longitud del string a detectar por el teclado y llamamos a su m\u00e9todo\n   clave = \"\";\n   longString = 8;\n   printKeyBoard(1);\n \n   if(clave != \"\"){\n       Serial.println(\"pyi \" + clave);\n       String inputRecibido = \"\";\n       while (!(inputRecibido.equals(\"true\") || inputRecibido.equals(\"false\"))) {\n           inputRecibido = Serial.readStringUntil('\\n');\n       }\n \n       if (inputRecibido.equals(\"true\")) {\n           vista = 9;\n       }\n       else if (inputRecibido.equals(\"false\")) {\n           vista = 10;\n       }\n   }\n}\n \nvoid vista9() {\n   String inputRecibido = \"\";\n   while (!(inputRecibido.length() == 4)) {\n       inputRecibido = Serial.readStringUntil('\\n');\n   }\n \n   digitalWrite(AZUL, HIGH);\n \n   tone(BUZZER, 3000, 720);\n   tone(BUZZER, 4000, 480);\n \n   \/\/Impresi\u00f3n de la vista\n   tft.fillScreen(BLACK);\n   tft.setCursor(75,80);\n   tft.setTextColor(GREEN);\n   tft.setTextSize(1);\n   tft.println(\"EXITO AL\");\n   tft.setCursor(55, 130);\n   tft.print(\"REGISTRAR\");\n   tft.setCursor(50, 180);\n   tft.print(\"CLAVE: \");\n   tft.println(inputRecibido);\n \n   delay(2000);\n \n   digitalWrite(AZUL, LOW);\n \n   \/\/Se vuelve al salvapantallas\n   vista = 0;\n}\n \nvoid vista10() {\n \n   digitalWrite(ROJO, HIGH);\n \n   tone(BUZZER, 1000, 800);\n   tone(BUZZER, 100, 720);\n \n   \/\/Impresi\u00f3n de la vista\n   tft.fillScreen(BLACK);\n   tft.setCursor(45,100);\n   tft.setTextColor(RED);\n   tft.setTextSize(1);\n   tft.println(\"HA SURGIDO\");\n   tft.setCursor(60, 150);\n   tft.println(\"UN ERROR\");\n \n   delay(2000);\n \n   digitalWrite(ROJO, LOW);\n \n   \/\/Se vuelve al salvapantallas\n   vista = 0;\n}\n \nvoid getTouch(){\n   while(1){\n       TSPoint p = ts.getPoint();\n       pinMode(XM, OUTPUT);\n       pinMode(YP, OUTPUT);\n       if (p.z &gt; MINPRESSURE) {\n           touchXY&#91;0] = p.y;\n           touchXY&#91;1] = p.x;\n           break;\n       }\n   }\n}\n \nvoid resetTouch() {\n   touchXY&#91;0] = -1;\n   touchXY&#91;1] = -1;\n}\n \nvoid printHomeButton() {\n   botonInicio.initButton(&amp;tft, 305, 15, 20, 20, RED, RED, WHITE, \"X\", 2);\n   botonInicio.drawButton();\n}\n \nvoid printKeyBoard(int op){\n    \n   \/*Alturas --&gt; fila 1 550 y 370\n               fila 2 330 y 160*\/\n \n   \/*  0 --&gt; 834 y 725\n       1 --&gt; 700 y 580\n       2 --&gt; 543 y 425\n       3 --&gt; 400 y 285\n       4 --&gt; 250 y 140\n       \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n   *\/\n   \/\/Bot\u00f3n eliminar --&gt;    260x780     130x780\n   \/\/                      260x610     130x610\n \n   \/\/Bot\u00f3n home --&gt; si touchXY&#91;0] &lt; 130\n   \/\/              si touchXY&#91;1] &gt; 840\n \n   \/\/Reestablecemos la fuente\n   tft.setFont();\n \n   \/\/Impresi\u00f3n de los num\u00e9ricos del teclado, el bot\u00f3n eliminar y el bot\u00f3n de volver a inicio\n   printHomeButton();\n \n   boton0.initButton(&amp;tft, 50,135, 50,50, WHITE, BLACK, WHITE, \"0\", 2);\n   boton0.drawButton(true);\n \n   boton1.initButton(&amp;tft, 105,135, 50,50, WHITE, BLACK, WHITE, \"1\", 2);\n   boton1.drawButton(true);\n \n   boton2.initButton(&amp;tft, 160,135, 50,50, WHITE, BLACK, WHITE, \"2\", 2);\n   boton2.drawButton(true);\n \n   boton3.initButton(&amp;tft, 215,135, 50,50, WHITE, BLACK, WHITE, \"3\", 2);\n   boton3.drawButton(true);\n  \n   boton4.initButton(&amp;tft, 270,135, 50,50, WHITE, BLACK, WHITE, \"4\", 2);\n   boton4.drawButton(true);\n  \n   boton5.initButton(&amp;tft, 50,195, 50,50, WHITE, BLACK, WHITE, \"5\", 2);\n   boton5.drawButton(true);\n  \n   boton6.initButton(&amp;tft, 105,195, 50,50, WHITE, BLACK, WHITE, \"6\", 2);\n   boton6.drawButton(true);\n \n   boton7.initButton(&amp;tft, 160,195, 50,50, WHITE, BLACK, WHITE, \"7\", 2);\n   boton7.drawButton(true);\n \n   boton8.initButton(&amp;tft, 215,195, 50,50, WHITE, BLACK, WHITE, \"8\", 2);\n   boton8.drawButton(true);\n  \n   boton9.initButton(&amp;tft, 270,195, 50,50, WHITE, BLACK, WHITE, \"9\", 2);\n   boton9.drawButton(true);\n \n   botonCancelar.initButton(&amp;tft, 270, 70, 50,50, RED, WHITE, RED, \"&lt;-\", 2);\n   botonCancelar.drawButton(true);\n \n   tft.setCursor(40,55);\n   tft.setTextSize(4);\n \n   tft.setTextColor(WHITE);\n   while(clave.length() &lt; longString){\n       getTouch();\n       if(touchXY&#91;1] &lt; 780 &amp;&amp; touchXY&#91;1] &gt; 610 &amp;&amp; touchXY&#91;0] &lt; 260 &amp;&amp; touchXY&#91;0] &gt; 130){\n           clave = \"\";\n           break;\n       }\n       else if(touchXY&#91;1] &lt; 550 &amp;&amp; touchXY&#91;1] &gt; 370){ \/\/fila 1\n           if(touchXY&#91;0] &lt; 834 &amp;&amp; touchXY&#91;0] &gt; 725){\n               if (op == 0) {\n                   tft.print(\"*\");\n               }\n               else if (op == 1) {\n                   tft.print(\"0\");\n               }\n               clave+=\"0\"; \n           }\n           else if(touchXY&#91;0] &lt; 700 &amp;&amp; touchXY&#91;0] &gt; 580){\n               if (op == 0) {\n                   tft.print(\"*\");\n               }\n               else if (op == 1) {\n                   tft.print(\"1\");\n               }\n               clave+=\"1\";\n           }\n           else if(touchXY&#91;0] &lt; 543 &amp;&amp; touchXY&#91;0] &gt; 425){\n               if (op == 0) {\n                   tft.print(\"*\");\n               }\n               else if (op == 1) {\n                   tft.print(\"2\");\n               }\n               clave+=\"2\";\n           }\n           else if(touchXY&#91;0] &lt; 400 &amp;&amp; touchXY&#91;0] &gt; 285){\n               if (op == 0) {\n                   tft.print(\"*\");\n               }\n               else if (op == 1) {\n                   tft.print(\"3\");\n               }\n               clave+=\"3\";\n           }\n           else if(touchXY&#91;0] &lt; 250 &amp;&amp; touchXY&#91;0] &gt; 140){\n               if (op == 0) {\n                   tft.print(\"*\");\n               }\n               else if (op == 1) {\n                   tft.print(\"4\");\n               }\n               clave+=\"4\";\n           }\n       }\n       else if(touchXY&#91;1] &lt; 330 &amp;&amp; touchXY&#91;1] &gt; 160){\n           if(touchXY&#91;0] &lt; 834 &amp;&amp; touchXY&#91;0] &gt; 725){\n               if (op == 0) {\n                   tft.print(\"*\");\n               }\n               else if (op == 1) {\n                   tft.print(\"5\");\n               }\n               clave+=\"5\";\n           }\n           else if(touchXY&#91;0] &lt; 700 &amp;&amp; touchXY&#91;0] &gt; 580){\n               if (op == 0) {\n                   tft.print(\"*\");\n               }\n               else if (op == 1) {\n                   tft.print(\"6\");\n               }\n               clave+=\"6\";\n           }\n           else if(touchXY&#91;0] &lt; 543 &amp;&amp; touchXY&#91;0] &gt; 425){\n               if (op == 0) {\n                   tft.print(\"*\");\n               }\n               else if (op == 1) {\n                   tft.print(\"7\");\n               }\n               clave+=\"7\";\n           }\n           else if(touchXY&#91;0] &lt; 400 &amp;&amp; touchXY&#91;0] &gt; 285){\n               if (op == 0) {\n                   tft.print(\"*\");\n               }\n               else if (op == 1) {\n                   tft.print(\"8\");\n               }\n               clave+=\"8\";\n           }\n           else if(touchXY&#91;0] &lt; 250 &amp;&amp; touchXY&#91;0] &gt; 140){\n               if (op == 0) {\n                   tft.print(\"*\");\n               }\n               else if (op == 1) {\n                   tft.print(\"9\");\n               }\n               clave+=\"9\";\n           }\n       }\n       else if (touchXY&#91;0] &lt; 130 &amp;&amp; touchXY&#91;1] &gt; 840) { \/\/botonHome\n           vista = 1;\n           clave = \"\";\n           break;\n       }\n       delay(300);\n   }\n \n   tft.setFont(&amp;FreeSansBold18pt7b);\n \n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>6.2 C\u00f3digo Python<\/strong><\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>import os\nimport errno\nfrom datetime import date\nfrom datetime import datetime\nimport readline\nimport serial\nimport time\n \nnuevaClave = \"\"\n \n# FICHAR USUARIO\n \ndef encontrarUsuario (clave):\n \n   with open (\"usuariosClaves.txt\", 'r') as us:\n       encontrado = False\n       for linea in us:\n           if (str(linea&#91;9:13]) == (str(clave))):\n               encontrado = True\n               return(linea&#91;:8])\n      \n       if (encontrado == False):\n           serialArduino.write(\"false\".encode())\n           return None\n \ndef ficharUsuario (identificador):\n  \n   fecha = str(date.today())\n \n   try:\n       os.mkdir(fecha)\n   except OSError as e:\n       if e.errno != errno.EEXIST:\n           raise\n \n   os.chdir(fecha)\n \n   fileE = open('entrada.txt', 'a+')\n   fileS = open('salida.txt', 'a+')\n      \n   if (identificador == None):\n       os.chdir(\"..\")\n       return 0\n      \n  \n  \n   esSalida = False\n   hora = str(datetime.now().time())&#91;:8]\n   vecesEntrada = 0\n   vecesSalida = 0\n   horaEntrada = \"\"\n   with open('entrada.txt', 'r') as f:\n       for linea in f:\n           if (str(linea&#91;:8]) == (str(identificador))):\n               vecesEntrada += 1\n               horaEntrada = linea&#91;9:17]\n  \n   with open('salida.txt', 'r') as f:\n       for linea in f:\n           if (str(linea&#91;:8]) == (str(identificador))):\n               vecesSalida += 1\n  \n   print(\"Entrada: \" + str(horaEntrada))\n  \n   if ((vecesEntrada == 0) or (vecesEntrada == vecesSalida)):\n        with open('entrada.txt', 'a+') as f2:\n            f2.write(str(identificador) + '-' + hora + '\\n')\n            serialArduino.write(\"trueE\".encode())\n           \n   else:\n       with open('salida.txt', 'a+') as f2:\n            f2.write(str(identificador) + '-' + hora + '\\n')\n            h1 = datetime.strptime(hora, \"%H:%M:%S\")\n            h2 = datetime.strptime(horaEntrada, \"%H:%M:%S\")\n            duracionJornada = h1 - h2\n            serialArduino.write(\"trueS\".encode())\n            strDuracionJornada = str(duracionJornada)\n            print(\"strDuracionJornada: \" + strDuracionJornada)\n            time.sleep(1.5)\n            serialArduino.write(strDuracionJornada.encode())\n           \n   os.chdir(\"..\")\n              \ndef guardarUsuario (identificador):\n   file = open(\"usuariosClaves.txt\", \"r+\")\n   file2 = open(\"contadorClave.txt\")\n   ultimaClave = file2.readline()\n   nuevaClave = int(ultimaClave) + 1\n   file2.close()\n   if(file.read().count(identificador) &gt; 0):\n       serialArduino.write(\"false\".encode())\n   else:\n       file.write(identificador + \" \" + str(nuevaClave)+\"\\n\")\n       file2 = open(\"contadorClave.txt\", \"w\")\n       file2.write(str(nuevaClave))\n       print(\"La nueva clave es \" + str(nuevaClave))\n       serialArduino.write(\"true\".encode())\n       time.sleep(1.5)\n       serialArduino.write(str(nuevaClave).encode())\n   file.close()\n   file2.close()\n  \ndef comprobarAdmin (clave):\n   file = open(\"admin.txt\")\n   if(clave == (file.readline())):\n       serialArduino.write(\"true\".encode())\n   else:\n       serialArduino.write(\"false\".encode())\n   file.close()\n \nserialArduino = serial.Serial(\"\/dev\/ttyACM0\", 9600)\ntime.sleep(1)\n \nwhile True:\n   linea = \"\"\n   while(not linea.startswith(\"py\")):\n       linea=serialArduino.readline().decode('ascii')\n  \n   print(linea)\n   clave = linea&#91;4:len(linea) - 2]\n   print()\n   print(clave)\n   print()\n   print(\"Vamos a comprobar el tipo de clave\")\n  \n   if (linea.startswith(\"pya\")):\n       print(\"- Es una clave de administrador\")\n       comprobarAdmin(clave)\n   elif (linea.startswith(\"pyc\")):\n       print(\"- Es una clave normal de trabajador\")\n       ficharUsuario(encontrarUsuario(clave))\n   elif (linea.startswith(\"pyi\")):\n       print(\"- Estamos enviando un identificador\")\n       guardarUsuario(clave)\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Trabajo realizado por el Grupo 1 del campus de M\u00f3stoles, formado por Sergio Carrascosa S\u00e1nchez, Francisco Daniel Fr\u00edas Quero, Jorge Garc\u00eda-Mauri\u00f1o Moll\u00e1 y Jose Manuel Soler Siles. 1.- INTRODUCCI\u00d3N AL PROYECTO Y OBJETIVOS PERSEGUIDOS&#46;&#46;&#46;<\/p>\n","protected":false},"author":29,"featured_media":5025,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-5018","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-proyectos"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Fichador de trabajo - Proyectos con Arduino.<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/fichador-de-trabajo\/\" \/>\n<meta property=\"og:locale\" content=\"es_ES\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Fichador de trabajo - Proyectos con Arduino.\" \/>\n<meta property=\"og:description\" content=\"Trabajo realizado por el Grupo 1 del campus de M\u00f3stoles, formado por Sergio Carrascosa S\u00e1nchez, Francisco Daniel Fr\u00edas Quero, Jorge Garc\u00eda-Mauri\u00f1o Moll\u00e1 y Jose Manuel Soler Siles. 1.- INTRODUCCI\u00d3N AL PROYECTO Y OBJETIVOS PERSEGUIDOS&#046;&#046;&#046;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/fichador-de-trabajo\/\" \/>\n<meta property=\"og:site_name\" content=\"Proyectos con Arduino.\" \/>\n<meta property=\"article:published_time\" content=\"2022-05-06T16:39:45+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-06-03T07:56:56+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2022\/05\/Captura.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1467\" \/>\n\t<meta property=\"og:image:height\" content=\"926\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Escrito por\" \/>\n\t<meta name=\"twitter:data1\" content=\"\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tiempo de lectura\" \/>\n\t<meta name=\"twitter:data2\" content=\"24 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/fichador-de-trabajo\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/fichador-de-trabajo\\\/\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Fichador de trabajo\",\"datePublished\":\"2022-05-06T16:39:45+00:00\",\"dateModified\":\"2022-06-03T07:56:56+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/fichador-de-trabajo\\\/\"},\"wordCount\":3375,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/fichador-de-trabajo\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/wp-content\\\/uploads\\\/sites\\\/8\\\/2022\\\/05\\\/Captura.jpg\",\"articleSection\":[\"Proyectos\"],\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/fichador-de-trabajo\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/fichador-de-trabajo\\\/\",\"url\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/fichador-de-trabajo\\\/\",\"name\":\"Fichador de trabajo - Proyectos con Arduino.\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/fichador-de-trabajo\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/fichador-de-trabajo\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/wp-content\\\/uploads\\\/sites\\\/8\\\/2022\\\/05\\\/Captura.jpg\",\"datePublished\":\"2022-05-06T16:39:45+00:00\",\"dateModified\":\"2022-06-03T07:56:56+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/fichador-de-trabajo\\\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/fichador-de-trabajo\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/fichador-de-trabajo\\\/#primaryimage\",\"url\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/wp-content\\\/uploads\\\/sites\\\/8\\\/2022\\\/05\\\/Captura.jpg\",\"contentUrl\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/wp-content\\\/uploads\\\/sites\\\/8\\\/2022\\\/05\\\/Captura.jpg\",\"width\":1467,\"height\":926,\"caption\":\"Fichador de trabajo\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/fichador-de-trabajo\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Portada\",\"item\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Fichador de trabajo\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#website\",\"url\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/\",\"name\":\"Proyectos con Arduino.\",\"description\":\"Blog de proyectos de Arduino de alumnos de la URJC\",\"publisher\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#organization\",\"name\":\"Universidad Rey Juan Carlos\",\"url\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/wp-content\\\/uploads\\\/sites\\\/8\\\/2022\\\/05\\\/logourjc-1.jpg\",\"contentUrl\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/wp-content\\\/uploads\\\/sites\\\/8\\\/2022\\\/05\\\/logourjc-1.jpg\",\"width\":745,\"height\":288,\"caption\":\"Universidad Rey Juan Carlos\"},\"image\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"\",\"url\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/author\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Fichador de trabajo - Proyectos con Arduino.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blogs.etsii.urjc.es\/dseytr\/fichador-de-trabajo\/","og_locale":"es_ES","og_type":"article","og_title":"Fichador de trabajo - Proyectos con Arduino.","og_description":"Trabajo realizado por el Grupo 1 del campus de M\u00f3stoles, formado por Sergio Carrascosa S\u00e1nchez, Francisco Daniel Fr\u00edas Quero, Jorge Garc\u00eda-Mauri\u00f1o Moll\u00e1 y Jose Manuel Soler Siles. 1.- INTRODUCCI\u00d3N AL PROYECTO Y OBJETIVOS PERSEGUIDOS&#46;&#46;&#46;","og_url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/fichador-de-trabajo\/","og_site_name":"Proyectos con Arduino.","article_published_time":"2022-05-06T16:39:45+00:00","article_modified_time":"2022-06-03T07:56:56+00:00","og_image":[{"width":1467,"height":926,"url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2022\/05\/Captura.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","twitter_misc":{"Escrito por":"","Tiempo de lectura":"24 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/fichador-de-trabajo\/#article","isPartOf":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/fichador-de-trabajo\/"},"author":{"name":"","@id":""},"headline":"Fichador de trabajo","datePublished":"2022-05-06T16:39:45+00:00","dateModified":"2022-06-03T07:56:56+00:00","mainEntityOfPage":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/fichador-de-trabajo\/"},"wordCount":3375,"commentCount":0,"publisher":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#organization"},"image":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/fichador-de-trabajo\/#primaryimage"},"thumbnailUrl":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2022\/05\/Captura.jpg","articleSection":["Proyectos"],"inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/blogs.etsii.urjc.es\/dseytr\/fichador-de-trabajo\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/fichador-de-trabajo\/","url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/fichador-de-trabajo\/","name":"Fichador de trabajo - Proyectos con Arduino.","isPartOf":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/fichador-de-trabajo\/#primaryimage"},"image":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/fichador-de-trabajo\/#primaryimage"},"thumbnailUrl":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2022\/05\/Captura.jpg","datePublished":"2022-05-06T16:39:45+00:00","dateModified":"2022-06-03T07:56:56+00:00","breadcrumb":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/fichador-de-trabajo\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blogs.etsii.urjc.es\/dseytr\/fichador-de-trabajo\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/fichador-de-trabajo\/#primaryimage","url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2022\/05\/Captura.jpg","contentUrl":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2022\/05\/Captura.jpg","width":1467,"height":926,"caption":"Fichador de trabajo"},{"@type":"BreadcrumbList","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/fichador-de-trabajo\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Portada","item":"https:\/\/blogs.etsii.urjc.es\/dseytr\/"},{"@type":"ListItem","position":2,"name":"Fichador de trabajo"}]},{"@type":"WebSite","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#website","url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/","name":"Proyectos con Arduino.","description":"Blog de proyectos de Arduino de alumnos de la URJC","publisher":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blogs.etsii.urjc.es\/dseytr\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#organization","name":"Universidad Rey Juan Carlos","url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#\/schema\/logo\/image\/","url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2022\/05\/logourjc-1.jpg","contentUrl":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2022\/05\/logourjc-1.jpg","width":745,"height":288,"caption":"Universidad Rey Juan Carlos"},"image":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"","url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/author\/"}]}},"_links":{"self":[{"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/posts\/5018","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/users\/29"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/comments?post=5018"}],"version-history":[{"count":9,"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/posts\/5018\/revisions"}],"predecessor-version":[{"id":5800,"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/posts\/5018\/revisions\/5800"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/media\/5025"}],"wp:attachment":[{"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/media?parent=5018"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/categories?post=5018"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/tags?post=5018"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}