Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Eclipse SmartHome » Send Command to another Binding(How to programmatically send a command inside your own binding handler to anther binding)
Send Command to another Binding [message #1759952] Thu, 20 April 2017 11:46 Go to next message
Hanno Wagner is currently offline Hanno WagnerFriend
Messages: 12
Registered: April 2017
Junior Member
Hello everyone,

I am developing an openHAB binding, it already starts and runs fine and I managed to implement most of my needs. But now I am stuck and I hope, you guys can help me.
I want to control an Item of another binding (testing it with the Z-Wave binding) through the interface of my own binding this way:

In PaperUI I have two panels, one for a Z-Wave Node 4: GWPN1 Single-socket PowerNode and one for my binding. The first one has an On/Off switch, which switches the power socket and it works just fine when clicking on it. My binding has a panel with an On/Off switch as well.
Now I want to (1) click on the switch of my binding's panel, which should (2) switch the Z-Wave panel's switch, which should (3) switch the physical power socket.
But only (1) and (2) are working, there is no physical switching triggered.

What is the correct Java method call for sending a command to another binding's Channel, such that is is handled exactly as if someone had clicked in the UI?

In my handler, inside the overridden
handleCommand(ChannelUID channelUID, Command command)
method, I tried both (separately) calling handleCommand() and postCommand()
void org.eclipse.smarthome.core.thing.binding.BaseThingHandler.postCommand(ChannelUID channelUID, Command command)
void org.eclipse.smarthome.core.thing.binding.BaseThingHandler.handleCommand(ChannelUID channelUID, Command command)

with the correct parameters(ChannelUID of the power socket like this zwave:device:f3f93cbf:node4:switch_binary and Command like
org.eclipse.smarthome.core.library.types.OnOffType.ON
and the Z-Wave panel switch is switching states as expected, but the actual action (physical switch) is not carried out.
I also tried this with the Kodi binding's mute switch and it is not working as well.

The log shows the following:
Clicking on Z-Wave's panel (physical switching working):
2017-04-19 16:49:21.038 [ItemCommandEvent          ] - Item 'zwave_device_f3f93cbf_node4_switch_binary' received command ON
2017-04-19 16:49:21.051 [ItemStateChangedEvent     ] - zwave_device_f3f93cbf_node4_switch_binary changed from OFF to ON

...
2017-04-19 16:49:30.171 [ItemCommandEvent          ] - Item 'zwave_device_f3f93cbf_node4_switch_binary' received command OFF
2017-04-19 16:49:30.194 [ItemStateChangedEvent     ] - zwave_device_f3f93cbf_node4_switch_binary changed from ON to OFF


Clicking on my binding's (jade_smarthomeagent) panel (physical switching not working):
2017-04-19 16:50:55.454 [ItemCommandEvent          ] - Item 'jade_smarthomeagent_d5d1eec3_on' received command ON
2017-04-19 16:50:55.465 [ItemCommandEvent          ] - Item 'zwave_device_f3f93cbf_node4_switch_binary' received command ON
2017-04-19 16:50:55.476 [ItemStateChangedEvent     ] - jade_smarthomeagent_d5d1eec3_on changed from OFF to ON
2017-04-19 16:50:55.488 [ItemStateChangedEvent     ] - zwave_device_f3f93cbf_node4_switch_binary changed from OFF to ON

...
2017-04-19 16:51:58.448 [ItemCommandEvent          ] - Item 'jade_smarthomeagent_d5d1eec3_on' received command OFF
2017-04-19 16:51:58.464 [ItemCommandEvent          ] - Item 'zwave_device_f3f93cbf_node4_switch_binary' received command OFF
2017-04-19 16:51:58.473 [ItemStateChangedEvent     ] - jade_smarthomeagent_d5d1eec3_on changed from ON to OFF
2017-04-19 16:51:58.481 [ItemStateChangedEvent     ] - zwave_device_f3f93cbf_node4_switch_binary changed from ON to OFF



Re: Send Command to another Binding [message #1759955 is a reply to message #1759952] Thu, 20 April 2017 13:10 Go to previous messageGo to next message
Henning Treu is currently offline Henning TreuFriend
Messages: 42
Registered: April 2017
Member
Hi Hanno,

in general there are two things to say to your question:

First:
Quote:
What is the correct Java method call for sending a command to another binding's Channel, such that is is handled exactly as if someone had clicked in the UI?


Its not allowed for bindings to directly interact with other bindings or Things/Channels they do not own. During normal operation you will not be able to obtain information about Things/Channels which are controlled by other bindings. The framework does currently not check the source and target of a command. So while technically possible, it might be risky to rely on this functionality as it may change in the future.

Second:
That said, technically the
BaseThingHandler#postCommand
method should do what you want. It will post a command event to the framework´s event bus which is handled as any other command (e.g. from the UI). If you want to analyse this further please consider setting the log level for your code and the Z-Wave binding to DEBUG. The log output you posted originates from the framework reacting to the command events.

Let me know if you need any further help.

Cheers,
Henning

Re: Send Command to another Binding [message #1759960 is a reply to message #1759955] Thu, 20 April 2017 14:07 Go to previous messageGo to next message
Hanno Wagner is currently offline Hanno WagnerFriend
Messages: 12
Registered: April 2017
Junior Member
Hi Henning,
thank you very much for your swift reply!

Huh, that is bad news for me Sad But it should be possible to extend openHAB/ESH by another type of bundle (not "binding"), which implements that functionality? Actually, I did implement a complete "mirroring" facility, which receives updates for channels to display them in my binding, by making a new class extending org.eclipse.smarthome.core.items.events.AbstractItemEventSubscriber and creating a new component/service with <provide interface="org.eclipse.smarthome.core.events.EventSubscriber" /> (see implementation here: https://github.com/pokerazor/openhab-binding-jade/blob/master/src/de.unidue.stud.sehawagn.openhab.binding.jade/src/main/java/de/unidue/stud/sehawagn/openhab/channelmirror/ChannelMirrorImpl.java).
This solution is working quite smoothly and I was under the impression that this wouldn't be a hack but using API functions?

So, since BaseThingHandler#postCommand doesn't work for me as expected, I will probably have to dig deep into the code and analyse... how can I set log levels to specific bundles?

Cheers,
Hanno
Re: Send Command to another Binding [message #1759972 is a reply to message #1759960] Thu, 20 April 2017 15:26 Go to previous messageGo to next message
Simon Kaufmann is currently offline Simon KaufmannFriend
Messages: 51
Registered: January 2011
Member
Have you considered using the rule engine for that? To me it sounds like a perfect use-case for it. Just define a rule that listens to state changes on one item and send the received command to the other one. In that way it's even nicely configurable. If you would hard-code stuff like that into your binding, then nobody else can use it (unless they name their things exactly as you did...). This actually is one of the core fundamentals of this project: Bindings introduce a way how to talk to real-world devices, and on the items/rules layer you make them the devices interact with each other and do all the cool & magic stuff.

[Updated on: Thu, 20 April 2017 15:27]

Report message to a moderator

Re: Send Command to another Binding [message #1759981 is a reply to message #1759960] Thu, 20 April 2017 20:01 Go to previous messageGo to next message
Hanno Wagner is currently offline Hanno WagnerFriend
Messages: 12
Registered: April 2017
Junior Member
I did another check, starting openHAB in development mode from the eclipse IDE and used the Kodi binding, trying 3 things:

1) Switching Mute from Kodi Binding's panel Off/On
2) Switching the "On" Channel of my binding (jade_smarthomeagent) Off/On, the line [INFO ] [.o.b.j.h.SmartHomeAgentHandler:231 ] - handleCommand(... is the place, where I issue the postCommand()
3) Switching Mute directly in Kodi On/Off

Still, everything looks right in the PaperUI, but Kodi is not actually switching to mute Sad

Here is the log, I removed entries wich had nothing to to with the issue and inserted blank lines between each switching event:
2017-04-20 21:49:47.727 [DEBUG] [io.rest.core.item.ItemResource:288  ] - Received HTTP POST request at 'items/kodi_kodi_e6a65b3b_mute' with value 'OFF'.
2017-04-20 21:49:47.730 [INFO ] [arthome.event.ItemCommandEvent:43   ] - Item 'kodi_kodi_e6a65b3b_mute' received command OFF
2017-04-20 21:49:47.730 [DEBUG] [.c.thing.internal.ThingManager:355  ] - Delegating command 'OFF' for item 'kodi_kodi_e6a65b3b_mute' to handler for channel 'kodi:kodi:e6a65b3b:mute'
2017-04-20 21:49:47.731 [DEBUG] [.k.i.protocol.KodiClientSocket:194  ] - send message: {"jsonrpc":"2.0","id":37,"method":"Application.SetMute","params":{"mute":false}}
2017-04-20 21:49:47.734 [DEBUG] [.k.i.protocol.KodiClientSocket:139  ] - Message received from server: {"id":37,"jsonrpc":"2.0","result":false}
2017-04-20 21:49:47.734 [DEBUG] [.k.i.protocol.KodiClientSocket:142  ] - Response received from server: {"id":37,"jsonrpc":"2.0","result":false}
2017-04-20 21:49:47.735 [DEBUG] [.k.i.protocol.KodiClientSocket:224  ] - callMethod returns {"id":37,"jsonrpc":"2.0","result":false}
2017-04-20 21:49:47.736 [INFO ] [smarthome.event.ItemStateEvent:43   ] - kodi_kodi_e6a65b3b_mute updated to OFF
2017-04-20 21:49:47.736 [DEBUG] [.c.thing.internal.ThingManager:405  ] - Delegating update 'OFF' for item 'kodi_kodi_e6a65b3b_mute' to handler for channel 'kodi:kodi:e6a65b3b:mute'
2017-04-20 21:49:47.737 [INFO ] [s.event.ItemStateChangedEvent :43   ] - kodi_kodi_e6a65b3b_mute changed from ON to OFF

2017-04-20 21:49:49.733 [DEBUG] [io.rest.core.item.ItemResource:288  ] - Received HTTP POST request at 'items/kodi_kodi_e6a65b3b_mute' with value 'ON'.
2017-04-20 21:49:49.735 [INFO ] [arthome.event.ItemCommandEvent:43   ] - Item 'kodi_kodi_e6a65b3b_mute' received command ON
2017-04-20 21:49:49.736 [DEBUG] [.c.thing.internal.ThingManager:355  ] - Delegating command 'ON' for item 'kodi_kodi_e6a65b3b_mute' to handler for channel 'kodi:kodi:e6a65b3b:mute'
2017-04-20 21:49:49.736 [DEBUG] [.k.i.protocol.KodiClientSocket:194  ] - send message: {"jsonrpc":"2.0","id":38,"method":"Application.SetMute","params":{"mute":true}}
2017-04-20 21:49:49.766 [DEBUG] [.k.i.protocol.KodiClientSocket:139  ] - Message received from server: {"jsonrpc":"2.0","method":"Application.OnVolumeChanged","params":{"data":{"muted":true,"volume":86.0},"sender":"xbmc"}}
2017-04-20 21:49:49.766 [DEBUG] [.k.i.protocol.KodiClientSocket:149  ] - Event received from server: {"jsonrpc":"2.0","method":"Application.OnVolumeChanged","params":{"data":{"muted":true,"volume":86.0},"sender":"xbmc"}}
2017-04-20 21:49:49.768 [DEBUG] [.k.i.protocol.KodiClientSocket:139  ] - Message received from server: {"id":38,"jsonrpc":"2.0","result":true}
2017-04-20 21:49:49.768 [DEBUG] [.k.i.protocol.KodiClientSocket:142  ] - Response received from server: {"id":38,"jsonrpc":"2.0","result":true}
2017-04-20 21:49:49.768 [DEBUG] [.k.i.protocol.KodiClientSocket:224  ] - callMethod returns {"id":38,"jsonrpc":"2.0","result":true}
2017-04-20 21:49:49.769 [INFO ] [smarthome.event.ItemStateEvent:43   ] - kodi_kodi_e6a65b3b_mute updated to ON
2017-04-20 21:49:49.770 [DEBUG] [.c.thing.internal.ThingManager:405  ] - Delegating update 'ON' for item 'kodi_kodi_e6a65b3b_mute' to handler for channel 'kodi:kodi:e6a65b3b:mute'
2017-04-20 21:49:49.771 [INFO ] [smarthome.event.ItemStateEvent:43   ] - kodi_kodi_e6a65b3b_volume updated to 86
2017-04-20 21:49:49.772 [INFO ] [smarthome.event.ItemStateEvent:43   ] - kodi_kodi_e6a65b3b_mute updated to ON
2017-04-20 21:49:49.773 [INFO ] [s.event.ItemStateChangedEvent :43   ] - kodi_kodi_e6a65b3b_mute changed from OFF to ON

2017-04-20 21:49:51.866 [DEBUG] [io.rest.core.item.ItemResource:288  ] - Received HTTP POST request at 'items/jade_smarthomeagent_2337767d_on' with value 'OFF'.
2017-04-20 21:49:51.869 [INFO ] [arthome.event.ItemCommandEvent:43   ] - Item 'jade_smarthomeagent_2337767d_on' received command OFF
2017-04-20 21:49:51.870 [DEBUG] [.c.thing.internal.ThingManager:355  ] - Delegating command 'OFF' for item 'jade_smarthomeagent_2337767d_on' to handler for channel 'jade:smarthomeagent:2337767d:on'
2017-04-20 21:49:51.870 [INFO ] [.o.b.j.h.SmartHomeAgentHandler:231  ] - handleCommand(jade:smarthomeagent:2337767d:on==ACTUATE_MIRROR_CHANNEL, OFF) => postCommand(kodi:kodi:e6a65b3b:mute, OFF)
2017-04-20 21:49:51.871 [INFO ] [smarthome.event.ItemStateEvent:43   ] - jade_smarthomeagent_2337767d_on updated to OFF
2017-04-20 21:49:51.871 [DEBUG] [.c.thing.internal.ThingManager:405  ] - Delegating update 'OFF' for item 'jade_smarthomeagent_2337767d_on' to handler for channel 'jade:smarthomeagent:2337767d:on'
2017-04-20 21:49:51.872 [INFO ] [arthome.event.ItemCommandEvent:43   ] - Item 'kodi_kodi_e6a65b3b_mute' received command OFF
2017-04-20 21:49:51.873 [INFO ] [s.event.ItemStateChangedEvent :43   ] - jade_smarthomeagent_2337767d_on changed from ON to OFF
2017-04-20 21:49:51.874 [INFO ] [smarthome.event.ItemStateEvent:43   ] - kodi_kodi_e6a65b3b_mute updated to OFF
2017-04-20 21:49:51.875 [DEBUG] [.c.thing.internal.ThingManager:405  ] - Delegating update 'OFF' for item 'kodi_kodi_e6a65b3b_mute' to handler for channel 'kodi:kodi:e6a65b3b:mute'
2017-04-20 21:49:51.880 [INFO ] [s.event.ItemStateChangedEvent :43   ] - kodi_kodi_e6a65b3b_mute changed from ON to OFF

2017-04-20 21:49:53.183 [DEBUG] [io.rest.core.item.ItemResource:288  ] - Received HTTP POST request at 'items/jade_smarthomeagent_2337767d_on' with value 'ON'.
2017-04-20 21:49:53.185 [INFO ] [arthome.event.ItemCommandEvent:43   ] - Item 'jade_smarthomeagent_2337767d_on' received command ON
2017-04-20 21:49:53.186 [DEBUG] [.c.thing.internal.ThingManager:355  ] - Delegating command 'ON' for item 'jade_smarthomeagent_2337767d_on' to handler for channel 'jade:smarthomeagent:2337767d:on'
2017-04-20 21:49:53.186 [INFO ] [.o.b.j.h.SmartHomeAgentHandler:227  ] - handleCommand(jade:smarthomeagent:2337767d:on==ACTUATE_MIRROR_CHANNEL, ON) => postCommand(kodi:kodi:e6a65b3b:mute, ON)
2017-04-20 21:49:53.188 [INFO ] [smarthome.event.ItemStateEvent:43   ] - jade_smarthomeagent_2337767d_on updated to ON
2017-04-20 21:49:53.188 [DEBUG] [.c.thing.internal.ThingManager:405  ] - Delegating update 'ON' for item 'jade_smarthomeagent_2337767d_on' to handler for channel 'jade:smarthomeagent:2337767d:on'
2017-04-20 21:49:53.190 [INFO ] [arthome.event.ItemCommandEvent:43   ] - Item 'kodi_kodi_e6a65b3b_mute' received command ON
2017-04-20 21:49:53.192 [INFO ] [s.event.ItemStateChangedEvent :43   ] - jade_smarthomeagent_2337767d_on changed from OFF to ON
2017-04-20 21:49:53.193 [INFO ] [smarthome.event.ItemStateEvent:43   ] - kodi_kodi_e6a65b3b_mute updated to ON
2017-04-20 21:49:53.194 [DEBUG] [.c.thing.internal.ThingManager:405  ] - Delegating update 'ON' for item 'kodi_kodi_e6a65b3b_mute' to handler for channel 'kodi:kodi:e6a65b3b:mute'
2017-04-20 21:49:53.194 [INFO ] [s.event.ItemStateChangedEvent :43   ] - kodi_kodi_e6a65b3b_mute changed from OFF to ON

2017-04-20 21:49:58.911 [DEBUG] [.k.i.protocol.KodiClientSocket:139  ] - Message received from server: {"jsonrpc":"2.0","method":"Application.OnVolumeChanged","params":{"data":{"muted":false,"volume":86.0},"sender":"xbmc"}}
2017-04-20 21:49:58.911 [DEBUG] [.k.i.protocol.KodiClientSocket:149  ] - Event received from server: {"jsonrpc":"2.0","method":"Application.OnVolumeChanged","params":{"data":{"muted":false,"volume":86.0},"sender":"xbmc"}}
2017-04-20 21:49:58.913 [INFO ] [smarthome.event.ItemStateEvent:43   ] - kodi_kodi_e6a65b3b_volume updated to 86
2017-04-20 21:49:58.917 [INFO ] [smarthome.event.ItemStateEvent:43   ] - kodi_kodi_e6a65b3b_mute updated to OFF
2017-04-20 21:49:58.918 [INFO ] [s.event.ItemStateChangedEvent :43   ] - kodi_kodi_e6a65b3b_mute changed from ON to OFF

2017-04-20 21:50:04.134 [DEBUG] [.k.i.protocol.KodiClientSocket:139  ] - Message received from server: {"jsonrpc":"2.0","method":"Application.OnVolumeChanged","params":{"data":{"muted":true,"volume":86.0},"sender":"xbmc"}}
2017-04-20 21:50:04.134 [DEBUG] [.k.i.protocol.KodiClientSocket:149  ] - Event received from server: {"jsonrpc":"2.0","method":"Application.OnVolumeChanged","params":{"data":{"muted":true,"volume":86.0},"sender":"xbmc"}}
2017-04-20 21:50:04.136 [INFO ] [smarthome.event.ItemStateEvent:43   ] - kodi_kodi_e6a65b3b_volume updated to 86
2017-04-20 21:50:04.138 [INFO ] [smarthome.event.ItemStateEvent:43   ] - kodi_kodi_e6a65b3b_mute updated to ON
2017-04-20 21:50:04.139 [INFO ] [s.event.ItemStateChangedEvent :43   ] - kodi_kodi_e6a65b3b_mute changed from OFF to ON

[Updated on: Thu, 20 April 2017 20:03]

Report message to a moderator

Re: Send Command to another Binding [message #1759982 is a reply to message #1759981] Thu, 20 April 2017 20:17 Go to previous messageGo to next message
Hanno Wagner is currently offline Hanno WagnerFriend
Messages: 12
Registered: April 2017
Junior Member
Hi Simon, also thanks for your quick response.
Yes, I have considered and tried the rule engine, but I think, it is not quite the right solution to my challenge.
The user would need to set up two rules, one for On and one for Off. Also, I want to use meter readings from the "low level" binding. My binding would work as a kind of high-level abstraction (say, a generic washing machine connected to a Z-Wave power socket), but access the low level binding to read Watts and switch the socket on or off, but the user would for example set a time window for the washing machine on a somewhat "higher" level.
But yes, you're right, I don't want to hard code any channels, obviously. Currently my binding/thing has two configuration fields, one for the sensor-channel and one for the actuator channel. Those config properties are read on initialization and used to tap into the command/event bus.
I would like to mimic the rule engine's way to issues commands to arbitrary channels.
Re: Send Command to another Binding [message #1760027 is a reply to message #1759982] Fri, 21 April 2017 10:28 Go to previous messageGo to next message
Henning Treu is currently offline Henning TreuFriend
Messages: 42
Registered: April 2017
Member
Hi Hanno,

when you want to build a high-level abstraction then maybe a binding is not ideal from a framework point of view. As Simon mentioned before, a binding is meant to talk to real-world devices and translate state/commands to and from the framework thing/channel/item abstraction.
That said, here are three officially supported ways of integrating high-level approaches with ESH and one unsupported, more hacky way to do so:

The "hacky" way
(since this is unsupported and is also subject to a possible API change in the future I list it only for completeness. Its a less hacky way than doing cross-binding-stuff though)
You might want to checkout the hue emulation which is implemented for openHAB2. It is based on the ItemRegistry and listens for events to expose various items to the outside in a specific protocol.

The "classic" rule engine
The classic rule engine is based on Xtext (as you already know) and lets you define rules in *.rules files. You may abstract from this text files and give users the opportunity to just define specific parameters (like start- and end-time of a time window) and you prepare the rules in the background and write them to disk.
Unfortunately there is no way of defining rules programatically for the classic rule engine.

The "new" rule engine
Disclaimer: The new rule engine is still in a beta state. The available documentation still has room for improvements and can be found here.
The new rule engine consists of Triggers, Conditions and Actions. There are already Triggers, Conditions and Actions defined but also may be extended by your bundle. The combination of the three components can be done programatically which is a great advantage compared to the Xtext rule engine. There is already the possibility to provide rule templates with parameters the user has to define. In the PaperUI of ESH you can already see a UI for the new rule engine.

An external app using the REST API
With an external app you can utilise the REST interface of ESH and control nearly everything from the outside. Things/Channels/Items are exposed as well as automation rules from the new rule engine. You may register event listeners and get an event stream over SSE (server side events).
Using this way your own solution is decoupled from the internal API and since the REST API is not meant to change it is very stable.

My suggestion is to go with one of "new rule engine" or "REST API" since they are the most stable and future proof ways of integrating with ESH.

Re: Send Command to another Binding [message #1760050 is a reply to message #1760027] Fri, 21 April 2017 13:29 Go to previous message
Hanno Wagner is currently offline Hanno WagnerFriend
Messages: 12
Registered: April 2017
Junior Member
Hi Henning,
thank you very much for your detailed explanation!

I was working in parallel and managed to make the approach I tried working. postCommand() was the right call, I only confused the channelUID parameter, because it is meant to be the SOURCE channel, not the target channel/item (seems, I'm also still not confident enough with the terms yet), and the ThingManager later filters out commands which seem to originate from itself. So what I did, I added an additional ItemChannelLink to the linkRegistry and then it worked! Smile (if it is of interest, it is now available in the aforementioned Github repository)
That sounds a little bit similar to the hue emulation approach. Though to me it looks quite stable and clean, so I'm hesitant to call it hacky Wink But I can understand, that it is using the framework in a different way than expected and intended and may break in the future.

The new rule engine will probably become the "correct" solution for me in the future, extending it on the Java source side, but I wasn't able to find it's source to learn how it works, can you provide a link? As you already said, using only the documentation seems quite hard to me, it's always helpful to look at a working example.

The classic rule engine won't work for me because you can't interface with it programmatically.

The REST API is a little bit too abstract for my purpose, I would like to directly access the Java objects.

Yes, I'm still not sure whether a "binding" would be the entirely correct approach/extension type, but on the other hand the metaphor is quite OK, because to the user it looks like any other smart device. I try to "smartify" dumb devices by turning your usual washing machine into a "smart" one through an arbitrary switchable power socket.

I will try to figure out, what the best way may be.

Thanks again for your help!
Previous Topic:Channel Configuration
Next Topic:Newbie question about new biding
Goto Forum:
  


Current Time: Thu Nov 15 12:09:37 GMT 2018

Powered by FUDForum. Page generated in 0.02826 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top