]> git.basschouten.com Git - openhab-addons.git/blob
f31e318423afa7b5f28683d9b4bee5a0257ee610
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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
14 package org.openhab.binding.miio.internal.basic;
15
16 import static java.nio.file.StandardWatchEventKinds.*;
17 import static org.openhab.binding.miio.internal.MiIoBindingConstants.BINDING_ID;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.net.URL;
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;
30 import java.util.Map;
31
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.config.core.ConfigConstants;
37 import org.openhab.core.service.AbstractWatchService;
38 import org.osgi.framework.Bundle;
39 import org.osgi.framework.FrameworkUtil;
40 import org.osgi.service.component.annotations.Activate;
41 import org.osgi.service.component.annotations.Component;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 import com.google.gson.Gson;
46 import com.google.gson.GsonBuilder;
47 import com.google.gson.JsonIOException;
48 import com.google.gson.JsonObject;
49 import com.google.gson.JsonSyntaxException;
50
51 /**
52  * The {@link MiIoDatabaseWatchService} creates a registry of database file per ModelId
53  *
54  * @author Marcel Verpaalen - Initial contribution
55  */
56 @Component(service = MiIoDatabaseWatchService.class)
57 @NonNullByDefault
58 public class MiIoDatabaseWatchService extends AbstractWatchService {
59     private static final String LOCAL_DATABASE_PATH = ConfigConstants.getConfigFolder() + File.separator + "misc"
60             + File.separator + BINDING_ID;
61     private static final String DATABASE_FILES = ".json";
62     private static final Gson GSON = new GsonBuilder().serializeNulls().create();
63
64     private final Logger logger = LoggerFactory.getLogger(MiIoDatabaseWatchService.class);
65     private Map<String, URL> databaseList = new HashMap<>();
66
67     @Activate
68     public MiIoDatabaseWatchService() {
69         super(LOCAL_DATABASE_PATH);
70         logger.debug(
71                 "Started miio basic devices local databases watch service. Watching for database files at path: {}",
72                 LOCAL_DATABASE_PATH);
73         processWatchEvent(null, null, Paths.get(LOCAL_DATABASE_PATH));
74         populateDatabase();
75         if (logger.isTraceEnabled()) {
76             for (String device : databaseList.keySet()) {
77                 logger.trace("Device: {} using URL: {}", device, databaseList.get(device));
78             }
79         }
80     }
81
82     @Override
83     protected boolean watchSubDirectories() {
84         return true;
85     }
86
87     @Override
88     protected Kind<?>[] getWatchEventKinds(@Nullable Path directory) {
89         return new Kind<?>[] { ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY };
90     }
91
92     @Override
93     protected void processWatchEvent(@Nullable WatchEvent<?> event, @Nullable Kind<?> kind, @Nullable Path path) {
94         if (path != null) {
95             final Path p = path.getFileName();
96             if (p != null && p.toString().endsWith(DATABASE_FILES)) {
97                 logger.debug("Local Databases file {} changed. Refreshing device database.", p.getFileName());
98                 populateDatabase();
99             }
100         }
101     }
102
103     /**
104      * Return the database file URL for a given modelId
105      *
106      * @param modelId the model
107      * @return URL with the definition for the model
108      */
109     public @Nullable URL getDatabaseUrl(String modelId) {
110         return databaseList.get(modelId);
111     }
112
113     private void populateDatabase() {
114         Map<String, URL> workingDatabaseList = new HashMap<>();
115         List<URL> urlEntries = findDatabaseFiles();
116         for (URL db : urlEntries) {
117             logger.trace("Adding devices for db file: {}", db);
118             try {
119                 JsonObject deviceMapping = Utils.convertFileToJSON(db);
120                 MiIoBasicDevice devdb = GSON.fromJson(deviceMapping, MiIoBasicDevice.class);
121                 for (String id : devdb.getDevice().getId()) {
122                     workingDatabaseList.put(id, db);
123                 }
124             } catch (JsonIOException | JsonSyntaxException | IOException e) {
125                 logger.debug("Error while processing database '{}': {}", db, e.getMessage());
126             }
127             databaseList = workingDatabaseList;
128         }
129     }
130
131     private List<URL> findDatabaseFiles() {
132         List<URL> urlEntries = new ArrayList<>();
133         Bundle bundle = FrameworkUtil.getBundle(getClass());
134         urlEntries.addAll(Collections.list(bundle.findEntries(MiIoBindingConstants.DATABASE_PATH, "*.json", false)));
135         String userDbFolder = ConfigConstants.getConfigFolder() + File.separator + "misc" + File.separator + BINDING_ID;
136         try {
137             File[] userDbFiles = new File(userDbFolder).listFiles((dir, name) -> name.endsWith(".json"));
138             if (userDbFiles != null) {
139                 for (File f : userDbFiles) {
140                     urlEntries.add(f.toURI().toURL());
141                     logger.debug("Adding local json db file: {}, {}", f.getName(), f.toURI().toURL());
142                 }
143             }
144         } catch (IOException e) {
145             logger.debug("Error while searching for database files: {}", e.getMessage());
146         }
147         return urlEntries;
148     }
149 }