Help on concept needed: migrating my heating control

I do this for my lights. In my current implementation I use

Rule that detects when a light was manually controlled, marks the Light as overridden

@rule("Lights Override",
      description=("Sets the Override flag when a light is manually changed "
                   "during the day"),
      tags=["lights"])
@when("Member of gLights_ON_WEATHER changed")
def override_lights(event):
    sleep(0.5) # Give pesistence a chance to catch up

    # Wait a minute before reacting after vTimeOfDay changes, ignore all other
    # times of day.
    if (items["vTimeOfDay"] != StringType("DAY") or
        (PersistenceExtensions.lastUpdate(ir.getItem("vTimeOfDay"), "mapdb")
            .isAfter(DateTime.now().minusSeconds(10)))):
        return

    if (not PersistenceExtensions.lastUpdate(ir.getItem("vIsCloudy"), "mapdb")
            .isAfter(DateTime.now().minusSeconds(5))):
        override_lights.log.info("Manual light trigger detected, overriding the"
                                 " light for auto control for {}."
                                 .format(event.itemName))
        set_metadata(event.itemName, "Flags", { "override" : "ON" },
                     overwrite=False)

Rule that does the automation (turns on/off the lights based on how cloudy it is).

@rule("Cloudy Lights",
      description="Turns ON or OFF some lights when it is cloudy during the day",
      tags=["lights"])
@when("Item vIsCloudy changed")
@when("Item vTimeOfDay changed")
def cloudy_lights(event):
    # If it's not DAY or cloudy isn't set, exit.
    if (items["vTimeOfDay"] != StringType("DAY") or
        isinstance(items["vIsCloudy"], UnDefType)):
        return

    # If no one is home, turn OFF any lights that are on.
    if items["vPresent"] == OFF:
        [event.sendCommand(light, "OFF") for light in ir.getItem("gLights_ON_WEATHER").members if light.state == ON]
        return

    # Someone is home and it's DAY time, turn ON/OFF the lights based on the cloudiness.
    if event.itemName == "vTimeOfDay":
        sleep(0.5)

    cloudy_lights.log.info("It is {} and cloudy changed: {}"
                           .format(items["vTimeOfDay"], items["vIsCloudy"]))

    for light in [light for light in ir.getItem("gLights_ON_WEATHER").members if get_key_value(light.name, "Flags", "override") != ON]:
        if items[light.name] != items["vIsCloudy"]:
            events.sendCommand(light, items["vIsCloudy"])

The relevant part is in

for light in [light for light in ir.getItem("gLights_ON_WEATHER").members if get_key_value(light.name, "Flags", "override") != ON]

This line filters out all the Items that do not have an override metadata value set to ON.

Finally, the Rule that resets the override flags when the sun goes down.

@rule("Reset Override",
      description="Change override flag when time of day changes",
      tags=["lights"])
@when("Item vTimeOfDay changed")
def reset_overrides(event):
    for light in ir.getItem("gLights_ON_WEATHER").members:
        set_metadata(light.name, "Flags", { "override" : "OFF" },
                     overwrite=False)

I haven’t yet figured out whether/the best way to extract this and make it more generic so it can be submitted to the library. I haven’t spent a lot of time thinking about it either though. :wink:

I’ve seen two approaches for presence simulation that most people go with. The first is to control the lights randomly. My preferred approach is to just store the lights states in the database and then “play back” what ever the lights were set to at this time last week. You can find a Rules DSL version of the Rule here. I’ve not yet moved it to Python.

1 Like