In this example a Google Home device which works as a Chromecast Audio device and is located in the bathroom of the house starts playing (a preferred) stream as soon as someone enters the room -> motion is detected.
The challenge is to not start the stream again and again when new motion is detected but the device is already playing something (i.e. because the stream was already started or a different stream is [i.e. via Audiogroup] is already playing.
What you need for this tutorial:
- OH 2 & Chromecast Binding set up
- Google Home Mini or other Chromecast Audio device in your selected room
- Motion Detector in your selected room
- A URL you want to stream or alternatively a mp3 file stored in the sounds subfolder of your configration (i.e. /etc/openhab2/sounds/mysound.mp3)
Thing definition (Google Home / Chromecast device):
file: chromecast.things
chromecast:audio:Floor [ ipAddress="192.168.1.220" ]
chromecast:audio:Office [ ipAddress="192.168.1.217" ]
chromecast:audio:Bath [ ipAddress="192.168.1.216" ]
/* Chromecast Audio Group for my Google Home Mini's */
/* must define this group in your Google Home App on the same device you point to here*/
chromecast:audiogroup:House [ ipAddress="192.168.1.220", port=42576]
Now set up your groups & items for the Chromecast device
/* Assistenten (Alexa, Google Home, ...) */
Group gAssistenten "Assitenten" <computer>
// Google Home Mini Bathroom - minimum items required for this tutorial
Dimmer Google_Home_Bath_Volume "GH Bath Volume " <soundvolume> (gAssistenten) { channel="chromecast:audio:Bath:volume" }
Player Google_Home_Bath_Player "GH Bath Player" (gAssistenten) { channel="chromecast:audio:Bath:control" }
Switch Google_Home_Bath_Idle "GH Bath Idle" <network> (gAssistenten) { channel="chromecast:audio:Bath:idling" }
and here are other items I make use of, defined in my items file:
// Power Switch - You need to adapt this to your setup - this is the power switch I turn on in case the Google Home is not already switched on
Switch Switch_DG_Bath_Google_Home "Google Home Bath" <recorder> (gAssistenten) [ "Switchable" ] { knx="<6/0/1" }
// Motion Detector
Switch Motion_DG_Bath "Motion Bath" <presence> (Motion_DG) { knx="<16/0/0" }
// Groups for motion detector
Group Motion "Motion" <present> (All)
Group Motion_DG "Motion Upper Level" <present> (Motion)
… and finally the rules which turn on the Google Home and start the stream (motion_sensors.rules)
var Timer TimerPlayStream = null
// this rule will turn on the GH device and start a stream
rule "Motion Bath DG"
when
Item Motion_DG_Bath received command
then
if(receivedCommand===ON) {
// Motion has been detected in the bathroom
if (Switch_DG_Bath_Google_Home.state===OFF){
//switch on Google Home (power switch)
sendCommand(Switch_DG_Bath_Google_Home, ON)
// because the booting of the Google Home takes in my case between 25 and 45 seconds we need to wait before we can start a stream
if (TimerPlayStream!==null)
TimerPlayStream.cancel()
TimerPlayStream = createTimer(now.plusSeconds(20)) [|
logInfo("RULE.SWITCH_ON_STREAM", "Timer - Google Home Bath Idle status -> " + Google_Home_Bath_Idle.state.toString())
while(Google_Home_Bath_Idle.state===ON) {
logInfo("RULE.SWITCH_ON_STREAM", "While Loop - Google Home Bath Idle status -> " + Google_Home_Bath_Idle.state.toString())
// we now try to start the stream, in case this is sucessful the Google_Home_Bath_Idle will switch to OFF (and we leave the While Loop)
// this example will start the german radio station Deutschlandfunk
playStream("chromecast:audio:Bath","http://st01.dlf.de/dlf/01/128/mp3/stream.mp3")
logInfo("RULE.SWITCH_ON_STREAM", "Stream send now sleep 1.5 seconds" )
Thread::sleep(1500)
}
]
}
// in case the power is already on and our Google Home should be started already, we only want to start the stream
else {
// Only start the stream if it is not already playing - so we check the state of the Player item
// we need to check != PLAY because when you startup OH the Play may not be initialized and thus the item state is not PAUSE
if (Google_Home_Bath_Player.state!==PLAY) {
// start the stream because Google Home is not playing anything right now -> Deutschlandfunk
playStream("chromecast:audio:Bath","http://st01.dlf.de/dlf/01/128/mp3/stream.mp3")
// alternatively you can start your own mp3 file
//playSound("chromecast:audio:Bath","mysound.mp3")
// I was not successful using the say command on a specified audio sink - per documentation it should work like this:
//say("Hello, welcome in the bathroom","voicerss:deDE","chromecast:audio:Bath")
}
}
} else if(receivedCommand===OFF) {
// at this time we do not do anything here
}
end
// when someone put the power off we force/switch the Player item to PAUSE, as it does not get initialized in PAUSE state when the the Google Home is booting
rule "Google Home Bath Power Off"
when
/* Google Home switch off */
Item Steckdose_DG_Bath_Waschbacken_Unten changed from ON to OFF
then
// need to set the player to Pause, so next time it is in the right state when we start
sendCommand(Google_Home_Bath_Player,PAUSE)
end
/* Is the Google Home busy ? - just logging the state changes - not needed for the example to work*/
rule "GH Bath Idle has changed"
when
Item Google_Home_Bath_Idle changed
then
logInfo("RULE.AUDIO", "Google Home Bath Idle changed! ->" + Google_Home_Bath_Idle.state.toString())
end
Please note I do not have a stopping of the Google Home streaming in this example as this can be done easily by applying a timer to either the motion detection (i.e. when turned of, reschedule everytime it is turned off) or by a timer when the stream is started.
I did translate my rules/items/things from German to English for this tutorial and hope I did not miss any translation so that the setup is working out of the box.
If you find and error please let me know so that I can update this tutorial.
If you have further suggerstions let me know and I can try to include them here as well. (i.e. I was thinking of playing a different stream depending on the time of the day or changing the volume of the stream based on time [no loud music after 10:00 pm])
Hope this helps others.