mirror of
https://github.com/danieldemus/openhab-addons
synced 2026-07-29 12:34:21 +02:00
[avmfritz] Add support for groups of blinds (#19513)
* Added support for groups of blinds Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
This commit is contained in:
@@ -113,10 +113,11 @@ The FRITZ!Box has to run at least on firmware FRITZ!OS 7.
|
||||
|
||||
### FRITZ! Groups
|
||||
|
||||
The FRITZ!OS supports two different types of groups.
|
||||
On the one hand there are groups for heating thermostats on the other hand there are groups for switchable outlets and power meters.
|
||||
The FRITZ!OS supports three different types of groups.
|
||||
On the one hand there are groups for heating thermostats on the other hand there are groups for switchable outlets and power meters, a third group supports control of roller shutters and blinds.
|
||||
The first one provides the same channels and actions like the [FRITZ!DECT 302 / FRITZ!DECT 301 / FRITZ!DECT 300 / Comet DECT](https://www.openhab.org/addons/bindings/avmfritz/#fritz-dect-302-fritz-dect-301-fritz-dect-300-comet-dect) devices.
|
||||
The latter provides the same channels like the [FRITZ!DECT 200 / FRITZ!DECT 210](https://www.openhab.org/addons/bindings/avmfritz/#fritz-dect-200-fritz-dect-210) / [FRITZ!Powerline 546E](https://www.openhab.org/addons/bindings/avmfritz/#fritz-powerline-546e) devices.
|
||||
A blind group provides the `rollershutter` channel similar to a `HAN_FUN_BLINDS` thing (e.g. [Becker BoxCTRL](https://becker-antriebe.shop/)).
|
||||
The FRITZ!Box has to run at least on firmware FRITZ!OS 6.69.
|
||||
|
||||
## Discovery
|
||||
|
||||
+4
-2
@@ -66,6 +66,7 @@ public class AVMFritzBindingConstants {
|
||||
public static final String DEVICE_SMART_ENERGY_250 = "FRITZ_Smart_Energy_250";
|
||||
|
||||
// List of main group types
|
||||
public static final String GROUP_BLINDS = "FRITZ_GROUP_BLINDS";
|
||||
public static final String GROUP_HEATING = "FRITZ_GROUP_HEATING";
|
||||
public static final String GROUP_SWITCH = "FRITZ_GROUP_SWITCH";
|
||||
|
||||
@@ -92,6 +93,7 @@ public class AVMFritzBindingConstants {
|
||||
DEVICE_HAN_FUN_COLOR_BULB);
|
||||
public static final ThingTypeUID HAN_FUN_DIMMABLE_BULB_THING_TYPE = new ThingTypeUID(BINDING_ID,
|
||||
DEVICE_HAN_FUN_DIMMABLE_BULB);
|
||||
public static final ThingTypeUID GROUP_BLINDS_THING_TYPE = new ThingTypeUID(BINDING_ID, GROUP_BLINDS);
|
||||
public static final ThingTypeUID GROUP_HEATING_THING_TYPE = new ThingTypeUID(BINDING_ID, GROUP_HEATING);
|
||||
public static final ThingTypeUID GROUP_SWITCH_THING_TYPE = new ThingTypeUID(BINDING_ID, GROUP_SWITCH);
|
||||
public static final ThingTypeUID HAN_FUN_SENSOR_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_HAN_FUN_SENSOR);
|
||||
@@ -208,8 +210,8 @@ public class AVMFritzBindingConstants {
|
||||
POWERLINE546E_THING_TYPE, HAN_FUN_CONTACT_THING_TYPE, HAN_FUN_ON_OFF_THING_TYPE, HAN_FUN_BLINDS_THING_TYPE,
|
||||
HAN_FUN_SENSOR_THING_TYPE, HAN_FUN_HOST_THING_TYPE, SMART_ENERGY_250_THING_TYPE);
|
||||
|
||||
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_GROUP_THING_TYPES_UIDS = Set.of(GROUP_BLINDS_THING_TYPE,
|
||||
GROUP_HEATING_THING_TYPE, GROUP_SWITCH_THING_TYPE);
|
||||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_BRIDGE_THING_TYPES_UIDS = Set.of(BRIDGE_THING_TYPE,
|
||||
POWERLINE546E_STANDALONE_THING_TYPE);
|
||||
|
||||
+17
-5
@@ -111,6 +111,17 @@ public abstract class AVMFritzBaseModel implements BatteryModel {
|
||||
@XmlElement(name = "hkr")
|
||||
private HeatingModel heatingModel;
|
||||
|
||||
@XmlElement(name = "levelcontrol")
|
||||
private @Nullable LevelControlModel levelControlModel;
|
||||
|
||||
public SwitchModel getSwitch() {
|
||||
return switchModel;
|
||||
}
|
||||
|
||||
public void setSwitch(SwitchModel switchModel) {
|
||||
this.switchModel = switchModel;
|
||||
}
|
||||
|
||||
public @Nullable SimpleOnOffModel getSimpleOnOffUnit() {
|
||||
return simpleOnOffUnit;
|
||||
}
|
||||
@@ -131,12 +142,12 @@ public abstract class AVMFritzBaseModel implements BatteryModel {
|
||||
this.heatingModel = heatingModel;
|
||||
}
|
||||
|
||||
public SwitchModel getSwitch() {
|
||||
return switchModel;
|
||||
public @Nullable LevelControlModel getLevelControlModel() {
|
||||
return levelControlModel;
|
||||
}
|
||||
|
||||
public void setSwitch(SwitchModel switchModel) {
|
||||
this.switchModel = switchModel;
|
||||
public void setLevelcontrol(LevelControlModel levelControlModel) {
|
||||
this.levelControlModel = levelControlModel;
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
@@ -265,7 +276,8 @@ public abstract class AVMFritzBaseModel implements BatteryModel {
|
||||
.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();
|
||||
.append(",").append(getPowerMeter()).append(",").append(getHkr()).append(",").append(levelControlModel)
|
||||
.append(",").toString();
|
||||
}
|
||||
|
||||
public transient boolean isLinked;
|
||||
|
||||
+2
-13
@@ -34,9 +34,6 @@ public class DeviceModel extends AVMFritzBaseModel {
|
||||
private HumidityModel humidity;
|
||||
private AlertModel alert;
|
||||
|
||||
@XmlElement(name = "levelcontrol")
|
||||
private LevelControlModel levelControlModel;
|
||||
|
||||
@XmlElement(name = "colorcontrol")
|
||||
private ColorControlModel colorControlModel;
|
||||
|
||||
@@ -69,14 +66,6 @@ public class DeviceModel extends AVMFritzBaseModel {
|
||||
this.alert = alertModel;
|
||||
}
|
||||
|
||||
public LevelControlModel getLevelControlModel() {
|
||||
return levelControlModel;
|
||||
}
|
||||
|
||||
public void setLevelControlModel(LevelControlModel levelControlModel) {
|
||||
this.levelControlModel = levelControlModel;
|
||||
}
|
||||
|
||||
public ColorControlModel getColorControlModel() {
|
||||
return colorControlModel;
|
||||
}
|
||||
@@ -104,8 +93,8 @@ public class DeviceModel extends AVMFritzBaseModel {
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder(super.toString()).append(temperature).append(",").append(humidity).append(",")
|
||||
.append(alert).append(",").append(levelControlModel).append(",").append(colorControlModel).append(",")
|
||||
.append(getButtons()).append(",").append(etsiunitinfo).append("]").toString();
|
||||
.append(alert).append(",").append(colorControlModel).append(",").append(getButtons()).append(",")
|
||||
.append(etsiunitinfo).append("]").toString();
|
||||
}
|
||||
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
|
||||
+3
-1
@@ -323,7 +323,9 @@ public abstract class AVMFritzBaseBridgeHandler extends BaseBridgeHandler {
|
||||
*/
|
||||
public String getThingTypeId(AVMFritzBaseModel device) {
|
||||
if (device instanceof GroupModel) {
|
||||
if (device.isHeatingThermostat()) {
|
||||
if (device.isHANFUNBlinds()) {
|
||||
return GROUP_BLINDS;
|
||||
} else if (device.isHeatingThermostat()) {
|
||||
return GROUP_HEATING;
|
||||
} else if (device.isSwitchableOutlet()) {
|
||||
return GROUP_SWITCH;
|
||||
|
||||
+5
-4
@@ -145,6 +145,9 @@ public abstract class AVMFritzBaseThingHandler extends BaseThingHandler implemen
|
||||
if (device.isHeatingThermostat()) {
|
||||
updateHeatingThermostat(device.getHkr());
|
||||
}
|
||||
if (device.isHANFUNBlinds()) {
|
||||
updateLevelControl(device.getLevelControlModel());
|
||||
}
|
||||
if (device instanceof DeviceModel deviceModel) {
|
||||
if (deviceModel.isTemperatureSensor()) {
|
||||
updateTemperatureSensor(deviceModel.getTemperature());
|
||||
@@ -159,9 +162,7 @@ public abstract class AVMFritzBaseThingHandler extends BaseThingHandler implemen
|
||||
updateHANFUNAlarmSensor(deviceModel.getAlert());
|
||||
}
|
||||
}
|
||||
if (deviceModel.isHANFUNBlinds()) {
|
||||
updateLevelControl(deviceModel.getLevelControlModel());
|
||||
} else if (deviceModel.isColorLight()) {
|
||||
if (deviceModel.isColorLight()) {
|
||||
updateColorLight(deviceModel.getColorControlModel(), deviceModel.getLevelControlModel(),
|
||||
deviceModel.getSimpleOnOffUnit());
|
||||
} else if (deviceModel.isDimmableLight() && !deviceModel.isHANFUNBlinds()) {
|
||||
@@ -473,7 +474,7 @@ public abstract class AVMFritzBaseThingHandler extends BaseThingHandler implemen
|
||||
} else if (command instanceof OnOffType) {
|
||||
fritzBox.setSwitch(ain, OnOffType.ON.equals(command));
|
||||
} else if (command instanceof IncreaseDecreaseType) {
|
||||
brightness = ((DeviceModel) currentDevice).getLevelControlModel().getLevelPercentage();
|
||||
brightness = currentDevice.getLevelControlModel().getLevelPercentage();
|
||||
if (IncreaseDecreaseType.INCREASE.equals(command)) {
|
||||
brightness.add(BigDecimal.TEN);
|
||||
} else {
|
||||
|
||||
+2
@@ -47,6 +47,8 @@ thing-type.avmfritz.FRITZ_DECT_500.label = FRITZ!DECT 500
|
||||
thing-type.avmfritz.FRITZ_DECT_500.description = FRITZ!DECT500 color light.
|
||||
thing-type.avmfritz.FRITZ_DECT_Repeater_100.label = FRITZ!DECT Repeater 100
|
||||
thing-type.avmfritz.FRITZ_DECT_Repeater_100.description = FRITZ!DECT Repeater 100 DECT repeater.
|
||||
thing-type.avmfritz.FRITZ_GROUP_BLINDS.label = Blinds Group
|
||||
thing-type.avmfritz.FRITZ_GROUP_BLINDS.description = Group for blinds.
|
||||
thing-type.avmfritz.FRITZ_GROUP_HEATING.label = Heating Group
|
||||
thing-type.avmfritz.FRITZ_GROUP_HEATING.description = Group for heating thermostats.
|
||||
thing-type.avmfritz.FRITZ_GROUP_HEATING.channel.actual_temp.label = Current Temperature
|
||||
|
||||
@@ -489,6 +489,24 @@
|
||||
</thing-type>
|
||||
|
||||
<!-- Supported FRITZ! groups and features -->
|
||||
<thing-type id="FRITZ_GROUP_BLINDS">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="fritzbox"/>
|
||||
<bridge-type-ref id="FRITZ_Powerline_546E_Solo"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Blinds Group</label>
|
||||
<description>Group for blinds.</description>
|
||||
<semantic-equipment-tag>Blinds</semantic-equipment-tag>
|
||||
<channels>
|
||||
<channel id="rollershutter" typeId="rollershutter"/>
|
||||
</channels>
|
||||
|
||||
<representation-property>ain</representation-property>
|
||||
|
||||
<config-description-ref uri="thing-type:avmfritz:fritzgroup"/>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="FRITZ_GROUP_HEATING">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="fritzbox"/>
|
||||
|
||||
+45
-1
@@ -61,6 +61,7 @@ public class AVMFritzDeviceListModelTest {
|
||||
final String xml =
|
||||
"""
|
||||
<devicelist version="1">\
|
||||
<group synchronized="0" identifier="grpdb3190-4195D62D5" id="901" functionbitmask="331776" fwversion="1.0" manufacturer="AVM" productname=""><present>1</present><txbusy>0</txbusy><name>Schlafzimmer</name><blind><endpositionsset>1</endpositionsset><mode>manuell</mode></blind><levelcontrol><level>0</level><levelpercentage>0</levelpercentage></levelcontrol><groupinfo><masterdeviceid>0</masterdeviceid><members>2003,2004,2005</members></groupinfo></group>\
|
||||
<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>\
|
||||
<device identifier="08761 0000434" id="17" functionbitmask="35712" fwversion="03.83" manufacturer="AVM" productname="FRITZ!DECT 200"><present>1</present><name>FRITZ!DECT 200 #1</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><temperature><celsius>255</celsius><offset>0</offset></temperature></device>\
|
||||
@@ -166,7 +167,7 @@ public class AVMFritzDeviceListModelTest {
|
||||
@Test
|
||||
public void validateDeviceListModel() {
|
||||
assertNotNull(devices);
|
||||
assertEquals(19, devices.getDevicelist().size());
|
||||
assertEquals(20, devices.getDevicelist().size());
|
||||
assertEquals("1", devices.getXmlApiVersion());
|
||||
}
|
||||
|
||||
@@ -916,6 +917,49 @@ public class AVMFritzDeviceListModelTest {
|
||||
assertNull(device.getLevelControlModel());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateBlindsGroupModel() {
|
||||
Optional<AVMFritzBaseModel> optionalGroup = findModelByIdentifier("grpdb3190-4195D62D5");
|
||||
assertTrue(optionalGroup.isPresent());
|
||||
assertTrue(optionalGroup.get() instanceof GroupModel);
|
||||
|
||||
GroupModel group = (GroupModel) optionalGroup.get();
|
||||
assertEquals("", group.getProductName());
|
||||
assertEquals("grpdb3190-4195D62D5", group.getIdentifier());
|
||||
assertEquals("901", group.getDeviceId());
|
||||
assertEquals("1.0", group.getFirmwareVersion());
|
||||
assertEquals("AVM", group.getManufacturer());
|
||||
|
||||
assertEquals(1, group.getPresent());
|
||||
assertEquals("Schlafzimmer", group.getName());
|
||||
|
||||
assertFalse(group.isButton());
|
||||
assertFalse(group.isHANFUNButton());
|
||||
assertFalse(group.isHANFUNAlarmSensor());
|
||||
assertFalse(group.isDectRepeater());
|
||||
assertFalse(group.isSwitchableOutlet());
|
||||
assertFalse(group.isTemperatureSensor());
|
||||
assertFalse(group.isHumiditySensor());
|
||||
assertFalse(group.isPowerMeter());
|
||||
assertFalse(group.isHeatingThermostat());
|
||||
assertTrue(group.isHANFUNBlinds());
|
||||
|
||||
assertNull(group.getSwitch());
|
||||
|
||||
assertNull(group.getPowerMeter());
|
||||
|
||||
assertNull(group.getHkr());
|
||||
|
||||
LevelControlModel levelcontrol = group.getLevelControlModel();
|
||||
assertNotNull(levelcontrol);
|
||||
assertEquals(BigDecimal.valueOf(0L), levelcontrol.getLevel());
|
||||
assertEquals(BigDecimal.valueOf(0L), levelcontrol.getLevelPercentage());
|
||||
|
||||
assertNotNull(group.getGroupinfo());
|
||||
assertEquals("0", group.getGroupinfo().getMasterdeviceid());
|
||||
assertEquals("2003,2004,2005", group.getGroupinfo().getMembers());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateHeatingGroupModel() {
|
||||
Optional<AVMFritzBaseModel> optionalGroup = findModelByIdentifier("F0:A3:7F-901");
|
||||
|
||||
+2
-1
@@ -95,7 +95,7 @@ public class AVMFritzDiscoveryServiceOSGiTest extends AVMFritzThingHandlerOSGiTe
|
||||
|
||||
@Test
|
||||
public void correctSupportedTypes() {
|
||||
assertEquals(22, discovery.getSupportedThingTypes().size());
|
||||
assertEquals(23, discovery.getSupportedThingTypes().size());
|
||||
assertTrue(discovery.getSupportedThingTypes().contains(DECT100_THING_TYPE));
|
||||
assertTrue(discovery.getSupportedThingTypes().contains(DECT200_THING_TYPE));
|
||||
assertTrue(discovery.getSupportedThingTypes().contains(DECT210_THING_TYPE));
|
||||
@@ -115,6 +115,7 @@ public class AVMFritzDiscoveryServiceOSGiTest extends AVMFritzThingHandlerOSGiTe
|
||||
assertTrue(discovery.getSupportedThingTypes().contains(HAN_FUN_DIMMABLE_BULB_THING_TYPE));
|
||||
assertTrue(discovery.getSupportedThingTypes().contains(HAN_FUN_SENSOR_THING_TYPE));
|
||||
assertTrue(discovery.getSupportedThingTypes().contains(HAN_FUN_HOST_THING_TYPE));
|
||||
assertTrue(discovery.getSupportedThingTypes().contains(GROUP_BLINDS_THING_TYPE));
|
||||
assertTrue(discovery.getSupportedThingTypes().contains(GROUP_HEATING_THING_TYPE));
|
||||
assertTrue(discovery.getSupportedThingTypes().contains(GROUP_SWITCH_THING_TYPE));
|
||||
assertTrue(discovery.getSupportedThingTypes().contains(SMART_ENERGY_250_THING_TYPE));
|
||||
|
||||
Reference in New Issue
Block a user