2 * Copyright (c) 2010-2020 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.miio.internal.discovery;
15 import static org.openhab.binding.miio.internal.MiIoBindingConstants.*;
17 import java.net.InetAddress;
18 import java.util.HashMap;
22 import javax.jmdns.ServiceInfo;
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;
41 * Discovers Mi IO devices announced by mDNS
43 * @author Marcel Verpaalen - Initial contribution
47 @Component(service = MDNSDiscoveryParticipant.class, immediate = true)
48 public class MiIoDiscoveryParticipant implements MDNSDiscoveryParticipant {
50 private final CloudConnector cloudConnector;
51 private Logger logger = LoggerFactory.getLogger(MiIoDiscoveryParticipant.class);
54 public MiIoDiscoveryParticipant(@Reference CloudConnector cloudConnector) {
55 this.cloudConnector = cloudConnector;
56 logger.debug("Start Xiaomi Mi IO mDNS discovery");
60 public Set<ThingTypeUID> getSupportedThingTypeUIDs() {
61 return (NONGENERIC_THING_TYPES_UIDS);
65 public String getServiceType() {
66 return "_miio._udp.local.";
70 public @Nullable ThingUID getThingUID(@Nullable ServiceInfo service) {
71 if (service == null) {
74 logger.trace("ServiceInfo: {}", service);
75 String id[] = service.getName().split("_miio");
77 logger.trace("mDNS Could not identify Type / Device Id from '{}'", service.getName());
82 did = Long.parseUnsignedLong(id[1]);
83 } catch (Exception e) {
84 logger.trace("mDNS Could not identify Device ID from '{}'", id[1]);
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);
93 private @Nullable InetAddress getIpAddress(ServiceInfo service) {
94 InetAddress address = null;
95 for (InetAddress addr : service.getInet4Addresses()) {
98 // Fallback for Inet6addresses
99 for (InetAddress addr : service.getInet6Addresses()) {
106 public @Nullable DiscoveryResult createResult(ServiceInfo service) {
107 DiscoveryResult result = null;
108 ThingUID uid = getThingUID(service);
110 Map<String, Object> properties = new HashMap<>(2);
111 // remove the domain from the name
112 InetAddress ip = getIpAddress(service);
114 logger.debug("Mi IO mDNS Discovery could not determine ip address from service info: {}", service);
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);
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);