-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from domapic/release-1.0.0-beta.1
Release 1.0.0 beta.1
- Loading branch information
Showing
42 changed files
with
2,157 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,5 +3,7 @@ | |
.scannerwork | ||
node_modules | ||
npm-debug.log | ||
.homebridge | ||
.test | ||
/.narval | ||
/plugin/package.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,94 @@ | ||
# homebridge-domapic-plugin | ||
Domapic plugin for controlling modules with Apple's HomeKit. | ||
# Homebridge Domapic Plugin | ||
|
||
> Domapic Plugin that automatically register Domapic abilities as Apple's HomeKit accessories (using the awesome [Homebridge][homebridge-url]) | ||
[![Build status][travisci-image]][travisci-url] [![Coverage Status][coveralls-image]][coveralls-url] [![Quality Gate][quality-gate-image]][quality-gate-url] [![js-standard-style][standard-image]][standard-url] | ||
|
||
[![NPM dependencies][npm-dependencies-image]][npm-dependencies-url] [![Last commit][last-commit-image]][last-commit-url] <!--[![Last release][release-image]][release-url] --> | ||
|
||
[![NPM downloads][npm-downloads-image]][npm-downloads-url] [![License][license-image]][license-url] | ||
|
||
## Intro | ||
|
||
The Homebridge Domapic Plugin retrieves the information about modules and abilities registered in your Domapic Controller, and automatically configures and starts an underlay Homebridge server that will act as a bridge between Apple's HomeKit and the Domapic abilities. | ||
|
||
Since Siri supports devices added through HomeKit, this means that **with this plugin you can ask Siri to control your own-made Domapic modules:** | ||
|
||
* _"Siri, turn on the living room light"_ | ||
* _"Siri, open the garage door"_ | ||
* _"Siri, activate my awesome webhook"_ | ||
|
||
> For now, only abilities which have "boolean" data type and have both `state` and `action` are being exposed as HomeKit `Switch` accessories. Soon will be added custom plugin configuration for abilities to [Domapic Controller][domapic-controller-url], and then the user will be able to decide which type of accessory should be each ability, as long as data type is compatible. | ||
## Prerequisites | ||
|
||
[Domapic Controller][domapic-controller-url] has to be installed and running in your LAN. | ||
At least one Domapic module, such as [relay-domapic-module][relay-domapic-module-url] has to be installed and connected to the Controller. | ||
Also read the system requisites of [Homebridge][homebridge-url], which is used underlay to connect with HomeKit. | ||
|
||
## Installation | ||
|
||
```bash | ||
npm i homebridge-domapic-plugin -g | ||
``` | ||
|
||
## Start the plugin | ||
|
||
Start the plugin providing the Controller url and connection token: | ||
|
||
```bash | ||
domapic-homebridge start --controller=http://192.168.1.100:3000 --controllerApiKey=foo-api-key | ||
``` | ||
|
||
The plugin will be started in background using [pm2][pm2-url] | ||
|
||
To display logs, type: | ||
|
||
```bash | ||
domapic-homebridge logs --lines=200 | ||
``` | ||
|
||
Once the Plugin has connected with the Controller, the Homebridge server will be started, and a QR code will be displayed in logs: | ||
|
||
![HomeKit connection QR][homekit-connection-qr-image] | ||
|
||
**Scan this code with your HomeKit app on your iOS device to add your accessories.** | ||
|
||
From now, all modules added to your Controller will automatically be added to your HomeKit app too, and **will be available through Siri**. | ||
|
||
## Options | ||
|
||
The plugin, apart of all common [domapic services options][domapic-service-options-url], provides custom options for configuring it: | ||
|
||
* `homebridgePort` - Number defining the port that Homebridge server will use. | ||
|
||
```bash | ||
domapic-homebridge start --homebridgePort=3200 | ||
``` | ||
|
||
[coveralls-image]: https://coveralls.io/repos/github/domapic/homebridge-domapic-plugin/badge.svg?branch=master | ||
[coveralls-url]: https://coveralls.io/github/domapic/homebridge-domapic-plugin | ||
[travisci-image]: https://travis-ci.org/domapic/homebridge-domapic-plugin.svg?branch=master | ||
[travisci-url]: https://travis-ci.org/domapic/homebridge-domapic-plugin | ||
[last-commit-image]: https://img.shields.io/github/last-commit/domapic/homebridge-domapic-plugin.svg | ||
[last-commit-url]: https://github.com/domapic/homebridge-domapic-plugin/commits | ||
[license-image]: https://img.shields.io/npm/l/homebridge-domapic-plugin.svg | ||
[license-url]: https://github.com/domapic/homebridge-domapic-plugin/blob/master/LICENSE | ||
[npm-downloads-image]: https://img.shields.io/npm/dm/homebridge-domapic-plugin.svg | ||
[npm-downloads-url]: https://www.npmjs.com/package/homebridge-domapic-plugin | ||
[npm-dependencies-image]: https://img.shields.io/david/domapic/homebridge-domapic-plugin.svg | ||
[npm-dependencies-url]: https://david-dm.org/domapic/homebridge-domapic-plugin | ||
[quality-gate-image]: https://sonarcloud.io/api/project_badges/measure?project=homebridge-domapic-plugin&metric=alert_status | ||
[quality-gate-url]: https://sonarcloud.io/dashboard?id=homebridge-domapic-plugin | ||
[release-image]: https://img.shields.io/github/release-date/domapic/homebridge-domapic-plugin.svg | ||
[release-url]: https://github.com/domapic/homebridge-domapic-plugin/releases | ||
[standard-image]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg | ||
[standard-url]: http://standardjs.com/ | ||
|
||
[pm2-url]: http://pm2.keymetrics.io/ | ||
[homebridge-url]: https://www.npmjs.com/package/homebridge | ||
[domapic-controller-url]: https://www.npmjs.com/package/domapic-controller | ||
[relay-domapic-module-url]: https://www.npmjs.com/package/relay-domapic-module | ||
[domapic-service-options-url]: https://github.com/domapic/domapic-service#options | ||
|
||
[homekit-connection-qr-image]: http://domapic.com/assets/homebridge_qr_screenshot.jpg |
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/usr/bin/env node | ||
|
||
require('../lib/cli') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
'use strict' | ||
|
||
const { | ||
LOADING_ABILITIES | ||
} = require('./statics') | ||
|
||
class Abilities { | ||
constructor (dpmcPlugin) { | ||
this.plugin = dpmcPlugin | ||
} | ||
|
||
async get () { | ||
const abilities = await this.plugin.controller.abilities.get() | ||
const services = await this.plugin.controller.services.get() | ||
await this.plugin.tracer.info(LOADING_ABILITIES) | ||
return abilities.map(ability => { | ||
return { | ||
...ability, | ||
service: {...services.find(service => service._id === ability._service)} | ||
} | ||
}) | ||
} | ||
} | ||
|
||
module.exports = Abilities |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
'use strict' | ||
|
||
const path = require('path') | ||
const childProcess = require('child_process') | ||
|
||
const { trim } = require('lodash') | ||
const kill = require('tree-kill') | ||
const fsExtra = require('fs-extra') | ||
|
||
const { | ||
HOMEBRIDGE_LOG, | ||
HOMEBRIDGE_EXITED, | ||
HOMEBRIDGE_STOPPING, | ||
HOMEBRIDGE_STARTING, | ||
PACKAGE_PATH, | ||
HOMEBRIDGE_PATH | ||
} = require('./statics') | ||
|
||
class HomeBridge { | ||
constructor (dpmcPlugin) { | ||
this.tracer = dpmcPlugin.tracer | ||
this.process = null | ||
this.binPath = path.resolve(PACKAGE_PATH, 'node_modules', '.bin', 'homebridge') | ||
this.libPath = path.resolve(__dirname) | ||
this.pluginPath = path.resolve(PACKAGE_PATH, 'plugin') | ||
this.pluginPackageJsonOrigin = path.resolve(this.libPath, 'plugin-package.json') | ||
this.pluginPackageJsonDest = path.resolve(this.pluginPath, 'package.json') | ||
|
||
this.start = this.start.bind(this) | ||
} | ||
|
||
log (data, method) { | ||
let cleanData = trim(data.toString()) | ||
if (cleanData.length) { | ||
if (cleanData.split('\n').length > 1) { | ||
cleanData = `\n${cleanData}` | ||
} | ||
this.tracer[method](`${HOMEBRIDGE_LOG} ${cleanData}`) | ||
} | ||
} | ||
|
||
async writePackageJson () { | ||
await fsExtra.copy(this.pluginPackageJsonOrigin, this.pluginPackageJsonDest) | ||
} | ||
|
||
async start () { | ||
await this.tracer.info(HOMEBRIDGE_STARTING) | ||
await this.writePackageJson() | ||
this.process = childProcess.spawn(this.binPath, [ | ||
'-U', | ||
HOMEBRIDGE_PATH, | ||
'-P', | ||
this.pluginPath | ||
], { | ||
cwd: PACKAGE_PATH, | ||
encoding: 'utf8' | ||
}) | ||
|
||
this.process.stdout.on('data', data => { | ||
this.log(data, 'info') | ||
}) | ||
|
||
this.process.stderr.on('data', data => { | ||
this.log(data, 'error') | ||
}) | ||
|
||
this.process.on('close', code => { | ||
this.log(`${HOMEBRIDGE_EXITED} ${code}`, 'info') | ||
this.process = null | ||
}) | ||
} | ||
|
||
async stop () { | ||
if (this.process) { | ||
await this.tracer.info(HOMEBRIDGE_STOPPING) | ||
return new Promise((resolve, reject) => { | ||
kill(this.process.pid, error => { | ||
if (error) { | ||
reject(error) | ||
} else { | ||
this.process = null | ||
resolve() | ||
} | ||
}) | ||
}) | ||
} | ||
return Promise.resolve() | ||
} | ||
|
||
async restart () { | ||
await this.stop() | ||
return this.start() | ||
} | ||
} | ||
|
||
module.exports = HomeBridge |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
'use strict' | ||
|
||
const path = require('path') | ||
|
||
const fsExtra = require('fs-extra') | ||
const ip = require('ip') | ||
const { cloneDeep } = require('lodash') | ||
|
||
const homebridgeConfig = require('./homebridge-config.json') | ||
|
||
const { | ||
HOMEBRIDGE_PATH, | ||
WRITING_HOMEBRIDGE_CONFIG, | ||
HOMEBRIDGE_PORT, | ||
|
||
ACCESORY_SWITCH_NAME | ||
} = require('./statics') | ||
|
||
class Accesories { | ||
constructor (dpmcPlugin) { | ||
this.configPath = path.resolve(HOMEBRIDGE_PATH, 'config.json') | ||
this.plugin = dpmcPlugin | ||
this.tracer = dpmcPlugin.tracer | ||
} | ||
|
||
async getPluginConnection () { | ||
const pluginConfig = await this.plugin.config.get() | ||
const pluginApiKeys = await this.plugin.storage.get('apiKeys') | ||
const host = pluginConfig.hostName.length ? pluginConfig.hostName : ip.address() | ||
const secureProtocolSuffix = pluginConfig.sslCert ? 's' : '' | ||
const port = pluginConfig.port | ||
|
||
return { | ||
url: `http${secureProtocolSuffix}://${host}:${port}/api/controller/abilities/`, | ||
apiKey: pluginApiKeys.find(apiKey => apiKey.role === 'admin').key | ||
} | ||
} | ||
|
||
getSwitchs (abilities, pluginConnection) { | ||
// Abilities with boolean data that have state and action can be considered as homebridge "switches" | ||
const switchValidAbilities = abilities.filter(ability => ability.type === 'boolean' && ability.state === true && ability.action === true) | ||
return switchValidAbilities.map(ability => { | ||
return { | ||
accessory: ACCESORY_SWITCH_NAME, | ||
apiKey: pluginConnection.apiKey, | ||
bridgeUrl: `${pluginConnection.url}${ability._id}`, | ||
servicePackageName: ability.service.package, | ||
serviceName: ability.service.name, | ||
serviceProcessId: ability.service.processId, | ||
abilityName: ability.name, | ||
name: `${ability.service.name} ${ability.name}` | ||
} | ||
}) | ||
} | ||
|
||
async getAccesories (abilities) { | ||
const pluginConnection = await this.getPluginConnection() | ||
return [ | ||
...this.getSwitchs(abilities, pluginConnection) | ||
] | ||
} | ||
|
||
async write (abilities) { | ||
await this.tracer.info(WRITING_HOMEBRIDGE_CONFIG) | ||
this.config = cloneDeep(homebridgeConfig) | ||
this.config.bridge.port = await this.plugin.config.get(HOMEBRIDGE_PORT) | ||
this.config.accessories = await this.getAccesories(abilities) | ||
await fsExtra.writeJson(this.configPath, this.config, { | ||
spaces: 2 | ||
}) | ||
} | ||
} | ||
|
||
module.exports = Accesories |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
'use strict' | ||
|
||
const { SENDING_ABILITY_ACTION, GETTING_ABILITY_STATE } = require('../statics') | ||
|
||
class AbilitiesBridge { | ||
constructor (dpmcPlugin) { | ||
this.plugin = dpmcPlugin | ||
|
||
this.actionOperationHandler = this.actionOperationHandler.bind(this) | ||
this.stateOperationHandler = this.stateOperationHandler.bind(this) | ||
} | ||
|
||
actionOperationHandler (params, body) { | ||
this.plugin.tracer.debug(`${SENDING_ABILITY_ACTION} ${params.path.id}`, body) | ||
return this.plugin.controller.abilities.action(params.path.id, body) | ||
} | ||
|
||
stateOperationHandler (params) { | ||
this.plugin.tracer.debug(`${GETTING_ABILITY_STATE} ${params.path.id}`) | ||
return this.plugin.controller.abilities.state(params.path.id) | ||
} | ||
|
||
operations () { | ||
return { | ||
abilityActionHandler: { | ||
handler: this.actionOperationHandler | ||
}, | ||
abilityStateHandler: { | ||
handler: this.stateOperationHandler | ||
} | ||
} | ||
} | ||
} | ||
|
||
module.exports = AbilitiesBridge |
Oops, something went wrong.