mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[mqtt.homeassistant] handle null component name (#15427)
* [mqtt.homeassistant] handle null component name channels from such components will not have a group. this is now done by zigbee2mqtt for the "default" component of a device, such as the light. HASS encourages this as of release 2023.8 Signed-off-by: Cody Cutrer <cody@cutrer.us>
This commit is contained in:
parent
a535caa13c
commit
7fc351c9c2
@ -224,7 +224,7 @@ public class ComponentChannel {
|
||||
ChannelType type;
|
||||
ChannelTypeUID channelTypeUID;
|
||||
|
||||
channelUID = new ChannelUID(component.getGroupUID(), channelID);
|
||||
channelUID = component.buildChannelUID(channelID);
|
||||
channelTypeUID = new ChannelTypeUID(MqttBindingConstants.BINDING_ID,
|
||||
channelUID.getGroupId() + "_" + channelID);
|
||||
channelState = new HomeAssistantChannelState(
|
||||
|
@ -14,6 +14,7 @@ package org.openhab.binding.mqtt.homeassistant.internal.component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
@ -31,8 +32,10 @@ import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannel;
|
||||
import org.openhab.binding.mqtt.homeassistant.internal.HaID;
|
||||
import org.openhab.binding.mqtt.homeassistant.internal.component.ComponentFactory.ComponentConfiguration;
|
||||
import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration;
|
||||
import org.openhab.binding.mqtt.homeassistant.internal.config.dto.Device;
|
||||
import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
|
||||
import org.openhab.core.thing.ChannelGroupUID;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.type.ChannelDefinition;
|
||||
import org.openhab.core.thing.type.ChannelGroupDefinition;
|
||||
import org.openhab.core.thing.type.ChannelGroupType;
|
||||
@ -54,8 +57,8 @@ public abstract class AbstractComponent<C extends AbstractChannelConfiguration>
|
||||
|
||||
// Component location fields
|
||||
private final ComponentConfiguration componentConfiguration;
|
||||
protected final ChannelGroupTypeUID channelGroupTypeUID;
|
||||
protected final ChannelGroupUID channelGroupUID;
|
||||
protected final @Nullable ChannelGroupTypeUID channelGroupTypeUID;
|
||||
protected final @Nullable ChannelGroupUID channelGroupUID;
|
||||
protected final HaID haID;
|
||||
|
||||
// Channels and configuration
|
||||
@ -83,10 +86,15 @@ public abstract class AbstractComponent<C extends AbstractChannelConfiguration>
|
||||
|
||||
this.haID = componentConfiguration.getHaID();
|
||||
|
||||
String groupId = this.haID.getGroupId(channelConfiguration.getUniqueId());
|
||||
if (channelConfiguration.getName() != null) {
|
||||
String groupId = this.haID.getGroupId(channelConfiguration.getUniqueId());
|
||||
|
||||
this.channelGroupTypeUID = new ChannelGroupTypeUID(MqttBindingConstants.BINDING_ID, groupId);
|
||||
this.channelGroupUID = new ChannelGroupUID(componentConfiguration.getThingUID(), groupId);
|
||||
this.channelGroupTypeUID = new ChannelGroupTypeUID(MqttBindingConstants.BINDING_ID, groupId);
|
||||
this.channelGroupUID = new ChannelGroupUID(componentConfiguration.getThingUID(), groupId);
|
||||
} else {
|
||||
this.channelGroupTypeUID = null;
|
||||
this.channelGroupUID = null;
|
||||
}
|
||||
|
||||
this.configSeen = false;
|
||||
|
||||
@ -142,7 +150,10 @@ public abstract class AbstractComponent<C extends AbstractChannelConfiguration>
|
||||
* @param channelTypeProvider The channel type provider
|
||||
*/
|
||||
public void addChannelTypes(MqttChannelTypeProvider channelTypeProvider) {
|
||||
channelTypeProvider.setChannelGroupType(getGroupTypeUID(), getType());
|
||||
ChannelGroupTypeUID groupTypeUID = channelGroupTypeUID;
|
||||
if (groupTypeUID != null) {
|
||||
channelTypeProvider.setChannelGroupType(groupTypeUID, Objects.requireNonNull(getType()));
|
||||
}
|
||||
channels.values().forEach(v -> v.addChannelTypes(channelTypeProvider));
|
||||
}
|
||||
|
||||
@ -154,20 +165,31 @@ public abstract class AbstractComponent<C extends AbstractChannelConfiguration>
|
||||
*/
|
||||
public void removeChannelTypes(MqttChannelTypeProvider channelTypeProvider) {
|
||||
channels.values().forEach(v -> v.removeChannelTypes(channelTypeProvider));
|
||||
channelTypeProvider.removeChannelGroupType(getGroupTypeUID());
|
||||
ChannelGroupTypeUID groupTypeUID = channelGroupTypeUID;
|
||||
if (groupTypeUID != null) {
|
||||
channelTypeProvider.removeChannelGroupType(groupTypeUID);
|
||||
}
|
||||
}
|
||||
|
||||
public ChannelUID buildChannelUID(String channelID) {
|
||||
final ChannelGroupUID groupUID = channelGroupUID;
|
||||
if (groupUID != null) {
|
||||
return new ChannelUID(groupUID, channelID);
|
||||
}
|
||||
return new ChannelUID(componentConfiguration.getThingUID(), channelID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Each HomeAssistant component corresponds to a Channel Group Type.
|
||||
*/
|
||||
public ChannelGroupTypeUID getGroupTypeUID() {
|
||||
public @Nullable ChannelGroupTypeUID getGroupTypeUID() {
|
||||
return channelGroupTypeUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* The unique id of this component.
|
||||
*/
|
||||
public ChannelGroupUID getGroupUID() {
|
||||
public @Nullable ChannelGroupUID getGroupUID() {
|
||||
return channelGroupUID;
|
||||
}
|
||||
|
||||
@ -175,7 +197,16 @@ public abstract class AbstractComponent<C extends AbstractChannelConfiguration>
|
||||
* Component (Channel Group) name.
|
||||
*/
|
||||
public String getName() {
|
||||
return channelConfiguration.getName();
|
||||
String result = channelConfiguration.getName();
|
||||
|
||||
Device device = channelConfiguration.getDevice();
|
||||
if (result == null && device != null) {
|
||||
result = device.getName();
|
||||
}
|
||||
if (result == null) {
|
||||
result = haID.objectID;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -207,11 +238,19 @@ public abstract class AbstractComponent<C extends AbstractChannelConfiguration>
|
||||
/**
|
||||
* Return the channel group type.
|
||||
*/
|
||||
public ChannelGroupType getType() {
|
||||
public @Nullable ChannelGroupType getType() {
|
||||
ChannelGroupTypeUID groupTypeUID = channelGroupTypeUID;
|
||||
if (groupTypeUID == null) {
|
||||
return null;
|
||||
}
|
||||
final List<ChannelDefinition> channelDefinitions = channels.values().stream().map(ComponentChannel::type)
|
||||
.collect(Collectors.toList());
|
||||
return ChannelGroupTypeBuilder.instance(channelGroupTypeUID, getName())
|
||||
.withChannelDefinitions(channelDefinitions).build();
|
||||
return ChannelGroupTypeBuilder.instance(groupTypeUID, getName()).withChannelDefinitions(channelDefinitions)
|
||||
.build();
|
||||
}
|
||||
|
||||
public List<ChannelDefinition> getChannels() {
|
||||
return channels.values().stream().map(ComponentChannel::type).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -225,8 +264,12 @@ public abstract class AbstractComponent<C extends AbstractChannelConfiguration>
|
||||
/**
|
||||
* Return the channel group definition for this component.
|
||||
*/
|
||||
public ChannelGroupDefinition getGroupDefinition() {
|
||||
return new ChannelGroupDefinition(channelGroupUID.getId(), getGroupTypeUID(), getName(), null);
|
||||
public @Nullable ChannelGroupDefinition getGroupDefinition() {
|
||||
ChannelGroupTypeUID groupTypeUID = channelGroupTypeUID;
|
||||
if (groupTypeUID == null) {
|
||||
return null;
|
||||
}
|
||||
return new ChannelGroupDefinition(channelGroupUID.getId(), groupTypeUID, getName(), null);
|
||||
}
|
||||
|
||||
public HaID getHaID() {
|
||||
|
@ -74,24 +74,23 @@ public class AlarmControlPanel extends AbstractComponent<AlarmControlPanel.Chann
|
||||
final String[] stateEnum = { channelConfiguration.stateDisarmed, channelConfiguration.stateArmedHome,
|
||||
channelConfiguration.stateArmedAway, channelConfiguration.statePending,
|
||||
channelConfiguration.stateTriggered };
|
||||
buildChannel(STATE_CHANNEL_ID, new TextValue(stateEnum), channelConfiguration.getName(),
|
||||
componentConfiguration.getUpdateListener())
|
||||
buildChannel(STATE_CHANNEL_ID, new TextValue(stateEnum), getName(), componentConfiguration.getUpdateListener())
|
||||
.stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate())//
|
||||
.build();
|
||||
|
||||
String commandTopic = channelConfiguration.commandTopic;
|
||||
if (commandTopic != null) {
|
||||
buildChannel(SWITCH_DISARM_CHANNEL_ID, new TextValue(new String[] { channelConfiguration.payloadDisarm }),
|
||||
channelConfiguration.getName(), componentConfiguration.getUpdateListener())
|
||||
getName(), componentConfiguration.getUpdateListener())
|
||||
.commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()).build();
|
||||
|
||||
buildChannel(SWITCH_ARM_HOME_CHANNEL_ID,
|
||||
new TextValue(new String[] { channelConfiguration.payloadArmHome }), channelConfiguration.getName(),
|
||||
new TextValue(new String[] { channelConfiguration.payloadArmHome }), getName(),
|
||||
componentConfiguration.getUpdateListener())
|
||||
.commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()).build();
|
||||
|
||||
buildChannel(SWITCH_ARM_AWAY_CHANNEL_ID,
|
||||
new TextValue(new String[] { channelConfiguration.payloadArmAway }), channelConfiguration.getName(),
|
||||
new TextValue(new String[] { channelConfiguration.payloadArmAway }), getName(),
|
||||
componentConfiguration.getUpdateListener())
|
||||
.commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()).build();
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ public class Camera extends AbstractComponent<Camera.ChannelConfiguration> {
|
||||
|
||||
ImageValue value = new ImageValue();
|
||||
|
||||
buildChannel(CAMERA_CHANNEL_ID, value, channelConfiguration.getName(),
|
||||
componentConfiguration.getUpdateListener()).stateTopic(channelConfiguration.topic).build();
|
||||
buildChannel(CAMERA_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener())
|
||||
.stateTopic(channelConfiguration.topic).build();
|
||||
}
|
||||
}
|
||||
|
@ -286,7 +286,7 @@ public class Climate extends AbstractComponent<Climate.ChannelConfiguration> {
|
||||
@Nullable String commandTopic, @Nullable String stateTemplate, @Nullable String stateTopic,
|
||||
@Nullable Predicate<Command> commandFilter) {
|
||||
if ((commandTopic != null && !commandTopic.isBlank()) || (stateTopic != null && !stateTopic.isBlank())) {
|
||||
return buildChannel(channelId, valueState, channelConfiguration.getName(), channelStateUpdateListener)
|
||||
return buildChannel(channelId, valueState, getName(), channelStateUpdateListener)
|
||||
.stateTopic(stateTopic, stateTemplate, channelConfiguration.getValueTemplate())
|
||||
.commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos(),
|
||||
commandTemplate)
|
||||
|
@ -56,8 +56,7 @@ public class Cover extends AbstractComponent<Cover.ChannelConfiguration> {
|
||||
RollershutterValue value = new RollershutterValue(channelConfiguration.payloadOpen,
|
||||
channelConfiguration.payloadClose, channelConfiguration.payloadStop);
|
||||
|
||||
buildChannel(SWITCH_CHANNEL_ID, value, channelConfiguration.getName(),
|
||||
componentConfiguration.getUpdateListener())
|
||||
buildChannel(SWITCH_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener())
|
||||
.stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate())
|
||||
.commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(),
|
||||
channelConfiguration.getQos())
|
||||
|
@ -281,7 +281,7 @@ public class DefaultSchemaLight extends Light {
|
||||
colorValue.update(newOnState);
|
||||
}
|
||||
|
||||
listener.updateChannelState(new ChannelUID(getGroupUID(), COLOR_CHANNEL_ID),
|
||||
listener.updateChannelState(buildChannelUID(COLOR_CHANNEL_ID),
|
||||
state.equals(OnOffType.ON) ? newOnState : HSBType.BLACK);
|
||||
} else if (brightnessChannel != null) {
|
||||
listener.updateChannelState(new ChannelUID(channel.getThingUID(), BRIGHTNESS_CHANNEL_ID),
|
||||
@ -301,8 +301,7 @@ public class DefaultSchemaLight extends Light {
|
||||
colorValue.update(new HSBType(DecimalType.ZERO, PercentType.ZERO,
|
||||
(PercentType) brightnessValue.getChannelState()));
|
||||
}
|
||||
listener.updateChannelState(new ChannelUID(getGroupUID(), COLOR_CHANNEL_ID),
|
||||
colorValue.getChannelState());
|
||||
listener.updateChannelState(buildChannelUID(COLOR_CHANNEL_ID), colorValue.getChannelState());
|
||||
} else {
|
||||
listener.updateChannelState(channel, state);
|
||||
}
|
||||
@ -330,13 +329,11 @@ public class DefaultSchemaLight extends Light {
|
||||
HSBType xyColor = HSBType.fromXY(x, y);
|
||||
colorValue.update(new HSBType(xyColor.getHue(), xyColor.getSaturation(), brightness));
|
||||
}
|
||||
listener.updateChannelState(new ChannelUID(getGroupUID(), COLOR_CHANNEL_ID),
|
||||
colorValue.getChannelState());
|
||||
listener.updateChannelState(buildChannelUID(COLOR_CHANNEL_ID), colorValue.getChannelState());
|
||||
return;
|
||||
case RGB_CHANNEL_ID:
|
||||
colorValue.update((HSBType) state);
|
||||
listener.updateChannelState(new ChannelUID(getGroupUID(), COLOR_CHANNEL_ID),
|
||||
colorValue.getChannelState());
|
||||
listener.updateChannelState(buildChannelUID(COLOR_CHANNEL_ID), colorValue.getChannelState());
|
||||
break;
|
||||
case RGBW_CHANNEL_ID:
|
||||
case RGBWW_CHANNEL_ID:
|
||||
|
@ -65,8 +65,7 @@ public class DeviceTrigger extends AbstractComponent<DeviceTrigger.ChannelConfig
|
||||
value = new TextValue();
|
||||
}
|
||||
|
||||
buildChannel(channelConfiguration.type, value, channelConfiguration.getName(),
|
||||
componentConfiguration.getUpdateListener())
|
||||
buildChannel(channelConfiguration.type, value, getName(), componentConfiguration.getUpdateListener())
|
||||
.stateTopic(channelConfiguration.topic, channelConfiguration.getValueTemplate()).trigger(true).build();
|
||||
}
|
||||
}
|
||||
|
@ -54,8 +54,7 @@ public class Fan extends AbstractComponent<Fan.ChannelConfiguration> {
|
||||
super(componentConfiguration, ChannelConfiguration.class);
|
||||
|
||||
OnOffValue value = new OnOffValue(channelConfiguration.payloadOn, channelConfiguration.payloadOff);
|
||||
buildChannel(SWITCH_CHANNEL_ID, value, channelConfiguration.getName(),
|
||||
componentConfiguration.getUpdateListener())
|
||||
buildChannel(SWITCH_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener())
|
||||
.stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate())
|
||||
.commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(),
|
||||
channelConfiguration.getQos(), channelConfiguration.commandTemplate)
|
||||
|
@ -286,12 +286,11 @@ public class JSONSchemaLight extends AbstractRawSchemaLight {
|
||||
colorModeValue.getChannelState());
|
||||
|
||||
if (hasColorChannel) {
|
||||
listener.updateChannelState(new ChannelUID(getGroupUID(), COLOR_CHANNEL_ID), colorValue.getChannelState());
|
||||
listener.updateChannelState(buildChannelUID(COLOR_CHANNEL_ID), colorValue.getChannelState());
|
||||
} else if (brightnessChannel != null) {
|
||||
listener.updateChannelState(new ChannelUID(getGroupUID(), BRIGHTNESS_CHANNEL_ID),
|
||||
brightnessValue.getChannelState());
|
||||
listener.updateChannelState(buildChannelUID(BRIGHTNESS_CHANNEL_ID), brightnessValue.getChannelState());
|
||||
} else {
|
||||
listener.updateChannelState(new ChannelUID(getGroupUID(), ON_OFF_CHANNEL_ID), onOffValue.getChannelState());
|
||||
listener.updateChannelState(buildChannelUID(ON_OFF_CHANNEL_ID), onOffValue.getChannelState());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,8 +58,8 @@ public class Lock extends AbstractComponent<Lock.ChannelConfiguration> {
|
||||
}
|
||||
|
||||
buildChannel(SWITCH_CHANNEL_ID,
|
||||
new OnOffValue(channelConfiguration.payloadLock, channelConfiguration.payloadUnlock),
|
||||
channelConfiguration.getName(), componentConfiguration.getUpdateListener())
|
||||
new OnOffValue(channelConfiguration.payloadLock, channelConfiguration.payloadUnlock), getName(),
|
||||
componentConfiguration.getUpdateListener())
|
||||
.stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate())
|
||||
.commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(),
|
||||
channelConfiguration.getQos())
|
||||
|
@ -82,8 +82,7 @@ public class Number extends AbstractComponent<Number.ChannelConfiguration> {
|
||||
NumberValue value = new NumberValue(channelConfiguration.min, channelConfiguration.max,
|
||||
channelConfiguration.step, UnitUtils.parseUnit(channelConfiguration.unitOfMeasurement));
|
||||
|
||||
buildChannel(NUMBER_CHANNEL_ID, value, channelConfiguration.getName(),
|
||||
componentConfiguration.getUpdateListener())
|
||||
buildChannel(NUMBER_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener())
|
||||
.stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate())
|
||||
.commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(),
|
||||
channelConfiguration.getQos(), channelConfiguration.commandTemplate)
|
||||
|
@ -66,8 +66,7 @@ public class Select extends AbstractComponent<Select.ChannelConfiguration> {
|
||||
|
||||
TextValue value = new TextValue(channelConfiguration.options);
|
||||
|
||||
buildChannel(SELECT_CHANNEL_ID, value, channelConfiguration.getName(),
|
||||
componentConfiguration.getUpdateListener())
|
||||
buildChannel(SELECT_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener())
|
||||
.stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate())
|
||||
.commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(),
|
||||
channelConfiguration.getQos(), channelConfiguration.commandTemplate)
|
||||
|
@ -88,8 +88,7 @@ public class Sensor extends AbstractComponent<Sensor.ChannelConfiguration> {
|
||||
|
||||
boolean trigger = TRIGGER_ICONS.matcher(icon).matches();
|
||||
|
||||
buildChannel(SENSOR_CHANNEL_ID, value, channelConfiguration.getName(),
|
||||
getListener(componentConfiguration, value))
|
||||
buildChannel(SENSOR_CHANNEL_ID, value, getName(), getListener(componentConfiguration, value))
|
||||
.stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate())//
|
||||
.trigger(trigger).build();
|
||||
}
|
||||
|
@ -294,7 +294,7 @@ public class Vacuum extends AbstractComponent<Vacuum.ChannelConfiguration> {
|
||||
ChannelStateUpdateListener channelStateUpdateListener, @Nullable String commandTemplate,
|
||||
@Nullable String commandTopic, @Nullable String stateTemplate, @Nullable String stateTopic) {
|
||||
if ((commandTopic != null && !commandTopic.isBlank()) || (stateTopic != null && !stateTopic.isBlank())) {
|
||||
return buildChannel(channelId, valueState, channelConfiguration.getName(), channelStateUpdateListener)
|
||||
return buildChannel(channelId, valueState, getName(), channelStateUpdateListener)
|
||||
.stateTopic(stateTopic, stateTemplate, channelConfiguration.getValueTemplate())
|
||||
.commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos(),
|
||||
commandTemplate)
|
||||
|
@ -33,8 +33,9 @@ import com.google.gson.annotations.SerializedName;
|
||||
@NonNullByDefault
|
||||
public abstract class AbstractChannelConfiguration {
|
||||
public static final char PARENT_TOPIC_PLACEHOLDER = '~';
|
||||
private static final String DEFAULT_THING_NAME = "Home Assistant Device";
|
||||
|
||||
protected String name;
|
||||
protected @Nullable String name;
|
||||
|
||||
protected String icon = "";
|
||||
protected int qos; // defaults to 0 according to HA specification
|
||||
@ -93,6 +94,9 @@ public abstract class AbstractChannelConfiguration {
|
||||
if (result == null) {
|
||||
result = name;
|
||||
}
|
||||
if (result == null) {
|
||||
result = DEFAULT_THING_NAME;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -127,7 +131,7 @@ public abstract class AbstractChannelConfiguration {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
public @Nullable String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@ -44,6 +45,7 @@ import org.openhab.binding.mqtt.homeassistant.internal.config.ChannelConfigurati
|
||||
import org.openhab.binding.mqtt.homeassistant.internal.exception.ConfigurationException;
|
||||
import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ChannelGroupUID;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
@ -53,7 +55,6 @@ import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.binding.builder.ThingBuilder;
|
||||
import org.openhab.core.thing.type.ChannelDefinition;
|
||||
import org.openhab.core.thing.type.ChannelGroupDefinition;
|
||||
import org.openhab.core.thing.type.ChannelGroupType;
|
||||
import org.openhab.core.thing.type.ThingType;
|
||||
import org.openhab.core.thing.util.ThingHelper;
|
||||
import org.slf4j.Logger;
|
||||
@ -93,7 +94,7 @@ public class HomeAssistantThingHandler extends AbstractMQTTThingHandler
|
||||
protected final DiscoverComponents discoverComponents;
|
||||
|
||||
private final Gson gson;
|
||||
protected final Map<String, AbstractComponent<?>> haComponents = new HashMap<>();
|
||||
protected final Map<@Nullable String, AbstractComponent<?>> haComponents = new HashMap<>();
|
||||
|
||||
protected HandlerConfiguration config = new HandlerConfiguration();
|
||||
private Set<HaID> discoveryHomeAssistantIDs = new HashSet<>();
|
||||
@ -137,10 +138,6 @@ public class HomeAssistantThingHandler extends AbstractMQTTThingHandler
|
||||
|
||||
for (Channel channel : thing.getChannels()) {
|
||||
final String groupID = channel.getUID().getGroupId();
|
||||
if (groupID == null) {
|
||||
logger.warn("Channel {} has no groupd ID", channel.getLabel());
|
||||
continue;
|
||||
}
|
||||
// Already restored component?
|
||||
@Nullable
|
||||
AbstractComponent<?> component = haComponents.get(groupID);
|
||||
@ -160,7 +157,12 @@ public class HomeAssistantThingHandler extends AbstractMQTTThingHandler
|
||||
try {
|
||||
component = ComponentFactory.createComponent(thingUID, haID, channelConfigurationJSON, this, this,
|
||||
scheduler, gson, transformationServiceProvider);
|
||||
haComponents.put(component.getGroupUID().getId(), component);
|
||||
final ChannelGroupUID groupUID = component.getGroupUID();
|
||||
String id = null;
|
||||
if (groupUID != null) {
|
||||
id = groupUID.getId();
|
||||
}
|
||||
haComponents.put(id, component);
|
||||
component.addChannelTypes(channelTypeProvider);
|
||||
} catch (ConfigurationException e) {
|
||||
logger.error("Cannot not restore component {}: {}", thing, e.getMessage());
|
||||
@ -228,9 +230,6 @@ public class HomeAssistantThingHandler extends AbstractMQTTThingHandler
|
||||
@Override
|
||||
public @Nullable ChannelState getChannelState(ChannelUID channelUID) {
|
||||
String groupID = channelUID.getGroupId();
|
||||
if (groupID == null) {
|
||||
return null;
|
||||
}
|
||||
AbstractComponent<?> component;
|
||||
synchronized (haComponents) { // sync whenever discoverComponents is started
|
||||
component = haComponents.get(groupID);
|
||||
@ -266,7 +265,12 @@ public class HomeAssistantThingHandler extends AbstractMQTTThingHandler
|
||||
|
||||
synchronized (haComponents) { // sync whenever discoverComponents is started
|
||||
for (AbstractComponent<?> discovered : discoveredComponentsList) {
|
||||
AbstractComponent<?> known = haComponents.get(discovered.getGroupUID().getId());
|
||||
final ChannelGroupUID groupUID = discovered.getGroupUID();
|
||||
String id = null;
|
||||
if (groupUID != null) {
|
||||
id = groupUID.getId();
|
||||
}
|
||||
AbstractComponent<?> known = haComponents.get(id);
|
||||
// Is component already known?
|
||||
if (known != null) {
|
||||
if (discovered.getConfigHash() != known.getConfigHash()) {
|
||||
@ -282,10 +286,10 @@ public class HomeAssistantThingHandler extends AbstractMQTTThingHandler
|
||||
// Add channel and group types to the types registry
|
||||
discovered.addChannelTypes(channelTypeProvider);
|
||||
// Add component to the component map
|
||||
haComponents.put(discovered.getGroupUID().getId(), discovered);
|
||||
haComponents.put(id, discovered);
|
||||
// Start component / Subscribe to channel topics
|
||||
discovered.start(connection, scheduler, 0).exceptionally(e -> {
|
||||
logger.warn("Failed to start component {}", discovered.getGroupUID(), e);
|
||||
logger.warn("Failed to start component {}", discovered.getHaID(), e);
|
||||
return null;
|
||||
});
|
||||
|
||||
@ -296,7 +300,7 @@ public class HomeAssistantThingHandler extends AbstractMQTTThingHandler
|
||||
// We remove all conflicting old channels, they will be re-added below based on the new discovery
|
||||
logger.debug(
|
||||
"Received component {} with slightly different config. Making sure we re-create conflicting channels...",
|
||||
discovered.getGroupUID());
|
||||
discovered.getHaID());
|
||||
removeJustRediscoveredChannels(discoveredChannels);
|
||||
}
|
||||
|
||||
@ -346,9 +350,8 @@ public class HomeAssistantThingHandler extends AbstractMQTTThingHandler
|
||||
List<ChannelDefinition> channelDefs;
|
||||
synchronized (haComponents) { // sync whenever discoverComponents is started
|
||||
groupDefs = haComponents.values().stream().map(AbstractComponent::getGroupDefinition)
|
||||
.collect(Collectors.toList());
|
||||
channelDefs = haComponents.values().stream().map(AbstractComponent::getType)
|
||||
.map(ChannelGroupType::getChannelDefinitions).flatMap(List::stream)
|
||||
.filter(Objects::nonNull).map(Objects::requireNonNull).collect(Collectors.toList());
|
||||
channelDefs = haComponents.values().stream().map(AbstractComponent::getChannels).flatMap(List::stream)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
ThingType thingType = channelTypeProvider.derive(typeID, MqttBindingConstants.HOMEASSISTANT_MQTT_THING)
|
||||
|
@ -22,6 +22,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@ -160,7 +161,8 @@ public class HomeAssistantMQTTImplementationTest extends MqttOSGiTest {
|
||||
ComponentDiscovered cd = (haID, c) -> {
|
||||
haComponents.put(c.getGroupUID().getId(), c);
|
||||
c.addChannelTypes(channelTypeProvider);
|
||||
channelTypeProvider.setChannelGroupType(c.getGroupTypeUID(), c.getType());
|
||||
channelTypeProvider.setChannelGroupType(Objects.requireNonNull(c.getGroupTypeUID()),
|
||||
Objects.requireNonNull(c.getType()));
|
||||
latch.countDown();
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user