Drayton Wiser Thermostat Binding

After many frustrations I seem to have managed to get the Basic UI switching between schedules created on the Wiser Heat app. The Heating Boilerplate Tutorial was very helpful but with a Drayton Wiser system I think it is better to use openHAB to change schedules rather than having every room in manual mode and using openHAB to change set point temperatures.

This is a simplified version of how I setup my system to switch between a schedule for when I am at work during the day and a shedule for when I am at home.

I created a heating.items file containing:

String Heating_Schedule            "Heating Schedule [%s]"
String Save_Heating_Schedule       "Save Heating Mode [%s]"

Group HS
String FF_LivingRoom_Schedule      "Living Room Heating Schedule [%s]" (HS) {channel="draytonwiser:room:deadbeef:livingroom:masterSchedule"}
String FF_Kitchen_Schedule         "Kitchen Heating Schedule [%s]"     (HS) {channel="draytonwiser:room:deadbeef:kitchen:masterSchedule"}

Group HS_Home
String FF_LivingRoom_Schedule_Home "Living Room Heating Schedule [%s]" (HS_Home) 
String FF_Kitchen_Schedule_Home    "Kitchen Heating Schedule [%s]"     (HS_Home) 

Group HS_Work
String FF_LivingRoom_Schedule_Work "Living Room Heating Schedule [%s]" (HS_Work) 
String FF_Kitchen_Schedule_Work    "Kitchen Heating Schedule [%s]"     (HS_Work) 

a heating.rules file containing:

val String prep_schedule_re = "s/\\{\"id\":\\d*,(.*),\"Type\":\"Heating\"\\}/\\{$1\\}/"
val String strip_home_re = "s/^(.*)_Home$/$1/"
val String strip_work_re = "s/^(.*)_Work$/$1/"

rule "Apply Heating Schedule"
when
    Item Heating_Schedule received command
then
    switch receivedCommand {
        case "HOME": {
		    HS_Home.members.forEach[ i | sendCommand(transform("REGEX", strip_home_re, i.name), i.state.toString) ]
			Save_Heating_Schedule.postUpdate("HOME")
			logInfo("heating.rules", "Applied Home heating schedule")
        }
        case "WORK": {
		    HS_Work.members.forEach[ i | sendCommand(transform("REGEX", strip_work_re, i.name), i.state.toString) ]
			Save_Heating_Schedule.postUpdate("WORK")
			logInfo("heating.rules", "Applied Work heating schedule")
        }
    }
end

rule "Save Heating Schedule"
when
    Item Save_Heating_Schedule received command
then
    switch receivedCommand {
        case "HOME": {
		    HS.members.forEach[ i | postUpdate(i.name+"_Home", transform("REGEX", prep_schedule_re, i.state.toString)) ]
			Heating_Schedule.postUpdate("HOME")
			logInfo("heating.rules", "Saved Home heating schedule")
        }
        case "WORK": {
		    HS.members.forEach[ i | postUpdate(i.name+"_Work", transform("REGEX", prep_schedule_re, i.state.toString)) ]
			Heating_Schedule.postUpdate("WORK")
			logInfo("heating.rules", "Saved Work heating schedule")
        }
    }
end

a mapdb.persist file containing:

Strategies {
    default = everyChange
}
Items {
    Heating_Schedule        : strategy = everyChange, restoreOnStartup
    HS*, HS_Home*, HS_Work* : strategy = everyChange, restoreOnStartup
}

and a home.sitemap file which included:

sitemap home label="Home" {
    Frame label="Choose Heating Schedule" icon="radiator" {
        Selection item=Heating_Schedule label="Heating Schedule []"
     		mappings=[
                HOME="Home",
                WORK="Work"
            ]
     }

// ...

    Frame label="Program Heating Schedule" icon="radiator" {
        Selection item=Save_Heating_Schedule label="Copy from Wiser Heat to []"
     		mappings=[
                HOME="Home",
                WORK="Work"
            ]
    }
}

Getting the rules working was the most frustrating thing. I tried to use a javascript transform to strip out the extra “id” and “Type” JSON items but could not get it to work and I had to resort to a regex transform.