こんにちは。ポン吉です。
妻が女神転生5に超ハマっているようで、深夜に永遠と香集めマラソン(ひたすらアイテムを拾い集める苦行)を実施して寝不足とのこと。
心を無にして不毛な時間を費やしているご様子。こりゃいかん。ゲーマー生産性向上?を図るべく自動化しようと思います。
うちは家族全員ゲーム大好き一家です!
調べたところ、ArduinoによるNintendo Switch自動化が主流のようです。
ラズパイでも「joycontrol-pluginloader」を使えば追加機器は一切不要で自動化が可能です。joycontrol 用プラグインローダの開発者Almtrさんありがとうございます!
ラズパイ & Nintendo Switchを持っているそこのアナタ!既に必要なものはすべて揃っています。
こちらの記事を読めば誰でもNintendo Switchの操作を自動化できるようになります。
今回のテーマはこちら!
- Raspberry PiだけでNintendo Switchの操作を自動化してみる
- 「レベル上げ、レアアイテム集め」といった不毛な単純作業を人類から解放する!
- どこまで自動化できるのか?実用性を評価! ※【次回記事にて詳細化】
ラズパイに導入する上でうまく動かずかなり悩んだポイントが多かったです。誰でも動かせる手順をまとめて公開したいと思います。
それではやってみましょう~♪
Nintendo Switch自動化に必要なもの
Nintendo Switch本体とラズパイがあればOK!
ラズパイ自体も品薄で購入が難しい状況が続いています。ラズパイの在庫と価格をリアルタイム確認できるページを作りました。ラズパイを購入しようとしている方は是非参考にしてみてください。
Raspberry Pi OS への joycontrol-pluginloader インストール
注意
最新Raspberry Pi OS bullseye での構築例を紹介します。以前のRaspberry Pi OS buster等では python ⇒ python3 pip ⇒ pip3 と読み替えて実行してください。
ラズパイ初期セットアップの詳細は、上記記事を参照してください。
ラズパイ自体も品薄で購入が難しい状況が続いています。ラズパイの在庫と価格をリアルタイム確認できるページを作りました。ラズパイを購入しようとしている方は是非参考にしてみてください。
必要パッケージをインストール
sudo apt update
sudo apt install -y python3-pip
sudo apt install -y git
sudo apt install -y python3-dbus
sudo apt install -y libhidapi-hidraw0
sudo apt install -y libbluetooth-dev
sudo apt install -y bluez
Rasbperry Pi OSの初期インストール状態から、上記コマンド実行で必要パッケージはすべてインストールできると思います。
joycontrol / joycontrol-pluginloaderをインストール
cd ~/
git clone https://github.com/mart1nro/joycontrol.git
sudo pip install joycontrol/
git clone --recursive https://github.com/Almtr/joycontrol-pluginloader.git
sudo pip install joycontrol-pluginloader/
git cloneで持ってきてpipでインストール。必要なpythonパッケージも一緒にインストールされます。
Raspberry Pi 内蔵BluetoothのMACアドレスを変更
以下、GitHubのissues情報によるとNintendo Switchコントローラ関連機器は「94:58:CB:」から始まるMACアドレスにする必要があるようです。また、相性問題があり動かないBluetooth機器もある模様。ちなみにラズパイ3,4の内蔵Bluetoothは動作OK。
外付けUSBのBluetoothだと記事にあるようなbccmdコマンド等で変更できるのですが、ラズパイの内蔵Bluetoothの場合はエラーになります。試行錯誤した結果、以下のhcitoolコマンドで無事変更することができました。
# 事前にBluetoothのMACアドレスをチェックしておく(デバイス名 hciX を確認)
hciconfig
# BluetoothのMACアドレスをNintendo Switchが認識するアドレス帯に変更
sudo hcitool -i hci0 cmd 0x04 0x009
sudo hcitool -i hci0 cmd 0x3f 0x001 0x56 0x34 0x12 0xCB 0x58 0x94
sudo systemctl restart bluetooth.service
# BluetoothのMACアドレスが変わったかチェック(UP RUNNINGになるのに少し待つかも)
hciconfig
注意
BluetoothのMACアドレス変更についてはラズパイを再起動すると元に戻ってしまうので注意。再起動時にシェル等で再度実行するようにした方がよいと思います。
Bluetooth設定を変更
# ファイル編集できればどんなコマンドでもOK
sudo vi /lib/systemd/system/bluetooth.service
/lib/systemd/system/bluetooth.serviceのファイルで、ExecStart=の行について赤字部分のオプションを指定するように変更。更新後にBuletoothサービス再起動します。
: 中略
[Service]
Type=dbus
BusName=org.bluez
ExecStart=/usr/libexec/bluetooth/bluetoothd -C -P sap,input,avrcp
: 中略
# bluetoothサービスの設定変更を再読み込みさせて再起動
sudo systemctl daemon-reload
sudo systemctl restart bluetooth.service
サービス再起動後bluetooth.serviceがエラーメッセージが出力していますが、動作に支障はないので先に進みます。
Nintendo Switchとのペアリング
ここがタイミング依存が絡む?のか難関なポイントとなります。以下の順番に従いペアリングを実行してみましょう。
ペアリング実行順番
- joycontrol-pluginloaderでペアリング用のpythonプログラムを実行
- Nintendo Switch側で [設定] ⇒ [コントローラとセンサー] ⇒ [コントローラの持ち方/順番を変える] を選択
- しばらくするとペアリング成功 ※ここで無応答になる事が多い
それでは順番にやっていきましょう。
cd joycontrol-pluginloader/
sudo joycontrol-pluginloader plugins/tests/PairingController.py
[21:52:34] joycontrol.device set_name::69 INFO - setting device name to Pro Controller…
[21:52:34] joycontrol.server create_hid_server::83 INFO - Advertising the Bluetooth SDP record…
[21:52:34] joycontrol.device set_class::61 INFO - setting device class to 0x002508…
[21:52:34] joycontrol.server create_hid_server::96 INFO - Waiting for Switch to connect… Please open the "Change Grip/Order" menu.
上記、コマンド実行後に Waiting for Switch to connect… と接続待ち状態になります。次にNinotendo Switch側の操作に移ります。
しばらくするとプログラムの標準出力が動き出しペアリングを実行。ペアリング成功後は自動的に切断されます。1分ほど待っても動きがない場合は下記をお試しください。
うまくいかない場合の手順
- pythonプログラムをCTRL+Cで終了させる
- Nintendo Switch側もコントローラ接続して待ち画面を終了させる
- Raspberry Piで bluetoothctlコマンドを実行してペアリング情報を確認
- 何故か登録済となっているNintendo Switchペアリング情報を削除
- 再度、ペアリング処理を実行して成功するまで繰り返す
bluetoothのペアリング情報の確認と削除については、下記実行例を参考にしてください。赤字部分はお持ちのNintendo Switch側のMACアドレスになりますので、remove時には適切置き換えて実行してください。
>_ command
bluetoothctl
[bluetooth]# paired-devices
Device XX:XX:XX:XX:XX:XX Nintendo Switch
[Nintendo Switch]# remove XX:XX:XX:XX:XX:XX
Device has been removed
[bluetooth]# (CTRL+Cで終了)
ペアリング済みのステータスにはなっているのですが、接続と切断を繰り返している挙動になっていることがありました。
なーんか上手くいかないなぁ!イライラ
焦らずリトライすればペアリングできるので頑張って!
joycontrol-pluginloader の動かし方
Bluetoothのペアリングが出来ればあとは動かすだけ!ボタン入力テストを実施しサンプルプログラムを動かします。
Nintendo Switch のボタン入力テスト
Nintendo Switch側で [設定] ⇒ [コントローラとセンサー] ⇒ [入力デバイスの動作チェック] [ボタンの動作チェック] を選択
ここで使っていたNintendo Switchのコントローラの電源をOFFにする必要があります。OFFにしないと各種自動化のプログラムは動かないので注意。
コントローラの内側側面に「押しにくい小さな黒いボタン」があります。このボタンを押すとコントローラの電源ON/OFFができます。LEDの点灯/無点灯でON/OFFを確認しましょう。
>_ command
cd ~/joycontrol-pluginloader/
sudo joycontrol-pluginloader -r XX:XX:XX:XX:XX:XX plugins/tests/TestControllerButtons.py
無事にコマンドが入力されれば、ラズパイからNintendo Switchの制御が可能な状態となりました!
サンプルプログラムの実行方法
サンプルプログラムは「~/joycontrol-pluginloader/plugins/samples」ディレクトリに入っています。左コントローラの「a」を押して「下▼」を押すだけのサンプルです。
>_ command
cd ~/joycontrol-pluginloader/
sudo joycontrol-pluginloader -r XX:XX:XX:XX:XX:XX plugins/samples/SamplePlugin.py
プログラム実行前に、コントローラの電源が切れていることを確認しましょう(よく忘れがち)
import logging
from JoycontrolPlugin import JoycontrolPlugin
logger = logging.getLogger(__name__)
class SamplePlugin(JoycontrolPlugin):
async def run(self):
logger.info('This is sample joycontrol plugin!')
logger.info(f'Plugin Options: {self.options}')
logger.info('Push the A Button')
await self.button_push('a')
await self.wait(0.3)
logger.info('Tilt the left stick down')
await self.left_stick('down')
await self.wait(0.3)
このpythonソースをベースにしてコマンド入力やスリープを組み合わせて処理を作ることになります。
SamplePlugin.pyをpenguin.pyという名前でコピーして・・
あれ動かないぞ!ムキー!!
pythonのクラス名をコピー後のファイル名に
変更する必要があるので注意。(サンプルの6行目)
コマンドリスト
ボタンを押す動作については以下のようにプログラムを記載します。
await self.button_push('a') # Aボタンを押す(押してすぐ離す操作)
await self.wait(0.3) # 0.3秒待つ
await self.button_press('up') # 上ボタンを押しっぱなしにする
await self.wait(5.0) # 5.0秒待つ(5秒上ボタンを押しっぱなし)
await self.button_release('up') # 押しっぱなしにしていた上ボタンを離す
await self.wait(0.3) # 0.3秒待つ
await self.button_push('a', 'b') # AボタンとBボタンを同時に押す(複数のボタンを指定可能)
await self.wait(0.3) # 0.3秒待つ
Nintendo Switchのボタンとプログラムで指定するキーを一覧にしてみました。
左コントローラ
Nintendo Switch コントローラボタン名 | Pythonプログラムで指定するボタン名 |
上ボタン | up |
下ボタン | down |
右ボタン | right |
左ボタン | left |
Lボタン | l |
ZLボタン | zl |
◎(左アナログスティックを押し込んだ時) | l_stick |
ー(マイナス) | minus |
右コントローラ
Nintendo Switch コントローラボタン名 | Pythonプログラムで指定するボタン名 |
Aボタン | a |
Bボタン | b |
Xボタン | x |
Yボタン | y |
Rボタン | r |
ZRボタン | zr |
◎(左アナログスティックを押し込んだ時) | r_stick |
ー(マイナス) | plus |
左右のアナログスティックは次のように使います。
# 方向を直接指定(up, down, right, left, centerから指定)
await self.right_stick('up')
# 角度を指定
angle=90
self.right_stick(angle=angle)
# 角度とパワーを指定
angle=90
power = self.max_stick_power / 2 # 最大値の半分のパワー
self.right_stick(angle=angle, power=power)
# 左アナログスティックはrightをleftに変えたものを指定
await self.left_stick('up')
どこまでNintendo Switchを自動化できるのか?実用性を検証
長くなったので細かい検証は別ページにて記載予定。大まかな評価だけ記載します。
コマンドが遅延したり抜け落ちたりする場合あり
いろいろと動かしてテストしていくとわかるのですが遅延や抜け等がまれに発生します。あまりシビアな操作を必要としない、RPG等が自動化対象になるかなと思います。
まとめ
- 特別なハードも不要でNintendo Switchの制御が可能
- Bluetooth通信にやや不安定な部分があり、コントロール操作に遅延が出る点はマイナス
- 家族の無駄ゲーム時間の削減は大いに期待できる!!(スクリプト作るのも大いに時間かかるけどね)
ペアリング部分は何度かリトライする前提でがんばろう~
おまけ
真女神転生5で香集めマラソンを完全自動化し、寝ている間にがっつりドーピングしたアモンさんを紹介。全ステータス999!メギドフレイムですべて焼き尽くせます(笑)宝石交換もクイーンメイブさんの場所まで移動し、全ての宝石交換まで完全自動化済みです。
Switch自動化はこれから
今回はサンプルプログラム実行までになりますが、将来的にNintendo Switchのあらゆるゲームに適用可能な自動化スクリプトとして整備していきましょう。自動化スクリプト実装ではBluetooth故の不安定挙動があるため、ややコツがいるのですが別記事で投稿予定です。