[homekit] fix for battery charging state (#12959)

* fix for battery charging state

Signed-off-by: Eugen Freiter <freiter@gmx.de>
This commit is contained in:
eugen
2022-06-22 11:20:36 +02:00
committed by GitHub
parent cf94687ad6
commit 565dc19508
8 changed files with 62 additions and 39 deletions

View File

@@ -153,4 +153,9 @@ public enum HomekitCharacteristicType {
public static Optional<HomekitCharacteristicType> valueOfTag(String tag) {
return Optional.ofNullable(TAG_MAP.get(tag));
}
@Override
public String toString() {
return tag;
}
}

View File

@@ -282,7 +282,7 @@ public class HomekitTaggedItem {
}
public String toString() {
return "Item:" + proxyItem.getItem() + " HomeKit type:" + homekitAccessoryType + " HomeKit characteristic:"
+ homekitCharacteristicType;
return "Item:" + proxyItem.getItem() + " HomeKit type: '" + homekitAccessoryType.getTag()
+ "' characteristic: '" + homekitCharacteristicType.getTag() + "'";
}
}

View File

@@ -141,8 +141,21 @@ public class HomekitAccessoryFactory {
}
};
private static List<HomekitCharacteristicType> getRequiredCharacteristics(HomekitTaggedItem taggedItem) {
if (taggedItem.getAccessoryType() == BATTERY) {
final String isChargeable = taggedItem.getConfiguration(HomekitBatteryImpl.BATTERY_TYPE, "false");
if ("true".equalsIgnoreCase(isChargeable) || "yes".equalsIgnoreCase(isChargeable)) {
final List<HomekitCharacteristicType> characteristics = new ArrayList<>();
characteristics.addAll(Arrays.asList(MANDATORY_CHARACTERISTICS.get(taggedItem.getAccessoryType())));
characteristics.add(BATTERY_CHARGING_STATE);
return characteristics;
}
}
return Arrays.asList(MANDATORY_CHARACTERISTICS.get(taggedItem.getAccessoryType()));
}
/**
* creates HomeKit accessory for a openhab item.
* creates HomeKit accessory for an openhab item.
*
* @param taggedItem openhab item tagged as HomeKit item
* @param metadataRegistry openhab metadata registry required to get item meta information
@@ -158,12 +171,12 @@ public class HomekitAccessoryFactory {
HomekitAccessoryUpdater updater, HomekitSettings settings) throws HomekitException {
final HomekitAccessoryType accessoryType = taggedItem.getAccessoryType();
logger.trace("Constructing {} of accessory type {}", taggedItem.getName(), accessoryType.getTag());
final List<HomekitTaggedItem> requiredCharacteristics = getMandatoryCharacteristics(taggedItem,
final List<HomekitTaggedItem> foundCharacteristics = getMandatoryCharacteristicsFromItem(taggedItem,
metadataRegistry);
final HomekitCharacteristicType[] mandatoryCharacteristics = MANDATORY_CHARACTERISTICS.get(accessoryType);
if ((mandatoryCharacteristics != null) && (requiredCharacteristics.size() < mandatoryCharacteristics.length)) {
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, requiredCharacteristics);
accessoryType.getTag(), mandatoryCharacteristics, foundCharacteristics);
throw new HomekitException("Missing mandatory characteristics");
}
AbstractHomekitAccessoryImpl accessoryImpl;
@@ -171,10 +184,9 @@ public class HomekitAccessoryFactory {
final @Nullable Class<? extends AbstractHomekitAccessoryImpl> accessoryImplClass = SERVICE_IMPL_MAP
.get(accessoryType);
if (accessoryImplClass != null) {
accessoryImpl = accessoryImplClass
.getConstructor(HomekitTaggedItem.class, List.class, HomekitAccessoryUpdater.class,
HomekitSettings.class)
.newInstance(taggedItem, requiredCharacteristics, updater, settings);
accessoryImpl = accessoryImplClass.getConstructor(HomekitTaggedItem.class, List.class,
HomekitAccessoryUpdater.class, HomekitSettings.class)
.newInstance(taggedItem, foundCharacteristics, updater, settings);
addOptionalCharacteristics(taggedItem, accessoryImpl, metadataRegistry);
return accessoryImpl;
} else {
@@ -255,7 +267,7 @@ public class HomekitAccessoryFactory {
* @param metadataRegistry meta data registry
* @return list of mandatory
*/
private static List<HomekitTaggedItem> getMandatoryCharacteristics(HomekitTaggedItem taggedItem,
private static List<HomekitTaggedItem> getMandatoryCharacteristicsFromItem(HomekitTaggedItem taggedItem,
MetadataRegistry metadataRegistry) {
List<HomekitTaggedItem> collectedCharacteristics = new ArrayList<>();
if (taggedItem.isGroup()) {
@@ -265,8 +277,7 @@ public class HomekitAccessoryFactory {
} else {
addMandatoryCharacteristics(taggedItem, collectedCharacteristics, taggedItem.getItem(), metadataRegistry);
}
logger.trace("Mandatory characteristics for item {} characteristics {}", taggedItem.getName(),
collectedCharacteristics);
logger.trace("Mandatory characteristics: {}", collectedCharacteristics);
return collectedCharacteristics;
}
@@ -285,9 +296,8 @@ public class HomekitAccessoryFactory {
private static void addMandatoryCharacteristics(HomekitTaggedItem mainItem, List<HomekitTaggedItem> characteristics,
Item item, MetadataRegistry metadataRegistry) {
// get list of mandatory characteristics
HomekitCharacteristicType[] mandatoryCharacteristics = MANDATORY_CHARACTERISTICS
.get(mainItem.getAccessoryType());
if ((mandatoryCharacteristics == null) || (mandatoryCharacteristics.length == 0)) {
List<HomekitCharacteristicType> mandatoryCharacteristics = getRequiredCharacteristics(mainItem);
if (mandatoryCharacteristics.isEmpty()) {
// no mandatory characteristics linked to accessory type of mainItem. we are done
return;
}
@@ -299,13 +309,12 @@ public class HomekitAccessoryFactory {
for (Entry<HomekitAccessoryType, HomekitCharacteristicType> accessory : getAccessoryTypes(item,
metadataRegistry)) {
// if the item has only accessory tag, e.g. TemperatureSensor,
// the we will link all mandatory characteristic to this item,
// then we will link all mandatory characteristic to this item,
// e.g. we will link CurrentTemperature in case of TemperatureSensor.
if (isRootAccessory(accessory)) {
Arrays.stream(mandatoryCharacteristics)
.forEach(c -> characteristics.add(new HomekitTaggedItem(itemProxy, accessory.getKey(), c,
mainItem.isGroup() ? (GroupItem) mainItem.getItem() : null,
HomekitAccessoryFactory.getItemConfiguration(item, metadataRegistry))));
mandatoryCharacteristics.forEach(c -> characteristics.add(new HomekitTaggedItem(itemProxy,
accessory.getKey(), c, mainItem.isGroup() ? (GroupItem) mainItem.getItem() : null,
HomekitAccessoryFactory.getItemConfiguration(item, metadataRegistry))));
} else {
// item has characteristic tag on it, so, adding it as that characteristic.
@@ -313,7 +322,7 @@ public class HomekitAccessoryFactory {
// check whether it is a mandatory characteristic. optional will be added later by another method.
if (belongsToType(mainItem.getAccessoryType(), accessory)
&& isMandatoryCharacteristic(mainItem.getAccessoryType(), characteristic)) {
&& isMandatoryCharacteristic(mainItem, characteristic)) {
characteristics.add(new HomekitTaggedItem(itemProxy, accessory.getKey(), characteristic,
mainItem.isGroup() ? (GroupItem) mainItem.getItem() : null,
HomekitAccessoryFactory.getItemConfiguration(item, metadataRegistry)));
@@ -373,30 +382,28 @@ public class HomekitAccessoryFactory {
GroupItem groupItem = (GroupItem) taggedItem.getItem();
groupItem.getMembers().forEach(item -> getAccessoryTypes(item, metadataRegistry).stream()
.filter(c -> !isRootAccessory(c)).filter(c -> belongsToType(taggedItem.getAccessoryType(), c))
.filter(c -> !isMandatoryCharacteristic(taggedItem.getAccessoryType(), c.getValue()))
.filter(c -> !isMandatoryCharacteristic(taggedItem, 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(), c.getValue()))
.filter(c -> !isMandatoryCharacteristic(taggedItem, c.getValue()))
.forEach(characteristic -> characteristicItems.put(characteristic.getValue(),
(GenericItem) taggedItem.getItem()));
}
logger.trace("Optional characteristics for item {} characteristics {}", taggedItem.getName(),
characteristicItems);
logger.trace("Optional characteristics for item {}: {}", taggedItem.getName(), characteristicItems.values());
return Collections.unmodifiableMap(characteristicItems);
}
/**
* return true is characteristic is a mandatory characteristic for the accessory.
*
* @param accessory accessory
* @param item item
* @param characteristic characteristic
* @return true if characteristic is mandatory, false if not mandatory
*/
private static boolean isMandatoryCharacteristic(HomekitAccessoryType accessory,
HomekitCharacteristicType characteristic) {
return MANDATORY_CHARACTERISTICS.containsKey(accessory)
&& Arrays.asList(MANDATORY_CHARACTERISTICS.get(accessory)).contains(characteristic);
private static boolean isMandatoryCharacteristic(HomekitTaggedItem item, HomekitCharacteristicType characteristic) {
return MANDATORY_CHARACTERISTICS.containsKey(item.getAccessoryType())
&& getRequiredCharacteristics(item).contains(characteristic);
}
/**

View File

@@ -37,7 +37,7 @@ import io.github.hapjava.services.impl.BatteryService;
* @author Eugen Freiter - Initial contribution
*/
public class HomekitBatteryImpl extends AbstractHomekitAccessoryImpl implements BatteryAccessory {
private static final String BATTERY_TYPE = "chargeable";
public static final String BATTERY_TYPE = "chargeable";
private final BooleanItemReader lowBatteryReader;
private BooleanItemReader chargingBatteryReader;
@@ -87,7 +87,9 @@ public class HomekitBatteryImpl extends AbstractHomekitAccessoryImpl implements
@Override
public void subscribeBatteryChargingState(final HomekitCharacteristicChangeCallback callback) {
subscribe(BATTERY_CHARGING_STATE, callback);
if (isChargeable) {
subscribe(BATTERY_CHARGING_STATE, callback);
}
}
@Override
@@ -102,6 +104,8 @@ public class HomekitBatteryImpl extends AbstractHomekitAccessoryImpl implements
@Override
public void unsubscribeBatteryChargingState() {
unsubscribe(BATTERY_CHARGING_STATE);
if (isChargeable) {
unsubscribe(BATTERY_CHARGING_STATE);
}
}
}

View File

@@ -184,13 +184,14 @@ public class HomekitCharacteristicFactory {
public static Characteristic createCharacteristic(HomekitTaggedItem item, HomekitAccessoryUpdater updater)
throws HomekitException {
final @Nullable HomekitCharacteristicType type = item.getCharacteristicType();
logger.trace("CreateCharacteristic, type {} item {}", type, item);
logger.trace("Create characteristic {}", item);
if (optional.containsKey(type)) {
return optional.get(type).apply(item, updater);
}
logger.warn("Unsupported optional characteristic. Accessory type {}, characteristic type {}",
item.getAccessoryType(), type);
throw new HomekitException("Unsupported optional characteristic. Characteristic type \"" + type + "\"");
item.getAccessoryType(), type.getTag());
throw new HomekitException(
"Unsupported optional characteristic. Characteristic type \"" + type.getTag() + "\"");
}
// METHODS TO CREATE SINGLE CHARACTERISTIC FROM OH ITEM

View File

@@ -24,7 +24,7 @@ public class IncompleteAccessoryException extends Exception {
private static final long serialVersionUID = 8595808359805444177L;
public IncompleteAccessoryException(HomekitCharacteristicType missingType) {
super(String.format("Missing accessory type %s", missingType.getTag()));
super(String.format("Missing accessory characteristic %s", missingType.getTag()));
}
public IncompleteAccessoryException(String message) {