HABApp 24

Good news everyone! I’ve just release a new version:

HABApp 24.01.0

This is a small release with the most notable addition of a built in rate limiter.
Full changes:

  • Added HABApp.util.RateLimiter
  • Added CompressedMidnightRotatingFileHandler
  • Updated dependencies
  • Small improvement for RGB and HSB types
  • Small improvements for openHAB items
  • Added toggle for SwitchItem

At least one person (@usambara ) reported an issue where HABApp does not connect to openHAB any more and the issue seems to be with aiohttp. Unfortunately I can not reproduce the issue at the moment. If your HABApp installation does also not connect a downgrade to aiohttp 3.8.5 might fix the issue. In any case give me a heads up.

2 Likes

Thank you. Just for clarifiaction, I am still using HABApp 1.0.8 with OH 3.4 and want to migrate step by step in order to deal with UoM.

To my knowledge HABApp 1.0.8 does not work with OH 4. Is HABApp 24.01 working with OH 3.4?

Yes - it should work as expected. You have to incorporate the HABApp changes - see the changelog from github for todos.
Protip:
Start a fresh HABApp instance on your local machine and connect read only to your openHAB instance. That way you can work on the migration and see quickly if everything works.

Thx, also for the tip :smiley:

1 Like

just a feedback: i am on oh 4.1.1 (openhabian) and installed habapp 24.01 - everything works as expected, no problems here.
thank you very much sebastian!

1 Like

Good news everyone! I’ve just release a new version:

HABApp 24.02.0

This is a small release that should fix excessive log messages with ItemTimeSeriesUpdatedEvent and brings further improved startup.

Changelog:

  • For openHAB >= 4.1 it’s possible to wait for a minimum openHAB uptime before connecting (defaults to 60s) - thanks @J-N-K for providing the value in the REST response.
    It’s possible to change this value in the configuration.
  • Renamed config entry mqtt.connection.client_id to identifier (backwards compatible)
  • ItemTimeSeriesUpdatedEvent gets ignored
  • Updated dependencies
  • Updated docs
5 Likes

I’m migrating to OH 4.1.1 and HABapp 24.02.

After the start of HABapp I am bombed with many warnings like

[WARN ] [HABApp.openhab.items                ] - Item <name> is a UoM item but "unit" is not found in item metadata

Nearly all my number items have a quantity type and a unit. So this might be a REST API issue.

i also had these warnings then, my fault was i did not specify unit in my file based *.items files. if you use filebased config check the items with warnings if you have defined “unit” in metadata like this for example:

Number:Temperature		Weather_OWM_Temperature			"Temperature [%.1f %unit%]" <temperature>		{ unit="°C", channel="openweathermap:weather-and-forecast:api:local:current#temperature" }
Number:Dimensionless 	Weather_OWM_Humidity			"Humidity [%d %unit%]"				            { unit="%", channel="openweathermap:weather-and-forecast:api:local:current#humidity" }
Number:Speed    		Weather_OWM_Wind_Speed			"Windspeed [%.1f km/h]"			                { unit="km/h", channel="openweathermap:weather-and-forecast:api:local:current#wind-speed" }
1 Like

This is a solution, somehow. but in my eyes not the correct one. Why should I configure the unit, when it is maintained correctly by OH?

In my eyes not the right field in the item’s JSON is used.

For my Netatmo station I have confgured a bunch of items (in an .items file). For the temperature the OH unit °C is used, so I have not configured a unit. The CO2 is dimensionless, so set the unit=“ppm”.

Via the API one gets the following values:

{
  "link": "http://ohdev4:8080/rest/items/Netatmo_WZ_Temperatur",
  "state": "20.2 °C",
  "stateDescription": {
    "pattern": "%.1f °C",
    "readOnly": false,
    "options": []
  },
  "unitSymbol": "°C",
  "editable": false,
  "type": "Number:Temperature",
  "name": "Netatmo_WZ_Temperatur",
  "label": "Temperatur",
  "category": "temperature",
  "tags": [],
  "groupNames": []
}

and

{
  "link": "http://ohdev4:8080/rest/items/Netatmo_WZ_Co2",
  "state": "813 ppm",
  "stateDescription": {
    "pattern": "%d ppm",
    "readOnly": true,
    "options": []
  },
  "unitSymbol": "ppm",
  "metadata": {
    "unit": {
      "value": "ppm"
    }
  },
  "editable": false,
  "type": "Number:Dimensionless",
  "name": "Netatmo_WZ_Co2",
  "label": "CO2",
  "category": "carbondioxide",
  "tags": [],
  "groupNames": []
}

Only in the second case metadata.unit.value is provided as “ppm”.

But, in both cases the field unitSymbol contains the right symbol, “°C” and “ppm”, independent of whether it is configured explicitly or not.

After setting the unit of Netatmo_WZ_Temperatur to “°F” manually in the .items file, which leads to

2024-03-02 11:36:01.037 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Netatmo_WZ_Temperatur' changed from 20.2 °C to 68.18 °F

one gets (I forgot to change the label)

{
  "link": "http://ohdev4:8080/rest/items/Netatmo_WZ_Temperatur",
  "state": "68.180 °F",
  "stateDescription": {
    "pattern": "%.1f °C",
    "readOnly": false,
    "options": []
  },
  "unitSymbol": "°F",
  "metadata": {
    "unit": {
      "value": "°F"
    }
  },
  "editable": false,
  "type": "Number:Temperature",
  "name": "Netatmo_WZ_Temperatur",
  "label": "Temperatur",
  "category": "temperature",
  "tags": [],
  "groupNames": []
}

both the unitSymbol and metadata.unit.value contain “°F”.

So in my eyes the best solution is that HABapp evaluates “unitSymbol” and not “metaData”.“unit”.“value”.

Then there is no need to maintain the “unit” field in the items file in most cases.

surely my skills are not good enough. it is already some time ago when i updated openhabian and had warnings about “unit” in the log. i searched the forum and found some more topics with the same issue, i did not refer that to a habapp issue but to a change in the management of uom in oh.

Please read up on the UoM change for openHAB and why it was required.
Then you’ll understand that you either have to set the metadata unit on the item or use a non UoM item.
The warning is justified and you should modify your items accordingly.

1 Like

I read in the UoM documentation:

In some cases the system default unit may not be the most useful unit for a given quantity. […] You can set the unit metadata to a different unit to change the item’s unit.

That means, if the system defautl unit is not the right one, one can set “unit”. So there is no need to act if the default unit is the right one.

Perhaps you are referring to the pre-4.0-documentation.

There have been multiple PRs that changed the system default which would result in HABApp not working properly any more (see the PR for 3.4 that was the root cause for the UoM change).
If you do not explicitly normalize the value there is always a chance that this might happen again.
Thus an unnormalized UoM item is just disaster waiting to happen and that’s why there is a warning.
This behavior is - until something changes on the openHAB side - not up for discussion. It’s also aligned with UI which does set the unit metadata by default.
If the warnings annoy you and you think they are issued wrongfully you can just filter them out with a log filter. :person_shrugging:

stateDescription is just how the value is visualized (e.g. in UI), metadata unit is how the value is reported to external systems (e.g. persistence or in this case HABApp).
The idea is that you can change the visualisation of an item state without having to e.g. change all values in a database.
So HABApp is of course using the correct field.

1 Like

Hi Sebastian,

I have a problem during shutdown of HABApp 24.0.2. I use EventListenerGroups plus add_listener() and listen() to create the groups and cancel() to stop listening.
During restart of a script I see the warning the event listener have already been removed, which I can ignore safely to my experience.

But during habapp service shutdown I get a big bunch of TypeErrors that flood the log:

2024-05-03 10:08:42.369 [ERROR] [HABApp.Rule] - File "/opt/habapp/lib/python3.11/site-packages/HABApp/core/internals/event_bus_listener.py", line 49 in describe
2024-05-03 10:08:42.369 [ERROR] [HABApp.Rule] - --------------------------------------------------------------------------------
2024-05-03 10:08:42.369 [ERROR] [HABApp.Rule] -      48 | def describe(self) -> str:
2024-05-03 10:08:42.369 [ERROR] [HABApp.Rule] - -->  49 |     return f'"{self.topic}" (filter={self.filter.describe()})'
2024-05-03 10:08:42.369 [ERROR] [HABApp.Rule] -    ------------------------------------------------------------
2024-05-03 10:08:42.369 [ERROR] [HABApp.Rule] -      self = <HABApp.core.internals.event_bus_listener.ContextBoundEventBusListener object at 0x7f2750327fd0>
2024-05-03 10:08:42.375 [ERROR] [HABApp.Rule] - Error "__str__ returned non-string (type float)" in unload_rule:
2024-05-03 10:08:42.375 [ERROR] [HABApp.Rule] - Error while formatting traceback: __str__ returned non-string (type float)
2024-05-03 10:08:42.375 [ERROR] [HABApp.Rule] - Traceback (most recent call last):
2024-05-03 10:08:42.375 [ERROR] [HABApp.Rule] -   File "/opt/habapp/lib/python3.11/site-packages/HABApp/rule_ctx/rule_ctx.py", line 43, in unload_rule
2024-05-03 10:08:42.375 [ERROR] [HABApp.Rule] -     to_cancel.cancel()
2024-05-03 10:08:42.375 [ERROR] [HABApp.Rule] -   File "/opt/habapp/lib/python3.11/site-packages/HABApp/core/internals/event_bus_listener.py", line 57, in cancel
2024-05-03 10:08:42.375 [ERROR] [HABApp.Rule] -     self._ctx_unlink()
2024-05-03 10:08:42.375 [ERROR] [HABApp.Rule] -   File "/opt/habapp/lib/python3.11/site-packages/HABApp/core/internals/event_bus_listener.py", line 52, in _ctx_unlink
2024-05-03 10:08:42.375 [ERROR] [HABApp.Rule] -     event_bus.remove_listener(self)
2024-05-03 10:08:42.375 [ERROR] [HABApp.Rule] -   File "/opt/habapp/lib/python3.11/site-packages/HABApp/core/internals/event_bus/event_bus.py", line 76, in remove_listener
2024-05-03 10:08:42.375 [ERROR] [HABApp.Rule] -     habapp_log.warning(f'Event listener for {listener.describe()} has already been removed!')
2024-05-03 10:08:42.375 [ERROR] [HABApp.Rule] -                     ^^^^^^^^^^^^^^^^^^^
2024-05-03 10:08:42.375 [ERROR] [HABApp.Rule] -   File "/opt/habapp/lib/python3.11/site-packages/HABApp/core/internals/event_bus_listener.py", line 49, in describe
2024-05-03 10:08:42.375 [ERROR] [HABApp.Rule] -     return f'"{self.topic}" (filter={self.filter.describe()})'
2024-05-03 10:08:42.375 [ERROR] [HABApp.Rule] -             ^^^^^^^^^^^^^^^^^^^^^^
2024-05-03 10:08:42.375 [ERROR] [HABApp.Rule] -   File "/opt/habapp/lib/python3.11/site-packages/HABApp/core/events/filter/event.py", line 64, in describe
2024-05-03 10:08:42.375 [ERROR] [HABApp.Rule] -     values += f', {self.attr_name1}={self.attr_value1}'
2024-05-03 10:08:42.375 [ERROR] [HABApp.Rule] -               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-05-03 10:08:42.375 [ERROR] [HABApp.Rule] - TypeError: __str__ returned non-string (type float)

Any hints?

Hm, this seems really strange because you are using the EventListenerGroup correctly.
Do the TypeErrors only appear during shutdown or also during reload? How do you set up the listener?

I never saw this during script restart yet.

The code is straight forward:

self._listeners = EventListenerGroup()
self._listeners_cnt = 0

With this method I add a listener:

    def __add_listener(self, item: str | BaseValueItem, event_type: Type[ValueUpdateEvent] | Type[ValueChangeEvent] | Type[OpenhabEvent], args: dict[str, Any]) -> None:
        if isinstance(item, str):
            item = BaseValueItem.get_item(item)
        
        self._listeners_cnt += 1
        self._listeners.add_listener(item, self.call, EventFilter(event_type, **args), str(self._listeners_cnt))

And with these I start and stop the listener group:

self._listeners.listen()
...
self._listeners.cancel()

I don’t see any problem in your lines of code.

The only reason I can imagine is that the EventFilter() has already been destroyed at the point in time the method describe() was called. So for some reasons during service shutdown other, additional code is executed that is not executed while a script shutdown.

Imho there are two issues which have to be analyzed separately.
The main issue is the error that your listener has already been canceled.
This should not happen with the EventListenerGroup.
The follow up issue is the failure to properly format the traceback.
Can you by any chance create a minimal example for the main error?

Currently it does not happen. So I cannot reproduce it.

I use the HABApp in a way that was not intended by you.

Before HABApp I used the Jython stuff. The Jython implementation dealt with scripts. Each script was started and stopped. So I was able to set up all my objects during start and release all my objects during stop of a script. I developed a longer list of scripts by themes. One dealt with the blinds, one with the heat pump and so on.

Due to a lack of a (documented) script object in HABApp each of my scripts consists of exactly one rule, derived from Rule, which is only used to create the context and to have a similar start and stop behavior as in the Jython implementation.

During initialization of this script_rule I setup and start all the the stuff I need within the script, e.g. create objects, timer with threads and own rule objects that mainly wrap one EventListenerGroup each. I never instantiate further HABApp rules in a script.

My rule objects can be activated (-> listener_group.listen()) and deactivated (-> listener_group.cancel()). During release of such a rule object it is deactivated first, so listener_group.cancel() is called.

While stopping a script the method script_rule.on_rule_removed() is called as documented. This I overload in order to release all objects I have created within the script.

Here also my rule objects are released, so that listener_group.cancel() is called.

At this point in time (on_rule_removed()) obviously you already have cancelled the EventListenerGroups created within the script, so that HABApp logs a warning because I try to cancel() them again.

I changed the code. Now cancel() is not called during a script or service shutdown, because HABApp takes care of cleaning up the event listeners.

1 Like