M pom.xml +4 -12
@@ 1,26 1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
- <modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
- <version>2.5.13-SNAPSHOT</version>
- <relativePath>../openhab-addons/bundles</relativePath>
+ <version>3.0.1</version>
</parent>
- <artifactId>org.openhab.binding.lutron-mqtt</artifactId>
+ <version>3.0.2-SNAPSHOT</version>
+ <artifactId>org.openhab.binding.lutronmqtt</artifactId>
<name>openHAB Add-ons :: Bundles :: Lutron-MQTT Binding</name>
- <repositories>
- <repository>
- <id>openhab</id>
- <name>openhab</name>
- <url>https://dl.bintray.com/openhab/mvn/</url>
- </repository>
- </repositories>
-
</project>
A => src/main/feature/feature.xml +11 -0
@@ 0,0 1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<features name="org.openhab.binding.lutronmqtt-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
+ <repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
+
+ <feature name="openhab-binding-lutronmqtt" description="Lutron-MQTT Binding" version="${project.version}">
+ <feature>openhab-runtime-base</feature>
+ <feature>openhab-transport-mqtt</feature>
+ <bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.lutronmqtt/${project.version}</bundle>
+ </feature>
+
+</features>
M src/main/java/org/openhab/binding/lutronmqtt/LutronMQTTBindingConstants.java +1 -1
@@ 53,7 53,7 @@ public class LutronMQTTBindingConstants
public final static String PROPERTY_OBJECT_ID = "objectId";
public final static String PROPERTY_OBJECT_NAME = "name";
public final static String PROPERTY_INTEGRATION_ID = "integrationId";
- public final static String PROPERTY_LINK_ADDRESS = "linkAddress";
+ // public final static String PROPERTY_LINK_ADDRESS = "linkAddress";
public final static String CONFIG_TOKEN = "token";
M src/main/java/org/openhab/binding/lutronmqtt/discovery/LutronMQTTHubDiscoveryParticipant.java +6 -13
@@ 12,14 12,18 @@ import org.eclipse.smarthome.config.disc
import org.eclipse.smarthome.core.thing.ThingTypeUID;
import org.eclipse.smarthome.core.thing.ThingUID;
import org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants;
+import org.openhab.core.config.discovery.DiscoveryResult;
+import org.openhab.core.config.discovery.DiscoveryResultBuilder;
+import org.openhab.core.config.discovery.mdns.MDNSDiscoveryParticipant;
+import org.openhab.core.thing.ThingTypeUID;
+import org.openhab.core.thing.ThingUID;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component(service = MDNSDiscoveryParticipant.class, immediate = true, configurationPid = "binding.lutronmqtt", name = "org.openhab.binding.lutronmqtt.discovery.hub")
-public class LutronMQTTHubDiscoveryParticipant implements MDNSDiscoveryParticipant, ExtendedDiscoveryService {
+public class LutronMQTTHubDiscoveryParticipant implements MDNSDiscoveryParticipant {
private Logger logger = LoggerFactory.getLogger(LutronMQTTHubDiscoveryParticipant.class);
- private DiscoveryServiceCallback discoveryServiceCallback;
@Override
public Set<ThingTypeUID> getSupportedThingTypeUIDs() {
@@ 109,15 113,4 @@ public class LutronMQTTHubDiscoveryParti
return null;
}
-
- @Override
- public void setDiscoveryServiceCallback(DiscoveryServiceCallback discoveryServiceCallback) {
- logger.warn(discoveryServiceCallback.toString());
- this.discoveryServiceCallback = discoveryServiceCallback;
- // log.debug(discoveryServiceCallback.toString());
- }
-
- public DiscoveryServiceCallback getDiscoveryServiceCallback() {
- return discoveryServiceCallback;
- }
}
A => src/main/java/org/openhab/binding/lutronmqtt/handler/BaseLutronDeviceHandler.java +193 -0
@@ 0,0 1,193 @@
+package org.openhab.binding.lutronmqtt.handler;
+
+import static org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants.*;
+
+import java.util.Map;
+import java.util.Objects;
+
+import org.openhab.binding.lutronmqtt.model.LutronDevice;
+import org.openhab.core.thing.*;
+import org.openhab.core.thing.binding.BaseThingHandler;
+import org.openhab.core.thing.binding.ThingHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class BaseLutronDeviceHandler extends BaseThingHandler implements DeviceStatusListener {
+
+ protected int deviceId; //
+ protected int integrationId;
+ protected LutronDevice device; // last update received for this device.
+ protected int linkAddress;
+
+ protected LutronMQTTHubHandler hubHandler;
+
+ static protected Logger log = LoggerFactory.getLogger(BaseLutronDeviceHandler.class);
+
+ public BaseLutronDeviceHandler(Thing thing) {
+ super(thing);
+ }
+
+ @Override
+ public void initialize() {
+ log.debug("Initializing lutron device handler.");
+ initializeThing((getBridge() == null) ? null : getBridge().getStatus());
+ }
+
+ protected void updateDeviceState(Map<String, Object> lightState) {
+ log.warn("updateDeviceState: " + lightState);
+ getHubHandler().setDesiredState(deviceId, lightState);
+ }
+
+ private void initializeThing(ThingStatus bridgeStatus) {
+ log.debug("initializeThing thing {} bridge status {}", getThing().getUID(), bridgeStatus);
+ final String configDeviceId = getThing().getProperties().get(PROPERTY_OBJECT_ID);
+ log.warn("intializeThing " + getThing().getProperties().get(PROPERTY_INTEGRATION_ID));
+ integrationId = Integer
+ .parseInt(Objects.requireNonNull(getThing().getProperties().get(PROPERTY_INTEGRATION_ID)));
+ linkAddress = Integer.parseInt(Objects.requireNonNull(getThing().getProperties().get(PROPERTY_LINK_ADDRESS)));
+
+ if (configDeviceId != null) {
+ deviceId = Integer.valueOf(configDeviceId);
+
+ if (getHubHandler() != null) {
+ if (bridgeStatus == ThingStatus.ONLINE) {
+ getHubHandler().requestUpdateForDevice(linkAddress);
+ LutronDevice device = getHubHandler().getDeviceByLinkAddress(linkAddress);
+ if (device == null) {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
+ return;
+ }
+ updateStatus(ThingStatus.ONLINE);
+
+ // receiving a response to the request update method above should trigger a state change.
+ // onDeviceStateChanged(getHubHandler().getDeviceByIntegrationId(integrationId));
+ // initializeProperties();
+ } else {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
+ }
+ } else {
+ updateStatus(ThingStatus.OFFLINE);
+ }
+ } else {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR);
+ }
+ }
+
+ protected synchronized LutronMQTTHubHandler getHubHandler() {
+ if (this.hubHandler == null) {
+ Bridge bridge = getBridge();
+ if (bridge == null) {
+ return null;
+ }
+ ThingHandler handler = bridge.getHandler();
+ if (handler instanceof LutronMQTTHubHandler) {
+ this.hubHandler = (LutronMQTTHubHandler) handler;
+ this.hubHandler.registerDeviceStatusListener(this);
+ } else {
+ return null;
+ }
+ }
+ return this.hubHandler;
+ }
+
+ public LutronDevice getDevice() {
+ if (device != null) {
+ return device;
+ }
+
+ LutronMQTTHubHandler handler = getHubHandler();
+ device = handler.getDeviceByLinkAddress(linkAddress);
+ return device;
+ }
+
+ @Override
+ public void onDeviceFound(LutronDevice d) {
+ if (d.getId() == deviceId) {
+ updateStatus(ThingStatus.ONLINE);
+ onDeviceStateChanged(d);
+ }
+ }
+
+ @Override
+ public void onDeviceRemoved(LutronDevice d) {
+ if (d.getId() == deviceId) {
+ updateStatus(ThingStatus.OFFLINE);
+ }
+ }
+
+ @Override
+ public void onDeviceStateChanged(LutronDevice d) {
+ if (d.getLinkAddress() != linkAddress) {
+ return;
+ }
+
+ log.info("Go device status change for " + this.getThing().getLabel());
+
+ if (d.hasUpdatedProperties()) {
+ log.info("Received notice of pending state change.");
+ }
+
+ if (false && device != null
+ && d.getProperty(LUTRON_PROPERTY_LEVEL) == (device.getProperty(LUTRON_PROPERTY_LEVEL))) {
+ log.info("Lutron Device: " + d.getName() + " Received State Changed but no difference");
+ return;
+ }
+
+ device = d;
+ }
+
+ abstract void updateDeviceState(LutronDevice d);
+
+ @Override
+ public void dispose() {
+ log.debug("Handler disposed. Unregistering listener.");
+ if (deviceId != 0) { // technically 0 is a valid device id but it appears to be reserved for the hub
+ LutronMQTTHubHandler hubHandler = getHubHandler();
+ if (hubHandler != null) {
+ hubHandler.unregisterDeviceStatusListener(this);
+ this.hubHandler = null;
+ }
+ deviceId = 0;
+ }
+ }
+
+ protected void scheduleUpdateForDevice(int deviceId) {
+ if (true == true) {
+ return;
+ }
+ log.info("Scheduling an update request for deviceId=" + deviceId);
+ scheduler.submit(new Runnable() {
+ @Override
+ public void run() {
+ LutronMQTTHubHandler handler = getHubHandler();
+ if (handler != null) {
+ onDeviceStateChanged(handler.getDeviceByLinkAddress(linkAddress));
+ }
+ }
+ });
+ }
+
+ @Override
+ public void bridgeStatusChanged(ThingStatusInfo bridgeStatus) {
+ super.bridgeStatusChanged(bridgeStatus);
+ if (bridgeStatus.getStatus() == ThingStatus.ONLINE) {
+ scheduleUpdateForDevice(linkAddress);
+ }
+ }
+
+ @Override
+ public void channelLinked(ChannelUID channelUID) {
+ if (this.getBridge().getStatus() == ThingStatus.ONLINE) {
+ // TODO really only need 1 for each device, no matter the channelse.
+ scheduleUpdateForDevice(linkAddress);
+ } else {
+ log.info("Channel Linked but hub is not online.");
+ }
+ }
+
+ protected Integer getCurrentLevel(LutronDevice light) {
+ int brightness = light.getProperty(LUTRON_PROPERTY_LEVEL);
+
+ return brightness;
+ }
+}
M src/main/java/org/openhab/binding/lutronmqtt/handler/LutronMQTTDimmableLightHandler.java +1 -1
@@ 10,7 10,7 @@ package org.openhab.binding.lutronmqtt.h
import static org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants.CHANNEL_LIGHT_LEVEL;
import static org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants.CHANNEL_LIGHT_STATE;
-import org.eclipse.smarthome.core.thing.Thing;
+import org.openhab.core.thing.Thing;
/**
* The {@link LutronMQTTDimmableLightHandler} is responsible for handling commands, which are
M src/main/java/org/openhab/binding/lutronmqtt/handler/LutronMQTTHubHandler.java +131 -36
@@ 31,7 31,14 @@ import org.eclipse.smarthome.core.types.
import org.eclipse.smarthome.io.transport.mqtt.*;
import org.eclipse.smarthome.io.transport.mqtt.reconnect.PeriodicReconnectStrategy;
import org.openhab.binding.lutronmqtt.internal.LutronMQTTConfiguration;
+import org.openhab.binding.lutronmqtt.internal.LutronMqttBrokerConnectionConfig;
import org.openhab.binding.lutronmqtt.model.LutronDevice;
+import org.openhab.core.config.core.Configuration;
+import org.openhab.core.io.transport.mqtt.*;
+import org.openhab.core.io.transport.mqtt.reconnect.PeriodicReconnectStrategy;
+import org.openhab.core.thing.*;
+import org.openhab.core.thing.binding.BaseBridgeHandler;
+import org.openhab.core.types.Command;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ 52,6 59,8 @@ public class LutronMQTTHubHandler extend
private List<LutronDevice> deviceList = Collections.EMPTY_LIST;
+ private static final int DEFAULT_TIMEOUT = 10000;
+
@Nullable
private LutronMQTTConfiguration config;
private String token;
@@ 66,6 75,57 @@ public class LutronMQTTHubHandler extend
logger.warn("LutronMQTTHubHandler create.");
}
+ /**
+ * Creates a broker connection based on the configuration of {@link #config}.
+ *
+ * @return Returns a valid MqttBrokerConnection
+ * @throws IllegalArgumentException If the configuration is invalid, this exception is thrown.
+ */
+ protected MqttBrokerConnection createBrokerConnection(LutronMqttBrokerConnectionConfig config)
+ throws IllegalArgumentException {
+ String host = config.host;
+ if (StringUtils.isBlank(host) || host == null) {
+ throw new IllegalArgumentException("Host is empty!");
+ }
+
+ logger.info("Connection config: " + config);
+
+ final MqttBrokerConnection connection = new MqttBrokerConnection(host, config.port, config.secure,
+ config.clientID);
+
+ final String username = config.username;
+ final String password = config.password;
+ if (StringUtils.isNotBlank(username) && password != null) {
+ connection.setCredentials(username, password); // Empty passwords are allowed
+ }
+
+ final String topic = config.lwtTopic;
+ if (topic != null) {
+ final String msg = config.lwtMessage;
+ MqttWillAndTestament will = new MqttWillAndTestament(topic, msg != null ? msg.getBytes() : null,
+ config.lwtQos, config.lwtRetain);
+ connection.setLastWill(will);
+ }
+
+ connection.setQos(config.qos);
+ if (config.reconnectTime != null) {
+ connection.setReconnectStrategy(new PeriodicReconnectStrategy(config.reconnectTime, 10000));
+ }
+ final Integer keepAlive = config.keepAlive;
+ if (keepAlive != null) {
+ connection.setKeepAliveInterval(keepAlive);
+ }
+ final Integer timeoutInMs = config.timeoutInMs;
+ if (timeoutInMs != null) {
+ connection.setTimeoutExecutor(scheduler, timeoutInMs);
+ } else {
+ connection.setTimeoutExecutor(scheduler, DEFAULT_TIMEOUT);
+ }
+
+ connection.addConnectionObserver(this);
+ return connection;
+ }
+
@Override
public void initialize() {
updateStatus(ThingStatus.UNKNOWN);
@@ 74,6 134,16 @@ public class LutronMQTTHubHandler extend
token = (String) config.get(CONFIG_TOKEN);
final String broker = properties.get(PROPERTY_URL);
+ URI uri = null;
+
+ try {
+ uri = new URI(broker);
+ } catch (URISyntaxException e) {
+ e.printStackTrace();
+ logger.error("Bad broker URL: " + broker, e);
+ updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.CONFIGURATION_ERROR);
+ return;
+ }
String clientId = "openhab-lutron-mqtt-" + (System.currentTimeMillis() / 1000);
@@ 114,7 184,16 @@ public class LutronMQTTHubHandler extend
@Override
public void dispose() {
- logger.info("Disposing of handler " + this);
+ try {
+ if (connection != null) {
+ connection.stop().get(1000, TimeUnit.MILLISECONDS);
+ } else {
+ logger.warn("Trying to dispose handler {} but connection is already null. Most likely this is a bug.",
+ thing.getUID());
+ }
+ } catch (InterruptedException | ExecutionException | TimeoutException ignore) {
+ }
+ cancelJobs();
super.dispose();
mqttClient.stop();
@@ 122,6 201,7 @@ public class LutronMQTTHubHandler extend
mqttClient = null;
}
+ // cl.unsubscribe(new String[] { "lutron/status", "lutron/events", "lutron/remote" });
private void cancelJobs() {
if (allItemsJob != null && !allItemsJob.isCancelled())
@@ 130,6 210,17 @@ public class LutronMQTTHubHandler extend
onlineTimeout.cancel(true);
}
+ private void connectionResult(Boolean res, Throwable th) {
+ if (th != null) {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, th.getMessage());
+ logger.error("Unable to connect to MQTT server.", th);
+ } else if (!res) {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
+ logger.error("Unable to connect to MQTT server.");
+ }
+ ;
+ }
+
private void setupSubscriptions() {
try {
mqttClient.unsubscribeAll().get();
@@ 200,7 291,7 @@ public class LutronMQTTHubHandler extend
}
public Collection<LutronDevice> getDevices() {
- return ImmutableList.copyOf(deviceList);
+ return List.copyOf(deviceList);
}
public void registerDeviceStatusListener(DeviceStatusListener lutronDeviceDiscoveryService) {
@@ 281,9 372,18 @@ public class LutronMQTTHubHandler extend
}
}
- protected void requestUpdateForDevice(int objectId) {
- byte[] b = ("{\"cmd\":\"RuntimePropertyQuery\", \"args\":{\"Params\":[[" + objectId + ",15,[1]]]}}").getBytes();
- mqttClient.publish("lutron/commands", b);
+ protected void requestUpdateForDevice(int linkAddress) {
+ byte[] b = ("{\"cmd\":\"RuntimePropertyQuery\", \"args\":{\"Params\":[[" + linkAddress + ",15,[1]]]}}")
+ .getBytes();
+ connection.publish("lutron/commands", b, 0, false).whenComplete(this::logErrorOnFailure);
+ }
+
+ void logErrorOnFailure(Boolean res, Throwable th) {
+ if (th != null) {
+ logger.error("Operation failed");
+ } else if (!res) {
+ logger.error(th.getMessage(), th);
+ }
}
protected void informDeviceListeners(LutronDevice device) {
@@ 323,54 423,49 @@ public class LutronMQTTHubHandler extend
protected void onlineTimeoutOccurred() {
goOffline(ThingStatusDetail.BRIDGE_OFFLINE, "Too long between status announcements.");
- try {
- mqttClient.stop().get();
- Thread.sleep(5000);
- initialize();
- } catch (Exception e) {
- logger.warn("An error occurred while restarting the service.", e);
- }
}
- public void setDesiredState(Map<String, Object> lightState) {
+ public void setDesiredState(int deviceId, Map<String, Object> lightState) {
byte[] bytes = new byte[0];
try {
bytes = (gson.toJson(lightState)).getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
- logger.warn("Error encoding JSON.", e);
+ logger.error("Unable to encode json", e);
+ return;
}
- // MqttMessage message = new MqttMessage(bytes);
- Boolean res = null;
- try {
- res = mqttClient.publish("lutron/commands", bytes, 0, false).get();
- if (res)
- logger.info("Sent message.");
- else
- logger.warn("Failed to send message: " + new String(bytes));
- } catch (InterruptedException | ExecutionException e) {
- logger.warn("Error sending message.", e);
+ connection.publish("lutron/commands", bytes, 0, false).whenComplete(this::logErrorOnFailure);
+ logger.info("Sent message.");
+ }
+
+ @Override
+ public void processMessage(String s, byte[] bytes) {
+ String message = new String(bytes);
+ logger.debug("messageArrived: " + s + " " + message);
+ switch (s) {
+ case "lutron/status":
+ handleStatusMessage(message);
+ break;
+ case "lutron/remote":
+ handleRemoteEvent(message);
+ break;
+ case "lutron/events":
+ handleGatewayEvent(message);
+ break;
}
}
@Override
public void connectionStateChanged(MqttConnectionState mqttConnectionState, @Nullable Throwable throwable) {
- if (mqttConnectionState == MqttConnectionState.CONNECTED) {
- logger.info("MQTT connection state changed to CONNECTED.");
- goOnline();
- logger.info("Online");
+ if (mqttConnectionState == MqttConnectionState.DISCONNECTED) {
+ goOffline(ThingStatusDetail.BRIDGE_OFFLINE, throwable.getMessage());
+ logger.warn("Lost connection to MQTT server. Should retry", throwable);
+ } else if (mqttConnectionState == MqttConnectionState.CONNECTED) {
scheduler.schedule(new Runnable() {
@Override
public void run() {
setupSubscriptions();
- logger.info("Subscribed.");
}
- }, 1, TimeUnit.SECONDS);
- } else if (mqttConnectionState == MqttConnectionState.CONNECTING) {
- goOffline(ThingStatusDetail.BRIDGE_OFFLINE, "MQTT Reconnecting");
- } else if (mqttConnectionState == MqttConnectionState.DISCONNECTED) {
- goOffline(ThingStatusDetail.BRIDGE_OFFLINE, "MQTT Disconnected");
- logger.warn("Lost connection to MQTT server.");
- cancelJobs();
+ }, 2, TimeUnit.SECONDS);
}
}
}
M src/main/java/org/openhab/binding/lutronmqtt/handler/LutronMQTTRemoteHandler.java +2 -2
@@ 19,13 19,13 @@ import org.openhab.binding.lutronmqtt.mo
*
* @author William Welliver - Initial contribution
*/
-public class LutronMQTTRemoteHandler extends BaseThingHandler implements DeviceStatusListener {
+public class LutronMQTTRemoteHandler extends BaseLutronDeviceHandler {
+ protected Logger log = LoggerFactory.getLogger(getClass());
public LutronMQTTRemoteHandler(Thing thing) {
super(thing);
}
- @Override
public void handleCommand(ChannelUID channelUID, Command command) {
}
M src/main/java/org/openhab/binding/lutronmqtt/handler/LutronMQTTVariableFanHandler.java +1 -1
@@ 10,7 10,7 @@ package org.openhab.binding.lutronmqtt.h
import static org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants.CHANNEL_FAN_SPEED;
import static org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants.CHANNEL_POWER_SWITCH;
-import org.eclipse.smarthome.core.thing.Thing;
+import org.openhab.core.thing.Thing;
/**
* The {@link LutronMQTTVariableFanHandler} is responsible for handling commands, which are
M src/main/java/org/openhab/binding/lutronmqtt/handler/PowerLevelDeviceHandler.java +12 -0
@@ 27,6 27,18 @@ import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
+import java.util.Map;
+
+import org.openhab.binding.lutronmqtt.model.LutronDevice;
+import org.openhab.core.library.types.IncreaseDecreaseType;
+import org.openhab.core.library.types.OnOffType;
+import org.openhab.core.library.types.PercentType;
+import org.openhab.core.thing.ChannelUID;
+import org.openhab.core.thing.Thing;
+import org.openhab.core.types.Command;
+
+import com.google.gson.Gson;
+
/**
* The {@link PowerLevelDeviceHandler} is responsible for handling commands, which are
* sent to one of the channels.
A => src/main/java/org/openhab/binding/lutronmqtt/internal/LutronMqttBrokerConnectionConfig.java +8 -0
@@ 0,0 1,8 @@
+package org.openhab.binding.lutronmqtt.internal;
+
+import org.openhab.core.io.transport.mqtt.MqttBrokerConnectionConfig;
+
+public class LutronMqttBrokerConnectionConfig extends MqttBrokerConnectionConfig {
+ public Integer reconnectTime;
+ public Integer timeoutInMs;
+}
A => src/main/resources/OH-INF/binding/binding.xml +10 -0
@@ 0,0 1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<binding:binding id="lutronmqtt" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:binding="http://eclipse.org/smarthome/schemas/binding/v1.0.0"
+ xsi:schemaLocation="http://eclipse.org/smarthome/schemas/binding/v1.0.0 http://eclipse.org/smarthome/schemas/binding-1.0.0.xsd">
+
+ <name>LutronMQTT Binding</name>
+ <description>This is the binding for LutronMQTT.</description>
+ <author>William Welliver</author>
+
+</binding:binding>
A => src/main/resources/OH-INF/i18n/lutronmqtt_xx_XX.properties +13 -0
@@ 0,0 1,13 @@
+# FIXME: please substitute the xx_XX with a proper locale, ie. de_DE
+# FIXME: please do not add the file to the repo if you add or change no content
+# binding
+binding.lutronmqtt.name = <Your localized Binding name>
+binding.lutronmqtt.description = <Your localized Binding description>
+
+# thing types
+thing-type.lutronmqtt.sample.label = <Your localized Thing label>
+thing-type.lutronmqtt.sample.description = <Your localized Thing description>
+
+# channel types
+channel-type.lutronmqtt.sample-channel.label = <Your localized Channel label>
+channel-type.lutronmqtt.sample-channel.description = <Your localized Channel description>
No newline at end of file
A => src/main/resources/OH-INF/thing/hub.xml +28 -0
@@ 0,0 1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<thing:thing-descriptions bindingId="lutronmqtt"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:thing="http://eclipse.org/smarthome/schemas/thing-description/v1.0.0"
+ xsi:schemaLocation="http://eclipse.org/smarthome/schemas/thing-description/v1.0.0 http://eclipse.org/smarthome/schemas/thing-description-1.0.0.xsd">
+
+ <!-- Wink Hub -->
+ <bridge-type id="hub">
+ <label>Lutron-MQTT Gateway</label>
+ <description>The Lutron-MQTT Gateway represents the network device communicating with the Lutron ClearConnect network.</description>
+
+ <properties>
+ <property name="vendor">Hacienda</property>
+ <property name="uuid"></property>
+ <property name="url"></property>
+ </properties>
+
+ <config-description>
+ <parameter name="token" type="text">
+ <label>Security Token</label>
+ <description>The token authorized by the luton-mqtt infrastructure</description>
+ <required>true</required>
+ </parameter>
+ </config-description>
+
+ </bridge-type>
+
+</thing:thing-descriptions>
A => src/main/resources/OH-INF/thing/thing-types.xml +97 -0
@@ 0,0 1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<thing:thing-descriptions bindingId="lutronmqtt"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:thing="http://eclipse.org/smarthome/schemas/thing-description/v1.0.0"
+ xsi:schemaLocation="http://eclipse.org/smarthome/schemas/thing-description/v1.0.0 http://eclipse.org/smarthome/schemas/thing-description-1.0.0.xsd">
+
+ <thing-type id="dimmableLight">
+ <supported-bridge-type-refs>
+ <bridge-type-ref id="hub"/>
+ </supported-bridge-type-refs>
+
+ <label>Dimmable Light</label>
+ <description>Controls dimmable loads</description>
+
+ <channels>
+ <channel id="lightlevel" typeId="lightDimmer"/>
+ <!-- <channel id="lightstate" typeId="lightSwitch"/> -->
+ </channels>
+
+ <properties>
+ <property name="objectId"></property>
+ <property name="integrationId"></property>
+ <property name="name"></property>
+ </properties>
+ </thing-type>
+
+ <thing-type id="variableFan">
+ <supported-bridge-type-refs>
+ <bridge-type-ref id="hub"/>
+ </supported-bridge-type-refs>
+
+ <label>Variable Speed Fan</label>
+ <description>Controls variable speed fans</description>
+
+ <channels>
+ <channel id="fanSpeed" typeId="fanSpeed"/>
+ <!-- <channel id="powerSwitch" typeId="powerSwitch"/> -->
+ </channels>
+
+ <properties>
+ <property name="objectId"></property>
+ <property name="integrationId"></property>
+ <property name="linkAddress"></property>
+ <property name="name"></property>
+ </properties>
+ </thing-type>
+
+ <channel-type id="lightDimmer">
+ <item-type>Dimmer</item-type>
+ <label>Light Level</label>
+ <description>Increase/decrease the light level</description>
+ <category>DimmableLight</category>
+ <state min="0" max="100" pattern="%d %%"/>
+ </channel-type>
+
+ <channel-type id="lightSwitch">
+ <item-type>Switch</item-type>
+ <label>Light State</label>
+ <description>Turn the light on or off</description>
+ <category>DimmableLight</category>
+ </channel-type>
+
+ <channel-type id="fanSpeed">
+ <item-type>Dimmer</item-type>
+ <label>Fan Speed</label>
+ <description>Increase/decrease the speed</description>
+ <category>VariableFan</category>
+ <state min="0" max="100" pattern="%d %%"/>
+ </channel-type>
+
+ <channel-type id="powerSwitch">
+ <item-type>Switch</item-type>
+ <label>Power State</label>
+ <description>Turn the item on or off</description>
+ <category>VariableFan</category>
+ </channel-type>
+
+
+ <!-- Sample Thing Type -->
+ <thing-type id="sample">
+ <label>LutronMQTT Binding Thing</label>
+ <description>Sample thing for LutronMQTT Binding</description>
+
+ <channels>
+ <channel id="channel1" typeId="sample-channel"/>
+ </channels>
+
+ <config-description>
+ <parameter name="config1" type="text" required="true">
+ <label>Sample parameter</label>
+ <description>This is a sample text configuration parameter.</description>
+ </parameter>
+ </config-description>
+
+ </thing-type>
+
+</thing:thing-descriptions>