]> git.basschouten.com Git - openhab-addons.git/commitdiff
[mqtt.homeassistant] ensure availability topics get subscribed (#13466)
authorCody Cutrer <cody@cutrer.us>
Sat, 8 Oct 2022 07:12:28 +0000 (01:12 -0600)
committerGitHub <noreply@github.com>
Sat, 8 Oct 2022 07:12:28 +0000 (09:12 +0200)
HASS registers availability topics before calling start(), so
the AbstractMQTTThingHandler was never subscribing/starting the
availability channel(s). So do so in start() of the base class.

I checked other implementations, and either they already handle
re-registering availabilityTopics in their start()
(GenericMQTTThingHandler), or they don't use availabilityTopics
at all from the base class and manage it themselves (Homie).

Note that this shows up as newly-added HASS things not having
a problem (because the components aren't discovered until after
the ThingHandler is started), but if you restart OpenHAB or
disable/enable the thing, the channels (and components) are
cached, thus how availabilityTopics are known before starting.

Signed-off-by: Cody Cutrer <cody@cutrer.us>
bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/AbstractMQTTThingHandler.java
bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java

index ded70ee8350bdae75fdbcd02aeedde98c5e85c41..9f7cc39be4d9ae59b22f38126e19173cfe8dfd4d 100644 (file)
@@ -25,6 +25,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.mqtt.generic.utils.FutureCollector;
 import org.openhab.binding.mqtt.generic.values.OnOffValue;
 import org.openhab.binding.mqtt.generic.values.Value;
 import org.openhab.binding.mqtt.handler.AbstractBrokerHandler;
@@ -103,7 +104,10 @@ public abstract class AbstractMQTTThingHandler extends BaseThingHandler
      * @param connection A started broker connection
      * @return A future that completes normal on success and exceptionally on any errors.
      */
-    protected abstract CompletableFuture<@Nullable Void> start(MqttBrokerConnection connection);
+    protected CompletableFuture<@Nullable Void> start(MqttBrokerConnection connection) {
+        return availabilityStates.values().parallelStream().map(cChannel -> cChannel.start(connection, scheduler, 0))
+                .collect(FutureCollector.allOf());
+    }
 
     /**
      * Called when the MQTT connection disappeared.
index 9a73aff1f4a7770500b98a370333b268c06a3492..6e147f20a36fb90f267e7f92d133b0eed830a6c5 100644 (file)
@@ -194,13 +194,14 @@ public class HomeAssistantThingHandler extends AbstractMQTTThingHandler
 
         // Start all known components and channels within the components and put the Thing offline
         // if any subscribing failed ( == broker connection lost)
-        CompletableFuture<@Nullable Void> future = haComponents.values().parallelStream()
-                .map(e -> e.start(connection, scheduler, attributeReceiveTimeout))
-                .reduce(CompletableFuture.completedFuture(null), (a, v) -> a.thenCompose(b -> v)) // reduce to one
-                .exceptionally(e -> {
-                    updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
-                    return null;
-                });
+        CompletableFuture<@Nullable Void> future = CompletableFuture.allOf(super.start(connection),
+                haComponents.values().parallelStream().map(e -> e.start(connection, scheduler, attributeReceiveTimeout))
+                        .reduce(CompletableFuture.completedFuture(null), (a, v) -> a.thenCompose(b -> v)) // reduce to
+                                                                                                          // one
+                        .exceptionally(e -> {
+                            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
+                            return null;
+                        }));
 
         return future
                 .thenCompose(b -> discoverComponents.startDiscovery(connection, 0, discoveryHomeAssistantIDs, this));