added migrated 2.x add-ons

Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Kai Kreuzer
2020-09-21 01:58:32 +02:00
parent bbf1a7fd29
commit 6df6783b60
11662 changed files with 1302875 additions and 11 deletions

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.rfxcom-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
<feature name="openhab-binding-rfxcom" description="RFXCOM Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<feature>openhab-transport-serial</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.rfxcom/${project.version}</bundle>
</feature>
</features>

View File

@@ -0,0 +1,34 @@
/**
* Copyright (c) 2010-2020 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;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.messages.RFXComDeviceMessage;
import org.openhab.core.thing.ThingUID;
/**
* The {@link DeviceMessageListener} is notified when a message is received.
*
*
* @author Pauli Anttila - Initial contribution
*/
public interface DeviceMessageListener {
/**
* This method is called whenever the message is received from the bridge.
*
* @param bridge The RFXCom bridge where message is received.
* @param message The message which received.
*/
void onDeviceMessageReceived(ThingUID bridge, RFXComDeviceMessage message) throws RFXComException;
}

View File

@@ -0,0 +1,245 @@
/**
* Copyright (c) 2010-2020 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;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage.PacketType;
import org.openhab.core.thing.ThingTypeUID;
/**
* The {@link RFXComBindingConstants} class defines common constants, which are
* used across the whole binding.
*
* @author Pauli Anttila - Initial contribution
*/
@NonNullByDefault
public class RFXComBindingConstants {
public static final String BINDING_ID = "rfxcom";
// List of all Bridge Type UIDs
public static final String BRIDGE_TYPE_MANUAL_BRIDGE = "bridge";
public static final String BRIDGE_TYPE_TCP_BRIDGE = "tcpbridge";
public static final String BRIDGE_TYPE_RFXTRX433 = "RFXtrx433";
public static final String BRIDGE_TYPE_RFXTRX315 = "RFXtrx315";
public static final String BRIDGE_TYPE_RFXREC433 = "RFXrec433";
public static final ThingTypeUID BRIDGE_MANUAL = new ThingTypeUID(BINDING_ID, BRIDGE_TYPE_MANUAL_BRIDGE);
public static final ThingTypeUID BRIDGE_TCP = new ThingTypeUID(BINDING_ID, BRIDGE_TYPE_TCP_BRIDGE);
public static final ThingTypeUID BRIDGE_RFXTRX443 = new ThingTypeUID(BINDING_ID, BRIDGE_TYPE_RFXTRX433);
public static final ThingTypeUID BRIDGE_RFXTRX315 = new ThingTypeUID(BINDING_ID, BRIDGE_TYPE_RFXTRX315);
public static final ThingTypeUID BRIDGE_RFXREC443 = new ThingTypeUID(BINDING_ID, BRIDGE_TYPE_RFXREC433);
/**
* Presents all supported Bridge types by RFXCOM binding.
*/
public static final Set<ThingTypeUID> SUPPORTED_BRIDGE_THING_TYPES_UIDS = Collections
.unmodifiableSet(Stream.of(BRIDGE_MANUAL, BRIDGE_TCP, BRIDGE_RFXTRX443, BRIDGE_RFXTRX315, BRIDGE_RFXREC443)
.collect(Collectors.toSet()));
/**
* Presents all discoverable Bridge types by RFXCOM binding.
*/
public static final Set<ThingTypeUID> DISCOVERABLE_BRIDGE_THING_TYPES_UIDS = Collections.unmodifiableSet(
Stream.of(BRIDGE_RFXTRX443, BRIDGE_RFXTRX315, BRIDGE_RFXREC443).collect(Collectors.toSet()));
// 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_SHUTTER = "shutter";
public static final String CHANNEL_VENETIAN_BLIND = "venetianBlind";
public static final String CHANNEL_SUN_WIND_DETECTOR = "sunWindDetector";
public static final String CHANNEL_COMMAND = "command";
public static final String CHANNEL_COMMAND_SECOND = "command2nd";
public static final String CHANNEL_CONTROL = "control";
public static final String CHANNEL_PROGRAM = "program";
public static final String CHANNEL_COMMAND_ID = "commandId";
public static final String CHANNEL_COMMAND_STRING = "commandString";
public static final String CHANNEL_MOOD = "mood";
public static final String CHANNEL_SIGNAL_LEVEL = "signalLevel";
public static final String CHANNEL_DIMMING_LEVEL = "dimmingLevel";
public static final String CHANNEL_UV = "uv";
public static final String CHANNEL_FAN_LIGHT = "fanLight";
public static final String CHANNEL_FAN_SPEED = "fanSpeed";
public static final String CHANNEL_TEMPERATURE = "temperature";
public static final String CHANNEL_FOOD_TEMPERATURE = "foodTemperature";
public static final String CHANNEL_BBQ_TEMPERATURE = "bbqTemperature";
public static final String CHANNEL_CHILL_TEMPERATURE = "chillTemperature";
public static final String CHANNEL_HUMIDITY = "humidity";
public static final String CHANNEL_HUMIDITY_STATUS = "humidityStatus";
public static final String CHANNEL_BATTERY_LEVEL = "batteryLevel";
public static final String CHANNEL_LOW_BATTERY = "lowBattery";
public static final String CHANNEL_PRESSURE = "pressure";
public static final String CHANNEL_FORECAST = "forecast";
public static final String CHANNEL_RAIN_RATE = "rainRate";
public static final String CHANNEL_RAIN_TOTAL = "rainTotal";
public static final String CHANNEL_WIND_DIRECTION = "windDirection";
public static final String CHANNEL_WIND_SPEED = "windSpeed";
public static final String CHANNEL_AVG_WIND_SPEED = "avgWindSpeed";
public static final String CHANNEL_INSTANT_POWER = "instantPower";
public static final String CHANNEL_TOTAL_USAGE = "totalUsage";
public static final String CHANNEL_INSTANT_AMPS = "instantAmp";
public static final String CHANNEL_TOTAL_AMP_HOUR = "totalAmpHour";
public static final String CHANNEL_CHANNEL1_AMPS = "channel1Amps";
public static final String CHANNEL_CHANNEL2_AMPS = "channel2Amps";
public static final String CHANNEL_CHANNEL3_AMPS = "channel3Amps";
public static final String CHANNEL_STATUS = "status";
public static final String CHANNEL_MOTION = "motion";
public static final String CHANNEL_CONTACT = "contact";
public static final String CHANNEL_CONTACT_1 = "contact1";
public static final String CHANNEL_CONTACT_2 = "contact2";
public static final String CHANNEL_CONTACT_3 = "contact3";
public static final String CHANNEL_VOLTAGE = "voltage";
public static final String CHANNEL_REFERENCE_VOLTAGE = "referenceVoltage";
public static final String CHANNEL_SET_POINT = "setpoint";
public static final String CHANNEL_DATE_TIME = "dateTime";
public static final String CHANNEL_CHIME_SOUND = "chimeSound";
// List of all Thing Type UIDs
private static final ThingTypeUID THING_TYPE_BAROMETRIC = new ThingTypeUID(BINDING_ID, "barometric");
private static final ThingTypeUID THING_TYPE_BBQ_TEMPERATURE = new ThingTypeUID(BINDING_ID, "bbqtemperature");
private static final ThingTypeUID THING_TYPE_BLINDS1 = new ThingTypeUID(BINDING_ID, "blinds1");
private static final ThingTypeUID THING_TYPE_CAMERA1 = new ThingTypeUID(BINDING_ID, "camera1");
private static final ThingTypeUID THING_TYPE_CHIME = new ThingTypeUID(BINDING_ID, "chime");
private static final ThingTypeUID THING_TYPE_CURRENT = new ThingTypeUID(BINDING_ID, "current");
private static final ThingTypeUID THING_TYPE_CURRENT_ENERGY = new ThingTypeUID(BINDING_ID, "currentenergy");
private static final ThingTypeUID THING_TYPE_CURTAIN1 = new ThingTypeUID(BINDING_ID, "curtain1");
private static final ThingTypeUID THING_TYPE_DATE_TIME = new ThingTypeUID(BINDING_ID, "datetime");
private static final ThingTypeUID THING_TYPE_ENERGY = new ThingTypeUID(BINDING_ID, "energy");
private static final ThingTypeUID THING_TYPE_FAN = new ThingTypeUID(BINDING_ID, "fan");
private static final ThingTypeUID THING_TYPE_FAN_SF01 = new ThingTypeUID(BINDING_ID, "fan_sf01");
private static final ThingTypeUID THING_TYPE_FAN_ITHO = new ThingTypeUID(BINDING_ID, "fan_itho");
private static final ThingTypeUID THING_TYPE_FAN_SEAV = new ThingTypeUID(BINDING_ID, "fan_seav");
private static final ThingTypeUID THING_TYPE_FAN_LUCCI_DC = new ThingTypeUID(BINDING_ID, "fan_lucci_dc");
private static final ThingTypeUID THING_TYPE_FAN_FT1211R = new ThingTypeUID(BINDING_ID, "fan_ft1211r");
private static final ThingTypeUID THING_TYPE_FAN_FALMEC = new ThingTypeUID(BINDING_ID, "fan_falmec");
private static final ThingTypeUID THING_TYPE_FAN_LUCCI_DC_II = new ThingTypeUID(BINDING_ID, "fan_lucci_dc_ii");
private static final ThingTypeUID THING_TYPE_FS20 = new ThingTypeUID(BINDING_ID, "fs20");
private static final ThingTypeUID THING_TYPE_GAS_USAGE = new ThingTypeUID(BINDING_ID, "gasusage");
private static final ThingTypeUID THING_TYPE_HOME_CONFORT = new ThingTypeUID(BINDING_ID, "homeconfort");
private static final ThingTypeUID THING_TYPE_HUMIDITY = new ThingTypeUID(BINDING_ID, "humidity");
private static final ThingTypeUID THING_TYPE_IO_LINES = new ThingTypeUID(BINDING_ID, "iolines");
private static final ThingTypeUID THING_TYPE_LIGHTNING1 = new ThingTypeUID(BINDING_ID, "lighting1");
private static final ThingTypeUID THING_TYPE_LIGHTNING2 = new ThingTypeUID(BINDING_ID, "lighting2");
private static final ThingTypeUID THING_TYPE_LIGHTNING3 = new ThingTypeUID(BINDING_ID, "lighting3");
private static final ThingTypeUID THING_TYPE_LIGHTNING4 = new ThingTypeUID(BINDING_ID, "lighting4");
private static final ThingTypeUID THING_TYPE_LIGHTNING5 = new ThingTypeUID(BINDING_ID, "lighting5");
private static final ThingTypeUID THING_TYPE_LIGHTNING6 = new ThingTypeUID(BINDING_ID, "lighting6");
private static final ThingTypeUID THING_TYPE_POWER = new ThingTypeUID(BINDING_ID, "power");
private static final ThingTypeUID THING_TYPE_RADIATOR1 = new ThingTypeUID(BINDING_ID, "radiator1");
private static final ThingTypeUID THING_TYPE_RAIN = new ThingTypeUID(BINDING_ID, "rain");
private static final ThingTypeUID THING_TYPE_REMOTE_CONTROL = new ThingTypeUID(BINDING_ID, "remotecontrol");
private static final ThingTypeUID THING_TYPE_RFX_METER = new ThingTypeUID(BINDING_ID, "rfxmeter");
private static final ThingTypeUID THING_TYPE_RFX_SENSOR = new ThingTypeUID(BINDING_ID, "rfxsensor");
private static final ThingTypeUID THING_TYPE_RFY = new ThingTypeUID(BINDING_ID, "rfy");
private static final ThingTypeUID THING_TYPE_SECURITY1 = new ThingTypeUID(BINDING_ID, "security1");
private static final ThingTypeUID THING_TYPE_SECURITY2 = new ThingTypeUID(BINDING_ID, "security2");
private static final ThingTypeUID THING_TYPE_TEMPERATURE = new ThingTypeUID(BINDING_ID, "temperature");
private static final ThingTypeUID THING_TYPE_TEMPERATURE_HUMIDITY = new ThingTypeUID(BINDING_ID,
"temperaturehumidity");
private static final ThingTypeUID THING_TYPE_TEMPERATURE_HUMIDITY_BAROMETRIC = new ThingTypeUID(BINDING_ID,
"temperaturehumiditybarometric");
private static final ThingTypeUID THING_TYPE_TEMPERATURE_RAIN = new ThingTypeUID(BINDING_ID, "temperaturerain");
private static final ThingTypeUID THING_TYPE_THERMOSTAT1 = new ThingTypeUID(BINDING_ID, "thermostat1");
private static final ThingTypeUID THING_TYPE_THERMOSTAT2 = new ThingTypeUID(BINDING_ID, "thermostat2");
private static final ThingTypeUID THING_TYPE_THERMOSTAT3 = new ThingTypeUID(BINDING_ID, "thermostat3");
private static final ThingTypeUID THING_TYPE_UNDECODED = new ThingTypeUID(BINDING_ID, "undecoded");
private static final ThingTypeUID THING_TYPE_UV = new ThingTypeUID(BINDING_ID, "uv");
private static final ThingTypeUID THING_TYPE_WATER_USAGE = new ThingTypeUID(BINDING_ID, "waterusage");
private static final ThingTypeUID THING_TYPE_WEIGHTING_SCALE = new ThingTypeUID(BINDING_ID, "weightingscale");
private static final ThingTypeUID THING_TYPE_WIND = new ThingTypeUID(BINDING_ID, "wind");
/**
* Presents all supported Thing types by RFXCOM binding.
*/
public static final Set<ThingTypeUID> SUPPORTED_DEVICE_THING_TYPES_UIDS = Collections.unmodifiableSet(Stream.of(
THING_TYPE_BAROMETRIC, THING_TYPE_BBQ_TEMPERATURE, THING_TYPE_BLINDS1, THING_TYPE_CAMERA1, THING_TYPE_CHIME,
THING_TYPE_CURRENT, THING_TYPE_CURRENT_ENERGY, THING_TYPE_CURTAIN1, THING_TYPE_DATE_TIME, THING_TYPE_ENERGY,
THING_TYPE_FAN, THING_TYPE_FAN_SF01, THING_TYPE_FAN_ITHO, THING_TYPE_FAN_SEAV, THING_TYPE_FAN_LUCCI_DC,
THING_TYPE_FAN_FT1211R, THING_TYPE_FAN_FALMEC, THING_TYPE_FAN_LUCCI_DC_II, THING_TYPE_GAS_USAGE,
THING_TYPE_HOME_CONFORT, THING_TYPE_HUMIDITY, THING_TYPE_IO_LINES, THING_TYPE_LIGHTNING1,
THING_TYPE_LIGHTNING2, THING_TYPE_LIGHTNING3, THING_TYPE_LIGHTNING4, THING_TYPE_LIGHTNING5,
THING_TYPE_LIGHTNING6, THING_TYPE_POWER, THING_TYPE_RADIATOR1, THING_TYPE_RAIN, THING_TYPE_REMOTE_CONTROL,
THING_TYPE_RFX_METER, THING_TYPE_RFX_SENSOR, THING_TYPE_RFY, THING_TYPE_SECURITY1, THING_TYPE_SECURITY2,
THING_TYPE_TEMPERATURE, THING_TYPE_TEMPERATURE_HUMIDITY, THING_TYPE_TEMPERATURE_HUMIDITY_BAROMETRIC,
THING_TYPE_TEMPERATURE_RAIN, THING_TYPE_THERMOSTAT1, 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 RFXCOM packet types to RFXCOM Thing types and vice versa.
*/
public static final Map<PacketType, ThingTypeUID> PACKET_TYPE_THING_TYPE_UID_MAP = Collections
.unmodifiableMap(new HashMap<PacketType, ThingTypeUID>() {
{
put(PacketType.BAROMETRIC, RFXComBindingConstants.THING_TYPE_BAROMETRIC);
put(PacketType.BBQ, RFXComBindingConstants.THING_TYPE_BBQ_TEMPERATURE);
put(PacketType.BLINDS1, RFXComBindingConstants.THING_TYPE_BLINDS1);
put(PacketType.CAMERA1, RFXComBindingConstants.THING_TYPE_CAMERA1);
put(PacketType.CHIME, RFXComBindingConstants.THING_TYPE_CHIME);
put(PacketType.CURRENT, RFXComBindingConstants.THING_TYPE_CURRENT);
put(PacketType.CURRENT_ENERGY, RFXComBindingConstants.THING_TYPE_CURRENT_ENERGY);
put(PacketType.CURTAIN1, RFXComBindingConstants.THING_TYPE_CURTAIN1);
put(PacketType.DATE_TIME, RFXComBindingConstants.THING_TYPE_DATE_TIME);
put(PacketType.ENERGY, RFXComBindingConstants.THING_TYPE_ENERGY);
put(PacketType.FAN, RFXComBindingConstants.THING_TYPE_FAN);
put(PacketType.FAN_SF01, RFXComBindingConstants.THING_TYPE_FAN_SF01);
put(PacketType.FAN_ITHO, RFXComBindingConstants.THING_TYPE_FAN_ITHO);
put(PacketType.FAN_SEAV, RFXComBindingConstants.THING_TYPE_FAN_SEAV);
put(PacketType.FAN_LUCCI_DC, RFXComBindingConstants.THING_TYPE_FAN_LUCCI_DC);
put(PacketType.FAN_FT1211R, RFXComBindingConstants.THING_TYPE_FAN_FT1211R);
put(PacketType.FAN_FALMEC, RFXComBindingConstants.THING_TYPE_FAN_FALMEC);
put(PacketType.FAN_LUCCI_DC_II, RFXComBindingConstants.THING_TYPE_FAN_LUCCI_DC_II);
put(PacketType.FS20, RFXComBindingConstants.THING_TYPE_FS20);
put(PacketType.GAS, RFXComBindingConstants.THING_TYPE_GAS_USAGE);
put(PacketType.HOME_CONFORT, RFXComBindingConstants.THING_TYPE_HOME_CONFORT);
put(PacketType.HUMIDITY, RFXComBindingConstants.THING_TYPE_HUMIDITY);
put(PacketType.IO_LINES, RFXComBindingConstants.THING_TYPE_IO_LINES);
put(PacketType.LIGHTING1, RFXComBindingConstants.THING_TYPE_LIGHTNING1);
put(PacketType.LIGHTING2, RFXComBindingConstants.THING_TYPE_LIGHTNING2);
put(PacketType.LIGHTING3, RFXComBindingConstants.THING_TYPE_LIGHTNING3);
put(PacketType.LIGHTING4, RFXComBindingConstants.THING_TYPE_LIGHTNING4);
put(PacketType.LIGHTING5, RFXComBindingConstants.THING_TYPE_LIGHTNING5);
put(PacketType.LIGHTING6, RFXComBindingConstants.THING_TYPE_LIGHTNING6);
put(PacketType.POWER, RFXComBindingConstants.THING_TYPE_POWER);
put(PacketType.RADIATOR1, RFXComBindingConstants.THING_TYPE_RADIATOR1);
put(PacketType.RAIN, RFXComBindingConstants.THING_TYPE_RAIN);
put(PacketType.REMOTE_CONTROL, RFXComBindingConstants.THING_TYPE_REMOTE_CONTROL);
put(PacketType.RFXMETER, RFXComBindingConstants.THING_TYPE_RFX_METER);
put(PacketType.RFXSENSOR, RFXComBindingConstants.THING_TYPE_RFX_SENSOR);
put(PacketType.RFY, RFXComBindingConstants.THING_TYPE_RFY);
put(PacketType.SECURITY1, RFXComBindingConstants.THING_TYPE_SECURITY1);
put(PacketType.SECURITY2, RFXComBindingConstants.THING_TYPE_SECURITY2);
put(PacketType.TEMPERATURE, RFXComBindingConstants.THING_TYPE_TEMPERATURE);
put(PacketType.TEMPERATURE_HUMIDITY, RFXComBindingConstants.THING_TYPE_TEMPERATURE_HUMIDITY);
put(PacketType.TEMPERATURE_HUMIDITY_BAROMETRIC,
RFXComBindingConstants.THING_TYPE_TEMPERATURE_HUMIDITY_BAROMETRIC);
put(PacketType.TEMPERATURE_RAIN, RFXComBindingConstants.THING_TYPE_TEMPERATURE_RAIN);
put(PacketType.THERMOSTAT1, RFXComBindingConstants.THING_TYPE_THERMOSTAT1);
put(PacketType.THERMOSTAT2, RFXComBindingConstants.THING_TYPE_THERMOSTAT2);
put(PacketType.THERMOSTAT3, RFXComBindingConstants.THING_TYPE_THERMOSTAT3);
put(PacketType.UNDECODED_RF_MESSAGE, RFXComBindingConstants.THING_TYPE_UNDECODED);
put(PacketType.UV, RFXComBindingConstants.THING_TYPE_UV);
put(PacketType.WATER, RFXComBindingConstants.THING_TYPE_WATER_USAGE);
put(PacketType.WEIGHT, RFXComBindingConstants.THING_TYPE_WEIGHTING_SCALE);
put(PacketType.WIND, RFXComBindingConstants.THING_TYPE_WIND);
}
});
}

View File

@@ -0,0 +1,113 @@
/**
* Copyright (c) 2010-2020 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;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.rfxcom.internal.discovery.RFXComDeviceDiscoveryService;
import org.openhab.binding.rfxcom.internal.handler.RFXComBridgeHandler;
import org.openhab.binding.rfxcom.internal.handler.RFXComHandler;
import org.openhab.core.config.discovery.DiscoveryService;
import org.openhab.core.io.transport.serial.SerialPortManager;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.ThingUID;
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerFactory;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
/**
* The {@link RFXComHandlerFactory} is responsible for creating things and thing
* handlers.
*
* @author Pauli Anttila - Initial contribution
*/
@NonNullByDefault
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.rfxcom")
public class RFXComHandlerFactory extends BaseThingHandlerFactory {
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Stream
.concat(RFXComBindingConstants.SUPPORTED_DEVICE_THING_TYPES_UIDS.stream(),
RFXComBindingConstants.SUPPORTED_BRIDGE_THING_TYPES_UIDS.stream())
.collect(Collectors.toSet());
/**
* Service registration map
*/
private final Map<ThingUID, ServiceRegistration<?>> discoveryServiceRegs = new HashMap<>();
private final SerialPortManager serialPortManager;
@Activate
public RFXComHandlerFactory(final @Reference SerialPortManager serialPortManager) {
this.serialPortManager = serialPortManager;
}
@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return SUPPORTED_THING_TYPES.contains(thingTypeUID);
}
@Override
protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (RFXComBindingConstants.SUPPORTED_BRIDGE_THING_TYPES_UIDS.contains(thingTypeUID)) {
RFXComBridgeHandler handler = new RFXComBridgeHandler((Bridge) thing, serialPortManager);
registerDeviceDiscoveryService(handler);
return handler;
} else if (supportsThingType(thingTypeUID)) {
return new RFXComHandler(thing);
}
return null;
}
@Override
protected void removeHandler(ThingHandler thingHandler) {
if (thingHandler instanceof RFXComBridgeHandler) {
unregisterDeviceDiscoveryService(thingHandler.getThing());
}
}
private synchronized void registerDeviceDiscoveryService(RFXComBridgeHandler handler) {
RFXComDeviceDiscoveryService discoveryService = new RFXComDeviceDiscoveryService(handler);
discoveryService.activate();
this.discoveryServiceRegs.put(handler.getThing().getUID(),
bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>()));
}
private synchronized void unregisterDeviceDiscoveryService(Thing thing) {
ServiceRegistration<?> serviceReg = discoveryServiceRegs.remove(thing.getUID());
if (serviceReg != null) {
RFXComDeviceDiscoveryService service = (RFXComDeviceDiscoveryService) bundleContext
.getService(serviceReg.getReference());
serviceReg.unregister();
if (service != null) {
service.deactivate();
}
}
}
}

View File

@@ -0,0 +1,75 @@
/**
* Copyright (c) 2010-2020 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 RFXComBaseConnector device.
*
* @author Pauli Anttila - Initial contribution
*/
public class RFXComBridgeConfiguration {
public static final String SERIAL_PORT = "serialPort";
public static final String BRIDGE_ID = "bridgeId";
// Serial port for manual configuration
public String serialPort;
// Configuration for discovered bridge devices
public String bridgeId;
// Host for using RFXCOM over TCP/IP
public String host;
// Port for using RFXCOM over TCP/IP
public int port;
public String transceiverType;
// Prevent unknown devices from being added to the inbox
public boolean disableDiscovery;
public int transmitPower;
// Won't configure protocols to RFXCOM transceiver
public boolean ignoreConfig;
public String setMode;
// Enabled protocols
public boolean enableUndecoded;
public boolean enableImagintronixOpus;
public boolean enableByronSX;
public boolean enableRSL;
public boolean enableLighting4;
public boolean enableFineOffsetViking;
public boolean enableRubicson;
public boolean enableAEBlyss;
public boolean enableBlindsT1T2T3T4;
public boolean enableBlindsT0;
public boolean enableProGuard;
public boolean enableFS20;
public boolean enableLaCrosse;
public boolean enableHidekiUPM;
public boolean enableADLightwaveRF;
public boolean enableMertik;
public boolean enableVisonic;
public boolean enableATI;
public boolean enableOregonScientific;
public boolean enableMeiantech;
public boolean enableHomeEasyEU;
public boolean enableAC;
public boolean enableARC;
public boolean enableX10;
public boolean enableHomeConfort;
public boolean enableKEELOQ;
}

View File

@@ -0,0 +1,33 @@
/**
* Copyright (c) 2010-2020 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 RfxcomBinding device.
*
* @author Pauli Anttila - Initial contribution
*/
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;
}

View File

@@ -0,0 +1,69 @@
/**
* Copyright (c) 2010-2020 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.connector;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* RFXCOM connector for serial port communication.
*
* @author James Hewitt-Thomas - Initial contribution
*/
public abstract class RFXComBaseConnector implements RFXComConnectorInterface {
private final Logger logger = LoggerFactory.getLogger(RFXComBaseConnector.class);
private List<RFXComEventListener> listeners = new ArrayList<>();
protected InputStream in;
@Override
public synchronized void addEventListener(RFXComEventListener rfxComEventListener) {
if (!listeners.contains(rfxComEventListener)) {
listeners.add(rfxComEventListener);
}
}
@Override
public synchronized void removeEventListener(RFXComEventListener listener) {
listeners.remove(listener);
}
void sendMsgToListeners(byte[] msg) {
try {
for (RFXComEventListener listener : listeners) {
listener.packetReceived(msg);
}
} catch (Exception e) {
logger.error("Event listener invoking error", e);
}
}
void sendErrorToListeners(String error) {
try {
for (RFXComEventListener listener : listeners) {
listener.errorOccurred(error);
}
} catch (Exception e) {
logger.error("Event listener invoking error", e);
}
}
int read(byte[] buffer, int offset, int length) throws IOException {
return in.read(buffer, offset, length);
}
}

View File

@@ -0,0 +1,59 @@
/**
* Copyright (c) 2010-2020 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.connector;
import java.io.IOException;
import org.openhab.binding.rfxcom.internal.config.RFXComBridgeConfiguration;
/**
* This interface defines interface to communicate RFXCOM controller.
*
* @author Pauli Anttila - Initial contribution
*/
public interface RFXComConnectorInterface {
/**
* Procedure for connecting to RFXCOM controller.
*
* @param device Controller connection parameters (e.g. serial port name or IP address).
*/
void connect(RFXComBridgeConfiguration device) throws Exception;
/**
* Procedure for disconnecting to RFXCOM controller.
*
*/
void disconnect();
/**
* Procedure for send raw data to RFXCOM controller.
*
* @param data raw bytes.
*/
void sendMessage(byte[] data) throws IOException;
/**
* Procedure for register event listener.
*
* @param listener Event listener instance to handle events.
*/
void addEventListener(RFXComEventListener listener);
/**
* Procedure for remove event listener.
*
* @param listener Event listener instance to remove.
*/
void removeEventListener(RFXComEventListener listener);
}

View File

@@ -0,0 +1,35 @@
/**
* Copyright (c) 2010-2020 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.connector;
/**
* This interface defines interface to receive data from RFXCOM controller.
*
* @author Pauli Anttila - Initial contribution
*/
public interface RFXComEventListener {
/**
* Procedure for receive raw data from RFXCOM controller.
*
* @param data Received raw data.
*/
void packetReceived(byte[] data);
/**
* Procedure for receiving information fatal error.
*
* @param error Error occurred.
*/
void errorOccurred(String error);
}

View File

@@ -0,0 +1,124 @@
/**
* Copyright (c) 2010-2020 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.connector;
import java.io.IOException;
import org.openhab.binding.rfxcom.internal.config.RFXComBridgeConfiguration;
import org.openhab.core.util.HexUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jd2xx.JD2XX;
import jd2xx.JD2XXInputStream;
import jd2xx.JD2XXOutputStream;
/**
* RFXCOM connector for direct access via D2XX driver.
*
* @author Pauli Anttila - Initial contribution
*/
public class RFXComJD2XXConnector extends RFXComBaseConnector {
private final Logger logger = LoggerFactory.getLogger(RFXComJD2XXConnector.class);
private JD2XX serialPort;
private JD2XXOutputStream out;
private final String readerThreadName;
private Thread readerThread;
public RFXComJD2XXConnector(String readerThreadName) {
super();
this.readerThreadName = readerThreadName;
}
@Override
public void connect(RFXComBridgeConfiguration device) throws IOException {
logger.info("Connecting to RFXCOM device '{}' using JD2XX.", device.bridgeId);
if (serialPort == null) {
serialPort = new JD2XX();
}
serialPort.openBySerialNumber(device.bridgeId);
serialPort.setBaudRate(38400);
serialPort.setDataCharacteristics(8, JD2XX.STOP_BITS_1, JD2XX.PARITY_NONE);
serialPort.setFlowControl(JD2XX.FLOW_NONE, 0, 0);
serialPort.setTimeouts(100, 100);
in = new JD2XXInputStream(serialPort);
out = new JD2XXOutputStream(serialPort);
out.flush();
if (in.markSupported()) {
in.reset();
}
readerThread = new RFXComStreamReader(this, readerThreadName);
readerThread.start();
}
@Override
public void disconnect() {
logger.debug("Disconnecting");
if (readerThread != null) {
logger.debug("Interrupt serial listener");
readerThread.interrupt();
try {
readerThread.join();
} catch (InterruptedException e) {
}
}
if (out != null) {
logger.debug("Close serial out stream");
try {
out.close();
} catch (IOException e) {
logger.debug("Error while closing the out stream: {}", e.getMessage());
}
}
if (in != null) {
logger.debug("Close serial in stream");
try {
in.close();
} catch (IOException e) {
logger.debug("Error while closing the in stream: {}", e.getMessage());
}
}
if (serialPort != null) {
logger.debug("Close serial port");
try {
serialPort.close();
} catch (IOException e) {
logger.debug("Serial port closing error: {}", e.getMessage());
}
}
readerThread = null;
serialPort = null;
out = null;
in = null;
logger.debug("Closed");
}
@Override
public void sendMessage(byte[] data) throws IOException {
if (logger.isTraceEnabled()) {
logger.trace("Send data (len={}): {}", data.length, HexUtils.bytesToHex(data));
}
out.write(data);
}
}

View File

@@ -0,0 +1,164 @@
/**
* Copyright (c) 2010-2020 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.connector;
import java.io.IOException;
import java.io.OutputStream;
import java.util.TooManyListenersException;
import org.openhab.binding.rfxcom.internal.config.RFXComBridgeConfiguration;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.core.io.transport.serial.PortInUseException;
import org.openhab.core.io.transport.serial.SerialPort;
import org.openhab.core.io.transport.serial.SerialPortEvent;
import org.openhab.core.io.transport.serial.SerialPortEventListener;
import org.openhab.core.io.transport.serial.SerialPortIdentifier;
import org.openhab.core.io.transport.serial.SerialPortManager;
import org.openhab.core.io.transport.serial.UnsupportedCommOperationException;
import org.openhab.core.util.HexUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* RFXCOM connector for serial port communication.
*
* @author Pauli Anttila - Initial contribution
*/
public class RFXComSerialConnector extends RFXComBaseConnector implements SerialPortEventListener {
private final Logger logger = LoggerFactory.getLogger(RFXComSerialConnector.class);
private OutputStream out;
private SerialPort serialPort;
private final SerialPortManager serialPortManager;
private final String readerThreadName;
private Thread readerThread;
public RFXComSerialConnector(SerialPortManager serialPortManager, String readerThreadName) {
super();
this.serialPortManager = serialPortManager;
this.readerThreadName = readerThreadName;
}
@Override
public void connect(RFXComBridgeConfiguration device)
throws RFXComException, PortInUseException, UnsupportedCommOperationException, IOException {
SerialPortIdentifier portIdentifier = serialPortManager.getIdentifier(device.serialPort);
if (portIdentifier == null) {
logger.debug("No serial port {}", device.serialPort);
throw new RFXComException("No serial port " + device.serialPort);
}
SerialPort commPort = portIdentifier.open(this.getClass().getName(), 2000);
serialPort = commPort;
serialPort.setSerialPortParams(38400, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
serialPort.enableReceiveThreshold(1);
serialPort.enableReceiveTimeout(100); // In ms. Small values mean faster shutdown but more cpu usage.
in = serialPort.getInputStream();
out = serialPort.getOutputStream();
out.flush();
if (in.markSupported()) {
in.reset();
}
// RXTX serial port library causes high CPU load
// Start event listener, which will just sleep and slow down event loop
try {
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
logger.debug("Serial port event listener started");
} catch (TooManyListenersException e) {
}
readerThread = new RFXComStreamReader(this, readerThreadName);
readerThread.start();
}
@Override
public void disconnect() {
logger.debug("Disconnecting");
if (serialPort != null) {
serialPort.removeEventListener();
logger.debug("Serial port event listener stopped");
}
if (readerThread != null) {
logger.debug("Interrupt serial listener");
readerThread.interrupt();
try {
readerThread.join();
} catch (InterruptedException e) {
}
}
if (out != null) {
logger.debug("Close serial out stream");
try {
out.close();
} catch (IOException e) {
logger.debug("Error while closing the out stream: {}", e.getMessage());
}
}
if (in != null) {
logger.debug("Close serial in stream");
try {
in.close();
} catch (IOException e) {
logger.debug("Error while closing the in stream: {}", e.getMessage());
}
}
if (serialPort != null) {
logger.debug("Close serial port");
serialPort.close();
}
readerThread = null;
serialPort = null;
out = null;
in = null;
logger.debug("Closed");
}
@Override
public void sendMessage(byte[] data) throws IOException {
if (out == null) {
throw new IOException("Not connected sending messages is not possible");
}
if (logger.isTraceEnabled()) {
logger.trace("Send data (len={}): {}", data.length, HexUtils.bytesToHex(data));
}
out.write(data);
out.flush();
}
@Override
public void serialEvent(SerialPortEvent arg0) {
try {
/*
* See more details from
* https://github.com/NeuronRobotics/nrjavaserial/issues/22
*/
logger.trace("RXTX library CPU load workaround, sleep forever");
Thread.sleep(Long.MAX_VALUE);
} catch (InterruptedException ignore) {
}
}
}

View File

@@ -0,0 +1,100 @@
/**
* Copyright (c) 2010-2020 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.connector;
import java.io.IOException;
import java.util.Arrays;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComTimeoutException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* RFXCOM stream reader to parse RFXCOM output into messages.
*
* @author Pauli Anttila - Initial contribution
* @author James Hewitt-Thomas - New class
* @author Mike Jagdis - Interruptible read loop
* @author Martin van Wingerden - Slight refactoring for read loop for TCP connector
*/
public class RFXComStreamReader extends Thread {
private final Logger logger = LoggerFactory.getLogger(RFXComStreamReader.class);
private static final int MAX_READ_TIMEOUTS = 4;
private static final int MAX_RFXCOM_MESSAGE_LEN = 256;
private RFXComBaseConnector connector;
private class ExceptionHandler implements Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
logger.debug("Connector died: ", throwable);
connector.sendErrorToListeners("Connector died: " + throwable.getMessage());
}
}
public RFXComStreamReader(RFXComBaseConnector connector, String threadName) {
super(threadName);
this.connector = connector;
setUncaughtExceptionHandler(new ExceptionHandler());
}
@Override
public void run() {
logger.debug("Data listener started");
byte[] buf = new byte[MAX_RFXCOM_MESSAGE_LEN];
// The stream has (or SHOULD have) a read timeout set. Taking a
// read timeout (read returns 0) between packets gives us a chance
// to check if we've been interrupted. Read interrupts during a
// packet are ignored but if too many timeouts occur we take it as
// meaning the RFXCOM has become missing presumed dead.
try {
while (!Thread.interrupted()) {
// First byte tells us how long the packet is
int bytesRead = connector.read(buf, 0, 1);
int packetLength = buf[0];
if (bytesRead > 0 && packetLength > 0) {
logger.trace("Message length is {} bytes", packetLength);
processMessage(buf, packetLength);
connector.sendMsgToListeners(Arrays.copyOfRange(buf, 0, packetLength + 1));
} else if (bytesRead == -1) {
throw new IOException("End of stream");
}
}
} catch (IOException | RFXComTimeoutException e) {
logger.debug("Received exception, will report it to listeners", e);
connector.sendErrorToListeners(e.getMessage());
}
logger.debug("Data listener stopped");
}
private void processMessage(byte[] buf, int packetLength) throws IOException, RFXComTimeoutException {
// Now read the rest of the packet
int bufferIndex = 1;
int readTimeoutCount = 1;
while (bufferIndex <= packetLength) {
int bytesRemaining = packetLength - bufferIndex + 1;
logger.trace("Waiting remaining {} bytes from the message", bytesRemaining);
int bytesRead = connector.read(buf, bufferIndex, bytesRemaining);
if (bytesRead > 0) {
logger.trace("Received {} bytes from the message", bytesRead);
bufferIndex += bytesRead;
readTimeoutCount = 1;
} else if (readTimeoutCount++ == MAX_READ_TIMEOUTS) {
throw new RFXComTimeoutException("Timeout during packet read");
}
}
}
}

View File

@@ -0,0 +1,110 @@
/**
* Copyright (c) 2010-2020 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.connector;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketTimeoutException;
import org.openhab.binding.rfxcom.internal.config.RFXComBridgeConfiguration;
import org.openhab.core.util.HexUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* RFXCOM connector for TCP/IP communication.
*
* @author Pauli Anttila - Initial contribution
* @author Ivan F. Martinez, James Hewitt-Thomas - Implementation
*/
public class RFXComTcpConnector extends RFXComBaseConnector {
private final Logger logger = LoggerFactory.getLogger(RFXComTcpConnector.class);
private OutputStream out;
private Socket socket;
private final String readerThreadName;
private Thread readerThread;
public RFXComTcpConnector(String readerThreadName) {
super();
this.readerThreadName = readerThreadName;
}
@Override
public void connect(RFXComBridgeConfiguration device) throws IOException {
logger.info("Connecting to RFXCOM at {}:{} over TCP/IP", device.host, device.port);
socket = new Socket(device.host, device.port);
socket.setSoTimeout(100); // In ms. Small values mean faster shutdown but more cpu usage.
in = socket.getInputStream();
out = socket.getOutputStream();
out.flush();
if (in.markSupported()) {
in.reset();
}
readerThread = new RFXComStreamReader(this, readerThreadName);
readerThread.start();
}
@Override
public void disconnect() {
logger.debug("Disconnecting");
if (readerThread != null) {
logger.debug("Interrupt stream listener");
readerThread.interrupt();
try {
readerThread.join();
} catch (InterruptedException e) {
}
}
if (socket != null) {
logger.debug("Close socket");
try {
socket.close();
} catch (IOException e) {
logger.debug("Error while closing the socket: {}", e.getMessage());
}
}
readerThread = null;
socket = null;
out = null;
in = null;
logger.debug("Closed");
}
@Override
public void sendMessage(byte[] data) throws IOException {
if (logger.isTraceEnabled()) {
logger.trace("Send data (len={}): {}", data.length, HexUtils.bytesToHex(data));
}
out.write(data);
out.flush();
}
@Override
int read(byte[] buffer, int offset, int length) throws IOException {
try {
return super.read(buffer, offset, length);
} catch (SocketTimeoutException ignore) {
// ignore this exception, instead return 0 to behave like the serial read
return 0;
}
}
}

View File

@@ -0,0 +1,141 @@
/**
* Copyright (c) 2010-2020 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.discovery;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.openhab.binding.rfxcom.internal.RFXComBindingConstants;
import org.openhab.binding.rfxcom.internal.config.RFXComBridgeConfiguration;
import org.openhab.core.config.discovery.AbstractDiscoveryService;
import org.openhab.core.config.discovery.DiscoveryResult;
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
import org.openhab.core.config.discovery.DiscoveryService;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.ThingUID;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jd2xx.JD2XX;
/**
* The {@link RFXComBridgeDiscovery} is responsible for discovering new RFXCOM
* transceivers.
*
* @author Pauli Anttila - Initial contribution
*
*/
@Component(service = DiscoveryService.class, immediate = true, configurationPid = "discovery.rfxcom")
public class RFXComBridgeDiscovery extends AbstractDiscoveryService {
private static final long REFRESH_INTERVAL_IN_SECONDS = 600;
private final Logger logger = LoggerFactory.getLogger(RFXComBridgeDiscovery.class);
private boolean unsatisfiedLinkErrorLogged = false;
private ScheduledFuture<?> discoveryJob;
public RFXComBridgeDiscovery() {
super(RFXComBindingConstants.DISCOVERABLE_BRIDGE_THING_TYPES_UIDS, 10, false);
}
@Override
public Set<ThingTypeUID> getSupportedThingTypes() {
return RFXComBindingConstants.DISCOVERABLE_BRIDGE_THING_TYPES_UIDS;
}
@Override
public void startScan() {
logger.debug("Start discovery scan for RFXCOM transceivers");
discoverRfxcom();
}
@Override
protected void startBackgroundDiscovery() {
logger.debug("Start background discovery for RFXCOM transceivers");
discoveryJob = scheduler.scheduleWithFixedDelay(this::discoverRfxcom, 0, REFRESH_INTERVAL_IN_SECONDS,
TimeUnit.SECONDS);
}
@Override
protected void stopBackgroundDiscovery() {
logger.debug("Stop background discovery for RFXCOM transceivers");
if (discoveryJob != null && !discoveryJob.isCancelled()) {
discoveryJob.cancel(true);
discoveryJob = null;
}
}
private synchronized void discoverRfxcom() {
try {
JD2XX jd2xx = new JD2XX();
logger.debug("Discovering RFXCOM transceiver devices by JD2XX version {}", jd2xx.getLibraryVersion());
String[] devDescriptions = (String[]) jd2xx.listDevicesByDescription();
String[] devSerialNumbers = (String[]) jd2xx.listDevicesBySerialNumber();
logger.debug("Discovered {} FTDI device(s)", devDescriptions.length);
for (int i = 0; i < devSerialNumbers.length; ++i) {
if (devDescriptions.length > 0) {
switch (devDescriptions[i]) {
case RFXComBindingConstants.BRIDGE_TYPE_RFXTRX433:
addBridge(RFXComBindingConstants.BRIDGE_RFXTRX443, devSerialNumbers[i]);
break;
case RFXComBindingConstants.BRIDGE_TYPE_RFXTRX315:
addBridge(RFXComBindingConstants.BRIDGE_RFXTRX315, devSerialNumbers[i]);
break;
case RFXComBindingConstants.BRIDGE_TYPE_RFXREC433:
addBridge(RFXComBindingConstants.BRIDGE_RFXREC443, devSerialNumbers[i]);
break;
default:
logger.trace("Ignore unknown device '{}'", devDescriptions[i]);
}
}
}
logger.debug("Discovery done");
} catch (IOException e) {
logger.error("Error occurred during discovery", e);
} catch (UnsatisfiedLinkError e) {
if (unsatisfiedLinkErrorLogged) {
logger.debug(
"Error occurred when trying to load native library for OS '{}' version '{}', processor '{}'",
System.getProperty("os.name"), System.getProperty("os.version"), System.getProperty("os.arch"),
e);
} else {
logger.error(
"Error occurred when trying to load native library for OS '{}' version '{}', processor '{}'",
System.getProperty("os.name"), System.getProperty("os.version"), System.getProperty("os.arch"),
e);
unsatisfiedLinkErrorLogged = true;
}
}
}
private void addBridge(ThingTypeUID bridgeType, String bridgeId) {
logger.debug("Discovered RFXCOM transceiver, bridgeType='{}', bridgeId='{}'", bridgeType, bridgeId);
Map<String, Object> properties = new HashMap<>();
properties.put(RFXComBridgeConfiguration.BRIDGE_ID, bridgeId);
ThingUID uid = new ThingUID(bridgeType, bridgeId);
DiscoveryResult result = DiscoveryResultBuilder.create(uid).withProperties(properties)
.withLabel("RFXCOM transceiver").build();
thingDiscovered(result);
}
}

View File

@@ -0,0 +1,86 @@
/**
* Copyright (c) 2010-2020 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.discovery;
import static org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage.ID_DELIMITER;
import java.util.Set;
import org.openhab.binding.rfxcom.internal.DeviceMessageListener;
import org.openhab.binding.rfxcom.internal.RFXComBindingConstants;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.handler.RFXComBridgeHandler;
import org.openhab.binding.rfxcom.internal.messages.RFXComDeviceMessage;
import org.openhab.core.config.discovery.AbstractDiscoveryService;
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.ThingUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link RFXComDeviceDiscoveryService} class is used to discover RFXCOM
* devices that send messages to RFXCOM bridge.
*
* @author Pauli Anttila - Initial contribution
*/
public class RFXComDeviceDiscoveryService extends AbstractDiscoveryService implements DeviceMessageListener {
private final Logger logger = LoggerFactory.getLogger(RFXComDeviceDiscoveryService.class);
private final int DISCOVERY_TTL = 3600;
private RFXComBridgeHandler bridgeHandler;
public RFXComDeviceDiscoveryService(RFXComBridgeHandler rfxcomBridgeHandler) {
super(null, 1, false);
this.bridgeHandler = rfxcomBridgeHandler;
}
public void activate() {
bridgeHandler.registerDeviceStatusListener(this);
}
@Override
public void deactivate() {
bridgeHandler.unregisterDeviceStatusListener(this);
}
@Override
public Set<ThingTypeUID> getSupportedThingTypes() {
return RFXComBindingConstants.SUPPORTED_DEVICE_THING_TYPES_UIDS;
}
@Override
protected void startScan() {
// this can be ignored here as we discover devices from received messages
}
@Override
public void onDeviceMessageReceived(ThingUID bridge, RFXComDeviceMessage message) throws RFXComException {
logger.trace("Received: bridge: {} message: {}", bridge, message);
String id = message.getDeviceId();
ThingTypeUID uid = RFXComBindingConstants.PACKET_TYPE_THING_TYPE_UID_MAP.get(message.getPacketType());
ThingUID thingUID = new ThingUID(uid, bridge, id.replace(ID_DELIMITER, "_"));
if (!bridgeHandler.getConfiguration().disableDiscovery) {
logger.trace("Adding new RFXCOM {} with id '{}' to smarthome inbox", thingUID, id);
DiscoveryResultBuilder discoveryResultBuilder = DiscoveryResultBuilder.create(thingUID).withBridge(bridge)
.withTTL(DISCOVERY_TTL);
message.addDevicePropertiesTo(discoveryResultBuilder);
thingDiscovered(discoveryResultBuilder.build());
} else {
logger.trace("Ignoring RFXCOM {} with id '{}' - discovery disabled", thingUID, id);
}
}
}

View File

@@ -0,0 +1,39 @@
/**
* Copyright (c) 2010-2020 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 RFXCOM errors.
*
* @author Pauli Anttila - Initial contribution
*/
public class RFXComException extends Exception {
private static final long serialVersionUID = 2975102966905930260L;
public RFXComException() {
super();
}
public RFXComException(String message) {
super(message);
}
public RFXComException(String message, Throwable cause) {
super(message, cause);
}
public RFXComException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,31 @@
/**
* Copyright (c) 2010-2020 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 RFXCOM errors.
*
* @author Pauli Anttila - Initial contribution
*/
public class RFXComMessageNotImplementedException extends RFXComException {
private static final long serialVersionUID = 5958462009164173495L;
public RFXComMessageNotImplementedException(String message, Throwable cause) {
super(message, cause);
}
public RFXComMessageNotImplementedException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,39 @@
/**
* Copyright (c) 2010-2020 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 are too long for the spec.
*
* @author James Hewitt-Thomas - Initial contribution
*/
public class RFXComMessageTooLongException extends RFXComException {
private static final long serialVersionUID = -3352067410289719335L;
public RFXComMessageTooLongException() {
super();
}
public RFXComMessageTooLongException(String message) {
super(message);
}
public RFXComMessageTooLongException(String message, Throwable cause) {
super(message, cause);
}
public RFXComMessageTooLongException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,24 @@
/**
* Copyright (c) 2010-2020 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 device has a timeout while processing a message
*
* @author Martin van Wingerden - Initial contribution
*/
public class RFXComTimeoutException extends RFXComException {
public RFXComTimeoutException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,24 @@
/**
* Copyright (c) 2010-2020 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 to indicate that a request was received for an unsupported channel
*
* @author Martin van Wingerden - Initial contribution
*/
public class RFXComUnsupportedChannelException extends RFXComException {
public RFXComUnsupportedChannelException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,35 @@
/**
* Copyright (c) 2010-2020 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 RFXComUnsupportedValueException extends RFXComException {
private static final long serialVersionUID = 402781611495845169L;
public RFXComUnsupportedValueException(Class<?> enumeration, String value) {
super("Unsupported value '" + value + "' for " + enumeration.getSimpleName());
}
public RFXComUnsupportedValueException(Class<?> enumeration, int value) {
this(enumeration, String.valueOf(value));
}
public RFXComUnsupportedValueException(Class<?> enumeration, int value, Object subType) {
super("Unsupported value '" + value + "' with subtype " + subType + " for " + enumeration.getSimpleName());
}
}

View File

@@ -0,0 +1,24 @@
/**
* Copyright (c) 2010-2020 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 org.openhab.core.types.Type;
/**
* Add support for a device state to be stored and retrieved later one
*
* @author Martin van Wingerden - Initial contribution
*/
public interface DeviceState {
Type getLastState(String channelId);
}

View File

@@ -0,0 +1,347 @@
/**
* Copyright (c) 2010-2020 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 java.io.IOException;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.rfxcom.internal.DeviceMessageListener;
import org.openhab.binding.rfxcom.internal.config.RFXComBridgeConfiguration;
import org.openhab.binding.rfxcom.internal.connector.RFXComConnectorInterface;
import org.openhab.binding.rfxcom.internal.connector.RFXComEventListener;
import org.openhab.binding.rfxcom.internal.connector.RFXComJD2XXConnector;
import org.openhab.binding.rfxcom.internal.connector.RFXComSerialConnector;
import org.openhab.binding.rfxcom.internal.connector.RFXComTcpConnector;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComMessageNotImplementedException;
import org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage;
import org.openhab.binding.rfxcom.internal.messages.RFXComDeviceMessage;
import org.openhab.binding.rfxcom.internal.messages.RFXComInterfaceControlMessage;
import org.openhab.binding.rfxcom.internal.messages.RFXComInterfaceMessage;
import org.openhab.binding.rfxcom.internal.messages.RFXComInterfaceMessage.Commands;
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.RFXComTransmitterMessage;
import org.openhab.core.io.transport.serial.SerialPortManager;
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.binding.BaseBridgeHandler;
import org.openhab.core.types.Command;
import org.openhab.core.util.HexUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* {@link RFXComBridgeHandler} is the handler for a RFXCOM transceivers. All
* {@link RFXComHandler}s use the {@link RFXComBridgeHandler} to execute the
* actual commands.
*
* @author Pauli Anttila - Initial contribution
*/
public class RFXComBridgeHandler extends BaseBridgeHandler {
private Logger logger = LoggerFactory.getLogger(RFXComBridgeHandler.class);
private RFXComConnectorInterface connector = null;
private MessageListener eventListener = new MessageListener();
private List<DeviceMessageListener> deviceStatusListeners = new CopyOnWriteArrayList<>();
private RFXComBridgeConfiguration configuration = null;
private ScheduledFuture<?> connectorTask;
private SerialPortManager serialPortManager;
private class TransmitQueue {
private Queue<RFXComBaseMessage> queue = new LinkedBlockingQueue<>();
public synchronized void enqueue(RFXComBaseMessage msg) throws IOException {
boolean wasEmpty = queue.isEmpty();
if (queue.offer(msg)) {
if (wasEmpty) {
send();
}
} else {
logger.error("Transmit queue overflow. Lost message: {}", msg);
}
}
public synchronized void sendNext() throws IOException {
queue.poll();
send();
}
public synchronized void send() throws IOException {
while (!queue.isEmpty()) {
RFXComBaseMessage msg = queue.peek();
try {
logger.debug("Transmitting message '{}'", msg);
byte[] data = msg.decodeMessage();
connector.sendMessage(data);
break;
} catch (RFXComException rfxe) {
logger.error("Error during send of {}", msg, rfxe);
queue.poll();
}
}
}
}
private TransmitQueue transmitQueue = new TransmitQueue();
public RFXComBridgeHandler(@NonNull Bridge br, SerialPortManager serialPortManager) {
super(br);
this.serialPortManager = serialPortManager;
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
logger.debug("Bridge commands not supported.");
}
@Override
public synchronized void dispose() {
logger.debug("Handler disposed.");
for (DeviceMessageListener deviceStatusListener : deviceStatusListeners) {
unregisterDeviceStatusListener(deviceStatusListener);
}
if (connector != null) {
connector.removeEventListener(eventListener);
connector.disconnect();
connector = null;
}
if (connectorTask != null && !connectorTask.isCancelled()) {
connectorTask.cancel(true);
connectorTask = null;
}
super.dispose();
}
@Override
public void initialize() {
logger.debug("Initializing RFXCOM bridge handler");
updateStatus(ThingStatus.OFFLINE);
configuration = getConfigAs(RFXComBridgeConfiguration.class);
if (configuration.serialPort != null && configuration.serialPort.startsWith("rfc2217")) {
logger.debug("Please use the Transceiver over TCP/IP bridge type for a serial over IP connection.");
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
"Please use the Transceiver over TCP/IP bridge type for a serial over IP connection.");
return;
}
if (connectorTask == null || connectorTask.isCancelled()) {
connectorTask = scheduler.scheduleWithFixedDelay(() -> {
logger.trace("Checking RFXCOM transceiver connection, thing status = {}", thing.getStatus());
if (thing.getStatus() != ThingStatus.ONLINE) {
connect();
}
}, 0, 60, TimeUnit.SECONDS);
}
}
private synchronized void connect() {
logger.debug("Connecting to RFXCOM transceiver");
try {
String readerThreadName = "OH-binding-" + getThing().getUID().getAsString();
if (configuration.serialPort != null) {
if (connector == null) {
connector = new RFXComSerialConnector(serialPortManager, readerThreadName);
}
} else if (configuration.bridgeId != null) {
if (connector == null) {
connector = new RFXComJD2XXConnector(readerThreadName);
}
} else if (configuration.host != null) {
if (connector == null) {
connector = new RFXComTcpConnector(readerThreadName);
}
}
if (connector != null) {
connector.disconnect();
connector.connect(configuration);
logger.debug("Reset controller");
connector.sendMessage(RFXComMessageFactory.CMD_RESET);
// controller does not response immediately after reset,
// so wait a while
Thread.sleep(300);
connector.addEventListener(eventListener);
logger.debug("Get status of controller");
connector.sendMessage(RFXComMessageFactory.CMD_GET_STATUS);
}
} catch (IOException e) {
logger.error("Connection to RFXCOM transceiver failed", e);
if ("device not opened (3)".equalsIgnoreCase(e.getMessage())) {
if (connector instanceof RFXComJD2XXConnector) {
logger.info("Automatically Discovered RFXCOM bridges use FTDI chip driver (D2XX)."
+ " Reason for this error normally is related to operating system native FTDI drivers,"
+ " which prevent D2XX driver to open device."
+ " To solve this problem, uninstall OS FTDI native drivers or add manually universal bridge 'RFXCOM USB Transceiver',"
+ " which use normal serial port driver rather than D2XX.");
}
}
} catch (Exception e) {
logger.error("Connection to RFXCOM transceiver failed", e);
} catch (UnsatisfiedLinkError e) {
logger.error("Error occurred when trying to load native library for OS '{}' version '{}', processor '{}'",
System.getProperty("os.name"), System.getProperty("os.version"), System.getProperty("os.arch"), e);
}
}
public void sendMessage(RFXComMessage msg) {
try {
RFXComBaseMessage baseMsg = (RFXComBaseMessage) msg;
transmitQueue.enqueue(baseMsg);
} catch (IOException e) {
logger.error("I/O Error", e);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
}
}
private class MessageListener implements RFXComEventListener {
@Override
public void packetReceived(byte[] packet) {
try {
RFXComMessage message = RFXComMessageFactory.createMessage(packet);
logger.debug("Message received: {}", message);
if (message instanceof RFXComInterfaceMessage) {
RFXComInterfaceMessage msg = (RFXComInterfaceMessage) message;
if (msg.subType == SubType.RESPONSE) {
if (msg.command == Commands.GET_STATUS) {
logger.debug("RFXCOM transceiver/receiver type: {}, hw version: {}.{}, fw version: {}",
msg.transceiverType, msg.hardwareVersion1, msg.hardwareVersion2,
msg.firmwareVersion);
thing.setProperty(Thing.PROPERTY_HARDWARE_VERSION,
msg.hardwareVersion1 + "." + msg.hardwareVersion2);
thing.setProperty(Thing.PROPERTY_FIRMWARE_VERSION, Integer.toString(msg.firmwareVersion));
if (configuration.ignoreConfig) {
logger.debug("Ignoring transceiver configuration");
} else {
byte[] setMode = null;
if (configuration.setMode != null && !configuration.setMode.isEmpty()) {
try {
setMode = HexUtils.hexToBytes(configuration.setMode);
if (setMode.length != 14) {
logger.warn("Invalid RFXCOM transceiver mode configuration");
setMode = null;
}
} catch (IllegalArgumentException ee) {
logger.warn("Failed to parse setMode data", ee);
}
} else {
RFXComInterfaceControlMessage modeMsg = new RFXComInterfaceControlMessage(
msg.transceiverType, configuration);
setMode = modeMsg.decodeMessage();
}
if (setMode != null) {
if (logger.isDebugEnabled()) {
logger.debug("Setting RFXCOM mode using: {}", HexUtils.bytesToHex(setMode));
}
connector.sendMessage(setMode);
}
}
// No need to wait for a response to any set mode. We start
// 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);
}
} else if (msg.subType == SubType.START_RECEIVER) {
updateStatus(ThingStatus.ONLINE);
logger.debug("Start TX of any queued messages");
transmitQueue.send();
} else {
logger.debug("Interface response received: {}", msg);
transmitQueue.sendNext();
}
} else if (message instanceof RFXComTransmitterMessage) {
RFXComTransmitterMessage resp = (RFXComTransmitterMessage) message;
logger.debug("Transmitter response received: {}", resp);
transmitQueue.sendNext();
} else if (message instanceof RFXComDeviceMessage) {
for (DeviceMessageListener deviceStatusListener : deviceStatusListeners) {
try {
deviceStatusListener.onDeviceMessageReceived(getThing().getUID(),
(RFXComDeviceMessage) message);
} catch (Exception e) {
// catch all exceptions give all handlers a fair chance of handling the messages
logger.error("An exception occurred while calling the DeviceStatusListener", e);
}
}
} else {
logger.warn("The received message cannot be processed, please create an "
+ "issue at the relevant tracker. Received message: {}", message);
}
} catch (RFXComMessageNotImplementedException e) {
logger.debug("Message not supported, data: {}", HexUtils.bytesToHex(packet));
} catch (RFXComException e) {
logger.error("Error occurred during packet receiving, data: {}", HexUtils.bytesToHex(packet), e);
} catch (IOException e) {
errorOccurred("I/O error");
}
}
@Override
public void errorOccurred(String error) {
logger.error("Error occurred: {}", error);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
}
}
public boolean registerDeviceStatusListener(DeviceMessageListener deviceStatusListener) {
if (deviceStatusListener == null) {
throw new IllegalArgumentException("It's not allowed to pass a null deviceStatusListener.");
}
return !deviceStatusListeners.contains(deviceStatusListener) && deviceStatusListeners.add(deviceStatusListener);
}
public boolean unregisterDeviceStatusListener(DeviceMessageListener deviceStatusListener) {
if (deviceStatusListener == null) {
throw new IllegalArgumentException("It's not allowed to pass a null deviceStatusListener.");
}
return deviceStatusListeners.remove(deviceStatusListener);
}
public RFXComBridgeConfiguration getConfiguration() {
return configuration;
}
}

View File

@@ -0,0 +1,220 @@
/**
* Copyright (c) 2010-2020 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.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.rfxcom.internal.DeviceMessageListener;
import org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfiguration;
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;
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.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.ThingStatusInfo;
import org.openhab.core.thing.ThingUID;
import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link RFXComHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Pauli Anttila - Initial contribution
*/
public class RFXComHandler extends BaseThingHandler implements DeviceMessageListener, DeviceState {
private static final int LOW_BATTERY_LEVEL = 1;
private final Logger logger = LoggerFactory.getLogger(RFXComHandler.class);
private final Map<String, Type> stateMap = new ConcurrentHashMap<>();
private RFXComBridgeHandler bridgeHandler;
private RFXComDeviceConfiguration config;
public RFXComHandler(@NonNull Thing thing) {
super(thing);
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
logger.debug("Received channel: {}, command: {}", channelUID, command);
if (bridgeHandler != null) {
if (command instanceof RefreshType) {
logger.trace("Received unsupported Refresh command");
} else {
try {
PacketType packetType = RFXComMessageFactory
.convertPacketType(getThing().getThingTypeUID().getId().toUpperCase());
RFXComMessage msg = RFXComMessageFactory.createMessage(packetType);
msg.setConfig(config);
msg.convertFromState(channelUID.getId(), command);
bridgeHandler.sendMessage(msg);
} catch (RFXComMessageNotImplementedException e) {
logger.error("Message not supported", e);
} catch (RFXComException e) {
logger.error("Transmitting error", e);
}
}
}
}
@Override
public void initialize() {
logger.debug("Initializing thing {}", getThing().getUID());
initializeBridge((getBridge() == null) ? null : getBridge().getHandler(),
(getBridge() == null) ? null : getBridge().getStatus());
stateMap.clear();
}
@Override
public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
logger.debug("bridgeStatusChanged {} for thing {}", bridgeStatusInfo, getThing().getUID());
initializeBridge((getBridge() == null) ? null : getBridge().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);
if (bridgeStatus == ThingStatus.ONLINE) {
updateStatus(ThingStatus.ONLINE);
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
}
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED);
}
}
@Override
public void dispose() {
logger.debug("Thing {} disposed.", getThing().getUID());
if (bridgeHandler != null) {
bridgeHandler.unregisterDeviceStatusListener(this);
}
bridgeHandler = null;
super.dispose();
}
@Override
public void onDeviceMessageReceived(ThingUID bridge, RFXComDeviceMessage message) {
try {
String id = message.getDeviceId();
if (config.deviceId.equals(id)) {
String receivedId = PACKET_TYPE_THING_TYPE_UID_MAP.get(message.getPacketType()).getId();
logger.debug("Received message from bridge: {} message: {}", bridge, message);
if (receivedId.equals(getThing().getThingTypeUID().getId())) {
updateStatus(ThingStatus.ONLINE);
for (Channel channel : getThing().getChannels()) {
ChannelUID uid = channel.getUID();
String channelId = uid.getId();
try {
switch (channelId) {
case CHANNEL_COMMAND:
case CHANNEL_CHIME_SOUND:
case CHANNEL_MOOD:
postNullableCommand(uid, message.convertToCommand(channelId, this));
break;
case CHANNEL_LOW_BATTERY:
updateNullableState(uid,
isLowBattery(message.convertToState(CHANNEL_BATTERY_LEVEL, this)));
break;
default:
updateNullableState(uid, message.convertToState(channelId, this));
break;
}
} catch (RFXComException e) {
logger.trace("{} does not handle {}", channelId, message);
}
}
}
}
} catch (Exception e) {
logger.error("Error occurred during message receiving", e);
}
}
private void updateNullableState(ChannelUID uid, State state) {
if (state == null) {
return;
}
stateMap.put(uid.getId(), state);
updateState(uid, state);
}
private void postNullableCommand(ChannelUID uid, Command command) {
if (command == null) {
return;
}
stateMap.put(uid.getId(), command);
postCommand(uid, command);
}
@Override
public Type getLastState(String channelId) {
return stateMap.get(channelId);
}
/**
* Check if battery level is below low battery threshold level.
*
* @param batteryLevel Internal battery level
* @return OnOffType
*/
private State isLowBattery(State batteryLevel) {
int level = ((DecimalType) batteryLevel).intValue();
if (level <= LOW_BATTERY_LEVEL) {
return OnOffType.ON;
} else {
return OnOffType.OFF;
}
}
}

View File

@@ -0,0 +1,66 @@
/**
* Copyright (c) 2010-2020 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 org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
/**
* An Utility class to handle {@link ByteEnumWrapper} instances
*
* @author Martin van Wingerden - Initial contribution
*/
@NonNullByDefault
public class ByteEnumUtil {
private ByteEnumUtil() {
// deliberately empty
}
public static <T extends ByteEnumWrapper> T fromByte(Class<T> typeClass, int input)
throws RFXComUnsupportedValueException {
for (T enumValue : typeClass.getEnumConstants()) {
if (enumValue.toByte() == input) {
return enumValue;
}
}
throw new RFXComUnsupportedValueException(typeClass, input);
}
public static <T extends ByteEnumWrapper> T convertSubType(Class<T> typeClass, String subType)
throws RFXComUnsupportedValueException {
for (T enumValue : typeClass.getEnumConstants()) {
if (enumValue.toString().equals(subType)) {
return enumValue;
}
}
try {
int byteValue = Integer.parseInt(subType);
return fromByte(typeClass, byteValue);
} catch (NumberFormatException e) {
throw new RFXComUnsupportedValueException(typeClass, subType);
}
}
public static <T extends ByteEnumWrapperWithSupportedSubTypes<?>> T fromByte(Class<T> typeClass, int input,
Object subType) throws RFXComUnsupportedValueException {
for (T enumValue : typeClass.getEnumConstants()) {
if (enumValue.toByte() == input && enumValue.supportedBySubTypes().contains(subType)) {
return enumValue;
}
}
throw new RFXComUnsupportedValueException(RFXComLighting5Message.Commands.class, input, subType);
}
}

View File

@@ -0,0 +1,22 @@
/**
* Copyright (c) 2010-2020 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;
/**
* An interface for all enums wrapping / mapping bytes
*
* @author Martin van Wingerden - Initial contribution
*/
interface ByteEnumWrapper {
byte toByte();
}

View File

@@ -0,0 +1,24 @@
/**
* Copyright (c) 2010-2020 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.util.List;
/**
* An interface for all enums wrapping / mapping bytes
*
* @author Martin van Wingerden - Initial contribution
*/
interface ByteEnumWrapperWithSupportedSubTypes<T extends ByteEnumWrapper> extends ByteEnumWrapper {
List<T> supportedBySubTypes();
}

View File

@@ -0,0 +1,156 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for BBQ temperature message.
*
* @author Mike Jagdis - Initial contribution
*/
public class RFXComBBQTemperatureMessage extends RFXComBatteryDeviceMessage<RFXComBBQTemperatureMessage.SubType> {
public enum SubType implements ByteEnumWrapper {
BBQ1(1); // Maverick ET-732
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public SubType subType;
public int sensorId;
public double foodTemperature;
public double bbqTemperature;
public byte signalLevel;
public byte batteryLevel;
public RFXComBBQTemperatureMessage() {
super(PacketType.BBQ);
}
public RFXComBBQTemperatureMessage(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
return super.toString() + ", Sub type = " + subType + ", Device Id = " + getDeviceId() + ", Food temperature = "
+ foodTemperature + ", BBQ temperature = " + bbqTemperature + ", Signal level = " + signalLevel
+ ", Battery level = " + batteryLevel;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[4] & 0xFF) << 8 | (data[5] & 0xFF);
foodTemperature = (data[6] & 0x7F) << 8 | (data[7] & 0xFF);
if ((data[6] & 0x80) != 0) {
foodTemperature = -foodTemperature;
}
bbqTemperature = (data[8] & 0x7F) << 8 | (data[9] & 0xFF);
if ((data[8] & 0x80) != 0) {
bbqTemperature = -bbqTemperature;
}
signalLevel = (byte) ((data[10] & 0xF0) >> 4);
batteryLevel = (byte) (data[10] & 0x0F);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[11];
data[0] = 0x0A;
data[1] = RFXComBaseMessage.PacketType.BBQ.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((sensorId & 0xFF00) >> 8);
data[5] = (byte) (sensorId & 0x00FF);
short temp = (short) Math.abs(foodTemperature);
data[6] = (byte) ((temp >> 8) & 0x7F);
data[7] = (byte) (temp & 0xFF);
if (foodTemperature < 0) {
data[6] |= 0x80;
}
temp = (short) Math.abs(bbqTemperature);
data[8] = (byte) ((temp >> 8) & 0x7F);
data[9] = (byte) (temp & 0xFF);
if (bbqTemperature < 0) {
data[8] |= 0x80;
}
data[10] = (byte) (((signalLevel & 0x0F) << 4) | (batteryLevel & 0x0F));
return data;
}
@Override
public String getDeviceId() {
return String.valueOf(sensorId);
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
if (CHANNEL_FOOD_TEMPERATURE.equals(channelId)) {
return new DecimalType(foodTemperature);
} else if (CHANNEL_BBQ_TEMPERATURE.equals(channelId)) {
return new DecimalType(bbqTemperature);
} else {
return super.convertToState(channelId, deviceState);
}
}
@Override
public void setSubType(SubType subType) {
throw new UnsupportedOperationException("Not supported");
}
@Override
public void setDeviceId(String deviceId) {
throw new UnsupportedOperationException("Not supported");
}
@Override
public void convertFromState(String channelId, Type type) {
throw new UnsupportedOperationException("Not supported");
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
}

View File

@@ -0,0 +1,175 @@
/**
* Copyright (c) 2010-2020 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 org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfiguration;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.core.util.HexUtils;
/**
* Base class for RFXCOM data classes. All other data classes should extend this class.
*
* @author Pauli Anttila - Initial contribution
*/
public abstract class RFXComBaseMessage implements RFXComMessage {
public static final String ID_DELIMITER = ".";
public enum PacketType implements ByteEnumWrapper {
INTERFACE_CONTROL(0),
INTERFACE_MESSAGE(1),
TRANSMITTER_MESSAGE(2),
UNDECODED_RF_MESSAGE(3),
LIGHTING1(16),
LIGHTING2(17),
LIGHTING3(18),
LIGHTING4(19),
LIGHTING5(20),
LIGHTING6(21),
CHIME(22),
FAN(23, RFXComFanMessage.SubType.LUCCI_AIR_FAN, RFXComFanMessage.SubType.WESTINGHOUSE_7226640,
RFXComFanMessage.SubType.CASAFAN),
FAN_SF01(23, RFXComFanMessage.SubType.SF01),
FAN_ITHO(23, RFXComFanMessage.SubType.CVE_RFT),
FAN_LUCCI_DC(23, RFXComFanMessage.SubType.LUCCI_AIR_DC),
FAN_LUCCI_DC_II(23, RFXComFanMessage.SubType.LUCCI_AIR_DC_II),
FAN_SEAV(23, RFXComFanMessage.SubType.SEAV_TXS4),
FAN_FT1211R(23, RFXComFanMessage.SubType.FT1211R),
FAN_FALMEC(23, RFXComFanMessage.SubType.FALMEC),
CURTAIN1(24),
BLINDS1(25),
RFY(26),
HOME_CONFORT(27),
EDISIO(28),
SECURITY1(32),
SECURITY2(33),
CAMERA1(40),
REMOTE_CONTROL(48),
THERMOSTAT1(64),
THERMOSTAT2(65),
THERMOSTAT3(66),
THERMOSTAT4(67),
RADIATOR1(72),
BBQ(78),
TEMPERATURE_RAIN(79),
TEMPERATURE(80),
HUMIDITY(81),
TEMPERATURE_HUMIDITY(82),
BAROMETRIC(83),
TEMPERATURE_HUMIDITY_BAROMETRIC(84),
RAIN(85),
WIND(86),
UV(87),
DATE_TIME(88),
CURRENT(89),
ENERGY(90),
CURRENT_ENERGY(91),
POWER(92),
WEIGHT(93),
GAS(94),
WATER(95),
CARTELECTRONIC(96),
RFXSENSOR(112),
RFXMETER(113),
FS20(114),
IO_LINES(128);
private final int packetType;
private final ByteEnumWrapper[] subTypes;
PacketType(int packetType, ByteEnumWrapper... subTypes) {
this.packetType = packetType;
this.subTypes = subTypes;
}
@Override
public byte toByte() {
return (byte) packetType;
}
}
public byte[] rawMessage;
private PacketType packetType;
public byte packetId;
public byte subType;
public byte seqNbr;
public byte id1;
public byte id2;
public RFXComBaseMessage() {
}
public RFXComBaseMessage(PacketType packetType) {
this.packetType = packetType;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
rawMessage = data;
packetId = data[1];
packetType = fromByte(data[1], data[2]);
subType = data[2];
seqNbr = data[3];
id1 = data[4];
if (data.length > 5) {
id2 = data[5];
}
}
private PacketType fromByte(byte packetId, byte subType) throws RFXComUnsupportedValueException {
for (PacketType enumValue : PacketType.values()) {
if (enumValue.toByte() == packetId) {
// if there are no subtypes?
if (enumValue.subTypes.length == 0) {
return enumValue;
}
// otherwise check for the matching subType
for (ByteEnumWrapper e : enumValue.subTypes) {
if (e.toByte() == subType) {
return enumValue;
}
}
}
}
throw new RFXComUnsupportedValueException(PacketType.class, packetId);
}
public PacketType getPacketType() {
return packetType;
}
@Override
public String toString() {
String str;
if (rawMessage == null) {
str = "Raw data = unknown";
} else {
str = "Raw data = " + HexUtils.bytesToHex(rawMessage);
}
str += ", Packet type = " + packetType;
str += ", Seq number = " + (short) (seqNbr & 0xFF);
return str;
}
@Override
public void setConfig(RFXComDeviceConfiguration deviceConfiguration) throws RFXComException {
// noop
}
}

View File

@@ -0,0 +1,59 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.CHANNEL_BATTERY_LEVEL;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.State;
/**
* A base class for all battery device messages
*
* @author Martin van Wingerden - Initial contribution
*/
abstract class RFXComBatteryDeviceMessage<T> extends RFXComDeviceMessageImpl<T> {
int batteryLevel;
RFXComBatteryDeviceMessage(PacketType packetType) {
super(packetType);
}
RFXComBatteryDeviceMessage() {
// deliberately empty
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_BATTERY_LEVEL:
return convertBatteryLevelToSystemWideLevel(batteryLevel);
default:
return super.convertToState(channelId, deviceState);
}
}
/**
* Convert internal battery level (0-9) to system wide battery level (0-100%).
*
* @param batteryLevel Internal battery level
* @return Battery level in system wide level
*/
private State convertBatteryLevelToSystemWideLevel(int batteryLevel) {
int ohLevel = (batteryLevel + 1) * 10;
return new DecimalType(ohLevel);
}
}

View File

@@ -0,0 +1,216 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.StopMoveType;
import org.openhab.core.library.types.UpDownType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for blinds1 message.
*
* @author Peter Janson / Pål Edman - Initial contribution
* @author Pauli Anttila - Migration to OH2
* @author Fabien Le Bars - Added support for Cherubini blinds
*/
public class RFXComBlinds1Message extends RFXComBatteryDeviceMessage<RFXComBlinds1Message.SubType> {
public enum SubType implements ByteEnumWrapper {
T0(0), // Hasta new/RollerTrol
T1(1),
T2(2),
T3(3),
T4(4), // Additional commands.
T5(5), // MEDIA MOUNT have different direction commands than the rest!! Needs to be fixed.
T6(6),
T7(7),
T8(8), // Chamberlain CS4330
T9(9), // Sunpery/BTX
T10(10), // Dolat DLM-1, Topstar
T11(11), // ASP
T12(12), // Confexx CNF24-2435
T13(13), // Screenline
T18(18); // Cherubini
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public enum Commands implements ByteEnumWrapper {
OPEN(0), // MediaMount DOWN(0),
CLOSE(1), // MediaMount UPP(1),
STOP(2),
CONFIRM(3),
SET_LIMIT(4), // YR1326 SET_UPPER_LIMIT(4),
SET_LOWER_LIMIT(5), // YR1326
DELETE_LIMITS(6), // YR1326
CHANGE_DIRECTON(7); // YR1326
private final int command;
Commands(int command) {
this.command = command;
}
@Override
public byte toByte() {
return (byte) command;
}
}
public SubType subType;
public int sensorId;
public byte unitCode;
public Commands command;
public RFXComBlinds1Message() {
super(PacketType.BLINDS1);
}
public RFXComBlinds1Message(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = "";
str += super.toString();
str += ", Sub type = " + subType;
str += ", Device Id = " + getDeviceId();
str += ", Command = " + command;
str += ", Signal level = " + signalLevel;
str += ", Battery level = " + batteryLevel;
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
if (subType == SubType.T6) {
sensorId = (data[4] & 0xFF) << 20 | (data[5] & 0xFF) << 12 | (data[6] & 0xFF) << 4 | (data[7] & 0xF0) >> 4;
unitCode = (byte) (data[7] & 0x0F);
} else {
sensorId = (data[4] & 0xFF) << 16 | (data[5] & 0xFF) << 8 | (data[6] & 0xFF);
unitCode = data[7];
}
command = fromByte(Commands.class, data[8]);
signalLevel = (byte) ((data[9] & 0xF0) >> 4);
batteryLevel = (byte) (data[9] & 0x0F);
}
@Override
public byte[] decodeMessage() {
// Example data
// BLINDS1 09 19 00 06 00 B1 8F 01 00 70
byte[] data = new byte[10];
data[0] = 0x09;
data[1] = RFXComBaseMessage.PacketType.BLINDS1.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
if (subType == SubType.T6) {
data[4] = (byte) ((sensorId >>> 20) & 0xFF);
data[5] = (byte) ((sensorId >>> 12) & 0xFF);
data[6] = (byte) ((sensorId >>> 4) & 0xFF);
data[7] = (byte) (((sensorId & 0x0F) << 4) | (unitCode & 0x0F));
} else {
data[4] = (byte) ((sensorId >> 16) & 0xFF);
data[5] = (byte) ((sensorId >> 8) & 0xFF);
data[6] = (byte) (sensorId & 0xFF);
data[7] = unitCode;
}
data[8] = command.toByte();
data[9] = (byte) (((signalLevel & 0x0F) << 4) | (batteryLevel & 0x0F));
return data;
}
@Override
public String getDeviceId() {
return sensorId + ID_DELIMITER + unitCode;
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
if (CHANNEL_COMMAND.equals(channelId)) {
return (command == Commands.CLOSE ? OpenClosedType.CLOSED : OpenClosedType.OPEN);
} else {
return super.convertToState(channelId, deviceState);
}
}
@Override
public void setSubType(SubType subType) {
this.subType = subType;
}
@Override
public void setDeviceId(String deviceId) throws RFXComException {
String[] ids = deviceId.split("\\" + ID_DELIMITER);
if (ids.length != 2) {
throw new RFXComException("Invalid device id '" + deviceId + "'");
}
sensorId = Integer.parseInt(ids[0]);
unitCode = Byte.parseByte(ids[1]);
}
@Override
public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
if (CHANNEL_SHUTTER.equals(channelId)) {
if (type instanceof OpenClosedType) {
command = (type == OpenClosedType.CLOSED ? Commands.CLOSE : Commands.OPEN);
} else if (type instanceof UpDownType) {
command = (type == UpDownType.UP ? Commands.OPEN : Commands.CLOSE);
} else if (type instanceof StopMoveType) {
command = Commands.STOP;
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
}
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
}

View File

@@ -0,0 +1,171 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.CHANNEL_CHIME_SOUND;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for chime messages.
*
* @author Mike Jagdis - Initial contribution
*/
public class RFXComChimeMessage extends RFXComDeviceMessageImpl<RFXComChimeMessage.SubType> {
public enum SubType implements ByteEnumWrapper {
BYRONSX(0),
BYRONMP001(1),
SELECTPLUS(2),
SELECTPLUS3(3),
ENVIVO(4);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public SubType subType;
public int sensorId;
public int chimeSound;
public RFXComChimeMessage() {
super(PacketType.CHIME);
}
public RFXComChimeMessage(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = "";
str += super.toString();
str += ", Sub type = " + subType;
str += ", Device Id = " + getDeviceId();
str += ", Chime Sound = " + chimeSound;
str += ", Signal level = " + signalLevel;
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
switch (subType) {
case BYRONSX:
sensorId = (data[4] & 0xFF) << 8 | (data[5] & 0xFF);
chimeSound = data[6];
break;
case BYRONMP001:
case SELECTPLUS:
case SELECTPLUS3:
case ENVIVO:
sensorId = (data[4] & 0xFF) << 16 | (data[5] & 0xFF) << 8 | (data[6] & 0xFF);
chimeSound = 1;
break;
}
signalLevel = (byte) ((data[7] & 0xF0) >> 4);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[8];
data[0] = 0x07;
data[1] = getPacketType().toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
switch (subType) {
case BYRONSX:
data[4] = (byte) ((sensorId & 0xFF00) >> 8);
data[5] = (byte) (sensorId & 0x00FF);
data[6] = (byte) chimeSound;
break;
case BYRONMP001:
case SELECTPLUS:
case SELECTPLUS3:
case ENVIVO:
data[4] = (byte) ((sensorId & 0xFF0000) >> 16);
data[5] = (byte) ((sensorId & 0x00FF00) >> 8);
data[6] = (byte) ((sensorId & 0x0000FF));
break;
}
data[7] = (byte) ((signalLevel & 0x0F) << 4);
return data;
}
@Override
public String getDeviceId() {
return String.valueOf(sensorId);
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
if (CHANNEL_CHIME_SOUND.equals(channelId)) {
return new DecimalType(chimeSound);
} else {
return super.convertToState(channelId, deviceState);
}
}
@Override
public void setSubType(SubType subType) {
this.subType = subType;
}
@Override
public void setDeviceId(String sensorId) {
this.sensorId = Integer.parseInt(sensorId);
}
@Override
public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
if (CHANNEL_CHIME_SOUND.equals(channelId)) {
if (type instanceof DecimalType) {
chimeSound = ((DecimalType) type).intValue();
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
}
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
}

View File

@@ -0,0 +1,182 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for Current and Energy message.
*
* @author Damien Servant - Initial contribution
*/
public class RFXComCurrentEnergyMessage extends RFXComBatteryDeviceMessage<RFXComCurrentEnergyMessage.SubType> {
private static final float TOTAL_USAGE_CONVERSION_FACTOR = 223.666F;
public enum SubType implements ByteEnumWrapper {
ELEC4(1); // OWL - CM180i
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public SubType subType;
public int sensorId;
public byte count;
public double channel1Amps;
public double channel2Amps;
public double channel3Amps;
public double totalUsage;
public RFXComCurrentEnergyMessage() {
super(PacketType.CURRENT_ENERGY);
}
public RFXComCurrentEnergyMessage(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = "";
str += super.toString();
str += ", Sub type = " + subType;
str += ", Id = " + sensorId;
str += ", Count = " + count;
str += ", Channel1 Amps = " + channel1Amps;
str += ", Channel2 Amps = " + channel2Amps;
str += ", Channel3 Amps = " + channel3Amps;
str += ", Total Usage = " + totalUsage;
str += ", Signal level = " + signalLevel;
str += ", Battery level = " + batteryLevel;
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[4] & 0xFF) << 8 | (data[5] & 0xFF);
count = data[6];
// Current = Field / 10
channel1Amps = ((data[7] & 0xFF) << 8 | (data[8] & 0xFF)) / 10.0;
channel2Amps = ((data[9] & 0xFF) << 8 | (data[10] & 0xFF)) / 10.0;
channel3Amps = ((data[11] & 0xFF) << 8 | (data[12] & 0xFF)) / 10.0;
totalUsage = ((long) (data[13] & 0xFF) << 40 | (long) (data[14] & 0xFF) << 32 | (data[15] & 0xFF) << 24
| (data[16] & 0xFF) << 16 | (data[17] & 0xFF) << 8 | (data[18] & 0xFF));
totalUsage = totalUsage / TOTAL_USAGE_CONVERSION_FACTOR;
signalLevel = (byte) ((data[19] & 0xF0) >> 4);
batteryLevel = (byte) (data[19] & 0x0F);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[20];
data[0] = (byte) (data.length - 1);
data[1] = RFXComBaseMessage.PacketType.CURRENT_ENERGY.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((sensorId & 0xFF00) >> 8);
data[5] = (byte) (sensorId & 0x00FF);
data[6] = count;
data[7] = (byte) (((int) (channel1Amps * 10.0) >> 8) & 0xFF);
data[8] = (byte) ((int) (channel1Amps * 10.0) & 0xFF);
data[9] = (byte) (((int) (channel2Amps * 10.0) >> 8) & 0xFF);
data[10] = (byte) ((int) (channel2Amps * 10.0) & 0xFF);
data[11] = (byte) (((int) (channel3Amps * 10.0) >> 8) & 0xFF);
data[12] = (byte) ((int) (channel3Amps * 10.0) & 0xFF);
long totalUsageLoc = (long) (totalUsage * TOTAL_USAGE_CONVERSION_FACTOR);
data[13] = (byte) ((totalUsageLoc >> 40) & 0xFF);
data[14] = (byte) ((totalUsageLoc >> 32) & 0xFF);
data[15] = (byte) ((totalUsageLoc >> 24) & 0xFF);
data[16] = (byte) ((totalUsageLoc >> 16) & 0xFF);
data[17] = (byte) ((totalUsageLoc >> 8) & 0xFF);
data[18] = (byte) (totalUsageLoc & 0xFF);
data[19] = (byte) (((signalLevel & 0x0F) << 4) | (batteryLevel & 0x0F));
return data;
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_CHANNEL1_AMPS:
return new DecimalType(channel1Amps);
case CHANNEL_CHANNEL2_AMPS:
return new DecimalType(channel2Amps);
case CHANNEL_CHANNEL3_AMPS:
return new DecimalType(channel3Amps);
case CHANNEL_TOTAL_USAGE:
return new DecimalType(totalUsage);
default:
return super.convertToState(channelId, deviceState);
}
}
@Override
public String getDeviceId() {
return String.valueOf(sensorId);
}
@Override
public void setDeviceId(String deviceId) {
throw new UnsupportedOperationException();
}
@Override
public void convertFromState(String channelId, Type type) {
throw new UnsupportedOperationException();
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
@Override
public void setSubType(SubType subType) {
this.subType = subType;
}
}

View File

@@ -0,0 +1,168 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for current message.
*
* @author Ben Jones - Initial contribution
* @author Pauli Anttila - for the Similar RFXComEnergyMessage code
* @author Jordan Cook - Added support for CURRENT devices, such as OWL CM113
* @author Martin van Wingerden - Updated CurrentMessage code to new style
*/
public class RFXComCurrentMessage extends RFXComBatteryDeviceMessage<RFXComCurrentMessage.SubType> {
public enum SubType implements ByteEnumWrapper {
ELEC1(1);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public SubType subType;
public int sensorId;
public byte count;
public double channel1Amps;
public double channel2Amps;
public double channel3Amps;
public RFXComCurrentMessage() {
super(PacketType.CURRENT);
}
public RFXComCurrentMessage(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = "";
str += super.toString();
str += ", Sub type = " + subType;
str += ", Device Id = " + sensorId;
str += ", Count = " + count;
str += ", Channel 1 Amps = " + channel1Amps;
str += ", Channel 2 Amps = " + channel2Amps;
str += ", Channel 3 Amps = " + channel3Amps;
str += ", Signal level = " + signalLevel;
str += ", Battery level = " + batteryLevel;
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[4] & 0xFF) << 8 | (data[5] & 0xFF);
count = data[6];
channel1Amps = ((data[7] & 0xFF) << 8 | (data[8] & 0xFF)) / 10.0;
channel2Amps = ((data[9] & 0xFF) << 8 | (data[10] & 0xFF)) / 10.0;
channel3Amps = ((data[11] & 0xFF) << 8 | (data[12] & 0xFF)) / 10.0;
signalLevel = (byte) ((data[13] & 0xF0) >> 4);
batteryLevel = (byte) (data[13] & 0x0F);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[14];
data[0] = 0x0D;
data[1] = PacketType.CURRENT.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((sensorId & 0xFF00) >> 8);
data[5] = (byte) (sensorId & 0x00FF);
data[6] = count;
data[7] = (byte) (((int) (channel1Amps * 10) >> 8) & 0xFF);
data[8] = (byte) ((int) (channel1Amps * 10) & 0xFF);
data[9] = (byte) (((int) (channel2Amps * 10) >> 8) & 0xFF);
data[10] = (byte) ((int) (channel2Amps * 10) & 0xFF);
data[11] = (byte) (((int) (channel3Amps * 10) >> 8) & 0xFF);
data[12] = (byte) ((int) (channel3Amps * 10) & 0xFF);
data[13] = (byte) (((signalLevel & 0x0F) << 4) | (batteryLevel & 0x0F));
return data;
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_CHANNEL1_AMPS:
return new DecimalType(channel1Amps);
case CHANNEL_CHANNEL2_AMPS:
return new DecimalType(channel2Amps);
case CHANNEL_CHANNEL3_AMPS:
return new DecimalType(channel3Amps);
default:
return super.convertToState(channelId, deviceState);
}
}
@Override
public String getDeviceId() {
return String.valueOf(sensorId);
}
@Override
public void setDeviceId(String deviceId) {
throw new UnsupportedOperationException();
}
@Override
public void convertFromState(String channelId, Type type) {
throw new UnsupportedOperationException();
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
@Override
public void setSubType(SubType subType) {
this.subType = subType;
}
}

View File

@@ -0,0 +1,179 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.StopMoveType;
import org.openhab.core.library.types.UpDownType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for curtain1 message. See Harrison.
*
* @author Evert van Es - Initial contribution
* @author Pauli Anttila - Migrated to OH2
*/
public class RFXComCurtain1Message extends RFXComBatteryDeviceMessage<RFXComCurtain1Message.SubType> {
public enum SubType implements ByteEnumWrapper {
HARRISON(0);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public enum Commands implements ByteEnumWrapper {
OPEN(0),
CLOSE(1),
STOP(2),
PROGRAM(3);
private final int command;
Commands(int command) {
this.command = command;
}
@Override
public byte toByte() {
return (byte) command;
}
}
public SubType subType;
public char sensorId;
public byte unitCode;
public Commands command;
public RFXComCurtain1Message() {
super(PacketType.CURTAIN1);
}
public RFXComCurtain1Message(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = "";
str += super.toString();
str += ", Sub type = " + subType;
str += ", Device Id = " + getDeviceId();
str += ", Command = " + command;
str += ", Signal level = " + signalLevel;
str += ", Battery level = " + batteryLevel;
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (char) data[4];
unitCode = data[5];
command = fromByte(Commands.class, data[6]);
signalLevel = (byte) ((data[7] & 0xF0) >> 4);
batteryLevel = (byte) ((data[7] & 0x0F));
}
@Override
public byte[] decodeMessage() {
// Example data 07 18 00 00 65 01 00 00
// 07 18 00 00 65 02 00 00
byte[] data = new byte[8];
data[0] = 0x07;
data[1] = 0x18;
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) sensorId;
data[5] = unitCode;
data[6] = command.toByte();
data[7] = (byte) (((signalLevel & 0x0F) << 4) + batteryLevel);
return data;
}
@Override
public String getDeviceId() {
return sensorId + ID_DELIMITER + unitCode;
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
if (channelId.equals(CHANNEL_COMMAND)) {
return (command == Commands.CLOSE ? OpenClosedType.CLOSED : OpenClosedType.OPEN);
} else {
return super.convertToState(channelId, deviceState);
}
}
@Override
public void setSubType(SubType subType) {
this.subType = subType;
}
@Override
public void setDeviceId(String deviceId) throws RFXComException {
String[] ids = deviceId.split("\\" + ID_DELIMITER);
if (ids.length != 2) {
throw new RFXComException("Invalid device id '" + deviceId + "'");
}
sensorId = ids[0].charAt(0);
unitCode = Byte.parseByte(ids[1]);
}
@Override
public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
if (channelId.equals(CHANNEL_SHUTTER)) {
if (type instanceof OpenClosedType) {
command = (type == OpenClosedType.CLOSED ? Commands.CLOSE : Commands.OPEN);
} else if (type instanceof UpDownType) {
command = (type == UpDownType.UP ? Commands.CLOSE : Commands.OPEN);
} else if (type instanceof StopMoveType) {
command = Commands.STOP;
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
}
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
}

View File

@@ -0,0 +1,157 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.CHANNEL_DATE_TIME;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for Date and Time message.
*
* @author Damien Servant - Initial contribution
*/
public class RFXComDateTimeMessage extends RFXComBatteryDeviceMessage<RFXComDateTimeMessage.SubType> {
public enum SubType implements ByteEnumWrapper {
RTGR328N(1);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public SubType subType;
public int sensorId;
String dateTime;
private int year;
private int month;
private int day;
private int dayOfWeek;
private int hour;
private int minute;
private int second;
public RFXComDateTimeMessage() {
super(PacketType.DATE_TIME);
}
public RFXComDateTimeMessage(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = super.toString();
str += ", Sub type = " + subType;
str += ", Id = " + sensorId;
str += ", Date Time = " + dateTime;
str += ", Signal level = " + signalLevel;
str += ", Battery level = " + batteryLevel;
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[4] & 0xFF) << 8 | (data[5] & 0xFF);
year = data[6] & 0xFF;
month = data[7] & 0xFF;
day = data[8] & 0xFF;
dayOfWeek = data[9] & 0xFF;
hour = data[10] & 0xFF;
minute = data[11] & 0xFF;
second = data[12] & 0xFF;
dateTime = String.format("20%02d-%02d-%02dT%02d:%02d:%02d", year, month, day, hour, minute, second);
signalLevel = (byte) ((data[13] & 0xF0) >> 4);
batteryLevel = (byte) (data[13] & 0x0F);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[14];
data[0] = (byte) (data.length - 1);
data[1] = RFXComBaseMessage.PacketType.DATE_TIME.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((sensorId & 0xFF00) >> 8);
data[5] = (byte) (sensorId & 0x00FF);
data[6] = (byte) (year & 0x00FF);
data[7] = (byte) (month & 0x00FF);
data[8] = (byte) (day & 0x00FF);
data[9] = (byte) (dayOfWeek & 0x00FF);
data[10] = (byte) (hour & 0x00FF);
data[11] = (byte) (minute & 0x00FF);
data[12] = (byte) (second & 0x00FF);
data[13] = (byte) (((signalLevel & 0x0F) << 4) | (batteryLevel & 0x0F));
return data;
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
if (channelId.equals(CHANNEL_DATE_TIME)) {
return new DateTimeType(dateTime);
} else {
return super.convertToState(channelId, deviceState);
}
}
@Override
public void convertFromState(String channelId, Type type) {
throw new UnsupportedOperationException();
}
@Override
public String getDeviceId() {
return String.valueOf(sensorId);
}
@Override
public void setDeviceId(String deviceId) {
throw new UnsupportedOperationException();
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
@Override
public void setSubType(SubType subType) {
this.subType = subType;
}
}

View File

@@ -0,0 +1,104 @@
/**
* Copyright (c) 2010-2020 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 org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfiguration;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
/**
* An interface for message about devices, so interface message do not (have to) implement this
*
* @author Martin van Wingerden - Initial contribution
*/
public interface RFXComDeviceMessage<T> extends RFXComMessage {
/**
* Procedure for converting RFXCOM value to openHAB command.
*
* @param channelId id of the channel
* @param deviceState
* @return openHAB command.
* @throws RFXComUnsupportedChannelException if the channel is not supported
*/
Command convertToCommand(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException;
/**
* Procedure for converting RFXCOM value to openHAB state.
*
* @param channelId id of the channel
* @param deviceState
* @return openHAB state.
* @throws RFXComUnsupportedChannelException if the channel is not supported
*/
State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException;
/**
* Procedure to get device id.
*
* @return device Id.
*/
String getDeviceId();
/**
* Get the packet type for this device message
*
* @return the message its packet type
*/
RFXComBaseMessage.PacketType getPacketType();
/**
* Given a DiscoveryResultBuilder add any new properties to the builder for the given message
*
* @param discoveryResultBuilder existing builder containing some early details
* @throws RFXComException
*/
void addDevicePropertiesTo(DiscoveryResultBuilder discoveryResultBuilder) throws RFXComException;
/**
* Procedure for converting sub type as string to sub type object.
*
* @param subType
* @return sub type object.
* @throws RFXComUnsupportedValueException if the given subType cannot be converted
*/
T convertSubType(String subType) throws RFXComUnsupportedValueException;
/**
* Procedure to set sub type.
*
* @param subType
*/
void setSubType(T subType);
/**
* Procedure to set device id.
*
* @param deviceId
* @throws RFXComException
*/
void setDeviceId(String deviceId) throws RFXComException;
/**
* Set the config to be applied to this message
*
* @param config
* @throws RFXComException
*/
@Override
void setConfig(RFXComDeviceConfiguration config) throws RFXComException;
}

View File

@@ -0,0 +1,124 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.CHANNEL_SIGNAL_LEVEL;
import org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfiguration;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
/**
* A base class for all device messages, so this is not about things as interface messages
*
* @author Martin van Wingerden - Initial contribution
*/
abstract class RFXComDeviceMessageImpl<T> extends RFXComBaseMessage implements RFXComDeviceMessage<T> {
byte signalLevel;
RFXComDeviceMessageImpl(PacketType packetType) {
super(packetType);
}
RFXComDeviceMessageImpl() {
// deliberately empty
}
@Override
public void setConfig(RFXComDeviceConfiguration config) throws RFXComException {
this.setSubType(convertSubType(config.subType));
this.setDeviceId(config.deviceId);
}
@Override
public Command convertToCommand(String channelId, DeviceState deviceState)
throws RFXComUnsupportedChannelException {
return (Command) convertToState(channelId, deviceState);
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_SIGNAL_LEVEL:
return convertSignalLevelToSystemWideLevel(signalLevel);
default:
throw new RFXComUnsupportedChannelException("Nothing relevant for " + channelId);
}
}
@Override
public void addDevicePropertiesTo(DiscoveryResultBuilder discoveryResultBuilder) throws RFXComException {
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);
}
/**
* Convert internal signal level (0-15) to system wide signal level (0-4).
*
* @param signalLevel Internal signal level
* @return Signal level in system wide level
*/
private State convertSignalLevelToSystemWideLevel(int signalLevel) {
int newLevel;
/*
* RFXCOM signal levels are always between 0-15.
*
* Use switch case to make level adaption easier in future if needed.
*/
switch (signalLevel) {
case 0:
case 1:
newLevel = 0;
break;
case 2:
case 3:
case 4:
newLevel = 1;
break;
case 5:
case 6:
case 7:
newLevel = 2;
break;
case 8:
case 9:
case 10:
case 11:
newLevel = 3;
break;
case 12:
case 13:
case 14:
case 15:
default:
newLevel = 4;
}
return new DecimalType(newLevel);
}
}

View File

@@ -0,0 +1,186 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for energy message.
*
* @author Unknown - Initial contribution
* @author Pauli Anttila
*/
public class RFXComEnergyMessage extends RFXComBatteryDeviceMessage<RFXComEnergyMessage.SubType> {
private static final double TOTAL_USAGE_CONVERSION_FACTOR = 223.666d;
private static final double WATTS_TO_AMPS_CONVERSION_FACTOR = 230d;
public enum SubType implements ByteEnumWrapper {
ELEC2(1),
ELEC3(2);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public SubType subType;
public int sensorId;
public byte count;
public double instantAmp;
public double totalAmpHour;
public double instantPower;
public double totalUsage;
public RFXComEnergyMessage() {
super(PacketType.ENERGY);
}
public RFXComEnergyMessage(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = "";
str += super.toString();
str += ", Sub type = " + subType;
str += ", Device Id = " + getDeviceId();
str += ", Count = " + count;
str += ", Instant Amps = " + instantAmp;
str += ", Total Amp Hours = " + totalAmpHour;
str += ", Signal level = " + signalLevel;
str += ", Battery level = " + batteryLevel;
str += ", Instant Power = " + instantPower;
str += ", Total Usage = " + totalUsage;
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[4] & 0xFF) << 8 | (data[5] & 0xFF);
count = data[6];
// all usage is reported in Watts based on 230V
instantPower = ((data[7] & 0xFF) << 24 | (data[8] & 0xFF) << 16 | (data[9] & 0xFF) << 8 | (data[10] & 0xFF));
totalUsage = ((long) (data[11] & 0xFF) << 40 | (long) (data[12] & 0xFF) << 32 | (data[13] & 0xFF) << 24
| (data[14] & 0xFF) << 16 | (data[15] & 0xFF) << 8 | (data[16] & 0xFF)) / TOTAL_USAGE_CONVERSION_FACTOR;
// convert to amps so external code can determine the watts based on local voltage
instantAmp = instantPower / WATTS_TO_AMPS_CONVERSION_FACTOR;
totalAmpHour = totalUsage / WATTS_TO_AMPS_CONVERSION_FACTOR;
signalLevel = (byte) ((data[17] & 0xF0) >> 4);
batteryLevel = (byte) (data[17] & 0x0F);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[18];
data[0] = 0x11;
data[1] = RFXComBaseMessage.PacketType.ENERGY.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((sensorId & 0xFF00) >> 8);
data[5] = (byte) (sensorId & 0x00FF);
data[6] = count;
// convert our 'amp' values back into Watts since this is what comes back
long instantUsage = (long) (instantAmp * WATTS_TO_AMPS_CONVERSION_FACTOR);
long totalUsage = (long) (totalAmpHour * WATTS_TO_AMPS_CONVERSION_FACTOR * TOTAL_USAGE_CONVERSION_FACTOR);
data[7] = (byte) ((instantUsage >> 24) & 0xFF);
data[8] = (byte) ((instantUsage >> 16) & 0xFF);
data[9] = (byte) ((instantUsage >> 8) & 0xFF);
data[10] = (byte) (instantUsage & 0xFF);
data[11] = (byte) ((totalUsage >> 40) & 0xFF);
data[12] = (byte) ((totalUsage >> 32) & 0xFF);
data[13] = (byte) ((totalUsage >> 24) & 0xFF);
data[14] = (byte) ((totalUsage >> 16) & 0xFF);
data[15] = (byte) ((totalUsage >> 8) & 0xFF);
data[16] = (byte) (totalUsage & 0xFF);
data[17] = (byte) (((signalLevel & 0x0F) << 4) | (batteryLevel & 0x0F));
return data;
}
@Override
public String getDeviceId() {
return String.valueOf(sensorId);
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_INSTANT_POWER:
return new DecimalType(instantPower);
case CHANNEL_TOTAL_USAGE:
return new DecimalType(totalUsage);
case CHANNEL_INSTANT_AMPS:
return new DecimalType(instantAmp);
case CHANNEL_TOTAL_AMP_HOUR:
return new DecimalType(totalAmpHour);
default:
return super.convertToState(channelId, deviceState);
}
}
@Override
public void setSubType(SubType subType) {
throw new UnsupportedOperationException();
}
@Override
public void setDeviceId(String deviceId) {
throw new UnsupportedOperationException();
}
@Override
public void convertFromState(String channelId, Type type) {
throw new UnsupportedOperationException();
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
}

View File

@@ -0,0 +1,444 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import static org.openhab.binding.rfxcom.internal.messages.RFXComFanMessage.Commands.*;
import static org.openhab.binding.rfxcom.internal.messages.RFXComFanMessage.SubType.*;
import java.util.Arrays;
import java.util.List;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.library.types.UpDownType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
import org.openhab.core.types.UnDefType;
/**
* RFXCOM data class for fan message.
*
* @author Martin van Wingerden - initial contribution
*/
public class RFXComFanMessage extends RFXComDeviceMessageImpl<RFXComFanMessage.SubType> {
public enum SubType implements ByteEnumWrapper {
SF01(0),
CVE_RFT(1),
LUCCI_AIR_FAN(2),
SEAV_TXS4(3),
WESTINGHOUSE_7226640(4),
LUCCI_AIR_DC(5),
CASAFAN(6),
FT1211R(7),
FALMEC(8),
LUCCI_AIR_DC_II(9);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public enum Commands implements ByteEnumWrapperWithSupportedSubTypes<SubType> {
HI(1, WESTINGHOUSE_7226640, CASAFAN, LUCCI_AIR_FAN),
MED(2, WESTINGHOUSE_7226640, CASAFAN, LUCCI_AIR_FAN),
LOW(3, WESTINGHOUSE_7226640, CASAFAN, LUCCI_AIR_FAN),
OFF(4, WESTINGHOUSE_7226640, CASAFAN, LUCCI_AIR_FAN),
LIGHT(5, WESTINGHOUSE_7226640, CASAFAN, LUCCI_AIR_FAN),
FALMEC_POWER_OFF(1, 0, FALMEC),
FALMEC_SPEED_1(2, 1, FALMEC),
FALMEC_SPEED_2(3, 2, FALMEC),
FALMEC_SPEED_3(4, 3, FALMEC),
FALMEC_SPEED_4(5, 4, FALMEC),
FALMEC_TIMER_1(6, FALMEC),
FALMEC_TIMER_2(7, FALMEC),
FALMEC_TIMER_3(8, FALMEC),
FALMEC_TIMER_4(9, FALMEC),
FALMEC_LIGHT_ON(10, FALMEC),
FALMEC_LIGHT_OFF(11, FALMEC),
FT1211R_POWER(1, 0, FT1211R),
FT1211R_LIGHT(2, FT1211R),
FT1211R_SPEED_1(3, 1, FT1211R),
FT1211R_SPEED_2(4, 2, FT1211R),
FT1211R_SPEED_3(5, 3, FT1211R),
FT1211R_SPEED_4(6, 4, FT1211R),
FT1211R_SPEED_5(7, 5, FT1211R),
FT1211R_FORWARD_REVERSE(8, FT1211R),
FT1211R_TIMER_1H(9, FT1211R),
FT1211R_TIMER_4H(10, FT1211R),
FT1211R_TIMER_8H(11, FT1211R),
LUCCI_AIR_DC_POWER(1, LUCCI_AIR_DC),
LUCCI_AIR_DC_UP(2, LUCCI_AIR_DC),
LUCCI_AIR_DC_DOWN(3, LUCCI_AIR_DC),
LUCCI_AIR_DC_LIGHT(4, LUCCI_AIR_DC),
LUCCI_AIR_DC_REVERSE(5, LUCCI_AIR_DC),
LUCCI_AIR_DC_NATURAL_FLOW(6, LUCCI_AIR_DC),
LUCCI_AIR_DC_PAIR(7, LUCCI_AIR_DC),
LUCCI_AIR_DC_II_POWER_OFF(1, 0, LUCCI_AIR_DC_II),
LUCCI_AIR_DC_II_SPEED_1(2, 1, LUCCI_AIR_DC_II),
LUCCI_AIR_DC_II_SPEED_2(3, 2, LUCCI_AIR_DC_II),
LUCCI_AIR_DC_II_SPEED_3(4, 3, LUCCI_AIR_DC_II),
LUCCI_AIR_DC_II_SPEED_4(5, 4, LUCCI_AIR_DC_II),
LUCCI_AIR_DC_II_SPEED_5(6, 5, LUCCI_AIR_DC_II),
LUCCI_AIR_DC_II_SPEED_6(7, 6, LUCCI_AIR_DC_II),
LUCCI_AIR_DC_II_LIGHT(8, LUCCI_AIR_DC_II),
LUCCI_AIR_DC_II_REVERSE(9, LUCCI_AIR_DC_II);
private final int command;
private final Integer speed;
private final List<SubType> supportedBySubTypes;
Commands(int command, SubType... supportedSubType) {
this(command, null, supportedSubType);
}
Commands(int command, Integer speed, SubType... supportedSubType) {
this.command = command;
this.speed = speed;
this.supportedBySubTypes = Arrays.asList(supportedSubType);
}
@Nullable
public static Commands bySpeed(SubType subType, int speed) {
for (Commands value : values()) {
if (value.supportedBySubTypes.contains(subType) && value.speed == speed) {
return value;
}
}
return null;
}
@Override
public byte toByte() {
return (byte) command;
}
public Integer getSpeed() {
return speed;
}
@Override
public List<SubType> supportedBySubTypes() {
return supportedBySubTypes;
}
}
private static final List<SubType> GENERIC_SUB_TYPES = Arrays.asList(WESTINGHOUSE_7226640, CASAFAN, LUCCI_AIR_FAN);
private static final List<Commands> LIGHT_ON_COMMANDS = Arrays.asList(LIGHT, LUCCI_AIR_DC_LIGHT,
LUCCI_AIR_DC_II_LIGHT, FALMEC_LIGHT_ON);
private static final List<Commands> ON_COMMANDS = Arrays.asList(Commands.HI, MED, LOW, FALMEC_SPEED_1,
FALMEC_SPEED_2, FALMEC_SPEED_3, FALMEC_SPEED_4, LUCCI_AIR_DC_II_SPEED_1, LUCCI_AIR_DC_II_SPEED_2,
LUCCI_AIR_DC_II_SPEED_3, LUCCI_AIR_DC_II_SPEED_4, LUCCI_AIR_DC_II_SPEED_5, LUCCI_AIR_DC_II_SPEED_6);
private static final List<Commands> OFF_COMMANDS = Arrays.asList(OFF, FALMEC_POWER_OFF, LUCCI_AIR_DC_II_POWER_OFF);
private SubType subType;
private int sensorId;
private Commands command;
public RFXComFanMessage() {
super(PacketType.FAN);
}
public RFXComFanMessage(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public PacketType getPacketType() {
switch (subType) {
case LUCCI_AIR_FAN:
case CASAFAN:
case WESTINGHOUSE_7226640:
return PacketType.FAN;
case SF01:
return PacketType.FAN_SF01;
case CVE_RFT:
return PacketType.FAN_ITHO;
case SEAV_TXS4:
return PacketType.FAN_SEAV;
case LUCCI_AIR_DC:
return PacketType.FAN_LUCCI_DC;
case FT1211R:
return PacketType.FAN_FT1211R;
case FALMEC:
return PacketType.FAN_FALMEC;
case LUCCI_AIR_DC_II:
return PacketType.FAN_LUCCI_DC_II;
}
return super.getPacketType();
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[4] & 0xFF) << 16 | (data[5] & 0xFF) << 8 | (data[6] & 0xFF);
command = fromByte(Commands.class, data[7], subType);
signalLevel = (byte) (data[8] & 0x0F);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[9];
data[0] = 0x08;
data[1] = PacketType.FAN.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((sensorId >> 16) & 0xFF);
data[5] = (byte) ((sensorId >> 8) & 0xFF);
data[6] = (byte) (sensorId & 0xFF);
data[7] = command.toByte();
data[8] = (byte) (signalLevel & 0x0F);
return data;
}
@Override
public String getDeviceId() {
return String.valueOf(sensorId);
}
@Override
public void setSubType(SubType subType) {
this.subType = subType;
}
@Override
public void setDeviceId(String deviceId) {
sensorId = Integer.parseInt(deviceId);
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_FAN_LIGHT:
return handleLightChannel();
case CHANNEL_FAN_SPEED:
return handleFanSpeedChannel();
case CHANNEL_COMMAND:
return handleCommandChannel();
case CHANNEL_COMMAND_STRING:
return handleCommandStringChannel();
default:
return super.convertToState(channelId, deviceState);
}
}
private State handleCommandStringChannel() {
if (command == null) {
return UnDefType.UNDEF;
}
return StringType.valueOf(command.toString().replace(subType.name() + "_", ""));
}
private State handleLightChannel() {
if (LIGHT_ON_COMMANDS.contains(command)) {
return OnOffType.ON;
} else if (command == Commands.FALMEC_LIGHT_OFF) {
return OnOffType.OFF;
} else {
return UnDefType.UNDEF;
}
}
private State handleFanSpeedChannel() {
switch (command) {
case HI:
case MED:
case LOW:
case OFF:
return StringType.valueOf(command.toString());
case FALMEC_POWER_OFF:
case FALMEC_SPEED_1:
case FALMEC_SPEED_2:
case FALMEC_SPEED_3:
case FALMEC_SPEED_4:
case FT1211R_POWER:
case FT1211R_SPEED_1:
case FT1211R_SPEED_2:
case FT1211R_SPEED_3:
case FT1211R_SPEED_4:
case FT1211R_SPEED_5:
case LUCCI_AIR_DC_II_POWER_OFF:
case LUCCI_AIR_DC_II_SPEED_1:
case LUCCI_AIR_DC_II_SPEED_2:
case LUCCI_AIR_DC_II_SPEED_3:
case LUCCI_AIR_DC_II_SPEED_4:
case LUCCI_AIR_DC_II_SPEED_5:
case LUCCI_AIR_DC_II_SPEED_6:
return new DecimalType(command.getSpeed());
case LUCCI_AIR_DC_DOWN:
return UpDownType.DOWN;
case LUCCI_AIR_DC_UP:
return UpDownType.UP;
default:
return null;
}
}
private State handleCommandChannel() {
if (ON_COMMANDS.contains(command)) {
return OnOffType.ON;
} else if (OFF_COMMANDS.contains(command)) {
return OnOffType.OFF;
} else {
return null;
}
}
@Override
public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_COMMAND:
command = handleCommand(channelId, type);
break;
case CHANNEL_FAN_SPEED:
command = handleFanSpeedCommand(channelId, type);
break;
case CHANNEL_FAN_LIGHT:
command = handleFanLightCommand(channelId, type);
break;
case CHANNEL_COMMAND_STRING:
command = handleCommandString(channelId, type);
break;
default:
throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
}
}
private Commands handleCommandString(String channelId, Type type) throws RFXComUnsupportedChannelException {
if (type instanceof StringType) {
String stringCommand = type.toString();
switch (stringCommand) {
case "POWER":
case "POWER_OFF":
case "UP":
case "DOWN":
case "LIGHT":
case "REVERSE":
case "NATURAL_FLOW":
case "PAIR":
case "SPEED_1":
case "SPEED_2":
case "SPEED_3":
case "SPEED_4":
case "SPEED_5":
case "SPEED_6":
return Commands.valueOf(subType.name() + "_" + stringCommand);
}
}
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
private Commands handleCommand(String channelId, Type type) throws RFXComUnsupportedChannelException {
if (type instanceof OnOffType) {
if (GENERIC_SUB_TYPES.contains(subType)) {
return (type == OnOffType.ON ? Commands.MED : Commands.OFF);
} else if (subType == FALMEC) {
return (type == OnOffType.ON ? Commands.FALMEC_SPEED_2 : Commands.FALMEC_POWER_OFF);
} else if (subType == LUCCI_AIR_DC_II) {
return (type == OnOffType.ON ? LUCCI_AIR_DC_II_SPEED_3 : LUCCI_AIR_DC_II_POWER_OFF);
}
}
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
private Commands handleFanSpeedCommand(String channelId, Type type) throws RFXComUnsupportedChannelException {
if (type instanceof StringType) {
String stringCommand = type.toString();
switch (stringCommand) {
case "HI":
case "MED":
case "LOW":
case "OFF":
return Commands.valueOf(stringCommand);
}
} else if (type instanceof DecimalType) {
Commands speedCommand = Commands.bySpeed(subType, ((DecimalType) type).intValue());
if (speedCommand != null) {
return speedCommand;
}
} else if (type instanceof UpDownType && subType == LUCCI_AIR_DC) {
if (UpDownType.UP == type) {
return Commands.LUCCI_AIR_DC_UP;
} else {
return Commands.LUCCI_AIR_DC_DOWN;
}
}
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
private Commands handleFanLightCommand(String channelId, Type type) throws RFXComUnsupportedChannelException {
if (type == OnOffType.ON) {
switch (subType) {
case LUCCI_AIR_FAN:
case CASAFAN:
case WESTINGHOUSE_7226640:
case LUCCI_AIR_DC:
return LIGHT;
case FALMEC:
return FALMEC_LIGHT_ON;
case LUCCI_AIR_DC_II:
return LUCCI_AIR_DC_II_LIGHT;
}
} else if (type == OnOffType.OFF && subType == FALMEC) {
return Commands.FALMEC_LIGHT_OFF;
}
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
}

View File

@@ -0,0 +1,176 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.CHANNEL_COMMAND;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for HomeConfort message.
*
* @author Mike Jagdis - Initial contribution
*/
public class RFXComHomeConfortMessage extends RFXComDeviceMessageImpl<RFXComHomeConfortMessage.SubType> {
public enum SubType implements ByteEnumWrapper {
TEL_010(0);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public enum Commands implements ByteEnumWrapper {
OFF(0),
ON(1),
GROUP_OFF(2),
GROUP_ON(3);
private final int command;
Commands(int command) {
this.command = command;
}
@Override
public byte toByte() {
return (byte) command;
}
}
public SubType subType;
public int deviceId;
public char houseCode;
public byte unitCode;
public Commands command;
public RFXComHomeConfortMessage() {
super(PacketType.HOME_CONFORT);
}
public RFXComHomeConfortMessage(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
return super.toString() + ", Sub type = " + subType + ", Device Id = " + getDeviceId() + ", Command = "
+ command + ", Signal level = " + signalLevel;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
deviceId = (((data[4] << 8) | data[5]) << 8) | data[6];
houseCode = (char) data[7];
unitCode = data[8];
command = fromByte(Commands.class, data[9]);
if (command == Commands.GROUP_ON || command == Commands.GROUP_OFF) {
unitCode = 0;
}
signalLevel = (byte) ((data[12] & 0xF0) >> 4);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[13];
data[0] = 0x0C;
data[1] = PacketType.HOME_CONFORT.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((deviceId >> 16) & 0xff);
data[5] = (byte) ((deviceId >> 8) & 0xff);
data[6] = (byte) (deviceId & 0xff);
data[7] = (byte) houseCode;
data[8] = unitCode;
data[9] = command.toByte();
data[10] = 0;
data[11] = 0;
data[12] = (byte) ((signalLevel & 0x0F) << 4);
return data;
}
@Override
public String getDeviceId() {
return deviceId + ID_DELIMITER + houseCode + ID_DELIMITER + unitCode;
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
if (channelId.equals(CHANNEL_COMMAND)) {
return (command == Commands.OFF || command == Commands.GROUP_OFF ? OnOffType.OFF : OnOffType.ON);
} else {
return super.convertToState(channelId, deviceState);
}
}
@Override
public void setSubType(SubType subType) {
this.subType = subType;
}
@Override
public void setDeviceId(String deviceId) throws RFXComException {
String[] ids = deviceId.split("\\" + ID_DELIMITER);
if (ids.length != 3) {
throw new RFXComException("Invalid device id '" + deviceId + "'");
}
this.deviceId = Integer.parseInt(ids[0]);
houseCode = ids[1].charAt(0);
unitCode = Byte.parseByte(ids[2]);
}
@Override
public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
if (CHANNEL_COMMAND.equals(channelId)) {
if (type instanceof OnOffType) {
if (unitCode == 0) {
command = (type == OnOffType.ON ? Commands.GROUP_ON : Commands.GROUP_OFF);
} else {
command = (type == OnOffType.ON ? Commands.ON : Commands.OFF);
}
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
}
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
}

View File

@@ -0,0 +1,164 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for humidity message.
*
* @author Pauli Anttila - Initial contribution
*/
public class RFXComHumidityMessage extends RFXComBatteryDeviceMessage<RFXComHumidityMessage.SubType> {
public enum SubType implements ByteEnumWrapper {
HUM1(1),
HUM2(2),
HUM3(3);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public enum HumidityStatus implements ByteEnumWrapper {
NORMAL(0),
COMFORT(1),
DRY(2),
WET(3);
private final int humidityStatus;
HumidityStatus(int humidityStatus) {
this.humidityStatus = humidityStatus;
}
@Override
public byte toByte() {
return (byte) humidityStatus;
}
}
public SubType subType;
public int sensorId;
public byte humidity;
public HumidityStatus humidityStatus;
public RFXComHumidityMessage() {
super(PacketType.HUMIDITY);
}
public RFXComHumidityMessage(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = "";
str += super.toString();
str += ", Sub type = " + subType;
str += ", Device Id = " + getDeviceId();
str += ", Humidity = " + humidity;
str += ", Humidity status = " + humidityStatus;
str += ", Signal level = " + signalLevel;
str += ", Battery level = " + batteryLevel;
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[4] & 0xFF) << 8 | (data[5] & 0xFF);
humidity = data[6];
humidityStatus = fromByte(HumidityStatus.class, data[7]);
signalLevel = (byte) ((data[8] & 0xF0) >> 4);
batteryLevel = (byte) (data[8] & 0x0F);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[9];
data[0] = 0x08;
data[1] = RFXComBaseMessage.PacketType.HUMIDITY.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((sensorId & 0xFF00) >> 8);
data[5] = (byte) (sensorId & 0x00FF);
data[6] = humidity;
data[7] = humidityStatus.toByte();
data[8] = (byte) (((signalLevel & 0x0F) << 4) | (batteryLevel & 0x0F));
return data;
}
@Override
public String getDeviceId() {
return String.valueOf(sensorId);
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_HUMIDITY:
return new DecimalType(humidity);
case CHANNEL_HUMIDITY_STATUS:
return new StringType(humidityStatus.toString());
default:
return super.convertToState(channelId, deviceState);
}
}
@Override
public void setSubType(SubType subType) {
throw new UnsupportedOperationException();
}
@Override
public void setDeviceId(String deviceId) {
throw new UnsupportedOperationException();
}
@Override
public void convertFromState(String channelId, Type type) {
throw new UnsupportedOperationException();
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
}

View File

@@ -0,0 +1,97 @@
/**
* Copyright (c) 2010-2020 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 org.openhab.binding.rfxcom.internal.config.RFXComBridgeConfiguration;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for control message.
*
* @author Pauli Anttila - Initial contribution
* @author Mike Jagdis
*/
public class RFXComInterfaceControlMessage extends RFXComBaseMessage {
private byte[] data = new byte[14];
public RFXComInterfaceControlMessage(RFXComInterfaceMessage.TransceiverType transceiverType,
RFXComBridgeConfiguration configuration) {
data[0] = 0x0D;
data[1] = RFXComBaseMessage.PacketType.INTERFACE_CONTROL.toByte();
data[2] = 0;
data[3] = 2;
data[4] = RFXComInterfaceMessage.Commands.SET_MODE.toByte();
data[5] = transceiverType.toByte();
data[6] = (byte) (configuration.transmitPower + 18);
//@formatter:off
data[7] = (byte) (
(configuration.enableUndecoded ? 0x80 : 0x00)
| (configuration.enableImagintronixOpus ? 0x40 : 0x00)
| (configuration.enableByronSX ? 0x20 : 0x00)
| (configuration.enableRSL ? 0x10 : 0x00)
| (configuration.enableLighting4 ? 0x08 : 0x00)
| (configuration.enableFineOffsetViking ? 0x04 : 0x00)
| (configuration.enableRubicson ? 0x02 : 0x00)
| (configuration.enableAEBlyss ? 0x01 : 0x00));
data[8] = (byte) (
(configuration.enableBlindsT1T2T3T4 ? 0x80 : 0x00)
| (configuration.enableBlindsT0 ? 0x40 : 0x00)
| (configuration.enableProGuard ? 0x20 : 0x00)
| (configuration.enableFS20 ? 0x10 : 0x00)
| (configuration.enableLaCrosse ? 0x08 : 0x00)
| (configuration.enableHidekiUPM ? 0x04 : 0x00)
| (configuration.enableADLightwaveRF ? 0x02 : 0x00)
| (configuration.enableMertik ? 0x01 : 0x00));
data[9] = (byte) (
(configuration.enableVisonic ? 0x80 : 0x00)
| (configuration.enableATI ? 0x40 : 0x00)
| (configuration.enableOregonScientific ? 0x20 : 0x00)
| (configuration.enableMeiantech ? 0x10 : 0x00)
| (configuration.enableHomeEasyEU ? 0x08 : 0x00)
| (configuration.enableAC ? 0x04 : 0x00)
| (configuration.enableARC ? 0x02 : 0x00)
| (configuration.enableX10 ? 0x01 : 0x00));
data[10] = (byte) (
(configuration.enableHomeConfort ? 0x02 : 0x00)
| (configuration.enableKEELOQ ? 0x01 : 0x00));
data[11] = 0;
data[12] = 0;
data[13] = 0;
//@formatter:on
}
public RFXComInterfaceControlMessage(byte[] data) {
// We should never receive control messages
throw new UnsupportedOperationException();
}
@Override
public byte[] decodeMessage() {
return data;
}
@Override
public void encodeMessage(byte[] data) {
throw new UnsupportedOperationException();
}
@Override
public void convertFromState(String channelId, Type type) {
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,311 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import java.nio.charset.StandardCharsets;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for interface message.
*
* @author Pauli Anttila - Initial contribution
* @author Ivan Martinez - Older firmware support (OH1)
*/
public class RFXComInterfaceMessage extends RFXComBaseMessage {
public enum SubType implements ByteEnumWrapper {
UNKNOWN_COMMAND(-1),
RESPONSE(0),
UNKNOWN_RTS_REMOTE(1),
NO_EXTENDED_HW_PRESENT(2),
LIST_RFY_REMOTES(3),
LIST_ASA_REMOTES(4),
START_RECEIVER(7);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public enum Commands implements ByteEnumWrapper {
RESET(0), // Reset the receiver/transceiver. No answer is transmitted!
GET_STATUS(2), // Get Status, return firmware versions and configuration of the interface
SET_MODE(3), // Set mode msg1-msg5, return firmware versions and configuration of the interface
ENABLE_ALL(4), // Enable all receiving modes of the receiver/transceiver
ENABLE_UNDECODED_PACKETS(5), // Enable reporting of undecoded packets
SAVE_RECEIVING_MODES(6), // Save receiving modes of the receiver/transceiver in non-volatile memory
START_RECEIVER(7), // Start RFXtrx receiver
T1(8), // For internal use by RFXCOM
T2(9), // For internal use by RFXCOM
UNSUPPORTED_COMMAND(-1); // wrong command received from the application
private final int command;
Commands(int command) {
this.command = command;
}
@Override
public byte toByte() {
return (byte) command;
}
}
public enum TransceiverType implements ByteEnumWrapper {
_310MHZ(80),
_315MHZ(81),
_433_92MHZ_RECEIVER_ONLY(82),
_433_92MHZ_TRANSCEIVER(83),
_868_00MHZ(85),
_868_00MHZ_FSK(86),
_868_30MHZ(87),
_868_30MHZ_FSK(88),
_868_35MHZ(89),
_868_35MHZ_FSK(90),
_868_95MHZ_FSK(91);
private final int type;
TransceiverType(int type) {
this.type = type;
}
@Override
public byte toByte() {
return (byte) type;
}
}
public enum FirmwareType implements ByteEnumWrapper {
TYPE1_RX_ONLY(0),
TYPE1(1),
TYPE2(2),
EXT(3),
EXT2(4);
private final int type;
FirmwareType(int type) {
this.type = type;
}
@Override
public byte toByte() {
return (byte) type;
}
}
public SubType subType;
public Commands command;
public String text = "";
public TransceiverType transceiverType;
public int firmwareVersion;
public boolean enableUndecodedPackets; // 0x80 - Undecoded packets
public boolean enableImagintronixOpusPackets; // 0x40 - Imagintronix/Opus (433.92)
public boolean enableByronSXPackets; // 0x20 - Byron SX (433.92)
public boolean enableRSLPackets; // 0x10 - RSL (433.92)
public boolean enableLighting4Packets; // 0x08 - Lighting4 (433.92)
public boolean enableFineOffsetPackets; // 0x04 - FineOffset / Viking (433.92)
public boolean enableRubicsonPackets; // 0x02 - Rubicson (433.92)
public boolean enableAEPackets; // 0x01 - AE (433.92)
public boolean enableBlindsT1T2T3T4Packets; // 0x80 - BlindsT1/T2/T3/T4 (433.92)
public boolean enableBlindsT0Packets; // 0x40 - BlindsT0 (433.92)
public boolean enableProGuardPackets; // 0x20 - ProGuard (868.35 FSK)
public boolean enableFS20Packets; // 0x10 - FS20 (868.35)
public boolean enableLaCrossePackets; // 0x08 - La Crosse (433.92/868.30)
public boolean enableHidekiUPMPackets; // 0x04 - Hideki/UPM (433.92)
public boolean enableADPackets; // 0x02 - AD LightwaveRF (433.92)
public boolean enableMertikPackets; // 0x01 - Mertik (433.92)
public boolean enableVisonicPackets; // 0x80 - Visonic (315/868.95)
public boolean enableATIPackets; // 0x40 - ATI (433.92)
public boolean enableOregonPackets; // 0x20 - Oregon Scientific (433.92)
public boolean enableMeiantechPackets; // 0x10 - Meiantech (433.92)
public boolean enableHomeEasyPackets; // 0x08 - HomeEasy EU (433.92)
public boolean enableACPackets; // 0x04 - AC (433.92)
public boolean enableARCPackets; // 0x02 - ARC (433.92)
public boolean enableX10Packets; // 0x01 - X10 (310/433.92)
public boolean enableHomeConfortPackets; // 0x02 - HomeConfort (433.92)
public boolean enableKEELOQPackets; // 0x01 - KEELOQ (433.92)
public byte hardwareVersion1;
public byte hardwareVersion2;
public int outputPower; // -18dBm to +13dBm. N.B. maximum allowed is +10dBm
public FirmwareType firmwareType;
public RFXComInterfaceMessage(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = "";
str += super.toString();
str += ", Sub type = " + subType;
str += ", Command = " + command;
if (subType == SubType.RESPONSE) {
str += ", Transceiver type = " + transceiverType;
str += ", Hardware version = " + hardwareVersion1 + "." + hardwareVersion2;
str += ", Firmware type = " + (firmwareType != null ? firmwareType : "unknown");
str += ", Firmware version = " + firmwareVersion;
str += ", Output power = " + outputPower + "dBm";
str += ", Undecoded packets = " + enableUndecodedPackets;
str += ", RFU6 packets = " + enableImagintronixOpusPackets;
str += ", Byron SX packets packets (433.92) = " + enableByronSXPackets;
str += ", RSL packets packets (433.92) = " + enableRSLPackets;
str += ", Lighting4 packets (433.92) = " + enableLighting4Packets;
str += ", FineOffset / Viking (433.92) packets = " + enableFineOffsetPackets;
str += ", Rubicson (433.92) packets = " + enableRubicsonPackets;
str += ", AE (433.92) packets = " + enableAEPackets;
str += ", BlindsT1/T2/T3 (433.92) packets = " + enableBlindsT1T2T3T4Packets;
str += ", BlindsT0 (433.92) packets = " + enableBlindsT0Packets;
str += ", ProGuard (868.35 FSK) packets = " + enableProGuardPackets;
str += ", FS20/Legrand CAD (868.35/433.92) packets = " + enableFS20Packets;
str += ", La Crosse (433.92/868.30) packets = " + enableLaCrossePackets;
str += ", Hideki/UPM (433.92) packets = " + enableHidekiUPMPackets;
str += ", AD LightwaveRF (433.92) packets = " + enableADPackets;
str += ", Mertik (433.92) packets = " + enableMertikPackets;
str += ", Visonic (315/868.95) packets = " + enableVisonicPackets;
str += ", ATI (433.92) packets = " + enableATIPackets;
str += ", Oregon Scientific (433.92) packets = " + enableOregonPackets;
str += ", Meiantech (433.92) packets = " + enableMeiantechPackets;
str += ", HomeEasy EU (433.92) packets = " + enableHomeEasyPackets;
str += ", AC (433.92) packets = " + enableACPackets;
str += ", ARC (433.92) packets = " + enableARCPackets;
str += ", X10 (310/433.92) packets = " + enableX10Packets;
str += ", HomeConfort (433.92) packets = " + enableHomeConfortPackets;
str += ", KEELOQ (433.92/868.95) packets = " + enableKEELOQPackets;
} else if (subType == SubType.START_RECEIVER) {
str += ", Text = " + text;
}
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
if (subType == SubType.RESPONSE) {
command = fromByte(Commands.class, data[4]);
transceiverType = fromByte(TransceiverType.class, data[5]);
firmwareVersion = data[6] & 0xFF;
enableUndecodedPackets = (data[7] & 0x80) != 0;
enableImagintronixOpusPackets = (data[7] & 0x40) != 0;
enableByronSXPackets = (data[7] & 0x20) != 0;
enableRSLPackets = (data[7] & 0x10) != 0;
enableLighting4Packets = (data[7] & 0x08) != 0;
enableFineOffsetPackets = (data[7] & 0x04) != 0;
enableRubicsonPackets = (data[7] & 0x02) != 0;
enableAEPackets = (data[7] & 0x01) != 0;
enableBlindsT1T2T3T4Packets = (data[8] & 0x80) != 0;
enableBlindsT0Packets = (data[8] & 0x40) != 0;
enableProGuardPackets = (data[8] & 0x20) != 0;
enableFS20Packets = (data[8] & 0x10) != 0;
enableLaCrossePackets = (data[8] & 0x08) != 0;
enableHidekiUPMPackets = (data[8] & 0x04) != 0;
enableADPackets = (data[8] & 0x02) != 0;
enableMertikPackets = (data[8] & 0x01) != 0;
enableVisonicPackets = (data[9] & 0x80) != 0;
enableATIPackets = (data[9] & 0x40) != 0;
enableOregonPackets = (data[9] & 0x20) != 0;
enableMeiantechPackets = (data[9] & 0x10) != 0;
enableHomeEasyPackets = (data[9] & 0x08) != 0;
enableACPackets = (data[9] & 0x04) != 0;
enableARCPackets = (data[9] & 0x02) != 0;
enableX10Packets = (data[9] & 0x01) != 0;
/*
* Different firmware versions have slightly different message formats.
* The firmware version numbering is unique to each hardware version
* but the location of the hardware version in the message is one of
* those things whose position varies. So we have to just look at the
* firmware version and pray. This condition below is taken from the
* openhab1-addons binding.
*/
if ((firmwareVersion >= 95 && firmwareVersion <= 100) || (firmwareVersion >= 195 && firmwareVersion <= 200)
|| (firmwareVersion >= 251)) {
enableHomeConfortPackets = (data[10] & 0x02) != 0;
enableKEELOQPackets = (data[10] & 0x01) != 0;
hardwareVersion1 = data[11];
hardwareVersion2 = data[12];
outputPower = data[13] - 18;
firmwareType = fromByte(FirmwareType.class, data[14]);
} else {
hardwareVersion1 = data[10];
hardwareVersion2 = data[11];
}
text = "";
} else if (subType == SubType.START_RECEIVER) {
command = fromByte(Commands.class, data[4]);
final int len = 16;
final int dataOffset = 5;
byte[] byteArray = new byte[len];
for (int i = dataOffset; i < (dataOffset + len); i++) {
byteArray[i - dataOffset] += data[i];
}
text = new String(byteArray, StandardCharsets.US_ASCII);
} else {
// We don't handle the other subTypes but to avoid null pointer
// exceptions we set command to something. It doesn't really
// matter what but it may b printed in log messages so...
command = Commands.UNSUPPORTED_COMMAND;
}
}
@Override
public byte[] decodeMessage() {
throw new UnsupportedOperationException();
}
@Override
public void convertFromState(String channelId, Type type) {
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,294 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.IncreaseDecreaseType;
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.Command;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
import org.openhab.core.types.UnDefType;
/**
* RFXCOM data class for lighting1 message. See X10, ARC, etc..
*
* @author Evert van Es, Cycling Engineer - Initial contribution
* @author Pauli Anttila
*/
public class RFXComLighting1Message extends RFXComDeviceMessageImpl<RFXComLighting1Message.SubType> {
public enum SubType implements ByteEnumWrapper {
X10(0),
ARC(1),
AB400D(2),
WAVEMAN(3),
EMW200(4),
IMPULS(5),
RISINGSUN(6),
PHILIPS(7),
ENERGENIE(8),
ENERGENIE_5(9),
COCO(10),
HQ_COCO20(11);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public enum Commands implements ByteEnumWrapper {
OFF(0),
ON(1),
DIM(2),
BRIGHT(3),
GROUP_OFF(5),
GROUP_ON(6),
CHIME(7);
private final int command;
Commands(int command) {
this.command = command;
}
@Override
public byte toByte() {
return (byte) command;
}
}
public SubType subType;
public char houseCode;
public byte unitCode;
public Commands command;
public boolean group;
private static byte[] lastUnit = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
public RFXComLighting1Message() {
super(PacketType.LIGHTING1);
}
public RFXComLighting1Message(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = "";
str += super.toString();
str += ", Sub type = " + subType;
str += ", Device Id = " + getDeviceId();
str += ", Command = " + command;
str += ", Signal level = " + signalLevel;
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = ByteEnumUtil.fromByte(SubType.class, super.subType);
houseCode = (char) data[4];
command = ByteEnumUtil.fromByte(Commands.class, data[6]);
if ((command == Commands.GROUP_ON) || (command == Commands.GROUP_OFF)) {
unitCode = 0;
} else if ((data[5] == 0) && ((command == Commands.DIM) || (command == Commands.BRIGHT))) {
// SS13 switches broadcast DIM/BRIGHT to X0 and the dimmers ignore
// the message unless the last X<n> ON they saw was for them. So we
// redirect an incoming broadcast DIM/BRIGHT to the correct item
// based on the last X<n> we saw or sent.
unitCode = lastUnit[(int) houseCode - (int) 'A'];
} else {
unitCode = data[5];
if (command == Commands.ON) {
lastUnit[(int) houseCode - (int) 'A'] = unitCode;
}
}
signalLevel = (byte) ((data[7] & 0xF0) >> 4);
}
@Override
public byte[] decodeMessage() {
// Example data 07 10 01 00 42 01 01 70
// 07 10 01 00 42 10 06 70
byte[] data = new byte[8];
data[0] = 0x07;
data[1] = PacketType.LIGHTING1.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) houseCode;
data[5] = unitCode;
data[6] = command.toByte();
data[7] = (byte) ((signalLevel & 0x0F) << 4);
return data;
}
@Override
public String getDeviceId() {
return houseCode + ID_DELIMITER + unitCode;
}
@Override
public Command convertToCommand(String channelId, DeviceState deviceState)
throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_COMMAND:
switch (command) {
case OFF:
case GROUP_OFF:
return OnOffType.OFF;
case ON:
case GROUP_ON:
return OnOffType.ON;
case DIM:
return IncreaseDecreaseType.DECREASE;
case BRIGHT:
return IncreaseDecreaseType.INCREASE;
case CHIME:
return OnOffType.ON;
default:
throw new RFXComUnsupportedChannelException(
"Channel " + channelId + " does not accept " + command);
}
default:
return super.convertToCommand(channelId, deviceState);
}
}
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_COMMAND:
switch (command) {
case OFF:
case GROUP_OFF:
case DIM:
return OnOffType.OFF;
case ON:
case GROUP_ON:
case BRIGHT:
case CHIME:
return OnOffType.ON;
default:
throw new RFXComUnsupportedChannelException(
"Channel " + channelId + " does not accept " + command);
}
case CHANNEL_COMMAND_STRING:
return command == null ? UnDefType.UNDEF : StringType.valueOf(command.toString());
case CHANNEL_CONTACT:
switch (command) {
case OFF:
case GROUP_OFF:
case DIM:
return OpenClosedType.CLOSED;
case ON:
case GROUP_ON:
case BRIGHT:
case CHIME:
return OpenClosedType.OPEN;
default:
throw new RFXComUnsupportedChannelException(
"Channel " + channelId + " does not accept " + command);
}
default:
throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
}
}
@Override
public void setSubType(SubType subType) {
this.subType = subType;
}
@Override
public void setDeviceId(String deviceId) throws RFXComException {
String[] ids = deviceId.split("\\" + ID_DELIMITER);
if (ids.length != 2) {
throw new RFXComException("Invalid device id '" + deviceId + "'");
}
houseCode = ids[0].charAt(0);
// Get unitcode, 0 means group
unitCode = Byte.parseByte(ids[1]);
if (unitCode == 0) {
unitCode = 1;
group = true;
}
}
@Override
public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_COMMAND:
if (type instanceof OnOffType) {
if (group) {
command = (type == OnOffType.ON ? Commands.GROUP_ON : Commands.GROUP_OFF);
} else {
command = (type == OnOffType.ON ? Commands.ON : Commands.OFF);
}
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
break;
case CHANNEL_COMMAND_STRING:
command = Commands.valueOf(type.toString().toUpperCase());
break;
default:
throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
}
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
}

View File

@@ -0,0 +1,288 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import static org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage.PacketType.LIGHTING2;
import static org.openhab.binding.rfxcom.internal.messages.RFXComLighting2Message.Commands.*;
import java.math.BigDecimal;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.IncreaseDecreaseType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for lighting2 message.
*
* @author Pauli Anttila - Initial contribution
*/
public class RFXComLighting2Message extends RFXComDeviceMessageImpl<RFXComLighting2Message.SubType> {
public enum SubType implements ByteEnumWrapper {
AC(0),
HOME_EASY_EU(1),
ANSLUT(2),
KAMBROOK(3);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public enum Commands implements ByteEnumWrapper {
OFF(0),
ON(1),
SET_LEVEL(2),
GROUP_OFF(3),
GROUP_ON(4),
SET_GROUP_LEVEL(5);
private final int command;
Commands(int command) {
this.command = command;
}
@Override
public byte toByte() {
return (byte) command;
}
}
public SubType subType;
public int sensorId;
public byte unitCode;
public Commands command;
public byte dimmingLevel;
public boolean group;
public RFXComLighting2Message() {
super(PacketType.LIGHTING2);
}
public RFXComLighting2Message(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = "";
str += super.toString();
str += ", Sub type = " + subType;
str += ", Device Id = " + getDeviceId();
str += ", Command = " + command;
str += ", Dim level = " + dimmingLevel;
str += ", Signal level = " + signalLevel;
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[4] & 0xFF) << 24 | (data[5] & 0xFF) << 16 | (data[6] & 0xFF) << 8 | (data[7] & 0xFF);
command = fromByte(Commands.class, data[9]);
if ((command == Commands.GROUP_ON) || (command == Commands.GROUP_OFF)) {
unitCode = 0;
} else {
unitCode = data[8];
}
dimmingLevel = data[10];
signalLevel = (byte) ((data[11] & 0xF0) >> 4);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[12];
data[0] = 0x0B;
data[1] = LIGHTING2.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((sensorId >> 24) & 0xFF);
data[5] = (byte) ((sensorId >> 16) & 0xFF);
data[6] = (byte) ((sensorId >> 8) & 0xFF);
data[7] = (byte) (sensorId & 0xFF);
data[8] = unitCode;
data[9] = command.toByte();
data[10] = dimmingLevel;
data[11] = (byte) ((signalLevel & 0x0F) << 4);
return data;
}
@Override
public String getDeviceId() {
return sensorId + ID_DELIMITER + unitCode;
}
/**
* Convert a 0-15 scale value to a percent type.
*
* @param pt percent type to convert
* @return converted value 0-15
*/
public static int getDimLevelFromPercentType(PercentType pt) {
return pt.toBigDecimal().multiply(BigDecimal.valueOf(15))
.divide(PercentType.HUNDRED.toBigDecimal(), 0, BigDecimal.ROUND_UP).intValue();
}
/**
* Convert a 0-15 scale value to a percent type.
*
* @param value percent type to convert
* @return converted value 0-15
*/
public static PercentType getPercentTypeFromDimLevel(int value) {
value = Math.min(value, 15);
return new PercentType(BigDecimal.valueOf(value).multiply(BigDecimal.valueOf(100))
.divide(BigDecimal.valueOf(15), 0, BigDecimal.ROUND_UP).intValue());
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_DIMMING_LEVEL:
return RFXComLighting2Message.getPercentTypeFromDimLevel(dimmingLevel);
case CHANNEL_COMMAND:
switch (command) {
case OFF:
case GROUP_OFF:
return OnOffType.OFF;
case ON:
case GROUP_ON:
return OnOffType.ON;
case SET_GROUP_LEVEL:
case SET_LEVEL:
default:
throw new RFXComUnsupportedChannelException("Can't convert " + command + " for " + channelId);
}
case CHANNEL_CONTACT:
switch (command) {
case OFF:
case GROUP_OFF:
return OpenClosedType.CLOSED;
case ON:
case GROUP_ON:
return OpenClosedType.OPEN;
case SET_GROUP_LEVEL:
case SET_LEVEL:
default:
throw new RFXComUnsupportedChannelException("Can't convert " + command + " for " + channelId);
}
default:
return super.convertToState(channelId, deviceState);
}
}
@Override
public void setSubType(SubType subType) {
this.subType = subType;
}
@Override
public void setDeviceId(String deviceId) throws RFXComException {
String[] ids = deviceId.split("\\" + ID_DELIMITER);
if (ids.length != 2) {
throw new RFXComException("Invalid device id '" + deviceId + "'");
}
sensorId = Integer.parseInt(ids[0]);
// Get unitcode, 0 means group
unitCode = Byte.parseByte(ids[1]);
if (unitCode == 0) {
unitCode = 1;
group = true;
}
}
@Override
public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_COMMAND:
if (type instanceof OnOffType) {
if (group) {
command = (type == OnOffType.ON ? GROUP_ON : GROUP_OFF);
} else {
command = (type == OnOffType.ON ? Commands.ON : Commands.OFF);
}
dimmingLevel = 0;
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
break;
case CHANNEL_DIMMING_LEVEL:
if (type instanceof OnOffType) {
command = (type == OnOffType.ON ? Commands.ON : Commands.OFF);
dimmingLevel = 0;
} else if (type instanceof PercentType) {
command = Commands.SET_LEVEL;
dimmingLevel = (byte) getDimLevelFromPercentType((PercentType) type);
if (dimmingLevel == 0) {
command = Commands.OFF;
}
} else if (type instanceof IncreaseDecreaseType) {
command = Commands.SET_LEVEL;
// Evert: I do not know how to get previous object state...
dimmingLevel = 5;
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
break;
default:
throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
}
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
}

View File

@@ -0,0 +1,289 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfiguration.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfiguration;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* RFXCOM data class for lighting4 message.
*
* a Lighting4 Base command is composed of 24 bit DATA plus PULSE information
*
* DATA:
* Code = 014554
* S1- S24 = <0000 0001 0100 0101 0101> <0100>
* first 20 are DeviceID last 4 are for Command
*
* PULSE:
* default 350
*
* Tested on a PT2262 remote PlugIn module
*
* Example:
*
* Switch TESTout "TestOut" (All) {rfxcom=">83205.350:LIGHTING4.PT2262:Command"}
* (SendCommand DeviceID(int).Pulse(int):LIGHTING4.Subtype:Command )
*
* Switch TESTin "TestIn" (All) {rfxcom="<83205:Command"}
* (ReceiveCommand ON/OFF Command )
*
* @author Alessandro Ballini (ITA) - Initial contribution
* @author Pauli Anttila - Migrated to OH2
* @author Martin van Wingerden - Extended support for more complex PT2262 devices
*/
public class RFXComLighting4Message extends RFXComDeviceMessageImpl<RFXComLighting4Message.SubType> {
// this logger is used from a static context, so is static as well
private static final Logger LOGGER = LoggerFactory.getLogger(RFXComLighting4Message.class);
private static final byte DEFAULT_OFF_COMMAND_ID = Commands.OFF_4.toByte();
private static final byte DEFAULT_ON_COMMAND_ID = Commands.ON_1.toByte();
public enum SubType implements ByteEnumWrapper {
PT2262(0);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public enum Commands implements ByteEnumWrapper {
OFF_0(0, false),
ON_1(1, true),
OFF_2(2, false),
ON_3(3, true),
OFF_4(4, false),
ON_5(5, true),
ON_6(6, true),
ON_7(7, true),
ON_8(8, true),
ON_9(9, true),
ON_10(10, true),
ON_11(11, true),
ON_12(12, true),
OFF_14(14, false),
ON_15(15, true),
UNKNOWN(-1, false);
private final int command;
private final boolean on;
Commands(int command, boolean on) {
this.command = command;
this.on = on;
}
@Override
public byte toByte() {
return (byte) command;
}
public boolean isOn() {
return on;
}
public static Commands fromByte(int input) {
for (Commands c : Commands.values()) {
if (c.command == input) {
return c;
}
}
LOGGER.info(
"A not completely supported command with value {} was received, we can send it but please report "
+ "it as an issue including what the command means, this helps to extend the binding with better support.",
input);
return UNKNOWN;
}
}
private SubType subType;
private int sensorId;
private int pulse;
private Commands command;
private int commandId;
private int offCommandId;
private int onCommandId;
public RFXComLighting4Message() {
super(PacketType.LIGHTING4);
}
public RFXComLighting4Message(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = "";
str += super.toString();
str += ", Sub type = " + subType;
str += ", Device Id = " + getDeviceId();
str += ", Command = " + command + "(" + commandId + ")";
str += ", Pulse = " + pulse;
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[4] & 0xFF) << 12 | (data[5] & 0xFF) << 4 | (data[6] & 0xF0) >> 4;
commandId = (data[6] & 0x0F);
command = Commands.fromByte(commandId);
onCommandId = command.isOn() ? commandId : DEFAULT_ON_COMMAND_ID;
offCommandId = command.isOn() ? DEFAULT_OFF_COMMAND_ID : commandId;
pulse = (data[7] & 0xFF) << 8 | (data[8] & 0xFF);
signalLevel = (byte) ((data[9] & 0xF0) >> 4);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[10];
data[0] = 0x09;
data[1] = PacketType.LIGHTING4.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
// SENSOR_ID + COMMAND
data[4] = (byte) ((sensorId >> 12) & 0xFF);
data[5] = (byte) ((sensorId >> 4) & 0xFF);
data[6] = (byte) ((sensorId << 4 & 0xF0) | (commandId & 0x0F));
// PULSE
data[7] = (byte) (pulse >> 8 & 0xFF);
data[8] = (byte) (pulse & 0xFF);
// SIGNAL
data[9] = (byte) ((signalLevel & 0x0F) << 4);
return data;
}
@Override
public String getDeviceId() {
return String.valueOf(sensorId);
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_COMMAND:
case CHANNEL_MOTION:
return command.isOn() ? OnOffType.ON : OnOffType.OFF;
case CHANNEL_CONTACT:
return command.isOn() ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
case CHANNEL_COMMAND_ID:
return new DecimalType(commandId);
default:
return super.convertToState(channelId, deviceState);
}
}
@Override
public void setSubType(SubType subType) {
this.subType = subType;
}
@Override
public void setDeviceId(String deviceId) {
sensorId = Integer.parseInt(deviceId);
}
@Override
public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_COMMAND:
if (type instanceof OnOffType) {
command = Commands.fromByte(type == OnOffType.ON ? onCommandId : offCommandId);
commandId = command.toByte();
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
break;
case CHANNEL_COMMAND_ID:
if (type instanceof DecimalType) {
commandId = ((DecimalType) type).toBigDecimal().byteValue();
command = Commands.fromByte(commandId);
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
break;
default:
throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
}
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
@Override
public void addDevicePropertiesTo(DiscoveryResultBuilder discoveryResultBuilder) throws RFXComException {
super.addDevicePropertiesTo(discoveryResultBuilder);
discoveryResultBuilder.withProperty(PULSE_LABEL, pulse);
discoveryResultBuilder.withProperty(ON_COMMAND_ID_LABEL, onCommandId);
discoveryResultBuilder.withProperty(OFF_COMMAND_ID_LABEL, offCommandId);
}
@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);
}
private int valueOrDefault(Integer commandId, byte defaultValue) {
if (commandId != null) {
return commandId;
}
return defaultValue;
}
}

View File

@@ -0,0 +1,363 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import static org.openhab.binding.rfxcom.internal.messages.RFXComLighting5Message.SubType.*;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.IncreaseDecreaseType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
import org.openhab.core.types.UnDefType;
/**
* RFXCOM data class for lighting5 message.
*
* @author Paul Hampson, Neil Renaud - Initial contribution
* @author Pauli Anttila
* @author Martin van Wingerden - added support for IT and some other subtypes
*/
public class RFXComLighting5Message extends RFXComDeviceMessageImpl<RFXComLighting5Message.SubType> {
public enum SubType implements ByteEnumWrapper {
LIGHTWAVERF(0),
EMW100(1),
BBSB_NEW(2),
MDREMOTE(3),
CONRAD_RSL2(4),
LIVOLO(5),
RGB_TRC02(6),
AOKE(7),
RGB_TRC02_2(8),
EURODOMEST(9),
LIVOLO_APPLIANCE(10),
MDREMOTE_107(12),
AVANTEK(14),
IT(15),
MDREMOTE_108(16),
KANGTAI(17);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
/**
* Note: for the lighting5 commands, some command are only supported for certain sub types and
* command-bytes might even have a different meaning for another sub type.
*
* If no sub types are specified for a command, its supported by all sub types.
* An example is the command OFF which is represented by the byte 0x00 for all subtypes.
*
* Otherwise the list of sub types after the command-bytes indicates the sub types
* which support this command with this byte.
* Example byte value 0x03 means GROUP_ON for IT and some others while it means MOOD1 for LIGHTWAVERF
*/
public enum Commands implements ByteEnumWrapperWithSupportedSubTypes<SubType> {
OFF(0x00),
ON(0x01),
GROUP_OFF(0x02, LIGHTWAVERF, BBSB_NEW, CONRAD_RSL2, EURODOMEST, AVANTEK, IT, KANGTAI),
LEARN(0x02, EMW100),
GROUP_ON(0x03, BBSB_NEW, CONRAD_RSL2, EURODOMEST, AVANTEK, IT, KANGTAI),
MOOD1(0x03, LIGHTWAVERF),
MOOD2(0x04, LIGHTWAVERF),
MOOD3(0x05, LIGHTWAVERF),
MOOD4(0x06, LIGHTWAVERF),
MOOD5(0x07, LIGHTWAVERF),
RESERVED1(0x08, LIGHTWAVERF),
RESERVED2(0x09, LIGHTWAVERF),
UNLOCK(0x0A, LIGHTWAVERF),
LOCK(0x0B, LIGHTWAVERF),
ALL_LOCK(0x0C, LIGHTWAVERF),
CLOSE_RELAY(0x0D, LIGHTWAVERF),
STOP_RELAY(0x0E, LIGHTWAVERF),
OPEN_RELAY(0x0F, LIGHTWAVERF),
SET_LEVEL(0x10, LIGHTWAVERF, IT),
COLOUR_PALETTE(0x11, LIGHTWAVERF),
COLOUR_TONE(0x12, LIGHTWAVERF),
COLOUR_CYCLE(0x13, LIGHTWAVERF),
TOGGLE_1(0x01, LIVOLO_APPLIANCE),
TOGGLE_2(0x02, LIVOLO_APPLIANCE),
TOGGLE_3(0x03, LIVOLO_APPLIANCE),
TOGGLE_4(0x04, LIVOLO_APPLIANCE),
TOGGLE_5(0x07, LIVOLO_APPLIANCE),
TOGGLE_6(0x0B, LIVOLO_APPLIANCE),
TOGGLE_7(0x06, LIVOLO_APPLIANCE),
TOGGLE_8(0x0A, LIVOLO_APPLIANCE),
TOGGLE_9(0x05, LIVOLO_APPLIANCE);
private final int command;
private final List<SubType> supportedBySubTypes;
Commands(int command) {
this(command, SubType.values());
}
Commands(int command, SubType... supportedBySubTypes) {
this.command = command;
this.supportedBySubTypes = Arrays.asList(supportedBySubTypes);
}
@Override
public List<SubType> supportedBySubTypes() {
return supportedBySubTypes;
}
@Override
public byte toByte() {
return (byte) command;
}
}
public SubType subType;
public int sensorId;
public byte unitCode;
public Commands command;
public byte dimmingLevel;
public RFXComLighting5Message() {
super(PacketType.LIGHTING5);
}
public RFXComLighting5Message(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = "";
str += super.toString();
str += ", Sub type = " + subType;
str += ", Device Id = " + getDeviceId();
str += ", Command = " + command;
str += ", Dim level = " + dimmingLevel;
str += ", Signal level = " + signalLevel;
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[4] & 0xFF) << 16 | (data[5] & 0xFF) << 8 | (data[6] & 0xFF);
unitCode = data[7];
command = fromByte(Commands.class, data[8], subType);
dimmingLevel = data[9];
signalLevel = (byte) ((data[10] & 0xF0) >> 4);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[11];
data[0] = 0x0A;
data[1] = RFXComBaseMessage.PacketType.LIGHTING5.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((sensorId >> 16) & 0xFF);
data[5] = (byte) ((sensorId >> 8) & 0xFF);
data[6] = (byte) (sensorId & 0xFF);
data[7] = unitCode;
data[8] = command.toByte();
data[9] = dimmingLevel;
data[10] = (byte) ((signalLevel & 0x0F) << 4);
return data;
}
@Override
public String getDeviceId() {
return sensorId + ID_DELIMITER + unitCode;
}
/**
* Convert a 0-31 scale value to a percent type.
*
* @param pt percent type to convert
* @return converted value 0-31
*/
public static int getDimLevelFromPercentType(PercentType pt) {
return pt.toBigDecimal().multiply(BigDecimal.valueOf(31))
.divide(PercentType.HUNDRED.toBigDecimal(), 0, BigDecimal.ROUND_UP).intValue();
}
/**
* Convert a 0-31 scale value to a percent type.
*
* @param value percent type to convert
* @return converted value 0-31
*/
public static PercentType getPercentTypeFromDimLevel(int value) {
value = Math.min(value, 31);
return new PercentType(BigDecimal.valueOf(value).multiply(BigDecimal.valueOf(100))
.divide(BigDecimal.valueOf(31), 0, BigDecimal.ROUND_UP).intValue());
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_MOOD:
switch (command) {
case GROUP_OFF:
return new DecimalType(0);
case MOOD1:
return new DecimalType(1);
case MOOD2:
return new DecimalType(2);
case MOOD3:
return new DecimalType(3);
case MOOD4:
return new DecimalType(4);
case MOOD5:
return new DecimalType(5);
default:
throw new RFXComUnsupportedChannelException(
"Unexpected mood command: " + command + " for " + channelId);
}
case CHANNEL_DIMMING_LEVEL:
return RFXComLighting5Message.getPercentTypeFromDimLevel(dimmingLevel);
case CHANNEL_COMMAND:
switch (command) {
case OFF:
case GROUP_OFF:
return OnOffType.OFF;
case ON:
case GROUP_ON:
return OnOffType.ON;
case SET_LEVEL:
default:
throw new RFXComUnsupportedChannelException("Can't convert " + command + " for " + channelId);
}
case CHANNEL_COMMAND_STRING:
return command == null ? UnDefType.UNDEF : StringType.valueOf(command.toString());
case CHANNEL_CONTACT:
switch (command) {
case OFF:
case GROUP_OFF:
return OpenClosedType.CLOSED;
case ON:
case GROUP_ON:
return OpenClosedType.OPEN;
case SET_LEVEL:
default:
throw new RFXComUnsupportedChannelException("Can't convert " + command + " for " + channelId);
}
default:
return super.convertToState(channelId, deviceState);
}
}
@Override
public void setSubType(SubType subType) {
this.subType = subType;
}
@Override
public void setDeviceId(String deviceId) throws RFXComException {
String[] ids = deviceId.split("\\" + ID_DELIMITER);
if (ids.length != 2) {
throw new RFXComException("Invalid device id '" + deviceId + "'");
}
sensorId = Integer.parseInt(ids[0]);
unitCode = Byte.parseByte(ids[1]);
}
@Override
public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_COMMAND:
if (type instanceof OnOffType) {
command = (type == OnOffType.ON ? Commands.ON : Commands.OFF);
dimmingLevel = 0;
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
break;
case CHANNEL_COMMAND_STRING:
command = Commands.valueOf(type.toString().toUpperCase());
break;
case CHANNEL_DIMMING_LEVEL:
if (type instanceof OnOffType) {
command = (type == OnOffType.ON ? Commands.ON : Commands.OFF);
dimmingLevel = 0;
} else if (type instanceof PercentType) {
command = Commands.SET_LEVEL;
dimmingLevel = (byte) getDimLevelFromPercentType((PercentType) type);
if (dimmingLevel == 0) {
command = Commands.OFF;
}
} else if (type instanceof IncreaseDecreaseType) {
command = Commands.SET_LEVEL;
// Evert: I do not know how to get previous object state...
dimmingLevel = 5;
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
break;
default:
throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
}
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
}

View File

@@ -0,0 +1,210 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import 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.types.State;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for lighting6 message. See Blyss.
*
* @author Damien Servant - Initial contribution
* @author Pauli Anttila - Migrated for OH2
*/
public class RFXComLighting6Message extends RFXComDeviceMessageImpl<RFXComLighting6Message.SubType> {
public enum SubType implements ByteEnumWrapper {
BLYSS(0);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public enum Commands implements ByteEnumWrapper {
ON(0),
OFF(1),
GROUP_ON(2),
GROUP_OFF(3);
private final int command;
Commands(int command) {
this.command = command;
}
@Override
public byte toByte() {
return (byte) command;
}
}
public SubType subType;
public int sensorId;
public char groupCode;
public byte unitCode;
public Commands command;
public RFXComLighting6Message() {
super(PacketType.LIGHTING6);
}
public RFXComLighting6Message(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = "";
str += super.toString();
str += ", Sub type = " + subType;
str += ", Device Id = " + getDeviceId();
str += ", Command = " + command;
str += ", Signal level = " + signalLevel;
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[4] & 0xFF) << 8 | (data[5] & 0xFF);
groupCode = (char) data[6];
unitCode = data[7];
command = fromByte(Commands.class, data[8]);
signalLevel = (byte) ((data[11] & 0xF0) >> 4);
}
@Override
public byte[] decodeMessage() {
// Example data 0B 15 00 02 01 01 41 01 00 04 8E 00
// 0B 15 00 02 01 01 41 01 01 04 8E 00
byte[] data = new byte[12];
data[0] = 0x0B;
data[1] = RFXComBaseMessage.PacketType.LIGHTING6.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((sensorId >> 8) & 0xFF);
data[5] = (byte) (sensorId & 0xFF);
data[6] = (byte) groupCode;
data[7] = unitCode;
data[8] = command.toByte();
data[9] = 0x00; // CmdSeqNbr1 - 0 to 4 - Useless for a Blyss Switch
data[10] = 0x00; // CmdSeqNbr2 - 0 to 145 - Useless for a Blyss Switch
data[11] = (byte) ((signalLevel & 0x0F) << 4);
return data;
}
@Override
public String getDeviceId() {
return sensorId + ID_DELIMITER + groupCode + ID_DELIMITER + unitCode;
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_COMMAND:
switch (command) {
case OFF:
case GROUP_OFF:
return OnOffType.OFF;
case ON:
case GROUP_ON:
return OnOffType.ON;
default:
throw new RFXComUnsupportedChannelException("Can't convert " + command + " for " + channelId);
}
case CHANNEL_CONTACT:
switch (command) {
case OFF:
case GROUP_OFF:
return OpenClosedType.CLOSED;
case ON:
case GROUP_ON:
return OpenClosedType.OPEN;
default:
throw new RFXComUnsupportedChannelException("Can't convert " + command + " for " + channelId);
}
default:
return super.convertToState(channelId, deviceState);
}
}
@Override
public void setSubType(SubType subType) {
this.subType = subType;
}
@Override
public void setDeviceId(String deviceId) throws RFXComException {
String[] ids = deviceId.split("\\" + ID_DELIMITER);
if (ids.length != 3) {
throw new RFXComException("Invalid device id '" + deviceId + "'");
}
sensorId = Integer.parseInt(ids[0]);
groupCode = ids[1].charAt(0);
unitCode = Byte.parseByte(ids[2]);
}
@Override
public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_COMMAND:
if (type instanceof OnOffType) {
command = (type == OnOffType.ON ? Commands.ON : Commands.OFF);
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
break;
default:
throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
}
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
}

View File

@@ -0,0 +1,53 @@
/**
* Copyright (c) 2010-2020 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 org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfiguration;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.core.types.Type;
/**
* This interface defines interface which every message class should implement.
*
* @author Pauli Anttila - Initial contribution
*/
public interface RFXComMessage {
/**
* Procedure for encode raw data.
*
* @param data Raw data.
*/
void encodeMessage(byte[] data) throws RFXComException;
/**
* Procedure for decode object to raw data.
*
* @return raw data.
*/
byte[] decodeMessage() throws RFXComException;
/**
* Procedure for converting openHAB state to RFXCOM object.
*/
void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException;
/**
* Procedure to pass configuration to a message
*
* @param deviceConfiguration configuration about the device
* @throws RFXComException if the configuration could not be handled properly
*/
void setConfig(RFXComDeviceConfiguration deviceConfiguration) throws RFXComException;
}

View File

@@ -0,0 +1,161 @@
/**
* Copyright (c) 2010-2020 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;
/**
*
* @author Pauli Anttila - Initial contribution
*/
public class RFXComMessageFactory {
@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.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.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);
}
}

View File

@@ -0,0 +1,294 @@
/**
* Copyright (c) 2010-2020 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 static java.math.BigDecimal.*;
import static java.math.RoundingMode.HALF_DOWN;
import static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import java.math.BigDecimal;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
import org.openhab.core.types.UnDefType;
import org.openhab.core.util.HexUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Add support for the rfx-sensor
*
* @author Martin van Wingerden - Initial contribution
*/
public class RFXComRFXSensorMessage extends RFXComDeviceMessageImpl<RFXComRFXSensorMessage.SubType> {
private final Logger logger = LoggerFactory.getLogger(RFXComRFXSensorMessage.class);
private static final BigDecimal PRESSURE_ADDITION = new BigDecimal("0.095");
private static final BigDecimal PRESSURE_DIVIDER = new BigDecimal("0.0009");
private static final BigDecimal HUMIDITY_VOLTAGE_SUBTRACTION = new BigDecimal("0.16");
private static final BigDecimal HUMIDITY_VOLTAGE_DIVIDER = new BigDecimal("0.0062");
private static final BigDecimal HUMIDITY_TEMPERATURE_CORRECTION = new BigDecimal("1.0546");
private static final BigDecimal HUMIDITY_TEMPERATURE_MULTIPLIER = new BigDecimal("0.00216");
private static final BigDecimal ONE_HUNDRED = BigDecimal.valueOf(100);
public enum SubType implements ByteEnumWrapper {
TEMPERATURE(0),
A_D(1),
VOLTAGE(2),
MESSAGE(3);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public SubType subType;
public int sensorId;
private Double temperature;
private BigDecimal miliVoltageTimesTen;
public byte signalLevel;
public RFXComRFXSensorMessage() {
super(PacketType.RFXSENSOR);
}
public RFXComRFXSensorMessage(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = super.toString();
str += ", Sub type = " + subType;
str += ", Device Id = " + getDeviceId();
str += ", Temperature = " + temperature;
str += ", Voltage = " + getVoltage();
str += ", Signal level = " + signalLevel;
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[4] & 0xFF);
byte msg1 = data[5];
byte msg2 = data[6];
switch (subType) {
case TEMPERATURE:
encodeTemperatureMessage(msg1, msg2);
break;
case A_D:
case VOLTAGE:
encodeVoltageMessage(msg1, msg2);
break;
case MESSAGE:
encodeStatusMessage(msg2);
break;
}
signalLevel = (byte) ((data[7] & 0xF0) >> 4);
}
private void encodeTemperatureMessage(byte msg1, byte msg2) {
temperature = (short) ((msg1 & 0x7F) << 8 | (msg2 & 0xFF)) * 0.01;
if ((msg1 & 0x80) != 0) {
temperature = -temperature;
}
}
private void encodeVoltageMessage(byte msg1, byte msg2) {
miliVoltageTimesTen = BigDecimal.valueOf((short) ((msg1 & 0xFF) << 8 | (msg2 & 0xFF)));
}
private void encodeStatusMessage(byte msg2) {
// noop
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[8];
data[0] = 0x07;
data[1] = PacketType.RFXSENSOR.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) (sensorId & 0x00FF);
if (subType == SubType.TEMPERATURE) {
decodeTemperatureMessage(data);
} else if (subType == SubType.A_D) {
decodeVoltageMessage(data);
} else if (subType == SubType.VOLTAGE) {
decodeVoltageMessage(data);
} else if (subType == SubType.MESSAGE) {
decodeStatusMessage(data);
}
data[7] = (byte) ((signalLevel & 0x0F) << 4);
return data;
}
@Override
public void convertFromState(String channelId, Type type) {
throw new UnsupportedOperationException();
}
private void decodeTemperatureMessage(byte[] data) {
short temp = (short) Math.abs(temperature * 100);
data[5] = (byte) ((temp >> 8) & 0xFF);
data[6] = (byte) (temp & 0xFF);
if (temperature < 0) {
data[5] |= 0x80;
}
}
private void decodeVoltageMessage(byte[] data) {
short miliVoltageTimesTenShort = this.miliVoltageTimesTen.shortValueExact();
data[5] = (byte) ((miliVoltageTimesTenShort >> 8) & 0xFF);
data[6] = (byte) (miliVoltageTimesTenShort & 0xFF);
}
private void decodeStatusMessage(byte[] data) {
logger.info("A status message was received {}", HexUtils.bytesToHex(data));
}
@Override
public String getDeviceId() {
return String.valueOf(sensorId);
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
@Override
public void setSubType(SubType subType) {
throw new UnsupportedOperationException();
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_TEMPERATURE:
return subType == SubType.TEMPERATURE ? getTemperature() : null;
case CHANNEL_VOLTAGE:
return subType == SubType.A_D ? handleVoltage() : null;
case CHANNEL_REFERENCE_VOLTAGE:
return subType == SubType.VOLTAGE ? handleVoltage() : null;
case CHANNEL_HUMIDITY:
return subType == SubType.A_D ? handleHumidity(deviceState) : null;
case CHANNEL_PRESSURE:
return subType == SubType.A_D ? handlePressure(deviceState) : null;
default:
return super.convertToState(channelId, deviceState);
}
}
private State getTemperature() {
if (temperature != null) {
return new DecimalType(temperature);
} else {
return UnDefType.UNDEF;
}
}
private State handleVoltage() {
if (miliVoltageTimesTen != null) {
return new DecimalType(getVoltage());
} else {
return UnDefType.UNDEF;
}
}
private State handleHumidity(DeviceState deviceState) {
DecimalType temperatureState = (DecimalType) deviceState.getLastState(CHANNEL_TEMPERATURE);
Type referenceVoltageState = deviceState.getLastState(CHANNEL_REFERENCE_VOLTAGE);
BigDecimal adVoltage = getVoltage();
if (temperatureState == null || referenceVoltageState == null || adVoltage == null) {
return null;
}
if (!(referenceVoltageState instanceof DecimalType)) {
return UnDefType.UNDEF;
}
BigDecimal temperature = temperatureState.toBigDecimal();
BigDecimal supplyVoltage = ((DecimalType) referenceVoltageState).toBigDecimal();
// RH = (((A/D voltage / supply voltage) - 0.16) / 0.0062) / (1.0546 - 0.00216 * temperature)
BigDecimal belowTheDivider = adVoltage.divide(supplyVoltage, 4, ROUND_HALF_DOWN)
.subtract(HUMIDITY_VOLTAGE_SUBTRACTION).divide(HUMIDITY_VOLTAGE_DIVIDER, 4, ROUND_HALF_DOWN);
BigDecimal underTheDivider = HUMIDITY_TEMPERATURE_CORRECTION
.subtract(HUMIDITY_TEMPERATURE_MULTIPLIER.multiply(temperature));
return new DecimalType(belowTheDivider.divide(underTheDivider, 4, ROUND_HALF_DOWN));
}
private State handlePressure(DeviceState deviceState) {
DecimalType referenceVoltageState = (DecimalType) deviceState.getLastState(CHANNEL_REFERENCE_VOLTAGE);
BigDecimal adVoltage = getVoltage();
if (referenceVoltageState == null || adVoltage == null) {
return null;
}
BigDecimal supplyVoltage = referenceVoltageState.toBigDecimal();
// hPa = ((A/D voltage / supply voltage) + 0.095) / 0.0009
return new DecimalType((adVoltage.divide(supplyVoltage, 4, HALF_DOWN).add(PRESSURE_ADDITION))
.divide(PRESSURE_DIVIDER, 4, ROUND_HALF_DOWN));
}
private BigDecimal getVoltage() {
if (miliVoltageTimesTen == null) {
return null;
}
return miliVoltageTimesTen.divide(ONE_HUNDRED, 100, ROUND_CEILING);
}
@Override
public void setDeviceId(String deviceId) throws RFXComException {
throw new RFXComException("Not supported");
}
}

View File

@@ -0,0 +1,168 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for temperature and humidity message.
*
* @author Marc SAUVEUR - Initial contribution
* @author Pauli Anttila - Migrated for OH2
*/
public class RFXComRainMessage extends RFXComBatteryDeviceMessage<RFXComRainMessage.SubType> {
public enum SubType implements ByteEnumWrapper {
RAIN1(1),
RAIN2(2),
RAIN3(3),
RAIN4(4),
RAIN5(5),
RAIN6(6),
RAIN7(7);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public SubType subType;
public int sensorId;
public double rainRate;
public double rainTotal;
public RFXComRainMessage() {
super(PacketType.RAIN);
}
public RFXComRainMessage(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = "";
str += super.toString();
str += ", Sub type = " + subType;
str += ", Device Id = " + getDeviceId();
str += ", Rain rate = " + rainRate;
str += ", Rain total = " + rainTotal;
str += ", Signal level = " + signalLevel;
str += ", Battery level = " + batteryLevel;
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[4] & 0xFF) << 8 | (data[5] & 0xFF);
rainRate = (short) ((data[6] & 0xFF) << 8 | (data[7] & 0xFF));
if (subType == SubType.RAIN2) {
rainRate *= 0.01;
}
if (subType == SubType.RAIN6) {
rainTotal = (short) ((data[10] & 0xFF)) * 0.266;
} else {
rainTotal = (short) ((data[8] & 0xFF) << 8 | (data[9] & 0xFF) << 8 | (data[10] & 0xFF)) * 0.1;
}
signalLevel = (byte) ((data[11] & 0xF0) >> 4);
batteryLevel = (byte) (data[11] & 0x0F);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[12];
data[0] = 0x0B;
data[1] = RFXComBaseMessage.PacketType.RAIN.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((sensorId & 0xFF00) >> 8);
data[5] = (byte) (sensorId & 0x00FF);
short rainR = (short) Math.abs(rainRate * 100);
data[6] = (byte) ((rainR >> 8) & 0xFF);
data[7] = (byte) (rainR & 0xFF);
short rainT = (short) Math.abs(rainTotal * 10);
data[8] = (byte) ((rainT >> 16) & 0xFF);
data[9] = (byte) ((rainT >> 8) & 0xFF);
data[10] = (byte) (rainT & 0xFF);
data[11] = (byte) (((signalLevel & 0x0F) << 4) | (batteryLevel & 0x0F));
return data;
}
@Override
public String getDeviceId() {
return String.valueOf(sensorId);
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_RAIN_RATE:
return new DecimalType(rainRate);
case CHANNEL_RAIN_TOTAL:
return new DecimalType(rainTotal);
default:
return super.convertToState(channelId, deviceState);
}
}
@Override
public void setSubType(SubType subType) {
throw new UnsupportedOperationException();
}
@Override
public void setDeviceId(String deviceId) {
throw new UnsupportedOperationException();
}
@Override
public void convertFromState(String channelId, Type type) {
throw new UnsupportedOperationException();
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
}

View File

@@ -0,0 +1,222 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.IncreaseDecreaseType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.StopMoveType;
import org.openhab.core.library.types.UpDownType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for RFY (Somfy RTS) message.
*
* @author Jürgen Richtsfeld - Initial contribution
* @author Pauli Anttila - Ported from OpenHAB1
* @author Mike Jagdis - Added venetian support and sun+wind detector
*/
public class RFXComRfyMessage extends RFXComDeviceMessageImpl<RFXComRfyMessage.SubType> {
public enum Commands implements ByteEnumWrapper {
STOP(0x00),
UP(0x01),
DOWN(0x03),
PROGRAM(0x07),
UP_SHORT(0x0F),
DOWN_SHORT(0x10),
UP_LONG(0x11),
DOWN_LONG(0x12),
ENABLE_SUN_WIND_DETECTOR(0x13),
DISABLE_SUN_DETECTOR(0x14);
private final int command;
Commands(int command) {
this.command = command;
}
@Override
public byte toByte() {
return (byte) command;
}
}
public enum SubType implements ByteEnumWrapper {
RFY(0),
RFY_EXT(1),
RESERVED(2),
ASA(3);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public SubType subType;
public int unitId;
public byte unitCode;
public Commands command;
public RFXComRfyMessage() {
super(PacketType.RFY);
}
public RFXComRfyMessage(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
return super.toString() + ", Sub type = " + subType + ", Unit Id = " + getDeviceId() + ", Unit Code = "
+ unitCode + ", Command = " + command + ", Signal level = " + signalLevel;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
unitId = (data[4] & 0xFF) << 16 | (data[5] & 0xFF) << 8 | (data[6] & 0xFF);
unitCode = data[7];
command = fromByte(Commands.class, data[8]);
signalLevel = (byte) ((data[12] & 0xF0) >> 4);
}
@Override
public byte[] decodeMessage() {
final byte[] data = new byte[13];
data[0] = 12;
data[1] = RFXComBaseMessage.PacketType.RFY.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((unitId >> 16) & 0xFF);
data[5] = (byte) ((unitId >> 8) & 0xFF);
data[6] = (byte) (unitId & 0xFF);
data[7] = unitCode;
data[8] = command.toByte();
data[12] = (byte) ((signalLevel & 0x0F) << 4);
return data;
}
@Override
public String getDeviceId() {
return unitId + ID_DELIMITER + unitCode;
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_COMMAND:
return (command == Commands.DOWN ? OpenClosedType.CLOSED : OpenClosedType.OPEN);
default:
return super.convertToState(channelId, deviceState);
}
}
@Override
public void setSubType(SubType subType) {
this.subType = subType;
}
@Override
public void setDeviceId(String deviceId) throws RFXComException {
String[] ids = deviceId.split("\\" + ID_DELIMITER);
if (ids.length != 2) {
throw new RFXComException("Invalid device id '" + deviceId + "'");
}
this.unitId = Integer.parseInt(ids[0]);
this.unitCode = Byte.parseByte(ids[1]);
}
@Override
public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_SHUTTER:
if (type instanceof OpenClosedType) {
this.command = (type == OpenClosedType.CLOSED ? Commands.DOWN : Commands.UP);
} else if (type instanceof UpDownType) {
this.command = (type == UpDownType.DOWN ? Commands.DOWN : Commands.UP);
} else if (type instanceof StopMoveType) {
this.command = Commands.STOP;
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
break;
case CHANNEL_PROGRAM:
if (type == OnOffType.ON) {
this.command = Commands.PROGRAM;
} else {
throw new RFXComUnsupportedChannelException("Can't convert " + type + " to Command");
}
break;
case CHANNEL_SUN_WIND_DETECTOR:
if (type instanceof OnOffType) {
this.command = (type == OnOffType.ON ? Commands.ENABLE_SUN_WIND_DETECTOR
: Commands.DISABLE_SUN_DETECTOR);
} else {
throw new RFXComUnsupportedChannelException("Can't convert " + type + " to Command");
}
break;
case CHANNEL_VENETIAN_BLIND:
if (type instanceof OpenClosedType) {
this.command = (type == OpenClosedType.CLOSED ? Commands.DOWN_SHORT : Commands.UP_SHORT);
} else if (type instanceof OnOffType) {
this.command = (type == OnOffType.ON ? Commands.DOWN_SHORT : Commands.UP_SHORT);
} else if (type instanceof IncreaseDecreaseType) {
this.command = (type == IncreaseDecreaseType.INCREASE ? Commands.DOWN_LONG : Commands.UP_LONG);
} else {
throw new RFXComUnsupportedChannelException("Can't convert " + type + " to Command");
}
break;
default:
throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
}
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
}

View File

@@ -0,0 +1,310 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import 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;
/**
* RFXCOM data class for Security1 message.
* (i.e. X10 Security, Visonic PowerCode, Meiantech, etc.)
*
* @author David Kalff - Initial contribution
* @author Pauli Anttila
*/
public class RFXComSecurity1Message extends RFXComBatteryDeviceMessage<RFXComSecurity1Message.SubType> {
public enum SubType implements ByteEnumWrapper {
X10_SECURITY(0),
X10_SECURITY_MOTION(1),
X10_SECURITY_REMOTE(2),
KD101(3),
VISONIC_POWERCODE_SENSOR_PRIMARY_CONTACT(4),
VISONIC_POWERCODE_MOTION(5),
VISONIC_CODESECURE(6),
VISONIC_POWERCODE_SENSOR_AUX_CONTACT(7),
MEIANTECH(8),
SA30(9), // Also SA33
RM174RF(10);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public enum Status implements ByteEnumWrapper {
NORMAL(0),
NORMAL_DELAYED(1),
ALARM(2),
ALARM_DELAYED(3),
MOTION(4),
NO_MOTION(5),
PANIC(6),
END_PANIC(7),
IR(8),
ARM_AWAY(9),
ARM_AWAY_DELAYED(10),
ARM_HOME(11),
ARM_HOME_DELAYED(12),
DISARM(13),
LIGHT_1_OFF(16),
LIGHT_1_ON(17),
LIGHT_2_OFF(18),
LIGHT_2_ON(19),
DARK_DETECTED(20),
LIGHT_DETECTED(21),
BATLOW(22),
PAIR_KD101(23),
NORMAL_TAMPER(128),
NORMAL_DELAYED_TAMPER(129),
ALARM_TAMPER(130),
ALARM_DELAYED_TAMPER(131),
MOTION_TAMPER(132),
NO_MOTION_TAMPER(133);
private final int status;
Status(int status) {
this.status = status;
}
@Override
public byte toByte() {
return (byte) status;
}
}
/* Added item for ContactTypes */
public enum Contact implements ByteEnumWrapper {
NORMAL(0),
NORMAL_DELAYED(1),
ALARM(2),
ALARM_DELAYED(3),
NORMAL_TAMPER(128),
NORMAL_DELAYED_TAMPER(129),
ALARM_TAMPER(130),
ALARM_DELAYED_TAMPER(131),
UNKNOWN(255);
private final int contact;
Contact(int contact) {
this.contact = contact;
}
@Override
public byte toByte() {
return (byte) contact;
}
public static Contact fromByte(int input) {
for (Contact status : Contact.values()) {
if (status.contact == input) {
return status;
}
}
return Contact.UNKNOWN;
}
}
/* Added item for MotionTypes */
public enum Motion implements ByteEnumWrapper {
MOTION(4),
NO_MOTION(5),
MOTION_TAMPER(132),
NO_MOTION_TAMPER(133),
UNKNOWN(255);
private final int motion;
Motion(int motion) {
this.motion = motion;
}
@Override
public byte toByte() {
return (byte) motion;
}
public static Motion fromByte(int input) {
for (Motion motion : Motion.values()) {
if (motion.motion == input) {
return motion;
}
}
return Motion.UNKNOWN;
}
}
public SubType subType;
public int sensorId;
public Status status;
public Contact contact;
public Motion motion;
public RFXComSecurity1Message() {
super(PacketType.SECURITY1);
}
public RFXComSecurity1Message(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = "";
str += super.toString();
str += ", Sub type = " + subType;
str += ", Device Id = " + getDeviceId();
str += ", Status = " + status;
str += ", Battery level = " + batteryLevel;
str += ", Signal level = " + signalLevel;
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[4] & 0xFF) << 16 | (data[5] & 0xFF) << 8 | (data[6] & 0xFF);
status = fromByte(Status.class, data[7]);
batteryLevel = (byte) ((data[8] & 0xF0) >> 4);
signalLevel = (byte) (data[8] & 0x0F);
contact = Contact.fromByte(data[7]);
motion = Motion.fromByte(data[7]);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[9];
data[0] = 0x08;
data[1] = RFXComBaseMessage.PacketType.SECURITY1.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((sensorId >> 16) & 0xFF);
data[5] = (byte) ((sensorId >> 8) & 0xFF);
data[6] = (byte) (sensorId & 0xFF);
data[7] = status.toByte();
data[8] = (byte) (((batteryLevel & 0x0F) << 4) | (signalLevel & 0x0F));
return data;
}
@Override
public String getDeviceId() {
return String.valueOf(sensorId);
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_MOTION:
switch (status) {
case MOTION:
return OnOffType.ON;
case NO_MOTION:
return OnOffType.OFF;
default:
throw new RFXComUnsupportedChannelException("Can't convert " + status + " for " + channelId);
}
case CHANNEL_CONTACT:
switch (status) {
case NORMAL:
return OpenClosedType.CLOSED;
case NORMAL_DELAYED:
return OpenClosedType.CLOSED;
case ALARM:
return OpenClosedType.OPEN;
case ALARM_DELAYED:
return OpenClosedType.OPEN;
default:
throw new RFXComUnsupportedChannelException("Can't convert " + status + " for " + channelId);
}
case CHANNEL_STATUS:
return new StringType(status.toString());
default:
return super.convertToState(channelId, deviceState);
}
}
@Override
public void setSubType(SubType subType) {
this.subType = subType;
}
@Override
public void setDeviceId(String deviceId) {
sensorId = Integer.parseInt(deviceId);
}
@Override
public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_COMMAND:
if ((type instanceof OnOffType) && (subType == SubType.X10_SECURITY_REMOTE)) {
status = (type == OnOffType.ON ? Status.ARM_AWAY_DELAYED : Status.DISARM);
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
break;
case CHANNEL_STATUS:
if (type instanceof StringType) {
status = Status.valueOf(type.toString());
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
break;
default:
throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
}
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
}

View File

@@ -0,0 +1,211 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import java.util.Arrays;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for Security2 message.
* (i.e. KEELOQ.)
*
* @author Mike Jagdis - Initial contribution
*/
public class RFXComSecurity2Message extends RFXComBatteryDeviceMessage<RFXComSecurity2Message.SubType> {
public enum SubType implements ByteEnumWrapper {
RAW_CLASSIC_KEELOQ(0),
ROLLING_CODE_PACKET(1),
RAW_AES_KEELOQ(2),
RAW_CLASS_KEELOQ_WITH_REPEATS(3);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public SubType subType;
public int sensorId;
public int buttonStatus;
private static final int BUTTON_0_BIT = 0x02;
private static final int BUTTON_1_BIT = 0x04;
private static final int BUTTON_2_BIT = 0x08;
private static final int BUTTON_3_BIT = 0x01;
public RFXComSecurity2Message() {
super(PacketType.SECURITY2);
}
public RFXComSecurity2Message(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
return super.toString() + ", Sub type = " + subType + ", Device Id = " + getDeviceId() + ", Button status = "
+ buttonStatus + ", Battery level = " + batteryLevel + ", Signal level = " + signalLevel;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[11] & 0x0F) << 24 | (data[10] & 0xFF) << 16 | (data[9] & 0xFF) << 8 | (data[8] & 0xFF);
buttonStatus = (data[11] & 0xF0) >> 4;
batteryLevel = (byte) ((data[28] & 0xF0) >> 4);
signalLevel = (byte) (data[28] & 0x0F);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[29];
Arrays.fill(data, (byte) 0);
data[0] = 0x1C;
data[1] = RFXComBaseMessage.PacketType.SECURITY2.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[8] = (byte) (sensorId & 0xFF);
data[9] = (byte) ((sensorId >> 8) & 0xFF);
data[10] = (byte) ((sensorId >> 16) & 0xFF);
data[11] = (byte) ((buttonStatus & 0x0f) << 4 | (sensorId >> 24) & 0x0F);
data[28] = (byte) (((batteryLevel & 0x0F) << 4) | (signalLevel & 0x0F));
return data;
}
@Override
public String getDeviceId() {
return String.valueOf(sensorId);
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_CONTACT:
return ((buttonStatus & BUTTON_0_BIT) == 0) ? OpenClosedType.CLOSED : OpenClosedType.OPEN;
case CHANNEL_CONTACT_1:
return ((buttonStatus & BUTTON_1_BIT) == 0) ? OpenClosedType.CLOSED : OpenClosedType.OPEN;
case CHANNEL_CONTACT_2:
return ((buttonStatus & BUTTON_2_BIT) == 0) ? OpenClosedType.CLOSED : OpenClosedType.OPEN;
case CHANNEL_CONTACT_3:
return ((buttonStatus & BUTTON_3_BIT) == 0) ? OpenClosedType.CLOSED : OpenClosedType.OPEN;
default:
return super.convertToState(channelId, deviceState);
}
}
@Override
public void setSubType(SubType subType) {
this.subType = subType;
}
@Override
public void setDeviceId(String deviceId) {
sensorId = Integer.parseInt(deviceId);
}
@Override
public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_CONTACT:
if (type instanceof OpenClosedType) {
if (type == OpenClosedType.CLOSED) {
buttonStatus |= BUTTON_0_BIT;
} else {
buttonStatus &= ~BUTTON_0_BIT;
}
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
break;
case CHANNEL_CONTACT_1:
if (type instanceof OpenClosedType) {
if (type == OpenClosedType.CLOSED) {
buttonStatus |= BUTTON_1_BIT;
} else {
buttonStatus &= ~BUTTON_1_BIT;
}
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
break;
case CHANNEL_CONTACT_2:
if (type instanceof OpenClosedType) {
if (type == OpenClosedType.CLOSED) {
buttonStatus |= BUTTON_2_BIT;
} else {
buttonStatus &= ~BUTTON_2_BIT;
}
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
break;
case CHANNEL_CONTACT_3:
if (type instanceof OpenClosedType) {
if (type == OpenClosedType.CLOSED) {
buttonStatus |= BUTTON_3_BIT;
} else {
buttonStatus &= ~BUTTON_3_BIT;
}
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
break;
default:
throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
}
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
}

View File

@@ -0,0 +1,222 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for temperature, humidity and barometric message.
*
* @author Damien Servant - Initial contribution
* @author Martin van Wingerden - ported to openHAB 2.0
*/
public class RFXComTemperatureHumidityBarometricMessage
extends RFXComBatteryDeviceMessage<RFXComTemperatureHumidityBarometricMessage.SubType> {
public enum SubType implements ByteEnumWrapper {
THB1(1), // BTHR918, BTHGN129
THB2(2); // BTHR918N, BTHR968
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public enum HumidityStatus implements ByteEnumWrapper {
NORMAL(0),
COMFORT(1),
DRY(2),
WET(3);
private final int humidityStatus;
HumidityStatus(int humidityStatus) {
this.humidityStatus = humidityStatus;
}
@Override
public byte toByte() {
return (byte) humidityStatus;
}
}
public enum ForecastStatus implements ByteEnumWrapper {
NO_INFO_AVAILABLE(0),
SUNNY(1),
PARTLY_CLOUDY(2),
CLOUDY(3),
RAIN(4);
private final int forecastStatus;
ForecastStatus(int forecastStatus) {
this.forecastStatus = forecastStatus;
}
@Override
public byte toByte() {
return (byte) forecastStatus;
}
}
public SubType subType;
public int sensorId;
public double temperature;
public byte humidity;
public HumidityStatus humidityStatus;
public double pressure;
public ForecastStatus forecastStatus;
public RFXComTemperatureHumidityBarometricMessage() {
super(PacketType.TEMPERATURE_HUMIDITY_BAROMETRIC);
}
public RFXComTemperatureHumidityBarometricMessage(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = super.toString();
str += ", Sub type = " + subType;
str += ", Device Id = " + sensorId;
str += ", Temperature = " + temperature;
str += ", Humidity = " + humidity;
str += ", Humidity status = " + humidityStatus;
str += ", Pressure = " + pressure;
str += ", Forecast = " + forecastStatus;
str += ", Signal level = " + signalLevel;
str += ", Battery level = " + batteryLevel;
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[4] & 0xFF) << 8 | (data[5] & 0xFF);
temperature = (short) ((data[6] & 0x7F) << 8 | (data[7] & 0xFF)) * 0.1;
if ((data[6] & 0x80) != 0) {
temperature = -temperature;
}
humidity = data[8];
humidityStatus = fromByte(HumidityStatus.class, data[9]);
pressure = (data[10] & 0xFF) << 8 | (data[11] & 0xFF);
forecastStatus = fromByte(ForecastStatus.class, data[12]);
signalLevel = (byte) ((data[13] & 0xF0) >> 4);
batteryLevel = (byte) (data[13] & 0x0F);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[14];
data[0] = 0x0D;
data[1] = RFXComBaseMessage.PacketType.TEMPERATURE_HUMIDITY_BAROMETRIC.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((sensorId & 0xFF00) >> 8);
data[5] = (byte) (sensorId & 0x00FF);
short temp = (short) Math.abs(temperature * 10);
data[6] = (byte) ((temp >> 8) & 0xFF);
data[7] = (byte) (temp & 0xFF);
if (temperature < 0) {
data[6] |= 0x80;
}
data[8] = humidity;
data[9] = humidityStatus.toByte();
temp = (short) (pressure);
data[10] = (byte) ((temp >> 8) & 0xFF);
data[11] = (byte) (temp & 0xFF);
data[12] = forecastStatus.toByte();
data[13] = (byte) (((signalLevel & 0x0F) << 4) | (batteryLevel & 0x0F));
return data;
}
@Override
public String getDeviceId() {
return String.valueOf(sensorId);
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_TEMPERATURE:
return new DecimalType(temperature);
case CHANNEL_HUMIDITY:
return new DecimalType(humidity);
case CHANNEL_PRESSURE:
return new DecimalType(pressure);
case CHANNEL_HUMIDITY_STATUS:
return new StringType(humidityStatus.toString());
case CHANNEL_FORECAST:
return new StringType(forecastStatus.toString());
default:
return super.convertToState(channelId, deviceState);
}
}
@Override
public void convertFromState(String channelId, Type type) {
throw new UnsupportedOperationException();
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
@Override
public void setSubType(SubType subType) {
throw new UnsupportedOperationException();
}
@Override
public void setDeviceId(String deviceId) {
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,196 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for temperature and humidity message.
*
* @author Pauli Anttila - Initial contribution
*/
public class RFXComTemperatureHumidityMessage
extends RFXComBatteryDeviceMessage<RFXComTemperatureHumidityMessage.SubType> {
public enum SubType implements ByteEnumWrapper {
TH1(1),
TH2(2),
TH3(3),
TH4(4),
TH5(5),
TH6(6),
TH7(7),
TH8(8),
TH9(9),
TH10(10),
TH11(11),
TH12(12),
TH13(13),
TH14(14);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public enum HumidityStatus implements ByteEnumWrapper {
NORMAL(0),
COMFORT(1),
DRY(2),
WET(3);
private final int humidityStatus;
HumidityStatus(int humidityStatus) {
this.humidityStatus = humidityStatus;
}
@Override
public byte toByte() {
return (byte) humidityStatus;
}
}
public SubType subType;
public int sensorId;
public double temperature;
public byte humidity;
public HumidityStatus humidityStatus;
public RFXComTemperatureHumidityMessage() {
super(PacketType.TEMPERATURE_HUMIDITY);
}
public RFXComTemperatureHumidityMessage(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = "";
str += super.toString();
str += ", Sub type = " + subType;
str += ", Device Id = " + getDeviceId();
str += ", Temperature = " + temperature;
str += ", Humidity = " + humidity;
str += ", Humidity status = " + humidityStatus;
str += ", Signal level = " + signalLevel;
str += ", Battery level = " + batteryLevel;
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[4] & 0xFF) << 8 | (data[5] & 0xFF);
temperature = (short) ((data[6] & 0x7F) << 8 | (data[7] & 0xFF)) * 0.1;
if ((data[6] & 0x80) != 0) {
temperature = -temperature;
}
humidity = data[8];
humidityStatus = fromByte(HumidityStatus.class, data[9]);
signalLevel = (byte) ((data[10] & 0xF0) >> 4);
batteryLevel = (byte) (data[10] & 0x0F);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[11];
data[0] = 0x0A;
data[1] = RFXComBaseMessage.PacketType.TEMPERATURE_HUMIDITY.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((sensorId & 0xFF00) >> 8);
data[5] = (byte) (sensorId & 0x00FF);
short temp = (short) Math.abs(temperature * 10);
data[6] = (byte) ((temp >> 8) & 0xFF);
data[7] = (byte) (temp & 0xFF);
if (temperature < 0) {
data[6] |= 0x80;
}
data[8] = humidity;
data[9] = humidityStatus.toByte();
data[10] = (byte) (((signalLevel & 0x0F) << 4) | (batteryLevel & 0x0F));
return data;
}
@Override
public String getDeviceId() {
return String.valueOf(sensorId);
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_TEMPERATURE:
return new DecimalType(temperature);
case CHANNEL_HUMIDITY:
return new DecimalType(humidity);
case CHANNEL_HUMIDITY_STATUS:
return new StringType(humidityStatus.toString());
default:
return super.convertToState(channelId, deviceState);
}
}
@Override
public void setSubType(SubType subType) {
throw new UnsupportedOperationException();
}
@Override
public void setDeviceId(String deviceId) {
throw new UnsupportedOperationException();
}
@Override
public void convertFromState(String channelId, Type type) {
throw new UnsupportedOperationException();
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
}

View File

@@ -0,0 +1,158 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.CHANNEL_TEMPERATURE;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for temperature and humidity message.
*
* @author Pauli Anttila - Initial contribution
*/
public class RFXComTemperatureMessage extends RFXComBatteryDeviceMessage<RFXComTemperatureMessage.SubType> {
public enum SubType implements ByteEnumWrapper {
TEMP1(1),
TEMP2(2),
TEMP3(3),
TEMP4(4),
TEMP5(5),
TEMP6(6),
TEMP7(7),
TEMP8(8),
TEMP9(9),
TEMP10(10),
TEMP11(11);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public SubType subType;
public int sensorId;
public double temperature;
public RFXComTemperatureMessage() {
super(PacketType.TEMPERATURE);
}
public RFXComTemperatureMessage(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = "";
str += super.toString();
str += ", Sub type = " + subType;
str += ", Device Id = " + getDeviceId();
str += ", Temperature = " + temperature;
str += ", Signal level = " + signalLevel;
str += ", Battery level = " + batteryLevel;
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[4] & 0xFF) << 8 | (data[5] & 0xFF);
temperature = (short) ((data[6] & 0x7F) << 8 | (data[7] & 0xFF)) * 0.1;
if ((data[6] & 0x80) != 0) {
temperature = -temperature;
}
signalLevel = (byte) ((data[8] & 0xF0) >> 4);
batteryLevel = (byte) (data[8] & 0x0F);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[9];
data[0] = 0x08;
data[1] = RFXComBaseMessage.PacketType.TEMPERATURE.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((sensorId & 0xFF00) >> 8);
data[5] = (byte) (sensorId & 0x00FF);
short temp = (short) Math.abs(temperature * 10);
data[6] = (byte) ((temp >> 8) & 0xFF);
data[7] = (byte) (temp & 0xFF);
if (temperature < 0) {
data[6] |= 0x80;
}
data[8] = (byte) (((signalLevel & 0x0F) << 4) | (batteryLevel & 0x0F));
return data;
}
@Override
public String getDeviceId() {
return String.valueOf(sensorId);
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_TEMPERATURE:
return new DecimalType(temperature);
default:
return super.convertToState(channelId, deviceState);
}
}
@Override
public void setSubType(SubType subType) {
throw new UnsupportedOperationException();
}
@Override
public void setDeviceId(String deviceId) {
throw new UnsupportedOperationException();
}
@Override
public void convertFromState(String channelId, Type type) {
throw new UnsupportedOperationException();
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
}

View File

@@ -0,0 +1,155 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for Temperature and Rain message.
*
* @author Damien Servant - Initial contribution
* @author Martin van Wingerden - ported to openHAB 2.0
*/
public class RFXComTemperatureRainMessage extends RFXComBatteryDeviceMessage<RFXComTemperatureRainMessage.SubType> {
public enum SubType implements ByteEnumWrapper {
WS1200(1);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public SubType subType;
public int sensorId;
public double temperature;
public double rainTotal;
public RFXComTemperatureRainMessage() {
super(PacketType.TEMPERATURE_RAIN);
}
public RFXComTemperatureRainMessage(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = super.toString();
str += ", Sub type = " + subType;
str += ", Device Id = " + sensorId;
str += ", Temperature = " + temperature;
str += ", Rain total = " + rainTotal;
str += ", Signal level = " + signalLevel;
str += ", Battery level = " + batteryLevel;
return str;
}
@Override
public String getDeviceId() {
return String.valueOf(sensorId);
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[4] & 0xFF) << 8 | (data[5] & 0xFF);
temperature = ((data[6] & 0x7F) << 8 | (data[7] & 0xFF)) * 0.1;
if ((data[6] & 0x80) != 0) {
temperature = -temperature;
}
rainTotal = ((data[8] & 0xFF) << 8 | (data[9] & 0xFF)) * 0.1;
signalLevel = (byte) ((data[10] & 0xF0) >> 4);
batteryLevel = (byte) (data[10] & 0x0F);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[11];
data[0] = (byte) (data.length - 1);
data[1] = RFXComBaseMessage.PacketType.TEMPERATURE_RAIN.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((sensorId & 0xFF00) >> 8);
data[5] = (byte) (sensorId & 0x00FF);
short temp = (short) Math.abs(temperature * 10);
data[6] = (byte) ((temp >> 8) & 0xFF);
data[7] = (byte) (temp & 0xFF);
if (temperature < 0) {
data[6] |= 0x80;
}
short rainT = (short) Math.abs(rainTotal * 10);
data[8] = (byte) ((rainT >> 8) & 0xFF);
data[9] = (byte) (rainT & 0xFF);
data[10] = (byte) (((signalLevel & 0x0F) << 4) | (batteryLevel & 0x0F));
return data;
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_TEMPERATURE:
return new DecimalType(temperature);
case CHANNEL_RAIN_TOTAL:
return new DecimalType(rainTotal);
default:
return super.convertToState(channelId, deviceState);
}
}
@Override
public void convertFromState(String channelId, Type type) {
throw new UnsupportedOperationException();
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
@Override
public void setSubType(SubType subType) {
throw new UnsupportedOperationException();
}
@Override
public void setDeviceId(String deviceId) {
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,200 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
import org.openhab.core.types.UnDefType;
/**
* RFXCOM data class for thermostat1 message.
* Digimax 210 Thermostat RF sensor operational
*
* @author Les Ashworth - Initial contribution
* @author Pauli Anttila - Migrated for OH2
*/
public class RFXComThermostat1Message extends RFXComDeviceMessageImpl<RFXComThermostat1Message.SubType> {
public enum SubType implements ByteEnumWrapper {
DIGIMAX(0),
DIGIMAX_SHORT(1);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
/* Added item for ContactTypes */
public enum Status implements ByteEnumWrapper {
NO_STATUS(0),
DEMAND(1),
NO_DEMAND(2),
INITIALIZING(3);
private final int status;
Status(int status) {
this.status = status;
}
@Override
public byte toByte() {
return (byte) status;
}
}
/* Operating mode */
public enum Mode implements ByteEnumWrapper {
HEATING(0),
COOLING(1);
private final int mode;
Mode(int mode) {
this.mode = mode;
}
@Override
public byte toByte() {
return (byte) mode;
}
}
public SubType subType;
public int sensorId;
public byte temperature;
public byte set;
public Mode mode;
public Status status;
public RFXComThermostat1Message() {
super(PacketType.THERMOSTAT1);
}
public RFXComThermostat1Message(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = "";
str += super.toString();
str += ", Sub type = " + subType;
str += ", Device Id = " + getDeviceId();
str += ", Temperature = " + temperature;
str += ", Set = " + set;
str += ", Mode = " + mode;
str += ", Status = " + status;
str += ", Signal level = " + signalLevel;
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[4] & 0xFF) << 8 | (data[5] & 0xFF);
temperature = data[6];
set = data[7];
mode = fromByte(Mode.class, (data[8] & 0xF0) >> 7);
status = fromByte(Status.class, data[8] & 0x03);
signalLevel = (byte) ((data[9] & 0xF0) >> 4);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[10];
data[0] = 0x09;
data[1] = RFXComBaseMessage.PacketType.THERMOSTAT1.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((sensorId & 0xFF00) >> 8);
data[5] = (byte) (sensorId & 0x00FF);
data[6] = (temperature);
data[7] = (set);
data[8] = (byte) ((mode.toByte() << 7) | (status.toByte() & 0xFF));
data[9] = (byte) (signalLevel << 4);
return data;
}
@Override
public String getDeviceId() {
return String.valueOf(sensorId);
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_TEMPERATURE:
return new DecimalType(temperature);
case CHANNEL_SET_POINT:
return new DecimalType(set);
case CHANNEL_CONTACT:
switch (status) {
case DEMAND:
return OpenClosedType.CLOSED;
case NO_DEMAND:
return OpenClosedType.OPEN;
default:
return UnDefType.UNDEF;
}
default:
return super.convertToState(channelId, deviceState);
}
}
@Override
public void setSubType(SubType subType) {
throw new UnsupportedOperationException();
}
@Override
public void setDeviceId(String deviceId) {
throw new UnsupportedOperationException();
}
@Override
public void convertFromState(String channelId, Type type) {
throw new UnsupportedOperationException();
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
}

View File

@@ -0,0 +1,263 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import static org.openhab.binding.rfxcom.internal.messages.RFXComThermostat3Message.SubType.*;
import java.util.Arrays;
import java.util.List;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.library.types.StopMoveType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.library.types.UpDownType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
import org.openhab.core.types.UnDefType;
/**
* RFXCOM data class for thermostat3message.
*
* Mertik G6R-XXX Thermostat RF sensor operational
*
* @author Sander Biesenbeek - Initial contribution
* @author Ruud Beukema - Initial contribution (parallel development)
* @author Martin van Wingerden - Joined contribution of Sander & Ruud
*/
public class RFXComThermostat3Message extends RFXComDeviceMessageImpl<RFXComThermostat3Message.SubType> {
public enum SubType implements ByteEnumWrapper {
MERTIK__G6R_H4T1(0),
MERTIK__G6R_H4TB__G6R_H4T__G6R_H4T21_Z22(1),
MERTIK__G6R_H4TD__G6R_H4T16(2),
MERTIK__G6R_H4S_TRANSMIT_ONLY(3);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public enum Commands implements ByteEnumWrapperWithSupportedSubTypes<SubType> {
OFF(0),
ON(1),
UP(2),
DOWN(3),
RUN_UP(4, MERTIK__G6R_H4T1),
SECOND_OFF(4, MERTIK__G6R_H4TB__G6R_H4T__G6R_H4T21_Z22),
RUN_DOWN(5, MERTIK__G6R_H4T1),
SECOND_ON(5, MERTIK__G6R_H4TB__G6R_H4T__G6R_H4T21_Z22),
STOP(6, MERTIK__G6R_H4T1);
private final int command;
private final List<SubType> supportedBySubTypes;
Commands(int command) {
this(command, SubType.values());
}
Commands(int command, SubType... supportedBySubTypes) {
this.command = command;
this.supportedBySubTypes = Arrays.asList(supportedBySubTypes);
}
@Override
public byte toByte() {
return (byte) command;
}
@Override
public List<SubType> supportedBySubTypes() {
return supportedBySubTypes;
}
}
public SubType subType;
private int unitId;
public Commands command;
public RFXComThermostat3Message() {
super(PacketType.THERMOSTAT3);
}
public RFXComThermostat3Message(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = "";
str += super.toString();
str += ", Sub type = " + subType;
str += ", Device Id = " + getDeviceId();
str += ", Command = " + command;
str += ", Signal level = " + signalLevel;
return str;
}
@Override
public String getDeviceId() {
return String.valueOf(unitId);
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
unitId = (data[4] & 0xFF) << 16 | (data[5] & 0xFF) << 8 | (data[6] & 0xFF);
command = fromByte(Commands.class, data[7], subType);
signalLevel = (byte) ((data[8] & 0xF0) >> 4);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[9];
data[0] = 0x08;
data[1] = RFXComBaseMessage.PacketType.THERMOSTAT3.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((unitId >> 16) & 0xFF);
data[5] = (byte) ((unitId >> 8) & 0xFF);
data[6] = (byte) (unitId & 0xFF);
data[7] = command.toByte();
data[8] = (byte) ((signalLevel & 0x0F) << 4);
return data;
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_COMMAND:
switch (command) {
case RUN_DOWN:
case OFF:
return OnOffType.OFF;
case ON:
case RUN_UP:
case UP:
return OnOffType.ON;
case SECOND_ON:
case SECOND_OFF:
return null;
default:
return UnDefType.UNDEF;
}
case CHANNEL_CONTROL:
switch (command) {
case ON:
return OnOffType.ON;
case UP:
case RUN_UP:
return UpDownType.UP;
case OFF:
return OnOffType.OFF;
case DOWN:
case RUN_DOWN:
return UpDownType.DOWN;
case SECOND_ON:
case SECOND_OFF:
case STOP:
return null;
default:
throw new RFXComUnsupportedChannelException("Can't convert " + command + " for " + channelId);
}
case CHANNEL_COMMAND_SECOND:
switch (command) {
case SECOND_OFF:
return OnOffType.OFF;
case SECOND_ON:
return OnOffType.ON;
default:
return null;
}
case CHANNEL_COMMAND_STRING:
return command == null ? UnDefType.UNDEF : StringType.valueOf(command.toString());
default:
return super.convertToState(channelId, deviceState);
}
}
@Override
public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_COMMAND:
if (type instanceof OnOffType) {
command = (type == OnOffType.ON ? Commands.ON : Commands.OFF);
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
break;
case CHANNEL_COMMAND_SECOND:
if (type instanceof OnOffType) {
command = (type == OnOffType.ON ? Commands.SECOND_ON : Commands.SECOND_OFF);
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
break;
case CHANNEL_CONTROL:
if (type instanceof UpDownType) {
command = (type == UpDownType.UP ? Commands.UP : Commands.DOWN);
} else if (type == StopMoveType.STOP) {
command = Commands.STOP;
} else if (type instanceof PercentType) {
command = ((PercentType) type).as(UpDownType.class) == UpDownType.UP ? Commands.UP : Commands.DOWN;
} else {
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
}
break;
case CHANNEL_COMMAND_STRING:
command = Commands.valueOf(type.toString().toUpperCase());
break;
default:
throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
}
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
@Override
public void setSubType(SubType subType) {
this.subType = subType;
}
@Override
public void setDeviceId(String deviceId) {
this.unitId = Integer.parseInt(deviceId);
}
}

View File

@@ -0,0 +1,117 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for transmitter message.
*
* @author Pauli Anttila - Initial contribution
*/
public class RFXComTransmitterMessage extends RFXComBaseMessage {
public enum SubType implements ByteEnumWrapper {
ERROR_RECEIVER_DID_NOT_LOCK(0),
RESPONSE(1);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public enum Response implements ByteEnumWrapper {
ACK(0), // ACK, transmit OK
ACK_DELAYED(1), // ACK, but transmit started after 3 seconds delay
// anyway with RF receive data
NAK(2), // NAK, transmitter did not lock on the requested transmit
// frequency
NAK_INVALID_AC_ADDRESS(3); // NAK, AC address zero in id1-id4 not
// allowed
private final int response;
Response(int response) {
this.response = response;
}
@Override
public byte toByte() {
return (byte) response;
}
}
public SubType subType;
public Response response;
public RFXComTransmitterMessage() {
super(PacketType.TRANSMITTER_MESSAGE);
}
public RFXComTransmitterMessage(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
String str = "";
str += super.toString();
if (subType == SubType.RESPONSE) {
str += ", Sub type = " + subType;
str += ", Response = " + response;
} else {
str += ", Sub type = " + subType;
// Response not used
}
return str;
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
response = fromByte(Response.class, data[4]);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[5];
data[0] = 0x04;
data[1] = RFXComBaseMessage.PacketType.TRANSMITTER_MESSAGE.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = response.toByte();
return data;
}
@Override
public void convertFromState(String channelId, Type type) {
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,160 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
import org.openhab.core.types.UnDefType;
/**
* RFXCOM data class for UV and temperature message.
*
* @author Damien Servant - OpenHAB1 version
* @author Mike Jagdis - Initial contribution, OpenHAB2 version
*/
public class RFXComUVMessage extends RFXComBatteryDeviceMessage<RFXComUVMessage.SubType> {
public enum SubType implements ByteEnumWrapper {
UV1(1), // UVN128, UV138
UV2(2), // UVN800
UV3(3); // TFA
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public SubType subType;
public int sensorId;
public double uv;
public double temperature;
public RFXComUVMessage() {
super(PacketType.UV);
}
public RFXComUVMessage(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
//@formatter:off
return super.toString()
+ ", Sub type = " + subType
+ ", Device Id = " + getDeviceId()
+ ", UV = " + uv
+ ", Temperature = " + temperature
+ ", Signal level = " + signalLevel
+ ", Battery level = " + batteryLevel;
//@formatter:on
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[4] & 0xFF) << 8 | (data[5] & 0xFF);
uv = (data[6] & 0xFF) * 0.1;
temperature = (short) ((data[7] & 0x7F) << 8 | (data[8] & 0xFF)) * 0.1;
if ((data[7] & 0x80) != 0) {
temperature = -temperature;
}
signalLevel = (byte) ((data[9] & 0xF0) >> 4);
batteryLevel = (byte) (data[9] & 0x0F);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[10];
data[0] = 0x09;
data[1] = RFXComBaseMessage.PacketType.UV.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((sensorId & 0xFF00) >> 8);
data[5] = (byte) (sensorId & 0x00FF);
data[6] = (byte) (((short) (uv * 10)) & 0xFF);
short temp = (short) Math.abs(temperature * 10);
data[7] = (byte) ((temp >> 8) & 0xFF);
data[8] = (byte) (temp & 0xFF);
if (temperature < 0) {
data[7] |= 0x80;
}
data[9] = (byte) (((signalLevel & 0x0F) << 4) | (batteryLevel & 0x0F));
return data;
}
@Override
public String getDeviceId() {
return String.valueOf(sensorId);
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_UV:
return new DecimalType(uv);
case CHANNEL_TEMPERATURE:
return (subType == SubType.UV3 ? new DecimalType(temperature) : UnDefType.UNDEF);
default:
return super.convertToState(channelId, deviceState);
}
}
@Override
public void setSubType(SubType subType) {
throw new UnsupportedOperationException();
}
@Override
public void setDeviceId(String deviceId) {
throw new UnsupportedOperationException();
}
@Override
public void convertFromState(String channelId, Type type) {
throw new UnsupportedOperationException();
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
}

View File

@@ -0,0 +1,171 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage.PacketType.UNDECODED_RF_MESSAGE;
import java.util.Arrays;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
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.StringType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
import org.openhab.core.util.HexUtils;
/**
* RFXCOM data class for undecoded messages.
*
* @author Ivan Martinez - Initial contribution
* @author James Hewitt-Thomas - Migrated for OH2
*/
public class RFXComUndecodedRFMessage extends RFXComDeviceMessageImpl<RFXComUndecodedRFMessage.SubType> {
public enum SubType implements ByteEnumWrapper {
AC(0x00),
ARC(0x01),
ATI(0x02),
HIDEKI_UPM(0x03),
LACROSSE_VIKING(0x04),
AD(0x05),
MERTIK(0x06),
OREGON1(0x07),
OREGON2(0x08),
OREGON3(0x09),
PROGUARD(0x0A),
VISONIC(0x0B),
NEC(0x0C),
FS20(0x0D),
RESERVED(0x0E),
BLINDS(0x0F),
RUBICSON(0x10),
AE(0x11),
FINE_OFFSET(0x12),
RGB(0x13),
RTS(0x14),
SELECT_PLUS(0x15),
HOME_CONFORT(0x16),
UNKNOWN(0xFF);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
public static SubType fromByte(int input) {
for (SubType c : SubType.values()) {
if (c.subType == input) {
return c;
}
}
return SubType.UNKNOWN;
}
}
public SubType subType;
public byte[] rawPayload = new byte[0];
public RFXComUndecodedRFMessage() {
super(UNDECODED_RF_MESSAGE);
}
public RFXComUndecodedRFMessage(byte[] message) throws RFXComException {
encodeMessage(message);
}
@Override
public String toString() {
String str = super.toString();
str += ", Sub type = " + subType;
return str;
}
@Override
public void encodeMessage(byte[] message) throws RFXComException {
super.encodeMessage(message);
subType = SubType.fromByte(super.subType);
rawPayload = Arrays.copyOfRange(rawMessage, 4, rawMessage.length);
}
@Override
public byte[] decodeMessage() throws RFXComException {
if (rawPayload.length > 33) {
throw new RFXComMessageTooLongException("Longest payload according to RFXCOM spec is 33 bytes.");
}
final int rawPayloadLen = rawPayload.length;
byte[] data = new byte[4 + rawPayloadLen];
data[0] = (byte) (data.length - 1);
data[1] = UNDECODED_RF_MESSAGE.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
System.arraycopy(rawPayload, 0, data, 4, rawPayloadLen);
return data;
}
@Override
public String getDeviceId() {
return "UNDECODED";
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_RAW_MESSAGE:
return new StringType(HexUtils.bytesToHex(rawMessage));
case CHANNEL_RAW_PAYLOAD:
return new StringType(HexUtils.bytesToHex(rawPayload));
default:
throw new RFXComUnsupportedChannelException("Nothing relevant for " + channelId);
}
}
@Override
public void setSubType(SubType subType) {
throw new UnsupportedOperationException();
}
@Override
public void setDeviceId(String deviceId) {
throw new UnsupportedOperationException();
}
@Override
public void convertFromState(String channelId, Type type) {
throw new UnsupportedOperationException();
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
}

View File

@@ -0,0 +1,212 @@
/**
* Copyright (c) 2010-2020 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 static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
import org.openhab.binding.rfxcom.internal.handler.DeviceState;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
/**
* RFXCOM data class for temperature and humidity message.
*
* @author Marc SAUVEUR - Initial contribution
* @author Pauli Anttila - Migrated for OH2
* @author Mike Jagdis - Support all available data from sensors
*/
public class RFXComWindMessage extends RFXComBatteryDeviceMessage<RFXComWindMessage.SubType> {
public enum SubType implements ByteEnumWrapper {
WIND1(1),
WIND2(2),
WIND3(3),
WIND4(4),
WIND5(5),
WIND6(6),
WIND7(7);
private final int subType;
SubType(int subType) {
this.subType = subType;
}
@Override
public byte toByte() {
return (byte) subType;
}
}
public SubType subType;
public int sensorId;
public double windDirection;
public double windSpeed;
public double avgWindSpeed;
public double temperature;
public double chillTemperature;
public RFXComWindMessage() {
super(PacketType.WIND);
}
public RFXComWindMessage(byte[] data) throws RFXComException {
encodeMessage(data);
}
@Override
public String toString() {
//@formatter:off
return super.toString()
+ ", Sub type = " + subType
+ ", Device Id = " + getDeviceId()
+ ", Wind direction = " + windDirection
+ ", Wind gust = " + windSpeed
+ ", Average wind speed = " + avgWindSpeed
+ ", Temperature = " + temperature
+ ", Chill temperature = " + chillTemperature
+ ", Signal level = " + signalLevel
+ ", Battery level = " + batteryLevel;
//@formatter:on
}
@Override
public void encodeMessage(byte[] data) throws RFXComException {
super.encodeMessage(data);
subType = fromByte(SubType.class, super.subType);
sensorId = (data[4] & 0xFF) << 8 | (data[5] & 0xFF);
windDirection = (short) ((data[6] & 0xFF) << 8 | (data[7] & 0xFF));
if (subType != SubType.WIND5) {
avgWindSpeed = (short) ((data[8] & 0xFF) << 8 | (data[9] & 0xFF)) * 0.1;
}
windSpeed = (short) ((data[10] & 0xFF) << 8 | (data[11] & 0xFF)) * 0.1;
if (subType == SubType.WIND4) {
temperature = (short) ((data[12] & 0x7F) << 8 | (data[13] & 0xFF)) * 0.1;
if ((data[12] & 0x80) != 0) {
temperature = -temperature;
}
chillTemperature = (short) ((data[14] & 0x7F) << 8 | (data[15] & 0xFF)) * 0.1;
if ((data[14] & 0x80) != 0) {
chillTemperature = -chillTemperature;
}
}
signalLevel = (byte) ((data[16] & 0xF0) >> 4);
batteryLevel = (byte) (data[16] & 0x0F);
}
@Override
public byte[] decodeMessage() {
byte[] data = new byte[17];
data[0] = 0x10;
data[1] = PacketType.WIND.toByte();
data[2] = subType.toByte();
data[3] = seqNbr;
data[4] = (byte) ((sensorId & 0xFF00) >> 8);
data[5] = (byte) (sensorId & 0x00FF);
short absWindDirection = (short) Math.abs(windDirection);
data[6] = (byte) ((absWindDirection >> 8) & 0xFF);
data[7] = (byte) (absWindDirection & 0xFF);
if (subType != SubType.WIND5) {
int absAvgWindSpeedTimesTen = (short) Math.abs(avgWindSpeed) * 10;
data[8] = (byte) ((absAvgWindSpeedTimesTen >> 8) & 0xFF);
data[9] = (byte) (absAvgWindSpeedTimesTen & 0xFF);
}
int absWindSpeedTimesTen = (short) Math.abs(windSpeed) * 10;
data[10] = (byte) ((absWindSpeedTimesTen >> 8) & 0xFF);
data[11] = (byte) (absWindSpeedTimesTen & 0xFF);
if (subType == SubType.WIND4) {
int temp = (short) Math.abs(temperature) * 10;
data[12] = (byte) ((temp >> 8) & 0x7F);
data[13] = (byte) (temp & 0xFF);
if (temperature < 0) {
data[12] |= 0x80;
}
int chill = (short) Math.abs(chillTemperature) * 10;
data[14] = (byte) ((chill >> 8) & 0x7F);
data[15] = (byte) (chill & 0xFF);
if (chillTemperature < 0) {
data[14] |= 0x80;
}
}
data[16] = (byte) (((signalLevel & 0x0F) << 4) | (batteryLevel & 0x0F));
return data;
}
@Override
public String getDeviceId() {
return String.valueOf(sensorId);
}
@Override
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
switch (channelId) {
case CHANNEL_WIND_DIRECTION:
return new DecimalType(windDirection);
case CHANNEL_AVG_WIND_SPEED:
return new DecimalType(avgWindSpeed);
case CHANNEL_WIND_SPEED:
return new DecimalType(windSpeed);
case CHANNEL_TEMPERATURE:
return new DecimalType(temperature);
case CHANNEL_CHILL_TEMPERATURE:
return new DecimalType(chillTemperature);
default:
return super.convertToState(channelId, deviceState);
}
}
@Override
public void setSubType(SubType subType) {
throw new UnsupportedOperationException();
}
@Override
public void setDeviceId(String deviceId) {
throw new UnsupportedOperationException();
}
@Override
public void convertFromState(String channelId, Type type) {
throw new UnsupportedOperationException();
}
@Override
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
return ByteEnumUtil.convertSubType(SubType.class, subType);
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<binding:binding id="rfxcom" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
<name>RFXCOM Binding</name>
<description>This is the binding for RFXCOM transceivers.</description>
<author>Pauli Anttila</author>
</binding:binding>

View File

@@ -0,0 +1,163 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<bridge-type id="RFXrec433">
<label>RFXrec433 USB 433.92MHz Receiver</label>
<description>This is an RFXCOM 433.92MHz receiver bridge.</description>
<config-description>
<parameter name="bridgeId" type="text" required="true">
<label>Serial Number</label>
<description>Serial number of the RFXCOM (FTDI) device</description>
</parameter>
<parameter name="disableDiscovery" type="boolean" required="true">
<label>Disable Discovery of Unknown Devices</label>
<description>These RF protocols are prone to noise. If you find a lot of unknown devices showing up in your inbox
enabling this will stop devices being added to your inbox.</description>
<default>false</default>
</parameter>
<parameter name="ignoreConfig" type="boolean">
<label>Skip Transceiver Configuration</label>
<description>Fully skip and ignore RFXCOM transceiver configuration. Binding assume that RFXCOM transceiver is
preconfigured e.g. via RFXcom Manager. When this is enabled, both set mode command and individual message
configurations are ignored.</description>
<default>true</default>
</parameter>
<parameter name="setMode" type="text">
<label>RFXCOM Transceiver Mode</label>
<description>RFXCOM transceiver set mode command. Command should be in hexadecimal string format and 28 characters
(14 bytes) long. If set mode command is given, individual message configurations are ignored.</description>
</parameter>
<parameter name="transmitPower" type="integer" min="-18" max="10">
<label>Transmit Power</label>
<description>Transmit power in dBm, between -18dBm and +10dBm.</description>
<default>-18</default>
</parameter>
<parameter name="enableUndecoded" type="boolean">
<label>Undecoded Messages</label>
<description>Enable display of unencoded messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableImagintronixOpus" type="boolean">
<label>Imagintronix/Opus Messages</label>
<description>Enable Imagintronix/Opus messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableByronSX" type="boolean">
<label>Byron SX Messages</label>
<description>Enable Byron SX messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableRSL" type="boolean">
<label>RSL Messages</label>
<description>Enable RSL messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableLighting4" type="boolean">
<label>Lighting4 Messages</label>
<description>Enable Lighting4 messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableFineOffsetViking" type="boolean">
<label>FineOffset/Viking Messages</label>
<description>Enable FineOffset/Viking messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableRubicson" type="boolean">
<label>Rubicson Messages</label>
<description>Enable Rubicson messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableAEBlyss" type="boolean">
<label>AE Blyss Messages</label>
<description>Enable AE Blyss messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableBlindsT1T2T3T4" type="boolean">
<label>BlindsT1/T2/T3/T4 Messages</label>
<description>Enable BlindsT1/T2/T3/T4 messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableBlindsT0" type="boolean">
<label>BlindsT0 Messages</label>
<description>Enable BlindsT0 messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableFS20" type="boolean">
<label>FS20/Legrand CAD Messages</label>
<description>Enable FS20/Legrand CAD messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableLaCrosse" type="boolean">
<label>La Crosse Messages</label>
<description>Enable La Crosse messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableHidekiUPM" type="boolean">
<label>Hideki/UPM Messages</label>
<description>Enable Hideki/UPM messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableADLightwaveRF" type="boolean">
<label>AD LightwaveRF Messages</label>
<description>Enable AD LightwaveRF messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableMertik" type="boolean">
<label>Mertik Messages</label>
<description>Enable Mertik messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableATI" type="boolean">
<label>ATI Messages</label>
<description>Enable ATI messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableOregonScientific" type="boolean">
<label>Oregon Scientific Messages</label>
<description>Enable Oregon Scientific messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableMeiantech" type="boolean">
<label>Meiantech Messages</label>
<description>Enable Meiantech messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableHomeEasyEU" type="boolean">
<label>HomeEasy EU Messages</label>
<description>Enable HomeEasy EU messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableAC" type="boolean">
<label>AC Messages</label>
<description>Enable AC messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableARC" type="boolean">
<label>ARC Messages</label>
<description>Enable ARC messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableX10" type="boolean">
<label>X10 Messages</label>
<description>Enable X10 messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableHomeConfort" type="boolean">
<label>HomeConfort Messages</label>
<description>Enable HomeConfort messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableKEELOQ" type="boolean">
<label>KEELOQ Messages</label>
<description>Enable KEELOQ messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
</config-description>
</bridge-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<bridge-type id="RFXtrx315">
<label>RFXtrx315 USB 315MHz Transceiver</label>
<description>This is an RFXCOM 315MHz transceiver bridge.</description>
<config-description>
<parameter name="bridgeId" type="text" required="true">
<label>Serial Number</label>
<description>Serial number of the RFXCOM (FTDI) device</description>
</parameter>
<parameter name="disableDiscovery" type="boolean" required="true">
<label>Disable Discovery of Unknown Devices</label>
<description>These RF protocols are prone to noise. If you find a lot of unknown devices showing up in your inbox
enabling this will stop devices being added to your inbox.</description>
<default>false</default>
</parameter>
<parameter name="ignoreConfig" type="boolean">
<label>Skip Transceiver Configuration</label>
<description>Fully skip and ignore RFXCOM transceiver configuration. Binding assume that RFXCOM transceiver is
preconfigured e.g. via RFXcom Manager. When this is enabled, both set mode command and individual message
configurations are ignored.</description>
<default>true</default>
</parameter>
<parameter name="setMode" type="text">
<label>RFXCOM Transceiver Mode</label>
<description>RFXCOM transceiver set mode command. Command should be in hexadecimal string format and 28 characters
(14 bytes) long. If set mode command is given, individual message configurations are ignored.</description>
</parameter>
<parameter name="transceiverType" type="text">
<label>RFXCOM Transceiver Type</label>
<description>RFXCOM transceiver type.</description>
<default>315MHz</default>
<options>
<option value="310MHz">310MHz</option>
<option value="315MHz">315MHz</option>
</options>
</parameter>
<parameter name="transmitPower" type="integer" min="-18" max="10">
<label>Transmit Power</label>
<description>Transmit power in dBm, between -18dBm and +10dBm.</description>
<default>-18</default>
</parameter>
<parameter name="enableUndecoded" type="boolean">
<label>Undecoded Messages</label>
<description>Enable display of unencoded messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableVisonic" type="boolean">
<label>Visonic Messages</label>
<description>Enable Visonic messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableX10" type="boolean">
<label>X10 Messages</label>
<description>Enable X10 messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
</config-description>
</bridge-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,163 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<bridge-type id="RFXtrx433">
<label>RFXtrx433E USB 433.92MHz Transceiver</label>
<description>This is an RFXCOM 433.92MHz transceiver bridge.</description>
<config-description>
<parameter name="bridgeId" type="text" required="true">
<label>Serial Number</label>
<description>Serial number of the RFXCOM (FTDI) device</description>
</parameter>
<parameter name="disableDiscovery" type="boolean" required="true">
<label>Disable Discovery of Unknown Devices</label>
<description>These RF protocols are prone to noise. If you find a lot of unknown devices showing up in your inbox
enabling this will stop devices being added to your inbox.</description>
<default>false</default>
</parameter>
<parameter name="ignoreConfig" type="boolean">
<label>Skip Transceiver Configuration</label>
<description>Fully skip and ignore RFXCOM transceiver configuration. Binding assume that RFXCOM transceiver is
preconfigured e.g. via RFXcom Manager. When this is enabled, both set mode command and individual message
configurations are ignored.</description>
<default>true</default>
</parameter>
<parameter name="setMode" type="text">
<label>RFXCOM Transceiver Mode</label>
<description>RFXCOM transceiver set mode command. Command should be in hexadecimal string format and 28 characters
(14 bytes) long. If set mode command is given, individual message configurations are ignored.</description>
</parameter>
<parameter name="transmitPower" type="integer" min="-18" max="10">
<label>Transmit Power</label>
<description>Transmit power in dBm, between -18dBm and +10dBm.</description>
<default>-18</default>
</parameter>
<parameter name="enableUndecoded" type="boolean">
<label>Undecoded Messages</label>
<description>Enable display of unencoded messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableImagintronixOpus" type="boolean">
<label>Imagintronix/Opus Messages</label>
<description>Enable Imagintronix/Opus messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableByronSX" type="boolean">
<label>Byron SX Messages</label>
<description>Enable Byron SX messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableRSL" type="boolean">
<label>RSL Messages</label>
<description>Enable RSL messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableLighting4" type="boolean">
<label>Lighting4 Messages</label>
<description>Enable Lighting4 messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableFineOffsetViking" type="boolean">
<label>FineOffset/Viking Messages</label>
<description>Enable FineOffset/Viking messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableRubicson" type="boolean">
<label>Rubicson Messages</label>
<description>Enable Rubicson messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableAEBlyss" type="boolean">
<label>AE Blyss Messages</label>
<description>Enable AE Blyss messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableBlindsT1T2T3T4" type="boolean">
<label>BlindsT1/T2/T3/T4 Messages</label>
<description>Enable BlindsT1/T2/T3/T4 messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableBlindsT0" type="boolean">
<label>BlindsT0 Messages</label>
<description>Enable BlindsT0 messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableFS20" type="boolean">
<label>FS20/Legrand CAD Messages</label>
<description>Enable FS20/Legrand CAD messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableLaCrosse" type="boolean">
<label>La Crosse Messages</label>
<description>Enable La Crosse messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableHidekiUPM" type="boolean">
<label>Hideki/UPM Messages</label>
<description>Enable Hideki/UPM messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableADLightwaveRF" type="boolean">
<label>AD LightwaveRF Messages</label>
<description>Enable AD LightwaveRF messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableMertik" type="boolean">
<label>Mertik Messages</label>
<description>Enable Mertik messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableATI" type="boolean">
<label>ATI Messages</label>
<description>Enable ATI messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableOregonScientific" type="boolean">
<label>Oregon Scientific Messages</label>
<description>Enable Oregon Scientific messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableMeiantech" type="boolean">
<label>Meiantech Messages</label>
<description>Enable Meiantech messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableHomeEasyEU" type="boolean">
<label>HomeEasy EU Messages</label>
<description>Enable HomeEasy EU messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableAC" type="boolean">
<label>AC Messages</label>
<description>Enable AC messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableARC" type="boolean">
<label>ARC Messages</label>
<description>Enable ARC messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableX10" type="boolean">
<label>X10 Messages</label>
<description>Enable X10 messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableHomeConfort" type="boolean">
<label>HomeConfort Messages</label>
<description>Enable HomeConfort messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableKEELOQ" type="boolean">
<label>KEELOQ Messages</label>
<description>Enable KEELOQ messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
</config-description>
</bridge-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="bbqtemperature">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM BBQ Temperature Sensor</label>
<description>A BBQ Temperature device.</description>
<channels>
<channel id="foodTemperature" typeId="foodTemperature"/>
<channel id="bbqTemperature" typeId="bbqTemperature"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
<channel id="batteryLevel" typeId="system.battery-level"/>
<channel id="lowBattery" typeId="system.low-battery"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Sensor Id. Example 56923</description>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="blinds1">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Blinds1 Actuator</label>
<description>A Blinds1 device.</description>
<channels>
<channel id="command" typeId="command"/>
<channel id="shutter" typeId="shutter"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
<channel id="batteryLevel" typeId="system.battery-level"/>
<channel id="lowBattery" typeId="system.low-battery"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Sensor Id + unit code, separated by dot. Example 23455.1</description>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="T0">RollerTrol, Hasta new</option>
<option value="T1">Hasta old</option>
<option value="T2">A-OK RF01</option>
<option value="T3">A-OK AC114/AC123</option>
<option value="T4">Raex YR1326</option>
<option value="T5">Media Mount</option>
<option value="T6">DC106/Rohrmotor24-RMF/Yooda</option>
<option value="T7">Forest</option>
<option value="T8">Chamberlain CS4330CN</option>
<option value="T11">ASP</option>
</options>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,188 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<bridge-type id="bridge">
<label>RFXCOM USB Transceiver</label>
<description>This is universal RFXCOM transceiver bridge for manual configuration purposes.</description>
<config-description>
<parameter name="serialPort" type="text" required="true">
<label>Serial Port</label>
<context>serial-port</context>
<limitToOptions>false</limitToOptions>
<description>Serial port where RFXCOM transceiver is connected.</description>
</parameter>
<parameter name="disableDiscovery" type="boolean" required="true">
<label>Disable Discovery of Unknown Devices</label>
<description>These RF protocols are prone to noise. If you find a lot of unknown devices showing up in your inbox
enabling this will stop devices being added to your inbox.</description>
<default>false</default>
</parameter>
<parameter name="ignoreConfig" type="boolean" required="true">
<label>Skip Transceiver Configuration</label>
<description>Fully skip and ignore RFXCOM transceiver configuration. Binding assume that RFXCOM transceiver is
preconfigured e.g. via RFXcom Manager. When this is enabled, both set mode command and individual message
configurations are ignored.
</description>
<default>true</default>
</parameter>
<parameter name="setMode" type="text">
<label>RFXCOM Transceiver Mode</label>
<description>RFXCOM transceiver set mode command. Command should be in hexadecimal string format and 28 characters
(14 bytes) long. If set mode command is given, individual message configurations are ignored.
</description>
</parameter>
<parameter name="transceiverType" type="text">
<label>RFXCOM Transceiver Type</label>
<description>RFXCOM transceiver type.</description>
<default>433.92MHz</default>
<options>
<option value="310MHz">310MHz</option>
<option value="315MHz">315MHz</option>
<option value="433.92MHz receiver only">433.92MHz receiver only</option>
<option value="433.92MHz">433.92MHz</option>
</options>
</parameter>
<parameter name="transmitPower" type="integer" min="-18" max="10">
<label>Transmit Power</label>
<description>Transmit power in dBm, between -18dBm and +10dBm.</description>
<default>-18</default>
</parameter>
<parameter name="enableUndecoded" type="boolean">
<label>Undecoded Messages</label>
<description>Enable display of unencoded messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableImagintronixOpus" type="boolean">
<label>Imagintronix/Opus Messages</label>
<description>Enable Imagintronix/Opus messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableByronSX" type="boolean">
<label>Byron SX Messages</label>
<description>Enable Byron SX messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableRSL" type="boolean">
<label>RSL Messages</label>
<description>Enable RSL messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableLighting4" type="boolean">
<label>Lighting4 Messages</label>
<description>Enable Lighting4 messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableFineOffsetViking" type="boolean">
<label>FineOffset/Viking Messages</label>
<description>Enable FineOffset/Viking messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableRubicson" type="boolean">
<label>Rubicson Messages</label>
<description>Enable Rubicson messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableAEBlyss" type="boolean">
<label>AE Blyss Messages</label>
<description>Enable AE Blyss messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableBlindsT1T2T3T4" type="boolean">
<label>BlindsT1/T2/T3/T4 Messages</label>
<description>Enable BlindsT1/T2/T3/T4 messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableBlindsT0" type="boolean">
<label>BlindsT0 Messages</label>
<description>Enable BlindsT0 messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableProGuard" type="boolean">
<label>ProGuard Messages</label>
<description>Enable ProGuard messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableFS20" type="boolean">
<label>FS20/Legrand CAD Messages</label>
<description>Enable FS20/Legrand CAD messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableLaCrosse" type="boolean">
<label>La Crosse Messages</label>
<description>Enable La Crosse messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableHidekiUPM" type="boolean">
<label>Hideki/UPM Messages</label>
<description>Enable Hideki/UPM messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableADLightwaveRF" type="boolean">
<label>AD LightwaveRF Messages</label>
<description>Enable AD LightwaveRF messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableMertik" type="boolean">
<label>Mertik Messages</label>
<description>Enable Mertik messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableVisonic" type="boolean">
<label>Visonic Messages</label>
<description>Enable Visonic messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableATI" type="boolean">
<label>ATI Messages</label>
<description>Enable ATI messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableOregonScientific" type="boolean">
<label>Oregon Scientific Messages</label>
<description>Enable Oregon Scientific messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableMeiantech" type="boolean">
<label>Meiantech Messages</label>
<description>Enable Meiantech messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableHomeEasyEU" type="boolean">
<label>HomeEasy EU Messages</label>
<description>Enable HomeEasy EU messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableAC" type="boolean">
<label>AC Messages</label>
<description>Enable AC messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableARC" type="boolean">
<label>ARC Messages</label>
<description>Enable ARC messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableX10" type="boolean">
<label>X10 Messages</label>
<description>Enable X10 messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableHomeConfort" type="boolean">
<label>HomeConfort Messages</label>
<description>Enable HomeConfort messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableKEELOQ" type="boolean">
<label>KEELOQ Messages</label>
<description>Enable KEELOQ messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
</config-description>
</bridge-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,283 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<!-- Channel definitions -->
<channel-type id="rawmessage">
<item-type>String</item-type>
<label>Raw Message</label>
<description>Hexadecimal representation of undecoded RFXCOM messages including header and payload</description>
</channel-type>
<channel-type id="rawpayload">
<item-type>String</item-type>
<label>Raw Payload</label>
<description>Hexadecimal representation of payload of undecoded RFXCOM messages</description>
</channel-type>
<channel-type id="command">
<item-type>Switch</item-type>
<label>Command</label>
<description>Command channel</description>
</channel-type>
<channel-type id="commandId">
<item-type>Number</item-type>
<label>Command ID</label>
<description>Command channel, ID of the command</description>
<state min="0" max="255" step="1" pattern="%d" readOnly="false"></state>
</channel-type>
<channel-type id="commandString">
<item-type>String</item-type>
<label>Command String</label>
<description>Command channel, Name of the command</description>
</channel-type>
<channel-type id="contact">
<item-type>Contact</item-type>
<label>Contact</label>
<description>Contact channel</description>
</channel-type>
<channel-type id="datetime">
<item-type>DateTime</item-type>
<label>DateTime</label>
<description>DateTime channel</description>
</channel-type>
<channel-type id="dimminglevel">
<item-type>Dimmer</item-type>
<label>Dimming Level</label>
<description>Dimming level channel</description>
<state min="0" max="100" step="1" readOnly="false"></state>
</channel-type>
<channel-type id="fanspeed">
<item-type>Number</item-type>
<label>Fan Speed</label>
<description>Speed of fan</description>
<state min="1" max="6" step="1" readOnly="false"></state>
</channel-type>
<channel-type id="fanspeedcontrol">
<item-type>Rollershutter</item-type>
<label>Global Speed Control</label>
<description>Requested speed setting, UP, DOWN</description>
</channel-type>
<channel-type id="fanspeedstring">
<item-type>String</item-type>
<label>Fan Speed</label>
<description>Speed of fan</description>
<state readOnly="true">
<options>
<option value="HI">Hi</option>
<option value="MED">Med</option>
<option value="LOW">Low</option>
<option value="OFF">Off</option>
</options>
</state>
</channel-type>
<channel-type id="fanreverse">
<item-type>Switch</item-type>
<label>Reverse Fan</label>
<description>Reverse direction of the Fan</description>
</channel-type>
<channel-type id="mood">
<item-type>Number</item-type>
<label>Mood</label>
<description>Mood channel</description>
<state min="1" max="5" step="1" readOnly="false"></state>
</channel-type>
<channel-type id="status">
<item-type>String</item-type>
<label>Status</label>
<description>Status channel</description>
<state readOnly="false"></state>
</channel-type>
<channel-type id="setpoint">
<item-type>Number</item-type>
<label>Set-point</label>
<description>Requested temperature</description>
<state min="0" max="255" step="1" pattern="%d °C" readOnly="false"></state>
</channel-type>
<channel-type id="tempcontrol">
<item-type>Rollershutter</item-type>
<label>Global Temperature Control</label>
<description>Requested temperature setting, UP, DOWN, STOP</description>
</channel-type>
<channel-type id="motion">
<item-type>Switch</item-type>
<label>Motion</label>
<description>Motion detection sensor state</description>
<state readOnly="false"></state>
</channel-type>
<channel-type id="rainrate">
<item-type>Number</item-type>
<label>Rain Rate</label>
<description>Rain fall rate in millimeters per hour</description>
<state pattern="%d mm/h" readOnly="true"></state>
</channel-type>
<channel-type id="raintotal">
<item-type>Number</item-type>
<label>Rain Total</label>
<description>Total rain in millimeters</description>
<state pattern="%.1f mm" readOnly="true"></state>
</channel-type>
<channel-type id="shutter">
<item-type>Rollershutter</item-type>
<label>Shutter</label>
<description>Open/Close shutter/blind</description>
</channel-type>
<channel-type id="venetianBlind">
<item-type>Dimmer</item-type>
<label>Venetian Blind</label>
<description>Open/close and adjust angle of venetian blind</description>
</channel-type>
<channel-type id="voltage">
<item-type>Number</item-type>
<label>Voltage</label>
<description>Measured voltage</description>
<state pattern="%d V" readOnly="true"></state>
</channel-type>
<channel-type id="instantpower">
<item-type>Number</item-type>
<label>Instant Power</label>
<description>Instant power consumption in Watts</description>
<state pattern="%d W" readOnly="true"></state>
</channel-type>
<channel-type id="totalusage">
<item-type>Number</item-type>
<label>Total Usage</label>
<description>Used energy in Watt hours</description>
<state pattern="%d Wh" readOnly="true"></state>
</channel-type>
<channel-type id="instantamp" advanced="true">
<item-type>Number</item-type>
<label>Instant Amp</label>
<description>Instant current in Amperes</description>
<state pattern="%.2f A" readOnly="true"></state>
</channel-type>
<channel-type id="totalamphour" advanced="true">
<item-type>Number</item-type>
<label>Total Ampere-hours</label>
<description>Used "energy" in ampere-hours</description>
<state pattern="%.2f Ah" readOnly="true"></state>
</channel-type>
<channel-type id="uv">
<item-type>Number</item-type>
<label>UV</label>
<description>Current UV level</description>
<state pattern="%.1f" readOnly="true"></state>
</channel-type>
<channel-type id="temperature">
<item-type>Number</item-type>
<label>Temperature</label>
<description>Current temperature in degree Celsius</description>
<category>Temperature</category>
<state pattern="%.1f °C" readOnly="true"></state>
</channel-type>
<channel-type id="foodTemperature">
<item-type>Number</item-type>
<label>Food Temperature</label>
<description>Current food temperature in degrees Celsius</description>
<category>Temperature</category>
<state pattern="%.1f °C" readOnly="true"></state>
</channel-type>
<channel-type id="bbqTemperature">
<item-type>Number</item-type>
<label>BBQ Temperature</label>
<description>Current BBQ temperature in degrees Celsius</description>
<category>Temperature</category>
<state pattern="%.1f °C" readOnly="true"></state>
</channel-type>
<channel-type id="humidity">
<item-type>Number</item-type>
<label>Humidity</label>
<description>Relative humidity level in percentages</description>
<category>Humidity</category>
<state min="0" max="100" step="1" pattern="%d %%" readOnly="true"></state>
</channel-type>
<channel-type id="humiditystatus" advanced="true">
<item-type>String</item-type>
<label>Humidity Status</label>
<description>Current humidity status</description>
<state readOnly="true">
<options>
<option value="NORMAL">Normal</option>
<option value="COMFORT">Comfort</option>
<option value="DRY">Dry</option>
<option value="WET">Wet</option>
</options>
</state>
</channel-type>
<channel-type id="pressure">
<item-type>Number</item-type>
<label>Pressure</label>
<description>Barometric value in hPa.</description>
<category>Pressure</category>
<state min="0" max="2000" step="1" pattern="%d hPa." readOnly="true"></state>
</channel-type>
<channel-type id="forecast">
<item-type>String</item-type>
<label>Forecast</label>
<description>Weather forecast from device</description>
<state readOnly="true">
<options>
<option value="NO_INFO_AVAILABLE">No information available</option>
<option value="SUNNY">Sunny</option>
<option value="PARTLY_CLOUDY">Partly cloudy</option>
<option value="CLOUDY">Cloudy</option>
<option value="RAIN">Rain</option>
</options>
</state>
</channel-type>
<channel-type id="windspeed">
<item-type>Number</item-type>
<label>Wind Speed</label>
<description>Average wind speed in meters per second</description>
<state pattern="%d m/s" readOnly="true"></state>
</channel-type>
<channel-type id="winddirection">
<item-type>Number</item-type>
<label>Wind Direction</label>
<description>Wind direction in degrees</description>
<state min="0" max="360" step="1" readOnly="true"></state>
</channel-type>
<channel-type id="chimesound">
<item-type>Number</item-type>
<label>Chime Sound</label>
<description>Chime Sound (not all devices support multiple sounds)</description>
</channel-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="chime">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Chime</label>
<description>A Chime device.</description>
<channels>
<channel id="chimeSound" typeId="chimesound"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Sensor Id. Example 2983</description>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="BYRONSX">Byron SX</option>
<option value="BYRONMP001">Byron MP001</option>
<option value="SELECTPLUS">SelectPlus</option>
<option value="SELECTPLUS3">SelectPlus3</option>
<option value="ENVIVO">Envivo</option>
</options>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="current">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Current Sensor</label>
<description>A Current sensing device.</description>
<channels>
<channel id="channel1Amps" typeId="instantamp"/>
<channel id="channel2Amps" typeId="instantamp"/>
<channel id="channel3Amps" typeId="instantamp"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
<channel id="batteryLevel" typeId="system.battery-level"/>
<channel id="lowBattery" typeId="system.low-battery"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Sensor Id. Example 5693</description>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="ELEC1">CM113</option>
</options>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="currentenergy">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM CurrentEnergy Actuator</label>
<description>A CurrentEnergy device.</description>
<channels>
<channel id="channel1Amps" typeId="instantamp"/>
<channel id="channel2Amps" typeId="instantamp"/>
<channel id="channel3Amps" typeId="instantamp"/>
<channel id="totalUsage" typeId="totalusage"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
<channel id="batteryLevel" typeId="system.battery-level"/>
<channel id="lowBattery" typeId="system.low-battery"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Sensor Id. Example 47104</description>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="ELEC4">OWL - CM180i</option>
</options>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="curtain1">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Curtain1 Actuator</label>
<description>A Curtain1 device.</description>
<channels>
<channel id="command" typeId="command"/>
<channel id="shutter" typeId="shutter"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
<channel id="batteryLevel" typeId="system.battery-level"/>
<channel id="lowBattery" typeId="system.low-battery"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>House code + unit code, separated by dot. Example A.1</description>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="HARRISON">Harrison Curtain</option>
</options>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="datetime">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Date/time Sensor</label>
<description>A DateTime device.</description>
<channels>
<channel id="dateTime" typeId="datetime"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
<channel id="batteryLevel" typeId="system.battery-level"/>
<channel id="lowBattery" typeId="system.low-battery"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Device id, example 47360</description>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="RTGR328N">Oregon RTGR328N</option>
</options>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="energy">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Energy Sensor</label>
<description>A Energy device.</description>
<channels>
<channel id="instantPower" typeId="instantpower"/>
<channel id="totalUsage" typeId="totalusage"/>
<channel id="instantAmp" typeId="instantamp"/>
<channel id="totalAmpHour" typeId="totalamphour"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
<channel id="batteryLevel" typeId="system.battery-level"/>
<channel id="lowBattery" typeId="system.low-battery"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Sensor Id. Example 5693</description>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="ELEC2">CM119/160</option>
<option value="ELEC3">CM180</option>
</options>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="fan">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Fan Device</label>
<description>A generic fan device.</description>
<channels>
<channel id="command" typeId="command"/>
<channel id="fanSpeed" typeId="fanspeedstring"/>
<channel id="fanLight" typeId="command"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Unit Id. Example 'B', '7' or 'D'</description>
<options>
<option value="00">0</option>
<option value="01">1</option>
<option value="02">2</option>
<option value="03">3</option>
<option value="04">4</option>
<option value="05">5</option>
<option value="06">6</option>
<option value="07">7</option>
<option value="08">8</option>
<option value="09">9</option>
<option value="10">A</option>
<option value="11">B</option>
<option value="12">C</option>
<option value="13">D</option>
<option value="14">E</option>
<option value="15">F</option>
</options>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="LUCCI_AIR_FAN">Lucci Air fan</option>
<option value="CASAFAN">Casafan</option>
<option value="WESTINGHOUSE_7226640">Westinghouse 7226640</option>
</options>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="fan_falmec">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Fan Device - Falmec</label>
<description>A Falmec fan device.</description>
<channels>
<channel id="command" typeId="command"/>
<channel id="fanSpeed" typeId="fanspeed"/>
<channel id="fanLight" typeId="command"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Unit Id. Example 1000</description>
</parameter>
<parameter name="subType" type="text">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="FALMEC">Falmec</option>
</options>
<default>FALMEC</default>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="fan_lucci_dc">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Fan Device - Lucci Air DC</label>
<description>A Lucci Air DC fan device.</description>
<channels>
<channel id="commandString" typeId="commandString"/>
<channel id="fanSpeed" typeId="fanspeedcontrol"/>
<channel id="fanLight" typeId="command"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Unit Id. Example 1000</description>
</parameter>
<parameter name="subType" type="text">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="LUCCI_AIR_DC">Lucci Air DC</option>
</options>
<default>LUCCI_AIR_DC</default>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="fan_lucci_dc_ii">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Fan Device - Lucci Air DC II</label>
<description>A Lucci Air DC II fan device.</description>
<channels>
<channel id="command" typeId="command"/>
<channel id="commandString" typeId="commandString"/>
<channel id="fanSpeed" typeId="fanspeed"/>
<channel id="fanLight" typeId="command"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Unit Id. Example 1000</description>
</parameter>
<parameter name="subType" type="text">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="LUCCI_AIR_DC_II">Lucci Air DC II</option>
</options>
<default>LUCCI_AIR_DC_II</default>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="homeconfort">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx315"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Home Confort Remote</label>
<description>A Home Confort device.</description>
<channels>
<channel id="command" typeId="command"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Device Id. Unit ID + house code + unit code, each separated by dot. Example 1234.A.1</description>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="humidity">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Humidity Sensor</label>
<description>A Humidity device.</description>
<channels>
<channel id="humidity" typeId="humidity"/>
<channel id="humidityStatus" typeId="humiditystatus"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
<channel id="batteryLevel" typeId="system.battery-level"/>
<channel id="lowBattery" typeId="system.low-battery"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Sensor Id. Example 5693</description>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="HUM1">LaCrosse TX3</option>
<option value="HUM2">LaCrosse WS2300</option>
</options>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="lighting1">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx315"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Lighting1 Actuator</label>
<description>A Lighting1 device.</description>
<channels>
<channel id="command" typeId="command"/>
<channel id="commandString" typeId="commandString"/>
<channel id="contact" typeId="contact"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Device Id. House code + unit code, separated by dot. Example A.1</description>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="X10">X10 lighting</option>
<option value="ARC">ARC</option>
<option value="AB400D">ELRO AB400D (Flamingo)</option>
<option value="WAVEMAN">Waveman</option>
<option value="EMW200">Chacon EMW200</option>
<option value="IMPULS">IMPULS</option>
<option value="RISINGSUN">RisingSun</option>
<option value="PHILIPS">Philips SBC</option>
<option value="ENERGENIE">Energenie ENER010</option>
<option value="ENERGENIE_5">Energenie 5-gang</option>
<option value="COCO">COCO GDR2-2000R</option>
<option value="HQ_COCO20">HQ COCO-20</option>
</options>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="lighting2">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Lighting2 Actuator</label>
<description>A Lighting2 device.</description>
<channels>
<channel id="command" typeId="command"/>
<channel id="contact" typeId="contact"/>
<channel id="dimmingLevel" typeId="dimminglevel"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Remote/switch/unit Id + unit code, separated by dot. Example 8773718.10</description>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="AC">AC</option>
<option value="HOME_EASY_EU">HomeEasy EU</option>
<option value="ANSLUT">ANSLUT</option>
<option value="KAMBROOK">Kambrook RF3672</option>
</options>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="lighting4">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Lighting4 Actuator</label>
<description>A Lighting4 device.</description>
<channels>
<channel id="command" typeId="command"/>
<channel id="commandId" typeId="commandId"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Device Id. Example 3456</description>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="PT2262">PT2262</option>
</options>
</parameter>
<parameter name="pulse" type="integer" min="100" max="800">
<label>Pulse Length</label>
<description>Pulse length of the device</description>
<default>350</default>
</parameter>
<parameter name="onCommandId" type="integer" required="true">
<label>On Command</label>
<description>Specifies command to be send when ON must be transmitted</description>
<options>
<option value="0">OFF (value 0)</option>
<option value="1">ON (value 1)</option>
<option value="2">OFF (value 2)</option>
<option value="3">ON (value 3)</option>
<option value="4">OFF (value 4)</option>
<option value="5">ON (value 5)</option>
<option value="6">value 5</option>
<option value="7">ON (value 7)</option>
<option value="8">value 8</option>
<option value="9">ON (value 9)</option>
<option value="10">ON (value 10)</option>
<option value="11">ON (value 11)</option>
<option value="12">ON (value 12)</option>
<option value="13">value 13</option>
<option value="14">OFF (value 14)</option>
<option value="15">value 15</option>
</options>
<default>1</default>
</parameter>
<parameter name="offCommandId" type="integer" required="true">
<label>Off Command</label>
<description>Specifies command to be send when OFF must be transmitted</description>
<options>
<option value="0">OFF (value 0)</option>
<option value="1">ON (value 1)</option>
<option value="2">OFF (value 2)</option>
<option value="3">ON (value 3)</option>
<option value="4">OFF (value 4)</option>
<option value="5">ON (value 5)</option>
<option value="6">value 5</option>
<option value="7">ON (value 7)</option>
<option value="8">value 8</option>
<option value="9">ON (value 9)</option>
<option value="10">ON (value 10)</option>
<option value="11">ON (value 11)</option>
<option value="12">ON (value 12)</option>
<option value="13">value 13</option>
<option value="14">OFF (value 14)</option>
<option value="15">value 15</option>
</options>
<default>4</default>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="lighting5">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Lighting5 Actuator</label>
<description>A Lighting5 device.</description>
<channels>
<channel id="command" typeId="command"/>
<channel id="contact" typeId="contact"/>
<channel id="dimmingLevel" typeId="dimminglevel"/>
<channel id="mood" typeId="mood"/>
<channel id="commandString" typeId="commandString"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Remote/switch/unit Id + unit code, separated by dot. Example 10001.1</description>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="AOKE">Aoke Relay</option>
<option value="AVANTEK">Avantek</option>
<option value="BBSB_NEW">BBSB new types</option>
<option value="CONRAD_RSL2">Conrad RSL2</option>
<option value="EMW100">EMW100 GAO/Everflourish</option>
<option value="EURODOMEST">Eurodomest</option>
<option value="IT">IT</option>
<option value="KANGTAI">Kangtai, Cotech</option>
<option value="LIGHTWAVERF">LightwaveRF, Siemens</option>
<option value="LIVOLO">Livolo Dimmer or On/Off 1-3</option>
<option value="LIVOLO_APPLIANCE">Livolo Appliance On/Off 1-10</option>
<option value="MDREMOTE">MDREMOTE LED dimmer v106</option>
<option value="MDREMOTE_107">MDREMOTE v107</option>
<option value="MDREMOTE_108">MDREMOTE v108, EKAB-10KRF</option>
<option value="RGB_TRC02">RGB TRC02 (2 batt)</option>
<option value="RGB_TRC02_2">RGB TRC02_2 (3 batt)</option>
</options>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="lighting6">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Lighting6 Actuator</label>
<description>A Lighting6 device.</description>
<channels>
<channel id="command" typeId="command"/>
<channel id="contact" typeId="contact"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Remote/switch/unit Id + group code + unit code, separated by dot. Example 100.A.1</description>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="BLYSS">Blyss</option>
</options>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="rain">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Rain Sensor</label>
<description>A Rain device.</description>
<channels>
<channel id="rainRate" typeId="rainrate"/>
<channel id="rainTotal" typeId="raintotal"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
<channel id="batteryLevel" typeId="system.battery-level"/>
<channel id="lowBattery" typeId="system.low-battery"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Sensor Id. Example 56923</description>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="RAIN1">RGR126/682/918/928</option>
<option value="RAIN2">PCR800</option>
<option value="RAIN3">TFA</option>
<option value="RAIN4">UPM RG700</option>
<option value="RAIN5">WS2300</option>
<option value="RAIN6">La Crosse TX5</option>
</options>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="rfxsensor">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM RFXSensor</label>
<description>A RFXSensor device.</description>
<channels>
<channel id="temperature" typeId="temperature"/>
<channel id="referenceVoltage" typeId="voltage"/>
<channel id="voltage" typeId="voltage"/>
<channel id="humidity" typeId="humidity"/>
<channel id="pressure" typeId="pressure"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Sensor Id. Example 8</description>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="rfy">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Rfy Actuator</label>
<description>A Rfy device.</description>
<channels>
<channel id="command" typeId="command"/>
<channel id="program" typeId="command">
<label>Send Program Command</label>
<description>Sends a program command to pair with a device when switched from off to on.</description>
</channel>
<channel id="shutter" typeId="shutter"/>
<channel id="venetianBlind" typeId="venetianBlind"/>
<channel id="sunWindDetector" typeId="command">
<label>Sun+Wind Detector</label>
<description>Enable the sun+wind detector.</description>
</channel>
<channel id="signalLevel" typeId="system.signal-strength"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Unit Id + unit code, separated by dot. Example 100.1</description>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="RFY">RFY</option>
<option value="RFY_EXT">RFY Ext</option>
<option value="ASA">ASA</option>
</options>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="security1">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXtrx315"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Security1 Sensor</label>
<description>A Security1 device.</description>
<channels>
<channel id="status" typeId="status"/>
<channel id="contact" typeId="contact"/>
<channel id="motion" typeId="motion"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
<channel id="batteryLevel" typeId="system.battery-level"/>
<channel id="lowBattery" typeId="system.low-battery"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Remote/sensor Id. Example 10001</description>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="X10_SECURITY">X10 security door/window sensor</option>
<option value="X10_SECURITY_MOTION">X10 security motion sensor</option>
<option value="X10_SECURITY_REMOTE">X10 security remote (no alive packets)</option>
<option value="KD101">KD101 (no alive packets)</option>
<option value="VISONIC_POWERCODE_SENSOR_PRIMARY_CONTACT">Visonic PowerCode door/window sensor primary contact (with alive packets)</option>
<option value="VISONIC_POWERCODE_MOTION">Visonic PowerCode motion sensor (with alive packets)</option>
<option value="VISONIC_CODESECURE">Visonic CodeSecure (no alive packets)</option>
<option value="VISONIC_POWERCODE_SENSOR_AUX_CONTACT">Visonic PowerCode door/window sensor auxiliary contact (no alive packets)</option>
<option value="MEIANTECH">Meiantech</option>
<option value="SA30">SA30 (no alive packets)</option>
</options>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="security2">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXtrx315"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Security2 Sensor</label>
<description>A Security2 device.</description>
<channels>
<channel id="contact" typeId="contact"/>
<channel id="contact1" typeId="contact"/>
<channel id="contact2" typeId="contact"/>
<channel id="contact3" typeId="contact"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
<channel id="batteryLevel" typeId="system.battery-level"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Remote/sensor Id. Example 10001</description>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,190 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<bridge-type id="tcpbridge">
<label>RFXCOM USB Transceiver over TCP/IP</label>
<description>This is universal RFXCOM transceiver bridge for using RFXCOM devices over a TCP/IP connection.</description>
<config-description>
<parameter name="host" type="text" required="true">
<label>Host</label>
<description>Host where RFXCOM transceiver is connected.</description>
<context>network-address</context>
</parameter>
<parameter name="port" type="integer" required="true">
<label>Port</label>
<description>Port where RFXCOM transceiver is connected.</description>
<default>10001</default>
</parameter>
<parameter name="disableDiscovery" type="boolean" required="true">
<label>Disable Discovery of Unknown Devices</label>
<description>These RF protocols are prone to noise. If you find a lot of unknown devices showing up in your inbox
enabling this will stop devices being added to your inbox.</description>
<default>false</default>
</parameter>
<parameter name="ignoreConfig" type="boolean" required="true">
<label>Skip Transceiver Configuration</label>
<description>Fully skip and ignore RFXCOM transceiver configuration. Binding assume that RFXCOM transceiver is
preconfigured e.g. via RFXcom Manager. When this is enabled, both set mode command and individual message
configurations are ignored.</description>
<default>true</default>
</parameter>
<parameter name="setMode" type="text">
<label>RFXCOM Transceiver Mode</label>
<description>RFXCOM transceiver set mode command. Command should be in hexadecimal string format and 28 characters
(14 bytes) long. If set mode command is given, individual message configurations are ignored.</description>
</parameter>
<parameter name="transceiverType" type="text">
<label>RFXCOM Transceiver Type</label>
<description>RFXCOM transceiver type.</description>
<default>433.92MHz</default>
<options>
<option value="310MHz">310MHz</option>
<option value="315MHz">315MHz</option>
<option value="433.92MHz receiver only">433.92MHz receiver only</option>
<option value="433.92MHz">433.92MHz</option>
</options>
</parameter>
<parameter name="transmitPower" type="integer" min="-18" max="10">
<label>Transmit Power</label>
<description>Transmit power in dBm, between -18dBm and +10dBm.</description>
<default>-18</default>
</parameter>
<parameter name="enableUndecoded" type="boolean">
<label>Undecoded Messages</label>
<description>Enable display of unencoded messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableImagintronixOpus" type="boolean">
<label>Imagintronix/Opus Messages</label>
<description>Enable Imagintronix/Opus messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableByronSX" type="boolean">
<label>Byron SX Messages</label>
<description>Enable Byron SX messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableRSL" type="boolean">
<label>RSL Messages</label>
<description>Enable RSL messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableLighting4" type="boolean">
<label>Lighting4 Messages</label>
<description>Enable Lighting4 messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableFineOffsetViking" type="boolean">
<label>FineOffset/Viking Messages</label>
<description>Enable FineOffset/Viking messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableRubicson" type="boolean">
<label>Rubicson Messages</label>
<description>Enable Rubicson messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableAEBlyss" type="boolean">
<label>AE Blyss Messages</label>
<description>Enable AE Blyss messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableBlindsT1T2T3T4" type="boolean">
<label>BlindsT1/T2/T3/T4 Messages</label>
<description>Enable BlindsT1/T2/T3/T4 messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableBlindsT0" type="boolean">
<label>BlindsT0 Messages</label>
<description>Enable BlindsT0 messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableProGuard" type="boolean">
<label>ProGuard Messages</label>
<description>Enable ProGuard messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableFS20" type="boolean">
<label>FS20/Legrand CAD Messages</label>
<description>Enable FS20/Legrand CAD messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableLaCrosse" type="boolean">
<label>La Crosse Messages</label>
<description>Enable La Crosse messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableHidekiUPM" type="boolean">
<label>Hideki/UPM Messages</label>
<description>Enable Hideki/UPM messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableADLightwaveRF" type="boolean">
<label>AD LightwaveRF Messages</label>
<description>Enable AD LightwaveRF messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableMertik" type="boolean">
<label>Mertik Messages</label>
<description>Enable Mertik messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableVisonic" type="boolean">
<label>Visonic Messages</label>
<description>Enable Visonic messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableATI" type="boolean">
<label>ATI Messages</label>
<description>Enable ATI messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableOregonScientific" type="boolean">
<label>Oregon Scientific Messages</label>
<description>Enable Oregon Scientific messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableMeiantech" type="boolean">
<label>Meiantech Messages</label>
<description>Enable Meiantech messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableHomeEasyEU" type="boolean">
<label>HomeEasy EU Messages</label>
<description>Enable HomeEasy EU messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableAC" type="boolean">
<label>AC Messages</label>
<description>Enable AC messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableARC" type="boolean">
<label>ARC Messages</label>
<description>Enable ARC messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableX10" type="boolean">
<label>X10 Messages</label>
<description>Enable X10 messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableHomeConfort" type="boolean">
<label>HomeConfort Messages</label>
<description>Enable HomeConfort messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
<parameter name="enableKEELOQ" type="boolean">
<label>KEELOQ Messages</label>
<description>Enable KEELOQ messages to RFXCOM transceiver.</description>
<default>false</default>
</parameter>
</config-description>
</bridge-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="temperature">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Temperature Sensor</label>
<description>A Temperature device.</description>
<channels>
<channel id="temperature" typeId="temperature"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
<channel id="batteryLevel" typeId="system.battery-level"/>
<channel id="lowBattery" typeId="system.low-battery"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Sensor Id. Example 56923</description>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="TEMP1">THR128/138, THC138</option>
<option value="TEMP2">THC238/268,THN132,THWR288,THRN122,THN122,AW129/131</option>
<option value="TEMP3">THWR800</option>
<option value="TEMP4">RTHN318</option>
<option value="TEMP5">La Crosse TX2, TX3, TX4, TX17</option>
<option value="TEMP6">TS15C. UPM temp only</option>
<option value="TEMP7">Viking 02811, Proove TSS330, 311346</option>
<option value="TEMP8">La Crosse WS2300</option>
<option value="TEMP9">Rubicson</option>
<option value="TEMP10">TFA 30.3133</option>
<option value="TEMP11">WT0122</option>
</options>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="temperaturehumidity">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Temperature-Humidity Sensor</label>
<description>A Temperature-Humidity device.</description>
<channels>
<channel id="temperature" typeId="temperature"/>
<channel id="humidity" typeId="humidity"/>
<channel id="humidityStatus" typeId="humiditystatus"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
<channel id="batteryLevel" typeId="system.battery-level"/>
<channel id="lowBattery" typeId="system.low-battery"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Sensor Id. Example 56923</description>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="TH1">THGN122/123, THGN132, THGR122/228/238/268</option>
<option value="TH2">THGR810, THGN800</option>
<option value="TH3">RTGR328</option>
<option value="TH4">THGR328</option>
<option value="TH5">WTGR800</option>
<option value="TH6">THGR918/928, THGRN228, THGN500</option>
<option value="TH7">TFA TS34C, Cresta</option>
<option value="TH8">WT260,WT260H,WT440H,WT450,WT450H</option>
<option value="TH9">Viking 02035,02038 (02035 has no humidity), Proove TSS320, 311501</option>
<option value="TH10">Rubicson</option>
<option value="TH11">EW109</option>
<option value="TH12">Imagintronix/Opus XT300 Soil sensor</option>
<option value="TH13">Alecto WS1700 and compatibles</option>
</options>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="rfxcom"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="temperaturehumiditybarometric">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="tcpbridge"/>
<bridge-type-ref id="RFXtrx433"/>
<bridge-type-ref id="RFXrec433"/>
</supported-bridge-type-refs>
<label>RFXCOM Temperature-Humidity-Barometric Sensor</label>
<description>A Temperature-Humidity-Barometric device.</description>
<channels>
<channel id="temperature" typeId="temperature"/>
<channel id="humidity" typeId="humidity"/>
<channel id="humidityStatus" typeId="humiditystatus"/>
<channel id="pressure" typeId="pressure"/>
<channel id="forecast" typeId="forecast"/>
<channel id="signalLevel" typeId="system.signal-strength"/>
<channel id="batteryLevel" typeId="system.battery-level"/>
<channel id="lowBattery" typeId="system.low-battery"/>
</channels>
<config-description>
<parameter name="deviceId" type="text" required="true">
<label>Device Id</label>
<description>Sensor Id. Example 59648</description>
</parameter>
<parameter name="subType" type="text" required="true">
<label>Sub Type</label>
<description>Specifies device sub type.</description>
<options>
<option value="THB1">BTHR918, BTHGN129</option>
<option value="THB2">BTHR918N, BTHR968</option>
</options>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

Some files were not shown because too many files have changed in this diff Show More