HowTo - Yamaha Verstärker per LAN/Netzwerk steuern

Es ist geschaft - jetzt können auch Yamaha Geräte z. B. Verstärker per Lan gesteuert werden.

Getestet mit einem Yamaha RX-V771 - laut Referenzdatei sind auch andere Geräte steuerbar z. B.

RX-A3010 RX-A2010 RX-A1010 RX-A810 RX-A710
RX-V3071 RX-V2071 RX-V1071 RX-V871 RX-V771 RX-V671
Hier mein Beispiel:


<?

$host = '192.168.20.100';      //IP des Gerätes anpassen!

// 0 = Power OFF
// 1 = Power ON
// 2 = Main Zone Mute ON
// 3 = Main Zone Mute Off
// 4 = Main Zone Mute On/Off
// 5 = Main Zone leiser (2 dB)
// 6 = Main Zone lauter (2 dB)
// 7 = Main Zone 55 dB setzten

$i = 5;

switch ($i) {
     case 0:
        $send = send_to_host($host,'<YAMAHA_AV cmd="PUT"><System><Power_Control><Power>Standby</Power></Power_Control></System></YAMAHA_AV>');
        break;
     case 1:
        $send = send_to_host($host,'<YAMAHA_AV cmd="PUT"><System><Power_Control><Power>On</Power></Power_Control></System></YAMAHA_AV>');
        break;
     case 2:
        $send = send_to_host($host,'<YAMAHA_AV cmd="PUT"><Main_Zone><Volume><Mute>On</Mute></Volume></Main_Zone></YAMAHA_AV>');
        break;
    case 3:
        $send = send_to_host($host,'<YAMAHA_AV cmd="PUT"><Main_Zone><Volume><Mute>Off</Mute></Volume></Main_Zone></YAMAHA_AV>');
        break;
    case 4:
        $send = send_to_host($host,'<YAMAHA_AV cmd="PUT"><Main_Zone><Volume><Mute>On/Off</Mute></Volume></Main_Zone></YAMAHA_AV>');
        break;
    case 5:
        $send = send_to_host($host,'<YAMAHA_AV cmd="PUT"><Main_Zone><Volume><Lvl><Val>Down 2 dB</Val><Exp></Exp><Unit></Unit></Lvl></Volume></Main_Zone></YAMAHA_AV>');
        break;
    case 6:
        $send = send_to_host($host,'<YAMAHA_AV cmd="PUT"><Main_Zone><Volume><Lvl><Val>Up 2 dB</Val><Exp></Exp><Unit></Unit></Lvl></Volume></Main_Zone></YAMAHA_AV>');
        break;
    case 7:
        $send = send_to_host($host,'<YAMAHA_AV cmd="PUT"><Main_Zone><Volume><Lvl><Val>-550</Val><Exp>1</Exp><Unit>dB</Unit></Lvl></Volume></Main_Zone></YAMAHA_AV>');
        break;
}


echo $send;  //Wenn Ok dann wird true (1) zurückgegeben



function send_to_host($host, $data){

    //echo $data;  //zum prüfen

    $command_lenght = strlen($data);
    
    //echo $command_lenght;    //zum prüfen
    
    $head = "";
    $head .= "POST /YamahaRemoteControl/ctrl HTTP/1.1
";
    $head .= "Host: ".$host."
";
    $head .= "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0
";
    $head .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
";
    $head .= "Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
";
    $head .= "Accept-Encoding: gzip, deflate
";
    $head .= "Connection: keep-alive
";
    $head .= "Content-Type: text/xml; charset=UTF-8
";
    $head .= "Referer: http://".$host."/
";
    $head .= "Content-Length: ".$command_lenght."
";
    $head .= "Pragma: no-cache
";
    $head .= "Cache-Control: no-cache

";
    $head .= $data;
    //echo $head; //zum prüfen

    $fp = fsockopen($host, 80) or die("Unable to open socket");
    fputs($fp, $head);

   $buf = fgets($fp,128);
    fclose($fp);
    //echo $buf;   //zum prüfen

    $return = substr($buf,13,2);
         
    if ($return == "OK") {
        return true;
        //return "OK";
    }
}

?>

Den Referenzdatei für die Befehle findet man hier: http://www.google.de/url?sa=t&rct=j&q=yamaha%20rx-vx67_ethernet_if_spec&source=web&cd=1&ved=0CDAQFjAA&url=http%3A%2F%2Fwww.avhifiresources.co.uk%2Fcontent%2FDealer%20News-Info%2FCustom%20Installer%20Info%2FRX%20AX10%20VX71%20Series%20Function%20Tree.xls&ei=yN_4TuyJHpGA8gO00eWsAQ&usg=AFQjCNHbx60435avSmn_xl8V69exhoTUSw

Reiter: „Func tree for comp functions“.

Viel Spaß!

Hallo,

Da ich auch plane mir einen Yamaha 3010 / 3020 zuzulegen (auch für multiroom), weißt du ob es möglich ist via iP-Symcon über nen knx taster eine zone ein / auszustellen. bzw, via visualisierung lautstärke und evtl. auch quelle zu ändern für die jeweilige zone?

grüße,
Matthias

Ich habe seit kurzem einen RX-A820 … die Befehle aus dem Code erlauben einem ja „nur“ das Absenden von Befehlen, gibt es auch eine Möglichkeit den Status auszulesen?
Eine Weboberfläche gibt es ja … !?

Gruß
Jens

Die Yamahas bestätigen jeden Befehl. Dies kannst du auswerten.

Wenn du zum Beispiel folgendes sendest:

<YAMAHA_AV cmd="PUT"><Main_Zone><Volume><Lvl><Val>-400</Val><Exp>1</Exp><Unit>dB</Unit></Lvl></Volume></Main_Zone></YAMAHA_AV>

und alles läuft, kommt folgende Antwort

<YAMAHA_AV rsp="PUT" RC="0"><Main_Zone><Volume><Lvl></Lvl></Volume></Main_Zone></YAMAHA_AV>

Wichtig sind dabei der RC (response code) Parameter und der bestätigte Parameterpfad.

Oben genanntes Beispiel bezieht sich auf des Webinterface. Analog funktioniert es an der Konsole (Socket Verbindung).
Dort ist aber das Format anders. Eine Bestätigung sieht so aus:

@MAIN:VOL=-40.0

Sehr gute Wahl. Ich habe mir die x020 Serie (unter Anderem auch den 3020 in Einzelteile zerlegt) auf der IFA angeschaut. Es juckt seitdem ja schon etwas in den Fingern. Ich habe einen gerade mal 2 Jahren alten 3067, aber wenn ich dafür noch einen guten Preis bekomme…Jemand interessiert? PN an mich.

Zur eigentliche Frage: Man kann jegliche Funktion steuern und seit dem die Yammis nen LAN Interface haben, ist das auch sehr komfortabel zu machen.

Um z.B. die Zone 2 zu aktivieren und diese auf NetRadio zu setzen, musst du lediglich das folgende Kommando absetzen.

<YAMAHA_AV cmd="PUT"><Zone_2><Power_Control><Power>On</Power></Power_Control></Zone_2></YAMAHA_AV>
<YAMAHA_AV cmd="PUT"><Zone_2><Input><Input_Sel>NET RADIO</Input_Sel></Input></Zone_2></YAMAHA_AV> 

Nutzt du zufällig IPS-Library mit IPS-Entertainment?

Das stimmt aber doch so nicht ganz … denn wenn der Befehl in Ordnung ist, dann kommt über die Funktion nur eine „1“ (TRUE) als Antwort zurück zurück (steht auch so im Script).

Die Verbindung über Socket funktioniert, das nutze ich auch schon testweise seit ein paar Tagem, aber leider verliert IPS immer mal wieder die Socketverbindung für ein paar Sekunden, so das nicht immer gewähleistet ist das die Infos auch ankommen!?
Ich würde auch gern bei der Socketverbindung bleiben, weil dann auch die Fernbedienungssignale an kommen und ausgewertet werden … Voraussetzung wäre aber die stabile Verbindung.

Im Webinterface kommen Änderungen ja auch an … gibt es eine Möglichkeit diese auch abzufangen ??

Gruß
Jens

@domizei385: Kannst du mal Schrittweise erklären wie du das Webinterface abfragst und an die Bestätigung kommst?
Bei mir kommt lediglich ein „OK“ zurück !?

Gruß
Jens

Passe mal den Code aus dem ersten Post an indem du - etwa so hier - die Antwort auswertest:


$result= ''; 
while(!feof($fp)) {
    // receive the results of the request
    $result.= fgets($fp, 128);
}

Ich hab jetzt gerade nicht die Zeit das überprüfen, aber ich glaube der „interessante“ Teil der Response kommt erst später.

Und dann so hier den Response header vom content splitten:


$result = explode("

", $result, 2);
$header = isset($result[0]) ? $result[0] : '';
$content = isset($result[1]) ? $result[1] : '';

Hmmm … also da passiert nicht viel. Die Antwort in $result ist z.b. bei Lautstärkeänderung:

HTTP/1.1 200 OK
Server: AV_Receiver/3.1 (RX-A820)
Content-Type: text/xml; charset=„utf-8“
Content-Length: 91

Ich gehe davon aus, das evtl. etwas im Content steht, aber wie da ran kommen ?

Hast du dir mal den Inhalt von „$content“ ausgeben lassen?

Ja klar, ist leer … wenn ich mir das Array mit print_r anzeigen lasse, dann ist der von mir gepostete Inhalt in $result[0] und $result[1] ist leer !

Hallo,

die Steuerung funktioniert ja super :slight_smile:

aber wie kann ich Werte auslesen und eine Variable befüllen? Z.B. den Radio Sender anzeigen der gerade läuft?

$send = send_to_host($host,’<YAMAHA_AV cmd=„GET“><NET_RADIO><Play_Info><Meta_Info><Station>GetParam</Station></Meta_Info></Play_Info></NET_RADIO></YAMAHA_AV>’);

Könnt ihr mir da weiterhelfen, kenn mich so genau mit PHP nicht aus.

Danke

Schon der Fakt, dass der Header eine Länge von 91 für den Content angibt, widerspricht dem. Eine einfache Gegenprobe ala

print_r(strlen($content));

sollte dies bestätigen.

Der Grund ist einfach, dass der $content valides HTML/XML beinhaltet und dieser nicht angezeigt wird. Du kannst es sichtbar machen per:

print_r(str_replace("<", "[", $content));

Ich würde dir empfehlen den IPSLogger von brownson zu verwenden. Dann siehst du den Inhalt sofort und ohne über den unschönen Umweg per str_replace.

Danke für den Hinweis … irgendwie war mir klar das da auf Grund der Contentlänge etwas sein müsste, ich wusste nur nicht wie ich das darstellen soll :wink:

Den Logger von Brownson habe ich installiert, aber zum einen nicht die aktuellste version und zum anderen war ich bisher zu blöd den Logger richtig zubenutzen :smiley:
:rolleyes:

Letztendlich werde ich aber wohl bei der Variante mit dem Client Socket bleiben, da ich dort auch aktuelle Änderungen am Gerät oder über die FB mitbekomme. Das einzig blöde an der Lösung ist leider die unzuverlässige Vebindung. Aber im Notfall sendet man einen Request um einen aktuellen Status zu bekommen.

Aktuell nutze ich das so:

<?
$antwort = $_IPS['VALUE'];
$array = explode ( ':', $antwort ); // Antwortstring in Array umwandeln

$quelle = $array[0];
$array2 = explode ( '=', $array[1] ); // Antwortstring in Array umwandeln
$funktion = $array2[0];

If($array[0] == "@MAIN")
{
	switch($funktion)
		   {
		      case "VOL":
		         SetValue(45510 /*[Media\Yamaha RX-A820\Main\Volume]*/, $array2[1]);
		      break;

		      case "PWR":
		         SetValue(23757 /*[Media\Yamaha RX-A820\Main\Power]*/, $array2[1]);
		      break;
		   }
}

$wert = $array2[1];
//echo $array2[1];

?>

RegVar_SendText(27009 /*[Client Socket RX-A820\Register Variable]*/, "@MAIN:VOL=Down 2 dB".chr(13).chr(10)); //Lautstärke um 2 dB anheben
RegVar_SendText(27009 /*[Client Socket RX-A820\Register Variable]*/, "@MAIN:PWR=?".chr(13).chr(10)); //Statusabfrage
RegVar_SendText(27009 /*[Client Socket RX-A820\Register Variable]*/, "@MAIN:PWR=On".chr(13).chr(10)); //Einschalten

Habs doch hinbekommen:

sicher kann dies jemand noch besser aber so funktioniert es zumindest:

<?
$host = '192.168.2.148';      //IP des Gerätes anpassen!



$send = send_to_host($host,'<YAMAHA_AV cmd="GET"><Main_Zone><Power_Control><Power>GetParam</Power></Power_Control></Main_Zone></YAMAHA_AV>');
$ausgabe = substr($send,61,2);

//echo $ausgabe;

SetValueString(48440, $ausgabe);



function send_to_host($host, $data){

    //echo $data;  //zum prüfen

    $command_lenght = strlen($data);

    //echo $command_lenght;    //zum prüfen

    $head = "";
    $head .= "POST /YamahaRemoteControl/ctrl HTTP/1.1
";
    $head .= "Host: ".$host."
";
    $head .= "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0
";
    $head .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
";
    $head .= "Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
";
    $head .= "Accept-Encoding: gzip, deflate
";
    $head .= "Connection: keep-alive
";
    $head .= "Content-Type: text/xml; charset=UTF-8
";
    $head .= "Referer: http://".$host."/
";
    $head .= "Content-Length: ".$command_lenght."
";
    $head .= "Pragma: no-cache
";
    $head .= "Cache-Control: no-cache

";
    $head .= $data;
    //echo $head; //zum prüfen

    $fp = fsockopen($host, 80) or die("Unable to open socket");
    fputs($fp, $head);

    $buf = "";

   while (!feof($fp))
        $buf .= fgets($fp,128);

          $zeile = explode("
", $buf);
        foreach( $zeile as $ausgabe );


    fclose($fp);
 
        return $ausgabe;
}


?>

// Gerät AN AUS
$send = send_to_host($host,'<YAMAHA_AV cmd="GET"><Main_Zone><Power_Control><Power>GetParam</Power></Power_Control></Main_Zone></YAMAHA_AV>');
$Status = substr($send,61,2);

If ($Status == 'On')
{
SetValueBoolean(10126 /*[Multimedia\Gerät]*/ , True);


//Lautstärke
$send = send_to_host($host,'<YAMAHA_AV cmd="GET"><Main_Zone><Volume><Lvl>GetParam</Lvl></Volume></Main_Zone></YAMAHA_AV>');
$Laustaerke = substr($send,57,3);
SetValue(59731 /*[Multimedia\Laustärke]*/ , $Laustaerke);

//Input gewählt
$send = send_to_host($host,'<YAMAHA_AV cmd="GET"><Main_Zone><Input><Input_Sel>GetParam</Input_Sel></Input></Main_Zone></YAMAHA_AV>');
$Input = $send;
$chars = preg_split("/Input_Sel>|Input_Sel>/", $Input, PREG_SPLIT_OFFSET_CAPTURE);
$chars[1] =explode("</", $chars[1]);
SetValue(42784 /*[Multimedia\Eingang\Input zur Zeit gewählt]*/ , $chars[1][0]);

//NET Radio Sender
$send = send_to_host($host,'<YAMAHA_AV cmd="GET"><NET_RADIO><Play_Info>GetParam</Play_Info></NET_RADIO></YAMAHA_AV>');
$Preset = $send;
$chars = preg_split("/Station>|Station>/", $Preset, PREG_SPLIT_OFFSET_CAPTURE);
$chars[1] =explode("</", $chars[1]);
SetValue(54007 /*[Multimedia\Internet Radio\zur Zeit laufender Radiosender]*/ , $chars[1][0]);


}
else
{
SetValueBoolean(10126 /*[Multimedia\Gerät]*/ , false);
}


Du kannst du einen „Keep-Alive“ absetzen, alle 30 Sekunden oder mehr. Auf diese Weise bleibt (bei mir) der Socket, soweit ich das nach 5 Minuten beobachten beurteilen kann, offen.

Kann man dir dabei helfen es richtig zu benutzen?

Bestimmt … Hängt davon ab wie geduldig du so bist. Sinn würde das aber nur per TS3, Skype oder Telefon machen :wink:

Gruß
Jens

Ich möchte auch gern die Client Socket Verbindung einrichten damit ich immer auch die Befehle der FB empfangen kann.
Könnt ihr das hier vielleicht alles genau erklären was man hier einrichten / einstellen muss?

Denn ich habe ein Client Socket mit der IP und Port 80 angelegt, darunter eine Register Variable. Die Client Socket Verbindung baut sich immer alle 5 Sekunden für ca. 2 Sekunden auf und schließt sich wieder. Bleibt die bei euch länger offen? Wie funktioniert das genau mit dem Keep-Alive? einfach irgendwas hinschicken? Ausser wenn ich alle 3 Sekunden irgendwas sende bleibt der socket geöffnet?

Ich empfange aber leider auch keine Befehle, wenn ich auf die Register Variable gehe und Debug aktiviere kommt nix an wenn ich zum Beispiel die Lautstärke erhöhe? warum nicht :frowning: ? Im Webinterface verändert sich die Lautstärke…

DANKE

ahhh es ist Socket Port: 50000 wieso schreibt das hier niemand…
jetzt siehts schon viel besser aus