Alarm clock with Bose Soundtouch

One of the biggest missing feature of the Soundtouch system is the ability to program an alarm on it.
I solved this integrating my soundtouch system in openHAB and controlling it from there, including time to switch on and volume ramping
To run this, you need a working installation of openHAB 2, at least one soundTouch system and its working binding

i will simply add a series of switche and selectors to choose the time, the day, and if the alarm is enabled

first of all we define the soundtouch items (you dont need all these for the alarm, but this is my actual setup)
soundtouch.items

//SOUNDTOUCH
Switch  SoundTouch_OnOff                      "Power: [%s]"          <onoff_monochrome>  (Sala, Home)    { channel="bosesoundtouch:30:000C8A7E7A1C:power" } 
Dimmer  SoundTouch_Volume                     "Volume: [%d %%]"      <soundvolume>    (Sala)  { channel="bosesoundtouch:30:000C8A7E7A1C:volume" }
String  SoundTouch_nowPlayingStationName  "Channel: [%s]" <speaker>   (Sala)     { channel="bosesoundtouch:30:000C8A7E7A1C:nowPlayingStationName" }
String  SoundTouch_nowPlayingArtist  "Artist: [%s]" <speaker>   (Sala)     { channel="bosesoundtouch:30:000C8A7E7A1C:nowPlayingArtist" }
String  SoundTouch_nowPlayingTrack  "Track: [%s]" <speaker>   (Sala)     { channel="bosesoundtouch:30:000C8A7E7A1C:nowPlayingTrack" }
String  SoundTouch_nowPlayingAlbum  "Album: [%s]" <speaker>   (Sala)     { channel="bosesoundtouch:30:000C8A7E7A1C:nowPlayingAlbum" }
Number  SoundTouch_preset  <speaker>   (Sala)     { channel="bosesoundtouch:30:000C8A7E7A1C:preset" }

next you need to add an alarm selector to your sitemap (and maybe the soundtouch control, here i added a basic one with power, volume, presets; inside every room the corresponding soundtouc got more info, like artist and track)
default.sitemap

    //BASIC SOUNDTOUCH CONTROLLER	
     Frame label="SoundTouch" {
		Switch item=SoundTouch_OnOff 
		Slider item=SoundTouch_Volume
		Switch icon="speaker" label="Presets" item=SoundTouch_preset mappings=[
		  "1"="Virgin",
		  "2"="Radio24",
		  "3"="Dinner Jazz"
		]
		Switch label="" item=SoundTouch_preset mappings=[
		  "4"="Vocal Jazz",
		  "5"="Electro swing",
		  "6"="Virgin Electro Shock"
		]
		
	}
      //A NEW PAGE WHERE I SET THE ALARM
      Group item=Wakeup {

            Frame label="Time" {
				Switch 	item=alarmEnabled
                Setpoint item=alarmTimeHour minValue=0 maxValue=23 step=1
                Setpoint item=alarmTimeMinutes minValue=0 maxValue=55 step=5
		
            }
            Frame label="Weekdays" {
                Switch item=alarm_MON
                Switch item=alarm_TUE
                Switch item=alarm_WED
                Switch item=alarm_THU
                Switch item=alarm_FRI
                Switch item=alarm_SAT
                Switch item=alarm_SUN
            }
     
		}

Next the rules, basically a cron that check every 5 minutes if the alarm should play (based on time and day), if it should play it calls a FadeIn function that sets the soundtouch volume to 0, select a preset and slowly increase the volume; both the preset and the target volume are hardcoded, but they could be easily added to the alarm configuratio as setpoints (the rule include quiete a lot of debug logging)
alarm.rules

rule "ClockAlarm"
when
    Time cron "0 */5 * ? * *"
then
var day_number = now.getDayOfWeek
    var minute_now = now.getMinuteOfHour
    var hour_now = now.getHourOfDay
	var day = ""

	//logInfo("default.rules", "Enabled: "+alarmEnabled.state.toString)
	
	switch day_number{
        case 1: day = "MON"
        case 2: day = "TUE"
        case 3: day = "WED"
        case 4: day = "THU"
        case 5: day = "FRI"
        case 6: day = "SAT"
        case 7: day = "SUN"
    }
	if (gAlarmWeekdays.members.filter[s | s.name == "alarm_"+day].head.state == ON && alarmEnabled.state == ON) {
		//logInfo("default.rules", "DAY should ring:"+day)
		
		if ((alarmTimeHour.state as Number).intValue==hour_now.intValue && (alarmTimeMinutes.state as Number).intValue == minute_now.intValue) {
			//logInfo("default.rules", "alarm: Time matched")
			//logInfo("default.rules", "alarm minutes set: "+(alarmTimeMinutes.state as Number).intValue+" now: "+minute_now.intValue)
			//logInfo("default.rules", "alarm hours set: "+(alarmTimeHour.state as Number).intValue+" now: "+hour_now.intValue)
			sendCommand (FadeIn, ON)
		} else {
			//logInfo("default.rules", "alarm: Time not matched")
			//logInfo("default.rules", "alarm minutes set: "+(alarmTimeMinutes.state as Number).intValue+" now: "+minute_now.intValue)
			//logInfo("default.rules", "alarm hours set: "+(alarmTimeHour.state as Number).intValue+" now: "+hour_now.intValue)
		}

		
	} else {
		//logInfo("default.rules", "alarm: should NOT ring")
	}
end

default.rules (where i store generic function like FadeIn that i also use elsewhere)

rule "Fade In"
when
	Item FadeIn received command ON
then
	val vol=0 //set volume to 0
	sendCommand(SoundTouch_preset,4) //hardoced presets
	SoundTouch_Volume.sendCommand(vol)
	Thread::sleep(10000)
	while((vol=vol+1) < 30) {
		SoundTouch_Volume.sendCommand(vol)
		Thread::sleep(1000)
	}
end

using this approach taking the function that play the alarm outside the function that check the alarm everything could be parametric, i can add a select for the type of alarm (instead that using FadeIn i can have multiple one with different devices)

Hope this could be useful

2 Likes

Lenna,

I am very new to this community and not a comp programmer at all but am willing to learn. My questions are,

  1. How do I get openHAB2 to get your program running?
  2. How do I get your program running using openHAB2?
  3. Do you have video clip posted on Youtube somewhere showing how to install and run your program?

Thanks Lenna!

Sincerely,
Sleepyhead