2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.miio.internal.basic;
15 import static java.nio.file.StandardWatchEventKinds.*;
16 import static org.openhab.binding.miio.internal.MiIoBindingConstants.BINDING_DATABASE_PATH;
19 import java.io.IOException;
20 import java.net.URISyntaxException;
22 import java.nio.file.Path;
23 import java.nio.file.Paths;
24 import java.nio.file.WatchEvent;
25 import java.nio.file.WatchEvent.Kind;
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.List;
32 import org.eclipse.jdt.annotation.NonNullByDefault;
33 import org.eclipse.jdt.annotation.Nullable;
34 import org.openhab.binding.miio.internal.MiIoBindingConstants;
35 import org.openhab.binding.miio.internal.Utils;
36 import org.openhab.core.service.AbstractWatchService;
37 import org.osgi.framework.Bundle;
38 import org.osgi.framework.FrameworkUtil;
39 import org.osgi.service.component.annotations.Activate;
40 import org.osgi.service.component.annotations.Component;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
44 import com.google.gson.Gson;
45 import com.google.gson.GsonBuilder;
46 import com.google.gson.JsonObject;
47 import com.google.gson.JsonParseException;
50 * The {@link MiIoDatabaseWatchService} creates a registry of database file per ModelId
52 * @author Marcel Verpaalen - Initial contribution
54 @Component(service = MiIoDatabaseWatchService.class)
56 public class MiIoDatabaseWatchService extends AbstractWatchService {
57 private static final String DATABASE_FILES = ".json";
58 private static final Gson GSON = new GsonBuilder().serializeNulls().create();
60 private final Logger logger = LoggerFactory.getLogger(MiIoDatabaseWatchService.class);
61 private Map<String, URL> databaseList = new HashMap<>();
64 public MiIoDatabaseWatchService() {
65 super(BINDING_DATABASE_PATH);
67 "Started miio basic devices local databases watch service. Watching for database files at path: {}",
68 BINDING_DATABASE_PATH);
69 processWatchEvent(null, null, Paths.get(BINDING_DATABASE_PATH));
71 if (logger.isTraceEnabled()) {
72 for (String device : databaseList.keySet()) {
73 logger.trace("Device: {} using URL: {}", device, databaseList.get(device));
79 protected boolean watchSubDirectories() {
84 protected Kind<?> @Nullable [] getWatchEventKinds(@Nullable Path directory) {
85 return new Kind<?>[] { ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY };
89 protected void processWatchEvent(@Nullable WatchEvent<?> event, @Nullable Kind<?> kind, @Nullable Path path) {
91 final Path p = path.getFileName();
92 if (p != null && p.toString().endsWith(DATABASE_FILES)) {
93 logger.debug("Local Databases file {} changed. Refreshing device database.", p.getFileName());
100 * Return the database file URL for a given modelId
102 * @param modelId the model
103 * @return URL with the definition for the model
105 public @Nullable URL getDatabaseUrl(String modelId) {
106 return databaseList.get(modelId);
109 private void populateDatabase() {
110 Map<String, URL> workingDatabaseList = new HashMap<>();
111 List<URL> urlEntries = findDatabaseFiles();
112 for (URL db : urlEntries) {
113 logger.trace("Adding devices for db file: {}", db);
115 JsonObject deviceMapping = Utils.convertFileToJSON(db);
116 MiIoBasicDevice devdb = GSON.fromJson(deviceMapping, MiIoBasicDevice.class);
120 for (String id : devdb.getDevice().getId()) {
121 workingDatabaseList.put(id, db);
123 } catch (JsonParseException | IOException | URISyntaxException e) {
124 logger.debug("Error while processing database '{}': {}", db, e.getMessage());
126 databaseList = workingDatabaseList;
130 private List<URL> findDatabaseFiles() {
131 List<URL> urlEntries = new ArrayList<>();
132 Bundle bundle = FrameworkUtil.getBundle(getClass());
133 urlEntries.addAll(Collections.list(bundle.findEntries(MiIoBindingConstants.DATABASE_PATH, "*.json", false)));
135 File[] userDbFiles = new File(BINDING_DATABASE_PATH).listFiles((dir, name) -> name.endsWith(".json"));
136 if (userDbFiles != null) {
137 for (File f : userDbFiles) {
138 urlEntries.add(f.toURI().toURL());
139 logger.debug("Adding local json db file: {}, {}", f.getName(), f.toURI().toURL());
142 } catch (IOException e) {
143 logger.debug("Error while searching for database files: {}", e.getMessage());