Skip to content

Commit

Permalink
Merge pull request #71 from NRCHKB/dev
Browse files Browse the repository at this point in the history
Release 0.6.1

- Fixes for #22 and #66 
- Some renaming to our new organisation name
- reintroduced debug mode for our module, run with DEBUG=NRCHKB node-red
- some small changes to process of finding Parent Service as Linked Service
  • Loading branch information
Shaquu authored Mar 20, 2019
2 parents 130b0f8 + 2655ecf commit 4e31fa4
Show file tree
Hide file tree
Showing 13 changed files with 182 additions and 100 deletions.
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

## Intro

Node-RED nodes to simulate Apple HomeKit devices. The goal is to emulate native HomeKit devices as closely as possible. We rely on community support - please read throught the README for the basics then head over to the [wiki page](https://github.com/node-red-contrib-homekit/node-red-contrib-homekit-bridged/wiki) for details and examples. If you're still stuck please open an issue, we are glad to help.
Node-RED nodes to simulate Apple HomeKit devices. The goal is to emulate native HomeKit devices as closely as possible. We rely on community support - please read throught the README for the basics then head over to the [wiki page](https://github.com/NRCHKB/node-red-contrib-homekit-bridged/wiki) for details and examples. If you're still stuck please open an issue, we are glad to help.

These nodes allow the creation of fully customizable accessories for use in Apple's Home app on iOS, Watch OS, and Mac OS. If you can get it in Node-RED, you can get it in HomeKit. The goal of the project is to create a platform where official HomeKit hardware can be emulated as closely as possible through node red.

Expand Down Expand Up @@ -49,16 +49,16 @@ All accessories behind a bridge noded are then automatically added by iOS.
### Service

The Service node represents the single device you want to control or query.
Every service node can be _Parent_ or _Linked_. Each Parent service creates an individual accessory in the Home app. Linked services add additional features to their Parent service - for example adding battery status to a motion detector. See examples in the [wiki](https://github.com/oliverrahner/node-red-contrib-homekit-bridged/wiki) for details.
Every service node can be _Parent_ or _Linked_. Each Parent service creates an individual accessory in the Home app. Linked services add additional features to their Parent service - for example adding battery status to a motion detector. See examples in the [wiki](https://github.com/NRCHKB/node-red-contrib-homekit-bridged/wiki) for details.

- **Service Hierarchy**: Whether the service is _Parent_ or _Linked_.
- **Bridge**: On what bridge to host this Service and its Accessory.
- **Parent Service**: Which Parent service the Linked service will be connected to.
- **Service**: Choose the type of Service from the list. [Services wiki](https://github.com/oliverrahner/node-red-contrib-homekit-bridged/wiki/Services)
- **Service**: Choose the type of Service from the list. [Services wiki](https://github.com/NRCHKB/node-red-contrib-homekit-bridged/wiki/Services)
- **Topic**: An optional property that can be configured in the node or, if left blank, can be set by msg.topic.
- **Manufacturer, Model, Serial Number**: Can be anything you want.
- **Name**: If you intend to simulate a rocket, then why don't you call it _Rocket_.
- **Characteristic Properties**: Customise the properties of characteristics. [Characteristics wiki](https://github.com/oliverrahner/node-red-contrib-homekit-bridged/wiki/Characteristics)
- **Characteristic Properties**: Customise the properties of characteristics. [Characteristics wiki](https://github.com/NRCHKB/node-red-contrib-homekit-bridged/wiki/Characteristics)

## Input Messages

Expand All @@ -81,7 +81,7 @@ Output messages are in the same format as input messages. They are emitted from

## Supported Types

The following is a list of _Services_ that are currently supported. Check for more details on [the wiki](https://github.com/oliverrahner/node-red-contrib-homekit-bridged/wiki/Services). If you encounter problems with any of them please file an Issue.
The following is a list of _Services_ that are currently supported. Check for more details on [the wiki](https://github.com/NRCHKB/node-red-contrib-homekit-bridged/wiki/Services). If you encounter problems with any of them please file an Issue.

- Air Quality Sensor
- Battery Service
Expand Down Expand Up @@ -157,16 +157,16 @@ The Topic parameter can be used to filter incoming messages, making it possible

#### How can I get started?

Our [wiki page](https://github.com/oliverrahner/node-red-contrib-homekit-bridged/wiki) has a growing list of examples and explanations of how to use many features of these nodes. After you've gone through the wiki page and you are still having questions, please open an issue.
Our [wiki page](https://github.com/NRCHKB/node-red-contrib-homekit-bridged/wiki) has a growing list of examples and explanations of how to use many features of these nodes. After you've gone through the wiki page and you are still having questions, please open an issue.

#### How can I upgrade from the non-bridged node-red-contrib-homekit?

[How to upgrade from node-red-homekit](https://github.com/oliverrahner/node-red-contrib-homekit-bridged/wiki/Upgrade-Information)
[How to upgrade from node-red-homekit](https://github.com/NRCHKB/node-red-contrib-homekit-bridged/wiki/Upgrade-Information)

#### How can I generate Debug logs?

Stop your node-red instance and start it again using the following command:
`DEBUG=Accessory,HAPServer,EventedHTTPServer node-red`
`DEBUG=NRCHKB,Accessory,HAPServer,EventedHTTPServer node-red`

This should output detailed information regarding everything in the homekit context.

Expand All @@ -187,11 +187,11 @@ This will filter out all messages with their payload property hap.context not se

## Contributors

#### Big thanks to [all who have contributed to the project](https://github.com/node-red-contrib-homekit/node-red-contrib-homekit-bridged/graphs/contributors).
#### Big thanks to [all who have contributed to the project](https://github.com/NRCHKB/node-red-contrib-homekit-bridged/graphs/contributors).

[Shaq](https://github.com/Shaquu) - leading the current efforts to fix bugs and add features

[Oliver Rahner](https://github.com/oliverrahner) - reworked the code to add bridged mode - [read his story](https://github.com/node-red-contrib-homekit/node-red-contrib-homekit-bridged/wiki/Credits#oliver-rahner-explains-his-work)
[Oliver Rahner](https://github.com/oliverrahner) - reworked the code to add bridged mode - [read his story](https://github.com/NRCHKB/node-red-contrib-homekit-bridged/wiki/Credits#oliver-rahner-explains-his-work)

[Marius Schmeding](https://github.com/mschm/node-red-contrib-homekit) - original implementation of HAP-NodeJS into Node-RED

Expand Down
21 changes: 16 additions & 5 deletions lib/HAPBridgeNode.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
module.exports = function(RED) {
const debug = require("debug")("NRCHKB");
const HapNodeJS = require("hap-nodejs");
const Bridge = HapNodeJS.Bridge;
const Accessory = HapNodeJS.Accessory;
Expand All @@ -7,14 +8,15 @@ module.exports = function(RED) {
const uuid = HapNodeJS.uuid;

const MdnsUtils = require("./utils/MdnsUtils.js")();
const ServerUtils = require("./utils/ServerUtils.js")();

const init = function (config) {
RED.nodes.createNode(this, config);

const self = this;

this.name = config.bridgeName;
this.debug("Setting name to " + config.bridgeName);
debug("Setting name to " + config.bridgeName);

this.pinCode = config.pinCode;
this.port = config.port;
Expand Down Expand Up @@ -61,7 +63,7 @@ module.exports = function(RED) {
this.bridgeUsername = macify(this.id);
const bridgeUUID = uuid.generate(this.id);

this.debug(
debug(
"Creating Bridge with name '" +
this.name +
"' and UUID '" +
Expand All @@ -72,7 +74,7 @@ module.exports = function(RED) {
let bridge = new Bridge(this.name, bridgeUUID);

this.publish = function () {
self.debug(
debug(
"publishing bridge with name '" +
self.name +
"', pin code '" +
Expand All @@ -93,6 +95,9 @@ module.exports = function(RED) {
self.allowInsecureRequest
);

bridge._server.removeAllListeners("unpair");
bridge._server.on("unpair", ServerUtils.handleUnpair.bind(bridge));

self.published = true;
};

Expand All @@ -104,13 +109,19 @@ module.exports = function(RED) {
// This node is being restarted
bridge.unpublish();
bridge = null;
this.published = false;
self.published = false;
}

done();
});

bridge.on("identify", function(paired, callback) {
self.debug("Identify called on Bridge " + self.name);
if (paired) {
debug("Identify called on paired Bridge " + self.name);
} else {
debug("Identify called on unpaired Bridge " + self.name);
}

callback();
});

Expand Down
37 changes: 29 additions & 8 deletions lib/HAPServiceNode.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
module.exports = function(RED) {
const debug = require("debug")("NRCHKB");
const HapNodeJS = require("hap-nodejs");
const Accessory = HapNodeJS.Accessory;
const Service = HapNodeJS.Service;
Expand All @@ -12,22 +13,42 @@ module.exports = function(RED) {
const isParentNode = typeof config.isParent === "boolean" ? config.isParent : true;

if (isParentNode) {
debug("Starting Parent Service " + config.name);
configure(this, config);
} else {
waitForParentAndConfigure(this, config);
waitForParent(this, config)
.then(() => {
debug("Starting Linked Service " + config.name);
configure(this, config);
})
.catch(e => {
this.status({
fill: "red",
shape: "ring",
text: "Error while starting Linked Service"
});

this.error("Error while starting Linked Service " + config.name + ": ", e);
});
}
};

async function waitForParentAndConfigure (node, config) {
return new Promise(resolve => {
(function waitForParent(){
function waitForParent (node, config) {
return new Promise((resolve, reject) => {
node.status({
fill: "yellow",
shape: "ring",
text: "Waiting for Parent Service"
});

const checkAndWait = () => {
if (RED.nodes.getNode(config.parentService)){
configure(node, config);
return resolve();
resolve();
} else {
setTimeout(waitForParent, 1000);
setTimeout(checkAndWait, 1000);
}
})();
};
checkAndWait();
});
}

Expand Down
1 change: 1 addition & 0 deletions lib/api.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = function(RED) {
("use strict");
const debug = require("debug")("NRCHKB");
const HapNodeJS = require("hap-nodejs");

// Accessory API
Expand Down
17 changes: 11 additions & 6 deletions lib/utils/AccessoryUtils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = function(node) {
("use strict");
const debug = require("debug")("NRCHKB");
const HapNodeJS = require("hap-nodejs");
const Accessory = HapNodeJS.Accessory;
const Service = HapNodeJS.Service;
Expand All @@ -17,7 +18,7 @@ module.exports = function(node) {
let accessory = null;

// create accessory object
node.debug("Looking for accessory with UUID '" + accessoryInformation.UUID + "'...");
debug("Looking for accessory with UUID '" + accessoryInformation.UUID + "'...");

for (let i in bridge.bridgedAccessories) {
if (!bridge.bridgedAccessories.hasOwnProperty(i)) {
Expand All @@ -30,12 +31,12 @@ module.exports = function(node) {
accessory = existingAccessory;
break;
} else {
node.debug("Accessory with UUID '" + existingAccessory.UUID + "' doesn't match '" + accessoryInformation.UUID + "'");
debug("Accessory with UUID '" + existingAccessory.UUID + "' doesn't match '" + accessoryInformation.UUID + "'");
}
}

if (!accessory) {
node.debug(
debug(
"... didn't find it. Adding new accessory with name '" +
accessoryInformation.name +
"' and UUID '" +
Expand All @@ -45,7 +46,7 @@ module.exports = function(node) {
accessory = new Accessory(accessoryInformation.name, accessoryInformation.UUID);
bridge.addBridgedAccessories([accessory]);
} else {
node.debug("... found it! Updating it.");
debug("... found it! Updating it.");
accessory
.getService(Service.AccessoryInformation)
.setCharacteristic(Characteristic.Name, accessoryInformation.name);
Expand All @@ -58,15 +59,19 @@ module.exports = function(node) {
.setCharacteristic(Characteristic.Model, accessoryInformation.model)
.setCharacteristic(Characteristic.Identify, true);

node.debug(
debug(
"Bridge now has " + bridge.bridgedAccessories.length + " accessories."
);

return accessory;
};

const onIdentify = function(paired, callback) {
node.debug("Identify called on Accessory " + node.accessory.displayName);
if (paired) {
debug("Identify called on paired Accessory " + node.accessory.displayName);
} else {
debug("Identify called on unpaired Accessory " + node.accessory.displayName);
}

let nodes = node.childNodes;

Expand Down
8 changes: 8 additions & 0 deletions lib/utils/BridgeUtils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = function(node) {
("use strict");
const debug = require("debug")("NRCHKB");

// Publish accessory after the service has been added
// BUT ONLY after 5 seconds with no new service have passed
Expand All @@ -16,8 +17,15 @@ module.exports = function(node) {
function () {
try {
node.bridgeNode.publish();
debug("Bridge [" + node.bridgeNode.id + "] published");
} catch(err) {
node.error("Bridge [" + node.bridgeNode.id + "] publish failed due to: " + err);

node.status({
fill: "red",
shape: "ring",
text: "Error while publishing Bridge"
});
}
},
5000
Expand Down
1 change: 1 addition & 0 deletions lib/utils/CharacteristicUtils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = function(node) {
("use strict");
const debug = require("debug")("NRCHKB");
const HapNodeJS = require("hap-nodejs");
const Characteristic = HapNodeJS.Characteristic;

Expand Down
2 changes: 1 addition & 1 deletion lib/utils/MdnsUtils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module.exports = function() {
("use strict");

const debug = require("debug")("NRCHKB");
const net = require("net");
const os = require("os");
let availableInterfaces;
Expand Down
23 changes: 23 additions & 0 deletions lib/utils/ServerUtils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module.exports = function() {
("use strict");
const debug = require("debug")("NRCHKB");

const handleUnpair = function(username, callback) {
debug("[%s] Unpairing with client %s", this.displayName, username);

// Unpair
this._accessoryInfo.removePairedClient(username);
this._accessoryInfo.save();

// update our advertisement so it can pick up on the paired status of AccessoryInfo
if (this._advertiser){
this._advertiser.updateAdvertisement();
}

callback();
};

return {
handleUnpair: handleUnpair
};
};
Loading

0 comments on commit 4e31fa4

Please sign in to comment.