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

[knx] Mods to enable the KNX ‘ETS’ Binding #3500

Closed
wants to merge 1 commit into from

Conversation

kgoderis
Copy link
Contributor

This PR contains all the changes to the KNX Basic binding that are required by https://github.com/openhab/openhab2-addons/pull/3451.

Signed-Off-By: Karel Goderis [email protected]

Copy link
Member

@wborn wborn left a comment

Choose a reason for hiding this comment

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

Here are a few comments while I casually scrolled through the code. :-)

return Collections.unmodifiableSet(new HashSet<>(Arrays.asList(values)));
}

protected abstract @NonNull Set<@NonNull String> getAllGAKeys();
Copy link
Member

Choose a reason for hiding this comment

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

You should annotate the class with @NonNullByDefault and use @Nullable where needed.

See also the ESH documentation.

/** stores the default Item Type to use for each openHAB type */
private final Map<Class<? extends Type>, Class<? extends GenericItem>> defaulItemTypeMap;

private HashMap<Class<? extends GenericItem>, String> itemTypeStringMap;
Copy link
Member

Choose a reason for hiding this comment

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

Can you change the type from HashMap to Map here?

@@ -116,6 +131,9 @@ public KNXCoreTypeMapper() {

dptTypeMap = new HashMap<String, Class<? extends Type>>();
dptMainTypeMap = new HashMap<Integer, Class<? extends Type>>();
defaultDptMap = new HashMap<Class<? extends Type>, String>();
defaulItemTypeMap = new HashMap<Class<? extends Type>, Class<? extends GenericItem>>();
itemTypeStringMap = new HashMap<Class<? extends GenericItem>, String>();
Copy link
Member

Choose a reason for hiding this comment

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

Can you use the diamond operator here?

*
* @author Karel Goderis - Initial contribution
*/
public enum LoadState {
Copy link
Member

Choose a reason for hiding this comment

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

Is this Enum used? I couldn't find any references to it.

@kgoderis
Copy link
Contributor Author

kgoderis commented Apr 21, 2018 via email

L5(5, "Load Completing");

private int code;
private String name;
Copy link
Member

Choose a reason for hiding this comment

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

@kgoderis I was searching for uses of this Enum to find out how the name property was used. The name property and getName(..) methods of this Enum are confusing because an Enum already has a .name() method. Maybe the property can be renamed to something else so there will be no confusion?

@kgoderis
Copy link
Contributor Author

kgoderis commented May 6, 2018

@SJKA Simon, any thoughts on this PR?

return defaulItemTypeMap.get(toTypeClass(dpt));
}

public String toItemType(String dpt) {
Copy link

Choose a reason for hiding this comment

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

This is neither part of the public API (i.e. interface) nor is it used internally. Therefore this method is dead code and can be deleted.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is used in the advanced binding, and in that context its natural place is in the KNXCoreTypeMapper (it can be potentially be used by other knx binding derivaties), but if it is really an issue I will put it in an inheriting class.

return defaulItemTypeMap.get(typeClass);
}

public Class<? extends GenericItem> toItemTypeClass(String dpt) {
Copy link

Choose a reason for hiding this comment

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

dead code - see below

@@ -534,6 +551,25 @@ public KNXCoreTypeMapper() {
defaultDptMap.put(DateTimeType.class, DPTXlatorTime.DPT_TIMEOFDAY.getID());
defaultDptMap.put(StringType.class, DPTXlatorString.DPT_STRING_8859_1.getID());
defaultDptMap.put(HSBType.class, DPTXlatorRGB.DPT_RGB.getID());

defaulItemTypeMap.put(DateTimeType.class, DateTimeItem.class);
Copy link

Choose a reason for hiding this comment

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

You are effectively duplicating (partially) the information from acceptedItemTypes/acceptedCommandTypes here. Not sure if that's a good idea...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the advanced binding I do implement I use a ChannelBuilder to create Channels based on the information stored in the ETS5 files. ChannelBuilder::create() takes an acceptedItemType as input, which is provided by the defaulItemTypeMap you mention, and for which in turn the Key is provided by KNXCoreTypeMapper::toTypeClass() based on the DPT that is derived from the ETS5 data.

@@ -11,6 +11,8 @@ Import-Package: gnu.io;resolution:=optional,
org.eclipse.smarthome.config.discovery,
org.eclipse.smarthome.core.common,
org.eclipse.smarthome.core.i18n,
org.eclipse.smarthome.core.items,
Copy link

Choose a reason for hiding this comment

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

I think we had this discussion a couple of times already: Bindings must be agnostic of items. Otherwise the whole functional abstraction won't work. So I hope you'll understand this won't pass without a single word of explanation?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

See https://github.com/openhab/openhab2-addons/pull/3500#discussion_r189028969

I do not use Items directly, but I need their class definitions for the TypeMapper.

}

@Nullable
protected abstract ChannelConfiguration parse(@Nullable String fancy);
Copy link

Choose a reason for hiding this comment

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

The ChannelConfiguration class is something internal to the "basic" KNX binding and therefore must not "leak" out of the API.

Most of the methods below have the same "issue": They are specific to the way the basic binding configures channels and therefore cannot reside in a commonly shared abstract class.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My main objective was to re-use as much as possible existing classes without re-inventing the wheel. The only part that is specific for each binding is the parsing of the configuration String. In fact, in the advanced binding I do construct a configuration String based on ETS5 information that is similar (but not the same) as the basic binding's configuration Strings

* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.binding.knx.internal.channel;
Copy link

Choose a reason for hiding this comment

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

If you plan to extend it, then this must not be in an "internal" package. I don't think though this is a good idea at all (see below).

if (ga != null) {
return new GroupAddress(ga.getGA());
} else {
throw new IllegalArgumentException("GroupAddressConfiguration should contain a group address");
Copy link

Choose a reason for hiding this comment

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

Why did you change the signature to be @Nullable and then throw a IAE in case null is passed?

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 should revert this and do the null check before calling this. Underlying to this is that in the advanced binding there can be ChannelConfigurations that do not have a MainGA (toGroupAddress is called in ReadResponseSpecImpl)

@@ -26,10 +27,10 @@
public class ChannelConfiguration {

private final @Nullable String dpt;
private final GroupAddressConfiguration mainGA;
private final @Nullable GroupAddressConfiguration mainGA;
Copy link

Choose a reason for hiding this comment

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

No, that's a pretty fundamental assumption: the first one is the "main" GA - and IF there is a configuration, it MUST contain an address.

Are you maybe changing the meaning of "main GA"? Then please don't do so for the basic binding.

Actually, I don't think it is a good idea to reuse this class. Advanced binding(s) may make their own choices how a channels is configured. That's why this is in an "internal" package - it is internal to the basic binding.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

mmh.. It is related to https://github.com/openhab/openhab2-addons/pull/3500#discussion_r189029968 . Maybe some of the internal classes of the basic binding should be exposed in order to facilitate re-usage elsewhere.

if (expectedTypeClass != null) {
logger.trace("The expected Type class for dpt '{}' is '{}'", dpt,
expectedTypeClass.getSimpleName());
Type convertedType = convertType(command, configuration);
Copy link

Choose a reason for hiding this comment

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

How is this related to the "ETS" binding? Aren't you changing the basic binding's behavior here?

Don't get me wrong, potentially this makes sense. I'm just not quite sure yet about the side-effects this might have. In any case, I'm just trying to understand the reason for this change.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For the basic binding this function returns the Type is was fed without any modification. In the advanced binding I overload it to do something meaningful. See for example TypeRollerShutter.java on how I do use this functionality.

@@ -26,12 +28,13 @@
private final Type type;
private final @Nullable GroupAddress groupAddress;

private final Logger logger = LoggerFactory.getLogger(WriteSpecImpl.class);
Copy link

Choose a reason for hiding this comment

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

what do you need this one for?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Debugging artefact. It should be removed indeed

@kaikreuzer
Copy link
Member

@kgoderis & @SJKA Where are we here? Is it right that we are waiting for some changes to be pushed by @kgoderis?

@lewie
Copy link

lewie commented Dec 3, 2018

@kgoderis, the review of sjka is complete. I personally think that without extensions in the basic binding, we will not get along. Duplication of source code is much more complicated and error-prone.

I would suggest to mark the parts required for extensions. A short Comment with the reason in the places as a dead code appear and in the classes which should not be internal.

That would be the easiest way to get ahead?
@SJKA, would that be a solution for your comments?

@wborn wborn changed the title [KNX] Mods to enable the KNX ‘ETS’ Binding [knx] Mods to enable the KNX ‘ETS’ Binding Dec 19, 2018
lewie added a commit to lewie/openhab2 that referenced this pull request Dec 29, 2018
In order to be able to abstract the 'basic' knx binding better from
extended bindings, it must be clarified which classes should be
internally which should be available as extensions. This is a copy of
kgoderis PR 'knx-api' # 3500. It is the first step, further
delimitations come in another PR.

Signed-off-by: lewie <[email protected]>
@vguna
Copy link

vguna commented Aug 11, 2019

Any news on this? This would be a really nice feature for the KNX integration into OH!

@Hilbrand Hilbrand added the stale As soon as a PR is marked stale, it can be removed 6 months later. label Jan 22, 2020
@Hilbrand
Copy link
Member

Given the discussion here it seems a valuable addition. But due too long time no activity closing this pr. if someone wants to pick this up please open a new pr.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion stale As soon as a PR is marked stale, it can be removed 6 months later.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants