diff --git a/CHANGES.md b/CHANGES.md index a50fc7fae..f3eb389dc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,6 @@ +# HAP-Java 2.0.10 +* Add constructors with a custom list of valid values to the remaining enum characteristics (except two-value sensor and status flags) [#163](https://github.com/hap-java/HAP-Java/issues/163) + # HAP-Java 2.0.9 * Fix Set Duration and Remaining Duration characteristics to advertise format `uint32` instead of `int` [#202](https://github.com/hap-java/HAP-Java/issues/202) * Stop logging the SRP shared secret, derived key and M5 message data during pairing at DEBUG level diff --git a/src/main/java/io/github/hapjava/characteristics/impl/airpurifier/CurrentAirPurifierCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/airpurifier/CurrentAirPurifierCharacteristic.java index c5b506c40..10f9ca313 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/airpurifier/CurrentAirPurifierCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/airpurifier/CurrentAirPurifierCharacteristic.java @@ -18,10 +18,18 @@ public CurrentAirPurifierCharacteristic( Supplier> getter, Consumer subscriber, Runnable unsubscriber) { + this(CurrentAirPurifierStateEnum.values(), getter, subscriber, unsubscriber); + } + + public CurrentAirPurifierCharacteristic( + CurrentAirPurifierStateEnum[] validValues, + Supplier> getter, + Consumer subscriber, + Runnable unsubscriber) { super( "000000A9-0000-1000-8000-0026BB765291", "current air purifier state", - CurrentAirPurifierStateEnum.values(), + validValues, Optional.of(getter), Optional.empty(), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/airpurifier/TargetAirPurifierStateCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/airpurifier/TargetAirPurifierStateCharacteristic.java index e8452d655..ea7c48944 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/airpurifier/TargetAirPurifierStateCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/airpurifier/TargetAirPurifierStateCharacteristic.java @@ -20,10 +20,19 @@ public TargetAirPurifierStateCharacteristic( ExceptionalConsumer setter, Consumer subscriber, Runnable unsubscriber) { + this(TargetAirPurifierStateEnum.values(), getter, setter, subscriber, unsubscriber); + } + + public TargetAirPurifierStateCharacteristic( + TargetAirPurifierStateEnum[] validValues, + Supplier> getter, + ExceptionalConsumer setter, + Consumer subscriber, + Runnable unsubscriber) { super( "000000A8-0000-1000-8000-0026BB765291", "Air purifier state", - TargetAirPurifierStateEnum.values(), + validValues, Optional.of(getter), Optional.of(setter), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/airquality/AirQualityCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/airquality/AirQualityCharacteristic.java index 448b90383..5615811c7 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/airquality/AirQualityCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/airquality/AirQualityCharacteristic.java @@ -16,10 +16,18 @@ public AirQualityCharacteristic( Supplier> getter, Consumer subscriber, Runnable unsubscriber) { + this(AirQualityEnum.values(), getter, subscriber, unsubscriber); + } + + public AirQualityCharacteristic( + AirQualityEnum[] validValues, + Supplier> getter, + Consumer subscriber, + Runnable unsubscriber) { super( "00000095-0000-1000-8000-0026BB765291", "air quality", - AirQualityEnum.values(), + validValues, Optional.of(getter), Optional.empty(), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/battery/ChargingStateCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/battery/ChargingStateCharacteristic.java index f034e2c3c..db4664af2 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/battery/ChargingStateCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/battery/ChargingStateCharacteristic.java @@ -17,10 +17,18 @@ public ChargingStateCharacteristic( Supplier> getter, Consumer subscriber, Runnable unsubscriber) { + this(ChargingStateEnum.values(), getter, subscriber, unsubscriber); + } + + public ChargingStateCharacteristic( + ChargingStateEnum[] validValues, + Supplier> getter, + Consumer subscriber, + Runnable unsubscriber) { super( "0000008F-0000-1000-8000-0026BB765291", "Charging state", - ChargingStateEnum.values(), + validValues, Optional.of(getter), Optional.empty(), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/common/ActiveCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/common/ActiveCharacteristic.java index 0d7fc2c1c..9dcebaff0 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/common/ActiveCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/common/ActiveCharacteristic.java @@ -19,10 +19,19 @@ public ActiveCharacteristic( ExceptionalConsumer setter, Consumer subscriber, Runnable unsubscriber) { + this(ActiveEnum.values(), getter, setter, subscriber, unsubscriber); + } + + public ActiveCharacteristic( + ActiveEnum[] validValues, + Supplier> getter, + ExceptionalConsumer setter, + Consumer subscriber, + Runnable unsubscriber) { super( "000000B0-0000-1000-8000-0026BB765291", "Active", - ActiveEnum.values(), + validValues, Optional.of(getter), Optional.of(setter), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/common/ProgramModeCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/common/ProgramModeCharacteristic.java index 1580ae392..84871a888 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/common/ProgramModeCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/common/ProgramModeCharacteristic.java @@ -16,10 +16,18 @@ public ProgramModeCharacteristic( Supplier> getter, Consumer subscriber, Runnable unsubscriber) { + this(ProgramModeEnum.values(), getter, subscriber, unsubscriber); + } + + public ProgramModeCharacteristic( + ProgramModeEnum[] validValues, + Supplier> getter, + Consumer subscriber, + Runnable unsubscriber) { super( "000000D1-0000-1000-8000-0026BB765291", "Program Mode", - ProgramModeEnum.values(), + validValues, Optional.of(getter), Optional.empty(), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/common/ServiceLabelNamespaceCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/common/ServiceLabelNamespaceCharacteristic.java index 9f8dd3248..68ffc379b 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/common/ServiceLabelNamespaceCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/common/ServiceLabelNamespaceCharacteristic.java @@ -13,10 +13,16 @@ public class ServiceLabelNamespaceCharacteristic extends EnumCharacteristic { public ServiceLabelNamespaceCharacteristic( Supplier> getter) { + this(ServiceLabelNamespaceEnum.values(), getter); + } + + public ServiceLabelNamespaceCharacteristic( + ServiceLabelNamespaceEnum[] validValues, + Supplier> getter) { super( "000000CD-0000-1000-8000-0026BB765291", "service label namespace", - ServiceLabelNamespaceEnum.values(), + validValues, Optional.of(getter), Optional.empty(), Optional.empty(), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/fan/CurrentFanStateCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/fan/CurrentFanStateCharacteristic.java index 75f932e50..4f3afd9d2 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/fan/CurrentFanStateCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/fan/CurrentFanStateCharacteristic.java @@ -19,10 +19,18 @@ public CurrentFanStateCharacteristic( Supplier> getter, Consumer subscriber, Runnable unsubscriber) { + this(CurrentFanStateEnum.values(), getter, subscriber, unsubscriber); + } + + public CurrentFanStateCharacteristic( + CurrentFanStateEnum[] validValues, + Supplier> getter, + Consumer subscriber, + Runnable unsubscriber) { super( "000000AF-0000-1000-8000-0026BB765291", "Current Fan State", - CurrentFanStateEnum.values(), + validValues, Optional.of(getter), Optional.empty(), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/fan/LockPhysicalControlsCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/fan/LockPhysicalControlsCharacteristic.java index 8ea6f35c6..2c821afa6 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/fan/LockPhysicalControlsCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/fan/LockPhysicalControlsCharacteristic.java @@ -18,10 +18,19 @@ public LockPhysicalControlsCharacteristic( ExceptionalConsumer setter, Consumer subscriber, Runnable unsubscriber) { + this(LockPhysicalControlsEnum.values(), getter, setter, subscriber, unsubscriber); + } + + public LockPhysicalControlsCharacteristic( + LockPhysicalControlsEnum[] validValues, + Supplier> getter, + ExceptionalConsumer setter, + Consumer subscriber, + Runnable unsubscriber) { super( "000000A7-0000-1000-8000-0026BB765291", "Physical Locks", - LockPhysicalControlsEnum.values(), + validValues, Optional.of(getter), Optional.of(setter), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/fan/RotationDirectionCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/fan/RotationDirectionCharacteristic.java index efa82681f..c920d3047 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/fan/RotationDirectionCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/fan/RotationDirectionCharacteristic.java @@ -18,10 +18,19 @@ public RotationDirectionCharacteristic( ExceptionalConsumer setter, Consumer subscriber, Runnable unsubscriber) { + this(RotationDirectionEnum.values(), getter, setter, subscriber, unsubscriber); + } + + public RotationDirectionCharacteristic( + RotationDirectionEnum[] validValues, + Supplier> getter, + ExceptionalConsumer setter, + Consumer subscriber, + Runnable unsubscriber) { super( "00000028-0000-1000-8000-0026BB765291", "Rotation direction", - RotationDirectionEnum.values(), + validValues, Optional.of(getter), Optional.of(setter), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/fan/SwingModeCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/fan/SwingModeCharacteristic.java index ba58dfd0f..3b6149619 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/fan/SwingModeCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/fan/SwingModeCharacteristic.java @@ -18,10 +18,19 @@ public SwingModeCharacteristic( ExceptionalConsumer setter, Consumer subscriber, Runnable unsubscriber) { + this(SwingModeEnum.values(), getter, setter, subscriber, unsubscriber); + } + + public SwingModeCharacteristic( + SwingModeEnum[] validValues, + Supplier> getter, + ExceptionalConsumer setter, + Consumer subscriber, + Runnable unsubscriber) { super( "000000B6-0000-1000-8000-0026BB765291", "Swing Mode", - SwingModeEnum.values(), + validValues, Optional.of(getter), Optional.of(setter), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/fan/TargetFanStateCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/fan/TargetFanStateCharacteristic.java index 1ab9ca305..a8388a0dc 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/fan/TargetFanStateCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/fan/TargetFanStateCharacteristic.java @@ -18,10 +18,19 @@ public TargetFanStateCharacteristic( ExceptionalConsumer setter, Consumer subscriber, Runnable unsubscriber) { + this(TargetFanStateEnum.values(), getter, setter, subscriber, unsubscriber); + } + + public TargetFanStateCharacteristic( + TargetFanStateEnum[] validValues, + Supplier> getter, + ExceptionalConsumer setter, + Consumer subscriber, + Runnable unsubscriber) { super( "000000BF-0000-1000-8000-0026BB765291", "Target Fan State", - TargetFanStateEnum.values(), + validValues, Optional.of(getter), Optional.of(setter), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/garagedoor/CurrentDoorStateCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/garagedoor/CurrentDoorStateCharacteristic.java index e06937daa..e5b28e8c9 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/garagedoor/CurrentDoorStateCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/garagedoor/CurrentDoorStateCharacteristic.java @@ -16,10 +16,18 @@ public CurrentDoorStateCharacteristic( Supplier> getter, Consumer subscriber, Runnable unsubscriber) { + this(CurrentDoorStateEnum.values(), getter, subscriber, unsubscriber); + } + + public CurrentDoorStateCharacteristic( + CurrentDoorStateEnum[] validValues, + Supplier> getter, + Consumer subscriber, + Runnable unsubscriber) { super( "0000000E-0000-1000-8000-0026BB765291", "Current Door State", - CurrentDoorStateEnum.values(), + validValues, Optional.of(getter), Optional.empty(), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/garagedoor/TargetDoorStateCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/garagedoor/TargetDoorStateCharacteristic.java index f5b490c6e..3501a1ce6 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/garagedoor/TargetDoorStateCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/garagedoor/TargetDoorStateCharacteristic.java @@ -18,10 +18,19 @@ public TargetDoorStateCharacteristic( ExceptionalConsumer setter, Consumer subscriber, Runnable unsubscriber) { + this(TargetDoorStateEnum.values(), getter, setter, subscriber, unsubscriber); + } + + public TargetDoorStateCharacteristic( + TargetDoorStateEnum[] validValues, + Supplier> getter, + ExceptionalConsumer setter, + Consumer subscriber, + Runnable unsubscriber) { super( "00000032-0000-1000-8000-0026BB765291", "Target Door State", - TargetDoorStateEnum.values(), + validValues, Optional.of(getter), Optional.of(setter), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/humidifier/CurrentHumidifierDehumidifierStateCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/humidifier/CurrentHumidifierDehumidifierStateCharacteristic.java index 229d0aa73..9560817b7 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/humidifier/CurrentHumidifierDehumidifierStateCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/humidifier/CurrentHumidifierDehumidifierStateCharacteristic.java @@ -17,10 +17,18 @@ public CurrentHumidifierDehumidifierStateCharacteristic( Supplier> getter, Consumer subscriber, Runnable unsubscriber) { + this(CurrentHumidifierDehumidifierStateEnum.values(), getter, subscriber, unsubscriber); + } + + public CurrentHumidifierDehumidifierStateCharacteristic( + CurrentHumidifierDehumidifierStateEnum[] validValues, + Supplier> getter, + Consumer subscriber, + Runnable unsubscriber) { super( "000000B3-0000-1000-8000-0026BB765291", "current humidifier state", - CurrentHumidifierDehumidifierStateEnum.values(), + validValues, Optional.of(getter), Optional.empty(), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/inputsource/CurrentVisibilityStateCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/inputsource/CurrentVisibilityStateCharacteristic.java index 65c358a3f..eb44ab638 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/inputsource/CurrentVisibilityStateCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/inputsource/CurrentVisibilityStateCharacteristic.java @@ -15,10 +15,18 @@ public CurrentVisibilityStateCharacteristic( Supplier> getter, Consumer subscriber, Runnable unsubscriber) { + this(CurrentVisibilityStateEnum.values(), getter, subscriber, unsubscriber); + } + + public CurrentVisibilityStateCharacteristic( + CurrentVisibilityStateEnum[] validValues, + Supplier> getter, + Consumer subscriber, + Runnable unsubscriber) { super( "00000135-0000-1000-8000-0026BB765291", "current visibility state", - CurrentVisibilityStateEnum.values(), + validValues, Optional.of(getter), Optional.empty(), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/inputsource/InputDeviceTypeCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/inputsource/InputDeviceTypeCharacteristic.java index 51a6fbde5..8b92f3eb3 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/inputsource/InputDeviceTypeCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/inputsource/InputDeviceTypeCharacteristic.java @@ -14,10 +14,18 @@ public InputDeviceTypeCharacteristic( Supplier> getter, Consumer subscriber, Runnable unsubscriber) { + this(InputDeviceTypeEnum.values(), getter, subscriber, unsubscriber); + } + + public InputDeviceTypeCharacteristic( + InputDeviceTypeEnum[] validValues, + Supplier> getter, + Consumer subscriber, + Runnable unsubscriber) { super( "000000DC-0000-1000-8000-0026BB765291", "input device type", - InputDeviceTypeEnum.values(), + validValues, Optional.of(getter), Optional.empty(), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/inputsource/InputSourceTypeCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/inputsource/InputSourceTypeCharacteristic.java index 91134891b..d77ba1895 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/inputsource/InputSourceTypeCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/inputsource/InputSourceTypeCharacteristic.java @@ -14,10 +14,18 @@ public InputSourceTypeCharacteristic( Supplier> getter, Consumer subscriber, Runnable unsubscriber) { + this(InputSourceTypeEnum.values(), getter, subscriber, unsubscriber); + } + + public InputSourceTypeCharacteristic( + InputSourceTypeEnum[] validValues, + Supplier> getter, + Consumer subscriber, + Runnable unsubscriber) { super( "000000DB-0000-1000-8000-0026BB765291", "input source type", - InputSourceTypeEnum.values(), + validValues, Optional.of(getter), Optional.empty(), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/inputsource/TargetVisibilityStateCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/inputsource/TargetVisibilityStateCharacteristic.java index ea466d182..8c94944e4 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/inputsource/TargetVisibilityStateCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/inputsource/TargetVisibilityStateCharacteristic.java @@ -17,10 +17,19 @@ public TargetVisibilityStateCharacteristic( ExceptionalConsumer setter, Consumer subscriber, Runnable unsubscriber) { + this(TargetVisibilityStateEnum.values(), getter, setter, subscriber, unsubscriber); + } + + public TargetVisibilityStateCharacteristic( + TargetVisibilityStateEnum[] validValues, + Supplier> getter, + ExceptionalConsumer setter, + Consumer subscriber, + Runnable unsubscriber) { super( "00000134-0000-1000-8000-0026BB765291", "target visibility state", - TargetVisibilityStateEnum.values(), + validValues, Optional.of(getter), Optional.of(setter), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/lock/LockCurrentStateCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/lock/LockCurrentStateCharacteristic.java index b6946313b..3dfb8723a 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/lock/LockCurrentStateCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/lock/LockCurrentStateCharacteristic.java @@ -14,10 +14,18 @@ public LockCurrentStateCharacteristic( Supplier> getter, Consumer subscriber, Runnable unsubscriber) { + this(LockCurrentStateEnum.values(), getter, subscriber, unsubscriber); + } + + public LockCurrentStateCharacteristic( + LockCurrentStateEnum[] validValues, + Supplier> getter, + Consumer subscriber, + Runnable unsubscriber) { super( "0000001D-0000-1000-8000-0026BB765291", "Current Lock State", - LockCurrentStateEnum.values(), + validValues, Optional.of(getter), Optional.empty(), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/lock/LockTargetStateCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/lock/LockTargetStateCharacteristic.java index c46a4eab5..b49a1deeb 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/lock/LockTargetStateCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/lock/LockTargetStateCharacteristic.java @@ -16,10 +16,19 @@ public LockTargetStateCharacteristic( ExceptionalConsumer setter, Consumer subscriber, Runnable unsubscriber) { + this(LockTargetStateEnum.values(), getter, setter, subscriber, unsubscriber); + } + + public LockTargetStateCharacteristic( + LockTargetStateEnum[] validValues, + Supplier> getter, + ExceptionalConsumer setter, + Consumer subscriber, + Runnable unsubscriber) { super( "0000001E-0000-1000-8000-0026BB765291", "Target Lock State", - LockTargetStateEnum.values(), + validValues, Optional.of(getter), Optional.of(setter), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/slat/CurrentSlatStateCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/slat/CurrentSlatStateCharacteristic.java index 84e5e1daa..ecc69ed85 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/slat/CurrentSlatStateCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/slat/CurrentSlatStateCharacteristic.java @@ -14,10 +14,18 @@ public CurrentSlatStateCharacteristic( Supplier> getter, Consumer subscriber, Runnable unsubscriber) { + this(CurrentSlatStateEnum.values(), getter, subscriber, unsubscriber); + } + + public CurrentSlatStateCharacteristic( + CurrentSlatStateEnum[] validValues, + Supplier> getter, + Consumer subscriber, + Runnable unsubscriber) { super( "000000AA-0000-1000-8000-0026BB765291", "current slat state", - CurrentSlatStateEnum.values(), + validValues, Optional.of(getter), Optional.empty(), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/slat/SlatTypeCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/slat/SlatTypeCharacteristic.java index 0d9f60608..f4705710f 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/slat/SlatTypeCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/slat/SlatTypeCharacteristic.java @@ -11,10 +11,15 @@ public class SlatTypeCharacteristic extends EnumCharacteristic { public SlatTypeCharacteristic(Supplier> getter) { + this(SlatTypeEnum.values(), getter); + } + + public SlatTypeCharacteristic( + SlatTypeEnum[] validValues, Supplier> getter) { super( "000000C0-0000-1000-8000-0026BB765291", "slat type", - SlatTypeEnum.values(), + validValues, Optional.of(getter), Optional.empty(), Optional.empty(), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/television/ClosedCaptionsCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/television/ClosedCaptionsCharacteristic.java index a963ca222..5299c8ed0 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/television/ClosedCaptionsCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/television/ClosedCaptionsCharacteristic.java @@ -19,10 +19,19 @@ public ClosedCaptionsCharacteristic( ExceptionalConsumer setter, Consumer subscriber, Runnable unsubscriber) { + this(ClosedCaptionsEnum.values(), getter, setter, subscriber, unsubscriber); + } + + public ClosedCaptionsCharacteristic( + ClosedCaptionsEnum[] validValues, + Supplier> getter, + ExceptionalConsumer setter, + Consumer subscriber, + Runnable unsubscriber) { super( "000000DD-0000-1000-8000-0026BB765291", "closed captions", - ClosedCaptionsEnum.values(), + validValues, Optional.of(getter), Optional.of(setter), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/television/CurrentMediaStateCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/television/CurrentMediaStateCharacteristic.java index ca72c4ee9..6f346feb6 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/television/CurrentMediaStateCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/television/CurrentMediaStateCharacteristic.java @@ -16,10 +16,18 @@ public CurrentMediaStateCharacteristic( Supplier> getter, Consumer subscriber, Runnable unsubscriber) { + this(CurrentMediaStateEnum.values(), getter, subscriber, unsubscriber); + } + + public CurrentMediaStateCharacteristic( + CurrentMediaStateEnum[] validValues, + Supplier> getter, + Consumer subscriber, + Runnable unsubscriber) { super( "000000E0-0000-1000-8000-0026BB765291", "current media state", - CurrentMediaStateEnum.values(), + validValues, Optional.of(getter), Optional.empty(), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/television/PictureModeCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/television/PictureModeCharacteristic.java index 7efefa23a..e77ce6147 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/television/PictureModeCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/television/PictureModeCharacteristic.java @@ -18,10 +18,19 @@ public PictureModeCharacteristic( ExceptionalConsumer setter, Consumer subscriber, Runnable unsubscriber) { + this(PictureModeEnum.values(), getter, setter, subscriber, unsubscriber); + } + + public PictureModeCharacteristic( + PictureModeEnum[] validValues, + Supplier> getter, + ExceptionalConsumer setter, + Consumer subscriber, + Runnable unsubscriber) { super( "000000E2-0000-1000-8000-0026BB765291", "picture mode", - PictureModeEnum.values(), + validValues, Optional.of(getter), Optional.of(setter), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/television/PowerModeCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/television/PowerModeCharacteristic.java index cebbe4124..29825a26e 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/television/PowerModeCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/television/PowerModeCharacteristic.java @@ -8,10 +8,15 @@ public class PowerModeCharacteristic extends EnumCharacteristic { public PowerModeCharacteristic(ExceptionalConsumer setter) { + this(PowerModeEnum.values(), setter); + } + + public PowerModeCharacteristic( + PowerModeEnum[] validValues, ExceptionalConsumer setter) { super( "000000DF-0000-1000-8000-0026BB765291", "power mode selection", - PowerModeEnum.values(), + validValues, Optional.empty(), Optional.of(setter), Optional.empty(), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/television/RemoteKeyCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/television/RemoteKeyCharacteristic.java index fe028d10d..d3c8c8af5 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/television/RemoteKeyCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/television/RemoteKeyCharacteristic.java @@ -10,10 +10,15 @@ */ public class RemoteKeyCharacteristic extends EnumCharacteristic { public RemoteKeyCharacteristic(ExceptionalConsumer setter) { + this(RemoteKeyEnum.values(), setter); + } + + public RemoteKeyCharacteristic( + RemoteKeyEnum[] validValues, ExceptionalConsumer setter) { super( "000000E1-0000-1000-8000-0026BB765291", "remote key", - RemoteKeyEnum.values(), + validValues, Optional.empty(), Optional.of(setter), Optional.empty(), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/television/SleepDiscoveryModeCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/television/SleepDiscoveryModeCharacteristic.java index 2a7f41829..f4bd09e94 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/television/SleepDiscoveryModeCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/television/SleepDiscoveryModeCharacteristic.java @@ -16,10 +16,18 @@ public SleepDiscoveryModeCharacteristic( Supplier> getter, Consumer subscriber, Runnable unsubscriber) { + this(SleepDiscoveryModeEnum.values(), getter, subscriber, unsubscriber); + } + + public SleepDiscoveryModeCharacteristic( + SleepDiscoveryModeEnum[] validValues, + Supplier> getter, + Consumer subscriber, + Runnable unsubscriber) { super( "000000E8-0000-1000-8000-0026BB765291", "sleep discovery mode", - SleepDiscoveryModeEnum.values(), + validValues, Optional.of(getter), Optional.empty(), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/television/TargetMediaStateCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/television/TargetMediaStateCharacteristic.java index 8909bb1ea..07b4c3587 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/television/TargetMediaStateCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/television/TargetMediaStateCharacteristic.java @@ -15,10 +15,19 @@ public TargetMediaStateCharacteristic( ExceptionalConsumer setter, Consumer subscriber, Runnable unsubscriber) { + this(TargetMediaStateEnum.values(), getter, setter, subscriber, unsubscriber); + } + + public TargetMediaStateCharacteristic( + TargetMediaStateEnum[] validValues, + Supplier> getter, + ExceptionalConsumer setter, + Consumer subscriber, + Runnable unsubscriber) { super( "00000137-0000-1000-8000-0026BB765291", "current media state", - TargetMediaStateEnum.values(), + validValues, Optional.of(getter), Optional.of(setter), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/televisionspeaker/VolumeControlTypeCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/televisionspeaker/VolumeControlTypeCharacteristic.java index c6d18a858..95acd520d 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/televisionspeaker/VolumeControlTypeCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/televisionspeaker/VolumeControlTypeCharacteristic.java @@ -16,10 +16,18 @@ public VolumeControlTypeCharacteristic( Supplier> getter, Consumer subscriber, Runnable unsubscriber) { + this(VolumeControlTypeEnum.values(), getter, subscriber, unsubscriber); + } + + public VolumeControlTypeCharacteristic( + VolumeControlTypeEnum[] validValues, + Supplier> getter, + Consumer subscriber, + Runnable unsubscriber) { super( "000000E9-0000-1000-8000-0026BB765291", "volume control type", - VolumeControlTypeEnum.values(), + validValues, Optional.of(getter), Optional.empty(), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/televisionspeaker/VolumeSelectorCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/televisionspeaker/VolumeSelectorCharacteristic.java index 8f2f84e7b..83314b409 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/televisionspeaker/VolumeSelectorCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/televisionspeaker/VolumeSelectorCharacteristic.java @@ -10,10 +10,15 @@ */ public class VolumeSelectorCharacteristic extends EnumCharacteristic { public VolumeSelectorCharacteristic(ExceptionalConsumer setter) { + this(VolumeSelectorEnum.values(), setter); + } + + public VolumeSelectorCharacteristic( + VolumeSelectorEnum[] validValues, ExceptionalConsumer setter) { super( "000000EA-0000-1000-8000-0026BB765291", "volume selector", - VolumeSelectorEnum.values(), + validValues, Optional.empty(), Optional.of(setter), Optional.empty(), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/thermostat/TemperatureDisplayUnitCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/thermostat/TemperatureDisplayUnitCharacteristic.java index 02a23553f..f5df0c01f 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/thermostat/TemperatureDisplayUnitCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/thermostat/TemperatureDisplayUnitCharacteristic.java @@ -20,10 +20,19 @@ public TemperatureDisplayUnitCharacteristic( ExceptionalConsumer setter, Consumer subscriber, Runnable unsubscriber) { + this(TemperatureDisplayUnitEnum.values(), getter, setter, subscriber, unsubscriber); + } + + public TemperatureDisplayUnitCharacteristic( + TemperatureDisplayUnitEnum[] validValues, + Supplier> getter, + ExceptionalConsumer setter, + Consumer subscriber, + Runnable unsubscriber) { super( "00000036-0000-1000-8000-0026BB765291", "Temperature units", - TemperatureDisplayUnitEnum.values(), + validValues, Optional.of(getter), Optional.of(setter), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/valve/ValveTypeCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/valve/ValveTypeCharacteristic.java index f98e468f4..3ea42815c 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/valve/ValveTypeCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/valve/ValveTypeCharacteristic.java @@ -14,10 +14,18 @@ public ValveTypeCharacteristic( Supplier> getter, Consumer subscriber, Runnable unsubscriber) { + this(ValveTypeEnum.values(), getter, subscriber, unsubscriber); + } + + public ValveTypeCharacteristic( + ValveTypeEnum[] validValues, + Supplier> getter, + Consumer subscriber, + Runnable unsubscriber) { super( "000000D5-0000-1000-8000-0026BB765291", "Valve type", - ValveTypeEnum.values(), + validValues, Optional.of(getter), Optional.empty(), Optional.of(subscriber), diff --git a/src/main/java/io/github/hapjava/characteristics/impl/windowcovering/PositionStateCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/windowcovering/PositionStateCharacteristic.java index 5b2488f52..8a15cfaad 100644 --- a/src/main/java/io/github/hapjava/characteristics/impl/windowcovering/PositionStateCharacteristic.java +++ b/src/main/java/io/github/hapjava/characteristics/impl/windowcovering/PositionStateCharacteristic.java @@ -14,10 +14,18 @@ public PositionStateCharacteristic( Supplier> getter, Consumer subscriber, Runnable unsubscriber) { + this(PositionStateEnum.values(), getter, subscriber, unsubscriber); + } + + public PositionStateCharacteristic( + PositionStateEnum[] validValues, + Supplier> getter, + Consumer subscriber, + Runnable unsubscriber) { super( "00000072-0000-1000-8000-0026BB765291", "Position state", - PositionStateEnum.values(), + validValues, Optional.of(getter), Optional.empty(), Optional.of(subscriber), diff --git a/src/test/java/io/github/hapjava/characteristics/impl/CustomValidValuesCharacteristicsTest.java b/src/test/java/io/github/hapjava/characteristics/impl/CustomValidValuesCharacteristicsTest.java new file mode 100644 index 000000000..dad276aca --- /dev/null +++ b/src/test/java/io/github/hapjava/characteristics/impl/CustomValidValuesCharacteristicsTest.java @@ -0,0 +1,614 @@ +package io.github.hapjava.characteristics.impl; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.github.hapjava.characteristics.Characteristic; +import io.github.hapjava.characteristics.impl.airpurifier.CurrentAirPurifierCharacteristic; +import io.github.hapjava.characteristics.impl.airpurifier.CurrentAirPurifierStateEnum; +import io.github.hapjava.characteristics.impl.airpurifier.TargetAirPurifierStateCharacteristic; +import io.github.hapjava.characteristics.impl.airpurifier.TargetAirPurifierStateEnum; +import io.github.hapjava.characteristics.impl.airquality.AirQualityCharacteristic; +import io.github.hapjava.characteristics.impl.airquality.AirQualityEnum; +import io.github.hapjava.characteristics.impl.battery.ChargingStateCharacteristic; +import io.github.hapjava.characteristics.impl.battery.ChargingStateEnum; +import io.github.hapjava.characteristics.impl.common.ActiveCharacteristic; +import io.github.hapjava.characteristics.impl.common.ActiveEnum; +import io.github.hapjava.characteristics.impl.common.ProgramModeCharacteristic; +import io.github.hapjava.characteristics.impl.common.ProgramModeEnum; +import io.github.hapjava.characteristics.impl.common.ServiceLabelNamespaceCharacteristic; +import io.github.hapjava.characteristics.impl.common.ServiceLabelNamespaceEnum; +import io.github.hapjava.characteristics.impl.fan.CurrentFanStateCharacteristic; +import io.github.hapjava.characteristics.impl.fan.CurrentFanStateEnum; +import io.github.hapjava.characteristics.impl.fan.LockPhysicalControlsCharacteristic; +import io.github.hapjava.characteristics.impl.fan.LockPhysicalControlsEnum; +import io.github.hapjava.characteristics.impl.fan.RotationDirectionCharacteristic; +import io.github.hapjava.characteristics.impl.fan.RotationDirectionEnum; +import io.github.hapjava.characteristics.impl.fan.SwingModeCharacteristic; +import io.github.hapjava.characteristics.impl.fan.SwingModeEnum; +import io.github.hapjava.characteristics.impl.fan.TargetFanStateCharacteristic; +import io.github.hapjava.characteristics.impl.fan.TargetFanStateEnum; +import io.github.hapjava.characteristics.impl.garagedoor.CurrentDoorStateCharacteristic; +import io.github.hapjava.characteristics.impl.garagedoor.CurrentDoorStateEnum; +import io.github.hapjava.characteristics.impl.garagedoor.TargetDoorStateCharacteristic; +import io.github.hapjava.characteristics.impl.garagedoor.TargetDoorStateEnum; +import io.github.hapjava.characteristics.impl.humidifier.CurrentHumidifierDehumidifierStateCharacteristic; +import io.github.hapjava.characteristics.impl.humidifier.CurrentHumidifierDehumidifierStateEnum; +import io.github.hapjava.characteristics.impl.inputsource.CurrentVisibilityStateCharacteristic; +import io.github.hapjava.characteristics.impl.inputsource.CurrentVisibilityStateEnum; +import io.github.hapjava.characteristics.impl.inputsource.InputDeviceTypeCharacteristic; +import io.github.hapjava.characteristics.impl.inputsource.InputDeviceTypeEnum; +import io.github.hapjava.characteristics.impl.inputsource.InputSourceTypeCharacteristic; +import io.github.hapjava.characteristics.impl.inputsource.InputSourceTypeEnum; +import io.github.hapjava.characteristics.impl.inputsource.TargetVisibilityStateCharacteristic; +import io.github.hapjava.characteristics.impl.inputsource.TargetVisibilityStateEnum; +import io.github.hapjava.characteristics.impl.lock.LockCurrentStateCharacteristic; +import io.github.hapjava.characteristics.impl.lock.LockCurrentStateEnum; +import io.github.hapjava.characteristics.impl.lock.LockTargetStateCharacteristic; +import io.github.hapjava.characteristics.impl.lock.LockTargetStateEnum; +import io.github.hapjava.characteristics.impl.slat.CurrentSlatStateCharacteristic; +import io.github.hapjava.characteristics.impl.slat.CurrentSlatStateEnum; +import io.github.hapjava.characteristics.impl.slat.SlatTypeCharacteristic; +import io.github.hapjava.characteristics.impl.slat.SlatTypeEnum; +import io.github.hapjava.characteristics.impl.television.ClosedCaptionsCharacteristic; +import io.github.hapjava.characteristics.impl.television.ClosedCaptionsEnum; +import io.github.hapjava.characteristics.impl.television.CurrentMediaStateCharacteristic; +import io.github.hapjava.characteristics.impl.television.CurrentMediaStateEnum; +import io.github.hapjava.characteristics.impl.television.PictureModeCharacteristic; +import io.github.hapjava.characteristics.impl.television.PictureModeEnum; +import io.github.hapjava.characteristics.impl.television.PowerModeCharacteristic; +import io.github.hapjava.characteristics.impl.television.PowerModeEnum; +import io.github.hapjava.characteristics.impl.television.RemoteKeyCharacteristic; +import io.github.hapjava.characteristics.impl.television.RemoteKeyEnum; +import io.github.hapjava.characteristics.impl.television.SleepDiscoveryModeCharacteristic; +import io.github.hapjava.characteristics.impl.television.SleepDiscoveryModeEnum; +import io.github.hapjava.characteristics.impl.television.TargetMediaStateCharacteristic; +import io.github.hapjava.characteristics.impl.television.TargetMediaStateEnum; +import io.github.hapjava.characteristics.impl.televisionspeaker.VolumeControlTypeCharacteristic; +import io.github.hapjava.characteristics.impl.televisionspeaker.VolumeControlTypeEnum; +import io.github.hapjava.characteristics.impl.televisionspeaker.VolumeSelectorCharacteristic; +import io.github.hapjava.characteristics.impl.televisionspeaker.VolumeSelectorEnum; +import io.github.hapjava.characteristics.impl.thermostat.TemperatureDisplayUnitCharacteristic; +import io.github.hapjava.characteristics.impl.thermostat.TemperatureDisplayUnitEnum; +import io.github.hapjava.characteristics.impl.valve.ValveTypeCharacteristic; +import io.github.hapjava.characteristics.impl.valve.ValveTypeEnum; +import io.github.hapjava.characteristics.impl.windowcovering.PositionStateCharacteristic; +import io.github.hapjava.characteristics.impl.windowcovering.PositionStateEnum; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import javax.json.Json; +import org.junit.Test; + +/** Custom valid values support, see https://github.com/hap-java/HAP-Java/issues/163 */ +public class CustomValidValuesCharacteristicsTest { + + @Test + public void defaultConstructorsKeepTheirSerializedOutput() { + // Serialized output captured before custom valid values were added. + for (Case c : + Arrays.asList( + Case.of( + new CurrentAirPurifierCharacteristic( + () -> CompletableFuture.completedFuture(CurrentAirPurifierStateEnum.INACTIVE), + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"A9\",\"perms\":[\"pr\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1,2]}"), + Case.of( + new TargetAirPurifierStateCharacteristic( + () -> CompletableFuture.completedFuture(TargetAirPurifierStateEnum.MANUAL), + v -> {}, + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"A8\",\"perms\":[\"pr\",\"pw\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1]}"), + Case.of( + new AirQualityCharacteristic( + () -> CompletableFuture.completedFuture(AirQualityEnum.UNKNOWN), + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"95\",\"perms\":[\"pr\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1,2,3,4,5]}"), + Case.of( + new ChargingStateCharacteristic( + () -> CompletableFuture.completedFuture(ChargingStateEnum.NOT_CHARGING), + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"8F\",\"perms\":[\"pr\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1,2]}"), + Case.of( + new ActiveCharacteristic( + () -> CompletableFuture.completedFuture(ActiveEnum.INACTIVE), + v -> {}, + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"B0\",\"perms\":[\"pr\",\"pw\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1]}"), + Case.of( + new ProgramModeCharacteristic( + () -> CompletableFuture.completedFuture(ProgramModeEnum.NO_SCHEDULED), + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"D1\",\"perms\":[\"pr\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1,2]}"), + Case.of( + new ServiceLabelNamespaceCharacteristic( + () -> CompletableFuture.completedFuture(ServiceLabelNamespaceEnum.DOTS)), + "{\"iid\":7,\"type\":\"CD\",\"perms\":[\"pr\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1]}"), + Case.of( + new CurrentFanStateCharacteristic( + () -> CompletableFuture.completedFuture(CurrentFanStateEnum.INACTIVE), + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"AF\",\"perms\":[\"pr\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1,2]}"), + Case.of( + new LockPhysicalControlsCharacteristic( + () -> + CompletableFuture.completedFuture( + LockPhysicalControlsEnum.CONTROL_LOCK_DISABLED), + v -> {}, + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"A7\",\"perms\":[\"pr\",\"pw\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1]}"), + Case.of( + new RotationDirectionCharacteristic( + () -> CompletableFuture.completedFuture(RotationDirectionEnum.CLOCKWISE), + v -> {}, + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"28\",\"perms\":[\"pr\",\"pw\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1]}"), + Case.of( + new SwingModeCharacteristic( + () -> CompletableFuture.completedFuture(SwingModeEnum.SWING_DISABLED), + v -> {}, + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"B6\",\"perms\":[\"pr\",\"pw\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1]}"), + Case.of( + new TargetFanStateCharacteristic( + () -> CompletableFuture.completedFuture(TargetFanStateEnum.MANUAL), + v -> {}, + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"BF\",\"perms\":[\"pr\",\"pw\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1]}"), + Case.of( + new CurrentDoorStateCharacteristic( + () -> CompletableFuture.completedFuture(CurrentDoorStateEnum.OPEN), + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"E\",\"perms\":[\"pr\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1,2,3,4]}"), + Case.of( + new TargetDoorStateCharacteristic( + () -> CompletableFuture.completedFuture(TargetDoorStateEnum.OPEN), + v -> {}, + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"32\",\"perms\":[\"pr\",\"pw\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1]}"), + Case.of( + new CurrentHumidifierDehumidifierStateCharacteristic( + () -> + CompletableFuture.completedFuture( + CurrentHumidifierDehumidifierStateEnum.INACTIVE), + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"B3\",\"perms\":[\"pr\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1,2,3]}"), + Case.of( + new CurrentVisibilityStateCharacteristic( + () -> CompletableFuture.completedFuture(CurrentVisibilityStateEnum.SHOWN), + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"135\",\"perms\":[\"pr\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1,2,3]}"), + Case.of( + new InputDeviceTypeCharacteristic( + () -> CompletableFuture.completedFuture(InputDeviceTypeEnum.OTHER), + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"DC\",\"perms\":[\"pr\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1,2,3,4,5]}"), + Case.of( + new InputSourceTypeCharacteristic( + () -> CompletableFuture.completedFuture(InputSourceTypeEnum.OTHER), + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"DB\",\"perms\":[\"pr\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1,2,3,4,5,6,7,8,9,10]}"), + Case.of( + new TargetVisibilityStateCharacteristic( + () -> CompletableFuture.completedFuture(TargetVisibilityStateEnum.SHOWN), + v -> {}, + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"134\",\"perms\":[\"pr\",\"pw\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1]}"), + Case.of( + new LockCurrentStateCharacteristic( + () -> CompletableFuture.completedFuture(LockCurrentStateEnum.UNSECURED), + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"1D\",\"perms\":[\"pr\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1,2,3]}"), + Case.of( + new LockTargetStateCharacteristic( + () -> CompletableFuture.completedFuture(LockTargetStateEnum.UNSECURED), + v -> {}, + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"1E\",\"perms\":[\"pr\",\"pw\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1]}"), + Case.of( + new CurrentSlatStateCharacteristic( + () -> CompletableFuture.completedFuture(CurrentSlatStateEnum.FIXED), + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"AA\",\"perms\":[\"pr\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1,2]}"), + Case.of( + new SlatTypeCharacteristic( + () -> CompletableFuture.completedFuture(SlatTypeEnum.HORIZONTAL)), + "{\"iid\":7,\"type\":\"C0\",\"perms\":[\"pr\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1]}"), + Case.of( + new ClosedCaptionsCharacteristic( + () -> CompletableFuture.completedFuture(ClosedCaptionsEnum.DISABLED), + v -> {}, + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"DD\",\"perms\":[\"pr\",\"pw\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1]}"), + Case.of( + new CurrentMediaStateCharacteristic( + () -> CompletableFuture.completedFuture(CurrentMediaStateEnum.PLAY), + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"E0\",\"perms\":[\"pr\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1,2,3]}"), + Case.of( + new PictureModeCharacteristic( + () -> CompletableFuture.completedFuture(PictureModeEnum.OTHER), + v -> {}, + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"E2\",\"perms\":[\"pr\",\"pw\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1,2,3,4,5,6,7]}"), + Case.of( + new PowerModeCharacteristic(v -> {}), + "{\"iid\":7,\"type\":\"DF\",\"perms\":[\"pw\"],\"format\":\"int\",\"valid-values\":[0,1]}"), + Case.of( + new RemoteKeyCharacteristic(v -> {}), + "{\"iid\":7,\"type\":\"E1\",\"perms\":[\"pw\"],\"format\":\"int\",\"valid-values\":[0,1,2,3,4,5,6,7,8,9,10,11,15]}"), + Case.of( + new SleepDiscoveryModeCharacteristic( + () -> + CompletableFuture.completedFuture(SleepDiscoveryModeEnum.NOT_DISCOVERABLE), + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"E8\",\"perms\":[\"pr\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1]}"), + Case.of( + new TargetMediaStateCharacteristic( + () -> CompletableFuture.completedFuture(TargetMediaStateEnum.PLAY), + v -> {}, + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"137\",\"perms\":[\"pr\",\"pw\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1,2]}"), + Case.of( + new VolumeControlTypeCharacteristic( + () -> CompletableFuture.completedFuture(VolumeControlTypeEnum.NONE), + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"E9\",\"perms\":[\"pr\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1,2,3]}"), + Case.of( + new VolumeSelectorCharacteristic(v -> {}), + "{\"iid\":7,\"type\":\"EA\",\"perms\":[\"pw\"],\"format\":\"int\",\"valid-values\":[0,1]}"), + Case.of( + new TemperatureDisplayUnitCharacteristic( + () -> CompletableFuture.completedFuture(TemperatureDisplayUnitEnum.CELSIUS), + v -> {}, + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"36\",\"perms\":[\"pr\",\"pw\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1]}"), + Case.of( + new ValveTypeCharacteristic( + () -> CompletableFuture.completedFuture(ValveTypeEnum.GENERIC), + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"D5\",\"perms\":[\"pr\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1,2,3]}"), + Case.of( + new PositionStateCharacteristic( + () -> CompletableFuture.completedFuture(PositionStateEnum.DECREASING), + cb -> {}, + () -> {}), + "{\"iid\":7,\"type\":\"72\",\"perms\":[\"pr\",\"ev\"],\"format\":\"int\",\"value\":0,\"valid-values\":[0,1,2]}"))) { + assertThat(c.characteristic.toJson(7).join().toString()) + .as(c.characteristic.getClass().getSimpleName()) + .isEqualTo(c.expected); + } + } + + @Test + public void customValidValuesAreAdvertised() { + for (Case c : + Arrays.asList( + Case.of( + new CurrentAirPurifierCharacteristic( + new CurrentAirPurifierStateEnum[] {CurrentAirPurifierStateEnum.PURIFYING_AIR}, + () -> CompletableFuture.completedFuture(CurrentAirPurifierStateEnum.INACTIVE), + cb -> {}, + () -> {}), + "[2]"), + Case.of( + new TargetAirPurifierStateCharacteristic( + new TargetAirPurifierStateEnum[] {TargetAirPurifierStateEnum.AUTO}, + () -> CompletableFuture.completedFuture(TargetAirPurifierStateEnum.MANUAL), + v -> {}, + cb -> {}, + () -> {}), + "[1]"), + Case.of( + new AirQualityCharacteristic( + new AirQualityEnum[] {AirQualityEnum.POOR}, + () -> CompletableFuture.completedFuture(AirQualityEnum.UNKNOWN), + cb -> {}, + () -> {}), + "[5]"), + Case.of( + new ChargingStateCharacteristic( + new ChargingStateEnum[] {ChargingStateEnum.NOT_CHARABLE}, + () -> CompletableFuture.completedFuture(ChargingStateEnum.NOT_CHARGING), + cb -> {}, + () -> {}), + "[2]"), + Case.of( + new ActiveCharacteristic( + new ActiveEnum[] {ActiveEnum.ACTIVE}, + () -> CompletableFuture.completedFuture(ActiveEnum.INACTIVE), + v -> {}, + cb -> {}, + () -> {}), + "[1]"), + Case.of( + new ProgramModeCharacteristic( + new ProgramModeEnum[] {ProgramModeEnum.SCHEDULED_MANUAL}, + () -> CompletableFuture.completedFuture(ProgramModeEnum.NO_SCHEDULED), + cb -> {}, + () -> {}), + "[2]"), + Case.of( + new ServiceLabelNamespaceCharacteristic( + new ServiceLabelNamespaceEnum[] {ServiceLabelNamespaceEnum.ARABIC_NUMERALS}, + () -> CompletableFuture.completedFuture(ServiceLabelNamespaceEnum.DOTS)), + "[1]"), + Case.of( + new CurrentFanStateCharacteristic( + new CurrentFanStateEnum[] {CurrentFanStateEnum.BLOWING_AIR}, + () -> CompletableFuture.completedFuture(CurrentFanStateEnum.INACTIVE), + cb -> {}, + () -> {}), + "[2]"), + Case.of( + new LockPhysicalControlsCharacteristic( + new LockPhysicalControlsEnum[] {LockPhysicalControlsEnum.CONTROL_LOCK_ENABLED}, + () -> + CompletableFuture.completedFuture( + LockPhysicalControlsEnum.CONTROL_LOCK_DISABLED), + v -> {}, + cb -> {}, + () -> {}), + "[1]"), + Case.of( + new RotationDirectionCharacteristic( + new RotationDirectionEnum[] {RotationDirectionEnum.COUNTER_CLOCKWISE}, + () -> CompletableFuture.completedFuture(RotationDirectionEnum.CLOCKWISE), + v -> {}, + cb -> {}, + () -> {}), + "[1]"), + Case.of( + new SwingModeCharacteristic( + new SwingModeEnum[] {SwingModeEnum.SWING_ENABLED}, + () -> CompletableFuture.completedFuture(SwingModeEnum.SWING_DISABLED), + v -> {}, + cb -> {}, + () -> {}), + "[1]"), + Case.of( + new TargetFanStateCharacteristic( + new TargetFanStateEnum[] {TargetFanStateEnum.AUTO}, + () -> CompletableFuture.completedFuture(TargetFanStateEnum.MANUAL), + v -> {}, + cb -> {}, + () -> {}), + "[1]"), + Case.of( + new CurrentDoorStateCharacteristic( + new CurrentDoorStateEnum[] {CurrentDoorStateEnum.STOPPED}, + () -> CompletableFuture.completedFuture(CurrentDoorStateEnum.OPEN), + cb -> {}, + () -> {}), + "[4]"), + Case.of( + new TargetDoorStateCharacteristic( + new TargetDoorStateEnum[] {TargetDoorStateEnum.CLOSED}, + () -> CompletableFuture.completedFuture(TargetDoorStateEnum.OPEN), + v -> {}, + cb -> {}, + () -> {}), + "[1]"), + Case.of( + new CurrentHumidifierDehumidifierStateCharacteristic( + new CurrentHumidifierDehumidifierStateEnum[] { + CurrentHumidifierDehumidifierStateEnum.DEHUMIDIFYING + }, + () -> + CompletableFuture.completedFuture( + CurrentHumidifierDehumidifierStateEnum.INACTIVE), + cb -> {}, + () -> {}), + "[3]"), + Case.of( + new CurrentVisibilityStateCharacteristic( + new CurrentVisibilityStateEnum[] {CurrentVisibilityStateEnum.UNKNOWN_2}, + () -> CompletableFuture.completedFuture(CurrentVisibilityStateEnum.SHOWN), + cb -> {}, + () -> {}), + "[3]"), + Case.of( + new InputDeviceTypeCharacteristic( + new InputDeviceTypeEnum[] {InputDeviceTypeEnum.AUDIO_SYSTEM}, + () -> CompletableFuture.completedFuture(InputDeviceTypeEnum.OTHER), + cb -> {}, + () -> {}), + "[5]"), + Case.of( + new InputSourceTypeCharacteristic( + new InputSourceTypeEnum[] {InputSourceTypeEnum.APPLICATION}, + () -> CompletableFuture.completedFuture(InputSourceTypeEnum.OTHER), + cb -> {}, + () -> {}), + "[10]"), + Case.of( + new TargetVisibilityStateCharacteristic( + new TargetVisibilityStateEnum[] {TargetVisibilityStateEnum.HIDDEN}, + () -> CompletableFuture.completedFuture(TargetVisibilityStateEnum.SHOWN), + v -> {}, + cb -> {}, + () -> {}), + "[1]"), + Case.of( + new LockCurrentStateCharacteristic( + new LockCurrentStateEnum[] {LockCurrentStateEnum.UNKNOWN}, + () -> CompletableFuture.completedFuture(LockCurrentStateEnum.UNSECURED), + cb -> {}, + () -> {}), + "[3]"), + Case.of( + new LockTargetStateCharacteristic( + new LockTargetStateEnum[] {LockTargetStateEnum.SECURED}, + () -> CompletableFuture.completedFuture(LockTargetStateEnum.UNSECURED), + v -> {}, + cb -> {}, + () -> {}), + "[1]"), + Case.of( + new CurrentSlatStateCharacteristic( + new CurrentSlatStateEnum[] {CurrentSlatStateEnum.SWINGING}, + () -> CompletableFuture.completedFuture(CurrentSlatStateEnum.FIXED), + cb -> {}, + () -> {}), + "[2]"), + Case.of( + new SlatTypeCharacteristic( + new SlatTypeEnum[] {SlatTypeEnum.VERTICAL}, + () -> CompletableFuture.completedFuture(SlatTypeEnum.HORIZONTAL)), + "[1]"), + Case.of( + new ClosedCaptionsCharacteristic( + new ClosedCaptionsEnum[] {ClosedCaptionsEnum.ENABLED}, + () -> CompletableFuture.completedFuture(ClosedCaptionsEnum.DISABLED), + v -> {}, + cb -> {}, + () -> {}), + "[1]"), + Case.of( + new CurrentMediaStateCharacteristic( + new CurrentMediaStateEnum[] {CurrentMediaStateEnum.UNKNOWN}, + () -> CompletableFuture.completedFuture(CurrentMediaStateEnum.PLAY), + cb -> {}, + () -> {}), + "[3]"), + Case.of( + new PictureModeCharacteristic( + new PictureModeEnum[] {PictureModeEnum.CUSTOM}, + () -> CompletableFuture.completedFuture(PictureModeEnum.OTHER), + v -> {}, + cb -> {}, + () -> {}), + "[7]"), + Case.of( + new PowerModeCharacteristic(new PowerModeEnum[] {PowerModeEnum.HIDE}, v -> {}), + "[1]"), + Case.of( + new RemoteKeyCharacteristic(new RemoteKeyEnum[] {RemoteKeyEnum.INFO}, v -> {}), + "[15]"), + Case.of( + new SleepDiscoveryModeCharacteristic( + new SleepDiscoveryModeEnum[] {SleepDiscoveryModeEnum.ALWAYS_DISCOVERABLE}, + () -> + CompletableFuture.completedFuture(SleepDiscoveryModeEnum.NOT_DISCOVERABLE), + cb -> {}, + () -> {}), + "[1]"), + Case.of( + new TargetMediaStateCharacteristic( + new TargetMediaStateEnum[] {TargetMediaStateEnum.STOP}, + () -> CompletableFuture.completedFuture(TargetMediaStateEnum.PLAY), + v -> {}, + cb -> {}, + () -> {}), + "[2]"), + Case.of( + new VolumeControlTypeCharacteristic( + new VolumeControlTypeEnum[] {VolumeControlTypeEnum.ABSOLUTE}, + () -> CompletableFuture.completedFuture(VolumeControlTypeEnum.NONE), + cb -> {}, + () -> {}), + "[3]"), + Case.of( + new VolumeSelectorCharacteristic( + new VolumeSelectorEnum[] {VolumeSelectorEnum.DECREMENT}, v -> {}), + "[1]"), + Case.of( + new TemperatureDisplayUnitCharacteristic( + new TemperatureDisplayUnitEnum[] {TemperatureDisplayUnitEnum.FAHRENHEIT}, + () -> CompletableFuture.completedFuture(TemperatureDisplayUnitEnum.CELSIUS), + v -> {}, + cb -> {}, + () -> {}), + "[1]"), + Case.of( + new ValveTypeCharacteristic( + new ValveTypeEnum[] {ValveTypeEnum.WATER_FAUCET}, + () -> CompletableFuture.completedFuture(ValveTypeEnum.GENERIC), + cb -> {}, + () -> {}), + "[3]"), + Case.of( + new PositionStateCharacteristic( + new PositionStateEnum[] {PositionStateEnum.STOPPED}, + () -> CompletableFuture.completedFuture(PositionStateEnum.DECREASING), + cb -> {}, + () -> {}), + "[2]"))) { + assertThat(c.characteristic.toJson(7).join().getJsonArray("valid-values").toString()) + .as(c.characteristic.getClass().getSimpleName()) + .isEqualTo(c.expected); + } + } + + @Test + public void writesOutsideCustomValidValuesAreIgnored() { + List written = new ArrayList<>(); + TemperatureDisplayUnitCharacteristic characteristic = + new TemperatureDisplayUnitCharacteristic( + new TemperatureDisplayUnitEnum[] {TemperatureDisplayUnitEnum.CELSIUS}, + () -> CompletableFuture.completedFuture(TemperatureDisplayUnitEnum.CELSIUS), + written::add, + cb -> {}, + () -> {}); + + characteristic.setValue(Json.createArrayBuilder().add(1).build().get(0)); + characteristic.setValue(Json.createArrayBuilder().add(0).build().get(0)); + + assertThat(written).containsExactly(TemperatureDisplayUnitEnum.CELSIUS); + } + + @Test + public void defaultIsFirstCustomValidValue() { + PositionStateCharacteristic characteristic = + new PositionStateCharacteristic( + new PositionStateEnum[] {PositionStateEnum.STOPPED, PositionStateEnum.DECREASING}, + () -> CompletableFuture.completedFuture(PositionStateEnum.STOPPED), + cb -> {}, + () -> {}); + + assertThat(characteristic.getDefault()).isEqualTo(PositionStateEnum.STOPPED.getCode()); + } + + private static class Case { + final Characteristic characteristic; + final String expected; + + private Case(Characteristic characteristic, String expected) { + this.characteristic = characteristic; + this.expected = expected; + } + + static Case of(Characteristic characteristic, String expected) { + return new Case(characteristic, expected); + } + } +}