Python + nfcpy + PaSoRi RC-S380 + launchdで、macにログイン後「FeliCaのIDmを通知センターへ出力する」処理を自動起動してみた

以前、Raspberry Pi 2 + PaSoRi RC-S380 + nfcpyにて、FeliCaを読み込んでみました。
Raspberry Pi 2 + PaSoRi RC-S380 + nfcpyにて、FeliCa読み取り時にPowerOffし、Slackへ通知してみた - メモ的な思考的な

そんな中、「RC-380はmacには対応していないけど、nfcpyを使えばmacFeliCaを読み込める」と知りました。

 
そこで、macにログイン後に "FeliCaIDmを通知センターへ出力する" 処理を自動起動してみたので、メモを残します。

 
目次

 

環境

  • mac
  • Python 3.9.5
    • anyenv + pyenv でインストール
  • nfcpy 1.0.3
  • PaSoRi RC-S380

 
なお、以前のRaspberry Pi 2 向けに作った環境・ソースコードを流用しているため、各種バージョンが古いです。

とはいえ、最新の各ライブラリの最新バージョンでも動作すると思います。

 
また、「launchdでPythonの仮想環境を有効化(activate)して実行する」方法が分からなかったため、今回はPython3.9.5の環境に直接 nfcpy まわりをインストールしています。

 

RC-S380で読んだFeliCaIDmを取得する

これはnfcpyの機能で実現できます。

なお、 usb:054c:06c3 という値は、nfcpyのドキュメント

For example, usb:054c:06c3 would open the first Sony RC-S380 reader while usb:054c would open the first Sony reader found on USB.

 
nfc.clf — nfcpy 1.0.4 documentation

にある通り、PaSoRi RC-S380のIDになります。

IDmを取得するソースコードはこちら。

# main.py
def on_connect(tag):
    idm = binascii.hexlify(tag._nfcid).decode('utf-8')

def main():
    with nfc.ContactlessFrontend('usb:054c:06c3') as cf:
        cf.connect(rdwr={'on-connect': on_connect})


if __name__ == "__main__":
    main()

 

通知センターへの出力

今回の最終形ではPythonスクリプトを自動実行します。

そこで、 print() で標準出力するのではなく、目に見えるような別の方法でログを出力したいと考えました。

調べてみたところ、macには通知センターという機能がありました。
Macで通知センターを使用する - Apple サポート (日本)

また、Pythonを使って通知センターへのメッセージ出力もできそうでした。
Macのデスクトップ通知をPythonから表示する #Python - Qiita

 
そこで、 notify 関数を用意し、メッセージとFeliCaIDmを出力するよう修正してみました。

# main.py
import binascii
import datetime
import os

import nfc


def notify(message):
    os.system(f"osascript -e 'display notification \"{datetime.datetime.now()} - {message}\"'")

def on_connect(tag):
    idm = binascii.hexlify(tag._nfcid).decode('utf-8')
    notify(f'FeliCa IDm: {idm}')

def main():
    notify('開始します')
    with nfc.ContactlessFrontend('usb:054c:06c3') as cf:
        cf.connect(rdwr={'on-connect': on_connect})
      
    notify('終わります')


if __name__ == "__main__":
    main()

 
このPythonスクリプトを実行後にFeliCaを読ませたころ、macの通知センターへと出力されました。

 

macのlaunchdを使って、mac起動後にFeliCaの読み込みを待機する

以前のRaspberry Pi 2では、systemd を使って起動後にFeliCaの読み込みを待機していました。

それと同じことができないか調べたところ、macの場合は launchd を使えば良さそうでした。

 
そこで今回は

という仕様で plist ファイルを作ってみます。

ちなみに、 plist ファイルの各設定については、以下のページが詳しいです。
A launchd Tutorial

 
今回は ~/Library/LaunchAgents/main_py.plist として、以下のファイルを作成しました。

なお、ファイル内の /Users/<Users>/path/to は、ログインユーザのディレクトリの下にある main.py ファイルが存在するディレクトリを指しています。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>NfcReader</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/<Users>/.anyenv/envs/pyenv/shims/python</string>
        <string>/Users/<Users>/path/to/main.py</string>
    </array>
    
    <key>KeepAlive</key>
    <true />

    <key>WorkingDirectory</key>
    <string>/Users/<Users>/path/to</string>
</dict>
</plist>

 
続いて、 plist ファイルをロードします。

% launchctl load ~/Library/LaunchAgents/main_py.plist

 
準備ができたので動作確認です。

macと接続したPaSoRi RC-S380の上にFeliCaを置き続けたところ、通知センターへ複数回通知されました。

 

資料:launchd の設定例