[homekit] extend support of inverted flag to other accessories (#10212)

Signed-off-by: Eugen Freiter <freiter@gmx.de>
This commit is contained in:
eugen 2021-02-25 19:28:34 +01:00 committed by GitHub
parent 6d2211a2e9
commit 50a01b439d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 72 additions and 54 deletions

View File

@ -421,6 +421,9 @@ Following table summarizes the optional characteristics supported by sensors.
| TamperedStatus | Switch, Contact | Accessory tampered status. "ON"/"OPEN" indicates that the accessory has been tampered. Value should return to "OFF"/"CLOSED" when the accessory has been reset to a non-tampered state. |
| BatteryLowStatus | Switch, Contact | Accessory battery status. "ON"/"OPEN" indicates that the battery level of the accessory is low. Value should return to "OFF"/"CLOSED" when the battery charges to a level thats above the low threshold. |
Switch and Contact items support inversion of the state mapping, e.g. by default the openHAB switch state "ON" is mapped to HomeKit contact sensor state "Open", and "OFF" to "Closed".
The configuration "inverted='true'" inverts this mapping, so that "ON" will be mapped to "Closed" and "OFF" to "Open".
Examples of sensor definitions.
Sensors without optional characteristics:
@ -429,6 +432,8 @@ Switch leaksensor_single "Leak Sensor" {homekit="LeakSenso
Number light_sensor "Light Sensor" {homekit="LightSensor"}
Number temperature_sensor "Temperature Sensor [%.1f C]" {homekit="TemperatureSensor"}
Contact contact_sensor "Contact Sensor" {homekit="ContactSensor"}
Contact contact_sensor "Contact Sensor" {homekit="ContactSensor" [inverted="true"]}
Switch occupancy_sensor "Occupancy Sensor" {homekit="OccupancyDetectedState"}
Switch motion_sensor "Motion Sensor" {homekit="MotionSensor"}
Number humidity_sensor "Humidity Sensor" {homekit="HumiditySensor"}
@ -439,19 +444,24 @@ Sensors with optional characteristics:
```xtend
Group gLeakSensor "Leak Sensor" {homekit="LeakSensor"}
Switch leaksensor "Leak Sensor State" (gLeakSensor) {homekit="LeakDetectedState"}
Switch leaksensor_bat "Leak Sensor Battery" (gLeakSensor) {homekit="BatteryLowStatus"}
Switch leaksensor_active "Leak Sensor Active" (gLeakSensor) {homekit="ActiveStatus"}
Switch leaksensor_bat "Leak Sensor Battery" (gLeakSensor) {homekit="BatteryLowStatus" }
Switch leaksensor_active "Leak Sensor Active" (gLeakSensor) {homekit="ActiveStatus" [inverted="true"]}
Switch leaksensor_fault "Leak Sensor Fault" (gLeakSensor) {homekit="FaultStatus"}
Switch leaksensor_tampered "Leak Sensor Tampered" (gLeakSensor) {homekit="TamperedStatus"}
Group gMotionSensor "Motion Sensor" {homekit="MotionSensor"}
Switch motionsensor "Motion Sensor State" (gMotionSensor) {homekit="MotionDetectedState"}
Switch motionsensor_bat "Motion Sensor Battery" (gMotionSensor) {homekit="BatteryLowStatus"}
Switch motionsensor_bat "Motion Sensor Battery" (gMotionSensor) {homekit="BatteryLowStatus" [inverted="true"]}
Switch motionsensor_active "Motion Sensor Active" (gMotionSensor) {homekit="ActiveStatus"}
Switch motionsensor_fault "Motion Sensor Fault" (gMotionSensor) {homekit="FaultStatus"}
Switch motionsensor_tampered "Motion Sensor Tampered" (gMotionSensor) {homekit="TamperedStatus"}
```
or using UI
![sensor_ui_config.png](doc/sensor_ui_config.png)
## Supported accessory type
| Accessory Tag | Mandatory Characteristics | Optional Characteristics | Supported OH items | Description |
@ -490,7 +500,7 @@ Switch motionsensor_tampered "Motion Sensor Tampered"
| | | FaultStatus | Switch, Contact | Fault status |
| | | TamperedStatus | Switch, Contact | Tampered status |
| | | BatteryLowStatus | Switch, Contact | Battery status |
| ContactSensor | | | | Contact Sensor,An accessory with on/off state that can be viewed in HomeKit but not changed such as a contact sensor for a door or window |
| ContactSensor | | | | Contact Sensor, An accessory with on/off state that can be viewed in HomeKit but not changed such as a contact sensor for a door or window |
| | ContactSensorState | | Switch, Contact | Contact sensor state (ON=open, OFF=closed) |
| | | Name | String | Name of the sensor |
| | | ActiveStatus | Switch, Contact | Working status |

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View File

@ -210,6 +210,16 @@ public class HomekitTaggedItem {
return defaultValue;
}
/**
* returns true if inverted flag is set, i.e. item has the configuration "inverted=true"
*
* @return true if inverted flag is set to true
*/
public boolean isInverted() {
final String invertedConfig = getConfiguration(HomekitTaggedItem.INVERTED, "false");
return invertedConfig.equalsIgnoreCase("yes") || invertedConfig.equalsIgnoreCase("true");
}
/**
* return configuration as double if exists otherwise return defaultValue
*

View File

@ -300,6 +300,15 @@ abstract class AbstractHomekitAccessoryImpl implements HomekitAccessory {
ImperialUnits.FAHRENHEIT);
}
/**
* create boolean reader with ON state mapped to trueOnOffValue or trueOpenClosedValue depending of item type
*
* @param characteristicType characteristic id
* @param trueOnOffValue ON value for switch
* @param trueOpenClosedValue ON value for contact
* @return boolean readed
* @throws IncompleteAccessoryException
*/
@NonNullByDefault
protected BooleanItemReader createBooleanReader(HomekitCharacteristicType characteristicType,
OnOffType trueOnOffValue, OpenClosedType trueOpenClosedValue) throws IncompleteAccessoryException {
@ -308,4 +317,20 @@ abstract class AbstractHomekitAccessoryImpl implements HomekitAccessory {
.orElseThrow(() -> new IncompleteAccessoryException(characteristicType)),
trueOnOffValue, trueOpenClosedValue);
}
/**
* create boolean reader with default ON/OFF mapping considering inverted flag
*
* @param characteristicType characteristic id
* @return boolean reader
* @throws IncompleteAccessoryException
*/
@NonNullByDefault
protected BooleanItemReader createBooleanReader(HomekitCharacteristicType characteristicType)
throws IncompleteAccessoryException {
final HomekitTaggedItem taggedItem = getCharacteristic(characteristicType)
.orElseThrow(() -> new IncompleteAccessoryException(characteristicType));
return new BooleanItemReader(taggedItem.getItem(), taggedItem.isInverted() ? OnOffType.OFF : OnOffType.ON,
taggedItem.isInverted() ? OpenClosedType.CLOSED : OpenClosedType.OPEN);
}
}

View File

@ -17,8 +17,6 @@ import static org.openhab.io.homekit.internal.HomekitCharacteristicType.CARBON_D
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitSettings;
import org.openhab.io.homekit.internal.HomekitTaggedItem;
@ -40,8 +38,7 @@ public class HomekitCarbonDioxideSensorImpl extends AbstractHomekitAccessoryImpl
List<HomekitTaggedItem> mandatoryCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
carbonDioxideDetectedReader = createBooleanReader(CARBON_DIOXIDE_DETECTED_STATE, OnOffType.ON,
OpenClosedType.OPEN);
carbonDioxideDetectedReader = createBooleanReader(CARBON_DIOXIDE_DETECTED_STATE);
getServices().add(new CarbonDioxideSensorService(this));
}

View File

@ -17,8 +17,6 @@ import static org.openhab.io.homekit.internal.HomekitCharacteristicType.CARBON_M
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitSettings;
import org.openhab.io.homekit.internal.HomekitTaggedItem;
@ -40,8 +38,7 @@ public class HomekitCarbonMonoxideSensorImpl extends AbstractHomekitAccessoryImp
List<HomekitTaggedItem> mandatoryCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
carbonMonoxideDetectedReader = createBooleanReader(CARBON_MONOXIDE_DETECTED_STATE, OnOffType.ON,
OpenClosedType.OPEN);
carbonMonoxideDetectedReader = createBooleanReader(CARBON_MONOXIDE_DETECTED_STATE);
getServices().add(new CarbonMonoxideSensorService(this));
}

View File

@ -164,9 +164,11 @@ public class HomekitCharacteristicFactory {
T offEnum, T onEnum, T defaultEnum) {
final State state = item.getItem().getState();
if (state instanceof OnOffType) {
return CompletableFuture.completedFuture(state.equals(OnOffType.OFF) ? offEnum : onEnum);
return CompletableFuture
.completedFuture(state.equals(item.isInverted() ? OnOffType.ON : OnOffType.OFF) ? offEnum : onEnum);
} else if (state instanceof OpenClosedType) {
return CompletableFuture.completedFuture(state.equals(OpenClosedType.CLOSED) ? offEnum : onEnum);
return CompletableFuture.completedFuture(
state.equals(item.isInverted() ? OpenClosedType.OPEN : OpenClosedType.CLOSED) ? offEnum : onEnum);
} else if (state instanceof DecimalType) {
return CompletableFuture.completedFuture(((DecimalType) state).intValue() == 0 ? offEnum : onEnum);
} else if (state instanceof UnDefType) {
@ -182,9 +184,9 @@ public class HomekitCharacteristicFactory {
CharacteristicEnum offEnum, CharacteristicEnum onEnum) {
if (taggedItem.getItem() instanceof SwitchItem) {
if (value.equals(offEnum)) {
((SwitchItem) taggedItem.getItem()).send(OnOffType.OFF);
((SwitchItem) taggedItem.getItem()).send(taggedItem.isInverted() ? OnOffType.ON : OnOffType.OFF);
} else if (value.equals(onEnum)) {
((SwitchItem) taggedItem.getItem()).send(OnOffType.ON);
((SwitchItem) taggedItem.getItem()).send(taggedItem.isInverted() ? OnOffType.OFF : OnOffType.ON);
} else {
logger.warn("Enum value {} is not supported. Only following values are supported: {},{}", value,
offEnum, onEnum);

View File

@ -17,8 +17,6 @@ import static org.openhab.io.homekit.internal.HomekitCharacteristicType.CONTACT_
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitSettings;
import org.openhab.io.homekit.internal.HomekitTaggedItem;
@ -38,7 +36,7 @@ public class HomekitContactSensorImpl extends AbstractHomekitAccessoryImpl imple
public HomekitContactSensorImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
contactSensedReader = createBooleanReader(CONTACT_SENSOR_STATE, OnOffType.ON, OpenClosedType.OPEN);
contactSensedReader = createBooleanReader(CONTACT_SENSOR_STATE);
getServices().add(new ContactSensorService(this));
}

View File

@ -17,8 +17,6 @@ import static org.openhab.io.homekit.internal.HomekitCharacteristicType.ACTIVE_S
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitSettings;
import org.openhab.io.homekit.internal.HomekitTaggedItem;
@ -38,7 +36,7 @@ class HomekitFanImpl extends AbstractHomekitAccessoryImpl implements FanAccessor
public HomekitFanImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
activeReader = createBooleanReader(ACTIVE_STATUS, OnOffType.ON, OpenClosedType.OPEN);
activeReader = createBooleanReader(ACTIVE_STATUS);
this.getServices().add(new FanService(this));
}

View File

@ -24,7 +24,6 @@ import org.openhab.core.items.Item;
import org.openhab.core.library.items.StringItem;
import org.openhab.core.library.items.SwitchItem;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.StringType;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitSettings;
@ -50,7 +49,7 @@ public class HomekitGarageDoorOpenerImpl extends AbstractHomekitAccessoryImpl im
public HomekitGarageDoorOpenerImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
obstructionReader = createBooleanReader(OBSTRUCTION_STATUS, OnOffType.ON, OpenClosedType.OPEN);
obstructionReader = createBooleanReader(OBSTRUCTION_STATUS);
getServices().add(new GarageDoorOpenerService(this));
}

View File

@ -17,8 +17,6 @@ import static org.openhab.io.homekit.internal.HomekitCharacteristicType.LEAK_DET
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitSettings;
import org.openhab.io.homekit.internal.HomekitTaggedItem;
@ -38,7 +36,7 @@ public class HomekitLeakSensorImpl extends AbstractHomekitAccessoryImpl implemen
public HomekitLeakSensorImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
leakDetectedReader = createBooleanReader(LEAK_DETECTED_STATE, OnOffType.ON, OpenClosedType.OPEN);
leakDetectedReader = createBooleanReader(LEAK_DETECTED_STATE);
getServices().add(new LeakSensorService(this));
}

View File

@ -46,10 +46,8 @@ public class HomekitLockImpl extends AbstractHomekitAccessoryImpl implements Loc
public HomekitLockImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) {
super(taggedItem, mandatoryCharacteristics, updater, settings);
final String invertedConfig = getAccessoryConfiguration(HomekitTaggedItem.INVERTED, "false");
final boolean inverted = invertedConfig.equalsIgnoreCase("yes") || invertedConfig.equalsIgnoreCase("true");
securedState = inverted ? OnOffType.OFF : OnOffType.ON;
unsecuredState = inverted ? OnOffType.ON : OnOffType.OFF;
securedState = taggedItem.isInverted() ? OnOffType.OFF : OnOffType.ON;
unsecuredState = taggedItem.isInverted() ? OnOffType.ON : OnOffType.OFF;
getServices().add(new LockMechanismService(this));
}

View File

@ -15,8 +15,6 @@ package org.openhab.io.homekit.internal.accessories;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitCharacteristicType;
import org.openhab.io.homekit.internal.HomekitSettings;
@ -36,8 +34,7 @@ public class HomekitMotionSensorImpl extends AbstractHomekitAccessoryImpl implem
public HomekitMotionSensorImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
motionSensedReader = createBooleanReader(HomekitCharacteristicType.MOTION_DETECTED_STATE, OnOffType.ON,
OpenClosedType.OPEN);
motionSensedReader = createBooleanReader(HomekitCharacteristicType.MOTION_DETECTED_STATE);
getServices().add(new MotionSensorService(this));
}

View File

@ -17,8 +17,6 @@ import static org.openhab.io.homekit.internal.HomekitCharacteristicType.OCCUPANC
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitSettings;
import org.openhab.io.homekit.internal.HomekitTaggedItem;
@ -38,7 +36,7 @@ public class HomekitOccupancySensorImpl extends AbstractHomekitAccessoryImpl imp
public HomekitOccupancySensorImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
occupancySensedReader = createBooleanReader(OCCUPANCY_DETECTED_STATE, OnOffType.ON, OpenClosedType.OPEN);
occupancySensedReader = createBooleanReader(OCCUPANCY_DETECTED_STATE);
getServices().add(new OccupancySensorService(this));
}

View File

@ -15,8 +15,6 @@ package org.openhab.io.homekit.internal.accessories;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitCharacteristicType;
import org.openhab.io.homekit.internal.HomekitSettings;
@ -37,8 +35,8 @@ public class HomekitOutletImpl extends AbstractHomekitAccessoryImpl implements O
public HomekitOutletImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
inUseReader = createBooleanReader(HomekitCharacteristicType.INUSE_STATUS, OnOffType.ON, OpenClosedType.OPEN);
onReader = createBooleanReader(HomekitCharacteristicType.ON_STATE, OnOffType.ON, OpenClosedType.OPEN);
inUseReader = createBooleanReader(HomekitCharacteristicType.INUSE_STATUS);
onReader = createBooleanReader(HomekitCharacteristicType.ON_STATE);
getServices().add(new OutletService(this));
}

View File

@ -17,8 +17,6 @@ import static org.openhab.io.homekit.internal.HomekitCharacteristicType.SMOKE_DE
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitSettings;
import org.openhab.io.homekit.internal.HomekitTaggedItem;
@ -38,7 +36,7 @@ public class HomekitSmokeSensorImpl extends AbstractHomekitAccessoryImpl impleme
public HomekitSmokeSensorImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
smokeDetectedReader = createBooleanReader(SMOKE_DETECTED_STATE, OnOffType.ON, OpenClosedType.OPEN);
smokeDetectedReader = createBooleanReader(SMOKE_DETECTED_STATE);
this.getServices().add(new SmokeSensorService(this));
}

View File

@ -15,8 +15,6 @@ package org.openhab.io.homekit.internal.accessories;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitCharacteristicType;
import org.openhab.io.homekit.internal.HomekitSettings;
@ -37,7 +35,7 @@ public class HomekitSpeakerImpl extends AbstractHomekitAccessoryImpl implements
public HomekitSpeakerImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
muteReader = createBooleanReader(HomekitCharacteristicType.MUTE, OnOffType.ON, OpenClosedType.OPEN);
muteReader = createBooleanReader(HomekitCharacteristicType.MUTE);
getServices().add(new SpeakerService(this));
}

View File

@ -17,8 +17,6 @@ import static org.openhab.io.homekit.internal.HomekitCharacteristicType.ON_STATE
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitSettings;
import org.openhab.io.homekit.internal.HomekitTaggedItem;
@ -38,7 +36,7 @@ public class HomekitSwitchImpl extends AbstractHomekitAccessoryImpl implements S
public HomekitSwitchImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
onReader = createBooleanReader(ON_STATE, OnOffType.ON, OpenClosedType.OPEN);
onReader = createBooleanReader(ON_STATE);
getServices().add(new SwitchService(this));
}

View File

@ -30,7 +30,6 @@ import org.openhab.core.items.GenericItem;
import org.openhab.core.library.items.SwitchItem;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.types.RefreshType;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitCharacteristicType;
@ -75,8 +74,8 @@ public class HomekitValveImpl extends AbstractHomekitAccessoryImpl implements Va
public HomekitValveImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
inUseReader = createBooleanReader(INUSE_STATUS, OnOffType.ON, OpenClosedType.OPEN);
activeReader = createBooleanReader(ACTIVE_STATUS, OnOffType.ON, OpenClosedType.OPEN);
inUseReader = createBooleanReader(INUSE_STATUS);
activeReader = createBooleanReader(ACTIVE_STATUS);
ValveService service = new ValveService(this);
getServices().add(service);
final String timerConfig = getAccessoryConfiguration(CONFIG_TIMER, "");