yes, now it works, thank you very much!
Sorry - not yet.
As so often there was an unexpected request that made me stop - and then the “free sunday” was gone.
I’ll try again later.
Greetings, I’m slowly working through converting my last few DSL rules to HABapp and then will begin tackling my jython rules, which will hopefully go faster. @Spaceman_Spiff thank you so much for your work on this. Quite incredible!
I have a question regarding every_minute()
rules. Currently when I save a rule that has an every_minute() in it the rule runs at some arbitrary time within the next minute and then exactly a minute after that time continuing. How do I make every_minute() rules run exactly on the minute, like a cron “every minute” rule would run in jython or dsl? (and I’m guessing this would also extend to every_hour as well).
I tried using every()
and specifying 60 sec as the interval, but that does approximately the same thing, except that it fires the rule immediately after saving, and then every [interval] after that.
I’ve tried searching the python time, timedelta, etc. docs for a generic “on the minute” type of entry to put in the start_time argument, but can’t figure it out.
Also, please let me know if I should have started a new thread for this, or if it’s OK for me to ask this on a release announcement thread. Thank you!
It’s okay to ask and I’m happy to help but I would have preferred a fresh thread so other users can find the answer more easily.
If you look at the docs you can see that you can specify a start time for every. If you omit the start time (None
) it’ll run immediately. So you have to pass a time
or a datetime
which has 0 seconds (e.g. 11:33:00
).
To achieve this we go one minute in the future and then replace the seconds with 0. Then we have the next minute (e.g. 11:32:59
+ 00:01:00
→ 11:33:59
→ 11:33:00
)
(datetime.now() + timedelta(minutes=1)).replace(second=0, microsecond=0)
Excellent, I didn’t consider doing that, very clever. Thank you so much for the response. And, if there’s a way to move my question and your answer to a separate thread, I’m happy to do it.
Has anyone observed strange behavior when reconnecting or starting HABApp + openHAB?
If not I’ll probably make a release in a couple of days … .
i did a couple of restarts (of the complete raspberry) today. for me everything seems fine
I am currently in the process of a huge rewrite of the scheduler.
The goal is to make it more easy to use yet very powerful.
Countdown and once will work as before, however triggering at a specific point in time will be fundamentally different.
The idea is that one can define triggers which define when something will run. Then one can apply operations at these triggers (e.g. add an offset or a jitter) and also filter which apply to these triggers.
Here are examples how I plan on implementing it:
from HABApp.scheduler import Trigger, TriggerFilter
# Will run every day at 08:00:00
self.run.at(
Trigger.time('08:00:00'),
my_func
)
# Will run at sunrise, but not before 07:00:00 and not after 09:00:00
# Shows operations on a trigger
self.run.at(
Trigger.sunrise().earliest('07:00:00').latest('09:00:00'),
my_func
)
# Will run during the week at 8, on the weekend at 9
# Shows that it's possible to invert the filter and how to use multiple triggers
self.run.at(
Trigger.group(
Trigger.time('08:00:00').only_on(TriggerFilter.not_(TriggerFilter.weekdays('Sa', 'So'))),
Trigger.time('09:00:00').only_on(TriggerFilter.weekdays('Sa', 'So')),
),
my_func
)
# Will run at 8 every Sunday in October, November, December
# Shows combinations of a filter
self.run.at(
Trigger.time('08:00:00').only_on(
TriggerFilter.all(
TriggerFilter.weekdays('So'),
TriggerFilter.months(10, 11, 12)
)
),
my_func
)
I’m not yet done with the implementation so currently I am looking for some early feedback may it be wording / usability / feature requests / whatever.
What do you think?
@nobbi123 (pinging you because you seem to be eager for a new scheduler version )
nice features! i am thinking about what i could do with it but actually i do not have a use case for it.
one timer i suppose i did more complicated than necessary but it works. i control my pool pump with a timer that i can set in main ui:
the item is a numberitem that i convert to minutes and then create a listener. when the timer will be adjusted the listener will be cancelled and created new.
time_on = int(NumberItem.get_item('iViPool_FilterTimer_ON').value)
hour_on, minute_on = self.sk_tools.minutes_to_time(time_on)
self.cron_filter_on_listener = self.run.on_every_day(time(hour=hour_on, minute=minute_on),
lambda: SwitchItem.get_item('iViPool_Regelfilterzeit').\
oh_post_update_if('ON', not_equal='ON'))
...
if self.cron_filter_on_listener is not None and \
self.cron_filter_on_listener.remaining() is not None:
self.cron_filter_on_listener.cancel()
This will be the new scheduler (once implemented).
So instead of
self.cron_filter_on_listener = self.run.on_every_day(time(hour=hour_on, minute=minute_on), ...
you will do
self.cron_filter_on_listener = self.run.at(Trigger.time(time(hour=hour_on, minute=minute_on), ...
My goal is to provide more flexibility by making it possible to combine, chain and filter triggers while still having a scheduler that is very easy to use
Somehow I did not see, that you mentioned me here…
My main request would be python 3.12 support. On the feature side I’m happy with the current functionality, but I also like your new proposals. Currently I do not really use advanced scheduler features. But maybe this will change with your new features
I’ve been working relentlessly during the last months and I finally have an early beta available.
It implements the scheduler as described above, however I made it so that the triggers are also available on self.run
. This also fixes the issue where the first run has to be in the future when specifying a time.
Example:
# Run the function at sunrise
self.run.at(self.run.trigger.sunrise(), self.dummy_func)
# Run the function every day at 12
self.run.at(self.run.trigger.time('12:00:00'), self.dummy_func)
Scheduler docs
Scheduler examples
This version requires at least Python 3.10 and finally supports Python 3.12.
There is one breaking change that I’m currently aware of:
- search for
self.run.at
and replace withself.run.once
.
Attention:
This is an early beta and I’d like some feedback because this is such a huge change.
Expect bugs and issues to arise.
So do not run this as your main installation, instead connect to an instance read only or spin up a testing openHAB instance (even better).
Installation instructions are in the first post of this thread.
I’m pinging some power users from this thread. If you don’t want to be pinged any more please send me a PM.
@Dominik_Bernhardt @yfaway @dan12345 @alfista2600 @bastler @nobbi123 @Schrott.Micha
sorry i cannot help much with testing, the only scheduler i actually use is this:
self.run.on_sunset(self.run_at_susnet)
this i would then change to
self.run.at(self.run.trigger.sunset(), self.run_at_susnet)
but actually i am not able to run the new version. i run 24.8.1, uninstalled it and installed 24.9.0.dev1 with this commands:
sudo systemctl stop habapp
cd /opt/habapp
source bin/activate
python3 -m pip uninstall habapp
python3 -m pip install git+https://github.com/spacemanspiff2007/HABApp.git@Develop
sudo systemctl start habapp
all this went without errors. but because on new start of habapp i recieved a lot of errors in the log i did a reboot. but still then i have much errors in the log. because i dont find all this errors in the log files i attached two errors that i manually copied from screen.
now i uninstalled the 24.9.0.dev1 and went back to 24.8.1 and everything works again. btw: i have python 3.11.2 installed.
copy from log 1 .txt (44.1 KB)
copy from log 2.txt (51.3 KB)
Thank you for testing.
I was able to reproduce the issue.
DEV2
is available which should work now as expected.
i tried again and installed dev2. now i see no more errors but it still seems that all rules get loaded again and again. i tried to filter my log in the browser for one rule, then i see this:
2024-09-22 08:43:06.745 [DEBUG] [HABApp.file.events ] - FileOpenedEvent(src_path='/etc/openhab/habapp/rules/pirs.py', dest_path='', event_type='opened', is_directory=False, is_synthetic=False)
2024-09-22 08:43:06.746 [DEBUG] [HABApp.files ] - rules/pirs.py added
2024-09-22 08:43:06.747 [DEBUG] [HABApp.file.events ] - FileClosedNoWriteEvent(src_path='/etc/openhab/habapp/rules/pirs.py', dest_path='', event_type='closed_no_write', is_directory=False, is_synthetic=False)
2024-09-22 08:43:07.179 [DEBUG] [HABApp.files ] - rules/pirs.py changed to DEPENDENCIES_OK
2024-09-22 08:43:08.816 [DEBUG] [HABApp.file.events ] - FileOpenedEvent(src_path='/etc/openhab/habapp/rules/pirs.py', dest_path='', event_type='opened', is_directory=False, is_synthetic=False)
2024-09-22 08:43:08.817 [DEBUG] [HABApp.files ] - rules/pirs.py added
2024-09-22 08:43:08.818 [DEBUG] [HABApp.file.events ] - FileClosedNoWriteEvent(src_path='/etc/openhab/habapp/rules/pirs.py', dest_path='', event_type='closed_no_write', is_directory=False, is_synthetic=False)
2024-09-22 08:43:09.222 [DEBUG] [HABApp.files ] - rules/pirs.py changed to DEPENDENCIES_OK
2024-09-22 08:43:11.030 [DEBUG] [HABApp.file.events ] - FileOpenedEvent(src_path='/etc/openhab/habapp/rules/pirs.py', dest_path='', event_type='opened', is_directory=False, is_synthetic=False)
2024-09-22 08:43:11.031 [DEBUG] [HABApp.files ] - rules/pirs.py added
2024-09-22 08:43:11.032 [DEBUG] [HABApp.file.events ] - FileClosedNoWriteEvent(src_path='/etc/openhab/habapp/rules/pirs.py', dest_path='', event_type='closed_no_write', is_directory=False, is_synthetic=False)
2024-09-22 08:43:11.446 [DEBUG] [HABApp.files ] - rules/pirs.py changed to DEPENDENCIES_OK
Strange - it seems the file is added over and over again - at least the file system is producing the corresponding events. I can not reproduce this - is this behavior reproducible on your machine?
Hint: You can create a new HABApp installation on your normal computer and connect to your running openHAB instance read only. That way everything works as normal but you still can test the new version and its behavior.
Hi Sebastian,
I had a short look at the changes. Till now i have two findings:
- how can I run some function at the first day of the next month at 0:00?
- Can we find a way to not pin the version of holidays to a fixed version? maybe change it to
holidays >= 0.57, < 1.0
The first one is easy:
self.run.trigger.time('00:00:00').only_on(self.run.filter.days(1))
If you want to run it only once just cancel the job during the first execution.
The second one not so much:
I’ve had HABApp break because of changed dependencies and I think it’s reasonable to expect that the setup installs a working version. Holidays 0.57 already emits a DeprecationWarning
that the API will change in one of the next versions so I think it’s not a good idea to allow that much of a range.
I know I’ve been negligent in pinning the used library versions and the versions of those libraries but I think I have to be even more strict. I’ve already had to try out multiple versions of dependencies of libraries because things were not working any more and the versions were not pinned. I’m not sure what the best approach is, but “let’s install something and hope for the best” can’t be it.
I really despise how this is solved in python
sorry, I did not really read your documentation. But now it is clear how the new triggers are working. The examples are really good
I understand that you need to set the requirements as tight as possible. For now, it is ok to pin the version of holidays, but if there are any nice changes I would appreciate if you would do a new release of HABApp.
My current state of testing is:
- I changed all my triggers to the new format
- All unittests are passed
- tomorrow during the day, I will run the new version
EDIT: feedback after first tests:
Python 3.11 seems to be ok.
With Python 3.12 i see two issues:
- If the default EventBus logger is enabled, HABApp does not start. I get the following error:
Error loading logging config: Unable to configure handler 'HABAppQueue_EventFile'
There was some change forlogging.config.dictConfig()
- I had to remove the profiler part in
HABApp.core.internals.wrapped_function.wraped_thread.PoolFunc.run
, otherwise I get the following exception and not all rules are loaded:
[ HABApp.Worker] ERROR | ValueError: Another profiling tool is already active
[ HABApp.EventBus] INFO | HABApp.Errors: <HABAppException func_name: load, exception: Another profiling tool is already active>
Thank you for testing.
Since I only verified with Python3.10 I was not aware of these issues.
I pushed Dev3
which fixes both these issues.