LoginSignup
1
0

Ubuntu + Pasori RC-S380 で Suica を読み込むときのトラブルシュートメモ

Posted at

これはなに?

Ubuntu 22.04、SONY Pasori RC-S380、nfcpy を使用して Suica を読み込もうとしたときのトラブルシュートメモです。

いきなりソースコード

とりあえず、こんなコードを動かしてみました。よくあるやつなので、スルーしていただいて大丈夫です。

実行には nfcpy が必要です。Poetry等を使用して環境を作るか、あるいは pip を使用するかして、nfcpy をインストールしてください。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import itertools
import nfc
from struct import unpack
from datetime import date, time, datetime
import csv

reader_id = 'usb:054c:06c1'
service_code_purchase = 0x090f
service_code_history = 0x108f
eki_code = {}

# 駅コード読み込み
with open("ekicode.csv") as csvfile:
    reader = csv.DictReader(csvfile, fieldnames=[
                            'area', 'line', 'station', 'company_name', 'line_name', 'station_name'])
    for row in reader:
        area = int(row['area'], 16)
        line = int(row['line'], 16)
        station = int(row['station'], 16)

        if not area in eki_code:
            eki_code[area] = {}
        if not line in eki_code[area]:
            eki_code[area][line] = {}

        eki_code[area][line][station] = row['station_name']


def resolve_station_name(area_code, line_code, station_code):
    try:
        return eki_code[area_code][line_code][station_code]
    except KeyError:
        return '不明'


def read_blocks(tag, sc):
    for i in itertools.count():
        try:
            # 例外起きるまで読み出し
            bc = nfc.tag.tt3.BlockCode(i, service=0)
            yield tag.read_without_encryption([sc], [bc])
        except nfc.tag.tt3.Type3TagCommandError:
            break


def read_purchase(tag):
    """
    支払い履歴
    """
    print("### Reading purchase history.")

    sc = nfc.tag.tt3.ServiceCode(
        service_code_purchase >> 6, service_code_purchase & 0x1f)

    for data in read_blocks(tag, sc):
        # print("" . join(['%02x ' % s for s in data]))

        # 0 B 機種種別
        # 1 B 利用種別
        # 2 B 支払い種別
        # 3 B 入出場種別
        # 4 H 出場日付
        # 5 B 入場路線コード
        # 6 B 入場駅順コード
        # 7 B 出場路線コード
        # 8 B 出場駅順コード
        # 9 H 残額
        # 10 B 不明
        # 11 H 取引連番
        # 12 地域コード等
        be = unpack('>BBBBHBBBBHBHB', data)
        le = unpack('<BBBBHBBBBHBHB', data)

        # 鉄道のみ対応
        if not be[1] in {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x14}:
            next

        p_date = date((be[4] >> 9) + 2000, (be[4] >> 5) & 0xf, be[4] & 0x1f)
        p_dep_area_code = (be[12] >> 6) & 0x3
        p_arr_area_code = (be[12] >> 4) & 0x3

        dep_station_name = resolve_station_name(p_dep_area_code, be[5], be[6])
        arr_station_name = resolve_station_name(p_arr_area_code, be[7], be[8])

        print(p_date.strftime('%Y-%m-%d'),
              f'{dep_station_name} -> {arr_station_name} {le[9]}',
              f'{p_dep_area_code} {be[5]} {be[6]} -> {p_dep_area_code} {be[7]} {be[8]}')


def read_history(tag):
    """
    改札履歴
    """
    print("### Reading gate history.")

    sc = nfc.tag.tt3.ServiceCode(
        service_code_history >> 6, service_code_history & 0x1f)

    for data in read_blocks(tag, sc):
        # print("" . join(['%02x ' % s for s in data]))

        be = unpack('>BBBBHHBBHHBB', data)
        h_line_code = be[2]
        h_station_code = be[3]
        h_time = datetime((be[5] >> 9) + 2000, (be[5] >> 5) & 0xf,
                          be[5] & 0x1f, int(hex(be[6])[2:]), int(hex(be[7])[2:]), 0)

        print(h_time.strftime('%Y-%m-%dT%H:%M:%S'), h_station_code)


def connected(tag):
    print(tag)

    if not isinstance(tag, nfc.tag.tt3.Type3Tag):
        print("error: tag isn't Type3Tag")
        return

    read_purchase(tag)

    read_history(tag)


# 接続開始
clf = nfc.ContactlessFrontend(reader_id)
try:
    clf.connect(rdwr={'on-connect': connected})
finally:
    clf.close()

Pasori に Suica をかざすと、なにか出力されるはずです。

トラブルシュート

ここからが本題です。

NO SUCH DEVICE と言われる

プログラムの中で定義しているreader_id usb:054c:06c1 が間違っているのかもしれません。

lsusb コマンドで確認してください。

下記は、自分の環境の場合です。

% lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 046d:c52b Logitech, Inc. Unifying Receiver
Bus 001 Device 002: ID 17ef:6009 Lenovo ThinkPad Keyboard with TrackPoint
Bus 001 Device 007: ID 054c:06c1 Sony Corp. RC-S380/S
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

パーミッションがなさそう?

自分自身を plugdev グループへ追加し、ログインし直してください。

gpasswd -a `whoami` plugdev

Pasori を刺して、/dev/bus/usb の下にあるデバイスを確認してみてください。plugdev グループに読み書き権限があればOKです。

下記は、自分の環境の場合です。

% ls -l /dev/bus/usb/001/007
crw-rw----+ 1 root plugdev 189, 6  3月 13 13:02 007

/dev/bus/usb 配下の 001/007 は、lsusb コマンドで確認できます。

RESOURCE BUSY と言われる

デフォルトで読み込まれる port100 モジュールと衝突しているのかもしれません。

いったん Pasori を抜き、以下の内容のファイルを /etc/modprobe.d/blacklist-nfc.conf として作成してください。

# Conflict with nfcpy
blacklist port100

作成したら、Pasori を刺してください。

以下のコマンドを実行し、モジュールがロードされていないことがわかればOKです。

lsmod | grep port100

駅名が見つからない

どういう理屈かわかりませんが、出場駅が 0 0 0 となっていることがあります。

探求中です。

リンク集

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0