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