diff --git a/pom.xml b/pom.xml
--- a/pom.xml
+++ b/pom.xml
@@ -1,19 +1,19 @@
4.0.0
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 3.0.1
+ 3.1.0
../openhab-addons/bundles
- 3.0.2-SNAPSHOT
+ 3.1.0
org.openhab.binding.lutronmqtt
openHAB Add-ons :: Bundles :: Lutron-MQTT Binding
diff --git a/src/main/history/dependencies.xml b/src/main/history/dependencies.xml
--- a/src/main/history/dependencies.xml
+++ b/src/main/history/dependencies.xml
@@ -1,10 +1,10 @@
-
+
openhab-runtime-base
openhab-transport-mqtt
wrap
- mvn:org.openhab.addons.bundles/org.openhab.binding.lutronmqtt/3.0.2-SNAPSHOT
+ mvn:org.openhab.addons.bundles/org.openhab.binding.lutronmqtt/3.1.0
wrap:mvn:org.lastnpe.eea/eea-all/2.2.1
diff --git a/src/main/java/org/openhab/binding/lutronmqtt/handler/LightStateConverter.java b/src/main/java/org/openhab/binding/lutronmqtt/handler/LightStateConverter.java
--- a/src/main/java/org/openhab/binding/lutronmqtt/handler/LightStateConverter.java
+++ b/src/main/java/org/openhab/binding/lutronmqtt/handler/LightStateConverter.java
@@ -1,181 +1,193 @@
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.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.library.types.UpDownType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link LightStateConverter} is responsible for mapping Eclipse SmartHome
* types to jue types and vice versa.
*
* @author Dennis Nobel - Initial contribution
* @author Oliver Libutzki - Adjustments
* @author Kai Kreuzer - made code static
* @author Andre Fuechsel - added method for brightness
* @author Yordan Zhelev - added method for alert
* @author Denis Dudnik - switched to internally integrated source of Jue library, minor code cleanup
*
*/
public class LightStateConverter {
private static final double BRIGHTNESS_FACTOR = 1.0;
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.
*
* @param onOffType
* on or off state
* @return light state containing the 'on' value
*/
- public static int toOnOffLightState(OnOffType onOffType) {
+ public static int toOnOffLightState(OnOffType onOffType, boolean inverted) {
int f = 0;
if (onOffType == OnOffType.ON)
f = 65535;
+ if (inverted)
+ f = 65535 - f;
return f;
}
- public static int toPercentLightState(PercentType percentType) {
+ public static int toPercentLightState(PercentType percentType, boolean inverted) {
int f = 0;
if (PercentType.ZERO.equals(percentType))
f = 0;
else if (PercentType.HUNDRED.equals(percentType))
f = 65535;
else {
f = (int) Math.round(percentType.floatValue() * 65535 / 100);
}
+ if (inverted)
+ f = 65535 - f;
return f;
}
- public static Map toLightState(OnOffType onOffType, LutronDevice device) {
- int level = toOnOffLightState(onOffType);
+ public static Map toLightState(OnOffType onOffType, LutronDevice device, boolean inverted) {
+ int level = toOnOffLightState(onOffType, inverted);
Map m = makeGoToLevelCommand(level, device);
return m;
}
public static Map makeGoToLevelCommand(int level, LutronDevice device) {
Map a = new HashMap<>();
log.warn("device: " + device);
a.put("ObjectId", device.getObjectId());
a.put("ObjectType", 15);
a.put("Fade", 0);
a.put("Delay", 0);
a.put("Level", level);
Map m = new HashMap<>();
m.put("cmd", "GoToLevel");
m.put("args", a);
return m;
}
/**
* Transforms the given {@link PercentType} into a light state containing
* the brightness and the 'on' value represented by {@link PercentType}.
*
* @param percentType
* brightness represented as {@link PercentType}
* @return light state containing the brightness and the 'on' value
*/
- public static Map toLightState(PercentType percentType, LutronDevice device) {
- int level = toPercentLightState(percentType);
+ public static Map toLightState(PercentType percentType, LutronDevice device, boolean inverted) {
+ int level = toPercentLightState(percentType, inverted);
Map m = makeGoToLevelCommand(level, device);
return m;
}
- public static Map toLightState(IncreaseDecreaseType increaseDecreaseType, LutronDevice device) {
- int level = toAdjustedBrightness(increaseDecreaseType, device.getProperty(LUTRON_PROPERTY_LEVEL));
+ public static Map toLightState(IncreaseDecreaseType increaseDecreaseType, LutronDevice device,
+ boolean inverted) {
+ int level = toAdjustedBrightness(increaseDecreaseType, device.getProperty(LUTRON_PROPERTY_LEVEL), inverted);
Map m = makeGoToLevelCommand(level, device);
return m;
}
- public static Map toLightState(UpDownType upDownType, LutronDevice device) {
- int level = toAdjustedBrightness(upDownType, device.getProperty(LUTRON_PROPERTY_LEVEL));
+ public static Map toLightState(UpDownType upDownType, LutronDevice device, boolean inverted) {
+ int level = toAdjustedBrightness(upDownType, device.getProperty(LUTRON_PROPERTY_LEVEL), inverted);
Map m = makeGoToLevelCommand(level, device);
return m;
}
/**
* Adjusts the given brightness using the {@link IncreaseDecreaseType} and
* returns the updated value.
*
* @param command
* The {@link IncreaseDecreaseType} to be used
* @param currentBrightness
* The current brightness
* @return The adjusted brightness value
*/
- public static int toAdjustedBrightness(IncreaseDecreaseType command, int currentBrightness) {
+ public static int toAdjustedBrightness(IncreaseDecreaseType command, int currentBrightness, boolean inverted) {
int newBrightness;
if (command == IncreaseDecreaseType.DECREASE) {
newBrightness = Math.max(currentBrightness - DIM_STEPSIZE, 0);
} else {
newBrightness = Math.min(currentBrightness + DIM_STEPSIZE, 65535);
}
+ if (inverted)
+ newBrightness = 65535 - newBrightness;
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) {
+ public static int toAdjustedBrightness(UpDownType command, int currentBrightness, boolean inverted) {
int newBrightness;
if (command == UpDownType.DOWN) {
newBrightness = Math.max(currentBrightness - DIM_STEPSIZE, 0);
} else {
newBrightness = Math.min(currentBrightness + DIM_STEPSIZE, 65535);
}
+
+ if (inverted)
+ newBrightness = 65535 - newBrightness;
return newBrightness;
}
/**
* Transforms Luton device state into {@link PercentType} representing
* the brightness.
*
* @param device
* lutron device
* @return percent type representing the brightness
*/
- public static PercentType toBrightnessPercentType(LutronDevice device) {
+ public static PercentType toBrightnessPercentType(LutronDevice device, boolean inverted) {
int percent = (int) Math.round(device.getProperty(LUTRON_PROPERTY_LEVEL) / (65535 / 100));
+ if (inverted)
+ percent = 100 - percent;
if (log.isTraceEnabled()) {
log.trace("Converting " + device.getProperty(LUTRON_PROPERTY_LEVEL) + " -> " + percent + " -> "
+ new PercentType(restrictToBounds(percent)));
}
return new PercentType(restrictToBounds(percent));
}
private static int restrictToBounds(int percentValue) {
if (percentValue < 0) {
return 0;
} else if (percentValue > 100) {
return 100;
}
return percentValue;
}
}
diff --git a/src/main/java/org/openhab/binding/lutronmqtt/handler/LutronMQTTShadeHandler.java b/src/main/java/org/openhab/binding/lutronmqtt/handler/LutronMQTTShadeHandler.java
--- a/src/main/java/org/openhab/binding/lutronmqtt/handler/LutronMQTTShadeHandler.java
+++ b/src/main/java/org/openhab/binding/lutronmqtt/handler/LutronMQTTShadeHandler.java
@@ -1,25 +1,26 @@
/**
* Copyright (c) 2014-2016 by the respective copyright holders.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.binding.lutronmqtt.handler;
import static org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants.*;
import org.openhab.core.thing.Thing;
/**
* The {@link LutronMQTTShadeHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author William Welliver - Initial contribution
*/
public class LutronMQTTShadeHandler extends PowerLevelDeviceHandler {
public LutronMQTTShadeHandler(Thing thing) {
super(thing, CHANNEL_SHADE_LEVEL, CHANNEL_POWER_SWITCH);
+ inverted = true;
}
}
diff --git a/src/main/java/org/openhab/binding/lutronmqtt/handler/PowerLevelDeviceHandler.java b/src/main/java/org/openhab/binding/lutronmqtt/handler/PowerLevelDeviceHandler.java
--- a/src/main/java/org/openhab/binding/lutronmqtt/handler/PowerLevelDeviceHandler.java
+++ b/src/main/java/org/openhab/binding/lutronmqtt/handler/PowerLevelDeviceHandler.java
@@ -1,279 +1,282 @@
/**
* Copyright (c) 2014-2016 by the respective copyright holders.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.binding.lutronmqtt.handler;
import static org.openhab.binding.lutronmqtt.LutronMQTTBindingConstants.*;
import java.util.Map;
import org.openhab.binding.lutronmqtt.model.LutronDevice;
import org.openhab.core.library.types.*;
import org.openhab.core.thing.*;
import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.types.Command;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
/**
* The {@link PowerLevelDeviceHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author William Welliver - Initial contribution
*/
public class PowerLevelDeviceHandler extends BaseThingHandler implements DeviceStatusListener {
protected Logger log = LoggerFactory.getLogger(getClass());
protected int objectId;
// protected int deviceId; //
// protected int integrationId;
+
+ protected boolean inverted = false;
+
protected LutronDevice device; // last update received for this device.
// protected int linkAddress;
boolean setAsIs = false;
protected LutronMQTTHubHandler hubHandler;
protected final String powerLevelChannelName;
// protected final String powerSwitchChannelName;
public PowerLevelDeviceHandler(Thing thing, String powerLevelChannel, String powerSwitchChannel) {
super(thing);
this.powerLevelChannelName = powerLevelChannel;
// this.powerSwitchChannelName = powerSwitchChannel;
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
Map lightState = null;
String ch = channelUID.getId();
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));
}
if (powerLevelChannelName.equals(ch)) {
if (command instanceof PercentType) {
- lightState = LightStateConverter.toLightState((PercentType) command, getDevice());
+ lightState = LightStateConverter.toLightState((PercentType) command, getDevice(), inverted);
} else if (command instanceof OnOffType) {
- lightState = LightStateConverter.toLightState((OnOffType) command, getDevice());
+ lightState = LightStateConverter.toLightState((OnOffType) command, getDevice(), inverted);
} else if (command instanceof IncreaseDecreaseType) {
- lightState = LightStateConverter.toLightState((IncreaseDecreaseType) command, getDevice());
+ lightState = LightStateConverter.toLightState((IncreaseDecreaseType) command, getDevice(), inverted);
} else if (command instanceof UpDownType) {
- lightState = LightStateConverter.toLightState((UpDownType) command, getDevice());
+ lightState = LightStateConverter.toLightState((UpDownType) command, getDevice(), inverted);
} else if (command == StopMoveType.STOP) {
setAsIs = true;
log.warn("STOPPING");
scheduleUpdateForDevice(objectId);
// lightState = LightStateConverter.toLightState((Sto) command, getDevice());
}
}
/*
* else if (powerSwitchChannelName.equals(ch)) {
* if (command instanceof OnOffType) {
* lightState = LightStateConverter.toOnOffLightState((OnOffType) command, getDevice());
* }
* }
*/
Gson gson = new Gson();
log.info("converted " + command + " to " + gson.toJson(lightState));
if (lightState != null) {
if (log.isTraceEnabled()) {
// Gson gson = new Gson();
log.trace("converted " + command + " to " + gson.toJson(lightState));
}
updateDeviceState(lightState);
} else {
log.warn("Got a command for an unhandled channel: " + ch);
}
}
protected void updateDeviceState(Map lightState) {
log.warn("updateDeviceState: " + lightState);
getHubHandler().setDesiredState(objectId, lightState);
}
@Override
public void initialize() {
log.debug("Initializing power level device handler.");
initializeThing((getBridge() == null) ? null : getBridge().getStatus());
}
private void initializeThing(ThingStatus bridgeStatus) {
log.debug("initializeThing thing {} bridge status {}", getThing().getUID(), bridgeStatus);
String objId = getThing().getProperties().get(PROPERTY_OBJECT_ID);
final Integer _objectId;
if (objId != null)
_objectId = Integer.valueOf(objId);
else
_objectId = null;
log.warn("intializeThing " + _objectId);
if (_objectId != null) {
this.objectId = _objectId;
if (getHubHandler() != null) {
if (bridgeStatus == ThingStatus.ONLINE) {
getHubHandler().requestUpdateForDevice(objectId);
LutronDevice device = getHubHandler().getDeviceByObjectId(objectId);
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);
}
}
@Override
public void dispose() {
log.debug("Handler disposed. Unregistering listener.");
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;
}
objectId = 0;
}
}
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;
}
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.getDeviceByObjectId(objectId));
}
}
});
}
public LutronDevice getDevice() {
if (device != null) {
return device;
}
LutronMQTTHubHandler handler = getHubHandler();
device = handler.getDeviceByObjectId(objectId);
return device;
}
@Override
public void bridgeStatusChanged(ThingStatusInfo bridgeStatus) {
super.bridgeStatusChanged(bridgeStatus);
if (bridgeStatus.getStatus() == ThingStatus.ONLINE) {
scheduleUpdateForDevice(objectId);
}
}
@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(objectId);
} else {
log.info("Channel Linked but hub is not online.");
}
}
@Override
public void onDeviceFound(LutronDevice d) {
if (d.getObjectId() == objectId) {
updateStatus(ThingStatus.ONLINE);
onDeviceStateChanged(d);
}
}
@Override
public void onDeviceRemoved(LutronDevice d) {
if (d.getObjectId() == objectId) {
updateStatus(ThingStatus.OFFLINE);
}
}
@Override
public void onDeviceStateChanged(LutronDevice d) {
log.trace("onDeviceStateChanged my id=" + objectId + ", update is for " + d.getObjectId() + ", name="
+ d.getName());
if (d.getObjectId() != objectId) {
return;
}
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))) {
log.info("Lutron Device: " + d.getName() + " Received State Changed but no difference");
return;
}
device = d;
log.info("Lutron Device: " + d.getName() + " State Changed: " + d.getProperty(LUTRON_PROPERTY_LEVEL));
// TODO we should keep the previous state so that we don't send unnecessary updates.
- PercentType percentType = LightStateConverter.toBrightnessPercentType(d);
+ PercentType percentType = LightStateConverter.toBrightnessPercentType(d, inverted);
log.info("Lutron: " + d.getName() + " Light Level: " + percentType.intValue());
updateState(powerLevelChannelName, percentType);
}
protected Integer getCurrentLevel(LutronDevice light) {
int brightness = light.getProperty(LUTRON_PROPERTY_LEVEL);
return brightness;
}
}