[miio] i18n translation handling for basic channels (#11576)

Signed-off-by: Marcel Verpaalen <marcel@verpaalen.com>
This commit is contained in:
Marcel 2021-12-02 09:08:17 +01:00 committed by GitHub
parent 7c8a197e17
commit 82ac5ee2d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 2640 additions and 51 deletions

View File

@ -123,4 +123,8 @@ public final class MiIoBindingConstants {
+ File.separator + BINDING_ID; + File.separator + BINDING_ID;
public static final String BINDING_USERDATA_PATH = OpenHAB.getUserDataFolder() + File.separator public static final String BINDING_USERDATA_PATH = OpenHAB.getUserDataFolder() + File.separator
+ MiIoBindingConstants.BINDING_ID; + MiIoBindingConstants.BINDING_ID;
public static final String I18N_THING_PREFIX = "thing.";
public static final String I18N_CHANNEL_PREFIX = "ch.";
public static final String I18N_OPTION_PREFIX = "option.";
} }

View File

@ -29,6 +29,8 @@ import org.openhab.binding.miio.internal.handler.MiIoGenericHandler;
import org.openhab.binding.miio.internal.handler.MiIoUnsupportedHandler; import org.openhab.binding.miio.internal.handler.MiIoUnsupportedHandler;
import org.openhab.binding.miio.internal.handler.MiIoVacuumHandler; import org.openhab.binding.miio.internal.handler.MiIoVacuumHandler;
import org.openhab.core.common.ThreadPoolManager; import org.openhab.core.common.ThreadPoolManager;
import org.openhab.core.i18n.LocaleProvider;
import org.openhab.core.i18n.TranslationProvider;
import org.openhab.core.io.net.http.HttpClientFactory; import org.openhab.core.io.net.http.HttpClientFactory;
import org.openhab.core.thing.Thing; import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID; import org.openhab.core.thing.ThingTypeUID;
@ -60,6 +62,8 @@ public class MiIoHandlerFactory extends BaseThingHandlerFactory {
private CloudConnector cloudConnector; private CloudConnector cloudConnector;
private ChannelTypeRegistry channelTypeRegistry; private ChannelTypeRegistry channelTypeRegistry;
private BasicChannelTypeProvider basicChannelTypeProvider; private BasicChannelTypeProvider basicChannelTypeProvider;
private final TranslationProvider i18nProvider;
private final LocaleProvider localeProvider;
private @Nullable Future<Boolean> scheduledTask; private @Nullable Future<Boolean> scheduledTask;
private final Logger logger = LoggerFactory.getLogger(MiIoHandlerFactory.class); private final Logger logger = LoggerFactory.getLogger(MiIoHandlerFactory.class);
@ -67,11 +71,14 @@ public class MiIoHandlerFactory extends BaseThingHandlerFactory {
public MiIoHandlerFactory(@Reference HttpClientFactory httpClientFactory, public MiIoHandlerFactory(@Reference HttpClientFactory httpClientFactory,
@Reference ChannelTypeRegistry channelTypeRegistry, @Reference ChannelTypeRegistry channelTypeRegistry,
@Reference MiIoDatabaseWatchService miIoDatabaseWatchService, @Reference CloudConnector cloudConnector, @Reference MiIoDatabaseWatchService miIoDatabaseWatchService, @Reference CloudConnector cloudConnector,
@Reference BasicChannelTypeProvider basicChannelTypeProvider, Map<String, Object> properties) { @Reference BasicChannelTypeProvider basicChannelTypeProvider, @Reference TranslationProvider i18nProvider,
@Reference LocaleProvider localeProvider, Map<String, Object> properties) {
this.httpClientFactory = httpClientFactory; this.httpClientFactory = httpClientFactory;
this.miIoDatabaseWatchService = miIoDatabaseWatchService; this.miIoDatabaseWatchService = miIoDatabaseWatchService;
this.channelTypeRegistry = channelTypeRegistry; this.channelTypeRegistry = channelTypeRegistry;
this.basicChannelTypeProvider = basicChannelTypeProvider; this.basicChannelTypeProvider = basicChannelTypeProvider;
this.i18nProvider = i18nProvider;
this.localeProvider = localeProvider;
this.cloudConnector = cloudConnector; this.cloudConnector = cloudConnector;
@Nullable @Nullable
String username = (String) properties.get("username"); String username = (String) properties.get("username");
@ -108,16 +115,18 @@ public class MiIoHandlerFactory extends BaseThingHandlerFactory {
protected @Nullable ThingHandler createHandler(Thing thing) { protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID(); ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (thingTypeUID.equals(THING_TYPE_MIIO)) { if (thingTypeUID.equals(THING_TYPE_MIIO)) {
return new MiIoGenericHandler(thing, miIoDatabaseWatchService, cloudConnector); return new MiIoGenericHandler(thing, miIoDatabaseWatchService, cloudConnector, i18nProvider,
localeProvider);
} }
if (thingTypeUID.equals(THING_TYPE_BASIC)) { if (thingTypeUID.equals(THING_TYPE_BASIC)) {
return new MiIoBasicHandler(thing, miIoDatabaseWatchService, cloudConnector, channelTypeRegistry, return new MiIoBasicHandler(thing, miIoDatabaseWatchService, cloudConnector, channelTypeRegistry,
basicChannelTypeProvider); basicChannelTypeProvider, i18nProvider, localeProvider);
} }
if (thingTypeUID.equals(THING_TYPE_VACUUM)) { if (thingTypeUID.equals(THING_TYPE_VACUUM)) {
return new MiIoVacuumHandler(thing, miIoDatabaseWatchService, cloudConnector, channelTypeRegistry); return new MiIoVacuumHandler(thing, miIoDatabaseWatchService, cloudConnector, channelTypeRegistry,
i18nProvider, localeProvider);
} }
return new MiIoUnsupportedHandler(thing, miIoDatabaseWatchService, cloudConnector, return new MiIoUnsupportedHandler(thing, miIoDatabaseWatchService, cloudConnector,
httpClientFactory.getCommonHttpClient()); httpClientFactory.getCommonHttpClient(), i18nProvider, localeProvider);
} }
} }

View File

@ -50,6 +50,8 @@ import org.openhab.binding.miio.internal.transport.MiIoAsyncCommunication;
import org.openhab.core.cache.ExpiringCache; import org.openhab.core.cache.ExpiringCache;
import org.openhab.core.common.NamedThreadFactory; import org.openhab.core.common.NamedThreadFactory;
import org.openhab.core.config.core.Configuration; import org.openhab.core.config.core.Configuration;
import org.openhab.core.i18n.LocaleProvider;
import org.openhab.core.i18n.TranslationProvider;
import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.StringType; import org.openhab.core.library.types.StringType;
import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.ChannelUID;
@ -60,6 +62,8 @@ import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.binding.BaseThingHandler; import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.thing.binding.builder.ThingBuilder; import org.openhab.core.thing.binding.builder.ThingBuilder;
import org.openhab.core.types.Command; import org.openhab.core.types.Command;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -81,6 +85,9 @@ public abstract class MiIoAbstractHandler extends BaseThingHandler implements Mi
protected static final int MAX_QUEUE = 5; protected static final int MAX_QUEUE = 5;
protected static final Gson GSON = new GsonBuilder().create(); protected static final Gson GSON = new GsonBuilder().create();
protected static final String TIMESTAMP = "timestamp"; protected static final String TIMESTAMP = "timestamp";
protected final Bundle bundle;
protected final TranslationProvider i18nProvider;
protected final LocaleProvider localeProvider;
protected ScheduledExecutorService miIoScheduler = new ScheduledThreadPoolExecutor(3, protected ScheduledExecutorService miIoScheduler = new ScheduledThreadPoolExecutor(3,
new NamedThreadFactory("binding-" + getThing().getUID().getAsString(), true)); new NamedThreadFactory("binding-" + getThing().getUID().getAsString(), true));
@ -114,10 +121,13 @@ public abstract class MiIoAbstractHandler extends BaseThingHandler implements Mi
protected MiIoDatabaseWatchService miIoDatabaseWatchService; protected MiIoDatabaseWatchService miIoDatabaseWatchService;
public MiIoAbstractHandler(Thing thing, MiIoDatabaseWatchService miIoDatabaseWatchService, public MiIoAbstractHandler(Thing thing, MiIoDatabaseWatchService miIoDatabaseWatchService,
CloudConnector cloudConnector) { CloudConnector cloudConnector, TranslationProvider i18nProvider, LocaleProvider localeProvider) {
super(thing); super(thing);
this.miIoDatabaseWatchService = miIoDatabaseWatchService; this.miIoDatabaseWatchService = miIoDatabaseWatchService;
this.cloudConnector = cloudConnector; this.cloudConnector = cloudConnector;
this.i18nProvider = i18nProvider;
this.localeProvider = localeProvider;
this.bundle = FrameworkUtil.getBundle(this.getClass());
} }
@Override @Override
@ -590,7 +600,8 @@ public abstract class MiIoAbstractHandler extends BaseThingHandler implements Mi
String label = getThing().getLabel(); String label = getThing().getLabel();
if (label == null || label.startsWith("Xiaomi Mi Device")) { if (label == null || label.startsWith("Xiaomi Mi Device")) {
ThingBuilder thingBuilder = editThing(); ThingBuilder thingBuilder = editThing();
thingBuilder.withLabel(miDevice.getDescription()); label = getLocalText(I18N_THING_PREFIX + modelId, miDevice.getDescription());
thingBuilder.withLabel(label);
updateThing(thingBuilder.build()); updateThing(thingBuilder.build());
} }
logger.info("Mi Device model {} identified as: {}. Does not match thingtype {}. Changing thingtype to {}", logger.info("Mi Device model {} identified as: {}. Does not match thingtype {}. Changing thingtype to {}",
@ -644,4 +655,13 @@ public abstract class MiIoAbstractHandler extends BaseThingHandler implements Mi
logger.debug("Error while handing message {}", response.getResponse(), e); logger.debug("Error while handing message {}", response.getResponse(), e);
} }
} }
protected String getLocalText(String key, String defaultText) {
try {
String text = i18nProvider.getText(bundle, key, defaultText, localeProvider.getLocale());
return text != null ? text : defaultText;
} catch (IllegalArgumentException e) {
return defaultText;
}
}
} }

View File

@ -49,6 +49,8 @@ import org.openhab.binding.miio.internal.basic.MiIoDeviceActionCondition;
import org.openhab.binding.miio.internal.cloud.CloudConnector; import org.openhab.binding.miio.internal.cloud.CloudConnector;
import org.openhab.binding.miio.internal.transport.MiIoAsyncCommunication; import org.openhab.binding.miio.internal.transport.MiIoAsyncCommunication;
import org.openhab.core.cache.ExpiringCache; import org.openhab.core.cache.ExpiringCache;
import org.openhab.core.i18n.LocaleProvider;
import org.openhab.core.i18n.TranslationProvider;
import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.HSBType; import org.openhab.core.library.types.HSBType;
import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OnOffType;
@ -106,8 +108,9 @@ public class MiIoBasicHandler extends MiIoAbstractHandler {
public MiIoBasicHandler(Thing thing, MiIoDatabaseWatchService miIoDatabaseWatchService, public MiIoBasicHandler(Thing thing, MiIoDatabaseWatchService miIoDatabaseWatchService,
CloudConnector cloudConnector, ChannelTypeRegistry channelTypeRegistry, CloudConnector cloudConnector, ChannelTypeRegistry channelTypeRegistry,
BasicChannelTypeProvider basicChannelTypeProvider) { BasicChannelTypeProvider basicChannelTypeProvider, TranslationProvider i18nProvider,
super(thing, miIoDatabaseWatchService, cloudConnector); LocaleProvider localeProvider) {
super(thing, miIoDatabaseWatchService, cloudConnector, i18nProvider, localeProvider);
this.channelTypeRegistry = channelTypeRegistry; this.channelTypeRegistry = channelTypeRegistry;
this.basicChannelTypeProvider = basicChannelTypeProvider; this.basicChannelTypeProvider = basicChannelTypeProvider;
} }
@ -452,6 +455,7 @@ public class MiIoBasicHandler extends MiIoAbstractHandler {
try { try {
JsonObject deviceMapping = Utils.convertFileToJSON(fn); JsonObject deviceMapping = Utils.convertFileToJSON(fn);
logger.debug("Using device database: {} for device {}", fn.getFile(), deviceName); logger.debug("Using device database: {} for device {}", fn.getFile(), deviceName);
String key = fn.getFile().replaceFirst("/database/", "").split("json")[0];
Gson gson = new GsonBuilder().serializeNulls().create(); Gson gson = new GsonBuilder().serializeNulls().create();
miioDevice = gson.fromJson(deviceMapping, MiIoBasicDevice.class); miioDevice = gson.fromJson(deviceMapping, MiIoBasicDevice.class);
for (Channel ch : getThing().getChannels()) { for (Channel ch : getThing().getChannels()) {
@ -475,7 +479,7 @@ public class MiIoBasicHandler extends MiIoAbstractHandler {
logger.debug("properties {}", miChannel); logger.debug("properties {}", miChannel);
if (!miChannel.getType().isEmpty()) { if (!miChannel.getType().isEmpty()) {
basicChannelTypeProvider.addChannelType(miChannel, deviceName); basicChannelTypeProvider.addChannelType(miChannel, deviceName);
ChannelUID channelUID = addChannel(thingBuilder, miChannel, deviceName); ChannelUID channelUID = addChannel(thingBuilder, miChannel, deviceName, key);
if (channelUID != null) { if (channelUID != null) {
actions.put(channelUID, miChannel); actions.put(channelUID, miChannel);
channelsAdded++; channelsAdded++;
@ -505,7 +509,8 @@ public class MiIoBasicHandler extends MiIoAbstractHandler {
return false; return false;
} }
private @Nullable ChannelUID addChannel(ThingBuilder thingBuilder, MiIoBasicChannel miChannel, String model) { private @Nullable ChannelUID addChannel(ThingBuilder thingBuilder, MiIoBasicChannel miChannel, String model,
String key) {
String channel = miChannel.getChannel(); String channel = miChannel.getChannel();
String dataType = miChannel.getType(); String dataType = miChannel.getType();
if (channel.isEmpty() || dataType.isEmpty()) { if (channel.isEmpty() || dataType.isEmpty()) {
@ -514,7 +519,8 @@ public class MiIoBasicHandler extends MiIoAbstractHandler {
return null; return null;
} }
ChannelUID channelUID = new ChannelUID(getThing().getUID(), channel); ChannelUID channelUID = new ChannelUID(getThing().getUID(), channel);
ChannelBuilder newChannel = ChannelBuilder.create(channelUID, dataType).withLabel(miChannel.getFriendlyName()); String label = getLocalText(I18N_CHANNEL_PREFIX + key + channel, miChannel.getFriendlyName());
ChannelBuilder newChannel = ChannelBuilder.create(channelUID, dataType).withLabel(label);
boolean useGeneratedChannelType = false; boolean useGeneratedChannelType = false;
if (!miChannel.getChannelType().isBlank()) { if (!miChannel.getChannelType().isBlank()) {
ChannelTypeUID channelTypeUID = new ChannelTypeUID(miChannel.getChannelType()); ChannelTypeUID channelTypeUID = new ChannelTypeUID(miChannel.getChannelType());

View File

@ -15,6 +15,8 @@ package org.openhab.binding.miio.internal.handler;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.miio.internal.basic.MiIoDatabaseWatchService; import org.openhab.binding.miio.internal.basic.MiIoDatabaseWatchService;
import org.openhab.binding.miio.internal.cloud.CloudConnector; import org.openhab.binding.miio.internal.cloud.CloudConnector;
import org.openhab.core.i18n.LocaleProvider;
import org.openhab.core.i18n.TranslationProvider;
import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing; import org.openhab.core.thing.Thing;
import org.openhab.core.types.Command; import org.openhab.core.types.Command;
@ -33,8 +35,8 @@ public class MiIoGenericHandler extends MiIoAbstractHandler {
private final Logger logger = LoggerFactory.getLogger(MiIoGenericHandler.class); private final Logger logger = LoggerFactory.getLogger(MiIoGenericHandler.class);
public MiIoGenericHandler(Thing thing, MiIoDatabaseWatchService miIoDatabaseWatchService, public MiIoGenericHandler(Thing thing, MiIoDatabaseWatchService miIoDatabaseWatchService,
CloudConnector cloudConnector) { CloudConnector cloudConnector, TranslationProvider i18nProvider, LocaleProvider localeProvider) {
super(thing, miIoDatabaseWatchService, cloudConnector); super(thing, miIoDatabaseWatchService, cloudConnector, i18nProvider, localeProvider);
} }
@Override @Override

View File

@ -44,6 +44,8 @@ import org.openhab.binding.miio.internal.basic.MiIoDatabaseWatchService;
import org.openhab.binding.miio.internal.cloud.CloudConnector; import org.openhab.binding.miio.internal.cloud.CloudConnector;
import org.openhab.binding.miio.internal.miot.MiotParser; import org.openhab.binding.miio.internal.miot.MiotParser;
import org.openhab.core.cache.ExpiringCache; import org.openhab.core.cache.ExpiringCache;
import org.openhab.core.i18n.LocaleProvider;
import org.openhab.core.i18n.TranslationProvider;
import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OnOffType;
import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing; import org.openhab.core.thing.Thing;
@ -87,8 +89,9 @@ public class MiIoUnsupportedHandler extends MiIoAbstractHandler {
}); });
public MiIoUnsupportedHandler(Thing thing, MiIoDatabaseWatchService miIoDatabaseWatchService, public MiIoUnsupportedHandler(Thing thing, MiIoDatabaseWatchService miIoDatabaseWatchService,
CloudConnector cloudConnector, HttpClient httpClientFactory) { CloudConnector cloudConnector, HttpClient httpClientFactory, TranslationProvider i18nProvider,
super(thing, miIoDatabaseWatchService, cloudConnector); LocaleProvider localeProvider) {
super(thing, miIoDatabaseWatchService, cloudConnector, i18nProvider, localeProvider);
this.httpClient = httpClientFactory; this.httpClient = httpClientFactory;
} }

View File

@ -52,6 +52,8 @@ import org.openhab.binding.miio.internal.robot.StatusType;
import org.openhab.binding.miio.internal.robot.VacuumErrorType; import org.openhab.binding.miio.internal.robot.VacuumErrorType;
import org.openhab.binding.miio.internal.transport.MiIoAsyncCommunication; import org.openhab.binding.miio.internal.transport.MiIoAsyncCommunication;
import org.openhab.core.cache.ExpiringCache; import org.openhab.core.cache.ExpiringCache;
import org.openhab.core.i18n.LocaleProvider;
import org.openhab.core.i18n.TranslationProvider;
import org.openhab.core.library.types.DateTimeType; import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OnOffType;
@ -113,8 +115,9 @@ public class MiIoVacuumHandler extends MiIoAbstractHandler {
private RRMapDrawOptions mapDrawOptions = new RRMapDrawOptions(); private RRMapDrawOptions mapDrawOptions = new RRMapDrawOptions();
public MiIoVacuumHandler(Thing thing, MiIoDatabaseWatchService miIoDatabaseWatchService, public MiIoVacuumHandler(Thing thing, MiIoDatabaseWatchService miIoDatabaseWatchService,
CloudConnector cloudConnector, ChannelTypeRegistry channelTypeRegistry) { CloudConnector cloudConnector, ChannelTypeRegistry channelTypeRegistry, TranslationProvider i18nProvider,
super(thing, miIoDatabaseWatchService, cloudConnector); LocaleProvider localeProvider) {
super(thing, miIoDatabaseWatchService, cloudConnector, i18nProvider, localeProvider);
this.channelTypeRegistry = channelTypeRegistry; this.channelTypeRegistry = channelTypeRegistry;
mapChannelUid = new ChannelUID(thing.getUID(), CHANNEL_VACUUM_MAP); mapChannelUid = new ChannelUID(thing.getUID(), CHANNEL_VACUUM_MAP);
status = new ExpiringCache<>(CACHE_EXPIRY, () -> { status = new ExpiringCache<>(CACHE_EXPIRY, () -> {

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,10 @@
*/ */
package org.openhab.binding.miio.internal; package org.openhab.binding.miio.internal;
import static org.openhab.binding.miio.internal.MiIoBindingConstants.*;
import java.io.File; import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
@ -24,6 +27,9 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
@ -59,6 +65,7 @@ public class ReadmeHelper {
private static final String BASEFILE = "./README.base.md"; private static final String BASEFILE = "./README.base.md";
private static final String OUTPUTFILE = "./README.md"; private static final String OUTPUTFILE = "./README.md";
private static final String DEVICE_NAMES_FILE = "./src/main/resources/misc/device_names.json"; private static final String DEVICE_NAMES_FILE = "./src/main/resources/misc/device_names.json";
private static final String I18N_CHANNEL_FILE = "./src/main/resources/OH-INF/i18n/basic.properties";
private static final boolean UPDATE_OPTION_MAPPING_README_COMMENTS = true; private static final boolean UPDATE_OPTION_MAPPING_README_COMMENTS = true;
@Disabled @Disabled
@ -71,7 +78,6 @@ public class ReadmeHelper {
StringWriter channelList = rm.channelList(); StringWriter channelList = rm.channelList();
LOGGER.info("## Creating Item Files for miio:basic devices"); LOGGER.info("## Creating Item Files for miio:basic devices");
StringWriter itemFileExamples = rm.itemFileExamples(); StringWriter itemFileExamples = rm.itemFileExamples();
LOGGER.info("## Done");
try { try {
String baseDoc = new String(Files.readAllBytes(Paths.get(BASEFILE)), StandardCharsets.UTF_8); String baseDoc = new String(Files.readAllBytes(Paths.get(BASEFILE)), StandardCharsets.UTF_8);
String newDoc = baseDoc.replaceAll("!!!devices", deviceList.toString()) String newDoc = baseDoc.replaceAll("!!!devices", deviceList.toString())
@ -79,8 +85,34 @@ public class ReadmeHelper {
.replaceAll("!!!itemFileExamples", itemFileExamples.toString()); .replaceAll("!!!itemFileExamples", itemFileExamples.toString());
Files.write(Paths.get(OUTPUTFILE), newDoc.getBytes(StandardCharsets.UTF_8)); Files.write(Paths.get(OUTPUTFILE), newDoc.getBytes(StandardCharsets.UTF_8));
} catch (IOException e) { } catch (IOException e) {
LOGGER.warn("IO exception", e); LOGGER.warn("IO exception writing readme", e);
} }
LOGGER.info("## Creating i18n entries for devices and miio:basic channels");
StringBuilder sb = new StringBuilder();
sb.append("# Automatic created list by miio readme maker for miio devices & database channels\n\n");
sb.append("# Devices\n\n");
for (MiIoDevices d : Arrays.asList(MiIoDevices.values())) {
sb.append(I18N_THING_PREFIX);
sb.append(d.getModel());
sb.append(" = ");
sb.append(d.getDescription());
sb.append("\n");
}
sb.append("\n# Channels\n\n");
for (Entry<String, String> e : sortByKeys(rm.createI18nEntries()).entrySet()) {
sb.append(e.getKey());
sb.append(" = ");
sb.append(e.getValue());
sb.append("\n");
}
sb.append("\n");
try {
Files.write(Paths.get(I18N_CHANNEL_FILE), sb.toString().getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
LOGGER.warn("IO exception creating i18n file", e);
}
LOGGER.info("## Done");
} }
private StringWriter deviceList() { private StringWriter deviceList() {
@ -163,25 +195,21 @@ public class ReadmeHelper {
} }
public static String readmeOptionMapping(MiIoBasicChannel channel, String model) { public static String readmeOptionMapping(MiIoBasicChannel channel, String model) {
StateDescriptionDTO stateDescription = channel.getStateDescription(); final List<OptionsValueListDTO> options = getChannelOptions(channel);
if (stateDescription != null && stateDescription.getOptions() != null) { if (!options.isEmpty()) {
final List<OptionsValueListDTO> options = stateDescription.getOptions(); StringBuilder mapping = new StringBuilder();
if (options != null && !options.isEmpty()) { mapping.append("Value mapping `[");
StringBuilder mapping = new StringBuilder(); options.forEach((option) -> {
mapping.append("Value mapping `["); mapping.append(
options.forEach((option) -> { String.format("\"%s\"=\"%s\",", String.valueOf(option.value), String.valueOf(option.label)));
mapping.append(String.format("\"%s\"=\"%s\",", String.valueOf(option.value), });
String.valueOf(option.label))); mapping.deleteCharAt(mapping.length() - 1);
}); mapping.append("]`");
mapping.deleteCharAt(mapping.length() - 1); String newComment = mapping.toString();
mapping.append("]`"); if (!channel.getReadmeComment().contentEquals(newComment)) {
String newComment = mapping.toString(); LOGGER.info("Channel {} - {} readme comment updated to '{}'", model, channel.getChannel(), newComment);
if (!channel.getReadmeComment().contentEquals(newComment)) {
LOGGER.info("Channel {} - {} readme comment updated to '{}'", model, channel.getChannel(),
newComment);
}
return newComment;
} }
return newComment;
} }
return channel.getReadmeComment(); return channel.getReadmeComment();
} }
@ -264,25 +292,80 @@ public class ReadmeHelper {
List<MiIoBasicDevice> arrayList = new ArrayList<>(); List<MiIoBasicDevice> arrayList = new ArrayList<>();
String path = "./src/main/resources/database/"; String path = "./src/main/resources/database/";
File dir = new File(path); File dir = new File(path);
File[] filesList = dir.listFiles(); FileFilter fileFilter = file -> !file.isDirectory() && file.getName().toLowerCase().endsWith(".json");
File[] filesList = dir.listFiles(fileFilter);
if (filesList == null) {
return arrayList;
}
for (File file : filesList) { for (File file : filesList) {
if (file.isFile()) { try {
try { JsonObject deviceMapping = convertFileToJSON(path + file.getName());
JsonObject deviceMapping = convertFileToJSON(path + file.getName()); Gson gson = new GsonBuilder().serializeNulls().create();
Gson gson = new GsonBuilder().serializeNulls().create(); @Nullable
@Nullable MiIoBasicDevice devdb = gson.fromJson(deviceMapping, MiIoBasicDevice.class);
MiIoBasicDevice devdb = gson.fromJson(deviceMapping, MiIoBasicDevice.class); if (devdb != null) {
if (devdb != null) { arrayList.add(devdb);
arrayList.add(devdb);
}
} catch (Exception e) {
LOGGER.info("Error while searching in database '{}': {}", file.getName(), e.getMessage());
} }
} catch (Exception e) {
LOGGER.info("Error while searching in database '{}': {}", file.getName(), e.getMessage());
} }
} }
return arrayList; return arrayList;
} }
public static List<OptionsValueListDTO> getChannelOptions(MiIoBasicChannel channel) {
StateDescriptionDTO state = channel.getStateDescription();
if (state != null) {
List<OptionsValueListDTO> options = state.getOptions();
if (options != null) {
return options;
}
}
return List.of();
}
private Map<String, String> createI18nEntries() {
Map<String, String> i18nEntries = new HashMap<>();
String path = "./src/main/resources/database/";
File dir = new File(path);
FileFilter fileFilter = file -> !file.isDirectory() && file.getName().toLowerCase().endsWith(".json");
File[] filesList = dir.listFiles(fileFilter);
if (filesList == null) {
return i18nEntries;
}
for (File file : filesList) {
try {
String key = file.getName().toLowerCase().split("json")[0];
JsonObject deviceMapping = convertFileToJSON(path + file.getName());
Gson gson = new GsonBuilder().serializeNulls().create();
@Nullable
MiIoBasicDevice devdb = gson.fromJson(deviceMapping, MiIoBasicDevice.class);
if (devdb == null) {
continue;
}
for (MiIoBasicChannel channel : devdb.getDevice().getChannels()) {
i18nEntries.put(I18N_CHANNEL_PREFIX + key + channel.getChannel(), channel.getFriendlyName());
List<OptionsValueListDTO> options = getChannelOptions(channel);
for (OptionsValueListDTO channelOption : options) {
String optionValue = channelOption.value;
String optionLabel = channelOption.label;
if (optionValue != null && optionLabel != null) {
i18nEntries.put(I18N_OPTION_PREFIX + key + channel.getChannel() + "-" + optionValue,
optionLabel);
}
}
}
} catch (Exception e) {
LOGGER.info("Error while searching in database '{}': {}", file.getName(), e.getMessage());
}
}
return i18nEntries;
}
public static <K extends Comparable, V> Map<K, V> sortByKeys(Map<K, V> map) {
return new TreeMap<>(map);
}
private static String minLengthString(String string, int length) { private static String minLengthString(String string, int length) {
return String.format("%-" + length + "s", string); return String.format("%-" + length + "s", string);
} }
@ -290,7 +373,6 @@ public class ReadmeHelper {
JsonObject convertFileToJSON(String fileName) { JsonObject convertFileToJSON(String fileName) {
// Read from File to String // Read from File to String
JsonObject jsonObject = new JsonObject(); JsonObject jsonObject = new JsonObject();
try { try {
JsonElement jsonElement = JsonParser.parseReader(new FileReader(fileName)); JsonElement jsonElement = JsonParser.parseReader(new FileReader(fileName));
jsonObject = jsonElement.getAsJsonObject(); jsonObject = jsonElement.getAsJsonObject();