Skip to content

Commit

Permalink
[avmfritz] Added support for DECT500 and HAN-FUN bulbs (openhab#11348)
Browse files Browse the repository at this point in the history
* Added support for DECT500 and HAN-FUN bulbs

Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>

* Incorporated comment from review

Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
  • Loading branch information
cweitkamp committed Oct 16, 2021
1 parent 080f696 commit 87125a2
Show file tree
Hide file tree
Showing 17 changed files with 294 additions and 61 deletions.
6 changes: 5 additions & 1 deletion bundles/org.openhab.binding.avmfritz/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ The FRITZ!DECT 400 supports a configurable button to trigger short or long press
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))

### FRITZ!DECT 500

The [FRITZ!DECT 500](https://avm.de/produkte/fritzdect/fritzdect-500/) is a dimmable colorized light bulb.

#### Supported Channel Groups

| Channel Group ID | Description | Available on thing |
Expand Down Expand Up @@ -178,7 +182,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 |
| on_off | Switch | Switchable device (ON/OFF) | FRITZ!DECT 500, 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 |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
*/
package org.openhab.binding.avmfritz.internal;

import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand Down Expand Up @@ -41,6 +40,7 @@ public class AVMFritzBindingConstants {
public static final String POWERLINE_MODEL_NAME = "FRITZ!Powerline";

// List of main device types
public static final String DEVICE_DECT500 = "FRITZ_DECT_500";
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";
Expand All @@ -62,6 +62,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 DECT500_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_DECT500);
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);
Expand Down Expand Up @@ -132,6 +133,8 @@ public class AVMFritzBindingConstants {
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";
public static final String CHANNEL_COLOR = "color";
public static final String CHANNEL_BRIGHTNESS = "brightness";

// List of all Channel config ids
public static final String CONFIG_CHANNEL_TEMP_OFFSET = "offset";
Expand Down Expand Up @@ -164,6 +167,8 @@ 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_LIGHTING_THING_TYPES = Set.of(DECT500_THING_TYPE);

public static final Set<ThingTypeUID> SUPPORTED_BUTTON_THING_TYPES_UIDS = Set.of(DECT400_THING_TYPE,
DECT440_THING_TYPE, HAN_FUN_SWITCH_THING_TYPE);

Expand All @@ -180,8 +185,8 @@ public class AVMFritzBindingConstants {
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,
SUPPORTED_GROUP_THING_TYPES_UIDS, SUPPORTED_BRIDGE_THING_TYPES_UIDS)
.flatMap(Set::stream).collect(Collectors.toSet()));
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Stream.of(SUPPORTED_LIGHTING_THING_TYPES,
SUPPORTED_BUTTON_THING_TYPES_UIDS, SUPPORTED_HEATING_THING_TYPES, SUPPORTED_DEVICE_THING_TYPES_UIDS,
SUPPORTED_GROUP_THING_TYPES_UIDS, SUPPORTED_BRIDGE_THING_TYPES_UIDS).flatMap(Set::stream)
.collect(Collectors.toUnmodifiableSet());
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.avmfritz.internal.handler.AVMFritzButtonHandler;
import org.openhab.binding.avmfritz.internal.handler.AVMFritzColorLightDeviceHandler;
import org.openhab.binding.avmfritz.internal.handler.AVMFritzHeatingDeviceHandler;
import org.openhab.binding.avmfritz.internal.handler.AVMFritzHeatingGroupHandler;
import org.openhab.binding.avmfritz.internal.handler.BoxHandler;
Expand Down Expand Up @@ -76,6 +77,8 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return new BoxHandler((Bridge) thing, httpClient, commandDescriptionProvider);
} else if (PL546E_STANDALONE_THING_TYPE.equals(thingTypeUID)) {
return new Powerline546EHandler((Bridge) thing, httpClient, commandDescriptionProvider);
} else if (SUPPORTED_LIGHTING_THING_TYPES.contains(thingTypeUID)) {
return new AVMFritzColorLightDeviceHandler(thing);
} else if (SUPPORTED_BUTTON_THING_TYPES_UIDS.contains(thingTypeUID)) {
return new AVMFritzButtonHandler(thing);
} else if (SUPPORTED_HEATING_THING_TYPES.contains(thingTypeUID)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import static org.openhab.binding.avmfritz.internal.AVMFritzBindingConstants.*;
import static org.openhab.core.thing.Thing.*;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -56,12 +55,10 @@ public class AVMFritzDiscoveryService extends AbstractDiscoveryService
private @NonNullByDefault({}) AVMFritzBaseBridgeHandler bridgeHandler;

public AVMFritzDiscoveryService() {
super(Collections
.unmodifiableSet(Stream
.of(SUPPORTED_BUTTON_THING_TYPES_UIDS, SUPPORTED_HEATING_THING_TYPES,
SUPPORTED_DEVICE_THING_TYPES_UIDS, SUPPORTED_GROUP_THING_TYPES_UIDS)
.flatMap(Set::stream).collect(Collectors.toSet())),
30);
super(Stream
.of(SUPPORTED_LIGHTING_THING_TYPES, SUPPORTED_BUTTON_THING_TYPES_UIDS, SUPPORTED_HEATING_THING_TYPES,
SUPPORTED_DEVICE_THING_TYPES_UIDS, SUPPORTED_GROUP_THING_TYPES_UIDS)
.flatMap(Set::stream).collect(Collectors.toUnmodifiableSet()), 30);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
*
* <ol>
* <li>Bit 0: HAN-FUN Gerät</li>
* <li>Bit 2: Licht/Lampe</li>
* <li>Bit 3: HAN-FUN Button - undocumented</li>
* <li>Bit 4: Alarm-Sensor</li>
* <li>Bit 5: AVM-Button</li>
Expand All @@ -37,6 +38,8 @@
* <li>Bit 11: Mikrofon</li>
* <li>Bit 13: HAN-FUN Unit</li>
* <li>Bit 15: an-/ausschaltbares Gerät / Steckdose / Lampe / Aktor</li>
* <li>Bit 16: Gerät mit einstellbarem Dimm-, Höhen- bzw. Niveau-Level</li>
* <li>Bit 17: Lampe mit einstellbarer Farbe/Farbtemperatur</li>
* <li>Bit 18: Rollladen - hoch, runter, stop und level 0% bis 100 %</li>
* </ol>
*
Expand All @@ -47,6 +50,7 @@
*/
public abstract class AVMFritzBaseModel implements BatteryModel {
protected static final int HAN_FUN_DEVICE_BIT = 1; // Bit 0
protected static final int LIGHT_BIT = 1 << 2; // Bit 2
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
Expand All @@ -58,6 +62,8 @@ public abstract class AVMFritzBaseModel implements BatteryModel {
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 DIMMABLE_LIGHT_BIT = 1 << 16; // Bit 16
protected static final int COLOR_LIGHT_BIT = 1 << 17; // Bit 17
protected static final int HAN_FUN_BLINDS_BIT = 1 << 18; // Bit 18
protected static final int HUMIDITY_SENSOR_BIT = 1 << 20; // Bit 20 - undocumented

Expand Down Expand Up @@ -195,6 +201,14 @@ public boolean isHANFUNOnOff() {
return (bitmask / HAN_FUN_ON_OFF_BIT) > 0;
}

public boolean isDimmableLight() {
return (bitmask & DIMMABLE_LIGHT_BIT) > 0;
}

public boolean isColorLight() {
return (bitmask & COLOR_LIGHT_BIT) > 0;
}

public boolean isHANFUNBlinds() {
return (bitmask & HAN_FUN_BLINDS_BIT) > 0;
}
Expand Down Expand Up @@ -239,7 +253,8 @@ public String toString() {
.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(isHANFUNOnOff()).append(",isDimmableLight=").append(isDimmableLight()).append(",isColorLight=")
.append(isColorLight()).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=")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* 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.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

/**
* See {@link DeviceListModel}.
*
* @author Joshua Bacher - Initial contribution
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "colorcontrol")
public class ColorControlModel {

@XmlAttribute(name = "supported_modes")
public int supportedModes;
@XmlAttribute(name = "current_mode")
public int currentMode;
public int hue;
public int saturation;
public int temperature;

@Override
public String toString() {
return new StringBuilder("[supportedModes=").append(supportedModes).append(",currentMode=").append(currentMode)
.append(",hue=").append(hue).append(",saturation=").append(saturation).append(",temperature=")
.append(temperature).append("]").toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@ public class DeviceModel extends AVMFritzBaseModel {
private TemperatureModel temperature;
private HumidityModel humidity;
private AlertModel alert;
private LevelcontrolModel levelcontrol;

@XmlElement(name = "levelcontrol")
private LevelControlModel levelControlModel;

@XmlElement(name = "colorcontrol")
private ColorControlModel colorControlModel;

@XmlElement(name = "button", type = ButtonModel.class)
private List<ButtonModel> buttons;
Expand Down Expand Up @@ -64,12 +69,20 @@ public void setAlert(AlertModel alertModel) {
this.alert = alertModel;
}

public LevelcontrolModel getLevelcontrol() {
return levelcontrol;
public LevelControlModel getLevelControlModel() {
return levelControlModel;
}

public void setLevelControlModel(LevelControlModel levelControlModel) {
this.levelControlModel = levelControlModel;
}

public ColorControlModel getColorControlModel() {
return colorControlModel;
}

public void setLevelcontrol(LevelcontrolModel levelcontrol) {
this.levelcontrol = levelcontrol;
public void setColorControlModel(ColorControlModel colorControlModel) {
this.colorControlModel = colorControlModel;
}

public List<ButtonModel> getButtons() {
Expand All @@ -91,7 +104,8 @@ public void setEtsiunitinfo(ETSUnitInfoModel etsiunitinfo) {
@Override
public String toString() {
return new StringBuilder(super.toString()).append(temperature).append(",").append(humidity).append(",")
.append(alert).append(",").append(getButtons()).append(",").append(etsiunitinfo).append("]").toString();
.append(alert).append(",").append(levelControlModel).append(",").append(colorControlModel).append(",")
.append(getButtons()).append(",").append(etsiunitinfo).append("]").toString();
}

@XmlAccessorType(XmlAccessType.FIELD)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "levelcontrol")
public class LevelcontrolModel {
public class LevelControlModel {

@XmlElement(name = "level")
private BigDecimal level;
Expand All @@ -52,7 +52,7 @@ public void setLevelPercentage(BigDecimal levelPercentage) {

@Override
public String toString() {
return new StringBuilder().append("[level=").append(getLevel()).append(",levelpercentage=")
.append(getLevelPercentage()).append("]").toString();
return new StringBuilder("[level=").append(getLevel()).append(",levelpercentage=").append(getLevelPercentage())
.append("]").toString();
}
}
Loading

0 comments on commit 87125a2

Please sign in to comment.