- Carbon Dioxide Sensor
- Carbon Monoxide Sensor
-**Attention: Some tags have been renamed. Old style may not be supported in future versions. See below for details.**
-
## Global Configuration
Your first step will be to create the `homekit.cfg` in your `$OPENHAB_CONF/services` folder.
Complex accessories require a tag on a Group Item indicating the accessory type, as well as tags on the items it composes.
A HomeKit accessory has mandatory and optional characteristics (listed below in the table).
-The mapping between openHAB items and HomeKit accessory and characteristics is done by means of tagging.
-You can tag openHAB items using:
-
-- [tags](https://www.openhab.org/docs/configuration/items.html#tags) (deprecated)
-- [metadata](https://www.openhab.org/docs/concepts/items.html#item-metadata)
-
+The mapping between openHAB items and HomeKit accessory and characteristics is done by means of [metadata](https://www.openhab.org/docs/concepts/items.html#item-metadata)
e.g.
```xtend
-Switch leaksensor_tag "Leak Sensor with Tag" [ "LeakSensor" ]
Switch leaksensor_metadata "Leak Sensor" {homekit="LeakSensor"}
```
-The HomeKit integration currently supports both options. You can mix both options in the same configuration file.
-If an openHAB item has both, tags and metadata, then HomeKit integration will use only metadata and ignore tags.
-In general, the `tag` way is considered legacy and may be removed in future releases.
-
You can link one openHAB item to one or more HomeKit accessory, e.g.
```xtend
If the shorthand version has only a characteristic then it must be a part of a group which has a HomeKit accessory type.
You can use openHAB group to define complex accessories. The group item must indicate the HomeKit accessory type,
-e.g. LeakSensor definition using tags
-
-```xtend
-Group gLegacy_leaksensor "Legacy Leak sensor Group" [ "LeakSensor" ]
-Switch legacy_leaksensor "Legacy Leak sensor" (gLegacy_Leaksensor) [ "LeakDetectedState" ]
-Switch legacy_leaksensor_battery "Legacy Leak sensor battery status" (gLegacy_Leaksensor) [ "homekit:BatteryLowStatus" ]
-```
-
-using metadata
+e.g. LeakSensor definition
```xtend
Group gLeakSensor "Leak Sensor Group" {homekit="LeakSensor"}
| | | LockCurrentState | Switch | current states of lock mechanism (OFF=SECURED, ON=UNSECURED) |
| | | LockTargetState | Switch | target states of lock mechanism (OFF=SECURED, ON=UNSECURED) |
-### Legacy tags
-
-Following tags are still supported but could be removed in the future releases. Please consider replacing them with the new style.
-
-| Old (tag style) | New (metadata style) |
-|:---------------------------------|:------------------------------------------------|
-| homekit:HeatingCoolingMode | CurrentHeatingCoolingMode |
-| homekit:TargetHeatingCoolingMode | TargetHeatingCoolingMode |
-| homekit:TargetTemperature | TargetTemperature |
-| homekit:BatteryLowStatus | BatteryLowStatus |
-| homekit:BatteryLevel | mapping to BatteryLowStatus |
-| CurrentHumidity | RelativeHumidity |
-| Blinds | WindowCovering |
-| DimmableLighting | Lighting with characteristic Brightness |
-| ColorfulLighting | Lighting with characteristic Brightness and Hue |
-
### Examples
See the sample below for example items:
-#### Using "tag"
-
-```xtend
-Color legacy_color_light_single "Legacy Color Light Single" [ "Lighting" ]
-Color legacy_color_light_dimmable "Legacy Color Light Dimmable" [ "DimmableLighting" ]
-Color legacy_color_light_hue "Legacy Color Light Hue" [ "ColorfulLighting" ]
-
-Rollershutter legacy_window_covering "Legacy Window Rollershutter" [ "WindowCovering" ]
-Switch legacy_switch_single "Legacy Switch single" [ "Switchable" ]
-Switch legacy_contactsensor_single "Legacy Contact Sensor single" [ "ContactSensor" ]
-Switch legacy_leaksensor_single "Legacy Leak Sensor single" [ "LeakSensor" ]
-Switch legacy_leaksensor_single2 "Legacy Leak Sensor single 2" [ "LeakSensor", "LeakSensor.LeakDetectedState" ]
-Switch legacy_motionsensor_single "Legacy Motion Sensor" [ "MotionSensor" ]
-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" ]
-
-Switch legacy_valve_single "Legacy Valve Single" [ "Valve" ]
-
-Group gLegacy_Valve "Legacy Valve Group" [ "Valve" ]
-Switch legacy_valve_active "Legacy Valve active" (gLegacy_Valve) [ "Active" ]
-Number legacy_valve_duration "Legacy Valve duration" (gLegacy_Valve) [ "Duration" ]
-Number legacy_valve_remaining_duration "Legacy Valve remaining duration" (gLegacy_Valve) [ "RemainingDuration" ]
-
-Group gLegacy_Thermo "Legacy Thermostat" [ "Thermostat" ]
-Number legacy_thermostat_current_temp "L Therm. Cur. Temp. [%.1f C]" (gLegacy_Thermo) [ "CurrentTemperature" ]
-Number legacy_thermostat_target_temp "L Therm. Target Temp.[%.1f C]" (gLegacy_Thermo) [ "homekit:TargetTemperature" ]
-String legacy_thermostat_current_mode "Legacy Thermostat Current Mode" (gLegacy_Thermo) [ "homekit:CurrentHeatingCoolingMode" ]
-String legacy_thermostat_target_mode "Thermostat Target Mode" (gLegacy_Thermo) [ "homekit:TargetHeatingCoolingMode" ]
-
-Group gLegacy_Leaksensor "Legacy Leak Sensor Group" [ "LeakSensor" ]
-Switch legacy_leaksensor "Legacy Leak Sensor" (gLegacy_Leaksensor) [ "LeakSensor" ]
-Switch legacy_leaksensor_bat "Legacy Leak sensor battery status" (gLegacy_Leaksensor) [ "homekit:BatteryLowStatus" ]
-Switch legacy_leaksensor_fault "Legacy Leak sensor fault" (gLegacy_Leaksensor) [ "FaultStatus" ]
-
-Group gLegacy_Security "Legacy Security System Group" [ "SecuritySystem" ]
-String legacy_SecurityCurrentState "Security Current State" (gLegacy_Security) [ "CurrentSecuritySystemState" ]
-String legacy_SecurityTargetState "Security Target State" (gLegacy_Security) [ "TargetSecuritySystemState" ]
-```
-
-#### Using "metadata"
-
```xtend
Color color_light_single "Color Light Single" {homekit="Lighting"}
Color color_light_dimmable "Legacy Color Light Dimmable" {homekit="Lighting, Lighting.Brightness"}
import org.openhab.core.items.Metadata;
import org.openhab.core.items.MetadataKey;
import org.openhab.core.items.MetadataRegistry;
-import org.openhab.core.library.items.ColorItem;
-import org.openhab.core.library.items.DimmerItem;
import org.openhab.io.homekit.internal.HomekitAccessoryType;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitCharacteristicType;
* @author Eugen Freiter - refactoring for optional characteristics
*/
@NonNullByDefault
-@SuppressWarnings("deprecation")
public class HomekitAccessoryFactory {
private static final Logger logger = LoggerFactory.getLogger(HomekitAccessoryFactory.class);
public final static String METADATA_KEY = "homekit"; // prefix for HomeKit meta information in items.xml
new HomekitCharacteristicType[] { CURRENT_DOOR_STATE, TARGET_DOOR_STATE, OBSTRUCTION_STATUS });
put(HEATER_COOLER, new HomekitCharacteristicType[] { ACTIVE_STATUS, CURRENT_HEATER_COOLER_STATE,
TARGET_HEATER_COOLER_STATE, CURRENT_TEMPERATURE });
- // LEGACY
- put(BLINDS, new HomekitCharacteristicType[] { TARGET_POSITION, CURRENT_POSITION, POSITION_STATE });
put(WINDOW, new HomekitCharacteristicType[] { CURRENT_POSITION, TARGET_POSITION, POSITION_STATE });
put(DOOR, new HomekitCharacteristicType[] { CURRENT_POSITION, TARGET_POSITION, POSITION_STATE });
-
- put(OLD_HUMIDITY_SENSOR, new HomekitCharacteristicType[] { RELATIVE_HUMIDITY });
- put(OLD_DIMMABLE_LIGHTBULB, new HomekitCharacteristicType[] { ON_STATE });
- put(OLD_COLORFUL_LIGHTBULB, new HomekitCharacteristicType[] { ON_STATE });
}
};
put(OUTLET, HomekitOutletImpl.class);
put(SPEAKER, HomekitSpeakerImpl.class);
put(GARAGE_DOOR_OPENER, HomekitGarageDoorOpenerImpl.class);
- put(BLINDS, HomekitWindowCoveringImpl.class);
put(DOOR, HomekitDoorImpl.class);
put(WINDOW, HomekitWindowImpl.class);
put(HEATER_COOLER, HomekitHeaterCoolerImpl.class);
- put(OLD_HUMIDITY_SENSOR, HomekitHumiditySensorImpl.class);
- put(OLD_DIMMABLE_LIGHTBULB, HomekitLightbulbImpl.class);
- put(OLD_COLORFUL_LIGHTBULB, HomekitLightbulbImpl.class);
- }
- };
-
- /** mapping of legacy attributes to new attributes. **/
- private final static Map<HomekitCharacteristicType, HomekitCharacteristicType> LEGACY_CHARACTERISTICS_MAPPING = new HashMap<HomekitCharacteristicType, HomekitCharacteristicType>() {
- {
- put(OLD_CURRENT_HEATING_COOLING_STATE, CURRENT_HEATING_COOLING_STATE);
- put(OLD_TARGET_HEATING_COOLING_MODE, TARGET_HEATING_COOLING_STATE);
- put(OLD_TARGET_TEMPERATURE, TARGET_TEMPERATURE);
- put(OLD_BATTERY_LOW_STATUS, BATTERY_LOW_STATUS);
- put(VERY_OLD_TARGET_HEATING_COOLING_MODE, CURRENT_HEATING_COOLING_STATE);
- }
- };
-
- /** list of optional implicit optional characteristics. mainly used for legacy accessory type */
- private final static Map<HomekitAccessoryType, HomekitCharacteristicType[]> IMPLICIT_OPTIONAL_CHARACTERISTICS = new HashMap<HomekitAccessoryType, HomekitCharacteristicType[]>() {
- {
- put(OLD_DIMMABLE_LIGHTBULB, new HomekitCharacteristicType[] { BRIGHTNESS });
- put(OLD_COLORFUL_LIGHTBULB, new HomekitCharacteristicType[] { HUE, SATURATION, BRIGHTNESS });
-
}
};
MetadataRegistry metadataRegistry) {
final List<Entry<HomekitAccessoryType, HomekitCharacteristicType>> accessories = new ArrayList<>();
final @Nullable Metadata metadata = metadataRegistry.get(new MetadataKey(METADATA_KEY, item.getUID()));
- boolean legacyMode = metadata == null;
- String[] tags = !legacyMode ? metadata.getValue().split(",") : item.getTags().toArray(new String[0]); // fallback
- for (String tag : tags) {
- final String[] meta = tag.split("\\.");
- Optional<HomekitAccessoryType> accessoryType = HomekitAccessoryType.valueOfTag(meta[0].trim());
- if (accessoryType.isPresent()) { // it accessory, check for characteristic
- HomekitAccessoryType type = accessoryType.get();
- if ((legacyMode) && (type.equals(LIGHTBULB))) { // support old smart logic to convert Lighting to
- // DimmableLighting or ColorfulLighting depending on
- // item type
- if (item instanceof ColorItem) {
- type = OLD_COLORFUL_LIGHTBULB;
- } else if (item instanceof DimmerItem) {
- type = OLD_DIMMABLE_LIGHTBULB;
+ if (metadata != null) {
+ String[] tags = metadata.getValue().split(",");
+ for (String tag : tags) {
+ final String[] meta = tag.split("\\.");
+ Optional<HomekitAccessoryType> accessoryType = HomekitAccessoryType.valueOfTag(meta[0].trim());
+ if (accessoryType.isPresent()) { // it accessory, check for characteristic
+ HomekitAccessoryType type = accessoryType.get();
+ if (meta.length > 1) {
+ // it has characteristic as well
+ accessories.add(new SimpleEntry<>(type,
+ HomekitCharacteristicType.valueOfTag(meta[1].trim()).orElse(EMPTY)));
+ } else {// it has no characteristic
+ accessories.add(new SimpleEntry<>(type, EMPTY));
}
+ } else { // it is no accessory, so, maybe it is a characteristic
+ HomekitCharacteristicType.valueOfTag(meta[0].trim())
+ .ifPresent(c -> accessories.add(new SimpleEntry<>(DUMMY, c)));
}
- if (meta.length > 1) {
- // it has characteristic as well
- accessories.add(new SimpleEntry<>(type,
- HomekitCharacteristicType.valueOfTag(meta[1].trim()).orElse(EMPTY)));
- } else {// it has no characteristic
- accessories.add(new SimpleEntry<>(type, EMPTY));
- }
- } else { // it is no accessory, so, maybe it is a characteristic
- HomekitCharacteristicType.valueOfTag(meta[0].trim())
- .ifPresent(c -> accessories.add(new SimpleEntry<>(DUMMY, c)));
}
}
return accessories;
} else {
// item has characteristic tag on it, so, adding it as that characteristic.
- // check whether it is a legacy characteristic, i.e. old tag was used, and replaced by a new one
- final HomekitCharacteristicType characteristic = legacyCheck(accessory.getValue());
+ final HomekitCharacteristicType characteristic = accessory.getValue();
// check whether it is a mandatory characteristic. optional will be added later by another method.
if (isMandatoryCharacteristic(mainItem.getAccessoryType(), characteristic)) {
GroupItem groupItem = (GroupItem) taggedItem.getItem();
groupItem.getMembers().forEach(item -> getAccessoryTypes(item, metadataRegistry).stream()
.filter(c -> !isRootAccessory(c))
- .filter(c -> !isMandatoryCharacteristic(taggedItem.getAccessoryType(), legacyCheck(c.getValue())))
- .forEach(characteristic -> characteristicItems.put(legacyCheck(characteristic.getValue()),
- (GenericItem) item)));
+ .filter(c -> !isMandatoryCharacteristic(taggedItem.getAccessoryType(), c.getValue()))
+ .forEach(characteristic -> characteristicItems.put(characteristic.getValue(), (GenericItem) item)));
} else {
getAccessoryTypes(taggedItem.getItem(), metadataRegistry).stream().filter(c -> !isRootAccessory(c))
- .filter(c -> !isMandatoryCharacteristic(taggedItem.getAccessoryType(), legacyCheck(c.getValue())))
- .forEach(characteristic -> characteristicItems.put(legacyCheck(characteristic.getValue()),
+ .filter(c -> !isMandatoryCharacteristic(taggedItem.getAccessoryType(), c.getValue()))
+ .forEach(characteristic -> characteristicItems.put(characteristic.getValue(),
(GenericItem) taggedItem.getItem()));
- final HomekitCharacteristicType[] implicitOptionalCharacteristics = IMPLICIT_OPTIONAL_CHARACTERISTICS
- .get(taggedItem.getAccessoryType());
- if (implicitOptionalCharacteristics != null) {
- Arrays.stream(implicitOptionalCharacteristics)
- .filter(c -> !isMandatoryCharacteristic(taggedItem.getAccessoryType(), c))
- .forEach(characteristic -> characteristicItems.put(legacyCheck(characteristic),
- (GenericItem) taggedItem.getItem()));
- }
}
logger.trace("Optional characteristics for item {} characteristics {}", taggedItem.getName(),
characteristicItems);
private static boolean isRootAccessory(Entry<HomekitAccessoryType, HomekitCharacteristicType> accessory) {
return ((accessory.getValue() == null) || (accessory.getValue() == EMPTY));
}
-
- /**
- * check whether it is legacy characteristic and return new name in such case. otherwise return the input parameter
- * unchanged.
- *
- * @param characteristicType characteristic to check
- * @return new characteristic type
- */
- private static HomekitCharacteristicType legacyCheck(HomekitCharacteristicType characteristicType) {
- return LEGACY_CHARACTERISTICS_MAPPING.getOrDefault(characteristicType, characteristicType);
- }
}