Send command from a binding?

Tags: #<Tag:0x00007f616ef05358> #<Tag:0x00007f616ef051c8> #<Tag:0x00007f616ef05010>

I’m not sure I understand the concern, either.
There are several existing bindings that can be configured to “go against convention” and issue commands to Items via channels, rather than the more usual state update.
Such commands appear on the OH event bus, just like a UI or rule issued command (and so obviously you can do the same things with them, like triggering some other binding with a channel linked to the same Item).

You might use this where the remote device is e.g. a control panel. User pokes a button, command arrives in openHAB. Just like a UI.
Switch someItem "my Light" {channel="knx:myTouchPanel" , channel="modbus:myLightRelay" }

For scheduler use, it seems reasonable that e.g. the scheduler service can command Item “alarmclock” on at 07:00.

However a compatible version would require that commands will be sent directly from the binding to other items outside the binding without the core rule engine.

I personally wouldn’t care too much on compatibility to an 1.x version as long as its functionallity could be reproduced with the new binding + rules. IMHO the binding should be rather kept simple.

To answer this it’s good to first define concepts. A binding is something that communicates with something external (in general) and communicates with openHAB through channels. Bindings are not allowed to directly talk to items and not access channels of other bindings. But this is purely a definition of a binding. Because the general concept is called an add-on. For example persistence is not a binding but an add-on. So I think we are talking about add-ons here, not specifically bindings.

So what can this be? I’m not completely familiar with how this intended to work, but it sound like a automation add-on, like a Trigger and/or Action. It’s possible to create a custom Trigger/Action and those can be configured to take an item as input/output. There are not a lot of add-ons, if you search for BaseTriggerModuleHandler only the hueemulation comes up. But in openhab-core there are more implementations that can give an idea. These automation add-ons would be completely compatible with the core rule engine.

As a replacement for CalDav-Command, this would not be using automation. I believe the specific functionality being referred to is to have a calendar entry send a command to an Item with data supplied in the description of the calendar entry when the meeting starts and ends.

Thank you all for this constructive discussion!

@AndrewFG, yes a quick PoC would be nice, the EventPublisher sounds like a great possibility to do that. It’s architecture is quite loosely coupled which is good in this case.

Yes the binding is now quite simple. However looking into the old addons’ voting thread there are many users of caldav-command. And it’s more flexible in a from user view understandable level than a big set of rules together with events-beginnings and ends.

However i want also to keep this addon maintainable - and i would like it if the addons would be later added to the official ones.

Yes, @5iver your understanding is fully correct. The binding will parse the contents of each iCalendar event looking for “Command Tags” which consist of a subject (Item name) and a targetState. At the beginning (resp. at the end) of the calendar event the binding will issue something like the following code…

    /**
     * @param tag 

     * Execute a sendCommand to the Item whose name is tag.subject, and
     * to change its state to the value in tag.targetState
     *        
     */
    private void sendCommandToOpenHAB(CommandTag tag) {
    	if (eventPublisher != null) {
	    	// TODO: we need to convert the tag.targetState String to a Command class  
	        Command command = null; 
	        ItemCommandEvent itemCommandEvent = ItemEventFactory.createCommandEvent(tag.subject, command);
	        eventPublisher.post(itemCommandEvent);
    	}
	}

As you can see from the comment in the code, I am struggling about how to convert the tag.targetState String to a Command object, so any advice here would be appreciated :slight_smile:

Done. I uploaded some files to your GitHub repo just now. It is not yet a full PoC since there are still three quite important methods that I have not yet been able to implement :frowning:

Today i’m not more able to look into code. Give me a bit time.

However, i’m really happy about the advice and the positive feedback. I think from non-technical side we can try an implementation after the PoC works.

You can see in such a way, but if you will take a look on MQTT 1.x -> 2.x migration topics are mapped to channels and things. It could send commands directly but for some reason it does not.
You either end up with multiple things, unaccepted architecture (see MQTT) or new type (s).
Be aware that some devices have a scheduling capabilities and drawing it on calendar widget would be helpful for users too.

Now I am confused. Most people here are saying that what we are proposing to do IS accepted (and therefore it does not require any new types). But you are saying the opposite. So is there any consensus on this? We want to follow the consensus, which is why @damihe created this post to discuss it.

In my perception what you do is fine, but final word will be said once you make a pull request. I am not eligible to accept these, I think other people in this topic are, but be aware that end decision can be surprising. You can end up with such conversation: https://github.com/openhab/openhab-addons/pull/1903#issuecomment-317404614 learning about dogmas and implied boundaries.

I expressed my concerns about clarity for developer here: Binding or Service ? Service Code Template. Even in this topic you can read that “Bindings are not allowed to directly talk to items and not access channels of other bindings”. My proposal for you is to not wait for consensus here but create [WIP] pull request and see what kind of feedback you will get from maintainers at github. Make it official that you want to send a command from a binding and wait for reactions.

Cheers,
Łukasz

1 Like

Hi @cweitkamp yes this EventPublisher seems definitely to be the way to go. We would use it based on pseudo- code something like that below. => So my “only” remaining question is how to instantiate the eventPublisher field in our class? – It says in your link “The EventPublisher will be injected via OSGi Declarative Services” – but what do I have to “declare”, in order to do that?

private EventPublisher eventPublisher;

private void executeCommandTag(CalendarEventCommandTag tag) {
    if (eventPublisher != null) {
        ItemCommandEvent itemCommandEvent = ItemEventFactory.createCommandEvent(tag.itemName, tag.command);
        eventPublisher.post(itemCommandEvent);
    }
}

Hi @daMihe I have now completed writing the new code (see https://github.com/openhab/openhab-addons/pull/6453) and except for the part “the EventPublisher will be injected via OSGi Declarative Services” its is ready to go. i.e. ready when you are :slight_smile:

Check out https://github.com/openhab/openhab-addons/blob/dependabot/maven/bundles/org.openhab.binding.chromecast/com.fasterxml.jackson.core-jackson-databind-2.9.10.1/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/NeeoService.java

for how to get it injected.

EDIT: you have to have it on some class marked as a @Component then the @Reference will inject the proper implementation right after initiation. If this is a true binding, usually your handler factory is a great place to have the event publisher injected and then you pass it to your handler.

Here you can find three different examples of how to injection a service into a bundle. The org.openhab.io.neeo - linked above - uses the “Method Injection”. Nowadays the “Constructor Injection” should be preferred.

Learn something new everyday - didn’t even know about constructor/field injection!

Hi @cweitkamp and @tmrobert8 many thanks for your advice.

@cweitkamp I hope you don’t mind, but notwithstanding your preference, I decided to go with the Method Injection, since I had followed @tmrobert8 suggestion to build this functionality onto the Thing Handler Factory component. And since the handler factory inherits from BaseHandlerFactory, and since BaseHandlerFactory already has its own constructor and @Activate and @Deactivate annotated methods, I did not want to get myself confused by overriding the constructor or multi- stacking @Override annotated methods on top of @Activate methods etc. ( or something like that :slight_smile: )

@AndrewFG
Since my sony addon is starting review - I changed over to the constructor injection - really simplified the class and it works fine. Here’s an example: https://github.com/tmrobert8/openhab-addons/blob/1234-Sony/bundles/org.openhab.binding.sony/src/main/java/org/openhab/binding/sony/internal/SonyHandlerFactory.java

Nope, I do not mind about that. I am just trying to help by giving hints for possible solutions. You have to figure out the best option for your use case.

I am afraid that is not true. The BaseHandlerFacrory does neither has a constructor nor annotated activate() / deactivate() methods. Even the JavaDoc states clearly that a sub class can overide them but must call super.... to initialize the BaseHandlerFactory properly.

I also think a constructor based injection is the cleaner way, just because we then don’t need a @Nullable which then needs to get checked on every access.