2 * Copyright (c) 2010-2024 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.*;
17 import org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfiguration;
18 import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
19 import org.openhab.binding.rfxcom.internal.exceptions.RFXComInvalidStateException;
20 import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
21 import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
22 import org.openhab.binding.rfxcom.internal.handler.DeviceState;
23 import org.openhab.core.library.types.IncreaseDecreaseType;
24 import org.openhab.core.library.types.OnOffType;
25 import org.openhab.core.library.types.OpenClosedType;
26 import org.openhab.core.library.types.StringType;
27 import org.openhab.core.types.Command;
28 import org.openhab.core.types.State;
29 import org.openhab.core.types.Type;
30 import org.openhab.core.types.UnDefType;
33 * RFXCOM data class for lighting1 message. See X10, ARC, etc..
35 * @author Evert van Es, Cycling Engineer - Initial contribution
36 * @author Pauli Anttila
38 public class RFXComLighting1Message extends RFXComDeviceMessageImpl<RFXComLighting1Message.SubType> {
40 public enum SubType implements ByteEnumWrapper {
53 OASE_INSCENIO_FM_N(12);
55 private final int subType;
57 SubType(int subType) {
58 this.subType = subType;
62 public byte toByte() {
63 return (byte) subType;
67 public enum Commands implements ByteEnumWrapper {
76 private final int command;
78 Commands(int command) {
79 this.command = command;
83 public byte toByte() {
84 return (byte) command;
88 public SubType subType;
89 public char houseCode;
91 public Commands command;
94 private static byte[] lastUnit = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
96 public RFXComLighting1Message() {
97 super(PacketType.LIGHTING1);
100 public RFXComLighting1Message(byte[] data) throws RFXComException {
105 public String toString() {
108 str += super.toString();
109 str += ", Sub type = " + subType;
110 str += ", Device Id = " + getDeviceId();
111 str += ", Command = " + command;
112 str += ", Signal level = " + signalLevel;
118 public void encodeMessage(byte[] data) throws RFXComException {
119 super.encodeMessage(data);
121 subType = ByteEnumUtil.fromByte(SubType.class, super.subType);
122 houseCode = (char) data[4];
123 command = ByteEnumUtil.fromByte(Commands.class, data[6]);
125 if ((command == Commands.GROUP_ON) || (command == Commands.GROUP_OFF)) {
127 } else if ((data[5] == 0) && ((command == Commands.DIM) || (command == Commands.BRIGHT))) {
128 // SS13 switches broadcast DIM/BRIGHT to X0 and the dimmers ignore
129 // the message unless the last X<n> ON they saw was for them. So we
130 // redirect an incoming broadcast DIM/BRIGHT to the correct item
131 // based on the last X<n> we saw or sent.
132 unitCode = lastUnit[houseCode - 'A'];
135 if (command == Commands.ON) {
136 lastUnit[houseCode - 'A'] = unitCode;
140 signalLevel = (byte) ((data[7] & 0xF0) >> 4);
144 public byte[] decodeMessage() {
145 // Example data 07 10 01 00 42 01 01 70
146 // 07 10 01 00 42 10 06 70
148 byte[] data = new byte[8];
151 data[1] = PacketType.LIGHTING1.toByte();
152 data[2] = subType.toByte();
154 data[4] = (byte) houseCode;
156 data[6] = command.toByte();
157 data[7] = (byte) ((signalLevel & 0x0F) << 4);
163 public String getDeviceId() {
164 return houseCode + ID_DELIMITER + unitCode;
168 public Command convertToCommand(String channelId, RFXComDeviceConfiguration config, DeviceState deviceState)
169 throws RFXComUnsupportedChannelException, RFXComInvalidStateException {
171 case CHANNEL_COMMAND:
175 return OnOffType.OFF;
182 return IncreaseDecreaseType.DECREASE;
185 return IncreaseDecreaseType.INCREASE;
191 throw new RFXComUnsupportedChannelException(
192 "Channel " + channelId + " does not accept " + command);
196 return super.convertToCommand(channelId, config, deviceState);
201 public State convertToState(String channelId, RFXComDeviceConfiguration config, DeviceState deviceState)
202 throws RFXComUnsupportedChannelException {
204 case CHANNEL_COMMAND:
209 return OnOffType.OFF;
218 throw new RFXComUnsupportedChannelException(
219 "Channel " + channelId + " does not accept " + command);
222 case CHANNEL_COMMAND_STRING:
223 return command == null ? UnDefType.UNDEF : StringType.valueOf(command.toString());
225 case CHANNEL_CONTACT:
230 return OpenClosedType.CLOSED;
236 return OpenClosedType.OPEN;
239 throw new RFXComUnsupportedChannelException(
240 "Channel " + channelId + " does not accept " + command);
244 throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
249 public void setSubType(SubType subType) {
250 this.subType = subType;
254 public void setDeviceId(String deviceId) throws RFXComException {
255 String[] ids = deviceId.split("\\" + ID_DELIMITER);
256 if (ids.length != 2) {
257 throw new RFXComException("Invalid device id '" + deviceId + "'");
260 houseCode = ids[0].charAt(0);
262 // Get unitcode, 0 means group
263 unitCode = Byte.parseByte(ids[1]);
271 public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
273 case CHANNEL_COMMAND:
274 if (type instanceof OnOffType) {
276 command = (type == OnOffType.ON ? Commands.GROUP_ON : Commands.GROUP_OFF);
279 command = (type == OnOffType.ON ? Commands.ON : Commands.OFF);
282 throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
286 case CHANNEL_COMMAND_STRING:
287 command = Commands.valueOf(type.toString().toUpperCase());
291 throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
296 public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
297 return ByteEnumUtil.convertSubType(SubType.class, subType);