- [SmartHome Bewegungsmelder](https://www.smarthome.de/geraete/telekom-smarthome-bewegungsmelder-innen) - a motion sensor (thing type `HAN_FUN_CONTACT`)
- [SmartHome Rauchmelder](https://www.smarthome.de/geraete/smarthome-rauchmelder-weiss) - a smoke detector (thing type `HAN_FUN_CONTACT`)
- [SmartHome Wandtaster](https://www.smarthome.de/geraete/telekom-smarthome-wandtaster) - a switch with two buttons (thing type `HAN_FUN_SWITCH`)
+- [Rollershutter/Blinds](https://www.rademacher.de/shop/rollladen-sonnenschutz/elektrischer-gurtwickler/rollotron-dect-1213) - an electronic belt winder (thing type `HAN_FUN_BLINDS`)
The use of other Sensors should be possible, if these are compatible with DECT-ULE / HAN-FUN standards.
| battery_low | Switch | Battery level low (ON/OFF) - FRITZ!OS 6.80 | FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT, FRITZ!DECT 400, FRITZ!DECT 440 |
| contact_state | Contact | Contact state information (OPEN/CLOSED). | HAN-FUN contact (e.g. SmartHome Tür-/Fensterkontakt or SmartHome Bewegungsmelder)- FRITZ!OS 7 |
| last_change | DateTime | States the last time the button was pressed. | FRITZ!DECT 400, FRITZ!DECT 440, HAN-FUN switch (e.g. SmartHome Wandtaster) - FRITZ!OS 7 |
+| rollershutter | Rollershutter | Rollershutter control and status. Accepts UP/DOWN/STOP commands and the opening level in percent. States the opening level in percent. | HAN-FUN blind (e.g. Rolltron DECT 1213) - FRITZ!OS 7 |
### Triggers
* @author Christoph Weitkamp - Added support for AVM FRITZ!DECT 300 and Comet DECT
* @author Christoph Weitkamp - Added support for groups
* @author Christoph Weitkamp - Added channels 'voltage' and 'battery_level'
+ * @author Ulrich Mertin - Added support for HAN-FUN blinds
*/
@NonNullByDefault
public class AVMFritzBindingConstants {
public static final String DEVICE_COMETDECT = "Comet_DECT";
public static final String DEVICE_HAN_FUN_CONTACT = "HAN_FUN_CONTACT";
public static final String DEVICE_HAN_FUN_SWITCH = "HAN_FUN_SWITCH";
+ public static final String DEVICE_HAN_FUN_BLINDS = "HAN_FUN_BLINDS";
// List of main group types
public static final String GROUP_HEATING = "FRITZ_GROUP_HEATING";
public static final ThingTypeUID COMETDECT_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_COMETDECT);
public static final ThingTypeUID HAN_FUN_CONTACT_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_HAN_FUN_CONTACT);
public static final ThingTypeUID HAN_FUN_SWITCH_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_HAN_FUN_SWITCH);
+ public static final ThingTypeUID HAN_FUN_BLINDS_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_HAN_FUN_BLINDS);
public static final ThingTypeUID GROUP_HEATING_THING_TYPE = new ThingTypeUID(BINDING_ID, GROUP_HEATING);
public static final ThingTypeUID GROUP_SWITCH_THING_TYPE = new ThingTypeUID(BINDING_ID, GROUP_SWITCH);
public static final String CHANNEL_CONTACT_STATE = "contact_state";
public static final String CHANNEL_PRESS = "press";
public static final String CHANNEL_LAST_CHANGE = "last_change";
+ public static final String CHANNEL_ROLLERSHUTTER = "rollershutter";
// List of all Channel config ids
public static final String CONFIG_CHANNEL_TEMP_OFFSET = "offset";
COMETDECT_THING_TYPE);
public static final Set<ThingTypeUID> SUPPORTED_DEVICE_THING_TYPES_UIDS = Set.of(DECT100_THING_TYPE,
- DECT200_THING_TYPE, DECT210_THING_TYPE, PL546E_THING_TYPE, HAN_FUN_CONTACT_THING_TYPE);
+ DECT200_THING_TYPE, DECT210_THING_TYPE, PL546E_THING_TYPE, HAN_FUN_CONTACT_THING_TYPE,
+ HAN_FUN_BLINDS_THING_TYPE);
public static final Set<ThingTypeUID> SUPPORTED_GROUP_THING_TYPES_UIDS = Set.of(GROUP_HEATING_THING_TYPE,
GROUP_SWITCH_THING_TYPE);
* @author Robert Bausdorf - Initial contribution
* @author Christoph Weitkamp - Added support for AVM FRITZ!DECT 300 and Comet DECT
* @author Christoph Weitkamp - Added support for groups
+ * @author Ulrich Mertin - Added support for HAN-FUN blinds
*/
public abstract class AVMFritzBaseModel implements BatteryModel {
protected static final int HAN_FUN_DEVICE_BIT = 1; // Bit 0
protected static final int DECT_REPEATER_BIT = 1 << 10; // Bit 10
protected static final int MICROPHONE_BIT = 1 << 11; // Bit 11
protected static final int HAN_FUN_UNIT_BIT = 1 << 13; // Bit 13
+ protected static final int HAN_FUN_BLINDS_BIT = 1 << 18; // Bit 18
protected static final int HUMIDITY_SENSOR_BIT = 1 << 20; // Bit 20 - undocumented
@XmlAttribute(name = "identifier")
return (bitmask & HAN_FUN_UNIT_BIT) > 0;
}
+ public boolean isHANFUNBlinds() {
+ return (bitmask & HAN_FUN_BLINDS_BIT) > 0;
+ }
+
public String getFirmwareVersion() {
return firmwareVersion;
}
.append(isTempSensor()).append(",isHumiditySensor=").append(isHumiditySensor()).append(",isPowermeter=")
.append(isPowermeter()).append(",isDectRepeater=").append(isDectRepeater())
.append(",isHeatingThermostat=").append(isHeatingThermostat()).append(",isMicrophone=")
- .append(isMicrophone()).append(",isHANFUNUnit=").append(isHANFUNUnit()).append(",id=").append(deviceId)
- .append(",manufacturer=").append(deviceManufacturer).append(",productname=").append(productName)
- .append(",fwversion=").append(firmwareVersion).append(",present=").append(present).append(",name=")
- .append(name).append(",battery=").append(getBattery()).append(",batterylow=").append(getBatterylow())
- .append(",").append(getSwitch()).append(",").append(getPowermeter()).append(",").append(getHkr())
- .append(",").toString();
+ .append(isMicrophone()).append(",isHANFUNUnit=").append(isHANFUNUnit()).append(",isHANFUNBlind=")
+ .append(isHANFUNBlinds()).append(",id=").append(deviceId).append(",manufacturer=")
+ .append(deviceManufacturer).append(",productname=").append(productName).append(",fwversion=")
+ .append(firmwareVersion).append(",present=").append(present).append(",name=").append(name)
+ .append(",battery=").append(getBattery()).append(",batterylow=").append(getBatterylow()).append(",")
+ .append(getSwitch()).append(",").append(getPowermeter()).append(",").append(getHkr()).append(",")
+ .toString();
}
}
*
* @author Robert Bausdorf - Initial contribution
* @author Christoph Weitkamp - Added support for groups
+ * @author Ulrich Mertin - Added support for HAN-FUN blinds
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "device")
private TemperatureModel temperature;
private HumidityModel humidity;
private AlertModel alert;
+ private LevelcontrolModel levelcontrol;
@XmlElement(name = "button", type = ButtonModel.class)
private List<ButtonModel> buttons;
this.alert = alertModel;
}
+ public LevelcontrolModel getLevelcontrol() {
+ return levelcontrol;
+ }
+
+ public void setLevelcontrol(LevelcontrolModel levelcontrol) {
+ this.levelcontrol = levelcontrol;
+ }
+
public List<ButtonModel> getButtons() {
return buttons == null ? List.of() : buttons;
}
--- /dev/null
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.avmfritz.internal.dto;
+
+import java.math.BigDecimal;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * See {@link DeviceListModel}.
+ *
+ * @author Ulrich Mertin - Initial contribution
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlRootElement(name = "levelcontrol")
+public class LevelcontrolModel {
+
+ @XmlElement(name = "level")
+ private BigDecimal level;
+
+ @XmlElement(name = "levelpercentage")
+ private BigDecimal levelPercentage;
+
+ public BigDecimal getLevel() {
+ return level != null ? level : BigDecimal.ZERO;
+ }
+
+ public void setLevel(BigDecimal level) {
+ this.level = level;
+ }
+
+ public BigDecimal getLevelPercentage() {
+ return levelPercentage != null ? levelPercentage : BigDecimal.ZERO;
+ }
+
+ public void setLevelPercentage(BigDecimal levelPercentage) {
+ this.levelPercentage = levelPercentage;
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder().append("[level=").append(getLevel()).append(",levelpercentage=")
+ .append(getLevelPercentage()).append("]").toString();
+ }
+}
* @author Robert Bausdorf - Initial contribution
* @author Christoph Weitkamp - Added support for AVM FRITZ!DECT 300 and Comet DECT
* @author Christoph Weitkamp - Added support for groups
+ * @author Ulrich Mertin - Added support for HAN-FUN blinds
*/
@NonNullByDefault
public abstract class AVMFritzBaseBridgeHandler extends BaseBridgeHandler {
return GROUP_SWITCH;
}
} else if (device instanceof DeviceModel && device.isHANFUNUnit()) {
+ if (device.isHANFUNBlinds()) {
+ return DEVICE_HAN_FUN_BLINDS;
+ }
List<String> interfaces = Arrays
.asList(((DeviceModel) device).getEtsiunitinfo().getInterfaces().split(","));
if (interfaces.contains(HAN_FUN_INTERFACE_ALERT)) {
import org.openhab.binding.avmfritz.internal.dto.HeatingModel;
import org.openhab.binding.avmfritz.internal.dto.HeatingModel.NextChangeModel;
import org.openhab.binding.avmfritz.internal.dto.HumidityModel;
+import org.openhab.binding.avmfritz.internal.dto.LevelcontrolModel;
import org.openhab.binding.avmfritz.internal.dto.PowerMeterModel;
import org.openhab.binding.avmfritz.internal.dto.SwitchModel;
import org.openhab.binding.avmfritz.internal.dto.TemperatureModel;
import org.openhab.binding.avmfritz.internal.hardware.FritzAhaStatusListener;
import org.openhab.binding.avmfritz.internal.hardware.FritzAhaWebInterface;
+import org.openhab.binding.avmfritz.internal.hardware.callbacks.FritzAhaSetBlindTargetCallback.BlindCommand;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.library.types.DateTimeType;
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.QuantityType;
+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.library.unit.SIUnits;
import org.openhab.core.library.unit.Units;
import org.openhab.core.thing.Bridge;
* @author Robert Bausdorf - Initial contribution
* @author Christoph Weitkamp - Added support for AVM FRITZ!DECT 300 and Comet DECT
* @author Christoph Weitkamp - Added support for groups
+ * @author Ulrich Mertin - Added support for HAN-FUN blinds
*/
@NonNullByDefault
public abstract class AVMFritzBaseThingHandler extends BaseThingHandler implements FritzAhaStatusListener {
if (deviceModel.isHANFUNAlarmSensor()) {
updateHANFUNAlarmSensor(deviceModel.getAlert());
}
+ if (deviceModel.isHANFUNBlinds()) {
+ updateLevelcontrol(deviceModel.getLevelcontrol());
+ }
}
}
}
}
}
+ protected void updateLevelcontrol(@Nullable LevelcontrolModel levelcontrolModel) {
+ if (levelcontrolModel != null) {
+ updateThingChannelState(CHANNEL_ROLLERSHUTTER, new PercentType(levelcontrolModel.getLevelPercentage()));
+ }
+ }
+
private void updateHeatingThermostat(@Nullable HeatingModel heatingModel) {
if (heatingModel != null) {
updateThingChannelState(CHANNEL_MODE, new StringType(heatingModel.getMode()));
}
}
break;
+ case CHANNEL_ROLLERSHUTTER:
+ if (command instanceof StopMoveType) {
+ StopMoveType rollershutterCommand = (StopMoveType) command;
+ if (StopMoveType.STOP.equals(rollershutterCommand)) {
+ fritzBox.setBlind(ain, BlindCommand.STOP);
+ } else {
+ logger.debug("Received unknown rollershutter StopMove command MOVE");
+ }
+ } else if (command instanceof UpDownType) {
+ UpDownType rollershutterCommand = (UpDownType) command;
+ if (UpDownType.UP.equals(rollershutterCommand)) {
+ fritzBox.setBlind(ain, BlindCommand.OPEN);
+ } else {
+ fritzBox.setBlind(ain, BlindCommand.CLOSE);
+ }
+ } else if (command instanceof PercentType) {
+ PercentType rollershutterCommand = (PercentType) command;
+ BigDecimal levelpercentage = rollershutterCommand.toBigDecimal();
+ fritzBox.setLevelpercentage(ain, levelpercentage);
+ } else {
+ logger.debug("Received unknown rollershutter command type '{}'", command.toString());
+ }
+ break;
default:
logger.debug("Received unknown channel {}", channelId);
break;
import org.openhab.binding.avmfritz.internal.handler.AVMFritzBaseBridgeHandler;
import org.openhab.binding.avmfritz.internal.hardware.callbacks.FritzAhaApplyTemplateCallback;
import org.openhab.binding.avmfritz.internal.hardware.callbacks.FritzAhaCallback;
+import org.openhab.binding.avmfritz.internal.hardware.callbacks.FritzAhaSetBlindLevelCallback;
+import org.openhab.binding.avmfritz.internal.hardware.callbacks.FritzAhaSetBlindTargetCallback;
+import org.openhab.binding.avmfritz.internal.hardware.callbacks.FritzAhaSetBlindTargetCallback.BlindCommand;
import org.openhab.binding.avmfritz.internal.hardware.callbacks.FritzAhaSetHeatingModeCallback;
import org.openhab.binding.avmfritz.internal.hardware.callbacks.FritzAhaSetHeatingTemperatureCallback;
import org.openhab.binding.avmfritz.internal.hardware.callbacks.FritzAhaSetSwitchCallback;
* @author Christoph Weitkamp - Added support for AVM FRITZ!DECT 300 and Comet
* DECT
* @author Christoph Weitkamp - Added support for groups
+ * @author Ulrich Mertin - Added support for HAN-FUN blinds
*/
@NonNullByDefault
public class FritzAhaWebInterface {
FritzAhaSetHeatingModeCallback callback = new FritzAhaSetHeatingModeCallback(this, ain, command, endTime);
return asyncGet(callback);
}
+
+ public FritzAhaContentExchange setLevelpercentage(String ain, BigDecimal levelpercentage) {
+ FritzAhaSetBlindLevelCallback callback = new FritzAhaSetBlindLevelCallback(this, ain, levelpercentage);
+ return asyncGet(callback);
+ }
+
+ public FritzAhaContentExchange setBlind(String ain, BlindCommand command) {
+ FritzAhaSetBlindTargetCallback callback = new FritzAhaSetBlindTargetCallback(this, ain, command);
+ return asyncGet(callback);
+ }
}
--- /dev/null
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.avmfritz.internal.hardware.callbacks;
+
+import static org.eclipse.jetty.http.HttpMethod.GET;
+
+import java.math.BigDecimal;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.binding.avmfritz.internal.hardware.FritzAhaWebInterface;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Callback implementation for updating blind commands. Supports reauthorization
+ *
+ * @author Ulrich Mertin - Initial contribution
+ */
+@NonNullByDefault
+public class FritzAhaSetBlindLevelCallback extends FritzAhaReauthCallback {
+
+ private final Logger logger = LoggerFactory.getLogger(FritzAhaSetBlindLevelCallback.class);
+
+ private final String ain;
+
+ /**
+ * Constructor
+ *
+ * @param webIface Interface to FRITZ!Box
+ * @param ain AIN of the device that should be switched
+ * @param level Opening level percentage (0 ... 100)
+ */
+ public FritzAhaSetBlindLevelCallback(FritzAhaWebInterface webIface, String ain, BigDecimal levelpercentage) {
+ super(WEBSERVICE_PATH, "switchcmd=setlevelpercentage&level=" + levelpercentage + "&ain=" + ain, webIface, GET,
+ 1);
+ this.ain = ain;
+ }
+
+ @Override
+ public void execute(int status, String response) {
+ super.execute(status, response);
+ if (isValidRequest()) {
+ logger.debug("Received response '{}' for item '{}'", response, ain);
+ }
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.avmfritz.internal.hardware.callbacks;
+
+import static org.eclipse.jetty.http.HttpMethod.GET;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.binding.avmfritz.internal.hardware.FritzAhaWebInterface;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Callback implementation for updating blind commands. Supports reauthorization
+ *
+ * @author Ulrich Mertin - Initial contribution
+ */
+@NonNullByDefault
+public class FritzAhaSetBlindTargetCallback extends FritzAhaReauthCallback {
+
+ private final Logger logger = LoggerFactory.getLogger(FritzAhaSetBlindTargetCallback.class);
+
+ private final String ain;
+
+ /**
+ * Constructor
+ *
+ * @param webIface Interface to FRITZ!Box
+ * @param ain AIN of the device that should be switched
+ * @param command Blind command to send
+ */
+ public FritzAhaSetBlindTargetCallback(FritzAhaWebInterface webIface, String ain, BlindCommand command) {
+ super(WEBSERVICE_PATH, "switchcmd=setblind&target=" + command.getTarget() + "&ain=" + ain, webIface, GET, 1);
+ this.ain = ain;
+ }
+
+ @Override
+ public void execute(int status, String response) {
+ super.execute(status, response);
+ if (isValidRequest()) {
+ logger.debug("Received response '{}' for item '{}'", response, ain);
+ }
+ }
+
+ public enum BlindCommand {
+ OPEN("open"),
+ CLOSE("close"),
+ STOP("stop");
+
+ private final String target;
+
+ private BlindCommand(final String target) {
+ this.target = target;
+ }
+
+ public String getTarget() {
+ return target;
+ }
+ }
+}
thing-type.avmfritz.FRITZ_Powerline_546E.description = FRITZ!Powerline 546E schaltbare Steckdose. Dient zur Steuerung der integrierten Steckdose und liefert Daten wie z.B. Temperatur.
+thing-type.avmfritz.HAN_FUN_BLINDS.label = HAN-FUN Rolladen
+thing-type.avmfritz.HAN_FUN_BLINDS.description = HAN-FUN Rolladen (z.B. Rollotron DECT 1213).
+
# thing types config groups
thing-type.avmfritz.FRITZ_GROUP_HEATING.label = Heizkörperregler
thing-type.avmfritz.FRITZ_GROUP_HEATING.description = Gruppe für Heizkörperregler. Dient zur Steuerung von Heizkörpern und liefert Daten wie z.B. Temperatur.
thing-type.avmfritz.FRITZ_DECT_440.channel.press.label = Tastendruck
thing-type.avmfritz.FRITZ_DECT_440.channel.press.description = Wird ausgelöst, wenn eine Taste gedrückt wird.
+channel-type.avmfritz.rollershutter.label = Rolladensteuerung
+channel-type.avmfritz.rollershutter.description = Steuert den Rolladen und zeigt seinen Öffnungsgrad in Prozent an.
+
channel-type.avmfritz.last_change.label = Letzte Änderung
channel-type.avmfritz.last_change.description = Zeigt an, wann der Schalter zuletzt gedrückt wurde.
channel-type.avmfritz.last_change.pattern = %1$td.%1$tm.%1$tY %1$tH:%1$tM:%1$tS
<category>Time</category>
<state readOnly="true"/>
</channel-type>
+
+ <channel-type id="rollershutter">
+ <item-type>Rollershutter</item-type>
+ <label>Rollershutter Control</label>
+ <description>Controls the rollershutter and states its opening level in percent</description>
+ <category>Blinds</category>
+ </channel-type>
+
</thing:thing-descriptions>
<config-description-ref uri="thing-type:avmfritz:fritzdevice"/>
</thing-type>
+ <thing-type id="HAN_FUN_BLINDS">
+ <supported-bridge-type-refs>
+ <bridge-type-ref id="fritzbox"/>
+ <bridge-type-ref id="FRITZ_Powerline_546E_Solo"/>
+ </supported-bridge-type-refs>
+
+ <label>HAN-FUN Blinds</label>
+ <description>HAN-FUN blinds (e.g. RolloTron DECT 1213)</description>
+
+ <channels>
+ <channel id="rollershutter" typeId="rollershutter"/>
+ </channels>
+
+ <representation-property>ain</representation-property>
+
+ <config-description-ref uri="thing-type:avmfritz:fritzdevice"/>
+ </thing-type>
+
<!-- Supported FRITZ! groups and features -->
<thing-type id="FRITZ_GROUP_HEATING">
<supported-bridge-type-refs>
* Tests for {@link DeviceListModel}.
*
* @author Christoph Weitkamp - Initial contribution
+ * @author Ulrich Mertin - Added support for HAN-FUN blinds
*/
@NonNullByDefault
public class AVMFritzDeviceListModelTest {
"<device identifier=\"11934 0059979-1\" id=\"2001\" functionbitmask=\"8200\" fwversion=\"0.0\" manufacturer=\"0x0feb\" productname=\"HAN-FUN\"><present>0</present><name>HAN-FUN #2: Unit #2</name><etsiunitinfo><etsideviceid>412</etsideviceid><unittype>273</unittype><interfaces>772</interfaces></etsiunitinfo><button><lastpressedtimestamp>1529590797</lastpressedtimestamp></button></device>" +
"<device identifier=\"13096 0007307\" id=\"29\" functionbitmask=\"32\" fwversion=\"04.90\" manufacturer=\"AVM\" productname=\"FRITZ!DECT 400\"><present>1</present><name>FRITZ!DECT 400 #14</name><battery>100</battery><batterylow>0</batterylow><button identifier=\"13096 0007307-0\" id=\"5000\"><name>FRITZ!DECT 400 #14: kurz</name><lastpressedtimestamp>1549195586</lastpressedtimestamp></button><button identifier=\"13096 0007307-9\" id=\"5001\"><name>FRITZ!DECT 400 #14: lang</name><lastpressedtimestamp>1549195595</lastpressedtimestamp></button></device>" +
"<device identifier=\"13096 0007308\" id=\"30\" functionbitmask=\"1048864\" fwversion=\"05.10\" manufacturer=\"AVM\" productname=\"FRITZ!DECT 440\"><present>1</present><name>FRITZ!DECT 440 #15</name><temperature><celsius>230</celsius><offset>0</offset></temperature><humidity><rel_humidity>43</rel_humidity></humidity><battery>100</battery><batterylow>0</batterylow><button identifier=\"13096 0007308-1\" id=\"5000\"><name>FRITZ!DECT 440 #15: Oben rechts</name><lastpressedtimestamp>1549195586</lastpressedtimestamp></button><button identifier=\"13096 0007308-3\" id=\"5001\"><name>FRITZ!DECT 440 #15: Unten rechts</name><lastpressedtimestamp>1549195595</lastpressedtimestamp></button><button identifier=\"13096 0007308-5\" id=\"5002\"><name>FRITZ!DECT 440 #15: Unten links</name><lastpressedtimestamp>1549195586</lastpressedtimestamp></button><button identifier=\"13096 0007308-7\" id=\"5003\"><name>FRITZ!DECT 440 #15: Oben links</name><lastpressedtimestamp>1549195595</lastpressedtimestamp></button></device>" +
+ "<device identifier=\"14276 0503450-1\" id=\"2000\" functionbitmask=\"335888\" fwversion=\"0.0\" manufacturer=\"0x37c4\" productname=\"Rollotron 1213\"><present>1</present><txbusy>0</txbusy><name>Rollotron 1213 #1</name><blind><endpositionsset>1</endpositionsset><mode>manuell</mode></blind><levelcontrol><level>26</level><levelpercentage>10</levelpercentage></levelcontrol><etsiunitinfo><etsideviceid>406</etsideviceid><unittype>281</unittype><interfaces>256,513,516,517</interfaces></etsiunitinfo><alert><state>0</state><lastalertchgtimestamp></lastalertchgtimestamp></alert></device>" +
"</devicelist>";
//@formatter:off
try {
@Test
public void validateDeviceListModel() {
assertNotNull(devices);
- assertEquals(13, devices.getDevicelist().size());
+ assertEquals(14, devices.getDevicelist().size());
assertEquals("1", devices.getXmlApiVersion());
}
assertFalse(device.isHumiditySensor());
assertFalse(device.isPowermeter());
assertFalse(device.isHeatingThermostat());
+ assertFalse(device.isHANFUNBlinds());
assertNull(device.getSwitch());
assertNull(device.getPowermeter());
assertNull(device.getHkr());
+
+ assertNull(device.getLevelcontrol());
}
@Test
assertFalse(device.isHumiditySensor());
assertTrue(device.isPowermeter());
assertFalse(device.isHeatingThermostat());
+ assertFalse(device.isHANFUNBlinds());
assertNotNull(device.getSwitch());
assertEquals(SwitchModel.ON, device.getSwitch().getState());
validatePowerMeter(device.getPowermeter());
assertNull(device.getHkr());
+
+ assertNull(device.getLevelcontrol());
}
@Test
assertFalse(device.isHumiditySensor());
assertTrue(device.isPowermeter());
assertFalse(device.isHeatingThermostat());
+ assertFalse(device.isHANFUNBlinds());
assertNotNull(device.getSwitch());
assertEquals(SwitchModel.ON, device.getSwitch().getState());
validatePowerMeter(device.getPowermeter());
assertNull(device.getHkr());
+
+ assertNull(device.getLevelcontrol());
}
@Test
assertFalse(device.isHumiditySensor());
assertFalse(device.isPowermeter());
assertTrue(device.isHeatingThermostat());
+ assertFalse(device.isHANFUNBlinds());
assertNull(device.getSwitch());
assertFalse(device.isHumiditySensor());
assertFalse(device.isPowermeter());
assertTrue(device.isHeatingThermostat());
+ assertFalse(device.isHANFUNBlinds());
assertNull(device.getSwitch());
assertFalse(device.isHumiditySensor());
assertFalse(device.isPowermeter());
assertTrue(device.isHeatingThermostat());
+ assertFalse(device.isHANFUNBlinds());
assertNull(device.getSwitch());
assertFalse(device.isHumiditySensor());
assertFalse(device.isPowermeter());
assertFalse(device.isHeatingThermostat());
+ assertFalse(device.isHANFUNBlinds());
assertEquals(new BigDecimal("100"), device.getBattery());
assertEquals(BatteryModel.BATTERY_OFF, device.getBatterylow());
assertNull(device.getPowermeter());
assertNull(device.getHkr());
+
+ assertNull(device.getLevelcontrol());
}
@Test
assertTrue(device.isHumiditySensor());
assertFalse(device.isPowermeter());
assertFalse(device.isHeatingThermostat());
+ assertFalse(device.isHANFUNBlinds());
assertEquals(new BigDecimal("100"), device.getBattery());
assertEquals(BatteryModel.BATTERY_OFF, device.getBatterylow());
assertNull(device.getPowermeter());
assertNull(device.getHkr());
+
+ assertNull(device.getLevelcontrol());
}
@Test
assertFalse(device.isHumiditySensor());
assertTrue(device.isPowermeter());
assertFalse(device.isHeatingThermostat());
+ assertFalse(device.isHANFUNBlinds());
assertNotNull(device.getSwitch());
assertEquals(SwitchModel.OFF, device.getSwitch().getState());
validatePowerMeter(device.getPowermeter());
assertNull(device.getHkr());
+
+ assertNull(device.getLevelcontrol());
}
@Test
assertFalse(device.isHumiditySensor());
assertFalse(device.isPowermeter());
assertFalse(device.isHeatingThermostat());
+ assertFalse(device.isHANFUNBlinds());
assertTrue(device.getButtons().isEmpty());
assertNull(device.getPowermeter());
assertNull(device.getHkr());
+
+ assertNull(device.getLevelcontrol());
}
@Test
assertFalse(device.isHumiditySensor());
assertFalse(device.isPowermeter());
assertFalse(device.isHeatingThermostat());
+ assertFalse(device.isHANFUNBlinds());
assertEquals(1, device.getButtons().size());
assertEquals(1529590797, device.getButtons().get(0).getLastpressedtimestamp());
assertNull(device.getPowermeter());
assertNull(device.getHkr());
+
+ assertNull(device.getLevelcontrol());
+ }
+
+ @Test
+ public void validateHANFUNBlindModel() {
+ Optional<AVMFritzBaseModel> optionalDevice = findModelByIdentifier("142760503450-1");
+ assertTrue(optionalDevice.isPresent());
+ assertTrue(optionalDevice.get() instanceof DeviceModel);
+
+ DeviceModel device = (DeviceModel) optionalDevice.get();
+ assertEquals("Rollotron 1213", device.getProductName());
+ assertEquals("142760503450-1", device.getIdentifier());
+ assertEquals("2000", device.getDeviceId());
+ assertEquals("0.0", device.getFirmwareVersion());
+ assertEquals("0x37c4", device.getManufacturer());
+
+ assertEquals(1, device.getPresent());
+ assertEquals("Rollotron 1213 #1", device.getName());
+
+ assertFalse(device.isButton());
+ assertFalse(device.isHANFUNButton());
+ assertTrue(device.isHANFUNAlarmSensor());
+ assertFalse(device.isDectRepeater());
+ assertFalse(device.isSwitchableOutlet());
+ assertFalse(device.isTempSensor());
+ assertFalse(device.isHumiditySensor());
+ assertFalse(device.isPowermeter());
+ assertFalse(device.isHeatingThermostat());
+ assertTrue(device.isHANFUNBlinds());
+
+ assertTrue(device.getButtons().isEmpty());
+
+ assertNotNull(device.getAlert());
+ assertEquals(BigDecimal.ZERO, device.getAlert().getState());
+
+ assertNull(device.getSwitch());
+
+ assertNull(device.getTemperature());
+
+ assertNull(device.getPowermeter());
+
+ assertNull(device.getHkr());
+
+ LevelcontrolModel levelcontrol = device.getLevelcontrol();
+ assertNotNull(levelcontrol);
+ assertEquals(BigDecimal.valueOf(26L), levelcontrol.getLevel());
+ assertEquals(BigDecimal.valueOf(10L), levelcontrol.getLevelPercentage());
}
@Test
assertFalse(group.isHumiditySensor());
assertFalse(group.isPowermeter());
assertTrue(group.isHeatingThermostat());
+ assertFalse(group.isHANFUNBlinds());
assertNull(group.getSwitch());
assertFalse(group.isHumiditySensor());
assertTrue(group.isPowermeter());
assertFalse(group.isHeatingThermostat());
+ assertFalse(group.isHANFUNBlinds());
assertNotNull(group.getSwitch());
assertEquals(SwitchModel.ON, group.getSwitch().getState());
* Tests for {@link AVMFritzDiscoveryService}.
*
* @author Christoph Weitkamp - Initial contribution
+ * @author Ulrich Mertin - Added support for HAN-FUN blinds
*/
@NonNullByDefault
public class AVMFritzDiscoveryServiceOSGiTest extends AVMFritzThingHandlerOSGiTest {
@Test
public void correctSupportedTypes() {
- assertEquals(13, discovery.getSupportedThingTypes().size());
+ assertEquals(14, discovery.getSupportedThingTypes().size());
assertTrue(discovery.getSupportedThingTypes().contains(DECT100_THING_TYPE));
assertTrue(discovery.getSupportedThingTypes().contains(DECT200_THING_TYPE));
assertTrue(discovery.getSupportedThingTypes().contains(DECT210_THING_TYPE));
assertTrue(discovery.getSupportedThingTypes().contains(COMETDECT_THING_TYPE));
assertTrue(discovery.getSupportedThingTypes().contains(HAN_FUN_CONTACT_THING_TYPE));
assertTrue(discovery.getSupportedThingTypes().contains(HAN_FUN_SWITCH_THING_TYPE));
+ assertTrue(discovery.getSupportedThingTypes().contains(HAN_FUN_BLINDS_THING_TYPE));
assertTrue(discovery.getSupportedThingTypes().contains(GROUP_HEATING_THING_TYPE));
assertTrue(discovery.getSupportedThingTypes().contains(GROUP_SWITCH_THING_TYPE));
}
assertEquals(CONFIG_AIN, discoveryResult.getRepresentationProperty());
}
+ @Test
+ public void validHANFUNBlindDiscoveryResult() throws JAXBException {
+ //@formatter:off
+ String xml =
+ "<devicelist version=\"1\">" +
+ "<device identifier=\"14276 0503450-1\" id=\"2000\" functionbitmask=\"335888\" fwversion=\"0.0\" manufacturer=\"0x37c4\" productname=\"Rollotron 1213\">"+
+ "<present>1</present>"+
+ "<txbusy>0</txbusy>"+
+ "<name>Rollotron 1213 #1</name>"+
+ "<blind>"+
+ "<endpositionsset>1</endpositionsset>"+
+ "<mode>manuell</mode>"+
+ "</blind>"+
+ "<levelcontrol>"+
+ "<level>26</level>"+
+ "<levelpercentage>10</levelpercentage>"+
+ "</levelcontrol>"+
+ "<etsiunitinfo>"+
+ "<etsideviceid>406</etsideviceid>"+
+ "<unittype>281</unittype>"+
+ "<interfaces>256,513,516,517</interfaces>"+
+ "</etsiunitinfo>"+
+ "<alert>"+
+ "<state>0</state>"+
+ "<lastalertchgtimestamp></lastalertchgtimestamp>"+
+ "</alert>"+
+ "</device>" +
+ "</devicelist>";
+ //@formatter:on
+
+ Unmarshaller u = JAXBUtils.JAXBCONTEXT_DEVICES.createUnmarshaller();
+ DeviceListModel devices = (DeviceListModel) u.unmarshal(new StringReader(xml));
+ assertNotNull(devices);
+ assertEquals(1, devices.getDevicelist().size());
+
+ AVMFritzBaseModel device = devices.getDevicelist().get(0);
+ assertNotNull(device);
+
+ discovery.onDeviceAdded(device);
+ assertNotNull(discoveryResult);
+
+ assertEquals(DiscoveryResultFlag.NEW, discoveryResult.getFlag());
+ assertEquals(new ThingUID("avmfritz:HAN_FUN_BLINDS:1:142760503450_1"), discoveryResult.getThingUID());
+ assertEquals(HAN_FUN_BLINDS_THING_TYPE, discoveryResult.getThingTypeUID());
+ assertEquals(BRIGE_THING_ID, discoveryResult.getBridgeUID());
+ assertEquals("142760503450-1", discoveryResult.getProperties().get(CONFIG_AIN));
+ assertEquals("0x37c4", discoveryResult.getProperties().get(PROPERTY_VENDOR));
+ assertEquals("Rollotron 1213", discoveryResult.getProperties().get(PRODUCT_NAME));
+ assertEquals("142760503450-1", discoveryResult.getProperties().get(PROPERTY_SERIAL_NUMBER));
+ assertEquals("0.0", discoveryResult.getProperties().get(PROPERTY_FIRMWARE_VERSION));
+ assertEquals(CONFIG_AIN, discoveryResult.getRepresentationProperty());
+ }
+
@Test
public void validHeatingGroupDiscoveryResult() throws JAXBException {
//@formatter:off