HABApp - Easy automation with openHAB

Hey, did I mention I love not having to create openHAB items to interact with MQTT? :heart:

1 Like

Me neither, but the “ding” tells me to look at the logfiles :wink:

1 Like

Wait, your phone has notifications sounds enabled? How do you focus? :slight_smile:

No, everything is silent except for calls and pushover notifications.
Because what could be more urgent than an error in one of my scripts :wink:

1 Like

Thank you @Spaceman_Spiff for all of your time, effort, patience while providing the HABApp framework to us. I’ve started to migrate all my JSR223/Jython scripts now. It will take a while.

I have a python file with some handy functions that I use to import from my rule python files. Those are not class methods, just stand-alone functions hence they can not interact through the self.openhab object that’s available in a typical rule class.

I wonder if it would be possible in such a function to access an openHAB group item and loop through all the members extraction the member item names. Below is my old jython function that can serve as an example:

def sayHello():
    hour = datetime.datetime.now().hour
    if (hour < 7 or hour > 21):
        return
    greetings = ['Hello', 'Good day', 'Cheers']
    people_at_home = []
    for member in scope.itemRegistry.getItem('G_Presence_Family').getAllMembers():
        if member.state in [scope.OPEN, scope.ON]:
            people_at_home.append(member.label)
    random.shuffle(people_at_home)
    msg = random.choice(greetings)
    for i in range(len(people_at_home)):
        person = people_at_home[i]
        msg += ' '+person
        if i+2 == len(people_at_home):
            msg +=' and'
        elif i+1 == len(people_at_home):
            msg +='.'
        elif i+2 < len(people_at_home):
            msg +=','
    tts(msg)
    notifyLaMetric(msg, icon='none')

I hope that it’s possible to understand what I’m trying to do. :grinning: Thanks in advance for any help.

You can create an HABApp internal Item say_hello and post True to it every time you want to do something. In a Rule you would listen for updates and then in the rule I’d make the check for 7-21.
Of course you can then iterate over the group members (I still can’t wrap my head around why this is used so much :smiley: ).
So there is no need make sayHello a library function.

You also could create an HABApp internal item people_at_home which always contains the people who are at home and keep it always up to date (HABApp items can contain use any data type as a value, even lists and tuples).

2 Likes

Hi,
I’m guessing this is the only habapp posting we have at the moment - or is there a sub forum for this?
Anyway, I’ve been using habapp for a little while now on my Windows cluster setup with OH3. One slightly annoying thing I’ve not yet resolved is that you can only start hapapp after openhab is successfully serving the homepage (a minute or two after starting). If you start habapp at the same time or even just after you start openhab, it normally fails to properly initialise and a quick restart of the habapp service (I’m using nssm) resolves it.
I could look at writing some logic in a pre-load app/script that checks if openhab is fully running/ready before launching habapp, but wondered if there is any simpler solution someone else has done.

Thanks,
Richie

Imho it could sure would make sense if there was a HABApp subsection under 3rd party.

The problem is currently it’s not clear when OH has fully started. Imho the most clean solution would be if the root endpoint of the Rest API would return the current start level of openhab. Then HABApp could properly wait for everything to be ready. But that’s something (even if it’s only a little thing) that something would have to implement.

For reboots I currently use the -wos command line argument and if I start openhab by hand I make the startup check by hand, too. :wink:

Edit:
I created an issue, maybe someone is nice and helpful and implements it.

3 Likes

Count this as a vote!

I’m currently heavily dependent on Area Triggers and Actions but since I’m now in the process of migrating all my scripts I’m curious to find out if anyone already has implemented something similar in HABApp… Otherwise I’ll give it a try.

Cheers!

You can use rules to dynamically listen to events and are able to quickly implement logic with the ItemNoChangeEvent / ItemNoUpdateEvent and the countdown timer.
Additionally you can use Parameter Files so you have a nice way of parametrizing everything or directly pass a config dict of a data class directly into your rules.

Play around with HABApp a little bit more and you’ll see that you can very quickly build similar logic that is tailored to your exact need so that the benefit of such a library is very small.


I really recommend not mixing item logic and automation logic, e.g. with metadata.
That is really bad style and normally only done as a workaround. HABApp has better ways to do it.
Everything will be easier and less error prone in the future if you separate properly.


:christmas_tree: Merry Christmas everyone! :christmas_tree:

2 Likes

Thanks @Spaceman_Spiff

I’m starting to get the hang of it, at least that’s what I believe. :grinning:

I now have my own working HABApp implementation of the Area Triggers and Actions (except for timers) and I’ve learned a lot while doing it. From now on, I’m a huge fan of HABApp so where can I buy the official HABApp T-shirt? (Just kidding, but I would buy it if there was one)

Cheers!

3 Likes

@Spaceman_Spiff , wouldn’t it be useful if the OpenhabPersistenceData had a sum()
function? :grinning:

However, I realize that I can achieve the same with

        self.rain_gauge = NumberItem.get_item('Pws_Rain')
        now = datetime.now()
        midnight = datetime.combine(date.today(), datetime.min.time())
        historical_data = self.rain_gauge.get_persistence_data(start_time=midnight, end_time=now)
        log.info(sum(historical_data.get_data().values()))
2 Likes

You can also use now.replace(hour=0, minute=0, second=0, microsecond=0) to quickly build the start time from now on so it’s one line less :wink:

2 Likes

In my old jsr223 scripts, before I commanded a new value to an Item i used to check it’s value first to avoid unnecessary calls. I guess it’s best to do the same in my HABApp scripts… e.g.

if item.state != new_state:
   self.openhab.send_command(item.name, new_state)

Am I right?

It depends.
If you want to push a command to the item then of course have to make the appropriate call.
If you just want the item to have the appropriate state then it makes sense to check before.

Note that HABApp provides various convenience function, e.g.:

if not item.is_off()
    item.off()
1 Like

Problem in installation of HABApp in a fresh openhabian 1.7.1 image

I am trying to install HABApp in a fresh installation of openhabian. The installation succeeds but HABApp does not start due to the lack of ‘pydantic’ module.
I have seen that there are threads about this error since november and I will try to manually add the packages as indicated there. Let me add the log of the openhabian ‘successfull’ install. It appears that pip is already upgraded. Maybe it is related to the fact that new installations are on the ‘bullseye’ version instead of ‘buster’?

$ apt-get install --yes python3-dev python3-venv
Lettura elenco dei pacchetti... Fatto
Generazione albero delle dipendenze... Fatto
Lettura informazioni sullo stato... Fatto
python3-dev è già alla versione più recente (3.9.2-3).
I seguenti pacchetti NUOVI saranno installati:
  python3-venv python3.9-venv
0 aggiornati, 2 installati, 0 da rimuovere e 0 non aggiornati.
È necessario scaricare 6.588 B di archivi.
Dopo quest'operazione, verranno occupati 33,8 kB di spazio su disco.
Scaricamento di:2 http://raspbian.raspberrypi.org/raspbian bullseye/main armhf python3-venv armhf 3.9.2-3 [1.188 B]
Scaricamento di:1 http://raspbian.raspberrypi.org/raspbian bullseye/main armhf python3.9-venv armhf 3.9.2-1+rpi1 [5.400 B]
Recuperati 6.588 B in 0s (13,8 kB/s)
Selezionato il pacchetto python3.9-venv non precedentemente selezionato.
(Lettura del database... 54428 file e directory attualmente installati.)
Preparativi per estrarre .../python3.9-venv_3.9.2-1+rpi1_armhf.deb...
Estrazione di python3.9-venv (3.9.2-1+rpi1)...
Selezionato il pacchetto python3-venv non precedentemente selezionato.
Preparativi per estrarre .../python3-venv_3.9.2-3_armhf.deb...
Estrazione di python3-venv (3.9.2-3)...
Configurazione di python3.9-venv (3.9.2-1+rpi1)...
Configurazione di python3-venv (3.9.2-3)...
Updating FireMotD available updates count ...
OK
2022-01-02_13:44:26_CET [openHABian] Creating venv ...
$ cd /opt

$ python3 -m venv habapp

$ chown -R openhab:openhabian /opt/habapp

$ chmod -R 775 /opt/habapp
OK
2022-01-02_13:44:43_CET [openHABian] Installing HABApp ...
$ cd habapp

$ source bin/activate

$ python3 -m pip install --upgrade pip
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Requirement already satisfied: pip in ./lib/python3.9/site-packages (20.3.4)
Collecting pip
  Downloading https://www.piwheels.org/simple/pip/pip-21.3.1-py3-none-any.whl (1.7 MB)
     |████████████████████████████████| 1.7 MB 972 kB/s
Installing collected packages: pip
  Attempting uninstall: pip
    Found existing installation: pip 20.3.4
    Uninstalling pip-20.3.4:
      Successfully uninstalled pip-20.3.4
Successfully installed pip-21.3.1

$ python3 -m pip install --upgrade habapp
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting habapp
  Downloading https://www.piwheels.org/simple/habapp/HABApp-0.31.2-py3-none-any.whl (152 kB)
     |████████████████████████████████| 152 kB 861 kB/s
Installing collected packages: habapp
Successfully installed habapp-0.31.2

$ deactivate
OK
2022-01-02_13:45:07_CET [openHABian] Creating HABApp configuration folder ...
$ mkdir -p /etc/openhab/habapp

$ fix_permissions /etc/openhab/habapp openhab:openhabian 775 775
OK
2022-01-02_13:45:07_CET [openHABian] Setting up HABApp as a service ...
$ systemctl enable --now habapp.service
Created symlink /etc/systemd/system/multi-user.target.wants/habapp.service → /etc/systemd/system/habapp.service.
OK
2022-01-02_13:45:13_CET [openHABian] Checking for default openHABian username:password combination... OK
2022-01-02_13:45:13_CET [openHABian] We hope you got what you came for! See you again soon ;)
openhabian@oh-devel:~ $ sudo systemctl status habapp.service
● habapp.service - HABApp
     Loaded: loaded (/etc/systemd/system/habapp.service; enabled; vendor preset: enabled)
     Active: failed (Result: exit-code) since Sun 2022-01-02 13:45:08 CET; 13s ago
       Docs: https://habapp.readthedocs.io
    Process: 4925 ExecStart=/opt/habapp/bin/habapp -c /etc/openhab/habapp (code=exited, status=1/FAILURE)
   Main PID: 4925 (code=exited, status=1/FAILURE)
        CPU: 120ms

gen 02 13:45:08 oh-devel habapp[4925]: Traceback (most recent call last):
gen 02 13:45:08 oh-devel habapp[4925]:   File "/opt/habapp/bin/habapp", line 5, in <module>
gen 02 13:45:08 oh-devel habapp[4925]:     from HABApp.__main__ import main
gen 02 13:45:08 oh-devel habapp[4925]:   File "/opt/habapp/lib/python3.9/site-packages/HABApp/__init__.py", line 5, in <module>
gen 02 13:45:08 oh-devel habapp[4925]:     import HABApp.__do_setup__
gen 02 13:45:08 oh-devel habapp[4925]:   File "/opt/habapp/lib/python3.9/site-packages/HABApp/__do_setup__.py", line 4, in <module>
gen 02 13:45:08 oh-devel habapp[4925]:     import pydantic  # noqa: E402
gen 02 13:45:08 oh-devel habapp[4925]: ModuleNotFoundError: No module named 'pydantic'
gen 02 13:45:08 oh-devel systemd[1]: habapp.service: Main process exited, code=exited, status=1/FAILURE
gen 02 13:45:08 oh-devel systemd[1]: habapp.service: Failed with result 'exit-code'.
o

Wishing you all a happy new year 2022 :grinning: May your code be bug free this year!

Today I’m trying to figure out the “best way” to set up logging for my HABApp rule classes.
As recommended in the documentation, I’ve extended the default configuration by setting up my own logger:

  MyRule:   # <-- Name of the logger
    level: DEBUG
    handlers:
      - HABApp_default  # This logger uses the HABApp_default
    propagate: False

It will use the same output file as the HABApp logger because I only want to watch a single log file while implementing/debugging my scripts. I do that by the tail -f command in VSC’s terminal window.

As it is now, I’ve set up logging using the following code in the beginning of each rule file:

log = logging.getLogger('MyRule')

Then each Rule Class definition uses that “file global” logger. It might look similar to

        log.debug( '[[%s]]: %s --> [%s]', self.rule_name, event.name), event.value)

A rule might have many log statements and after implementing the rule, I need to comment out all my log statements in that rule. I wish that there was a way to set the logging level per rule class instead so that when I’m finished implementing/debugging a specific rule I just edit a single line in the code … e.g. something similar to

        self.log.setLevel(logging.ERROR)

That would prevent any debug logging (from instances of this specific class) from spamming the log.

I guess that requires that each rule has its own logger and probably created dynamically, I’m not sure if it’s advisable or how you guys accomplish the same thing. I’m terrible in explaining things but I hope you can understand what I’d like to achieve. Any advice on this topic is highly appreciiated!

Cheers

I have noticed that openhabian does not update setuptools (as indicated in the docs).

python3 -m pip install --upgrade pip setuptools

but even by issuing this command the manual installation is successful but habapp does not start.
I therefore installed in the environment all the packages indicated at this link, and habapp finally started.

In summary, even though I am not an expert, I would say that there is a problem in the python distribution of bullseye and not in openhabian (where the upgrade of setuptools is lacking anyway).

Why do you think this would not work?
You have to reload the rule but you can always set log levels programatically.

I would

  • use format/f-strings for logging (% is really terrible)
  • create main loggers logically (e.g. living room, roller shutters, etc.)
    Then you can create sub loggers for the logic (e.g. livingroom.lamp).
    In the logging config you create the logger livingroom and change the level there.
    That way you have a somewhat more fine control over the loggers without making it too much effort.

The setup of pendulum is broken and I think upgrading setuptools first might fix the issue. I’ve created a PR for openhabian and it has been merged but I think they have to create an release, first.

2 Likes