From ff782e41015cc99273e97d65d47b56ddf82986c0 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Mon, 22 Jan 2024 14:36:53 -0700 Subject: [PATCH] [mqtt.homeassistant] Trigger HA devices to update discovery information (#16143) * [mqtt.homeassistant] Trigger HA devices to update discovery information Signed-off-by: Cody Cutrer Signed-off-by: Ciprian Pascu --- .../internal/HomeAssistantConfiguration.java | 22 ++++++++++ .../discovery/HomeAssistantDiscovery.java | 42 ++++++++++++++++++- .../main/resources/OH-INF/config/config.xml | 22 ++++++++++ .../resources/OH-INF/i18n/mqtt.properties | 12 ++---- .../HomeAssistantDiscoveryTests.java | 1 + 5 files changed, 88 insertions(+), 11 deletions(-) create mode 100644 bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/HomeAssistantConfiguration.java create mode 100644 bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/OH-INF/config/config.xml diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/HomeAssistantConfiguration.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/HomeAssistantConfiguration.java new file mode 100644 index 00000000000..bb68c4053ab --- /dev/null +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/HomeAssistantConfiguration.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2010-2024 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.mqtt.homeassistant.internal; + +/** + * Provides the configured and static settings for the Homekit addon + * + * @author Cody Cutrer - Initial contribution + */ +public class HomeAssistantConfiguration { + public boolean status = true; +} diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscovery.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscovery.java index e1f3649debb..4626a986046 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscovery.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscovery.java @@ -39,9 +39,12 @@ import org.openhab.binding.mqtt.generic.MqttChannelTypeProvider; import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.HaID; import org.openhab.binding.mqtt.homeassistant.internal.HandlerConfiguration; +import org.openhab.binding.mqtt.homeassistant.internal.HomeAssistantConfiguration; import org.openhab.binding.mqtt.homeassistant.internal.config.ChannelConfigurationTypeAdapterFactory; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.binding.mqtt.homeassistant.internal.exception.ConfigurationException; +import org.openhab.core.config.core.ConfigurableService; +import org.openhab.core.config.core.Configuration; import org.openhab.core.config.discovery.DiscoveryResult; import org.openhab.core.config.discovery.DiscoveryResultBuilder; import org.openhab.core.config.discovery.DiscoveryService; @@ -49,7 +52,10 @@ import org.openhab.core.io.transport.mqtt.MqttBrokerConnection; import org.openhab.core.thing.ThingTypeUID; import org.openhab.core.thing.ThingUID; import org.openhab.core.thing.type.ThingType; +import org.osgi.framework.Constants; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Modified; import org.osgi.service.component.annotations.Reference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -63,10 +69,13 @@ import com.google.gson.GsonBuilder; * * @author David Graeff - Initial contribution */ -@Component(service = DiscoveryService.class, configurationPid = "discovery.mqttha") +@Component(service = DiscoveryService.class, configurationPid = "discovery.mqttha", property = Constants.SERVICE_PID + + "=discovery.mqttha") +@ConfigurableService(category = "system", label = "Home Assistant Discovery", description_uri = "binding:mqtt.homeassistant") @NonNullByDefault public class HomeAssistantDiscovery extends AbstractMQTTDiscovery { private final Logger logger = LoggerFactory.getLogger(HomeAssistantDiscovery.class); + private HomeAssistantConfiguration configuration; protected final Map> componentsPerThingID = new TreeMap<>(); protected final Map thingIDPerTopic = new TreeMap<>(); protected final Map results = new ConcurrentHashMap<>(); @@ -89,6 +98,8 @@ public class HomeAssistantDiscovery extends AbstractMQTTDiscovery { } static final String BASE_TOPIC = "homeassistant"; + static final String BIRTH_TOPIC = "homeassistant/status"; + static final String ONLINE_STATUS = "online"; @NonNullByDefault({}) protected MqttChannelTypeProvider typeProvider; @@ -96,9 +107,11 @@ public class HomeAssistantDiscovery extends AbstractMQTTDiscovery { @NonNullByDefault({}) protected MQTTTopicDiscoveryService mqttTopicDiscovery; - public HomeAssistantDiscovery() { + @Activate + public HomeAssistantDiscovery(@Nullable Map properties) { super(null, 3, true, BASE_TOPIC + "/#"); this.gson = new GsonBuilder().registerTypeAdapterFactory(new ChannelConfigurationTypeAdapterFactory()).create(); + configuration = (new Configuration(properties)).as(HomeAssistantConfiguration.class); } @Reference @@ -111,6 +124,11 @@ public class HomeAssistantDiscovery extends AbstractMQTTDiscovery { this.mqttTopicDiscovery = null; } + @Modified + protected void modified(@Nullable Map properties) { + configuration = (new Configuration(properties)).as(HomeAssistantConfiguration.class); + } + @Override protected MQTTTopicDiscoveryService getDiscoveryService() { return mqttTopicDiscovery; @@ -237,6 +255,26 @@ public class HomeAssistantDiscovery extends AbstractMQTTDiscovery { } } + @Override + protected void startScan() { + super.startScan(); + triggerDeviceDiscovery(); + } + + @Override + protected void startBackgroundDiscovery() { + super.startBackgroundDiscovery(); + triggerDeviceDiscovery(); + } + + private void triggerDeviceDiscovery() { + if (!configuration.status) { + return; + } + // https://www.home-assistant.io/integrations/mqtt/#use-the-birth-and-will-messages-to-trigger-discovery + getDiscoveryService().publish(BIRTH_TOPIC, ONLINE_STATUS.getBytes(), 1, false); + } + protected void publishResults() { Collection localResults; diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/OH-INF/config/config.xml b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/OH-INF/config/config.xml new file mode 100644 index 00000000000..55e5bd47284 --- /dev/null +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/OH-INF/config/config.xml @@ -0,0 +1,22 @@ + + + + + + + true + online to homeassistant/status when discovering Home Assistant + things in order to trigger devices to publish up-to-date discovery information. + If you also run Home Assistant and other services that depend on knowing if Home + Assistant is not running, then it's possible for those services to be out-of-sync with + the actual status of Home Assistant, and you may want to disable this. + ]]> + + + + diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/OH-INF/i18n/mqtt.properties b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/OH-INF/i18n/mqtt.properties index f5b418c2e6a..408ba398263 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/OH-INF/i18n/mqtt.properties +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/OH-INF/i18n/mqtt.properties @@ -16,13 +16,7 @@ thing-type.config.mqtt.homeassistant-updatable.topics.description = List of Home thing-type.config.mqtt.homeassistant-updatable.doUpdate.label = Update thing-type.config.mqtt.homeassistant-updatable.doUpdate.description = Request the device do an OTA update -# channel types config +# binding config -channel-type.config.mqtt.ha-channel.component.label = Component -channel-type.config.mqtt.ha-channel.component.description = HomeAssistant component type (e.g. binary_sensor, switch, light) -channel-type.config.mqtt.ha-channel.config.label = Json Configuration -channel-type.config.mqtt.ha-channel.config.description = The json configuration string received by the component via MQTT. -channel-type.config.mqtt.ha-channel.nodeid.label = Node ID -channel-type.config.mqtt.ha-channel.nodeid.description = Optional node name of the component -channel-type.config.mqtt.ha-channel.objectid.label = Object ID -channel-type.config.mqtt.ha-channel.objectid.description = Object id of the component +binding.config.mqtt.homeassistant-status.label = Publish Online Status +binding.config.mqtt.homeassistant-status.description = Publish online to homeassistant/status when discovering Home Assistant things in order to trigger devices to publish up-to-date discovery information. If you also run Home Assistant and other services that depend on knowing if Home Assistant is not running, then it's possible for those services to be out-of-sync with the actual status of Home Assistant, and you may want to disable this. diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscoveryTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscoveryTests.java index d9bfeb6c5e3..15999087f4b 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscoveryTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscoveryTests.java @@ -95,6 +95,7 @@ public class HomeAssistantDiscoveryTests extends AbstractHomeAssistantTests { private static class TestHomeAssistantDiscovery extends HomeAssistantDiscovery { public TestHomeAssistantDiscovery(MqttChannelTypeProvider typeProvider) { + super(null); this.typeProvider = typeProvider; } }