2 * Copyright (c) 2010-2023 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.denonmarantz.internal.discovery;
15 import static org.openhab.binding.denonmarantz.internal.DenonMarantzBindingConstants.*;
17 import java.util.HashMap;
20 import java.util.regex.Matcher;
21 import java.util.regex.Pattern;
23 import javax.jmdns.ServiceInfo;
25 import org.openhab.core.config.discovery.DiscoveryResult;
26 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
27 import org.openhab.core.config.discovery.mdns.MDNSDiscoveryParticipant;
28 import org.openhab.core.thing.Thing;
29 import org.openhab.core.thing.ThingTypeUID;
30 import org.openhab.core.thing.ThingUID;
31 import org.osgi.service.component.annotations.Component;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
36 * @author Jan-Willem Veldhuis - Initial contribution
40 public class DenonMarantzDiscoveryParticipant implements MDNSDiscoveryParticipant {
42 private Logger logger = LoggerFactory.getLogger(DenonMarantzDiscoveryParticipant.class);
44 // Service type for 'Airplay enabled' receivers
45 private static final String RAOP_SERVICE_TYPE = "_raop._tcp.local.";
48 * Match the serial number, vendor and model of the discovered AVR.
49 * Input is like "0006781D58B1@Marantz SR5008._raop._tcp.local."
50 * A Denon AVR serial (MAC address) starts with 0005CD
51 * A Marantz AVR serial (MAC address) starts with 000678
53 private static final Pattern DENON_MARANTZ_PATTERN = Pattern
54 .compile("^((?:0005CD|000678)[A-Z0-9]+)@(.+)\\._raop\\._tcp\\.local\\.$");
57 * Denon AVRs have a MAC address / serial number starting with 0005CD
59 private static final String DENON_MAC_PREFIX = "0005CD";
62 * Marantz AVRs have a MAC address / serial number starting with 000678
64 private static final String MARANTZ_MAC_PREFIX = "000678";
67 public Set<ThingTypeUID> getSupportedThingTypeUIDs() {
68 return Set.of(THING_TYPE_AVR);
72 public String getServiceType() {
73 return RAOP_SERVICE_TYPE;
77 public DiscoveryResult createResult(ServiceInfo serviceInfo) {
78 String qualifiedName = serviceInfo.getQualifiedName();
79 logger.debug("AVR found: {}", qualifiedName);
80 ThingUID thingUID = getThingUID(serviceInfo);
81 if (thingUID != null) {
82 Matcher matcher = DENON_MARANTZ_PATTERN.matcher(qualifiedName);
83 matcher.matches(); // we already know it matches, it was matched in getThingUID
84 String serial = matcher.group(1).toLowerCase();
87 * The Vendor is not available from the mDNS result.
88 * We assign the Vendor based on our assumptions of the MAC address prefix.
91 if (serial.startsWith(MARANTZ_MAC_PREFIX)) {
93 } else if (serial.startsWith(DENON_MAC_PREFIX)) {
97 // 'am=...' property describes the model name
98 String model = serviceInfo.getPropertyString("am");
99 String friendlyName = matcher.group(2).trim();
101 Map<String, Object> properties = new HashMap<>(2);
103 if (serviceInfo.getHostAddresses().length == 0) {
104 logger.debug("Could not determine IP address for the Denon/Marantz AVR");
107 String host = serviceInfo.getHostAddresses()[0];
109 logger.debug("IP Address: {}", host);
111 properties.put(PARAMETER_HOST, host);
112 properties.put(Thing.PROPERTY_SERIAL_NUMBER, serial);
113 properties.put(Thing.PROPERTY_VENDOR, vendor);
114 properties.put(Thing.PROPERTY_MODEL_ID, model);
116 String label = friendlyName + " (" + vendor + ' ' + model + ")";
117 return DiscoveryResultBuilder.create(thingUID).withProperties(properties).withLabel(label)
118 .withRepresentationProperty(Thing.PROPERTY_SERIAL_NUMBER).build();
126 public ThingUID getThingUID(ServiceInfo service) {
127 Matcher matcher = DENON_MARANTZ_PATTERN.matcher(service.getQualifiedName());
128 if (matcher.matches()) {
129 logger.debug("This seems like a supported Denon/Marantz AVR!");
130 String serial = matcher.group(1).toLowerCase();
131 return new ThingUID(THING_TYPE_AVR, serial);
133 logger.trace("This discovered device is not supported by the DenonMarantz binding, ignoring..");