post-cover

2024-09-09 技術ブログ

MQTT を使用し、インターネット経由でマウスを遠隔操作| Raspberry Pi Zero 2 W を USB マウスに変える(記事第 3 弾)

はじめに

前回の記事では、2 台の Raspberry Pi Zero 2 W を使い、1 台を送信機としてキーボード信号を送信し、もう 1 台を受信機としてその信号を受け取り、PC のマウスカーソルを動かす方法を紹介しました。

今回は、さらに進化させて MQTT プロトコルを活用します。EMQX MQTT プラットフォーム上にブローカーを設定し、2 台の Raspberry Pi Zero 2 W を使って、1 台を送信機としてキーボード信号をインターネット経由で送信し、もう 1 台を受信機としてその信号を基に PC のマウスカーソルを操作します。前回は同じ LAN 内に両方の Raspberry Pi が必要でしたが、今回は異なるネットワークにあっても遠隔操作が可能になります。

関連記事

EMQX ブローカーのセットアップ手順

アカウント作成

まずは EMQX のウェブサイト(https://www.emqx.io/)にアクセスし、無料アカウントを作成します。

raspberry-pi-usb-hid-pi-03-emqx-001

raspberry-pi-usb-hid-pi-03-emqx-002

MQTT ブローカーの作成

アカウントを作成すると新規デプロイメント画面に遷移します。

Serverless タイプを選択し、リージョンAsia-Pacificを選択。

raspberry-pi-usb-hid-pi-03-emqx-003

デプロイメント名を入力後、今すぐ導入を選択します。

raspberry-pi-usb-hid-pi-03-emqx-004

約款の同意画面が表示されるので文章をスクロールすると読んで同意しましたのチェックボックスが表示されます。

チェックを入れると同意ボタンがクリック可能になります。

raspberry-pi-usb-hid-pi-03-emqx-005

同意ボタンクリック後、別の同意画面が表示されるので同様にスクロール後、読んで同意しましたのチェックボックスにチェックを入れ、

今すぐに開始を選択するとデプロイメントが開始され、MQTT ブローカーが作成されます。

raspberry-pi-usb-hid-pi-03-emqx-006

ユーザーの作成

MQTT ブローカーの作成が完了したら、ユーザー を作成します。

サイドバーのアクセス制御認証からユーザー作成画面を開き、追加ボタンをクリックします。

raspberry-pi-usb-hid-pi-03-user-001

ユーザー名パスワードを入力し、確認ボタンをクリックします。

raspberry-pi-usb-hid-pi-03-user-002

これでユーザーが作成されます。

アクセス権限の付与

ユーザーを作成したら、アクセス権限を付与します。

今回の記事では送受信

サイドバーのアクセス制御アクセス承認からアクセス承認画面を開き、追加ボタンをクリックします。

raspberry-pi-usb-hid-pi-03-user-003

  • クライアント ID:アクセス権限を付与するユーザーを指定します。
  • トピック:トピック名を入力します。今回はkeyboard/movementと入力します。
  • アクション:Publish&Subscribe(送受信)を選択します。権限の範囲を限定したい場合はPublish(送信側)またはSubscribe(受信側)を選択してください。
  • 許可/拒否:許可を選択します。

確認ボタンを押すとアクセス権限の付与が完了します。

raspberry-pi-usb-hid-pi-03-user-004

接続情報の確認

サイドバーの概要をクリックし、ダッシュボードを表示します。

接続情報の接続先をメモし、CA証明書をダウンロードします。

raspberry-pi-usb-hid-pi-03-user-005

Raspberry Pi にプログラムを実装

次に、2 台の Raspberry Pi Zero 2 W にプログラムを実装します。1 台を送信機、もう 1 台を受信機として使い、それぞれの役割を果たすためのコードを以下に示します。

このサンプルコードではCA証明書/home/piに配置しています。

またMQTT_BROKERにはメモした接続先を入力してください。

MQTT_USERMQTT_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 デバイス間の通信技術を応用したシステム開発に取り組んでいます。ご興味がある方は、ぜひお問い合わせください。