Index
USB Devices have reset
ときどき、KURO-RSが全く動かなくなるときが
あって、どうしてかなぁと調べてたら
USBコントローラ(?)でリセットが発生しており
USBデバイスがいつもは/dev/ttyUSB0で認識していたのが
それが発生したときに/dev/ttyUSB1として再認識していた
ようでKURO-RSへのコマンドが失敗するという事象があった。
同様の理由でPasoriも使えない。
こりゃどうしたもんかと。
今まではKURO-RS側は2度目のリセットが発生したときに
/dev/ttyUSB0で認識されいつの間にか直っていたのだが
Pasoriは頑固で元に戻らない。
ケーブル抜き差しで事なきを得ていた。
Watching kernel message
簡単な対処として監視プログラムを動かすことにした。
/var/log/kern.logにリセットのログが出力されたら
意図的にもう一度リセットさせて認識するデバイスファイルを
強引に書き換える。
sequenceDiagram Kernel ->> Kernel : Something occured Kernel ->> device file : ttyUSB0->ttsUSB1 Kernel ->> kern.log : Reset event occured Watch Program ->> kern.log : Watching Watch Program ->> Watch Program : The event was found! Watch Program ->> Kernel : ioctl USBDEVFS_RESET Kernel ->> device file : ttyUSB1->ttsUSB0 Kernel ->> kern.log : Reset event occured Watch Program ->> Watch Program : Was the device file changed into ttyUSB0?
こんな感じのものをつくる。
ただこれだとPasoriは救えないが
とりあえずはKURO-RSだけ救おうかなと。
Reset command
調べると既に同じ体験をされている方がいて
リセットコマンドを作っている先輩がいた。
ありがたく使わせていただく。
使い方は
$ usbdevicereset.sh 054c:06c3
Resetting USB device /dev/bus/usb/xxx/xxx
Reset successful
$
Watch Program
次に監視プログラムを。
#!/bin/bash
LOGFILE=/var/log/kern.log
MESSAGE='usb.*1\-1\.XXX.*reset' #トリガーとなるメッセージ。XXXにUSBポート番号を。
USBDEVCMD=`which lsusb`
AWKCMD=`which awk`
GREPCMD=`which grep`
CATCMD=`which cat`
SUDOCMD=`which sudo`
TAILCMD=`which tail`
FINDCMD=`which find`
RESETCMD=`which usbdevicereset.sh`
USBADDR='XXXX:XXXX' #USBデバイスのID
USBTTYDEV='/dev/ttyUSB0' #期待するデバイスファイル
CHECKFILE=/tmp/${0}.check
#check environment
if [ "x$SUDOCMD" == "x" \
-o "x$CATCMD" == "x" \
-o "x$GREPCMD" == "x" \
-o "x$USBDEVCMD" == "x" \
-o "x$RESETCMD" == "x" \
-o "x$AWKCMD" == "x" \
-o "x$TAILCMD" == "x" \
-o "x$FINDCMD" == "x" ];
then
echo "some comand[s] was/were not found"
exit 1
fi
if [ ! -f $LOGFILE ];
then
echo "log file was not found"
echo "log file is [${LOGFILE}]"
exit 1
fi
#functions
checkaddress () {
$USBDEVCMD |\
$GREPCMD $USBADDR >/dev/null 2>&1 && \
echo -n "OK" || echo -n "!"
}
watchcheckfile () {
if [ ! -f $CHECKFILE ];
then
echo -n "OK"
fi
$FINDCMD `dirname $CHECKFILE` -type f -mtime +1 -print 2>/dev/null |\
$GREPCMD `basename $CHECKFILE` >/dev/null 2>&1 && \
echo -n "OK" || echo -n "!"
}
watchreset () {
$CATCMD $LOGFILE |\
$GREPCMD "${MESSAGE}" >/dev/null 2>&1 && \
echo -n "OK" || echo -n "!"
}
usbreset () {
$RESETCMD $USBADDR |\
$GREPCMD "Reset successful" >/dev/null 2>&1 && \
$CATCMD $LOGFILE |\
$TAIL -1 |\
$GREPCMD $USBTTYDEV >/dev/null 2>&1 && \
echo -n "OK" || echo -n "!"
}
#main
#check usb address
ret=`checkaddress`
if [ "x$ret" == "x!" -o "x$ret" == "x" ];
then
echo "usb device was not found"
exit 1
fi
#watch checkfile
ret=`watchcheckfile`
if [ "x$ret" == "x!" -o "x$ret" == "x" ];
then
exit 0
fi
#watch usbdevice reset
ret=`watchreset`
if [ "x$ret" == "x!" -o "x$ret" == "x" ];
then
exit 0
fi
#reset usbdevice
ret=`usbreset`
if [ "x$ret" == "x!" -o "x$ret" == "x" ];
then
ret=`usbreset`
if [ "x$ret" == "x!" -o "x$ret" == "x" ];
then
echo "FAIL!!!"
exit 1
else
touch $CHECKFILE
exit 0
fi
fi
これをwatchusbdevice.shのようなファイル名で保存。
使い方は
$ ./watchusbdevice.sh
これをcronにでも仕込んでおく。
10 0 * * * /srv/google-home-helper/watchusbdevice.sh
まだテストしてないけど
これでうまくいってもPasoriの方はどうしようも
ないので、こっちは別に考えなくてはいけないな。
Next is…
次は、不在時にあったことをまとめて帰宅時に
教えてくれる仕組みを作りたい。
私「OK Google,ただいま。」
ぐ「おかえりなさい。不在時の5月11日 7時37分から5月11日 22時05分までの出来事は、、、」
ぐ「11時15分、任天堂のつぶやきが更新されました。」
ぐ「19時2分、誰かが部屋に入っていました。」
ぐ「19時5分、電気が付きました。」
ぐ「19時10分、加湿器が付きました。」
ぐ「21時00分、兄者弟者の動画が更新されました。」
このくらいは言えるかな。
ちょっとやってみようかな。