M pom.xml +13 -2
@@ 1,15 1,26 @@
-<?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">
+<?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>
<parent>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
- <version>2.5.3-SNAPSHOT</version>
+ <version>2.5.13-SNAPSHOT</version>
+ <relativePath>../openhab-addons/bundles</relativePath>
</parent>
<artifactId>org.openhab.binding.lutron-mqtt</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>
M src/main/java/org/openhab/binding/lutronmqtt/LutronMQTTBindingConstants.java +52 -11
@@ 12,36 12,39 @@
*/
package org.openhab.binding.lutronmqtt;
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.smarthome.core.thing.ThingTypeUID;
-
import java.util.Collections;
+import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.smarthome.core.thing.ThingTypeUID;
+
/**
* The {@link LutronMQTTBindingConstants} class defines common constants, which are
* used across the whole binding.
*
* @author William Welliver - Initial contribution
*/
- @NonNullByDefault
+@NonNullByDefault
public class LutronMQTTBindingConstants {
private static final String BINDING_ID = "lutronmqtt";
public final static ThingTypeUID THING_TYPE_MQTTHUB = new ThingTypeUID(BINDING_ID, "hub");
+ public final static ThingTypeUID THING_TYPE_LIGHT = new ThingTypeUID(BINDING_ID, "light");
public final static ThingTypeUID THING_TYPE_DIMMABLE_LIGHT = new ThingTypeUID(BINDING_ID, "dimmableLight");
public final static ThingTypeUID THING_TYPE_VARIABLE_FAN = new ThingTypeUID(BINDING_ID, "variableFan");
public final static ThingTypeUID THING_TYPE_REMOTE = new ThingTypeUID(BINDING_ID, "remote");
-
- public final static Set<ThingTypeUID> SUPPORTED_HUBS_UIDS = Collections.unmodifiableSet(
- Stream.of(THING_TYPE_MQTTHUB).collect(Collectors.toSet()));
+ public final static ThingTypeUID THING_TYPE_SHADE = new ThingTypeUID(BINDING_ID, "shade");
- public final static Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet(
- Stream.of(THING_TYPE_DIMMABLE_LIGHT,
- THING_TYPE_VARIABLE_FAN, THING_TYPE_REMOTE).collect(Collectors.toSet()));
+ public final static Set<ThingTypeUID> SUPPORTED_HUBS_UIDS = Collections
+ .unmodifiableSet(Stream.of(THING_TYPE_MQTTHUB).collect(Collectors.toSet()));
+
+ public final static Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections
+ .unmodifiableSet(Stream.of(THING_TYPE_DIMMABLE_LIGHT, THING_TYPE_LIGHT, THING_TYPE_SHADE,
+ THING_TYPE_VARIABLE_FAN, THING_TYPE_REMOTE).collect(Collectors.toSet()));
// List of all Channel ids
public final static String PROPERTY_UUID = "uuid";
@@ 56,7 59,7 @@ public class LutronMQTTBindingConstants
// List of all Channel ids
public final static String CHANNEL_LIGHT_LEVEL = "lightlevel";
- public final static String CHANNEL_LIGHT_STATE = "lightstate";
+ public final static String CHANNEL_LIGHT_STATE = "state";
public final static String CHANNEL_LIGHT_COLORTEMPERATURE = "colorTemperature";
public final static String CHANNEL_LIGHT_COLOR = "color";
@@ 64,5 67,43 @@ public class LutronMQTTBindingConstants
public final static String CHANNEL_FAN_SPEED = "fanSpeed";
public final static String CHANNEL_POWER_SWITCH = "powerSwitch";
+ public final static String CHANNEL_SHADE_LEVEL = "shadeLevel";
+
public final static int LUTRON_PROPERTY_LEVEL = 1;
+
+ static final public Set<Integer> lightDeviceClasses = new HashSet<>();
+ static {
+ lightDeviceClasses.add(68223489); // MRF2-6ANS
+ lightDeviceClasses.add(70451457); // Caseta Wall Switch
+ }
+
+ static final public Set<Integer> dimmableLightDeviceClasses = new HashSet<>();
+ static {
+ dimmableLightDeviceClasses.add(70713601); // GE Bulb
+ dimmableLightDeviceClasses.add(70385921); // Caseta Wall Dimmer
+ dimmableLightDeviceClasses.add(70516993); // Caseta Plug-In Dimmer
+ dimmableLightDeviceClasses.add(70582529); // RRD-6CL
+ }
+
+ static final public Set<Integer> variableFanDeviceClasses = new HashSet<>();
+ static {
+ variableFanDeviceClasses.add(67567873); // RRD-2ANF
+ }
+
+ static final public Set<Integer> shadeDeviceClasses = new HashSet<>();
+ static {
+ shadeDeviceClasses.add(50725121); // Serena Honeycomb
+ shadeDeviceClasses.add(50921729); // Serena Roller
+ shadeDeviceClasses.add(50987265); // Sivoia QS Wireless Triathlon Roller
+ shadeDeviceClasses.add(50594049); // RF QS Roller Shade
+ }
+
+ public final static Set<Integer> remoteDeviceClasses = new HashSet<>();
+ static {
+ remoteDeviceClasses.add(17235974); // 3 Button Pico with Raise/Lower
+ remoteDeviceClasses.add(17235973); // 3 Button Pico
+ remoteDeviceClasses.add(17235972); // 2 Button Pico with Raise/Lower
+ remoteDeviceClasses.add(17235971); // 2 Button Pico
+ remoteDeviceClasses.add(17235970); // 1 Button Pico
+ }
}
M src/main/java/org/openhab/binding/lutronmqtt/discovery/LutronMQTTDeviceDiscoveryService.java +29 -18
@@ 1,5 1,7 @@
package org.openhab.binding.lutronmqtt.discovery;
+import static org.openhab.binding.lutronmqtt.internal.LutronMQTTHandlerFactory.SUPPORTED_THING_TYPES_UIDS;
+
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
@@ 16,11 18,11 @@ import org.openhab.binding.lutronmqtt.Lu
import org.openhab.binding.lutronmqtt.handler.DeviceStatusListener;
import org.openhab.binding.lutronmqtt.handler.LutronMQTTHubHandler;
import org.openhab.binding.lutronmqtt.model.LutronDevice;
+import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import static org.openhab.binding.lutronmqtt.internal.LutronMQTTHandlerFactory.SUPPORTED_THING_TYPES_UIDS;
-
+@Component(service = AbstractDiscoveryService.class, immediate = true, configurationPid = "binding.lutronmqtt", name = "org.openhab.binding.lutronmqtt.discovery.device")
public class LutronMQTTDeviceDiscoveryService extends AbstractDiscoveryService implements DeviceStatusListener {
private final static int SEARCH_TIME = 60;
private final Logger logger = LoggerFactory.getLogger(LutronMQTTDeviceDiscoveryService.class);
@@ 64,6 66,7 @@ public class LutronMQTTDeviceDiscoverySe
Collection<LutronDevice> devices = hubHandler.getDevices();
for (LutronDevice d : devices) {
+ logger.info("DEVICE: " + d);
onDeviceFound(d);
}
}
@@ 79,25 82,25 @@ public class LutronMQTTDeviceDiscoverySe
if (thingUID != null) {
if (hubHandler.getThingByUID(thingUID) != null) {
- logger.debug("ignoring already registered device of name '{}' with id {}", d.getName(), d.getId());
+ logger.debug("ignoring already registered device of name '{}' with objectId {}", d.getName(),
+ d.getObjectId());
}
ThingUID bridgeUID = hubHandler.getThing().getUID();
Map<String, Object> properties = new HashMap<>(1);
- properties.put(LutronMQTTBindingConstants.PROPERTY_OBJECT_ID, "" + d.getId());
- properties.put(LutronMQTTBindingConstants.PROPERTY_INTEGRATION_ID, "" + d.getIntegrationId());
- properties.put(LutronMQTTBindingConstants.PROPERTY_LINK_ADDRESS, "" + d.getLinkAddress());
+ properties.put(LutronMQTTBindingConstants.PROPERTY_OBJECT_ID, "" + d.getObjectId());
+ // properties.put(LutronMQTTBindingConstants.PROPERTY_INTEGRATION_ID, "" + d.getIntegrationId());
+ // properties.put(LutronMQTTBindingConstants.PROPERTY_LINK_ADDRESS, "" + d.getObjectId());
properties.put(LutronMQTTBindingConstants.PROPERTY_OBJECT_NAME, d.getName());
- logger.warn("discovery result " + d.getName() + " " + d.getIntegrationId());
+ logger.warn("discovery result " + d.getName() + " " + d.getObjectId());
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withThingType(thingTypeUID)
.withProperties(properties).withBridge(bridgeUID).withLabel(d.getName()).build();
thingDiscovered(discoveryResult);
} else {
- logger.debug("discovered unsupported device of name '{}' with id {}", d.getName(), d.getId());
+ logger.debug("discovered unsupported device of name '{}' with objectId {}", d.getName(), d.getObjectId());
}
-
}
@Override
@@ 111,7 114,7 @@ public class LutronMQTTDeviceDiscoverySe
ThingTypeUID thingTypeUID = getThingTypeUID(device);
if (thingTypeUID != null && getSupportedThingTypes().contains(thingTypeUID)) {
- return new ThingUID(thingTypeUID, bridgeUID, "" + device.getId());
+ return new ThingUID(thingTypeUID, bridgeUID, "" + device.getObjectId());
} else {
return null;
}
@@ 120,20 123,28 @@ public class LutronMQTTDeviceDiscoverySe
private ThingTypeUID getThingTypeUID(LutronDevice device) {
ThingTypeUID thingTypeId = null;
String name = device.getName();
- if (name.endsWith("Remote")) {
- thingTypeId = LutronMQTTBindingConstants.THING_TYPE_REMOTE;
- } else if (name.contains("Fan")) {
- thingTypeId = LutronMQTTBindingConstants.THING_TYPE_VARIABLE_FAN;
- } else {
- thingTypeId = LutronMQTTBindingConstants.THING_TYPE_DIMMABLE_LIGHT;
- }
+ int deviceClass = device.getDeviceClass();
+ logger.info("device class:" + deviceClass);
+ if (LutronMQTTBindingConstants.remoteDeviceClasses.contains(deviceClass)) {
+ thingTypeId = LutronMQTTBindingConstants.THING_TYPE_REMOTE;
+ } else if (LutronMQTTBindingConstants.variableFanDeviceClasses.contains(deviceClass)) {
+ thingTypeId = LutronMQTTBindingConstants.THING_TYPE_VARIABLE_FAN;
+ } else if (LutronMQTTBindingConstants.dimmableLightDeviceClasses.contains(deviceClass)) {
+ thingTypeId = LutronMQTTBindingConstants.THING_TYPE_DIMMABLE_LIGHT;
+ } else if (LutronMQTTBindingConstants.lightDeviceClasses.contains(deviceClass)) {
+ thingTypeId = LutronMQTTBindingConstants.THING_TYPE_LIGHT;
+ } else if (LutronMQTTBindingConstants.shadeDeviceClasses.contains(deviceClass)) {
+ thingTypeId = LutronMQTTBindingConstants.THING_TYPE_SHADE;
+ }
+
+ logger.info("Thing type ID" + thingTypeId);
+
return thingTypeId;
}
@Override
public void onDeviceRemoved(LutronDevice d) {
// TODO Remove devices
-
}
@Override
M src/main/java/org/openhab/binding/lutronmqtt/discovery/LutronMQTTHubDiscoveryParticipant.java +56 -57
@@ 1,11 1,14 @@
package org.openhab.binding.lutronmqtt.discovery;
+import java.util.*;
+
+import javax.jmdns.ServiceInfo;
+
import org.eclipse.smarthome.config.discovery.DiscoveryResult;
import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder;
import org.eclipse.smarthome.config.discovery.DiscoveryServiceCallback;
import org.eclipse.smarthome.config.discovery.ExtendedDiscoveryService;
import org.eclipse.smarthome.config.discovery.mdns.MDNSDiscoveryParticipant;
-import org.eclipse.smarthome.core.thing.Thing;
import org.eclipse.smarthome.core.thing.ThingTypeUID;
import org.eclipse.smarthome.core.thing.ThingUID;
import org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants;
@@ 13,12 16,6 @@ import org.osgi.service.component.annota
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.jmdns.ServiceInfo;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.Socket;
-import java.util.*;
-
@Component(service = MDNSDiscoveryParticipant.class, immediate = true, configurationPid = "binding.lutronmqtt", name = "org.openhab.binding.lutronmqtt.discovery.hub")
public class LutronMQTTHubDiscoveryParticipant implements MDNSDiscoveryParticipant, ExtendedDiscoveryService {
private Logger logger = LoggerFactory.getLogger(LutronMQTTHubDiscoveryParticipant.class);
@@ 36,64 33,65 @@ public class LutronMQTTHubDiscoveryParti
@Override
public DiscoveryResult createResult(ServiceInfo service) {
-logger.warn("Discovery result: " + service.toString());
- ThingUID uid = getThingUID(service);
+ logger.warn("Discovery result: " + service.toString());
+ ThingUID uid = getThingUID(service);
- logger.warn("text: " + service.getTextString());
- logger.warn("server: " + service.getServer());
- logger.warn("name: " + service.getName());
- logger.warn("qname: " + service.getQualifiedName());
- logger.warn("nice: " + service.getNiceTextString());
- logger.warn("text: " + new String(service.getTextBytes()));
+ logger.warn("text: " + service.getTextString());
+ logger.warn("server: " + service.getServer());
+ logger.warn("name: " + service.getName());
+ logger.warn("qname: " + service.getQualifiedName());
+ logger.warn("nice: " + service.getNiceTextString());
+ logger.warn("text: " + new String(service.getTextBytes()));
+
+ Enumeration<String> pn = service.getPropertyNames();
+ while (pn.hasMoreElements()) {
+ String name;
+ logger.warn("prop: " + (name = pn.nextElement()) + " " + service.getPropertyString(name));
+ }
- Enumeration<String> pn = service.getPropertyNames();
- while(pn.hasMoreElements()) {
- String name;
- logger.warn("prop: " + (name = pn.nextElement()) + " " + service.getPropertyString(name));
- }
+ logger.debug("Got discovered device.");
+ if (true /* getDiscoveryServiceCallback() != null */) {
+ /*
+ * logger.debug("Looking to see if this thing exists already.");
+ * Thing thing = getDiscoveryServiceCallback().getExistingThing(uid);
+ * if (thing != null) {
+ * logger.debug("Already have thing with ID=<" + uid + ">");
+ * return null;
+ * } else {
+ * logger.debug("Nope. This should trigger a new inbox entry.");
+ * }
+ * } else {
+ * logger.warn("DiscoveryServiceCallback not set. This shouldn't happen!");
+ * return null;
+ * }
+ *
+ */
+ if (uid != null) {
+ Map<String, Object> properties = new HashMap<>(2);
+ String u = service.getPropertyString("uuid");
+ String s = service.getServer();
- logger.debug("Got discovered device.");
- if (true /*getDiscoveryServiceCallback() != null*/) {
- /* logger.debug("Looking to see if this thing exists already.");
- Thing thing = getDiscoveryServiceCallback().getExistingThing(uid);
- if (thing != null) {
- logger.debug("Already have thing with ID=<" + uid + ">");
- return null;
- } else {
- logger.debug("Nope. This should trigger a new inbox entry.");
+ if (s == null || s.isEmpty()) {
+ String[] addrs = service.getHostAddresses();
+ if (addrs.length > 0)
+ s = addrs[0];
}
- } else {
- logger.warn("DiscoveryServiceCallback not set. This shouldn't happen!");
- return null;
- }
-*/
- if (uid != null) {
- Map<String, Object> properties = new HashMap<>(2);
- String u = service.getPropertyString("uuid");
- String s = service.getServer();
-
- if(s== null || s.isEmpty()) {
- String [] addrs = service.getHostAddresses();
- if(addrs.length > 0) s = addrs[0];
- }
+ if (u == null || s == null || u.isEmpty() || s.isEmpty()) // incomplete discovery result
+ {
+ logger.warn("Found lutron-mqtt service but missing data. Try restarting device.");
+ return null;
+ }
- if(u == null || s == null || u.isEmpty() || s.isEmpty()) // incomplete discovery result
- {
- logger.warn("Found lutron-mqtt service but missing data. Try restarting device.");
- return null;
- }
+ properties.put(LutronMQTTBindingConstants.PROPERTY_URL, "tcp://" + s + ":" + service.getPort());
+ properties.put(LutronMQTTBindingConstants.PROPERTY_UUID, u);
- properties.put(LutronMQTTBindingConstants.PROPERTY_URL, "tcp://" + s +
- ":" + service.getPort());
- properties.put(LutronMQTTBindingConstants.PROPERTY_UUID, u);
-
- return DiscoveryResultBuilder.create(uid).withProperties(properties)
- .withRepresentationProperty(uid.getId()).withLabel(service.getName() + " Lutron-MQTT Gateway").build();
- }
+ return DiscoveryResultBuilder.create(uid).withProperties(properties)
+ .withRepresentationProperty(uid.getId()).withLabel(service.getName() + " Lutron-MQTT Gateway")
+ .build();
}
+ }
return null;
-
}
@Override
@@ 103,7 101,8 @@ logger.warn("Discovery result: " + servi
if (service.getType() != null) {
if (service.getType().equals(getServiceType())) {
logger.trace("Discovered a Lutron-MQTT gateway thing with name '{}'", service.getName());
- return new ThingUID(LutronMQTTBindingConstants.THING_TYPE_MQTTHUB, service.getName().replace(" ", "_"));
+ return new ThingUID(LutronMQTTBindingConstants.THING_TYPE_MQTTHUB,
+ service.getName().replace(" ", "_"));
}
}
}
M src/main/java/org/openhab/binding/lutronmqtt/handler/DeviceStatusListener.java +0 -1
@@ 9,5 9,4 @@ public interface DeviceStatusListener {
public void onDeviceRemoved(LutronDevice d);
public void onDeviceStateChanged(LutronDevice light);
-
}
M src/main/java/org/openhab/binding/lutronmqtt/handler/LightStateConverter.java +50 -25
@@ 1,18 1,18 @@
package org.openhab.binding.lutronmqtt.handler;
+import static org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants.LUTRON_PROPERTY_LEVEL;
+
+import java.util.HashMap;
+import java.util.Map;
+
import org.eclipse.smarthome.core.library.types.IncreaseDecreaseType;
import org.eclipse.smarthome.core.library.types.OnOffType;
import org.eclipse.smarthome.core.library.types.PercentType;
+import org.eclipse.smarthome.core.library.types.UpDownType;
import org.openhab.binding.lutronmqtt.model.LutronDevice;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants.LUTRON_PROPERTY_LEVEL;
-
/**
* The {@link LightStateConverter} is responsible for mapping Eclipse SmartHome
* types to jue types and vice versa.
@@ 29,11 29,10 @@ public class LightStateConverter {
private static final double BRIGHTNESS_FACTOR = 1.0;
- private static final int DIM_STEPSIZE = 30;
+ private static final int DIM_STEPSIZE = 65535 / 25; // 4 %
protected static Logger log = LoggerFactory.getLogger(LightStateConverter.class);
-
/**
* Transforms the given {@link OnOffType} into a light state containing the
* 'on' value.
@@ 44,15 43,16 @@ public class LightStateConverter {
*/
public static int toOnOffLightState(OnOffType onOffType) {
int f = 0;
- if(onOffType == OnOffType.ON) f = 65535;
+ if (onOffType == OnOffType.ON)
+ f = 65535;
return f;
}
public static int toPercentLightState(PercentType percentType) {
int f = 0;
- if(PercentType.ZERO.equals(percentType))
+ if (PercentType.ZERO.equals(percentType))
f = 0;
- else if(PercentType.HUNDRED.equals(percentType))
+ else if (PercentType.HUNDRED.equals(percentType))
f = 65535;
else {
f = (int) Math.round(percentType.floatValue() * 65535 / 100);
@@ 60,21 60,21 @@ public class LightStateConverter {
return f;
}
- public static Map<String,Object> toLightState(OnOffType onOffType, LutronDevice device) {
+ public static Map<String, Object> toLightState(OnOffType onOffType, LutronDevice device) {
int level = toOnOffLightState(onOffType);
- Map<String,Object> m = makeGoToLevelCommand(level, device);
+ Map<String, Object> m = makeGoToLevelCommand(level, device);
return m;
}
- public static Map<String,Object> makeGoToLevelCommand(int level, LutronDevice device) {
- Map<String,Object> a = new HashMap<>();
+ public static Map<String, Object> makeGoToLevelCommand(int level, LutronDevice device) {
+ Map<String, Object> a = new HashMap<>();
log.warn("device: " + device);
- a.put("ObjectId", device.getLinkAddress());
+ a.put("ObjectId", device.getObjectId());
a.put("ObjectType", 15);
- a.put("Fade", 7);
+ a.put("Fade", 0);
a.put("Delay", 0);
a.put("Level", level);
- Map<String,Object> m = new HashMap<>();
+ Map<String, Object> m = new HashMap<>();
m.put("cmd", "GoToLevel");
m.put("args", a);
@@ 89,18 89,26 @@ public class LightStateConverter {
* brightness represented as {@link PercentType}
* @return light state containing the brightness and the 'on' value
*/
- public static Map<String,Object> toLightState(PercentType percentType, LutronDevice device) {
+ public static Map<String, Object> toLightState(PercentType percentType, LutronDevice device) {
int level = toPercentLightState(percentType);
- Map<String,Object> m = makeGoToLevelCommand(level, device);
+ Map<String, Object> m = makeGoToLevelCommand(level, device);
return m;
}
- public static Map<String,Object> toLightState(IncreaseDecreaseType increaseDecreaseType, LutronDevice device) {
+ public static Map<String, Object> toLightState(IncreaseDecreaseType increaseDecreaseType, LutronDevice device) {
int level = toAdjustedBrightness(increaseDecreaseType, device.getProperty(LUTRON_PROPERTY_LEVEL));
- Map<String,Object> m = makeGoToLevelCommand(level, device);
+ Map<String, Object> m = makeGoToLevelCommand(level, device);
+
+ return m;
+ }
+
+ public static Map<String, Object> toLightState(UpDownType upDownType, LutronDevice device) {
+ int level = toAdjustedBrightness(upDownType, device.getProperty(LUTRON_PROPERTY_LEVEL));
+
+ Map<String, Object> m = makeGoToLevelCommand(level, device);
return m;
}
@@ 125,6 133,25 @@ public class LightStateConverter {
return newBrightness;
}
+ /**
+ * Adjusts the given brightness using the {@link IncreaseDecreaseType} and
+ * returns the updated value.
+ *
+ * @param command
+ * The {@link UpDownType} to be used
+ * @param currentBrightness
+ * The current brightness
+ * @return The adjusted brightness value
+ */
+ public static int toAdjustedBrightness(UpDownType command, int currentBrightness) {
+ int newBrightness;
+ if (command == UpDownType.DOWN) {
+ newBrightness = Math.max(currentBrightness - DIM_STEPSIZE, 0);
+ } else {
+ newBrightness = Math.min(currentBrightness + DIM_STEPSIZE, 65535);
+ }
+ return newBrightness;
+ }
/**
* Transforms Luton device state into {@link PercentType} representing
@@ 135,7 162,7 @@ public class LightStateConverter {
* @return percent type representing the brightness
*/
public static PercentType toBrightnessPercentType(LutronDevice device) {
- int percent = (int) Math.round(device.getProperty(LUTRON_PROPERTY_LEVEL) / (65535/100));
+ int percent = (int) Math.round(device.getProperty(LUTRON_PROPERTY_LEVEL) / (65535 / 100));
if (log.isTraceEnabled()) {
log.trace("Converting " + device.getProperty(LUTRON_PROPERTY_LEVEL) + " -> " + percent + " -> "
+ new PercentType(restrictToBounds(percent)));
@@ 143,7 170,6 @@ public class LightStateConverter {
return new PercentType(restrictToBounds(percent));
}
-
private static int restrictToBounds(int percentValue) {
if (percentValue < 0) {
return 0;
@@ 152,5 178,4 @@ public class LightStateConverter {
}
return percentValue;
}
-
}
M src/main/java/org/openhab/binding/lutronmqtt/handler/LutronMQTTDimmableLightHandler.java +2 -3
@@ 7,11 7,11 @@
*/
package org.openhab.binding.lutronmqtt.handler;
-import org.eclipse.smarthome.core.thing.Thing;
-
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;
+
/**
* The {@link LutronMQTTDimmableLightHandler} is responsible for handling commands, which are
* sent to one of the channels.
@@ 23,5 23,4 @@ public class LutronMQTTDimmableLightHand
public LutronMQTTDimmableLightHandler(Thing thing) {
super(thing, CHANNEL_LIGHT_LEVEL, CHANNEL_LIGHT_STATE);
}
-
}
M src/main/java/org/openhab/binding/lutronmqtt/handler/LutronMQTTHubHandler.java +97 -97
@@ 12,8 12,17 @@
*/
package org.openhab.binding.lutronmqtt.handler;
-import com.google.gson.Gson;
-import jersey.repackaged.com.google.common.collect.ImmutableList;
+import static org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants.CONFIG_TOKEN;
+import static org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants.PROPERTY_URL;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.*;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.config.core.Configuration;
import org.eclipse.smarthome.core.thing.*;
@@ 26,17 35,9 @@ import org.openhab.binding.lutronmqtt.mo
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.UnsupportedEncodingException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.*;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
+import com.google.gson.Gson;
-import static org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants.CONFIG_TOKEN;
-import static org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants.PROPERTY_URL;
-import static org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants.PROPERTY_UUID;
+import jersey.repackaged.com.google.common.collect.ImmutableList;
/**
* The {@link LutronMQTTHubHandler} is responsible for handling commands, which are
@@ 56,7 57,7 @@ public class LutronMQTTHubHandler extend
private String token;
private MqttBrokerConnection mqttClient;
private Gson gson = new Gson();
- private Map<Integer, LutronDevice> devicesByLinkAddress = new HashMap<>();
+ private Map<Integer, LutronDevice> devicesByObjectId = new HashMap<>();
private ScheduledFuture<?> onlineTimeout;
private ScheduledFuture<?> allItemsJob;
@@ 74,42 75,41 @@ public class LutronMQTTHubHandler extend
final String broker = properties.get(PROPERTY_URL);
-
- String clientId = "openhab-lutron-mqtt-" + (System.currentTimeMillis()/1000);
-
- if(mqttClient == null || mqttClient.connectionState() == MqttConnectionState.DISCONNECTED) {
- logger.warn("Attempting to connect to MQTT Broker.");
- URI brokerUri = null;
- try {
- brokerUri = new URI(broker);
- } catch (URISyntaxException e) {
- logger.error("Lutron-MQTT broker url was invalid: " + broker);
- goOffline(ThingStatusDetail.CONFIGURATION_ERROR, "Lutron-MQTT broker url was invalid: " + broker);
- return;
- }
+ String clientId = "openhab-lutron-mqtt-" + (System.currentTimeMillis() / 1000);
- MqttBrokerConnection brokerConnection = new MqttBrokerConnection(brokerUri.getHost(), brokerUri.getPort(), false, clientId);
- brokerConnection.addConnectionObserver(this);
- brokerConnection.setReconnectStrategy(new PeriodicReconnectStrategy());
- updateStatus(ThingStatus.OFFLINE, "Preparing to connect to " + brokerUri.toASCIIString());
-
- Boolean bool = null;
- try {
- mqttClient = brokerConnection;
- bool = brokerConnection.start().get();
- } catch (InterruptedException|ExecutionException e) {
- logger.warn("MQTT startup failed.", e);
- }
- logger.warn("MQTT startup returned " + bool);
+ if (mqttClient == null || mqttClient.connectionState() == MqttConnectionState.DISCONNECTED) {
+ logger.warn("Attempting to connect to MQTT Broker.");
+ URI brokerUri = null;
+ try {
+ brokerUri = new URI(broker);
+ } catch (URISyntaxException e) {
+ logger.error("Lutron-MQTT broker url was invalid: " + broker);
+ goOffline(ThingStatusDetail.CONFIGURATION_ERROR, "Lutron-MQTT broker url was invalid: " + broker);
+ return;
}
- // logger.error("Unable to connect to MQTT broker at " + broker, e);
- // goOffline(ThingStatusDetail.COMMUNICATION_ERROR, "Unable to connect to MQTT broker at broker");
+ MqttBrokerConnection brokerConnection = new MqttBrokerConnection(brokerUri.getHost(), brokerUri.getPort(),
+ false, clientId);
+ brokerConnection.addConnectionObserver(this);
+ brokerConnection.setReconnectStrategy(new PeriodicReconnectStrategy());
+ updateStatus(ThingStatus.OFFLINE, "Preparing to connect to " + brokerUri.toASCIIString());
+ Boolean bool = null;
+ try {
+ mqttClient = brokerConnection;
+ bool = brokerConnection.start().get();
+ } catch (InterruptedException | ExecutionException e) {
+ logger.warn("MQTT startup failed.", e);
+ }
+ logger.warn("MQTT startup returned " + bool);
+ }
+
+ // logger.error("Unable to connect to MQTT broker at " + broker, e);
+ // goOffline(ThingStatusDetail.COMMUNICATION_ERROR, "Unable to connect to MQTT broker at broker");
}
protected void updateStatus(ThingStatus status, String statusDetail) {
- this.updateStatus(status, ThingStatusDetail.NONE, (String)statusDetail);
+ this.updateStatus(status, ThingStatusDetail.NONE, (String) statusDetail);
}
@Override
@@ 117,34 117,34 @@ public class LutronMQTTHubHandler extend
logger.info("Disposing of handler " + this);
super.dispose();
- mqttClient.stop();
- cancelJobs();
+ mqttClient.stop();
+ cancelJobs();
- mqttClient = null;
+ mqttClient = null;
}
private void cancelJobs() {
- if(allItemsJob != null && !allItemsJob.isCancelled())
+ if (allItemsJob != null && !allItemsJob.isCancelled())
allItemsJob.cancel(true);
- if(onlineTimeout != null && !onlineTimeout.isCancelled())
+ if (onlineTimeout != null && !onlineTimeout.isCancelled())
onlineTimeout.cancel(true);
}
private void setupSubscriptions() {
try {
mqttClient.unsubscribeAll().get();
- } catch (InterruptedException|ExecutionException e) {
+ } catch (InterruptedException | ExecutionException e) {
logger.warn("An error occurred while unsubscribing.", e);
}
logger.info("Subscribing.");
- for(String topic : new String[] {"lutron/status", "lutron/events", "lutron/remote"}) {
+ for (String topic : new String[] { "lutron/status", "lutron/events", "lutron/remote" }) {
try {
logger.info("subscribing to " + topic);
- if(!mqttClient.subscribe(topic, this).get()) {
+ if (!mqttClient.subscribe(topic, this).get()) {
logger.error("subscribe failed.");
goOffline(ThingStatusDetail.COMMUNICATION_ERROR, "Unable to subscribe to events");
}
- } catch (InterruptedException|ExecutionException e) {
+ } catch (InterruptedException | ExecutionException e) {
logger.warn("An error occurred while subscribing.", e);
}
}
@@ 157,7 157,7 @@ public class LutronMQTTHubHandler extend
public void run() {
requestAllItems();
}
- }, 5, TimeUnit.SECONDS);
+ }, 10, TimeUnit.SECONDS);
}
private void requestAllItems() {
@@ 171,8 171,8 @@ public class LutronMQTTHubHandler extend
try {
Boolean res = mqttClient.publish("lutron/commands", (b), 0, false).get();
logger.warn("Publish returned " + res);
- } catch(Exception e) {
- logger.warn("Exception while publishing.", e);
+ } catch (Exception e) {
+ logger.warn("Exception while publishing.", e);
}
allItemsJob = scheduler.schedule(new Runnable() {
@@ 185,7 185,6 @@ public class LutronMQTTHubHandler extend
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
-
}
protected void goOnline() {
@@ 194,8 193,10 @@ public class LutronMQTTHubHandler extend
protected void goOffline(ThingStatusDetail detail, String reason) {
updateStatus(ThingStatus.OFFLINE, detail, reason);
- if(onlineTimeout != null) onlineTimeout.cancel(true);
- if(allItemsJob != null) onlineTimeout.cancel(true);
+ if (onlineTimeout != null)
+ onlineTimeout.cancel(true);
+ if (allItemsJob != null)
+ onlineTimeout.cancel(true);
}
public Collection<LutronDevice> getDevices() {
@@ 213,7 214,7 @@ public class LutronMQTTHubHandler extend
@Override
public void processMessage(String s, byte[] mqttMessage) {
logger.warn("messageArrived: " + s + " " + mqttMessage.toString());
- switch(s) {
+ switch (s) {
case "lutron/status":
handleStatusMessage(mqttMessage);
break;
@@ 227,52 228,51 @@ public class LutronMQTTHubHandler extend
}
private void handleGatewayEvent(byte[] mqttMessage) {
- //logger.info("gateway event: " + new String(mqttMessage.getPayload()));
- Map <String,Object> msg = gson.fromJson(new String(mqttMessage), HashMap.class);
+ // logger.info("gateway event: " + new String(mqttMessage.getPayload()));
+ Map<String, Object> msg = gson.fromJson(new String(mqttMessage), HashMap.class);
- if(msg.containsKey("cmd")) {
- String key = (String)msg.get("cmd");
+ if (msg.containsKey("cmd")) {
+ String key = (String) msg.get("cmd");
Object arg = msg.get("args");
- switch(key) {
+ switch (key) {
case "ListDevices":
int i = 0;
logger.warn("ListDevices Response: " + arg);
List<LutronDevice> devices = new ArrayList<>();
- for(Map<String,Object> objectMap : (List<Map<String,Object>>)arg) {
+ for (Map<String, Object> objectMap : (List<Map<String, Object>>) arg) {
getThing().getThings();
final LutronDevice device = new LutronDevice(objectMap);
logger.info("Device: " + device);
devices.add(device);
- if(devicesByLinkAddress.containsKey(device.getLinkAddress())) {
+ if (devicesByObjectId.containsKey(device.getObjectId())) {
// TODO copy properties to new device
}
- devicesByLinkAddress.put(device.getLinkAddress(), device);
+ devicesByObjectId.put(device.getObjectId(), device);
scheduler.schedule(new Runnable() {
@Override
public void run() {
- requestUpdateForDevice(device.getLinkAddress());
+ requestUpdateForDevice(device.getObjectId());
}
- }, i++%3, TimeUnit.SECONDS);
+ }, i++ % 3, TimeUnit.SECONDS);
}
this.deviceList = devices;
break;
case "RuntimePropertyUpdate":
- int linkAddress = ((Number)(((Map)arg).get("ObjectId"))).intValue();
- LutronDevice device = getDeviceByLinkAddress(linkAddress);
- if(device == null) {
- logger.warn("Unable to find LutronDevice with linkAddress=" + linkAddress);
+ int objectId = ((Number) (((Map) arg).get("ObjectId"))).intValue();
+ LutronDevice device = getDeviceByObjectId(objectId);
+ if (device == null) {
+ logger.warn("Unable to find LutronDevice with objectId=" + objectId);
}
- List<List<Object>> l = (List<List<Object>>)(((Map)arg).get("Properties"));
- for(List property : l) {
- int pnum = ((Number)(property.get(0))).intValue();
- int pval = ((Number)(property.get(1))).intValue();
+ List<List<Object>> l = (List<List<Object>>) (((Map) arg).get("Properties"));
+ for (List property : l) {
+ int pnum = ((Number) (property.get(0))).intValue();
+ int pval = ((Number) (property.get(1))).intValue();
device.putProperty(pnum, pval);
}
informDeviceListeners(device);
-
break;
default:
logger.warn("Received unknown message type " + key + " with args " + arg);
@@ 281,9 281,9 @@ public class LutronMQTTHubHandler extend
}
}
- protected void requestUpdateForDevice(int linkAddress) {
- byte[] b = ("{\"cmd\":\"RuntimePropertyQuery\", \"args\":{\"Params\":[[" + linkAddress + ",15,[1]]]}}").getBytes();
- mqttClient.publish("lutron/commands", b);
+ protected void requestUpdateForDevice(int objectId) {
+ byte[] b = ("{\"cmd\":\"RuntimePropertyQuery\", \"args\":{\"Params\":[[" + objectId + ",15,[1]]]}}").getBytes();
+ mqttClient.publish("lutron/commands", b);
}
protected void informDeviceListeners(LutronDevice device) {
@@ 293,23 293,23 @@ public class LutronMQTTHubHandler extend
}
}
- public LutronDevice getDeviceByLinkAddress(int linkAddress) {
- logger.warn("looking for device with link address =" + linkAddress);
- return devicesByLinkAddress.get(linkAddress);
+ public LutronDevice getDeviceByObjectId(int objectId) {
+ logger.warn("looking for device with objectId =" + objectId);
+ return devicesByObjectId.get(objectId);
}
private void handleRemoteEvent(byte[] mqttMessage) {
logger.info("remote event: " + new String(mqttMessage));
- Map <String,Object> msg = gson.fromJson(new String(mqttMessage), HashMap.class);
- // {"serial" : "C726CA", "action": "down", "button": "select"}
+ Map<String, Object> msg = gson.fromJson(new String(mqttMessage), HashMap.class);
+ // {"serial" : "C726CA", "action": "down", "button": "select"}
}
private void handleStatusMessage(byte[] mqttMessage) {
logger.info("status message: " + new String(mqttMessage));
- Map <String,Object> msg = gson.fromJson(new String(mqttMessage), HashMap.class);
- if(msg.containsKey("state") && "running".equals(msg.get("state"))) {
- if(onlineTimeout != null)
+ Map<String, Object> msg = gson.fromJson(new String(mqttMessage), HashMap.class);
+ if (msg.containsKey("state") && "running".equals(msg.get("state"))) {
+ if (onlineTimeout != null)
onlineTimeout.cancel(true);
goOnline();
onlineTimeout = scheduler.schedule(new Runnable() {
@@ 317,7 317,7 @@ public class LutronMQTTHubHandler extend
public void run() {
onlineTimeoutOccurred();
}
- },120, TimeUnit.SECONDS);
+ }, 120, TimeUnit.SECONDS);
}
}
@@ 327,12 327,12 @@ public class LutronMQTTHubHandler extend
mqttClient.stop().get();
Thread.sleep(5000);
initialize();
- } catch(Exception e) {
+ } catch (Exception e) {
logger.warn("An error occurred while restarting the service.", e);
}
}
- public void setDesiredState(int deviceId, Map<String, Object> lightState) {
+ public void setDesiredState(Map<String, Object> lightState) {
byte[] bytes = new byte[0];
try {
bytes = (gson.toJson(lightState)).getBytes("UTF-8");
@@ 343,17 343,18 @@ public class LutronMQTTHubHandler extend
Boolean res = null;
try {
res = mqttClient.publish("lutron/commands", bytes, 0, false).get();
- if(res)
+ if (res)
logger.info("Sent message.");
- else logger.warn("Failed to send message: " + new String(bytes));
- } catch (InterruptedException|ExecutionException e) {
+ else
+ logger.warn("Failed to send message: " + new String(bytes));
+ } catch (InterruptedException | ExecutionException e) {
logger.warn("Error sending message.", e);
}
}
@Override
public void connectionStateChanged(MqttConnectionState mqttConnectionState, @Nullable Throwable throwable) {
- if(mqttConnectionState == MqttConnectionState.CONNECTED) {
+ if (mqttConnectionState == MqttConnectionState.CONNECTED) {
logger.info("MQTT connection state changed to CONNECTED.");
goOnline();
logger.info("Online");
@@ 362,9 363,8 @@ public class LutronMQTTHubHandler extend
public void run() {
setupSubscriptions();
logger.info("Subscribed.");
-
}
- },1, TimeUnit.SECONDS);
+ }, 1, TimeUnit.SECONDS);
} else if (mqttConnectionState == MqttConnectionState.CONNECTING) {
goOffline(ThingStatusDetail.BRIDGE_OFFLINE, "MQTT Reconnecting");
} else if (mqttConnectionState == MqttConnectionState.DISCONNECTED) {
M src/main/java/org/openhab/binding/lutronmqtt/handler/LutronMQTTRemoteHandler.java +0 -7
@@ 13,9 13,6 @@ import org.eclipse.smarthome.core.thing.
import org.eclipse.smarthome.core.types.Command;
import org.openhab.binding.lutronmqtt.model.LutronDevice;
-import static org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants.CHANNEL_LIGHT_LEVEL;
-import static org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants.CHANNEL_LIGHT_STATE;
-
/**
* The {@link LutronMQTTRemoteHandler} is responsible for handling commands, which are
* sent to one of the channels.
@@ 30,21 27,17 @@ public class LutronMQTTRemoteHandler ext
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
-
}
@Override
public void onDeviceFound(LutronDevice d) {
-
}
@Override
public void onDeviceRemoved(LutronDevice d) {
-
}
@Override
public void onDeviceStateChanged(LutronDevice light) {
-
}
}
M src/main/java/org/openhab/binding/lutronmqtt/handler/LutronMQTTVariableFanHandler.java +2 -2
@@ 7,11 7,11 @@
*/
package org.openhab.binding.lutronmqtt.handler;
-import org.eclipse.smarthome.core.thing.Thing;
-
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;
+
/**
* The {@link LutronMQTTVariableFanHandler} is responsible for handling commands, which are
* sent to one of the channels.
M src/main/java/org/openhab/binding/lutronmqtt/handler/PowerLevelDeviceHandler.java +57 -42
@@ 7,10 7,11 @@
*/
package org.openhab.binding.lutronmqtt.handler;
-import com.google.gson.Gson;
-import org.eclipse.smarthome.core.library.types.IncreaseDecreaseType;
-import org.eclipse.smarthome.core.library.types.OnOffType;
-import org.eclipse.smarthome.core.library.types.PercentType;
+import static org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants.*;
+
+import java.util.Map;
+
+import org.eclipse.smarthome.core.library.types.*;
import org.eclipse.smarthome.core.thing.Bridge;
import org.eclipse.smarthome.core.thing.ChannelUID;
import org.eclipse.smarthome.core.thing.Thing;
@@ 24,9 25,7 @@ import org.openhab.binding.lutronmqtt.mo
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Map;
-
-import static org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants.*;
+import com.google.gson.Gson;
/**
* The {@link PowerLevelDeviceHandler} is responsible for handling commands, which are
@@ 38,11 37,13 @@ public class PowerLevelDeviceHandler ext
protected Logger log = LoggerFactory.getLogger(getClass());
- protected int deviceId; //
- protected int integrationId;
+ protected int objectId;
+ // protected int deviceId; //
+ // protected int integrationId;
protected LutronDevice device; // last update received for this device.
- protected int linkAddress;
+ // protected int linkAddress;
+ boolean setAsIs = false;
protected LutronMQTTHubHandler hubHandler;
protected final String powerLevelChannelName;
@@ 56,12 57,15 @@ public class PowerLevelDeviceHandler ext
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
- Map<String,Object> lightState = null;
+ Map<String, Object> lightState = null;
String ch = channelUID.getId();
- log.warn("Got a command for channel id=" + ch + ", command=" + command);
+ log.warn("Got a command for channel id=" + ch + ", command=" + command);
+
+ log.info("command= " + command + ", last device reading=" + getDevice().getProperty(LUTRON_PROPERTY_LEVEL));
if (log.isTraceEnabled()) {
- log.trace("command= " + command + ", last device reading=" + getDevice().getProperty(LUTRON_PROPERTY_LEVEL));
+ log.trace(
+ "command= " + command + ", last device reading=" + getDevice().getProperty(LUTRON_PROPERTY_LEVEL));
}
if (powerLevelChannelName.equals(ch)) {
if (command instanceof PercentType) {
@@ 70,6 74,13 @@ public class PowerLevelDeviceHandler ext
lightState = LightStateConverter.toLightState((OnOffType) command, getDevice());
} else if (command instanceof IncreaseDecreaseType) {
lightState = LightStateConverter.toLightState((IncreaseDecreaseType) command, getDevice());
+ } else if (command instanceof UpDownType) {
+ lightState = LightStateConverter.toLightState((UpDownType) command, getDevice());
+ } else if (command == StopMoveType.STOP) {
+ setAsIs = true;
+ log.warn("STOPPING");
+ scheduleUpdateForDevice(objectId);
+ // lightState = LightStateConverter.toLightState((Sto) command, getDevice());
}
}
@@ 80,10 91,12 @@ public class PowerLevelDeviceHandler ext
* }
* }
*/
+ Gson gson = new Gson();
+ log.info("converted " + command + " to " + gson.toJson(lightState));
if (lightState != null) {
if (log.isTraceEnabled()) {
- Gson gson = new Gson();
+ // Gson gson = new Gson();
log.trace("converted " + command + " to " + gson.toJson(lightState));
}
updateDeviceState(lightState);
@@ 94,7 107,7 @@ public class PowerLevelDeviceHandler ext
protected void updateDeviceState(Map<String, Object> lightState) {
log.warn("updateDeviceState: " + lightState);
- getHubHandler().setDesiredState(deviceId, lightState);
+ getHubHandler().setDesiredState(lightState);
}
@Override
@@ 105,18 118,15 @@ public class PowerLevelDeviceHandler ext
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(getThing().getProperties().get(PROPERTY_INTEGRATION_ID));
- linkAddress = Integer.parseInt(getThing().getProperties().get(PROPERTY_LINK_ADDRESS));
+ final Integer _objectId = Integer.valueOf(getThing().getProperties().get(PROPERTY_OBJECT_ID));
+ log.warn("intializeThing " + _objectId);
- if (configDeviceId != null) {
- deviceId = Integer.valueOf(configDeviceId);
-
+ if (_objectId != null) {
+ this.objectId = _objectId;
if (getHubHandler() != null) {
if (bridgeStatus == ThingStatus.ONLINE) {
- getHubHandler().requestUpdateForDevice(linkAddress);
- LutronDevice device = getHubHandler().getDeviceByLinkAddress(linkAddress);
+ getHubHandler().requestUpdateForDevice(objectId);
+ LutronDevice device = getHubHandler().getDeviceByObjectId(objectId);
if (device == null) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
return;
@@ 124,7 134,7 @@ public class PowerLevelDeviceHandler ext
updateStatus(ThingStatus.ONLINE);
// receiving a response to the request update method above should trigger a state change.
- //onDeviceStateChanged(getHubHandler().getDeviceByIntegrationId(integrationId));
+ // onDeviceStateChanged(getHubHandler().getDeviceByIntegrationId(integrationId));
// initializeProperties();
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
@@ 140,13 150,13 @@ public class PowerLevelDeviceHandler ext
@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
+ if (objectId != 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;
+ objectId = 0;
}
}
@@ 167,17 177,15 @@ public class PowerLevelDeviceHandler ext
return this.hubHandler;
}
- protected void scheduleUpdateForDevice(int deviceId) {
- if (true == true) {
- return;
- }
- log.info("Scheduling an update request for deviceId=" + deviceId);
+ protected void scheduleUpdateForDevice(int objectId) {
+
+ log.info("Scheduling an update request for deviceId=" + objectId);
scheduler.submit(new Runnable() {
@Override
public void run() {
LutronMQTTHubHandler handler = getHubHandler();
if (handler != null) {
- onDeviceStateChanged(handler.getDeviceByLinkAddress(linkAddress));
+ onDeviceStateChanged(handler.getDeviceByObjectId(objectId));
}
}
});
@@ 189,7 197,7 @@ public class PowerLevelDeviceHandler ext
}
LutronMQTTHubHandler handler = getHubHandler();
- device = handler.getDeviceByLinkAddress(linkAddress);
+ device = handler.getDeviceByObjectId(objectId);
return device;
}
@@ 197,7 205,7 @@ public class PowerLevelDeviceHandler ext
public void bridgeStatusChanged(ThingStatusInfo bridgeStatus) {
super.bridgeStatusChanged(bridgeStatus);
if (bridgeStatus.getStatus() == ThingStatus.ONLINE) {
- scheduleUpdateForDevice(linkAddress);
+ scheduleUpdateForDevice(objectId);
}
}
@@ 205,7 213,7 @@ public class PowerLevelDeviceHandler ext
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);
+ scheduleUpdateForDevice(objectId);
} else {
log.info("Channel Linked but hub is not online.");
}
@@ 213,7 221,7 @@ public class PowerLevelDeviceHandler ext
@Override
public void onDeviceFound(LutronDevice d) {
- if (d.getId() == deviceId) {
+ if (d.getObjectId() == objectId) {
updateStatus(ThingStatus.ONLINE);
onDeviceStateChanged(d);
}
@@ 221,24 229,32 @@ public class PowerLevelDeviceHandler ext
@Override
public void onDeviceRemoved(LutronDevice d) {
- if (d.getId() == deviceId) {
+ if (d.getObjectId() == objectId) {
updateStatus(ThingStatus.OFFLINE);
}
}
@Override
public void onDeviceStateChanged(LutronDevice d) {
- if (d.getLinkAddress() != linkAddress) {
+ log.trace("onDeviceStateChanged my id=" + objectId + ", update is for " + d.getObjectId() + ", name="
+ + d.getName());
+ if (d.getObjectId() != objectId) {
return;
}
- log.info("Go device status change for " + this.getThing().getLabel());
+ if (setAsIs) {
+ log.warn("AS IS: " + d.getProperty(LUTRON_PROPERTY_LEVEL));
+ setAsIs = false;
+ }
+
+ log.debug("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))) {
+ 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;
}
@@ 260,5 276,4 @@ public class PowerLevelDeviceHandler ext
return brightness;
}
-
}
M src/main/java/org/openhab/binding/lutronmqtt/internal/LutronMQTTHandlerFactory.java +11 -10
@@ 20,18 20,15 @@ import org.eclipse.jdt.annotation.NonNul
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.config.discovery.DiscoveryService;
import org.eclipse.smarthome.core.thing.Bridge;
-import org.eclipse.smarthome.core.thing.ThingUID;
-import org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants;
import org.eclipse.smarthome.core.thing.Thing;
import org.eclipse.smarthome.core.thing.ThingTypeUID;
+import org.eclipse.smarthome.core.thing.ThingUID;
import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory;
import org.eclipse.smarthome.core.thing.binding.ThingHandler;
import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory;
+import org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants;
import org.openhab.binding.lutronmqtt.discovery.LutronMQTTDeviceDiscoveryService;
-import org.openhab.binding.lutronmqtt.handler.LutronMQTTDimmableLightHandler;
-import org.openhab.binding.lutronmqtt.handler.LutronMQTTHubHandler;
-import org.openhab.binding.lutronmqtt.handler.LutronMQTTRemoteHandler;
-import org.openhab.binding.lutronmqtt.handler.LutronMQTTVariableFanHandler;
+import org.openhab.binding.lutronmqtt.handler.*;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
@@ 43,7 40,7 @@ import org.slf4j.LoggerFactory;
*
* @author William Welliver - Initial contribution
*/
-@Component(service = ThingHandlerFactory.class, immediate = true, configurationPid = "binding.lutronmqtt", name="lutronmqtt")
+@Component(service = ThingHandlerFactory.class, immediate = true, configurationPid = "binding.lutronmqtt", name = "lutronmqtt")
@NonNullByDefault
public class LutronMQTTHandlerFactory extends BaseThingHandlerFactory {
@@ 73,13 70,18 @@ public class LutronMQTTHandlerFactory ex
} else if (thingTypeUID.equals(THING_TYPE_REMOTE)) {
LutronMQTTRemoteHandler handler = new LutronMQTTRemoteHandler(thing);
return handler;
- }
- else if (thingTypeUID.equals(THING_TYPE_DIMMABLE_LIGHT)) {
+ } else if (thingTypeUID.equals(THING_TYPE_DIMMABLE_LIGHT)) {
LutronMQTTDimmableLightHandler handler = new LutronMQTTDimmableLightHandler(thing);
return handler;
+ } else if (thingTypeUID.equals(THING_TYPE_LIGHT)) {
+ LutronMQTTLightHandler handler = new LutronMQTTLightHandler(thing);
+ return handler;
} else if (thingTypeUID.equals(THING_TYPE_VARIABLE_FAN)) {
LutronMQTTVariableFanHandler handler = new LutronMQTTVariableFanHandler(thing);
return handler;
+ } else if (thingTypeUID.equals(THING_TYPE_SHADE)) {
+ LutronMQTTShadeHandler handler = new LutronMQTTShadeHandler(thing);
+ return handler;
}
return null;
@@ 106,5 108,4 @@ public class LutronMQTTHandlerFactory ex
}
}
}
-
}
M src/main/java/org/openhab/binding/lutronmqtt/model/LutronDevice.java +59 -45
@@ 4,50 4,64 @@ import java.util.HashMap;
import java.util.Map;
public class LutronDevice {
- int id;
+ // int id;
String name;
- int integrationId;
+ // int integrationId;
String description;
- int linkAddress;
+ int objectId;
+ // int linkAddress;
int serialNumber;
int deviceClass;
- Map<Integer,Integer> properties = new HashMap<>();
+ Map<Integer, Integer> properties = new HashMap<>();
private long lastUpdated;
- public LutronDevice(Map<String,Object> d) {
- setSerialNumber(Integer.parseInt((String)d.get("SerialNumber")));
- setDeviceClass(Integer.parseInt((String)d.get("DeviceClass")));
- setDescription((String)d.get("Description"));
- setLinkAddress(Integer.parseInt((String)d.get("LinkAddress")));
- setName((String)d.get("Name"));
- setId(Integer.parseInt((String)d.get("DeviceID")));
- setIntegrationId(Integer.parseInt((String)d.get("IntegrationID")));
+ public LutronDevice(Map<String, Object> d) {
+ setSerialNumber(Integer.parseInt((String) d.get("SerialNumber")));
+ setDeviceClass(Integer.parseInt((String) d.get("DeviceClass")));
+ setDescription((String) d.get("Description"));
+ setObjectId(Integer.parseInt((String) d.get("ObjectId")));
+ // setLinkAddress(Integer.parseInt((String) d.get("LinkAddress")));
+ setName((String) d.get("Name"));
+ // setId(Integer.parseInt((String) d.get("DeviceID")));
+ // setIntegrationId(Integer.parseInt((String) d.get("IntegrationID")));
}
- public int getId() {
- return id;
+ // public int getId() {
+ // return id;
+ // }
+ //
+ // public void setId(int id) {
+ // this.id = id;
+ // }
+
+ public int getObjectId() {
+ return objectId;
}
- public void setId(int id) {
- this.id = id;
+ public void setObjectId(int objectId) {
+ this.objectId = objectId;
}
- public int getLinkAddress() { return linkAddress; }
-
- public void setLinkAddress(int linkAddress) { this.linkAddress = linkAddress; }
+ // public int getLinkAddress() {
+ // return linkAddress;
+ // }
+ //
+ // public void setLinkAddress(int linkAddress) {
+ // this.linkAddress = linkAddress;
+ // }
public String getName() {
return name;
}
- public int getIntegrationId() {
- return integrationId;
- }
-
- public void setIntegrationId(int integrationId) {
- this.integrationId = integrationId;
- }
+ // public int getIntegrationId() {
+ // return integrationId;
+ // }
+ //
+ // public void setIntegrationId(int integrationId) {
+ // this.integrationId = integrationId;
+ // }
public String getDescription() {
return description;
@@ 83,25 97,32 @@ public class LutronDevice {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
LutronDevice that = (LutronDevice) o;
- if (id != that.id) return false;
- if (integrationId != that.integrationId) return false;
- if (serialNumber != that.serialNumber) return false;
- if (deviceClass != that.deviceClass) return false;
- if (name != null ? !name.equals(that.name) : that.name != null) return false;
+ if (objectId != that.objectId)
+ return false;
+ // if (integrationId != that.integrationId)
+ // return false;
+ if (serialNumber != that.serialNumber)
+ return false;
+ if (deviceClass != that.deviceClass)
+ return false;
+ if (name != null ? !name.equals(that.name) : that.name != null)
+ return false;
return description != null ? description.equals(that.description) : that.description == null;
}
@Override
public int hashCode() {
- int result = id;
+ int result = objectId;
result = 31 * result + (name != null ? name.hashCode() : 0);
- result = 31 * result + integrationId;
- result = 31 * result + linkAddress;
+ // result = 31 * result + integrationId;
+ // result = 31 * result + objectId;
result = 31 * result + (description != null ? description.hashCode() : 0);
result = 31 * result + serialNumber;
result = 31 * result + deviceClass;
@@ 110,15 131,8 @@ public class LutronDevice {
@Override
public String toString() {
- return "LutronDevice{" +
- "id=" + id +
- ", name='" + name + '\'' +
- ", integrationId=" + integrationId +
- ", linkAddress=" + linkAddress +
- ", description='" + description + '\'' +
- ", serialNumber=" + serialNumber +
- ", deviceClass=" + deviceClass +
- '}';
+ return "LutronDevice{" + "objectId=" + objectId + ", name='" + name + '\'' + ", description='" + description
+ + '\'' + ", serialNumber=" + serialNumber + ", deviceClass=" + deviceClass + '}';
}
public boolean hasUpdatedProperties() {
M src/main/java/org/openhab/binding/lutronmqtt/model/LutronDeviceState.java +1 -1
@@ 19,4 19,4 @@ public class LutronDeviceState {
public void setLevel(float level) {
this.level = level;
}
-}
No newline at end of file
+}
M src/main/resources/ESH-INF/binding/binding.xml +3 -4
@@ 1,8 1,7 @@
<?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">
+<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>
M src/main/resources/ESH-INF/thing/hub.xml +21 -21
@@ 1,28 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">
+ 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>
+ <!-- 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>
+ <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>
+ <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>
+ </bridge-type>
-</thing:thing-descriptions>
No newline at end of file
+</thing:thing-descriptions>
M src/main/resources/ESH-INF/thing/thing-types.xml +130 -81
@@ 1,96 1,145 @@
<?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>
+<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">
- <properties>
- <property name="objectId"></property>
- <property name="integrationId"></property>
- <property name="name"></property>
- </properties>
- </thing-type>
+ <thing-type id="dimmableLight">
+ <supported-bridge-type-refs>
+ <bridge-type-ref id="hub"/>
+ </supported-bridge-type-refs>
- <thing-type id="variableFan">
- <supported-bridge-type-refs>
- <bridge-type-ref id="hub"/>
- </supported-bridge-type-refs>
+ <label>Dimmable Light</label>
+ <description>Controls dimmable loads</description>
- <label>Variable Speed Fan</label>
- <description>Controls variable speed fans</description>
-
- <channels>
- <channel id="fanSpeed" typeId="fanSpeed"/>
- <!-- <channel id="powerSwitch" typeId="powerSwitch"/> -->
- </channels>
+ <channels>
+ <channel id="lightlevel" typeId="lightDimmer"/>
+ <!-- <channel id="lightstate" typeId="lightSwitch"/> -->
+ </channels>
- <properties>
- <property name="objectId"></property>
- <property name="integrationId"></property>
- <property name="linkAddress"></property>
- <property name="name"></property>
- </properties>
- </thing-type>
+ <properties>
+ <property name="objectId"></property>
+ <!-- <property name="integrationId"></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>
+ <thing-type id="light">
+ <supported-bridge-type-refs>
+ <bridge-type-ref id="hub"/>
+ </supported-bridge-type-refs>
- <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>
+ <label>Light Switch</label>
+ <description>Controls switchable loads</description>
+
+ <channels>
+ <channel id="state" typeId="lightSwitch"/>
+ </channels>
- <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>
+ <properties>
+ <property name="objectId"></property>
+ <!-- <property name="integrationId"></property> -->
+ <property name="name"></property>
+ </properties>
+ </thing-type>
- <!-- Sample Thing Type -->
- <thing-type id="sample">
- <label>LutronMQTT Binding Thing</label>
- <description>Sample thing for LutronMQTT Binding</description>
+ <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>
- <channels>
- <channel id="channel1" typeId="sample-channel" />
- </channels>
+ <thing-type id="shade">
+ <supported-bridge-type-refs>
+ <bridge-type-ref id="hub"/>
+ </supported-bridge-type-refs>
+
+ <label>Shade</label>
+ <description>Remotely controllable window covering</description>
+
+ <channels>
+ <channel id="shadeLevel" typeId="shadeLevel"/>
+ </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>
- <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>
+ <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="shadeLevel">
+ <item-type>Rollershutter</item-type>
+ <label>Shade Level</label>
+ <description>Increase/decrease the speed</description>
+ <category>Blinds</category>
+ <state min="0" max="100" pattern="%d %%"/>
+ </channel-type>
- </thing-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>