]> git.basschouten.com Git - openhab-addons.git/blob
1bb9490c6972a1ab05e1e1683ceef8aa84d4faff
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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.dscalarm.internal.discovery;
14
15 import java.io.BufferedReader;
16 import java.io.IOException;
17 import java.io.InputStreamReader;
18 import java.net.InetAddress;
19 import java.net.InetSocketAddress;
20 import java.net.NetworkInterface;
21 import java.net.Socket;
22 import java.net.SocketException;
23 import java.net.SocketTimeoutException;
24
25 import org.apache.commons.net.util.SubnetUtils;
26 import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30 /**
31  * This class is responsible for discovering the EyezOn Envisalink 3/2DS Ethernet interface.
32  *
33  * @author Russell Stephens - Initial Contribution
34  *
35  */
36 public class EnvisalinkBridgeDiscovery {
37     private final Logger logger = LoggerFactory.getLogger(EnvisalinkBridgeDiscovery.class);
38
39     static final int ENVISALINK_BRIDGE_PORT = 4025;
40     static final int CONNECTION_TIMEOUT = 10;
41     static final int SO_TIMEOUT = 15000;
42     static final String ENVISALINK_DISCOVERY_RESPONSE = "505";
43
44     private DSCAlarmBridgeDiscovery dscAlarmBridgeDiscovery = null;
45     private String ipAddress;
46
47     /**
48      * Constructor.
49      */
50     public EnvisalinkBridgeDiscovery(DSCAlarmBridgeDiscovery dscAlarmBridgeDiscovery) {
51         this.dscAlarmBridgeDiscovery = dscAlarmBridgeDiscovery;
52     }
53
54     /**
55      * Method for Bridge Discovery.
56      */
57     public synchronized void discoverBridge() {
58         logger.debug("Starting Envisalink Bridge Discovery.");
59
60         SubnetUtils subnetUtils = null;
61         SubnetInfo subnetInfo = null;
62         long lowIP = 0;
63         long highIP = 0;
64
65         try {
66             InetAddress localHost = InetAddress.getLocalHost();
67             NetworkInterface networkInterface = NetworkInterface.getByInetAddress(localHost);
68             subnetUtils = new SubnetUtils(localHost.getHostAddress() + "/"
69                     + networkInterface.getInterfaceAddresses().get(0).getNetworkPrefixLength());
70             subnetInfo = subnetUtils.getInfo();
71             lowIP = convertIPToNumber(subnetInfo.getLowAddress());
72             highIP = convertIPToNumber(subnetInfo.getHighAddress());
73         } catch (IllegalArgumentException e) {
74             logger.warn("discoverBridge(): Illegal Argument Exception - {}", e.toString());
75             return;
76         } catch (Exception e) {
77             logger.warn("discoverBridge(): Error - Unable to get Subnet Information! {}", e.toString());
78             return;
79         }
80
81         logger.debug("   Local IP Address: {} - {}", subnetInfo.getAddress(),
82                 convertIPToNumber(subnetInfo.getAddress()));
83         logger.debug("   Subnet:           {} - {}", subnetInfo.getNetworkAddress(),
84                 convertIPToNumber(subnetInfo.getNetworkAddress()));
85         logger.debug("   Network Prefix:   {}", subnetInfo.getCidrSignature().split("/")[1]);
86         logger.debug("   Network Mask:     {}", subnetInfo.getNetmask());
87         logger.debug("   Low IP:           {}", convertNumberToIP(lowIP));
88         logger.debug("   High IP:          {}", convertNumberToIP(highIP));
89
90         for (long ip = lowIP; ip <= highIP; ip++) {
91             try (Socket socket = new Socket()) {
92                 ipAddress = convertNumberToIP(ip);
93
94                 socket.setReuseAddress(true);
95                 socket.setReceiveBufferSize(32);
96                 socket.connect(new InetSocketAddress(ipAddress, ENVISALINK_BRIDGE_PORT), CONNECTION_TIMEOUT);
97                 if (socket.isConnected()) {
98                     String message = "";
99                     socket.setSoTimeout(SO_TIMEOUT);
100                     try (BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
101                         message = input.readLine();
102                     } catch (SocketTimeoutException e) {
103                         logger.debug("discoverBridge(): No Message Read from Socket at [{}] - {}", ipAddress,
104                                 e.getMessage());
105                         continue;
106                     } catch (Exception e) {
107                         logger.debug("discoverBridge(): Exception Reading from Socket at [{}]! {}", ipAddress,
108                                 e.toString());
109                         continue;
110                     }
111
112                     if (message.substring(0, 3).equals(ENVISALINK_DISCOVERY_RESPONSE)) {
113                         logger.debug("discoverBridge(): Bridge Found - [{}]!  Message - '{}'", ipAddress, message);
114                         dscAlarmBridgeDiscovery.addEnvisalinkBridge(ipAddress);
115                     } else {
116                         logger.debug("discoverBridge(): No Response from Connection -  [{}]!  Message - '{}'",
117                                 ipAddress, message);
118                     }
119                 }
120             } catch (IllegalArgumentException e) {
121                 logger.debug("discoverBridge(): Illegal Argument Exception - {}", e.toString());
122             } catch (SocketTimeoutException e) {
123                 logger.trace("discoverBridge(): No Connection on Port 4025! [{}]", ipAddress);
124             } catch (SocketException e) {
125                 logger.debug("discoverBridge(): Socket Exception! [{}] - {}", ipAddress, e.toString());
126             } catch (IOException e) {
127                 logger.debug("discoverBridge(): IO Exception! [{}] - {}", ipAddress, e.toString());
128             }
129         }
130     }
131
132     /**
133      * Convert an IP address to a number.
134      *
135      * @param ipAddress
136      * @return
137      */
138     private long convertIPToNumber(String ipAddress) {
139         String[] octets = ipAddress.split("\\.");
140
141         if (octets.length != 4) {
142             throw new IllegalArgumentException("Invalid IP address: " + ipAddress);
143         }
144
145         long ip = 0;
146
147         for (int i = 3; i >= 0; i--) {
148             long octet = Long.parseLong(octets[3 - i]);
149
150             if (octet != (octet & 0xff)) {
151                 throw new IllegalArgumentException("Invalid IP address: " + ipAddress);
152             }
153
154             ip |= octet << (i * 8);
155         }
156
157         return ip;
158     }
159
160     /**
161      * Convert a number to an IP address.
162      *
163      * @param ip
164      * @return
165      */
166     private String convertNumberToIP(long ip) {
167         StringBuilder ipAddress = new StringBuilder(15);
168
169         for (int i = 0; i < 4; i++) {
170
171             ipAddress.insert(0, Long.toString(ip & 0xff));
172
173             if (i < 3) {
174                 ipAddress.insert(0, '.');
175             }
176
177             ip = ip >> 8;
178         }
179
180         return ipAddress.toString();
181     }
182 }