Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added ability to listen to all events #379

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

dobernhardt
Copy link

For scenarios where not all possible items are know upfront it might be beneficial to be able to listen to all events on the bus.
This change adds the ability to add a catch all event listener by specifying the topic HABApp.Any

spacemanspiff2007 and others added 6 commits April 5, 2023 08:20
* Added a warning when dynamically creating rules
* Add log entry for threaded loggers (closes spacemanspiff2007#358)
* Thing status is a StrEnum
* Small doc fixes
* Added py.typed
* Updated dependencies
* small refactor
* asyncio refactor
* doc fix
* Inspect HABApp
@spacemanspiff2007
Copy link
Owner

This was actually possible in older versions of HABApp.
However I removed it due to the lack of usage and because I haven't had a use case which I couldn't solve by dynamically creating the listeners based on the name.
E.g. by passing the Shelly-ID to a rule I was able to construct all required topics.

Can you outline the use case and why you want to achieve that?

@dobernhardt
Copy link
Author

I currently have two usecases for the catch_all listener:

  1. I have a persistence solution in habapp that currently grabs all items and attaches listeners to all of them
for item in Items.get_items ():
            if isinstance(item, OpenhabItem):
                self.logger.debug (str(item.name))
                num_items = num_items +1
                item.listen_event(self.item_updated,ValueUpdateEventFilter()) 

Whenever I add an item I need to restart this rule. Having a catch_all listener a HABApp persistence solution would be a bit simpler

  1. As already mentioned in the openhab forum I have some rules dealing with shellies and tasmotas. To do autodiscovery it would be beneficial to listen to all mqtt topics below a certain prefix. For shellies not really necessary as they all use shellies/announce

For the MQTT sub hirarchy handling an alternative option would be to directly work with the MQTT client and bypass the habapp event bus.

In sumary non of my scenarious would be impossible without the catchall but they would be easier. Where do you see a concern in having catch all functionality?

@spacemanspiff2007
Copy link
Owner

Whenever I add an item I need to restart this rule. Having a catch_all listener a HABApp persistence solution would be a bit simpler

You can listen to openHAB.Items. All ItemAdded / ItemRemoved / ItemUpdatedEvent events will appear there. So there is no need to manually restart the rule. You just have to create listeners for all items on startup and then can track the changes through the topic.
Maybe I have to add an example to the docs but I think that's much more elegant than to listen to all events.

2. To do autodiscovery it would be beneficial to listen to all mqtt topics below a certain prefix.

I agree this is a tricky one and I have not yet come up with a simple and elegant solution.
Does tasmota use retain for auto discovery? Retained topics will be stored in a MqttItem.
HABApp connects to mqtt before it loads the rule so at least it's possible to auto generate all devices when the rule is loaded for the first time.
Maybe it makes sense to implement something for retained messages? Maybe MQTT.Items and issue some kind of ItemAddedEvent there?

In sumary non of my scenarious would be impossible without the catchall but they would be easier. Where do you see a concern in having catch all functionality?

I'm hesitant to add this again because it feels like there has to be a more elegant and better solution than to additionally process every event. However this is not a very strong opinion so you might be as well successful to convince me otherwise.
In the mean time you can use your implementation of the EventBus and override the HABApp.core.internals.EventBus with your implementation and play around with it.

@dobernhardt
Copy link
Author

You can listen to openHAB.Items. All ItemAdded / ItemRemoved / ItemUpdatedEvent events will appear there.

That's a good hint. I will give that a try.

Does tasmota use retain for auto discovery? Retained topics will be stored in a MqttItem.

Yes, the tasmota topics are retained. I.e. if I could iterate over all MqttItems that would also be an option.
But I still think that a typical use of Mqtt is, to listen to a complete hierarchy of topics. That is probably quite different to how to deal with openhab items.

In the mean time you can use your implementation of the EventBus and override the HABApp.core.internals.EventBus with your implementation

Could give me one more hint how to use custom startup code to override the internal EventBus implementation? My approach would have been to just work on my branch

@dobernhardt
Copy link
Author

I'm hesitant to add this again because it feels like there has to be a more elegant and better solution than to additionally process every event.

I completely understand this concern. If we want to keep the event processing in EventBus one option would be to introduce a new kind of MqttItem that represents a complete subtree.
At the end I'm not so much interested in listening to all events but primarily to listen to some Mqtt events where I do not know the exact topic upfront

@spacemanspiff2007
Copy link
Owner

spacemanspiff2007 commented May 9, 2023

if I could iterate over all MqttItems that would also be an option.

It works exactly like you iterate over the openHAB items.

Could give me one more hint how to use custom startup code to override the internal EventBus implementation? My approach would have been to just work on my branch

Just create a HABAppUser module as described in the docs and there you can assign your own event bus.
Somehow like this (untested).

import HABApp

class MyEventBus(HABApp.core.internals.EventBus)
    pass

HABApp.core.internals.EventBus = MyEventBus

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants