package com.beowulfe.hap.impl.jmdns; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.HashMap; import java.util.Map; import javax.jmdns.JmDNS; import javax.jmdns.ServiceInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class JmdnsHomekitAdvertiser { private static final String SERVICE_TYPE = "_hap._tcp.local."; private final JmDNS jmdns; private boolean discoverable = true; private final static Logger logger = LoggerFactory.getLogger(JmdnsHomekitAdvertiser.class); private boolean isAdvertising = false; private String label; private String mac; private int port; private int configurationIndex; public JmdnsHomekitAdvertiser(InetAddress localAddress) throws UnknownHostException, IOException { jmdns = JmDNS.create(localAddress); } public synchronized void advertise(String label, String mac, int port, int configurationIndex) throws Exception { if (isAdvertising) { throw new IllegalStateException("Homekit advertiser is already running"); } this.label = label; this.mac = mac; this.port = port; this.configurationIndex = configurationIndex; logger.info("Advertising accessory "+label); registerService(); Runtime.getRuntime().addShutdownHook(new Thread(() -> { logger.info("Stopping advertising in response to shutdown."); jmdns.unregisterAllServices(); })); isAdvertising = true; } public synchronized void stop() { jmdns.unregisterAllServices(); } public synchronized void setDiscoverable(boolean discoverable) throws IOException { if (this.discoverable != discoverable) { this.discoverable = discoverable; if (isAdvertising) { logger.info("Re-creating service due to change in discoverability to "+discoverable); jmdns.unregisterAllServices(); registerService(); } } } public synchronized void setConfigurationIndex(int revision) throws IOException { if (this.configurationIndex != revision) { this.configurationIndex = revision; if (isAdvertising) { logger.info("Re-creating service due to change in configuration index to "+revision); jmdns.unregisterAllServices(); registerService(); } } } private void registerService() throws IOException { logger.info("Registering "+SERVICE_TYPE+" on port "+port); Map<String, String> props = new HashMap<>(); props.put("sf", discoverable ? "1" : "0"); props.put("id", mac); props.put("md", label); props.put("c#", Integer.toString(configurationIndex)); props.put("s#", "1"); props.put("ff", "0"); props.put("ci", "1"); jmdns.registerService(ServiceInfo.create(SERVICE_TYPE, label, port, 1, 1, props)); } }