2 * Copyright (c) 2010-2022 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.nikohomecontrol.internal.protocol;
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;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.openhab.core.util.HexUtils;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
27 * Class {@link NikoHomeControlDiscover} is used to get the Niko Home Control IP-interface IP address for bridge
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.
35 * @author Mark Herwege - Initial Contribution
38 * @author Mark Herwege - Initial Contribution
42 public final class NikoHomeControlDiscover {
44 private final Logger logger = LoggerFactory.getLogger(NikoHomeControlDiscover.class);
46 private InetAddress addr;
47 private String nhcBridgeId = "";
48 private boolean isNhcII;
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.
54 * @param broadcast Broadcast address of the network
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;
62 DatagramPacket discoveryPacket = new DatagramPacket(discoverBuffer, discoverBuffer.length, broadcastAddr,
64 byte[] buffer = new byte[1024];
65 DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
67 try (DatagramSocket datagramSocket = new DatagramSocket(null)) {
68 datagramSocket.setBroadcast(true);
69 datagramSocket.setSoTimeout(500);
70 datagramSocket.send(discoveryPacket);
72 datagramSocket.receive(packet);
73 logger.trace("bridge discovery response {}",
74 HexUtils.bytesToHex(Arrays.copyOf(packet.getData(), packet.getLength())));
79 addr = packet.getAddress();
80 setNhcBridgeId(packet);
82 logger.debug("IP address is {}, unique ID is {}", addr, nhcBridgeId);
89 public InetAddress getAddr() {
94 * @return the nhcBridgeId
96 public String getNhcBridgeId() {
101 * Check if the UDP packet comes from a Niko Home Control controller. The response should start with 0x44.
104 * @return true if packet is from a Niko Home Control controller
106 private boolean isNhc(DatagramPacket packet) {
107 byte[] packetData = packet.getData();
108 return ((packet.getLength() > 2) && (packetData[0] == 0x44));
112 * Retrieves a unique ID from the returned datagram packet received after sending the UDP discovery message.
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]));
124 nhcBridgeId = sb.toString();
128 * Checks if this is a NHC II Connected Controller
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)) {
144 * Test if the installation is a Niko Home Control II installation
146 * @return true if this is a Niko Home Control II installation
148 public boolean isNhcII() {