2 * Copyright (c) 2010-2020 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.rfxcom.internal.messages;
15 import static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
16 import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
17 import static org.openhab.binding.rfxcom.internal.messages.RFXComThermostat3Message.SubType.*;
19 import java.util.Arrays;
20 import java.util.List;
22 import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
23 import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
24 import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
25 import org.openhab.binding.rfxcom.internal.handler.DeviceState;
26 import org.openhab.core.library.types.OnOffType;
27 import org.openhab.core.library.types.PercentType;
28 import org.openhab.core.library.types.StopMoveType;
29 import org.openhab.core.library.types.StringType;
30 import org.openhab.core.library.types.UpDownType;
31 import org.openhab.core.types.State;
32 import org.openhab.core.types.Type;
33 import org.openhab.core.types.UnDefType;
36 * RFXCOM data class for thermostat3message.
38 * Mertik G6R-XXX Thermostat RF sensor operational
40 * @author Sander Biesenbeek - Initial contribution
41 * @author Ruud Beukema - Initial contribution (parallel development)
42 * @author Martin van Wingerden - Joined contribution of Sander & Ruud
44 public class RFXComThermostat3Message extends RFXComDeviceMessageImpl<RFXComThermostat3Message.SubType> {
45 public enum SubType implements ByteEnumWrapper {
47 MERTIK__G6R_H4TB__G6R_H4T__G6R_H4T21_Z22(1),
48 MERTIK__G6R_H4TD__G6R_H4T16(2),
49 MERTIK__G6R_H4S_TRANSMIT_ONLY(3);
51 private final int subType;
53 SubType(int subType) {
54 this.subType = subType;
58 public byte toByte() {
59 return (byte) subType;
63 public enum Commands implements ByteEnumWrapperWithSupportedSubTypes<SubType> {
68 RUN_UP(4, MERTIK__G6R_H4T1),
69 SECOND_OFF(4, MERTIK__G6R_H4TB__G6R_H4T__G6R_H4T21_Z22),
70 RUN_DOWN(5, MERTIK__G6R_H4T1),
71 SECOND_ON(5, MERTIK__G6R_H4TB__G6R_H4T__G6R_H4T21_Z22),
72 STOP(6, MERTIK__G6R_H4T1);
74 private final int command;
75 private final List<SubType> supportedBySubTypes;
77 Commands(int command) {
78 this(command, SubType.values());
81 Commands(int command, SubType... supportedBySubTypes) {
82 this.command = command;
83 this.supportedBySubTypes = Arrays.asList(supportedBySubTypes);
87 public byte toByte() {
88 return (byte) command;
92 public List<SubType> supportedBySubTypes() {
93 return supportedBySubTypes;
97 public SubType subType;
99 public Commands command;
101 public RFXComThermostat3Message() {
102 super(PacketType.THERMOSTAT3);
105 public RFXComThermostat3Message(byte[] data) throws RFXComException {
110 public String toString() {
113 str += super.toString();
114 str += ", Sub type = " + subType;
115 str += ", Device Id = " + getDeviceId();
116 str += ", Command = " + command;
117 str += ", Signal level = " + signalLevel;
123 public String getDeviceId() {
124 return String.valueOf(unitId);
128 public void encodeMessage(byte[] data) throws RFXComException {
129 super.encodeMessage(data);
131 subType = fromByte(SubType.class, super.subType);
132 unitId = (data[4] & 0xFF) << 16 | (data[5] & 0xFF) << 8 | (data[6] & 0xFF);
133 command = fromByte(Commands.class, data[7], subType);
134 signalLevel = (byte) ((data[8] & 0xF0) >> 4);
138 public byte[] decodeMessage() {
139 byte[] data = new byte[9];
142 data[1] = RFXComBaseMessage.PacketType.THERMOSTAT3.toByte();
143 data[2] = subType.toByte();
145 data[4] = (byte) ((unitId >> 16) & 0xFF);
146 data[5] = (byte) ((unitId >> 8) & 0xFF);
147 data[6] = (byte) (unitId & 0xFF);
148 data[7] = command.toByte();
149 data[8] = (byte) ((signalLevel & 0x0F) << 4);
155 public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
157 case CHANNEL_COMMAND:
161 return OnOffType.OFF;
170 return UnDefType.UNDEF;
173 case CHANNEL_CONTROL:
179 return UpDownType.UP;
181 return OnOffType.OFF;
184 return UpDownType.DOWN;
190 throw new RFXComUnsupportedChannelException("Can't convert " + command + " for " + channelId);
192 case CHANNEL_COMMAND_SECOND:
195 return OnOffType.OFF;
201 case CHANNEL_COMMAND_STRING:
202 return command == null ? UnDefType.UNDEF : StringType.valueOf(command.toString());
205 return super.convertToState(channelId, deviceState);
210 public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
212 case CHANNEL_COMMAND:
213 if (type instanceof OnOffType) {
214 command = (type == OnOffType.ON ? Commands.ON : Commands.OFF);
216 throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
220 case CHANNEL_COMMAND_SECOND:
221 if (type instanceof OnOffType) {
222 command = (type == OnOffType.ON ? Commands.SECOND_ON : Commands.SECOND_OFF);
224 throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
228 case CHANNEL_CONTROL:
229 if (type instanceof UpDownType) {
230 command = (type == UpDownType.UP ? Commands.UP : Commands.DOWN);
231 } else if (type == StopMoveType.STOP) {
232 command = Commands.STOP;
233 } else if (type instanceof PercentType) {
234 command = ((PercentType) type).as(UpDownType.class) == UpDownType.UP ? Commands.UP : Commands.DOWN;
236 throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
240 case CHANNEL_COMMAND_STRING:
241 command = Commands.valueOf(type.toString().toUpperCase());
245 throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
250 public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
251 return ByteEnumUtil.convertSubType(SubType.class, subType);
255 public void setSubType(SubType subType) {
256 this.subType = subType;
260 public void setDeviceId(String deviceId) {
261 this.unitId = Integer.parseInt(deviceId);