]> git.basschouten.com Git - openhab-addons.git/blob
f72d00351bc74ae60d8ccbf6fdb331204ecb167c
[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
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         LinkedHashMap<String, String> checksums = new LinkedHashMap<>();
61         LinkedHashSet<String> models = new LinkedHashSet<>();
62         if (args.length > 0) {
63             models.add(args[0]);
64         }
65
66         String m = models.isEmpty() ? "" : (String) models.toArray()[0];
67         boolean scan = m.isEmpty() ? false : !Character.isDigit(m.charAt(m.length() - 1));
68         if (scan) {
69             for (int i = 1; i <= 12; i++) {
70                 models.add(models.toArray()[0] + String.valueOf(i));
71             }
72         }
73
74         MiotParser miotParser;
75         for (String model : models) {
76             LOGGER.info("Processing: {}", model);
77             HttpClient httpClient = null;
78             try {
79                 httpClient = new HttpClient(new SslContextFactory.Client());
80                 httpClient.setFollowRedirects(false);
81                 httpClient.start();
82                 miotParser = MiotParser.parse(model, httpClient);
83                 LOGGER.info("urn: ", miotParser.getUrn());
84                 LOGGER.info("{}", miotParser.getUrnData());
85                 MiIoBasicDevice device = miotParser.getDevice();
86                 if (device != null) {
87                     LOGGER.info("Device: {}", device);
88                     String fileName = String.format("%s%s%s", BASEDIR, model, FILENAME_EXTENSION);
89                     if (!OVERWRITE_EXISTING_DATABASE_FILE) {
90                         int counter = 0;
91                         while (new File(fileName).isFile()) {
92                             fileName = String.format("%s%s-%d%s", BASEDIR, model, counter, FILENAME_EXTENSION);
93                             counter++;
94                         }
95                     }
96                     miotParser.writeDevice(fileName, device);
97                     String channelsJson = GSON.toJson(device.getDevice().getChannels()).toString();
98                     checksums.put(model, checksumMD5(channelsJson));
99                 }
100                 LOGGER.info("Finished");
101             } catch (MiotParseException e) {
102                 LOGGER.info("Error processing model {}: {}", model, e.getMessage());
103             } catch (Exception e) {
104                 LOGGER.info("Failed to initiate http Client: {}", e.getMessage());
105             } finally {
106                 try {
107                     if (httpClient != null && httpClient.isRunning()) {
108                         httpClient.stop();
109                     }
110                 } catch (Exception e) {
111                     // ignore
112                 }
113             }
114         }
115         StringBuilder sb = new StringBuilder();
116         for (Entry<String, String> ch : checksums.entrySet()) {
117             sb.append(ch.getValue());
118             sb.append(" --> ");
119             sb.append(ch.getKey());
120             sb.append("\r\n");
121         }
122         LOGGER.info("Checksums for device comparisons\r\n{}", sb);
123     }
124
125     public static String checksumMD5(String input) {
126         try {
127             MessageDigest md = MessageDigest.getInstance("MD5");
128             md.update(input.getBytes());
129             return Utils.getHex(md.digest());
130         } catch (NoSuchAlgorithmException e) {
131             return "No MD5";
132         }
133     }
134 }