Area Triggers --> Area Actions

Thank you Scott for this lovely piece of work. It’s a clever design and I’ve started to adopt it here.

I already have an item for “Lighting Theme” (E.g. OFF, NORMAL, MOVIE, PARTY, PANIC) that I will synchronize to the “Mode” item. It would be great to be able to use a customized name instead of “Mode” btw. I also have separate modes for Clock_Time_Of_Day and Solar_Time_Of_Day that I use in my scripting.

I have defined my own light action function named generic_light_action and I have set it in the configuration file to be the default, "default_action_function": "generic_light_action".

I had some trouble to make it run instead of the light_action function and I’ve seen it’s been hard coded in the area_trigger.py as

                        if not action_function_names or "light_action" in action_function_names:
                            start_action(item, True if event is not None else trigger_group.state in [ON, OPEN], "light_action")

The following modified code works better for me:

                        if not action_function_names or area_triggers_and_actions_dict["default_action_function"] in action_function_names:
                            start_action(item, True if event is not None else trigger_group.state in [ON, OPEN], area_triggers_and_actions_dict["default_action_function"])

Cheers!

EDIT: Since the low_lux_trigger is baked into a named Mode, I’d also like to add an “ELSE” mode in so that I do’nt have to repeat low_lux_trigger for every possible mode. I’d like to suggest something like this:

low_lux_trigger = get_key_value(item.name, "area_triggers_and_actions", "modes", str(items["Mode"]), "low_lux_trigger") or get_key_value(item.name, "area_triggers_and_actions", "modes", 'ELSE', "low_lux_trigger") or area_triggers_and_actions_dict["default_levels"]["low_lux_trigger"]`

Then I could just add metadata like the following for a light bulb that’s ON in all modes:

set_metadata("Light_Facade_Tenants", "area_triggers_and_actions",
    {
        "modes": {
            "ELSE":    {"low_lux_trigger": 380, "brightness": 60}
        }
    }, overwrite=True)

And in my area_actions.py

    low_lux_trigger = get_key_value(item.name, "area_triggers_and_actions", "modes", str(items["Mode"]), "low_lux_trigger") or get_key_value(item.name, "area_triggers_and_actions", "modes", 'ELSE', "low_lux_trigger") or area_triggers_and_actions_dict["default_levels"]["low_lux_trigger"]
    hue = DecimalType(int(get_key_value(item.name, "area_triggers_and_actions", "modes", str(items["Mode"]), "hue") or get_key_value(item.name, "area_triggers_and_actions", "modes", 'ELSE', "hue") or area_triggers_and_actions_dict["default_levels"]["hue"]))
    saturation = PercentType(int(get_key_value(item.name, "area_triggers_and_actions", "modes", str(items["Mode"]), "saturation") or get_key_value(item.name, "area_triggers_and_actions", "modes", 'ELSE', "saturation") or area_triggers_and_actions_dict["default_levels"]["saturation"]))
    brightness = PercentType(int(get_key_value(item.name, "area_triggers_and_actions", "modes", str(items["Mode"]), "brightness") or get_key_value(item.name, "area_triggers_and_actions", "modes", 'ELSE', "brightness") or area_triggers_and_actions_dict["default_levels"]["brightness"]))

Edit: There is an issue with my code above so don’t use it. The issue is that if a zero brightness is set for an item, it’s sucessfully fetched but the or operator will interprete that as False and go on with fetching the next value in the chain. I have reworked the code since then.

(Needed the int cast due to that get_key_value might return a float)

@5iver,

I’ve been working more with your lovely contribution lately and it works really well here. It’s so cool. Thanks again for sharing it.

In my kitchen I always have some lights on when it’s dark or shady outside. I keep them at a relatively low dim level. When someone approaches the kitcken sink a motion sensor triggers and the “Kitchen Work Lights” over the sink lights up. However the ambient light in the kitchen might still be percieved as a bit murky for some. So I thought that it would be a great idea to raise the dim level a bit for some lights in the kitchen that already follows a “Mode”. As I already have a customized lights_actionit was quite easy for me to add some extra metadata like this:

    set_metadata("Light_Dim_Kitchen_Ceiling", "area_triggers_and_actions",
        {
            "emphasized_by_device": "MD_Kitchen",
            "manual_dimmer_lock_level": -1,
            "modes": {
                "OFF":    {"brightness": DIMLEVELS['OFF']},
                "NORMAL": {"brightness": DIMLEVELS['MEDIUM']},
                "MOVIE":  {"brightness": DIMLEVELS['MIN']},
                "DINNER": {"brightness": DIMLEVELS['LOW']},
                "PARTY":  {"brightness": DIMLEVELS['MEDIUM']},
                "ALERT":  {"brightness": DIMLEVELS['MAX']}
            }
        }, overwrite=True)

So in my customized lights_action I just check for if there is an emphasized_by_device value for the item and I check the state of the emphasized_by_device device to determine if I should raise the dim level or use the level that’s defined for the current mode. That works well but whenever the emphasized_by_device device changes it’s state I will need the “Mode or lux change” rule defined in community/area_triggers_and_actions/area_triggers.py to trigger so that the rule can iterates through all triggering groups and replays the actions. I made a quick and dirty fix and added an item trigger in that function and I also had to make set the variable mode_change_or_system_start to true when triggered by the newly added item. When doing that, I’m aware that my changes will be overwritten when i update that community file. Anyway, I thought that it would be nice if I could define a device or a list of devices in the configuration (e.g, 'replayTriggeringDevices': ['MD_Kitchen', 'MD_Hallway'],) that the “Mode or lux change” rule will pick up and trigger upon? Wouldn’t that be cool?

Cheers!

I’m very pleased to hear that you like and appreciate it!

I agree. It makes sense for this Item to be configurable. Please create an issue in the repo for this feature request and also the hard coded reference to “light_action”. I have local commits for these, as well as a few others.

I’m not sure what you mean here, but will take a look later tonight.

I think I have the exact same scenario… I’ll take a look at how I’ve managed this…

Just copy everything over into the /personal/ directories so that you can make customizations. Then diff the files when updating to see what changes were made. If you think your changes woiuld be useful, then submit an issue in the repo to discuss.

Hi there Scott!

I’ve implemented the example 2. A light switch with a motion sensor and contact sensor in Example Lighting Scenarios.

This example will describe the use of a contact sensor to stop a light from turning off if the door is closed. The light will turn ON when there is motion or the door closes. The light will turn OFF when there is no motion and the door is open.

Things are working as described but I think I need to customize it a bit because here we keep the bathroom door closed both when using the bathroom and after we’ve left it. I haven’t yet figured out a clever solution to achive what I want.

I’d like to turn on the lights in the bathroom when someone opens the door or when motion is detected (in case the door actually was opened before entering the bathroom). I’d wan’t to keep the lights on during the time it’s occupied. When the door opens again I’d like to turn off the lights immediately. I’d like a reset here so that the light will tun on again if the door is reopened. In case the door was never closed during the “visit” I’d need a timer to turn off the lights after some time.

I think my scenario is quite common. I’m not sure it’s possible to implement without lots of code… any ideas? Maybe I should just solve it by mounting a sensor on the lock of the door. That would be easy and I wouldn’t need a motion detector in the bathroom. The MD looks like a webcam anyway so :wink:

Cheers!

Edit: I’ll take the lock switch route. It involves some work mounting a micro switch to detect the lock status but I think it will be great.

I don’t think there is any way around this, other than leaving the door open when the room is empty. This has some benefits though, since the air will circulate through the house better… and you’ll never walk in on someone accidentally! To avoid walking into a dark room, I always set the next area out to become active so that the lights are always one step ahead!

Hey Amazing work ! I just managed to setup the first two areas without Metadata etc. Before doing this i was wondering how I would use separate indoor lux levels for all the areas. I use hue Sensors which provide ambient light as well so i would like to use that. I will now try to get my head around the whole logic as i would really love to use the logic for other things.

Thomas

I have setup some ESP12E based luminance/temp/humidity/pressure sensors and have adjusted the code for room level luminance. I have a lot of things to push and will try to get to them this weekend.

With the ESP’s do you have them in an enclosure? Link?

Not yet. They are working great but are still breadboarded until I find time to get some more experimenting in. Although, it’s been an amazingly good science project for our 7 year old, so it may be sooner than later! I definitely want to try out Tasmota, add motion, and setup an outdoor version with a camera. I plan to post when complete!

1 Like

That sounds amazing! Thanks a lot

1 Like

Hey Scott,

Did you manage to update the library?

No, but I expanded our garden by about 20x! Looks like rain today, so I’ll be at the computer.

:joy: Sounds like smart irrigation is the next project

Any updated here?

Hey sorry To keep bothering you gut did you manage Top Updates the Files?

I also have another questions. In some modes I would like motion to only trigger the lights if they were off before. If somebody turned them on by a switch item or a wall switch it should override the rule for either some time or until the light is turned off with a switch again.

No, no, no! I appreciate the nudges, so keep at me until I get it done! Thank you!

I’ve been lost in the garden, so I have not gotten these changes in! 20 blueberry bushes, Triumph, Sterling, some Multi-headed neomexicanus hops, and one bed are planted, but I’m still transferring compost to 3 more new beds and a new composting site. I also have three more rain barrels to setup. I can’t wait for harvest time! We’re in a bit of a heat wave though, so I’ll be getting in some time at the computer and I’ll put this at the top of my list!

Currently, you can set dimmers to 100 and they will not turn off. I suppose this could also work for any specific value that you’d like by making a custom action for by modifying light_action.

I’ve also setup a SwitchItem for each room that I want to disable automation in and add it to the Area Trigger group for those rooms. When it is ON, the automation will not run in that room, since the area stays active for as long as the switch is ON, and you can manually adjust the light. I also have it hooked up to Alexa, so I can use voice commands to turn ON/OFF the automations in a room. This is very nice for sick days in bed! There are other things that can be done, but I wanted something that was always going to work.

I love this one

I had another thought about this. Its easy to imagine how this works when the lights are alread on -> switch virtual item on -> turns off automation group cant go to off anymore so light stays on. No change needed in script.

What if I want to turn off automation while the lights are off let us say in a bedroom. Lights are already off and I want to turn off automation. With the standard Script, it would turn on the light if I activate the virtual switch and it would then stay on.

Would that need a custom light action that every time the group changes checks if the override switch is on?

Thanks in advance Thomas

@Tomibeck, I am having similar challenges with overriding automation as you describe. There is the additional challenge that whenever the Area Trigger group is mismatching a manually set switch (even if you check the override switch when the group changes) any (unpredictable) change in lux or mode would also eliminate the mismatch, i.e. undoing the manual switch setting (e.g. turn on override switch, turn off light, mode change, light turns back on to configured brightness).

Area Triggers are very powerful and by being able to combine them in groups/hierarchies with boolean operators a large set of use cases can be elegantly solved as demonstrated by the many Area Triggers and Actions examples. However, I found there are additional use cases where I need more advanced “building blocks” for the Area Triggers group. I found @mjcumming’s OccupancyManager to nicely provide these building blocks. An Occupancy Area in the end is still just an Item that is occupied or not (ON or OFF), but the OccupancyManager helps maintain that occupancy state. Use cases like the one above are easily expressed. OccupancyManager is particularly strong around timers - occupancy can start with delays or expire upon trigger start or end with delay upon trigger end, triggers get extended etc. Note that this timer support is for the Occupancy Area itself, NOT on the resulting actions. That allows you to build up your Area Trigger group out of multiple complex Occupancy Areas each using various timers and other functionality.
Additionally Occupancy Areas support locking. In a locked state they don’t accept triggers. I recently submitted a PR to use an Occupancy Area as the lock for another Occupancy Area. If the Lock Area is occupied it’s owning Occupancy Area is locked. With that you can use any triggers including sensors and switches to set the lock. In your case you simply lock the Area Trigger with the virtual item and everything will stay in the desired state. I am actually setting the lock using the light switch itself as the trigger - turn the light off turns off occupancy and locks for 30min (since the lock is an Occupancy Area itself I simply use an Occupancy Area with an expiration). For 30min all sensors are locked out; no motion will trigger the light back on. After 30min the lock expires and automation kicks back in. Same if I turn the light on - only everything gets locked in in the ON state.
Note that in addition to overriding automation through locks I have a need to override actual brightness. E.g. at night my motion sensors just trigger a low “nightlight” brightness. But when I use the light switch I want full brightness. For that I have implemented a prototype that maintains an optional brightness override as part of the Occupancy Area (which I will submit as a proposal shortly). Together with custom brightness support in Area Actions I then get my brightness override.

Hopefully you find this helpful. Obviously it’s work in progress, but would love to hear your thoughts.

That sounds all very interesting. I probably need a quite weekend to get my head around it.