Felica RC-S330からIDmを取得する(値のリトルエンディアン化)

以前のエントリで、大須にある佐古前装備さんで購入したカードリーダーFelica RC-S330RaspberryPiから使用してみたという内容を書いていました。

f:id:ueponx:20211209234351j:plain

結論から言えば、RaspberryPiからはnfcpyの使用はできず、libpafeをインストールすれば、使用できるというような結果でした。

その後、pythonのユーザープログラムからIDmを取得してみたところ、IDmの値の並び(エンディアン)が異なっていました。そこでlibpafeを使用した場合でもnfcpytagtool.pyと同じIDmの値を取得する方法を調べてみました。

参考

uepon.hatenadiary.com

uepon.hatenadiary.com

状況の確認

まずは状況の確認になります。libpafeのインストールを行ったときに同時にインストールされるfelica_dumpというコマンドを実行してみると、交通系Felicaから多くの情報を取得することができます。すると以下の様な表示が行われます。

f:id:ueponx:20211230154158p:plain

そして、nfcpyをインストールしてtagtool.pyコマンドからIDmを取得すると以下の様な表示が行われます。(注)RaspberryPiから使用できないので、Ubuntuからの実行結果を表示しています。

f:id:ueponx:20211230154205p:plain

このときのIDmの値は同じようです。

ですが、以下のような自作のプログラムを作成し、IDmを取得してみると…

IDm.py

# -*- coding: utf-8 -*-

from __future__ import print_function
from ctypes import *

FELICA_POLLING_ANY = 0xffff

if __name__ == '__main__':

    libpafe = cdll.LoadLibrary("/usr/local/lib/libpafe.so")

    libpafe.pasori_open.restype = c_void_p
    pasori = libpafe.pasori_open()

    libpafe.pasori_init(pasori)

    libpafe.felica_polling.restype = c_void_p
    felica = libpafe.felica_polling(pasori, FELICA_POLLING_ANY, 0, 0)

    idm = c_ulonglong() #←16桁受けとる
    libpafe.felica_get_idm.restype = c_void_p
    libpafe.felica_get_idm(felica, byref(idm))

    # IDm16進表記
    print("%016X" % idm.value) #←16桁の16進数文字列の表示

    # READMEより、felica_polling()使用後はfree()を使う必要あり
    libpafe.free(felica)

    libpafe.pasori_close(pasori)

実行結果は以下のようになってしまします。

f:id:ueponx:20211230153102p:plain

tagtool.pyなどから取得されるIDm(自分の実験カード)では 0112から始まり8F06で終わる16桁の値になっているのですが、 自作プログラムで取得した値は 068Fから始まり1201で終わる16桁になっています。

つまり、エンディアン表記が異なっている状況になっています。メモリやバイナリファイルなどでは比較的エンディアンの違いに気をつけるようにはしていましたが、NFCも同じようにエンディアン気をつける必要があるとは思っていませんでした。

そこで以下の情報を参考にソースを変更することにしました。

参考 16進文字列のリトルエンディアン化変換

qiita.com

具体的な内容としては

  1. 16進数文字列を2桁のバイト配列として変換
  2. 変換後の配列の順序を反転
  3. 再度文字列化する

配列化まで行えれば反転はpythonでは容易な処理ですね。

IDm_le.py

# -*- coding: utf-8 -*-

from __future__ import print_function
from ctypes import *

FELICA_POLLING_ANY = 0xffff

if __name__ == '__main__':

    libpafe = cdll.LoadLibrary("/usr/local/lib/libpafe.so")

    libpafe.pasori_open.restype = c_void_p
    pasori = libpafe.pasori_open()

    libpafe.pasori_init(pasori)

    libpafe.felica_polling.restype = c_void_p
    felica = libpafe.felica_polling(pasori, FELICA_POLLING_ANY, 0, 0)

    idm = c_ulonglong() #←16桁を受けとる
    libpafe.felica_get_idm.restype = c_void_p
    libpafe.felica_get_idm(felica, byref(idm))

    # IDmは16進表記(リトルエンディアン化処理も行う)
    # print("%016X" % idm.value) #←16桁の16進数文字列化
    hex_be = "%016X" % idm.value
    bytes_be = bytes.fromhex(hex_be)
    bytes_le = bytes_be[::-1]
    idm_le = bytes_le.hex()
    print(idm_le)

    # READMEより、felica_polling()使用後はfree()を使う必要あり
    libpafe.free(felica)

    libpafe.pasori_close(pasori)

このプログラムを実行すると以下のようになります。

f:id:ueponx:20220118000742p:plain

これでtagtool.pyと同じ実行結果になりました。

おわりに

久々にエンディアンを気をつける必要のあるコードを書いたような気がします。 個人的にはそこはビックエンディアンにしておいてよという気持ちでいっぱいですが致し方ないですね。 これでpythonからも容易にIDmが取得できるようになったので、いろいろな自作の工作にも応用できそうです。

Windowsで接続済みの無線LANの接続パスワードを知る

昔購入した小型ルータを取り出して使ってみようと思ったのだけど、接続パスワードがわからず困っていました。ただ、以前接続済みのWindowsPCがあったことを思い出し、そこから接続パスワードを表示させて無事に接続ができました。

正直できなかったらルータ設定の初期化するかなと思っていましたが、今回はその手順をメモ。割と知っている方も多いと思いますが、よく忘れてしまいますので記録しておきます。

参考 support.microsoft.com

参考ページをみてもよくわからない感じというか操作が若干違うみたいです。

続きを読む

pythonでテキストデータから絵文字(emoji)を削除する

f:id:ueponx:20220107003357p:plain

年末に久しぶりに紅白歌合戦のツイートを取得してWordCloudのデータを作成してみようと思ったのですが、今まで使っていたPCを実家に持って行かなかったので以前のブログエントリを使って再構成していこうとしたのですが、pythonのライブラリ(モジュール)関係が少し変わっていたようでそのままでは動きませんでした。

参考

uepon.hatenadiary.com

uepon.hatenadiary.com

そのままで動作しない理由はemojiモジュールのバージョンアップにより動作が違っていたためでした。pip freezeと使用してrequirements.txtなどを作成しておけば旧バージョンをインストールできたのになあと思ってしまったのですが、さすがに2018年当時のライブラリをつかうのもどうかなと思って今回はソースを修正して対応することにしました。

状態の保持と一括インストール

# インストール済のライブラリ(モジュール)を保存
$ pip freeze > requirements.txt
# モジュールの状態を一括インストール
$ pip install -r requirements.txt

当時emojiモジュールを使用していたのはなぜかというとツイートに含まれる絵文字を削除するためでした。

以前は以下のような関数を作成して、絵文字の削除をしていました。絵文字集合に含まれるかをfor文で走査して絵文字を含まない文字列にしていました。

import emoji

def removeEmoji(src):
    return ''.join(c for c in src if c not in emoji.UNICODE_EMOJI)

今回は新しいemojiモジュールをインストールして、以下のようなコードに変更しました。今回は正規表現を使用して絵文字の判定を行い、絵文字の場合は空文字に変更して文字列にするという処理に変えました。下記のコードを実行すると絵文字以外のなんちゃってという部分のみが残る形になります。

import re
import emoji

emojiString = '😢🥺🤮🤣🤣🤣😆なんちゃって😅🙂😱😸🤔😛😾'
print(re.sub(emoji.get_emoji_regexp(), '', emojiString))

関数化するのであれば以下のようになります。

def removeEmoji(src):
    return re.sub(emoji.get_emoji_regexp(), '', src)

絵文字のコードは結構増えてきていることもあるので、モジュールに準備されている機能を純粋に使用するのがいいのかなと思いました。

emojiモジュールの使い方は以下が参考になると思います。

参考

qiita.com

おわりに

今回は3年前に作成していたエントリがそのままで動作しなかったので、新しいモジュールに対応させるべく修正を行ってみました。 Twitterの書き込みにも絵文字が増えたこともあり、絵文字を削除してデータ収集を行いましたが、逆にどんな絵文字が使われているのかを調べてみるのも面白いかなと思ったりもしました。

今年の紅白のWordCloudのデータは以下のようになっていましたが、今年は出演者の名前が大きくなっていたなあという印象がありますね。

f:id:ueponx:20220107002845p:plain

色々と興味深いテキストが取得できてよかったです。

SDカード書き込み不能状態からの復帰操作(結論:復帰できず)

Raspberry Piを使用していて突然起動できなくなるようなことはないでしょうか。昨年末、突然Raspberry Piが起動しなくなりリモートで使用していたこともあり、ネットワーク側が原因ではないかなと色々試していたのですが、最終的にHDMIでモニタを接続するとファイルシステム側の問題で起動できないというメッセージが表示されていました。SDメモリカード(以降SDカード)書き込み回数などが多すぎたというよりも、ふとしたきっかけでファイルシステムが壊れてしまったという印象です。

しかたないなあと思い、SDカードイメージファイルを再書き込みすることにしたのですが、/boot領域はアクセスできるにも関わらず、/(ルート)領域には全くアクセスできないというものでした。Windowsのディスクツールを使用しても全くアクセスできず、Ubuntuからのgpartなどからもアクセスはできないようです。

そんなことがあったので、なんとかして復帰させたかったので、いろいろ手をつくしてみました。結果はとしては全くだめでしたが、こういうことも書いておいたほうがいいのかなと思い今回のエントリーを書いています。

SDカードにはなにが起こったのか?

結論からいうとSDカードは書き込み禁止状態になっていました。マイクロSDメモリカードには書き込み禁止のスイッチがあるというわけでもないのですが、その状態と同じ状態です。ソフトウエア的に書き込み禁止状態になっているようです。なぜこの状態になったかがわかったかというとUbuntu側でCDドライブのような表示がされていたためです。

改めてWindowsにSDカードを認識させると、以下のようなダイアログ表示が行われています。ファイルシステムが壊れていいるような感じです。

f:id:ueponx:20211230153605p:plain

Raspberry Pi Imagerを使用するとSDカードは以下のように表示されています。WRITE PROTECTEDという表示がされています。

f:id:ueponx:20211230153540p:plain

これが原因のようです。もっとローレベルでの領域操作が必要になるので、Windowsディスク管理ツールを使用して領域の開放をしてみると、以下のようなエラーが発生します。

f:id:ueponx:20211230153608p:plain

続きを読む

RaspberryPi&nfcpyで動作しなかったPaSoRi RC-S330をUbuntu(x86)で動作するか確認する

以前のエントリで佐古前装備さんで購入したRaspberryPiに接続したPaSoRi RC-S330nfcpyPythonモジュール)で使用できないということを書いていました。

f:id:ueponx:20211209234351j:plain

ですが、公式ドキュメントでは対応していますという記載があり、それを見ながらRaspberryPiで設定にチャレンジしていました。

f:id:ueponx:20211231161355p:plain

うまく行かないけどそれは本能なのだろうかと思い、UbuntuをPCにインストールして検証してみました。

参考・過去エントリ

uepon.hatenadiary.com

参考・対応デバイス

nfcpy.readthedocs.io

続きを読む