Skip to content

Commit

Permalink
[MiHome] Add a Bridge property for the network interface to be used f…
Browse files Browse the repository at this point in the history
…or multicast traffic

Signed-off-by: Ion Marusic <ion.marusic@gmail.com>
  • Loading branch information
ratza committed Dec 31, 2020
1 parent bf2d40c commit e15a831
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 6 deletions.
20 changes: 18 additions & 2 deletions bundles/org.openhab.binding.mihome/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,17 @@ Just follow the instructions in ["Connecting devices to the gateway"](#connectin

- The binding requires port `9898` to not be used by any other service on the system.
- Make sure multicast traffic is correctly routed between the gateway and your openHAB instance
- To correctly receive multicast traffic, when your OpenHAB machine is using multiple network interfaces, you might need to configure the optional `interface` property on the `Bridge` Thing, like so:
```
Bridge mihome:bridge:f0b429XXXXXX "Xiaomi Gateway" [ ..., interface="eth0", ... ] {
```

## Configuration examples

### xiaomi.things:

```
Bridge mihome:bridge:f0b429XXXXXX "Xiaomi Gateway" [ serialNumber="f0b429XXXXXX", ipAddress="192.168.0.3", port=9898, key="XXXXXXXXXXXXXXXX", pollingInterval=6000 ] {
Bridge mihome:bridge:f0b429XXXXXX "Xiaomi Gateway" [ serialNumber="f0b429XXXXXX", ipAddress="192.168.0.3", port=9898, key="XXXXXXXXXXXXXXXX" ] {
Things:
gateway f0b429XXXXXX "Xiaomi Mi Smart Home Gateway" [itemId="f0b429XXXXXX"]
sensor_ht 158d0001XXXXXX "Xiaomi Temperature Sensor" [itemId="158d0001XXXXXX"]
Expand Down Expand Up @@ -545,7 +549,18 @@ In case you want to check if the communication between the machine and the gatew
- make sure you have __netcat__ installed
- Enter ```netcat -ukl 9898```
- At least every 10 seconds you should see a message coming in from the gateway which looks like
```{"cmd":"heartbeat","model":"gateway","sid":"`xxx","short_id":"0","token":"xxx","data":"{\"ip\":\"`xxx\"}"}```
```{"cmd":"heartbeat","model":"gateway","sid":"`xxx","short_id":"0","token":"xxx","data":"{\"ip\":\"`xxx\"}"}```

#### Multiple network interfaces

When the computer running OpenHAB has more than one network interface configured (typically, a VLAN for your segregated IoT devices, and the other for your regular traffic like internet, OpenHAB panel access, etc), it could be that OpenHAB will attempt to listen for Multicast traffic of the Gateway on the wrong network interface. That will prevent OpenHAB and `netcat` from receiving the messages from the Xiaomi Gateway. Within OpenHAB this manifests by seeing the Gateway and its devices online for a brief period after OpenHAB startup, after which they timeout and are shown Offline. No channel triggers from the Gateway work in this case.

In order to verify that traffic is actually received by the machine use `tcpdump` on each interface:
- List your network interfaces `ifconfig | grep MULTICAST` or `ip link | grep MULTICAST`
- Use `tcpdump -i <interface> port 9898` for each interface to verify if you receive traffic

If you already know the correct interface, or you found the correct one through tcpdump:
- Configure the `interface` property of the `Bridge` Thing with the correct name (for example `eth0`, etc)

### Check if your Windows/Mac machine receives multicast traffic

Expand All @@ -562,6 +577,7 @@ __My gateway shows up in openHAB and I have added all devices, but I don't get a
- Make sure the gateway and the machine are in the same subnet
- Try to connect your machine via Ethernet instead of Wifi
- Make sure you don't have any firewall rules blocking multicast
- If you have multiple network interfaces, try to configure the `interface` property of the `Bridge` Thing

__I have connected my gateway to the network but it doesn't show up in openHAB:__
- Make sure to have the developer mode enabled in the MiHome app
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ public class XiaomiGatewayBindingConstants {
public static final String SERIAL_NUMBER = "serialNumber";
public static final String HOST = "ipAddress";
public static final String PORT = "port";
public static final String INTERFACE = "interface";
public static final String TOKEN = "token";

// Item config properties
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public void initialize() {
return;
}
logger.debug("Init socket on Port: {}", port);
socket = new XiaomiBridgeSocket(port, getThing().getUID().getId());
socket = new XiaomiBridgeSocket(port, (String) config.get(INTERFACE), getThing().getUID().getId());
socket.initialize();
socket.registerListener(this);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
import java.io.IOException;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.NetworkInterface;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -30,9 +32,11 @@
public class XiaomiBridgeSocket extends XiaomiSocket {

private final Logger logger = LoggerFactory.getLogger(XiaomiBridgeSocket.class);
private @Nullable final String netIf;

public XiaomiBridgeSocket(int port, String owner) {
public XiaomiBridgeSocket(int port, String netIf, String owner) {
super(port, owner);
this.netIf = netIf;
}

/**
Expand All @@ -51,10 +55,16 @@ protected synchronized void setupSocket() {
try {
logger.debug("Setup socket");
socket = new MulticastSocket(getPort());

if (netIf != null) {
socket.setNetworkInterface(NetworkInterface.getByName(netIf));
}

setSocket(socket); // must bind receive side
socket.joinGroup(InetAddress.getByName(MCAST_ADDR));
logger.debug("Initialized socket to {}:{} on {}:{}", socket.getRemoteSocketAddress(), socket.getPort(),
socket.getLocalAddress(), socket.getLocalPort());
logger.debug("Initialized socket to {}:{} on {}:{} bound to {} network interface",
socket.getRemoteSocketAddress(), socket.getPort(), socket.getLocalAddress(), socket.getLocalPort(),
socket.getNetworkInterface());
} catch (IOException e) {
logger.error("Setup socket error", e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@
<advanced>true</advanced>
</parameter>

<parameter name="interface" type="text">
<context>network-address</context>
<label>Interface</label>
<description>Interface to bind to for the MiHome communication channel</description>
<required>false</required>
<advanced>true</advanced>
</parameter>

<parameter name="key" type="text">
<label>Developer Key</label>
<description>Developer key extracted from Xiaomi's app</description>
Expand Down

0 comments on commit e15a831

Please sign in to comment.