Skip to content

Commit

Permalink
Generic OSGi console command for HomeKit
Browse files Browse the repository at this point in the history
Removed eclipse specific OSGi console commands and replaced with ESH console command extension.
Added copyright headers.
Updated documentation.
Decreased log levels from info to debug
Signed-off-by: Andy Lintner <[email protected]> (github: beowulfe)
  • Loading branch information
andylintner committed Feb 16, 2016
1 parent 8331cf9 commit 717e522
Show file tree
Hide file tree
Showing 29 changed files with 371 additions and 96 deletions.
5 changes: 3 additions & 2 deletions addons/io/org.openhab.io.homekit/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: HomeKit Binding
Bundle-Name: HomeKit Integration
Bundle-SymbolicName: org.openhab.io.homekit;singleton:=true
Bundle-Vendor: openhab.org
Bundle-Version: 2.0.0.qualifier
Expand All @@ -18,7 +18,6 @@ Import-Package: com.google.common.collect,
javax.jmdns,
org.apache.commons.io,
org.apache.commons.lang.builder,
org.eclipse.osgi.framework.console,
org.eclipse.smarthome.config.core,
org.eclipse.smarthome.core.common.registry,
org.eclipse.smarthome.core.events,
Expand All @@ -30,6 +29,8 @@ Import-Package: com.google.common.collect,
org.eclipse.smarthome.core.thing,
org.eclipse.smarthome.core.thing.binding,
org.eclipse.smarthome.core.types,
org.eclipse.smarthome.io.console,
org.eclipse.smarthome.io.console.extensions,
org.eclipse.smarthome.model.item,
org.osgi.framework,
org.osgi.service.cm,
Expand Down
1 change: 1 addition & 0 deletions addons/io/org.openhab.io.homekit/OSGI-INF/homekit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<!--
Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@
<!--
Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
-->
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="org.openhab.io.homekit.commands">
<implementation class="org.openhab.io.homekit.internal.HomekitCommandProvider"/>
<implementation class="org.openhab.io.homekit.internal.HomekitCommandExtension"/>
<reference bind="setStorageService" cardinality="1..1" interface="org.eclipse.smarthome.core.storage.StorageService" policy="static" name="StorageService"/>
<reference bind="setHomekit" cardinality="1..1" interface="org.openhab.io.homekit.Homekit" policy="static" name="HomekitService"/>
<service>
<provide interface="org.eclipse.osgi.framework.console.CommandProvider" />
<provide interface="org.eclipse.smarthome.io.console.extensions.ConsoleCommandExtension" />
</service>
</scr:component>
20 changes: 10 additions & 10 deletions addons/io/org.openhab.io.homekit/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# HomeKit Add-on

This is an add-on that exposes your OpenHAB system as a bridge over the HomeKit protocol.
This is an add-on that exposes your openHAB system as a bridge over the HomeKit protocol.

Using this add-on, you will be able to control your OpenHAB system using Apple's Siri, or any of a number of HomeKit enabled iOS apps. In order to do so, you will need to make some configuration changes. HomeKit organizes your home into "accessories" that are made up of a number of "characteristics". Some accessory types require a specific set of characteristics.
Using this add-on, you will be able to control your openHAB system using Apple's Siri, or any of a number of HomeKit enabled iOS apps. In order to do so, you will need to make some configuration changes. HomeKit organizes your home into "accessories" that are made up of a number of "characteristics". Some accessory types require a specific set of characteristics.

## Global Configuration
Your first step will be to create the homekit.cfg in your conf/services folder. At the very least, you will need to define a pin number for the bridge. This will be used in iOS when pairing. The pin code is in the form "###-##-###". Requirements beyond this are not clear, and Apple enforces limitations on eligible pins within iOS. At the very least, you cannot use repeating (111-11-111) or sequential (123-45-678) pin codes. If your home network is secure, a good starting point is the pin code used in most sample applications: 031-45-154.
Expand All @@ -20,11 +20,11 @@ org.openhab.homekit:networkInterface=192.168.0.6
```

## Item Configuration
After setting this global configuration, you will need to tag your OpenHAB items in order to map them to the HomeKit ontology. For our purposes, you may consider HomeKit accessories to be of two forms: simple and complex.
After setting this global configuration, you will need to tag your openHAB items in order to map them to the HomeKit ontology. For our purposes, you may consider HomeKit accessories to be of two forms: simple and complex.

A simple accessory will be mapped to a single OpenHAB item (i.e. a Lighbulb is mapped to a Switch, Dimmer, or Color item). A complex accessory will be made up of multiple OpenHAB items (i.e. a Thermostat is composed of Heating and Cooling thresholds, a mode, and current temperature). Complex accessories require a tag on a Group indicating the accessory type, as well as tags on the items it composes.
A simple accessory will be mapped to a single openHAB item (i.e. a Lighbulb is mapped to a Switch, Dimmer, or Color item). A complex accessory will be made up of multiple openHAB items (i.e. a Thermostat is composed of Heating and Cooling thresholds, a mode, and current temperature). Complex accessories require a tag on a Group indicating the accessory type, as well as tags on the items it composes.

A A full list of supported accessory types can be found in the table below.
A full list of supported accessory types can be found in the table below.

<table>
<tr>
Expand Down Expand Up @@ -67,7 +67,7 @@ A A full list of supported accessory types can be found in the table below.
<td>Thermostat</td>
<td>&nbsp;</td>
<td>Group</td>
<td>A thermostat requires all child tags defined below.
<td>A thermostat requires all child tags defined below, with the exception of autoThreshold, which is optional</td>
</tr>
<tr>
<td>&nbsp;</td>
Expand Down Expand Up @@ -97,7 +97,7 @@ A A full list of supported accessory types can be found in the table below.
<td>&nbsp;</td>
<td>autoThreshold</td>
<td>Number</td>
<td>A target temperature that will engage the thermostat's heating and cooling actions as necessary. This only applies when heatingCoolingMode is AUTO</td>
<td>An optional target temperature that will engage the thermostat's heating and cooling actions as necessary. This only applies when heatingCoolingMode is AUTO</td>
</tr>
</table>

Expand All @@ -116,9 +116,9 @@ String DownstairsThermostatHeatingCoolingMode "Downstairs Thermostat Heating/Coo
```

## Additional Notes
HomeKit allows only a single pairing to be established with the bridge. This pairing is normally shared across devices via iCloud. If you need to establish a new pairing, you'll need to clear the existing pairings. To do this, you can issue the command ```clearHomekitPairings``` from the OSGi console.
HomeKit allows only a single pairing to be established with the bridge. This pairing is normally shared across devices via iCloud. If you need to establish a new pairing, you'll need to clear the existing pairings. To do this, you can issue the command ```smarthome homekit clearPairings``` from the OSGi console.

HomeKit requires a unique identifier for each accessory advertised by the bridge. This unique identifier is hashed from the Item's name. For that reason, it is important that the name of your Items exposed to HomeKit remain consistent.

If you encounter any issues with the add-on and need support, it may be important to get detailed logs of your device's communication with OpenHAB. In order to get logs from the underlying library used to implement the HomeKit protocol, add the following to your logback.xml:
```<logger name="com.beowulfe.hap" level="TRACE" />```
If you encounter any issues with the add-on and need support, it may be important to get detailed logs of your device's communication with openHAB. In order to get logs from the underlying library used to implement the HomeKit protocol, enable trace logging using the following command:
```openhab> log:set TRACE com.beowulfe.hap```
21 changes: 21 additions & 0 deletions addons/io/org.openhab.io.homekit/about.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<title>About</title>
</head>
<body lang="EN-US">
<h2>About This Content</h2>
<h3>Third Party Content</h3>
<ul>
<li><a href="https://github.com/beowulfe/HAP-Java">HAP-Java</a>: Homekit protocol implementation, under MIT license</li>
<li><a href="http://connect2id.com/products/nimbus-srp">Nimbusds SRP6A</a>: Secure Remote Password library, dependency of HAP-Java, under Apache 2.0 license</li>
<li><a href="http://netty.io">Netty</a>: Socket handling, dependency of HAP-Java, under Apache 2.0 license</li>
<li><a href="https://jsonp.java.net">JSONP</a>: API and Glassfish implementation for JSR-353, dependency of HAP-Java, under GPLv2 or CDDL 1.1 license</li>
<li><a href="https://github.com/str4d/ed25519-java">ed25519-java</a>: Java implementation of the Edwards-curve Digital Signature Algorithm, dependency of HAP-Java, under CC0 1.0 license</li>
<li><a href="https://www.bouncycastle.org">Bouncycastle</a>: General purpose cryptography library, dependency of HAP-Java, under MIT license</li>
<li><a href="https://code.google.com/archive/p/curve25519-java/">curve25519-java</a>: Java implementation of the Diffie-Hellman key agreement scheme, dependency of HAP_Java, under Apache 2.0 license</li>
</ul>
</body>
</html>
2 changes: 1 addition & 1 deletion addons/io/org.openhab.io.homekit/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<artifactId>org.openhab.io.homekit</artifactId>
<version>2.0.0-SNAPSHOT</version>

<name>HomeKit Binding</name>
<name>HomeKit Integration</name>
<packaging>eclipse-plugin</packaging>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,36 @@
/**
* Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.io.homekit;

import java.io.IOException;

/**
* HomeKit integration API
*
* @author Andy Lintner
*/
public interface Homekit {

/**
* Refreshes the saved authentication info from the underlying storage service. If you
* make changes to the saved authentication info, call this.
*
* @throws IOException
*/
public void refreshAuthInfo() throws IOException;

/**
* HomeKit requests normally require authentication via the pairing mechanism. Use this
* method to bypass that check and enable unauthenticated requests. This can be useful
* when debugging.
*
* @param allow boolean indicating whether or not to allow unauthenticated requests
*/
void allowUnauthenticatedRequests(boolean allow);
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
/**
* Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.io.homekit.internal;

import java.util.HashMap;
Expand Down Expand Up @@ -36,7 +44,7 @@ public void remove(HomekitTaggedItem taggedItem) {
while (i.hasNext()) {
HomekitAccessory accessory = i.next();
if (accessory.getId() == taggedItem.getId()) {
logger.info("Removed accessory " + accessory.getId());
logger.debug("Removed accessory " + accessory.getId());
bridge.removeAccessory(accessory);
i.remove();
}
Expand Down Expand Up @@ -73,12 +81,12 @@ public synchronized void addCharacteristic(HomekitTaggedItem item) {
for (String group : item.getItem().getGroupNames()) {
if (pendingGroupedAccessories.containsKey(group)) {
addCharacteristicToGroup(group, item);
logger.info("Added " + item.getItem().getName() + " to " + group);
logger.debug("Added " + item.getItem().getName() + " to " + group);
return;
}
}
pendingCharacteristics.add(item);
logger.info("Stored " + item.getItem().getName() + " until group is ready");
logger.debug("Stored " + item.getItem().getName() + " until group is ready");
}

private void addCharacteristicToGroup(String group, HomekitTaggedItem item) {
Expand All @@ -96,7 +104,7 @@ private void doAddDevice(HomekitAccessory accessory) {
if (bridge != null) {
bridge.addAccessory(accessory);
}
logger.info("Added accessory " + accessory.getId());
logger.debug("Added accessory " + accessory.getId());
}

}
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
/**
* Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.io.homekit.internal;

import java.util.concurrent.ConcurrentHashMap;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
/**
* Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.io.homekit.internal;

import java.math.BigInteger;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
/**
* Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.io.homekit.internal;

import java.util.Collection;
Expand Down Expand Up @@ -86,17 +94,17 @@ public void stop() {

private void createRootDevice(HomekitTaggedItem taggedItem) {
try {
logger.info("Adding homekit device " + taggedItem.getItem().getName());
logger.debug("Adding homekit device " + taggedItem.getItem().getName());
accessoryRegistry
.addRootDevice(HomekitAccessoryFactory.create(taggedItem, itemRegistry, updater, settings));
logger.info("Added homekit device " + taggedItem.getItem().getName());
logger.debug("Added homekit device " + taggedItem.getItem().getName());
} catch (Exception e) {
logger.error("Could not add device: " + e.getMessage(), e);
}
}

private void createCharacteristic(HomekitTaggedItem taggedItem) {
logger.info("Adding grouped homekit characteristic " + taggedItem.getItem().getName());
logger.debug("Adding grouped homekit characteristic " + taggedItem.getItem().getName());
accessoryRegistry.addCharacteristic(taggedItem);
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
/**
* Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.io.homekit.internal;

import java.util.HashMap;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/**
* Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.io.homekit.internal;

import java.util.Arrays;
import java.util.List;

import org.eclipse.smarthome.core.storage.StorageService;
import org.eclipse.smarthome.io.console.Console;
import org.eclipse.smarthome.io.console.extensions.AbstractConsoleCommandExtension;
import org.openhab.io.homekit.Homekit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Console commands for interacting with the HomeKit integration
*
* @author Andy Lintner
*/
public class HomekitCommandExtension extends AbstractConsoleCommandExtension {

private static final String SUBCMD_CLEAR_PAIRINGS = "clearPairings";
private static final String SUBCMD_ALLOW_UNAUTHENTICATED = "allowUnauthenticated";

private final Logger logger = LoggerFactory.getLogger(HomekitCommandExtension.class);
private StorageService storageService;
private Homekit homekit;

public HomekitCommandExtension() {
super("homekit", "Interact with the HomeKit integration.");
}

@Override
public void execute(String[] args, Console console) {
if (args.length > 0) {
String subCommand = args[0];
switch (subCommand) {
case SUBCMD_CLEAR_PAIRINGS:
clearHomekitPairings(console);
break;

case SUBCMD_ALLOW_UNAUTHENTICATED:
if (args.length > 1) {
boolean allow = Boolean.valueOf(args[1]);
allowUnauthenticatedHomekitRequests(allow, console);
} else {
console.println("true/false is required as an argument");
}
break;

default:
console.println("Unknown command '" + subCommand + "'");
printUsage(console);
break;
}
}
}

@Override
public List<String> getUsages() {
return Arrays.asList(
new String[] { buildCommandUsage(SUBCMD_CLEAR_PAIRINGS, "removes all pairings with Homekit clients"),
buildCommandUsage(SUBCMD_ALLOW_UNAUTHENTICATED + " <boolean>",
"enables or disables unauthenticated access to facilitate debugging") });
}

public void setStorageService(StorageService storageService) {
this.storageService = storageService;
}

public void setHomekit(Homekit homekit) {
this.homekit = homekit;
}

private void clearHomekitPairings(Console console) {
try {
new HomekitAuthInfoImpl(storageService, null).clear();
homekit.refreshAuthInfo();
console.println("Cleared homekit pairings");
} catch (Exception e) {
logger.error("Could not clear homekit pairings", e);
}
}

private void allowUnauthenticatedHomekitRequests(boolean allow, Console console) {
homekit.allowUnauthenticatedRequests(allow);
console.println((allow ? "Enabled " : "Disabled ") + "unauthenticated homekit access");
}

}
Loading

0 comments on commit 717e522

Please sign in to comment.