mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-25 14:55:55 +01:00
[comfoair] improve data handling (#9401)
* improve data handling and suspend * fix command position * add ACK to subResponse * fix data position * fix reactivation, trim too long responses * ensure correct setting of activation channel * Remove @SuppressWarnings(null), which is not needed anymore * Remove updateState on dispose Signed-off-by: Hans Böhm <h.boehm@gmx.at>
This commit is contained in:
parent
1cc6577b20
commit
2ea32faa5d
@ -75,7 +75,7 @@ public enum ComfoAirCommandType {
|
||||
*/
|
||||
ACTIVATE(ComfoAirBindingConstants.CG_CONTROL_PREFIX + ComfoAirBindingConstants.CHANNEL_ACTIVATE,
|
||||
DataTypeBoolean.getInstance(), new int[] { 0x03 }, Constants.REQUEST_SET_RS232, 1, 0,
|
||||
Constants.EMPTY_TYPE_ARRAY, Constants.REPLY_SET_RS232, Constants.REPLY_SET_RS232, new int[] { 0 }, 0x03),
|
||||
Constants.EMPTY_TYPE_ARRAY),
|
||||
MENU20_MODE(ComfoAirBindingConstants.CG_MENUP1_PREFIX + ComfoAirBindingConstants.CHANNEL_MENU20_MODE,
|
||||
DataTypeBoolean.getInstance(), Constants.REQUEST_GET_STATES, Constants.REPLY_GET_STATES, new int[] { 6 },
|
||||
0x01),
|
||||
@ -771,7 +771,7 @@ public enum ComfoAirCommandType {
|
||||
public static @Nullable ComfoAirCommand getReadCommand(String key) {
|
||||
ComfoAirCommandType commandType = getCommandTypeByKey(key);
|
||||
|
||||
if (commandType != null) {
|
||||
if (commandType != null && commandType.readCommand > 0) {
|
||||
return new ComfoAirCommand(key);
|
||||
}
|
||||
return null;
|
||||
@ -891,7 +891,6 @@ public enum ComfoAirCommandType {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("null")
|
||||
private static void uniteCommandsMap(Map<Integer, ComfoAirCommand> commands, ComfoAirCommandType commandType) {
|
||||
if (commandType.readReplyCommand != 0) {
|
||||
int replyCmd = commandType.readReplyCommand;
|
||||
|
@ -24,6 +24,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.comfoair.internal.datatypes.ComfoAirDataType;
|
||||
import org.openhab.core.io.transport.serial.SerialPortManager;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
@ -55,6 +56,8 @@ public class ComfoAirHandler extends BaseThingHandler {
|
||||
private @Nullable ComfoAirSerialConnector comfoAirConnector;
|
||||
|
||||
public static final int BAUDRATE = 9600;
|
||||
public static final String ACTIVATE_CHANNEL_ID = ComfoAirBindingConstants.CG_CONTROL_PREFIX
|
||||
+ ComfoAirBindingConstants.CHANNEL_ACTIVATE;
|
||||
|
||||
public ComfoAirHandler(Thing thing, final SerialPortManager serialPortManager) {
|
||||
super(thing);
|
||||
@ -64,29 +67,36 @@ public class ComfoAirHandler extends BaseThingHandler {
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
String channelId = channelUID.getId();
|
||||
if (comfoAirConnector != null) {
|
||||
boolean isActive = !comfoAirConnector.getIsSuspended();
|
||||
|
||||
if (command instanceof RefreshType) {
|
||||
Channel channel = this.thing.getChannel(channelUID);
|
||||
if (channel != null) {
|
||||
updateChannelState(channel);
|
||||
}
|
||||
} else {
|
||||
ComfoAirCommand changeCommand = ComfoAirCommandType.getChangeCommand(channelId, command);
|
||||
if (isActive || channelId.equals(ACTIVATE_CHANNEL_ID)) {
|
||||
if (command instanceof RefreshType) {
|
||||
Channel channel = this.thing.getChannel(channelUID);
|
||||
if (channel != null) {
|
||||
updateChannelState(channel);
|
||||
}
|
||||
} else {
|
||||
ComfoAirCommand changeCommand = ComfoAirCommandType.getChangeCommand(channelId, command);
|
||||
|
||||
if (changeCommand != null) {
|
||||
Set<String> keysToUpdate = getThing().getChannels().stream().map(Channel::getUID).filter(this::isLinked)
|
||||
.map(ChannelUID::getId).collect(Collectors.toSet());
|
||||
sendCommand(changeCommand, channelId);
|
||||
if (changeCommand != null) {
|
||||
Set<String> keysToUpdate = getThing().getChannels().stream().map(Channel::getUID)
|
||||
.filter(this::isLinked).map(ChannelUID::getId).collect(Collectors.toSet());
|
||||
sendCommand(changeCommand, channelId);
|
||||
|
||||
Collection<ComfoAirCommand> affectedReadCommands = ComfoAirCommandType
|
||||
.getAffectedReadCommands(channelId, keysToUpdate);
|
||||
Collection<ComfoAirCommand> affectedReadCommands = ComfoAirCommandType
|
||||
.getAffectedReadCommands(channelId, keysToUpdate);
|
||||
|
||||
if (affectedReadCommands.size() > 0) {
|
||||
Runnable updateThread = new AffectedItemsUpdateThread(affectedReadCommands);
|
||||
affectedItemsPoller = scheduler.schedule(updateThread, 3, TimeUnit.SECONDS);
|
||||
if (affectedReadCommands.size() > 0) {
|
||||
Runnable updateThread = new AffectedItemsUpdateThread(affectedReadCommands);
|
||||
affectedItemsPoller = scheduler.schedule(updateThread, 3, TimeUnit.SECONDS);
|
||||
}
|
||||
} else {
|
||||
logger.warn("Unhandled command type: {}, channelId: {}", command.toString(), channelId);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.warn("Unhandled command type: {}, channelId: {}", command.toString(), channelId);
|
||||
logger.debug("Binding control is currently not active.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -115,6 +125,8 @@ public class ComfoAirHandler extends BaseThingHandler {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
pullDeviceProperties();
|
||||
|
||||
updateState(ACTIVATE_CHANNEL_ID, OnOffType.ON);
|
||||
|
||||
List<Channel> channels = this.thing.getChannels();
|
||||
|
||||
poller = scheduler.scheduleWithFixedDelay(() -> {
|
||||
@ -159,14 +171,38 @@ public class ComfoAirHandler extends BaseThingHandler {
|
||||
if (!isLinked(channel.getUID())) {
|
||||
return;
|
||||
}
|
||||
String commandKey = channel.getUID().getId();
|
||||
|
||||
ComfoAirCommand readCommand = ComfoAirCommandType.getReadCommand(commandKey);
|
||||
if (readCommand != null) {
|
||||
scheduler.submit(() -> {
|
||||
State state = sendCommand(readCommand, commandKey);
|
||||
if (comfoAirConnector != null) {
|
||||
boolean isActive = !comfoAirConnector.getIsSuspended();
|
||||
|
||||
String commandKey = channel.getUID().getId();
|
||||
if (commandKey.equals(ACTIVATE_CHANNEL_ID)) {
|
||||
State state = OnOffType.from(isActive);
|
||||
updateState(channel.getUID(), state);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isActive) {
|
||||
logger.debug("Binding control is currently not active.");
|
||||
return;
|
||||
}
|
||||
|
||||
ComfoAirCommand readCommand = ComfoAirCommandType.getReadCommand(commandKey);
|
||||
if (readCommand != null && readCommand.getRequestCmd() != null) {
|
||||
scheduler.submit(() -> {
|
||||
State state = sendCommand(readCommand, commandKey);
|
||||
updateState(channel.getUID(), state);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelLinked(ChannelUID channelUID) {
|
||||
super.channelLinked(channelUID);
|
||||
Channel channel = this.thing.getChannel(channelUID);
|
||||
if (channel != null) {
|
||||
updateChannelState(channel);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,8 +47,7 @@ public class ComfoAirSerialConnector {
|
||||
private static final byte[] END = { CTRL, (byte) 0x0f };
|
||||
private static final byte[] ACK = { CTRL, (byte) 0xf3 };
|
||||
|
||||
private static final int RS232_ENABLED_VALUE = 0x03;
|
||||
private static final int RS232_DISABLED_VALUE = 0x00;
|
||||
private static final int MAX_RETRIES = 5;
|
||||
|
||||
private boolean isSuspended = true;
|
||||
|
||||
@ -150,14 +149,17 @@ public class ComfoAirSerialConnector {
|
||||
*/
|
||||
public synchronized int[] sendCommand(ComfoAirCommand command, int[] preRequestData) {
|
||||
Integer requestCmd = command.getRequestCmd();
|
||||
Integer requestValue = command.getRequestValue();
|
||||
int retry = 0;
|
||||
|
||||
if (requestCmd != null) {
|
||||
// Switch support for app or ccease control
|
||||
if (requestCmd == ComfoAirCommandType.Constants.REQUEST_SET_RS232) {
|
||||
isSuspended = !isSuspended;
|
||||
} else if (requestCmd == ComfoAirCommandType.Constants.REPLY_SET_RS232) {
|
||||
return new int[] { isSuspended ? RS232_DISABLED_VALUE : RS232_ENABLED_VALUE };
|
||||
if (requestCmd == ComfoAirCommandType.Constants.REQUEST_SET_RS232 && requestValue != null) {
|
||||
if (requestValue == 1) {
|
||||
isSuspended = false;
|
||||
} else if (requestValue == 0) {
|
||||
isSuspended = true;
|
||||
}
|
||||
} else if (isSuspended) {
|
||||
logger.trace("Ignore cmd. Service is currently suspended");
|
||||
return ComfoAirCommandType.Constants.EMPTY_INT_ARRAY;
|
||||
@ -226,13 +228,44 @@ public class ComfoAirSerialConnector {
|
||||
return ComfoAirCommandType.Constants.EMPTY_INT_ARRAY;
|
||||
}
|
||||
|
||||
boolean isValidData = false;
|
||||
|
||||
// check for start and end sequence and if the response cmd
|
||||
// matches
|
||||
// 11 is the minimum response length with one data byte
|
||||
if (responseBlock.length >= 11 && responseBlock[2] == START[0] && responseBlock[3] == START[1]
|
||||
&& responseBlock[responseBlock.length - 2] == END[0]
|
||||
&& responseBlock[responseBlock.length - 1] == END[1]
|
||||
&& (responseBlock[5] & 0xff) == command.getReplyCmd()) {
|
||||
&& responseBlock[responseBlock.length - 1] == END[1]) {
|
||||
if ((responseBlock[5] & 0xff) == command.getReplyCmd()) {
|
||||
isValidData = true;
|
||||
} else {
|
||||
int startIndex = -1;
|
||||
int endIndex = -1;
|
||||
|
||||
for (int i = 4; i < (responseBlock.length - 11) && endIndex < 0; i++) {
|
||||
if (responseBlock[i] == START[0] && responseBlock[i + 1] == START[1]
|
||||
&& ((responseBlock[i + 3] & 0xff) == command.getReplyCmd())) {
|
||||
startIndex = i;
|
||||
for (int j = startIndex; j < responseBlock.length; j++) {
|
||||
if (responseBlock[j] == END[0] && responseBlock[j + 1] == END[1]) {
|
||||
endIndex = j + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (startIndex > -1 && endIndex > -1) {
|
||||
byte[] subResponse = new byte[endIndex - startIndex + 3];
|
||||
System.arraycopy(responseBlock, 0, subResponse, 0, 2);
|
||||
System.arraycopy(responseBlock, startIndex, subResponse, 2, subResponse.length - 2);
|
||||
responseBlock = subResponse;
|
||||
isValidData = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isValidData) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("receive RAW DATA: {}", dumpData(responseBlock));
|
||||
}
|
||||
@ -294,9 +327,9 @@ public class ComfoAirSerialConnector {
|
||||
logger.warn("Transmission was interrupted: {}", e.getMessage());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} while (retry++ < 5);
|
||||
} while (retry++ < MAX_RETRIES);
|
||||
|
||||
if (retry == 5) {
|
||||
if (retry >= MAX_RETRIES) {
|
||||
logger.debug("Unable to send command. {} retries failed.", retry);
|
||||
}
|
||||
}
|
||||
@ -375,6 +408,10 @@ public class ComfoAirSerialConnector {
|
||||
}
|
||||
cleanedBuffer[pos] = processBuffer[i];
|
||||
pos++;
|
||||
// Trim unrequested data in response
|
||||
if (END[0] == processBuffer[i + 1] && END[1] == processBuffer[i + 2]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Arrays.copyOf(cleanedBuffer, pos);
|
||||
}
|
||||
@ -560,4 +597,8 @@ public class ComfoAirSerialConnector {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean getIsSuspended() {
|
||||
return isSuspended;
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,6 @@ public class DataTypeBoolean implements ComfoAirDataType {
|
||||
} else {
|
||||
int[] readReplyDataPos = commandType.getReadReplyDataPos();
|
||||
int readReplyDataBits = commandType.getReadReplyDataBits();
|
||||
int readCommand = commandType.getReadCommand();
|
||||
boolean result;
|
||||
|
||||
if (readReplyDataPos != null && readReplyDataPos[0] < data.length) {
|
||||
@ -59,8 +58,6 @@ public class DataTypeBoolean implements ComfoAirDataType {
|
||||
result = (data[readReplyDataPos[0]] & readReplyDataBits) == readReplyDataBits;
|
||||
}
|
||||
return OnOffType.from(result);
|
||||
} else if (readCommand == 0) {
|
||||
return OnOffType.OFF; // handle write-only commands (resets)
|
||||
} else {
|
||||
return UnDefType.NULL;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user