ThingHandler: How to determine channel group type id?

Hi all,

is there a possibility to determine channel group type id within ThingHandler.handleCommand(ChannelUID channelUID, Command command)?

I was able to determine the following IDs but I am missing channel group type id:
String channel_id = channelUID.getIdWithoutGroup();
Channel channel = getThing().getChannel(channelUID);
String channel_type_id = channel.getChannelTypeUID().getId();
String channel_group_id = channelUID.getGroupId();
String channel_group_type_id = ?

Thanks in advance and Happy Easter!

From a quick “Find Usages” it looks like ChannelGroupTypeUID is normally only used when creating/editing things. I guess in a ThingHandler you are expected to only need channel_group_id unless you are dynamically adding channels.

If you really want one you can create it yourself:

new ChannelGroupTypeUID(MyBindingConstants.BINDING_ID, channel_group_id)

It overrides equals(...) so should be equivalent to the “real” channel group type id.

1 Like

@rossgb: Thank you for you quick response!

I have a thing using multiple channel groups (group types). Each channel group type has - beside others - channels with id “command” and “state” - some of them having the same channel type id in addition. Now I want to differentiate command handling in handleCommand based on the channel group type.

I have looked some more into it and found the following solution:

BundleContext context = FrameworkUtil.getBundle(ThingTypeProvider.class).getBundleContext();
ServiceReference<@NonNull ThingTypeProvider> serviceReference = context
        .getServiceReference(ThingTypeProvider.class);
ThingTypeProvider service = context.getService(serviceReference);

ChannelGroupDefinition channelGroupDefinition = service.getThingType(getThing().getThingTypeUID(), null)
        .getChannelGroupDefinitions().stream().filter(d -> d.getId().contentEquals(channelUID.getGroupId()))
        .findFirst().get();
String channel_group_type_id = channelGroupDefinition.getTypeUID().getId();

But I am wondering, if there’s an easier solution to get channel group type id - looking at the easy determination of channel (type) id and channel group id from the first post :wink:

Oops. Looking back at my post I realize at some point in my search I got mixed up between ChannelGroupUID and ChannelGroupTypeUID. Obviously creating a new ChannelGroupTypeUID would not help in your case.

I cannot find an easy way to get it like you can get ChannelTypeUID. As I said before it seems to only be used in creating/editing things (hence you being able to extract it from ThingTypeProvider).

I guess the only other (still not simple) way would be to keep your own map of ChannelGroupID => ChannelGroupTypeID which you could refer to.

Can you inject the ChannelGroupTypeRegistry into your handler factory, then use getChannelGroupType​(@Nullable ChannelGroupTypeUID channelGroupTypeUID) in the handler to get the ChannelGroupType?

Edit: Or, maybe you need to create your own ChannelGroupTypeProvider.

BTW, I built the Javadoc for openHAB core. Until it’s hosted somewhere on openhab.org, I have a version of it here. The search feature is very useful…

https://mhilbush.github.io/apidocs-next/index.html?overview-summary.html

Edit: I also have the 2.5.0 Javadoc, but it doesn’t have the nifty search feature. So far, there aren’t that many differences between 2.5.0 and 3.0 to be a problem.

1 Like

I had nothing else to do so I came up with an example of what I would probably do
N.B. Only for statically defined things and not actually tested.

HandlerFactory:

@NonNullByDefault
@Component(configurationPid = "binding.example", service = ThingHandlerFactory.class)
public final class ExampleHandlerFactory extends BaseThingHandlerFactory {
    // Replace with your ThingTypeUIDs
    private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.emptySet();

    private final Map<ThingTypeUID, Map<String, ChannelGroupTypeUID>> thingTypeChannelGroupTypeMap;

    private static @Nullable ThingType getThingTypeForUid(
            final List<ThingTypeProvider> thingTypeProviders,
            final ThingTypeUID thingTypeUID
    ) {
        @Nullable ThingType thingType = null;

        // Try each ThingTypeProvider to find a ThingType.
        final Iterator<ThingTypeProvider> thingTypeProviderIterator = thingTypeProviders.iterator();
        while (thingType == null && thingTypeProviderIterator.hasNext()) {
            final ThingTypeProvider thingTypeProvider = thingTypeProviderIterator.next();

            thingType = thingTypeProvider.getThingType(thingTypeUID, null);
        }

        return thingType;
    }

    @Activate
    public ExampleHandlerFactory(@Reference final List<ThingTypeProvider> thingTypeProviders) {
        final Map<ThingTypeUID, Map<String, ChannelGroupTypeUID>> thingTypeChannelGroupTypeMap = new HashMap<>();

        for (final ThingTypeUID thingTypeUID : SUPPORTED_THING_TYPES) {
            final @Nullable ThingType thingType = getThingTypeForUid(thingTypeProviders, thingTypeUID);
            
            if (thingType != null) {
                final Map<String, ChannelGroupTypeUID> channelGroupTypeMap = new HashMap<>();
                
                for (final ChannelGroupDefinition channelGroupDefinition : thingType.getChannelGroupDefinitions()) {
                    channelGroupTypeMap.put(channelGroupDefinition.getId(), channelGroupDefinition.getTypeUID());
                }

                thingTypeChannelGroupTypeMap.put(thingTypeUID, Collections.unmodifiableMap(channelGroupTypeMap));
            }
        }

        this.thingTypeChannelGroupTypeMap = Collections.unmodifiableMap(thingTypeChannelGroupTypeMap);
    }

    @Override
    protected @Nullable ThingHandler createHandler(final Thing thing) {
        final ThingTypeUID thingTypeUID = thing.getThingTypeUID();
        final Map<String, ChannelGroupTypeUID> channelGroupTypeMap = this.thingTypeChannelGroupTypeMap.get(thingTypeUID);

        if (BindingConstants.THING_TYPE_XXX.equals(thingTypeUID)) {
            return new XxxHandler(thing, channelGroupTypeMap);
        } else {
            return null;
        }
    }

    @Override
    public boolean supportsThingType(final ThingTypeUID thingTypeUID) {
        return SUPPORTED_THING_TYPES.contains(thingTypeUID);
    }
}

Handler:

@NonNullByDefault
public class XxxHandler extends BaseThingHandler {
    final Map<String, ChannelGroupTypeUID> channelGroupTypeMap;

    public XxxHandler(final Thing thing, final Map<String, ChannelGroupTypeUID> channelGroupTypeMap) {
        super(thing);

        this.channelGroupTypeMap = channelGroupTypeMap;
    }

    @Override
    public void initialize() {
        // Do stuff...
    }

    @Override
    public final void handleCommand(final ChannelUID channelUID, final Command command) {
        // Tada!
        final @Nullable ChannelGroupTypeUID channelGroupTypeUID = this.channelGroupTypeMap.get(channelUID.getGroupId());
    }
}

@mhilbush Injecting the ChannelGroupTypeRegistry within the handler factory did the trick.
Thank you all for you efforts!

Edit: I have to revoke my success message. Because of an error in my code I had a “false positive” at first. Having only Channel and ChannelGroupTypeRegistry I couldn’t match “channel - channel group - channel group type” because ChannelGroupTypeRegistry doesn’t know about channel groups. I finally ended up with injecting ThingProvider in my handler factory which now provides the desired mapping from channel to channel group type by analyzing ThingProvider’s ChannelGroupDefinitions as in my second post.

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.