はじめに
前回の記事では、2 台の Raspberry Pi Zero 2 W を使い、1 台を送信機としてキーボード信号を送信し、もう 1 台を受信機としてその信号を受け取り、PC のマウスカーソルを動かす方法を紹介しました。
今回は、さらに進化させて MQTT プロトコルを活用します。EMQX MQTT プラットフォーム上にブローカーを設定し、2 台の Raspberry Pi Zero 2 W を使って、1 台を送信機としてキーボード信号をインターネット経由で送信し、もう 1 台を受信機としてその信号を基に PC のマウスカーソルを操作します。前回は同じ LAN 内に両方の Raspberry Pi が必要でしたが、今回は異なるネットワークにあっても遠隔操作が可能になります。
関連記事
- 第0弾 Raspberry Pi OS をインストールする
- 第1弾 LAN経由でマウスを操作する
- 第2弾 USB キーボード信号の送受信とマウス操作
- 第3弾 MQTT を使用し、インターネット経由でマウスを遠隔操作
EMQX ブローカーのセットアップ手順
アカウント作成
まずは EMQX のウェブサイト(https://www.emqx.io/)にアクセスし、無料アカウントを作成します。
MQTT ブローカーの作成
アカウントを作成すると新規デプロイメント画面に遷移します。
Serverless タイプを選択し、リージョンAsia-Pacific
を選択。
デプロイメント名を入力後、今すぐ導入
を選択します。
約款の同意画面が表示されるので文章をスクロールすると読んで同意しました
のチェックボックスが表示されます。
チェックを入れると同意
ボタンがクリック可能になります。
同意
ボタンクリック後、別の同意画面が表示されるので同様にスクロール後、読んで同意しました
のチェックボックスにチェックを入れ、
今すぐに開始
を選択するとデプロイメントが開始され、MQTT ブローカーが作成されます。
ユーザーの作成
MQTT ブローカーの作成が完了したら、ユーザー を作成します。
サイドバーのアクセス制御
>認証
からユーザー作成画面を開き、追加
ボタンをクリックします。
ユーザー名
とパスワード
を入力し、確認
ボタンをクリックします。
これでユーザーが作成されます。
アクセス権限の付与
ユーザーを作成したら、アクセス権限を付与します。
今回の記事では送受信
サイドバーのアクセス制御
>アクセス承認
からアクセス承認画面を開き、追加
ボタンをクリックします。
- クライアント ID:アクセス権限を付与するユーザーを指定します。
- トピック:トピック名を入力します。今回は
keyboard/movement
と入力します。 - アクション:
Publish&Subscribe
(送受信)を選択します。権限の範囲を限定したい場合はPublish
(送信側)またはSubscribe
(受信側)を選択してください。 - 許可/拒否:
許可
を選択します。
確認ボタンを押すとアクセス権限の付与が完了します。
接続情報の確認
サイドバーの概要
をクリックし、ダッシュボードを表示します。
接続情報の接続先
をメモし、CA証明書
をダウンロードします。
Raspberry Pi にプログラムを実装
次に、2 台の Raspberry Pi Zero 2 W にプログラムを実装します。1 台を送信機、もう 1 台を受信機として使い、それぞれの役割を果たすためのコードを以下に示します。
このサンプルコードではCA証明書
を/home/pi
に配置しています。
またMQTT_BROKER
にはメモした接続先
を入力してください。
MQTT_USER
とMQTT_PASSWORD
にはユーザーの作成で設定したユーザー名をパスワードを入力してください。
CA 証明書の権限を確認・設定
CA 証明書の権限が正しいか確認し、必要に応じて設定します。
sudo chmod 644 /home/pi/emqxsl-ca.crt
送信機のプログラム
# mqtt-tx.py: キーボードのイベントをMQTTブローカーに送信するプログラム
import evdev
import paho.mqtt.client as mqtt
import json
# MQTTブローカーの設定
MQTT_BROKER = 'xxxx1234.ala.asia-southeast1.emqxsl.com'
MQTT_PORT = 8883
MQTT_TOPIC = 'keyboard/movement'
MQTT_USER = 'zero-1'
MQTT_PASSWORD = 'password'
MQTT_CAFILE = '/home/pi/emqxsl-ca.crt'
# MQTTクライアントの設定
client = mqtt.Client()
client.username_pw_set(MQTT_USER, MQTT_PASSWORD)
client.tls_set(MQTT_CAFILE, tls_version=mqtt.ssl.PROTOCOL_TLSv1_2)
client.connect(MQTT_BROKER, MQTT_PORT, 60)
# デバイスのevent番号を指定(キーボードのイベントデバイス)
device = evdev.InputDevice('/dev/input/event0')
# キーボードイベントの読み取りと送信
try:
for event in device.read_loop():
if event.type == evdev.ecodes.EV_KEY:
# データの送信 (JSON形式)
data = json.dumps({'type': event.type, 'code': event.code, 'value': event.value})
client.publish(MQTT_TOPIC, data)
print(f"Sent: {data}") # 送信したデータを表示
except Exception as e:
print(f"An error occurred: {e}")
finally:
client.disconnect()
受信機のプログラム
# mqtt-rx.py - MQTTメッセージを受信して、マウスの移動やクリックを行う
import paho.mqtt.client as mqtt
import json
import sys
import termios
import tty
# MQTTブローカーの設定
MQTT_BROKER = 'xxxx1234.ala.asia-southeast1.emqxsl.com'
MQTT_PORT = 8883
MQTT_TOPIC = 'keyboard/movement'
MQTT_USER = 'zero-2'
MQTT_PASSWORD = 'password'
MQTT_CAFILE = '/home/pi/emqxsl-ca.crt'
# HIDファイルのパス
MOUSE_DEV = "/dev/hidg0"
# 初期設定
movement_amount = 10
min_movement = 1
max_movement = 127
# MQTTメッセージのコールバック関数
def on_message(client, userdata, msg):
global movement_amount # ここでグローバル変数として宣言
try:
obj = json.loads(msg.payload)
if obj['type'] == 1: # EV_KEY
if obj['value'] in (1, 2): # キーが押された、または押し続けられている
if obj['code'] == 103: # 上方向キー
move_mouse(0, -movement_amount)
elif obj['code'] == 108: # 下方向キー
move_mouse(0, movement_amount)
elif obj['code'] == 105: # 左方向キー
move_mouse(-movement_amount, 0)
elif obj['code'] == 106: # 右方向キー
move_mouse(movement_amount, 0)
elif obj['code'] == 44: # Zキー
movement_amount = max(min_movement, movement_amount - 4)
elif obj['code'] == 45: # Xキー
movement_amount = min(max_movement, movement_amount + 4)
elif obj['code'] == 30: # Aキーで左クリック
move_mouse(0, 0, buttons=1)
elif obj['code'] == 31: # Sキーで右クリック
move_mouse(0, 0, buttons=2)
elif obj['code'] == 16: # Qキー
print("Q key pressed. Exiting...")
client.disconnect()
sys.exit()
elif obj['value'] == 0: # キーが離されたとき、クリックを解除
if obj['code'] in (30, 31): # AキーまたはSキー
move_mouse(0, 0, buttons=0)
print(f"Received: {obj}")
except json.JSONDecodeError:
pass
# マウスの移動やクリックを送信する関数
def move_mouse(dx, dy, buttons=0):
report = bytearray([buttons, dx & 0xFF, dy & 0xFF])
with open(MOUSE_DEV, "wb") as f:
f.write(report)
# MQTTクライアントの設定
client = mqtt.Client()
client.username_pw_set(MQTT_USER, MQTT_PASSWORD)
client.tls_set(MQTT_CAFILE, tls_version=mqtt.ssl.PROTOCOL_TLSv1_2)
client.on_message = on_message
# MQTTブローカーに接続し、トピックを購読
client.connect(MQTT_BROKER, MQTT_PORT, 60)
client.subscribe(MQTT_TOPIC)
try:
print("Waiting for MQTT messages...")
client.loop_forever()
except KeyboardInterrupt:
client.disconnect()
print("終了しました。")
結果の確認
送信側と受信側の両方の Raspberry Pi に paho-mqtt
をインストールします。
直接インストールする場合は以下のコマンドを使用します
sudo apt-get install python3-paho-mqtt
仮想環境を使用する場合は、次のコマンドでインストールします
pip3 install paho-mqtt
インストール後、送信側と受信側それぞれでプログラムを実行します。
sudo python3 mqtt-tx.py
sudo python3 mqtt-rx.py
送信側でキーボードの十字キーを押すと、その信号が受信側に送信され、Raspberry Pi に接続された PC のマウスが動作します。
アイゼック株式会社の IoT ソリューション
アイゼック株式会社では、Raspberry Pi を活用した IoT ソリューションの開発を積極的に進めています。今回のようなマウス操作の遠隔制御に限らず、さまざまな IoT デバイス間の通信技術を応用したシステム開発に取り組んでいます。ご興味がある方は、ぜひお問い合わせください。