From 04507d98fcd5760a99965d41268a52bbf83e292f Mon Sep 17 00:00:00 2001 From: Christoph Weitkamp Date: Sat, 29 May 2021 14:25:36 +0200 Subject: [PATCH] Added support for HAN-FUN outlets / simple on-off devices (#10760) Signed-off-by: Christoph Weitkamp --- .../org.openhab.binding.avmfritz/README.md | 3 + .../internal/AVMFritzBindingConstants.java | 5 +- .../internal/dto/AVMFritzBaseModel.java | 46 +++-- .../avmfritz/internal/dto/DeviceModel.java | 17 +- .../internal/dto/SimpleOnOffModel.java | 34 ++++ .../handler/AVMFritzBaseBridgeHandler.java | 2 + .../handler/AVMFritzBaseThingHandler.java | 21 ++- .../handler/Powerline546EHandler.java | 10 +- .../OH-INF/i18n/avmfritz_de.properties | 9 +- .../resources/OH-INF/thing/thing-types.xml | 18 ++ .../dto/AVMFritzDeviceListModelTest.java | 161 +++++++++++++----- .../AVMFritzDiscoveryServiceOSGiTest.java | 3 +- 12 files changed, 247 insertions(+), 82 deletions(-) create mode 100644 bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/SimpleOnOffModel.java diff --git a/bundles/org.openhab.binding.avmfritz/README.md b/bundles/org.openhab.binding.avmfritz/README.md index 9e94b9a9e..ad2d4fc2d 100644 --- a/bundles/org.openhab.binding.avmfritz/README.md +++ b/bundles/org.openhab.binding.avmfritz/README.md @@ -84,6 +84,8 @@ The following sensors have been successfully tested using FRITZ!OS 7 for FRITZ!B - [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`) +- [SmartHome Zwischenstecker innen](https://www.smarthome.de/geraete/smarthome-zwischenstecker-innen-weiss) - a switchable indoor outlet (thing type `HAN_FUN_ON_OFF`) +- [SmartHome Zwischenstecker außen](https://www.smarthome.de/geraete/smarthome-zwischenstecker-aussen-schwarz) - a switchable outdoor outlet (thing type `HAN_FUN_ON_OFF`) - [Rollotron DECT 1213](https://www.rademacher.de/shop/rollladen-sonnenschutz/elektrischer-gurtwickler/rollotron-dect-1213) - an electronic belt winder (thing type `HAN_FUN_BLINDS`) - [Becker BoxCTRL](https://becker-antriebe.shop/) - a radio controlled roller shutter drive (thing type `HAN_FUN_BLINDS`) @@ -176,6 +178,7 @@ The AIN (actor identification number) can be found in the FRITZ!Box interface -> | power | Number:Power | Current power consumption | FRITZ!DECT 210, FRITZ!DECT 200, FRITZ!Powerline 546E | | voltage | Number:ElectricPotential | Current voltage - FRITZ!OS 7 | FRITZ!DECT 210, FRITZ!DECT 200, FRITZ!Powerline 546E | | outlet | Switch | Switchable outlet (ON/OFF) | FRITZ!DECT 210, FRITZ!DECT 200, FRITZ!Powerline 546E | +| on_off | Switch | Switchable device (ON/OFF) | HAN_FUN_ON_OFF | | actual_temp | Number:Temperature | Current temperature of heating thermostat | FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT | | set_temp | Number:Temperature | Set Temperature of heating thermostat | FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT | | eco_temp | Number:Temperature | Eco Temperature of heating thermostat | FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT | diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/AVMFritzBindingConstants.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/AVMFritzBindingConstants.java index 792e7e466..bbdf5dc3d 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/AVMFritzBindingConstants.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/AVMFritzBindingConstants.java @@ -53,6 +53,7 @@ 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_ON_OFF = "HAN_FUN_ON_OFF"; public static final String DEVICE_HAN_FUN_BLINDS = "HAN_FUN_BLINDS"; // List of main group types @@ -74,6 +75,7 @@ public class AVMFritzBindingConstants { 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_ON_OFF_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_HAN_FUN_ON_OFF); 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); @@ -129,6 +131,7 @@ public class AVMFritzBindingConstants { public static final String CHANNEL_PRESS = "press"; public static final String CHANNEL_LAST_CHANGE = "last_change"; public static final String CHANNEL_ROLLERSHUTTER = "rollershutter"; + public static final String CHANNEL_ON_OFF = "on_off"; // List of all Channel config ids public static final String CONFIG_CHANNEL_TEMP_OFFSET = "offset"; @@ -169,7 +172,7 @@ public class AVMFritzBindingConstants { public static final Set SUPPORTED_DEVICE_THING_TYPES_UIDS = Set.of(DECT100_THING_TYPE, DECT200_THING_TYPE, DECT210_THING_TYPE, PL546E_THING_TYPE, HAN_FUN_CONTACT_THING_TYPE, - HAN_FUN_BLINDS_THING_TYPE); + HAN_FUN_ON_OFF_THING_TYPE, HAN_FUN_BLINDS_THING_TYPE); public static final Set SUPPORTED_GROUP_THING_TYPES_UIDS = Set.of(GROUP_HEATING_THING_TYPE, GROUP_SWITCH_THING_TYPE); diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/AVMFritzBaseModel.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/AVMFritzBaseModel.java index 60e38a1b2..82bdae0d6 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/AVMFritzBaseModel.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/AVMFritzBaseModel.java @@ -17,6 +17,8 @@ import java.math.BigDecimal; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; +import org.eclipse.jdt.annotation.Nullable; + /** * See {@link DeviceListModel}. * @@ -34,6 +36,8 @@ import javax.xml.bind.annotation.XmlElement; *
  • Bit 10: AVM DECT Repeater
  • *
  • Bit 11: Mikrofon
  • *
  • Bit 13: HAN-FUN Unit
  • + *
  • Bit 15: an-/ausschaltbares Gerät / Steckdose / Lampe / Aktor
  • + *
  • Bit 18: Rollladen - hoch, runter, stop und level 0% bis 100 %
  • * * * @author Robert Bausdorf - Initial contribution @@ -53,6 +57,7 @@ public abstract class AVMFritzBaseModel implements BatteryModel { 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_ON_OFF_BIT = 1 << 15; // Bit 15 protected static final int HAN_FUN_BLINDS_BIT = 1 << 18; // Bit 18 protected static final int HUMIDITY_SENSOR_BIT = 1 << 20; // Bit 20 - undocumented @@ -89,12 +94,19 @@ public abstract class AVMFritzBaseModel implements BatteryModel { @XmlElement(name = "switch") private SwitchModel switchModel; + @XmlElement(name = "simpleonoff") + private @Nullable SimpleOnOffModel simpleOnOffUnit; + @XmlElement(name = "powermeter") private PowerMeterModel powermeterModel; @XmlElement(name = "hkr") private HeatingModel heatingModel; + public @Nullable SimpleOnOffModel getSimpleOnOffUnit() { + return simpleOnOffUnit; + } + public PowerMeterModel getPowermeter() { return powermeterModel; } @@ -151,7 +163,7 @@ public abstract class AVMFritzBaseModel implements BatteryModel { return (bitmask & OUTLET_BIT) > 0; } - public boolean isTempSensor() { + public boolean isTemperatureSensor() { return (bitmask & TEMPERATURE_SENSOR_BIT) > 0; } @@ -171,7 +183,7 @@ public abstract class AVMFritzBaseModel implements BatteryModel { return (bitmask & HEATING_THERMOSTAT_BIT) > 0; } - public boolean isMicrophone() { + public boolean hasMicrophone() { return (bitmask & MICROPHONE_BIT) > 0; } @@ -179,6 +191,10 @@ public abstract class AVMFritzBaseModel implements BatteryModel { return (bitmask & HAN_FUN_UNIT_BIT) > 0; } + public boolean isHANFUNOnOff() { + return (bitmask / HAN_FUN_ON_OFF_BIT) > 0; + } + public boolean isHANFUNBlinds() { return (bitmask & HAN_FUN_BLINDS_BIT) > 0; } @@ -215,19 +231,19 @@ public abstract class AVMFritzBaseModel implements BatteryModel { @Override public String toString() { - return new StringBuilder().append("[ain=").append(ident).append(",bitmask=").append(bitmask) - .append(",isHANFUNDevice=").append(isHANFUNDevice()).append(",isHANFUNButton=").append(isHANFUNButton()) + return new StringBuilder("[ain=").append(ident).append(",bitmask=").append(bitmask).append(",isHANFUNDevice=") + .append(isHANFUNDevice()).append(",isHANFUNButton=").append(isHANFUNButton()) .append(",isHANFUNAlarmSensor=").append(isHANFUNAlarmSensor()).append(",isButton=").append(isButton()) - .append(",isSwitchableOutlet=").append(isSwitchableOutlet()).append(",isTempSensor=") - .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(",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(); + .append(",isSwitchableOutlet=").append(isSwitchableOutlet()).append(",isTemperatureSensor=") + .append(isTemperatureSensor()).append(",isHumiditySensor=").append(isHumiditySensor()) + .append(",isPowermeter=").append(isPowermeter()).append(",isDectRepeater=").append(isDectRepeater()) + .append(",isHeatingThermostat=").append(isHeatingThermostat()).append(",hasMicrophone=") + .append(hasMicrophone()).append(",isHANFUNUnit=").append(isHANFUNUnit()).append(",isHANFUNOnOff=") + .append(isHANFUNOnOff()).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(getSimpleOnOffUnit()) + .append(",").append(getPowermeter()).append(",").append(getHkr()).append(",").toString(); } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/DeviceModel.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/DeviceModel.java index 9bfe1bda0..759602652 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/DeviceModel.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/DeviceModel.java @@ -90,25 +90,30 @@ public class DeviceModel extends AVMFritzBaseModel { @Override public String toString() { - return new StringBuilder().append(super.toString()).append(temperature).append(",").append(humidity).append(",") + return new StringBuilder(super.toString()).append(temperature).append(",").append(humidity).append(",") .append(alert).append(",").append(getButtons()).append(",").append(etsiunitinfo).append("]").toString(); } @XmlAccessorType(XmlAccessType.FIELD) @XmlType(propOrder = { "etsideviceid", "unittype", "interfaces" }) public static class ETSUnitInfoModel { + public static final String HAN_FUN_UNITTYPE_AC_OUTLET = "262"; + public static final String HAN_FUN_UNITTYPE_AC_OUTLET_SIMPLE_POWER_METERING = "263"; public static final String HAN_FUN_UNITTYPE_SIMPLE_BUTTON = "273"; public static final String HAN_FUN_UNITTYPE_SIMPLE_DETECTOR = "512"; - public static final String HAN_FUN_UNITTYPE_MAGNETIC_CONTACT = "513"; - public static final String HAN_FUN_UNITTYPE_OPTICAL_CONTACT = "514"; + public static final String HAN_FUN_UNITTYPE_DOOR_OPEN_CLOSE_DETECTOR = "513"; + public static final String HAN_FUN_UNITTYPE_WINDOW_OPEN_CLOSE_DETECTOR = "514"; public static final String HAN_FUN_UNITTYPE_MOTION_DETECTOR = "515"; - public static final String HAN_FUN_UNITTYPE_SMOKE_DETECTOR = "516"; + public static final String HAN_FUN_UNITTYPE_SMOKE_DETECTOR = "516"; // undocumented public static final String HAN_FUN_UNITTYPE_FLOOD_DETECTOR = "518"; public static final String HAN_FUN_UNITTYPE_GLAS_BREAK_DETECTOR = "519"; public static final String HAN_FUN_UNITTYPE_VIBRATION_DETECTOR = "520"; + public static final String HAN_FUN_UNITTYPE_SIREN = "640"; public static final String HAN_FUN_INTERFACE_ALERT = "256"; public static final String HAN_FUN_INTERFACE_KEEP_ALIVE = "277"; + public static final String HAN_FUN_INTERFACE_ON_OFF = "512"; + public static final String HAN_FUN_INTERFACE_SIMPLE_POWER_METERING = "768"; // undocumented public static final String HAN_FUN_INTERFACE_SIMPLE_BUTTON = "772"; private String etsideviceid; @@ -141,8 +146,8 @@ public class DeviceModel extends AVMFritzBaseModel { @Override public String toString() { - return new StringBuilder().append("[etsideviceid=").append(etsideviceid).append(",unittype=") - .append(unittype).append(",interfaces=").append(interfaces).append("]").toString(); + return new StringBuilder("[etsideviceid=").append(etsideviceid).append(",unittype=").append(unittype) + .append(",interfaces=").append(interfaces).append("]").toString(); } } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/SimpleOnOffModel.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/SimpleOnOffModel.java new file mode 100644 index 000000000..b51ef8b58 --- /dev/null +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/SimpleOnOffModel.java @@ -0,0 +1,34 @@ +/** + * 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 javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlType; + +/** + * See {@link DeviceListModel}. + * + * @author Joshua Bacher - Initial contribution + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(propOrder = { "state" }) +public class SimpleOnOffModel { + + public boolean state; + + @Override + public String toString() { + return new StringBuilder("[state=").append(state).append(']').toString(); + } +} diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzBaseBridgeHandler.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzBaseBridgeHandler.java index 62b3c5180..4656fa79d 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzBaseBridgeHandler.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzBaseBridgeHandler.java @@ -336,6 +336,8 @@ public abstract class AVMFritzBaseBridgeHandler extends BaseBridgeHandler { return DEVICE_HAN_FUN_CONTACT; } else if (interfaces.contains(HAN_FUN_INTERFACE_SIMPLE_BUTTON)) { return DEVICE_HAN_FUN_SWITCH; + } else if (interfaces.contains(HAN_FUN_INTERFACE_ON_OFF)) { + return DEVICE_HAN_FUN_ON_OFF; } } return device.getProductName().replaceAll(INVALID_PATTERN, "_"); diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzBaseThingHandler.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzBaseThingHandler.java index b6759a1c4..00debd023 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzBaseThingHandler.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzBaseThingHandler.java @@ -35,6 +35,7 @@ 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.SimpleOnOffModel; import org.openhab.binding.avmfritz.internal.dto.SwitchModel; import org.openhab.binding.avmfritz.internal.dto.TemperatureModel; import org.openhab.binding.avmfritz.internal.hardware.FritzAhaStatusListener; @@ -140,9 +141,12 @@ public abstract class AVMFritzBaseThingHandler extends BaseThingHandler implemen if (device.isHeatingThermostat()) { updateHeatingThermostat(device.getHkr()); } + if (device.isHANFUNUnit() && device.isHANFUNOnOff()) { + updateSimpleOnOffUnit(device.getSimpleOnOffUnit()); + } if (device instanceof DeviceModel) { DeviceModel deviceModel = (DeviceModel) device; - if (deviceModel.isTempSensor()) { + if (deviceModel.isTemperatureSensor()) { updateTemperatureSensor(deviceModel.getTemperature()); } if (deviceModel.isHumiditySensor()) { @@ -225,8 +229,13 @@ public abstract class AVMFritzBaseThingHandler extends BaseThingHandler implemen if (lowBattery == null) { updateThingChannelState(CHANNEL_BATTERY_LOW, UnDefType.UNDEF); } else { - updateThingChannelState(CHANNEL_BATTERY_LOW, - BatteryModel.BATTERY_ON.equals(lowBattery) ? OnOffType.ON : OnOffType.OFF); + updateThingChannelState(CHANNEL_BATTERY_LOW, OnOffType.from(BatteryModel.BATTERY_ON.equals(lowBattery))); + } + } + + private void updateSimpleOnOffUnit(@Nullable SimpleOnOffModel simpleOnOffUnit) { + if (simpleOnOffUnit != null) { + updateThingChannelState(CHANNEL_ON_OFF, OnOffType.from(simpleOnOffUnit.state)); } } @@ -241,7 +250,7 @@ public abstract class AVMFritzBaseThingHandler extends BaseThingHandler implemen if (state == null) { updateThingChannelState(CHANNEL_OUTLET, UnDefType.UNDEF); } else { - updateThingChannelState(CHANNEL_OUTLET, SwitchModel.ON.equals(state) ? OnOffType.ON : OnOffType.OFF); + updateThingChannelState(CHANNEL_OUTLET, OnOffType.from(SwitchModel.ON.equals(state))); } } } @@ -370,11 +379,9 @@ public abstract class AVMFritzBaseThingHandler extends BaseThingHandler implemen logger.debug("Channel {} is a read-only channel and cannot handle command '{}'", channelId, command); break; case CHANNEL_OUTLET: + case CHANNEL_ON_OFF: if (command instanceof OnOffType) { fritzBox.setSwitch(ain, OnOffType.ON.equals(command)); - if (state != null) { - state.getSwitch().setState(OnOffType.ON.equals(command) ? SwitchModel.ON : SwitchModel.OFF); - } } break; case CHANNEL_SETTEMP: diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/Powerline546EHandler.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/Powerline546EHandler.java index b31128851..dc5176a0c 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/Powerline546EHandler.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/Powerline546EHandler.java @@ -66,10 +66,6 @@ public class Powerline546EHandler extends AVMFritzBaseBridgeHandler implements F private final Logger logger = LoggerFactory.getLogger(Powerline546EHandler.class); - /** - * keeps track of the current state for handling of increase/decrease - */ - private @Nullable AVMFritzBaseModel state; private @Nullable String identifier; /** @@ -128,7 +124,6 @@ public class Powerline546EHandler extends AVMFritzBaseBridgeHandler implements F } else { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "Device not present"); } - state = device; updateProperties(device); @@ -272,11 +267,8 @@ public class Powerline546EHandler extends AVMFritzBaseBridgeHandler implements F } break; case CHANNEL_OUTLET: - fritzBox.setSwitch(ain, OnOffType.ON.equals(command)); if (command instanceof OnOffType) { - if (state != null) { - state.getSwitch().setState(OnOffType.ON.equals(command) ? SwitchModel.ON : SwitchModel.OFF); - } + fritzBox.setSwitch(ain, OnOffType.ON.equals(command)); } break; default: diff --git a/bundles/org.openhab.binding.avmfritz/src/main/resources/OH-INF/i18n/avmfritz_de.properties b/bundles/org.openhab.binding.avmfritz/src/main/resources/OH-INF/i18n/avmfritz_de.properties index b0ebf7f09..f871defc6 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/resources/OH-INF/i18n/avmfritz_de.properties +++ b/bundles/org.openhab.binding.avmfritz/src/main/resources/OH-INF/i18n/avmfritz_de.properties @@ -13,6 +13,12 @@ thing-type.avmfritz.HAN_FUN_CONTACT.description = HAN-FUN Kontakt (e.g. SmartHom thing-type.avmfritz.HAN_FUN_SWITCH.label = HAN-FUN Schalter thing-type.avmfritz.HAN_FUN_SWITCH.description = HAN-FUN Schalter (e.g. SmartHome Wandtaster). +thing-type.avmfritz.HAN_FUN_BLINDS.label = HAN-FUN Rollladen +thing-type.avmfritz.HAN_FUN_BLINDS.description = HAN-FUN Rollladen (z.B. Rollotron DECT 1213, Becker BoxCTRL). + +thing-type.avmfritz.HAN_FUN_ON_OFF.label = HAN-FUN an-/ausschaltbares Gerät +thing-type.avmfritz.HAN_FUN_ON_OFF.description = HAN-FUN an-/ausschaltbares Gerät (e.g. SmartHome Zwischenstecker innen / SmartHome Zwischenstecker außen). + # bridge types config groups bridge-type.config.avmfritz.fritzbox.group.network.label = Netzwerk bridge-type.config.avmfritz.fritzbox.group.network.description = Einstellungen für das Netzwerk. @@ -99,9 +105,6 @@ thing-type.avmfritz.FRITZ_DECT_440.description = FRITZ!DECT 440 Taster. Dient zu 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 Rollladen -thing-type.avmfritz.HAN_FUN_BLINDS.description = HAN-FUN Rollladen (z.B. Rollotron DECT 1213, Becker BoxCTRL). - # 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. diff --git a/bundles/org.openhab.binding.avmfritz/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.avmfritz/src/main/resources/OH-INF/thing/thing-types.xml index bdf606ed2..c4f11d5ab 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.avmfritz/src/main/resources/OH-INF/thing/thing-types.xml @@ -295,6 +295,24 @@ + + + + + + + + HAN-FUN switchable device (e.g. SmartHome Zwischenstecker innen / SmartHome Zwischenstecker außen) + + + + + + ain + + + + diff --git a/bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/dto/AVMFritzDeviceListModelTest.java b/bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/dto/AVMFritzDeviceListModelTest.java index 5c325c9a7..32fd63ab7 100644 --- a/bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/dto/AVMFritzDeviceListModelTest.java +++ b/bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/dto/AVMFritzDeviceListModelTest.java @@ -45,21 +45,47 @@ public class AVMFritzDeviceListModelTest { public void setUp() throws JAXBException, XMLStreamException { //@formatter:off final String xml = - "" + - "1Schlafzimmer1manuell00230051020871717,18" + - "1Schlafzimmer220-104442284211000000100148434120028020,21,22" + - "1FRITZ!DECT 200 #11manuell00230051020872550" + - "1FRITZ!DECT 210 #81manuell00230051020872550" + - "0FRITZ!DECT 300 #1220-104442284211000000100148434120028" + - "0FRITZ!DECT 301 #1220-104442284211000000100148434120028" + - "0Comet DECT #1220-104442284211000000100148434120028" + - "1FRITZ!Powerline 546E #10manuell0123005102087" + - "1FRITZ!DECT Repeater 100 #52300" + - "0HAN-FUN #2: Unit #24065142561" + - "0HAN-FUN #2: Unit #2412273772" + - "1FRITZ!DECT 400 #141000" + - "1FRITZ!DECT 440 #152300431000" + - "10Rollotron 1213 #11manuell2610406281256,513,516,5170" + + "" + + "1Schlafzimmer1manuell00230051020871717,18" + + "1Schlafzimmer220-104442284211000000100148434120028020,21,22" + + "1FRITZ!DECT 200 #11manuell00230051020872550" + + "1FRITZ!DECT 210 #81manuell00230051020872550" + + "0FRITZ!DECT 300 #1220-104442284211000000100148434120028" + + "0FRITZ!DECT 301 #1220-104442284211000000100148434120028" + + "0Comet DECT #1220-104442284211000000100148434120028" + + "1FRITZ!Powerline 546E #10manuell0123005102087" + + "1FRITZ!DECT Repeater 100 #52300" + + "0HAN-FUN #2: Unit #24065142561" + + "0HAN-FUN #2: Unit #2412273772" + + "1FRITZ!DECT 400 #141000" + + "1FRITZ!DECT 440 #152300431000" + + "10Rollotron 1213 #11manuell2610406281256,513,516,5170" + + "\n" + + " 1\n" + + " 0\n" + + " Steckdose innen\n" + + " \n" + + " 0\n" + + " \n" + + " \n" + + " 408\n" + + " 263\n" + + " 512,768\n" + + " \n" + + "" + + "\n" + + " 1\n" + + " 0\n" + + " Steckdose außen\n" + + " \n" + + " 0\n" + + " \n" + + " \n" + + " 407\n" + + " 262\n" + + " 512\n" + + " \n" + + "" + ""; //@formatter:on XMLStreamReader xsr = JAXBUtils.XMLINPUTFACTORY.createXMLStreamReader(new StringReader(xml)); @@ -70,7 +96,7 @@ public class AVMFritzDeviceListModelTest { @Test public void validateDeviceListModel() { assertNotNull(devices); - assertEquals(14, devices.getDevicelist().size()); + assertEquals(16, devices.getDevicelist().size()); assertEquals("1", devices.getXmlApiVersion()); } @@ -95,7 +121,7 @@ public class AVMFritzDeviceListModelTest { assertFalse(device.isHANFUNAlarmSensor()); assertTrue(device.isDectRepeater()); assertFalse(device.isSwitchableOutlet()); - assertTrue(device.isTempSensor()); + assertTrue(device.isTemperatureSensor()); assertFalse(device.isHumiditySensor()); assertFalse(device.isPowermeter()); assertFalse(device.isHeatingThermostat()); @@ -130,16 +156,19 @@ public class AVMFritzDeviceListModelTest { assertEquals(1, device.getPresent()); assertEquals("FRITZ!DECT 200 #1", device.getName()); - assertFalse(device.isButton()); assertFalse(device.isHANFUNButton()); assertFalse(device.isHANFUNAlarmSensor()); - assertFalse(device.isDectRepeater()); - assertTrue(device.isSwitchableOutlet()); - assertTrue(device.isTempSensor()); - assertFalse(device.isHumiditySensor()); - assertTrue(device.isPowermeter()); + assertFalse(device.isButton()); assertFalse(device.isHeatingThermostat()); + assertTrue(device.isPowermeter()); + assertTrue(device.isTemperatureSensor()); + assertTrue(device.isSwitchableOutlet()); + assertFalse(device.isDectRepeater()); + assertTrue(device.hasMicrophone()); + assertFalse(device.isHANFUNUnit()); + assertTrue(device.isHANFUNOnOff()); assertFalse(device.isHANFUNBlinds()); + assertFalse(device.isHumiditySensor()); assertNotNull(device.getSwitch()); assertEquals(SwitchModel.ON, device.getSwitch().getState()); @@ -174,16 +203,19 @@ public class AVMFritzDeviceListModelTest { assertEquals(1, device.getPresent()); assertEquals("FRITZ!DECT 210 #8", device.getName()); - assertFalse(device.isButton()); assertFalse(device.isHANFUNButton()); assertFalse(device.isHANFUNAlarmSensor()); - assertFalse(device.isDectRepeater()); - assertTrue(device.isSwitchableOutlet()); - assertTrue(device.isTempSensor()); - assertFalse(device.isHumiditySensor()); - assertTrue(device.isPowermeter()); + assertFalse(device.isButton()); assertFalse(device.isHeatingThermostat()); + assertTrue(device.isPowermeter()); + assertTrue(device.isTemperatureSensor()); + assertTrue(device.isSwitchableOutlet()); + assertFalse(device.isDectRepeater()); + assertTrue(device.hasMicrophone()); + assertFalse(device.isHANFUNUnit()); + assertTrue(device.isHANFUNOnOff()); assertFalse(device.isHANFUNBlinds()); + assertFalse(device.isHumiditySensor()); assertNotNull(device.getSwitch()); assertEquals(SwitchModel.ON, device.getSwitch().getState()); @@ -223,7 +255,7 @@ public class AVMFritzDeviceListModelTest { assertFalse(device.isHANFUNAlarmSensor()); assertFalse(device.isDectRepeater()); assertFalse(device.isSwitchableOutlet()); - assertTrue(device.isTempSensor()); + assertTrue(device.isTemperatureSensor()); assertFalse(device.isHumiditySensor()); assertFalse(device.isPowermeter()); assertTrue(device.isHeatingThermostat()); @@ -261,7 +293,7 @@ public class AVMFritzDeviceListModelTest { assertFalse(device.isHANFUNAlarmSensor()); assertFalse(device.isDectRepeater()); assertFalse(device.isSwitchableOutlet()); - assertTrue(device.isTempSensor()); + assertTrue(device.isTemperatureSensor()); assertFalse(device.isHumiditySensor()); assertFalse(device.isPowermeter()); assertTrue(device.isHeatingThermostat()); @@ -299,7 +331,7 @@ public class AVMFritzDeviceListModelTest { assertFalse(device.isHANFUNAlarmSensor()); assertFalse(device.isDectRepeater()); assertFalse(device.isSwitchableOutlet()); - assertTrue(device.isTempSensor()); + assertTrue(device.isTemperatureSensor()); assertFalse(device.isHumiditySensor()); assertFalse(device.isPowermeter()); assertTrue(device.isHeatingThermostat()); @@ -337,7 +369,7 @@ public class AVMFritzDeviceListModelTest { assertFalse(device.isHANFUNAlarmSensor()); assertFalse(device.isDectRepeater()); assertFalse(device.isSwitchableOutlet()); - assertFalse(device.isTempSensor()); + assertFalse(device.isTemperatureSensor()); assertFalse(device.isHumiditySensor()); assertFalse(device.isPowermeter()); assertFalse(device.isHeatingThermostat()); @@ -386,7 +418,7 @@ public class AVMFritzDeviceListModelTest { assertFalse(device.isHANFUNAlarmSensor()); assertFalse(device.isDectRepeater()); assertFalse(device.isSwitchableOutlet()); - assertTrue(device.isTempSensor()); + assertTrue(device.isTemperatureSensor()); assertTrue(device.isHumiditySensor()); assertFalse(device.isPowermeter()); assertFalse(device.isHeatingThermostat()); @@ -456,7 +488,7 @@ public class AVMFritzDeviceListModelTest { assertFalse(device.isHANFUNAlarmSensor()); assertFalse(device.isDectRepeater()); assertTrue(device.isSwitchableOutlet()); - assertFalse(device.isTempSensor()); + assertFalse(device.isTemperatureSensor()); assertFalse(device.isHumiditySensor()); assertTrue(device.isPowermeter()); assertFalse(device.isHeatingThermostat()); @@ -498,7 +530,7 @@ public class AVMFritzDeviceListModelTest { assertTrue(device.isHANFUNAlarmSensor()); assertFalse(device.isDectRepeater()); assertFalse(device.isSwitchableOutlet()); - assertFalse(device.isTempSensor()); + assertFalse(device.isTemperatureSensor()); assertFalse(device.isHumiditySensor()); assertFalse(device.isPowermeter()); assertFalse(device.isHeatingThermostat()); @@ -541,7 +573,7 @@ public class AVMFritzDeviceListModelTest { assertFalse(device.isHANFUNAlarmSensor()); assertFalse(device.isDectRepeater()); assertFalse(device.isSwitchableOutlet()); - assertFalse(device.isTempSensor()); + assertFalse(device.isTemperatureSensor()); assertFalse(device.isHumiditySensor()); assertFalse(device.isPowermeter()); assertFalse(device.isHeatingThermostat()); @@ -584,7 +616,7 @@ public class AVMFritzDeviceListModelTest { assertTrue(device.isHANFUNAlarmSensor()); assertFalse(device.isDectRepeater()); assertFalse(device.isSwitchableOutlet()); - assertFalse(device.isTempSensor()); + assertFalse(device.isTemperatureSensor()); assertFalse(device.isHumiditySensor()); assertFalse(device.isPowermeter()); assertFalse(device.isHeatingThermostat()); @@ -609,6 +641,55 @@ public class AVMFritzDeviceListModelTest { assertEquals(BigDecimal.valueOf(10L), levelcontrol.getLevelPercentage()); } + @Test + public void validateHANFUNOnOffModel() { + Optional optionalDevice = findModelByIdentifier("113240824499-1"); + assertTrue(optionalDevice.isPresent()); + assertTrue(optionalDevice.get() instanceof DeviceModel); + + DeviceModel device = (DeviceModel) optionalDevice.get(); + assertEquals("HAN-FUN", device.getProductName()); + assertEquals("113240824499-1", device.getIdentifier()); + assertEquals("2002", device.getDeviceId()); + assertEquals("0.0", device.getFirmwareVersion()); + assertEquals("0x2c3c", device.getManufacturer()); + + assertEquals(1, device.getPresent()); + assertEquals("Steckdose innen", device.getName()); + + assertFalse(device.isHANFUNButton()); + assertFalse(device.isHANFUNAlarmSensor()); + assertFalse(device.isButton()); + assertFalse(device.isHeatingThermostat()); + assertFalse(device.isPowermeter()); + assertFalse(device.isTemperatureSensor()); + assertFalse(device.isSwitchableOutlet()); + assertFalse(device.isDectRepeater()); + assertFalse(device.hasMicrophone()); + assertTrue(device.isHANFUNUnit()); + assertTrue(device.isHANFUNOnOff()); + assertFalse(device.isHANFUNBlinds()); + assertFalse(device.isHumiditySensor()); + + assertTrue(device.getButtons().isEmpty()); + + assertNull(device.getAlert()); + + assertNull(device.getSwitch()); + + assertNull(device.getTemperature()); + + SimpleOnOffModel model = device.getSimpleOnOffUnit(); + assertNotNull(model); + assertEquals(false, model.state); + + assertNull(device.getPowermeter()); + + assertNull(device.getHkr()); + + assertNull(device.getLevelcontrol()); + } + @Test public void validateHeatingGroupModel() { Optional optionalGroup = findModelByIdentifier("F0:A3:7F-901"); @@ -630,7 +711,7 @@ public class AVMFritzDeviceListModelTest { assertFalse(group.isHANFUNAlarmSensor()); assertFalse(group.isDectRepeater()); assertFalse(group.isSwitchableOutlet()); - assertFalse(group.isTempSensor()); + assertFalse(group.isTemperatureSensor()); assertFalse(group.isHumiditySensor()); assertFalse(group.isPowermeter()); assertTrue(group.isHeatingThermostat()); @@ -668,7 +749,7 @@ public class AVMFritzDeviceListModelTest { assertFalse(group.isHANFUNAlarmSensor()); assertFalse(group.isDectRepeater()); assertTrue(group.isSwitchableOutlet()); - assertFalse(group.isTempSensor()); + assertFalse(group.isTemperatureSensor()); assertFalse(group.isHumiditySensor()); assertTrue(group.isPowermeter()); assertFalse(group.isHeatingThermostat()); diff --git a/itests/org.openhab.binding.avmfritz.tests/src/main/java/org/openhab/binding/avmfritz/internal/discovery/AVMFritzDiscoveryServiceOSGiTest.java b/itests/org.openhab.binding.avmfritz.tests/src/main/java/org/openhab/binding/avmfritz/internal/discovery/AVMFritzDiscoveryServiceOSGiTest.java index 4eb5a4020..3265dd8be 100644 --- a/itests/org.openhab.binding.avmfritz.tests/src/main/java/org/openhab/binding/avmfritz/internal/discovery/AVMFritzDiscoveryServiceOSGiTest.java +++ b/itests/org.openhab.binding.avmfritz.tests/src/main/java/org/openhab/binding/avmfritz/internal/discovery/AVMFritzDiscoveryServiceOSGiTest.java @@ -89,7 +89,7 @@ public class AVMFritzDiscoveryServiceOSGiTest extends AVMFritzThingHandlerOSGiTe @Test public void correctSupportedTypes() { - assertEquals(14, discovery.getSupportedThingTypes().size()); + assertEquals(15, discovery.getSupportedThingTypes().size()); assertTrue(discovery.getSupportedThingTypes().contains(DECT100_THING_TYPE)); assertTrue(discovery.getSupportedThingTypes().contains(DECT200_THING_TYPE)); assertTrue(discovery.getSupportedThingTypes().contains(DECT210_THING_TYPE)); @@ -101,6 +101,7 @@ public class AVMFritzDiscoveryServiceOSGiTest extends AVMFritzThingHandlerOSGiTe 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_ON_OFF_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));