Examples needed

Hello guys!

I’m looking for some examples in these situations

1- An automation should be activated iff a particular sequence of events has occurred. I mean, if the events (state changes) occurred in a chronological way.
For example, "Notify me if MotionSensorA detected movement and then the DoorContactB was opened and ...."

2- An automation should be activated iff a number X of events has occurred.
For example, "Notify me if the boiler's temperature was 3 times over 60 C in the last hour"

3- An automation should be activated iff a threshold X if achieved.
For example, "Notify me if my electricity consumption is more than X kw in 3 weeks" Consider that you get your daily consumption of electricity every day at 00:00, so you need to keep historical data

If you can share any automation that uses a similar kind of logic will be appreciated

thanks in advance!
Humberto

For nr 1 I am interested as well.

For nr 2 you can use a counter sensor, increment it each time the temperature was over 60. And then do a trigger when the counter is 3, then reset the counter.

For nr 3 you can you a Stats sensor

@Skye thanks

For #1… this is non-trivial. There are at least 5 different ways to do this and they are all not the best. Other tools (AppDaemon, in particular) make this quite a bit easier. However, using only Home Assistant, I’d recommend this.

Have multiple automations, one for each “phase” of the check. They should all start out turned “off” except for the first phase.

So, you have one automation with a trigger of MotionSensorA detected movement. It’s only action is to turn on the next automation. It might also turn itself off, depending on how you intend to “reset” this particular string of automations.

The second automation waits for DoorContactB to open and then does whatever. At some point, perhaps when DoorContactB is opened, the MotionSensorA automation will need to be turned back on and the DoorContactB automation turned back off.

For #2… it’s also non-trivial. Again, something like AppDaemon makes this easier. In Home Assistant only, there are lots of way. I’d recommend a counter (https://www.home-assistant.io/components/counter/). When the boiler temp goes over 60, increment the counter. With a second automation, when the counter reaches 3, do something.

But, since you specifically want “in the last hour” you’ll probably want to use a history_stats sensor (https://www.home-assistant.io/components/history_stats/). Since it only works with “states” and doesn’t handle “above” and “below”, you’ll also want a template binary_sensor (https://www.home-assistant.io/components/binary_sensor.template/) that turns on when the boiler temp is over 60. The history_stats sensor would then be attached to the template binary_sensor. And your automation would be based on the history_stats sensor.

For #3… there are some built in sensors that measure energy usage. I’m unfamiliar with them so I can’t offer advice. But if I were doing this, I’d start with the utility_meter sensor (https://www.home-assistant.io/components/utility_meter/) and work my way from there.

Happy Automating!

1 Like

hey @swiftlyfalling thanks for your reply and your time :+1:

1 Like

You can use wait_templates in your action section for #1 without having tons of automations.

It’s fairly linear though.

1 Like

thanks for the hint @petro!

The biggest problem with wait_template (and delay) is… what happens if the script/automation is triggered again while it’s delaying/waiting? In my experience, at least with delay, I’ve seen the script simply SKIP the delay it was working on and move to the next task in the “action” list. In most cases, this isn’t what we want. By using a timer, or a second automation (that may have a “for” configuration in it’s trigger) we can get around that unexpected/undesired behavior. But, of course, it comes with the cost of a more complicated automation(s).

@swiftlyfalling thanks for sharing your experience!

Yes, that’s with a delay. It remains to be seen what happens with a wait template. The condition has not been med, i’d be willing to bet it’s just canceled.

Also, to get around that delay behavior, you can always separate the action section into a script and cancel the script before executing it. I really see no reason to have this as multiple automations personally.

I guess the part I’d need to see, using @rhumbertgz 's example…

The automation Trigger would be MotionSensorA turns “on”. The first step of the automation would be a wait_template for DoorContactB to turn “on”. So if MotionSensorA turns “on”, and then turns “off” again before DoorContactB turns “on”… what happens once DoorContactB turns on?

My impression, based on what I’ve seen happen in other automations, is that the automation was triggered and therefore still running. So, when DoorContactB turns “on”, even though MotionSensorA is no longer “on”, the script will continue to run. Which, might be what OP desires. But, if that’s not what OP desires, then a “condition” in the action will have to be added after the wait_template to ensure that it’s still on. From my experience, the condition of an automation (not in the action, but on the automation itself) only affects if the automation triggers. Once triggered, it’s still triggered until the “action” portion of the automation either completes or meets a “wait_template” or “condition” that ends the action.

This really makes the automations get long and ugly, when having more than one automation would make it easier to read. Imagine if we add another requirements to OP’s original idea:

If MotionSensorA turns on, THEN DoorContactB turns on, THEN LightC turns on, send a notification.

Then you end up with this (untested, possibly typos):

trigger: 
  - platform: state
    entity_id: MotionSensorA
    to: 'on'
action:
  - wait_template: "{{ is_state('DoorContactB','on' }}"
  - condition: state
    entity_id: MotionSensorA
    state: 'on'
  - wait_template: "{{ is_state('LightC', 'on' }}"
  - condition: state
    entity_id: MotionSensorA
    state: 'on'
  - condition: state
    entity_id: DoorContactB
    state: 'on'
  - service: notify.me
    message: 'The Thing Happened'

Now add that you only want this to kick in if you’re “home” when it happens, and also only if you’re watching TV, and it gets awful. By, instead, turning on and off related automations, you can ensure that things only happen when other things have happened first.

- alias: motion happened
  initial_state: 'on'
  trigger:
    - platform: state
      entity_id: MotionSensorA
      to: 'on'
  action:
    - service: automation.turn_on
      entity_id: automation.door_opened

- alias: motion stopped
  trigger:
    - platform: state
      entity_id: MotionSensorA
      to: 'off'
  action:
    - service: automation.turn_off
      entity_id: 
        - automation.door_opened
        - automation.light_on

- alias: door opened
  initial_state: 'off'
  trigger:
    - platform: state
      entity_id: DoorContactB
      to: 'on'
  action:
     - service: automation.turn_on
       entity_id: automation.light_on

- alias: light on
  initial_state: 'off'
  trigger:
    - platform: state
      entity_id: LightC
      to: 'on'
  action:
    - service: notify.me
      message: "The Thing Happened"

Sure, it’s now 40 lines and 4 automations, compared to 18 lines and one automaton. But, adding something like “and only do this when Someone is Home” becomes easy and requires only 3 lines added to one automation. Additional problems are also solved, like, what if the door was already open when motion was detected? The wait_template version executes anyway, even though OP said “and THEN DoorContactB was opened”. So you’d have to add a condition before the wait_template to check that it was “off” first. But then, what if, while MotionSensorA turned on (while the door was open) and then the door closed, and then reopened (with MotionSensorA staying on the whole time)… the condition before the wait_template would have ended the action already. And this can be worked around by using an event trigger instead of a state trigger for the motion sensor (which most of them support), but, even then, timing becomes an issue (how often does your motion sensor send the event, and did the door close and reopen within that window?).

I’m not saying a “wait_template” is wrong. It serves a purpose. But, I quickly realized, way in the early days of my automation journey, that most of my automations got too complex for the “wait_template” I originally wrote to still apply, that I just stopped using them entirely and always went for multiple automations. Then, when you want to add a condition, or realize you want to wait for the door to be open for at least a minute before progressing, or whatever… the path to get there is simple, even if it’s more verbose.

To make grouping such automations together easier, I have this in my configuration.yaml:

automation: !include_dir_merge_list automations/

So I can make a file called “livingMotion” that has all the automation pieces together to make fine tuning it easier.

But, to be fair, I quickly got tired of the verbosity of multiple automations, as well, and, for anything new, I tend to handle it in AppDaemon if it’s even a little complicated or I have the foresight to know it will end up complicated in the future.

I get where you’re going but maybe this guy should walk before he runs. Just saying. I’ve been in your shoes before. Seems like he’s just trying to get his toes wet and you’re trying to drown him :wink:

HA!!!

You may be right. I forget that sometimes people have to follow the natural progression of things or they will drown.

Hi @swiftlyfalling

After read the documentation and based on my dev experience, I will pursue automation based AppDeamon.

Can you share some of your examples using AppDeamon?

humberto

There are plenty of examples in the appdeamon section of this forum.

Also, you can take a look at my config but I’ll warn you, I’ve made helper classes that are now obsolete because I haven’t updated my code in years. A lot of my config can be optimized with v4 of appdeamon, so it may not be the best help. I also don’t use voluptuous, which was a mistake on my end when I first started. My config is linked in my profile.

Also, take a look at @ReneTode’s configuration. He pretty much has an up to date appdaeomon apps that utilize all the new functionality, which removes the need for the helper classes that I created.

1 Like

thx for the credits, but allthough my apps are up to date with the dev version from AD, those apps i didnt share.

@rhumbertgz
the type of automations you are looking for would be something like:
(pseudo code if you want to try please create a real app structure (see docs))
1)

def intialise(..):
  self.listen_handler = None
  self.listen_state(self.motion_triggered, "motionsensora", new = "on")

def motion_triggered(...):
  self.listen_handler = self.listen_state(self.door_opened, "doorcontactB", new = "on",oneshot = True)
  self.run_in(self.stop_listening,60)

def door_opened(...):
  self.notify("the door was opened within 60 seconds after motion was detected")

def stop_listening(...):
  # door didnt open in 60 secs, stop listener
  self.cancel_listen_state(self.listen_handler)
  self.listen_handler = None

this will notify if a door is opened within 60 sec after a motion is detected, can be adapted in any way

def initialise(..):
  temptime[1] = datetime.datetime.now - datetime.timedelta(hour = 1)
  temptime[2] = datetime.datetime.now - datetime.timedelta(hour = 1)
  temptime[3] = datetime.datetime.now - datetime.timedelta(hour = 1)
  self.listen_state(self.check_temp, "boiler_sensor")

def check_temp(..):
  if new > 60:
    temptime[1] = temptime[2]
    temptime[2] = temptime[3]
    temptime[3] = datetime.datetime.now()
    checktime = datetime.datetime.now - datetime.timedelta(hour = 1)
  if temptime[1] > checktime and temptime[2] > checktime and temptime[3] > checktime:
    self.notify("temp was 3 times above 60C in the last hour)
  1. is simular but you listen to the daily consumption you get at 00:00, then you save that to a file or database, then you retrieve the last 21 values and calculate the value and send a notify if needed.

my code is kept very simple, to make it easy to understand. off course it can be made more pretty and more advanced in any way you like.

please feel free to visit our discord server where i give faster answers when you have more questions.

1 Like

Every AppDaemon app has two parts to it: 1) a Python module and class that does the work, 2) YAML configuration to turn that module on.

There are two ways to pursue AppDaemon:

#1) Write Apps for YOUR ONE TIME use only. This means you might hardcode the entity ID’s or certain configuration aspects into the Python Module, because it’s quicker and you’ll never use it again. This is great for those situations were your home has very specific need (like, perhaps, you want to turn on a light but only when there is motion in a room within 10 seconds of the door being opened and only when it’s daylight out). These are pretty simple and there are examples all over the place since most people begin here.

#2) Write Apps that you’ll use again and again and possibly share with others.

Here’s an example of an app that allows me to use my HVAC system like a switch. If I turn the switch on, the AC starts cooling the house. When I turn the switch off, it stops. This is useful as part of a larger whole, where I’ve given my house mutti-room climate control: If only my livingroom is occupied, then the AC system can focus on getting that room (and only that room) to 72 degrees and keeping it there. To do this, I don’t much care what the HVAC system thinks the temperature is.

This example is untested as I had to modify the actual code I use to take out a few pieces that require in other modules I’ve written and use in almost every AppDaemon module I write. They are useful as well, but, muddy things up a bit for the example.

1 Like

Here’s another example of an app that runs once a day (at 5am, which is hardcoded and probably shouldn’t be) as well as on demand by event. It checks all device batteries and creates a persistent notification if any are low. This app doesn’t use Voluptuous either, though, I’d prefer it if it did as it prevents a lot of need for double checking in code as well as ensures that changes made to the app are consistent with the app configuration:

It’s also a good example of a less than perfect AppDaemon app, because, I wrote this code a while ago and haven’t updated it. There are pieces that COULD break for other people, however, it’s just enough that it works for me. For instance, if you look at line 45… what happens if “battery” isn’t int()-able? It breaks. Mine all happen to be, so it’s fine. But if yours aren’t, this’ll need work.

As I’m sure you know, it takes a lot of effort to make an app sharable and reusable for other out of the box. But, you don’t have to jump through all of those hoops to use AppDaemon. And if this one app happens to break, it doesn’t break EVERYTHING else. There’s a sandbox of sorts for each app that runs, which is nice.

1 Like

Hi @Skye

Maybe this post App #8: Detect a particular sequence of events can help