-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
293 additions
and
1 deletion.
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 |
---|---|---|
@@ -0,0 +1,3 @@ | ||
language: node_js | ||
node_js: | ||
- "4" |
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,5 @@ | ||
# Release History | ||
|
||
|
||
* 20160905, V0.9.0 | ||
* Initial Version |
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,70 @@ | ||
# pimatic-amazing-dash-button | ||
A pimatic plugin for Amazon's dash-buttons | ||
|
||
[![Npm Version](https://badge.fury.io/js/pimatic-amazing-dash-button.svg)](http://badge.fury.io/js/pimatic-amazing-dash-button) | ||
[![Build Status](https://travis-ci.org/mwittig/pimatic-amazing-dash-button.svg?branch=master)](https://travis-ci.org/mwittig/pimatic-amazing-dash-button) | ||
[![Dependency Status](https://david-dm.org/mwittig/pimatic-amazing-dash-button.svg)](https://david-dm.org/mwittig/pimatic-amazing-dash-button) | ||
|
||
A pimatic plugin for Amazon's dash-buttons. It is a pretty light-weight implementation which uses a `ContactSensor` | ||
device abstraction for the dash-button. Auto-discovery of dash-buttons is supported. | ||
|
||
The plugin sniffs for ARP probes which will be sent out by a dash-button when the | ||
button is pressed. The plugin is based on [cap](https://www.npmjs.com/package/cap), a | ||
cross-platform binding for performing packet capturing with node.js. It can be used on *nix and Windows systems. | ||
|
||
## Installation | ||
|
||
**This plugin requires libpcap to capture ARP requests on the network**. On Raspberry PI and comparable systems `libpcap` | ||
must be installed, i.e. `sudo apt-get install libpcap-dev`. | ||
On Windows, [WinPcap](http://www.winpcap.org/install/default.htm) most be installed. | ||
|
||
|
||
## Plugin Configuration | ||
|
||
{ | ||
"plugin": "amazing-dash-button", | ||
"interfaceAddress": "192.168.1.15", | ||
} | ||
|
||
The plugin has the following configuration properties: | ||
|
||
| Property | Default | Type | Description | | ||
|:------------------|:---------|:--------|:--------------------------------------------| | ||
| interfaceAddress | - | String | IP address associated with the network interface which shall be used to listen to ARP requests (optional) | | ||
|
||
|
||
|
||
## Device Configuration | ||
|
||
With pimatic v0.9 nad higher dash-button devices can be automatically discovered. | ||
|
||
{ | ||
"id": "AmazingDashButton1", | ||
"name": "AmazingDashButton1", | ||
"class": "AmazingDashButton", | ||
"macAddress": "AC:63:BE:B3:BE:78" | ||
} | ||
|
||
The plugin has the following configuration properties: | ||
|
||
| Property | Default | Type | Description | | ||
|:------------------|:---------|:--------|:--------------------------------------------| | ||
| interfaceAddress | - | String | MAC address of the device | | ||
| invert | false | String | If true, invert the contact state, i.e., contact is 'closed' if dash-button not pressed | | ||
| holdTime | 1500 | Integer | The number of milliseconds the contact shall enter the state indicating button pressed (closed if not inverted) | | ||
|
||
## Contributions and Donations | ||
|
||
[![PayPal donate button](https://img.shields.io/paypal/donate.png?color=blue)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=E44SSB34CVXP2) | ||
|
||
Contributions to the project are welcome. You can simply fork the project and create a pull request with | ||
your contribution to start with. If you wish to support my work with a donation I'll highly appreciate this. | ||
|
||
## History | ||
|
||
See [Release History](https://github.com/mwittig/pimatic-amazing-dash-button/blob/master/HISTORY.md). | ||
|
||
## License | ||
|
||
Copyright (c) 2016, Marcus Wittig and contributors. All rights reserved. | ||
|
||
[AGPL-3.0](https://github.com/mwittig/pimatic-amazing-dash-button/blob/master/LICENSE) |
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,16 @@ | ||
module.exports = { | ||
title: "pimatic-amazing-dash-button plugin configuration config options" | ||
type: "object" | ||
properties: | ||
debug: | ||
description: "Debug mode. Writes debug messages to the pimatic log, if set to true." | ||
type: "boolean" | ||
default: false | ||
interfaceAddress: | ||
description: " | ||
the IP address associated with the network interface which shall be used to listen to ARP requests. | ||
If omitted the interface with a bound IP address will be used. | ||
" | ||
type: "string" | ||
required: false | ||
} |
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,126 @@ | ||
# The amazing dash-button plugin | ||
module.exports = (env) -> | ||
|
||
Promise = env.require 'bluebird' | ||
cap = require 'cap' | ||
commons = require('pimatic-plugin-commons')(env) | ||
|
||
|
||
# ###AmazingDashButtonPlugin class | ||
class AmazingDashButtonPlugin extends env.plugins.Plugin | ||
|
||
init: (app, @framework, @config) => | ||
@interfaceAddress = @config.interfaceAddress if @config.interfaceAddress? | ||
@invert = @config.invert || false | ||
@_contact = @invert | ||
@debug = @config.debug || false | ||
@base = commons.base @, 'Plugin' | ||
@capture = new cap.Cap() | ||
@buffer = new Buffer(65536) | ||
|
||
process.on "SIGINT", @_stop | ||
@_start() | ||
|
||
# register devices | ||
deviceConfigDef = require("./device-config-schema") | ||
@framework.deviceManager.registerDeviceClass("AmazingDashButton", | ||
configDef: deviceConfigDef.AmazingDashButton, | ||
createCallback: (@config, lastState) => | ||
new AmazingDashButton(@config, @, lastState) | ||
) | ||
|
||
# auto-discovery | ||
@framework.deviceManager.on('discover', (eventData) => | ||
@framework.deviceManager.discoverMessage 'pimatic-amazing-dash-button', 'Searching for dash-buttons. Press dash-button now!' | ||
@candidatesSeen = [] | ||
@lastId = null | ||
|
||
@arpPacketHandler = (arp) => | ||
candidateArp = arp.info.srcmac.toUpperCase() | ||
strippedArpTrunc = candidateArp.replace(/:/g,'').substring(0,6) | ||
|
||
# List of registered Mac addresses with IEEE as of 18 July 2016 for Amazon Technologies Inc. | ||
# source: https://regauth.standards.ieee.org/standards-ra-web/pub/view.html#registries | ||
amazonVendorIds = [ | ||
"747548", "F0D2F1", "8871E5", "74C246", "F0272D", "0C47C9", | ||
"A002DC", "AC63BE", "44650D", "50F5DA", "84D6D0" | ||
] | ||
if strippedArpTrunc in amazonVendorIds and candidateArp not in @candidatesSeen | ||
@base.debug 'Amazon device (possibly a dash-button) detected: ' + candidateArp | ||
@candidatesSeen.push candidateArp | ||
@lastId = @base.generateDeviceId @framework, "dash", @lastId | ||
|
||
deviceConfig = | ||
id: @lastId | ||
name: @lastId | ||
class: 'AmazingDashButton' | ||
macAddress: candidateArp | ||
|
||
@framework.deviceManager.discoveredDevice( | ||
'pimatic-amazing-dash-button', "#{deviceConfig.name} (#{deviceConfig.macAddress})", deviceConfig | ||
) | ||
|
||
@on 'arpPacket', @arpPacketHandler | ||
@timer = setTimeout( => | ||
@removeListener 'arpPacket', @arpPacketHandler | ||
, eventData.time | ||
) | ||
) | ||
|
||
_start: () -> | ||
if @interfaceAddress? | ||
device = cap.findDevice @interfaceAddress | ||
else | ||
device = cap.findDevice() | ||
@base.debug "Sniffing for ARP requests on device", device | ||
|
||
linkType = @capture.open device, 'arp', 10 * 1024 * 1024, @buffer | ||
try | ||
@capture.setMinBytes 0 | ||
catch e | ||
@_base.debug e | ||
|
||
@capture.on "packet", @_rawPacketHandler | ||
|
||
_stop: () => | ||
@capture.removeListener "packet", @_rawPacketHandler | ||
@capture.close(); | ||
|
||
_rawPacketHandler: () => | ||
ret = cap.decoders.Ethernet @buffer | ||
@emit 'arpPacket', ret if ret.info.type is 2054 | ||
|
||
class AmazingDashButton extends env.devices.ContactSensor | ||
# Initialize device by reading entity definition from middleware | ||
constructor: (@config, @plugin, lastState) -> | ||
@id = @config.id | ||
@name = @config.name | ||
@macAddress = @config.macAddress.toUpperCase() | ||
@_invert = @config.invert || false | ||
@_contact = @_invert | ||
@debug = @plugin.debug || false | ||
@base = commons.base @, @config.class | ||
@arpPacketHandler = (arp) => | ||
if arp.info.srcmac.toUpperCase() is @macAddress | ||
@_setContact not @_invert | ||
clearTimeout @timer if @timer? | ||
@timer = setTimeout( => | ||
@_setContact @_invert | ||
@timer = null | ||
, @config.holdTime | ||
) | ||
super() | ||
@plugin.on 'arpPacket', @arpPacketHandler | ||
|
||
destroy: () -> | ||
clearTimeout @timer if @timer? | ||
@plugin.removeListener 'arpPacket', @arpPacketHandler | ||
super() | ||
|
||
getContact: () -> Promise.resolve @_contact | ||
|
||
|
||
# ###Finally | ||
# Create a instance of my plugin | ||
# and return it to the framework. | ||
return new AmazingDashButtonPlugin |
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,20 @@ | ||
module.exports = { | ||
title: "pimatic-amazing-dash-button device config schemas" | ||
AmazingDashButton: | ||
title: "AmazingDashButton config" | ||
type: "object" | ||
extensions: ["xLink"] | ||
properties: { | ||
macAddress: | ||
description: "MAC address of the dash-button" | ||
type: "string" | ||
invert: | ||
description: "If true, invert the contact state, i.e., contact is 'closed' if dash-button not pressed." | ||
type: "boolean" | ||
default: false | ||
holdTime: | ||
description: "The number of milliseconds the contact shall enter the state indicating button pressed (closed if not inverted)." | ||
type: "integer" | ||
default: 1500 | ||
} | ||
} |
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,54 @@ | ||
{ | ||
"name": "pimatic-amazing-dash-button", | ||
"version": "0.9.0", | ||
"author": { | ||
"name": "Marcus Wittig", | ||
"url": "https://github.com/mwittig" | ||
}, | ||
"main": "amazing-dash-button", | ||
"files": [ | ||
"amazing-dash-button.coffee", | ||
"amazing-dash-button-config-schema.coffee", | ||
"device-config-schema.coffee", | ||
"LICENSE", | ||
"HISTORY.md", | ||
"README.md" | ||
], | ||
"keywords": [ | ||
"amazon", | ||
"amazon-dash", | ||
"dash", | ||
"button", | ||
"arp", | ||
"pimatic" | ||
], | ||
"homepage": "https://github.com/mwittig/pimatic-amazing-dash-button/tree/master", | ||
"private": false, | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/mwittig/pimatic-amazing-dash-button.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/mwittig/pimatic-amazing-dash-button/issues" | ||
}, | ||
"license": "AGPL-3.0", | ||
"maintainers": [ | ||
{ | ||
"name": "mwittig", | ||
"url": "https://github.com/mwittig" | ||
} | ||
], | ||
"configSchema": "amazing-dash-button-config-schema.coffee", | ||
"dependencies": { | ||
"cap": "^0.1.1", | ||
"pimatic-plugin-commons": "^0.9.2" | ||
}, | ||
"optionalDependencies": {}, | ||
"peerDependencies": { | ||
"pimatic": ">=0.8.0 <1.0.0" | ||
}, | ||
"engines": { | ||
"node": ">0.8.x", | ||
"npm": ">1.1.x" | ||
} | ||
} |