HABApp 0.30

Apologies for hijacking the thread. I really want to get this running consistently before I start really migrating rules.

the service status has this log entry that I think is related to the issue:

May 03 08:59:17 pi-openhab3 habapp[6739]: Error loading logging config: Unable to configure handler 'EventFile'

and that section of the logging.yaml file looks like this:

  EventFile:
    class: HABApp.core.lib.handler.MidnightRotatingFileHandler
    filename: '/var/log/openhab/HABApp_events.log'
    maxBytes: 1_048_576
    backupCount: 3
    formatter: HABApp_format
    level: DEBUG

Happy to buy some coffee or beer to support all this hard work.

This is definately a permission issue.
Can you try and see if “Fix Permissions” (option 14 in openhabian-config) will fix your problems?

You should definitely treat yourself to a cold one after you have everything set up an running! :wink:

1 Like

That’s the ticket!

Permissions on the log files looked consistent, but I should have thought to apply that option. It should be step 1 in many troubleshooting situations…

Thanks! Ready to get rolling!

Hi Sebastian,

There’s either a bug/limitation importing lib modules or I’m making a silly mistake.

I’ve a file habapp_utils.py in my lib folder which I import into my rules with “import habapp_utils” and “from habapp_utils import *”. This works fine, however any changes I make into habapp_utils.py aren’t reflected when I run my rules unless I first restart habapp.

Is it intentional, a bug, or am I doing something dumb?

thanks!

Dan

Oh i think i know it, me, me, me me please

As far as i understand. HabApp reconises your change, but the already loaded rules do not. There is a specific dependency option. With this option you could say reload my rule if file xyz changes.

See the documentation on this:File-Properties

Thomas

@Dibbler42 While file properties are really nice they don’t apply here

@dan12345
It’s a library folder that gets imported on startup.
Currently there is no proper method in python to dynamically reload libraries, that’s why changes to the libraries don’t get picked up during runtime.

And to be fair most of the time this is not necessary:

  • HABApp can build rules dynamically based on parameter files and reload the rule files on parameter change (see the link from Thomas).
  • You also can run functions from rules from different files.
  • As a third option you can create HABApp internal items and use these to transfer data between rules/files.
  • Overlaying states and a device driver/logic model can be created with the MultiModeIItem

With these mechanisms creating libraries in the original sense of library is not necessary any more.
And when it makes sense it’s so static that restarts don’t matter :wink:

Ohhhh so much to learn …

It’s interesting how different people have different approaches. I like building a big library with all the utility functions, and then having short simple rules files. But restarting when the library changes isn’t a hardship!

For me that’s HABApp :wink:

I used to try that too, but I changed that to create a rule class that does exactly one thing and I’m rather creating multiple instances of the rule than try working with a big library.
For example I now have six rules per rollershutter and they are combined through the multimode item.

If you like you can create a thread and I’ll have a look at your things and give you an example how I would have done it. If not and you’re happy restarting HABApp that’s fine with me, too! :slight_smile:
Whatever suits you the best!

Just found an alternative:

import importlib
importlib.reload(habapp_utils)

Forces a reload of the library module. Cool!

Almost :wink:

Other references to the old objects (such as names external to the module) are not rebound to refer to the new objects and must be updated in each namespace where they occur if that is desired.

Basically you can never be sure which version you are using from the file that imported it.

Good news everyone!

I just released HABApp 0.30.1!

This is just a small bugfix release


Changelog:

  • latitude is now set correctly for sun calculation
  • Added missing " for tags in textual thing configuration
  • Updated scheduler which fixes an overflow error
  • States of openHAB groups are now unpacked correctly

Good news everyone!

I just released HABApp 0.30.2!

This is just a small release which brings some bugfixes and small features


Changelog:

  • Item and Thing loading from openHAB is more robust and disconnects now properly if openHAB is only partly ready
  • Renamed command line argument “-s” to “-wos” or “–wait_os_uptime”
    Now waits until the system uptime is at least the specified value before starting HABApp
  • Renamed HABApp.openhab.exceptions to HABApp.openhab.errors
  • Updated dependencies
2 Likes

Good news everyone!

I just released HABApp 0.30.3!

This release brings support for a custom mqtt certificate and changes some internal HABApp things


Changelog:

  • add support for custom ca cert for MQTT
  • Scheduler runs only when the rule file has been loaded properly
  • Sync openhab calls raise an error when called from an async context
  • Replaced thread check for asyncio with a contextvar
2 Likes

@Spaceman_Spiff

I just moved from OH 2.5 to OH 3.1, and it was made so much easier with having all my rules in HABApp! all my rules just worked after the upgrade. Thank you.

I do have a question about OH 3.1. I used to use the “System started” trigger (in my one and only DSL rule) to restart HABApp when OH stated up, and whenever I edited an .items file.

Now with OH3.1, this rule does not trigger when an .items file is edited, so the question is - what happens to HABApp if it’s running, and I edit an '.items file? do I need to manually restart HABApp for it to pick up the changes in the .items files? would touching all my rules achieve the same thing? (assuming I haven’t changed anything vital, say changing the label or group or adding an item).

Is there a way to set HABApp up so that changing any .items file trigger a rules reload in HABApp (or a restart if that is what is needed).

What would you suggest?
Thanks.

I use the dependency definitions to restart rule if my parameter file are changes.

Example:

# Dependency definitions
# HABApp:
#   reloads on:
#     - params/thermostats.yml

But i think this is not linked to the openhab files.

@Spaceman_Spiff

I have updated my CreateTimer class to use your new coundown timer. Here it is, if anyone else is interested (this is in my utils.py library).
Basically it makes the basic countdown timer into a persistent, cancellable timer with some added methods and properties.
This solves the problem that you can’t cancel() a countdown timer and then restart it, you have to recreate the countdown timer, if you cancel() it early.

import datetime, logging
from eascheduler.const import FAR_FUTURE
from threading import Lock
class createTimer(HABApp.Rule):
    '''
    General timer class
    Restartable Timer, with cancel and reschedule functions
    accepts float, int or datetime.timedelta as seconds parameter (not claiming that the timer is that accurate though)
    based on countdown timer (new in Habapp V0.30)
    '''
    
    def __init__(self, seconds=0.0, exec_func=None, run=False, *args, **kwargs):
        super().__init__()
        self.log = logging.getLogger('MyRule.'+self.__class__.__name__)
        self.t = seconds
        self.exec_func = exec_func
        self.args = args
        self.kwargs = kwargs
        self._task = self.run.countdown(self.t, self.exec_func, *args, **kwargs)
        self.lock = Lock()      #needed to prevent race condition
        if run:
            self.reset()
             
    @property
    def is_running(self):
        return self.time_till_run != 0
        
    @property    
    def time_till_run(self):
        if self._task._next_run < FAR_FUTURE:
            return (self._task.get_next_run() - datetime.datetime.now()).total_seconds()
        return 0
        
    def get_next_run(self):
        return self._task.get_next_run()
        
    def reset(self):
        with self.lock:
            self._task.reset()
        
    def reschedule(self, seconds=0.0):
        self.start(seconds)
        
    def start(self, seconds=0.0, *args, **kwargs):
        if args:
            self.args = args
        if kwargs:
            self.kwargs = kwargs
        if args or kwargs:
            self.cancel()
        self.countdown(seconds)
        self.reset()
        
    def countdown(self, seconds=0.0):
        if seconds > 0:
            self.t = seconds
            with self.lock:
                self._task.countdown(self.t)
        
    def cancel(self, job=False):
        with self.lock:
            if self._task._parent is not None:
                self._task.cancel()
            if not job:
                self._task = self.run.countdown(self.t, self.exec_func, *self.args, **self.kwargs)

You could simplify it more - reset(), reschedule() and start() are all basically the same thing, but I didn’t want to make too many changes to my original.

You use this as a drop in replacement for self.run.countdown()

Update: Fixed race condition…

1 Like

Yep - the only difference to the built in counter is the is_running property and the time_till_run.
But you already had it in place before the new scheduler in HABApp so it’s valid to keep this around.

HABApp will pick up the changed item definitions automatically.
There is no need to restart HABApp if you change the *.items file.
You’ll see the corresponding events on the event bus.

Of course you have to reload the rules that used the existing items.

Any ideas on how to do that? I have 39 rules files, and it’s not easy to know which files uses which items - is there a way of triggering a reload on all rules when any .items file is changed?

Weird things happen if I don’t reload after editing .items files.

If its adding items or modifying e.g. a label (not the type/name) it is fine.
Things go south if you rename items or delete existing ones.

The only way I can think of is to take one or two items of every *.items file and listen to the ItemAddedEvent or the ItemRemovedEvent and then issue a FileLoadEvent with all rule names.

But it might be easier to just create a button in openhab and link a shell execute with a systemctl reload HABApp and just flick it once you’re done editing.

1 Like