-
Notifications
You must be signed in to change notification settings - Fork 784
Conversation
Hm, I find it very hard to follow the ESH documentation in some parts and the newly added profiles.md is one of those sections that would highly confuse me. I think this is mainly because there are no diagrams that provide an overview with whom and how profiles are interacting with other components and there are no example usages. |
I agree, the docu is not yet complete. Examples can be added only once it actually can be configured. As this part is yet missing, there is not much to put there right now. I will add some pictures for the concrete profiles once all this here somehow got agreed. I hope it will get clearer then. For the time being I just thought it's important to write it down anywhere at all. For all the other confusing parts: Fully agreed. Any help is highly appreciated! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good, just some very minor remarks.
|
||
private final Logger logger = LoggerFactory.getLogger(CommunicationManager.class); | ||
private final Set<String> subscribedEventTypes = ImmutableSet.of(ItemStateEvent.TYPE, ItemCommandEvent.TYPE, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you do it without Guava?
* @author Simon Kaufmann - initial contribution and API. | ||
* | ||
*/ | ||
public class DefaultSlaveProfile extends DefaultMasterProfile { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does it extend the master profile? Shouldn't it rather implements StateProfile
as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just was trying to prevent code duplication by delegating slave's onUpdate(...)
to master's onCommand(...)
. But I see this is confusing. I will change that.
* This is the default profile for stateful channels. | ||
* | ||
* It forwards commands to the {@link ThingHandler}. In the other direction it posts events to the event bus | ||
* for state updates and commands which are initiated by the handler. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"...and commands which are initiated by the handler" - was that really a use case for a "master" device? Do you have an example?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really good point - I just mindlessly took that from the old API. Now thinking about it, I don't have a good example.
No binding in ESH is using it.
In openhab2-addons there are only two bindings using it: lutron and squeezebox. I'm not familiar with both yet, so it's hard to judge whether this in fact is correct or not. On a first glance it looks like it might not be needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PS: Just do double-check I read you correctly: This is not only about the JavaDoc, but you are suggesting to make master's "postCommand" a no-op. Correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct.
import org.eclipse.smarthome.core.thing.link.ItemChannelLink; | ||
import org.eclipse.smarthome.core.thing.profiles.TriggerProfile; | ||
|
||
public class RawButtonTriggerProfile implements TriggerProfile { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JavaDoc missing
* <p> | ||
* This allows devices to be operated as "slaves" of another one directly, without the need to write any rules. | ||
* <p> | ||
* No events are send for state updates or commands initiated by the ThingHandler. They are assumed to be passive only. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: are sent
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry if I forgot the details again: Taking the KNX wall switch as an example. Would this have to be modelled as two channels? One with master-profile only sending commands and one with slave-profile only receiving updates? What spoke against allowing slave-channels to send commands (to their "master" within ESH)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What spoke against allowing slave-channels to send commands (to their "master" within ESH)?
Nothing really, IIRC.
If a slave issues a command towards ESH, it will have to live with the fact that the state bounces back as an update via the master (which then gets turned into a command again by the slave profile, this time flowing from ESH towards the binding). But that shouldn't matter much - it rather makes sense because it gets the real value that the master reported back as an update, which is not necessarily identical to the command that the slave initially sent towards ESH.
Signed-off-by: Simon Kaufmann <simon.kfm@googlemail.com>
...between the framework and the binding (i.e. ThingHandler). By now, the profiles are still statically set. Selecting a different profile for a link will be done in a next step. Signed-off-by: Simon Kaufmann <simon.kfm@googlemail.com>
Signed-off-by: Simon Kaufmann <simon.kfm@googlemail.com>
...and adding a slave profile which could be used instead in order to configure channels to react on item state updates and therefore running as "slave" of another one. Signed-off-by: Simon Kaufmann <simon.kfm@googlemail.com>
Signed-off-by: Simon Kaufmann <simon.kfm@googlemail.com>
41e8898
to
a2d3488
Compare
There are 3 test failures:
|
a2d3488
to
c32139f
Compare
My bad, I neglected to update the tests... |
Still one failing test :-( |
Signed-off-by: Simon Kaufmann <simon.kfm@googlemail.com>
c32139f
to
e5cffbb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It has been my first reading of the code, so I added some comments. All the nullness stuff for private method is just because I realized it while reading. If we only care about on public methods ignore it.
return new NoOpProfile(); | ||
} | ||
|
||
Channel channel = thing.getChannel(link.getLinkedUID().getId()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, the parameter link
must not be null.
ItemChannelLink link
=> @NonNull ItemChannelLink link
"Cannot delegate command '{}' for item '{}' to handler for channel '{}', " | ||
+ "because no thing with the UID '{}' could be found.", | ||
command, itemName, channelUID, channelUID.getThingUID()); | ||
private Profile getProfile(ItemChannelLink link, Item item, Thing thing) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could mark the return type with @NonNull
for (ProfileFactory profileFactory : profileFactories.keySet()) { | ||
Profile profile = profileFactory.createProfile(link, item, channel); | ||
if (profile != null) { | ||
profileFactories.get(profileFactory).add(link.getLinkedUID()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you need access to the profileFactory, wouldn't it make sense to use entrySet()
instead of keySet()
?
return null; | ||
} | ||
|
||
private Profile createDefaultProfile(Channel channel) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@NonNull Channel
return null; | ||
} | ||
|
||
private void receiveCommand(ItemCommandEvent commandEvent) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@NonNull ItemCommandEvent
}); | ||
} | ||
|
||
private void receiveTrigger(ChannelTriggeredEvent channelTriggeredEvent) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@NonNull ChannelTriggeredEvent
eventPublisher | ||
.post(ItemEventFactory.createStateEvent(item.getName(), acceptedState, channelUID.toString())); | ||
} | ||
final Thing thing = getThing(channelUID.getThingUID()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@NonNull ChannelUID channelUID
for (String item : items) { | ||
eventPublisher.post(ItemEventFactory.createCommandEvent(item, command, channelUID.toString())); | ||
} | ||
final Thing thing = getThing(channelUID.getThingUID()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nonnull ChannelUID channelUID
* This profile allows a channel of the "system:rawbutton" type to be bound to an item. | ||
* | ||
* It reads the triggered events and uses the item's current state to calculate the new state once it detects that the | ||
* button was pressed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, it is a toggle profile. Correct?
|
||
|
||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you add all that empty lines?
Damn, merged while reviewing 😉 |
Sorry, I had put my approval 18 hours ago and the PR is 15 days old - so I was hoping you didn't have any further comments. But never mind - I am sure @SJKA will happily address everything in a follow-up PR :-) |
I am slow 😉 |
Sure, no problem |
...as a follow-up of eclipse-archived#4108 Signed-off-by: Simon Kaufmann <simon.kfm@googlemail.com>
...as a follow-up of eclipse-archived#4108 Signed-off-by: Simon Kaufmann <simon.kfm@googlemail.com>
...as a follow-up of eclipse-archived#4108 Signed-off-by: Simon Kaufmann <simon.kfm@googlemail.com>
...as a follow-up of #4108 Signed-off-by: Simon Kaufmann <simon.kfm@googlemail.com>
This pull request has been mentioned on openHAB Community. There might be relevant details there: |
This PR now reworks the factored CommunicationManager (#4067) and makes its behavior modifiable by "profiles". Such profiles are basically exchangeable parts which the communication manager delegates its actual duties to. I also outlined their purpose in the profiles.md file below to become part of the documentation.
The idea is to make the used profile configurable on ItemChannelLinks. In this first step the profile selection is more or less static though. Although I already anticipated a "ProfileFactory" interface (mainly for testing purposes here), this PR is still missing the configurability by purpose. As this will involve touching many files and the Thing-DSL, I would like to handle this in a separate follow-up PR.
Using profiles also opens up another interesting use-case: I noticed that so far no binding implements the
ThingHandler.handleUpdate(...)
method. Technically spoken some very few do, but they don't do anything there. The main idea of this method apparently was to allow devices to run as "slaves" of other devices, i.e. react on item updates only. A typical use-case for this would be a light switch with an indicator light which should follow the state of the the physical lamp without the risk of running out-of-sync.Therefore I already added a "slave" profile which does exactly that: it listens to item updates, transforms them to commands (if possible) and forwards them to the
ThingHandler.handleCommand(...)
directly. At the same time it cuts off all other communication coming out of the thing handle. With this it would be easily possible to run any device now as a slave without the need to fix/implement this in all of the existing bindings.At the same time I deprecated the
ThingHandler.handleUpdate(...)
method to prevent any new binding to implement it. I think it is fair to allow for a grace period before we drop this method from the interface.The profiles here (especially the TriggerProfiles) are required for the second part of #1043 a.k.a. #2226. I only created a RawButtonTriggerProfile here as an example and proof-of-concept. But there are more required, of course. Especially for the system channels they make much sense! Nevertheless, I would like to keep the work of implementing these out this PR as well.