Skip to content

Commit

Permalink
Cleanup (#388)
Browse files Browse the repository at this point in the history
* option to destroy the server, even when not started

* accessoire: add option to remove all bridged accessories (usefull when updating data)

* option to set default manufacturer/serial/model via env variable

* remove console.log

* linting fixes

* remove console.log and replace with debug

* more linting

* fix typo

* add option to disable save and load data from file

* add possible TODO

* update readme, bump node-persist package, revert non persist option

* cleanup readme

* drop obsolete test files

* cleanup package.json

* bump minor mdns

* review fixes
  • Loading branch information
neophob authored and KhaosT committed Feb 1, 2017
1 parent 1cbf035 commit 2ea9d76
Show file tree
Hide file tree
Showing 25 changed files with 218 additions and 191 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Ignore all differences in line endings
* -crlf
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ HAP-NodeJS is a Node.js implementation of HomeKit Accessory Server.

With this project, you should be able to create your own HomeKit Accessory on Raspberry Pi, Intel Edison or any other platform that can run Node.js :)

The implementation may not 100% follow the HAP MFi Specification since MFi program doesn't allow individual developer to join.
The implementation may not 100% follow the HAP MFi Specification since MFi program doesn't allow individual developer to join.

Remember to run `npm install` before actually running the server.

Expand All @@ -31,6 +31,11 @@ The HAP-NodeJS library uses the [debug](https://github.com/visionmedia/debug) li
DEBUG=* node BridgedCore.js
```

HOMEKIT PROTOCOL
================

Hint: the Homekit Application Protocol (HAP) allows that you can pair a Homekit device with one device. As soon as the Homekit device is paired, its not possible to pair with another iOS device anymore.

API
===

Expand Down Expand Up @@ -60,10 +65,8 @@ Projects based on HAP-NodeJS
============================

* [Homebridge](https://github.com/nfarina/homebridge) - HomeKit support for the impatient - Pluggable HomeKit Bridge. Plugins available for e.g. Pilight, Telldus TDtool, Savant, Netatmo, Open Pixel Control, HomeWizard, Fritz!Box, LG WebOS TV, Home Assistant, HomeMatic and many many more.
* [OpenHAB-HomeKit-Bridge](https://github.com/htreu/OpenHAB-HomeKit-Bridge) - OpenHAB HomeKit Bridge bridges openHAB items to Apple´s HomeKit Accessory Protocol.
* [OpenHAB-HomeKit-Bridge](https://github.com/htreu/OpenHAB-HomeKit-Bridge) - OpenHAB HomeKit Bridge bridges openHAB items to Apple´s HomeKit Accessory Protocol.
* [homekit2mqtt](https://github.com/hobbyquaker/homekit2mqtt) - HomeKit to MQTT bridge.
* [pimatic-hap](https://github.com/michbeck100/pimatic-hap) - Pimatic homekit bridge.
* [node-red-contrib-homekit](https://github.com/mschm/node-red-contrib-homekit) - Node-RED nodes to simulate Apple HomeKit devices.
* [ioBroker.homekit](https://github.com/ioBroker/ioBroker.homekit2) - connect ioBroker to HomeKit.


13 changes: 10 additions & 3 deletions lib/Accessory.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict';

var debug = require('debug')('Accessory');
var crypto = require('crypto');
var inherits = require('util').inherits;
Expand All @@ -13,8 +15,6 @@ var AccessoryInfo = require('./model/AccessoryInfo').AccessoryInfo;
var IdentifierCache = require('./model/IdentifierCache').IdentifierCache;
// var RelayServer = require("./util/relayserver").RelayServer;

'use strict';

module.exports = {
Accessory: Accessory
};
Expand Down Expand Up @@ -305,6 +305,13 @@ Accessory.prototype.removeBridgedAccessories = function(accessories) {
this._updateConfiguration();
}

Accessory.prototype.removeAllBridgedAccessories = function() {
for (var i = this.bridgedAccessories.length - 1; i >= 0; i --) {
this.removeBridgedAccessory(this.bridgedAccessories[i], true);
}
this._updateConfiguration();
}

Accessory.prototype.getCharacteristicByIID = function(iid) {
for (var index in this.services) {
var service = this.services[index];
Expand Down Expand Up @@ -508,7 +515,7 @@ Accessory.prototype.destroy = function() {
}
if (this._advertiser) {
this._advertiser.stopAdvertising();
this._advertiser = undefined;
this._advertiser = undefined;
}
}

Expand Down
75 changes: 39 additions & 36 deletions lib/AccessoryLoader.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
'use strict';

var fs = require('fs');
var path = require('path');
var Accessory = require('./Accessory').Accessory;
var Service = require('./Service').Service;
var Characteristic = require('./Characteristic').Characteristic;
var uuid = require('./util/uuid');
var storage = require('node-persist');
var debug = require('debug')('AccessoryLoader');

module.exports = {
loadDirectory: loadDirectory,
Expand All @@ -19,34 +21,33 @@ module.exports = {
*/

function loadDirectory(dir) {

// exported accessory objects loaded from this dir
var accessories = [];

fs.readdirSync(dir).forEach(function(file) {

// "Accessories" are modules that export a single accessory.
if (file.split('_').pop() === "accessory.js") {
console.log("Parsing accessory: " + file);

if (file.split('_').pop() === 'accessory.js') {
debug('Parsing accessory: %s', file);
var loadedAccessory = require(path.join(dir, file)).accessory;
accessories.push(loadedAccessory);
}
// "Accessory Factories" are modules that export an array of accessories.
else if (file.split('_').pop() === "accfactory.js") {
console.log("Parsing accessory factory: " + file);
else if (file.split('_').pop() === 'accfactory.js') {
debug('Parsing accessory factory: %s', file);

// should return an array of objects { accessory: accessory-json }
var loadedAccessories = require(path.join(dir, file));
accessories = accessories.concat(loadedAccessories);
}
});

// now we need to coerce all accessory objects into instances of Accessory (some or all of them may
// be object-literal JSON-style accessories)
return accessories.map(function(accessory) {
return (accessory instanceof Accessory) ? accessory : parseAccessoryJSON(accessory);
})
});
}

/**
Expand All @@ -58,36 +59,38 @@ function parseAccessoryJSON(json) {

// parse services first so we can extract the accessory name
var services = [];

json.services.forEach(function(serviceJSON) {
var service = parseServiceJSON(serviceJSON);
services.push(service);
});

var displayName = json.displayName;

services.forEach(function(service) {
if (service.UUID == '0000003E-0000-1000-8000-0026BB765291') // Service.AccessoryInformation.UUID
if (service.UUID === '0000003E-0000-1000-8000-0026BB765291') { // Service.AccessoryInformation.UUID
service.characteristics.forEach(function(characteristic) {
if (characteristic.UUID == '00000023-0000-1000-8000-0026BB765291') // Characteristic.Name.UUID
if (characteristic.UUID === '00000023-0000-1000-8000-0026BB765291') {// Characteristic.Name.UUID
displayName = characteristic.value;
}
});
}
});

var accessory = new Accessory(displayName, uuid.generate(displayName));

// create custom properties for "username" and "pincode" for Core.js to find later (if using Core.js)
accessory.username = json.username;
accessory.pincode = json.pincode;

// clear out the default services
accessory.services.length = 0;

// add services
services.forEach(function(service) {
accessory.addService(service);
});

return accessory;
}

Expand All @@ -100,7 +103,7 @@ function parseServiceJSON(json) {
json.characteristics.forEach(function(characteristicJSON) {
var characteristic = parseCharacteristicJSON(characteristicJSON);
characteristics.push(characteristic);
})
});

var displayName = null;

Expand All @@ -109,23 +112,23 @@ function parseServiceJSON(json) {
if (characteristic.UUID == '00000023-0000-1000-8000-0026BB765291') // Characteristic.Name.UUID
displayName = characteristic.value;
});

// Use UUID for "displayName" if necessary, as the JSON structures don't have a value for this
var service = new Service(displayName || serviceUUID, serviceUUID, displayName);

characteristics.forEach(function(characteristic) {
if (characteristic.UUID != '00000023-0000-1000-8000-0026BB765291') // Characteristic.Name.UUID, already present in all Services
service.addCharacteristic(characteristic);
})
});

return service;
}

function parseCharacteristicJSON(json) {
var characteristicUUID = json.cType;

var characteristic = new Characteristic(json.manfDescription || characteristicUUID, characteristicUUID);

// copy simple properties
characteristic.value = json.initialValue;
characteristic.setProps({
Expand All @@ -136,39 +139,39 @@ function parseCharacteristicJSON(json) {
unit: json.unit,
perms: json.perms // example: ["pw","pr","ev"]
});

// monkey-patch this characteristic to add the legacy method `updateValue` which used to exist,
// and that accessory modules had access to via the `onRegister` function. This was the old mechanism
// for communicating state changes about accessories that happened "outside" HomeKit.
characteristic.updateValue = function(value, peer) {
characteristic.setValue(value);
}
};

// monkey-patch legacy "locals" property which used to exist.
characteristic.locals = json.locals;

var updateFunc = json.onUpdate; // optional function(value)
var readFunc = json.onRead; // optional function(callback(value))
var registerFunc = json.onRegister; // optional function

if (updateFunc) {
characteristic.on('set', function(value, callback) {
updateFunc(value);
callback();
});
}

if (readFunc) {
characteristic.on('get', function(callback) {
readFunc(function(value) {
callback(null, value); // old onRead callbacks don't use Error as first param
});
});
}

if (registerFunc) {
registerFunc(characteristic);
}

return characteristic;
}
}
6 changes: 3 additions & 3 deletions lib/Advertiser.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
var mdns = require('mdns');

'use strict';

var mdns = require('mdns');

module.exports = {
Advertiser: Advertiser
};
Expand All @@ -27,7 +27,7 @@ Advertiser.prototype.startAdvertising = function(port) {
if (this._advertisement) {
this.stopAdvertising();
}

var txtRecord = {
md: this.accessoryInfo.displayName,
pv: "1.0",
Expand Down
2 changes: 2 additions & 0 deletions lib/Bridge.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict';

var Accessory = require('./Accessory').Accessory;
var inherits = require('util').inherits;

Expand Down
Loading

0 comments on commit 2ea9d76

Please sign in to comment.