HABApp - Easy automation with openHAB

I strongly disagree. If you compare items you always want to only compare the state.
If you take the item into account this would fail:

assert Item.get_create_item('a', initial_state=1) == Item.get_create_item('b', initial_state=1)

In python if you want to check for equality of objects you have to use the “is” operator, not the “==” operator !!

StringItem.get_item('a') is StringItem.get_item('a')  # True

But since all items have a .name property I’d just compare that.


Unrelated:
I sometimes wonder if your approach of using another abstraction layer over HABApp is really worth all the effort. I get where you coming from and that you might want to switch back to the internal rule engine.
But to be compatible you can’t use all the good stuff or you have to re implement everything yourself (e.g. ItemNoUpdate events with item.watch_update, MultiModeItems, textual thing configuration).

If the rule logic is already in place it’s always easy to migrate back and forth between two “languages”.
Imho much easier and way less effort than to always try to merge two things in an abstraction layer that are not actually meant to be merged.

Seb, the reason I think the item name should be part of the equality check is that the majority of our items are backed by OpenHab items, and in that world equality is based on the item name. You can see this in openhab-core/GenericItem.java at main · openhab/openhab-core · GitHub.

That said I understand if you wanted to take a different approach. Would perhaps one or two lines documentation on this be reasonable, especially as this is a significantly different approach?

My zone-api work started quite a while back when I was working with the Jython library. In my post comparing HABApp versus Jython, I mentioned of abstraction layer on top of HABApp mainly to motivate people to adopt HABApp. There are always fears when it comes to changing the underlying frameworks. To be honest, I do not expect OpenHab to run in GraalVM and thus supporting Python3 anytime soon. Thus the chance of my work moving back to Jython is very low.

That said, IMO, my zone-api is sort of a framework itself sitting above OpenHab (and thus also sitting above HABApp and Jython). Working with the native item layer in OpenHab is too primitive. I strongly believe that an abstraction for the devices makes much more sense. We would be dealing with rooms, devices such as light, camera, chromcast, and actions that operate on those devices. A device is made up of zero (virtual device), one or more OpenHab items. The framework allows for reusable of actions, as the actions have meta data to indicate the zone, the devices, and the events that it can operate on.

I recently added some docs on what my library does at GitHub - yfaway/zone-apis: APIs to group Home Automation devices / sensors into zones and associate them with actions. It remains just a personal project as I don’t have a lot of time. But the idea if fully developed would allow reusability of rules.

Be it as it might, but in python there is an explicit operator for object equality and another one for object identity.
So you can either use

StringItem.get_item('a') is StringItem.get_item('a')   # True
OpenhabItem.get_item('a') is StringItem.get_item('a')  # True

which will compare object identity and since both items come from the registry this will work
or use the name property to check if they have an equal name

StringItem.get_item('a').name == StringItem.get_item('a').name   # True
OpenhabItem.get_item('a').name == StringItem.get_item('a').name  # True

That’s very nice and I have sure misread that part.
It’s awesome that you build your own framework and I definitely encourage you to continue to do so.
I guess my point was:
As long as you keep compatibility with jsr223 you can’t use all the cool HABApp stuff and features.
Maybe migrate your framework once to HABApp and make use of the nice things.
If in the future you’ll migrate away from HABApp the time saved through the nice things will still be greater than the time for both migrations.

This worked for me!

I just released HABApp 0.20.2

Scheduling is a great feature in HABApp and has some interesting addons like jitter.

But today i do not see the solution: I like to run something every hour at a specific munite and seconde. to be preceise every hour at minute 0 and second 0

I just updated my openhab installation from 2.x to 3.1M3 and made more. use of the semantic modelling via tags. I was wondering whether it would be useful to have access to the tags in habapp. I.e. get all items that relate to “light”. Or more general have access to the /items api endpoint of the openhab REST api to query items.
Any thoughts? Anyone else interested in this?

@Dibbler42
You can specify the time the function runs for the first time in run_every

from datetime import datetime, timedelta
self.run_every(datetime.now().replace(minute=0, second=0), timedelta(hours=1), my_function)

@Dominik_Bernhardt
The interface is already there, but just missing the get_all_items function.
It’s a rest call that takes quite some time and you have to parse the tags yourself.
Additionally I am not sure if there is an ItemChangeEvent emitted by openhab if you add/remove a tag - maybe you can test that out?
Imho a good naming scheme will make access to tags obsolete because you can quickly iterate over all items and get the ones you need (e.g. get all items that end with _Light). The textual thing configuration also encourages proper naming.
However if there is a good mechanism to keep data in sync I can see this implemented (at some point :wink: )

1 Like

@Spaceman_Spiff I tried it with the replace command, but it did not work. If you see the time stamps in my log

[2021-04-08 20:19:10,718] [                    Rules]     INFO | Energy management: Initialized.

[2021-04-08 20:19:10,719] [             HABApp.Rules]     INFO | Added rule "NaturalGasManager" from energymanagement.py

[2021-04-08 20:21:06,532] [                    Rules]     INFO | Energy management: New value = 1650.209999m³.

[2021-04-08 20:23:21,053] [                    Rules]     INFO | Energy management: New value = 1650.23m³.

[2021-04-08 20:25:21,410] [                    Rules]     INFO | Energy management: New value = 1650.24m³.

[2021-04-08 20:28:10,341] [                    Rules]     INFO | Energy management: New value = 1650.26m³.

[2021-04-08 20:30:45,167] [                    Rules]     INFO | Energy management: New value = 1650.280001m³.

[2021-04-08 20:33:05,803] [                    Rules]     INFO | Energy management: New value = 1650.299999m³.

[2021-04-08 20:35:12,511] [                    Rules]     INFO | Energy management: New value = 1650.309999m³.

[2021-04-08 20:38:07,559] [                    Rules]     INFO | Energy management: New value = 1650.34m³.

[2021-04-08 20:40:48,447] [                    Rules]     INFO | Energy management: New value = 1650.360001m³.

[2021-04-08 20:43:15,418] [                    Rules]     INFO | Energy management: New value = 1650.379999m³.

[2021-04-08 20:45:28,227] [                    Rules]     INFO | Energy management: New value = 1650.42m³.

[2021-04-08 20:47:26,872] [                    Rules]     INFO | Energy management: New value = 1650.48m³.

[2021-04-08 20:50:14,105] [                    Rules]     INFO | Energy management: New value = 1650.549999m³.

[2021-04-08 20:52:47,181] [                    Rules]     INFO | Energy management: New value = 1650.6m³.

[2021-04-08 20:55:06,091] [                    Rules]     INFO | Energy management: New value = 1650.639999m³.

[2021-04-08 20:57:10,847] [                    Rules]     INFO | Energy management: New value = 1650.67m³.

[2021-04-08 21:00:04,182] [                    Rules]     INFO | Energy management: New value = 1650.709999m³.

[2021-04-08 21:02:43,354] [                    Rules]     INFO | Energy management: New value = 1650.719999m³.

[2021-04-08 21:05:08,370] [                    Rules]     INFO | Energy management: New value = 1650.74m³.

[2021-04-08 21:07:19,477] [                    Rules]     INFO | Energy management: New value = 1650.76m³.

[2021-04-08 21:10:18,911] [                    Rules]     INFO | Energy management: New value = 1650.780001m³.

[2021-04-08 21:13:04,189] [                    Rules]     INFO | Energy management: New value = 1650.799999m³.

[2021-04-08 21:15:35,552] [                    Rules]     INFO | Energy management: New value = 1650.82m³.

[2021-04-08 21:17:52,758] [                    Rules]     INFO | Energy management: New value = 1650.84m³.

[2021-04-08 21:19:11,008] [                    Rules]     INFO | Energy management: Hourly update

[2021-04-08 21:19:55,803] [                    Rules]     INFO | Energy management: New value = 1650.870001m³.

so the hourly intervall is working, but the initial value doen’t. I put the “datetime.now().replace(minute=0, second=0)” in a log statement and get the right starting time, so i assume that there is some other thing wrong.

Any ideas?

Hm - it looks like a bug because I’m sure this has been working already. :unamused:
I’m currently in a rather big rewrite of the scheduler so this will be fixed with the next big release.
If you like you can already look at the “Develop” branch and test it from another machine(!) but be aware that there are/might/will still bugs in it.

Just a heads up for everyone:

The next version of HABApp will drop support for python 3.6.
Every major distribution is at least at 3.7 so this should be no problem but be sure to double check.
There will also be code changes necessary to properly use the scheduler but I’ll wrap the new usage in the old functions and issue a deprecation warning.

1 Like

As I was struggeling with getting persistence running after my upgrade to OH3 I quickly implemented an OH3 compatible influxdb persistence as an habapp rule.
Just if someone is interested…

class InfluxDBPersistence(HABApp.Rule):
    def __init__(self):
        super().__init__()
        self.logger = logging.getLogger("RuleLoggers").getChild (self.rule_name)
        self.logger.debug ("Initializing Persistence")
        config = HABApp.Parameter("influxdb").value
        self.client = InfluxDBClient(url=config['url'], token=config['token'], org=config['org'])
        self.bucket = config['bucket']
        self.write_api = self.client.write_api(write_options=WriteOptions(batch_size=10))
        num_items = 0
        for item in HABApp.core.Items.get_all_items():
            if isinstance(item, OpenhabItem):
                num_items = num_items +1
                item.listen_event(self.item_updated,ValueUpdateEvent)
        self.logger.info (f"Init completed. Registered {num_items} items")


    def item_updated(self,event):
        if event.value is not None:
            item_name = event.name
            item = HABApp.core.Items.get_item(item_name)
            if isinstance(item,SwitchItem):
                item_value = 1 if item.is_on() else 0
            elif isinstance(item,ContactItem):
                item_value = 1 if event.is_closed() else 0
            elif isinstance(item,NumberItem) or isinstance(item,DimmerItem) or isinstance(item,RollershutterItem):
                item_value = float(event.value)
            elif isinstance(item,DatetimeItem):
                item_value = int(event.value.timestamp() * 1000)
            else:
                item_value = str(event.value)
            record = {
                "measurement": item_name,
                "fields": {
                    "value": item_value
                },
                "tags": {
                    "item": item_name
                }
            }
            self.write_api.write(bucket=self.bucket, record=record)

                
InfluxDBPersistence()
2 Likes

Seb, I just upgraded to OpenHab3, and had to do this change to get HABapp to work w. OH.

Run “ssh -p 8101 openhab@localhost”. Use password “habopen”.
Once inside the section, run "bundle:stop org.openhab.core.io.rest.auth:

I notice that your patch for OH is now merged. Does it mean that we don’t have to run the above command for OH 3.1 and above? However, we would still have to enable the Basic digest authentication for REST API in the Settngs UI.

What do you think about adding section for configuring OH? E.g.:

  • 2.5.x: no need to configure anything
  • 3.0.1 → 3.1.0: disable rest authentication as above.
  • 3.1.0+: enable Basic digest authentication for REST API in the Settngs UI and configure username and password in HABApp’s config.yml file.

Thanks,

Hai

In the 3.1.0 M3 the changes are already included.
If there is a Cache Expiration Time Parameter the requests will be speed up.
There is no need for any more commands, just activate basic auth.

grafik

good idea

Good news everyone! Release 0.30.0 is out!

1 Like

Hi Sebastian - quick and possibly dumb question. How do I create an event listener that is triggered only by a command sent to an item, and not mere updates? ValueUpdateEvent and ValueChangeEvent seems to be triggered by updates and commands.

thanks!

Dan

Use HABApp.openhab.events.ItemCommandEvent as an event filter.

ValueUpdateEvent gets triggered by an ItemStateEvent, since the latter is a subclass of the former.

In the Example 1 the last listener uses it.

thank you again!

hello @Spaceman_Spiff i’ve noticed an error while creating item tags: it doesn’t properly set values in example:

create items:

  • type: Group
    name: ‘{thing_label, “\s+”, “"}’
    label: '{thing_label, “\s+”, "
    ”}’
    groups: [‘gThermostats’]
    tags: [‘HVAC’]
    metadata:
    model: ‘ZTEMP2’

creates
Group termostatoMatrimoniale “termostatoMatrimoniale” (gThermostats) [HVAC] {model=“ZTEMP2”}

instead of

Group termostatoMatrimoniale “termostatoMatrimoniale” (gThermostats) [“HVAC”] {model=“ZTEMP2”}

so the semantic model doesn’t working properly. did you already know it? is there a way to fix this?
thanks in advace

No, just heard of it

Is this only a problem with the generated *.items file or an actual problem with the generated item?