배터리 상태에 따라 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_delete
#!/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 스트립을 올바른 색상으로 즉시 설정하십시오. 이후 1분마다 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"이 정확히 무엇인지 잘 모르겠습니다.