diff --git a/bundles/org.openhab.io.homekit/README.md b/bundles/org.openhab.io.homekit/README.md index a8273c7eb0d85..20e159dc9c4b9 100644 --- a/bundles/org.openhab.io.homekit/README.md +++ b/bundles/org.openhab.io.homekit/README.md @@ -171,7 +171,7 @@ A full list of supported accessory types can be found in the table *below*. | | | TamperedStatus | Switch, Contact | accessory tampered status. A status of "ON"/"OPEN" indicates that the accessory has been tampered with. Value should return to "OFF"/"CLOSED" when the accessory has been reset to a non-tampered state. | | | | BatteryLowStatus | Switch, Contact | accessory battery status. A value of "ON"/"OPEN" indicate that the battery level of the accessory is low. Value should return to "OFF"/"CLOSED" when the battery charges to a level thats above the low threshold. | | TemperatureSensor | | | | Temperature sensor | -| | CurrentTemperature | | Number | current temperature | +| | CurrentTemperature | | Number | current temperature. supported configuration: minValue, maxValue, step. | | | | Name | String | Name of the sensor | | | | ActiveStatus | Switch, Contact | accessory current working status. A value of "ON"/"OPEN" indicate that the accessory is active and is functioning without any errors. | | | | FaultStatus | Switch, Contact | accessory fault status. "ON"/"OPEN" value indicates that the accessory has experienced a fault that may be interfering with its intended functionality. A value of "OFF"/"CLOSED" indicates that there is no fault. | @@ -229,8 +229,8 @@ A full list of supported accessory types can be found in the table *below*. | | | SwingMode | Number,SwitchItem | swing mode. values: 0/OFF=SWING DISABLED, 1/ON=SWING ENABLED | | | | LockControl | Number,SwitchItem | status of physical control lock. values: 0/OFF=CONTROL LOCK DISABLED, 1/ON=CONTROL LOCK ENABLED | | Thermostat | | | | A thermostat requires all mandatory characteristics defined below | -| | CurrentTemperature | | Number | current temperature | -| | TargetTemperature | | Number | target temperature | +| | CurrentTemperature | | Number | current temperature. supported configuration: minValue, maxValue, step | +| | TargetTemperature | | Number | target temperature. supported configuration: minValue, maxValue, step | | | CurrentHeatingCoolingMode | | String | Current heating cooling mode (OFF, AUTO, HEAT, COOL). for mapping see homekit settings above. | | | TargetHeatingCoolingMode | | String | Target heating cooling mode (OFF, AUTO, HEAT, COOL). for mapping see homekit settings above. | | Lock | | | | A Lock Mechanism | @@ -295,6 +295,7 @@ Switch legacy_motionsensor_single "Legacy Motion Sensor" Switch legacy_occupancy_single "Legacy Occupanncy Sensor" [ "OccupancySensor" ] Switch legacy_smoke_single "Legacy Smoke Sensor" [ "SmokeSensor" ] Number legacy_humidity_single "Legacy Humidity Sensor" [ "CurrentHumidity" ] +Number legacy_temperature_sensor "Temperature Sensor" ["TemperatureSensor"] Switch legacy_lock "Legacy Lock single" [ "Lock" ] @@ -332,14 +333,16 @@ Switch leaksensor_single "Leak Sensor single" Switch lock "Lock single" {homekit="Lock"} Switch valve_single "Valve single" {homekit="Valve" [homekitValveType="Shower"]} +Number temperature_sensor "Temperature Sensor [%.1f C]" {homekit="TemperatureSensor" [minValue=10.5, maxValue=27] } + Group gValve "Valve Group" {homekit="Valve" [homekitValveType="Irrigation"]} Switch valve_active "Valve active" (gValve) {homekit="Valve.ActiveStatus, Valve.InUseStatus"} Number valve_duration "Valve duration" (gValve) {homekit="Valve.Duration"} Number valve_remaining_duration "Valve remaining duration" (gValve) {homekit="Valve.RemainingDuration"} Group gThermostat "Thermostat" {homekit="Thermostat"} -Number thermostat_current_temp "Thermostat Current Temp [%.1f C]" (gThermostat) {homekit="Thermostat.CurrentTemperature"} -Number thermostat_target_temp "Thermostat Target Temp[%.1f C]" (gThermostat) {homekit="Thermostat.TargetTemperature"} +Number thermostat_current_temp "Thermostat Current Temp [%.1f C]" (gThermostat) {homekit="Thermostat.CurrentTemperature" [minValue=0, maxValue=40]} +Number thermostat_target_temp "Thermostat Target Temp[%.1f C]" (gThermostat) {homekit="Thermostat.TargetTemperature" [minValue=10.5, maxValue=27]} String thermostat_current_mode "Thermostat Current Mode" (gThermostat) {homekit="Thermostat.CurrentHeatingCoolingMode"} String thermostat_target_mode "Thermostat Target Mode" (gThermostat) {homekit="Thermostat.TargetHeatingCoolingMode"} diff --git a/bundles/org.openhab.io.homekit/pom.xml b/bundles/org.openhab.io.homekit/pom.xml index d1737ad85c96e..ac6a9765a44a2 100644 --- a/bundles/org.openhab.io.homekit/pom.xml +++ b/bundles/org.openhab.io.homekit/pom.xml @@ -21,9 +21,9 @@ - io.github.hap-java - hap - 2.0.0.OH + com.github.j-n-k + hap-java + 2.0.0.OH2 compile diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitTaggedItem.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitTaggedItem.java index 1d66243ab5a94..6cc57f78e38fa 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitTaggedItem.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitTaggedItem.java @@ -33,6 +33,11 @@ public class HomekitTaggedItem { private final Logger logger = LoggerFactory.getLogger(HomekitTaggedItem.class); + /** configuration keywords at items level **/ + public final static String MIN_VALUE = "minValue"; + public final static String MAX_VALUE = "maxValue"; + public final static String STEP = "step"; + private static final Map CREATED_ACCESSORY_IDS = new ConcurrentHashMap<>(); /** * The type of HomekitDevice we've decided this was. If the item is question is the member of a group which is a diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/AbstractHomekitAccessoryImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/AbstractHomekitAccessoryImpl.java index 00d1be3791977..0a66dcd95c202 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/AbstractHomekitAccessoryImpl.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/AbstractHomekitAccessoryImpl.java @@ -147,8 +147,8 @@ protected void unsubscribe(HomekitCharacteristicType characteristicType) { return (T) state.as(type); } } - logger.warn("State for characteristic {} at accessory {} cannot be retrieved.", characteristic, - accessory.getId()); + logger.debug("State for characteristic {} at accessory {} cannot be retrieved.", characteristic, + accessory.getName()); return null; } @@ -170,8 +170,8 @@ protected void unsubscribe(HomekitCharacteristicType characteristicType) { } @SuppressWarnings("unchecked") - protected T getAccessoryConfiguration(String key, @NonNull T defaultValue) { - final @Nullable Map configuration = accessory.getConfiguration(); + private T getItemConfiguration(@NonNull HomekitTaggedItem item, @NonNull String key, @NonNull T defaultValue) { + final @Nullable Map configuration = item.getConfiguration(); if (configuration != null) { Object value = configuration.get(key); if (value != null && value.getClass().equals(defaultValue.getClass())) { @@ -181,6 +181,38 @@ protected T getAccessoryConfiguration(String key, @NonNull T defaultValue) { return defaultValue; } + /** + * return configuration attached to the root accessory, e.g. groupItem. + * Note: result will be casted to the type of the default value. + * The type for number is BigDecimal. + * + * @param key configuration key + * @param defaultValue default value + * @param expected type + * @return configuration value + */ + protected T getAccessoryConfiguration(@NonNull String key, @NonNull T defaultValue) { + return getItemConfiguration(accessory, key, defaultValue); + } + + /** + * return configuration of the characteristic item, e.g. currentTemperature. + * Note: result will be casted to the type of the default value. + * The type for number is BigDecimal. + * + * @param characteristicType characteristic type + * @param key configuration key + * @param defaultValue default value + * @param expected type + * @return configuration value + */ + protected T getAccessoryConfiguration(@NonNull HomekitCharacteristicType characteristicType, + @NonNull String key, @NonNull T defaultValue) { + final Optional characteristic = getCharacteristic(characteristicType); + return characteristic.isPresent() ? getItemConfiguration(characteristic.get(), key, defaultValue) + : defaultValue; + } + protected void addCharacteristic(HomekitTaggedItem characteristic) { characteristics.add(characteristic); } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitTemperatureSensorImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitTemperatureSensorImpl.java index 31e5777c6c0a0..c7f459c09989f 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitTemperatureSensorImpl.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitTemperatureSensorImpl.java @@ -12,6 +12,7 @@ */ package org.openhab.io.homekit.internal.accessories; +import java.math.BigDecimal; import java.util.List; import java.util.concurrent.CompletableFuture; @@ -24,6 +25,7 @@ import io.github.hapjava.accessories.TemperatureSensorAccessory; import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.characteristics.impl.thermostat.TargetTemperatureCharacteristic; import io.github.hapjava.services.impl.TemperatureSensorService; /** @@ -51,6 +53,24 @@ public void subscribeCurrentTemperature(HomekitCharacteristicChangeCallback call subscribe(HomekitCharacteristicType.CURRENT_TEMPERATURE, callback); } + @Override + public double getMinCurrentTemperature() { + return getAccessoryConfiguration(HomekitCharacteristicType.CURRENT_TEMPERATURE, HomekitTaggedItem.MIN_VALUE, + BigDecimal.valueOf(TargetTemperatureCharacteristic.DEFAULT_MIN_VALUE)).doubleValue(); + } + + @Override + public double getMaxCurrentTemperature() { + return getAccessoryConfiguration(HomekitCharacteristicType.CURRENT_TEMPERATURE, HomekitTaggedItem.MAX_VALUE, + BigDecimal.valueOf(TargetTemperatureCharacteristic.DEFAULT_MAX_VALUE)).doubleValue(); + } + + @Override + public double getMinStepCurrentTemperature() { + return getAccessoryConfiguration(HomekitCharacteristicType.CURRENT_TEMPERATURE, HomekitTaggedItem.STEP, + BigDecimal.valueOf(TargetTemperatureCharacteristic.DEFAULT_STEP)).doubleValue(); + } + @Override public void unsubscribeCurrentTemperature() { unsubscribe(HomekitCharacteristicType.CURRENT_TEMPERATURE); diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitThermostatImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitThermostatImpl.java index 495bffbdc8f79..76003a87962ce 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitThermostatImpl.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitThermostatImpl.java @@ -32,6 +32,7 @@ import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; import io.github.hapjava.characteristics.impl.thermostat.CurrentHeatingCoolingStateEnum; import io.github.hapjava.characteristics.impl.thermostat.TargetHeatingCoolingStateEnum; +import io.github.hapjava.characteristics.impl.thermostat.TargetTemperatureCharacteristic; import io.github.hapjava.characteristics.impl.thermostat.TemperatureDisplayUnitEnum; import io.github.hapjava.services.impl.ThermostatService; @@ -93,6 +94,24 @@ public CompletableFuture getCurrentTemperature() { return CompletableFuture.completedFuture(state != null ? convertToCelsius(state.doubleValue()) : 0.0); } + @Override + public double getMinCurrentTemperature() { + return getAccessoryConfiguration(HomekitCharacteristicType.CURRENT_TEMPERATURE, HomekitTaggedItem.MIN_VALUE, + BigDecimal.valueOf(TargetTemperatureCharacteristic.DEFAULT_MIN_VALUE)).doubleValue(); + } + + @Override + public double getMaxCurrentTemperature() { + return getAccessoryConfiguration(HomekitCharacteristicType.CURRENT_TEMPERATURE, HomekitTaggedItem.MAX_VALUE, + BigDecimal.valueOf(TargetTemperatureCharacteristic.DEFAULT_MAX_VALUE)).doubleValue(); + } + + @Override + public double getMinStepCurrentTemperature() { + return getAccessoryConfiguration(HomekitCharacteristicType.CURRENT_TEMPERATURE, HomekitTaggedItem.STEP, + BigDecimal.valueOf(TargetTemperatureCharacteristic.DEFAULT_STEP)).doubleValue(); + } + @Override public CompletableFuture getTargetState() { final HomekitSettings settings = getSettings(); @@ -187,6 +206,24 @@ public void setTargetTemperature(Double value) { } } + @Override + public double getMinTargetTemperature() { + return getAccessoryConfiguration(HomekitCharacteristicType.TARGET_TEMPERATURE, HomekitTaggedItem.MIN_VALUE, + BigDecimal.valueOf(TargetTemperatureCharacteristic.DEFAULT_MIN_VALUE)).doubleValue(); + } + + @Override + public double getMaxTargetTemperature() { + return getAccessoryConfiguration(HomekitCharacteristicType.TARGET_TEMPERATURE, HomekitTaggedItem.MAX_VALUE, + BigDecimal.valueOf(TargetTemperatureCharacteristic.DEFAULT_MAX_VALUE)).doubleValue(); + } + + @Override + public double getMinStepTargetTemperature() { + return getAccessoryConfiguration(HomekitCharacteristicType.TARGET_TEMPERATURE, HomekitTaggedItem.STEP, + BigDecimal.valueOf(TargetTemperatureCharacteristic.DEFAULT_STEP)).doubleValue(); + } + @Override public void subscribeCurrentState(HomekitCharacteristicChangeCallback callback) { subscribe(HomekitCharacteristicType.CURRENT_HEATING_COOLING_STATE, callback);