FlircUSBユニバーサルリモートコントロールレシーバーというデバイスを使って、ファイヤーウォールを超えてRaspberryPiを制御する方法を紹介します。
FlircUSBユニバーサルリモートコントロールレシーバーとは?
手持ちの適当な赤外線リモコンの信号を覚えさせると、その信号を受信したときにあらかじめ設定したキー入力をエミュレーションしてくれるデバイスです。
設定はWindowsなどから専用のソフトを使用しますが、設定はデバイス本体に記憶されるためUSBキーボードに対応した機器であればOS等の制限なく使用できます。BIOS画面も操作可能です。
このデバイスとSwitchBotやNatureRemoのような赤外線リモコンを組み合わせて、家の外から特定のリモコン信号を送信したときに特定のスクリプトが実行されるようにします。
例えば”普段はSSHをNGとしておいて使うときだけONにする”ような、本来であれば物理的にマシンにアクセスしないと設定を変更できないようなことを行ったり、そのマシンがオフラインであってもオンラインでの操作が可能になります。
必要なもの
- FlircUSBユニバーサルリモートコントロールレシーバー
- スマートホーム用家電リモコン(なんでも可)
- Linuxマシン(今回はRaspberryPi 2B,Raspberry Pi OS Lite2022/04/04を使用)
- Windowsマシン(Mac,Linuxでも可)
手順1:FLIRC にリモコン信号をおぼさせる
スマートホーム用家電リモコンで、家で使っていない適当なリモコンを選んでFLIRCに覚えさせます。
今回はシャープのリモコンの1,2,3,4チャンネルのボタンをキーボードの1,2,3,4に対応させました。
手順2:制御したいLinuxPCの設定をする
ここからが本番です。以前WiiリモコンでLINUXマシンを制御するという記事を書きましたが今回も基本的には同じ方法をとります。
デバイスの確認
制御したいPCにFLIRCを接続して以下のコマンドを実行してください。
$ cat /proc/bus/input/devices
以下のような出力が出るはずです。
I: Bus=0003 Vendor=20a0 Product=0006 Version=0101 N: Name="flirc.tv flirc Keyboard" P: Phys=usb-3f980000.usb-1.4/input1 S: Sysfs=/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4/1-1.4:1.1/0003:20A0:0006.0004/input/input6 U: Uniq= H: Handlers=sysrq kbd event5 B: PROP=0
今回の場合イベントハンドラはevent5ですので、/dev/input/event5を監視すればよいことがわかります。この数字は環境により異なりますので、これを正しく認識する必要があります。
FLIRCデバイスのイベントハンドラ番号を取得するスクリプトを作る
スクリプトを作ります。エディタはemacsを使用します。(当然ですがなんでもいいです)
$emacs irevent.sh
#!/bin/bash function SearchEvent(){ RESULT=`cat /proc/bus/input/devices | grep -A 4 '"flirc.tv flirc Keyboard"' | grep "Handlers"` RESULT=`echo $RESULT | grep -o event[0-9]*` echo $RESULT } function connectDevice(){ DEVNUM=`SearchEvent` if [ -n "$DEVNUM" ];then IRDEV="/dev/input/"$DEVNUM #echo $IRDEV ./irevent $IRDEV wait fi } SCRIPT_DIR=`dirname $0` cd $SCRIPT_DIR connectDevice
相変わらず無理くりですが、これで動きます。
動作チェックをする場合は、11行目のコメントアウトを外して12行目をコメントアウトしてください。正しくFLIRCを認識していれば
/dev/input/event5
と出力されるはずです。(末尾の数字は環境により異なる)
イベントを監視するプログラムを作る
指定されたデバイスのイベントを監視し、キーに応じたスクリプトを実行するプログラムを作成します。各イベントの条件分岐で使用しているevent.codeについては以下のファイルを参照してください。
/usr/include/linux/input-event-codes.h
emacs irevent.c
#include <errno.h> #include <fcntl.h> #include <linux/input.h> #include <linux/uinput.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> int main(int argc,char *argv[]) { char *INPUT_DEVICE =argv[1]; int input = open(INPUT_DEVICE, O_RDWR); ioctl(input, EVIOCGRAB, 1); for(;;) { struct input_event event; if (read(input, &event, sizeof(event)) != sizeof(event)) { break; } if(event.type ==1){ if(event.code == 2 && event.value==1){ //#1キー system("bash ./script01.sh"); } else if(event.code == 3 && event.value==1){ //#2キー system("bash ./script02.sh"); } else if(event.code == 4 && event.value==1){ //#3キー system("bash ./script03.sh"); } else if(event.code == 5 && event.value==1){ //#4キー system("bash ./script04.sh"); } } } ioctl(input, EVIOCGRAB, 0); return 0; }
出来たらコンパイル
gcc irevent.c -o irevent
サービスとして起動する設定
2.2で作成したスクリプトをサービスとして起動します。
sudo emacs /etc/systemd/system/irevent.service
[Unit] After=network-online.target [Service] User=root ExecStart=/home/hoge/irevent.sh [Install] WantedBy=multi-user.target
$sudo systemctl enable irevent.service
実行したいスクリプトを書く
script01.sh~script04.shを好きに書いてください。
あとは煮るなり焼くなり。
コメント