バッテリーの状態に基づいてDualshock4ゲームコントローラーのLEDカラーバーを変更する簡単なスクリプトを作成しました(回答を使用して https://gaming.stackexchange.com/questions/336934/how-to-set-default-color -and-brightness-of-leds-of-the-dualshock-4-controller-on およびバッテリーレベルのステータス https://wiki.gentoo.org/wiki/Sony_DualShock ):
#!/bin/bash
function float_to_int() {
echo $1 | cut -d. -f1 # or use -d, if decimals separator is ,
}
LED=$(echo "$1" | egrep -o '[[:xdigit:]]{4}:[[:xdigit:]]{4}:[[:xdigit:]]{4}\.[[:xdigit:]]{4}')
[[ -z "$LED" || ! -d "/sys/class/leds/$LED:global" ]] && exit
BRIGHTNESS=0.2
POWER=$(cat "/sys/class/power_supply/sony_controller_battery_$2/capacity")
GREEN=$(float_to_int $(echo "($POWER*255/100*$BRIGHTNESS)" | bc -l))
RED=$(float_to_int $(echo "((255 - $POWER*255/100)*$BRIGHTNESS)" | bc -l))
BLUE=0
echo $RED > /sys/class/leds/$LED:red/brightness
echo $GREEN > /sys/class/leds/$LED:green/brightness
echo $BLUE > /sys/class/leds/$LED:blue/brightness
/etc/udev/rules.d/10-local.rulesの下に、コントローラーが接続されるとすぐにこのスクリプトを実行する非常に単純なudevルールを作成しました。
ACTION=="add", SUBSYSTEM=="input", ATTRS{uniq}=="XX:XX:XX:XX:XX:XX" RUN+="/usr/local/bin/ds4led '%p' XX:XX:XX:XX:XX:XX"
これは今のところ完全に機能します。今必要なのは、このスクリプトを1分ごとに実行することです(そうしないと、バッテリーの状態が更新されません)。
私はこれを達成するためにいくつかの方法を試しました:
do-whileループでスクリプト全体を実行する
while :
do
// CODE
sleep 60
done
->これはバッテリーの状態を表示するために機能しますが、コントローラー自体は使用できなくなります
スクリプト全体をバックグラウンドでdo-whileループで実行する
そのために、角かっことアンパサンド構文を使用しました。
(
while :
do
// CODE
sleep 60
done
) &
->これは原則として機能し、コントローラーは使用可能です。しかし、コントローラーが切断されるとすぐに、スクリプトは実行を続行し、エラーを吐き出します。さらに、このスクリプトの複数のインスタンスが常に実行されていることに悩まされます。
解決策?
複数のインスタンスが常に実行され、コントローラーが切断されている場合でもスクリプトが実行を続行するという問題をどのように解決できますか?
確かに、コントローラーを削除して実行する追加のスクリプトを作成して、まだ実行中のスクリプトを最初から強制終了することができます。しかし、現時点では、この解決策は非常に不法なようです。このスクリプトを毎分実行する簡単な方法はありませんか?毎分実行され、コントローラーのプラグが抜かれるとすぐに停止するこのスクリプトからcronジョブを生成することを考えましたが、これもそれほどエレガントではないようです。
あなたは間違った問題を解決しようとしていると思います。 udev
サブシステムは、デバイスが接続されたとき(注意している場合は、デバイスが切断されたとき)を報告します。一方、cron
サブシステムは定期的にプロセスを実行します。
したがって、2つを組み合わせ、udev
を使用して、cron
スクリプトがそのアクションを実行できるようにするトグルを有効または無効にします。
些細なレベルでは、次のようなものになる可能性があります(いいえ、権限と所有権で保護しない限り、/tmp
のフラグファイルは特にお勧めしません)
Udev
ACTION=="add" [...] RUN+="touch /tmp/.ds4led_on"
Cronスクリプト
#!/bin/bash
#
[[ -f "/tmp/.ds4led_on" ]] || exit 0
# ...Code to perform the update...
Roaimaの答えの助けを借りて、私はついにそれを機能させました:
/usr/local/bin
で3つの異なるスクリプトを作成しました。
ds4led
#!/bin/bash
function float_to_int() {
echo $1 | cut -d. -f1 # or use -d, if decimals separator is ,
}
function setrgb() {
LED=$(echo "$1" | egrep -o '[[:xdigit:]]{4}:[[:xdigit:]]{4}:[[:xdigit:]]{4}\.[[:xdigit:]]{4}')
[[ -z "$LED" || ! -d "/sys/class/leds/$LED:global" ]] && exit
BRIGHTNESS=0.2
POWER=$(cat "/sys/class/power_supply/sony_controller_battery_$2/capacity")
GREEN=$(float_to_int $(echo "($POWER*255/100*$BRIGHTNESS)" | bc -l))
RED=$(float_to_int $(echo "((255 - $POWER*255/100)*$BRIGHTNESS)" | bc -l))
BLUE=0
echo $RED > /sys/class/leds/$LED:red/brightness
echo $GREEN > /sys/class/leds/$LED:green/brightness
echo $BLUE > /sys/class/leds/$LED:blue/brightness
}
if [ "$#" -ne 2 ]
then
while read -r line; do
linesplit=($line)
LEDINPUT=${linesplit[0]}
POWERINPUT=${linesplit[1]}
setrgb $LEDINPUT $POWERINPUT
done < /tmp/ds4led
else
setrgb $1 $2
fi
ds4led_write
#!/bin/bash
/usr/local/bin/ds4led $1 $2
echo $1 $2 >> /tmp/ds4led
ds4led_remove
#!/bin/bash
sed "\!$1!d" /tmp/ds4led --in-place
私の/etc/udev/rules.d/20-ds4.rules
ファイル:
ACTION=="add", KERNEL=="event28", ATTRS{uniq}=="00:1f:e2:e5:c3:2e" RUN+="/usr/local/bin/ds4led_write '%p' 00:1f:e2:e5:c3:2e"
ACTION=="remove", KERNEL=="event28", ATTRS{uniq}=="00:1f:e2:e5:c3:2e" RUN+="/usr/local/bin/ds4led_remove '%p'"
Sudo crontab -e
* * * * * /usr/local/bin/ds4led
説明:
Dualshock 4コントローラーが接続されると、そのシリアル番号とバッテリー識別子がファイル/tmp/ds4led
に書き込まれます。接続時に、ds4led
スクリプトが正確にそれらの識別子を使用して直接呼び出され、RGBバーを即座に適切な色に設定します。その後、crontabが毎分実行され、接続されたデバイスの/tmp/ds4led
の下でこのファイルをチェックし、RGBバー手順を実行します。コントローラが切断されるたびに、ファイル内のそのエントリが削除されます。
dev-rules:デュアルショック4コントローラーのすべての接続は、粗いフィルターのために約8つのudevトリガーを生成したため、接続ごとに1回だけトリガーされるudevイベントを見つけようとしました。合計すると、これらのデバイスのすべてがトリガーされました。
/devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.0/bluetooth/hci0/hci0:256/0005:054C:09CC.0013/input/input67 00:1f:e2:e5:c3:2e
/devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.0/bluetooth/hci0/hci0:256/0005:054C:09CC.0013/input/input68 00:1f:e2:e5:c3:2e
/devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.0/bluetooth/hci0/hci0:256/0005:054C:09CC.0013/input/input66 00:1f:e2:e5:c3:2e
/devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.0/bluetooth/hci0/hci0:256/0005:054C:09CC.0013/input/input67/mouse3 00:1f:e2:e5:c3:2e
/devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.0/bluetooth/hci0/hci0:256/0005:054C:09CC.0013/input/input66/js0 00:1f:e2:e5:c3:2e
/devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.0/bluetooth/hci0/hci0:256/0005:054C:09CC.0013/input/input68/event27 00:1f:e2:e5:c3:2e
/devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.0/bluetooth/hci0/hci0:256/0005:054C:09CC.0013/input/input66/event28 00:1f:e2:e5:c3:2e
/devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.0/bluetooth/hci0/hci0:256/0005:054C:09CC.0013/input/input67/event26 00:1f:e2:e5:c3:2e
フィルタとして「event28」を選択したのは、これが1回だけ表示され、コントローラの実際のジョイスティック部分と関係があるためです(すべてのデュアルショックコントローラはタッチパッドと追加のエミュレートされたデバイスで構成されていることを忘れないでください)。しかし、「event28」が実際に何であるかはわかりません。