.. note::

    Ciao, benvenuto nella community di appassionati di SunFounder Raspberry Pi & Arduino & ESP32 su Facebook! Approfondisci Raspberry Pi, Arduino ed ESP32 insieme ad altri appassionati.

    **Perché unirti a noi?**

    - **Supporto Esperto**: Risolvi i problemi post-vendita e le sfide tecniche con l'aiuto della nostra community e del nostro team.
    - **Impara & Condividi**: Scambia suggerimenti e tutorial per migliorare le tue competenze.
    - **Anteprime Esclusive**: Accedi in anteprima agli annunci di nuovi prodotti e alle anticipazioni.
    - **Sconti Speciali**: Approfitta di sconti esclusivi sui nostri nuovi prodotti.
    - **Promozioni Festive e Giveaway**: Partecipa a promozioni festive e giveaway.

    👉 Pronto a esplorare e creare con noi? Clicca [|link_sf_facebook|] e unisciti oggi stesso!

.. _4.1.19_py:

4.1.19 Sistema di Presenze
================================

Introduzione
---------------

Creiamo un semplice sistema di presenze. Quando si scansiona la carta, il Raspberry Pi registrerà le informazioni e genererà un file CSV.

Componenti Necessari
------------------------------

In questo progetto, ci servono i seguenti componenti.

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

È sicuramente conveniente acquistare un kit completo, ecco il link: 

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

    *   - Nome	
        - ELEMENTI IN QUESTO KIT
        - LINK
    *   - Raphael Kit
        - 337
        - |link_Raphael_kit|

Puoi anche acquistare i componenti separatamente dai link qui sotto.

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

    *   - INTRODUZIONE COMPONENTI
        - LINK ACQUISTO

    *   - :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|

Schema Elettrico
----------------------

============ ======== ======== ====
T-Board Name physical 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

Procedure Sperimentali
-------------------------

.. note::

    Attiva SPI prima di iniziare l'esperimento, fai riferimento a :ref:`Configurazione SPI` per i dettagli.
    
    Sono necessarie anche le librerie :ref:`Luma.LED_Matrix` e :ref:`Spidev e MFRC522`.

Passo 1: Costruisci il circuito.

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

Passo 2: Esegui il file ``2.2.10_write.py`` per modificare il contenuto della carta RFID.

.. raw:: html

   <run></run>

.. code-block:: 

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

Passo 3: Inserisci il nome (qui usiamo ``John`` come esempio) e premi ``Enter`` per confermare, quindi avvicina la carta al modulo MFRC522, aspetta che appaia "Data writing is complete" e rimuovi la carta, oppure riscrivi il messaggio su un'altra carta ed esci con ``Ctrl+C``.

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

Passo 4: Vai nella cartella del codice ed esegui.

.. raw:: html

   <run></run>

.. code-block::

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

Dopo aver avviato il programma, avvicina la carta RFID al modulo MFRC522 RFID, il Raspberry Pi ti invierà un saluto vocale e lo visualizzerà sulla matrice LED.

Troveremo anche un file ``.csv`` che registra il tempo e l'elenco nella stessa directory. Aprilo con il comando nano e vedrai il record appena creato.

.. raw:: html

   <run></run>

.. code-block::

    sudo nano attendance_sheet.2021.06.29.csv

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

**Codice**

.. note::
    Puoi **Modificare/Reimpostare/Copiare/Eseguire/Interrompere** il codice qui sotto. Ma prima di farlo, devi andare nel percorso del codice sorgente come ``raphael-kit/python``. Dopo aver modificato il codice, puoi eseguirlo direttamente per vedere l'effetto.

.. 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()

Spiegazione del Codice
---------------------------

Per comprendere meglio il programma, potrebbe essere necessario completare prima :ref:`1.1.6 Matrice a Punti LED`, :ref:`2.2.10 Modulo RFID MFRC522` e :ref:`3.1.4 Sintesi vocale (Text-to-speech)`.

.. 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 funzione ``get_time()`` per ottenere il timestamp corrente e restituire due valori.
Tra questi, ``present_date`` è preciso al numero di giorni del timestamp corrente e ``present_time`` è preciso al numero di secondi del timestamp corrente.

.. code-block:: python

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

La funzione ``reader.read()`` legge le informazioni sul nome, quindi crea un saluto.
Successivamente viene generato un dizionario ``attendance_statistics``, e ``name.rstrip()`` e ``present_time`` vengono memorizzati come chiavi e valori.

.. code-block:: python

    tts.say(greeting)

Pronuncia un saluto tramite l'altoparlante.

.. 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()]

Scrivi i dati di ``attendance_statistics`` nel file .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)

Fai scorrere questo saluto sul display.

**Immagine del Fenomeno**

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

