I’m currently working on a setup using static .thing configuration files and ran into an architectural limitation that I would love to discuss with the community.
The Challenge:
Currently, many bindings provide powerful “Thing Actions” (e.g., sending a custom raw command, triggering a specific discovery/reboot sequence, or executing a dynamic API call). However, if you want to trigger these actions directly from the MainUI, openHAB forces you to go through the UI → Item → Channel → Thing pipeline.
For statically defined things, this means creating dummy Items and boilerplate Rules just to forward a UI button press to a Thing Action.
The Idea:
I am thinking about a way to make Thing Actions directly interactable via the UI for static definitions, without requiring a backing channel. Since MainUI is highly customizable, it would be amazing if a Widget Action could directly call a Core/Thing Action.
Something like a new UI action type:
Action:rule-action or thing-action
Thing UID:binding:type:mything
Action Name:myAction
Parameters:[param1, param2]
Questions for the Community & Maintainers:
Has this been proposed before, and were there fundamental architectural objections (e.g., breaking the abstraction layer between UI and Things)?
Since text-based .thing files don’t easily support dynamic channels, could a REST API extension for direct Action execution be the right way forward?
If I want to look into creating a Pull Request for this, should this be implemented purely as a core REST extension (/rest/things/{thingUID}/actions), or is this strictly against the openHAB design philosophy?
Not necessarily. You could do this with just the rule. The UI can call a rule directly without needing to go through an Item.
I don’t see how the “static definitions” part is relevant. Discovered Things and statically defined Things have the same limitations in this reguard.
You actually could achieve this today with a single rule.
From the widget use the “action:rule” as the action that occurs when the widget is clicked. When you choose this as the action, the UID of the rule to call and a JSON object for the context. You’ll configure the context as { "binding": "mqtt", "thingid": "mqtt:some:thing:id", "action": "publishMQTT", "arguments": ["some/mqtt/topic", "message", true"] }. This will be passed into the called rule. (The YAML formats have changed a little so I’m not sure of the exact syntax right now, it used to be something like:
I’ve not done this myself so there might be something wrong with the JS.
The thingActions is relatively new so if you are on an older OH you’d use actions.get().
The big thing I’m not certain of is if the context variables are passed in like above or if you need to pull them from the ctx Object.If the latter the rule becomes:
Note this uses some JS specirfic features, namely using ["functionName"]() to call a function when you only have it’s name as a String and ... to “spread” the array into the arguments to the function call.
Some work has been done on the API to enable the abilty for the API to make the Thing’s actions callable through the REST API (a prerequisite to make being able to configure the wdiget action to call them directly). And in UI rules one can configure a direct call to a Thing’s Actions and the form is already there with all the arguments. So theoretically the openhab-webui oh-X widgets would just need to have a new action created that lets the user call the actions directly. Most everything else is already in place.
I don’t see how that’s relevant. A Thing does not require dynamic Channels to have actions that can be called. And whether you define a Thing via a .things file, the new(ish) yaml formatted files, or through the UI, if the binding supports an action for the Thing the action will be availble to call.
That part is already impelmented. You’d just need to add a new type of widget action and the UI stuff necessary to support it.
I’m not intierly sure I undertsand your reply but I think you are saying the same thing. All the API stuff already exists. It’s strictly the a widget library and UI (i.e. the UI that lets you create a widget from MainUI) that needs to be implemented.
I tested this in openHAB 5.1.4 with a small binding-side ThingActions implementation, exposed through getServices() and annotated with @RuleAction / @ActionInput.
Result: the actions do indeed appear directly on the Thing properties page, with an input dialog generated from the action method parameters. So this is exactly the native path I was looking for.
I also checked ActionInputsHelper and now understand that action inputs are mapped to ConfigDescriptionParameter instances, which explains the rendered input fields. For richer persistent UI controls like options/sliders, channels or config descriptions still seem to be the better fit, but for one-shot operations like reboot(), permitJoin(), stopJoin(), rediscover(), forget(), Thing Actions are a clean solution.
Thanks again for pointing me in the right direction. A massive shoutout and respect to all the contributors and developers who make openHAB possible!