scheduler-component icon indicating copy to clipboard operation
scheduler-component copied to clipboard

Ensure scheduler state (eg. manual run with checking time and conditions)

Open fpytloun opened this issue 1 year ago • 12 comments

Checklist

  • [x] I checked for similar existing requests (both open and closed) before posting.
  • [x] My request is generic, other users may benefit from it too.

Proposal

If there's some issue with entities scheduler is calling, there is no simple way to find out or fix the state. Eg. if scheduler triggers a light off but it remains on for any reason. Possible solutions:

  1. I would expect repeat_type to repeat actions, so basically retry, but it does not seem to happen or there's some longer period, not able to configure. UPDATE: based on this, repeat happens every 10 minutes https://github.com/nielsfaber/scheduler-component/blob/061d882f686083cedf1ea4a50333ca030f305840/custom_components/scheduler/switch.py#L181
  2. Have automation with scheduler.run_action to re-try actions but it will skip time checks so it also does not solve the issue.

Ideal solution would be to have action eg. scheduler.ensure_state or it would probably be same as what would happen after scheduler.edit as I think scheduler fires if updated 🤔

Additional info

[some example of how the new functionality should look like]

fpytloun avatar Jul 22 '24 08:07 fpytloun

If there's some issue with entities scheduler is calling, there is no simple way to find out or fix the state. Eg. if scheduler triggers a light off but it remains on for any reason.

Scheduler checks if an entity is unavailable, if this is the case the action is postponed until the entity becomes available, otherwise the action is executed directly. There is a maximum applicable to the amount of time that can be postponed (for a schedule using timeslots without start+end time), this could be the 9 minutes you are referring to.

I would expect repeat_type to repeat actions

No, this property relates to the repetition of the schedule itself, so whether a schedule should loop to the next day after ending, it has nothing to do with execution of actions.

Ideal solution would be to have action eg. scheduler.ensure_state

No idea what you mean by this.

Note that scheduler is only designed to execute a given action at given time and day. If an entity changes its state afterwards, this is not detected nor reacted upon. The behaviour you can expect from scheduler is equivalent of creating an automation that is triggered by time.

nielsfaber avatar Jul 22 '24 16:07 nielsfaber

Ideal solution would be to have action eg. scheduler.ensure_state

No idea what you mean by this.

I may have some idea. Some definitions to make the discussion more precise:

  • Scheduler Entity: a scheduler entity such as switch.schedule_0c9ddd.
  • Controlled Entity: an entity such as switch.bedroom that refers to a physical object like a light switch, for which at least one Scheduler Entity exists (i.e., there would be at least one Scheduler Entity whose entities: property referred to the Controlled Entity).
  • Implied State: the “implied” or “expected” state of a Controlled Entity at a given time. For example, if Scheduler Entities dictated that a Controlled Entity like switch.bedroom should be turned on at 8pm and turned off at 10pm (there being no other Scheduler Entities for this Controlled Entity for this period of time), then, from this information alone, it could be implied that the state of switch.bedroom should be “turned on” at all times between 8pm and 9:59pm. As such, the implied state of switch.bedroom for a given time of “9pm” would be “turned on”.

My impression of the meaning of an “ensure state” service is that, given a Controlled Entity ID, it would compare the current actual state of the Controlled Entity with its Implied State as defined above, and if these states differed, an action would be executed to change the current actual state so that it matches the Implied State. In other words: If a light switch was supposed to be turned on at 8pm and turned off at 10pm, and now it’s 9pm and the light switch is turned off, then turn it on!

If so, it’s something that in the past I had myself wished, not in the context of an unavailable entity, but in the context of the home assistant server being “down for maintenance” for a period of time. When the server was up again, such an “ensure state” service could “correct” the state of entities for which scheduled actions were missed while the server was down.

A less ambitious, perhaps pre-requisite feature would be a “scheduler.get_implied_state” service that, given a Controlled Entity ID such as “switch.bedroom” and a time such as “9pm”, would return the Controlled Entity’s Implied State such as “turned on”. A user could then setup an automation that ran periodically to compare a Controlled Entity’s current state with its Implied State, correcting the current state as needed.

pdcastro avatar Jul 22 '24 19:07 pdcastro

Scheduler checks if an entity is unavailable, if this is the case the action is postponed until the entity becomes available, otherwise the action is executed directly.

So this will be probably my issue. Because some entities are not unavailable but changing it's state might not succeed (in my case Z-Wave devices). So one addition might be to wait a while and check if state was actually changed and if not then retry.

But what I wanted was to have option to know if actual state is matching scheduled state (eg. by having some sensor or attribute on scheduler entities) and option to enforce scheduled state (by service similar to scheduler.run_action but that will respect all scheduler settings).

fpytloun avatar Jul 23 '24 07:07 fpytloun

+1 on this feature.

In my case, it would be nice to be sure a switch changed states successfully. I've got a schedule for switching on and off our pool pump to circulate the water. On hot summer days, this is really important, so no part of the schedule should be missed. The pump is controlled by a Zigbee smart plug, which will be switched by the scheduler. If there is an error in the Zigbee network and the packet gets lost, or a Timeout occurs, the smart plug is not switched and continues in the same state as before.

So it would be handy to have the scheduler being able to check if the state change really happened and, if not, try to switch the entity again. I would go even further and implement a notification feature, so the user could be notified if:

  1. The entity change was not successful the first time, but it was able to switch the entity by the x-th try
  2. The entity change was not successful after x tries

The timeline should look like this: image

Floyd-Schramm avatar Aug 06 '24 06:08 Floyd-Schramm

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days

github-actions[bot] avatar Sep 06 '24 00:09 github-actions[bot]

Bump

fpytloun avatar Sep 06 '24 07:09 fpytloun

Hi, I have the same problem with an on-off Zigbee switch. The entity is never unavailabe in Home Assistant, but sometimes the switch does not respond to the "turn on" or "turn off" action and stays in the same state as before.

In my case I use the scheduler to run some appliances at night, when electricity is cheaper, but yesterday the appliance did not turn off in the morning.

xThrodx avatar Sep 09 '24 09:09 xThrodx

To summarize (if I understand correctly), the feature requested here is: after scheduler has triggered an action, a check if performed whether the targeted entity indeed changes state. If not, some retry is performed.

I understand this can be desirable in some cases, however I'm reluctant such complexity should be added to the scheduler code. The main issue I have with this request is the problem caused by the device being poor, not by scheduler. The problem will also exist with a regular automation or even manual controlled action, so why should the solution be provided specifically by scheduler? I feel more for having a generic solution provided by HA, e.g. by additional parameters that can be provided to a service/action call, that will trigger internal check&retry mechanisms.

Some other concerns I have:

  • Scheduler has no knowledge of how long it should (normally) take for an entity to respond to an action. In some cases (e.g. turning on a switch that is already on), the entity is not expected to respond ever.
  • Scheduler has no knowledge of what state change is to be expected after triggering an action. For example, calling service climate.set_temperature may result into the climate entity starting to heat (or not), it depends on its internal logic. There are also various entity types that don't have any state (e.g. button, script, notify).
  • I expect the desired retry behavior will be very user-dependent. It's possible to have scheduler check (and repeat action) every minute for up to 10 times in a row, but both the 'every minute' and 'up to 10 times' are debatable.
  • Actions triggered by user (or automations) may conflict with the check&retry behavior. e.g. if scheduler turns on a light but the user directly turns it off, scheduler may decide to turn it on again.
  • Scheduler offers support for time slots (having a start+stop time), but also simple actions having only a point in time. For the latter type (and perhaps also timeslots of only 1 or 2 minute duration), a retry mechanism may conflict with the allowed timespan.

nielsfaber avatar Sep 21 '24 05:09 nielsfaber

I was now re-reading the scheduler’s README and it gives me the impression that the “ensure state” feature requested here has nearly been implemented already, in the form of tracked conditions — the track_conditions boolean attribute of the Timeslot object.

Consider a switch controlled by the scheduler. The idea is to setup Timeslots where the tracked condition is the state of the controlled switch itself:

  • Timeslot: from 00:00 to 08:00
    • Action: switch turn ‘on’
    • Condition: switch state is not ‘on’
    • Track conditions: True (meaning that if the switch state changes to not ‘on’ during this time slot, the turn on action triggers again)
  • Timeslot: from 08:00 to 00:00
    • Action: switch turn ‘off’
    • Condition: switch state is not ‘off’
    • Track conditions: True (meaning that if the switch state changes to not ‘off’ during this time slot, the turn off action triggers again)

Wouldn’t this substantially deliver the state diagram shared by @Floyd-Schramm, and the action retry originally asked by @fpytloun? Instead of “wait 1-2 minutes” and “try up to 5 times”, the above tracked conditions would trigger whenever the switch state changed away from what it should be, an unlimited number of times within each time slot.

However, after some brief playing with the scheduler card UI, if I got it right, setting up the tracked conditions above is not currently possible because:

  • When adding a new schedule of the “scheme” type (multiple Timeslots in a single scheme):
    • The Options tab shows a checkbox “Re-evaluate when conditions change” that I gather matches the track_conditions boolean attribute. That’s good.
    • Unfortunately, the same set of conditions seem to apply equally to all timeslots in the scheme (as opposed to each timeslot having its own set of conditions). This means that the opposing conditions “is not ‘on’” and “is not ‘off’” would apply simultaneously to all timeslots in the scheme, which defeats my intention.
    • A “scheme” has to have a minimum of two timeslots, and altogether the timeslots must span a whole day (24h). (This means I could not reasonably get around the limitation that the same set of conditions applies to all timeslots in the scheme.)
New schedule Track conditions

 

  • When adding a new schedule with a single Timeslot (not a “scheme”):
    • The Options tab does not show that same checkbox “Re-evaluate when conditions change,” so I could not turn on the track_conditions boolean attribute through the UI.

But if we established that these were “merely” UI limitations, the focus could shift to tweaking the UI. (I’d have some further comments in that case...)

Hint to help understanding what's going on behind the scenes: Check the contents of your Home Assistant config/.storage/scheduler.storage JSON file after you make changes through the scheduler card UI.

Regarding @xThrodx’s Zigbee switch that “sometimes does not respond to the "turn on" or "turn off" action and stays in the same state as before,” I suspect that a tracked condition would not trigger in the absence of a state change (e.g. in the case where the switch state remained ‘off’ after a ’turn on’ action was executed). But we could consider enhancing the tracked conditions feature. The Condition object could have a new attribute evaluation_interval_sec that would be an integer number of seconds after which the condition would be re-evaluated, repeatedly. For example, if evaluation_interval_sec was 60, then every 60 seconds the condition would be re-evaluated; if the condition was true (e.g. switch state is not ‘on’), then the Timeslot action would be executed again (e.g. switch turn on).

pdcastro avatar Sep 21 '24 16:09 pdcastro

[...] I understand this can be desirable in some cases, however I'm reluctant such complexity should be added to the scheduler code.

That’s fair. Short of the scheduler itself “ensuring the state,” the scheduler could make it easier for users to write their own automations or scripts, as follows. A common pattern in such automations or scripts is to repeatedly perform the following steps:

  1. Get the target state: Should the switch be ‘on’ or ‘off’ at this time?
  2. Get the current state: Is the switch ‘on’ or ‘off’ at this time?
  3. If the current and the target states don’t match (e.g. should be ‘on’ but is ‘off’), execute a corrective action (e.g. turn it ‘on’).
  4. Repeat the previous steps (e.g. every 2 minutes).

Say the user is using the scheduler to control a switch, e.g. turn ‘on’ at 8pm and turn ‘off’ at 10pm. The user would be doing this because the scheduler card UI is so nice and powerful! 😍 But the switch is not reliable 😣 and the user decides to complement the scheduler with an automation or script coded as above. It turns out that the trickiest part of such an automation or script is the first step: Should the switch be ‘on’ or ‘off’ at the time when the automation is executed? The scheduler has the data to answer this question. If the switch was scheduled to turn on at 8pm and turn off at 10pm, then the answer would be ‘on’ at 8:33pm, or ‘off’ at 10:17pm.

[...] Scheduler has no knowledge of what state change is to be expected after triggering an action. For example, calling service climate.set_temperature may result into the climate entity starting to heat (or not), it depends on its internal logic. There are also various entity types that don't have any state (e.g. button, script, notify).

An automation/script could figure out the required state if a scheduler service returned previous and next Timeslot action lists. For example, given the following excerpt from my config/.storage/scheduler.storage file:

  "data": {
    "schedules": [
      {
        "schedule_id": "c1b0f7",
        "timeslots": [
          {
            "start": "05:30:00",
            "stop": null,
            "conditions": [],
            "condition_type": null,
            "track_conditions": false,
            "actions": [
              {
                "service": "climate.set_temperature",
                "entity_id": "climate.living_room",
                "service_data": {
                  "hvac_mode": "heat",
                  "temperature": 18.5
                }
              }
            ]
          }
        ],
      ...
      },
      {
        "schedule_id": "b29c0f",
        "timeslots": [
          {
            "start": "07:00:00",
            "stop": null,
            "conditions": [],
            "condition_type": null,
            "track_conditions": false,
            "actions": [
              {
                "service": "climate.set_temperature",
                "entity_id": "climate.living_room",
                "service_data": {
                  "hvac_mode": "heat",
                  "temperature": 19.5
                }
              }
            ]
          }
        ],
      ...

The scheduler component could provide a scheduler.get_actions service that, given the following input (timestamp provided in ISO format):

{ "entity_id": "climate.living_room",
  "timestamp": "2024-09-22T05:37:08",
}

... produced the following output:

{
  "previous": {
    "start": "05:30:00",
    "stop": null,
    "actions": [
      {
        "service": "climate.set_temperature",
        "entity_id": "climate.living_room",
        "service_data": {
          "hvac_mode": "heat",
          "temperature": 18.5
        }
      }
    ]
  },
  "next": {
    "start": "07:00:00",
    "stop": null,
    "actions": [
      {
        "service": "climate.set_temperature",
        "entity_id": "climate.living_room",
        "service_data": {
          "hvac_mode": "heat",
          "temperature": 19.5
        }
      }
    ]
  }
}

Given the above output, the automation or script could figure out that the target temperature state is 18.5 at 05:37 (and since 05:30) and expected to next change to 19.5 at 07:00. Similarly, an automation or script could figure that a target switch state is ‘on’ if the previous action list included "service": "switch.turn_on".

pdcastro avatar Sep 21 '24 23:09 pdcastro

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days

github-actions[bot] avatar Oct 22 '24 00:10 github-actions[bot]

Not stalled.

fpytloun avatar Oct 22 '24 08:10 fpytloun

My schedule do not run at all when I add a condition.

I added the following condition based on a calendar:

Condition = IS

STATE ON

I checked that this condistion was met on the time the schedule was supposed to run, and it was. If I remove the condition, the schedule runs fine.

fahlsen avatar Oct 30 '24 12:10 fahlsen

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days

github-actions[bot] avatar Nov 30 '24 00:11 github-actions[bot]

Not stale, this is still needed

fpytloun avatar Nov 30 '24 11:11 fpytloun

[...] the scheduler could make it easier for users to write their own automations or scripts [...] It turns out that the trickiest part of such an automation or script is the first step: Should the switch be ‘on’ or ‘off’ at the time when the automation is executed?

I’ve just realised that there is a simple enough solution (or workaround) to the matter of finding out whether a switch controlled by the scheduler should be on or off at a given point in time, for the purpose of writing an automation or script that monitors the state of an unreliable switch in a loop (e.g. once a minute) and “fixes” it as needed.

Say the switch in question is switch.bedroom. When setting up the schedule, instead of selecting switch.bedroom, select a helper toggle button such as input_boolean.bedroom. Such a helper can be created in Settings ➔ Devices and Services ➔ Helpers ➔ Create Helper ➔ Toggle:

toggle

Because a helper toggle is a virtual entity that only exists within Home Assistant, its on/off state is always correct as set by the scheduler. Then the user’s automation can simply monitor the state of the helper toggle (input_boolean.bedroom), compare it with the state of the actual physical switch (switch.bedroom), and fix the state of the physical switch whenever the states differ.

This workaround does not require any changes to the scheduler component and card.

pdcastro avatar Nov 30 '24 21:11 pdcastro

@pdcastro yes, good idea, this workaround might work for some use-cases like turning on/off switches but will not work well for using scheduler for climate control (setting temperature) 🙁

fpytloun avatar Dec 10 '24 09:12 fpytloun

this workaround might work for some use-cases like turning on/off switches but will not work well for using scheduler for climate control (setting temperature) 🙁

I think “it depends”. The Toggle (input_boolean) helper maps to a physical on/off switch, but there are several types of helpers, and the Number (input_number) helper would map to a physical device that exposed a Number interface for setting a temperature value, like the Climate integration does (services.yaml section). An automation could then regularly read the temperature setting from the physical device (which may be “wrong”), compare it with the value of the input_number helper entity (which is “always correct”), and re-write the temperature setting to the physical device whenever they differed.

I say “it depends” for at least a couple of reasons. The standard Climate integration is a reference “building block”, and the actual integration used for a “climate control” physical device might conceivably not provide a Number interface for setting the temperature (it could even be an OS add-on that that only exposed some HTML frontend to HASS). Alternatively, if the climate control was built around a Generic Thermostat integration where the temperature value only existed within Home Assistant, then actually the temperature setting would be “always correct,” and what could go wrong is the heater switch (or cooling air conditioner switch) that might not turn on/off when the scheduler issued an on/off command. In this case, we would be back to using a Toggle (input_boolean) helper instead of a Number (input_number).

But to be clear, I didn’t mean that the use of a helper invalidates the feature request for the scheduler component to “ensure a state”. It is mainly a good alternative to my own previous suggestion that the scheduler component could provide some sort of scheduler.get_actions service for the purpose of determining the intended (target) state of an entity (like a switch or a number) at the time when an automation is executed.

pdcastro avatar Dec 10 '24 11:12 pdcastro

+1 for this. Im trying scheduler for a thermostatic valve, and it just isnt working properly. A few times it didnt work because I was restarting HA at the time of a scheduled event (yeah, on hindsight, DUH, but why wouldnt the scheduler just do the actions once it can?).

But even when that is not an issue, this is a schedule for my bedroom radiator valve: image

It should switch to 18C at 7pm, and then open up all the way at night (to prevent TRV noise while I sleep). Instead it did this: image

It seems like it turned on heating but somehow missed the target temp, and the valve just set the last temp. Whatever the cause of this, the valve never went offline, and I would expect a scheduler to at least make an effort to ensure its schedule is actually applied, be it check the device state once per minute, or at user selectable interval or something.

R5fan avatar Dec 17 '24 20:12 R5fan

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days

github-actions[bot] avatar Jan 17 '25 00:01 github-actions[bot]

This issue is still valid but I cannot reopen? 🙁

fpytloun avatar Jan 24 '25 06:01 fpytloun