diff --git a/README.md b/README.md index 4633e26..cbc1937 100644 --- a/README.md +++ b/README.md @@ -68,10 +68,23 @@ When it comes to processing the input from the Nuimo, I've left this largely up - Distance (when the sensor is activated with a long touch on the top) You receive unadulterated event data from the Nuimo for all these actions, with the exception of button press. 'Press' is actually triggered on 'Release' in order to implement the long-press app switcher function. This means you're unable to program your own button holding rules, but I hope this trade-off is a small price to pay for a nicer app switcher. Maybe down the track I'll program the option to change how the app switcher is invoked. +## Using the matrix node +The matrix node allows your Nuimo to respond to changes in your smart home environment, like increased volume or brightness, or alerting you to something's completion. + +At the most basic level you can define the matrix's output using it's editor interface and GUI input, or you can pass a payload with instructions on how to update the display, using it's inbuilt methods or completely raw. + +The matrix node will respond first to payload instructions before defaulting back to the editor interface options. + +See the editor help on the matrix node for more information. + ### Known issues yet to be fixed - Currently node-red needs to be stopped and restarted if the latest deploy was a 'full' deploy, due to the config node (which maintains the bluetooth connection) not cleaning up properly. **To get around this problem on the regular, make use of the Modified Flows deployment option**, unless you've made changes to the config node, in which case you'll have to restart Node Red. (N.b This is related to an [outstanding pull request on the Noble BLE library](https://github.com/noble/noble/pull/577), so likely won't be resolved until it is merged ) - If activeApp (in the global context) is updated programatically rather than through the Nuimo controller, then you lose the ability to bring up the app switcher. Until this is resolved, avoid changing that variable via function nodes. +### Future plans +- Implement an optional 'translator' for raw rotation data making it a bit easier to use. +- Further to this, implement a 'momentum' feature that picks up on increased rotation speed + ### Contribution guide - If you'd like to be a maintainer, just let me know! :) - Requests for tests are warmly encouraged, [pending a discussion on a suitable testing approach](https://github.com/readeral/node-red-contrib-nuimo-controller/issues/1). diff --git a/config/nuimo-config.js b/config/nuimo-config.js index e30bd35..55d7207 100644 --- a/config/nuimo-config.js +++ b/config/nuimo-config.js @@ -1,18 +1,15 @@ //Needs to 'hold' the bluetooth connection and expose it to the various 'normal' nodes module.exports = function(RED) { -let Timeout = require('../Timeout'); function nuimoConfigNode(n) { RED.nodes.createNode(this,n); var globalContext = this.context().global; var node = this; - if (!globalContext.get("activeApp")) { - globalContext.set("activeApp", "pending"); - } - var activeApp = globalContext.get("activeApp"); + var activeApp = globalContext.get("activeApp") || "pending"; var sensitivity = globalContext.get("sensitivity") || [70, 800]; + let Timeout = require('../Timeout'); let Nuimo = require('nuimojs'), nuimo = new Nuimo(); @@ -46,8 +43,10 @@ let Timeout = require('../Timeout'); device.on("release", () => { Timeout.clear('extender'); if (Date.now() - longPress < sensitivity[1]) { + longPress = null; node.emit('press', activeApp) } else { + longPress = null; node.emit('longPress') } }) @@ -97,6 +96,7 @@ let Timeout = require('../Timeout'); device.connect(); node.on('close', function() { + device.disconnect(); device.removeAllListeners(); }); }); @@ -104,6 +104,7 @@ let Timeout = require('../Timeout'); nuimo.scan(); node.on('close', function () { + nuimo.stop(); nuimo.removeAllListeners(); delete nuimo; diff --git a/matrix/nuimo-set-matrix.html b/matrix/nuimo-set-matrix.html index d4ee612..d66fe27 100644 --- a/matrix/nuimo-set-matrix.html +++ b/matrix/nuimo-set-matrix.html @@ -347,5 +347,22 @@

App Matrix Image

diff --git a/matrix/nuimo-set-matrix.js b/matrix/nuimo-set-matrix.js index 9e50784..abdaf85 100644 --- a/matrix/nuimo-set-matrix.js +++ b/matrix/nuimo-set-matrix.js @@ -4,12 +4,13 @@ module.exports = function(RED) { function nuimoSetMatrixNode(config) { RED.nodes.createNode(this,config); + var node = this; //import the config node nuimo = RED.nodes.getNode(config.nuimoConfig); var appMatrixImage = config.appMatrixImage.replace(/\s/g,'').split(','); - var numbers = [ + const numbers = [ [[1,1,1],[1,0,1],[1,0,1],[1,0,1],[1,1,1]], [[0,0,1],[0,0,1],[0,0,1],[0,0,1],[0,0,1]], [[1,1,1],[0,0,1],[1,1,1],[1,0,0],[1,1,1]], @@ -24,43 +25,62 @@ module.exports = function(RED) { ]; function buildNumberArray(num) { - if (num > 0 && num <= 99) { + if (num > -1 && num <= 99) { if (num < 10) { var first = numbers[0]; var second = numbers[num]; } else { - var first = numbers[Number(num.toString().split('')[0])] - var second = numbers[Number(num.toString().split('')[1])] + var first = numbers[Number(num.toString().split('')[0])]; + var second = numbers[Number(num.toString().split('')[1])]; } - var output = []; - output.push(numbers[10], numbers[10], numbers[10]); - var step; - for (step = 0; step < 5; step++) { - // Runs 5 times, with values of step 0 through 4. - output.push(0); - output.push(first[step]); - output.push(0); - output.push(second[step]); - output.push(0); + var output = Array(27).fill(0); + for (var step = 0; step < 5; step++) { + output = output.concat(0, first[step], 0, second[step], 0); } - output.push(numbers[10]); - var merged = output.join().split(',') - return merged; - } else if (num == 0) { - return [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,1,1,0,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0]; - } else { - return [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,1,1,0,0,1,0,1,0,1,0,1,0,0,1,1,1,0,1,1,1,0,0,0,0,1,0,0,0,1,0,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0]; + return output.concat(numbers[10]); } + return [0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0, + 0,1,1,1,0,1,1,1,0, + 0,1,0,1,0,1,0,1,0, + 0,1,1,1,0,1,1,1,0, + 0,0,0,1,0,0,0,1,0, + 0,1,1,1,0,1,1,1,0, + 0,0,0,0,0,0,0,0,0]; }; - var node = this; + function scale(scale) { + var height = scale[0], width = scale[1]; + const line = (width) => ({ + 1: [0,0,0,0,1,0,0,0,0], + 3: [0,0,0,1,1,1,0,0,0], + 5: [0,0,1,1,1,1,1,0,0], + 7: [0,1,1,1,1,1,1,1,0], + 9: [1,1,1,1,1,1,1,1,1], + 0: [0,0,0,0,0,0,0,0,0] + })[width]; + var output = []; + for (var step = 9; step > 0; step--) { + output = (step > height) ? output.concat(line(0)) : output.concat(line(width)); + } + return output; + } + this.on('input', function(msg) { - if (msg.int) { + if (msg.int || msg.payload.int) { appMatrixImage = buildNumberArray(msg.int); } - msg.instructions = { matrix: appMatrixImage, brightness: config.brightness, timeout: config.timeout, options: {onionSkinning: config.onionSkinning}}; - nuimo.writeMatrix(msg.instructions); + if (msg.scale || msg.payload.scale) { + var params = msg.scale || msg.payload.scale; + appMatrixImage = scale(params); + } + var brightness = msg.brightness || msg.payload.brightness || config.brightness; + var timeout = msg.timeout || msg.payload.timeout || config.timeout; + var onionSkinning = msg.onionSkinning || msg.payload.onionSkinning || config.onionSkinning; + msg.instructions = { matrix: appMatrixImage, brightness: brightness, timeout: timeout, options: {onionSkinning: onionSkinning}}; node.send(msg); + nuimo.writeMatrix(msg.instructions); }); } RED.nodes.registerType("nuimo-set-matrix",nuimoSetMatrixNode);