Sonos in openHAB

Für welche Projekte verwendet Ihr OpenHAB? Was habt Ihr automatisiert? Stellt eure Projekte hier vor.

Moderatoren: Cyrelian, seppy

Antworten
Benutzeravatar
Cyrelian
Beiträge: 601
Registriert: 24. Sep 2015 17:55
Answers: 4

Sonos in openHAB

Beitrag von Cyrelian »

Hallo zusammen,

nach dem ich mir nun nach und nach SONOS Lautsprecher zugelegt habe, war ich auf der Suche, wie ich die am besten in openHAB integrieren kann.
Dabei bin ich auf eine sehr interessante Herangehensweise von Torstein Heien-Sunde gestoßen. Der Sinn dahinter ist, jeden SONOS Lautsprecher, egal wo er sich befindet mit anderen SONOS Lautsprechen zu gruppieren.
Hier dazu erstmal die ITEMS:

Code: Alles auswählen

Group  gSonos	"Sonos Soundsystem"	<sonos> (gSystem)

Group gSonosKitc (gSonos)
Group gSonosBedr (gSonos)
Group gSonosBath (gSonos)
Group gSonosLivi (gSonos)

Group gSonosDoorBellVolu	(gSonos)
Group gSonosDoorBellNotifi	(gSonos)

Group gSonosVolu "Volume"  <soundvolume>	(gSonos)
Group gSonosMute "Mute"    <sonos_mute>		(gSonos)
Group gSonosStop "Stop"    <sonos_stop>		(gSonos) {autoupdate="false"}

String SonosGroupID_Kitc	"Kitchen group [%s]"
String SonosGroupID_Bedr	"Bedroom group [%s]"
String SonosGroupID_Bath	"Bathroom group [%s]"
String SonosGroupID_Livi	"Living room group [%s]"

Number Sonos_Group1_Number "Players in group 1 [%.1f]"
Number Sonos_Group2_Number "Players in group 2 [%.1f]"
Number Sonos_Group3_Number "Players in group 3 [%.1f]"

String Sonos_Group1_Visibility "Group 1 visibility [%s]"
String Sonos_Group2_Visibility "Group 2 visibility [%s]"
String Sonos_Group3_Visibility "Group 3 visibility [%s]"


/* -------------  WOHNZIMMER (EG) --------------------
 */
String EGWZ_Sonos_Add                     "Add [%s]"                  <sonos_add>			(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:add"}
Switch EGWZ_Sonos_SetAlarm                "Set Alarm"                 <sonos_alarm>			(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:alarm"}
String EGWZ_Sonos_AlarmProperties         "Alarm Properties [%s]"     <sonos_alarm_prop>	(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:alarmproperties"}
Switch EGWZ_Sonos_AlarmIsrunning          "Alarm is running"          <sonso_alarm_run>		(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:alarmrunning"}
Player EGWZ_Sonos_Control                 "Control"                   <sonos>				(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:control"}
String EGWZ_Sonos_CurrentAlbum            "Album [%s]"                <sonos_playlist>		(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:currentalbum"}
String EGWZ_Sonos_CurrentArtist           "Artist [%s]"               <sonos_playlist>		(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:currentartist"}
String EGWZ_Sonos_CurrentTitle            "Now playing [%s]"          <sonos_playlist>		(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:currenttitle"}
String EGWZ_Sonos_CurrentTrack            "Track [%s]"                <sonos_playlist>		(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:currenttrack"}
Switch EGWZ_Sonos_Shuffle                 "Shuffle"                   <sonos_shuffle>		(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:shuffle"}
String EGWZ_Sonos_Repeat                  "Repeat [%s]"               <sonos_repeat>		(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:repeat"}
String EGWZ_Sonos_Favorite                "Favorite [%s]"             <sonos_favorite>		(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:favorite"}
Switch EGWZ_Sonos_Led                     "Led"                       <switch>				(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:led"}
Switch EGWZ_Sonos_LocalCoordinator        "Local Coordinator"         <sonos_coordinator>	(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:localcoordinator"}
Switch EGWZ_Sonos_Mute                    "Mute"                      <soundvolume_mute>	(gSonosLivi,gSonosMute)				{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:mute"}
String EGWZ_Sonos_NotificationSound       "Notification Sound [%s]"   <sonos_notification>	(gSonosLivi,gSonosDoorBellNotifi)	{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:notificationsound"}
Dimmer EGWZ_Sonos_Notificationsoundvolume "Notification Sound Volume" <soundvolume>			(gSonosLivi,gSonosDoorBellVolu)		{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:notificationvolume"}
String EGWZ_Sonos_PlayPlaylist            "Play Playlist [%s]"        <sonos_playlist>		(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:playlist"}
Switch EGWZ_Sonos_PlayQueue               "Play Queue"                <sonos_que>			(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:playqueue"}
Number EGWZ_Sonos_PlayTrack               "Play Track"                <sonos_play_track>	(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:playtrack"}
String EGWZ_Sonos_PlayURI                 "Play URI [%s]"             <sonos_play_uri>		(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:playuri"}
Switch EGWZ_Sonos_PublicAddress           "Public Address"            <sonos_publiv>		(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:publicaddress"}
String EGWZ_Sonos_Radio                   "Radio [%s]"                <sonos_radio>			(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:radio"}
String EGWZ_Sonos_Remove                  "Remove [%s]"               <sonos_remove>		(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:remove"}
Switch EGWZ_Sonos_Restore                 "Restore"                   <sonos_restore>		(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:restore"}
Switch EGWZ_Sonos_RestoreAll              "Restore All"               <sonos_restore_all>	(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:restoreall"}
Switch EGWZ_Sonos_Save                    "Save"                      <sonos_save>			(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:save"}
Switch EGWZ_Sonos_SaveAll                 "Save All"                  <sonos_save_all>		(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:saveall"}
Number EGWZ_Sonos_Snooze                  "Snooze"                    <sonos_snooze>		(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:snooze"}
Switch EGWZ_Sonos_StandAlone              "Stand Alone"               <sonos_stand_alone>	(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:standalone"}
String EGWZ_Sonos_State                   "Status [%s]"               <sonos_speaker>       (gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:state"}
Switch EGWZ_Sonos_Stop                    "Stop"                      <sonos_stop>			(gSonosLivi,gSonosStop)				{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:stop", autoupdate="false"}
Dimmer EGWZ_Sonos_Volume                  "Volume [%.1f %%]"          <soundvolume>			(gSonosLivi,gSonosVolu)				{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:volume"}
String EGWZ_Sonos_ZoneGroupID             "Zone Group ID [%s]"        <sonos_zone>			(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:zonegroupid"}
String EGWZ_Sonos_ZoneName                "Zone Name [%s]"            <sonos_zone>			(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:zonename"}
String EGWZ_Sonos_Coordinator             "Coordinator [%s]"          <sonos_coordinator>	(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:coordinator"}
Number EGWZ_Sonos_SleepTimer              "Sleep Timer"               <sonos_sleep_timer>	(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:sleeptimer"}
String EGWZ_Sonos_CurrentAVtransportURI   "AV transport URI [%s]"     <sonos_uri>			(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:currenttransporturi"}
String EGWZ_Sonos_CurrenttrackURI         "track URI [%s]"            <sonos_uri>			(gSonosLivi)						{channel="sonos:PLAY1:RINCON_XXXXXXXXXXXXXXXXX:currenttrackuri"}
Ob man später tatsächlich mal alles benötig.....wer weiß :D .

In der Sitemap kann das dann so aussehen:

Code: Alles auswählen

Frame item=gSonos {
	Default item=EGWZ_Sonos_Control 
	Slider item=EGWZ_Sonos_Volume
	Switch item=EGWZ_Sonos_Mute 
	Switch item=EGWZ_Sonos_Shuffle 
	Switch item=EGWZ_Sonos_Repeat mappings=[ALL="All", ONE="One", OFF="Off"]
	Selection item=EGWZ_Sonos_Radio mappings=[0="None",1="SWR3 Elchradio 91.6"]
	Text item=EGWZ_Sonos_CurrentArtist
	Text item=EGWZ_Sonos_CurrentAlbum
	Text item=EGWZ_Sonos_CurrentTitle
	Text item=EGWZ_Sonos_State	
}
sonos.PNG
Sobald ich die Rules einwandfrei laufen habe, werde ich diese hier ergänzen.

UPDATE...RULES:

Code: Alles auswählen

val String filename = "sonos.rules"

var Timer CheckSinglePlayerTimer = null
var Timer SonosGroupVisibility = null

val Functions$Function6 updateSingleGroups = [
	NumberItem group1_num,
	NumberItem group2_num,
	NumberItem group3_num,
	StringItem player_a_groupID,
	StringItem player_b_groupID,
	StringItem player_a_name | 

	// If the updated player has been grouped to is in the "NONE"-group (or is NULL),
	// find a group with zero players and update status of both players.
	if (player_b_groupID.state=="0" || player_b_groupID.state==NULL) {
		if (group1_num.state==0) {
			postUpdate(player_a_groupID,"1")
			postUpdate(player_b_groupID,"1")
			logInfo(filename, player_a_name + " player + 1 updated to group 1")
		} else if (group2_num.state==0) {
			postUpdate(player_a_groupID,"2")
			postUpdate(player_b_groupID,"2")
			logInfo(filename, player_a_name + " player + 1 updated to group 2")

		} else if (group3_num.state==0) {
			postUpdate(player_a_groupID,"3")
			postUpdate(player_b_groupID,"3")
			logInfo(filename, player_a_name + " player + 1 updated to group 3")
		}
	// Else set the updated player to the group id of the matched player
	} else if (player_a_groupID.state!=player_b_groupID.state) {
		postUpdate(player_a_groupID,player_b_groupID.state)
		logInfo(filename, player_a_name + " player updated to group " + player_b_groupID.state.toString)
	}
	return NULL
]

val Functions$Function6 checkSinglePlayers = [
	StringItem CheckZonegroupID,
	StringItem ZonegroupID_a,
	StringItem ZonegroupID_b,
	StringItem ZonegroupID_c,
	StringItem UpdatePlayer,
	StringItem UpdatePlayerName |

	if (CheckZonegroupID.state!=ZonegroupID_a.state && CheckZonegroupID.state!=ZonegroupID_b.state && CheckZonegroupID.state!=ZonegroupID_c.state) {
		postUpdate(UpdatePlayer,"0")
		logInfo(filename, UpdatePlayerName + "player updated to group 0")
	}
	return NULL
]

///// NUMBER OF PLAYERS IN GROUP
//
//	A simple count of the number of players
//	in each group is made. This is used in
//	various rules, e.g. to determine
//	if a group should be visible in the UI or not.
//
/////////////////////////////////

rule "Sonos number of players in group"
when
	Item SonosGroupID_Kitc received update or
	Item SonosGroupID_Bedr received update or
	Item SonosGroupID_Livi received update or
	Item SonosGroupID_Bath received update
then
	var Number Group_1 = 0
	var Number Group_2 = 0
	var Number Group_3 = 0

	if (SonosGroupID_Kitc.state=="1"){
		Group_1 = Group_1 + 1
	} else if (SonosGroupID_Kitc.state=="2"){
		Group_2 = Group_2 + 1
	} else if (SonosGroupID_Kitc.state=="3"){
		Group_3 = Group_3 + 1
	}

	if (SonosGroupID_Bedr.state=="1"){
		Group_1 = Group_1 + 1
	} else if (SonosGroupID_Bedr.state=="2"){
		Group_2 = Group_2 + 1
	} else if (SonosGroupID_Bedr.state=="3"){
		Group_3 = Group_3 + 1
	}

	if (SonosGroupID_Bath.state=="1"){
		Group_1 = Group_1 + 1
	} else if (SonosGroupID_Bath.state=="2"){
		Group_2 = Group_2 + 1
	} else if (SonosGroupID_Bath.state=="3"){
		Group_3 = Group_3 + 1
	}

	if (SonosGroupID_Livi.state=="1"){
		Group_1 = Group_1 + 1
	} else if (SonosGroupID_Livi.state=="2"){
		Group_2 = Group_2 + 1
	} else if (SonosGroupID_Livi.state=="3"){
		Group_3 = Group_3 + 1
	}

	postUpdate(Sonos_Group1_Number,Group_1)
	postUpdate(Sonos_Group2_Number,Group_2)
	postUpdate(Sonos_Group3_Number,Group_3)
end

///// GROUPING RULES
//
//	The rule will check every other player that the
//	  (1) Group number of the player beeing added corresponds to the player it is beeing added to
//	  (2) Zone-ids are not equal (not already grouped)
//	  (3) That the player beeing checked has a state (not NULL)
//
//	Additional nested logic is required to determine in what direction the player shall be grouped (A to B or B to A).
//	This is a special case that kicks in when both players are single before grouping: It is not possible
//	to add a player that is the local coordinator to a player which is not.
//
/////////////////////////////////


rule "Sonos group kitchen"
when 
	Item SonosGroupID_Kitc received command
then

	// Short sleep to make shure the rule to calculate the number of players in a group has executed before the logic is applied.
	Thread::sleep(300)

	if (SonosGroupID_Kitc.state==SonosGroupID_Bedr.state && SonosGroupID_Kitc.state!="0" && FK_Sonos_ZoneGroupID.state!=SZ_Sonos_ZoneGroupID.state && SZ_Sonos_ZoneGroupID.state!=NULL && ((SZ_Sonos_LocalCoordinator.state==ON) || (FK_Sonos_LocalCoordinator.state==ON && ((SonosGroupID_Kitc.state=="1" && Sonos_Group1_Number.state=="2") || (SonosGroupID_Kitc.state=="2" && Sonos_Group2_Number.state=="2") || (SonosGroupID_Kitc.state=="3" && Sonos_Group3_Number.state=="2"))))){ 
		
		logInfo(filename, "Entered sonos kitchen grouping rule number 1")
		
		if (SZ_Sonos_LocalCoordinator.state==ON){
			SZ_Sonos_Add.sendCommand("RINCON_kitchenplayer")
			logInfo(filename, "Kitchen player added to bedroom")
		} else if (FK_Sonos_LocalCoordinator.state==ON && ((SonosGroupID_Kitc.state=="1" && Sonos_Group1_Number.state=="2") || (SonosGroupID_Kitc.state=="2" && Sonos_Group2_Number.state=="2") || (SonosGroupID_Kitc.state=="3" && Sonos_Group3_Number.state=="2"))) {
			FK_Sonos_Add.sendCommand("RINCON_bedroomplayer")
			logInfo(filename, "bedroom player added to kitchen")
		}

	} else if (SonosGroupID_Kitc.state==SonosGroupID_Bath.state && SonosGroupID_Kitc.state!="0" && FK_Sonos_ZoneGroupID.state!=BD_Sonos_ZoneGroupID.state && BD_Sonos_ZoneGroupID.state!=NULL && ((BD_Sonos_LocalCoordinator.state==ON) || (FK_Sonos_LocalCoordinator.state==ON && ((SonosGroupID_Kitc.state=="1" && Sonos_Group1_Number.state=="2") || (SonosGroupID_Kitc.state=="2" && Sonos_Group2_Number.state=="2") || (SonosGroupID_Kitc.state=="3" && Sonos_Group3_Number.state=="2"))))){ 
		
		logInfo(filename, "Entered sonos kitchen grouping rule number 2")
		
		if (BD_Sonos_LocalCoordinator.state==ON){
			BD_Sonos_Add.sendCommand("RINCON_kitchenplayer")
			logInfo(filename, "Kitchen player added to bathroom")
		} else if (FK_Sonos_LocalCoordinator.state==ON && ((SonosGroupID_Kitc.state=="1" && Sonos_Group1_Number.state=="2") || (SonosGroupID_Kitc.state=="2" && Sonos_Group2_Number.state=="2") || (SonosGroupID_Kitc.state=="3" && Sonos_Group3_Number.state=="2"))) {
			FK_Sonos_Add.sendCommand("RINCON_bathroomplayer")
			logInfo(filename, "Bathroom player added to kitchen")
		}

	} else if (SonosGroupID_Kitc.state==SonosGroupID_Livi.state && SonosGroupID_Kitc.state!="0" && FK_Sonos_ZoneGroupID.state!=WZ_Sonos_ZoneGroupID.state && WZ_Sonos_ZoneGroupID.state!=NULL && ((WZ_Sonos_LocalCoordinator.state==ON) || (FK_Sonos_LocalCoordinator.state==ON && ((SonosGroupID_Kitc.state=="1" && Sonos_Group1_Number.state=="2") || (SonosGroupID_Kitc.state=="2" && Sonos_Group2_Number.state=="2") || (SonosGroupID_Kitc.state=="3" && Sonos_Group3_Number.state=="2"))))){ 
		
		logInfo(filename, "Entered sonos kitchen grouping rule number 3")
		
		if (WZ_Sonos_LocalCoordinator.state==ON){
			WZ_Sonos_Add.sendCommand("RINCON_kitchenplayer")
			logInfo(filename, "Kitchen player added to living room")
		} else if (FK_Sonos_LocalCoordinator.state==ON && ((SonosGroupID_Kitc.state=="1" && Sonos_Group1_Number.state=="2") || (SonosGroupID_Kitc.state=="2" && Sonos_Group2_Number.state=="2") || (SonosGroupID_Kitc.state=="3" && Sonos_Group3_Number.state=="2"))) {
			FK_Sonos_Add.sendCommand("RINCON_livingroomplayer")
			logInfo(filename, "Living room player added to Kitchen")
		}

	} else {
		FK_Sonos_StandAlone.sendCommand("ON")
		logInfo(filename, "Kitchen player set to stand alone")
	}
end

//// UPDATE GROUPING RULES
//
//	The rules will update the appropiate group
//	when a sonos player is grouped, either
//  in the OH2 UI or within the Sonos app.
//	
/////////////////////////////////

rule "Sonos update group membership bathroom"
when
	Item BD_Sonos_ZoneGroupID changed
then
	if (BD_Sonos_ZoneGroupID.state==FK_Sonos_ZoneGroupID.state && FK_Sonos_ZoneGroupID.state!=NULL) {
		updateSingleGroups.apply(Sonos_Group1_Number, Sonos_Group2_Number, Sonos_Group3_Number, SonosGroupID_Bath, SonosGroupID_Kitc, "Bathroom")

	} else if (BD_Sonos_ZoneGroupID.state==SZ_Sonos_ZoneGroupID.state && SZ_Sonos_ZoneGroupID.state!=NULL) {
		updateSingleGroups.apply(Sonos_Group1_Number, Sonos_Group2_Number, Sonos_Group3_Number, SonosGroupID_Bath, SonosGroupID_Bedr, "Bathroom")

	} else if (BD_Sonos_ZoneGroupID.state==WZ_Sonos_ZoneGroupID.state && WZ_Sonos_ZoneGroupID.state!=NULL) {
		updateSingleGroups.apply(Sonos_Group1_Number, Sonos_Group2_Number, Sonos_Group3_Number, SonosGroupID_Bath, SonosGroupID_Livi, "Bathroom")

	// The zone-id changed, but is not grouped with any other players (removed from group).
	// To allow grouping in the UI without the state being reset to single, a timer is applied.
	// This works since grouping in both the OH UI and the Sonos app usually is not performed simultaneously.
	} else {
		if (CheckSinglePlayerTimer==null) {
			CheckSinglePlayerTimer = createTimer(now.plusSeconds(20), [|
				checkSinglePlayers.apply(BD_Sonos_ZoneGroupID, FK_Sonos_ZoneGroupID, SZ_Sonos_ZoneGroupID, WZ_Sonos_ZoneGroupID, SonosGroupID_Bath,"Bathroom")
				checkSinglePlayers.apply(FK_Sonos_ZoneGroupID, BD_Sonos_ZoneGroupID, SZ_Sonos_ZoneGroupID, WZ_Sonos_ZoneGroupID, SonosGroupID_Kitc,"Kitchen")
				checkSinglePlayers.apply(SZ_Sonos_ZoneGroupID, BD_Sonos_ZoneGroupID, FK_Sonos_ZoneGroupID, WZ_Sonos_ZoneGroupID, SonosGroupID_Bedr,"Bedroom")
				checkSinglePlayers.apply(WZ_Sonos_ZoneGroupID, BD_Sonos_ZoneGroupID, FK_Sonos_ZoneGroupID, SZ_Sonos_ZoneGroupID, SonosGroupID_Livi,"Living room")
				CheckSinglePlayerTimer = null
			])
			logInfo(filename, "CheckSinglePlayerTimer scheduled")
		} else {
			CheckSinglePlayerTimer.reschedule(now.plusSeconds(20))
			logInfo(filename, "CheckSinglePlayerTimer rescheduled")
		}
	}
end

///// GROUP VISIBILITY
//
//	The rule is used to control the UI.
//  Specifically, it used to determin
//  if a group should be hidden and if
//  no, which player is to be shown within
//  the group. This has to be the local
//	coordinator in the group.
// 
/////////////////////////////////

rule "Sonos group visibility"
when
	Item SonosGroupID_Kitc received update or
	Item SonosGroupID_Bedr received update or
	Item SonosGroupID_Bath received update or
	Item SonosGroupID_Livi received update 
then
	if (SonosGroupVisibility==null) {
		SonosGroupVisibility = createTimer(now.plusSeconds(5), [ |

			if (Sonos_Group1_Number.state<=1){
				postUpdate(Sonos_Group1_Visibility,"Hide")

			} else if (Sonos_Group1_Number.state>=2){
				if (SonosGroupID_Kitc.state=="1" && FK_Sonos_LocalCoordinator.state==ON){
					postUpdate(Sonos_Group1_Visibility,"Kitchen")
				} else if (SonosGroupID_Bedr.state=="1" && SZ_Sonos_LocalCoordinator.state==ON){
					postUpdate(Sonos_Group1_Visibility,"Bedroom")
				} else if (SonosGroupID_Bath.state=="1" && BD_Sonos_LocalCoordinator.state==ON){
					postUpdate(Sonos_Group1_Visibility,"Bathroom")
				} else if (SonosGroupID_Livi.state=="1" && WZ_Sonos_LocalCoordinator.state==ON){
					postUpdate(Sonos_Group1_Visibility,"Living room")
				}
			}

			if (Sonos_Group2_Number.state<=1){
				postUpdate(Sonos_Group2_Visibility,"Hide")
			} else if (Sonos_Group2_Number.state>=2){
				if (SonosGroupID_Kitc.state=="2" && FK_Sonos_LocalCoordinator.state==ON){
					postUpdate(Sonos_Group2_Visibility,"Kitchen")
				} else if (SonosGroupID_Bedr.state=="2" && SZ_Sonos_LocalCoordinator.state==ON){
					postUpdate(Sonos_Group2_Visibility,"Bedroom")
				} else if (SonosGroupID_Bath.state=="2" && BD_Sonos_LocalCoordinator.state==ON){
					postUpdate(Sonos_Group2_Visibility,"Bathroom")
				} else if (SonosGroupID_Livi.state=="2" && WZ_Sonos_LocalCoordinator.state==ON){
					postUpdate(Sonos_Group2_Visibility,"Living room")
				}
			}

			if (Sonos_Group3_Number.state<=1){
				postUpdate(Sonos_Group3_Visibility,"Hide")
			} else if (Sonos_Group3_Number.state>=2){
				if (SonosGroupID_Kitc.state=="3" && FK_Sonos_LocalCoordinator.state==ON){
					postUpdate(Sonos_Group3_Visibility,"Kitchen")
				} else if (SonosGroupID_Bedr.state=="3" && SZ_Sonos_LocalCoordinator.state==ON){
					postUpdate(Sonos_Group3_Visibility,"Bedroom")
				} else if (SonosGroupID_Bath.state=="3" && BD_Sonos_LocalCoordinator.state==ON){
					postUpdate(Sonos_Group3_Visibility,"Bathroom")
				} else if (SonosGroupID_Livi.state=="3" && WZ_Sonos_LocalCoordinator.state==ON){
					postUpdate(Sonos_Group3_Visibility,"Living room")
				}
			}

		])
		logInfo(filename, "SonosGroupVisibility scheduled")
		SonosGroupVisibility = null

	} else {
		SonosGroupVisibility.reschedule(now.plusSeconds(5))
		logInfo(filename, "SonosGroupVisibility rescheduled")
	}
end

val Functions$Function6 sonosGroupAllSetVolume = [
		String trigger,
		String mode,
		Number guesVolume,
		Number bathVolume,
		Number kitcVolume,
		Number liviVolume |

		var Timer SonosTimer_1 = null
		var Timer SonosTimer_2 = null
		var Timer SonosTimer_3 = null
		var Timer SonosTimer_4 = null
		var Timer SonosTimer_5 = null

		logInfo("openhab","Sonos group all and set volume command triggered by "  + trigger + ".")

		if(SonosTimer_1==null) {
			SonosTimer_1 = createTimer(now.plusSeconds(1), [|
				sendCommand(Sonos_Gues_StandAlone,ON)
				logInfo("openhab","Guest room player set to stand alone")
				SonosTimer_1 = null
			])
		}else {
			SonosTimer_1.reschedule(now.plusSeconds(1)
		}

		if(SonosTimer_2==null) {
			SonosTimer_2 = createTimer(now.plusSeconds(3), [|
				sendCommand(Sonos_Gues_Add,"RINCON_KITCHEN")
				logInfo("openhab","Kitchen player added to guest room")
				SonosTimer_2 = null
			])
		}else {
			SonosTimer_2.reschedule(now.plusSeconds(3)
		}

		if(SonosTimer_3==null) {
			SonosTimer_3 = createTimer(now.plusSeconds(5), [|
				sendCommand(Sonos_Gues_Add,"RINCON_GUESTROOM")
				logInfo("openhab","Bathroom player added to guest room")
				SonosTimer_3 = null
			])
		}else {
			SonosTimer_3.reschedule(now.plusSeconds(5)
		}

		if(SonosTimer_4==null) {
			SonosTimer_4 = createTimer(now.plusSeconds(7), [|
				sendCommand(Sonos_Gues_Add,"RINCON_LIVINGROOM")
				logInfo("openhab","Living room player added to guest room")
				SonosTimer_4 = null
			])
		}else {
			SonosTimer_4.reschedule(now.plusSeconds(7)
		}
		
		if(SonosTimer_5==null) {
			SonosTimer_5 = createTimer(now.plusSeconds(9), [|
				if(mode=="notification") {
					sendCommand(gSonosStop,ON)
					sendCommand(Sonos_Kitc_Notificationsoundvolume,kitcVolume)
					sendCommand(Sonos_Gues_Notificationsoundvolume,guesVolume)
					sendCommand(Sonos_Livi_Notificationsoundvolume,liviVolume)
					sendCommand(Sonos_Bath_Notificationsoundvolume,bathVolume)

				}else if(mode=="normal") {
					sendCommand(Sonos_Kitc_Volume,kitcVolume)
					sendCommand(Sonos_Gues_Volume,guesVolume)
					sendCommand(Sonos_Livi_Volume,liviVolume)
					sendCommand(Sonos_Bath_Volume,bathVolume)
				}

				SonosTimer_5 = null
			])

		}else {
			SonosTimer_5.reschedule(now.plusSeconds(9)
		}
		return NULL
]

.....to be continued
CYA
Cyrelian
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

ibot1989
Beiträge: 99
Registriert: 30. Jul 2016 19:51
Wohnort: östlich von Hamburg, südlich von Lübeck, nördlich von Geesthacht

Re: Sonos in openHAB

Beitrag von ibot1989 »

Cooles Projekt.

Hast du deine Rules mittlerweile fertig überarbeitet und kannst diese hier ergänzen?

Benutzeravatar
Cyrelian
Beiträge: 601
Registriert: 24. Sep 2015 17:55
Answers: 4

Re: Sonos in openHAB

Beitrag von Cyrelian »

Hi Ibot,

bin noch nicht dazu gekommen....finde immer wieder andere spannende Projekte :D . Aber ich setze mich bei Gelegenheit nochmal dran.

CU
Cyrelian

Antworten