Python の hid (hidapi) モジュールを理解する
Python には、(非公式な) hid あるいは hidapi モジュールが複数あって仕様が微妙に異なっているので使う人は困ってしまいます。
仕方がないので把握できる限りをまとめました。
pypi で配布されているパッケージが少なくとも3系統あります。
どれも libusb のサブプロジェクトである hidapi ライブラリを Python から使えるようにすることを意図している点は同じです。
import | pypi | github | debian | windows対応 | mac対応 |
---|---|---|---|---|---|
hid | hid | pyhidapi | - | △ | ▽ |
hid または hidraw | hidapi | cython-hidapi | python3-hid | ◯ | ◯ |
hidapi | hidapi-cffi | hidapi-cffi | python3-hidapi | △ | △ |
△=Windowsでは要hidapi.dll 、Macでは要hidapiシェアドライブラリ
▽=Macでhidapiシェアドライブラリをインストールするだけでは動きません。 libhidapi.dylib の名前で見えるようにする必要があります。
以下 github でのプロジェクト名で識別します。
これらのうち cython-hidapi では、Linuxプラットフォームの場合モジュールとして hid と hidraw の二つがインストールされます。
cython-hidapi の hid モジュールは、 libusb ベースの hidapi ライブラリを利用し、
cython-hidapi の hidraw モジュールは、 Linux の hidraw ドライバで動作する hidapi ライブラリを利用する点だけが違いです。
cython-hidapi を Windows にインストールした場合は hid.dll を利用する hidapi ライブラリの実装が hid モジュールにリンクされます。
Windows や Mac にインストールした場合 hidraw モジュールはありません。
pyhidapi と hidapi-cffi の場合は、 それぞれ libusb ベースと hidraw ベースの hidapi ライブラリのどちらでもシステムに存在する方を利用するようになっています。
ただ pyhidapi は libusb ベースの方を優先し、hidapi-cffi は hidraw の方を優先するようです。
Windows 環境では、hidapi.dll がロード出来る位置に存在していることを必要とします。
上で云う2種類の hidapi ライブラリは、以下の Debian パッケージに対応します。
libusb ベースの hidapi ライブラリ libhidapi-libusb0
hidraw ベースの hidapi ライブラリ libhidapi-hidraw0
2つのパッケージは、同じソースパッケージ(hidapi)からビルドされています。
それぞれのパッケージが異なるアーキテクチャに基づいているという意味で、
それぞれに存在意義がある、ということにはなっているようです。
improt | アーキテクチャ | pypi | github | debian |
---|---|---|---|---|
hid | ctypes ( cdll.LoadLibrary() ) | hid | pyhidapi | - |
hid または hidraw | Cython または cython3 | hidapi | cython-hidapi | python3-hid |
hidapi | cffi または python3-cffi | hidapi-cffi | hidapi-cffi | python3-hidapi |
さまざまに非互換な仕様
主要クラスのクラス名
improt | class | pypi | github | debian |
---|---|---|---|---|
hid | Device | hid | pyhidapi | - |
hid または hidraw | device | hidapi | cython-hidapi | python3-hid |
hidapi | Device | hidapi-cffi | hidapi-cffi | python3-hidapi |
デバイス列挙時の情報
improt | enumerate() | pypi | github | debian |
---|---|---|---|---|
hid | dict の list | hid | pyhidapi | - |
hid または hidraw | dict の list | hidapi | cython-hidapi | python3-hid |
hidapi | hidapi.DeviceInfo の list | hidapi-cffi | hidapi-cffi | python3-hidapi |
デバイスをオープンする操作
improt | open | pypi | github | debian |
---|---|---|---|---|
hid | dev = Device(vid=None, pid=None, serial=None, path=None) | hid | pyhidapi | - |
hid または hidraw | dev = device(); dev.open(int vendor_id=0, int product_id=0, unicode serial_number=None) | hidapi | cython-hidapi | python3-hid |
hidapi | dev = Device(info=None, path=None, vendor_id=None, product_id=None, serial_number=None, blocking=True) | hidapi-cffi | hidapi-cffi | python3-hidapi |
ノンブロッキングの指定方法
improt | nonblocking | pypi | github | debian |
---|---|---|---|---|
hid | dev.nonblocking = True | hid | pyhidapi | - |
hid または hidraw | dev.set_nonblocking(1) または dev.set_nonblocking(True) | hidapi | cython-hidapi | python3-hid |
hidapi | Device オープン時の引数で blocking=False を指定 | hidapi-cffi | hidapi-cffi | python3-hidapi |
send_feature_report() 周り
improt | report id | pypi | github | debian |
---|---|---|---|---|
hid | 先頭バイトで指定 | hid | pyhidapi | - |
hid または hidraw | 先頭バイトで指定 | hidapi | cython-hidapi | python3-hid |
hidapi | 引数で指定 (..., report_id=bytes(bytearray([0]))) | hidapi-cffi | hidapi-cffi | python3-hidapi |
get_feature_report() 周り
improt | 引数 | 返り値 | pypi | github | debian |
---|---|---|---|---|---|
hid | sizeにはレポートID分を加算して指定 | 先頭バイトはレポートID | hid | pyhidapi | - |
hid または hidraw | max_lengthにはレポートID分を加算して指定 | 先頭バイトはレポートID | hidapi | cython-hidapi | python3-hid |
hidapi | rebort_id=bytes(bytearray([0])) のように指定 , lengthにはレポートID分を含まない | 返り値はレポートIDを含まない | hidapi-cffi | hidapi-cffi | python3-hidapi |
エラー処理
improt | エラー処理 | pypi | github | debian |
---|---|---|---|---|
hid | 例外 HIDException | hid | pyhidapi | - |
hid または hidraw | 返り値 < 0 | hidapi | cython-hidapi | python3-hid |
hidapi | 例外 IOError | hidapi-cffi | hidapi-cffi | python3-hidapi |
データの取り扱い
各モジュールとも内部では bytes型 が利用されています。
※ Python2 では bytes型 は、str型 で代用されます。
呼び出し側のプログラムでは、簡単に、整数の配列で扱いたいかもしれません。
その場合、
data=bytes(bytearray(data)) と変換することで、
data に b'\x00\x01\x02\x03' が来ても [0,1,2,3] が来ても同じように扱える、
という工夫があるので、知っておくと便利です。
Python3 に限定するなら data=bytes(data) と書いても動きます。
逆に data が b'\x00\x01\x02\x03' でも [0,1,2,3] でも配列にしたい場合は、
data=list(bytearray(data)) と出来ます。
Python3 に限定するなら data=list(data) と書いても動きます。
古い環境の問題
Debian Buster 以前 あるいは Ubuntu focal (20.04LTS) 以前の環境では
最新の hid 1.0.5 はライブラリのロードに失敗します。
pip でインストールする時に python3 -mpip hid==1.0.4 とバージョンを指定するか
ライブラリについても新しいものをビルドしてインストールするか、いずれかが必要です。
Python2の場合
import | pypi | github | debian | Python2対応 |
---|---|---|---|---|
hid | hid | pyhidapi | - | ✕ |
hid または hidraw | hidapi | cython-hidapi | python-hid | ◯ ※注 |
hidapi | hidapi-cffi | hidapi-cffi | python-hidapi | ◯ |
✕=この問題のため get_feature_report() が機能しません。
__init__.py を hid.py としてローカルにコピーしパッチを当てれば使うことは出来ます。
※注=pip でインストールする場合には適切にバージョンを指定する必要があります。
例: python2 -mpip install hidapi==0.7.99.post21
放棄されたパッケージ
python -mpip install pyhidapi とした場合にインストールされるものは、
現状メンテナンスされておらず、少なくとも linux 環境では素直に動かないので注意が必要です。
※ /usr/local/lib/ にライブラリがインストールされている前提になっているようです
import | アーキテクチャ | pypi | github | origin | archive |
---|---|---|---|---|---|
pyhidapi | ctypes | pyhidapi | pyhidapi | pyhidapi | pyhidapi |
Discussion