Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

time_trigger does not work reliably for "x seconds before midnight" #330

Closed
herrfrei opened this issue Mar 1, 2022 · 8 comments
Closed

Comments

@herrfrei
Copy link

herrfrei commented Mar 1, 2022

I want to collect the daily energy meter values (absolute and daily values in / out) and wrote a function for that:

sensors_daily = [
    {"name": "sensor.energy_meter_energy_in_kwh", "format": "%7.1f"},
    {"name": "sensor.energy_meter_energy_out_kwh", "format": "%7.1f"},
    {"name": "sensor.energy_meter_energy_in_daily", "format": "%4.1f"},
    {"name": "sensor.energy_meter_energy_out_daily", "format": "%4.1f"}]

sensors_monthly = [
    {"name": "sensor.energy_meter_energy_in_kwh", "format": "%7.1f"},
    {"name": "sensor.energy_meter_energy_out_kwh", "format": "%7.1f"},
    {"name": "sensor.energy_meter_energy_in_monthly", "format": "%5.1f"},
    {"name": "sensor.energy_meter_energy_out_monthly", "format": "%5.1f"}]

sensors_yearly = [
    {"name": "sensor.energy_meter_energy_in_kwh", "format": "%7.1f"},
    {"name": "sensor.energy_meter_energy_out_kwh", "format": "%7.1f"},
    {"name": "sensor.energy_meter_energy_in_yearly", "format": "%6.1f"},
    {"name": "sensor.energy_meter_energy_out_yearly", "format": "%6.1f"}]

@time_trigger("once(midnight-30s)")
def write_at_midnight():
    dt_now = datetime.now() #+ timedelta(days=-1) # for the day before
    write_sensors_to_file(dt_now, dt_now.strftime('/config/logs/%Y-%m-energy.log'), sensors_daily)
    if is_last_day_in_month(dt_now):
        write_sensors_to_file(dt_now, dt_now.strftime('/config/logs/%Y-energy.log'), sensors_monthly)
    if is_last_day_in_year(dt_now):
        write_sensors_to_file(dt_now, '/config/logs/energy.log', sensors_yearly)

The function works in general, but is not triggered every day:

`
2021-10-06 23:59:30 2038.3 114.5 8.3 0.1
2021-10-08 23:59:30 2059.6 114.8 12.8 0.0
2021-10-12 23:59:30 2107.0 115.0 9.8 0.0
2021-10-23 23:59:30 2228.3 115.7 13.1 0.1
2021-10-25 23:59:30 2253.5 115.8 13.6 0.0
2021-10-30 23:59:30 2306.2 116.0 10.4 0.0

2021-11-01 23:59:30 2325.2 116.1 10.4 0.0
2021-11-13 23:59:30 2486.4 116.2 17.4 0.0
2021-11-17 23:59:30 2542.1 116.2 14.5 0.0
2021-11-21 23:59:30 2605.7 116.2 16.4 0.0

2021-12-12 23:59:30 2972.2 116.2 17.0 0.0
2021-12-13 23:59:30 2986.4 116.2 14.2 0.0
2021-12-22 23:59:30 3127.4 116.2 17.8 0.0
2021-12-24 23:59:30 3164.0 116.2 16.6 0.0
2021-12-29 23:59:30 3252.3 116.2 14.4 0.0
2021-12-30 23:59:30 3266.9 116.2 14.6 0.0

...
`

I have no idea how to solve it. Right now I changed the trigger to @time_trigger("cron(0 0 * * *)") to check if this is running every day, but here I have to compute the daily usage since the values are zeroed at midnight...

@dlashua
Copy link
Contributor

dlashua commented Mar 3, 2022

try cron(59 23 * * *) to get almost the same time as you originally wanted.

you could also try once(23:59:30).

I will add all three of these to my own setup to see if I get consistent operation.

@herrfrei
Copy link
Author

herrfrei commented Mar 3, 2022

I already changed my setup to cron(59 23 * * *). This works now for 2 days without dropout. I'll wait another two days before I change it to once(23:59:30). Thanks!

@herrfrei
Copy link
Author

herrfrei commented Mar 7, 2022

It is working as expected, closing the issue now. Many thanks!

@herrfrei herrfrei closed this as completed Mar 7, 2022
@craigbarratt
Copy link
Member

Did you try once(23:59:30), and was that reliable?

@craigbarratt
Copy link
Member

craigbarratt commented Mar 7, 2022

In looking at the code, I think what's happening is that midnight (which is replaced by 0:0:0) is at the start of the day, and midnight with a negative offset is yesterday. For triggers like once that don't have a date, pyscript checks tomorrow too, but at 23:59:30, tomorrow's midnight minus 30 seconds is still 11:59:30 today, which is the current trigger, which is ignored since that trigger just happened. So I'm guessing the trigger only happens once after restart, and never again, which is why it appears to be intermittent.

I could fix it by checking additional days in the future to see if the trigger evaluates to some time in the future. Or perhaps I should just add a caveat to the documentation that time offsets should be within the same day, and note that midnight is at the start of the day. Thoughts?

@craigbarratt craigbarratt reopened this Mar 7, 2022
@dlashua
Copy link
Contributor

dlashua commented Mar 7, 2022

@craigbarratt I think it's fantastic if it can do what the user expects in all cases. I.e. (midnight-30s is today unless that time is right now, or already past, then it's tomorrow). However, if it's a lot of work, it's probably not worth the effort since "23:59:30" is just as easy as "midnight-30s", in which case, documenting the caveat should be enough.

I, personally, don't use many time based triggers, since all my automations are based on things happening and not specific times. For my use cases the "now+some_offset" feature gets the job done. And "now-20s" doesn't really make a lot of sense syntactically.

@craigbarratt
Copy link
Member

craigbarratt commented Mar 7, 2022

I pushed a fix 6b4ea76 that should do the right thing for any offset. It will adjust it to be in the next 24 hours.

@herrfrei
Copy link
Author

herrfrei commented Mar 8, 2022

@craigbarratt Many thanks for fixing this issue. I can't decide if it makes sense or not to have the possibility to set a time trigger several seconds before midnight. I use it to collect energy consumption (per day, month, year) externally in simple tabular files and started with a timer at midnight. Then I saw that the utility_meter value was already reset and moved the timer 30 seconds before midnight. For me it would be sufficient to have a remark that negative offsets are not allowed (or to implement this check in pyscript), but you found already a solution for that. Again, many thanks!

FYI, I didn't test once(23:59:30) since I modified my code to use the last_period attribute of the utility_meter and moved the timer back to midnight.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants