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.touchwand.internal.discovery;
15 import static org.openhab.binding.touchwand.internal.TouchWandBindingConstants.THING_TYPE_BRIDGE;
17 import java.io.IOException;
18 import java.net.DatagramPacket;
19 import java.net.DatagramSocket;
20 import java.net.InetAddress;
21 import java.net.SocketException;
22 import java.nio.charset.StandardCharsets;
23 import java.util.HashMap;
26 import org.eclipse.jdt.annotation.NonNullByDefault;
27 import org.eclipse.jdt.annotation.Nullable;
28 import org.openhab.binding.touchwand.internal.TouchWandBindingConstants;
29 import org.openhab.binding.touchwand.internal.TouchWandBridgeHandler;
30 import org.openhab.core.config.discovery.AbstractDiscoveryService;
31 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
32 import org.openhab.core.config.discovery.DiscoveryService;
33 import org.openhab.core.thing.ThingUID;
34 import org.osgi.service.component.annotations.Component;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
38 import com.google.gson.JsonObject;
39 import com.google.gson.JsonParser;
40 import com.google.gson.JsonSyntaxException;
43 * The {@link TouchWandControllerDiscoveryService} Discovery service for Touchwand Controllers.
45 * @author Roie Geron - Initial contribution
47 @Component(service = DiscoveryService.class, configurationPid = "discovery.touchwand")
49 public class TouchWandControllerDiscoveryService extends AbstractDiscoveryService {
51 private static final int SEARCH_TIME_SEC = 2;
52 private static final int TOUCHWAND_BCAST_PORT = 35000;
53 private final Logger logger = LoggerFactory.getLogger(TouchWandControllerDiscoveryService.class);
55 private @Nullable Thread socketReceiveThread = null;
56 private DatagramSocket listenSocket;
58 public TouchWandControllerDiscoveryService() throws SocketException {
59 super(TouchWandBridgeHandler.SUPPORTED_THING_TYPES, SEARCH_TIME_SEC, true);
61 listenSocket = new DatagramSocket(TOUCHWAND_BCAST_PORT);
65 protected void startScan() {
66 DatagramSocket localListenSocket = listenSocket;
67 runReceiveThread(localListenSocket);
71 protected void stopScan() {
76 public void activate(@Nullable Map<String, Object> configProperties) {
77 removeOlderResults(getTimestampOfLastScan());
78 super.activate(configProperties);
82 public void deactivate() {
83 Thread mySocketReceiveThread = socketReceiveThread;
84 if (mySocketReceiveThread != null) {
85 mySocketReceiveThread.interrupt();
86 socketReceiveThread = null;
93 private void addDeviceDiscoveryResult(String label, String ip) {
94 String id = ip.replace(".", "");
95 ThingUID thingUID = new ThingUID(THING_TYPE_BRIDGE, id);
96 Map<String, Object> properties = new HashMap<>();
97 properties.put("label", label);
98 properties.put("ipAddress", ip);
100 logger.debug("Add new Bridge label:{} id {} ",label, id);
101 thingDiscovered(DiscoveryResultBuilder.create(thingUID)
102 .withThingType(THING_TYPE_BRIDGE)
104 .withProperties(properties)
105 .withRepresentationProperty("ipAddress")
111 protected void runReceiveThread(DatagramSocket socket) {
112 Thread localSocketReceivedThread = socketReceiveThread = new ReceiverThread(socket);
113 localSocketReceivedThread.setName(TouchWandBindingConstants.DISCOVERY_THREAD_ID);
114 localSocketReceivedThread.setDaemon(true);
115 localSocketReceivedThread.start();
118 private class ReceiverThread extends Thread {
120 private static final int BUFFER_LENGTH = 256;
121 private DatagramPacket dgram = new DatagramPacket(new byte[BUFFER_LENGTH], BUFFER_LENGTH);
122 private DatagramSocket mySocket;
124 public ReceiverThread(DatagramSocket socket) {
133 private void receiveData(DatagramPacket datagram) {
135 while (!isInterrupted()) {
136 mySocket.receive(datagram);
137 InetAddress address = datagram.getAddress();
138 String sentence = new String(dgram.getData(), 0, dgram.getLength(), StandardCharsets.US_ASCII);
139 JsonObject bridge = JsonParser.parseString(sentence).getAsJsonObject();//
140 String name = bridge.get("name").getAsString();
141 addDeviceDiscoveryResult(name, address.getHostAddress());
142 logger.debug("Received Datagram from {}:{} on Port {} message {}", address.getHostAddress(),
143 dgram.getPort(), mySocket.getLocalPort(), sentence);
145 } catch (IOException | JsonSyntaxException e) {
146 if (!isInterrupted()) {
147 logger.debug("Error while receiving {}", e.getMessage());
149 logger.debug("Receiver thread was interrupted {}", e.getMessage());