]> git.basschouten.com Git - openhab-addons.git/blob
cb919f77957b98cc4d8e086023117502c5111fc0
[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 package org.openhab.binding.chromecast.internal.discovery;
14
15 import static org.openhab.binding.chromecast.internal.ChromecastBindingConstants.*;
16
17 import java.net.Inet4Address;
18 import java.util.Dictionary;
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.core.config.discovery.DiscoveryResult;
27 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
28 import org.openhab.core.config.discovery.DiscoveryService;
29 import org.openhab.core.config.discovery.mdns.MDNSDiscoveryParticipant;
30 import org.openhab.core.thing.ThingTypeUID;
31 import org.openhab.core.thing.ThingUID;
32 import org.osgi.service.component.ComponentContext;
33 import org.osgi.service.component.annotations.Activate;
34 import org.osgi.service.component.annotations.Component;
35 import org.osgi.service.component.annotations.Modified;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 /**
40  * The {@link ChromecastDiscoveryParticipant} is responsible for discovering Chromecast devices through mDNS.
41  *
42  * @author Kai Kreuzer - Initial contribution
43  * @author Daniel Walters - Change discovery protocol to mDNS
44  * @author Christoph Weitkamp - Use "discovery.chromecast:background=false" to disable discovery service
45  */
46 @Component(configurationPid = "discovery.chromecast")
47 @NonNullByDefault
48 public class ChromecastDiscoveryParticipant implements MDNSDiscoveryParticipant {
49
50     private final Logger logger = LoggerFactory.getLogger(ChromecastDiscoveryParticipant.class);
51
52     private static final String PROPERTY_MODEL = "md";
53     private static final String PROPERTY_FRIENDLY_NAME = "fn";
54     private static final String PROPERTY_DEVICE_ID = "id";
55     private static final String SERVICE_TYPE = "_googlecast._tcp.local.";
56
57     private boolean isAutoDiscoveryEnabled = true;
58
59     @Activate
60     protected void activate(ComponentContext componentContext) {
61         activateOrModifyService(componentContext);
62     }
63
64     @Modified
65     protected void modified(ComponentContext componentContext) {
66         activateOrModifyService(componentContext);
67     }
68
69     private void activateOrModifyService(ComponentContext componentContext) {
70         Dictionary<String, @Nullable Object> properties = componentContext.getProperties();
71         String autoDiscoveryPropertyValue = (String) properties
72                 .get(DiscoveryService.CONFIG_PROPERTY_BACKGROUND_DISCOVERY);
73         if (autoDiscoveryPropertyValue != null && !autoDiscoveryPropertyValue.isBlank()) {
74             isAutoDiscoveryEnabled = Boolean.valueOf(autoDiscoveryPropertyValue);
75         }
76     }
77
78     @Override
79     public Set<ThingTypeUID> getSupportedThingTypeUIDs() {
80         return SUPPORTED_THING_TYPES_UIDS;
81     }
82
83     @Override
84     public String getServiceType() {
85         return SERVICE_TYPE;
86     }
87
88     @Override
89     public @Nullable DiscoveryResult createResult(ServiceInfo service) {
90         if (isAutoDiscoveryEnabled) {
91             ThingUID uid = getThingUID(service);
92             if (uid != null) {
93                 Inet4Address[] addresses = service.getInet4Addresses();
94                 if (addresses.length == 0) {
95                     return null;
96                 }
97                 String host = addresses[0].getHostAddress();
98                 int port = service.getPort();
99                 logger.debug("Chromecast Found: {} {}", host, port);
100                 String id = service.getPropertyString(PROPERTY_DEVICE_ID);
101                 String friendlyName = service.getPropertyString(PROPERTY_FRIENDLY_NAME); // friendly name;
102                 return DiscoveryResultBuilder.create(uid).withThingType(getThingType(service))
103                         .withProperties(Map.of(HOST, host, PORT, port, DEVICE_ID, id))
104                         .withRepresentationProperty(DEVICE_ID).withLabel(friendlyName).build();
105             }
106         }
107         return null;
108     }
109
110     private @Nullable ThingTypeUID getThingType(final ServiceInfo service) {
111         String model = service.getPropertyString(PROPERTY_MODEL); // model
112         logger.debug("Chromecast Type: {}", model);
113         if (model == null) {
114             return null;
115         }
116         switch (model) {
117             case "Chromecast Audio":
118                 return THING_TYPE_AUDIO;
119             case "Google Cast Group":
120                 return THING_TYPE_AUDIOGROUP;
121             default:
122                 return THING_TYPE_CHROMECAST;
123         }
124     }
125
126     @Override
127     public @Nullable ThingUID getThingUID(ServiceInfo service) {
128         ThingTypeUID thingTypeUID = getThingType(service);
129         if (thingTypeUID != null) {
130             String id = service.getPropertyString(PROPERTY_DEVICE_ID); // device id
131             return new ThingUID(thingTypeUID, id);
132         }
133         return null;
134     }
135 }