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