diff --git a/bundles/org.openhab.binding.avmfritz/README.md b/bundles/org.openhab.binding.avmfritz/README.md index a168d9bcb..94405eadd 100644 --- a/bundles/org.openhab.binding.avmfritz/README.md +++ b/bundles/org.openhab.binding.avmfritz/README.md @@ -1,6 +1,8 @@ # AVM FRITZ! Binding -The binding integrates AVM FRITZ!Boxes with a special focus on the AHA ( [AVM Home Automation](https://avm.de/ratgeber/smart-home/) ) features. +The binding integrates AVM FRITZ!Boxes with a special focus on the AHA ([AVM Home Automation](https://avm.de/ratgeber/filter/smart-home/)) features. + +![FRITZ!DECT 200 301 500](doc/AVM_FRITZDECT_200_301_500_freigestellt.png) ## Supported Things @@ -26,23 +28,34 @@ It only supports temperature readings. ### FRITZ!Powerline 546E -This [powerline adapter](https://avm.de/produkte/fritzpowerline/fritzpowerline-546e/) can be used via the bridge or in stand-alone mode. +This [powerline adapter](https://avm.de/produkte/fritzpowerline/) can be used via the bridge or in stand-alone mode. It supports switching the outlet and reading the current power, current voltage and accumulated energy consumption. This device does not contain a temperature sensor. **NOTE:** The `voltage` channel will be added to the thing during runtime - if the interface supports it (FRITZ!OS 7 or higher). ### FRITZ!DECT 301 / FRITZ!DECT 300 / Comet DECT -These devices [FRITZ!DECT 301](https://avm.de/produkte/fritzdect/fritzdect-301/), FRITZ!DECT 300 and [Comet DECT](https://www.eurotronic.org/produkte/comet-dect.html) ( [EUROtronic Technology GmbH](https://www.eurotronic.org) ) are used to regulate radiators via DECT protocol. +These devices [FRITZ!DECT 301](https://avm.de/produkte/fritzdect/fritzdect-301/), FRITZ!DECT 300 and [Comet DECT](https://eurotronic.org/produkte/dect-ule-heizkoerperthermostat/comet-dect/) ([EUROtronic Technology GmbH](https://eurotronic.org/)) are used to regulate radiators via DECT-ULE protocol. The FRITZ!Box can handle up to twelve heating thermostats. The binding provides channels for reading and setting the temperature. Additionally you can check the eco temperature, the comfort temperature and the battery level of the device. The FRITZ!Box has to run at least on firmware FRITZ!OS 6.35. **NOTE:** The `battery_level` channel will be added to the thing during runtime - if the interface supports it (FRITZ!OS 7 or higher). -### FRITZ!DECT 400 +### FRITZ!DECT 400 / FRITZ!DECT 440 -The [FRITZ!DECT 400](https://avm.de/produkte/fritzdect/fritzdect-400/) is a button for convenient operation of FRITZ! Smart Home devices (FRITZ!OS 7.08 or higher). +The [FRITZ!DECT 400](https://avm.de/produkte/fritzdect/fritzdect-400/) and [FRITZ!DECT 440](https://avm.de/produkte/fritzdect/fritzdect-440/) are buttons for convenient operation of FRITZ! Smart Home devices (FRITZ!OS 7.08 or higher for FRITZ!DECT 400, 7.20 or higher for FRITZ!DECT 440). +The FRITZ!DECT 400 supports a configurable button to trigger short or long press events. +Beside four customizable buttons the FRITZ!DECT 440 supports temperature readings. +** NOTE: ** FRITZ!DECT 440 now uses Channel Groups to group its Channels like `device#battery_level`, `device#battery_low` for device information, `sensors#temperature` for sensor data and `top-left`, `bottom-left`, `top-right` and `bottom-right` combined with `press` and `last_change` (see [Full Example](#full-example)) + +#### Supported Channel Groups + +| Channel Group ID | Description | Available on thing | +|--------------------------------------------------------|---------------------|--------------------| +| `device` | Device information. | FRITZ!DECT 440 | +| `sensors` | Sensor data. | FRITZ!DECT 440 | +| `top-left`, `bottom-left`, `top-right`, `bottom-right` | Button and trigger. | FRITZ!DECT 440 | ### DECT-ULE / HAN-FUN Devices @@ -80,7 +93,7 @@ To do so - Enable the option "Login with FRITZ!Box user name and password". - Click "Apply" to save the settings. -Note: Now you can only log in to the FRITZ!Box with a user account, i.e. after entering a user name and password. +**NOTE:** Now you can only log in to the FRITZ!Box with a user account, i.e. after entering a user name and password. Auto-discovery is enabled by default. To disable it, you can add the following line to `/services/runtime.cfg`: @@ -121,47 +134,48 @@ If the FRITZ!Powerline 546E is added via auto-discovery it determines its own `a - `ain` (mandatory), no default (AIN number of the device) -### Finding The AIN ### +### Finding The AIN The AIN (actor identification number) can be found in the FRITZ!Box interface -> Home Network -> SmartHome. When opening the details view for a device with the edit button, the AIN is shown. Use the AIN without the blank. ## Supported Channels -| Channel Type ID | Item Type | Description | Available on thing | -|-----------------|--------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------| -| incoming_call | Call | Details about incoming call. | FRITZ!Box | -| outgoing_call | Call | Details about outgoing call. | FRITZ!Box | -| active_call | Call | Details about active call. | FRITZ!Box | -| call_state | String | Details about current call state, either IDLE, RINGING, DIALING or ACTIVE. | FRITZ!Box | -| apply_template | String | Apply template for device(s) (channel's state options contains available templates, for an alternative way see the description below) - FRITZ!OS 7 | FRITZ!Box, FRITZ!Powerline 546E | -| mode | String | States the mode of the device (MANUAL/AUTOMATIC/VACATION) | FRITZ!DECT 210, FRITZ!DECT 200, FRITZ!Powerline 546E, FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT | -| locked | Contact | Device is locked for switching over external sources (OPEN/CLOSE) | FRITZ!DECT 210, FRITZ!DECT 200, FRITZ!Powerline 546E, FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT | -| device_locked | Contact | Device is locked for switching manually (OPEN/CLOSE) - FRITZ!OS 6.90 | FRITZ!DECT 210, FRITZ!DECT 200, FRITZ!Powerline 546E, FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT | -| temperature | Number:Temperature | Current measured temperature | FRITZ!DECT 210, FRITZ!DECT 200, FRITZ!DECT Repeater 100, FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT | -| energy | Number:Energy | Accumulated energy consumption | FRITZ!DECT 210, FRITZ!DECT 200, FRITZ!Powerline 546E | -| 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 | -| 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 | -| comfort_temp | Number:Temperature | Comfort Temperature of heating thermostat | FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT | -| radiator_mode | String | Mode of heating thermostat (ON/OFF/COMFORT/ECO/BOOST/WINDOW_OPEN) | FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT | -| next_change | DateTime | Next change of the Set Temperature if scheduler is activated in the FRITZ!Box settings - FRITZ!OS 6.80 | FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT | -| next_temp | Number:Temperature | Next Set Temperature if scheduler is activated in the FRITZ!Box settings - FRITZ!OS 6.80 | FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT | -| battery_level | Number | Battery level (in %) - FRITZ!OS 7 | FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT, FRITZ!DECT 400 | -| battery_low | Switch | Battery level low (ON/OFF) - FRITZ!OS 6.80 | FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT, FRITZ!DECT 400 | -| 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, HAN-FUN switch (e.g. SmartHome Wandtaster) - FRITZ!OS 7 | +| Channel Type ID | Item Type | Description | Available on thing | +|-----------------|--------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------| +| incoming_call | Call | Details about incoming call. | FRITZ!Box | +| outgoing_call | Call | Details about outgoing call. | FRITZ!Box | +| active_call | Call | Details about active call. | FRITZ!Box | +| call_state | String | Details about current call state, either IDLE, RINGING, DIALING or ACTIVE. | FRITZ!Box | +| apply_template | String | Apply template for device(s) (channel's state options contains available templates, for an alternative way see the description below) - FRITZ!OS 7 | FRITZ!Box, FRITZ!Powerline 546E | +| mode | String | States the mode of the device (MANUAL/AUTOMATIC/VACATION) | FRITZ!DECT 210, FRITZ!DECT 200, FRITZ!Powerline 546E, FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT | +| locked | Contact | Device is locked for switching over external sources (OPEN/CLOSE) | FRITZ!DECT 210, FRITZ!DECT 200, FRITZ!Powerline 546E, FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT | +| device_locked | Contact | Device is locked for switching manually (OPEN/CLOSE) - FRITZ!OS 6.90 | FRITZ!DECT 210, FRITZ!DECT 200, FRITZ!Powerline 546E, FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT | +| temperature | Number:Temperature | Current measured temperature | FRITZ!DECT 210, FRITZ!DECT 200, FRITZ!DECT Repeater 100, FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT, FRITZ!DECT 440 | +| energy | Number:Energy | Accumulated energy consumption | FRITZ!DECT 210, FRITZ!DECT 200, FRITZ!Powerline 546E | +| 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 | +| 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 | +| comfort_temp | Number:Temperature | Comfort Temperature of heating thermostat | FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT | +| radiator_mode | String | Mode of heating thermostat (ON/OFF/COMFORT/ECO/BOOST/WINDOW_OPEN) | FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT | +| next_change | DateTime | Next change of the Set Temperature if scheduler is activated in the FRITZ!Box settings - FRITZ!OS 6.80 | FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT | +| next_temp | Number:Temperature | Next Set Temperature if scheduler is activated in the FRITZ!Box settings - FRITZ!OS 6.80 | FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT | +| battery_level | Number | Battery level (in %) - FRITZ!OS 7 | FRITZ!DECT 301, FRITZ!DECT 300, Comet DECT, FRITZ!DECT 400, FRITZ!DECT 440 | +| 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 | ### Triggers -| Channel Type ID | Item Type | Description | Available on thing | -|-----------------|-----------|--------------------------------------------------------------------------------|---------------------------------------------------------| -| press | Trigger | Dispatches a `PRESSED` event when a button is pressed. | HAN-FUN switch (e.g. SmartHome Wandtaster) - FRITZ!OS 7 | -| press | Trigger | Dispatches a `SHORT_PRESSED` or `LONG_PRESSED` event when a button is pressed. | FRITZ!DECT 400 - FRITZ!OS 7.08 | +| Channel Type ID | Item Type | Description | Available on thing | +|-----------------|-----------|--------------------------------------------------------------------------------|-----------------------------------------------------------| +| press | Trigger | Dispatches a `PRESSED` event when a button is pressed. | FRITZ!DECT440, HAN-FUN switch (e.g. SmartHome Wandtaster) | +| press | Trigger | Dispatches a `SHORT_PRESSED` or `LONG_PRESSED` event when a button is pressed. | FRITZ!DECT 400 | -The trigger channel `press` is of type `system.rawbutton` to allow the usage of the `rawbutton-toggle-switch` profile. +The trigger channel `press` for a FRITZ!DECT 440 device or HAN-FUN switch is of type `system.rawbutton` to allow the usage of the `rawbutton-toggle-switch` profile. +The trigger channel `press` for a FRITZ!DECT 400 device is of type `system.button`. ### FRITZ! Smart Home Templates @@ -210,6 +224,7 @@ demo.things: ```java Bridge avmfritz:fritzbox:1 "FRITZ!Box" [ ipAddress="192.168.x.x", password="xxx", user="xxx" ] { + Thing FRITZ_DECT_440 vvvvvvvvvvvv "FRITZ!DECT 440 #15" [ ain="vvvvvvvvvvvv" ] Thing FRITZ_DECT_200 xxxxxxxxxxxx "FRITZ!DECT 200 #1" [ ain="xxxxxxxxxxxx" ] Thing FRITZ_Powerline_546E yy_yy_yy_yy_yy_yy "FRITZ!Powerline 546E #2" [ ain="yy:yy:yy:yy:yy:yy" ] Thing Comet_DECT aaaaaabbbbbb "Comet DECT #3" [ ain="aaaaaabbbbbb" ] @@ -230,6 +245,14 @@ Call OutgoingCall "Outgoing call: [%1$s to %2$s]" { channel="avmfritz:fritzbo Call ActiveCall "Call established [%1$s]" { channel="avmfritz:fritzbox:1:active_call" } String ApplyTemplate "Apply template" { channel="avmfritz:fritzbox:1:apply_template" } +Number:Temperature SwitchTemperature "Current measured temperature [%.1f %unit%]" { channel="avmfritz:FRITZ_DECT_440:1:vvvvvvvvvvvv:sensors#temperature" } +Number SwitchBatteryLevel "Battery level" { channel="avmfritz:FRITZ_DECT_440:1:vvvvvvvvvvvv:device#battery_level" } +Switch SwitchBatteryLow "Battery low" { channel="avmfritz:FRITZ_DECT_440:1:vvvvvvvvvvvv:device#battery_low" } +DateTime TopLeftSwitchLastChanged "Last change" { channel="avmfritz:FRITZ_DECT_440:1:vvvvvvvvvvvv:top-left#last_change" } +DateTime BottomLeftSwitchLastChanged "Last change" { channel="avmfritz:FRITZ_DECT_440:1:vvvvvvvvvvvv:bottom-left#last_change" } +DateTime TopRightSwitchLastChanged "Last change" { channel="avmfritz:FRITZ_DECT_440:1:vvvvvvvvvvvv:top-right#last_change" } +DateTime BottomRightSwitchLastChanged "Last change" { channel="avmfritz:FRITZ_DECT_440:1:vvvvvvvvvvvv:bottom-right#last_change" } + Switch Outlet1 "Switchable outlet" { channel="avmfritz:FRITZ_DECT_200:1:xxxxxxxxxxxx:outlet" } Number:Temperature Temperature1 "Current measured temperature [%.1f %unit%]" { channel="avmfritz:FRITZ_DECT_200:1:xxxxxxxxxxxx:temperature" } Number:Energy Energy1 "Accumulated energy consumption [%.3f kWh]" { channel="avmfritz:FRITZ_DECT_200:1:xxxxxxxxxxxx:energy" } @@ -300,6 +323,15 @@ sitemap demo label="Main Menu" { demo.rules: +```java +rule "FRITZ!DECT 440 Top Left Button pressed" +when + Channel "avmfritz:FRITZ_DECT_440:1:vvvvvvvvvvvv:top-left#press" triggered PRESSED +then + logInfo("demo", "Top Left Button pressed") +end +``` + ```java rule "HAN-FUN Button pressed" when diff --git a/bundles/org.openhab.binding.avmfritz/doc/AVM_FRITZDECT_200_301_500_freigestellt.png b/bundles/org.openhab.binding.avmfritz/doc/AVM_FRITZDECT_200_301_500_freigestellt.png new file mode 100644 index 000000000..2cbaa23c8 Binary files /dev/null and b/bundles/org.openhab.binding.avmfritz/doc/AVM_FRITZDECT_200_301_500_freigestellt.png differ 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 f3328affe..0589c5e37 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 @@ -41,6 +41,7 @@ public class AVMFritzBindingConstants { // List of main device types public static final String DEVICE_DECT400 = "FRITZ_DECT_400"; + public static final String DEVICE_DECT440 = "FRITZ_DECT_440"; public static final String DEVICE_DECT301 = "FRITZ_DECT_301"; public static final String DEVICE_DECT300 = "FRITZ_DECT_300"; public static final String DEVICE_DECT210 = "FRITZ_DECT_210"; @@ -59,6 +60,7 @@ public class AVMFritzBindingConstants { // List of all Thing Type UIDs public static final ThingTypeUID BRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, BRIDGE_FRITZBOX); public static final ThingTypeUID DECT400_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_DECT400); + public static final ThingTypeUID DECT440_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_DECT440); public static final ThingTypeUID DECT301_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_DECT301); public static final ThingTypeUID DECT300_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_DECT300); public static final ThingTypeUID DECT210_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_DECT210); @@ -86,6 +88,12 @@ public class AVMFritzBindingConstants { public static final String PROPERTY_MASTER = "master"; public static final String PROPERTY_MEMBERS = "members"; + // List of all channel groups + public static final String CHANNEL_GROUP_TOP_LEFT = "top-left"; + public static final String CHANNEL_GROUP_BOTTOM_LEFT = "bottom-left"; + public static final String CHANNEL_GROUP_TOP_RIGHT = "top-right"; + public static final String CHANNEL_GROUP_BOTTOM_RIGHT = "bottom-right"; + // List of all Channel ids public static final String CHANNEL_CALL_INCOMING = "incoming_call"; public static final String CHANNEL_CALL_OUTGOING = "outgoing_call"; @@ -145,21 +153,20 @@ public class AVMFritzBindingConstants { public static final String MODE_WINDOW_OPEN = "WINDOW_OPEN"; public static final String MODE_UNKNOWN = "UNKNOWN"; - public static final Set SUPPORTED_BUTTON_THING_TYPES_UIDS = Collections - .unmodifiableSet(Stream.of(DECT400_THING_TYPE, HAN_FUN_SWITCH_THING_TYPE).collect(Collectors.toSet())); + public static final Set SUPPORTED_BUTTON_THING_TYPES_UIDS = Set.of(DECT400_THING_TYPE, + DECT440_THING_TYPE, HAN_FUN_SWITCH_THING_TYPE); - public static final Set SUPPORTED_HEATING_THING_TYPES = Collections.unmodifiableSet( - Stream.of(DECT300_THING_TYPE, DECT301_THING_TYPE, COMETDECT_THING_TYPE).collect(Collectors.toSet())); + public static final Set SUPPORTED_HEATING_THING_TYPES = Set.of(DECT300_THING_TYPE, DECT301_THING_TYPE, + COMETDECT_THING_TYPE); - public static final Set SUPPORTED_DEVICE_THING_TYPES_UIDS = Collections - .unmodifiableSet(Stream.of(DECT100_THING_TYPE, DECT200_THING_TYPE, DECT210_THING_TYPE, PL546E_THING_TYPE, - HAN_FUN_CONTACT_THING_TYPE).collect(Collectors.toSet())); + 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); - public static final Set SUPPORTED_GROUP_THING_TYPES_UIDS = Collections - .unmodifiableSet(Stream.of(GROUP_HEATING_THING_TYPE, GROUP_SWITCH_THING_TYPE).collect(Collectors.toSet())); + public static final Set SUPPORTED_GROUP_THING_TYPES_UIDS = Set.of(GROUP_HEATING_THING_TYPE, + GROUP_SWITCH_THING_TYPE); - public static final Set SUPPORTED_BRIDGE_THING_TYPES_UIDS = Collections - .unmodifiableSet(Stream.of(BRIDGE_THING_TYPE, PL546E_STANDALONE_THING_TYPE).collect(Collectors.toSet())); + public static final Set SUPPORTED_BRIDGE_THING_TYPES_UIDS = Set.of(BRIDGE_THING_TYPE, + PL546E_STANDALONE_THING_TYPE); public static final Set SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet(Stream .of(SUPPORTED_BUTTON_THING_TYPES_UIDS, SUPPORTED_HEATING_THING_TYPES, SUPPORTED_DEVICE_THING_TYPES_UIDS, 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 6093ed584..0dbe19773 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 @@ -24,8 +24,9 @@ import javax.xml.bind.annotation.XmlElement; * *
    *
  1. Bit 0: HAN-FUN Gerät
  2. - *
  3. Bit 3: Button
  4. + *
  5. Bit 3: HAN-FUN Button - undocumented
  6. *
  7. Bit 4: Alarm-Sensor
  8. + *
  9. Bit 5: AVM-Button
  10. *
  11. Bit 6: Comet DECT, Heizkörperregler
  12. *
  13. Bit 7: Energie Messgerät
  14. *
  15. Bit 8: Temperatursensor
  16. @@ -43,7 +44,7 @@ public abstract class AVMFritzBaseModel implements BatteryModel { protected static final int HAN_FUN_DEVICE_BIT = 1; // Bit 0 protected static final int HAN_FUN_BUTTON_BIT = 1 << 3; // Bit 3 - undocumented protected static final int HAN_FUN_ALARM_SENSOR_BIT = 1 << 4; // Bit 4 - protected static final int BUTTON_BIT = 1 << 5; // Bit 5 - undocumented + protected static final int BUTTON_BIT = 1 << 5; // Bit 5 protected static final int HEATING_THERMOSTAT_BIT = 1 << 6; // Bit 6 protected static final int POWERMETER_BIT = 1 << 7; // Bit 7 protected static final int TEMPSENSOR_BIT = 1 << 8; // Bit 8 diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzButtonHandler.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzButtonHandler.java index e59f2edcd..d8d681794 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzButtonHandler.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzButtonHandler.java @@ -18,13 +18,16 @@ import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.List; +import java.util.Optional; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.avmfritz.internal.dto.AVMFritzBaseModel; import org.openhab.binding.avmfritz.internal.dto.ButtonModel; import org.openhab.binding.avmfritz.internal.dto.DeviceModel; import org.openhab.core.library.types.DateTimeType; import org.openhab.core.thing.Channel; +import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.CommonTriggerEvents; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingUID; @@ -40,6 +43,11 @@ import org.slf4j.LoggerFactory; @NonNullByDefault public class AVMFritzButtonHandler extends DeviceHandler { + private static final String TOP_RIGHT_SUFFIX = "-1"; + private static final String BOTTOM_RIGHT_SUFFIX = "-3"; + private static final String BOTTOM_LEFT_SUFFIX = "-5"; + private static final String TOP_LEFT_SUFFIX = "-7"; + private final Logger logger = LoggerFactory.getLogger(AVMFritzButtonHandler.class); /** * keeps track of the last timestamp for handling trigger events @@ -67,7 +75,11 @@ public class AVMFritzButtonHandler extends DeviceHandler { updateHANFUNButton(deviceModel.getButtons()); } if (deviceModel.isButton()) { - updateShortLongPressButton(deviceModel.getButtons()); + if (DECT400_THING_TYPE.equals(thing.getThingTypeUID())) { + updateShortLongPressButton(deviceModel.getButtons()); + } else if (DECT440_THING_TYPE.equals(thing.getThingTypeUID())) { + updateButtons(deviceModel.getButtons()); + } updateBattery(deviceModel); } } @@ -88,6 +100,29 @@ public class AVMFritzButtonHandler extends DeviceHandler { } } + private void updateButtons(List buttons) { + Optional topLeft = buttons.stream().filter(b -> b.getIdentifier().endsWith(TOP_LEFT_SUFFIX)) + .findFirst(); + if (topLeft.isPresent()) { + updateButton(topLeft.get(), CommonTriggerEvents.PRESSED, CHANNEL_GROUP_TOP_LEFT); + } + Optional bottomLeft = buttons.stream().filter(b -> b.getIdentifier().endsWith(BOTTOM_LEFT_SUFFIX)) + .findFirst(); + if (bottomLeft.isPresent()) { + updateButton(bottomLeft.get(), CommonTriggerEvents.PRESSED, CHANNEL_GROUP_BOTTOM_LEFT); + } + Optional topRight = buttons.stream().filter(b -> b.getIdentifier().endsWith(TOP_RIGHT_SUFFIX)) + .findFirst(); + if (topRight.isPresent()) { + updateButton(topRight.get(), CommonTriggerEvents.PRESSED, CHANNEL_GROUP_TOP_RIGHT); + } + Optional bottomRight = buttons.stream() + .filter(b -> b.getIdentifier().endsWith(BOTTOM_RIGHT_SUFFIX)).findFirst(); + if (bottomRight.isPresent()) { + updateButton(bottomRight.get(), CommonTriggerEvents.PRESSED, CHANNEL_GROUP_BOTTOM_RIGHT); + } + } + private void updateHANFUNButton(List buttons) { if (!buttons.isEmpty()) { updateButton(buttons.get(0), CommonTriggerEvents.PRESSED); @@ -95,9 +130,16 @@ public class AVMFritzButtonHandler extends DeviceHandler { } private void updateButton(ButtonModel buttonModel, String event) { + updateButton(buttonModel, event, null); + } + + private void updateButton(ButtonModel buttonModel, String event, @Nullable String channelGroupId) { int lastPressedTimestamp = buttonModel.getLastpressedtimestamp(); if (lastPressedTimestamp == 0) { - updateThingChannelState(CHANNEL_LAST_CHANGE, UnDefType.UNDEF); + updateThingChannelState( + channelGroupId == null ? CHANNEL_LAST_CHANGE + : channelGroupId + ChannelUID.CHANNEL_GROUP_SEPARATOR + CHANNEL_LAST_CHANGE, + UnDefType.UNDEF); } else { ZonedDateTime timestamp = ZonedDateTime.ofInstant(Instant.ofEpochSecond(lastPressedTimestamp), ZoneId.systemDefault()); @@ -106,9 +148,13 @@ public class AVMFritzButtonHandler extends DeviceHandler { // restart) if (then.isAfter(lastTimestamp)) { lastTimestamp = then; - triggerThingChannel(CHANNEL_PRESS, event); + triggerThingChannel(channelGroupId == null ? CHANNEL_PRESS + : channelGroupId + ChannelUID.CHANNEL_GROUP_SEPARATOR + CHANNEL_PRESS, event); } - updateThingChannelState(CHANNEL_LAST_CHANGE, new DateTimeType(timestamp)); + updateThingChannelState( + channelGroupId == null ? CHANNEL_LAST_CHANGE + : channelGroupId + ChannelUID.CHANNEL_GROUP_SEPARATOR + CHANNEL_LAST_CHANGE, + new DateTimeType(timestamp)); } } 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 3da3e2133..a006fc748 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 @@ -95,6 +95,8 @@ thing-type.avmfritz.Comet_DECT.description = Comet DECT Heizk thing-type.avmfritz.FRITZ_DECT_400.description = FRITZ!DECT 400 Taster. Dient zur komfortablen Bedienung von FRITZ! Smart-Home-Geräten. +thing-type.avmfritz.FRITZ_DECT_440.description = FRITZ!DECT 440 Taster. Dient zur komfortablen Bedienung von FRITZ! Smart-Home-Geräten und liefert Daten wie z.B. Temperatur. + 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 types config groups @@ -109,8 +111,23 @@ thing-type.config.avmfritz.fritzdevice.ain.description = Die AHA ID (AIN) zur Id thing-type.config.avmfritz.fritzgroup.ain.description = Die AHA ID (AIN) zur Identifikation der FRITZ! Gruppe. -# channel types +# channel group types +channel-group-type.avmfritz.button.label = Taste +channel-group-type.avmfritz.device.label = Geräteinformationen + +channel-group-type.avmfritz.sensors.label = Sensordaten + +# channel groups +thing-type.avmfritz.FRITZ_DECT_440.group.top-left.label = Taste Oben Links + +thing-type.avmfritz.FRITZ_DECT_440.group.top-right.label = Taste Oben Rechts + +thing-type.avmfritz.FRITZ_DECT_440.group.bottom-left.label = Taste Unten Links + +thing-type.avmfritz.FRITZ_DECT_440.group.bottom-right.label = Taste Unten Rechts + +# channel types channel-type.avmfritz.incoming_call.label = Eingehender Anruf channel-type.avmfritz.incoming_call.description = Informationen zu anrufender und angerufener Telefonnummer. channel-type.avmfritz.outgoing_call.label = Ausgehender Anruf @@ -188,6 +205,12 @@ channel-type.avmfritz.contact_state.description = Zeigt an, ob die T thing-type.avmfritz.HAN_FUN_SWITCH.channel.press.label = Tastendruck thing-type.avmfritz.HAN_FUN_SWITCH.channel.press.description = Wird ausgelöst, wenn eine Taste gedrückt wird. +thing-type.avmfritz.FRITZ_DECT_400.channel.press.label = Tastendruck +thing-type.avmfritz.FRITZ_DECT_400.channel.press.description = Wird ausgelöst, wenn eine Taste gedrückt wird. + +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.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 diff --git a/bundles/org.openhab.binding.avmfritz/src/main/resources/OH-INF/thing/channel-types.xml b/bundles/org.openhab.binding.avmfritz/src/main/resources/OH-INF/thing/channel-types.xml index e2ec3e141..410d7ca60 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/resources/OH-INF/thing/channel-types.xml +++ b/bundles/org.openhab.binding.avmfritz/src/main/resources/OH-INF/thing/channel-types.xml @@ -73,7 +73,34 @@ - + + + + + + + Triggeres PRESSED when a button was pressed. + + + + + + + + + + + + + + + + + + + + + Number:Temperature 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 58c640c50..3921f4948 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 @@ -16,8 +16,8 @@ - - Triggered SHORT_PRESSED or LONG_PRESSED when a button was pressed. + + Triggeres SHORT_PRESSED or LONG_PRESSED when a button was pressed. @@ -29,6 +29,37 @@ + + + + + + + + FRITZ!DECT440 switch. + + + + + + + + + + + + + + + + + + + ain + + + + @@ -236,7 +267,7 @@ - Triggered when a button was pressed. + Triggeres PRESSED when a button was pressed. 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 b5ce63c9f..045d7ec9e 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 @@ -44,7 +44,7 @@ public class AVMFritzDeviceListModelTest { @BeforeEach public void setUp() { //@formatter:off - String xml = + final String xml = "" + "1Schlafzimmer1manuell00230051020871717,18" + "1Schlafzimmer220-104442284211000000100148434120028020,21,22" + @@ -58,9 +58,9 @@ public class AVMFritzDeviceListModelTest { "0HAN-FUN #2: Unit #24065142561" + "0HAN-FUN #2: Unit #2412273772" + "1FRITZ!DECT 400 #141000" + + "1FRITZ!DECT 440 #1523001000" + ""; //@formatter:off - try { Unmarshaller u = JAXBUtils.JAXBCONTEXT_DEVICES.createUnmarshaller(); devices = (DeviceListModel) u.unmarshal(new StringReader(xml)); @@ -72,7 +72,7 @@ public class AVMFritzDeviceListModelTest { @Test public void validateDeviceListModel() { assertNotNull(devices); - assertEquals(12, devices.getDevicelist().size()); + assertEquals(13, devices.getDevicelist().size()); assertEquals("1", devices.getXmlApiVersion()); } @@ -345,6 +345,69 @@ public class AVMFritzDeviceListModelTest { assertNull(device.getHkr()); } + @Test + public void validateDECT440Model() { + Optional optionalDevice = findModelByIdentifier("130960007308"); + assertTrue(optionalDevice.isPresent()); + assertTrue(optionalDevice.get() instanceof DeviceModel); + + DeviceModel device = (DeviceModel) optionalDevice.get(); + assertEquals("FRITZ!DECT 440", device.getProductName()); + assertEquals("130960007308", device.getIdentifier()); + assertEquals("30", device.getDeviceId()); + assertEquals("04.90", device.getFirmwareVersion()); + assertEquals("AVM", device.getManufacturer()); + + assertEquals(1, device.getPresent()); + assertEquals("FRITZ!DECT 440 #15", device.getName()); + + assertTrue(device.isButton()); + assertFalse(device.isHANFUNButton()); + assertFalse(device.isHANFUNAlarmSensor()); + assertFalse(device.isDectRepeater()); + assertFalse(device.isSwitchableOutlet()); + assertTrue(device.isTempSensor()); + assertFalse(device.isPowermeter()); + assertFalse(device.isHeatingThermostat()); + + assertEquals(new BigDecimal("100"), device.getBattery()); + assertEquals(BatteryModel.BATTERY_OFF, device.getBatterylow()); + + assertEquals(4, device.getButtons().size()); + final ButtonModel topRight = device.getButtons().get(0); + assertEquals("130960007308-1", topRight.getIdentifier()); + assertEquals("5000", topRight.getButtonId()); + assertEquals("FRITZ!DECT 440 #15: Oben rechts", topRight.getName()); + assertEquals(1549195586, topRight.getLastpressedtimestamp()); + final ButtonModel bottomRight = device.getButtons().get(1); + assertEquals("130960007308-3", bottomRight.getIdentifier()); + assertEquals("5001", bottomRight.getButtonId()); + assertEquals("FRITZ!DECT 440 #15: Unten rechts", bottomRight.getName()); + assertEquals(1549195595, bottomRight.getLastpressedtimestamp()); + final ButtonModel bottomLeft = device.getButtons().get(2); + assertEquals("130960007308-5", bottomLeft.getIdentifier()); + assertEquals("5002", bottomLeft.getButtonId()); + assertEquals("FRITZ!DECT 440 #15: Unten links", bottomLeft.getName()); + assertEquals(1549195586, bottomLeft.getLastpressedtimestamp()); + final ButtonModel topLeft = device.getButtons().get(3); + assertEquals("130960007308-7", topLeft.getIdentifier()); + assertEquals("5003", topLeft.getButtonId()); + assertEquals("FRITZ!DECT 440 #15: Oben links", topLeft.getName()); + assertEquals(1549195595, topLeft.getLastpressedtimestamp()); + + assertNull(device.getAlert()); + + assertNull(device.getSwitch()); + + assertNotNull(device.getTemperature()); + assertEquals(new BigDecimal("23.0"), device.getTemperature().getCelsius()); + assertEquals(new BigDecimal("0.0"), device.getTemperature().getOffset()); + + assertNull(device.getPowermeter()); + + assertNull(device.getHkr()); + } + @Test public void validatePowerline546EModel() { Optional optionalDevice = findModel("FRITZ!Powerline 546E"); 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 c6d988714..13aae28eb 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 @@ -86,13 +86,14 @@ public class AVMFritzDiscoveryServiceOSGiTest extends AVMFritzThingHandlerOSGiTe @Test public void correctSupportedTypes() { - assertEquals(12, discovery.getSupportedThingTypes().size()); + assertEquals(13, 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(DECT300_THING_TYPE)); assertTrue(discovery.getSupportedThingTypes().contains(DECT301_THING_TYPE)); assertTrue(discovery.getSupportedThingTypes().contains(DECT400_THING_TYPE)); + assertTrue(discovery.getSupportedThingTypes().contains(DECT440_THING_TYPE)); assertTrue(discovery.getSupportedThingTypes().contains(PL546E_THING_TYPE)); assertTrue(discovery.getSupportedThingTypes().contains(COMETDECT_THING_TYPE)); assertTrue(discovery.getSupportedThingTypes().contains(HAN_FUN_CONTACT_THING_TYPE));