]> git.basschouten.com Git - openhab-addons.git/commitdiff
[mqtt.espmilighthub] use availability topic to set thing status (#13800)
authorCody Cutrer <cody@cutrer.us>
Fri, 24 Mar 2023 23:52:37 +0000 (17:52 -0600)
committerGitHub <noreply@github.com>
Fri, 24 Mar 2023 23:52:37 +0000 (00:52 +0100)
also refactor a bit so that the thing will work even if the bridge
gets added and removed, etc.

Signed-off-by: Cody Cutrer <cody@cutrer.us>
bundles/org.openhab.binding.mqtt.espmilighthub/src/main/java/org/openhab/binding/mqtt/espmilighthub/internal/EspMilightHubBindingConstants.java
bundles/org.openhab.binding.mqtt.espmilighthub/src/main/java/org/openhab/binding/mqtt/espmilighthub/internal/handler/EspMilightHubHandler.java

index 3d41ae13acb8b90ef0fd0ef84a97e006f2d802d8..bd5bf8c73e349285fa6f1a9b404b62144dc9fd4c 100644 (file)
@@ -31,6 +31,7 @@ import org.openhab.core.thing.ThingTypeUID;
 public class EspMilightHubBindingConstants {
     public static final String STATES_BASE_TOPIC = "milight/states/";
     public static final String COMMANDS_BASE_TOPIC = "milight/commands/";
+    public static final String STATUS_TOPIC = "milight/status";
     public static final BigDecimal BIG_DECIMAL_100 = new BigDecimal(100);
     // List of all Thing Type UIDs
     public static final ThingTypeUID THING_TYPE_RGB_CCT = new ThingTypeUID(BINDING_ID, "rgb_cct");
@@ -50,4 +51,7 @@ public class EspMilightHubBindingConstants {
     public static final String CHANNEL_DISCO_MODE = "discoMode";
     public static final String CHANNEL_BULB_MODE = "bulbMode";
     public static final String CHANNEL_COMMAND = "command";
+
+    // Status
+    public static final String CONNECTED = "connected";
 }
index bcd20df09ca169f7e2a6e09ba8bc16d3e9cfa48d..73e3139122ddb8e5df68ac100398412f8de117cf 100644 (file)
@@ -19,6 +19,9 @@ import static org.openhab.binding.mqtt.espmilighthub.internal.EspMilightHubBindi
 import java.math.BigDecimal;
 import java.math.MathContext;
 import java.nio.charset.StandardCharsets;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
@@ -26,8 +29,6 @@ import org.openhab.binding.mqtt.espmilighthub.internal.ConfigOptions;
 import org.openhab.binding.mqtt.espmilighthub.internal.Helper;
 import org.openhab.binding.mqtt.handler.AbstractBrokerHandler;
 import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
-import org.openhab.core.io.transport.mqtt.MqttConnectionObserver;
-import org.openhab.core.io.transport.mqtt.MqttConnectionState;
 import org.openhab.core.io.transport.mqtt.MqttMessageSubscriber;
 import org.openhab.core.library.types.DecimalType;
 import org.openhab.core.library.types.HSBType;
@@ -41,7 +42,7 @@ import org.openhab.core.thing.Thing;
 import org.openhab.core.thing.ThingRegistry;
 import org.openhab.core.thing.ThingStatus;
 import org.openhab.core.thing.ThingStatusDetail;
-import org.openhab.core.thing.ThingUID;
+import org.openhab.core.thing.ThingStatusInfo;
 import org.openhab.core.thing.binding.BaseThingHandler;
 import org.openhab.core.thing.binding.ThingHandler;
 import org.openhab.core.types.Command;
@@ -57,7 +58,7 @@ import org.slf4j.LoggerFactory;
  * @author Matthew Skinner - Initial contribution
  */
 @NonNullByDefault
-public class EspMilightHubHandler extends BaseThingHandler implements MqttConnectionObserver, MqttMessageSubscriber {
+public class EspMilightHubHandler extends BaseThingHandler implements MqttMessageSubscriber {
     // these are all constants used in color conversion calcuations.
     // strings are necessary to prevent floating point loss of precision
     private static final BigDecimal BIG_DECIMAL_THOUSAND = new BigDecimal(1000);
@@ -451,29 +452,22 @@ public class EspMilightHubHandler extends BaseThingHandler implements MqttConnec
                 return;
             }
         }
-        Bridge localBridge = getBridge();
-        if (localBridge == null) {
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_PENDING,
-                    "Globe must have a valid bridge selected before it can come online.");
-            return;
-        } else {
-            globeType = thing.getThingTypeUID().getId();// eg rgb_cct
-            String globeLocation = this.getThing().getUID().getId();// eg 0x014
-            remotesGroupID = globeLocation.substring(globeLocation.length() - 1, globeLocation.length());// eg 4
-            String remotesIDCode = globeLocation.substring(0, globeLocation.length() - 1);// eg 0x01
-            fullCommandTopic = COMMANDS_BASE_TOPIC + remotesIDCode + "/" + globeType + "/" + remotesGroupID;
-            fullStatesTopic = STATES_BASE_TOPIC + remotesIDCode + "/" + globeType + "/" + remotesGroupID;
-            // Need to remove the lowercase x from 0x12AB in case it contains all numbers
-            String caseCheck = globeLocation.substring(2, globeLocation.length() - 1);
-            if (!caseCheck.equals(caseCheck.toUpperCase())) {
-                logger.warn(
-                        "The milight globe {}{} is using lowercase for the remote code when the hub needs UPPERCASE",
-                        remotesIDCode, remotesGroupID);
-            }
-            channelPrefix = BINDING_ID + ":" + globeType + ":" + localBridge.getUID().getId() + ":" + remotesIDCode
-                    + remotesGroupID + ":";
-            connectMQTT();
+
+        globeType = thing.getThingTypeUID().getId();// eg rgb_cct
+        String globeLocation = this.getThing().getUID().getId();// eg 0x014
+        remotesGroupID = globeLocation.substring(globeLocation.length() - 1, globeLocation.length());// eg 4
+        String remotesIDCode = globeLocation.substring(0, globeLocation.length() - 1);// eg 0x01
+        fullCommandTopic = COMMANDS_BASE_TOPIC + remotesIDCode + "/" + globeType + "/" + remotesGroupID;
+        fullStatesTopic = STATES_BASE_TOPIC + remotesIDCode + "/" + globeType + "/" + remotesGroupID;
+        // Need to remove the lowercase x from 0x12AB in case it contains all numbers
+        String caseCheck = globeLocation.substring(2, globeLocation.length() - 1);
+        if (!caseCheck.equals(caseCheck.toUpperCase())) {
+            logger.warn("The milight globe {}{} is using lowercase for the remote code when the hub needs UPPERCASE",
+                    remotesIDCode, remotesGroupID);
         }
+        channelPrefix = BINDING_ID + ":" + globeType + ":" + thing.getBridgeUID().getId() + ":" + remotesIDCode
+                + remotesGroupID + ":";
+        bridgeStatusChanged(getBridgeStatus());
     }
 
     private void sendMQTT(String payload) {
@@ -487,57 +481,64 @@ public class EspMilightHubHandler extends BaseThingHandler implements MqttConnec
     public void processMessage(String topic, byte[] payload) {
         String state = new String(payload, StandardCharsets.UTF_8);
         logger.trace("Received the following new Milight state:{}:{}", topic, state);
-        try {
-            processIncomingState(state);
-        } catch (Exception e) {
-            logger.warn("Failed processing Milight state {} for {}", state, topic, e);
-        }
-    }
 
-    @Override
-    public void connectionStateChanged(MqttConnectionState state, @Nullable Throwable error) {
-        logger.debug("MQTT brokers state changed to:{}", state);
-        switch (state) {
-            case CONNECTED:
+        if (topic.equals(STATUS_TOPIC)) {
+            if (state.equals(CONNECTED)) {
                 updateStatus(ThingStatus.ONLINE);
-                break;
-            case CONNECTING:
-            case DISCONNECTED:
+            } else {
                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
-                        "Bridge (broker) is not connected to your MQTT broker.");
+                        "Milight Hub is not connected to your MQTT broker.");
+            }
+        } else {
+            try {
+                processIncomingState(state);
+            } catch (Exception e) {
+                logger.warn("Failed processing Milight state {} for {}", state, topic, e);
+            }
         }
     }
 
-    public void connectMQTT() {
-        Bridge localBridge = this.getBridge();
-        if (localBridge == null) {
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED,
-                    "Bridge is missing or offline, you need to setup a working MQTT broker first.");
+    public ThingStatusInfo getBridgeStatus() {
+        Bridge b = getBridge();
+        if (b != null) {
+            return b.getStatusInfo();
+        } else {
+            return new ThingStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, null);
+        }
+    }
+
+    @Override
+    public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
+        if (bridgeStatusInfo.getStatus() == ThingStatus.OFFLINE) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
+            connection = null;
             return;
         }
-        ThingUID thingUID = localBridge.getUID();
-        Thing thing = thingRegistry.get(thingUID);
-        if (thing == null) {
+        if (bridgeStatusInfo.getStatus() != ThingStatus.ONLINE) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
+            return;
+        }
+
+        Bridge localBridge = this.getBridge();
+        if (localBridge == null) {
             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED,
                     "Bridge is missing or offline, you need to setup a working MQTT broker first.");
             return;
         }
-        ThingHandler handler = thing.getHandler();
+        ThingHandler handler = localBridge.getHandler();
         if (handler instanceof AbstractBrokerHandler) {
             AbstractBrokerHandler abh = (AbstractBrokerHandler) handler;
-            MqttBrokerConnection localConnection = abh.getConnection();
-            if (localConnection != null) {
-                localConnection.setKeepAliveInterval(20);
-                localConnection.setQos(1);
-                localConnection.setUnsubscribeOnStop(true);
-                localConnection.addConnectionObserver(this);
-                localConnection.start();
-                localConnection.subscribe(fullStatesTopic + "/#", this);
-                connection = localConnection;
-                if (localConnection.connectionState().compareTo(MqttConnectionState.CONNECTED) == 0) {
-                    updateStatus(ThingStatus.ONLINE);
-                }
+            final MqttBrokerConnection connection;
+            try {
+                connection = abh.getConnectionAsync().get(500, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException | ExecutionException | TimeoutException ignored) {
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED,
+                        "Bridge handler has no valid broker connection!");
+                return;
             }
+            this.connection = connection;
+            connection.subscribe(fullStatesTopic, this);
+            connection.subscribe(STATUS_TOPIC, this);
         }
         return;
     }
@@ -546,7 +547,8 @@ public class EspMilightHubHandler extends BaseThingHandler implements MqttConnec
     public void dispose() {
         MqttBrokerConnection localConnection = connection;
         if (localConnection != null) {
-            localConnection.unsubscribe(fullStatesTopic + "/#", this);
+            localConnection.unsubscribe(fullStatesTopic, this);
+            localConnection.unsubscribe(STATUS_TOPIC, this);
         }
     }
 }