Die Vorgeschichte:
Nachdem ich die Bose Soundtouch Lautsprecher (habe inzwischen 4) erfolgreich in mein Smarthome intergriert habe, und diese auch erfolgreich liefen, habe ich mal die dafür erstellten Programme und Systemvariablen durchgezählt und kam auf sage und schreibe 12 Programme und 23 Variablen.
Das war mir zu viel und sorgte immer wieder für Verwirrung bei Anpassungen. Aber so ist es leider, wenn man immer mal eben schnell anbaut und es trotzdem dauerhaft funktioniert.
Jedenfalls habe ich mal gesammelt, gebündelt und umstrukturiert und programmiert.
Ich war selbst erstaunt: Ich habe nur noch ein Programm und eine Systemvariable.
Man muss aber dazu sagen, dass ich auf das Auslesen des Aktuellen Tracks verzichte. (Seit dem Bose Plugin für Mediola NEO benötige ich das nicht mehr.
Meine Soundtouch Anforderungen:
Wenn bei uns zu Hause (Zwei-Personen Haushalt) Musik läuft, dann immer in allen Räumen das gleiche.
Die Soundtouch geht an wenn jemand nach hause kommt und geht aus wenn alle aus dem Haus sind.
Genau so ist es wenn der Fernseher eingeschaltet wird: TV an -> Musik aus, TV aus -> Musik an.
Nachdem abends dann die Nachttischlampen aus sind, geht die Musik zu schlafen aus und morgens mit dem Wecker wieder an.
Ihr merkt schon. Bei uns läuft immer Musik so lange jemand zu hause ist und nicht schläft oder TV guckt.
Und abhängig von Tageszeit, Helligkeit, Wochentag, Gästen usw. andere Presets.
Changelog:
v2.180922
- Das Ausschalten der Slaves wurde wieder hinzugefügt (Logikfehler)
v2.180904
- Lautstärkeregelung für jedes Preset & jeden Lautsprecher Definierbar
- Optional: Soll Lautstärke bei einem Presetwechsel geändert oder beibehalten werden
v2.180824
- Neue Versionierunsbezeichnung
- Neudesign des Codes
- Ausschalten optimiert
- aus SV Wert "aus" wurde "Aus"
- Die Name der Systemvariable kann frei gewählt werden
- Klingelfunktion wurde entfernt
v1.4 (22.08.2017)
- Es gibt einen Definitionsbereich. Änderungen außerhalb dieses
Bereichs sind nicht mehr notwendig
- Die Slaves werden nur noch im Definitionsbereich definiert.
- Sind keine Slaves definiert, findet auch kein Koppeln statt
- SHUFFLE und REPEAT_ALL sind definierbar
- Klingelfunktion wurde hinzugefügt:
Wird ein Klingelsensor verwendet und mit Soundtouch angesteuert,
kann ein Preset für die Klingel definiert werden. Dies kann dann
mit einer eigenen Lautstärke pro device gestartet werden.
v1.3
- Beim Start des Skripts wird geprüft welche Soundtouch
bereits an ist und in einer Booleal wariabel ablegelt
- Beim ausschlaten wird jede Soundtouch ausgeschlatet,
für den Fall, dass eine Soundtouch ohne Master betrieben wurde
- Beim Einschalten werden nur Slaves gekoppelt,
die vorher nicht an waren
v1.2
- SystemVariable in Status.Soundtouch umbenannt
- Status "0" in "aus" umbenannt
v1.1
- prüfen ob Soundtouch vorher schon an war,
dann alle einstellungen (Lautstärke, Slaves) beibehalten
- Durch Preset 0 Soundtouch ausschalten
- SystemVariable von String zu Werteliste geändert
Meine Lösung:
Ich habe nur noch eine Systemvariable mit dem Namen Status.Soundtouch. Eine Werteliste mit den Zahlen von 1-6 und "Aus" (Das Bild ist aus einer Älteren Version):
"1"-"6" sind meine Presets und "Aus" heisst ausschalten.
In einem anderen Programm, in dem ich dann z.B. die Musik wieder einschalten möchte,
wähle ich die Systemvariable ST.Preset aus und gebe mein Wunschpreset an.
Kommen wir nun zum eigentlichen Programm:
Mein Programm ist Systemintern und heißt Musik und sieht so aus:
Ändert sich meine Systemvariable springt wird das Programm "aktiv" und führt das folgende Skript aus:
Ich hab mir mühe gegeben, alles soweit es geht zu kommentieren.
(Die CUxD Adresse ist CUxD.CUX2801001:1 wie man unschwer im Skript erkennen kann.)
Code: Alles auswählen
!*******************************************************************************
!** Bose Soundtouch HomeMatic-Script V2.180922
!** by TobiNedo
!** 22.09.2018
!**
!** Durch wählen eines Presets aus der Werteliste einer
!** Systemwariablen werden alle im Script enthaltenen
!** SoundTouch Geräte eingeschaltet, synchronisiert auf eine
!** individuell für jedes Gerät vorgegebene Lautstärke gesetzt und
!** nach wunsch SHUFFLE_ON und REPEAT_ALL aktiviert.
!**
!** Verwendete Homematic Systemvariablen:
!** Werteliste (Name im Definitionsbereich angeben)
!** - Aus;1;2;3;4;5;6
!** - "Aus" wird jetzt groß geschrieben ;)
!**
!** Voraussetzungen:
!** - Feste IP-Adressen für Soundtouch-Geräte
!** - Definierte Presets
!** - CUxD muss auf der CCU installiert sein
!** - CUxD Adresse von Soundtouch
!**
!** Inspiriert durch fraat:
!** https://homematic-forum.de/forum/viewtopic.php?f=37&t=29122
!*******************************************************************************
!*******************************************************************************
!************************** START DEFINITIONSBEREICH ***************************
!*******************************************************************************
!Name der Systemvariable mit Werteliste
var sv_Werteliste = "Status.Soundtouch.Preset";
!Soll die Lautstärke mit einem Preset Wechsel
!neu gesetzt (true) oder beibehalten (false) werden?
boolean change_Volume = true;
!Master und Slaves Definieren:
!Die Device ID findet man unter http://<<SoundtouchIP>>:8090/now_playing
!Master bestimmen:
var ST_Master_IP = "192.168.178.29";
var ST_Master_DeviceID = "EC1127B0xxxx";
!Volume für den Master für einzelne Presets 0-100
!Schreibweise: "Preset1,Preset2,...,Preset6";
var ST_Master_Volume = "30,30,15,30,30,30";
!Slaves bestimmen:
!Schreibweise: "IP-Adresse,DeviceID,Volume Preset1,Volume Preset2,...,Lautstärke Preset6;";
!Der Letzte darf kein ";" innerhalb der Anführungszeichen und statt dem "+" ein ";" enthalten.
!Wenn keine Slaves vorhanden: "";
!Schlafzimmer, Badezimmer, Wintergarten, Ankleidezimmer, Wohnzimmer
string ST_Slaves = "192.168.178.27,EC24B8E8xxxx,25,25,15,25,25,25;"+
"192.168.178.25,EC24B8Cxxxx,30,30,15,30,30,30;"+
"192.168.178.35,C4F31270xxxx,25,25,15,25,25,25;"+
"192.168.178.23,EC24B8Cxxxx,30,30,15,30,30,30;"+
"192.168.178.37,04A316B5xxxx,25,25,15,25,25,25";
!Liste der Presets, die mit einer REPEAT_ALL Funktion gestartet werden sollen
var repeat_list = "4,5,6";
!Liste der Presets, die mit einer SCHUFFLE_ON Funktion gestarte werden sollen
var shuffle_list = "4,5,6";
!*******************************************************************************
!*************************** ENDE DEFINITIONSBEREICH ***************************
!*******************************************************************************
WriteLine("Definition CHECK");
!gewünschtes Soundtouch Preset aus Systemvariable holen und setzen
var ST_Preset = web.webGetValueFromList(dom.GetObject(sv_Werteliste).ValueList(),dom.GetObject(sv_Werteliste).Value());
boolean ST_Master_Status;
string ST_Slave; !ST_Slave.StrValueByIndex(",", 0) 0=IP, 1=ID, 2=Volume1, 3=Volume2
!Zählen wieviele Slaves vorhanden sind
integer ST_Slavecount = 0;
foreach(ST_Slave, ST_Slaves.Split(";")) {
ST_Slavecount = ST_Slavecount+1;
}
!Überprüfen ob der Master bereits eingeschlatet ist
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State("/usr/local/addons/cuxd/curl -s -k -L http://" # ST_Master_IP #":8090/now_playing");
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
if(dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State().Find("STANDBY") != "-1"){ ST_Master_Status = false; }
else { ST_Master_Status = true; }
if (ST_Preset == "Aus") {
!Wenn Master bereits eingeschlatet war
if (ST_Master_Status == true) {
!Virtuellen Powerbutton drücken
string CurlCmd='/usr/local/addons/cuxd/curl --data "<key state="press" sender="Gabbo">POWER</key>" http://' # ST_Master_IP # ':8090/key';
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State(CurlCmd);
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
!Virtuellen Powerbutton loslassen
string CurlCmd='/usr/local/addons/cuxd/curl --data "<key state="release" sender="Gabbo">POWER</key>" http://' # ST_Master_IP # ':8090/key';
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State(CurlCmd);
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
}
!Slaves ausschlaten
if(ST_Slavecount >= 1) {
foreach(ST_Slave, ST_Slaves.Split(";")) {
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State("/usr/local/addons/cuxd/curl -s -k -L http://" # ST_Slave.StrValueByIndex(",", 0) #":8090/now_playing");
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
if(dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State().Find("STANDBY") == "-1"){
!Virtuellen Powerbutton drücken
string CurlCmd='/usr/local/addons/cuxd/curl --data "<key state="press" sender="Gabbo">POWER</key>" http://' # ST_Slave.StrValueByIndex(",", 0) # ':8090/key';
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State(CurlCmd);
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
!Virtuellen Powerbutton loslassen
string CurlCmd='/usr/local/addons/cuxd/curl --data "<key state="release" sender="Gabbo">POWER</key>" http://' # ST_Slave.StrValueByIndex(",", 0) # ':8090/key';
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State(CurlCmd);
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
}
}
}
}
else{
!ST_Master mit Preset einschalten Einschalten
!Preset in Soundtouch-Key wandeln
var tmp_Key = "PRESET_" + ST_Preset;
!Soundtouch-Key auf ST_Master ausführen
string CurlCmd='/usr/local/addons/cuxd/curl --data "<key state="press" sender="Gabbo">' # tmp_Key # '</key>" http://' # ST_Master_IP # ':8090/key';
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State(CurlCmd);
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
!SoundTouch-Key auf ST_Master beenden
string CurlCmd='/usr/local/addons/cuxd/curl --data "<key state="release" sender="Gabbo">' # tmp_Key # '</key>" http://' # ST_Master_IP # ':8090/key';
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State(CurlCmd);
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
if ((ST_Master_Status == false) || (change_Volume == true)) {
!ST_Master Lautstärke setzen
string CurlCmd='/usr/local/addons/cuxd/curl --data "<volume>' # ST_Master_Volume.StrValueByIndex(",", ST_Preset.ToInteger() - 1) # '</volume>" http://' # ST_Master_IP # ':8090/volume';
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State(CurlCmd);
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
}
!Slaves koppeln
if(ST_Slavecount >= 1) {
foreach(ST_Slave, ST_Slaves.Split(";")) {
!Prüfen ob Slave eingeschlatet ist
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State("/usr/local/addons/cuxd/curl -s -k -L http://" # ST_Slave.StrValueByIndex(",", 0) #":8090/now_playing");
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
if(dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State().Find("STANDBY") != "-1"){
if (ST_Master_Status == false) {
!Slave mit Master koppeln
dom.GetObject("CUxD.CUX2801001:1.CMD_EXEC").State("LD_LIBRARY_PATH=/usr/local/addons/cuxd /usr/local/addons/cuxd/curl -d '<zone master='" # ST_Master_DeviceID # "'>
<member ipaddress='" # ST_Slave.StrValueByIndex(",", 0) # "'>" # ST_Slave.StrValueByIndex(",", 1) # "</member>
</zone>' http://" # ST_Master_IP # ":8090/setZone");
}
}
if((ST_Master_Status == false) || (change_Volume == true)){
!Lautstärke des Slaves setzen
string CurlCmd='/usr/local/addons/cuxd/curl --data "<volume>' # ST_Slave.StrValueByIndex(",", ST_Preset.ToInteger() + 1) # '</volume>" http://' # ST_Slave.StrValueByIndex(",", 0) # ':8090/volume';
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State(CurlCmd);
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
}
}
}
!ST_Master auf SHUFFLE_ON und REPEAT_ALL setzen
!Shuffle bestimmen
var shuffle_check;
boolean shuffle = false;
foreach(shuffle_check, shuffle_list.Split(",")) {
if (shuffle_check == ST_Preset) {shuffle = true;}
}
if(shuffle) {
!Soundtouch-Key auf ST_Master ausführen
string CurlCmd='/usr/local/addons/cuxd/curl --data "<key state="press" sender="Gabbo">SHUFFLE_ON</key>" http://' # ST_Master_IP # ':8090/key';
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State(CurlCmd);
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
!SoundTouchKey auf ST_Master beenden
string CurlCmd='/usr/local/addons/cuxd/curl --data "<key state="release" sender="Gabbo">SHUFFLE_ON</key>" http://' # ST_Master_IP # ':8090/key';
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State(CurlCmd);
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
!SoundTouch-Key für NEXT_TRACK, dass es nicht immer mit dem gleichen Track startet
!Soundtouch-Key auf ST_Master ausführen
string CurlCmd='/usr/local/addons/cuxd/curl --data "<key state="press" sender="Gabbo">NEXT_TRACK</key>" http://' # ST_Master_IP # ':8090/key';
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State(CurlCmd);
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
!SoundTouchKey auf ST_Master beenden
string CurlCmd='/usr/local/addons/cuxd/curl --data "<key state="release" sender="Gabbo">NEXT_TRACK</key>" http://' # ST_Master_IP # ':8090/key';
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State(CurlCmd);
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
}
!SoundTouch-Key für REPEAT_ALL
!Repeat Bestimmen
var repeat_check;
boolean repeat = false;
foreach(repeat_check, shuffle_list.Split(",")) {
if (repeat_check == ST_Preset) {repeat = true;}
}
if(repeat) {
!Soundtouch-Key auf ST_Master ausführen
string CurlCmd='/usr/local/addons/cuxd/curl --data "<key state="press" sender="Gabbo">REPEAT_ALL</key>" http://' # ST_Master_IP # ':8090/key';
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State(CurlCmd);
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
!SoundTouchKey auf ST_Master beenden
string CurlCmd='/usr/local/addons/cuxd/curl --data "<key state="release" sender="Gabbo">REPEAT_ALL</key>" http://' # ST_Master_IP # ':8090/key';
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State(CurlCmd);
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
}
}
Inspiriert durch:
viewtopic.php?f=37&t=29122
DANKE!