]> git.basschouten.com Git - openhab-addons.git/blob
f09fceee1ca2319240fbc9635286f6e952f63eaa
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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;
15
16 import java.io.File;
17 import java.security.MessageDigest;
18 import java.security.NoSuchAlgorithmException;
19 import java.util.LinkedHashMap;
20 import java.util.LinkedHashSet;
21 import java.util.Map.Entry;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jetty.client.HttpClient;
25 import org.eclipse.jetty.util.ssl.SslContextFactory;
26 import org.junit.jupiter.api.Disabled;
27 import org.openhab.binding.miio.internal.basic.MiIoBasicDevice;
28 import org.openhab.binding.miio.internal.miot.MiotParseException;
29 import org.openhab.binding.miio.internal.miot.MiotParser;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 import com.google.gson.Gson;
34 import com.google.gson.GsonBuilder;
35
36 /**
37  * Supporting tool for creation of the json database files for miot devices
38  * *
39  * Run in IDE with 'run as java application' or run in command line as:
40  * mvn exec:java -Dexec.mainClass="org.openhab.binding.miio.internal.MiotJsonFileCreator" -Dexec.classpathScope="test"
41  * -Dexec.args="zhimi.humidifier.ca4"
42  *
43  * The argument is the model string to create the database file for.
44  * If the digit at the end of the model is omitted, it will try a range of devices
45  *
46  * @author Marcel Verpaalen - Initial contribution
47  *
48  */
49 @NonNullByDefault
50 public class MiotJsonFileCreator {
51     private static final Logger LOGGER = LoggerFactory.getLogger(MiotJsonFileCreator.class);
52     private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
53
54     private static final String BASEDIR = "./src/main/resources/database/";
55     private static final String FILENAME_EXTENSION = "-miot.json";
56     private static final boolean OVERWRITE_EXISTING_DATABASE_FILE = false;
57
58     @Disabled
59     public static void main(String[] args) {
60
61         LinkedHashMap<String, String> checksums = new LinkedHashMap<>();
62         LinkedHashSet<String> models = new LinkedHashSet<>();
63         if (args.length > 0) {
64             models.add(args[0]);
65         }
66
67         String m = models.isEmpty() ? "" : (String) models.toArray()[0];
68         boolean scan = m.isEmpty() ? false : !Character.isDigit(m.charAt(m.length() - 1));
69         if (scan) {
70             for (int i = 1; i <= 12; i++) {
71                 models.add(models.toArray()[0] + String.valueOf(i));
72             }
73         }
74
75         MiotParser miotParser;
76         for (String model : models) {
77             LOGGER.info("Processing: {}", model);
78             HttpClient httpClient = null;
79             try {
80                 httpClient = new HttpClient(new SslContextFactory.Client());
81                 httpClient.setFollowRedirects(false);
82                 httpClient.start();
83                 miotParser = MiotParser.parse(model, httpClient);
84                 LOGGER.info("urn: ", miotParser.getUrn());
85                 LOGGER.info("{}", miotParser.getUrnData());
86                 MiIoBasicDevice device = miotParser.getDevice();
87                 if (device != null) {
88                     LOGGER.info("Device: {}", device);
89                     String fileName = String.format("%s%s%s", BASEDIR, model, FILENAME_EXTENSION);
90                     if (!OVERWRITE_EXISTING_DATABASE_FILE) {
91                         int counter = 0;
92                         while (new File(fileName).isFile()) {
93                             fileName = String.format("%s%s-%d%s", BASEDIR, model, counter, FILENAME_EXTENSION);
94                             counter++;
95                         }
96                     }
97                     miotParser.writeDevice(fileName, device);
98                     String channelsJson = GSON.toJson(device.getDevice().getChannels()).toString();
99                     checksums.put(model, checksumMD5(channelsJson));
100                 }
101                 LOGGER.info("Finished");
102             } catch (MiotParseException e) {
103                 LOGGER.info("Error processing model {}: {}", model, e.getMessage());
104             } catch (Exception e) {
105                 LOGGER.info("Failed to initiate http Client: {}", e.getMessage());
106             } finally {
107                 try {
108                     if (httpClient != null && httpClient.isRunning()) {
109                         httpClient.stop();
110                     }
111                 } catch (Exception e) {
112                     // ignore
113                 }
114             }
115         }
116         StringBuilder sb = new StringBuilder();
117         for (Entry<String, String> ch : checksums.entrySet()) {
118             sb.append(ch.getValue());
119             sb.append(" --> ");
120             sb.append(ch.getKey());
121             sb.append("\r\n");
122         }
123         LOGGER.info("Checksums for device comparisons\r\n{}", sb);
124     }
125
126     public static String checksumMD5(String input) {
127         try {
128             MessageDigest md = MessageDigest.getInstance("MD5");
129             md.update(input.getBytes());
130             return Utils.getHex(md.digest());
131         } catch (NoSuchAlgorithmException e) {
132             return "No MD5";
133         }
134     }
135 }