HABApp 25

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

HABApp 25.04.0

This is a huge release which changes lots of HABApp internals.
Most notably this changes the communication with openHAB to web sockets which results in a very nice speed boost.


Changelog:

  • Updated thread pool and asyncio handling
  • Dropped support for OpenHAB 3
  • Number item has a dimension property which is set if it’s a UoM item
  • Added QuantityInt and QuantityFloat which is normal int/float but carries the unit in .unit
  • Added Point datatype for dealing with coordinates
  • Added StringList
  • Use websockets for openHAB connection
  • Sending events and commands to openHAB is stricter and will raise an error if the value will not be accepted
  • Removed ComplexEventValue
  • Added RingCounter, RingCounterTracker and ExpiringCache to utils
  • on_rule_loaded and on_rule_unloaded can be both sync and async
  • Changed license to EUPL

Thank you for providing valuable feedback during the HABApp Beta
@bastler @Dominik_Bernhardt @hakan @Lionello_Marrelli @usambara

If you experience any issues with the new version please use this thread to ask for help

6 Likes

i am on openhabian with openHAB 4.3.5 - Release Build. i uninstalled HABApp-25.2.0.dev7 and installed HABApp-25.4.0 and at first sight everything seems to work without having to change anything. great! thank you @Spaceman_Spiff

1 Like

I updated this evening from 24.11.1. Since all known incompatibilities have been fixed this went smooth.
But now I came across a topic:
Before I had this code (the triggering item is a ColorItem):

    # Farbe (HSB)
    def _Cmd_Color(self, event: ItemCommandEvent) -> None:
        LOGGER: Final[str] = "{}: ".format(inspect.currentframe().f_code.co_name)

        if not isinstance(event.value, tuple):
            # Kommando ignorieren, wir werten nur Farbcodes aus
            self._log.info(LOGGER + "Kommando {} ignoriert".format(event.value))
            return

but now it is not working anymore and it needs:
if not isinstance(event.value, tuple) and not isinstance(event.value, HSB):
Maybe the test for tuple can be removed now.

Correct! The raw value tuples have been removed.
ColorItems will always use the HABApp HSB type and LocationItem will use the new HABApp Point type, only CallItem will still use StringListType which is a tuple.

The only place where this is different will be an isinstance check but you can still access the values like before, e.g.

h, s, b = HsbObj
h = HsbObj[0]

Thank you for your continued maintenance and improvement of HABApp.

The new version is a good reason for a migration from 24.08 to 25.04.

Unfortunately I am missing the classes OnOffValue and OpenClosedValue, Their literals, e.g. OnOffValue.ON, I use in more or less all rule files.

You are now using the literals in StringItem and ContactItem directly. In addition you defined new model classes, also w/o defining ON, OFF, … explicitly.

Will it stay that way in the next releases?

I think I will introduce an corresponding Enum or something like that in the next major version again. However I’m not 100% sure how it will look like. There are many changes at the moment because openHAB changes some of the internals with 5.0 (e.g. last_update and last_change comes to openHAB, too).

If you really use it that much I suggest that you create a file in the lib folder where you define these constants. That way your imports keep static (and these values never change anyway).

An alternative would be to use the corresponding item types instead of the event:

def __init__(self):
    self.switch_item.get_item('MySwitchItem')
    self.switch_item.listen_event(self.change, ValueChangeEventFilter())

def change(self, event):
    self.switch_item.is_on()  # <-- this works with full ide support

Thank you. I already created a file lib/definitions.py.

At the moment I don’t know whether I will switch to openHAB 5.

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

HABApp 25.05.0

This is a small release which fixes bugs with scientific floats for UoM items and a small bug with the InstantView.

It also bumps the whenever library to 0.8.0 which introduced some changes.
If your using this library yourself please refer to the change log.

i tried to install the new version with this code:

python3 -m pip install git+https://github.com/spacemanspiff2007/HABApp.git@Develop

but i recieve this error:

Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting git+https://github.com/spacemanspiff2007/HABApp.git@Develop
  Cloning https://github.com/spacemanspiff2007/HABApp.git (to revision Develop) to /tmp/pip-req-build-_hg8uuyf
  Running command git clone --filter=blob:none --quiet https://github.com/spacemanspiff2007/HABApp.git /tmp/pip-req-build-_hg8uuyf
  WARNING: Did not find branch or tag 'Develop', assuming revision or ref.
  Running command git checkout -q Develop
  Fehler: Pfadspezifikation 'Develop' stimmt mit keinen Git bekannten Dateien überein
  error: subprocess-exited-with-error
  
  × git checkout -q Develop did not run successfully.
  │ exit code: 1
  ╰─> See above for output.
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
error: subprocess-exited-with-error

× git checkout -q Develop did not run successfully.
│ exit code: 1
╰─> See above for output.

note: This error originates from a subprocess, and is likely not a problem with pip.

sorry i am lost, what can i do here?

got it, with

python3 -m pip install habapp

version 25.5.0 is installed

I forgot to create a new Developement branch - sorry!
Glad you got it working though!

1 Like

If I am right, last_update and last_change are provided in milliseconds since the epoch in the API.

I use the same value as time type throughout my whole code, that means, I convert naive and timezone-aware datetimes to milliseconds since the epoch, also the datetimes you provide currently as last_update and last_change.

So I would appreciate if you could provide the original openHAB 5 values, e.g. as last_update_ms / last_change_ms or …_since_the_epoch, so that people like me could save some conversion.

Additionally I do not need to take care of Pendulum datetimes then.

It’s an InstantView which provides various convenience options.
See Timestamps for code samples. The underlying data type is an Instant from whenever.

However you can just use InstantView.now() in your code and then don’t have to take care of anything and deltas / compares should just “work”.

Edit:
I just realize you might refer to the openHAB api. There it’s reported as an ISO DateTime string.
The last_change and last_update already works, it might just be off a couple of ms because it’s the instant when the change is received and not the instant when the change is emitted. However that’s negligible.

Edit2: Do you mean you would like a convenience conversion function instead of using InstantView.now()?

I see, my fault. In my current HABApp 24.08 installation last_update and last_change provide (Pendulum) datetimes.

I convert those to milliseconds since the epoch and therefore I am interested in the upcoming openHAB 5 values "lastStateUpdate" and "lastStateChange", provided in the REST API of an item.
So I was asking whether you could provide those values w/o any conversion in the upcoming HABApp interface, e.g. as properties oh_last_update / oh_last_change.

Just for clarification: Since 24.11 I need to take item.last_update.py_datetime() to derive milliseconds since the epoch? Or is there is a less expensive way?
InstantView.py_datetime() is self._instant.to_system_tz().to_plain().py_datetime()…

EDIT: It would be great if you could provide InstantView.timestamp_millis() as property.
That is self._instant.timestamp_millis() for openHAB 4.
Starting with openHAB 5 you could pass through the API values directly there.