Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[homekit] make use of openHAB mDNS service #10076

Merged
merged 5 commits into from
Feb 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -712,16 +715,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 @@ -753,3 +746,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);
yfre marked this conversation as resolved.
Show resolved Hide resolved
} 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