The goal of this package is to provide a complete implementation of the Homekit Accessory Protocol, to build your DIY accessories, or provide a bridge for non-HAP devices.
- Persistent configuration
- Pair by scanning QR code (WWDC 2017)
- Write custom services and characteristics
- Linux support
Install libsodium (used for Curve25519 and Ed25519):
brew install libsodium
And then build the project itself:
swift build -c release
Install dependencies:
sudo apt install openssl libssl-dev libsodium-dev libcurl4-openssl-dev
Make sure you have libsodium 1.0.9 or above. Ubuntu 16.10 or later suffices. Otherwise you have to compile and install libsodium from source;
wget https://download.libsodium.org/libsodium/releases/libsodium-1.0.12.tar.gz
tar xzf libsodium-1.0.12.tar.gz
cd libsodium-1.0.12
./configure
make && make check
sudo make install
sudo ldconfig
And then build the project itself:
swift build -c release
Run swift build
to compile and .build/debug/hap-server
to run. Modify Sources/hap-server/main.swift
to include your own accessories.
On Mac OS, you can debug using XCode by running the command swift package generate-xcodeproj
and the opening the resulting HAP.xcodeproj
project. Select the hap-server
target to execute.
The following code snippet how you would model a fictious accessory representing a mobile power bank.
class PowerBankAccessory: Accessory {
let service = PowerBankService()
init(info: Service.Info) {
super.init(info: info, type: .outlet, services: [service])
}
}
class PowerBankService: Service {
public let on = GenericCharacteristic<Bool>(
type: .on,
value: false)
public let inUse = GenericCharacteristic<Bool>(
type: .outletInUse,
value: true,
permissions: [.read, .events])
public let batteryLevel = GenericCharacteristic<Double>(
type: .batteryLevel,
value: 100,
permissions: [.read, .events])
init() {
super.init(type: .outlet, characteristics: [
AnyCharacteristic(on),
AnyCharacteristic(inUse),
AnyCharacteristic(batteryLevel)
])
}
}
There is some support on Linux. It uses my own implementation of NetService for multicast DNS (mDNS). However this implementation might be working for some use-cases, it isn't production grade. Patches welcome. Another solution would be to switch to using Avahi instead.
CommonCrypto has been replaced with the portable BlueCryptor; it uses CommonCrypto on Apple platforms and OpenSSL on Linux.
A high-level overview of the objects involved are shown in the diagram below. The terminology of HAP (Device, Accessory, Service, Characteristic) is followed for ease of understanding.
+------------+
| NetService |
+------------+
|
|delegate
v
+--------+ 1 0…1 +--------+
| Device |-----------| Server |
+--------+\ +--------+
|1 -\notify |1
|* -\ |*
+-----------+ -\ +------------+ 1 0…1 +---------------+
| Accessory | ->| Connection |---------| Cryptographer |
+-----------+ +------------+ +---------------+
|1
|*
+---------+
| Service |
+---------+
|1
|*
+----------------+
| Characteristic |
+----------------+
Certain tests involve crypto, which can be a bit slow in debug builds. Best to run the tests with a release build, like this:
swift test -c release -Xswiftc -enable-testing
Currently GenericCharacteristic<T>
is used, to allow for user-defined value types. As Swift requires homegenous arrays, a protocol AnyCharacteristic
is introduced. I don't like the resulting implementation as the generics result in a cascade of workarounds (boxing + ObjectIdentifier()
).
This library was written by Bouke Haarsma and contributors.