Skip to content

Commit

Permalink
Also adjust system channel types for unit (openhab#3649)
Browse files Browse the repository at this point in the history
Signed-off-by: Jan N. Klug <github@klug.nrw>
GitOrigin-RevId: 545ecfe
  • Loading branch information
J-N-K authored and splatch committed Jul 12, 2023
1 parent 935ef3b commit 21757e6
Showing 1 changed file with 71 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
*/
package org.openhab.core.tools.internal;

import static org.openhab.core.thing.DefaultSystemChannelTypeProvider.SYSTEM_CHANNEL_TYPE_UID_ATMOSPHERIC_HUMIDITY;
import static org.openhab.core.thing.DefaultSystemChannelTypeProvider.SYSTEM_CHANNEL_TYPE_UID_BATTERY_LEVEL;
import static org.openhab.core.thing.DefaultSystemChannelTypeProvider.SYSTEM_CHANNEL_TYPE_UID_COLOR_TEMPERATURE_ABS;

import java.nio.file.Files;
import java.nio.file.Path;
import java.time.ZonedDateTime;
Expand All @@ -27,6 +31,7 @@
import org.openhab.core.items.MetadataKey;
import org.openhab.core.library.items.NumberItem;
import org.openhab.core.storage.json.internal.JsonStorage;
import org.openhab.core.thing.dto.ThingDTO;
import org.openhab.core.thing.internal.link.ItemChannelLinkConfigDescriptionProvider;
import org.openhab.core.thing.link.ItemChannelLink;
import org.openhab.core.types.util.UnitUtils;
Expand All @@ -53,6 +58,7 @@ public Upgrader(String baseDir, boolean force) {
this.force = force;

Path upgradeJsonDatabasePath = Path.of(baseDir, "jsondb", "org.openhab.core.tools.UpgradeTool");

upgradeRecords = new JsonStorage<>(upgradeJsonDatabasePath.toFile(), null, 5, 0, 0, List.of());
}

Expand All @@ -67,17 +73,29 @@ private boolean checkUpgradeRecord(String key) {
}

public void itemCopyUnitToMetadata() {
boolean noLink;

if (!checkUpgradeRecord(ITEM_COPY_UNIT_TO_METADATA)) {
return;
}
Path itemJsonDatabasePath = Path.of(baseDir, "jsondb", "org.openhab.core.items.Item.json");
Path metadataJsonDatabasePath = Path.of(baseDir, "jsondb", "org.openhab.core.items.Metadata.json");
Path linkJsonDatabasePath = Path.of(baseDir, "jsondb", "org.openhab.core.thing.link.ItemChannelLink.json");
Path thingJsonDatabasePath = Path.of(baseDir, "jsondb", "org.openhab.core.thing.Thing.json");
logger.info("Copying item unit from state description to metadata in database '{}'", itemJsonDatabasePath);

if (!Files.isReadable(itemJsonDatabasePath)) {
logger.error("Cannot access item database '{}', check path and access rights.", itemJsonDatabasePath);
return;
}

if (!Files.isReadable(linkJsonDatabasePath) || !Files.isReadable(thingJsonDatabasePath)) {
logger.warn("Cannot access thing or link database '{}', update may be incomplete.", linkJsonDatabasePath);
noLink = true;
} else {
noLink = false;
}

// missing metadata database is also fine, we create one in that case
if (!Files.isWritable(metadataJsonDatabasePath) && Files.exists(metadataJsonDatabasePath)) {
logger.error("Cannot access metadata database '{}', check path and access rights.",
Expand All @@ -89,16 +107,60 @@ public void itemCopyUnitToMetadata() {
null, 5, 0, 0, List.of());
JsonStorage<Metadata> metadataStorage = new JsonStorage<>(metadataJsonDatabasePath.toFile(), null, 5, 0, 0,
List.of());
JsonStorage<ItemChannelLink> linkStorage = noLink ? null
: new JsonStorage<>(linkJsonDatabasePath.toFile(), null, 5, 0, 0, List.of());
JsonStorage<ThingDTO> thingStorage = noLink ? null
: new JsonStorage<>(thingJsonDatabasePath.toFile(), null, 5, 0, 0, List.of());

itemStorage.getKeys().forEach(itemName -> {
ManagedItemProvider.PersistedItem item = itemStorage.get(itemName);
if (item != null && item.itemType.startsWith("Number:")) {
if (metadataStorage.containsKey(NumberItem.UNIT_METADATA_NAMESPACE + ":" + itemName)) {
logger.debug("{}: Already contains a 'unit' metadata, skipping it", itemName);
} else {
String unit = null;
if (!noLink) {
List<ItemChannelLink> links = linkStorage.getValues().stream().map(Objects::requireNonNull)
.filter(link -> itemName.equals(link.getItemName())).toList();
// check if we can find the channel for these links
for (ItemChannelLink link : links) {
ThingDTO thing = thingStorage.get(link.getLinkedUID().getThingUID().toString());
if (thing == null) {
logger.info(
"{}: Could not find thing for channel '{}'. Check if you need to set unit metadata.",
itemName, link.getLinkedUID());
continue;
}
String channelTypeUID = thing.channels.stream()
.filter(channel -> link.getLinkedUID().toString().equals(channel.uid))
.map(channel -> channel.channelTypeUID).findFirst().orElse(null);
if (channelTypeUID == null) {
continue;
}
// replace . with :, if the database is already correct, we can ignore that
channelTypeUID = channelTypeUID.replace(".", ":");
if (channelTypeUID.startsWith("system")) {
if (channelTypeUID.equals(SYSTEM_CHANNEL_TYPE_UID_BATTERY_LEVEL.toString())
|| channelTypeUID
.equals(SYSTEM_CHANNEL_TYPE_UID_ATMOSPHERIC_HUMIDITY.toString())) {
unit = "%";
} else if (channelTypeUID
.equals(SYSTEM_CHANNEL_TYPE_UID_COLOR_TEMPERATURE_ABS.toString())) {
unit = "K";
}
} else {
logger.warn(
"{}: Could not determine if channel '{}' sets a state description. Check if you need to set unit metadata.",
itemName, link.getLinkedUID());
}
}
}

// metadata state description has higher priority, so we check that and override the unit if
// necessary
Metadata metadata = metadataStorage.get("stateDescription:" + itemName);
if (metadata == null) {
logger.debug("{}: Nothing to do, no state description found.", itemName);
logger.debug("{}: No state description in metadata found.", itemName);
} else {
String pattern = (String) metadata.getConfiguration().get("pattern");
if (pattern != null) {
Expand All @@ -109,18 +171,20 @@ public void itemCopyUnitToMetadata() {
} else {
Unit<?> stateDescriptionUnit = UnitUtils.parseUnit(pattern);
if (stateDescriptionUnit != null) {
String unit = stateDescriptionUnit.toString();
MetadataKey defaultUnitMetadataKey = new MetadataKey(
NumberItem.UNIT_METADATA_NAMESPACE, itemName);
Metadata defaultUnitMetadata = new Metadata(defaultUnitMetadataKey, unit, null);
metadataStorage.put(defaultUnitMetadataKey.toString(), defaultUnitMetadata);
logger.info("{}: Wrote 'unit={}' to metadata.", itemName, unit);
unit = stateDescriptionUnit.toString();
}
}
} else {
logger.debug("{}: Nothing to do, no pattern found.", itemName);
}
}
if (unit != null) {
MetadataKey defaultUnitMetadataKey = new MetadataKey(NumberItem.UNIT_METADATA_NAMESPACE,
itemName);
Metadata defaultUnitMetadata = new Metadata(defaultUnitMetadataKey, unit, null);
metadataStorage.put(defaultUnitMetadataKey.toString(), defaultUnitMetadata);
logger.info("{}: Wrote 'unit={}' to metadata.", itemName, unit);
}
}
}
});
Expand Down

0 comments on commit 21757e6

Please sign in to comment.