.. note::

    こんにちは、SunFounderのRaspberry Pi & Arduino & ESP32愛好家コミュニティへようこそ！Facebook上でRaspberry Pi、Arduino、ESP32についてもっと深く掘り下げ、他の愛好家と交流しましょう。

    **参加する理由は？**

    - **エキスパートサポート**：コミュニティやチームの助けを借りて、販売後の問題や技術的な課題を解決します。
    - **学び＆共有**：ヒントやチュートリアルを交換してスキルを向上させましょう。
    - **独占的なプレビュー**：新製品の発表や先行プレビューに早期アクセスしましょう。
    - **特別割引**：最新製品の独占割引をお楽しみください。
    - **祭りのプロモーションとギフト**：ギフトや祝日のプロモーションに参加しましょう。

    👉 私たちと一緒に探索し、創造する準備はできていますか？[|link_sf_facebook|]をクリックして今すぐ参加しましょう！

.. _4.1.19_py:

4.1.19 出席システム
================================

はじめに
---------------

シンプルな出席システムを作成しましょう。カードをスキャンすると、Raspberry Piは私たちの情報を記録し、csvファイルを生成します。

必要な部品
------------------------------

このプロジェクトには、以下のコンポーネントが必要です。

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

一式を購入するのが間違いなく便利です。以下はリンクです:

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

    *   - 名前
        - このキットのアイテム
        - リンク
    *   - Raphael Kit
        - 337
        - |link_Raphael_kit|

以下のリンクからそれぞれのアイテムを購入することもできます。

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

    *   - コンポーネントの紹介
        - 購入リンク

    *   - :ref:`cpn_gpio_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|

回路図
----------------------

============ ======== ======== ====
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

実験手順
-------------------------

.. note::

    実験を開始する前にSPIをオンにしてください。詳しくは :ref:`spi_configuration` を参照してください。
    
    :ref:`Luma.LED_Matrix` と :ref:`SpidevとMFRC522` のライブラリも必要です。

ステップ1: 回路を組む。

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

ステップ2: ``2.2.10_write.py`` ファイルを実行して、rfidカードの内容を変更します。

.. raw:: html

   <run></run>

.. code-block:: 

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

ステップ3: 名前を入力します（ここでは ``John`` を例にします）。「Enter」キーを押して確認し、カードをMFRC522モジュールに置き、"Data writing is complete" が表示されるのを待ち、カードを取り外します。または、別のカードにメッセージを書き直すか、 ``Ctrl+C`` で終了します。

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

ステップ4: コードのフォルダに移動して、実行します。

.. raw:: html

   <run></run>

.. code-block::

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

プログラムを起動した後、RFIDカードをMFRC522 RFIDモジュールに近づけると、Raspberry Piは挨拶の声を出してLEDマトリックスに表示します。

同じディレクトリに時間とリストを記録した ``.csv`` ファイルも見つけることができます。nanoコマンドでそれを開くと、今の記録を見ることができます。

.. raw:: html

   <run></run>

.. code-block::

    sudo nano attendance_sheet.2021.06.29.csv

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

**コード**

.. note::
    下記のコードを **修正/リセット/コピー/実行/停止** することができます。しかし、その前に ``raphael-kit/python`` のようなソースコードのパスに移動する必要があります。コードを修正した後、その効果を直接見るために実行することができます。


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

コード説明
-------------------

プログラムをよりよく理解するために、先に :ref:`1.1.6_py`, :ref:`2.2.10_py` および :ref:`3.1.4_py` を完了することをおすすめします。

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

``get_time()`` 関数を使用して、現在のタイムスタンプを取得し、2つの値を返します。
その中で、 ``present_date`` は現在のタイムスタンプの日数まで正確であり、 ``present_time`` は現在のタイムスタンプの秒数まで正確です。

.. code-block:: python

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

``reader.read()`` 関数は名前の情報を読み取り、次に挨拶を作成します。
その後、 ``attendance_statistics`` 辞書が生成され、 ``name.rstrip()`` および ``present_time`` がキーと値として保存されます。

.. code-block:: python

    tts.say(greeting)

スピーカーを通して挨拶を伝えます。

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

``attendance_statistics`` を .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)

この挨拶をスクロールして表示します。


現象の画像
-----------------------

.. image:: ../img/attend_system.JPG
    :align: center