-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
[avmfritz] Added ThingActions to handle Boost and Window-Open modes for heating devices / groups #8222
Conversation
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
*/ | ||
package org.openhab.binding.avmfritz.internal.actions; |
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 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...
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.
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
.
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.
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.
Good point. I moved them.
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 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.
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 moved it back to an internal package.
...b.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/HeatingModel.java
Show resolved
Hide resolved
.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())); |
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.
.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())); |
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.
Thanks for the hint. I changed it. But we do not need orElseGet(...)
combined with flatMap(...)
.
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"); | ||
} |
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.
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.
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.
Isn't that the pattern that was just done on ALL our thing actions in this repo?
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.
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.
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.
Done.
bundles/org.openhab.binding.avmfritz/src/main/resources/ESH-INF/i18n/avmfritz.properties
Show resolved
Hide resolved
bundles/org.openhab.binding.avmfritz/src/main/resources/ESH-INF/i18n/avmfritz.properties
Show resolved
Hide resolved
if (actions.getClass().getName().equals(AVMFritzHeatingActions.class.getName())) { | ||
if (actions instanceof AVMFritzHeatingActions) { | ||
return (AVMFritzHeatingActions) actions; | ||
if (actions.getClass().getName().equals(AVMFritzHeatingActionsHandler.class.getName())) { |
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 (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) { |
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.
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.
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.
Thanks for your details explanation. I think I now got the point.
Signed-off-by: Christoph Weitkamp <[email protected]>
Signed-off-by: Christoph Weitkamp <[email protected]>
Signed-off-by: Christoph Weitkamp <[email protected]>
Signed-off-by: Christoph Weitkamp <[email protected]>
2e9ca32
to
6c820a0
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.
LGTM
…or heating devices / groups (openhab#8222) * Added ThingActions to handle Boost and Window-Open modes Signed-off-by: Christoph Weitkamp <[email protected]>
…or heating devices / groups (openhab#8222) * Added ThingActions to handle Boost and Window-Open modes Signed-off-by: Christoph Weitkamp <[email protected]>
…or heating devices / groups (openhab#8222) * Added ThingActions to handle Boost and Window-Open modes Signed-off-by: Christoph Weitkamp <[email protected]>
Closes #8144
Signed-off-by: Christoph Weitkamp [email protected]