What is the proper way of adding channels dynamically to replace the existing ones?

Recently, I was trying to add channels dynamically to my thing. I provided default channel configurations to the XML.

Channel Type Definition XML:

<channel-type id="switch-01">
        <item-type>Switch</item-type>
        <label>Switch 1</label>
</channel-type>

Thing Type Definition XML:

<thing-type id="smart-switch">
    
        <label>Smart Switch</label>
        <description>Smart switch provides advanced functionality than regular switches.</description>
        
        <channels>
            <channel id="switch-01" typeId="switch-01" />
        </channels>        
        
        <config-description-ref uri="gridpal:config:apl-smart-switch" />
   
 </thing-type>

Thing Configuration XML:

<?xml version="1.0" encoding="UTF-8"?>
<config-description:config-descriptions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:config-description="http://eclipse.org/smarthome/schemas/config-description/v1.0.0"
    xsi:schemaLocation="http://eclipse.org/smarthome/schemas/config-description/v1.0.0 http://eclipse.org/smarthome/schemas/config-description-1.0.0.xsd">

    <config-description uri="gridpal:config:apl-smart-switch">
        
        <parameter-group name="switch-item-params">
            <label>Switch Parameters</label>
        </parameter-group>
        
        
        <parameter name="switch01" type="text" groupName="switch-item-params">
            <label>Switch 01</label>
            <default>Switchable</default>
            <options>
                <option value="Switchable">Switchable</option>
                <option value="Dimmable">Dimmable</option>
            </options>
        </parameter>
        
        
    </config-description>
    
    
</config-description:config-descriptions>

The idea is- based on the configuration, the channels item types should vary. For example, if switch-01 is configured to Dimmable during runtime, then channel item type should switch from Switch to Dimmer.

Channels created with different ChannelUID seems to work nicely. However, I want to reuse the existing ChannelUIDs. I tried as I’ve mentioned below. Although in the Paper UI, Dimmer is displayed on the Configuration page, Control page shows Switch UI item. Using REST, I figured out that the item type is actually of Switch. So, it seems the XML is overriding the channel configurations. Kindly let me know the proper way of doing this.

I have tried it the following way-

private void thingStructureChanged()
	{
		logger.debug("\n\n[ THING STRUCTURE CHANGED ]\n\n");

		ThingBuilder thingBuilder = editThing();
		ChannelBuilder channelBuilder;

		String[] switchConfigs = { config.switch01 };

		List<Channel> oldChannels = getThing().getChannels();
		List<Channel> newChannels = new ArrayList<>();

		for (int i = 0; i < oldChannels.size(); i++)
		{
			Channel oldChannel = oldChannels.get(i);

			if (switchConfigs[i].equals("Switchable"))
			{
				channelBuilder = ChannelBuilder.create(oldChannel.getUID(), "Switch");
			}
			else if (switchConfigs[i].equals("Dimmable"))
			{
				channelBuilder = ChannelBuilder.create(oldChannel.getUID(), "Dimmer");
			}

			channelBuilder.withLabel(oldChannel.getLabel()).withDescription(oldChannel.getDescription())
					.withType(oldChannel.getChannelTypeUID()).withConfiguration(oldChannel.getConfiguration())
					.withProperties(oldChannel.getProperties()).withDefaultTags(oldChannel.getDefaultTags())
					.withKind(oldChannel.getKind());

			thingBuilder.withoutChannel(oldChannel.getUID());
			newChannels.add(channelBuilder.build());
		}

		updateThing(thingBuilder.withChannels(newChannels).build());
}

@Override
public void handleConfigurationUpdate(@NonNull Map<@NonNull String, @NonNull Object> configurationParameters)
{
	logger.debug("\n\n[ APL SMART SWITCH HANDLING CONFIG UPDATE ]\n\n");

	Configuration configuration = editConfiguration();

	for (Entry<String, Object> configurationParameter : configurationParameters.entrySet())
	{
		configuration.put(configurationParameter.getKey(), configurationParameter.getValue());
	}

	dispose();

	updateConfiguration(configuration);
	config = configuration.as(SmartSwitchConfiguration.class);

	initialize();
}

@Override
public void initialize()
{
	logger.debug("\n\n[ APL SMART SWITCH INITIALIZE ]\n\n");
	thingStructureChanged();
	updateStatus(ThingStatus.ONLINE);
}

I’m pretty certain that this will never work and OH was not designed to have channels dynamically change their types.

The way it is designed to work is you have Things with a set of static channels. The channels define what sort of Item should be linked to them (e.g. if you have a Color light you would have a channel for the switch that can only be linked to a switch Item, one for the Dimmer that can only be linked to a Dimmer Item, and one for the color that can only be linked to a Color Item). You link your Items to the appropriate channels and use your Items to build the home automation.

There is no way built in to change the Type of a Channel because that would instantly break your Items, particularly if the Channel requires a different type for the Item. And you can’t just go changing the types for your Items without a person being involved because that can potentially break everything else (persistence, rules, sitemaps, habpanel, etc).

So the typical approach I’ve seen is to provide all the Channels statically and link your Items to those Channels and then handle in Rules or sitemap or where ever to change out which Item you are using.

Looking at the last posted piece of code I think he is trying to make the binding accept such changes. Such a change would be correctly posted as a PullRequest on GitHub. Questions concerning the how to do such thinks can be discussed in Here.