Skip to content

vojtamolda/homebridge-bluetooth

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

42 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

homebridge-bluetooth

NPM version

Homebridge plugin for exposing services and characteristics of nearby Bluetooth Low Energy (BLE) peripherals as HomeKit accesories. Ideal for wireless DIY home automation projects if you'd like to control them comfortably with Siri on any Apple device.

Homebridge runs on top of Node.js server and is an open-source implementation of the Apple HomeKit protocol. HomeKit provides the API between your Apple device (i.e. Watch) and your home automation server (i.e. Raspberry Pi). This Homebridge plugin relays the communication from the home automation server to the BLE peripheral device (i.e. Arduino 101). Take a peek into the examples folder for inspiration.

Installation

Make sure your systems matches the prerequisites. You need to have a C compiler, Node.js server and if you're running on Linux the libbluez-dev library.

Install Homebridge & Noble

Homebridge is a lightweight framework built on top of Node.js server that provides the HomeKit bridge for your Apple devices to connect to. Noble is BLE central module library for Node.js that abstracts away intricacies of each OS BLE stack implementation and provides a nice universal high-level API.

[sudo] npm install -g noble
[sudo] npm install -g --unsafe-perm homebridge node-gyp
[sudo] npm install -g homebridge-bluetooth

Note Depending on your privileges -g flag may need root permissions to install to the global npm module directory.

Configure Homebridge

Homebridge is setup via config.json file sitting in the ~/.homebridge/ directory. The example config included in the repository has lots of comments and is a good starting point. Each BLE peripheral device is uniquely identified by it's address. Services and characteristics are identified by UUID. Also, each of the examples comes with it's own config.json file.

The easiest way to find the address of a BLE device is to start the plugin with a random/default address and then check the output for Ignored | MyDevice - 01:23:45:67:89:ab message. Alternatively you can run [sudo] hcitool lescan to discover available BLE devices.

Mapping of services and characteristics from Bluetooth to HomeKit relies on two things - matching read/write/nofity permissions and matching data type. To see what is available, take a look at the very long list here. Services are towards the bottom of the file. Each characteristic has pre-defined permissions that represent the expected way to use it - i.e. it doesn't make sense to write (set) the current temperature. These permissions must match the corresponding permissions of the Bluetooth characteristic. All data are assumed to use little endian encoding for multi-byte values.

The following table summarizes permission matching for a very popular BLEPeripheral library that can run on most Arduino boards:

HomeKit Characteristic.Perms[...] BLEPeripheral BLECharacteristic(...)
READ BLEWrite
WRITE BLERead
NOTIFY BLENotify

Similar to permissions, matching of the exchanged data type for BLEPeripheral is summarized here:

HomeKit Characteristic.Formats[...] BLEPeripheral BLETypedCharacteristic<...>
BOOL BLECharCharacteristic
INT BLEIntCharacteristic
FLOAT BLEFloatCharacteristic
STRING BLECharacteristic
UINT8 BLEUnsignedCharCharacteristic
UINT16 BLEUnsignedShortCharacteristic
UINT32 BLEUnsignedIntCharacteristic
UINT64 BLEUnsignedLongCharacteristic

For instance if you'd like create a HomeKit thermometer, you have to implement the TemperatureSensor service. According to the list of available services and characteristics the service has one mandatory characteristic - CurrentTemperature and a handful of optional ones.

The CurrentTemperature characteristic communicates a FLOAT value and needs READ and NOTIFY permissions. Using the BLEPeripheral library, the characteristic would be implemented as:

BLEService temperatureSensorService("SERVICE-UUID-HERE");
BLEFloatCharacteristic currentTemperatureCharacteristic("CHARACTERISTIC-UUID-HERE", BLERead | BLENotify);

The corresponding entry in the config.json file that connects to the characteristic above is:

"services" : [ {
    "name": "The Best HomeKit Thermometer",
    "type": "TemperatureSensor",
    "UUID": "SERVICE-UUID-HERE",
    "characteristics": [ {
        "type": "CurrentTemperature",
        "UUID": "CHARACTERISTIC-UUID-HERE"
    } ]
} ]

Note All UUIDs should be randomly generated to prevent collisions. This page is a good place to get your own.

Run Homebridge

Depending on your privileges, accessing the BLE kernel subsystem may need root permissions.

[sudo] homebridge -D

Note Running with -D turns on additional debugging output that is very helpful for getting addresses and UUIDs of your BLE devices that needs to match with the config.json file.

Note See this section of Noble readme for more details about running without sudo.

Troubleshooting

If you encouter a different problem, please, open an issue.

Home app can't discover any nearby accessories

Make sure the Apple device and the Homebridge server are on the same subnet and connected to the same wifi router.

Sometimes, homebridge server might think that, it has successfully paired with iOS, but iOS doesn't agree. Try to delete the persist/ directory in the ~/.homebridge/ configuration folder. This removes all pairings that normally persist from session to session.

rm -rf ~/.homebridge/persist/

From time to time it looks like iOS ignores HomeKit bridges with username that it has already paired with. Try to change the username in the bridge section of config.json to a new value never used before.

"username": "CC:22:3D:E3:CE:30"  ->  "username": "DD:33:4E:F4:DF:41"

BLE peripheral is discovered, but immediately disconnects

This isssue seems to be happening on some versions of Raspbian running on the Pi 3. Resetting the BLE adapter seems to resolve the issue:

[sudo] hciconfig hci0 reset

Obviously, the solution is not really addressing the core of the problem, but it seems to help.

FAQ

Can I contribute my own example or a new feature?

Sure thing! All contributions are welcome. Just do a pull-request or open a new issue if you see something broken.

Is this thing secure?

No. Not even close. Connection from your Apple device to Homebridge server is encrypted. However, all BLE communication is currently unencrypted and anyone with the right spoofing equipment can listen to it. Moreover, once the attacker has figured out what devices you have, he can also connect to any of your peripherals and control them directly. So don't use this if you're paranoid or if NSA is after you. You wouldn't sleep well.

MFi certified HomeKit BLE encryption uses quite-strong Ed25519 elliptic cypher. BLE has built-in support for encryption, but it seems that Apple has decided to build their own thing as usual. It makes some sense in this case since a lot is at stake - once HomeKit becomes widespread a security bug literally means open doors to your house. Hooray - let's connect billions of unsecured IoT devices to the internet! What could possibly go wrong??

Moreover, from bits and pieces available on the Internet, it seems that Apple has changed the specs several times and caused a lot of trouble for the manufacturers, since slower microprocessors tend to have a hard time doing all the involved encryption math. Initial pairing can take literally minutes. Pairing procedure uses SRP (Secure Remote Password (3072-bit) protocol with an 8-digit code (the number you have to type in when first pairing with Homebridge). After pairing, per session communication always uses unique keys derived by HKDF-SHA-512 and encrypted by the ChaCha20-Poly1305.

Theoretically, one should be able to get rid of the Homebridge 'middle-man' since HomeKit over BLE allows direct connection to any Apple device. While there are many good HomeKit IP stacks around BLE implementations are few and far between. There's only one implementation I'm aware of here, but it can't be easily ported to other boards.

BTW, I think it might be possible to re-write the BLE implementation above with BLEPeripheral library instead of Nordic Semi's SoftDevice to make it run essentially everywhere. If anyone is interested in this project, please, let me know and maybe we can figure a plan and come up with something useful and fun to use.

Implementing a HomeKit over BLE stack correctly requires access to MFi internal documentation, which isn't publicly available, unless you're a registered developer at a company with big $$$. Making BLE accessories is simple, but making them secure seems to be very, very hard.

What are the prerequisites for installation?

Linux (Debian Based, Kernel 3.6 or newer)

A supported BLE (Bluetooth 4.0) USB dongle is required, if your device doesn't have it built-in.

  • Install Node.js

    Node.js is an asynchronous event driven JavaScript server, ideal for building scalable, low-latency network applications. Homebridge is built on top of this server. It is being developed so quickly that package repositories of most distributions contain a very old version. Getting latest from the official website is recommended.

  • Install libbluetooth-dev and libavahi-compat-libdnssd-dev

    These libraries and their dependencies are required by Noble package and provide access to the kernel Bluetooth subsystem.

    sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev libavahi-compat-libdnssd-dev

macOS (10.10 or newer)

Check this link to see if your mac has built-in BLE (Bluetooth 4.0) support. All macs from 2012 and newer are generally fine.

  • Install Node.js

    Node.js is an asynchronous event driven JavaScript server, ideal for building scalable, low-latency network applications. Homebridge is built on top of this server. It is being developed so quickly that package repositories of most distributions contain a very old version. Getting latest from the official website is recommended.

  • Install XCode

    XCode comes with a C compiler that is needed to compile the JavaScript to C bindings required by Noble package.

Windows (8.1 or newer)

Pull request is welcomed here... Both Homebridge and Noble should run on Windows, but I don't have a machine to test.

On what devices was this plugin tested?

Here's a list of testing devices. The list is by no means exhaustive and the plugin will work with many more.

License

This work is licensed under the MIT license. See license for more details.