[homekit] add support for number and dimmer item type to window covering accessory (#10051)

Signed-off-by: Eugen Freiter <freiter@gmx.de>
This commit is contained in:
eugen 2021-02-04 21:09:19 +01:00 committed by GitHub
parent da387618fd
commit 0d13b8d1ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 13 deletions

View File

@ -129,7 +129,9 @@ A HomeKit accessory has mandatory and optional characteristics (listed below in
The mapping between openHAB items and HomeKit accessory and characteristics is done by means of [metadata](https://www.openhab.org/docs/concepts/items.html#item-metadata) The mapping between openHAB items and HomeKit accessory and characteristics is done by means of [metadata](https://www.openhab.org/docs/concepts/items.html#item-metadata)
### UI based Configuration ### UI based Configuration
In order to add metadata to an item: In order to add metadata to an item:
- select desired item in mainUI - select desired item in mainUI
- click on "Add Metadata" - click on "Add Metadata"
@ -151,6 +153,7 @@ In order to add metadata to an item:
### Textual configuration ### Textual configuration
```xtend ```xtend
Switch leaksensor_metadata "Leak Sensor" {homekit="LeakSensor"} Switch leaksensor_metadata "Leak Sensor" {homekit="LeakSensor"}
``` ```
@ -283,7 +286,19 @@ Rollershutter window_covering "Blind" (gBlind)
Dimmer window_covering_htilt "Blind horizontal tilt" (gBlind) {homekit = "WindowCovering.CurrentHorizontalTiltAngle, WindowCovering.TargetHorizontalTiltAngle"} Dimmer window_covering_htilt "Blind horizontal tilt" (gBlind) {homekit = "WindowCovering.CurrentHorizontalTiltAngle, WindowCovering.TargetHorizontalTiltAngle"}
Dimmer window_covering_vtilt "Blind vertical tilt" (gBlind) {homekit = "WindowCovering.CurrentVerticalTiltAngle, WindowCovering.TargetVerticalTiltAngle"} Dimmer window_covering_vtilt "Blind vertical tilt" (gBlind) {homekit = "WindowCovering.CurrentVerticalTiltAngle, WindowCovering.TargetVerticalTiltAngle"}
``` ```
Current and Target Position characteristics can be linked to Rollershutter but also to Number or Dimmer item types.
e.g.
```xtend
Group gBlind "Blinds" {homekit = "WindowCovering"}
Dimmer blind_current_position (gBlind) {homekit = "CurrentPosition"}
Number blind_target_position (gBlind) {homekit = "TargetPosition"}
String blind_position (gBlind) {homekit = "PositionState"}
```
### Thermostat ### Thermostat
A HomeKit thermostat has following mandatory characteristics: A HomeKit thermostat has following mandatory characteristics:
- CurrentTemperature - CurrentTemperature
@ -319,6 +334,7 @@ Number thermostat_heat_thrs "Thermostat Heat Threshold Temp [%.1f C]"
Current and target temperatures have default min and max values. Any values below or above max limits will be replaced with min or max limits. Current and target temperatures have default min and max values. Any values below or above max limits will be replaced with min or max limits.
Default limits are: Default limits are:
- current temperature: min value = 0 C, max value = 100 C - current temperature: min value = 0 C, max value = 100 C
- target temperature: min value = 10 C, max value = 38 C - target temperature: min value = 10 C, max value = 38 C
@ -526,23 +542,23 @@ Switch motionsensor_tampered "Motion Sensor Tampered"
| | | TamperedStatus | Switch, Contact | Tampered status | | | | TamperedStatus | Switch, Contact | Tampered status |
| | | BatteryLowStatus | Switch, Contact | Battery status | | | | BatteryLowStatus | Switch, Contact | Battery status |
| Door | | | | Motorized door. One Rollershutter item covers all mandatory characteristics. see examples below. | | Door | | | | Motorized door. One Rollershutter item covers all mandatory characteristics. see examples below. |
| | CurrentPosition | | Rollershutter | Current position of motorized door | | | CurrentPosition | | Rollershutter, Dimmer, Number | Current position of motorized door |
| | TargetPosition | | Rollershutter | Target position of motorized door | | | TargetPosition | | Rollershutter, Dimmer, Number | Target position of motorized door |
| | PositionState | | Rollershutter | Position state. Supported states: DECREASING, INCREASING, STOPPED. Mapping can be redefined at item level, e.g. [DECREASING="Down", INCREASING="Up"]. If no state provided, "STOPPED" is used. | | | PositionState | | Rollershutter, String | Position state. Supported states: DECREASING, INCREASING, STOPPED. Mapping can be redefined at item level, e.g. [DECREASING="Down", INCREASING="Up"]. If no state provided, "STOPPED" is used. |
| | | Name | String | Name of the motorized door | | | | Name | String | Name of the motorized door |
| | | HoldPosition | Switch | Motorized door should stop at its current position. A value of ON must hold the state of the accessory. A value of OFF should be ignored. | | | | HoldPosition | Switch | Motorized door should stop at its current position. A value of ON must hold the state of the accessory. A value of OFF should be ignored. |
| | | ObstructionStatus | Switch, Contact | Current status of obstruction sensor. ON-obstruction detected, OFF - no obstruction | | | | ObstructionStatus | Switch, Contact | Current status of obstruction sensor. ON-obstruction detected, OFF - no obstruction |
| Window | | | | Motorized window. One Rollershutter item covers all mandatory characteristics. see examples below. | | Window | | | | Motorized window. One Rollershutter item covers all mandatory characteristics. see examples below. |
| | CurrentPosition | | Rollershutter | Current position of motorized window | | | CurrentPosition | | Rollershutter, Dimmer, Number | Current position of motorized window |
| | TargetPosition | | Rollershutter | Target position of motorized window | | | TargetPosition | | Rollershutter, Dimmer, Number | Target position of motorized window |
| | PositionState | | Rollershutter | Position state. Supported states: DECREASING, INCREASING, STOPPED. Mapping can be redefined at item level, e.g. [DECREASING="Down", INCREASING="Up"]. If no state provided, "STOPPED" is used. | | | PositionState | | Rollershutter, String | Position state. Supported states: DECREASING, INCREASING, STOPPED. Mapping can be redefined at item level, e.g. [DECREASING="Down", INCREASING="Up"]. If no state provided, "STOPPED" is used. |
| | | Name | String | Name of the motorized window | | | | Name | String | Name of the motorized window |
| | | HoldPosition | Switch | Motorized door should stop at its current position. A value of ON must hold the state of the accessory. A value of OFF should be ignored. | | | | HoldPosition | Switch | Motorized door should stop at its current position. A value of ON must hold the state of the accessory. A value of OFF should be ignored. |
| | | ObstructionStatus | Switch, Contact | Current status of obstruction sensor. ON-obstruction detected, OFF - no obstruction | | | | ObstructionStatus | Switch, Contact | Current status of obstruction sensor. ON-obstruction detected, OFF - no obstruction |
| WindowCovering | | | | Window covering / blinds. One Rollershutter item covers all mandatory characteristics. see examples below. | | WindowCovering | | | | Window covering / blinds. One Rollershutter item covers all mandatory characteristics. see examples below. |
| | CurrentPosition | | Rollershutter | Current position of window covering | | | CurrentPosition | | Rollershutter, Dimmer, Number | Current position of window covering |
| | TargetPosition | | Rollershutter | Target position of window covering | | | TargetPosition | | Rollershutter, Dimmer, Number | Target position of window covering |
| | PositionState | | Rollershutter | current only "STOPPED" is supported. | | | PositionState | | Rollershutter, String | current only "STOPPED" is supported. |
| | | Name | String | Name of the windows covering | | | | Name | String | Name of the windows covering |
| | | HoldPosition | Switch | Window covering should stop at its current position. A value of ON must hold the state of the accessory. A value of OFF should be ignored. | | | | HoldPosition | Switch | Window covering should stop at its current position. A value of ON must hold the state of the accessory. A value of OFF should be ignored. |
| | | ObstructionStatus | Switch, Contact | Current status of obstruction sensor. ON-obstruction detected, OFF - no obstruction | | | | ObstructionStatus | Switch, Contact | Current status of obstruction sensor. ON-obstruction detected, OFF - no obstruction |

View File

@ -19,10 +19,14 @@ import static org.openhab.io.homekit.internal.HomekitCharacteristicType.TARGET_P
import java.util.EnumMap; import java.util.EnumMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.items.Item;
import org.openhab.core.library.items.DimmerItem;
import org.openhab.core.library.items.NumberItem;
import org.openhab.core.library.items.RollershutterItem; import org.openhab.core.library.items.RollershutterItem;
import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.PercentType; import org.openhab.core.library.types.PercentType;
@ -30,6 +34,8 @@ import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitCharacteristicType; import org.openhab.io.homekit.internal.HomekitCharacteristicType;
import org.openhab.io.homekit.internal.HomekitSettings; import org.openhab.io.homekit.internal.HomekitSettings;
import org.openhab.io.homekit.internal.HomekitTaggedItem; import org.openhab.io.homekit.internal.HomekitTaggedItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
import io.github.hapjava.characteristics.impl.windowcovering.PositionStateEnum; import io.github.hapjava.characteristics.impl.windowcovering.PositionStateEnum;
@ -41,6 +47,7 @@ import io.github.hapjava.characteristics.impl.windowcovering.PositionStateEnum;
*/ */
@NonNullByDefault @NonNullByDefault
abstract class AbstractHomekitPositionAccessoryImpl extends AbstractHomekitAccessoryImpl { abstract class AbstractHomekitPositionAccessoryImpl extends AbstractHomekitAccessoryImpl {
private final Logger logger = LoggerFactory.getLogger(AbstractHomekitPositionAccessoryImpl.class);
protected int closedPosition; protected int closedPosition;
protected int openPosition; protected int openPosition;
private final Map<PositionStateEnum, String> positionStateMapping; private final Map<PositionStateEnum, String> positionStateMapping;
@ -73,10 +80,24 @@ abstract class AbstractHomekitPositionAccessoryImpl extends AbstractHomekitAcces
return CompletableFuture.completedFuture(convertPositionState(TARGET_POSITION, openPosition, closedPosition)); return CompletableFuture.completedFuture(convertPositionState(TARGET_POSITION, openPosition, closedPosition));
} }
@NonNullByDefault({})
public CompletableFuture<Void> setTargetPosition(int value) { public CompletableFuture<Void> setTargetPosition(int value) {
getItem(TARGET_POSITION, RollershutterItem.class) getCharacteristic(TARGET_POSITION).ifPresentOrElse(taggedItem -> {
.ifPresent(item -> item.send(new PercentType(convertPosition(value, openPosition)))); final Item item = taggedItem.getItem();
final int targetPosition = convertPosition(value, openPosition);
if (item instanceof RollershutterItem) {
((RollershutterItem) item).send(new PercentType(targetPosition));
} else if (item instanceof DimmerItem) {
((DimmerItem) item).send(new PercentType(targetPosition));
} else if (item instanceof NumberItem) {
((NumberItem) item).send(new DecimalType(targetPosition));
} else {
logger.warn(
"Unsupported item type for characteristic {} at accessory {}. Expected Rollershutter, Dimmer or Number item, got {}",
TARGET_POSITION, getName(), item.getClass());
}
}, () -> {
logger.warn("Mandatory characteristic {} not found at accessory {}. ", TARGET_POSITION, getName());
});
return CompletableFuture.completedFuture(null); return CompletableFuture.completedFuture(null);
} }
@ -130,7 +151,17 @@ abstract class AbstractHomekitPositionAccessoryImpl extends AbstractHomekitAcces
} }
protected int convertPositionState(HomekitCharacteristicType type, int openPosition, int closedPosition) { protected int convertPositionState(HomekitCharacteristicType type, int openPosition, int closedPosition) {
final @Nullable DecimalType value = getStateAs(type, PercentType.class); @Nullable
DecimalType value = null;
final Optional<HomekitTaggedItem> taggedItem = getCharacteristic(type);
if (taggedItem.isPresent()) {
final Item item = taggedItem.get().getItem();
if ((item instanceof RollershutterItem) || ((item instanceof DimmerItem))) {
value = item.getStateAs(PercentType.class);
} else {
value = item.getStateAs(DecimalType.class);
}
}
return value != null ? convertPosition(value.intValue(), openPosition) : closedPosition; return value != null ? convertPosition(value.intValue(), openPosition) : closedPosition;
} }
} }