.. note::

    Hola, bienvenido a la Comunidad de Entusiastas de SunFounder Raspberry Pi & Arduino & ESP32 en Facebook. Profundiza en Raspberry Pi, Arduino y ESP32 con otros entusiastas.

    **¿Por qué unirse?**

    - **Soporte Experto**: Resuelve problemas post-venta y desafíos técnicos con la ayuda de nuestra comunidad y equipo.
    - **Aprende y Comparte**: Intercambia consejos y tutoriales para mejorar tus habilidades.
    - **Previews Exclusivos**: Obtén acceso anticipado a nuevos anuncios de productos y adelantos.
    - **Descuentos Especiales**: Disfruta de descuentos exclusivos en nuestros productos más nuevos.
    - **Promociones Festivas y Sorteos**: Participa en sorteos y promociones navideñas.

    👉 ¿Listo para explorar y crear con nosotros? Haz clic en [|link_sf_facebook|] y únete hoy mismo.

.. _4.1.19_py:

4.1.19 Sistema de Asistencia
===================================

Introducción
---------------

Vamos a crear un sistema de asistencia simple. Cuando escaneamos la tarjeta, la Raspberry Pi registrará nuestra información y generará un archivo csv.

Componentes Necesarios
------------------------------

En este proyecto, necesitamos los siguientes componentes.

.. image:: ../img/4.1.20components2.png

Es definitivamente conveniente comprar un kit completo, aquí está el enlace:

.. list-table::
    :widths: 20 20 20
    :header-rows: 1

    *   - Nombre	
        - ARTÍCULOS EN ESTE KIT
        - ENLACE
    *   - Kit Raphael
        - 337
        - |link_Raphael_kit|

También puedes comprarlos por separado en los enlaces a continuación.

.. list-table::
    :widths: 30 20
    :header-rows: 1

    *   - INTRODUCCIÓN DE COMPONENTES
        - ENLACE DE COMPRA

    *   - :ref:`cpn_gpio_extension_board`
        - |link_gpio_board_buy|
    *   - :ref:`cpn_breadboard`
        - |link_breadboard_buy|
    *   - :ref:`cpn_wires`
        - |link_wires_buy|
    *   - :ref:`cpn_audio_speaker`
        - \-
    *   - :ref:`cpn_dot_matrix`
        - |link_led_matrix_buy|
    *   - :ref:`cpn_mfrc522`
        - |link_mfrc522_rfid_buy|

Diagrama Esquemático
---------------------------

============== =============== ======== ====
Nombre T-Board Conexión física wiringPi BCM
GPIO25         Pin 22          6        25
SPIMOSI        Pin 19          12       MOSI
SPIMISO        Pin 19          12       MISO
SPICE0         pin 24          10       CE0
SPICE1         pin 26          11       CE1
SPISCLK        Pin 23          14       SCLK
============== =============== ======== ====

.. image:: ../img/4.1.20_schematic.png
   :align: center

Procedimientos Experimentales
---------------------------------

.. note::

    Activa el SPI antes de comenzar el experimento, consulta :ref:spi configuration` para más detalles.
    
    También se necesitan las bibliotecas :ref:`Luma.LED_Matrix` y :ref:`Spidev y MFRC522`.

Paso 1: Construye el circuito.

.. image:: ../img/atten1.png

Paso 2: Ejecuta el archivo ``2.2.10_write.py`` para modificar el contenido de la tarjeta rfid.

.. raw:: html

   <run></run>

.. code-block:: 

    cd ~/raphael-kit/python
    sudo python3 2.2.10_write.py

Paso 3: Ingresa el nombre (aquí usamos ``John`` como ejemplo) y presiona ``Enter`` para confirmar, luego coloca la tarjeta en el módulo MFRC522, espera a que aparezca "La escritura de datos está completa" y retira la tarjeta, o reescribe el mensaje en otra tarjeta y sal con ``Ctrl+C``.

.. image:: ../img/write_card.png

Paso 4: Ingresa en la carpeta del código y ejecuta.

.. raw:: html

   <run></run>

.. code-block::

    cd ~/raphael-kit/python
    sudo python3 4.1.19_Attendance_Machine.py

Después de iniciar el programa, acercamos la tarjeta RFID al Módulo RFID MFRC522, la Raspberry Pi emitirá una voz para saludarte y lo mostrará en la matriz LED.

También podemos encontrar un archivo ``.csv`` que registra el tiempo y la lista en el mismo directorio. Ábrelo con el comando nano y verás el registro justo ahora.

.. raw:: html

   <run></run>

.. code-block::

    sudo nano attendance_sheet.2021.06.29.csv

.. image:: ../img/atten3.png
  :width: 400

**Código**

.. note::
    Puedes **Modificar/Resetear/Copiar/Ejecutar/Detener** el código a continuación. Pero antes de eso, necesitas ir a la ruta del código fuente como ``raphael-kit/python``. Después de modificar el código, puedes ejecutarlo directamente para ver el efecto.

.. raw:: html

    <run></run>

.. code-block:: python

    import time
    from tts import TTS
    import RPi.GPIO as GPIO
    from mfrc522 import SimpleMFRC522
    from luma.core.interface.serial import spi, noop
    from luma.core.render import canvas
    from luma.core.virtual import viewport
    from luma.led_matrix.device import max7219
    from luma.core.legacy import text
    from luma.core.legacy.font import proportional, CP437_FONT, LCD_FONT

    serial = spi(port=0, device=1, gpio=noop())
    device = max7219(serial, rotate=1)
    virtual = viewport(device, width=200, height=400)

    reader = SimpleMFRC522()

    tts = TTS(engine="espeak")
    tts.lang('en-US')

    attendance_statistics = {}

    def get_time():
        time.time()
        year = str(time.strftime('%Y',time.localtime(time.time())))
        month = str(time.strftime('%m',time.localtime(time.time())))
        day = str(time.strftime('%d',time.localtime(time.time())))
        hour = str(time.strftime('%H',time.localtime(time.time())))
        minute = str(time.strftime('%M',time.localtime(time.time())))
        second = str(time.strftime('%S',time.localtime(time.time())))
        present_time = year + '.' + month + '.' + day + '.' + hour + '.' + minute + '.' + second
        present_date = year + '.' + month + '.' + day
        return present_date, present_time

    def main():
        while True:
            print("Reading...Please place the card...")
            id, name = reader.read()
            print(id,name)
            greeting = name.rstrip() + ", Welcome!"
            present_date, present_time = get_time()
            attendance_statistics[name.rstrip()] = present_time
            tts.say(greeting)
            with open('attendance_sheet.' + present_date + '.csv', 'w') as f:
                [f.write('{0}  {1}\n'.format(key, value)) for key, value in attendance_statistics.items()]
            with canvas(virtual) as draw:
                text(draw, (0, 0), greeting, fill="white", font=proportional(CP437_FONT))
            for offset in range(95):
                virtual.set_position((offset,0))
                time.sleep(0.1)

    def destroy():
        GPIO.cleanup()
        pass

    if __name__ == '__main__':
        try:
            main()
        except KeyboardInterrupt:
            destroy()

Explicación del Código
-------------------------

Para entender mejor el programa, puede que necesites completar :ref:`1.1.6 Matriz de LEDs`, :ref:`2.2.10 Módulo RFID MFRC522` y :ref:`3.1.4 Conversión de texto a voz` primero.

.. code-block:: python

    def get_time():
        time.time()
        year = str(time.strftime('%Y',time.localtime(time.time())))
        month = str(time.strftime('%m',time.localtime(time.time())))
        day = str(time.strftime('%d',time.localtime(time.time())))
        hour = str(time.strftime('%H',time.localtime(time.time())))
        minute = str(time.strftime('%M',time.localtime(time.time())))
        second = str(time.strftime('%S',time.localtime(time.time())))
        present_time = year + '.' + month + '.' + day + '.' + hour + '.' + minute + '.' + second
        present_date = year + '.' + month + '.' + day
        return present_date, present_time

Usa la función ``get_time()`` para obtener la marca de tiempo actual y devolver dos valores. 
Entre ellos, ``present_date`` es precisa hasta el día actual y ``present_time`` es precisa hasta el segundo actual.

.. code-block:: python

    id, name = reader.read()
    greeting = name.rstrip() + ", Welcome!"
    present_date, present_time = get_time()
    attendance_statistics[name.rstrip()] = present_time

La función ``reader.read()`` lee la información del nombre y luego crea un saludo. 
Luego se genera un diccionario ``attendance_statistics``, y ``name.rstrip()`` y ``present_time`` se almacenan como claves y valores.

.. code-block:: python

    tts.say(greeting)

Pronuncia un saludo a través del altavoz.

.. code-block:: python

    with open('attendance_sheet.' + present_date + '.csv', 'w') as f:
        [f.write('{0}  {1}\n'.format(key, value)) for key, value in attendance_statistics.items()]

Escribe las ``attendance_statistics`` en el archivo .csv.

.. code-block:: python

    with canvas(virtual) as draw:
        text(draw, (0, 0), greeting, fill="white", font=proportional(CP437_FONT))
    for offset in range(95):
        virtual.set_position((offset,0))
        time.sleep(0.1)

Despliega este saludo en la pantalla.

**Imagen del Fenómeno**

.. image:: ../img/attend_system.JPG

