Permalink
Browse files

Added support for thermostat3 (#2981)

Also-By: Sander Biesenbeek <sander.biesenbeek@gmail.com>
Also-By: Ruud Beukema <ruudbeukema@gmail.com> (github: ruudbeukema)
Signed-off-by: Martin van Wingerden <martinvw@mtin.nl>
  • Loading branch information...
martinvw authored and kaikreuzer committed Mar 26, 2018
1 parent 8988ed7 commit 48d87768b3c49e28e3b4f12596e52227fd1ec515
@@ -8,21 +8,50 @@
*/
package org.openhab.binding.rfxcom.internal.messages;
import static org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage.PacketType.THERMOSTAT3;
import org.junit.Test;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComMessageNotImplementedException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import javax.xml.bind.DatatypeConverter;
import static org.junit.Assert.assertEquals;
import static org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage.PacketType.THERMOSTAT3;
import static org.openhab.binding.rfxcom.internal.messages.RFXComThermostat3Message.SubType.MERTIK__G6R_H4TB__G6R_H4T__G6R_H4T21_Z22;
/**
* Test for RFXCom-binding
*
* @author Martin van Wingerden
* @since 1.9.0
* @author Martin van Wingerden - Initial contribution
*/
public class RFXComThermostat3MessageTest {
@Test(expected = RFXComMessageNotImplementedException.class)
public void checkNotImplemented() throws Exception {
// TODO Note that this message is supported in the 1.9 binding
@Test
public void checkForSupportTest() throws RFXComException {
RFXComMessageFactory.createMessage(THERMOSTAT3);
}
@Test
public void basicBoundaryCheck() throws RFXComException {
RFXComThermostat3Message message = (RFXComThermostat3Message) RFXComMessageFactory.createMessage(THERMOSTAT3);
message.subType = RFXComThermostat3Message.SubType.MERTIK__G6R_H4S_TRANSMIT_ONLY;
message.command = RFXComThermostat3Message.Commands.ON;
RFXComTestHelper.basicBoundaryCheck(THERMOSTAT3, message);
}
@Test
public void testSomeMessages() throws RFXComException {
String hexMessage = "08420101019FAB0280";
byte[] message = DatatypeConverter.parseHexBinary(hexMessage);
RFXComThermostat3Message msg = (RFXComThermostat3Message) RFXComMessageFactory.createMessage(message);
assertEquals("SubType", MERTIK__G6R_H4TB__G6R_H4T__G6R_H4T21_Z22, msg.subType);
assertEquals("Seq Number", 1, (short) (msg.seqNbr & 0xFF));
assertEquals("Sensor Id", "106411", msg.getDeviceId());
assertEquals("Command", RFXComThermostat3Message.Commands.UP, msg.command);
assertEquals("Signal Level", (byte) 8, msg.signalLevel);
byte[] decoded = msg.decodeMessage();
assertEquals("Message converted back", hexMessage, DatatypeConverter.printHexBinary(decoded));
}
// TODO please add tests for real messages
}
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom" 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="thermostat3">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge" />
<bridge-type-ref id="tcpbridge" />
<bridge-type-ref id="RFXtrx433" />
<bridge-type-ref id="RFXrec433" />
</supported-bridge-type-refs>
<label>RFXCOM Thermostat3 Sensor</label>
<description>A Thermostat3 device.</description>
<channels>
<channel id="command" typeId="command" />
<channel id="signalLevel" typeId="system.signal-strength" />
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Sensor Id. Example 106411</description>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="MERTIK__G6R_H4T1">Mertik (G6R H4T1)</option>
<option value="MERTIK__G6R_H4TB__G6R_H4T__G6R_H4T21_Z22">Mertik (G6R H4TB, G6R H4T, or G6R
H4T21-Z22)
</option>
<option value="MERTIK__G6R_H4TD__G6R_H4T16">Mertik (G6R H4TD or G6R H4T16)</option>
<option value="MERTIK__G6R_H4S_TRANSMIT_ONLY">Mertik (G6R H4S - transmit only)</option>
</options>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>
@@ -231,6 +231,7 @@ This binding currently supports the following things / message types:
* [temperaturerain - RFXCOM Temperature-Rain Sensor](#temperaturerain---rfxcom-temperature-rain-sensor)
* [temperature - RFXCOM Temperature Sensor](#temperature---rfxcom-temperature-sensor)
* [thermostat1 - RFXCOM Thermostat1 Sensor](#thermostat1---rfxcom-thermostat1-sensor)
* [thermostat3 - RFXCOM Thermostat3 Sensor](#thermostat3---rfxcom-thermostat3-sensor)
* [undecoded - RFXCOM Undecoded RF Messages](#undecoded---rfxcom-undecoded-rf-messages)
* [uv - RFXCOM UV/Temperature Sensor](#uv---rfxcom-uvtemperature-sensor)
* [wind - RFXCOM Wind Sensor](#wind---rfxcom-wind-sensor)
@@ -950,6 +951,32 @@ A Thermostat1 device.
* DIGIMAX\_SHORT - Digimax with short format (no set point)
### thermostat3 - RFXCOM Thermostat3 Sensor
A Thermostat3 device.
#### Channels
| Name | Channel Type | Item Type | Remarks |
|-------------|-------------------------------------|-----------|----------|
| command | [command](#channels) | Switch | |
| signalLevel | [system.signal-strength](#channels) | Number | |
#### Configuration Options
* deviceId - Device Id
* Sensor Id. Example 106411
* subType - Sub Type
* Specifies device sub type.
* MERTIK\_\_G6R\_H4T1 - Mertik (G6R H4T1)
* MERTIK\_\_G6R\_H4TB\_\_G6_H4T\_\_G6R\_H4T21\_Z22 - Mertik (G6R H4TB, G6R H4T, or G6R H4T21\-Z22)
* MERTIK\_\_G6R\_H4TD\_\_G6R\_H4T16 - Mertik (G6R H4TD or G6R H4T16)
* MERTIK\_\_G6R\_H4S\_TRANSMIT\_ONLY - Mertik (G6R H4S \- transmit only)
### undecoded - RFXCOM Undecoded RF Messages
Any messages that RFXCOM can receive but not decode.
@@ -50,7 +50,7 @@
// put(PacketType.REMOTE_CONTROL, RFXComRemoteControlMessage.class);
put(PacketType.THERMOSTAT1, RFXComThermostat1Message.class);
// put(PacketType.THERMOSTAT2, RFXComThermostat2Message.class);
// put(PacketType.THERMOSTAT3, RFXComThermostat3Message.class);
put(PacketType.THERMOSTAT3, RFXComThermostat3Message.class);
// put(PacketType.RADIATOR1, RFXComRadiator1Message.class);
put(PacketType.BBQ, RFXComBBQTemperatureMessage.class);
put(PacketType.TEMPERATURE_RAIN, RFXComTemperatureRainMessage.class);
@@ -0,0 +1,211 @@
/**
* Copyright (c) 2010-2018 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.rfxcom.internal.messages;
import org.eclipse.smarthome.core.library.types.OnOffType;
import org.eclipse.smarthome.core.library.types.OpenClosedType;
import org.eclipse.smarthome.core.library.types.UpDownType;
import org.eclipse.smarthome.core.types.State;
import org.eclipse.smarthome.core.types.Type;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import java.util.Arrays;
import java.util.List;
import static org.openhab.binding.rfxcom.RFXComBindingConstants.CHANNEL_COMMAND;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import static org.openhab.binding.rfxcom.internal.messages.RFXComThermostat3Message.SubType.MERTIK__G6R_H4T1;
import static org.openhab.binding.rfxcom.internal.messages.RFXComThermostat3Message.SubType.MERTIK__G6R_H4TB__G6R_H4T__G6R_H4T21_Z22;
/**
* RFXCOM data class for thermostat3message.
*
* Mertik G6R-XXX Thermostat RF sensor operational
*
* @author Sander Biesenbeek - Initial contribution
* @author Ruud Beukema - Initial contribution (parallel development)
* @author Martin van Wingerden - Joined contribution of Sander & Ruud
*/
public class RFXComThermostat3Message extends RFXComDeviceMessageImpl<RFXComThermostat3Message.SubType> {
public enum SubType implements ByteEnumWrapper {
MERTIK__G6R_H4T1(0),
MERTIK__G6R_H4TB__G6R_H4T__G6R_H4T21_Z22(1),
MERTIK__G6R_H4TD__G6R_H4T16(2),
MERTIK__G6R_H4S_TRANSMIT_ONLY(3);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public enum Commands implements ByteEnumWrapper {
OFF(0),
ON(1),
UP(2),
DOWN(3),
RUN_UP(4, MERTIK__G6R_H4T1),
SECOND_OFF(4, MERTIK__G6R_H4TB__G6R_H4T__G6R_H4T21_Z22),
RUN_DOWN(5, MERTIK__G6R_H4T1),
SECOND_ON(5, MERTIK__G6R_H4TB__G6R_H4T__G6R_H4T21_Z22),
STOP(6, MERTIK__G6R_H4T1);
private final int command;
private final List<SubType> supportedBySubTypes;
Commands(int command) {
this(command, SubType.values());
}
Commands(int command, SubType... supportedBySubTypes) {
this.command = command;
this.supportedBySubTypes = Arrays.asList(supportedBySubTypes);
}
@Override
public byte toByte() {
return (byte) command;
}
public static Commands fromByte(int input, SubType subType) throws RFXComUnsupportedValueException {
for (Commands c : Commands.values()) {
if (c.command == input && c.supportedBySubTypes.contains(subType)) {
return c;
}
}
throw new RFXComUnsupportedValueException(Commands.class, input);
}
}
public SubType subType;
private int unitId;
public Commands command;
private byte commandId;
public RFXComThermostat3Message() {
super(PacketType.THERMOSTAT3);
}
public RFXComThermostat3Message(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = "";
str += super.toString();
str += ", Sub type = " + subType;
str += ", Device Id = " + getDeviceId();
str += ", Command = " + command + "(" + commandId + ")";
str += ", Signal level = " + signalLevel;
return str;
}
@Override
public String getDeviceId() {
return String.valueOf(unitId);
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
unitId = (data[4] & 0xFF) << 16 | (data[5] & 0xFF) << 8 | (data[6] & 0xFF);
commandId = data[7];
command = Commands.fromByte(commandId, subType);
signalLevel = (byte) ((data[8] & 0xF0) >> 4);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[9];
data[0] = 0x08;
data[1] = RFXComBaseMessage.PacketType.THERMOSTAT3.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((unitId >> 16) & 0xFF);
data[5] = (byte) ((unitId >> 8) & 0xFF);
data[6] = (byte) (unitId & 0xFF);
data[7] = command.toByte();
data[8] = (byte) ((signalLevel & 0x0F) << 4);
return data;
}
@Override
public State convertToState(String channelId) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_COMMAND:
switch (command) {
case OFF:
case SECOND_OFF:
return OnOffType.OFF;
case ON:
case SECOND_ON:
return OnOffType.ON;
case UP:
return UpDownType.UP;
case DOWN:
return UpDownType.DOWN;
default:
throw new RFXComUnsupportedChannelException("Can't convert " + command + " for " + channelId);
}
default:
return super.convertToState(channelId);
}
}
@Override
public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_COMMAND:
if (type instanceof OnOffType) {
command = (type == OnOffType.ON ? Commands.ON : Commands.OFF);
} else if (type instanceof UpDownType) {
command = (type == UpDownType.UP ? Commands.UP : Commands.DOWN);
} else if (type instanceof OpenClosedType) {
command = (type == OpenClosedType.CLOSED ? Commands.ON : Commands.OFF);
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
break;
default:
throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
}
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
@Override
public void setSubType(SubType subType) {
this.subType = subType;
}
@Override
public void setDeviceId(String deviceId) throws RFXComException {
this.unitId = Integer.parseInt(deviceId);
}
}

0 comments on commit 48d8776

Please sign in to comment.