Dynamically created channel not showing up in Main UI

I am experimenting with adding a dynamically created channel to one of the thing types in a binding that I am working on.

I have been able to create and add the Channel. I can confirm this by logging iteratively over getThing().getChannels() in the handler. However I cannot get the new channel to show up in Main UI | Thing | Channels.

Any thoughts?

Does it show up after deleting and recreating the Thing?

@laursen since you had experience of doing this successfully in HDPowerView, I wonder if you can give me any tips?

@laursen for background … the binding that I am working on is the Velux one; and in that binding I just added support for a vanePosition channel; and since only some actuators support a vanePosition I want to create that channel dynamically only when supported. … and … and … perhaps we should also consider doing the same thing for the HDPowerView secondaryPosition channel too? :slight_smile:

Unfortunately no. My thing is created via a .things file, so I first commented the thing out, reloaded .things file, waited a while and then reversed the change.

You can also check my Intesis binding which uses dynamic channels as well.

If you already created the channel correctly, I guess I would need to see some code to figure out why it’s not working. For HD PowerView you could have a look at this method where a channel is built:

as well as this line where all the built channels are applied to the thing (within the handler):

updateThing(editThing().withChannels(channelBuilder.build()).build());

That’s actually all there is to it, IIRC. In this example the channels are truly dynamic, i.e. a unique channel is created for each scene, scene group and automation. So this use case is not about hiding irrelevant channels, but being able to add as many channels as needed to the same thing.

Sure, why not. :slight_smile: Just keep performance in mind when implementing this, and consider the position of this secondary channel, so it will appear right after position (most likely you would end up with a mix of statically defined channels and the dynamic one).

Thanks guys for your support.

In the meantime I discovered that the added channel does exist according to the OH Developer Tools API Explorer, but it is not visible in OH Main UI | Thing | Channels. So I think it might actually be a bug in Main UI. However the mystery is why it doesn’t show up for my thing / channel whereas it does show up for yours…

I think the differences between mine and your cases may be…

  1. The dynamic channel is added to a thing rather than a bridge, and/or
  2. The dynamic channel is not assigned to a channel group

EDIT: my code is on this branch of my repo

Last time I tried I found I could not dynamically ADD a channel, so instead I went with dynamically removing the channel instead which works. If your having an issue I would add I had a similar issue and this may be a bug.

Wled binding has example code on removing channels dynamically.

1 Like

True genius! :slight_smile:

I will give that a try too.

            // build the vane channel
            Channel newChannel = ChannelBuilder.create(vaneChannelUID).withAcceptedItemType(CoreItemFactory.DIMMER)
                    .withKind(ChannelKind.STATE)
                    .withDescription(localization.getText("channel-type.velux.vanePosition.description"))
                    .withLabel(localization.getText("channel-type.velux.vanePosition.label")).build();

I think you need to specify the channelType in order for MainUI to display it properly, i.e add:

.withType(VeluxBindingConstants.CHANNEL_TYPE_VANE)

Make sure your binding declares proper channel type and it is marked extensible. I found that missing these two points leads to mixed results back in core and ui.

@pacive @splatch thank-you for the tip about channel type.

@splatch sorry but I don’t understand what you mean by marking it as extensible. Could you kindly explain more? TIA.

You mention dynamically added channel. This means that your thing definition should have a extensible attribute with list of channel types which can be defined by end user.

Extensible is for channels that can add or not a user. Dynamic channels added by the binding developer which are not optional do not need that.

Adding channels dynamically is done by many bindings and it works well in UIs. Just look at an rxample in a binding to understand what is wrong in your code.

Generally speaking yes, practically - it depends. Thing definitions (thing types) are being read from XML files by default. If you add a channel at runtime then thing type and its definition remains same as earlier, what you change is instance of a specific thing. Practically a lot depends on a fact if a caller is looking for channels of a thing or channels of a thing type. UI can do both.

In my perception it is a gray area as there is no way to declare a channel as optional within XML file. All channels you put there are enabled by default and will appear for each thing of given type no matter if handler can cover it or not. I know that in ideal universe we would have a new thing type for each of these cases, but again in practice a updated firmware version can bring new functionality, hence channels.

I would say that this is one big reason why you have channel types defined separately from thing types in the xml-files. That way you can define all possible channel types, and then dynamically add them to the Thing by the thing handler.

:slight_smile:

@Lolodomo @pacive @splatch I interpret the discussion to mean 1) an extensible tag MAY or MAY NOT be necessary, and 2) if it IS is added, it can probably do no harm. Ergo I should add it. Or??

^
Dear All,

Thanks to your help I got it working (see screenshot below).

FWIW I added both the channel type to the channel instantiation and an extensible tag on the thing type declaration.

For me now, the only peculiarity is why the statically added channel is prefixed by a big “P” in Main UI, whereas the dynamically added one has no prefix??

I would use the browser’s developer tools to check what is returned from the rest API for the different channel type definitions, thing type definition and thing, and see if there’s any difference. If there is, you could probably modify the code to add whatever’s missing.

1 Like

I think the issue was to do with localisation. In the first attempt I was relying on OH to get the channel label (and description) from the channel-type definition. But in the second attempt I explicitly added a localised .withLabel() (and .withDescription()) … see below