diff --git a/config-sample.json b/config-sample.json index 012739239400410c3d94b1360be4c1f8f95b0749..686299c118f6aade19ca53c59bea8262323615c7 100644 --- a/config-sample.json +++ b/config-sample.json @@ -12,17 +12,43 @@ "status": { "entity_id": "" }, - "on": { - "entity": "", - "entity_id": "", - "entity_action": "" + "single": { + "on": { + "entity": "", + "entity_id": "", + "entity_action": "" + }, + "off": { + "entity": "", + "entity_id": "", + "entity_action": "" + } }, - "off": { - "entity": "", - "entity_id": "", - "entity_action": "" + "double": { + "on": { + "entity": "", + "entity_id": "", + "entity_action": "" + }, + "off": { + "entity": "", + "entity_id": "", + "entity_action": "" + } + }, + "hold": { + "on": { + "entity": "", + "entity_id": "", + "entity_action": "" + }, + "off": { + "entity": "", + "entity_id": "", + "entity_action": "" + } } } }, - "config_version": 2 + "config_version": 3 } diff --git a/index.js b/index.js index 68d1b553d1eead852537cbae88180e287d601d6a..6779a7378867316ae55d058011cb531eaa4ac87c 100644 --- a/index.js +++ b/index.js @@ -13,8 +13,8 @@ var request = require( 'request' ); */ var config = require( './config.json' ); -if ( 'undefined' === typeof config.config_version || config.config_version < 2 ) { - console.error( 'Configuration is for v0.1.0 and must be updated to work with this release. Exiting!' ); +if ( 'undefined' === typeof config.config_version || config.config_version < 3 ) { + console.error( 'Configuration is for a release prior to v0.2.5 and must be updated to work with this release. Exiting!' ); process.exit(); } @@ -40,24 +40,53 @@ client.on( 'newVerifiedButton', function( bdAddr ) { * BUTTON REACTIONS */ function listenToButton( bdAddr ) { + // Not much to do if the button isn't configured if ( "object" !== typeof config.buttons[bdAddr] ) { console.error( 'No configuration for button ' + bdAddr ); return; } + // Establish button connection var cc = new FlicConnectionChannel( bdAddr ); client.addConnectionChannel( cc ); - cc.on( 'buttonUpOrDown', function( clickType, wasQueued, timeDiff ) { - if ( 'ButtonDown' !== clickType ) { + // Bind to our desired click type; see ProtocolDocumentation.md in fliclib-linux-hci + cc.on( 'buttonSingleOrDoubleClickOrHold', function( clickType, wasQueued, timeDiff ) { + // Don't handle long-queued events, to avoid excessive toggling of HA entities + if ( wasQueued && timeDiff > 2 ) { return; } - if ( wasQueued && timeDiff > 2 ) { + // Convert the verbose click name to something convenient + // Also validates click type + var parsedClickType = ''; + + switch ( clickType ) { + case 'ButtonSingleClick': + parsedClickType = 'single'; + break; + + case 'ButtonDoubleClick': + parsedClickType = 'double'; + break; + + case 'ButtonHold': + parsedClickType = 'hold'; + break; + + default: + // Do nothing, this type isn't supported + break; + } + + // Click type is unsupported + if ( 0 === parsedClickType.length ) { + console.error( 'Unsupported click type ' + clickType ); return; } - buttonActivated( bdAddr ); + // Time to pass the click to HA + buttonActivated( bdAddr, parsedClickType ); } ); } @@ -68,9 +97,24 @@ function listenToButton( bdAddr ) { /** * Make HTTP(s) requests to Home Assistant to toggle status of device assigned to pushed button */ -function buttonActivated( mac ) { - var buttonConfig = config.buttons[mac]; +function buttonActivated( mac, clickType ) { + // Check for a button config + if ( 'undefined' === typeof config.buttons[ mac ] ) { + console.error( 'No configuration for button ' + mac ); + return; + } + + var buttonConfig = config.buttons[ mac ]; + + // Check for a config for this click type + if ( 'undefined' === typeof buttonConfig[ clickType ] ) { + console.error( 'No configuration for click type `' + clickType + '` on button "' + buttonConfig.label + '"' ); + return; + } + + var buttonClickConfig = buttonConfig[ clickType ]; + // Check current state of button's entity var req = { url: homeAssistantApiBase + 'states/' + buttonConfig.status.entity_id, headers: { @@ -95,12 +139,13 @@ function buttonActivated( mac ) { // HA only deals with JSON body = JSON.parse( body ); + // Use entity's current state to determine new state, per config var service = 'services/', postBody = {}; - if ( 'object' === typeof buttonConfig[ body.state ] ) { - service += buttonConfig[ body.state ].entity + '/' + buttonConfig[ body.state ].entity_action; - postBody.entity_id = buttonConfig[ body.state ].entity_id; + if ( 'object' === typeof buttonClickConfig[ body.state ] ) { + service += buttonClickConfig[ body.state ].entity + '/' + buttonClickConfig[ body.state ].entity_action; + postBody.entity_id = buttonClickConfig[ body.state ].entity_id; } else { console.error( 'Unhandled state: ' + body.state ); return; @@ -111,7 +156,7 @@ function buttonActivated( mac ) { req.method = 'POST'; req.body = JSON.stringify( postBody ); - // Make request to change alarm status + // Make request to update entity status request( req, function( err, res, body ) { // Handle error states if ( err ) { diff --git a/package.json b/package.json index 38b71f74f20276dbce3ac74028f8a80cef892709..c3bd5e4751b3717c77b4925d34b31861f9bdc8d1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "flic-button-home-assistant-controller", - "version": "0.2.0", + "version": "0.2.5", "description": "Control Home Assistant entities with Flic buttons", "author": "Erick Hitter <contact@ethitter.com>", "license": "GPL-2.0+",