はじめに (作ろうと思ったきっかけ)
大学のWebサービスのログインパスコードをブラウザで自動生成した結果、非常に長く覚えらづらいパスコードが出来てしまいました。(それ自体は良いこと。)
ところが、自分の端末で入力するときはブラウザによる自動入力があるのでいいものの、学内のパソコンでログインするとき、いちいち手打ちする必要がありました。
これがめちゃくちゃ面倒くさい。
てなわけで、自作キーボードの要領でパスコード自動入力機を作れないか構想していました。
Raspberry Pi Pico を選んだ理由
最初は自作キーボードといえばの、Pro Micro
を使おうかとも思いましたが、主にマイコンの値段が高いことなどを理由にやめました。
(それのためだけに使うのはコスパ的に見合わないという意味)
そこで目をつけたのが Raspberry Pi Pico
(以下、ラズパイピコ
) です。
ラズパイピコ自体は発売直後に手に入れていたのですが、使用用途が思いつかず、ずっと寝かしていました。
最近になり、ラズパイピコがHIDデバイス(ヒューマンインターフェースデバイス)として認識させることが出来ることを知りました。
すなわち、ラズパイピコをキーボードとしてパソコンに認識させることが出来るのです。
これは使うしか無い!!
と、思い製作を始めました。
実行環境の選定
ラズパイピコのプログラミングにどのファームウェア(言語)を用いるかについてです。
今回の候補となったファームウェアについてまとめたいと思います。
ファームウェア | 言語系 | メリット | デメリット |
---|---|---|---|
C/C++ | C/C++ | 高速かつ安定 | プログラミングが超面倒 |
MicroPython | Python | お手軽かつ公式で安心 | HIDのライブラリが無い |
CircuitPython | Python | お手軽でありながら発展的 | 公式環境ではない |
Arduino | C系 | Arduinoライブラリの資産を活かせる | 初期設定がちょい面倒 |
C/C++
まず、C/C++
について、プログラム記述方法が非常に複雑かつ面倒で、挫折してしまいました。
コンパイルするので高速かつ安定して動作するので良いのですが、今回は断念。
MicroPython
続いてMicroPython
について、当初は公式サポートのあるこの環境を用いようとしていました。
ところが、調べをすすめるうちにHIDのライブラリが無いことがわかり、やむなく使用を断念。
ただ、調査という意味でLチカやシリアル通信、ディスプレイ描画などのチュートリアルは行いました。
CircuitPython
そこで代替手段として発見したのが、CircuitPython
です。
軽く調べたところ、このCircuitPython
というのはAdafruit社がMicroPython
を発展させたものとのことです。
そして、こちらのCircuitPython
環境下であれば、HIDのライブラリがあります!
よって、今回はこの環境を採用です。
実環境調査
ラズパイピコが2台手元にあったので、以下の写真のようにブレッドボード上にならべて、MicroPython
とCircuitPython
の両方を試してみました。
Arduino
最後にArduino
環境についてですが、未だ情報が少ないことや、初期設定が少し手間だということから今回はパスしました。
それ以外にも、この間までM5Stackシリーズの製品をArduinoを使ってプログラミングしまくっていたため、ちょっと飽きたというのもあります(笑)。
これとか↓
これとかも↓
コード
では実際にコードを書いていきます。
パスコードは仮のものとしてABCDEfghij01234
としています。
まずは全体像から。
import usb_hid
from time import sleep
import digitalio
from board import *
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
keyboard = Keyboard(usb_hid.devices)
led = digitalio.DigitalInOut(GP25)
led.direction = digitalio.Direction.OUTPUT
#パスコード(例) : ABCDEfghij01234
pass_list = [4,5,6,7,8,9,10,11,12,13,39,30,31,32,33]
big_or_small = [1,1,1,1,1,0,0,0,0,0,0,0,0,0,0]
led.value = True
sleep(2.5)
led.value = False
for i in range(len(pass_list)):
if big_or_small[i]==1:
keyboard.press(225)
sleep(0.01)
keyboard.send(pass_list[i])
sleep(0.01)
keyboard.release(225)
led.value = True
sleep(5)
led.value = False
それでは、コードの説明をしていきます。
ライブラリ
導入したライブラリは全部で6つありますが、前半の4つと、後半の2つに分けられます。
前半の4つ
import usb_hid
from time import sleep
import digitalio
from board import *
これらはCircuitPython
の標準ライブラリです。上から順番に、
- USB経由でHID認識させるもの
- スリープ(待機)させるもの
- GPIOを制御するもの
- ボードの定義を参照するもの
です。特に設定等なく、記述するだけで利用できます。
後半の2つ
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
問題はこれらのライブラリについてです。
これらのライブラリは、ラズパイピコ内のライブラリ格納フォルダ(lib
という名前のフォルダ)に、ライブラリファイルをコピーしておかなければなりません。
CircuitPythonで利用可能なライブラリは、以下のサイトよりダウンロード出来ます。
CircuitPython Libraries
上の画像のように、adafruit-circuitpython-bundle-7.x-mpy-20220304
というzipファイルをダウンロードします。
(バージョンは問いません。)
フォルダを展開すると、まずはrequirements
フォルダを開いて、インポートしたいライブラリを探してください。
ライブラリのフォルダを開くと、requirements.txt
というテキストファイルがあります。
これを参考に、インポートすべきライブラリを確認します。
ひとつ上の階層に戻り、lib
フォルダを開き、インポートしたいライブラリを探します。
探したら、それをコピーした後、ラズパイピコ本体のlib
フォルダにペーストします。
今回の場合は、adafruit_hid
フォルダをそのままコピーすればオッケーです。
これで、ライブラリを利用できます。
定義
keyboard = Keyboard(usb_hid.devices)
led = digitalio.DigitalInOut(GP25)
led.direction = digitalio.Direction.OUTPUT
#パスコード(例) : ABCDEfghij01234
pass_list = [4,5,6,7,8,9,10,11,12,13,39,30,31,32,33]
big_or_small = [1,1,1,1,1,0,0,0,0,0,0,0,0,0,0]
キーボードとLEDの定義
1行目はキーボードの定義
3行目はLEDピンのピン番号の定義
4行目はLEDピンをアウトプットに定義
という流れです。
パスコードをキーコードに変換して変数に保存
adafruit_hid.keyboard.Keyboard Reference
↑のサイトにアクセスし、打ちたいパスコードの文字を1字ずつキーコードに変換していきます。
例えば最初の文字のA
を打ちたいとするならば、A = 4
の記述より、pass_list
の最初に4
を入れます。
ただし、このままだと通常のキーボードと同様に小文字が入力されます。
すなわち、Shiftキーを押して大文字を入力する必要があります。
そこで、big_or_small
という、大文字・小文字を判別するためのリストを用意し、大文字なら1
を、小文字なら0
を入れることとします。
メインタスク
led.value = True
sleep(2.5)
led.value = False
for i in range(len(pass_list)):
if big_or_small[i]==1:
keyboard.press(225)
sleep(0.01)
keyboard.send(pass_list[i])
sleep(0.01)
keyboard.release(225)
led.value = True
sleep(5)
led.value = False
プログラムの流れとしては、
- LEDを点灯する (キー操作準備体制の表示)
- 2.5秒待機 (ホスト側に認識してもらうための待機)
- LEDを消灯
- for文で全文字を入力する
- 大文字か小文字かの判定
- 大文字ならShiftキー押下(
keyboard.press(225)
) - リストよりキーコードを取り出し、キー送信
- Shiftキー押下を解除
- LEDを点灯し、実行終了を知らせる
- 5秒待機した後、消灯
といった感じです。
実行風景
ラズパイピコをHIDデバイス(キーボード)と認識させて、任意の文字列を打ち込むテスト pic.twitter.com/YbUPXdT0Yr
— Koushiro (@Koushiro_A) March 6, 2022
課題点
セキュリティ面が弱い
例えば誰かに無断で使われてしまった場合、モロにパスワードが流出します。
またCircuitPythonの場合、パソコンにストレージとしても認識されるため、ソースコードが丸見えです。
これらの点から、セキュリティ的にはあまりよろしくない状況です。
スタイリッシュじゃない
このパスワード打ち込みのためだけにラズパイピコをパソコンとMicroUSBケーブルを使ってつなげるというのは、正直スマートでは無いと感じます。
そもそも、今回のプロダクトにおいてGPIOピンは一切必要ないので、もっと小さくて良いのです。
解決策
そこで、こんな物を発見しました。
こちらは、Adafruit Trinkey QT2040 - RP2040 USB Key with Stemma QT というもので、Adafruit社が製作しているRP2040
搭載ボードです。
すなわち、今回のラズパイピコでの開発を、そのまま移植出来る(はず)なのです。
これなら、小型化でき、なおかつパソコンとの接続に必要なケーブルも要りません!
セキュリティ面についても解決策が出来たので、
次回、こちらのボードを使ってデバイスを完成させたいと思います。
参考サイト
Adafruit CircuitPython API Reference
Adafruit HID Library