[BASH] Sterowanie amplitunerem A/V Yamaha

Nudziło mi się trochę to zrobiłem sniffing komunikacji webowego panelu sterowania amplitunerem YAMAHA (RX-A840) i napisałem skrypt w BASHu umożliwiający zarządzanie nim spod konsoli :wink:

Skrypt prawdopodobnie działa też dla innych modeli Yamahy z obsługą sterowania przez przeglądarkę.

Wbrew pozorom jest przydatny nie tylko do sterowania spod konsoli, ale np. do ustawiania parametrów amplitunera w zależności od włączonej aplikacji/okna itp.
Jeżeli jakiś błąd znajdziecie to dajcie znać.

Udostępniam moje wypociny :wink: do pobrania:
yamaha-control.zip (2,1 KB)

Sterowanie:

yamaha-control vst [num] | mt | vu | vd | vm | vv | vs [num] | h[num] | a[num] | on | off

vst - ustaw krok zmiany głośności od 5-50 (np. "vst 5" zmieni głośność, co 0.5 dB, "vst 10", co 1 dB ...)
mt - wycisz / wyłącz wyciszenie
vu - głośniej
vd - ciszej
vm - głośność -38dB - dla trybu muzyka
vv - głośnośc -32dB - dla trybu wideo
vs - ustaw głośność na wartość od 15-60 (np. "vs 45" ustawi głośność -45dB)

h1-7 - ustaw numer kanału HDMI (np. "h1" przełączy na HDMI 1)
a1-6 - ustaw numer kanału AV (np. "a4" przełączy na AV 4)

on - włącz amplituner
off - wyłącz amplituner
#!/bin/bash
#USTAWIENIA --->

#parametry opcjonalne
WEBURL=

#parametry obowiązkowe
NMAPR="" #zakres IP dla szukania urządzeń przez nmap, gdy nie istnieją w wykazie ARP - np. 192.168.1.101-120
MACADDR="" #adres MAC amplitunera format: xx:xx:xx:xx:xx:xx

#<--- KONIEC USTAWIEŃ


#zmienna ustawiana za pomocą parametru "vst" - NIE MODYFIKOWAĆ RĘCZNIE
VOLUMESTEP=10

#sprawdzanie obecności urządzenia po podanym adresie IP (WEBURL) / szukanie po adresie MAC
if [ -n "$WEBURL" ]; then 

    ping -c1 -w3 $WEBURL &> /dev/null || echo "Urządzenie o adresie $WEBURL nie jest online!"; exit 1

else

    [ -z "$MACADDR" ] && echo "Nie uzupełniono w pliku adresu MAC amplitunera !" && set ERR
    [ -z "$NMAPR" ] && echo "Nie uzupełniono w pliku zakresu przeszukiwanych IP !" && set ERR
    [ -z "$ERR" ] && exit 1
    
    WEBURL=$(arp -na | grep $MACADDR | awk -F"[()]" '{print $2}') #sed 's/[^1-2]*\([^)]*\).*/\1/'
    ping -c1 -w3 $WEBURL &> /dev/null || (nmap -T4 -F $NMAPR &> /dev/null && echo -e "Nie znaleziono w wykazie ARP lub urządzenie jest offline\nSpróbuj ponownie...")
    #ponowne wywołanie skryptu powinno zadziałać, ponieważ 
    #nmap sprawi, że urządzenie pojawi się w wykazie ARP o ile prawidłowo podany jest zakres IP
fi


#FUNKCJE --->
function avcurl() {
   local mode=$1
   local inset=$2

   [[ ${mode} == "PUT" ]] && shutup="-o/dev/null" #"wyciszanie" wyjścia"

   cat <<EOF
curl -s 'http://${WEBURL}/YamahaRemoteControl/ctrl' -X POST -d \
    '<YAMAHA_AV cmd="${mode}">${inset}</YAMAHA_AV>' ${shutup}
EOF
}

function av_power() {
    local status=$1
    avcurl PUT "<Main_Zone><Power_Control><Power>${status}</Power></Power_Control></Main_Zone>"
}

function hdmi_ch() {
    local ch=$1
    avcurl PUT "<Main_Zone><Input><Input_Sel>HDMI${ch}</Input_Sel></Input></Main_Zone>"
}

function av_ch() {
    local ch=$1
    avcurl PUT "<Main_Zone><Input><Input_Sel>AV${ch}</Input_Sel></Input></Main_Zone>"
}

function volume() {
    local mode=$1 volume newvolume
    local val=$2
    local A=$(eval $(avcurl GET "<Main_Zone><Volume><Lvl>GetParam</Lvl></Volume></Main_Zone>"))
    volume=$(echo $A|sed 's/.*<Val..//;s/..Val.*//')

    [[ ${mode} == "up" ]] && newvolume=$[volume-${VOLUMESTEP}]
    [[ ${mode} == "down" ]] && newvolume=$[volume+${VOLUMESTEP}]
    [[ ${mode} == "video" ]] && newvolume=$[320]
    [[ ${mode} == "music" ]] && newvolume=$[380]
    [[ ${mode} == "set" ]] && newvolume=$[$val]0 #dodane dodatkowe "0", wartość była odpowiednia
    [[ ${mode} == "vstep" ]] && sed -i "s/VOLUMESTEP=$VOLUMESTEP/VOLUMESTEP=$val/" $PWD/$(basename $0)
    avcurl PUT "<Main_Zone><Volume><Lvl><Val>-${newvolume}</Val><Exp>1</Exp><Unit>dB</Unit></Lvl></Volume></Main_Zone>"
}

function mute_switch() {
    local newmode
    local A=$(eval $(avcurl GET "<Main_Zone><Volume><Mute>GetParam</Mute></Volume></Main_Zone>"))
    local ismute=$(echo ${A}|sed 's/.*<Mute.//;s/..Mute.*//')
    [[ ${ismute} == Off ]] && newmode=On || newmode=Off

    avcurl PUT "<Main_Zone><Volume><Mute>${newmode}</Mute></Volume></Main_Zone>"
}
# <--- KONIEC FUNKCJI

opt=$1
case $opt in
    vst)
        [[ "$2" -ge 5 && "$2" -le 50 ]] || { echo "Krok zmiany głośności musi być w przedziale 5-50 (czyli od 0.5-5 dB)"; exit 1; }
        eval $(volume vstep $2)
        ;;
    mt)
        eval $(mute_switch)
        ;;
    vu)
        eval $(volume up)
        ;;
    vd)
        eval $(volume down)
        ;;
    vv)
        eval $(volume video)
        ;;
    vm)
        eval $(volume music)
        ;;
    vs)
        [[ "$2" -ge 15 && "$2" -le 60 ]] || { echo "Głośność musi być w przedziale 15-60"; exit 1; }
        eval $(volume set $2)
        ;;
    h*)
        [[ $opt =~ h([0-9])$ ]] && number=${BASH_REMATCH[1]}
        [[ -z $number ]] && { echo "Kanał nie wykryty: ${opt}"; exit 1; }
        eval $(hdmi_ch ${number})
        ;;
    a*)
        [[ $opt =~ a([0-9])$ ]] && number=${BASH_REMATCH[1]}
        [[ -z $number ]] && { echo "Kanał nie wykryty: ${opt}"; exit 1; }
        eval $(av_ch ${number})
        ;;
    [oO]n|1)
        eval $(av_power On)
        ;;

    [oO]ff|0)
        eval $(av_power Standby)
        ;;
    *)
        cat <<EOF
        
yamaha-control vst [num] | mt | vu | vd | vm | vv | vs [num] | h[num] | a[num] | on | off

vst - ustaw krok zmiany głośności od 5-50 (np. "vst 5" zmieni głośność, co 0.5 dB, "vst 10", co 1 dB ...)
mt - wycisz / wyłącz wyciszenie
vu - głośniej
vd - ciszej
vm - głośność -38dB - dla trybu muzyka
vv - głośnośc -32dB - dla trybu wideo
vs - ustaw głośność na wartość od 15-60 (np. "vs 45" ustawi głośność -45dB)

h1-7 - ustaw numer kanału HDMI (np. "h1" przełączy na HDMI 1)
a1-6 - ustaw numer kanału AV (np. "a4" przełączy na AV 4)

on - włącz amplituner
off - wyłącz amplituner

EOF
        exit 1
        ;;
esac