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

[avmfritz] Added ThingActions to handle Boost and Window-Open modes for heating devices / groups #8222

Merged
merged 4 commits into from
Sep 2, 2020

Conversation

cweitkamp
Copy link
Contributor

  • Added ThingActions to handle Boost and Window-Open modes for heating devices / groups

Closes #8144

Signed-off-by: Christoph Weitkamp [email protected]

@cweitkamp cweitkamp added the enhancement An enhancement or new feature for an existing add-on label Jul 29, 2020
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.avmfritz.internal.actions;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am actually not certain myself anymore, but shouldn't actions be in exported packages, so that they can be seen by the rule engine? Scanning our repo here, I noticed that we have a few bindings putting actions in exported packages, while others have it in internal packages...

Copy link
Contributor Author

@cweitkamp cweitkamp Aug 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Me neither. But does the rule engine really need to know them? I don't think so because we use a wrapper action to access all available ThingActions by filtering on scope and ThingUID.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is using the wrapper at runtime, but for the DSL and specifically the content completion in the editor, it is imho required:

Bildschirmfoto 2020-08-05 um 22 50 37

The mail action is so far the only one I am using, but that one is in an exported package, so I'd suggest to do the same with the others.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I moved them.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that you moved not only the Actions class, but also the AVMFritzHeatingActionsHandler interface - is this necessary to be exposed? If not, I'd say it should stay internal.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved it back to an internal package.

Comment on lines 153 to 156
.of(SUPPORTED_BUTTON_THING_TYPES_UIDS.stream(), SUPPORTED_HEATING_THING_TYPES.stream(),
SUPPORTED_DEVICE_THING_TYPES_UIDS.stream(), SUPPORTED_GROUP_THING_TYPES_UIDS.stream(),
SUPPORTED_BRIDGE_THING_TYPES_UIDS.stream())
.reduce(Stream::concat).orElseGet(Stream::empty).collect(Collectors.toSet()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.of(SUPPORTED_BUTTON_THING_TYPES_UIDS.stream(), SUPPORTED_HEATING_THING_TYPES.stream(),
SUPPORTED_DEVICE_THING_TYPES_UIDS.stream(), SUPPORTED_GROUP_THING_TYPES_UIDS.stream(),
SUPPORTED_BRIDGE_THING_TYPES_UIDS.stream())
.reduce(Stream::concat).orElseGet(Stream::empty).collect(Collectors.toSet()));
.of(SUPPORTED_BUTTON_THING_TYPES_UIDS, SUPPORTED_HEATING_THING_TYPES,
SUPPORTED_DEVICE_THING_TYPES_UIDS, SUPPORTED_GROUP_THING_TYPES_UIDS,
SUPPORTED_BRIDGE_THING_TYPES_UIDS)
.flatMap(Set::stream).orElseGet(Stream::empty).collect(Collectors.toSet()));

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the hint. I changed it. But we do not need orElseGet(...) combined with flatMap(...).

Comment on lines 81 to 106
private static AVMFritzHeatingActions invokeMethodOf(@Nullable ThingActions actions) {
if (actions == null) {
throw new IllegalArgumentException("Actions cannot be null");
}
if (actions.getClass().getName().equals(AVMFritzHeatingActions.class.getName())) {
if (actions instanceof AVMFritzHeatingActions) {
return (AVMFritzHeatingActions) actions;
} else {
return (AVMFritzHeatingActions) Proxy.newProxyInstance(AVMFritzHeatingActions.class.getClassLoader(),
new Class[] { AVMFritzHeatingActions.class }, (Object proxy, Method method, Object[] args) -> {
Method m = actions.getClass().getDeclaredMethod(method.getName(),
method.getParameterTypes());
return m.invoke(actions, args);
});
}
}
throw new IllegalArgumentException("Actions is not an instance of AVMFritzHeatingActions");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Proxy instances can only be interfaces, not concrete classes. So you need to make an interface that has all of your methods your actions are going to use.

This invokeMethodOf method should likewise return an interface instead.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't that the pattern that was just done on ALL our thing actions in this repo?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't that the pattern that was just done on ALL our thing actions in this repo?

It is, but the pattern wasn't done correctly in this particular instance. All of the other ones (or at least the ones that I approved) require an additional interface class to be created.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@kaikreuzer kaikreuzer requested a review from cpmeister August 30, 2020 13:15
if (actions.getClass().getName().equals(AVMFritzHeatingActions.class.getName())) {
if (actions instanceof AVMFritzHeatingActions) {
return (AVMFritzHeatingActions) actions;
if (actions.getClass().getName().equals(AVMFritzHeatingActionsHandler.class.getName())) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (actions.getClass().getName().equals(AVMFritzHeatingActionsHandler.class.getName())) {
if (actions.getClass().getName().equals(AVMFritzHeatingActions.class.getName())) {

The class name should be compared against the name of the concrete action class since you would never receive an instance of a non-concrete class as a parameter.

invokeMethodOf(actions).setWindowOpenMode(duration);
}

private static AVMFritzHeatingActionsHandler invokeMethodOf(@Nullable ThingActions actions) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although yes AVMFritzHeatingActionsHandler is an interface, I think it is the wrong interface here since it extends ThingHandler. The interface returned by the invokeMethodOf should be an interface implemented by AVMFritzHeatingActions so it would reason that it would be a type of ThingHandlerService not a ThingHandler.
You should create a new interface that has only two methods: setBoostMode(Long) and setWindowOpenMode(Long) and have AVMFritzHeatingActions implement that new interface. Likewise it is that new interface which would be returned from invokeMethodOf. So you would need to change your usages of AVMFritzHeatingActionsHandler here use the new interface instead.

Sorry if this has all been confusing but you are almost there. If you need a concrete reference to follow then you can look at the way the Ecobee binding has done it.

https://github.com/openhab/openhab-addons/blob/2.5.x/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/action/EcobeeActions.java#L89

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your details explanation. I think I now got the point.

@cweitkamp cweitkamp force-pushed the feature-avmfritz-heating-modes branch from 2e9ca32 to 6c820a0 Compare September 1, 2020 18:55
@cweitkamp cweitkamp added rebuild Triggers Jenkins PR build and removed rebuild Triggers Jenkins PR build labels Sep 2, 2020
Copy link
Contributor

@cpmeister cpmeister left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@cpmeister cpmeister merged commit cfd2ae5 into openhab:2.5.x Sep 2, 2020
@cpmeister cpmeister added this to the 2.5.9 milestone Sep 2, 2020
@cweitkamp cweitkamp deleted the feature-avmfritz-heating-modes branch September 3, 2020 05:25
CSchlipp pushed a commit to CSchlipp/openhab-addons that referenced this pull request Sep 12, 2020
…or heating devices / groups (openhab#8222)

* Added ThingActions to handle Boost and Window-Open modes

Signed-off-by: Christoph Weitkamp <[email protected]>
markus7017 pushed a commit to markus7017/openhab-addons that referenced this pull request Sep 19, 2020
…or heating devices / groups (openhab#8222)

* Added ThingActions to handle Boost and Window-Open modes

Signed-off-by: Christoph Weitkamp <[email protected]>
andrewfg pushed a commit to andrewfg/openhab-addons that referenced this pull request Oct 8, 2020
…or heating devices / groups (openhab#8222)

* Added ThingActions to handle Boost and Window-Open modes

Signed-off-by: Christoph Weitkamp <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement An enhancement or new feature for an existing add-on
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[avmfritz] Add window-open and boost mode for radiator thermostats
3 participants