Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mqtt.homeassistant] handle null component name #15427

Merged
merged 4 commits into from
Nov 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ public ComponentChannel build(boolean addToComponent) {
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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

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;
Expand All @@ -31,8 +32,10 @@
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;
Expand All @@ -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
Expand Down Expand Up @@ -83,10 +86,15 @@ public AbstractComponent(ComponentFactory.ComponentConfiguration componentConfig

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;

Expand Down Expand Up @@ -142,7 +150,10 @@ public void setConfigSeen() {
* @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));
}

Expand All @@ -154,28 +165,48 @@ public void addChannelTypes(MqttChannelTypeProvider channelTypeProvider) {
*/
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;
}

/**
* 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;
}

/**
Expand Down Expand Up @@ -207,11 +238,19 @@ public int getConfigHash() {
/**
* 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());
}

/**
Expand All @@ -225,8 +264,12 @@ public void resetState() {
/**
* 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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,24 +74,23 @@ public AlarmControlPanel(ComponentFactory.ComponentConfiguration componentConfig
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();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public Camera(ComponentFactory.ComponentConfiguration componentConfiguration) {

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();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ private ComponentChannel buildOptionalChannel(String channelId, Value valueState
@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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ public Cover(ComponentFactory.ComponentConfiguration componentConfiguration) {
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())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ public void updateChannelState(ChannelUID channel, State state) {
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),
Expand All @@ -301,8 +301,7 @@ public void updateChannelState(ChannelUID channel, State state) {
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);
}
Expand Down Expand Up @@ -330,13 +329,11 @@ public void updateChannelState(ChannelUID channel, State state) {
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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,7 @@ public DeviceTrigger(ComponentFactory.ComponentConfiguration componentConfigurat
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();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ public Fan(ComponentFactory.ComponentConfiguration componentConfiguration) {
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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,12 +225,11 @@ public void updateChannelState(ChannelUID channel, State state) {
}

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());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ public Lock(ComponentFactory.ComponentConfiguration componentConfiguration) {
}

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())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,7 @@ public Number(ComponentFactory.ComponentConfiguration componentConfiguration) {
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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ public Select(ComponentFactory.ComponentConfiguration componentConfiguration) {

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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,7 @@ public Sensor(ComponentFactory.ComponentConfiguration componentConfiguration) {

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();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ private ComponentChannel buildOptionalChannel(String channelId, Value valueState
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)
Expand Down
Loading