Automating Hunter Douglas PowerView automations

I’m slowly migrating my rules from DSL to JavaScript, and at the same time improving and simplifying them.

Now it was time to migrate some of my PowerView rules, and along the way I finally also added some new logic that I’ve been missing for a long time (regarding holidays).

The use-case is to be able to extend the logic provided by Hunter Douglas PowerView automations. I prefer to let the PowerView Hub handle as much as it can in order to have as much autonomy as possible and not be too dependent on openHAB. This improves the reliability, since automations will still work while openHAB is down, for example due to maintenance.

I have two sets of automations configured on the hub:

  • Wake-up at sunrise on weekdays: Shades in the bedroom and children’s rooms should open at sunrise, but only on weekdays. This is used in the winter.
  • Wake-up at fixed time on weekdays: Shades in the bedroom and children’s rooms should open at 6:25 and 6:30 respectively, but only on weekdays. This is used in the summer.

This setup alone requires some manual handling:

  • Four times per year the two automations must be switched, i.e. when sunrise is before 6:25 or the other way. Because of DST it happens four times, not two.
  • On public holidays the automations must be manually switched off. Otherwise the sun will wake up the house before desired.

So of course this should be automated. Furthermore, it should be planned one day in advance and I should receive a notification, so I have a chance to know beforehand if something is wrong.

So here we go…

powerview.things:

Bridge hdpowerview:hub:hub "PowerView Hub" [host="powerview", refresh=60000, hardRefresh=15, hardRefreshBatteryLevel=12] {
    // Shade things
}

powerview.items:

Switch PowerViewHub_Automation_ChildrenUp_Sun "Children up at sunrise" <blinds> (Blind7, Blind8) ["Control"] {channel="hdpowerview:hub:hub:automations#1262"}
Switch PowerViewHub_Automation_ChildrenUp_Time "Children up at 6:30" <blinds> (Blind7, Blind8) ["Control"] {channel="hdpowerview:hub:hub:automations#49023"}
Switch PowerViewHub_Automation_Goodmorning_Sun "Good morning at sunrise" <blinds> (Blind10, Blind11) ["Point"] {channel="hdpowerview:hub:hub:automations#65238"}
Switch PowerViewHub_Automation_Goodmorning_Time "Good morning at 6:25" <blinds> (Blind10, Blind11) ["Point"] {channel="hdpowerview:hub:hub:automations#14214"}
String PowerViewHub_Automations_Paused "Paused automations" <blinds>

persistence:

PowerViewHub_Automations_Paused: strategy = everyChange, restoreOnStartup

powerview.js:

var notification = require('jlaur/notification.js');

function updateWakeupAutomation(sunriseTime, wakeupTime, sunAutomationItemName, timeAutomationItemName) {
    var sunAutomationItem = items.getItem(sunAutomationItemName);
    var timeAutomationItem = items.getItem(timeAutomationItemName);
    if (sunAutomationItem.state == "OFF" && timeAutomationItem.state == "OFF") {
        // Both are disabled, don't change anything.
        return;
    }
    if (sunriseTime.isAfter(wakeupTime)) {
        if (sunAutomationItem.state == "OFF") {
            console.log("Switching from automation " + timeAutomationItemName + " to " + sunAutomationItemName);
            sunAutomationItem.sendCommand("ON");
            timeAutomationItem.sendCommand("OFF");
            notification.send("PowerView", "Switching to " + sunAutomationItem.label);
        }
    } else if (timeAutomationItem.state == "OFF") {
        console.log("Switching from automation " + sunAutomationItemName + " to " + timeAutomationItemName);
        sunAutomationItem.sendCommand("OFF");
        timeAutomationItem.sendCommand("ON");
        notification.send("PowerView", "Switching to " + timeAutomationItem.label);
    }
}

rules.when()
    .cron("0 0 15 ? * ?")
    .then(event =>
    {
        var sunActions = actions.get("astro", "astro:sun:home");
        //var sunriseTime = utils.javaZDTToJsZDT(sunActions.getEventTime("SUN_RISE", time.ZonedDateTime.now().plusDays(1), "START")).toLocalTime();
        var sunriseTime = time.ZonedDateTime.parse(sunActions.getEventTime("SUN_RISE", time.ZonedDateTime.now().plusDays(1), "START").toString()).toLocalTime();

        console.log("Checking PowerView automations - sunrise tomorrow at " + sunriseTime + ", holiday tomorrow: " + actions.Ephemeris.isBankHoliday(1));

        // Update wake-up automations according to upcoming holiday.
        var pausedItem = items.getItem("PowerViewHub_Automations_Paused")

        if (actions.Ephemeris.isBankHoliday(1) && !actions.Ephemeris.isWeekend(1) && (pausedItem.isUninitialized || pausedItem.state == "")) {
            const automationItemNames = [
                "PowerViewHub_Automation_Goodmorning_Time",
                "PowerViewHub_Automation_Goodmorning_Sun",
                "PowerViewHub_Automation_ChildrenUp_Time",
                "PowerViewHub_Automation_ChildrenUp_Sun"
            ];

            var automationsToPauseItemNames = new Array();
            var automationsToPauseLabels = new Array();
            for (automationItemName of automationItemNames) {
                var automationItem = items.getItem(automationItemName);
                if (automationItem.state == "ON") {
                    automationsToPauseItemNames.push(automationItemName);
                    automationsToPauseLabels.push(automationItem.label);
                    console.log("Pausing automation " + automationItemName);
                    automationItem.sendCommand("OFF");
                }
            }
            pausedItem.postUpdate(String(automationsToPauseItemNames));
            notification.send("PowerView", "Automations disabled, since it's holiday tomorrow: " + automationsToPauseLabels.join(", "));
        }
        else if (!pausedItem.isUninitialized && pausedItem.state != "")
        {
            var automationsToResumeItemNames = pausedItem.state.split(",");
            var automationsToResumeLabels = new Array();
            for (automationItemName of automationsToResumeItemNames) {
                var automationItem = items.getItem(automationItemName);
                console.log("Resuming automation " + automationItemName);
                automationItem.sendCommand("ON");
                automationsToResumeLabels.push(automationItem.label);
            }
            pausedItem.postUpdate("");
            notification.send("PowerView", "Automations enabled again, since it's not holiday tomorrow: " + automationsToResumeLabels.join(", "));
        }

        // Update wake-up automations according to sunrise.
        updateWakeupAutomation(sunriseTime, time.LocalTime.of(6, 25, 0, 0), "PowerViewHub_Automation_Goodmorning_Sun", "PowerViewHub_Automation_Goodmorning_Time");
        updateWakeupAutomation(sunriseTime, time.LocalTime.of(6, 30, 0, 0), "PowerViewHub_Automation_ChildrenUp_Sun", "PowerViewHub_Automation_ChildrenUp_Time");

    })
    .build("PowerView wake-up", "Manage PowerView automations according to sunrise and holidays");
1 Like