我创建了一个简单的脚本,根据电池状态更改 Dualshock 4 Gamecontroller 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"
到目前为止,这工作得很好。我现在需要的是让这个脚本每分钟左右运行一次(否则电池状态将不会更新)。
我尝试了几种方法来实现这一目标:
在 do-while 循环中运行整个脚本
while :
do
// CODE
sleep 60
done
-> 这适用于显示电池状态,但控制器本身不再可用
在后台的 do-while 循环中运行整个脚本
为此,我使用了括号和&符号语法:
(
while :
do
// CODE
sleep 60
done
) &
-> 这原则上是有效的,控制器是可用的。但是,一旦控制器断开连接,脚本就会继续运行,并抛出错误,此外,令我烦恼的是该脚本的多个实例不断运行。
解决方案?
如何解决多个实例不断运行,控制器断线脚本仍继续运行的问题?
当然,我可以编写一个额外的脚本,在删除控制器时运行,从而从一开始就终止仍在运行的脚本。但在这一点上,这个解决方案显得非常不优雅。难道没有一种简单的方法可以让这个脚本每分钟运行一次吗?我想从这个脚本中生成一个每分钟运行一次的 cronjob,并在控制器拔下插头后立即停止,但这似乎也不是那么优雅。
答案1
我相信您正在尝试解决错误的问题。子系统udev
会报告设备何时连接(如果您小心的话,还会报告设备何时断开连接)。另一方面,cron
子系统会定期运行一个进程。
因此,将两者放在一起并用于udev
启用或禁用允许cron
脚本执行其操作的切换。
在一个简单的层面上,它可能是这样的(不,我不特别推荐一个标志文件,/tmp
除非你用权限和所有权来保护它)
乌德夫
ACTION=="add" [...] RUN+="touch /tmp/.ds4led_on"
计划任务脚本
#!/bin/bash
#
[[ -f "/tmp/.ds4led_on" ]] || exit 0
# ...Code to perform the update...
答案2
在 roaima 的回答的帮助下,我终于成功了:
我创建了 3 个不同的脚本/usr/local/bin
:
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_删除
#!/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 条过程。每当控制器断开连接时,其在文件中的条目就会被删除。
udev 规则: 由于由于我的粗过滤器,dualshock 4 控制器的每次连接都会生成大约 8 个 udev 触发器,因此我试图找到一个每个连接仅触发一次的 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”作为过滤器,因为它只会出现一次,并且与控制器的实际操纵杆部分有关(不要忘记每个 Dualshock 控制器都包含触摸板和其他模拟设备)。但是,我不确定“event28”到底是什么。