[rfxcom] Enable Raw message transmission (#10866)

This enables raw message transmission by configuring a raw thing with pulses to
send for either ON, OFF, OPEN or CLOSED commands.

To enable extended config, this includes a refactor for the RFXComHandler to
support different Configuration objects depending on the thing type, and moves
the parsing, validation, and message matching logic to the Configuration objects
where the logic is more appropriate.

To enable testing of the RFXComHandler, the RFXComMessageFactory was abstracted
out and injected as a dependency.

Signed-off-by: James Hewitt <james.hewitt@uk.ibm.com>
This commit is contained in:
James Hewitt 2021-06-24 18:37:37 +01:00 committed by GitHub
parent c5c2cab0a7
commit 6403e03cea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
74 changed files with 1199 additions and 330 deletions

View File

@ -171,6 +171,7 @@ This binding currently supports following channel types:
| mood | Number | Mood channel. |
| motion | Switch | Motion detection sensor state. |
| pressure | Number | Barometric value in hPa. |
| pulses | String | Space separated decimal pulse lengths for a raw message in usec. |
| rainrate | Number | Rain fall rate in millimeters per hour. |
| raintotal | Number | Total rain in millimeters. |
| rawmessage | String | Hexadecimal representation of the raw RFXCOM msg incl. header and payload |
@ -918,9 +919,15 @@ A Rain device
* RAIN6 - La Crosse TX5
* RAIN9 - TFA 30.3233.1
### raw - RFXCOM Raw Messages
Raw messages.
Raw messages. These messages are included in the Pro firmware and represent messages
for which the device does not understand the protocol. The raw message is a list of the
length of the RF pulses before they have been interpreted as bytes.
You can also send raw messages by recording the pulses of an incoming message and
using them to configure a raw thing item.
#### Channels
@ -928,11 +935,13 @@ Raw messages.
|------------|---------------------------|-----------|-------------|
| rawMessage | [rawmessage](#channels) | String | |
| rawPayload | [rawpayload](#channels) | String | |
| pulses | [pulses](#channels) | String | |
#### Configuration Options
* deviceId - Device Id
* Raw items cannot provide a device ID, so this value is always RAW.
* Raw items cannot provide a device ID, so to receive RAW messages use
a Device Id of RAW. For transmit only devices, use any Device Id.
* subType - Sub Type
* Specifies message sub type.
@ -942,6 +951,79 @@ Raw messages.
* RAW_PACKET3
* RAW_PACKET4
* repeat - Repeat
* Number of times to repeat message on transmit. Defaults to 5.
* onPulses - On Pulses
* Pulses to send for an ON command. Space delimited pulse lengths
in usec. Must be an even number of pulse lengths, with a maximum
of 142 total pulses. Max pulse length is 65535. Pulses of value 0
will be transmitted as 10000. See the RFXtfx user guide for more
information.
* offPulses - Off Pulses
* Pulses to send for an OFF command. Space delimited pulse lengths
in usec. Must be an even number of pulse lengths, with a maximum
of 142 total pulses. Max pulse length is 65535. Pulses of value 0
will be transmitted as 10000. See the RFXtfx user guide for more
information.
* openPulses - Open Pulses
* Pulses to send for an OPEN command. Space delimited pulse lengths
in usec. Must be an even number of pulse lengths, with a maximum
of 142 total pulses. Max pulse length is 65535. Pulses of value 0
will be transmitted as 10000. See the RFXtfx user guide for more
information.
* closedPulses - Closed Pulses
* Pulses to send for an CLOSED command. Space delimited pulse lengths
in usec. Must be an even number of pulse lengths, with a maximum
of 142 total pulses. Max pulse length is 65535. Pulses of value 0
will be transmitted as 10000. See the RFXtfx user guide for more
information.
#### Examples
This can be used to transmit raw messages.
The first step is to work out the right pulses for the device. You can do this using RFXmngr, or
you can do this using openhab:
1. Set up a RAW thing to receive raw pulses:
```
Bridge rfxcom:tcpbridge:rfxtrx0 [ host="192.168.42.10", port=10001, enableUndecoded=true ] {
Thing raw RAW [ deviceId="RAW", subType="RAW_PACKET1" ]
}
```
2. Add an item to see what the pulses are:
```
String RawPulses { channel="rfxcom:raw:rfxtrx0:RAW:pulses" }
```
3. Activate the device and look at the pulses that are set. Look for a higher value in the pulses, that is
likely to be a gap for a repeat. Take the pulses from before the gap. Make sure there are an
even number, and if not, drop a 0 on the end.
Now you have the pulses, set up a send device:
1. Set up a RAW thing to send a command:
```
Bridge rfxcom:tcpbridge:rfxtrx0 [ host="192.168.42.10", port=10001, enableUndecoded=true ] {
Thing raw MySwitch [ deviceId="MySwitch", subType="RAW_PACKET1", onPulses="100 200 300 0", offPulses="400 500 600 0" ]
}
```
2. Add an item to send the command:
```
Switch MySwitch { channel="rfxcom:raw:rfxtrx0:MySwitch:command" }
```
3. Use the command to send the raw message.
### rfxsensor - RFXCOM RFXSensor
@ -1230,7 +1312,12 @@ A Thermostat3 device.
### undecoded - RFXCOM Undecoded RF Messages
Any messages that RFXCOM can receive but not decode.
Undecoded messages are messages where RFCOM understands the protocol and has converted
the raw RF pulses into bytes, but has not attempted to decode the bytes into meaningful
data.
Undecoded message are receive only, there is not way to transmit an undecoded message.
If you need to repeat an undecoded message, consider looking at Raw messages instead.
#### Channels

View File

@ -12,6 +12,7 @@
*/
package org.openhab.binding.rfxcom.internal;
import java.util.AbstractMap;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@ -20,6 +21,9 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfiguration;
import org.openhab.binding.rfxcom.internal.config.RFXComLighting4DeviceConfiguration;
import org.openhab.binding.rfxcom.internal.config.RFXComRawDeviceConfiguration;
import org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage.PacketType;
import org.openhab.core.thing.ThingTypeUID;
@ -65,6 +69,7 @@ public class RFXComBindingConstants {
// List of all Channel ids
public static final String CHANNEL_RAW_MESSAGE = "rawMessage";
public static final String CHANNEL_RAW_PAYLOAD = "rawPayload";
public static final String CHANNEL_PULSES = "pulses";
public static final String CHANNEL_SHUTTER = "shutter";
public static final String CHANNEL_VENETIAN_BLIND = "venetianBlind";
public static final String CHANNEL_SUN_WIND_DETECTOR = "sunWindDetector";
@ -188,6 +193,16 @@ public class RFXComBindingConstants {
THING_TYPE_THERMOSTAT2, THING_TYPE_THERMOSTAT3, THING_TYPE_UNDECODED, THING_TYPE_UV,
THING_TYPE_WATER_USAGE, THING_TYPE_WEIGHTING_SCALE, THING_TYPE_WIND).collect(Collectors.toSet()));
/**
* Map Device ThingTypeUIDs to their Configuration class
*/
public static final Map<ThingTypeUID, Class<? extends RFXComDeviceConfiguration>> THING_TYPE_UID_CONFIGURATION_CLASS_MAP = Map
.ofEntries(
new AbstractMap.SimpleEntry<ThingTypeUID, Class<? extends RFXComDeviceConfiguration>>(
THING_TYPE_RAW, RFXComRawDeviceConfiguration.class),
new AbstractMap.SimpleEntry<ThingTypeUID, Class<? extends RFXComDeviceConfiguration>>(
THING_TYPE_LIGHTNING4, RFXComLighting4DeviceConfiguration.class));
/**
* Map RFXCOM packet types to RFXCOM Thing types and vice versa.
*/

View File

@ -64,7 +64,7 @@ public class RFXComHandlerFactory extends BaseThingHandlerFactory {
if (RFXComBindingConstants.SUPPORTED_BRIDGE_THING_TYPES_UIDS.contains(thingTypeUID)) {
return new RFXComBridgeHandler((Bridge) thing, serialPortManager);
} else if (supportsThingType(thingTypeUID)) {
} else if (RFXComBindingConstants.SUPPORTED_DEVICE_THING_TYPES_UIDS.contains(thingTypeUID)) {
return new RFXComHandler(thing);
}

View File

@ -12,22 +12,17 @@
*/
package org.openhab.binding.rfxcom.internal.config;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComInvalidParameterException;
import org.openhab.binding.rfxcom.internal.messages.RFXComDeviceMessage;
/**
* Configuration class for RfxcomBinding device.
* Configuration interface for RFXCom devices.
*
* @author Pauli Anttila - Initial contribution
* @author James Hewitt-Thomas - Convert to interface and add validation and matching
*/
public interface RFXComDeviceConfiguration {
public void parseAndValidate() throws RFXComInvalidParameterException;
public class RFXComDeviceConfiguration {
public static final String DEVICE_ID_LABEL = "deviceId";
public static final String SUB_TYPE_LABEL = "subType";
public static final String PULSE_LABEL = "pulse";
public static final String ON_COMMAND_ID_LABEL = "onCommandId";
public static final String OFF_COMMAND_ID_LABEL = "offCommandId";
public String deviceId;
public String subType;
public Integer pulse;
public Integer onCommandId;
public Integer offCommandId;
public boolean matchesMessage(RFXComDeviceMessage message);
}

View File

@ -0,0 +1,44 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.rfxcom.internal.config;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComInvalidParameterException;
import org.openhab.binding.rfxcom.internal.messages.RFXComDeviceMessage;
/**
* Configuration class for generic RFXCOM device.
*
* @author Pauli Anttila - Initial contribution
* @author James Hewitt-Thomas - Add validations and matching
*/
public class RFXComGenericDeviceConfiguration implements RFXComDeviceConfiguration {
public static final String DEVICE_ID_LABEL = "deviceId";
public static final String SUB_TYPE_LABEL = "subType";
public String deviceId;
public String subType;
@Override
public void parseAndValidate() throws RFXComInvalidParameterException {
if (deviceId == null) {
throw new RFXComInvalidParameterException("deviceId", null, "RFXCOM device missing deviceId");
}
if (subType == null) {
throw new RFXComInvalidParameterException("subType", null, "RFXCOM device missing subType");
}
}
@Override
public boolean matchesMessage(RFXComDeviceMessage message) {
return deviceId.equals(message.getDeviceId());
}
}

View File

@ -0,0 +1,27 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.rfxcom.internal.config;
/**
* Configuration class for Lighting4 RFXCOM device.
*
* @author James Hewitt-Thomas - Initial contribution
*/
public class RFXComLighting4DeviceConfiguration extends RFXComGenericDeviceConfiguration {
public static final String PULSE_LABEL = "pulse";
public static final String ON_COMMAND_ID_LABEL = "onCommandId";
public static final String OFF_COMMAND_ID_LABEL = "offCommandId";
public Integer pulse;
public Integer onCommandId;
public Integer offCommandId;
}

View File

@ -0,0 +1,99 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.rfxcom.internal.config;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComInvalidParameterException;
/**
* Configuration class for Raw RFXCOM device.
*
* @author James Hewitt-Thomas - Initial contribution
*/
@NonNullByDefault
public class RFXComRawDeviceConfiguration extends RFXComGenericDeviceConfiguration {
public static final String REPEAT_LABEL = "repeat";
public int repeat;
public static final String ON_PULSES_LABEL = "onPulses";
public static final String OFF_PULSES_LABEL = "offPulses";
@Nullable
public String onPulses;
@Nullable
public String offPulses;
public short @Nullable [] onPulsesArray;
public short @Nullable [] offPulsesArray;
public static final String OPEN_PULSES_LABEL = "openPulses";
public static final String CLOSED_PULSES_LABEL = "closedPulses";
@Nullable
public String openPulses;
@Nullable
public String closedPulses;
public short @Nullable [] openPulsesArray;
public short @Nullable [] closedPulsesArray;
@Override
public void parseAndValidate() throws RFXComInvalidParameterException {
super.parseAndValidate();
onPulsesArray = parseAndValidatePulses("onPulses", onPulses);
offPulsesArray = parseAndValidatePulses("offPulses", offPulses);
openPulsesArray = parseAndValidatePulses("openPulses", openPulses);
closedPulsesArray = parseAndValidatePulses("closedPulses", closedPulses);
}
private static short @Nullable [] parseAndValidatePulses(String parameter, @Nullable String pulses)
throws RFXComInvalidParameterException {
if (pulses != null) {
return parseAndValidatePulsesNonNull(parameter, pulses);
} else {
return null;
}
}
private static short[] parseAndValidatePulsesNonNull(String parameter, String pulses)
throws RFXComInvalidParameterException {
String[] strings = pulses.trim().split("\\s+");
if (strings.length > 124) {
throw new RFXComInvalidParameterException(parameter, pulses, "Cannot have more than 124 pulses");
}
if (strings.length % 2 != 0) {
throw new RFXComInvalidParameterException(parameter, pulses, "Pulses must be in pairs");
}
try {
short[] shorts = new short[strings.length];
for (int i = 0; i < strings.length; i++) {
int pulse = Integer.parseInt(strings[i]);
if (pulse > 65535) {
throw new RFXComInvalidParameterException(parameter, pulses, "Cannot have pulse above 65535 usec");
} else if (pulse < 0) {
throw new RFXComInvalidParameterException(parameter, pulses, "Cannot have negative pulse");
} else if (pulse == 0) {
// The user guide suggests that received pulses of size 0 should be
// replaced with something above 8000, as they represent gaps.
shorts[i] = 10000;
} else {
shorts[i] = (short) pulse;
}
}
return shorts;
} catch (NumberFormatException e) {
throw new RFXComInvalidParameterException(parameter, pulses, e.getMessage(), e);
}
}
}

View File

@ -0,0 +1,39 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.rfxcom.internal.exceptions;
/**
* Exception for when RFXCOM messages have a value that we don't understand.
*
* @author James Hewitt-Thomas - Initial contribution
*/
public class RFXComInvalidParameterException extends RFXComException {
private static final long serialVersionUID = -2778120072474013560L;
public RFXComInvalidParameterException(String parameter, String value) {
super("Invalid value '" + value + "' for parameter " + parameter);
}
public RFXComInvalidParameterException(String parameter, String value, String reason) {
super("Invalid value '" + value + "' for parameter " + parameter + ": " + reason);
}
public RFXComInvalidParameterException(String parameter, String value, Throwable cause) {
super("Invalid value '" + value + "' for parameter " + parameter, cause);
}
public RFXComInvalidParameterException(String parameter, String value, String reason, Throwable cause) {
super("Invalid value '" + value + "' for parameter " + parameter + ": " + reason, cause);
}
}

View File

@ -0,0 +1,31 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.rfxcom.internal.exceptions;
/**
* Exception for when RFXCOM messages have a value that we don't understand.
*
* @author James Hewitt-Thomas - Initial contribution
*/
public class RFXComInvalidStateException extends RFXComException {
private static final long serialVersionUID = -2770653643474013560L;
public RFXComInvalidStateException(String channel, String state) {
super("Invalid state '" + state + "' for parameter " + channel);
}
public RFXComInvalidStateException(String channel, String state, String reason) {
super("Invalid state '" + state + "' for parameter " + channel + ": " + reason);
}
}

View File

@ -41,6 +41,7 @@ import org.openhab.binding.rfxcom.internal.messages.RFXComInterfaceMessage.Comma
import org.openhab.binding.rfxcom.internal.messages.RFXComInterfaceMessage.SubType;
import org.openhab.binding.rfxcom.internal.messages.RFXComMessage;
import org.openhab.binding.rfxcom.internal.messages.RFXComMessageFactory;
import org.openhab.binding.rfxcom.internal.messages.RFXComMessageFactoryImpl;
import org.openhab.binding.rfxcom.internal.messages.RFXComTransmitterMessage;
import org.openhab.core.io.transport.serial.SerialPortManager;
import org.openhab.core.thing.Bridge;
@ -75,6 +76,8 @@ public class RFXComBridgeHandler extends BaseBridgeHandler {
private SerialPortManager serialPortManager;
private RFXComMessageFactory messageFactory;
private class TransmitQueue {
private Queue<RFXComBaseMessage> queue = new LinkedBlockingQueue<>();
@ -116,6 +119,14 @@ public class RFXComBridgeHandler extends BaseBridgeHandler {
public RFXComBridgeHandler(@NonNull Bridge br, SerialPortManager serialPortManager) {
super(br);
this.serialPortManager = serialPortManager;
this.messageFactory = RFXComMessageFactoryImpl.INSTANCE;
}
public RFXComBridgeHandler(@NonNull Bridge br, SerialPortManager serialPortManager,
RFXComMessageFactory messageFactory) {
super(br);
this.serialPortManager = serialPortManager;
this.messageFactory = messageFactory;
}
@Override
@ -198,7 +209,7 @@ public class RFXComBridgeHandler extends BaseBridgeHandler {
connector.connect(configuration);
logger.debug("Reset controller");
connector.sendMessage(RFXComMessageFactory.CMD_RESET);
connector.sendMessage(RFXComInterfaceMessage.CMD_RESET);
// controller does not response immediately after reset,
// so wait a while
@ -207,7 +218,7 @@ public class RFXComBridgeHandler extends BaseBridgeHandler {
connector.addEventListener(eventListener);
logger.debug("Get status of controller");
connector.sendMessage(RFXComMessageFactory.CMD_GET_STATUS);
connector.sendMessage(RFXComInterfaceMessage.CMD_GET_STATUS);
}
} catch (IOException e) {
logger.error("Connection to RFXCOM transceiver failed", e);
@ -243,7 +254,7 @@ public class RFXComBridgeHandler extends BaseBridgeHandler {
@Override
public void packetReceived(byte[] packet) {
try {
RFXComMessage message = RFXComMessageFactory.createMessage(packet);
RFXComMessage message = messageFactory.createMessage(packet);
logger.debug("Message received: {}", message);
if (message instanceof RFXComInterfaceMessage) {
@ -299,7 +310,7 @@ public class RFXComBridgeHandler extends BaseBridgeHandler {
// regardless of whether it fails and the RFXCOM's buffer
// is big enough to queue up the command.
logger.debug("Start receiver");
connector.sendMessage(RFXComMessageFactory.CMD_START_RECEIVER);
connector.sendMessage(RFXComInterfaceMessage.CMD_START_RECEIVER);
}
} else if (msg.subType == SubType.START_RECEIVER) {
updateStatus(ThingStatus.ONLINE);

View File

@ -19,15 +19,22 @@ import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.rfxcom.internal.DeviceMessageListener;
import org.openhab.binding.rfxcom.internal.RFXComBindingConstants;
import org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfiguration;
import org.openhab.binding.rfxcom.internal.config.RFXComGenericDeviceConfiguration;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComInvalidParameterException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComInvalidStateException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComMessageNotImplementedException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage.PacketType;
import org.openhab.binding.rfxcom.internal.messages.RFXComDeviceMessage;
import org.openhab.binding.rfxcom.internal.messages.RFXComMessage;
import org.openhab.binding.rfxcom.internal.messages.RFXComMessageFactory;
import org.openhab.binding.rfxcom.internal.messages.RFXComMessageFactoryImpl;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
@ -58,10 +65,22 @@ public class RFXComHandler extends BaseThingHandler implements DeviceMessageList
private final Map<String, Type> stateMap = new ConcurrentHashMap<>();
private RFXComBridgeHandler bridgeHandler;
private Class<? extends RFXComDeviceConfiguration> configType;
private RFXComDeviceConfiguration config;
private RFXComMessageFactory messageFactory;
public RFXComHandler(@NonNull Thing thing) {
this(thing, RFXComMessageFactoryImpl.INSTANCE);
}
public RFXComHandler(@NonNull Thing thing, RFXComMessageFactory messageFactory) {
super(thing);
this.messageFactory = messageFactory;
configType = RFXComBindingConstants.THING_TYPE_UID_CONFIGURATION_CLASS_MAP.getOrDefault(thing.getThingTypeUID(),
RFXComGenericDeviceConfiguration.class);
}
@Override
@ -73,10 +92,10 @@ public class RFXComHandler extends BaseThingHandler implements DeviceMessageList
logger.trace("Received unsupported Refresh command");
} else {
try {
PacketType packetType = RFXComMessageFactory
PacketType packetType = RFXComMessageFactoryImpl
.convertPacketType(getThing().getThingTypeUID().getId().toUpperCase());
RFXComMessage msg = RFXComMessageFactory.createMessage(packetType);
RFXComMessage msg = messageFactory.createMessage(packetType);
msg.setConfig(config);
msg.convertFromState(channelUID.getId(), command);
@ -84,6 +103,10 @@ public class RFXComHandler extends BaseThingHandler implements DeviceMessageList
bridgeHandler.sendMessage(msg);
} catch (RFXComMessageNotImplementedException e) {
logger.error("Message not supported", e);
} catch (RFXComUnsupportedChannelException e) {
logger.error("Channel not supported", e);
} catch (RFXComInvalidStateException e) {
logger.error("Invalid state supplied for channel", e);
} catch (RFXComException e) {
logger.error("Transmitting error", e);
}
@ -94,8 +117,14 @@ public class RFXComHandler extends BaseThingHandler implements DeviceMessageList
@Override
public void initialize() {
logger.debug("Initializing thing {}", getThing().getUID());
initializeBridge((getBridge() == null) ? null : getBridge().getHandler(),
(getBridge() == null) ? null : getBridge().getStatus());
Bridge bridge = getBridge();
if (bridge == null) {
initializeBridge(null, null);
} else {
initializeBridge(bridge.getHandler(), bridge.getStatus());
}
stateMap.clear();
}
@ -103,27 +132,36 @@ public class RFXComHandler extends BaseThingHandler implements DeviceMessageList
@Override
public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
logger.debug("bridgeStatusChanged {} for thing {}", bridgeStatusInfo, getThing().getUID());
initializeBridge((getBridge() == null) ? null : getBridge().getHandler(), bridgeStatusInfo.getStatus());
Bridge bridge = getBridge();
if (bridge == null) {
initializeBridge(null, bridgeStatusInfo.getStatus());
} else {
initializeBridge(bridge.getHandler(), bridgeStatusInfo.getStatus());
}
}
private void initializeBridge(ThingHandler thingHandler, ThingStatus bridgeStatus) {
logger.debug("initializeBridge {} for thing {}", bridgeStatus, getThing().getUID());
config = getConfigAs(RFXComDeviceConfiguration.class);
if (config.deviceId == null || config.subType == null) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
"RFXCOM device missing deviceId or subType");
} else if (thingHandler != null && bridgeStatus != null) {
bridgeHandler = (RFXComBridgeHandler) thingHandler;
bridgeHandler.registerDeviceStatusListener(this);
try {
config = getConfigAs(configType);
config.parseAndValidate();
if (thingHandler != null && bridgeStatus != null) {
bridgeHandler = (RFXComBridgeHandler) thingHandler;
bridgeHandler.registerDeviceStatusListener(this);
if (bridgeStatus == ThingStatus.ONLINE) {
updateStatus(ThingStatus.ONLINE);
if (bridgeStatus == ThingStatus.ONLINE) {
updateStatus(ThingStatus.ONLINE);
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
}
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED);
}
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED);
} catch (RFXComInvalidParameterException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
}
}
@ -140,8 +178,7 @@ public class RFXComHandler extends BaseThingHandler implements DeviceMessageList
@Override
public void onDeviceMessageReceived(ThingUID bridge, RFXComDeviceMessage message) {
try {
String id = message.getDeviceId();
if (config.deviceId.equals(id)) {
if (config.matchesMessage(message)) {
String receivedId = PACKET_TYPE_THING_TYPE_UID_MAP.get(message.getPacketType()).getId();
logger.debug("Received message from bridge: {} message: {}", bridge, message);

View File

@ -15,6 +15,7 @@ package org.openhab.binding.rfxcom.internal.messages;
import static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.CHANNEL_SIGNAL_LEVEL;
import org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfiguration;
import org.openhab.binding.rfxcom.internal.config.RFXComGenericDeviceConfiguration;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
@ -41,8 +42,9 @@ abstract class RFXComDeviceMessageImpl<T> extends RFXComBaseMessage implements R
@Override
public void setConfig(RFXComDeviceConfiguration config) throws RFXComException {
this.setSubType(convertSubType(config.subType));
this.setDeviceId(config.deviceId);
RFXComGenericDeviceConfiguration genericConfig = (RFXComGenericDeviceConfiguration) config;
this.setSubType(convertSubType(genericConfig.subType));
this.setDeviceId(genericConfig.deviceId);
}
@Override
@ -67,8 +69,9 @@ abstract class RFXComDeviceMessageImpl<T> extends RFXComBaseMessage implements R
String subTypeString = convertSubType(String.valueOf(subType)).toString();
String label = getPacketType() + "-" + getDeviceId();
discoveryResultBuilder.withLabel(label).withProperty(RFXComDeviceConfiguration.DEVICE_ID_LABEL, getDeviceId())
.withProperty(RFXComDeviceConfiguration.SUB_TYPE_LABEL, subTypeString);
discoveryResultBuilder.withLabel(label)
.withProperty(RFXComGenericDeviceConfiguration.DEVICE_ID_LABEL, getDeviceId())
.withProperty(RFXComGenericDeviceConfiguration.SUB_TYPE_LABEL, subTypeString);
}
/**

View File

@ -373,4 +373,32 @@ public class RFXComInterfaceMessage extends RFXComBaseMessage {
public void convertFromState(String channelId, Type type) {
throw new UnsupportedOperationException();
}
/**
* Command to reset RFXCOM controller.
*
*/
public static final byte[] CMD_RESET = new byte[] { 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
/**
* Command to get RFXCOM controller status.
*
*/
public static final byte[] CMD_GET_STATUS = new byte[] { 0x0D, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
/**
* Command to save RFXCOM controller configuration.
*
*/
public static final byte[] CMD_SAVE = new byte[] { 0x0D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00 };
/**
* Command to start RFXCOM receiver.
*
*/
public static final byte[] CMD_START_RECEIVER = new byte[] { 0x0D, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00 };
}

View File

@ -13,10 +13,11 @@
package org.openhab.binding.rfxcom.internal.messages;
import static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfiguration.*;
import static org.openhab.binding.rfxcom.internal.config.RFXComLighting4DeviceConfiguration.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfiguration;
import org.openhab.binding.rfxcom.internal.config.RFXComLighting4DeviceConfiguration;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
@ -274,10 +275,11 @@ public class RFXComLighting4Message extends RFXComDeviceMessageImpl<RFXComLighti
@Override
public void setConfig(RFXComDeviceConfiguration config) throws RFXComException {
super.setConfig(config);
this.pulse = config.pulse != null ? config.pulse : 350;
this.onCommandId = valueOrDefault(config.onCommandId, DEFAULT_ON_COMMAND_ID);
this.offCommandId = valueOrDefault(config.offCommandId, DEFAULT_OFF_COMMAND_ID);
RFXComLighting4DeviceConfiguration lighting4Config = (RFXComLighting4DeviceConfiguration) config;
super.setConfig(lighting4Config);
this.pulse = lighting4Config.pulse != null ? lighting4Config.pulse : 350;
this.onCommandId = valueOrDefault(lighting4Config.onCommandId, DEFAULT_ON_COMMAND_ID);
this.offCommandId = valueOrDefault(lighting4Config.offCommandId, DEFAULT_OFF_COMMAND_ID);
}
private int valueOrDefault(Integer commandId, byte defaultValue) {

View File

@ -14,6 +14,7 @@ package org.openhab.binding.rfxcom.internal.messages;
import org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfiguration;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComInvalidStateException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.core.types.Type;
@ -40,8 +41,12 @@ public interface RFXComMessage {
/**
* Procedure for converting openHAB state to RFXCOM object.
*
* @throws RFXComUnsupportedChannelException If we do not support setting this channel
* @throws RFXComInvalidStateException If the state (type) is invalid for the channel
*/
void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException;
void convertFromState(String channelId, Type type)
throws RFXComUnsupportedChannelException, RFXComInvalidStateException;
/**
* Procedure to pass configuration to a message

View File

@ -12,152 +12,18 @@
*/
package org.openhab.binding.rfxcom.internal.messages;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComMessageNotImplementedException;
import org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage.PacketType;
/**
* Factory to create RFXCom messages from either bytes delivered by the RFXCom device
* or from openhab state to transmit.
*
* @author Pauli Anttila - Initial contribution
* @author James Hewitt-Thomas - Convert to interface to allow dependency injection
*/
public class RFXComMessageFactory {
public interface RFXComMessageFactory {
public RFXComMessage createMessage(PacketType packetType) throws RFXComException;
@SuppressWarnings("serial")
private static final Map<PacketType, Class<? extends RFXComMessage>> MESSAGE_CLASSES = Collections
.unmodifiableMap(new HashMap<PacketType, Class<? extends RFXComMessage>>() {
{
put(PacketType.INTERFACE_CONTROL, RFXComInterfaceControlMessage.class);
put(PacketType.INTERFACE_MESSAGE, RFXComInterfaceMessage.class);
put(PacketType.TRANSMITTER_MESSAGE, RFXComTransmitterMessage.class);
put(PacketType.UNDECODED_RF_MESSAGE, RFXComUndecodedRFMessage.class);
put(PacketType.LIGHTING1, RFXComLighting1Message.class);
put(PacketType.LIGHTING2, RFXComLighting2Message.class);
// put(PacketType.LIGHTING3, RFXComLighting3Message.class);
put(PacketType.LIGHTING4, RFXComLighting4Message.class);
put(PacketType.LIGHTING5, RFXComLighting5Message.class);
put(PacketType.LIGHTING6, RFXComLighting6Message.class);
put(PacketType.CHIME, RFXComChimeMessage.class);
put(PacketType.FAN, RFXComFanMessage.class);
// put(PacketType.FAN_SF01, RFXComFanMessage.class);
// put(PacketType.FAN_ITHO, RFXComFanMessage.class);
// put(PacketType.FAN_SEAV, RFXComFanMessage.class);
put(PacketType.FAN_LUCCI_DC, RFXComFanMessage.class);
// put(PacketType.FAN_FT1211R, RFXComFanMessage.class);
put(PacketType.FAN_FALMEC, RFXComFanMessage.class);
put(PacketType.FAN_LUCCI_DC_II, RFXComFanMessage.class);
put(PacketType.FAN_NOVY, RFXComFanMessage.class);
put(PacketType.CURTAIN1, RFXComCurtain1Message.class);
put(PacketType.BLINDS1, RFXComBlinds1Message.class);
put(PacketType.RFY, RFXComRfyMessage.class);
put(PacketType.HOME_CONFORT, RFXComHomeConfortMessage.class);
put(PacketType.SECURITY1, RFXComSecurity1Message.class);
put(PacketType.SECURITY2, RFXComSecurity2Message.class);
// put(PacketType.CAMERA1, RFXComCamera1Message.class);
// put(PacketType.REMOTE_CONTROL, RFXComRemoteControlMessage.class);
put(PacketType.THERMOSTAT1, RFXComThermostat1Message.class);
// put(PacketType.THERMOSTAT2, RFXComThermostat2Message.class);
put(PacketType.THERMOSTAT3, RFXComThermostat3Message.class);
// put(PacketType.RADIATOR1, RFXComRadiator1Message.class);
put(PacketType.BBQ, RFXComBBQTemperatureMessage.class);
put(PacketType.TEMPERATURE_RAIN, RFXComTemperatureRainMessage.class);
put(PacketType.TEMPERATURE, RFXComTemperatureMessage.class);
put(PacketType.HUMIDITY, RFXComHumidityMessage.class);
put(PacketType.TEMPERATURE_HUMIDITY, RFXComTemperatureHumidityMessage.class);
// put(PacketType.BAROMETRIC, RFXComBarometricMessage.class);
put(PacketType.TEMPERATURE_HUMIDITY_BAROMETRIC, RFXComTemperatureHumidityBarometricMessage.class);
put(PacketType.RAIN, RFXComRainMessage.class);
put(PacketType.WIND, RFXComWindMessage.class);
put(PacketType.UV, RFXComUVMessage.class);
put(PacketType.DATE_TIME, RFXComDateTimeMessage.class);
put(PacketType.CURRENT, RFXComCurrentMessage.class);
put(PacketType.ENERGY, RFXComEnergyMessage.class);
put(PacketType.CURRENT_ENERGY, RFXComCurrentEnergyMessage.class);
// put(PacketType.POWER, RFXComPowerMessage.class);
// put(PacketType.WEIGHT, RFXComWeightMessage.class);
// put(PacketType.GAS, RFXComGasMessage.class);
// put(PacketType.WATER, RFXComWaterMessage.class);
put(PacketType.RFXSENSOR, RFXComRFXSensorMessage.class);
// put(PacketType.RFXMETER, RFXComRFXMeterMessage.class);
// put(PacketType.FS20, RFXComFS20Message.class);
put(PacketType.RAW, RFXComRawMessage.class);
// put(PacketType.IO_LINES, RFXComIOLinesMessage.class);
}
});
/**
* Command to reset RFXCOM controller.
*
*/
public static final byte[] CMD_RESET = new byte[] { 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
/**
* Command to get RFXCOM controller status.
*
*/
public static final byte[] CMD_GET_STATUS = new byte[] { 0x0D, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
/**
* Command to save RFXCOM controller configuration.
*
*/
public static final byte[] CMD_SAVE = new byte[] { 0x0D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00 };
/**
* Command to start RFXCOM receiver.
*
*/
public static final byte[] CMD_START_RECEIVER = new byte[] { 0x0D, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00 };
public static RFXComMessage createMessage(PacketType packetType) throws RFXComException {
try {
Class<? extends RFXComMessage> cl = MESSAGE_CLASSES.get(packetType);
if (cl == null) {
throw new RFXComMessageNotImplementedException("Message " + packetType + " not implemented");
}
return cl.newInstance();
} catch (IllegalAccessException | InstantiationException e) {
throw new RFXComException(e);
}
}
public static RFXComMessage createMessage(byte[] packet) throws RFXComException {
PacketType packetType = ByteEnumUtil.fromByte(PacketType.class, packet[1]);
try {
Class<? extends RFXComMessage> cl = MESSAGE_CLASSES.get(packetType);
if (cl == null) {
throw new RFXComMessageNotImplementedException("Message " + packetType + " not implemented");
}
Constructor<?> c = cl.getConstructor(byte[].class);
return (RFXComMessage) c.newInstance(packet);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof RFXComException) {
throw (RFXComException) e.getCause();
} else {
throw new RFXComException(e);
}
} catch (NoSuchMethodException | IllegalAccessException | InstantiationException e) {
throw new RFXComException(e);
}
}
public static PacketType convertPacketType(String packetType) throws IllegalArgumentException {
for (PacketType p : PacketType.values()) {
if (p.toString().replace("_", "").equals(packetType.replace("_", ""))) {
return p;
}
}
throw new IllegalArgumentException("Unknown packet type " + packetType);
}
public RFXComMessage createMessage(byte[] packet) throws RFXComException;
}

View File

@ -0,0 +1,147 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.rfxcom.internal.messages;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComMessageNotImplementedException;
import org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage.PacketType;
/**
* Factory to create RFXCom messages from either bytes delivered by the RFXCom device
* or from openhab state to transmit.
*
* @author Pauli Anttila - Initial contribution
* @author James Hewitt-Thomas - Use the enum singleton pattern to allow dependency injection
*/
public enum RFXComMessageFactoryImpl implements RFXComMessageFactory {
INSTANCE();
@SuppressWarnings("serial")
private static final Map<PacketType, Class<? extends RFXComMessage>> MESSAGE_CLASSES = Collections
.unmodifiableMap(new HashMap<PacketType, Class<? extends RFXComMessage>>() {
{
put(PacketType.INTERFACE_CONTROL, RFXComInterfaceControlMessage.class);
put(PacketType.INTERFACE_MESSAGE, RFXComInterfaceMessage.class);
put(PacketType.TRANSMITTER_MESSAGE, RFXComTransmitterMessage.class);
put(PacketType.UNDECODED_RF_MESSAGE, RFXComUndecodedRFMessage.class);
put(PacketType.LIGHTING1, RFXComLighting1Message.class);
put(PacketType.LIGHTING2, RFXComLighting2Message.class);
// put(PacketType.LIGHTING3, RFXComLighting3Message.class);
put(PacketType.LIGHTING4, RFXComLighting4Message.class);
put(PacketType.LIGHTING5, RFXComLighting5Message.class);
put(PacketType.LIGHTING6, RFXComLighting6Message.class);
put(PacketType.CHIME, RFXComChimeMessage.class);
put(PacketType.FAN, RFXComFanMessage.class);
// put(PacketType.FAN_SF01, RFXComFanMessage.class);
// put(PacketType.FAN_ITHO, RFXComFanMessage.class);
// put(PacketType.FAN_SEAV, RFXComFanMessage.class);
put(PacketType.FAN_LUCCI_DC, RFXComFanMessage.class);
// put(PacketType.FAN_FT1211R, RFXComFanMessage.class);
put(PacketType.FAN_FALMEC, RFXComFanMessage.class);
put(PacketType.FAN_LUCCI_DC_II, RFXComFanMessage.class);
put(PacketType.FAN_NOVY, RFXComFanMessage.class);
put(PacketType.CURTAIN1, RFXComCurtain1Message.class);
put(PacketType.BLINDS1, RFXComBlinds1Message.class);
put(PacketType.RFY, RFXComRfyMessage.class);
put(PacketType.HOME_CONFORT, RFXComHomeConfortMessage.class);
put(PacketType.SECURITY1, RFXComSecurity1Message.class);
put(PacketType.SECURITY2, RFXComSecurity2Message.class);
// put(PacketType.CAMERA1, RFXComCamera1Message.class);
// put(PacketType.REMOTE_CONTROL, RFXComRemoteControlMessage.class);
put(PacketType.THERMOSTAT1, RFXComThermostat1Message.class);
// put(PacketType.THERMOSTAT2, RFXComThermostat2Message.class);
put(PacketType.THERMOSTAT3, RFXComThermostat3Message.class);
// put(PacketType.RADIATOR1, RFXComRadiator1Message.class);
put(PacketType.BBQ, RFXComBBQTemperatureMessage.class);
put(PacketType.TEMPERATURE_RAIN, RFXComTemperatureRainMessage.class);
put(PacketType.TEMPERATURE, RFXComTemperatureMessage.class);
put(PacketType.HUMIDITY, RFXComHumidityMessage.class);
put(PacketType.TEMPERATURE_HUMIDITY, RFXComTemperatureHumidityMessage.class);
// put(PacketType.BAROMETRIC, RFXComBarometricMessage.class);
put(PacketType.TEMPERATURE_HUMIDITY_BAROMETRIC, RFXComTemperatureHumidityBarometricMessage.class);
put(PacketType.RAIN, RFXComRainMessage.class);
put(PacketType.WIND, RFXComWindMessage.class);
put(PacketType.UV, RFXComUVMessage.class);
put(PacketType.DATE_TIME, RFXComDateTimeMessage.class);
put(PacketType.CURRENT, RFXComCurrentMessage.class);
put(PacketType.ENERGY, RFXComEnergyMessage.class);
put(PacketType.CURRENT_ENERGY, RFXComCurrentEnergyMessage.class);
// put(PacketType.POWER, RFXComPowerMessage.class);
// put(PacketType.WEIGHT, RFXComWeightMessage.class);
// put(PacketType.GAS, RFXComGasMessage.class);
// put(PacketType.WATER, RFXComWaterMessage.class);
put(PacketType.RFXSENSOR, RFXComRFXSensorMessage.class);
// put(PacketType.RFXMETER, RFXComRFXMeterMessage.class);
// put(PacketType.FS20, RFXComFS20Message.class);
put(PacketType.RAW, RFXComRawMessage.class);
// put(PacketType.IO_LINES, RFXComIOLinesMessage.class);
}
});
/**
* Create message for transmission from the packet type associated with the thing.
*/
@Override
public RFXComMessage createMessage(PacketType packetType) throws RFXComException {
try {
Class<? extends RFXComMessage> cl = MESSAGE_CLASSES.get(packetType);
if (cl == null) {
throw new RFXComMessageNotImplementedException("Message " + packetType + " not implemented");
}
return cl.getDeclaredConstructor().newInstance();
} catch (ReflectiveOperationException e) {
throw new RFXComException(e);
}
}
/**
* Create message from received bytes.
*/
@Override
public RFXComMessage createMessage(byte[] packet) throws RFXComException {
PacketType packetType = ByteEnumUtil.fromByte(PacketType.class, packet[1]);
try {
Class<? extends RFXComMessage> cl = MESSAGE_CLASSES.get(packetType);
if (cl == null) {
throw new RFXComMessageNotImplementedException("Message " + packetType + " not implemented");
}
Constructor<?> c = cl.getConstructor(byte[].class);
return (RFXComMessage) c.newInstance(packet);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof RFXComException) {
throw (RFXComException) e.getCause();
} else {
throw new RFXComException(e);
}
} catch (NoSuchMethodException | IllegalAccessException | InstantiationException e) {
throw new RFXComException(e);
}
}
public static PacketType convertPacketType(String packetType) throws IllegalArgumentException {
for (PacketType p : PacketType.values()) {
if (p.toString().replace("_", "").equals(packetType.replace("_", ""))) {
return p;
}
}
throw new IllegalArgumentException("Unknown packet type " + packetType);
}
}

View File

@ -16,12 +16,19 @@ import static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage.PacketType.RAW;
import java.nio.ByteBuffer;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfiguration;
import org.openhab.binding.rfxcom.internal.config.RFXComRawDeviceConfiguration;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComInvalidStateException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComMessageTooLongException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
@ -68,6 +75,8 @@ public class RFXComRawMessage extends RFXComDeviceMessageImpl<RFXComRawMessage.S
public byte repeat;
public short[] pulses;
private RFXComRawDeviceConfiguration config;
public RFXComRawMessage() {
super(RAW);
pulses = new short[0];
@ -114,7 +123,7 @@ public class RFXComRawMessage extends RFXComDeviceMessageImpl<RFXComRawMessage.S
data[1] = RAW.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = repeat;
data[4] = (byte) config.repeat;
ByteBuffer.wrap(data, 5, pulsesByteLen).asShortBuffer().put(pulses);
@ -126,6 +135,12 @@ public class RFXComRawMessage extends RFXComDeviceMessageImpl<RFXComRawMessage.S
return "RAW";
}
@Override
public void setConfig(RFXComDeviceConfiguration config) throws RFXComException {
super.setConfig(config);
this.config = (RFXComRawDeviceConfiguration) config;
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
@ -137,6 +152,11 @@ public class RFXComRawMessage extends RFXComDeviceMessageImpl<RFXComRawMessage.S
ByteBuffer.wrap(payload).asShortBuffer().put(pulses);
return new StringType(HexUtils.bytesToHex(payload));
case CHANNEL_PULSES:
return new StringType(IntStream.range(0, pulses.length)
.mapToObj(s -> Integer.toString(Short.toUnsignedInt(pulses[s])))
.collect(Collectors.joining(" ")));
default:
throw new RFXComUnsupportedChannelException("Nothing relevant for " + channelId);
}
@ -144,34 +164,47 @@ public class RFXComRawMessage extends RFXComDeviceMessageImpl<RFXComRawMessage.S
@Override
public void setSubType(SubType subType) {
throw new UnsupportedOperationException();
this.subType = subType;
}
@Override
public void setDeviceId(String deviceId) {
throw new UnsupportedOperationException();
// Nothing to do here
}
@Override
public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
public void convertFromState(String channelId, Type type)
throws RFXComUnsupportedChannelException, RFXComInvalidStateException {
switch (channelId) {
case CHANNEL_RAW_MESSAGE:
if (type instanceof StringType) {
// TODO: Check the raw message for validity (length, no more than 124 shorts, multiple of 4 bytes in
// payload)
throw new RFXComUnsupportedChannelException("Channel " + channelId + " inot yet implemented");
case CHANNEL_RAW_PAYLOAD:
case CHANNEL_PULSES:
throw new RFXComUnsupportedChannelException("Cannot send on channel " + channelId);
case CHANNEL_COMMAND:
if (type instanceof OnOffType) {
if (type == OnOffType.ON) {
this.pulses = config.onPulsesArray;
} else {
this.pulses = config.offPulsesArray;
}
} else if (type instanceof OpenClosedType) {
if (type == OpenClosedType.OPEN) {
this.pulses = config.openPulsesArray;
} else {
this.pulses = config.closedPulsesArray;
}
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
case CHANNEL_RAW_PAYLOAD:
if (type instanceof StringType) {
// TODO: Check the payload for validity (no more than 124 shorts, multiple of 4 bytes
throw new RFXComUnsupportedChannelException("Channel " + channelId + " not yet implemented");
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
if (this.pulses == null) {
throw new RFXComInvalidStateException(channelId, null,
"No pulses provided in the device configuration for command" + type);
}
break;
default:
throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
}

View File

@ -18,6 +18,12 @@
<description>Hexadecimal representation of payload of raw and undecoded RFXCOM messages</description>
</channel-type>
<channel-type id="pulses">
<item-type>String</item-type>
<label>Pulses</label>
<description>Decimal representation of the pulse lengths for a raw message in usec.</description>
</channel-type>
<channel-type id="command">
<item-type>Switch</item-type>
<label>Command</label>

View File

@ -18,12 +18,15 @@
<channels>
<channel id="rawMessage" typeId="rawmessage"/>
<channel id="rawPayload" typeId="rawpayload"/>
<channel id="pulses" typeId="pulses"/>
<channel id="command" typeId="command"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Raw items cannot provide a device ID, so this value is always RAW.</description>
<description>Received raw message cannot provide a device ID, so to receive raw messages the device id must be RAW.
For transmit-only things, use any device id.</description>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
@ -35,6 +38,35 @@
<option value="RAW_PACKET4">RAW_PACKET4</option>
</options>
</parameter>
<parameter name="repeat" type="integer" min="1" max="255">
<label>Repeat</label>
<description>Number of times to repeat. Defaults to 5.</description>
<default>5</default>
</parameter>
<parameter name="onPulses" type="text" required="false">
<label>On Pulses</label>
<description>Pulses to send for an ON command. Space delimited pulse lengths in usec. Must be an even number of
pulse lengths, with a maximum of 142 total pulses. Max pulse length is 65535. Pulses of value 0 will be transmitted
as 10000. See the RFXtfx user guide for more information.</description>
</parameter>
<parameter name="offPulses" type="text" required="false">
<label>Off Pulses</label>
<description>Pulses to send for an OFF command. Space delimited pulse lengths in usec. Must be an even number of
pulse lengths, with a maximum of 142 total pulses. Max pulse length is 65535. Pulses of value 0 will be transmitted
as 10000. See the RFXtfx user guide for more information.</description>
</parameter>
<parameter name="openPulses" type="text" required="false">
<label>Open Pulses</label>
<description>Pulses to send for an OPEN command. Space delimited pulse lengths in usec. Must be an even number of
pulse lengths, with a maximum of 142 total pulses. Max pulse length is 65535. Pulses of value 0 will be transmitted
as 10000. See the RFXtfx user guide for more information.</description>
</parameter>
<parameter name="closedPulses" type="text" required="false">
<label>Closed Pulses</label>
<description>Pulses to send for an CLOSED command. Space delimited pulse lengths in usec. Must be an even number of
pulse lengths, with a maximum of 142 total pulses. Max pulse length is 65535. Pulses of value 0 will be transmitted
as 10000. See the RFXtfx user guide for more information.</description>
</parameter>
</config-description>
</thing-type>

View File

@ -1,45 +0,0 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.rfxcom.internal.config;
/**
* Test helper for RFXCom-binding
*
* @author Martin van Wingerden - Initial contribution
*/
public class RFXComDeviceConfigurationBuilder {
private final RFXComDeviceConfiguration config;
public RFXComDeviceConfigurationBuilder() {
config = new RFXComDeviceConfiguration();
}
public RFXComDeviceConfigurationBuilder withDeviceId(String deviceId) {
config.deviceId = deviceId;
return this;
}
public RFXComDeviceConfigurationBuilder withSubType(String subType) {
config.subType = subType;
return this;
}
public RFXComDeviceConfigurationBuilder withPulse(Integer pulse) {
config.pulse = pulse;
return this;
}
public RFXComDeviceConfiguration build() {
return config;
}
}

View File

@ -0,0 +1,56 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.rfxcom.internal.config;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComInvalidParameterException;
/**
* Configuration class for generic devices.
*
* @author James Hewitt-Thomas - Initial contribution
*/
@ExtendWith(MockitoExtension.class)
public class RFXComGenericDeviceConfigurationTest {
private RFXComGenericDeviceConfiguration config;
@BeforeEach
public void before() {
config = new RFXComGenericDeviceConfiguration();
}
@Test
public void testNoDeviceId() {
config.subType = "PT2262";
assertThrows(RFXComInvalidParameterException.class, () -> config.parseAndValidate());
}
@Test
public void testNoSubType() {
config.deviceId = "90000";
assertThrows(RFXComInvalidParameterException.class, () -> config.parseAndValidate());
}
@Test
public void testValidConfig() {
config.deviceId = "90000";
config.subType = "PT2262";
assertDoesNotThrow(() -> config.parseAndValidate());
}
}

View File

@ -0,0 +1,43 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.rfxcom.internal.config;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
/**
* Configuration class for Lighting 4 devices.
*
* @author James Hewitt-Thomas - Initial contribution
*/
@ExtendWith(MockitoExtension.class)
public class RFXComLighting4DeviceConfigurationTest {
private RFXComLighting4DeviceConfiguration config;
@BeforeEach
public void before() {
config = new RFXComLighting4DeviceConfiguration();
config.deviceId = "90000";
config.subType = "PT2262";
}
@Test
public void testConfig() {
assertDoesNotThrow(() -> config.parseAndValidate());
}
}

View File

@ -0,0 +1,79 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.rfxcom.internal.config;
import static org.junit.jupiter.api.Assertions.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComInvalidParameterException;
/**
* Configuration class for Raw devices.
*
* @author James Hewitt-Thomas - Initial contribution
*/
@ExtendWith(MockitoExtension.class)
public class RFXComRawDeviceConfigurationTest {
private RFXComRawDeviceConfiguration config;
@BeforeEach
public void before() {
config = new RFXComRawDeviceConfiguration();
config.deviceId = "RAW";
config.subType = "RAW_PACKET1";
}
@Test
public void testConfigWithoutPulses() {
assertDoesNotThrow(() -> config.parseAndValidate());
}
@Test
public void testConfigWithUnevenPulses() {
config.onPulses = "100 200 300";
assertThrows(RFXComInvalidParameterException.class, () -> config.parseAndValidate());
}
@Test
public void testConfigWithTooManyPulses() {
String pulses = IntStream.range(1, 126).mapToObj(Integer::toString).collect(Collectors.joining(" "));
config.offPulses = pulses;
assertThrows(RFXComInvalidParameterException.class, () -> config.parseAndValidate());
}
@Test
public void testConfigWithTooLargePulse() {
config.openPulses = "100000 200000";
assertThrows(RFXComInvalidParameterException.class, () -> config.parseAndValidate());
}
@Test
public void testConfigWithNaN() {
config.closedPulses = "abc def";
assertThrows(RFXComInvalidParameterException.class, () -> config.parseAndValidate());
}
@Test
public void testConfigWithValidPulses() {
config.onPulses = "100 200 300 400";
config.offPulses = "500 600 700 800";
assertDoesNotThrow(() -> config.parseAndValidate());
}
}

View File

@ -0,0 +1,189 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.rfxcom.internal.handler;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import java.util.Map;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfiguration;
import org.openhab.binding.rfxcom.internal.config.RFXComGenericDeviceConfiguration;
import org.openhab.binding.rfxcom.internal.config.RFXComRawDeviceConfiguration;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage.PacketType;
import org.openhab.binding.rfxcom.internal.messages.RFXComDeviceMessage;
import org.openhab.binding.rfxcom.internal.messages.RFXComMessage;
import org.openhab.binding.rfxcom.internal.messages.RFXComMessageFactory;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.ThingStatusInfo;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.ThingUID;
import org.openhab.core.thing.binding.ThingHandlerCallback;
import org.openhab.core.types.Command;
/**
* The {@link RFXComRawHandler} is responsible for extra validation for Raw things.
*
* @author James Hewitt-Thomas - Initial contribution
*/
@ExtendWith(MockitoExtension.class)
public class RFXComHandlerTest {
static ThingUID bridgeUID = new ThingUID("rfxcom", "tcpbridge", "rfxtrx0");
static ThingUID thingUID = new ThingUID("rfxcom", bridgeUID, "mocked");
static ThingTypeUID thingTypeUID = new ThingTypeUID("rfxcom", "raw");
@Mock
Bridge bridge;
@Mock
RFXComBridgeHandler bridgeHandler;
@Mock
Thing thing;
@Mock
ThingHandlerCallback callback;
@Mock
RFXComMessageFactory messageFactory;
@Mock
RFXComMessage message;
@Captor
ArgumentCaptor<ThingStatusInfo> thingStatusInfoCaptor;
@Captor
ArgumentCaptor<RFXComGenericDeviceConfiguration> deviceConfigurationCaptor;
@Captor
ArgumentCaptor<RFXComDeviceMessage> deviceMessageCaptor;
RFXComHandler handler;
private void initBridge() {
when(bridge.getHandler()).thenReturn(bridgeHandler);
when(thing.getBridgeUID()).thenReturn(bridgeUID);
when(callback.getBridge(bridgeUID)).thenReturn(bridge);
}
private void initOfflineBridge() {
initBridge();
when(bridge.getStatus()).thenReturn(ThingStatus.OFFLINE);
}
private void initOnlineBridge() {
initBridge();
when(bridge.getStatus()).thenReturn(ThingStatus.ONLINE);
}
private void verifyStatusUpdated(ThingStatus status, ThingStatusDetail thingStatusDetail) {
verify(callback).statusUpdated(eq(thing), thingStatusInfoCaptor.capture());
ThingStatusInfo tsi = thingStatusInfoCaptor.getValue();
assertEquals(status, tsi.getStatus());
assertEquals(thingStatusDetail, tsi.getStatusDetail());
}
private RFXComGenericDeviceConfiguration sendMessageToGetConfig(String channel, Command command)
throws RFXComException {
when(messageFactory.createMessage(any(PacketType.class))).thenReturn(message);
ChannelUID cuid = new ChannelUID(thing.getUID(), channel);
handler.handleCommand(cuid, command);
verify(message).setConfig(deviceConfigurationCaptor.capture());
return deviceConfigurationCaptor.getValue();
}
@BeforeEach
public void before() {
when(thing.getUID()).thenReturn(thingUID);
when(thing.getThingTypeUID()).thenReturn(thingTypeUID);
handler = new RFXComHandler(thing, messageFactory);
handler.setCallback(callback);
}
@Test
public void testValidConfig() {
initOnlineBridge();
when(thing.getConfiguration()).thenReturn(new Configuration(Map.of("deviceId", "1088338.11", "subType", "AC")));
handler.initialize();
verifyStatusUpdated(ThingStatus.ONLINE, ThingStatusDetail.NONE);
}
@Test
public void testInvalidConfig() {
initOnlineBridge();
when(thing.getConfiguration()).thenReturn(new Configuration(Map.of()));
handler.initialize();
verifyStatusUpdated(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR);
}
@Test
public void testOfflineBridge() {
initOfflineBridge();
when(thing.getConfiguration()).thenReturn(new Configuration(Map.of("deviceId", "1088338.11", "subType", "AC")));
handler.initialize();
verifyStatusUpdated(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
}
@Test
public void testUnititialisedBridge() {
initBridge();
when(thing.getConfiguration())
.thenReturn(new Configuration(Map.of("deviceId", "RAW", "subType", "RAW_PACKET1")));
handler.initialize();
verifyStatusUpdated(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED);
}
@Test
public void testWithoutBridge() {
when(thing.getConfiguration()).thenReturn(new Configuration(Map.of("deviceId", "1088338.11", "subType", "AC")));
handler.initialize();
verifyStatusUpdated(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED);
}
@Test
public void testConfigType() throws RFXComException {
initOnlineBridge();
when(thing.getConfiguration()).thenReturn(
new Configuration(Map.of("deviceId", "RAW", "subType", "RAW_PACKET1", "onPulses", "1 2 3 4")));
handler.initialize();
verifyStatusUpdated(ThingStatus.ONLINE, ThingStatusDetail.NONE);
RFXComDeviceConfiguration config = sendMessageToGetConfig("command", OnOffType.ON);
assertEquals(RFXComRawDeviceConfiguration.class, config.getClass());
}
}

View File

@ -31,7 +31,8 @@ public class RFXComBBQTemperatureMessageTest {
public void testSomeMessages() throws RFXComException {
String hexMessage = "0A4E012B2955001A002179";
byte[] message = HexUtils.hexToBytes(hexMessage);
RFXComBBQTemperatureMessage msg = (RFXComBBQTemperatureMessage) RFXComMessageFactory.createMessage(message);
RFXComBBQTemperatureMessage msg = (RFXComBBQTemperatureMessage) RFXComMessageFactoryImpl.INSTANCE
.createMessage(message);
assertEquals(BBQ1, msg.subType, "SubType");
assertEquals(43, msg.seqNbr, "Seq Number");
assertEquals("10581", msg.getDeviceId(), "Sensor Id");

View File

@ -29,6 +29,6 @@ public class RFXComBarometricMessageTest {
@Test
public void checkNotImplemented() {
assertThrows(RFXComMessageNotImplementedException.class,
() -> RFXComMessageFactory.createMessage(PacketType.BAROMETRIC));
() -> RFXComMessageFactoryImpl.INSTANCE.createMessage(PacketType.BAROMETRIC));
}
}

View File

@ -30,7 +30,7 @@ import org.openhab.core.util.HexUtils;
public class RFXComBlinds1MessageTest {
private void testMessage(String hexMsg, SubType subType, int seqNbr, String deviceId, int signalLevel,
RFXComBlinds1Message.Commands command) throws RFXComException {
final RFXComBlinds1Message msg = (RFXComBlinds1Message) RFXComMessageFactory
final RFXComBlinds1Message msg = (RFXComBlinds1Message) RFXComMessageFactoryImpl.INSTANCE
.createMessage(HexUtils.hexToBytes(hexMsg));
assertEquals(subType, msg.subType, "SubType");
assertEquals(seqNbr, (short) (msg.seqNbr & 0xFF), "Seq Number");

View File

@ -29,6 +29,6 @@ public class RFXComCamera1MessageTest {
@Test
public void checkNotImplemented() {
assertThrows(RFXComMessageNotImplementedException.class,
() -> RFXComMessageFactory.createMessage(PacketType.CAMERA1));
() -> RFXComMessageFactoryImpl.INSTANCE.createMessage(PacketType.CAMERA1));
}
}

View File

@ -33,7 +33,7 @@ public class RFXComChimeMessageTest {
public void testSomeMessages() throws RFXComException {
String hexMessage = "0716020900A1F350";
byte[] message = HexUtils.hexToBytes(hexMessage);
RFXComChimeMessage msg = (RFXComChimeMessage) RFXComMessageFactory.createMessage(message);
RFXComChimeMessage msg = (RFXComChimeMessage) RFXComMessageFactoryImpl.INSTANCE.createMessage(message);
assertEquals(SubType.SELECTPLUS, msg.subType, "SubType");
assertEquals(9, msg.seqNbr, "Seq Number");
assertEquals("41459", msg.getDeviceId(), "Sensor Id");

View File

@ -29,7 +29,7 @@ public class RFXComCurrentEnergyMessageTest {
private void testMessage(String hexMsg, RFXComCurrentEnergyMessage.SubType subType, int seqNbr, String deviceId,
int count, double channel1, double channel2, double channel3, double totalUsage, int signalLevel,
int batteryLevel) throws RFXComException {
final RFXComCurrentEnergyMessage msg = (RFXComCurrentEnergyMessage) RFXComMessageFactory
final RFXComCurrentEnergyMessage msg = (RFXComCurrentEnergyMessage) RFXComMessageFactoryImpl.INSTANCE
.createMessage(HexUtils.hexToBytes(hexMsg));
assertEquals(subType, msg.subType, "SubType");
assertEquals(seqNbr, (short) (msg.seqNbr & 0xFF), "Seq Number");

View File

@ -32,7 +32,7 @@ public class RFXComCurrentMessageTest {
public void testSomeMessages() throws RFXComException {
String message = "0D59010F860004001D0000000049";
final RFXComCurrentMessage msg = (RFXComCurrentMessage) RFXComMessageFactory
final RFXComCurrentMessage msg = (RFXComCurrentMessage) RFXComMessageFactoryImpl.INSTANCE
.createMessage(HexUtils.hexToBytes(message));
assertEquals(SubType.ELEC1, msg.subType, "SubType");
assertEquals(15, (short) (msg.seqNbr & 0xFF), "Seq Number");

View File

@ -27,12 +27,13 @@ import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
public class RFXComCurtain1MessageTest {
@Test
public void checkForSupportTest() throws RFXComException {
RFXComMessageFactory.createMessage(CURTAIN1);
RFXComMessageFactoryImpl.INSTANCE.createMessage(CURTAIN1);
}
@Test
public void basicBoundaryCheck() throws RFXComException {
RFXComCurtain1Message message = (RFXComCurtain1Message) RFXComMessageFactory.createMessage(CURTAIN1);
RFXComCurtain1Message message = (RFXComCurtain1Message) RFXComMessageFactoryImpl.INSTANCE
.createMessage(CURTAIN1);
message.subType = RFXComCurtain1Message.SubType.HARRISON;
message.command = RFXComCurtain1Message.Commands.OPEN;

View File

@ -32,7 +32,7 @@ public class RFXComDateTimeMessageTest {
public void testSomeMessages() throws RFXComException {
String hexMessage = "0D580117B90003041D030D150A69";
byte[] message = HexUtils.hexToBytes(hexMessage);
RFXComDateTimeMessage msg = (RFXComDateTimeMessage) RFXComMessageFactory.createMessage(message);
RFXComDateTimeMessage msg = (RFXComDateTimeMessage) RFXComMessageFactoryImpl.INSTANCE.createMessage(message);
assertEquals(RFXComDateTimeMessage.SubType.RTGR328N, msg.subType, "SubType");
assertEquals(23, (short) (msg.seqNbr & 0xFF), "Seq Number");
assertEquals("47360", msg.getDeviceId(), "Sensor Id");

View File

@ -28,6 +28,7 @@ import org.openhab.binding.rfxcom.internal.exceptions.RFXComMessageNotImplemente
public class RFXComEdisioTest {
@Test
public void checkNotImplemented() {
assertThrows(RFXComMessageNotImplementedException.class, () -> RFXComMessageFactory.createMessage(EDISIO));
assertThrows(RFXComMessageNotImplementedException.class,
() -> RFXComMessageFactoryImpl.INSTANCE.createMessage(EDISIO));
}
}

View File

@ -31,7 +31,7 @@ public class RFXComEnergyMessageTest {
public void testSomeMessages() throws RFXComException {
String hexMessage = "115A01071A7300000003F600000000350B89";
byte[] message = HexUtils.hexToBytes(hexMessage);
RFXComEnergyMessage msg = (RFXComEnergyMessage) RFXComMessageFactory.createMessage(message);
RFXComEnergyMessage msg = (RFXComEnergyMessage) RFXComMessageFactoryImpl.INSTANCE.createMessage(message);
assertEquals(ELEC2, msg.subType, "SubType");
assertEquals(7, msg.seqNbr, "Seq Number");
assertEquals("6771", msg.getDeviceId(), "Sensor Id");

View File

@ -30,6 +30,6 @@ public class RFXComFS20MessageTest {
@Test
public void checkNotImplemented() {
assertThrows(RFXComMessageNotImplementedException.class,
() -> RFXComMessageFactory.createMessage(PacketType.FS20));
() -> RFXComMessageFactoryImpl.INSTANCE.createMessage(PacketType.FS20));
}
}

View File

@ -38,12 +38,12 @@ public class RFXComFanMessageTest {
@Test
public void checkForSupportTest() throws RFXComException {
RFXComMessageFactory.createMessage(FAN);
RFXComMessageFactoryImpl.INSTANCE.createMessage(FAN);
}
@Test
public void basicBoundaryCheck() throws RFXComException {
RFXComFanMessage message = (RFXComFanMessage) RFXComMessageFactory.createMessage(FAN);
RFXComFanMessage message = (RFXComFanMessage) RFXComMessageFactoryImpl.INSTANCE.createMessage(FAN);
message.setSubType(RFXComFanMessage.SubType.CASAFAN);
message.convertFromState(CHANNEL_FAN_SPEED, StringType.valueOf("OFF"));
@ -54,7 +54,8 @@ public class RFXComFanMessageTest {
private void testMessage(String hexMsg, int seqNbr, String deviceId, int signalLevel,
@Nullable State expectedCommand, State expectedLightCommand, @Nullable State expectedFanSpeed,
RFXComBaseMessage.PacketType packetType) throws RFXComException {
final RFXComFanMessage msg = (RFXComFanMessage) RFXComMessageFactory.createMessage(HexUtils.hexToBytes(hexMsg));
final RFXComFanMessage msg = (RFXComFanMessage) RFXComMessageFactoryImpl.INSTANCE
.createMessage(HexUtils.hexToBytes(hexMsg));
assertEquals(seqNbr, (short) (msg.seqNbr & 0xFF), "Seq Number");
assertEquals(deviceId, msg.getDeviceId(), "Sensor Id");
assertEquals(signalLevel, msg.signalLevel, "Signal Level");

View File

@ -30,6 +30,6 @@ public class RFXComGasMessageTest {
@Test
public void checkNotImplemented() {
assertThrows(RFXComMessageNotImplementedException.class,
() -> RFXComMessageFactory.createMessage(PacketType.GAS));
() -> RFXComMessageFactoryImpl.INSTANCE.createMessage(PacketType.GAS));
}
}

View File

@ -12,7 +12,7 @@
*/
package org.openhab.binding.rfxcom.internal.messages;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage.PacketType.HOME_CONFORT;
import org.eclipse.jdt.annotation.NonNullByDefault;
@ -31,7 +31,8 @@ import org.openhab.core.util.HexUtils;
@NonNullByDefault
public class RFXComHomeConfortTest {
private void testMessage(SubType subType, Commands command, String deviceId, String data) throws RFXComException {
RFXComHomeConfortMessage message = (RFXComHomeConfortMessage) RFXComMessageFactory.createMessage(HOME_CONFORT);
RFXComHomeConfortMessage message = (RFXComHomeConfortMessage) RFXComMessageFactoryImpl.INSTANCE
.createMessage(HOME_CONFORT);
message.setSubType(subType);
message.command = command;
message.setDeviceId(deviceId);

View File

@ -31,7 +31,7 @@ public class RFXComHumidityMessageTest {
public void testSomeMessages() throws RFXComException {
String hexMessage = "085101027700360189";
byte[] message = HexUtils.hexToBytes(hexMessage);
RFXComHumidityMessage msg = (RFXComHumidityMessage) RFXComMessageFactory.createMessage(message);
RFXComHumidityMessage msg = (RFXComHumidityMessage) RFXComMessageFactoryImpl.INSTANCE.createMessage(message);
assertEquals(RFXComHumidityMessage.SubType.HUM1, msg.subType, "SubType");
assertEquals(2, (short) (msg.seqNbr & 0xFF), "Seq Number");
assertEquals("30464", msg.getDeviceId(), "Sensor Id");

View File

@ -30,6 +30,6 @@ public class RFXComIOLinesMessageTest {
@Test
public void checkNotImplemented() {
assertThrows(RFXComMessageNotImplementedException.class,
() -> RFXComMessageFactory.createMessage(PacketType.IO_LINES));
() -> RFXComMessageFactoryImpl.INSTANCE.createMessage(PacketType.IO_LINES));
}
}

View File

@ -32,7 +32,7 @@ import org.openhab.core.util.HexUtils;
public class RFXComInterfaceMessageTest {
private RFXComInterfaceMessage testMessage(String hexMsg, SubType subType, int seqNbr, Commands command)
throws RFXComException {
RFXComInterfaceMessage msg = (RFXComInterfaceMessage) RFXComMessageFactory
RFXComInterfaceMessage msg = (RFXComInterfaceMessage) RFXComMessageFactoryImpl.INSTANCE
.createMessage(HexUtils.hexToBytes(hexMsg));
assertEquals(subType, msg.subType, "SubType");
assertEquals(seqNbr, (short) (msg.seqNbr & 0xFF), "Seq Number");

View File

@ -30,6 +30,7 @@ public class RFXComInvalidMessageTypeTest {
@Test
public void testMessage() {
byte[] message = HexUtils.hexToBytes("07CC01271356ECC0");
assertThrows(RFXComUnsupportedValueException.class, () -> RFXComMessageFactory.createMessage(message));
assertThrows(RFXComUnsupportedValueException.class,
() -> RFXComMessageFactoryImpl.INSTANCE.createMessage(message));
}
}

View File

@ -36,7 +36,7 @@ public class RFXComLighting1MessageTest {
private void testMessage(String hexMsg, RFXComLighting1Message.SubType subType, int seqNbr, String deviceId,
byte signalLevel, Commands command, String commandString) throws RFXComException {
final RFXComLighting1Message msg = (RFXComLighting1Message) RFXComMessageFactory
final RFXComLighting1Message msg = (RFXComLighting1Message) RFXComMessageFactoryImpl.INSTANCE
.createMessage(HexUtils.hexToBytes(hexMsg));
assertEquals(subType, msg.subType, "SubType");
assertEquals(seqNbr, (short) (msg.seqNbr & 0xFF), "Seq Number");

View File

@ -31,7 +31,7 @@ public class RFXComLighting2MessageTest {
public void testSomeMessages() throws RFXComException {
String hexMessage = "0B11000600109B520B000080";
byte[] message = HexUtils.hexToBytes(hexMessage);
RFXComLighting2Message msg = (RFXComLighting2Message) RFXComMessageFactory.createMessage(message);
RFXComLighting2Message msg = (RFXComLighting2Message) RFXComMessageFactoryImpl.INSTANCE.createMessage(message);
assertEquals(RFXComLighting2Message.SubType.AC, msg.subType, "SubType");
assertEquals(6, (short) (msg.seqNbr & 0xFF), "Seq Number");
assertEquals("1088338.11", msg.getDeviceId(), "Sensor Id");

View File

@ -31,6 +31,6 @@ public class RFXComLighting3MessageTest {
public void checkNotImplemented() {
// TODO Note that this message is supported in the 1.9 binding
assertThrows(RFXComMessageNotImplementedException.class,
() -> RFXComMessageFactory.createMessage(PacketType.LIGHTING3));
() -> RFXComMessageFactoryImpl.INSTANCE.createMessage(PacketType.LIGHTING3));
}
}

View File

@ -24,8 +24,7 @@ import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.junit.jupiter.api.Test;
import org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfiguration;
import org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfigurationBuilder;
import org.openhab.binding.rfxcom.internal.config.RFXComLighting4DeviceConfiguration;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.util.HexUtils;
@ -39,15 +38,19 @@ import org.openhab.core.util.HexUtils;
public class RFXComLighting4MessageTest {
@Test
public void basicBoundaryCheck() throws RFXComException {
RFXComLighting4Message message = (RFXComLighting4Message) RFXComMessageFactory.createMessage(LIGHTING4);
RFXComLighting4Message message = (RFXComLighting4Message) RFXComMessageFactoryImpl.INSTANCE
.createMessage(LIGHTING4);
RFXComDeviceConfiguration build = new RFXComDeviceConfigurationBuilder().withDeviceId("90000").withPulse(300)
.withSubType("PT2262").build();
message.setConfig(build);
RFXComLighting4DeviceConfiguration config = new RFXComLighting4DeviceConfiguration();
config.deviceId = "90000";
config.subType = "PT2262";
config.pulse = 300;
message.setConfig(config);
message.convertFromState(CHANNEL_COMMAND, OnOffType.ON);
byte[] binaryMessage = message.decodeMessage();
RFXComLighting4Message msg = (RFXComLighting4Message) RFXComMessageFactory.createMessage(binaryMessage);
RFXComLighting4Message msg = (RFXComLighting4Message) RFXComMessageFactoryImpl.INSTANCE
.createMessage(binaryMessage);
assertEquals("90000", msg.getDeviceId(), "Sensor Id");
}
@ -61,7 +64,7 @@ public class RFXComLighting4MessageTest {
private void testMessage(String hexMsg, RFXComLighting4Message.SubType subType, String deviceId,
@Nullable Integer pulse, byte commandByte, @Nullable Integer seqNbr, int signalLevel, int offCommand,
int onCommand) throws RFXComException {
RFXComLighting4Message msg = (RFXComLighting4Message) RFXComMessageFactory
RFXComLighting4Message msg = (RFXComLighting4Message) RFXComMessageFactoryImpl.INSTANCE
.createMessage(HexUtils.hexToBytes(hexMsg));
assertEquals(deviceId, msg.getDeviceId(), "Sensor Id");
assertEquals(commandByte, RFXComTestHelper.getActualIntValue(msg, CHANNEL_COMMAND_ID), "Command");

View File

@ -37,14 +37,15 @@ public class RFXComLighting5MessageTest {
@Test
public void convertFromStateItMessage() throws RFXComException {
RFXComDeviceMessage itMessageObject = (RFXComDeviceMessage) RFXComMessageFactory.createMessage(LIGHTING5);
RFXComDeviceMessage itMessageObject = (RFXComDeviceMessage) RFXComMessageFactoryImpl.INSTANCE
.createMessage(LIGHTING5);
itMessageObject.setDeviceId("2061.1");
itMessageObject.setSubType(IT);
itMessageObject.convertFromState(CHANNEL_COMMAND, OnOffType.ON);
byte[] message = itMessageObject.decodeMessage();
String hexMessage = HexUtils.bytesToHex(message);
assertEquals("0A140F0000080D01010000", hexMessage, "Message is not as expected");
RFXComLighting5Message msg = (RFXComLighting5Message) RFXComMessageFactory.createMessage(message);
RFXComLighting5Message msg = (RFXComLighting5Message) RFXComMessageFactoryImpl.INSTANCE.createMessage(message);
assertEquals(IT, msg.subType, "SubType");
assertEquals("2061.1", msg.getDeviceId(), "Sensor Id");
assertEquals(ON, msg.command, "Command");
@ -52,7 +53,8 @@ public class RFXComLighting5MessageTest {
@Test
public void basicBoundaryCheck() throws RFXComException {
RFXComLighting5Message message = (RFXComLighting5Message) RFXComMessageFactory.createMessage(LIGHTING5);
RFXComLighting5Message message = (RFXComLighting5Message) RFXComMessageFactoryImpl.INSTANCE
.createMessage(LIGHTING5);
message.subType = RFXComLighting5Message.SubType.LIGHTWAVERF;
message.command = ON;

View File

@ -31,7 +31,7 @@ public class RFXComLighting6MessageTest {
public void testSomeMessages() throws RFXComException {
String hexMessage = "0B150005D950450101011D80";
byte[] message = HexUtils.hexToBytes(hexMessage);
RFXComLighting6Message msg = (RFXComLighting6Message) RFXComMessageFactory.createMessage(message);
RFXComLighting6Message msg = (RFXComLighting6Message) RFXComMessageFactoryImpl.INSTANCE.createMessage(message);
assertEquals(RFXComLighting6Message.SubType.BLYSS, msg.subType, "SubType");
assertEquals(5, (short) (msg.seqNbr & 0xFF), "Seq Number");
assertEquals("55632.E.1", msg.getDeviceId(), "Sensor Id");

View File

@ -29,6 +29,6 @@ public class RFXComPowerMessageTest {
public void checkNotImplemented() {
// TODO Note that this message is supported in the 1.9 binding
assertThrows(RFXComMessageNotImplementedException.class,
() -> RFXComMessageFactory.createMessage(RFXComBaseMessage.PacketType.POWER));
() -> RFXComMessageFactoryImpl.INSTANCE.createMessage(RFXComBaseMessage.PacketType.POWER));
}
}

View File

@ -30,6 +30,6 @@ public class RFXComRFXMeterMessageTest {
@Test
public void checkNotImplemented() {
assertThrows(RFXComMessageNotImplementedException.class,
() -> RFXComMessageFactory.createMessage(PacketType.RFXMETER));
() -> RFXComMessageFactoryImpl.INSTANCE.createMessage(PacketType.RFXMETER));
}
}

View File

@ -39,7 +39,7 @@ public class RFXComRFXSensorMessageTest {
@Nullable Double temperature, @Nullable Double voltage, @Nullable Double referenceVoltage,
@Nullable Double expectedPressure, @Nullable Double expectedHumidity, int signalLevel,
DeviceState deviceState) throws RFXComException {
final RFXComRFXSensorMessage msg = (RFXComRFXSensorMessage) RFXComMessageFactory
final RFXComRFXSensorMessage msg = (RFXComRFXSensorMessage) RFXComMessageFactoryImpl.INSTANCE
.createMessage(DatatypeConverter.parseHexBinary(hexMsg));
assertEquals(subType, msg.subType, "SubType");
assertEquals(seqNbr, (short) (msg.seqNbr & 0xFF), "Seq Number");

View File

@ -28,6 +28,7 @@ import org.openhab.binding.rfxcom.internal.exceptions.RFXComMessageNotImplemente
public class RFXComRadiator1MessageTest {
@Test
public void checkNotImplemented() {
assertThrows(RFXComMessageNotImplementedException.class, () -> RFXComMessageFactory.createMessage(RADIATOR1));
assertThrows(RFXComMessageNotImplementedException.class,
() -> RFXComMessageFactoryImpl.INSTANCE.createMessage(RADIATOR1));
}
}

View File

@ -32,7 +32,7 @@ public class RFXComRainMessageTest {
public void testSomeMessages() throws RFXComException {
String hexMessage = "0B550217B6000000004D3C69";
byte[] message = HexUtils.hexToBytes(hexMessage);
RFXComRainMessage msg = (RFXComRainMessage) RFXComMessageFactory.createMessage(message);
RFXComRainMessage msg = (RFXComRainMessage) RFXComMessageFactoryImpl.INSTANCE.createMessage(message);
assertEquals(RAIN2, msg.subType, "SubType");
assertEquals(23, msg.seqNbr, "Seq Number");
assertEquals("46592", msg.getDeviceId(), "Sensor Id");

View File

@ -18,9 +18,13 @@ import java.nio.ByteBuffer;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.Test;
import org.openhab.binding.rfxcom.internal.RFXComBindingConstants;
import org.openhab.binding.rfxcom.internal.config.RFXComRawDeviceConfiguration;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComMessageTooLongException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComInvalidStateException;
import org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage.PacketType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.types.Type;
import org.openhab.core.util.HexUtils;
/**
@ -31,9 +35,10 @@ import org.openhab.core.util.HexUtils;
@NonNullByDefault
public class RFXComRawMessageTest {
private void testMessage(String hexMsg, RFXComRawMessage.SubType subType, int seqNbr, int repeat, String pulses)
private void testMessageRx(String hexMsg, RFXComRawMessage.SubType subType, int seqNbr, int repeat, String pulses)
throws RFXComException {
final RFXComRawMessage msg = (RFXComRawMessage) RFXComMessageFactory.createMessage(HexUtils.hexToBytes(hexMsg));
final RFXComRawMessage msg = (RFXComRawMessage) RFXComMessageFactoryImpl.INSTANCE
.createMessage(HexUtils.hexToBytes(hexMsg));
assertEquals(subType, msg.subType, "SubType");
assertEquals(seqNbr, (short) (msg.seqNbr & 0xFF), "Seq Number");
assertEquals("RAW", msg.getDeviceId(), "Device Id");
@ -41,25 +46,43 @@ public class RFXComRawMessageTest {
byte[] payload = new byte[msg.pulses.length * 2];
ByteBuffer.wrap(payload).asShortBuffer().put(msg.pulses);
assertEquals(pulses, HexUtils.bytesToHex(payload), "Pulses");
}
@Test
public void testSomeRxMessages() throws RFXComException {
testMessageRx("087F0027051356ECC0", RFXComRawMessage.SubType.RAW_PACKET1, 0x27, 5, "1356ECC0");
}
private void testMessageTx(RFXComRawDeviceConfiguration config, Type command, String hexMsg)
throws RFXComException {
RFXComRawMessage msg = (RFXComRawMessage) RFXComMessageFactoryImpl.INSTANCE.createMessage(PacketType.RAW);
msg.setConfig(config);
msg.convertFromState(RFXComBindingConstants.CHANNEL_COMMAND, command);
byte[] decoded = msg.decodeMessage();
assertEquals(hexMsg, HexUtils.bytesToHex(decoded), "Message converted back");
assertEquals(hexMsg, HexUtils.bytesToHex(decoded), "Transmitted message");
}
@Test
public void testSomeMessages() throws RFXComException {
testMessage("087F0027051356ECC0", RFXComRawMessage.SubType.RAW_PACKET1, 0x27, 5, "1356ECC0");
public void testTxBasicPulses() throws RFXComException {
RFXComRawDeviceConfiguration config = new RFXComRawDeviceConfiguration();
config.deviceId = "RAW";
config.subType = "RAW_PACKET1";
config.repeat = 5;
config.onPulsesArray = new short[] { 0x10, 0x20, 0x30, 0x40 };
testMessageTx(config, OnOffType.ON, "0C7F0000050010002000300040");
}
@Test
public void testLongMessage() throws RFXComException {
RFXComRawMessage msg = (RFXComRawMessage) RFXComMessageFactory.createMessage(PacketType.RAW);
msg.subType = RFXComRawMessage.SubType.RAW_PACKET1;
msg.seqNbr = 1;
msg.repeat = 5;
msg.pulses = new short[125];
public void testTxMissingPulses() throws RFXComException {
RFXComRawDeviceConfiguration config = new RFXComRawDeviceConfiguration();
config.deviceId = "RAW";
config.subType = "RAW_PACKET1";
config.repeat = 5;
config.onPulsesArray = new short[] { 0x10, 0x20, 0x30, 0x40 };
assertThrows(RFXComMessageTooLongException.class, () -> msg.decodeMessage());
assertThrows(RFXComInvalidStateException.class,
() -> testMessageTx(config, OnOffType.OFF, "0C7F0000050010002000300040"));
}
}

View File

@ -29,6 +29,6 @@ public class RFXComRemoteControlMessageTest {
@Test
public void checkNotImplemented() {
assertThrows(RFXComMessageNotImplementedException.class,
() -> RFXComMessageFactory.createMessage(PacketType.REMOTE_CONTROL));
() -> RFXComMessageFactoryImpl.INSTANCE.createMessage(PacketType.REMOTE_CONTROL));
}
}

View File

@ -12,7 +12,7 @@
*/
package org.openhab.binding.rfxcom.internal.messages;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage.PacketType.RFY;
import org.eclipse.jdt.annotation.NonNullByDefault;
@ -32,7 +32,7 @@ public class RFXComRfyMessageTest {
@Test
public void basicBoundaryCheck() throws RFXComException {
RFXComRfyMessage message = (RFXComRfyMessage) RFXComMessageFactory.createMessage(RFY);
RFXComRfyMessage message = (RFXComRfyMessage) RFXComMessageFactoryImpl.INSTANCE.createMessage(RFY);
message.subType = SubType.RFY;
message.command = Commands.UP;
@ -41,7 +41,7 @@ public class RFXComRfyMessageTest {
}
private void testMessage(SubType subType, Commands command, String deviceId, String data) throws RFXComException {
RFXComRfyMessage message = (RFXComRfyMessage) RFXComMessageFactory.createMessage(RFY);
RFXComRfyMessage message = (RFXComRfyMessage) RFXComMessageFactoryImpl.INSTANCE.createMessage(RFY);
message.setSubType(subType);
message.command = command;
message.setDeviceId(deviceId);

View File

@ -37,7 +37,7 @@ public class RFXComSecurity1MessageTest {
@Nullable String deviceId, int batteryLevel, @Nullable Contact contact, @Nullable Motion motion,
@Nullable Status status, int signalLevel) throws RFXComException {
byte[] message = HexUtils.hexToBytes(hexMessage);
RFXComSecurity1Message msg = (RFXComSecurity1Message) RFXComMessageFactory.createMessage(message);
RFXComSecurity1Message msg = (RFXComSecurity1Message) RFXComMessageFactoryImpl.INSTANCE.createMessage(message);
assertEquals(subType, msg.subType, "SubType");
assertEquals(sequenceNumber, (short) (msg.seqNbr & 0xFF), "Seq Number");
assertEquals(deviceId, msg.getDeviceId(), "Sensor Id");

View File

@ -34,7 +34,7 @@ public class RFXComSecurity2MessageTest {
String hexMessage = "1C21020000000000131211C30000000000000000000000000000000045";
byte[] message = HexUtils.hexToBytes(hexMessage);
RFXComSecurity2Message msg = (RFXComSecurity2Message) RFXComMessageFactory.createMessage(message);
RFXComSecurity2Message msg = (RFXComSecurity2Message) RFXComMessageFactoryImpl.INSTANCE.createMessage(message);
assertEquals(SubType.RAW_AES_KEELOQ, msg.subType, "SubType");
assertEquals(0, msg.seqNbr, "Seq Number");
assertEquals("51450387", msg.getDeviceId(), "Sensor Id");

View File

@ -34,7 +34,7 @@ public class RFXComTemperatureHumidityBarometricMessageTest {
public void testSomeMessages() throws RFXComException {
String hexMessage = "0D54020EE90000C9270203E70439";
byte[] message = HexUtils.hexToBytes(hexMessage);
RFXComTemperatureHumidityBarometricMessage msg = (RFXComTemperatureHumidityBarometricMessage) RFXComMessageFactory
RFXComTemperatureHumidityBarometricMessage msg = (RFXComTemperatureHumidityBarometricMessage) RFXComMessageFactoryImpl.INSTANCE
.createMessage(message);
assertEquals(THB2, msg.subType, "SubType");
assertEquals(14, msg.seqNbr, "Seq Number");

View File

@ -35,7 +35,7 @@ public class RFXComTemperatureHumidityMessageTest {
double temperature, int humidity, HumidityStatus humidityStatus, int signalLevel, int batteryLevel)
throws RFXComException {
byte[] binaryMessage = HexUtils.hexToBytes(hexMsg);
final RFXComTemperatureHumidityMessage msg = (RFXComTemperatureHumidityMessage) RFXComMessageFactory
final RFXComTemperatureHumidityMessage msg = (RFXComTemperatureHumidityMessage) RFXComMessageFactoryImpl.INSTANCE
.createMessage(binaryMessage);
assertEquals(subType, msg.subType, "SubType");
assertEquals(seqNbr, (short) (msg.seqNbr & 0xFF), "Seq Number");

View File

@ -29,7 +29,7 @@ import org.openhab.core.util.HexUtils;
public class RFXComTemperatureMessageTest {
private void testMessage(String hexMsg, RFXComTemperatureMessage.SubType subType, int seqNbr, String deviceId,
double temperature, int signalLevel, int bateryLevel) throws RFXComException {
final RFXComTemperatureMessage msg = (RFXComTemperatureMessage) RFXComMessageFactory
final RFXComTemperatureMessage msg = (RFXComTemperatureMessage) RFXComMessageFactoryImpl.INSTANCE
.createMessage(HexUtils.hexToBytes(hexMsg));
assertEquals(subType, msg.subType, "SubType");
assertEquals(seqNbr, (short) (msg.seqNbr & 0xFF), "Seq Number");

View File

@ -31,7 +31,8 @@ public class RFXComTemperatureRainMessageTest {
public void testSomeMessages() throws RFXComException {
String hexMessage = "0A4F01CCF001004F03B759";
byte[] message = HexUtils.hexToBytes(hexMessage);
RFXComTemperatureRainMessage msg = (RFXComTemperatureRainMessage) RFXComMessageFactory.createMessage(message);
RFXComTemperatureRainMessage msg = (RFXComTemperatureRainMessage) RFXComMessageFactoryImpl.INSTANCE
.createMessage(message);
assertEquals(WS1200, msg.subType, "SubType");
assertEquals(204, (short) (msg.seqNbr & 0xFF), "Seq Number");
assertEquals("61441", msg.getDeviceId(), "Sensor Id");

View File

@ -31,7 +31,8 @@ public class RFXComThermostat1MessageTest {
public void testSomeMessages() throws RFXComException {
String hexMessage = "0940001B6B1816150270";
byte[] message = HexUtils.hexToBytes(hexMessage);
RFXComThermostat1Message msg = (RFXComThermostat1Message) RFXComMessageFactory.createMessage(message);
RFXComThermostat1Message msg = (RFXComThermostat1Message) RFXComMessageFactoryImpl.INSTANCE
.createMessage(message);
assertEquals(RFXComThermostat1Message.SubType.DIGIMAX, msg.subType, "SubType");
assertEquals(27, (short) (msg.seqNbr & 0xFF), "Seq Number");
assertEquals("27416", msg.getDeviceId(), "Sensor Id");

View File

@ -30,6 +30,6 @@ public class RFXComThermostat2MessageTest {
public void checkNotImplemented() {
// TODO Note that this message is supported in the 1.9 binding
assertThrows(RFXComMessageNotImplementedException.class,
() -> RFXComMessageFactory.createMessage(PacketType.THERMOSTAT2));
() -> RFXComMessageFactoryImpl.INSTANCE.createMessage(PacketType.THERMOSTAT2));
}
}

View File

@ -41,12 +41,13 @@ public class RFXComThermostat3MessageTest {
@Test
public void checkForSupportTest() throws RFXComException {
RFXComMessageFactory.createMessage(THERMOSTAT3);
RFXComMessageFactoryImpl.INSTANCE.createMessage(THERMOSTAT3);
}
@Test
public void basicBoundaryCheck() throws RFXComException {
RFXComThermostat3Message message = (RFXComThermostat3Message) RFXComMessageFactory.createMessage(THERMOSTAT3);
RFXComThermostat3Message message = (RFXComThermostat3Message) RFXComMessageFactoryImpl.INSTANCE
.createMessage(THERMOSTAT3);
message.subType = RFXComThermostat3Message.SubType.MERTIK__G6R_H4S_TRANSMIT_ONLY;
message.command = RFXComThermostat3Message.Commands.ON;
@ -68,7 +69,8 @@ public class RFXComThermostat3MessageTest {
@Nullable State secondCommandChannel, State controlChannel, State commandStringChannel)
throws RFXComException {
byte[] message = HexUtils.hexToBytes(hexMessage);
RFXComThermostat3Message msg = (RFXComThermostat3Message) RFXComMessageFactory.createMessage(message);
RFXComThermostat3Message msg = (RFXComThermostat3Message) RFXComMessageFactoryImpl.INSTANCE
.createMessage(message);
assertEquals(subtype, msg.subType, "SubType");
assertEquals(sequenceNumber, (short) (msg.seqNbr & 0xFF), "Seq Number");
assertEquals(sensorId, msg.getDeviceId(), "Sensor Id");

View File

@ -28,6 +28,7 @@ import org.openhab.binding.rfxcom.internal.exceptions.RFXComMessageNotImplemente
public class RFXComThermostat4MessageTest {
@Test
public void checkNotImplemented() {
assertThrows(RFXComMessageNotImplementedException.class, () -> RFXComMessageFactory.createMessage(THERMOSTAT4));
assertThrows(RFXComMessageNotImplementedException.class,
() -> RFXComMessageFactoryImpl.INSTANCE.createMessage(THERMOSTAT4));
}
}

View File

@ -31,7 +31,7 @@ import org.openhab.core.util.HexUtils;
@NonNullByDefault
public class RFXComTransmitterMessageTest {
private void testMessage(String hexMsg, Response response, SubType subType, int seqNbr) throws RFXComException {
final RFXComTransmitterMessage msg = (RFXComTransmitterMessage) RFXComMessageFactory
final RFXComTransmitterMessage msg = (RFXComTransmitterMessage) RFXComMessageFactoryImpl.INSTANCE
.createMessage(HexUtils.hexToBytes(hexMsg));
assertEquals(subType, msg.subType, "SubType");
assertEquals(response, msg.response, "Response");

View File

@ -32,7 +32,7 @@ public class RFXComUVMessageTest {
String hexMessage = "095703123421194731E9";
byte[] message = HexUtils.hexToBytes(hexMessage);
RFXComUVMessage msg = (RFXComUVMessage) RFXComMessageFactory.createMessage(message);
RFXComUVMessage msg = (RFXComUVMessage) RFXComMessageFactoryImpl.INSTANCE.createMessage(message);
assertEquals(RFXComUVMessage.SubType.UV3, msg.subType, "SubType");
assertEquals(18, msg.seqNbr, "Seq Number");
@ -54,7 +54,7 @@ public class RFXComUVMessageTest {
String hexMessage = "09570312342119C731E9";
byte[] message = HexUtils.hexToBytes(hexMessage);
RFXComUVMessage msg = (RFXComUVMessage) RFXComMessageFactory.createMessage(message);
RFXComUVMessage msg = (RFXComUVMessage) RFXComMessageFactoryImpl.INSTANCE.createMessage(message);
assertEquals(RFXComUVMessage.SubType.UV3, msg.subType, "SubType");
assertEquals(18, msg.seqNbr, "Seq Number");

View File

@ -32,7 +32,7 @@ public class RFXComUndecodedRFMessageTest {
private void testMessage(String hexMsg, RFXComUndecodedRFMessage.SubType subType, int seqNbr, String rawPayload)
throws RFXComException {
final RFXComUndecodedRFMessage msg = (RFXComUndecodedRFMessage) RFXComMessageFactory
final RFXComUndecodedRFMessage msg = (RFXComUndecodedRFMessage) RFXComMessageFactoryImpl.INSTANCE
.createMessage(HexUtils.hexToBytes(hexMsg));
assertEquals(subType, msg.subType, "SubType");
assertEquals(seqNbr, (short) (msg.seqNbr & 0xFF), "Seq Number");
@ -51,7 +51,7 @@ public class RFXComUndecodedRFMessageTest {
@Test
public void testLongMessage() throws RFXComException {
RFXComUndecodedRFMessage msg = (RFXComUndecodedRFMessage) RFXComMessageFactory
RFXComUndecodedRFMessage msg = (RFXComUndecodedRFMessage) RFXComMessageFactoryImpl.INSTANCE
.createMessage(PacketType.UNDECODED_RF_MESSAGE);
msg.subType = RFXComUndecodedRFMessage.SubType.ARC;
msg.seqNbr = 1;

View File

@ -30,6 +30,6 @@ public class RFXComWaterMessageTest {
@Test
public void checkNotImplemented() {
assertThrows(RFXComMessageNotImplementedException.class,
() -> RFXComMessageFactory.createMessage(PacketType.WATER));
() -> RFXComMessageFactoryImpl.INSTANCE.createMessage(PacketType.WATER));
}
}

View File

@ -30,6 +30,6 @@ public class RFXComWeightMessageTest {
public void checkNotImplemented() {
// TODO Note that this message is supported in the 1.9 binding
assertThrows(RFXComMessageNotImplementedException.class,
() -> RFXComMessageFactory.createMessage(PacketType.WEIGHT));
() -> RFXComMessageFactoryImpl.INSTANCE.createMessage(PacketType.WEIGHT));
}
}

View File

@ -31,7 +31,7 @@ public class RFXComWindMessageTest {
public void testSomeMessages() throws RFXComException {
String hexMessage = "105601122F000087000000140000000079";
byte[] message = HexUtils.hexToBytes(hexMessage);
RFXComWindMessage msg = (RFXComWindMessage) RFXComMessageFactory.createMessage(message);
RFXComWindMessage msg = (RFXComWindMessage) RFXComMessageFactoryImpl.INSTANCE.createMessage(message);
assertEquals(WIND1, msg.subType, "SubType");
assertEquals(18, msg.seqNbr, "Seq Number");
assertEquals("12032", msg.getDeviceId(), "Sensor Id");