[mqtt.homeassistant] JSON Attributes can exist on Climate (#17610)

Signed-off-by: Cody Cutrer <cody@cutrer.us>
Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
Cody Cutrer 2024-10-21 23:24:32 -05:00 committed by Ciprian Pascu
parent 5e040e3dc4
commit 0deda9d22b
3 changed files with 27 additions and 12 deletions

View File

@ -33,6 +33,7 @@ import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChanne
import org.openhab.core.library.types.StringType;
import org.openhab.core.library.unit.ImperialUnits;
import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.thing.type.AutoUpdatePolicy;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
@ -63,6 +64,7 @@ public class Climate extends AbstractComponent<Climate.ChannelConfiguration> {
public static final String TEMPERATURE_LOW_CH_ID = "temperature-low";
public static final String TEMPERATURE_LOW_CH_ID_DEPRECATED = "temperatureLow";
public static final String POWER_CH_ID = "power";
public static final String JSON_ATTRIBUTES_CHANNEL_ID = "json-attributes";
public enum TemperatureUnit {
@SerializedName("C")
@ -149,7 +151,7 @@ public class Climate extends AbstractComponent<Climate.ChannelConfiguration> {
// hold modes.
@SerializedName("json_attributes_template")
protected @Nullable String jsonAttributesTemplate; // Attributes are not supported yet
protected @Nullable String jsonAttributesTemplate;
@SerializedName("json_attributes_topic")
protected @Nullable String jsonAttributesTopic;
@ -295,6 +297,13 @@ public class Climate extends AbstractComponent<Climate.ChannelConfiguration> {
buildOptionalChannel(POWER_CH_ID, ComponentChannelType.SWITCH, new OnOffValue(), updateListener, null,
channelConfiguration.powerCommandTopic, null, null, null);
if (channelConfiguration.jsonAttributesTopic != null) {
buildChannel(JSON_ATTRIBUTES_CHANNEL_ID, ComponentChannelType.STRING, new TextValue(), "JSON Attributes",
componentConfiguration.getUpdateListener())
.stateTopic(channelConfiguration.jsonAttributesTopic, channelConfiguration.jsonAttributesTemplate)
.withAutoUpdatePolicy(AutoUpdatePolicy.VETO).build();
}
finalizeChannels();
}

View File

@ -70,7 +70,7 @@ public class ClimateTests extends AbstractComponentTests {
"unique_id": "0x847127fffe11dd6a_climate_zigbee2mqtt"}\
""");
assertThat(component.channels.size(), is(6));
assertThat(component.channels.size(), is(7));
assertThat(component.getName(), is("th1"));
assertChannel(component, Climate.ACTION_CH_ID, "zigbee2mqtt/th1", "", "th1", TextValue.class);
@ -84,6 +84,8 @@ public class ClimateTests extends AbstractComponentTests {
TextValue.class);
assertChannel(component, Climate.TEMPERATURE_CH_ID, "zigbee2mqtt/th1",
"zigbee2mqtt/th1/set/current_heating_setpoint", "th1", NumberValue.class);
assertChannel(component, Climate.JSON_ATTRIBUTES_CHANNEL_ID, "zigbee2mqtt/th1", "", "JSON Attributes",
TextValue.class);
publishMessage("zigbee2mqtt/th1", """
{"running_state": "idle", "away_mode": "ON", \
@ -140,7 +142,7 @@ public class ClimateTests extends AbstractComponentTests {
"unique_id": "0x847127fffe11dd6a_climate_zigbee2mqtt", "send_if_off": "false"}\
""");
assertThat(component.channels.size(), is(7));
assertThat(component.channels.size(), is(8));
assertThat(component.getName(), is("th1"));
assertChannel(component, Climate.ACTION_CH_ID, "zigbee2mqtt/th1", "", "th1", TextValue.class);
@ -154,6 +156,8 @@ public class ClimateTests extends AbstractComponentTests {
TextValue.class);
assertChannel(component, Climate.TEMPERATURE_CH_ID, "zigbee2mqtt/th1",
"zigbee2mqtt/th1/set/current_heating_setpoint", "th1", NumberValue.class);
assertChannel(component, Climate.JSON_ATTRIBUTES_CHANNEL_ID, "zigbee2mqtt/th1", "", "JSON Attributes",
TextValue.class);
publishMessage("zigbee2mqtt/th1", """
{"running_state": "idle", "away_mode": "ON", \
@ -244,7 +248,7 @@ public class ClimateTests extends AbstractComponentTests {
"temp_step": "1", "precision": "0.5", "send_if_off": "false" }\
""");
assertThat(component.channels.size(), is(12));
assertThat(component.channels.size(), is(13));
assertThat(component.getName(), is("MQTT HVAC"));
assertChannel(component, Climate.ACTION_CH_ID, "zigbee2mqtt/th1", "", "MQTT HVAC", TextValue.class);
@ -269,6 +273,8 @@ public class ClimateTests extends AbstractComponentTests {
assertChannel(component, Climate.TEMPERATURE_LOW_CH_ID_DEPRECATED, "zigbee2mqtt/th1",
"zigbee2mqtt/th1/temperature_low", "MQTT HVAC", NumberValue.class);
assertChannel(component, Climate.POWER_CH_ID, "", "zigbee2mqtt/th1/power", "MQTT HVAC", OnOffValue.class);
assertChannel(component, Climate.JSON_ATTRIBUTES_CHANNEL_ID, "zigbee2mqtt/th1", "", "JSON Attributes",
TextValue.class);
publishMessage("zigbee2mqtt/th1", """
{ "action": "fan", "aux": "ON", "away_mode": "OFF", \

View File

@ -119,8 +119,8 @@ public class HomeAssistantThingHandlerTests extends AbstractHomeAssistantTests {
verify(thingHandler, times(1)).componentDiscovered(eq(new HaID(configTopic)), any(Climate.class));
thingHandler.delayedProcessing.forceProcessNow();
assertThat(nonSpyThingHandler.getThing().getChannels().size(), is(6));
verify(stateDescriptionProvider, times(6)).setDescription(any(), any(StateDescription.class));
assertThat(nonSpyThingHandler.getThing().getChannels().size(), is(7));
verify(stateDescriptionProvider, times(7)).setDescription(any(), any(StateDescription.class));
verify(channelTypeProvider, times(1)).putChannelGroupType(any());
configTopic = "homeassistant/switch/0x847127fffe11dd6a_auto_lock_zigbee2mqtt/config";
@ -130,8 +130,8 @@ public class HomeAssistantThingHandlerTests extends AbstractHomeAssistantTests {
verify(thingHandler, times(1)).componentDiscovered(eq(new HaID(configTopic)), any(Switch.class));
thingHandler.delayedProcessing.forceProcessNow();
assertThat(nonSpyThingHandler.getThing().getChannels().size(), is(7));
verify(stateDescriptionProvider, atLeast(7)).setDescription(any(), any(StateDescription.class));
assertThat(nonSpyThingHandler.getThing().getChannels().size(), is(8));
verify(stateDescriptionProvider, atLeast(8)).setDescription(any(), any(StateDescription.class));
verify(channelTypeProvider, times(3)).putChannelGroupType(any());
}
@ -253,7 +253,7 @@ public class HomeAssistantThingHandlerTests extends AbstractHomeAssistantTests {
"homeassistant/switch/0x847127fffe11dd6a_auto_lock_zigbee2mqtt/config",
getResourceAsByteArray("component/configTS0601AutoLock.json"));
thingHandler.delayedProcessing.forceProcessNow();
assertThat(nonSpyThingHandler.getThing().getChannels().size(), is(7));
assertThat(nonSpyThingHandler.getThing().getChannels().size(), is(8));
verify(stateDescriptionProvider, atLeast(7)).setDescription(any(), any(StateDescription.class));
// When dispose
@ -281,13 +281,13 @@ public class HomeAssistantThingHandlerTests extends AbstractHomeAssistantTests {
"homeassistant/switch/0x847127fffe11dd6a_auto_lock_zigbee2mqtt/config",
getResourceAsByteArray("component/configTS0601AutoLock.json"));
thingHandler.delayedProcessing.forceProcessNow();
assertThat(nonSpyThingHandler.getThing().getChannels().size(), is(7));
assertThat(nonSpyThingHandler.getThing().getChannels().size(), is(8));
// When dispose
nonSpyThingHandler.handleRemoval();
// Expect channel descriptions removed, 6 for climate and 1 for switch
verify(stateDescriptionProvider, times(7)).remove(any());
// Expect channel descriptions removed, 7 for climate and 1 for switch
verify(stateDescriptionProvider, times(8)).remove(any());
// Expect channel group types removed, 1 for each component
verify(channelTypeProvider, times(2)).removeChannelGroupType(any());
}