]> git.basschouten.com Git - openhab-addons.git/blob
86756be823f4096947d591a09a2ea88bfb7e1bd3
[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.denonmarantz.internal.discovery;
14
15 import static org.openhab.binding.denonmarantz.internal.DenonMarantzBindingConstants.*;
16
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.Map;
20 import java.util.Set;
21 import java.util.regex.Matcher;
22 import java.util.regex.Pattern;
23
24 import javax.jmdns.ServiceInfo;
25
26 import org.openhab.core.config.discovery.DiscoveryResult;
27 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
28 import org.openhab.core.config.discovery.mdns.MDNSDiscoveryParticipant;
29 import org.openhab.core.thing.Thing;
30 import org.openhab.core.thing.ThingTypeUID;
31 import org.openhab.core.thing.ThingUID;
32 import org.osgi.service.component.annotations.Component;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 /**
37  * @author Jan-Willem Veldhuis - Initial contribution
38  *
39  */
40 @Component
41 public class DenonMarantzDiscoveryParticipant implements MDNSDiscoveryParticipant {
42
43     private Logger logger = LoggerFactory.getLogger(DenonMarantzDiscoveryParticipant.class);
44
45     // Service type for 'Airplay enabled' receivers
46     private static final String RAOP_SERVICE_TYPE = "_raop._tcp.local.";
47
48     /**
49      * Match the serial number, vendor and model of the discovered AVR.
50      * Input is like "0006781D58B1@Marantz SR5008._raop._tcp.local."
51      * A Denon AVR serial (MAC address) starts with 0005CD
52      * A Marantz AVR serial (MAC address) starts with 000678
53      */
54     private static final Pattern DENON_MARANTZ_PATTERN = Pattern
55             .compile("^((?:0005CD|000678)[A-Z0-9]+)@(.+)\\._raop\\._tcp\\.local\\.$");
56
57     /**
58      * Denon AVRs have a MAC address / serial number starting with 0005CD
59      */
60     private static final String DENON_MAC_PREFIX = "0005CD";
61
62     /**
63      * Marantz AVRs have a MAC address / serial number starting with 000678
64      */
65     private static final String MARANTZ_MAC_PREFIX = "000678";
66
67     @Override
68     public Set<ThingTypeUID> getSupportedThingTypeUIDs() {
69         return Collections.singleton(THING_TYPE_AVR);
70     }
71
72     @Override
73     public String getServiceType() {
74         return RAOP_SERVICE_TYPE;
75     }
76
77     @Override
78     public DiscoveryResult createResult(ServiceInfo serviceInfo) {
79         String qualifiedName = serviceInfo.getQualifiedName();
80         logger.debug("AVR found: {}", qualifiedName);
81         ThingUID thingUID = getThingUID(serviceInfo);
82         if (thingUID != null) {
83             Matcher matcher = DENON_MARANTZ_PATTERN.matcher(qualifiedName);
84             matcher.matches(); // we already know it matches, it was matched in getThingUID
85             String serial = matcher.group(1).toLowerCase();
86
87             /**
88              * The Vendor is not available from the mDNS result.
89              * We assign the Vendor based on our assumptions of the MAC address prefix.
90              */
91             String vendor = "";
92             if (serial.startsWith(MARANTZ_MAC_PREFIX)) {
93                 vendor = "Marantz";
94             } else if (serial.startsWith(DENON_MAC_PREFIX)) {
95                 vendor = "Denon";
96             }
97
98             // 'am=...' property describes the model name
99             String model = serviceInfo.getPropertyString("am");
100             String friendlyName = matcher.group(2).trim();
101
102             Map<String, Object> properties = new HashMap<>(2);
103
104             if (serviceInfo.getHostAddresses().length == 0) {
105                 logger.debug("Could not determine IP address for the Denon/Marantz AVR");
106                 return null;
107             }
108             String host = serviceInfo.getHostAddresses()[0];
109
110             logger.debug("IP Address: {}", host);
111
112             properties.put(PARAMETER_HOST, host);
113             properties.put(Thing.PROPERTY_SERIAL_NUMBER, serial);
114             properties.put(Thing.PROPERTY_VENDOR, vendor);
115             properties.put(Thing.PROPERTY_MODEL_ID, model);
116
117             String label = friendlyName + " (" + vendor + ' ' + model + ")";
118             DiscoveryResult result = DiscoveryResultBuilder.create(thingUID).withProperties(properties).withLabel(label)
119                     .withRepresentationProperty(Thing.PROPERTY_SERIAL_NUMBER).build();
120             return result;
121
122         } else {
123             return null;
124         }
125     }
126
127     @Override
128     public ThingUID getThingUID(ServiceInfo service) {
129         Matcher matcher = DENON_MARANTZ_PATTERN.matcher(service.getQualifiedName());
130         if (matcher.matches()) {
131             logger.debug("This seems like a supported Denon/Marantz AVR!");
132             String serial = matcher.group(1).toLowerCase();
133             return new ThingUID(THING_TYPE_AVR, serial);
134         } else {
135             logger.trace("This discovered device is not supported by the DenonMarantz binding, ignoring..");
136         }
137         return null;
138     }
139 }