]> git.basschouten.com Git - openhab-addons.git/commitdiff
[homekit] Allow configuring thermostat modes via metadata (#17056)
authorCody Cutrer <cody@cutrer.us>
Sun, 14 Jul 2024 22:18:10 +0000 (16:18 -0600)
committerGitHub <noreply@github.com>
Sun, 14 Jul 2024 22:18:10 +0000 (00:18 +0200)
* [homekit] allow configuring thermostat modes via metadata

Signed-off-by: Cody Cutrer <cody@cutrer.us>
44 files changed:
bundles/org.openhab.io.homekit/README.md
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitCharacteristicType.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/AbstractHomekitAccessoryImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/AbstractHomekitPositionAccessoryImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitAccessoryFactory.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitAccessoryGroupImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitAirQualitySensorImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitBasicFanImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitBatteryImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitCarbonDioxideSensorImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitCarbonMonoxideSensorImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitCharacteristicFactory.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitContactSensorImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitDoorImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitFanImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitFaucetImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitFilterMaintenanceImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitGarageDoorOpenerImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitHeaterCoolerImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitHumiditySensorImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitInputSourceImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitIrrigationSystemImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitLeakSensorImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitLightSensorImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitLightbulbImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitLockImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitMetadataCharacteristicFactory.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitMicrophoneImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitMotionSensorImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitOccupancySensorImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitOutletImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitSecuritySystemImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitSlatImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitSmartSpeakerImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitSmokeSensorImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitSpeakerImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitSwitchImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitTelevisionImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitTelevisionSpeakerImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitTemperatureSensorImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitThermostatImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitValveImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitWindowCoveringImpl.java
bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitWindowImpl.java

index fe562d006c76d8e4e31b1210d83195f0cb76672f..f1b539848599dbc2ca93bbbadd517850dfd3ab76 100644 (file)
@@ -899,6 +899,8 @@ All accessories also support the following optional characteristic that can be l
 |                      |                             | CoolingThresholdTemperature | Number                                  | Maximum temperature that must be reached before cooling is turned on                                                                                                                                                                                                                                                                                          | minValue (10), maxValue (35), step (0.1)                              |                                                                                                             |
 |                      |                             | HeatingThresholdTemperature | Number                                  | Minimum temperature that must be reached before heating is turned on                                                                                                                                                                                                                                                                                          | minValue (0), maxValue (25), step (0.1)                               |                                                                                                             |
 |                      |                             | RelativeHumidity            | Number                                  | Relative humidity in % between 0 and 100.                                                                                                                                                                                                                                                                                                                     |                                                                       |                                                                                                             |
+|                      |                             | TargetRelativeHumidity      | Number                                  | Target relative humidity in % between 0 and 100.                                                                                                                                                                                                                                                                                                              |                                                                       |                                                                                                             |
+|                      |                             | TemperatureUnit             | Number, String, Switch                  | The units the accessory itself uses to display the temperature. Can also be configured via metadata, e.g. [TemperatureUnit="CELSIUS"]                                                                                                                                                                                                                         |                                                                       | CELSIUS (0, OFF), FAHRENHEIT (1, ON)                                                                        |
 | Valve                |                             |                             |                                         | Valve                                                                                                                                                                                                                                                                                                                                                         | ValveType = ["Generic", "Irrigation", "Shower", "Faucet"] ("Generic") |                                                                                                             |
 |                      | ActiveStatus                |                             | Dimmer, Switch                          | Accessory current working status. A value of "ON"/"OPEN" indicates that the accessory is active and is functioning without any errors.                                                                                                                                                                                                                        |                                                                       |                                                                                                             |
 |                      | InUseStatus                 |                             | Contact, Dimmer, Switch                 | Indicates whether fluid flowing through the valve. A value of "ON"/"OPEN" indicates that fluid is flowing.                                                                                                                                                                                                                                                    | inverted (false)                                                      |                                                                                                             |
index 556b975facad138925d5afbe3185d7ede890664e..bd4052898ea5551bbeab24b7fddb57bb2bccb910 100644 (file)
@@ -90,6 +90,7 @@ public enum HomekitCharacteristicType {
     CURRENT_HEATING_COOLING_STATE("CurrentHeatingCoolingMode"),
     TARGET_TEMPERATURE("TargetTemperature"),
     TEMPERATURE_UNIT("TemperatureUnit"),
+    TARGET_RELATIVE_HUMIDITY("TargetRelativeHumidity"),
 
     LOCK_CURRENT_STATE("LockCurrentState"),
     LOCK_TARGET_STATE("LockTargetState"),
index 36836a01b6c023d732fdab9a084ad08947d07d09..25e1865321cc379714e1d6488b663aa646a94b55 100644 (file)
@@ -72,9 +72,10 @@ public abstract class AbstractHomekitAccessoryImpl implements HomekitAccessory {
     private final Map<Class<? extends Characteristic>, Characteristic> rawCharacteristics;
     private boolean isLinkedService = false;
 
-    public AbstractHomekitAccessoryImpl(HomekitTaggedItem accessory, List<HomekitTaggedItem> characteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) {
-        this.characteristics = characteristics;
+    public AbstractHomekitAccessoryImpl(HomekitTaggedItem accessory, List<HomekitTaggedItem> mandatoryCharacteristics,
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater,
+            HomekitSettings settings) {
+        this.characteristics = mandatoryCharacteristics;
         this.accessory = accessory;
         this.updater = updater;
         this.services = new ArrayList<>();
@@ -88,6 +89,15 @@ public abstract class AbstractHomekitAccessoryImpl implements HomekitAccessory {
                 rawCharacteristics.put(rawCharacteristic.getClass(), rawCharacteristic);
             }
         });
+        mandatoryRawCharacteristics.forEach(c -> {
+            if (rawCharacteristics.get(c.getClass()) != null) {
+                logger.warn(
+                        "Accessory {} already has a characteristic of type {}; ignoring additional definition from metadata.",
+                        accessory.getName(), c.getClass().getSimpleName());
+            } else {
+                rawCharacteristics.put(c.getClass(), c);
+            }
+        });
     }
 
     /**
index 5df0ac611c22d8e028866ccb022547e824ff7f93..08ba0be13de798f8c00c604d132547456e7289b5 100644 (file)
@@ -39,6 +39,7 @@ import org.openhab.io.homekit.internal.HomekitTaggedItem;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.windowcovering.PositionStateEnum;
 
@@ -58,9 +59,9 @@ abstract class AbstractHomekitPositionAccessoryImpl extends AbstractHomekitAcces
     protected PositionStateEnum emulatedState = PositionStateEnum.STOPPED;
 
     public AbstractHomekitPositionAccessoryImpl(HomekitTaggedItem taggedItem,
-            List<HomekitTaggedItem> mandatoryCharacteristics, HomekitAccessoryUpdater updater,
-            HomekitSettings settings) {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<HomekitTaggedItem> mandatoryCharacteristics, List<Characteristic> mandatoryRawCharacteristics,
+            HomekitAccessoryUpdater updater, HomekitSettings settings) {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         final boolean inverted = getAccessoryConfigurationAsBoolean(HomekitTaggedItem.INVERTED, true);
         emulateState = getAccessoryConfigurationAsBoolean(HomekitTaggedItem.EMULATE_STOP_STATE, false);
         emulateStopSameDirection = getAccessoryConfigurationAsBoolean(HomekitTaggedItem.EMULATE_STOP_SAME_DIRECTION,
index f84d11f0ff021586e575c16d0b78b46ad30f1663..ad14edb65f6ffd5994a8a4665c1ef1475c21a25e 100644 (file)
@@ -192,12 +192,14 @@ public class HomekitAccessoryFactory {
             throws HomekitException {
         final HomekitAccessoryType accessoryType = taggedItem.getAccessoryType();
         LOGGER.trace("Constructing {} of accessory type {}", taggedItem.getName(), accessoryType.getTag());
-        final List<HomekitTaggedItem> foundCharacteristics = getMandatoryCharacteristicsFromItem(taggedItem,
-                metadataRegistry);
+        final List<HomekitTaggedItem> characteristics = new ArrayList<>();
+        final List<Characteristic> rawCharacteristics = new ArrayList<>();
+
+        getMandatoryCharacteristicsFromItem(taggedItem, metadataRegistry, characteristics, rawCharacteristics);
         final List<HomekitCharacteristicType> mandatoryCharacteristics = getRequiredCharacteristics(taggedItem);
-        if (foundCharacteristics.size() < mandatoryCharacteristics.size()) {
-            LOGGER.warn("Accessory of type {} must have following characteristics {}. Found only {}",
-                    accessoryType.getTag(), mandatoryCharacteristics, foundCharacteristics);
+        if (characteristics.size() + rawCharacteristics.size() < mandatoryCharacteristics.size()) {
+            LOGGER.warn("Accessory of type {} must have following characteristics {}. Found only {}, {}",
+                    accessoryType.getTag(), mandatoryCharacteristics, characteristics, rawCharacteristics);
             throw new HomekitException("Missing mandatory characteristics");
         }
         AbstractHomekitAccessoryImpl accessoryImpl;
@@ -210,9 +212,10 @@ public class HomekitAccessoryFactory {
                             taggedItem.getName());
                     throw new HomekitException("Circular accessory references");
                 }
-                accessoryImpl = accessoryImplClass.getConstructor(HomekitTaggedItem.class, List.class,
-                        HomekitAccessoryUpdater.class, HomekitSettings.class)
-                        .newInstance(taggedItem, foundCharacteristics, updater, settings);
+                accessoryImpl = accessoryImplClass
+                        .getConstructor(HomekitTaggedItem.class, List.class, List.class, HomekitAccessoryUpdater.class,
+                                HomekitSettings.class)
+                        .newInstance(taggedItem, characteristics, rawCharacteristics, updater, settings);
                 addOptionalCharacteristics(taggedItem, accessoryImpl, metadataRegistry);
                 addOptionalMetadataCharacteristics(taggedItem, accessoryImpl);
                 accessoryImpl.setIsLinkedService(!ancestorServices.isEmpty());
@@ -298,18 +301,18 @@ public class HomekitAccessoryFactory {
      * @param metadataRegistry meta data registry
      * @return list of mandatory
      */
-    private static List<HomekitTaggedItem> getMandatoryCharacteristicsFromItem(HomekitTaggedItem taggedItem,
-            MetadataRegistry metadataRegistry) {
-        List<HomekitTaggedItem> collectedCharacteristics = new ArrayList<>();
+    private static void getMandatoryCharacteristicsFromItem(HomekitTaggedItem taggedItem,
+            MetadataRegistry metadataRegistry, List<HomekitTaggedItem> characteristics,
+            List<Characteristic> rawCharacteristics) {
         if (taggedItem.isGroup()) {
             for (Item item : ((GroupItem) taggedItem.getItem()).getMembers()) {
-                addMandatoryCharacteristics(taggedItem, collectedCharacteristics, item, metadataRegistry);
+                addMandatoryCharacteristics(taggedItem, characteristics, rawCharacteristics, item, metadataRegistry);
             }
         } else {
-            addMandatoryCharacteristics(taggedItem, collectedCharacteristics, taggedItem.getItem(), metadataRegistry);
+            addMandatoryCharacteristics(taggedItem, characteristics, rawCharacteristics, taggedItem.getItem(),
+                    metadataRegistry);
         }
-        LOGGER.trace("Mandatory characteristics: {}", collectedCharacteristics);
-        return collectedCharacteristics;
+        LOGGER.trace("Mandatory characteristics: {}, {}", characteristics, rawCharacteristics);
     }
 
     /**
@@ -325,7 +328,7 @@ public class HomekitAccessoryFactory {
      * @param metadataRegistry meta date registry
      */
     private static void addMandatoryCharacteristics(HomekitTaggedItem mainItem, List<HomekitTaggedItem> characteristics,
-            Item item, MetadataRegistry metadataRegistry) {
+            List<Characteristic> rawCharacteristics, Item item, MetadataRegistry metadataRegistry) {
         // get list of mandatory characteristics
         List<HomekitCharacteristicType> mandatoryCharacteristics = getRequiredCharacteristics(mainItem);
         if (mandatoryCharacteristics.isEmpty()) {
@@ -362,6 +365,23 @@ public class HomekitAccessoryFactory {
                 }
             }
         }
+        mandatoryCharacteristics.forEach(c -> {
+            // Check every metadata key looking for a characteristics we can create
+            var config = mainItem.getConfiguration();
+            if (config == null) {
+                return;
+            }
+            for (var entry : config.entrySet().stream().sorted((lhs, rhs) -> lhs.getKey().compareTo(rhs.getKey()))
+                    .collect(Collectors.toList())) {
+                var type = HomekitCharacteristicType.valueOfTag(entry.getKey());
+                if (type.isPresent() && isMandatoryCharacteristic(mainItem, type.get())) {
+                    var characteristic = HomekitMetadataCharacteristicFactory.createCharacteristic(type.get(),
+                            entry.getValue());
+
+                    characteristic.ifPresent(rc -> rawCharacteristics.add(rc));
+                }
+            }
+        });
     }
 
     /**
index ddc176bd9e98e5f3d44752bcd72903661ea48e50..579f62d0b213dff6e9a5c868490dcbe67eeb20f6 100644 (file)
@@ -19,6 +19,8 @@ import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
 import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
+import io.github.hapjava.characteristics.Characteristic;
+
 /**
  * Bare accessory (for being the root of a multi-service accessory).
  *
@@ -27,7 +29,8 @@ import org.openhab.io.homekit.internal.HomekitTaggedItem;
 @NonNullByDefault
 public class HomekitAccessoryGroupImpl extends AbstractHomekitAccessoryImpl {
     public HomekitAccessoryGroupImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
     }
 }
index 73b0646d29c8546fa852089a4d3416c199e915ec..946201b0d9058c24889d02b3b27ee867e44022f1 100644 (file)
@@ -24,6 +24,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.AirQualityAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.airquality.AirQualityEnum;
 import io.github.hapjava.services.impl.AirQualityService;
@@ -37,8 +38,9 @@ public class HomekitAirQualitySensorImpl extends AbstractHomekitAccessoryImpl im
     private final Map<AirQualityEnum, String> qualityStateMapping;
 
     public HomekitAirQualitySensorImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         qualityStateMapping = createMapping(AIR_QUALITY, AirQualityEnum.class);
     }
 
index 5e4066894a6e8573fcbe5102af00c25874c0c8ee..ef35afad08042b2ce8795c513a9de8bbcea2416e 100644 (file)
@@ -24,6 +24,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.BasicFanAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.services.impl.BasicFanService;
 
@@ -37,8 +38,9 @@ class HomekitBasicFanImpl extends AbstractHomekitAccessoryImpl implements BasicF
     private final BooleanItemReader onReader;
 
     public HomekitBasicFanImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         onReader = createBooleanReader(ON_STATE);
     }
 
index 3ca666afd3dbe22f7a98eb92d1e3649e8804e5d4..b4ce91d841d797e6a9781d81c0897a25fab86c6c 100644 (file)
@@ -29,6 +29,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.BatteryAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.battery.ChargingStateEnum;
 import io.github.hapjava.characteristics.impl.battery.StatusLowBatteryEnum;
@@ -48,8 +49,9 @@ public class HomekitBatteryImpl extends AbstractHomekitAccessoryImpl implements
     private final BigDecimal lowThreshold;
 
     public HomekitBatteryImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         lowThreshold = getAccessoryConfiguration(HomekitCharacteristicType.BATTERY_LOW_STATUS,
                 HomekitTaggedItem.BATTERY_LOW_THRESHOLD, BigDecimal.valueOf(20));
         lowBatteryReader = createBooleanReader(BATTERY_LOW_STATUS, lowThreshold, true);
index adfe18314ec992d3071abaeee776ed45564fea86..d8a099b802f36a1c8147eae59dd7005d11f5ab9d 100644 (file)
@@ -24,6 +24,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.CarbonDioxideSensorAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.carbondioxidesensor.CarbonDioxideDetectedEnum;
 import io.github.hapjava.services.impl.CarbonDioxideSensorService;
@@ -37,9 +38,9 @@ public class HomekitCarbonDioxideSensorImpl extends AbstractHomekitAccessoryImpl
     private final Map<CarbonDioxideDetectedEnum, String> mapping;
 
     public HomekitCarbonDioxideSensorImpl(HomekitTaggedItem taggedItem,
-            List<HomekitTaggedItem> mandatoryCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
-            throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<HomekitTaggedItem> mandatoryCharacteristics, List<Characteristic> mandatoryRawCharacteristics,
+            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         mapping = createMapping(CARBON_DIOXIDE_DETECTED_STATE, CarbonDioxideDetectedEnum.class);
     }
 
index 29693a6baf890071b75a7475ca55a14bef74c966..179c223434f9e8d4440d1d64e9e545ba89a81bf1 100644 (file)
@@ -24,6 +24,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.CarbonMonoxideSensorAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.carbonmonoxidesensor.CarbonMonoxideDetectedEnum;
 import io.github.hapjava.services.impl.CarbonMonoxideSensorService;
@@ -37,9 +38,9 @@ public class HomekitCarbonMonoxideSensorImpl extends AbstractHomekitAccessoryImp
     private final Map<CarbonMonoxideDetectedEnum, String> mapping;
 
     public HomekitCarbonMonoxideSensorImpl(HomekitTaggedItem taggedItem,
-            List<HomekitTaggedItem> mandatoryCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
-            throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<HomekitTaggedItem> mandatoryCharacteristics, List<Characteristic> mandatoryRawCharacteristics,
+            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         mapping = createMapping(CARBON_MONOXIDE_DETECTED_STATE, CarbonMonoxideDetectedEnum.class);
     }
 
index cd5126887c69bc882d8ad6ce5f2d4345ebdad278..4ecd982778a84244f4f4ac08dd535a8f67b008d1 100644 (file)
@@ -16,6 +16,7 @@ import static org.openhab.io.homekit.internal.HomekitCharacteristicType.*;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.util.ArrayList;
 import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.List;
@@ -116,6 +117,7 @@ import io.github.hapjava.characteristics.impl.fan.TargetFanStateEnum;
 import io.github.hapjava.characteristics.impl.filtermaintenance.FilterLifeLevelCharacteristic;
 import io.github.hapjava.characteristics.impl.filtermaintenance.ResetFilterIndicationCharacteristic;
 import io.github.hapjava.characteristics.impl.humiditysensor.CurrentRelativeHumidityCharacteristic;
+import io.github.hapjava.characteristics.impl.humiditysensor.TargetRelativeHumidityCharacteristic;
 import io.github.hapjava.characteristics.impl.inputsource.CurrentVisibilityStateCharacteristic;
 import io.github.hapjava.characteristics.impl.inputsource.CurrentVisibilityStateEnum;
 import io.github.hapjava.characteristics.impl.inputsource.InputDeviceTypeCharacteristic;
@@ -149,7 +151,15 @@ import io.github.hapjava.characteristics.impl.televisionspeaker.VolumeControlTyp
 import io.github.hapjava.characteristics.impl.televisionspeaker.VolumeSelectorCharacteristic;
 import io.github.hapjava.characteristics.impl.televisionspeaker.VolumeSelectorEnum;
 import io.github.hapjava.characteristics.impl.thermostat.CoolingThresholdTemperatureCharacteristic;
+import io.github.hapjava.characteristics.impl.thermostat.CurrentHeatingCoolingStateCharacteristic;
+import io.github.hapjava.characteristics.impl.thermostat.CurrentHeatingCoolingStateEnum;
+import io.github.hapjava.characteristics.impl.thermostat.CurrentTemperatureCharacteristic;
 import io.github.hapjava.characteristics.impl.thermostat.HeatingThresholdTemperatureCharacteristic;
+import io.github.hapjava.characteristics.impl.thermostat.TargetHeatingCoolingStateCharacteristic;
+import io.github.hapjava.characteristics.impl.thermostat.TargetHeatingCoolingStateEnum;
+import io.github.hapjava.characteristics.impl.thermostat.TargetTemperatureCharacteristic;
+import io.github.hapjava.characteristics.impl.thermostat.TemperatureDisplayUnitCharacteristic;
+import io.github.hapjava.characteristics.impl.thermostat.TemperatureDisplayUnitEnum;
 import io.github.hapjava.characteristics.impl.valve.RemainingDurationCharacteristic;
 import io.github.hapjava.characteristics.impl.valve.SetDurationCharacteristic;
 import io.github.hapjava.characteristics.impl.windowcovering.CurrentHorizontalTiltAngleCharacteristic;
@@ -184,6 +194,8 @@ public class HomekitCharacteristicFactory {
             put(CONFIGURED, HomekitCharacteristicFactory::createIsConfiguredCharacteristic);
             put(CONFIGURED_NAME, HomekitCharacteristicFactory::createConfiguredNameCharacteristic);
             put(COOLING_THRESHOLD_TEMPERATURE, HomekitCharacteristicFactory::createCoolingThresholdCharacteristic);
+            put(CURRENT_HEATING_COOLING_STATE,
+                    HomekitCharacteristicFactory::createCurrentHeatingCoolingStateCharacteristic);
             put(CURRENT_FAN_STATE, HomekitCharacteristicFactory::createCurrentFanStateCharacteristic);
             put(CURRENT_HORIZONTAL_TILT_ANGLE,
                     HomekitCharacteristicFactory::createCurrentHorizontalTiltAngleCharacteristic);
@@ -192,6 +204,7 @@ public class HomekitCharacteristicFactory {
             put(CURRENT_VERTICAL_TILT_ANGLE,
                     HomekitCharacteristicFactory::createCurrentVerticalTiltAngleCharacteristic);
             put(CURRENT_VISIBILITY, HomekitCharacteristicFactory::createCurrentVisibilityStateCharacteristic);
+            put(CURRENT_TEMPERATURE, HomekitCharacteristicFactory::createCurrentTemperatureCharacteristic);
             put(DURATION, HomekitCharacteristicFactory::createDurationCharacteristic);
             put(FAULT_STATUS, HomekitCharacteristicFactory::createStatusFaultCharacteristic);
             put(FIRMWARE_REVISION, HomekitCharacteristicFactory::createFirmwareRevisionCharacteristic);
@@ -229,12 +242,17 @@ public class HomekitCharacteristicFactory {
             put(SWING_MODE, HomekitCharacteristicFactory::createSwingModeCharacteristic);
             put(TAMPERED_STATUS, HomekitCharacteristicFactory::createStatusTamperedCharacteristic);
             put(TARGET_FAN_STATE, HomekitCharacteristicFactory::createTargetFanStateCharacteristic);
+            put(TARGET_HEATING_COOLING_STATE,
+                    HomekitCharacteristicFactory::createTargetHeatingCoolingStateCharacteristic);
             put(TARGET_HORIZONTAL_TILT_ANGLE,
                     HomekitCharacteristicFactory::createTargetHorizontalTiltAngleCharacteristic);
             put(TARGET_MEDIA_STATE, HomekitCharacteristicFactory::createTargetMediaStateCharacteristic);
+            put(TARGET_RELATIVE_HUMIDITY, HomekitCharacteristicFactory::createTargetRelativeHumidityCharacteristic);
+            put(TARGET_TEMPERATURE, HomekitCharacteristicFactory::createTargetTemperatureCharacteristic);
             put(TARGET_TILT_ANGLE, HomekitCharacteristicFactory::createTargetTiltAngleCharacteristic);
             put(TARGET_VERTICAL_TILT_ANGLE, HomekitCharacteristicFactory::createTargetVerticalTiltAngleCharacteristic);
             put(TARGET_VISIBILITY_STATE, HomekitCharacteristicFactory::createTargetVisibilityStateCharacteristic);
+            put(TEMPERATURE_UNIT, HomekitCharacteristicFactory::createTemperatureDisplayUnitCharacteristic);
             put(VOC_DENSITY, HomekitCharacteristicFactory::createVOCDensityCharacteristic);
             put(VOLUME, HomekitCharacteristicFactory::createVolumeCharacteristic);
             put(VOLUME_CONTROL_TYPE, HomekitCharacteristicFactory::createVolumeControlTypeCharacteristic);
@@ -339,6 +357,9 @@ public class HomekitCharacteristicFactory {
                 }
             });
         }
+        if (customEnumList != null && customEnumList.isEmpty()) {
+            customEnumList.addAll(map.keySet());
+        }
         LOGGER.debug("Created {} mapping for item {} ({}): {}", klazz.getSimpleName(), item.getName(),
                 item.getBaseItem().getClass().getSimpleName(), map);
         return map;
@@ -349,6 +370,11 @@ public class HomekitCharacteristicFactory {
         return createMapping(item, klazz, null, false);
     }
 
+    public static <T extends Enum<T> & CharacteristicEnum> Map<T, String> createMapping(HomekitTaggedItem item,
+            Class<T> klazz, @Nullable List<T> customEnumList) {
+        return createMapping(item, klazz, customEnumList, false);
+    }
+
     public static <T extends Enum<T> & CharacteristicEnum> Map<T, String> createMapping(HomekitTaggedItem item,
             Class<T> klazz, boolean inverted) {
         return createMapping(item, klazz, null, inverted);
@@ -405,6 +431,16 @@ public class HomekitCharacteristicFactory {
                 .getServiceReference(Homekit.class.getName()).getProperty("useFahrenheitTemperature"));
     }
 
+    public static TemperatureDisplayUnitCharacteristic createSystemTemperatureDisplayUnitCharacteristic() {
+        return new TemperatureDisplayUnitCharacteristic(() -> CompletableFuture
+                .completedFuture(HomekitCharacteristicFactory.useFahrenheit() ? TemperatureDisplayUnitEnum.FAHRENHEIT
+                        : TemperatureDisplayUnitEnum.CELSIUS),
+                (value) -> {
+                }, (cb) -> {
+                }, () -> {
+                });
+    }
+
     private static <T extends CharacteristicEnum> CompletableFuture<T> getEnumFromItem(HomekitTaggedItem item,
             Map<T, String> mapping, T defaultValue) {
         return CompletableFuture.completedFuture(getKeyFromMapping(item, mapping, defaultValue));
@@ -761,6 +797,16 @@ public class HomekitCharacteristicFactory {
                 getUnsubscriber(taggedItem, COOLING_THRESHOLD_TEMPERATURE, updater));
     }
 
+    private static CurrentHeatingCoolingStateCharacteristic createCurrentHeatingCoolingStateCharacteristic(
+            HomekitTaggedItem taggedItem, HomekitAccessoryUpdater updater) {
+        List<CurrentHeatingCoolingStateEnum> validValues = new ArrayList<>();
+        var map = createMapping(taggedItem, CurrentHeatingCoolingStateEnum.class, validValues);
+        return new CurrentHeatingCoolingStateCharacteristic(validValues.toArray(new CurrentHeatingCoolingStateEnum[0]),
+                () -> getEnumFromItem(taggedItem, map, CurrentHeatingCoolingStateEnum.OFF),
+                getSubscriber(taggedItem, CURRENT_HEATING_COOLING_STATE, updater),
+                getUnsubscriber(taggedItem, CURRENT_HEATING_COOLING_STATE, updater));
+    }
+
     private static CurrentFanStateCharacteristic createCurrentFanStateCharacteristic(HomekitTaggedItem taggedItem,
             HomekitAccessoryUpdater updater) {
         var map = createMapping(taggedItem, CurrentFanStateEnum.class);
@@ -785,6 +831,18 @@ public class HomekitCharacteristicFactory {
                 getUnsubscriber(taggedItem, CURRENT_MEDIA_STATE, updater));
     }
 
+    private static CurrentTemperatureCharacteristic createCurrentTemperatureCharacteristic(HomekitTaggedItem taggedItem,
+            HomekitAccessoryUpdater updater) {
+        double minValue = HomekitCharacteristicFactory.convertToCelsius(taggedItem.getConfigurationAsDouble(
+                HomekitTaggedItem.MIN_VALUE, CurrentTemperatureCharacteristic.DEFAULT_MIN_VALUE));
+        double maxValue = HomekitCharacteristicFactory.convertToCelsius(taggedItem.getConfigurationAsDouble(
+                HomekitTaggedItem.MAX_VALUE, CurrentTemperatureCharacteristic.DEFAULT_MAX_VALUE));
+        double step = getTemperatureStep(taggedItem, CurrentTemperatureCharacteristic.DEFAULT_STEP);
+        return new CurrentTemperatureCharacteristic(minValue, maxValue, step,
+                getTemperatureSupplier(taggedItem, minValue), getSubscriber(taggedItem, TARGET_TEMPERATURE, updater),
+                getUnsubscriber(taggedItem, TARGET_TEMPERATURE, updater));
+    }
+
     private static CurrentTiltAngleCharacteristic createCurrentTiltAngleCharacteristic(HomekitTaggedItem taggedItem,
             HomekitAccessoryUpdater updater) {
         return new CurrentTiltAngleCharacteristic(getAngleSupplier(taggedItem, 0),
@@ -1192,6 +1250,17 @@ public class HomekitCharacteristicFactory {
                 getUnsubscriber(taggedItem, TARGET_FAN_STATE, updater));
     }
 
+    private static TargetHeatingCoolingStateCharacteristic createTargetHeatingCoolingStateCharacteristic(
+            HomekitTaggedItem taggedItem, HomekitAccessoryUpdater updater) {
+        List<TargetHeatingCoolingStateEnum> validValues = new ArrayList<>();
+        var map = createMapping(taggedItem, TargetHeatingCoolingStateEnum.class, validValues);
+        return new TargetHeatingCoolingStateCharacteristic(validValues.toArray(new TargetHeatingCoolingStateEnum[0]),
+                () -> getEnumFromItem(taggedItem, map, TargetHeatingCoolingStateEnum.OFF),
+                (value) -> setValueFromEnum(taggedItem, value, map),
+                getSubscriber(taggedItem, TARGET_HEATING_COOLING_STATE, updater),
+                getUnsubscriber(taggedItem, TARGET_HEATING_COOLING_STATE, updater));
+    }
+
     private static TargetHorizontalTiltAngleCharacteristic createTargetHorizontalTiltAngleCharacteristic(
             HomekitTaggedItem taggedItem, HomekitAccessoryUpdater updater) {
         return new TargetHorizontalTiltAngleCharacteristic(getAngleSupplier(taggedItem, 0),
@@ -1208,6 +1277,26 @@ public class HomekitCharacteristicFactory {
                 getUnsubscriber(taggedItem, TARGET_MEDIA_STATE, updater));
     }
 
+    private static TargetRelativeHumidityCharacteristic createTargetRelativeHumidityCharacteristic(
+            HomekitTaggedItem item, HomekitAccessoryUpdater updater) {
+        return new TargetRelativeHumidityCharacteristic(getDoubleSupplier(item, 0), setDoubleConsumer(item),
+                getSubscriber(item, TARGET_RELATIVE_HUMIDITY, updater),
+                getUnsubscriber(item, TARGET_RELATIVE_HUMIDITY, updater));
+    }
+
+    private static TargetTemperatureCharacteristic createTargetTemperatureCharacteristic(HomekitTaggedItem taggedItem,
+            HomekitAccessoryUpdater updater) {
+        double minValue = HomekitCharacteristicFactory.convertToCelsius(taggedItem.getConfigurationAsDouble(
+                HomekitTaggedItem.MIN_VALUE, TargetTemperatureCharacteristic.DEFAULT_MIN_VALUE));
+        double maxValue = HomekitCharacteristicFactory.convertToCelsius(taggedItem.getConfigurationAsDouble(
+                HomekitTaggedItem.MAX_VALUE, TargetTemperatureCharacteristic.DEFAULT_MAX_VALUE));
+        double step = getTemperatureStep(taggedItem, TargetTemperatureCharacteristic.DEFAULT_STEP);
+        return new TargetTemperatureCharacteristic(minValue, maxValue, step,
+                getTemperatureSupplier(taggedItem, minValue), setTemperatureConsumer(taggedItem),
+                getSubscriber(taggedItem, TARGET_TEMPERATURE, updater),
+                getUnsubscriber(taggedItem, TARGET_TEMPERATURE, updater));
+    }
+
     private static TargetTiltAngleCharacteristic createTargetTiltAngleCharacteristic(HomekitTaggedItem taggedItem,
             HomekitAccessoryUpdater updater) {
         return new TargetTiltAngleCharacteristic(getAngleSupplier(taggedItem, 0), setAngleConsumer(taggedItem),
@@ -1232,6 +1321,17 @@ public class HomekitCharacteristicFactory {
                 getUnsubscriber(taggedItem, TARGET_VISIBILITY_STATE, updater));
     }
 
+    private static TemperatureDisplayUnitCharacteristic createTemperatureDisplayUnitCharacteristic(
+            HomekitTaggedItem taggedItem, HomekitAccessoryUpdater updater) {
+        var map = createMapping(taggedItem, TemperatureDisplayUnitEnum.class, true);
+        return new TemperatureDisplayUnitCharacteristic(
+                () -> getEnumFromItem(taggedItem, map,
+                        useFahrenheit() ? TemperatureDisplayUnitEnum.FAHRENHEIT : TemperatureDisplayUnitEnum.CELSIUS),
+                (value) -> setValueFromEnum(taggedItem, value, map),
+                getSubscriber(taggedItem, TEMPERATURE_UNIT, updater),
+                getUnsubscriber(taggedItem, TEMPERATURE_UNIT, updater));
+    }
+
     private static VOCDensityCharacteristic createVOCDensityCharacteristic(final HomekitTaggedItem taggedItem,
             HomekitAccessoryUpdater updater) {
         return new VOCDensityCharacteristic(
index bb6cc5f6148beb9747ccd8a8e7c0dc6405b899c9..b02d6ad59e5699ab781428dc9b2dd772af34cb64 100644 (file)
@@ -24,6 +24,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.ContactSensorAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.contactsensor.ContactStateEnum;
 import io.github.hapjava.services.impl.ContactSensorService;
@@ -36,8 +37,9 @@ public class HomekitContactSensorImpl extends AbstractHomekitAccessoryImpl imple
     private final Map<ContactStateEnum, String> mapping;
 
     public HomekitContactSensorImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         mapping = createMapping(CONTACT_SENSOR_STATE, ContactStateEnum.class);
     }
 
index 7e51d3f7f9f786a89583dafd558d1a4141a061bc..e5dd42edc491d50f076b6569635e81e628030acd 100644 (file)
@@ -22,6 +22,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.DoorAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.windowcovering.PositionStateEnum;
 import io.github.hapjava.services.impl.DoorService;
@@ -34,8 +35,9 @@ import io.github.hapjava.services.impl.DoorService;
 public class HomekitDoorImpl extends AbstractHomekitPositionAccessoryImpl implements DoorAccessory {
 
     public HomekitDoorImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater,
+            HomekitSettings settings) {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
     }
 
     @Override
index 416fa6e31beeb3c91bb7b6496a0a721bbb42483a..8f09fb1874cd3d624503b1c1aaf5da83da3f7544 100644 (file)
@@ -23,6 +23,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.FanAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.services.impl.FanService;
 
@@ -35,8 +36,9 @@ class HomekitFanImpl extends AbstractHomekitAccessoryImpl implements FanAccessor
     private final BooleanItemReader activeReader;
 
     public HomekitFanImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         activeReader = createBooleanReader(ACTIVE_STATUS);
     }
 
index a2fb8248422dbcf5128d5becc68c5af939127377..cb6642c706be6680afba79dd2b894c51e8a7ff20 100644 (file)
@@ -23,6 +23,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.FaucetAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.services.impl.FaucetService;
 
@@ -35,8 +36,9 @@ class HomekitFaucetImpl extends AbstractHomekitAccessoryImpl implements FaucetAc
     private final BooleanItemReader activeReader;
 
     public HomekitFaucetImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         activeReader = createBooleanReader(ACTIVE);
     }
 
index 792922ee5fff2586bdf664a3b8ed728bdaeab512..2dcfcc046e10357caac36a5e77ed770b3d2b65a4 100644 (file)
@@ -24,6 +24,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.FilterMaintenanceAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.filtermaintenance.FilterChangeIndicationEnum;
 import io.github.hapjava.services.impl.FilterMaintenanceService;
@@ -37,8 +38,9 @@ public class HomekitFilterMaintenanceImpl extends AbstractHomekitAccessoryImpl i
     private final Map<FilterChangeIndicationEnum, String> mapping;
 
     public HomekitFilterMaintenanceImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         mapping = createMapping(FILTER_CHANGE_INDICATION, FilterChangeIndicationEnum.class);
     }
 
index b217f3e1f991541733f1fb467fe2b454a675395c..8a43da9a8daebd07b56a890791f9c496fbe352a8 100644 (file)
@@ -28,6 +28,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import io.github.hapjava.accessories.GarageDoorOpenerAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.garagedoor.CurrentDoorStateEnum;
 import io.github.hapjava.characteristics.impl.garagedoor.TargetDoorStateEnum;
@@ -45,8 +46,9 @@ public class HomekitGarageDoorOpenerImpl extends AbstractHomekitAccessoryImpl im
     private final Map<TargetDoorStateEnum, String> targetDoorStateMapping;
 
     public HomekitGarageDoorOpenerImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         obstructionReader = createBooleanReader(OBSTRUCTION_STATUS);
         currentDoorStateMapping = createMapping(CURRENT_DOOR_STATE, CurrentDoorStateEnum.class, true);
         targetDoorStateMapping = createMapping(TARGET_DOOR_STATE, TargetDoorStateEnum.class, true);
index c85286ce68d3c33d21c59d9d236720612aebdd9a..4a84ee72bb9f555a241158256ed582a9b37bba55 100644 (file)
@@ -35,12 +35,12 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import io.github.hapjava.accessories.HeaterCoolerAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.heatercooler.CurrentHeaterCoolerStateEnum;
 import io.github.hapjava.characteristics.impl.heatercooler.TargetHeaterCoolerStateEnum;
 import io.github.hapjava.characteristics.impl.thermostat.CurrentTemperatureCharacteristic;
 import io.github.hapjava.characteristics.impl.thermostat.TemperatureDisplayUnitCharacteristic;
-import io.github.hapjava.characteristics.impl.thermostat.TemperatureDisplayUnitEnum;
 import io.github.hapjava.services.impl.HeaterCoolerService;
 
 /**
@@ -59,8 +59,9 @@ public class HomekitHeaterCoolerImpl extends AbstractHomekitAccessoryImpl implem
     private final List<TargetHeaterCoolerStateEnum> customTargetStateList = new ArrayList<>();
 
     public HomekitHeaterCoolerImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         activeReader = new BooleanItemReader(getItem(ACTIVE_STATUS, GenericItem.class)
                 .orElseThrow(() -> new IncompleteAccessoryException(ACTIVE_STATUS)), OnOffType.ON, OpenClosedType.OPEN);
         currentStateMapping = createMapping(CURRENT_HEATER_COOLER_STATE, CurrentHeaterCoolerStateEnum.class,
@@ -73,10 +74,14 @@ public class HomekitHeaterCoolerImpl extends AbstractHomekitAccessoryImpl implem
     public void init() throws HomekitException {
         super.init();
         final HeaterCoolerService service = new HeaterCoolerService(this);
+
+        var temperatureDisplayUnit = getCharacteristic(TemperatureDisplayUnitCharacteristic.class);
+        if (temperatureDisplayUnit.isEmpty()) {
+            service.addOptionalCharacteristic(
+                    HomekitCharacteristicFactory.createSystemTemperatureDisplayUnitCharacteristic());
+        }
+
         addService(service);
-        service.addOptionalCharacteristic(new TemperatureDisplayUnitCharacteristic(this::getTemperatureDisplayUnit,
-                this::setTemperatureDisplayUnit, this::subscribeTemperatureDisplayUnit,
-                this::unsubscribeTemperatureDisplayUnit));
     }
 
     @Override
@@ -133,17 +138,6 @@ public class HomekitHeaterCoolerImpl extends AbstractHomekitAccessoryImpl implem
         return CompletableFuture.completedFuture(null);
     }
 
-    public CompletableFuture<TemperatureDisplayUnitEnum> getTemperatureDisplayUnit() {
-        return CompletableFuture
-                .completedFuture(HomekitCharacteristicFactory.useFahrenheit() ? TemperatureDisplayUnitEnum.FAHRENHEIT
-                        : TemperatureDisplayUnitEnum.CELSIUS);
-    }
-
-    public void setTemperatureDisplayUnit(TemperatureDisplayUnitEnum value) {
-        // temperature unit set globally via binding setting and cannot be changed at item level.
-        // this method is intentionally empty.
-    }
-
     @Override
     public void subscribeCurrentHeaterCoolerState(HomekitCharacteristicChangeCallback callback) {
         subscribe(HomekitCharacteristicType.CURRENT_HEATER_COOLER_STATE, callback);
@@ -183,14 +177,4 @@ public class HomekitHeaterCoolerImpl extends AbstractHomekitAccessoryImpl implem
     public void unsubscribeCurrentTemperature() {
         unsubscribe(HomekitCharacteristicType.CURRENT_TEMPERATURE);
     }
-
-    public void subscribeTemperatureDisplayUnit(HomekitCharacteristicChangeCallback callback) {
-        // temperature unit set globally via binding setting and cannot be changed at item level.
-        // this method is intentionally empty
-    }
-
-    public void unsubscribeTemperatureDisplayUnit() {
-        // temperature unit set globally via binding setting and cannot be changed at item level.
-        // this method is intentionally empty
-    }
 }
index cb3c38e6c3d91e84926c194aef9fb379f16d8c0d..c470571aa2fe08bb30e80f24550f735ccb9be7a7 100644 (file)
@@ -25,6 +25,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.HumiditySensorAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.services.impl.HumiditySensorService;
 
@@ -36,8 +37,9 @@ public class HomekitHumiditySensorImpl extends AbstractHomekitAccessoryImpl impl
     private static final String CONFIG_MULTIPLICATOR = "homekitMultiplicator";
 
     public HomekitHumiditySensorImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater,
+            HomekitSettings settings) {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
     }
 
     @Override
index dcca031e0c913aefd186a29fc7f50f7611c8fed1..8085dffc32e2552d6af4b7c985af809f826a6998 100644 (file)
@@ -22,6 +22,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.HomekitAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.impl.common.ConfiguredNameCharacteristic;
 import io.github.hapjava.characteristics.impl.common.IdentifierCharacteristic;
 import io.github.hapjava.characteristics.impl.common.IsConfiguredCharacteristic;
@@ -46,8 +47,9 @@ import io.github.hapjava.services.impl.InputSourceService;
 public class HomekitInputSourceImpl extends AbstractHomekitAccessoryImpl {
 
     public HomekitInputSourceImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
     }
 
     @Override
index b24b762ad63ee8843f665d7cd38bde51c8c7ff2e..44450af8ea31898c553448c646e4ee32d8cf2850 100644 (file)
@@ -25,6 +25,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.IrrigationSystemAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.common.ActiveEnum;
 import io.github.hapjava.characteristics.impl.common.InUseEnum;
@@ -50,8 +51,9 @@ public class HomekitIrrigationSystemImpl extends AbstractHomekitAccessoryImpl im
     private static final String SERVICE_LABEL = "ServiceLabel";
 
     public HomekitIrrigationSystemImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         inUseMapping = createMapping(HomekitCharacteristicType.INUSE_STATUS, InUseEnum.class);
         programModeMap = HomekitCharacteristicFactory
                 .createMapping(getCharacteristic(HomekitCharacteristicType.PROGRAM_MODE).get(), ProgramModeEnum.class);
index 5f59cd761413db2bbde37a2a39ba8e4553c56ced..e059e19be1e2a4f8e5cc58f1ae163e5bce0906fd 100644 (file)
@@ -24,6 +24,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.LeakSensorAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.leaksensor.LeakDetectedStateEnum;
 import io.github.hapjava.services.impl.LeakSensorService;
@@ -36,8 +37,9 @@ public class HomekitLeakSensorImpl extends AbstractHomekitAccessoryImpl implemen
     private final Map<LeakDetectedStateEnum, String> mapping;
 
     public HomekitLeakSensorImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         mapping = createMapping(LEAK_DETECTED_STATE, LeakDetectedStateEnum.class);
     }
 
index 193970725822f818c54d26f5f7167b35c3ee4078..cea33839e3151b934da425a4d29a5ddc8bb7d8e3 100644 (file)
@@ -27,6 +27,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.LightSensorAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.lightsensor.CurrentAmbientLightLevelCharacteristic;
 import io.github.hapjava.services.impl.LightSensorService;
@@ -39,8 +40,9 @@ import io.github.hapjava.services.impl.LightSensorService;
 public class HomekitLightSensorImpl extends AbstractHomekitAccessoryImpl implements LightSensorAccessory {
 
     public HomekitLightSensorImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater,
+            HomekitSettings settings) {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
     }
 
     @Override
index b1c63c1383bd04eaf727a6e0a45cce67d6eb2480..c0c1d800ffeaff4e46c61ba797250599f553861f 100644 (file)
@@ -26,6 +26,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.LightbulbAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.services.impl.LightbulbService;
 
@@ -37,8 +38,9 @@ import io.github.hapjava.services.impl.LightbulbService;
 class HomekitLightbulbImpl extends AbstractHomekitAccessoryImpl implements LightbulbAccessory {
 
     public HomekitLightbulbImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater,
+            HomekitSettings settings) {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
     }
 
     @Override
index bec2026480e43e3f579c73e6d3ab585fdb9ad95b..14e2a05f82d9ec19bd72c63190bc6159a5b231f4 100644 (file)
@@ -23,6 +23,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.LockMechanismAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.lock.LockCurrentStateEnum;
 import io.github.hapjava.characteristics.impl.lock.LockTargetStateEnum;
@@ -39,8 +40,9 @@ public class HomekitLockImpl extends AbstractHomekitAccessoryImpl implements Loc
     final Map<LockTargetStateEnum, String> targetStateMapping;
 
     public HomekitLockImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater,
+            HomekitSettings settings) {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
 
         currentStateMapping = createMapping(HomekitCharacteristicType.LOCK_CURRENT_STATE, LockCurrentStateEnum.class);
         targetStateMapping = createMapping(HomekitCharacteristicType.LOCK_TARGET_STATE, LockTargetStateEnum.class);
index 582c5b9b5393a94aff96983a4ca3184b492da752..7a0bb8affcf91951c6af49d0d789999b00a08113 100644 (file)
@@ -65,6 +65,8 @@ import io.github.hapjava.characteristics.impl.thermostat.CurrentHeatingCoolingSt
 import io.github.hapjava.characteristics.impl.thermostat.CurrentHeatingCoolingStateEnum;
 import io.github.hapjava.characteristics.impl.thermostat.TargetHeatingCoolingStateCharacteristic;
 import io.github.hapjava.characteristics.impl.thermostat.TargetHeatingCoolingStateEnum;
+import io.github.hapjava.characteristics.impl.thermostat.TemperatureDisplayUnitCharacteristic;
+import io.github.hapjava.characteristics.impl.thermostat.TemperatureDisplayUnitEnum;
 
 /**
  * Creates an optional characteristics from metadata
@@ -104,16 +106,24 @@ public class HomekitMetadataCharacteristicFactory {
                     HomekitMetadataCharacteristicFactory::createTargetHeaterCoolerStateCharacteristic);
             put(TARGET_HEATING_COOLING_STATE,
                     HomekitMetadataCharacteristicFactory::createTargetHeatingCoolingStateCharacteristic);
+            put(TEMPERATURE_UNIT, HomekitMetadataCharacteristicFactory::createTemperatureDisplayUnitCharacteristic);
             put(VOLUME_CONTROL_TYPE, HomekitMetadataCharacteristicFactory::createVolumeControlTypeCharacteristic);
         }
     };
 
     public static Optional<Characteristic> createCharacteristic(String characteristic, Object value) {
         var type = HomekitCharacteristicType.valueOfTag(characteristic);
-        if (type.isEmpty() || !OPTIONAL.containsKey(type.get())) {
+        if (type.isEmpty()) {
             return Optional.empty();
         }
-        return Optional.of(OPTIONAL.get(type.get()).apply(value));
+        return createCharacteristic(type.get(), value);
+    }
+
+    public static Optional<Characteristic> createCharacteristic(HomekitCharacteristicType type, Object value) {
+        if (!OPTIONAL.containsKey(type)) {
+            return Optional.empty();
+        }
+        return Optional.of(OPTIONAL.get(type).apply(value));
     }
 
     private static Supplier<CompletableFuture<Integer>> getInteger(Object value) {
@@ -321,6 +331,22 @@ public class HomekitMetadataCharacteristicFactory {
                 });
     }
 
+    private static Characteristic createTemperatureDisplayUnitCharacteristic(Object value) {
+        var enumSupplier = getEnum(value, TemperatureDisplayUnitEnum.class);
+        TemperatureDisplayUnitEnum enumValue;
+        try {
+            enumValue = enumSupplier.get().get();
+        } catch (InterruptedException | ExecutionException e) {
+            enumValue = HomekitCharacteristicFactory.useFahrenheit() ? TemperatureDisplayUnitEnum.FAHRENHEIT
+                    : TemperatureDisplayUnitEnum.CELSIUS;
+        }
+
+        return new TemperatureDisplayUnitCharacteristic(enumSupplier, v -> {
+        }, v -> {
+        }, () -> {
+        });
+    }
+
     private static Characteristic createVolumeControlTypeCharacteristic(Object value) {
         return new VolumeControlTypeCharacteristic(getEnum(value, VolumeControlTypeEnum.class), v -> {
         }, () -> {
index d1bcfb65c943833dbbdb23f90be40550b5c83c19..33648b7e9249e9339d349b816a043baf031f2572 100644 (file)
@@ -22,6 +22,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.MicrophoneAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.services.impl.MicrophoneService;
 
@@ -34,8 +35,9 @@ public class HomekitMicrophoneImpl extends AbstractHomekitAccessoryImpl implemen
     private final BooleanItemReader muteReader;
 
     public HomekitMicrophoneImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         muteReader = createBooleanReader(HomekitCharacteristicType.MUTE);
     }
 
index 9503c29c097140d64845865fafa69f0311a9f099..c0075c454ce83b4b55473bfefd2172c4ccf7301c 100644 (file)
@@ -22,6 +22,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.MotionSensorAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.services.impl.MotionSensorService;
 
@@ -33,8 +34,9 @@ public class HomekitMotionSensorImpl extends AbstractHomekitAccessoryImpl implem
     private final BooleanItemReader motionSensedReader;
 
     public HomekitMotionSensorImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         motionSensedReader = createBooleanReader(HomekitCharacteristicType.MOTION_DETECTED_STATE);
     }
 
index ae821158b97eba894071768babfe1a39d2f5e28f..54fc964b4941033aa92f27a9ff88723514b54621 100644 (file)
@@ -24,6 +24,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.OccupancySensorAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.occupancysensor.OccupancyDetectedEnum;
 import io.github.hapjava.services.impl.OccupancySensorService;
@@ -36,8 +37,9 @@ public class HomekitOccupancySensorImpl extends AbstractHomekitAccessoryImpl imp
     private final Map<OccupancyDetectedEnum, String> mapping;
 
     public HomekitOccupancySensorImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         mapping = createMapping(OCCUPANCY_DETECTED_STATE, OccupancyDetectedEnum.class);
     }
 
index 4e8dc1c921276f50fe6f1d3301a32f6eb6ed1310..4c75a9d8d12fc2678906ed90e25099e407c9b748 100644 (file)
@@ -22,6 +22,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.OutletAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.services.impl.OutletService;
 
@@ -34,8 +35,9 @@ public class HomekitOutletImpl extends AbstractHomekitAccessoryImpl implements O
     private final BooleanItemReader onReader;
 
     public HomekitOutletImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         inUseReader = createBooleanReader(HomekitCharacteristicType.INUSE_STATUS);
         onReader = createBooleanReader(HomekitCharacteristicType.ON_STATE);
     }
index 23d83b1e84dde206eb7498d169525c5166666a1e..1c4f623ea4149580c2e1f4c11c277bde2211d267 100644 (file)
@@ -27,6 +27,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.SecuritySystemAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.securitysystem.CurrentSecuritySystemStateEnum;
 import io.github.hapjava.characteristics.impl.securitysystem.TargetSecuritySystemStateEnum;
@@ -48,8 +49,9 @@ public class HomekitSecuritySystemImpl extends AbstractHomekitAccessoryImpl impl
     private final List<TargetSecuritySystemStateEnum> customTargetStateList = new ArrayList<>();
 
     public HomekitSecuritySystemImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater,
+            HomekitSettings settings) {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         currentStateMapping = createMapping(SECURITY_SYSTEM_CURRENT_STATE, CurrentSecuritySystemStateEnum.class,
                 customCurrentStateList);
         targetStateMapping = createMapping(SECURITY_SYSTEM_TARGET_STATE, TargetSecuritySystemStateEnum.class,
index 6d5c379039670667328fe0ef212ff8fa7b3fa76b..a8fe068033acf23cccdcab6765ef872cd26b31a8 100644 (file)
@@ -24,6 +24,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.SlatAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.slat.CurrentSlatStateEnum;
 import io.github.hapjava.characteristics.impl.slat.SlatTypeEnum;
@@ -39,8 +40,9 @@ public class HomekitSlatImpl extends AbstractHomekitAccessoryImpl implements Sla
     private final SlatTypeEnum slatType;
 
     public HomekitSlatImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater,
+            HomekitSettings settings) {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         final String slatTypeConfig = getAccessoryConfiguration(CONFIG_TYPE, "horizontal");
         slatType = "horizontal".equalsIgnoreCase(slatTypeConfig) ? SlatTypeEnum.HORIZONTAL : SlatTypeEnum.VERTICAL;
         currentSlatStateMapping = createMapping(CURRENT_SLAT_STATE, CurrentSlatStateEnum.class);
index 8cbbf588e2f03e96e15f004b92dc9aca489d46e5..231fcfb3d65b78648d9119b09310abc02bb38099 100644 (file)
@@ -25,6 +25,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.SmartSpeakerAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.television.CurrentMediaStateEnum;
 import io.github.hapjava.characteristics.impl.television.TargetMediaStateEnum;
@@ -39,8 +40,9 @@ public class HomekitSmartSpeakerImpl extends AbstractHomekitAccessoryImpl implem
     private final Map<TargetMediaStateEnum, String> targetMediaState;
 
     public HomekitSmartSpeakerImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater,
+            HomekitSettings settings) {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         currentMediaState = createMapping(CURRENT_MEDIA_STATE, CurrentMediaStateEnum.class);
         targetMediaState = createMapping(TARGET_MEDIA_STATE, TargetMediaStateEnum.class);
     }
index e1295e6e13e0114b018810fd18a51a64219f48ef..a2f4c02fa915d79fb3ebc3a30d81a416aa9084c1 100644 (file)
@@ -24,6 +24,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.SmokeSensorAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.smokesensor.SmokeDetectedStateEnum;
 import io.github.hapjava.services.impl.SmokeSensorService;
@@ -36,8 +37,9 @@ public class HomekitSmokeSensorImpl extends AbstractHomekitAccessoryImpl impleme
     private final Map<SmokeDetectedStateEnum, String> mapping;
 
     public HomekitSmokeSensorImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         mapping = createMapping(SMOKE_DETECTED_STATE, SmokeDetectedStateEnum.class);
     }
 
index 2a0d9eb95c5e685c6bdf77125ebe9ca690206fb1..e95cb400c4eb78162478458028ae7c08b5779e14 100644 (file)
@@ -22,6 +22,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.SpeakerAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.services.impl.SpeakerService;
 
@@ -34,8 +35,9 @@ public class HomekitSpeakerImpl extends AbstractHomekitAccessoryImpl implements
     private final BooleanItemReader muteReader;
 
     public HomekitSpeakerImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         muteReader = createBooleanReader(HomekitCharacteristicType.MUTE);
     }
 
index 6dbc1f6808442d9ce579e6918272c5592e44d6e5..464958ec2b797c1ed97ad6d1f8303d0e83e2cc3d 100644 (file)
@@ -23,6 +23,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.SwitchAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.services.impl.SwitchService;
 
@@ -35,8 +36,9 @@ public class HomekitSwitchImpl extends AbstractHomekitAccessoryImpl implements S
     private final BooleanItemReader onReader;
 
     public HomekitSwitchImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         onReader = createBooleanReader(ON_STATE);
     }
 
index 433a36f85e8941a4fb75ddeb1ced964a2979517c..ec9036939ec35d3f990d4ed56612f3199eb69b97 100644 (file)
@@ -21,6 +21,7 @@ import org.openhab.io.homekit.internal.HomekitException;
 import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.impl.common.ActiveCharacteristic;
 import io.github.hapjava.characteristics.impl.common.ActiveIdentifierCharacteristic;
 import io.github.hapjava.characteristics.impl.common.ConfiguredNameCharacteristic;
@@ -43,8 +44,9 @@ import io.github.hapjava.services.impl.TelevisionService;
 public class HomekitTelevisionImpl extends AbstractHomekitAccessoryImpl {
 
     public HomekitTelevisionImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
     }
 
     @Override
index f3cbd23645f61c921f38adeadc5429ca6cd33afd..8c28c533e33f9911ae6539022d0e7af4c4761f3f 100644 (file)
@@ -22,6 +22,7 @@ import org.openhab.io.homekit.internal.HomekitException;
 import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.impl.audio.MuteCharacteristic;
 import io.github.hapjava.characteristics.impl.audio.VolumeCharacteristic;
 import io.github.hapjava.characteristics.impl.televisionspeaker.VolumeControlTypeCharacteristic;
@@ -43,8 +44,9 @@ import io.github.hapjava.services.impl.TelevisionSpeakerService;
 public class HomekitTelevisionSpeakerImpl extends AbstractHomekitAccessoryImpl {
 
     public HomekitTelevisionSpeakerImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
     }
 
     @Override
index 84e0da9428f71dbd484003e04435ed3e2130095d..c5f0bb7ac2464bfa36ca9711b4ed4133e2674142 100644 (file)
@@ -24,6 +24,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.TemperatureSensorAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.thermostat.CurrentTemperatureCharacteristic;
 import io.github.hapjava.characteristics.impl.thermostat.TargetTemperatureCharacteristic;
@@ -37,8 +38,9 @@ import io.github.hapjava.services.impl.TemperatureSensorService;
 class HomekitTemperatureSensorImpl extends AbstractHomekitAccessoryImpl implements TemperatureSensorAccessory {
 
     public HomekitTemperatureSensorImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater,
+            HomekitSettings settings) {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
     }
 
     @Override
index fab0d0ce5a2107f77bb655d0144763db3bf20c9b..b3b6e756ffdda9bbf8beb883eeeb13664e81c0ec 100644 (file)
  */
 package org.openhab.io.homekit.internal.accessories;
 
-import static org.openhab.io.homekit.internal.HomekitCharacteristicType.CURRENT_HEATING_COOLING_STATE;
-import static org.openhab.io.homekit.internal.HomekitCharacteristicType.TARGET_HEATING_COOLING_STATE;
+import static org.openhab.io.homekit.internal.HomekitCharacteristicType.*;
 
-import java.math.BigDecimal;
-import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.concurrent.CompletableFuture;
 
-import org.openhab.core.library.items.NumberItem;
-import org.openhab.core.library.types.DecimalType;
 import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
-import org.openhab.io.homekit.internal.HomekitCharacteristicType;
 import org.openhab.io.homekit.internal.HomekitException;
 import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import io.github.hapjava.accessories.ThermostatAccessory;
-import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
-import io.github.hapjava.characteristics.impl.thermostat.CurrentHeatingCoolingStateEnum;
+import io.github.hapjava.characteristics.Characteristic;
+import io.github.hapjava.characteristics.impl.thermostat.CurrentHeatingCoolingStateCharacteristic;
 import io.github.hapjava.characteristics.impl.thermostat.CurrentTemperatureCharacteristic;
-import io.github.hapjava.characteristics.impl.thermostat.TargetHeatingCoolingStateEnum;
+import io.github.hapjava.characteristics.impl.thermostat.TargetHeatingCoolingStateCharacteristic;
 import io.github.hapjava.characteristics.impl.thermostat.TargetTemperatureCharacteristic;
-import io.github.hapjava.characteristics.impl.thermostat.TemperatureDisplayUnitEnum;
+import io.github.hapjava.characteristics.impl.thermostat.TemperatureDisplayUnitCharacteristic;
 import io.github.hapjava.services.impl.ThermostatService;
 
 /**
@@ -52,203 +42,26 @@ import io.github.hapjava.services.impl.ThermostatService;
  *
  * @author Andy Lintner - Initial contribution
  */
-class HomekitThermostatImpl extends AbstractHomekitAccessoryImpl implements ThermostatAccessory {
+class HomekitThermostatImpl extends AbstractHomekitAccessoryImpl {
     private final Logger logger = LoggerFactory.getLogger(HomekitThermostatImpl.class);
-    private final Map<CurrentHeatingCoolingStateEnum, String> currentHeatingCoolingStateMapping;
-    private final Map<TargetHeatingCoolingStateEnum, String> targetHeatingCoolingStateMapping;
-    private final List<CurrentHeatingCoolingStateEnum> customCurrentHeatingCoolingStateList;
-    private final List<TargetHeatingCoolingStateEnum> customTargetHeatingCoolingStateList;
 
     public HomekitThermostatImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
-        customCurrentHeatingCoolingStateList = new ArrayList<>();
-        customTargetHeatingCoolingStateList = new ArrayList<>();
-        currentHeatingCoolingStateMapping = createMapping(CURRENT_HEATING_COOLING_STATE,
-                CurrentHeatingCoolingStateEnum.class, customCurrentHeatingCoolingStateList);
-        targetHeatingCoolingStateMapping = createMapping(TARGET_HEATING_COOLING_STATE,
-                TargetHeatingCoolingStateEnum.class, customTargetHeatingCoolingStateList);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater,
+            HomekitSettings settings) {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
     }
 
     @Override
     public void init() throws HomekitException {
         super.init();
-        addService(new ThermostatService(this));
-    }
-
-    @Override
-    public CurrentHeatingCoolingStateEnum[] getCurrentHeatingCoolingStateValidValues() {
-        return customCurrentHeatingCoolingStateList.isEmpty()
-                ? currentHeatingCoolingStateMapping.keySet().toArray(new CurrentHeatingCoolingStateEnum[0])
-                : customCurrentHeatingCoolingStateList.toArray(new CurrentHeatingCoolingStateEnum[0]);
-    }
-
-    @Override
-    public TargetHeatingCoolingStateEnum[] getTargetHeatingCoolingStateValidValues() {
-        return customTargetHeatingCoolingStateList.isEmpty()
-                ? targetHeatingCoolingStateMapping.keySet().toArray(new TargetHeatingCoolingStateEnum[0])
-                : customTargetHeatingCoolingStateList.toArray(new TargetHeatingCoolingStateEnum[0]);
-    }
-
-    @Override
-    public CompletableFuture<CurrentHeatingCoolingStateEnum> getCurrentState() {
-        return CompletableFuture.completedFuture(getKeyFromMapping(CURRENT_HEATING_COOLING_STATE,
-                currentHeatingCoolingStateMapping, CurrentHeatingCoolingStateEnum.OFF));
-    }
 
-    @Override
-    public CompletableFuture<Double> getCurrentTemperature() {
-        Double state = getStateAsTemperature(HomekitCharacteristicType.CURRENT_TEMPERATURE);
-        return CompletableFuture.completedFuture(state != null ? state : getMinCurrentTemperature());
-    }
-
-    @Override
-    public double getMinCurrentTemperature() {
-        // Apple defines default values in Celsius. We need to convert them to Fahrenheit if openHAB is using Fahrenheit
-        // convertToCelsius and convertFromCelsius are only converting if useFahrenheit is set to true, so no additional
-        // check here needed
-
-        return HomekitCharacteristicFactory.convertToCelsius(
-                getAccessoryConfiguration(HomekitCharacteristicType.CURRENT_TEMPERATURE, HomekitTaggedItem.MIN_VALUE,
-                        BigDecimal.valueOf(HomekitCharacteristicFactory
-                                .convertFromCelsius(CurrentTemperatureCharacteristic.DEFAULT_MIN_VALUE)))
-                        .doubleValue());
-    }
+        // This characteristic is technically mandatory, but we provide a default if it's not provided
+        var displayUnitCharacteristic = getCharacteristic(TemperatureDisplayUnitCharacteristic.class)
+                .orElseGet(() -> HomekitCharacteristicFactory.createSystemTemperatureDisplayUnitCharacteristic());
 
-    @Override
-    public double getMaxCurrentTemperature() {
-        return HomekitCharacteristicFactory.convertToCelsius(
-                getAccessoryConfiguration(HomekitCharacteristicType.CURRENT_TEMPERATURE, HomekitTaggedItem.MAX_VALUE,
-                        BigDecimal.valueOf(HomekitCharacteristicFactory
-                                .convertFromCelsius(CurrentTemperatureCharacteristic.DEFAULT_MAX_VALUE)))
-                        .doubleValue());
-    }
-
-    @Override
-    public double getMinStepCurrentTemperature() {
-        return HomekitCharacteristicFactory.getTemperatureStep(
-                getCharacteristic(HomekitCharacteristicType.CURRENT_TEMPERATURE).get(),
-                TargetTemperatureCharacteristic.DEFAULT_STEP);
-    }
-
-    @Override
-    public CompletableFuture<TargetHeatingCoolingStateEnum> getTargetState() {
-        return CompletableFuture.completedFuture(getKeyFromMapping(TARGET_HEATING_COOLING_STATE,
-                targetHeatingCoolingStateMapping, TargetHeatingCoolingStateEnum.OFF));
-    }
-
-    @Override
-    public CompletableFuture<TemperatureDisplayUnitEnum> getTemperatureDisplayUnit() {
-        return CompletableFuture
-                .completedFuture(HomekitCharacteristicFactory.useFahrenheit() ? TemperatureDisplayUnitEnum.FAHRENHEIT
-                        : TemperatureDisplayUnitEnum.CELSIUS);
-    }
-
-    @Override
-    public void setTemperatureDisplayUnit(TemperatureDisplayUnitEnum value) {
-        // TODO: add support for display unit change
-    }
-
-    @Override
-    public CompletableFuture<Double> getTargetTemperature() {
-        Double state = getStateAsTemperature(HomekitCharacteristicType.TARGET_TEMPERATURE);
-        return CompletableFuture.completedFuture(state != null ? state : 0.0);
-    }
-
-    @Override
-    public void setTargetState(TargetHeatingCoolingStateEnum mode) {
-        HomekitCharacteristicFactory.setValueFromEnum(getCharacteristic(TARGET_HEATING_COOLING_STATE).get(), mode,
-                targetHeatingCoolingStateMapping);
-    }
-
-    @Override
-    public void setTargetTemperature(Double value) {
-        final Optional<HomekitTaggedItem> characteristic = getCharacteristic(
-                HomekitCharacteristicType.TARGET_TEMPERATURE);
-        if (characteristic.isPresent()) {
-            ((NumberItem) characteristic.get().getItem())
-                    .send(new DecimalType(BigDecimal.valueOf(HomekitCharacteristicFactory.convertFromCelsius(value))));
-        } else {
-            logger.warn("Missing mandatory characteristic {}", HomekitCharacteristicType.TARGET_TEMPERATURE);
-        }
-    }
-
-    @Override
-    public double getMinTargetTemperature() {
-        return HomekitCharacteristicFactory
-                .convertToCelsius(
-                        getAccessoryConfiguration(HomekitCharacteristicType.TARGET_TEMPERATURE,
-                                HomekitTaggedItem.MIN_VALUE,
-                                BigDecimal.valueOf(HomekitCharacteristicFactory
-                                        .convertFromCelsius(TargetTemperatureCharacteristic.DEFAULT_MIN_VALUE)))
-                                .doubleValue());
-    }
-
-    @Override
-    public double getMaxTargetTemperature() {
-        return HomekitCharacteristicFactory
-                .convertToCelsius(
-                        getAccessoryConfiguration(HomekitCharacteristicType.TARGET_TEMPERATURE,
-                                HomekitTaggedItem.MAX_VALUE,
-                                BigDecimal.valueOf(HomekitCharacteristicFactory
-                                        .convertFromCelsius(TargetTemperatureCharacteristic.DEFAULT_MAX_VALUE)))
-                                .doubleValue());
-    }
-
-    @Override
-    public double getMinStepTargetTemperature() {
-        return HomekitCharacteristicFactory.getTemperatureStep(
-                getCharacteristic(HomekitCharacteristicType.TARGET_TEMPERATURE).get(),
-                TargetTemperatureCharacteristic.DEFAULT_STEP);
-    }
-
-    @Override
-    public void subscribeCurrentState(HomekitCharacteristicChangeCallback callback) {
-        subscribe(CURRENT_HEATING_COOLING_STATE, callback);
-    }
-
-    @Override
-    public void subscribeCurrentTemperature(HomekitCharacteristicChangeCallback callback) {
-        subscribe(HomekitCharacteristicType.CURRENT_TEMPERATURE, callback);
-    }
-
-    @Override
-    public void subscribeTargetState(HomekitCharacteristicChangeCallback callback) {
-        subscribe(HomekitCharacteristicType.TARGET_HEATING_COOLING_STATE, callback);
-    }
-
-    @Override
-    public void subscribeTargetTemperature(HomekitCharacteristicChangeCallback callback) {
-        subscribe(HomekitCharacteristicType.TARGET_TEMPERATURE, callback);
-    }
-
-    @Override
-    public void subscribeTemperatureDisplayUnit(HomekitCharacteristicChangeCallback callback) {
-        // TODO: add support for display unit change
-    }
-
-    @Override
-    public void unsubscribeCurrentState() {
-        unsubscribe(CURRENT_HEATING_COOLING_STATE);
-    }
-
-    @Override
-    public void unsubscribeCurrentTemperature() {
-        unsubscribe(HomekitCharacteristicType.CURRENT_TEMPERATURE);
-    }
-
-    @Override
-    public void unsubscribeTemperatureDisplayUnit() {
-        // TODO: add support for display unit change
-    }
-
-    @Override
-    public void unsubscribeTargetState() {
-        unsubscribe(HomekitCharacteristicType.TARGET_HEATING_COOLING_STATE);
-    }
-
-    @Override
-    public void unsubscribeTargetTemperature() {
-        unsubscribe(HomekitCharacteristicType.TARGET_TEMPERATURE);
+        addService(new ThermostatService(getCharacteristic(CurrentHeatingCoolingStateCharacteristic.class).get(),
+                getCharacteristic(TargetHeatingCoolingStateCharacteristic.class).get(),
+                getCharacteristic(CurrentTemperatureCharacteristic.class).get(),
+                getCharacteristic(TargetTemperatureCharacteristic.class).get(), displayUnitCharacteristic));
     }
 }
index aede260fa6a5055da144b3517fe7411ecdb04b66..b9829e6eae01543c9a1fe74551bb8a9000578874 100644 (file)
@@ -41,6 +41,7 @@ import org.slf4j.LoggerFactory;
 
 import io.github.hapjava.accessories.HomekitAccessory;
 import io.github.hapjava.accessories.ValveAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.common.ActiveEnum;
 import io.github.hapjava.characteristics.impl.common.InUseEnum;
@@ -76,8 +77,9 @@ public class HomekitValveImpl extends AbstractHomekitAccessoryImpl implements Va
     private ValveTypeEnum valveType;
 
     public HomekitValveImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
+            throws IncompleteAccessoryException {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
         inUseReader = createBooleanReader(INUSE_STATUS);
         activeReader = createBooleanReader(ACTIVE_STATUS);
         homekitTimer = getAccessoryConfigurationAsBoolean(CONFIG_TIMER, false);
index b4a3440819cc9f634efb8030aec905978857613f..919fac16277f0a8a39799939c7c6d6b294790b82 100644 (file)
@@ -22,6 +22,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.WindowCoveringAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.windowcovering.PositionStateEnum;
 import io.github.hapjava.services.impl.WindowCoveringService;
@@ -34,8 +35,9 @@ import io.github.hapjava.services.impl.WindowCoveringService;
 public class HomekitWindowCoveringImpl extends AbstractHomekitPositionAccessoryImpl implements WindowCoveringAccessory {
 
     public HomekitWindowCoveringImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater,
+            HomekitSettings settings) {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
     }
 
     @Override
index 87c8d360b454c4044a06a4d42e4ba97cc8652be4..333ccfc006bc9d8c3465cd4b7e60c8db3ea707ce 100644 (file)
@@ -22,6 +22,7 @@ import org.openhab.io.homekit.internal.HomekitSettings;
 import org.openhab.io.homekit.internal.HomekitTaggedItem;
 
 import io.github.hapjava.accessories.WindowAccessory;
+import io.github.hapjava.characteristics.Characteristic;
 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
 import io.github.hapjava.characteristics.impl.windowcovering.PositionStateEnum;
 import io.github.hapjava.services.impl.WindowService;
@@ -34,8 +35,9 @@ import io.github.hapjava.services.impl.WindowService;
 public class HomekitWindowImpl extends AbstractHomekitPositionAccessoryImpl implements WindowAccessory {
 
     public HomekitWindowImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
-            HomekitAccessoryUpdater updater, HomekitSettings settings) {
-        super(taggedItem, mandatoryCharacteristics, updater, settings);
+            List<Characteristic> mandatoryRawCharacteristics, HomekitAccessoryUpdater updater,
+            HomekitSettings settings) {
+        super(taggedItem, mandatoryCharacteristics, mandatoryRawCharacteristics, updater, settings);
     }
 
     @Override