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.wifiled.internal.discovery;
15 import static org.openhab.binding.wifiled.internal.WiFiLEDBindingConstants.*;
17 import java.io.IOException;
18 import java.net.DatagramPacket;
19 import java.net.DatagramSocket;
20 import java.net.InetAddress;
21 import java.net.SocketTimeoutException;
22 import java.util.HashMap;
25 import java.util.concurrent.TimeUnit;
27 import org.openhab.binding.wifiled.internal.handler.AbstractWiFiLEDDriver;
28 import org.openhab.binding.wifiled.internal.handler.ClassicWiFiLEDDriver;
29 import org.openhab.core.config.discovery.AbstractDiscoveryService;
30 import org.openhab.core.config.discovery.DiscoveryResult;
31 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
32 import org.openhab.core.config.discovery.DiscoveryService;
33 import org.openhab.core.thing.ThingTypeUID;
34 import org.openhab.core.thing.ThingUID;
35 import org.osgi.service.component.annotations.Component;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
40 * The {@link WiFiLEDDiscoveryService} class implements a service
41 * for discovering supported WiFi LED Devices.
43 * @author Osman Basha - Initial contribution
45 @Component(service = DiscoveryService.class, configurationPid = "discovery.wifiled")
46 public class WiFiLEDDiscoveryService extends AbstractDiscoveryService {
48 private static final int DEFAULT_BROADCAST_PORT = 48899;
49 private static final String DISCOVER_MESSAGE = "HF-A11ASSISTHREAD";
50 private Logger logger = LoggerFactory.getLogger(WiFiLEDDiscoveryService.class);
52 public WiFiLEDDiscoveryService() {
53 super(SUPPORTED_THING_TYPES_UIDS, 15, true);
57 public Set<ThingTypeUID> getSupportedThingTypes() {
58 return SUPPORTED_THING_TYPES_UIDS;
62 protected void startBackgroundDiscovery() {
63 logger.debug("Start WiFi LED background discovery");
64 scheduler.schedule(() -> discover(), 0, TimeUnit.SECONDS);
68 public void startScan() {
69 logger.debug("Start WiFi LED scan");
73 private synchronized void discover() {
74 logger.debug("Try to discover all WiFi LED devices");
76 try (DatagramSocket socket = new DatagramSocket(DEFAULT_BROADCAST_PORT)) {
77 socket.setBroadcast(true);
78 socket.setSoTimeout(5000);
80 InetAddress inetAddress = InetAddress.getByName("255.255.255.255");
83 byte[] discover = DISCOVER_MESSAGE.getBytes();
84 DatagramPacket packet = new DatagramPacket(discover, discover.length, inetAddress, DEFAULT_BROADCAST_PORT);
86 logger.debug("Discover message sent: '{}'", DISCOVER_MESSAGE);
90 byte[] rxbuf = new byte[256];
91 packet = new DatagramPacket(rxbuf, rxbuf.length);
93 socket.receive(packet);
94 } catch (SocketTimeoutException e) {
95 logger.trace("Timeout exceeded. Discovery process ended.");
99 byte[] data = packet.getData();
100 String s = bytesToString(data);
101 logger.debug("Discovery response received: '{}' [{}] ", s, ClassicWiFiLEDDriver.bytesToHex(data));
103 // 192.168.178.25,ACCF23489C9A,HF-LPB100-ZJ200
104 // ^-IP..........,^-MAC.......,^-HOSTNAME.....
106 String[] ss = s.split(",");
108 logger.debug("Ignoring unparseable discovery response: '{}'", s);
115 logger.debug("Adding a new WiFi LED with IP '{}' and MAC '{}' to inbox", ip, mac);
116 Map<String, Object> properties = new HashMap<>();
117 properties.put("ip", ip);
118 properties.put("protocol", AbstractWiFiLEDDriver.Protocol.LD382A);
119 ThingUID uid = new ThingUID(THING_TYPE_WIFILED, mac);
121 DiscoveryResult result = DiscoveryResultBuilder.create(uid).withProperties(properties).withLabel(name)
123 thingDiscovered(result);
124 logger.debug("Thing discovered '{}'", result);
126 } catch (IOException e) {
127 logger.debug("Device discovery encountered an I/O Exception: {}", e.getMessage(), e);
131 private static String bytesToString(byte[] bytes) {
132 StringBuilder sb = new StringBuilder();
133 for (byte aByte : bytes) {
137 sb.append((char) (aByte & 0xFF));
140 return sb.toString();