]> git.basschouten.com Git - openhab-addons.git/blob
cd9a8c6457eaa1feda69e7714f9ec29de675d859
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 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.discovery;
14
15 import static org.openhab.binding.miio.internal.MiIoBindingConstants.*;
16
17 import java.net.InetAddress;
18 import java.util.HashMap;
19 import java.util.Map;
20 import java.util.Set;
21
22 import javax.jmdns.ServiceInfo;
23
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.openhab.binding.miio.internal.MiIoDevices;
27 import org.openhab.binding.miio.internal.cloud.CloudConnector;
28 import org.openhab.binding.miio.internal.cloud.CloudDeviceDTO;
29 import org.openhab.core.config.discovery.DiscoveryResult;
30 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
31 import org.openhab.core.config.discovery.mdns.MDNSDiscoveryParticipant;
32 import org.openhab.core.thing.ThingTypeUID;
33 import org.openhab.core.thing.ThingUID;
34 import org.osgi.service.component.annotations.Activate;
35 import org.osgi.service.component.annotations.Component;
36 import org.osgi.service.component.annotations.Reference;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 /**
41  * Discovers Mi IO devices announced by mDNS
42  *
43  * @author Marcel Verpaalen - Initial contribution
44  *
45  */
46 @NonNullByDefault
47 @Component(service = MDNSDiscoveryParticipant.class)
48 public class MiIoDiscoveryParticipant implements MDNSDiscoveryParticipant {
49
50     private final CloudConnector cloudConnector;
51     private Logger logger = LoggerFactory.getLogger(MiIoDiscoveryParticipant.class);
52
53     @Activate
54     public MiIoDiscoveryParticipant(@Reference CloudConnector cloudConnector) {
55         this.cloudConnector = cloudConnector;
56         logger.debug("Start Xiaomi Mi IO mDNS discovery");
57     }
58
59     @Override
60     public Set<ThingTypeUID> getSupportedThingTypeUIDs() {
61         return (NONGENERIC_THING_TYPES_UIDS);
62     }
63
64     @Override
65     public String getServiceType() {
66         return "_miio._udp.local.";
67     }
68
69     @Override
70     public @Nullable ThingUID getThingUID(@Nullable ServiceInfo service) {
71         if (service == null) {
72             return null;
73         }
74         logger.trace("ServiceInfo: {}", service);
75         String id[] = service.getName().split("_miio");
76         if (id.length != 2) {
77             logger.trace("mDNS Could not identify Type / Device Id from '{}'", service.getName());
78             return null;
79         }
80         long did;
81         try {
82             did = Long.parseUnsignedLong(id[1]);
83         } catch (Exception e) {
84             logger.trace("mDNS Could not identify Device ID from '{}'", id[1]);
85             return null;
86         }
87         ThingTypeUID thingType = MiIoDevices.getType(id[0].replaceAll("-", ".")).getThingType();
88         String uidName = String.format("%08X", did);
89         logger.debug("mDNS {} identified as thingtype {} with did {} ({})", id[0], thingType, uidName, did);
90         return new ThingUID(thingType, uidName);
91     }
92
93     private @Nullable InetAddress getIpAddress(ServiceInfo service) {
94         InetAddress address = null;
95         for (InetAddress addr : service.getInet4Addresses()) {
96             return addr;
97         }
98         // Fallback for Inet6addresses
99         for (InetAddress addr : service.getInet6Addresses()) {
100             return addr;
101         }
102         return address;
103     }
104
105     @Override
106     public @Nullable DiscoveryResult createResult(ServiceInfo service) {
107         DiscoveryResult result = null;
108         ThingUID uid = getThingUID(service);
109         if (uid != null) {
110             Map<String, Object> properties = new HashMap<>(2);
111             // remove the domain from the name
112             InetAddress ip = getIpAddress(service);
113             if (ip == null) {
114                 logger.debug("Mi IO mDNS Discovery could not determine ip address from service info: {}", service);
115                 return null;
116             }
117             String inetAddress = ip.toString().substring(1); // trim leading slash
118             String id = uid.getId();
119             String label = "Xiaomi Mi Device " + id + " (" + Long.parseUnsignedLong(id, 16) + ") " + service.getName();
120             if (cloudConnector.isConnected()) {
121                 cloudConnector.getDevicesList();
122                 CloudDeviceDTO cloudInfo = cloudConnector.getDeviceInfo(id);
123                 if (cloudInfo != null) {
124                     logger.debug("Cloud Info: {}", cloudInfo);
125                     properties.put(PROPERTY_TOKEN, cloudInfo.getToken());
126                     label = label + " with token";
127                     String country = cloudInfo.getServer();
128                     if (!country.isEmpty() && cloudInfo.getIsOnline()) {
129                         properties.put(PROPERTY_CLOUDSERVER, country);
130                     }
131                 }
132             }
133             properties.put(PROPERTY_HOST_IP, inetAddress);
134             properties.put(PROPERTY_DID, id);
135             result = DiscoveryResultBuilder.create(uid).withProperties(properties)
136                     .withRepresentationProperty(PROPERTY_DID).withLabel(label).build();
137             logger.debug("Mi IO mDNS Discovery found {} with address '{}:{}' name '{}'", uid, inetAddress,
138                     service.getPort(), label);
139         }
140         return result;
141     }
142 }