]> git.basschouten.com Git - openhab-addons.git/blob
45d3cdbb0778862f894d0f6441b97f0d9df2d043
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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.nikohomecontrol.internal.protocol;
14
15 import java.io.IOException;
16 import java.net.DatagramPacket;
17 import java.net.DatagramSocket;
18 import java.net.InetAddress;
19 import java.util.Arrays;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.openhab.core.util.HexUtils;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 /**
27  * Class {@link NikoHomeControlDiscover} is used to get the Niko Home Control IP-interface IP address for bridge
28  * discovery.
29  * <p>
30  * The constructor broadcasts a UDP packet with content 0x44 on port 10000.
31  * The Niko Home Control IP-interface responds to this UDP packet.
32  * The IP-address from the Niko Home Control IP-interface is then extracted from the response packet.
33  * The data content of the response packet is used as a unique identifier for the bridge.
34  *
35  * @author Mark Herwege - Initial Contribution
36  */
37 /**
38  * @author Mark Herwege - Initial Contribution
39  *
40  */
41 @NonNullByDefault
42 public final class NikoHomeControlDiscover {
43
44     private final Logger logger = LoggerFactory.getLogger(NikoHomeControlDiscover.class);
45
46     private InetAddress addr;
47     private String nhcBridgeId = "";
48     private boolean isNhcII;
49
50     /**
51      * Discover a Niko Home Control IP interface by broadcasting UDP packet 0x44 to port 10000. The IP interface will
52      * reply. The address of the IP interface is than derived from that response.
53      *
54      * @param broadcast Broadcast address of the network
55      * @throws IOException
56      */
57     public NikoHomeControlDiscover(String broadcast) throws IOException {
58         final byte[] discoverBuffer = { (byte) 0x44 };
59         final InetAddress broadcastAddr = InetAddress.getByName(broadcast);
60         final int broadcastPort = 10000;
61
62         DatagramPacket discoveryPacket = new DatagramPacket(discoverBuffer, discoverBuffer.length, broadcastAddr,
63                 broadcastPort);
64         byte[] buffer = new byte[1024];
65         DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
66
67         try (DatagramSocket datagramSocket = new DatagramSocket(null)) {
68             datagramSocket.setBroadcast(true);
69             datagramSocket.setSoTimeout(500);
70             datagramSocket.send(discoveryPacket);
71             while (true) {
72                 datagramSocket.receive(packet);
73                 logger.trace("bridge discovery response {}",
74                         HexUtils.bytesToHex(Arrays.copyOf(packet.getData(), packet.getLength())));
75                 if (isNhc(packet)) {
76                     break;
77                 }
78             }
79             addr = packet.getAddress();
80             setNhcBridgeId(packet);
81             setIsNhcII(packet);
82             logger.debug("IP address is {}, unique ID is {}", addr, nhcBridgeId);
83         }
84     }
85
86     /**
87      * @return the addr
88      */
89     public InetAddress getAddr() {
90         return addr;
91     }
92
93     /**
94      * @return the nhcBridgeId
95      */
96     public String getNhcBridgeId() {
97         return nhcBridgeId;
98     }
99
100     /**
101      * Check if the UDP packet comes from a Niko Home Control controller. The response should start with 0x44.
102      *
103      * @param packet
104      * @return true if packet is from a Niko Home Control controller
105      */
106     private boolean isNhc(DatagramPacket packet) {
107         byte[] packetData = packet.getData();
108         return ((packet.getLength() > 2) && (packetData[0] == 0x44));
109     }
110
111     /**
112      * Retrieves a unique ID from the returned datagram packet received after sending the UDP discovery message.
113      *
114      * @param packet
115      */
116     private void setNhcBridgeId(DatagramPacket packet) {
117         byte[] packetData = packet.getData();
118         int packetLength = packet.getLength();
119         packetLength = packetLength > 6 ? 6 : packetLength;
120         StringBuilder sb = new StringBuilder(packetLength);
121         for (int i = 0; i < packetLength; i++) {
122             sb.append(String.format("%02x", packetData[i]));
123         }
124         nhcBridgeId = sb.toString();
125     }
126
127     /**
128      * Checks if this is a NHC II Connected Controller
129      *
130      * @param packet
131      */
132     private void setIsNhcII(DatagramPacket packet) {
133         byte[] packetData = packet.getData();
134         int packetLength = packet.getLength();
135         // The 16th byte in the packet is 2 for a NHC II Connected Controller
136         if ((packetLength >= 16) && (packetData[15] >= 2)) {
137             isNhcII = true;
138         } else {
139             isNhcII = false;
140         }
141     }
142
143     /**
144      * Test if the installation is a Niko Home Control II installation
145      *
146      * @return true if this is a Niko Home Control II installation
147      */
148     public boolean isNhcII() {
149         return isNhcII;
150     }
151 }