Sonos Lautstärke mit Homematic Taster ändern

Du darfst das Script nicht über die Console ausführen !
Diese Werte stehen nur zur Verfügung wenn das Ereignis das Script startet.

Michael

Danke für den Hinweis, jetzt funktioniert es natürlich :wink:

Ich bin begeistert, auch der Eintrag im Log ist so super um es nachzuvollziehen perfekt! :smiley:

Im Moment nutze ich das ganze noch über die RaspberryMatic CCU mit HVL um Sonos, Hue und Harmony zu steuern.

Ich schalte die Sonos Player momentan so:

Alle Player sind Aus / Pause drücke ich jetzt im Badezimmer eine Taste am HomeMatic taster geht der Speaker an.
Gehe ich nun in die Küche und drücke dort auf eine Taste am HomeMatic taster wird der Player in der Küche automatisch dem vom Badezimmer untergeordnet.

Drücke ich nun im Badezimmer wieder drauf bekommt der Küchenplayer automatisch den Coordinator zugewiesen und der Player im Badezimmer wird aus der Gruppe entfernt und auf Pause gesetzt.
Das funktioniert so mit beliebig vielen Lautsprechern.

Ist sowas auch mit IP Symcon als Anfänger zu realisieren ?
Oder ist das sehr komplex zu Programmieren ?

Gruß,
Adrian

Grundsätzlich geht alles, Du solltest erst mal mit einzelen Befehlen testen ob das ausgeführt wird was Du willst. Wenn das so funktioniert musst Du dann halt beliebig die Methoden hinter einander auflisten die Du willst das diese abgearbeitet werden.

Du brauchst dazu so was wie


SNS_SetGroup(integer $InstanceID, integer $groupCoordinator);
SNS_SetGroupVolume(integer $InstanceID, integer $volume);
SNS_Stop(integer $InstanceID);
usw.

Wie so was grundsätzlich funktioniert hast Du ja bereits an einem Skript getestet, mit einem Ereignis das auslöst sobald der Taster gedrückt wurde wird dann ein Skript aufrufen das wiederum bestimmte Dinge ausführt.

Ich würde mal ein grobes Skript auf Grundlage des Skripts oben zusammen kopieren mit den Funktionen die Du brauchst.
Dann kannst Du das ja ausprobieren bzw. hier posten dann kann man Dir bei Bedarf noch einen Hinweis geben wo etwas angepasst werden muss. Am ehesten versteht und lernt man solche Dinge, wenn man diese selber ausprobiert, wobei man Dir, wenn es hängt, gerne Tipps geben und helfen kann.

Ich hab mich mal dran getraut, die toggle Funktion klappt schonmal…

<?

IPS_LogMessage("Sonos Play/Pause", "Event ".$_IPS['EVENT'].", ID ".$_IPS['VARIABLE'] ); // Gibt eine Meldung im Meldungsfenster aus
$status = GetValue(IPS_GetObjectIDByIdent("Status",21503 /*[Sonos_Badezimmer\Status]*/ )); // Auslesen der Variable Volume 
// Abfragen der auslösenden Variable über Objekt ID
if($_IPS['VARIABLE'] == 21533) // Auslöser ist Variable mit der ObjektID 12345
{
 if($status == 3) 
 { 
    SNS_Play(21503 /*[Sonos_Badezimmer\Status]*/,1);   
 }  
}
if($_IPS['VARIABLE'] == 21533) // Auslöser ist Variable mit der ObjektID 23456
{
if($status != 1) 
 { 
    SNS_Play(21503 /*[Sonos_Badezimmer\Status]*/,3);    
 }  
}  



?>

Jedoch erhalte ich im Log Fehler trotz korrekter Funktion:

20.05.2018 19:22:25 | ScriptEngine | Ergebnis für Ereignis 28552
<br />
<b>Warning</b>: Objekt mit Ident Status wurde nicht gefunden in <b>C:\IP-Symcon\scripts\10048.ips.php</b> on line <b>4</b><br />
<br />
<b>Warning</b>: Variable #0 existiert nicht in <b>C:\IP-Symcon\scripts\10048.ips.php</b> on line <b>4</b><br />
<br />
<b>Warning</b>: Instanz #21503 existiert nicht in <b>C:\IP-Symcon\scripts__generated.inc.php</b> on line <b>119</b><br />
<br />
<b>Fatal error</b>: Uncaught exception ‚Exception‘ with message ‚Instance does not implement this function‘ in C:\IP-Symcon\scripts__generated.inc.php:124
Stack trace:
#0 C:\IP-Symcon\scripts\10048.ips.php(17): SNS_Play(21503, 3)
#1 {main}
thrown in <b>C:\IP-Symcon\scripts__generated.inc.php</b> on line <b>124</b><br />

Das Objekt Status kennt ja insgesamt 6 Möglichkeiten

0 - Prev
1 - Play
2 - Pause
3 - Stop
4 - Next
5 - Transition

muss ich hier noch etwas beachten beim ausgeben des Variablen inhaltes?
Könnte hier der Fehler im Log herkommen?

Gruß,

Mir fällt gerade noch auf das mir jetzt immer die aktuelle Position etc. im Log ausgegeben wird:

20.05.2018 19:30:52*| VariableManager*| [Sonos_Badezimmer\Position] = 0:00:23
20.05.2018 19:30:52*| VariableManager*| [Sonos_Badezimmer\Position] = 0:00:23
20.05.2018 19:30:57*| VariableManager*| [Sonos_Badezimmer\Position] = 0:00:28
20.05.2018 19:31:02*| VariableManager*| [Sonos_Badezimmer\ContentStream] = SWR3 CLUB - POP AND GO
20.05.2018 19:31:02*| VariableManager*| [Sonos_Badezimmer\Position] = 0:00:03
20.05.2018 19:31:02*| VariableManager*| [Sonos_Badezimmer\Details] = <table width=„100%“>
<tr>
<td>
<div style=„text-align: right;“>
<div><b>SWR3 CLUB - POP AND GO</b></div>
<div> </div>
<div>SWR3</div>
</div>
</td><td width=„170px“ valign=„top“>
<div style=„width: 170px; height: 170px; perspective: 170px; right: 0px; margin-bottom: 10px;“>
<img src=„http://cdn-radiotime-logos.tunein.com/s24896q.png“ style=„max-width: 170px; max-height: 170px; -webkit-box-reflect: below 0 -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.88, transparent), to(rgba(255, 255, 255, 0.5))); transform: rotateY(-10deg) translateZ(-35px);“>
</div>
</td></tr>
</table>

Das bläst ja das Logfile unnötig auf oder?

Jede Variablenänderung landet im Logfile.
Michael

Ok,
Das heißt die Einträge kommen dann nicht von meinem Skript…
Aber woher kommt die Fehlermeldung ? Die wird mir um Log auch Rot hervorgehoben.

Die Methode IPS_GetObjectIDByIdent holt die ObjektID eines Objekts, in dem Fall der Variable Status, um diese zurückzugeben. Dabei wird nach der Ident gesucht, diese kann eingesehen werden, wenn das Objekt mit CTRL+Enter geöffnet wird, dort kann man die Ident ablesen. Dabei wird unter der übergeordneten Instanz, das ist in dem Fall die Sonos Instanz, geschaut ob eine Variable mit der Ident „Status“ vorhanden ist.


$status = GetValue(IPS_GetObjectIDByIdent("Status",21503 /*[Sonos_Badezimmer\Status]*/ ));

Der Fehler liegt also in dem Fall darin, dass im zweiten Teil die Variable selber ausgewählt worden ist, hier müstest Du einfach die Sonos Instanz selber angeben, dann wird die Variable mit Status innerhalb der Instanz gefunden.

Alternativ kannst Du natürlich auch den Wert direkt auslesen.

Also entweder


$status = GetValue(IPS_GetObjectIDByIdent("Status",12345 /*[Sonos_Badezimmer]*/ )); // Objekt ID der Sonos Badezimmer Instanz angeben

oder


$status =  GetValue(21503 /*[Sonos_Badezimmer\Status]*/ );

Guten Tag zusammen,

Ich bin absolut hell auf begeistert, ich habe zuvor auch schon ioBroker versucht und bin an dieser Aufgabe komplett verzweifelt mit JavaScript…

Ich habe die Funktion nun wie beschrieben umgesetzt bekommen, ohne Fehlermeldungen im Log :smiley:

Hier mal der Code:

<?

IPS_LogMessage("Sonos Play/Pause", "Event ".$_IPS['EVENT'].", ID ".$_IPS['VARIABLE'] ); // Gibt eine Meldung im Meldungsfenster aus

//Definition bzw. hohlen diverser Variablen

//Play Status
$statusBadezimmer = GetValue(IPS_GetObjectIDByIdent("Status",19980 /*[Sonos_Badezimmer]*/));
$statusEsszimmer = GetValue(IPS_GetObjectIDByIdent("Status",10049 /*[Sonos_Esszimmer]*/));

//Gruppenmember
$ingroupBadezimmer = GetValue(16352 /*[Sonos_Badezimmer\MemberOfGroup]*/);
$ingroupEsszimmer = GetValue(16369 /*[Sonos_Esszimmer\MemberOfGroup]*/);


if($_IPS['VARIABLE'] == 21533 /*[Taste 8 Badezimmer\PRESS_SHORT]*/) 
{
 if($statusEsszimmer == 1 && $statusBadezimmer == 3) 
 { 
    SNS_SetGroup(19980 /*[Sonos_Badezimmer]*/,10049 /*[Sonos_Esszimmer]*/);
    SNS_Play(19980 /*[Sonos_Badezimmer]*/);  
 }  
}


if($_IPS['VARIABLE'] == 21533 /*[Taste 8 Badezimmer\PRESS_SHORT]*/)
{
if($statusBadezimmer == 1 && $ingroupBadezimmer == true) 
 { 
    SNS_SetGroup(19980 /*[Sonos_Badezimmer]*/,0);
    SNS_Stop(19980 /*[Sonos_Badezimmer]*/);
 }  
 if($statusBadezimmer == 1 && $ingroupBadezimmer == false) 
 { 
    SNS_Stop(19980 /*[Sonos_Badezimmer]*/);
 }  
}  



?>

Gibt es hier eventuell Verbesserungsmöglichkeiten?

Jetzt wirds ja dann komplizierter… nun bringe ich einen dritten Player ins Spiel jetzt muss ich ja zwischen 2 suchen welcher gerade läuft und genau diesen auswählen um meinen neuen hinzuzufügen.
Würde man dies ebenfalls nach diesem Schema wieder mit diversen „if bedingungen“ Aufbauen oder gibt es hier eine andere Taktik ?

Vielen dank schonmal für eure sehr Hilfreichen Beiträge.

Liebe Grüße,
Adrian

Ein kleiner Fehler meinerseits…

Ich hatte die andere Software noch am Laufen nun Funktioniert das doch nicht mehr ganz so wie gewünscht :frowning:

Mach da wohl doch irgendetwas falsch.

Spielt bei beiden Lautsprechern Musik ohne das sie in einer Gruppe sind und ich auf die Taste drücke wird der Player im Badezimmer zum Esszimmer hinzugefügt, eigentlich sollte dieser erst einmal ausgeschalten werden und beim erneuten wieder einschalten dann zur Gruppe Esszimmer hinzugefügt werden.

Das Ausschalten bzw. entfernen aus der Gruppe funktioniert so leider garnicht…

Vielleicht schilderst du nochmal Stichpunkt artig wann genau was bei welchem Tastendruck passieren soll und ob es sich um einen normalen Taster oder einen 6fach Taster handelt. Dann kann man Dir auch eher bei dem logischen Aufbau Tipps geben. Momentan bist Du wohl der einzige der weis was genau wann passieren soll.

Also wie viele Player sind es insgesamt? Wann soll welches Szenario greifen, wieviele verschiedene Gruppen Konstellationen gibt es usw.?

Das sollte an sich auch kein Problem sein um Dir da zu helfen musst Du nur eine Klare Vorstellung davon haben wann was passieren soll und was es für Ausnahmen gibt. Entsprechend Deinen Annahmen kann man dann so ein Skript zusammen bauen. Dies wird dann halt sehr individuell, aber wenn es steht bist Du froh wenn es funktioniert.
In dem von Dir geschilderten Fall müsstest Du also erst mal, bevor das Skript etwas macht, prüfen in welchem Zustand die Geräte eigentlich sind und davon abhängig dann erst etwas ausführen. Das was Du Dir im Prinzip im Kopf ausdenkst, wenn ich das mache soll dies passieren, ist nichts anderes als eine weitere If Abfrage.

In Deinem Beispiel müsstest Du also erst mal prüfen ob denn beide Geräte in einer Gruppe sind. Wenn das nicht der Fall ist sendest Du nur einen Stop Befehl an das Gerät im Bad.


if($statusBadezimmer == 1 && $ingroupBadezimmer == true) 

Kann nicht stimmen, die Variable die Du abfragst MemberOfGroup enthält 0 für keine Gruppe und ansonsten einen numerischen Wert für ein Sonos Gerät. Die Variable ist also vom Typ Integer und nicht Boolean (true/false).

Daher müsste die Bedingung eher so aussehen


if($statusBadezimmer == 1 && $ingroupBadezimmer > 0) 

Wenn das Gerät also auf Play ist (1) und Teil einer Gruppe, der Wert der Gruppe muss dann eben nicht 0 sein, dann soll sich das Gerät nur ausschalten.

Ich weis ja nicht wie Du den Taster drücken willst, aber ich gehe mal davon aus das z.B. Tastendruck rauf Play sein soll und Tastendruck runter Stop. Oder willst Du z.B. immer nur nach oben drücken und es soll eben abwechselnd auf Play oder Stop geschaltet werden, je nachdem was für ein Zustand das Gerät zuletzt hatte?

Guten Tag,

Vielen dank für die Antworten.

Im Prinzip geht es um folgendes:

Wir haben Momentan 3 Player, früher oder später 5.
Als Taste verwende ich das 8-Fach Sendemodul von HomeMatic.

Ziel ist es Heim zukommen und alle Player sind aus.
Dann gehe ich ins Badezimmer Drücke dort am Taster die Taste 8, Radio SWR3 z.B. läuft nun.

Anschließend gehe ich in die Küche und drücke dort ebenfalls die Taste 8 Player dort geht an und wird der Gruppe „Badezimmer“ zugewiesen.

Selbes Spiel für Schlafzimmer, Wohnzimmer, Büro…

Nun kann man wieder irgendwo auf die Taste 8 drücken und der Player wird aus der Gruppe entfernt.
Also quasi auf Taste 8 immer ein Toggle Modus.

Spielt jetzt in der Küche SWR3 und im Badezimmer SWR4 z.B.
Dann sollte beim Drücken der Taste 8 im Badezimmer ja erst einmal die Musik ausgehen. Drückt man die Taste erneut, so wird diese wieder dem Player Esszimmer untergeordnet.

Im Regelfall (95%) hören wir überall die selbe Musik.
Trotzdem muss ich ja irgendwie drauf reagieren können wenn bereits 2 Player in einer Gruppe spielen welchem ich den 3ten unterordne, denn soweit ich weis geht das nur mit dem Coordinator.

Liebe Grüße,
Adrian.

Verwendest Du HM-RC-8?

Ich verwende das hier: ELV Homematic Komplettbausatz 8-Kanal-Sendemodul für Smart Home / Hausautomation | ELV-Elektronik

Hier ist die Frage soll immer SWR3 laufen oder willst Du was auswählen, dann lässt sich das schwer mit nur einer Taste realisieren. Wenn immer der gleiche Sender aufgerufen wird geht das auch mit einer Taste.

So als Entwurf die Objekt ID im Define Block müssen halt individuell angepasst werden zum einfachen ein aus schalten wenn das Gerät nicht in einer Gruppe ist.


<?

IPS_LogMessage("Sonos Play/Pause", "Event ".IPS_GetName($_IPS['EVENT'])." (".$_IPS['EVENT']."), Variable ".IPS_GetName($_IPS['VARIABLE'])." (".$_IPS['VARIABLE'].")" ); // Gibt eine Meldung im Meldungsfenster aus

// Festlegen der Gerätebezeichnung, Zuordnung der ObjektID

// Sonos Geräte
define("Sonos_Badezimmer", 28191 /*[Geräte\Heimkino\Audio\Sonos\Sonos Bad]*/);
define("Sonos_Schlafzimmer", 37212 /*[Geräte\Heimkino\Audio\Sonos\Sonos Schlafzimmer]*/);
define("Sonos_Kueche", 51749 /*[Geräte\Heimkino\Audio\Sonos\Sonos Küche]*/);
define("Sonos_Wohnzimmer", 32720 /*[Geräte\Heimkino\Audio\Sonos\Sonos Wohnzimmer]*/);
define("Sonos_Buero", 28191 /*[Geräte\Heimkino\Audio\Sonos\Sonos Büro]*/);
define("Sonos_Esszimmer", 28191 /*[Geräte\Heimkino\Audio\Sonos\Sonos Esszimmer]*/);

// Taster
define("Taste8_Sonos_Badezimmer", 58098 /*[Geräte\Homematic\Räume\Bad\Sonos Taster Bad\PRESS_SHORT]*/);
define("Taste8_Sonos_Schlafzimmer", 44743 /*[Geräte\Homematic\Räume\Schlafzimmer\Sonos Taster Schlafzimmer\PRESS_SHORT]*/);
define("Taste8_Sonos_Kueche", 22579 /*[Geräte\Homematic\Räume\Küche\Sonos Taster Küche\PRESS_SHORT]*/);
define("Taste8_Sonos_Wohnzimmer", 39761 /*[Geräte\Homematic\Räume\Wohnzimmer\Sonos Taster Wohnzimmer\PRESS_SHORT]*/);
define("Taste8_Sonos_Buero", 39761 /*[Geräte\Homematic\Räume\Büro\Sonos Taster Büro\PRESS_SHORT]*/);
define("Taste8_Sonos_Esszimmer", 39761 /*[Geräte\Homematic\Räume\Esszimmer\Sonos Taster Esszimmer\PRESS_SHORT]*/);

//Definition bzw. hohlen diverser Variablen

//Play Status
$statusBadezimmer = GetSonosStatus(Sonos_Badezimmer); // Badezimmer
$statusSchlafzimmer = GetSonosStatus(Sonos_Schlafzimmer); // Schlafzimmer
$statusKueche = GetSonosStatus(Sonos_Kueche); // Küche
$statusWohnzimmer = GetSonosStatus(Sonos_Wohnzimmer); // Wohnzimmer
$statusBuero = GetSonosStatus(Sonos_Buero); // Büro
$statusEsszimmer = GetSonosStatus(Sonos_Esszimmer); // Esszimmer



//Gruppenmember
$ingroupBadezimmer = GetSonosGroup(Sonos_Badezimmer);
$ingroupSchlafzimmer = GetSonosGroup(Sonos_Schlafzimmer);
$ingroupKueche = GetSonosGroup(Sonos_Kueche);
$ingroupWohnzimmer = GetSonosGroup(Sonos_Wohnzimmer);
$ingroupBuero = GetSonosGroup(Sonos_Buero);
$ingroupEsszimmer = GetSonosGroup(Sonos_Esszimmer);


// Auslöser Badezimmer
if($_IPS['VARIABLE'] == Taste8_Sonos_Badezimmer) 
{
	ToggleSonosStatus(Sonos_Badezimmer);
}

// Auslöser Schlafzimmer
if($_IPS['VARIABLE'] == Taste8_Sonos_Schlafzimmer)
{
	ToggleSonosStatus(Sonos_Schlafzimmer);  
}  

// Auslöser Küche
if($_IPS['VARIABLE'] == Taste8_Sonos_Kueche)
{
	ToggleSonosStatus(Sonos_Kueche);    
}  

// Auslöser Wohnzimmer
if($_IPS['VARIABLE'] == Taste8_Sonos_Wohnzimmer)
{
	ToggleSonosStatus(Sonos_Wohnzimmer);  
}  

// Auslöser Büro
if($_IPS['VARIABLE'] == Taste8_Sonos_Buero)
{
	ToggleSonosStatus(Sonos_Buero);
}  

// Auslöser Esszimmer
if($_IPS['VARIABLE'] == Taste8_Sonos_Esszimmer)
{
	ToggleSonosStatus(Sonos_Esszimmer); 
}  

/***********************************************************
 * Helper methods
 ***********************************************************/

 
/* Get Sonos Status
* @param int $sonosname ObjectID
* return string $status
*/
function ToggleSonosStatus($sonosname)
{
	// Wenn nicht in Gruppe
	if((GetSonosStatus($sonosname) == "pause" || GetSonosStatus($sonosname) == "stop") && GetSonosGroup($sonosname) == "none") 
	 { 
	    SNS_Play(Sonos_Badezimmer);  
	 }
	 else
	 {
	 	SNS_Stop(Sonos_Badezimmer);
	 } 
	
	$status = GetValueFormatted(IPS_GetObjectIDByIdent("Status", $sonosname));
	return $status;
}
 
 
/* Get Sonos Status
* @param int $sonosname ObjectID
* return string $status
*/
function GetSonosStatus($sonosname)
{
	$status = GetValueFormatted(IPS_GetObjectIDByIdent("Status", $sonosname));
	return $status;
}

/* Get Sonos Group Name
* @param int $sonosname ObjectID
* return string $groupname
*/
function GetSonosGroup($sonosname)
{
	$groupname = GetValueFormatted(IPS_GetObjectIDByIdent("MemberOfGroup", $sonosname));
	return $groupname; 
}

?>

Grundsätzlich zu togglen mit einer Taste also Play/pause ist nicht das Problem. Wo ich selber mal drüber nachdenken müsste wie ob das das mit Gruppen mit ein und der selben Taste gehen soll, da fällt mir auf Anhieb nichts ein. Das Problem ist, wenn immer das gleiche passieren soll, sprich Du drückst in der Küche, wenn im Bad Musik läuft wird er in die Gruppe ergänzt, mag das ja noch gehen. Aber eine allgemeine Bedienbarkeit, das Du in jedem Raum ein Gerät der passenden Gruppe hinzufügen kannst bzw. wieder aus der Gruppe nimmst und das nur mit einem Knopf stelle ich mir schwer vor aber vielleicht fällt Dir, jemand oder mir da noch was ein.

Hier ist eben die Frage bei mehreren Räumen wie soll da jeweils die Gruppenzuordnung erfolgen. Es gibt also stets nur eine Gruppe und das Gerät soll immer entweder der Gruppe zugeordnet werden wenn nichts läuft?

Die Frage ist halt wenn schon zwei Räume Musik spielen und Du im dritten auch einen Knopf drückst dann soll dieser Raum auch der Gruppe zugeordnet werden und die gleiche Musik spielen, richtig? Soll dann auch aus jedem Raum die Musik insgesamt beendet werden, bei erneuten Knopfdruck und die Gruppe dann wieder automatisch aufgelöst?

Hallo Fonzo,

Vielen dank für das Umfangreiche Skript :slight_smile:

Ja das ist echt eine etwas schwierige Aufgabe Sache…
Ich kenne das eben nur von HVL ( HomeMatic Virtual Layer) so wie genau das dort realisiert wird weis ich allerdings auch nicht genau…
Homematic-Virtual-Interface/plugins/SonosPlugin at master · thkl/Homematic-Virtual-Interface · GitHub

Dort wir soweit ich das jetzt verstehe glaube ich immer alles über den Coordinator gelenkt, also irgendwo im Skript muss wohl durchgegangen werden welcher Player der Coordinator ist somit habe ich dann immer den richtigen Player dann muss ich „nur noch“ den weiteren hinzufügen.

und Anderst rum wenn einer bereits in der Gruppe ist und die Taste gedrückt wird wird dieser wieder entfernt, und ich meine wenn man den Coordinator entfernt wird diese „berechtigung“ einfach an einen anderen weitergegeben.

Gruß,
Ardrian

Also ich weis jetzt nicht ob das so möglich ist, aber wäre es machbar eine Variable zu definieren die sich „Coordinator“ nennt?
Diese Variable füllt man mit einer if Abfrage immer mit der aktuellen Objekt ID des Coordinators bzw. wahrscheinlich geht das mit einer einfach if Abfrage so garnicht?

Und dann könnte man eventuell in dieser Funktion:

SNS_SetGroup(<InstanceID>,<CoordinatorInstanceID>);

Statt einer Statischen ID für „CoordinatorInstanceID“ die Variable „Coordinator“ einsetzen ?
Und im Skript kann ich ja dann theoretisch wieder für jede Taste diese Funktion anlegen.
Somit sollte das ja immer Funktionieren da man nicht über die Festen ObjectID´s geht bzw. nur eine Feste ObjektID definiert hat und zwar diese die man einer Gruppe hinzufügen möchte.

Ist das so denkbar?

Gruß,
Adrian