]> git.basschouten.com Git - openhab-addons.git/blob
e5acc5cf8f086f8947479b67a746d0ac75675f46
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 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.touchwand.internal.discovery;
14
15 import static org.openhab.binding.touchwand.internal.TouchWandBindingConstants.THING_TYPE_BRIDGE;
16
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;
24 import java.util.Map;
25
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;
37
38 /**
39  * The {@link TouchWandControllerDiscoveryService} Discovery service for Touchwand Controllers.
40  *
41  * @author Roie Geron - Initial contribution
42  */
43 @Component(service = DiscoveryService.class, configurationPid = "discovery.touchwand")
44 @NonNullByDefault
45 public class TouchWandControllerDiscoveryService extends AbstractDiscoveryService {
46
47     private static final int SEARCH_TIME_SEC = 2;
48     private static final int TOUCHWAND_BCAST_PORT = 35000;
49     private final Logger logger = LoggerFactory.getLogger(TouchWandControllerDiscoveryService.class);
50
51     private @Nullable Thread socketReceiveThread = null;
52     private DatagramSocket listenSocket;
53
54     public TouchWandControllerDiscoveryService() throws SocketException {
55         super(TouchWandBridgeHandler.SUPPORTED_THING_TYPES, SEARCH_TIME_SEC, true);
56
57         listenSocket = new DatagramSocket(TOUCHWAND_BCAST_PORT);
58     }
59
60     @Override
61     protected void startScan() {
62         DatagramSocket localListenSocket = listenSocket;
63         runReceiveThread(localListenSocket);
64     }
65
66     @Override
67     protected void stopScan() {
68         super.stopScan();
69     }
70
71     @Override
72     public void activate(@Nullable Map<String, Object> configProperties) {
73         removeOlderResults(getTimestampOfLastScan());
74         super.activate(configProperties);
75     }
76
77     @Override
78     public void deactivate() {
79         Thread mySocketReceiveThread = socketReceiveThread;
80         if (mySocketReceiveThread != null) {
81             mySocketReceiveThread.interrupt();
82             socketReceiveThread = null;
83         }
84
85         listenSocket.close();
86         super.deactivate();
87     }
88
89     private void addDeviceDiscoveryResult(String label, String ip) {
90         String id = ip.replaceAll("\\.", "");
91         ThingUID thingUID = new ThingUID(THING_TYPE_BRIDGE, id);
92         Map<String, Object> properties = new HashMap<>();
93         properties.put("label", label);
94         properties.put("ipAddress", ip);
95         // @formatter:off
96         logger.debug("Add new Bridge label:{} id {} ",label, id);
97         thingDiscovered(DiscoveryResultBuilder.create(thingUID)
98                 .withThingType(THING_TYPE_BRIDGE)
99                 .withLabel(label)
100                 .withProperties(properties)
101                 .withRepresentationProperty("ipAddress")
102                 .build()
103         );
104         // @formatter:on
105     }
106
107     protected void runReceiveThread(DatagramSocket socket) {
108         Thread localSocketReceivedThread = socketReceiveThread = new ReceiverThread(socket);
109         localSocketReceivedThread.setName(TouchWandBindingConstants.DISCOVERY_THREAD_ID);
110         localSocketReceivedThread.setDaemon(true);
111         localSocketReceivedThread.start();
112     }
113
114     private class ReceiverThread extends Thread {
115
116         private static final int BUFFER_LENGTH = 256;
117         private DatagramPacket dgram = new DatagramPacket(new byte[BUFFER_LENGTH], BUFFER_LENGTH);
118         private DatagramSocket mySocket;
119
120         public ReceiverThread(DatagramSocket socket) {
121             mySocket = socket;
122         }
123
124         @Override
125         public void run() {
126             receiveData(dgram);
127         }
128
129         private void receiveData(DatagramPacket datagram) {
130             try {
131                 while (!isInterrupted()) {
132                     mySocket.receive(datagram);
133                     InetAddress address = datagram.getAddress();
134                     String sentence = new String(dgram.getData(), 0, dgram.getLength(), StandardCharsets.US_ASCII);
135                     addDeviceDiscoveryResult(sentence, address.getHostAddress().toString());
136                     logger.debug("Received Datagram from {}:{} on Port {} message {}", address.getHostAddress(),
137                             dgram.getPort(), mySocket.getLocalPort(), sentence);
138                 }
139             } catch (IOException e) {
140                 if (!isInterrupted()) {
141                     logger.warn("Error while receiving {}", e.getMessage());
142                 } else {
143                     logger.debug("Receiver thread was interrupted {}", e.getMessage());
144                 }
145             }
146         }
147     }
148 }