[mqtt.homeassistant] Trigger HA devices to update discovery information (#16143)

* [mqtt.homeassistant] Trigger HA devices to update discovery information

Signed-off-by: Cody Cutrer <cody@cutrer.us>
Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
Cody Cutrer 2024-01-22 14:36:53 -07:00 committed by Ciprian Pascu
parent 68e912b19f
commit ff782e4101
5 changed files with 88 additions and 11 deletions

View File

@ -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;
}

View File

@ -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<String, Set<HaID>> componentsPerThingID = new TreeMap<>();
protected final Map<String, ThingUID> thingIDPerTopic = new TreeMap<>();
protected final Map<String, DiscoveryResult> 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<String, Object> 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<String, Object> 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<DiscoveryResult> localResults;

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<config-description:config-descriptions
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:config-description="https://openhab.org/schemas/config-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0
https://openhab.org/schemas/config-description-1.0.0.xsd">
<config-description uri="binding:mqtt.homeassistant">
<parameter name="status" type="boolean" required="false">
<label>Publish Online Status</label>
<default>true</default>
<description><![CDATA[
Publish <tt>online</tt> to <tt>homeassistant/status</tt> when discovering Home Assistant
things in order to trigger devices to publish up-to-date discovery information.
If you also run Home Assistant <i>and</i> 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.
]]></description>
</parameter>
</config-description>
</config-description:config-descriptions>

View File

@ -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 <tt>online</tt> to <tt>homeassistant/status</tt> when discovering Home Assistant things in order to trigger devices to publish up-to-date discovery information. If you also run Home Assistant <i>and</i> 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.

View File

@ -95,6 +95,7 @@ public class HomeAssistantDiscoveryTests extends AbstractHomeAssistantTests {
private static class TestHomeAssistantDiscovery extends HomeAssistantDiscovery {
public TestHomeAssistantDiscovery(MqttChannelTypeProvider typeProvider) {
super(null);
this.typeProvider = typeProvider;
}
}