Skip to content

Commit

Permalink
[homematic] Better support for rollershutters + several smaller fixes (
Browse files Browse the repository at this point in the history
…openhab#8242)

* Set bridge state to offline for duty cycle = -1
* Use correct type Contact for state channel of tilt sensor
* Support type Int64 for messages from Homegear
* Correct support of UP/DOWN for rollershutter devices - Important: UP command must send 1.0 to the device instead of the maximum
value returned by Homematic which is 1.01 and does not work.
* Correct max data point value of certain HmIP devices - Some data points of HmIP are returning 1.01d as max value instead of the correct value of 1.0.
* HM channel "Blind Transmitter" also indicates a rollershutter
* Reduced log level for certain datapoints to avoid flooding the logs - HmIP devices introduced new channel configuration datapoints that can't currently be detected automatically, but the CCU sometimes sends events and the logs were flooded with warnings.
* CuxD interface apparently does not support the rssiInfo method
* equals method call not necessary because of enum usage
* HM method does not return any data if HmIP only is used

Fixes openhab#6360
Fixes openhab#6145
Fixes openhab#5042
Fixes openhab#5674
Fixes openhab#8081
Fixes openhab#6688
Fixes openhab#5048
Fixes openhab#6743
Fixes openhab#5062

Signed-off-by: Martin Herbst <develop@mherbst.de>
  • Loading branch information
MHerbst authored and markus7017 committed Sep 18, 2020
1 parent 169e5c5 commit 7841ca9
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ public void loadDatapointValue(HmDatapoint dp) throws IOException {
@Override
public void loadRssiValues() throws IOException {
for (HmInterface hmInterface : availableInterfaces.keySet()) {
if (hmInterface == HmInterface.RF || hmInterface == HmInterface.CUXD) {
if (hmInterface == HmInterface.RF) {
List<HmRssiInfo> rssiInfos = getRpcClient(hmInterface).loadRssiInfo(hmInterface);
for (HmRssiInfo hmRssiInfo : rssiInfos) {
updateRssiInfo(hmRssiInfo.getAddress(), DATAPOINT_NAME_RSSI_DEVICE, hmRssiInfo.getDevice());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ protected synchronized Object[] sendMessage(int port, RpcRequest<String> request
for (int rpcRetryCounter = 1; rpcRetryCounter <= MAX_RPC_RETRY; rpcRetryCounter++) {
try {
byte[] response = send(port, request);
if (response.length == 0 && "setInstallMode".equals(request.getMethodName())) {
return new Object[] {};
}
Object[] data = new XmlRpcResponse(new ByteArrayInputStream(response), config.getEncoding())
.getResponseData();
return new RpcResponseParser(request).parse(data);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,13 @@ private int readInt() {
return (new BigInteger(bi)).intValue();
}

private long readInt64() {
byte bi[] = new byte[8];
System.arraycopy(binRpcData, offset, bi, 0, 8);
offset += 8;
return (new BigInteger(bi)).longValue();
}

private String readString() throws UnsupportedEncodingException {
int len = readInt();
offset += len;
Expand All @@ -226,6 +233,9 @@ private Object readRpcValue() throws IOException {
return bd.setScale(6, RoundingMode.HALF_DOWN).doubleValue();
case 5:
return new Date(readInt() * 1000);
case 0xD1:
// Int64
return new Long(readInt64());
case 0x100:
// Array
int numElements = readInt();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.openhab.binding.homematic.internal.model.HmChannel;
import org.openhab.binding.homematic.internal.model.HmDatapoint;
import org.openhab.binding.homematic.internal.model.HmDatapointInfo;
import org.openhab.binding.homematic.internal.model.HmInterface;
import org.openhab.binding.homematic.internal.model.HmParamsetType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -60,7 +61,13 @@ public Void parse(Object[] message) throws IOException {
boolean isHmSenMdirNextTrans = dpInfo.getName().equals("NEXT_TRANSMISSION")
&& (deviceType.startsWith("HM-Sen-MDIR-O") || deviceType.startsWith("HM-Sen-MDIR-WM55"));
if (!isHmSenMdirNextTrans) {
logger.warn("Can't set value for datapoint '{}'", dpInfo);
if (dpInfo.getAddress().contains(":M_")
&& channel.getDevice().getHmInterface() == HmInterface.HMIP) {
// These data points can't currently be recognized and therefore can't be created
logger.debug("Can't set value for channel configuration datapoint '{}'", dpInfo);
} else {
logger.warn("Can't set value for datapoint '{}'", dpInfo);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.eclipse.smarthome.core.types.Type;
import org.openhab.binding.homematic.internal.converter.ConverterException;
import org.openhab.binding.homematic.internal.model.HmDatapoint;
import org.openhab.binding.homematic.internal.model.HmInterface;
import org.openhab.binding.homematic.internal.type.MetadataUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -47,16 +48,17 @@ protected Object commandToBinding(Command command, HmDatapoint dp) throws Conver
PercentType type = new PercentType(command.equals(OnOffType.ON) ? 100 : 0);
return convertToBinding(type, dp);
} else if (command.getClass() == UpDownType.class) {
int result = command.equals(UpDownType.UP) ? 100 : 0;
if (MetadataUtils.isRollerShutter(dp)) {
result = command.equals(UpDownType.UP) ? 0 : 100;
}
return convertToBinding(new PercentType(result), dp);
return convertToBinding(command.equals(UpDownType.UP) ? PercentType.ZERO : PercentType.HUNDRED, dp);
} else {
return super.commandToBinding(command, dp);
}
}

private double getCorrectedMaxValue(HmDatapoint dp) {
double max = dp.getMaxValue().doubleValue();
return (max == 1.01 && dp.getChannel().getDevice().getHmInterface() == HmInterface.HMIP ? 1.0d : max);
}

@Override
protected boolean toBindingValidation(HmDatapoint dp, Class<? extends Type> typeClass) {
return dp.isNumberType() && dp.getMaxValue() != null && dp.getMinValue() != null
Expand All @@ -65,10 +67,16 @@ protected boolean toBindingValidation(HmDatapoint dp, Class<? extends Type> type

@Override
protected Object toBinding(PercentType type, HmDatapoint dp) throws ConverterException {
Double number = (type.doubleValue() / 100) * dp.getMaxValue().doubleValue();
double maxValue = getCorrectedMaxValue(dp);
Double number = (type.doubleValue() / 100) * maxValue;

if (MetadataUtils.isRollerShutter(dp)) {
number = dp.getMaxValue().doubleValue() - number;
if (type == PercentType.HUNDRED) { // means DOWN
return dp.getMinValue().doubleValue();
} else if (type == PercentType.ZERO) { // means UP
return maxValue;
}
return maxValue - number;
}
if (number < 0.0 || number > 100.0) {
logger.warn("Percent value '{}' out of range, truncating value for {}", number, dp);
Expand All @@ -89,8 +97,11 @@ protected boolean fromBindingValidation(HmDatapoint dp) {
@Override
protected PercentType fromBinding(HmDatapoint dp) throws ConverterException {
Double number = ((Number) dp.getValue()).doubleValue();
int percent = (int) ((100 / dp.getMaxValue().doubleValue()) * number);

int percent = (int) (100 / getCorrectedMaxValue(dp) * number);
if (percent > 100) {
logger.warn("Percent value '{}' out of range, truncating value for {}", number, dp);
percent = 100;
}
if (MetadataUtils.isRollerShutter(dp)) {
percent = 100 - percent;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public class HomematicBridgeHandler extends BaseBridgeHandler implements Homemat
private final Logger logger = LoggerFactory.getLogger(HomematicBridgeHandler.class);
private static final long REINITIALIZE_DELAY_SECONDS = 10;
private static final int DUTY_CYCLE_RATIO_LIMIT = 99;
private static final int DUTY_CYCLE_DISCONNECTED = -1;
private static SimplePortPool portPool = new SimplePortPool();

private final Object dutyCycleRatioUpdateLock = new Object();
Expand Down Expand Up @@ -349,19 +350,30 @@ public void onDutyCycleRatioUpdate(int dutyCycleRatio) {
this.dutyCycleRatio = dutyCycleRatio;
Channel dutyCycleRatioChannel = thing.getChannel(CHANNEL_TYPE_DUTY_CYCLE_RATIO);
if (dutyCycleRatioChannel != null) {
this.updateState(dutyCycleRatioChannel.getUID(), new DecimalType(dutyCycleRatio));
this.updateState(dutyCycleRatioChannel.getUID(),
new DecimalType(dutyCycleRatio < 0 ? 0 : dutyCycleRatio));
}

if (!isInDutyCycle && dutyCycleRatio >= DUTY_CYCLE_RATIO_LIMIT) {
logger.info("Duty cycle threshold exceeded by homematic bridge {}, it will go OFFLINE.",
thing.getUID());
isInDutyCycle = true;
this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.DUTY_CYCLE);
} else if (isInDutyCycle && dutyCycleRatio < DUTY_CYCLE_RATIO_LIMIT) {
logger.info("Homematic bridge {} fell below duty cycle threshold and will come ONLINE again.",
thing.getUID());
isInDutyCycle = false;
this.updateStatus(ThingStatus.ONLINE);
if (!isInDutyCycle) {
if (dutyCycleRatio >= DUTY_CYCLE_RATIO_LIMIT) {
logger.info("Duty cycle threshold exceeded by homematic bridge {}, it will go OFFLINE.",
thing.getUID());
isInDutyCycle = true;
this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.DUTY_CYCLE);
} else if (dutyCycleRatio == DUTY_CYCLE_DISCONNECTED) {
logger.info(
"Duty cycle indicates a communication problem by homematic bridge {}, it will go OFFLINE.",
thing.getUID());
isInDutyCycle = true;
this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
}
} else {
if (dutyCycleRatio < DUTY_CYCLE_RATIO_LIMIT && dutyCycleRatio != DUTY_CYCLE_DISCONNECTED) {
logger.info("Homematic bridge {}: duty cycle back to normal and bridge will come ONLINE again.",
thing.getUID());
isInDutyCycle = false;
this.updateStatus(ThingStatus.ONLINE);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,16 @@ public class HomematicConstants {
public static final String CHANNEL_TYPE_RAINDETECTOR = "RAINDETECTOR";
public static final String CHANNEL_TYPE_POWERMETER = "POWERMETER";
public static final String CHANNEL_TYPE_SHUTTER_CONTACT = "SHUTTER_CONTACT";
public static final String CHANNEL_TYPE_TILT_SENSOR = "TILT_SENSOR";
public static final String CHANNEL_TYPE_SENSOR = "SENSOR";
public static final String CHANNEL_TYPE_BLIND = "BLIND";
public static final String CHANNEL_TYPE_WINMATIC = "WINMATIC";
public static final String CHANNEL_TYPE_AKKU = "AKKU";
public static final String CHANNEL_TYPE_JALOUSIE = "JALOUSIE";
public static final String CHANNEL_TYPE_SHUTTER_TRANSMITTER = "SHUTTER_TRANSMITTER";
public static final String CHANNEL_TYPE_SHUTTER_VIRTUAL_RECEIVER = "SHUTTER_VIRTUAL_RECEIVER";
public static final String CHANNEL_TYPE_BLIND_TRANSMITTER = "BLIND_TRANSMITTER";
public static final String CHANNEL_TYPE_BLIND_VIRTUAL_RECEIVER = "BLIND_VIRTUAL_RECEIVER";

public static final String DATAPOINT_NAME_CONFIG_PENDING = "CONFIG_PENDING";
public static final String DATAPOINT_NAME_UPDATE_PENDING = "UPDATE_PENDING";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,8 @@ public static String getItemType(HmDatapoint dp) {

if (dp.isBooleanType()) {
if (((dpName.equals(DATAPOINT_NAME_STATE) || dpName.equals(VIRTUAL_DATAPOINT_NAME_STATE_CONTACT))
&& channelType.equals(CHANNEL_TYPE_SHUTTER_CONTACT))
&& (channelType.equals(CHANNEL_TYPE_SHUTTER_CONTACT)
|| channelType.contentEquals(CHANNEL_TYPE_TILT_SENSOR)))
|| (dpName.equals(DATAPOINT_NAME_SENSOR) && channelType.equals(CHANNEL_TYPE_SENSOR))) {
return ITEM_TYPE_CONTACT;
} else {
Expand Down Expand Up @@ -344,8 +345,10 @@ public static String getItemType(HmDatapoint dp) {
public static boolean isRollerShutter(HmDatapoint dp) {
String channelType = dp.getChannel().getType();
return channelType.equals(CHANNEL_TYPE_BLIND) || channelType.equals(CHANNEL_TYPE_JALOUSIE)
|| channelType.equals(CHANNEL_TYPE_BLIND_TRANSMITTER)
|| channelType.equals(CHANNEL_TYPE_SHUTTER_TRANSMITTER)
|| channelType.equals(CHANNEL_TYPE_SHUTTER_VIRTUAL_RECEIVER);
|| channelType.equals(CHANNEL_TYPE_SHUTTER_VIRTUAL_RECEIVER)
|| channelType.contentEquals(CHANNEL_TYPE_BLIND_VIRTUAL_RECEIVER);
}

/**
Expand Down

0 comments on commit 7841ca9

Please sign in to comment.