[avmfritz] Added support for DECT440 device (#8588)

Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
This commit is contained in:
Christoph Weitkamp 2020-09-28 21:35:37 +02:00 committed by GitHub
parent 64a713e74a
commit bff1810aec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 295 additions and 64 deletions

View File

@ -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 `<openHAB-conf>/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -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<ThingTypeUID> SUPPORTED_BUTTON_THING_TYPES_UIDS = Collections
.unmodifiableSet(Stream.of(DECT400_THING_TYPE, HAN_FUN_SWITCH_THING_TYPE).collect(Collectors.toSet()));
public static final Set<ThingTypeUID> SUPPORTED_BUTTON_THING_TYPES_UIDS = Set.of(DECT400_THING_TYPE,
DECT440_THING_TYPE, HAN_FUN_SWITCH_THING_TYPE);
public static final Set<ThingTypeUID> SUPPORTED_HEATING_THING_TYPES = Collections.unmodifiableSet(
Stream.of(DECT300_THING_TYPE, DECT301_THING_TYPE, COMETDECT_THING_TYPE).collect(Collectors.toSet()));
public static final Set<ThingTypeUID> SUPPORTED_HEATING_THING_TYPES = Set.of(DECT300_THING_TYPE, DECT301_THING_TYPE,
COMETDECT_THING_TYPE);
public static final Set<ThingTypeUID> 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<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);
public static final Set<ThingTypeUID> SUPPORTED_GROUP_THING_TYPES_UIDS = Collections
.unmodifiableSet(Stream.of(GROUP_HEATING_THING_TYPE, GROUP_SWITCH_THING_TYPE).collect(Collectors.toSet()));
public static final Set<ThingTypeUID> SUPPORTED_GROUP_THING_TYPES_UIDS = Set.of(GROUP_HEATING_THING_TYPE,
GROUP_SWITCH_THING_TYPE);
public static final Set<ThingTypeUID> SUPPORTED_BRIDGE_THING_TYPES_UIDS = Collections
.unmodifiableSet(Stream.of(BRIDGE_THING_TYPE, PL546E_STANDALONE_THING_TYPE).collect(Collectors.toSet()));
public static final Set<ThingTypeUID> SUPPORTED_BRIDGE_THING_TYPES_UIDS = Set.of(BRIDGE_THING_TYPE,
PL546E_STANDALONE_THING_TYPE);
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet(Stream
.of(SUPPORTED_BUTTON_THING_TYPES_UIDS, SUPPORTED_HEATING_THING_TYPES, SUPPORTED_DEVICE_THING_TYPES_UIDS,

View File

@ -24,8 +24,9 @@ import javax.xml.bind.annotation.XmlElement;
*
* <ol>
* <li>Bit 0: HAN-FUN Gerät</li>
* <li>Bit 3: Button</li>
* <li>Bit 3: HAN-FUN Button - undocumented</li>
* <li>Bit 4: Alarm-Sensor</li>
* <li>Bit 5: AVM-Button</li>
* <li>Bit 6: Comet DECT, Heizkörperregler</li>
* <li>Bit 7: Energie Messgerät</li>
* <li>Bit 8: Temperatursensor</li>
@ -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

View File

@ -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<ButtonModel> buttons) {
Optional<ButtonModel> 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<ButtonModel> 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<ButtonModel> 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<ButtonModel> 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<ButtonModel> 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));
}
}

View File

@ -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

View File

@ -73,7 +73,34 @@
<state pattern="%s" readOnly="true"/>
</channel-type>
<!-- Channel definitions of specific FRITZ! devices -->
<!-- Channel Group definitions of specific FRITZ! devices -->
<channel-group-type id="button">
<label>Button</label>
<channels>
<channel id="press" typeId="system.rawbutton">
<label>Button Press</label>
<description>Triggeres PRESSED when a button was pressed.</description>
</channel>
<channel id="last_change" typeId="last_change"/>
</channels>
</channel-group-type>
<channel-group-type id="device">
<label>Device Data</label>
<channels>
<channel id="battery_level" typeId="system.battery-level"/>
<channel id="battery_low" typeId="system.low-battery"/>
</channels>
</channel-group-type>
<channel-group-type id="sensors">
<label>Sensor Data</label>
<channels>
<channel id="temperature" typeId="temperature"/>
</channels>
</channel-group-type>
<!-- Channel definitions of specific FRITZ! devices or Channel Groups -->
<channel-type id="temperature">
<item-type>Number:Temperature</item-type>
<label>Current Temperature</label>

View File

@ -16,8 +16,8 @@
<channels>
<channel id="press" typeId="system.button">
<label>Button press</label>
<description>Triggered SHORT_PRESSED or LONG_PRESSED when a button was pressed.</description>
<label>Button Press</label>
<description>Triggeres SHORT_PRESSED or LONG_PRESSED when a button was pressed.</description>
</channel>
<channel id="last_change" typeId="last_change"/>
<channel id="battery_level" typeId="system.battery-level"/>
@ -29,6 +29,37 @@
<config-description-ref uri="thing-type:avmfritz:fritzdevice"/>
</thing-type>
<thing-type id="FRITZ_DECT_440">
<supported-bridge-type-refs>
<bridge-type-ref id="fritzbox"/>
<bridge-type-ref id="FRITZ_Powerline_546E_Solo"/>
</supported-bridge-type-refs>
<label>FRITZ!DECT 440</label>
<description>FRITZ!DECT440 switch.</description>
<channel-groups>
<channel-group id="top-left" typeId="button">
<label>Top Left Button</label>
</channel-group>
<channel-group id="top-right" typeId="button">
<label>Top Right Button</label>
</channel-group>
<channel-group id="bottom-left" typeId="button">
<label>Bottom Left Button</label>
</channel-group>
<channel-group id="bottom-right" typeId="button">
<label>Bottom Right Button</label>
</channel-group>
<channel-group id="device" typeId="device"/>
<channel-group id="sensors" typeId="sensors"/>
</channel-groups>
<representation-property>ain</representation-property>
<config-description-ref uri="thing-type:avmfritz:fritzdevice"/>
</thing-type>
<thing-type id="Comet_DECT">
<supported-bridge-type-refs>
<bridge-type-ref id="fritzbox"/>
@ -236,7 +267,7 @@
<channels>
<channel id="press" typeId="system.rawbutton">
<label>Button Press</label>
<description>Triggered when a button was pressed.</description>
<description>Triggeres PRESSED when a button was pressed.</description>
</channel>
<channel typeId="last_change" id="last_change"/>
</channels>

View File

@ -44,7 +44,7 @@ public class AVMFritzDeviceListModelTest {
@BeforeEach
public void setUp() {
//@formatter:off
String xml =
final String xml =
"<devicelist version=\"1\">" +
"<group identifier=\"F0:A3:7F-900\" id=\"20000\" functionbitmask=\"6784\" fwversion=\"1.0\" manufacturer=\"AVM\" productname=\"\"><present>1</present><name>Schlafzimmer</name><switch><state>1</state><mode>manuell</mode><lock>0</lock><devicelock>0</devicelock></switch><powermeter><voltage>230051</voltage><power>0</power><energy>2087</energy></powermeter><groupinfo><masterdeviceid>17</masterdeviceid><members>17,18</members></groupinfo></group>" +
"<group identifier=\"F0:A3:7F-901\" id=\"20001\" functionbitmask=\"4160\" fwversion=\"1.0\" manufacturer=\"AVM\" productname=\"\"><present>1</present><name>Schlafzimmer</name><temperature><celsius>220</celsius><offset>-10</offset></temperature><hkr><tist>44</tist><tsoll>42</tsoll><absenk>28</absenk><komfort>42</komfort><lock>1</lock><devicelock>1</devicelock><errorcode>0</errorcode><windowopenactiv>0</windowopenactiv><windowopenactiveendtime>0</windowopenactiveendtime><boostactive>0</boostactive><boostactiveendtime>0</boostactiveendtime><batterylow>0</batterylow><battery>100</battery><nextchange><endperiod>1484341200</endperiod><tchange>28</tchange></nextchange></hkr><groupinfo><masterdeviceid>0</masterdeviceid><members>20,21,22</members></groupinfo></group>" +
@ -58,9 +58,9 @@ public class AVMFritzDeviceListModelTest {
"<device identifier=\"11934 0059978-1\" id=\"2000\" functionbitmask=\"8208\" fwversion=\"0.0\" manufacturer=\"0x0feb\" productname=\"HAN-FUN\"><present>0</present><name>HAN-FUN #2: Unit #2</name><etsiunitinfo><etsideviceid>406</etsideviceid><unittype>514</unittype><interfaces>256</interfaces></etsiunitinfo><alert><state>1</state></alert></device>" +
"<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=\"288\" fwversion=\"04.90\" manufacturer=\"AVM\" productname=\"FRITZ!DECT 440\"><present>1</present><name>FRITZ!DECT 440 #15</name><temperature><celsius>230</celsius><offset>0</offset></temperature><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>" +
"</devicelist>";
//@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<AVMFritzBaseModel> 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<AVMFritzBaseModel> optionalDevice = findModel("FRITZ!Powerline 546E");

View File

@ -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));