Skip to content

Commit

Permalink
[homekit] make use of openHAB mDNS service (openhab#10076)
Browse files Browse the repository at this point in the history
* make use of openHAB mdns service
* remove unnecessary null check
* add network configuration back

Signed-off-by: Eugen Freiter <freiter@gmx.de>
Signed-off-by: John Marshall <john.marshall.au@gmail.com>
  • Loading branch information
yfre authored and themillhousegroup committed May 10, 2021
1 parent 78642d6 commit 5254b0d
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 27 deletions.
41 changes: 30 additions & 11 deletions bundles/org.openhab.io.homekit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ org.openhab.homekit:maximumTemperature=100

| Setting | Description | Default value |
|:-------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------|
| networkInterface | IP address or domain name under which the HomeKit bridge can be reached. If no value is configured, the add-on uses the first network adapter address. | (none) |
| networkInterface | IP address or domain name under which the HomeKit bridge can be reached. If no value is configured, the add-on uses the first network adapter address configured for openHAB. | (none) |
| port | Port under which the HomeKit bridge can be reached. | 9123 |
| pin | Pin code used for pairing with iOS devices. Apparently, pin codes are provided by Apple and represent specific device types, so they cannot be chosen freely. The pin code 031-45-154 is used in sample applications and known to work. | 031-45-154 |
| startDelay | HomeKit start delay in seconds in case the number of accessories is lower than last time. This helps to avoid resetting home app in case not all items have been initialised properly before HomeKit integration start. | 30 |
Expand All @@ -128,6 +128,9 @@ Complex accessories require a tag on a Group Item indicating the accessory type,
A HomeKit accessory has mandatory and optional characteristics (listed below in the table).
The mapping between openHAB items and HomeKit accessory and characteristics is done by means of [metadata](https://www.openhab.org/docs/concepts/items.html#item-metadata)

If the first word of the item name match the room name in home app, home app will hide it.
E.g. item with the name "Kitchen Light" will be shown in "Kitchen" room as "Light". This is recommended naming convention for HomeKit items and rooms.

### UI based Configuration

In order to add metadata to an item:
Expand Down Expand Up @@ -724,16 +727,6 @@ String cooler_target_mode "Cooler Target Mode" (gCooler)
Number cooler_cool_thrs "Cooler Cool Threshold Temp [%.1f C]" (gCooler) {homekit="CoolingThresholdTemperature" [minValue=10.5, maxValue=50]}
Number cooler_heat_thrs "Cooler Heat Threshold Temp [%.1f C]" (gCooler) {homekit="HeatingThresholdTemperature" [minValue=0.5, maxValue=20]}
```


## Common Problems

**openHAB HomeKit hub shows up when I manually scan for devices, but Home app reports "can't connect to device"**

If you see this error in the Home app, and don't see any log messages, it could be because your IP address in the `networkInterface` setting is misconfigured.
The openHAB HomeKit hub is advertised via mDNS.
If you register an IP address that isn't reachable from your phone (such as `localhost`, `0.0.0.0`, `127.0.0.1`, etc.), then Home will be unable to reach openHAB.

## Additional Notes

HomeKit allows only a single pairing to be established with the bridge.
Expand Down Expand Up @@ -765,3 +758,29 @@ openhab> log:tail io.github.hapjava
`openhab:homekit list` - list all HomeKit accessories currently advertised to the HomeKit clients.

`openhab:homekit show <accessory_id | name>` - print additional details of the accessories which partially match provided ID or name.

## Troubleshooting

### openHAB is not listed in home app
if you don't see openHAB in the home app, probably multicast DNS (mDNS) traffic is not routed correctly from openHAB to home app device or openHAB is already in paired state.
You can verify this with [Discovery DNS iOS app](https://apps.apple.com/us/app/discovery-dns-sd-browser/id305441017) as follow:

- install discovery dns app from app store
- start discovery app
- find `_hap._tcp` in the list of service types
- if you don't find _hap._tcp on the list, probably the traffic is blocked.
- to confirm this, check whether you can find _openhab-server._tcp. if you don't see it as well, traffic is blocked. check your network router/firewall settings.
- if you found _hap._tcp, open it. you should see the name of your openHAB HomeKit bridge (default name is openHAB)

![discovery_hap_list.png](doc/discovery_hap_list.png)

- if you don't see openHAB bridge name, the traffic is blocked
- if you see openHAB HomeKit bridge, open it

![discovery_openhab_details.png](doc/discovery_openhab_details.png)

- verify the IP address. it must be the IP address of your openHAB server, if not, set the correct IP address using `networkInterface` settings
- verify the flag "sf".
- if sf is equal 1, openHAB is accepting pairing from new iOS device.
- if sf is equal 0 (as on screenshot), openHAB is already paired and does not accept any new pairing request. you can reset pairing using `openhab:homekit clearPairings` command in karaf console.
- if you see openHAB bridge and sf is equal 1 but you dont see openHAB in home app, probably you home app still think it is already paired with openHAB. remove your home from home app and restart iOS device.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.jmdns.JmDNS;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.common.ThreadPoolManager;
import org.openhab.core.config.core.ConfigurableService;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.io.transport.mdns.MDNSClient;
import org.openhab.core.items.ItemRegistry;
import org.openhab.core.items.MetadataRegistry;
import org.openhab.core.net.NetworkAddressService;
Expand Down Expand Up @@ -69,6 +72,8 @@ public class HomekitImpl implements Homekit {
private @Nullable InetAddress networkInterface;
private @Nullable HomekitServer homekitServer;
private @Nullable HomekitRoot bridge;
private MDNSClient mdnsClient;

private final HomekitChangeListener changeListener;

private final ScheduledExecutorService scheduler = ThreadPoolManager
Expand All @@ -77,11 +82,12 @@ public class HomekitImpl implements Homekit {
@Activate
public HomekitImpl(@Reference StorageService storageService, @Reference ItemRegistry itemRegistry,
@Reference NetworkAddressService networkAddressService, @Reference MetadataRegistry metadataRegistry,
@Reference ConfigurationAdmin configAdmin, Map<String, Object> properties)
@Reference ConfigurationAdmin configAdmin, @Reference MDNSClient mdnsClient, Map<String, Object> properties)
throws IOException, InvalidAlgorithmParameterException {
this.networkAddressService = networkAddressService;
this.configAdmin = configAdmin;
this.settings = processConfig(properties);
this.mdnsClient = mdnsClient;
this.changeListener = new HomekitChangeListener(itemRegistry, settings, metadataRegistry, storageService);
try {
authInfo = new HomekitAuthInfoImpl(storageService.getStorage(HomekitAuthInfoImpl.STORAGE_KEY), settings.pin,
Expand Down Expand Up @@ -199,8 +205,24 @@ private void startBridge() throws IOException {

private void startHomekitServer() throws IOException {
if (homekitServer == null) {
networkInterface = InetAddress.getByName(settings.networkInterface);
homekitServer = new HomekitServer(networkInterface, settings.port);
if ((settings.networkInterface == null) || (settings.networkInterface.isEmpty())) {
logger.trace(
"No IP address configured in homekit settings. HomeKit will use the first configured address of openHAB");
homekitServer = new HomekitServer(mdnsClient.getClientInstances().iterator().next(), settings.port);
} else {
networkInterface = InetAddress.getByName(settings.networkInterface);
for (JmDNS mdns : mdnsClient.getClientInstances()) {
if (mdns.getInetAddress().equals(networkInterface)) {
logger.trace("suitable mDNS client for IP {} found. Reusing it.", networkInterface);
homekitServer = new HomekitServer(mdns, settings.port);
}
}
if (homekitServer == null) {
logger.trace("Not suitable mDNS client fpr IP {} found. Create new mDNS instance.",
networkInterface);
homekitServer = new HomekitServer(networkInterface, settings.port);
}
}
startBridge();
} else {
logger.warn("trying to start HomeKit server but it is already initialized");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ public class HomekitSettings {
public String qrCode;
public int startDelay = 30;
public boolean useFahrenheitTemperature = false;
public double minimumTemperature = -100;
public double maximumTemperature = 100;
public String thermostatTargetModeHeat = "HeatOn";
public String thermostatTargetModeCool = "CoolOn";
public String thermostatTargetModeAuto = "Auto";
Expand All @@ -53,11 +51,6 @@ public class HomekitSettings {
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(maximumTemperature);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(minimumTemperature);
result = prime * result + (int) (temp ^ (temp >>> 32));
result = prime * result + ((pin == null) ? 0 : pin.hashCode());
result = prime * result + ((setupId == null) ? 0 : setupId.hashCode());
result = prime * result + port;
Expand All @@ -81,12 +74,6 @@ public boolean equals(Object obj) {
return false;
}
HomekitSettings other = (HomekitSettings) obj;
if (Double.doubleToLongBits(maximumTemperature) != Double.doubleToLongBits(other.maximumTemperature)) {
return false;
}
if (Double.doubleToLongBits(minimumTemperature) != Double.doubleToLongBits(other.minimumTemperature)) {
return false;
}
if (pin == null) {
if (other.pin != null) {
return false;
Expand Down

0 comments on commit 5254b0d

Please sign in to comment.