Skip to content

Commit

Permalink
[mqtt] Dynamically change accepted item-type for Number channels
Browse files Browse the repository at this point in the history
Signed-off-by: Jan N. Klug <github@klug.nrw>
  • Loading branch information
J-N-K committed Jul 14, 2023
1 parent 72c0e1f commit caa0168
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import javax.measure.Unit;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.mqtt.generic.AbstractMQTTThingHandler;
Expand All @@ -28,6 +31,7 @@
import org.openhab.binding.mqtt.generic.ChannelStateUpdateListener;
import org.openhab.binding.mqtt.generic.MqttChannelStateDescriptionProvider;
import org.openhab.binding.mqtt.generic.TransformationServiceProvider;
import org.openhab.binding.mqtt.generic.internal.MqttBindingConstants;
import org.openhab.binding.mqtt.generic.utils.FutureCollector;
import org.openhab.binding.mqtt.generic.values.Value;
import org.openhab.binding.mqtt.generic.values.ValueFactory;
Expand All @@ -37,8 +41,12 @@
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.binding.ThingHandlerCallback;
import org.openhab.core.thing.binding.builder.ChannelBuilder;
import org.openhab.core.thing.binding.builder.ThingBuilder;
import org.openhab.core.thing.type.ChannelTypeUID;
import org.openhab.core.types.StateDescription;
import org.openhab.core.types.util.UnitUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -136,6 +144,15 @@ protected ChannelState createChannelState(ChannelConfig channelConfig, ChannelUI
public void initialize() {
initializeAvailabilityTopicsFromConfig();

ThingHandlerCallback callback = getCallback();
if (callback == null) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "Framework failure: callback must not be null");
return;
}

ThingBuilder thingBuilder = editThing();
boolean modified = false;

List<ChannelUID> configErrors = new ArrayList<>();
for (Channel channel : thing.getChannels()) {
final ChannelTypeUID channelTypeUID = channel.getChannelTypeUID();
Expand All @@ -144,6 +161,29 @@ public void initialize() {
continue;
}
final ChannelConfig channelConfig = channel.getConfiguration().as(ChannelConfig.class);

if (channelTypeUID
.equals(new ChannelTypeUID(MqttBindingConstants.BINDING_ID, MqttBindingConstants.NUMBER))) {
Unit<?> unit = UnitUtils.parseUnit(channelConfig.unit);
String dimension = unit == null ? null : UnitUtils.getDimensionName(unit);
String expectedItemType = dimension == null ? "Number" : "Number:" + dimension; // unknown dimension ->
// Number
String actualItemType = channel.getAcceptedItemType();
if (!expectedItemType.equals(actualItemType)) {
ChannelBuilder channelBuilder = callback.createChannelBuilder(channel.getUID(), channelTypeUID)
.withAcceptedItemType(expectedItemType).withConfiguration(channel.getConfiguration());
if (channel.getLabel() != null) {
channelBuilder.withLabel(Objects.requireNonNull(channel.getLabel()));
}
if (channel.getDescription() != null) {
channelBuilder.withDescription(Objects.requireNonNull(channel.getDescription()));
}
thingBuilder.withoutChannel(channel.getUID());
thingBuilder.withChannel(channelBuilder.build());
modified = true;
}
}

try {
Value value = ValueFactory.createValueState(channelConfig, channelTypeUID.getId());
ChannelState channelState = createChannelState(channelConfig, channel.getUID(), value);
Expand All @@ -159,6 +199,10 @@ public void initialize() {
}
}

if (modified) {
updateThing(thingBuilder.build());
}

// If some channels could not start up, put the entire thing offline and display the channels
// in question to the user.
if (!configErrors.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,16 @@ public static Channel cb(String id, String acceptedType, Configuration config, C
}

static {
THING_CHANNEL_LIST.add(cb("mytext", "TextItemType", textConfiguration(), TEXT_CHANNEL));
THING_CHANNEL_LIST.add(cb("onoff", "OnOffType", onoffConfiguration(), ON_OFF_CHANNEL));
THING_CHANNEL_LIST.add(cb("num", "NumberType", numberConfiguration(), NUMBER_CHANNEL));
THING_CHANNEL_LIST.add(cb("percent", "NumberType", percentageConfiguration(), PERCENTAGE_CHANNEL));

THING_CHANNEL_LIST.add(cb("mytext", "String", textConfiguration(), TEXT_CHANNEL));
THING_CHANNEL_LIST.add(cb("onoff", "Switch", onoffConfiguration(), ON_OFF_CHANNEL));
THING_CHANNEL_LIST.add(cb("num", "Number", numberConfiguration(), NUMBER_CHANNEL));
THING_CHANNEL_LIST.add(cb("percent", "Number:Dimensionless", percentageConfiguration(), PERCENTAGE_CHANNEL));

THING_CHANNEL_LIST_WITH_JSON.add(cb("mytext", "String", textConfigurationWithJson(), TEXT_WITH_JSON_CHANNEL));
THING_CHANNEL_LIST_WITH_JSON.add(cb("onoff", "Switch", onoffConfiguration(), ON_OFF_CHANNEL));
THING_CHANNEL_LIST_WITH_JSON.add(cb("num", "Number", numberConfiguration(), NUMBER_CHANNEL));
THING_CHANNEL_LIST_WITH_JSON
.add(cb("mytext", "TextItemType", textConfigurationWithJson(), TEXT_WITH_JSON_CHANNEL));
THING_CHANNEL_LIST_WITH_JSON.add(cb("onoff", "OnOffType", onoffConfiguration(), ON_OFF_CHANNEL));
THING_CHANNEL_LIST_WITH_JSON.add(cb("num", "NumberType", numberConfiguration(), NUMBER_CHANNEL));
THING_CHANNEL_LIST_WITH_JSON.add(cb("percent", "NumberType", percentageConfiguration(), PERCENTAGE_CHANNEL));
.add(cb("percent", "Number:Dimensionless", percentageConfiguration(), PERCENTAGE_CHANNEL));
}

static Configuration textConfiguration() {
Expand Down

0 comments on commit caa0168

Please sign in to comment.