Raspberry Pi で メール送信(Gmailアカウント)

Gmailアカウントを使用してメールを送信しようと思ったのですが、ログイン処理の個所で次のようなエラーが発生していました。ログインできません。

Username and Password not accepted.

 

しばらく原因がわからなかったのですが、Gmailのセキュリティ設定を緩くすることで対応できることを確認しました。

今回はその方法ですが、セキュリティが甘くなる、ということを知ったうえで設定してください。

(先に、GmailGoogle)のアカウントは作成しておいてください)

 

 

1. Gmailにログイン、設定画面まで進む

  まずは、送信元となるGoogleアカウントでGmailへログインします。

f:id:kobatom5278:20210220105119j:plain

  管理画面まで進みます。右上の自分のアイコン(私の場合は「T」)をクリック、「Google アカウントを管理」をクリックします

f:id:kobatom5278:20210220105122j:plain

 

  管理画面が開いたら、「セキュリティ」をクリックします。

f:id:kobatom5278:20210220105135j:plain

 

  下へスクロールして、「安全性の低いアプリのアクセス」を探します。そして、「アクセスを有効にする(非推奨)」をクリック。

f:id:kobatom5278:20210220105149j:plain

 

  「安全性の低いアプリの許可」の右のトグルスイッチをクリックします。

f:id:kobatom5278:20210220105157j:plain

 

  「ON」の状態になったらOKです。

f:id:kobatom5278:20210220105205j:plain

 

  無意味ですが、元の画面に戻って設定を確認しましょう。

f:id:kobatom5278:20210220105212j:plain

 

  「オン」になっていることを確認します。非推奨なので、ビックリマークアイコンが出ているのかと思います。

f:id:kobatom5278:20210220105218j:plain

 

  注意点として、「セキュリティ」の中にある、「2段階認証プロセス」が「オン」になっていると、この設定項目が出ないようです。ですので、「2段階認証プロセス」も「オフ」になっている必要もあるようです。

f:id:kobatom5278:20210220105225j:plain

 

2. Pythonプログラミング

  前回の、添付ファイルを送付するプログラムの、GmailSMTPサーバーを変更したものです。

# -*- coding: utf-8 -*-
# 日本語コメントをエラーとしないように、UTF-8で保存

# 使用するライブラリのインポート
import smtplib
from email import encoders
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.utils import formatdate
from email.mime.base import MIMEBase

# 定数の定義
SELF_MAIL_ADDRESS = '*****@gmail.com'           # 自分のGmailのメールアドレス
SELF_MAIL_PASSWORD = '*****'                    # 自分のGmailのログインパスワード
SELF_SMTP_SERVER = 'smtp.gmail.com'             # GmailのメールアドレスのSMTPサーバー名
SELF_SMTP_PORT = 587                            # SMTPサーバーのポート番号

def create_mail(mail_subject, mail_body, mail_from, mail_to, attach_filename = None):
    """
    送信メールを生成、返却
    """

    # 添付ファイル名の指定有無により切り分け
    if attach_filename == None:
        # 添付ファイルを指定していない場合
        mail_message = MIMEText(mail_body)
    else:
        # 添付ファイルを指定した場合
        mail_message = MIMEMultipart()

        # 本文(添付ファイルより先に指定する必要がある)
        mail_message.attach(MIMEText(mail_body, "plain"))

        # 添付ファイルを読み込んで添付
        try:
            # 添付ファイル名が指定されている場合、ファイルを読み込む
            with open(attach_filename, 'rb') as attach_File:
                att = MIMEBase('application', 'octet-stream')
                att.set_payload(attach_File.read())
        except Exception as e:
            # 指定された添付ファイルが読み込めなかった場合は、ログを吐いて終了
            print(f'Error:{e}')
            exit(0)        

        # 添付ファイルをbase64エンコードして添付
        encoders.encode_base64(att)
        att.add_header('Content-Disposition', f'attachment; filename={attach_filename}')
        mail_message.attach(att)

    # 送信メールを編集
    mail_message['Subject'] = mail_subject              # 件名
    mail_message['From'] = mail_from                    # 送信元メールアドレス
    mail_message['To'] = mail_to                        # 送信先メールアドレス
    mail_message['Date'] = formatdate(localtime=True)   # 送信時間。OSのタイムゾーン依存
           
    # デバッグ用に送信メールの内容を出力
    print(mail_message)

    return mail_message

def send_mail(mail_message):
    """
    メールを送信する
    """

    try:
        smtp = smtplib.SMTP(SELF_SMTP_SERVER, SELF_SMTP_PORT)
        smtp.ehlo()
        smtp.starttls()
        smtp.ehlo()
        smtp.login(SELF_MAIL_ADDRESS, SELF_MAIL_PASSWORD)
    
        smtp.sendmail(SELF_MAIL_ADDRESS, mail_to, mail_message.as_string())
    except Exception as e:
        print(f'Error:{e}')
    finally:
        smtp.quit()


# 継承した場合など、実行されないようにする(現状、意味は特にない)
if __name__ == '__main__':
    # メールの内容
    # 送信先メールアドレス
    mail_to = '*****@*****'
    # メールの件名
    mail_subject = '件名テスト'
    # メールの本文
    mail_body = '本文テスト'
    # 添付ファイル名
    mail_att = 'penguin.jpg'

    # 送信メールを作成する(添付ファイル付き)
    mail_message = create_mail(mail_subject, mail_body, SELF_MAIL_ADDRESS, mail_to, mail_att)
    #  送信メールを作成する(添付ファイルなし)
    # mail_message = create_mail(mail_subject, mail_body, SELF_MAIL_ADDRESS, mail_to)

    # メールを送信する
    send_mail(mail_message)

Raspberry Pi で メール送信(添付ファイル指定可能版)

前回に引き続き、Rapsberry Pi にてPythonを使用してコーディング、メールを送信します。

今回は、添付ファイルの指定有無を選択できます。

オプショナルな引数に添付ファイル名を指定すれば添付できます。

これと人感センサー、カメラを組み合わせれば、

「人が通ったら写真を撮り、それを添付したメールを送信」

する、簡易的な監視カメラが作れます。

写真ではなく、動画でもできるでしょうが、ファイルサイズが大きいと制限がありますのでお気をつけて。

 

Pythonプログラミング

# -*- coding: utf-8 -*-
# 日本語コメントをエラーとしないように、UTF-8で保存

# 使用するライブラリのインポート
import smtplib
from email import encoders
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.utils import formatdate
from email.mime.base import MIMEBase

# 定数の定義
SELF_MAIL_ADDRESS = '****@*****'      # 自分のメールアドレス
SELF_MAIL_PASSWORD = '*****'          # 自分のメールサーバーへのパスワード
SELF_SMTP_SERVER = '******'           # 自分のメールアドレスのSMTPサーバー名
SELF_SMTP_PORT = 587                  # SMTPサーバーのポート番号

def create_mail(mail_subject, mail_body, mail_from, mail_to, attach_filename = None):
    """
    送信メールを生成、返却
    """

    # 添付ファイル名の指定有無により切り分け
    if attach_filename == None:
        # 添付ファイルを指定していない場合
        mail_message = MIMEText(mail_body)
    else:
        # 添付ファイルを指定した場合
        mail_message = MIMEMultipart()

        # 本文(添付ファイルより先に指定する必要がある)
        mail_message.attach(MIMEText(mail_body, "plain"))

        # 添付ファイルを読み込んで添付
        try:
            # 添付ファイル名が指定されている場合、ファイルを読み込む
            with open(attach_filename, 'rb') as attach_File:
                att = MIMEBase('application', 'octet-stream')
                att.set_payload(attach_File.read())
        except Exception as e:
            # 指定された添付ファイルが読み込めなかった場合は、ログを吐いて終了
            print(f'Error:{e}')
            exit(0)        

        # 添付ファイルをbase64エンコードして添付
        encoders.encode_base64(att)
        att.add_header('Content-Disposition', f'attachment; filename={attach_filename}')
        mail_message.attach(att)

    # 送信メールを編集
    mail_message['Subject'] = mail_subject              # 件名
    mail_message['From'] = mail_from                    # 送信元メールアドレス
    mail_message['To'] = mail_to                        # 送信先メールアドレス
    mail_message['Date'] = formatdate(localtime=True)   # 送信時間。OSのタイムゾーン依存
           
    # デバッグ用に送信メールの内容を出力
    print(mail_message)

    return mail_message

def send_mail(mail_message):
    """
    メールを送信する
    """

    try:
        smtp = smtplib.SMTP(SELF_SMTP_SERVER, SELF_SMTP_PORT)
        smtp.ehlo()
        smtp.starttls()
        smtp.ehlo()
        smtp.login(SELF_MAIL_ADDRESS, SELF_MAIL_PASSWORD)
    
        smtp.sendmail(SELF_MAIL_ADDRESS, mail_to, mail_message.as_string())
    except Exception as e:
        print(f'Error:{e}')
    finally:
        smtp.quit()


# 継承した場合など、実行されないようにする(現状、意味は特にない)
if __name__ == '__main__':
    # メールの内容
    # 送信先メールアドレス
    mail_to = '***@***'
    # メールの件名
    mail_subject = '件名テスト'
    # メールの本文
    mail_body = '本文テスト'
    # 添付ファイル名
    mail_att = '***.jpg'

    # 送信メールを作成する(添付ファイル付き)
    mail_message = create_mail(mail_subject, mail_body, SELF_MAIL_ADDRESS, mail_to, mail_att)
    #  送信メールを作成する(添付ファイルなし)
    # mail_message = create_mail(mail_subject, mail_body, SELF_MAIL_ADDRESS, mail_to)

    # メールを送信する
    send_mail(mail_message)

Raspberry Pi で メール送信

Rapberry Pi は、いわゆるIoT機器としての代表格です。

インターネットに簡単に接続できます。

 

ということは、Eメールを送れると、使い道が一気に広がります。

・人感センサーに何かが反応したら写真を撮影、メールに添付して送る

・温度センサーが異常な数値を示したらメールでお知らせ

・玄関に置いておいて、子供が帰ったらスイッチボタンを押すようにルールを決めたら、メールでお知らせ

 

今回は、ごくごく単純に、件名と本文だけのメールを送信する方法です。

画像ファイルの添付とか、あまり欲張らずに、テキストだけです。

 

なお、インターネットへの接続は必須です。

有線LAN、Wifiによる無線など、方法はなんでもOK。

 

 

1. メールアドレスの準備

  メールを送る先のメールアドレスはもちろんですが、その特性上、

  ・宛先メールアドレス

  ・送り元(要するに、自分)のメールアドレス

  ・送り元の送信メールサーバー(SMTPサーバー)

  が必要です。

  宛先はともかく、簡単にメールアドレスを取得できる方法としてGmailGoogle)が便利でしたが、いろいろとセキュリティ対策が取られるようになり、

  プログラムから送り元として使うのは難しくなりました。

  これらについては自前でSMTPサーバーを建てるなどの方法があると思いますが、今回はそこまでは立ち入りません。

2. Pythonプログラミング

  下記プログラム中の、

  ・自分のメールアドレス

  ・自分のメールサーバーへのパスワード

  ・自分のメールアドレスのSMTPサーバー名

  ・送信先メールアドレス

  ・件名、本文

  は、適宜書き換えてください。

  このままでは動きません。

 

# -*- coding: utf-8 -*-
# 日本語コメントをエラーとしないように、UTF-8で保存

# 使用するライブラリのインポート
import smtplib
from email.mime.text import MIMEText
from email.utils import formatdate

# 定数の定義
SELF_MAIL_ADDRESS = '*****@*****'   # 自分のメールアドレス
SELF_MAIL_PASSWORD = '*****'        # 自分のメールサーバーへのパスワード
SELF_SMTP_SERVER = '***.**.*.'      # 自分のメールアドレスのSMTPサーバー名
SELF_SMTP_PORT = 587                # SMTPサーバーのポート番号(おそらくは、このままでOK)

def create_mail(mail_subject, mail_from, mail_to):
    """
    送信メールを生成、返却
    """

    mail_message = MIMEText(mail_body)
    mail_message['Subject'] = mail_subject
    mail_message['From'] = mail_from
    mail_message['To'] = mail_to
    mail_message['Date'] = formatdate()

    # デバッグ用に送信メールの内容を出力
    print(mail_message)

    return mail_message

def send_mail(mail_message):
    """
    メールを送信する
    """
    smtp = smtplib.SMTP(SELF_SMTP_SERVER, SELF_SMTP_PORT)
    smtp.ehlo()
    smtp.starttls()
    smtp.ehlo()
    smtp.login(SELF_MAIL_ADDRESS, SELF_MAIL_PASSWORD)
    
    smtp.sendmail(SELF_MAIL_ADDRESS, mail_to, mail_message.as_string())
    smtp.close()


# 継承した場合など、実行されないようにする(現状、意味は特にない)
if __name__ == "__main__":
    # メールの内容
    # 送信先メールアドレス
    mail_to = "***@***"
    # メールの件名
    mail_subject = "件名テスト"
    # メールの本文
    mail_body = "本文テスト"

    # 送信メールを作成する
    mail_message = create_mail(mail_subject, SELF_MAIL_ADDRESS, mail_to)

    # メールを送信する
    send_mail(mail_message)

Raspberry Pi で スマホを使った勤怠管理2

前回の続きです。

仕様としては以下です。
Felicaをスキャンした際に、スキャンした日時とIDをログに出力する

・ログファイルの形式はTSV(データをタブで区切る)

・ログファイルは日ごとに別のファイルに出力、ファイル名は「年月日.tsv」とする

・当アプリケーションはtsvファイルを出力するまでで、その集計は、別途Excelなどで行う

・日ごとのスキャンした最小時間、最大時間をそれぞれ勤務開始時間、勤務終了時間として扱う

・日ごとにスキャンログを出力するため、日を跨いでの勤怠管理は対象としない

 

出力したログ(TSV)を読み込んだりするのは、Excelに詳しい方にお任せします。

 

お仕事部屋の入口において、入退出ごとにスキャンする運用にすれば、「仕事部屋にいて、仕事をしていたであろう時間の集計」にも使えます。

逆に、「仕事部屋にいない、サボっているかもしれない」時間の集計にも使えます。
(部屋にいれば仕事しているとみなすのは古臭いですよね)

 

Pythonプログラミング

# -*- coding: utf-8 -*-
# 日本語コメントをエラーとしないように、UTF-8で保存

# 使用するライブラリのインポート
import datetime
import os
from ctypes import *
from time import sleep

# 定数の定義
FELICA_POLLING_ANY = 0xffff
NONE_SCAN = '0000000000000000'
TSV_DIR = 'TSV'

# ライブラリの読込
libpafe = cdll.LoadLibrary("/usr/local/lib/libpafe.so")

def scan_felica():
    """
    felicaのスキャン
    """
    # 初期化
    libpafe.pasori_open.restype = c_void_p
    pasori = libpafe.pasori_open()
    libpafe.pasori_init(pasori)
    libpafe.felica_polling.restype = c_void_p
    idm = c_ulonglong()
    # 読込
    felica = libpafe.felica_polling(pasori, FELICA_POLLING_ANY, 0, 0)
    libpafe.felica_get_idm.restype = c_void_p
    libpafe.felica_get_idm(felica, byref(idm))
    # 16進表記で取得
    fericaData = "%016X" % idm.value
    # 後始末
    libpafe.free(felica)
    libpafe.pasori_close(pasori)
    # スキャン結果を返す
    return fericaData

# 継承した場合など、実行されないようにする(現状、意味は特にない)
if __name__ == "__main__":
    #TSV保存先フォルダの作成
    if os.path.exists(TSV_DIR) == False :
        os.mkdir(TSV_DIR)

    # 初期値を設定しておく
    felicaID_old = NONE_SCAN
    felicaID = NONE_SCAN

    while True:
        # felicaスキャンする
        felicaID = scan_felica()

        if felicaID == NONE_SCAN:
            # スキャンされていない
            if felicaID_old != NONE_SCAN:
                # カードを離した
                felicaID_old = NONE_SCAN
            else:
                # スキャンされていないのが続いている
                pass
        elif felicaID_old == felicaID:
            # 同じものがスキャンされ続けているので何もしない(カードを離してくれるのを待つ)
            pass
        else:
            # スキャンされた日時
            now = datetime.datetime.now()            
            # 日時とIDの表示(デバッグ用)
            scan_info = f'SCAN,{now.strftime("%Y/%m/%d %H:%M:%S")},{felicaID}'
            print(scan_info)

            # 日時とIDの出力ファイル名(ファイルは日ごとに増えていく)
            log_File = f'{TSV_DIR}/{now.strftime("%Y%m%d")}.tsv'
            # 出力内容
            tsv_line = f'{now.strftime("%Y/%m/%d %H:%M:%S")}\t{felicaID}'
            # 出力する
            with open(log_File, mode="a") as tsv_file:
                tsv_file.write(tsv_line + '\r\n')

            # スキャンされたIDの更新
            felicaID_old = felicaID
        
        sleep(1)

Raspberry Pi Pithon でカメラを操作2

前回は、Raspberry Pi に接続したカメラを使って、Pythonで「写真(静止画」を取る方法でしたが、今回は動画です。
前回同様、何も難しいことはしていません。

接続したカメラを操作するインスタンスを生成、動画撮影を開始、10秒後に撮影を終了するだけです。

動画エンコードはライブラリの中でやってくれているようですので、難しいことはほとんどありません。

なお、「picamera.Picamera()」の反応がない場合、カメラを接続するケーブルの接触不良が考えられます。リボンについているだけのカメラなので、つい動かしてしまいますが、それにより、ケーブルが微妙に外れることがあるようです。

Pythonプログラミング

  今回の仕様は、約10秒の動画を、カレントディレクトリの「caputure_video」フォルダに、「撮影開始時間.h264」ファイルとして保存する、です。

  ソースコードを少し修正しました。

  録画が終わったのち、PiCameraインスタンスに対してcloseするようにしてあります。

# -*- coding: utf-8 -*-
# 日本語コメントをエラーとしないように、UTF-8で保存

# 使用するライブラリのインポート
import os
import picamera
import datetime
from time import sleep

# 定数
CAPTURE_DIR = 'capture_video'     # 撮像動画を格納するフォルダ

# 継承した場合など、実行されないようにする(現状、意味は特にない)
if __name__ == "__main__":
    # 撮影した動画を格納するフォルダを作成(存在しない場合)
    if os.path.exists(CAPTURE_DIR) == False :
        os.mkdir(CAPTURE_DIR)
    
    # PiCameraインスタンスを生成
    with picamera.PiCamera() as camera:
        # ファイル名は、「年月日時分秒.h264」とする
        now = datetime.datetime.now()
        camera.start_recording(f'{CAPTURE_DIR}/{now.strftime("%Y%m%d_%H%M%S")}.h264')        

        # 10秒録画する
        camera.wait_recording(10)    

        # 録画終了
        camera.stop_recording()   
   
    print('finished')

Raspberry Pi Pithon でカメラを操作1

Raspberry Pi にカメラを接続、ちょっとプログラムを組んであげると、カメラで撮影したりできます。

今回は、カメラを接続して、「python-picamera」ライブラリを使用して写真撮影をしてみようと思います。

 

 

1. カメラの購入

  ともあれ、対応したカメラを購入します。

  よくある、セットに付属のカメラでも問題ないと思います。

  リボンでつながっているだけなので、こだわる方はカメラのケースも購入されるといいと思います。


 


 

 

2. Raspberry Pi OS の設定

  接続はリボンでつなぐだけなので難しくないと思います。

  電源は切った状態で行いましょう。

  設定方法などは以前の記事で紹介していますので、よろしければどうぞ。

letraspberry.hatenablog.com

  

3. ライブラリのインストール

  ここからが今回の新しい内容です。

  Pythonからカメラをコントロールする方法はいくつかあるようですが、今回は本家の公式ドキュメントを参考にしています。

  使用しているRaspberry Pi OS の状態によっては、すでにインストールされているかもしれません。

 

  まず、以下のコマンドを実行します。LXTerminalで行います。

  なお、上2行は、こういうタイミング以外でも、定期的に行ったほうが良いと思います。

  たまにしか行わないと時間がかかります。

  システムを最新に保ち、セキュリティ対策された、バグなどが少ない状態にしてくれるはずです。

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install python-picamera

 

4. Pythonプログラミング

  今回は、カレントディレクトリに「capture」というフォルダを作成、その中に1秒ぐらい間隔で「年月日_時分秒.jpg」というファイル名でカメラで撮影した画像を保存します。10回。

  なお、「1秒ぐらい間隔」というのは、「撮影しろ」という命令の完了に時間を要するため、自分の状態では2秒間隔で撮影されています。

  ソースコードを修正しました。

  一度生成したPiCameraインスタンスを使いまわしていたのですが、繰り返し動かすうちにPiCameraインスタンスが作れなくなった、などのトラブルがあったためです。

 

 

# -*- coding: utf-8 -*-
# 日本語コメントをエラーとしないように、UTF-8で保存

# 使用するライブラリのインポート
import os
import picamera
import datetime
from time import sleep

# 定数
CAPTURE_DIR = 'capture'     # 撮影画像を格納するフォルダ

# 継承した場合など、実行されないようにする(現状、意味は特にない)
if __name__ == "__main__":
    # 撮影した画像を格納するフォルダを作成(存在しない場合)
    if os.path.exists(CAPTURE_DIR) == False :
        os.mkdir(CAPTURE_DIR)

    # PiCameraインスタンスを生成
    with picamera.PiCamera() as camera:
        for i in range(0, 10):
            # 1秒ごとに写真を撮る(10回)

            # ファイル名は、「年月日時分秒.jpg」とする
            now = datetime.datetime.now()

            # キャプチャしてファイル保存
            camera.capture(f'{CAPTURE_DIR}/{now.strftime("%Y%m%d_%H%M%S")}.jpg')

            sleep(1)

    print('finished')

Raspberry Pi で スマホを使った勤怠管理1

大抵のスマホに標準装備な「felica」いわゆるオサイフケータイですね。

今回は、非接触ICカードリーダ(ライタ)を使用して、このfelicaをスキャン、日時とIDを取得してみます。

この「非接触カードリーダ(ライタ)」ですが、SONY製で、この時期(年度末)によく売れているようです。

理由は確定申告。「マイナンバーカード」を持っていれば、PCを使ってWEBで入力、マイナンバーカードをスキャンすることで確定申告が完了するのですが、この「スキャンする」際に使用します。

 

 

1. 機器の購入

  自分は引き出しに眠っていた古い機種を使用します。(RC-310Sという機種)

  いろいろな機種が発売されていますが、今回の目的であればどれでも使用できると思います。(試していませんので、断言できませんが)


 


 

 

2. 接続

  USB(Type-A)で差すだけ。
  Raspberry Pi Zero を使用している場合は変換が必要です。

 


 

 

3. ライブラリのインストール

  以前の記事で、その内容を紹介しています。

 

letraspberry.hatenablog.com

 

4. Pythonプログラミング

  基本的に、ライブラリインストール時のものと変わりません。

  変更したのは以下の仕様。

  ・定期的(約1秒毎)にスキャンしてみる

  ・スキャンできたら、その日時とIDを表示

  ・リーダにずっとかざしたままの状態ではスキャンしたとみなさない(一度話して、何もスキャンされていない状態にしないと、スキャンしたとみなさない)

  

  スキャンログとして、スキャンした(されていない)結果も表示しています。

  次回は、この内容を外部にファイル出力(CSV形式を想定)してみようと思います。

  Excelあたりでこのファイルを読込み、IDと氏名を紐づけして勤怠管理(出社、退社)をしてみようかと思います。

 

# -*- coding: utf-8 -*-
# 日本語コメントをエラーとしないように、UTF-8で保存

# 使用するライブラリのインポート
import datetime
from ctypes import *
from time import sleep

# 定数の定義
FELICA_POLLING_ANY = 0xffff
NONE_SCAN = '0000000000000000'

# ライブラリの読込
libpafe = cdll.LoadLibrary("/usr/local/lib/libpafe.so")

def scan_felica():
    """
    felicaのスキャン
    """
    # 初期化
    libpafe.pasori_open.restype = c_void_p
    pasori = libpafe.pasori_open()
    libpafe.pasori_init(pasori)
    libpafe.felica_polling.restype = c_void_p
    idm = c_ulonglong()
    # 読込
    felica = libpafe.felica_polling(pasori, FELICA_POLLING_ANY, 0, 0)
    libpafe.felica_get_idm.restype = c_void_p
    libpafe.felica_get_idm(felica, byref(idm))
    # 16進表記で取得
    fericaData = "%016X" % idm.value
    # 後始末
    libpafe.free(felica)
    libpafe.pasori_close(pasori)
    # スキャン結果を返す
    return fericaData

felicaID_old = NONE_SCAN
felicaID = NONE_SCAN

while True:
    # デバッグ用ログ
    print(f'{felicaID}, {felicaID_old}')
    # felicaスキャンする
    felicaID = scan_felica()

    if felicaID == NONE_SCAN:
        # スキャンされていない
        if felicaID_old != NONE_SCAN:
            # カードを離した
            felicaID_old = NONE_SCAN
            # 終わってしまえ
            # exit(0)
        else:
            # スキャンされていないのが続いている
            pass
    elif felicaID_old == felicaID:
        # 同じものがスキャンされ続けているので何もしない(カードを離してくれるのを待つ)
        pass
    else:
        # スキャンされた
        now = datetime.datetime.now()
        # 日時とIDの表示
        scan_info = f'SCAN,{now.strftime("%Y/%m/%d %H:%M:%S")},{felicaID}'
        print(scan_info)
        # 日時とIDのログ出力
        with open('log.txt', mode="a") as logfile:
            logfile.write(scan_info + '\r\n')
        # スキャンされたIDの更新
        felicaID_old = felicaID
    
    sleep(1)