]> git.basschouten.com Git - openhab-addons.git/commitdiff
[mqtt.homeassistant] JSON Attributes can exist on Climate (#17610)
authorCody Cutrer <cody@cutrer.us>
Tue, 22 Oct 2024 04:24:32 +0000 (23:24 -0500)
committerGitHub <noreply@github.com>
Tue, 22 Oct 2024 04:24:32 +0000 (06:24 +0200)
Signed-off-by: Cody Cutrer <cody@cutrer.us>
bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Climate.java
bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/ClimateTests.java
bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandlerTests.java

index 1f156d103c6a724a7c5447f417d8ee1f848375b2..f384cac0406c4a8e589158109c0e9bcb97ba167c 100644 (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();
     }
 
index 3ea6c61914dd128a266cc81f9c40bab3b689473e..d5e6bb7d490eb67839af121b9994c1d98ce85bea 100644 (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", \
index 26932da0396813ba10cd3c17608b503b132ec804..ef52a2a588cc7d1391ad9522a25cb31937ba1cb5 100644 (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());
     }