]> git.basschouten.com Git - openhab-addons.git/blob
0a58620cabe3a31d1a546972445b51c41cdf1313
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.miio.internal.basic;
14
15 import static org.openhab.binding.miio.internal.MiIoBindingConstants.BINDING_DATABASE_PATH;
16
17 import java.io.File;
18 import java.io.IOException;
19 import java.net.URISyntaxException;
20 import java.net.URL;
21 import java.nio.file.Path;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.eclipse.jdt.annotation.NonNullByDefault;
29 import org.eclipse.jdt.annotation.Nullable;
30 import org.openhab.binding.miio.internal.MiIoBindingConstants;
31 import org.openhab.binding.miio.internal.Utils;
32 import org.openhab.core.OpenHAB;
33 import org.openhab.core.service.WatchService;
34 import org.osgi.framework.Bundle;
35 import org.osgi.framework.FrameworkUtil;
36 import org.osgi.service.component.annotations.Activate;
37 import org.osgi.service.component.annotations.Component;
38 import org.osgi.service.component.annotations.Deactivate;
39 import org.osgi.service.component.annotations.Reference;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 import com.google.gson.Gson;
44 import com.google.gson.GsonBuilder;
45 import com.google.gson.JsonObject;
46 import com.google.gson.JsonParseException;
47
48 /**
49  * The {@link MiIoDatabaseWatchService} creates a registry of database file per ModelId
50  *
51  * @author Marcel Verpaalen - Initial contribution
52  * @author Jan N. Klug - Refactored to new WatchService
53  */
54 @Component(service = MiIoDatabaseWatchService.class)
55 @NonNullByDefault
56 public class MiIoDatabaseWatchService implements WatchService.WatchEventListener {
57     private static final String DATABASE_FILES = ".json";
58     private static final Gson GSON = new GsonBuilder().serializeNulls().create();
59
60     private final Logger logger = LoggerFactory.getLogger(MiIoDatabaseWatchService.class);
61     private final WatchService watchService;
62     private Map<String, URL> databaseList = new HashMap<>();
63     private final Path watchPath;
64
65     @Activate
66     public MiIoDatabaseWatchService(@Reference(target = WatchService.CONFIG_WATCHER_FILTER) WatchService watchService) {
67         this.watchService = watchService;
68         this.watchPath = Path.of(BINDING_DATABASE_PATH).relativize(Path.of(OpenHAB.getConfigFolder()));
69         watchService.registerListener(this, watchPath);
70
71         logger.debug(
72                 "Started miio basic devices local databases watch service. Watching for database files at path: {}",
73                 BINDING_DATABASE_PATH);
74         processWatchEvent(WatchService.Kind.CREATE, watchPath);
75         populateDatabase();
76         if (logger.isTraceEnabled()) {
77             for (String device : databaseList.keySet()) {
78                 logger.trace("Device: {} using URL: {}", device, databaseList.get(device));
79             }
80         }
81     }
82
83     @Deactivate
84     public void deactivate() {
85         watchService.unregisterListener(this);
86     }
87
88     @Override
89     public void processWatchEvent(WatchService.Kind kind, Path path) {
90         final Path p = path.getFileName();
91         if (p != null && p.toString().endsWith(DATABASE_FILES)) {
92             logger.debug("Local Databases file {} changed. Refreshing device database.", p.getFileName());
93             populateDatabase();
94         }
95     }
96
97     /**
98      * Return the database file URL for a given modelId
99      *
100      * @param modelId the model
101      * @return URL with the definition for the model
102      */
103     public @Nullable URL getDatabaseUrl(String modelId) {
104         return databaseList.get(modelId);
105     }
106
107     private void populateDatabase() {
108         Map<String, URL> workingDatabaseList = new HashMap<>();
109         List<URL> urlEntries = findDatabaseFiles();
110         for (URL db : urlEntries) {
111             logger.trace("Adding devices for db file: {}", db);
112             try {
113                 JsonObject deviceMapping = Utils.convertFileToJSON(db);
114                 MiIoBasicDevice devdb = GSON.fromJson(deviceMapping, MiIoBasicDevice.class);
115                 if (devdb == null) {
116                     continue;
117                 }
118                 for (String id : devdb.getDevice().getId()) {
119                     workingDatabaseList.put(id, db);
120                 }
121             } catch (JsonParseException | IOException | URISyntaxException e) {
122                 logger.debug("Error while processing database '{}': {}", db, e.getMessage());
123             }
124             databaseList = workingDatabaseList;
125         }
126     }
127
128     private List<URL> findDatabaseFiles() {
129         List<URL> urlEntries = new ArrayList<>();
130         Bundle bundle = FrameworkUtil.getBundle(getClass());
131         urlEntries.addAll(Collections.list(bundle.findEntries(MiIoBindingConstants.DATABASE_PATH, "*.json", false)));
132         try {
133             File[] userDbFiles = new File(BINDING_DATABASE_PATH).listFiles((dir, name) -> name.endsWith(".json"));
134             if (userDbFiles != null) {
135                 for (File f : userDbFiles) {
136                     urlEntries.add(f.toURI().toURL());
137                     logger.debug("Adding local json db file: {}, {}", f.getName(), f.toURI().toURL());
138                 }
139             }
140         } catch (IOException e) {
141             logger.debug("Error while searching for database files: {}", e.getMessage());
142         }
143         return urlEntries;
144     }
145 }