Skip to content

Commit

Permalink
Add support for discovering devices by MacOS UUID
Browse files Browse the repository at this point in the history
  • Loading branch information
hannseman committed Jun 24, 2018
1 parent b820031 commit a303ae5
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 4 deletions.
8 changes: 8 additions & 0 deletions README.md
Expand Up @@ -84,6 +84,14 @@ Update your Homebridge `config.json` and specify the `address` key:

Note that this step is also required when running [Mi Flora](https://xiaomi-mi.com/sockets-and-sensors/xiaomi-huahuacaocao-flower-care-smart-monitor/) devices in the same location as they use the same protocol and their data will be intercepted by this plugin.

#### MacOS

On MacOS `hcitool` can't be used since MacOS does not provide a way to read the MAC-address of a BLE device.
Instead MacOS assigns a device unique identifier for each BLE device in the format of `5C61F8CE-9F0B-4371-B996-5C9AE0E0D14B`.
This identifier can be found using iOS apps like [nRF Connect](https://itunes.apple.com/us/app/nrf-connect/id1054362403)
or MacOS tools like [Bluetooth Explorer](https://developer.apple.com/bluetooth/). Use this identifier as `address` in the configuration file.


### Timeout
If the accessory has not received an updated value from the sensor within the specified timeout it will inform Homekit
that the accessory is not responsive by returning an error until it receives an updated value.
Expand Down
8 changes: 6 additions & 2 deletions lib/scanner.js
Expand Up @@ -38,7 +38,7 @@ class Scanner extends EventEmitter {
address
} = peripheral;

if (!this.isValidAddress(address)) {
if (!this.isValidAddress(address) && !this.isValidAddress(id)) {
return;
}

Expand Down Expand Up @@ -99,10 +99,14 @@ class Scanner extends EventEmitter {
}
}

cleanAddress(address) {
return address.toLowerCase().replace(/[:-]/g, "");
}

isValidAddress(address) {
return (
this.address == null ||
this.address.toLowerCase() === address.toLowerCase()
this.cleanAddress(this.address) === this.cleanAddress(address)
);
}

Expand Down
9 changes: 7 additions & 2 deletions test/mocks.js
Expand Up @@ -32,8 +32,13 @@ class NobleMock extends EventEmitter {
}

class PeripheralMock {
constructor(event, address = "4c:65:a8:d0:ae:64", uuid = "fe95") {
this.id = "4c65a8d0ae65";
constructor(
event,
address = "4c:65:a8:d0:ae:64",
id = "4c65a8d0ae65",
uuid = "fe95"
) {
this.id = id;
this.address = address;
this.rssi = -67;
this.advertisement = {
Expand Down
35 changes: 35 additions & 0 deletions test/scanner.test.js
Expand Up @@ -108,12 +108,37 @@ describe("scanner", () => {
assert(eventSpy.calledWith(21.7));
});

it("should discover peripherals with matching id", () => {
const eventSpy = sinon.spy();
const uuid = "f4f7f9907f7c4d5a8c9f8c264e9baa7d";
const wrongPeripheral = new PeripheralMock(
sensorData.temperatureAndHumidity,
"unknown",
"a09e0b69-0742-4353-b7e7-653fa4f2993b"
);
const correctPeripheral = new PeripheralMock(
sensorData.temperatureAndHumidity,
"unknown",
uuid
);
const scanner = new Scanner(
mockLogger,
"f4f7f990-7f7c-4d5a-8c9f-8c264e9baa7d"
);
scanner.on("temperatureChange", eventSpy);
nobleMock.emit("discover", wrongPeripheral);
assert(eventSpy.notCalled);
nobleMock.emit("discover", correctPeripheral);
assert(eventSpy.calledWith(21.7));
});

it("should discard wrongs uuids", () => {
const eventSpy = sinon.spy();
this.scanner.on("temperatureChange", eventSpy);
const peripheral = new PeripheralMock(
sensorData.temperature,
"123",
"123",
"deadbeef"
);
nobleMock.emit("discover", peripheral);
Expand Down Expand Up @@ -190,4 +215,14 @@ describe("scanner", () => {
assert(spyInfoLogger.called);
spyInfoLogger.restore();
});

it("should clean addresses", () => {
const address = "de:ad:be:ef";
const scanner = new Scanner(mockLogger, address);
assert.deepEqual(scanner.cleanAddress(scanner.address), "deadbeef");
assert.deepEqual(
scanner.cleanAddress("F4F7F990-7F7C-4D5A-8C9F-8C264E9BAA7D"),
"f4f7f9907f7c4d5a8c9f8c264e9baa7d"
);
});
});

0 comments on commit a303ae5

Please sign in to comment.