├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── examples ├── repl.js └── replMocked.js ├── index.js ├── lib ├── PiGlowBackend.js ├── PiGlowBackendMock.js ├── PiGlowBackendMockPrettyPrint.js ├── interface.js └── util │ ├── gammaCorrection.js │ ├── ledToAddress.js │ └── valueProcessor.js ├── package.json ├── pics ├── piglow.jpg ├── piglow_leds.jpg ├── piglow_legs.jpg └── piglow_rings.jpg └── tests ├── piglowBackend.tests.js ├── piglowInterface.tests.js └── util.tests.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .idea 2 | pics 3 | .travis.yml 4 | TODO.md 5 | node_modules -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | branches: 3 | only: 4 | - master 5 | node_js: 6 | - "4" 7 | - "5" 8 | - "6" 9 | script: npm test 10 | 11 | sudo: required 12 | dist: trusty -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2013- Manuel Ernst 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # node-piglow [![Build Status](https://travis-ci.org/seriousManual/node-piglow.png)](https://travis-ci.org/seriousManual/node-piglow) 2 | 3 | **v2 does not contain the commandline interface and the animations interface anymore. They are moved to two seperate modules. ([node-piglow-cli](https://github.com/zaphod1984/node-piglow-cli) and [node-piglow-animations](https://github.com/zaphod1984/node-piglow-animations))** 4 | 5 | **v3 removes node 0.10 and 0.12 support and only works for node versions >4** 6 | 7 | [![NPM](https://nodei.co/npm/piglow.png)](https://nodei.co/npm/piglow/) 8 | 9 | [![NPM](https://nodei.co/npm-dl/piglow.png?months=3)](https://nodei.co/npm/piglow/) 10 | 11 | The piGlow is a little LED-Board for the [Raspberry Pi](http://www.raspberrypi.org/) sold by [Pimoroni](http://shop.pimoroni.com/products/piglow). It features 18 LEDs in six different colors (white, blue, green, yellow, orange, red) arranged like a vortex: 12 | 13 |

14 | 15 |

16 | 17 | This module offers an interface to control the individual LEDs. 18 | 19 | In action video: 20 | http://www.youtube.com/watch?v=s-rD8PfAke8 21 | 22 | ## TOC 23 | 24 | * [Installation](#installation) 25 | * [Setup](#setup) 26 | * [Invocation](#invocation) 27 | * [Adressing](#adressing) 28 | * [Transactions](#transactions) 29 | * [Animations](#animations) 30 | * [CLI](#command-line-interface) 31 | * [Mocking](#mocking) 32 | * [Used in](#used-in) 33 | 34 | ## Installation 35 | 36 | ````bash 37 | $ npm install piglow 38 | ```` 39 | 40 | ## Setup 41 | 42 | ````bash 43 | $ sudo vi /etc/modules 44 | ```` 45 | 46 | Add these two lines 47 | 48 | ````bash 49 | i2c-bcm2708 50 | i2c-dev 51 | ```` 52 | 53 | ````bash 54 | $ sudo vi /etc/modprobe.d/raspi-blacklist.conf 55 | ```` 56 | 57 | Comment out blacklist i2c-bcm2708 58 | 59 | ```` 60 | #blacklist i2c-bcm2708 61 | ```` 62 | 63 | ## Invocation 64 | 65 | ```javascript 66 | var piGlow = require('piglow'); 67 | 68 | //callback fires when board is initialized 69 | piGlow(function(error, pi) { 70 | pi.all; 71 | }); 72 | 73 | ``` 74 | 75 | ## Adressing 76 | 77 |

78 |
79 | 80 | 81 |

82 | 83 | To each LED a brightness value between 0 (off) and 255 (freakin' bright) can be assigned. 84 | If one preferrs percentage values, as a convenience function all values smaller than 1 are treated as percentage values. Note that the value of '1' is not treated as 100% but as the brightness value of 1! 85 | 86 | ### Individual LEDs 87 | ```javascript 88 | //parameter sets the brightness: 89 | pi.l_0_0 = 100; //sets LED 1 of leg 1 to a brightness of 100 (of 255) 90 | pi.l_0_1 = 10; //sets LED 2 of leg 1 to a brightness of 10 91 | pi.l_0_1 = 0.5; //sets LED 2 of leg 1 to a brightness of 50% (=brightness of 127) 92 | ... 93 | pi.l_2_5 = 200; //sets LED 6 of leg 3 to a brightness of 200 94 | 95 | //shorthand form: 96 | pi.l_0_0; //sets LED 1 of leg 1 to a brightness of 255 97 | ``` 98 | 99 | ### Legs 100 | ```javascript 101 | pi.leg_0 = 100; //sets all LEDs of leg 1 to a brightness of 100 102 | 103 | //shorthand 104 | pi.leg_0; //sets all LEDs of leg 1 to 255 105 | ``` 106 | 107 | ### Rings 108 | ```javascript 109 | pi.ring_0 = 100; //sets LED 1 of leg 1, LED 1 of leg 2 and LED 1 of leg 3 to 100 110 | 111 | //shorthand 112 | pi.ring_0; //sets LED 1 of leg 1, LED 1 of leg 1 and LED 1 of leg 2 to 255 113 | ``` 114 | 115 | As the rings are distinguishable by color (order from outer ring to the inner: red, orange, yellow, green, blue, white), they can be adressed via the ring's color: 116 | ```javascript 117 | pi.red = 100; //sets the first ring to a brightness of 100 118 | 119 | //shorthand 120 | pi.red; //sets the first ring to maximum brightness 121 | ``` 122 | 123 | 124 | ### All LEDs 125 | ```javascript 126 | pi.all = 100; //set all LEDs to 100 127 | 128 | //shorthand 129 | pi.all; //set all LEDs to 255 (watch your eyes) 130 | 131 | pi.reset; //set all LEDs to 0 132 | ``` 133 | 134 | ### Random 135 | ```javascript 136 | pi.random = 0.5; 137 | 138 | //shorthand 139 | pi.random; 140 | ``` 141 | The propbability of lighting up can be defined (`pi.random = 0.1;`) and is otherwise calculated via this formula: `(0.4 + Math.random() * 0.2);`. 142 | The brightness is calculated via this formula: `parseInt(MAX_VALUE / 2 + (MAX_VALUE / 2 * Math.random()), 10)` 143 | 144 | ## Transactions 145 | 146 | Each parameter that is set causes the backend to transfer the complete set of values to the piglow board. 147 | Thus the following operation would cause three write operations: 148 | 149 | ```javascript 150 | pi.l_0_1 = 100; 151 | pi.l_0_2 = 100; 152 | pi.l_0_3 = 100; 153 | ``` 154 | 155 | The piglow-interface offers the possibility to open up a transaction and to commit it when all changes have been made. So the following code will cause only one write to the hardware board: 156 | 157 | ```javascript 158 | pi.startTransaction(); 159 | pi.l_0_1 = 100; 160 | pi.l_0_2 = 100; 161 | pi.l_0_3 = 100; 162 | pi.commitTransaction(); 163 | ``` 164 | 165 | This benefits performance especially when the LEDs are changed in high frequency. 166 | 167 | ## Animations 168 | 169 | Do you like your piglow animated? Checkout [piglow-animations](https://www.npmjs.org/package/piglow-animations)! 170 |

171 | 172 |

173 | 174 | ## Command-Line-Interface 175 | 176 | [node-piglow-cli](https://www.npmjs.org/package/piglow-cli) wraps piglow and offers a command line interface. You can than invoke the piglow like this (lights up the red LEDs): 177 | ```bash 178 | $ piglow --red 179 | ``` 180 | 181 | Possible use cases: 182 | * use it in your Makefile to indicate a sucessfull built 183 | * use it in your CI server to indicate failed (or sucessfull) built 184 | * ... 185 | 186 | ## Mocking 187 | 188 | This module also exposes its internal structure, with the possibility to invoke the piGlow interface with a injected mocking backend. 189 | There are two backends, `BackendMock` prints the piglow data as JSON, `BackendMockPrettyPrint` structures the data in a readable way. 190 | ```javascript 191 | var piGlow = require('piglow'); 192 | var PiGlowBackendMock = piGlow.BackendMock; 193 | var piGlowInterface = piGLow.piGlowInterface; 194 | 195 | var myMock = new PiGlowBackendMock(); 196 | var myInterface = piGlowInterface(myMock); 197 | 198 | //lets hack 199 | myInterface.ring_0 = 255; 200 | ``` 201 | 202 | This way the module can be used in a non raspi environment for development or with a testing mock for unit tests. 203 | To implement your own mocks follow this interface: 204 | ```javascript 205 | function PiGlowMock() {} 206 | 207 | PiGlowMock.prototype.update = function(piGlowConfiguration, callback) { 208 | /* 209 | piGlowConfiguration is a object in the following form: 210 | { 211 | "l_0_0":0, "l_0_1":0, "l_0_2":0, "l_0_3":0, "l_0_4":0, "l_0_5":0, 212 | "l_1_0":0, "l_1_1":0, "l_1_2":0, "l_1_3":0, "l_1_4":0, "l_1_5":0, 213 | "l_2_0":0, "l_2_1":0, "l_2_2":0, "l_2_3":0, "l_2_4":0, "l_2_5":0 214 | } 215 | */ 216 | }; 217 | ``` 218 | 219 | ## Used in 220 | - *[piglow-system](https://www.npmjs.com/package/piglow-system)* 221 | a system utlity tool that shows metrics about your system 222 | - *[piglow-clock](https://www.npmjs.com/package/piglow-clock)* 223 | a binary watch implemented via the piglow 224 | -------------------------------------------------------------------------------- /examples/repl.js: -------------------------------------------------------------------------------- 1 | var repl = require('repl'); 2 | 3 | //TODO: reset piglow on repl.end 4 | 5 | var PiGlowBackend = require('../lib/PiGlowBackend'); 6 | var piGlowInterface = require('../lib/interface'); 7 | 8 | var myPiGlow = new PiGlowBackend(); 9 | var myInterface = piGlowInterface(myPiGlow); 10 | 11 | myPiGlow.on('initialize', function() { 12 | repl.start("> ").context.i = myInterface; 13 | }); 14 | -------------------------------------------------------------------------------- /examples/replMocked.js: -------------------------------------------------------------------------------- 1 | var repl = require('repl'); 2 | 3 | var PiGlowBackendMock = require('../lib/PiGlowBackendMockPrettyPrint'); 4 | var piGlowInterface = require('../lib/interface'); 5 | 6 | var myMock = new PiGlowBackendMock(); 7 | var myInterface = piGlowInterface(myMock); 8 | 9 | myMock.on('initialize', function() { 10 | repl.start("> ").context.i = myInterface; 11 | }); 12 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var processValue = require('./lib/util/valueProcessor'); 2 | var piGlowInterface = require('./lib/interface'); 3 | var PiGlowBackend = require('./lib/PiGlowBackend'); 4 | var PiGlowBackendMock = require('./lib/PiGlowBackendMock'); 5 | var BackendMockPrettyPrint = require('./lib/PiGlowBackendMockPrettyPrint'); 6 | 7 | /** 8 | * convenience constructor function 9 | */ 10 | function createPiGlow(callback) { 11 | var myPiGlow = new PiGlowBackend(); 12 | var myInterface = piGlowInterface(myPiGlow); 13 | 14 | myPiGlow 15 | .on('initialize', function() { 16 | callback(null, myInterface); 17 | }) 18 | .on('error', function(error) { 19 | callback(error, null); 20 | }); 21 | } 22 | 23 | createPiGlow.Backend = PiGlowBackend; 24 | createPiGlow.BackendMock = PiGlowBackendMock; 25 | createPiGlow.BackendMockPrettyPrint = BackendMockPrettyPrint; 26 | createPiGlow.piGlowInterface = piGlowInterface; 27 | createPiGlow.processValue = processValue; 28 | 29 | module.exports = createPiGlow; 30 | -------------------------------------------------------------------------------- /lib/PiGlowBackend.js: -------------------------------------------------------------------------------- 1 | var Emitter = require('events').EventEmitter; 2 | var util = require('util'); 3 | 4 | var sigmund = require('sigmund'); 5 | 6 | var ledMapper = require('./util/ledToAddress'); 7 | var gammaCorrection = require('./util/gammaCorrection'); 8 | 9 | var PIGLOW_ADDRESS = 0x54; //the gpio adress 10 | var CMD_ENABLE_OUTPUT = 0x00; //command to enable all outputs 11 | var CMD_ENABLE_LEDS = 0x13; //enable the LEDs 12 | var CMD_SET_PWM_VALUES = 0x01; //command adress that sets the brightness values 13 | var CMD_UPDATE = 0x16; //command that causes the hardware board to update its LED values 14 | 15 | /** 16 | * PiGlow Backend 17 | * @constructor 18 | */ 19 | function PiGlow() { 20 | var that = this; 21 | 22 | this._wire = null; 23 | this._currentState = null; 24 | 25 | Emitter.call(this); 26 | 27 | this._initialize(function (error) { 28 | if (error) { 29 | that.emit('error', error); 30 | } else { 31 | that.emit('initialize'); 32 | } 33 | }); 34 | } 35 | 36 | util.inherits(PiGlow, Emitter); 37 | 38 | /** 39 | * initializes the piglow board 40 | * @param callback 41 | * @return {*} 42 | * @private 43 | */ 44 | PiGlow.prototype._initialize = function (callback) { 45 | //evil hack alert!!!! 46 | //as requires are done at runtime, no error will be thrown if i2c is not present 47 | var I2c = require('i2c'); 48 | 49 | var that = this; 50 | this._wire = new I2c(PIGLOW_ADDRESS, {device: '/dev/i2c-1'}); 51 | 52 | try { 53 | //explicitly setting the adress so we can catch the event in the try/catch block 54 | this._wire.setAddress(PIGLOW_ADDRESS); 55 | } 56 | catch (e) { 57 | return process.nextTick(callback.bind(null, e)); 58 | } 59 | 60 | that._wire.writeBytes(CMD_ENABLE_OUTPUT, [0x01], function (error) { 61 | if (error) return callback(error); 62 | 63 | that._wire.writeBytes(CMD_ENABLE_LEDS, [0xFF, 0xFF, 0xFF], callback); 64 | }); 65 | }; 66 | 67 | /** 68 | * writes the complete array of brightness values to the hardware board 69 | * @param piGlowConfiguration array 70 | * @param callback 71 | */ 72 | PiGlow.prototype.update = function (piGlowConfiguration, callback) { 73 | var that = this; 74 | 75 | var mappedValues = ledMapper 76 | .mapAll(piGlowConfiguration) 77 | .map(gammaCorrection); 78 | 79 | if (!this._isActualUpdate(mappedValues)) return process.nextTick(callback); 80 | 81 | that._wire.writeBytes(CMD_SET_PWM_VALUES, mappedValues, function (error) { 82 | if (error) return callback(error); 83 | 84 | that._wire.writeBytes(CMD_UPDATE, [0xFF], function (error) { 85 | if (error) return callback(error); 86 | 87 | that._currentState = that._createSignature(mappedValues); 88 | callback(); 89 | }); 90 | }); 91 | }; 92 | 93 | PiGlow.prototype._isActualUpdate = function (newValues) { 94 | return this._currentState !== this._createSignature(newValues); 95 | }; 96 | 97 | PiGlow.prototype._createSignature = function (values) { 98 | return sigmund(values); 99 | }; 100 | 101 | module.exports = PiGlow; 102 | -------------------------------------------------------------------------------- /lib/PiGlowBackendMock.js: -------------------------------------------------------------------------------- 1 | var Emitter = require('events').EventEmitter; 2 | var util = require('util'); 3 | 4 | /** 5 | * this is a mocking class that has the same interface as the piglow backend 6 | * it outputs the values that should be written to the console 7 | * @constructor 8 | */ 9 | function PiGlowMock() { 10 | Emitter.call(this); 11 | 12 | var that = this; 13 | 14 | setTimeout(function () { 15 | that.emit('initialize'); 16 | }, 15); 17 | } 18 | 19 | util.inherits(PiGlowMock, Emitter); 20 | 21 | PiGlowMock.prototype.update = function (bytes, callback) { 22 | console.log(JSON.stringify(bytes)); 23 | }; 24 | 25 | module.exports = PiGlowMock; -------------------------------------------------------------------------------- /lib/PiGlowBackendMockPrettyPrint.js: -------------------------------------------------------------------------------- 1 | var Emitter = require('events').EventEmitter; 2 | var util = require('util'); 3 | 4 | /** 5 | * this is a mocking class that has the same interface as the piglow backend 6 | * it outputs the values that should be written to the console 7 | * @constructor 8 | */ 9 | function PiGlowMockPrettyPrint() { 10 | Emitter.call(this); 11 | 12 | var that = this; 13 | 14 | setTimeout(function () { 15 | that.emit('initialize'); 16 | }, 15); 17 | } 18 | 19 | util.inherits(PiGlowMockPrettyPrint, Emitter); 20 | 21 | PiGlowMockPrettyPrint.prototype.update = function (piGlowConfiguration, callback) { 22 | this._prettyPrint(piGlowConfiguration); 23 | }; 24 | 25 | PiGlowMockPrettyPrint.prototype._prettyPrint = function(piGlowConfiguration) { 26 | console.log('piglowConfiguration:'); 27 | console.log(util.format(' leg0 leg1 leg2')); 28 | console.log(util.format('ring0 %s %s %s', _p(piGlowConfiguration.l_0_0), _p(piGlowConfiguration.l_1_0), _p(piGlowConfiguration.l_2_0))); 29 | console.log(util.format('ring1 %s %s %s', _p(piGlowConfiguration.l_0_1), _p(piGlowConfiguration.l_1_1), _p(piGlowConfiguration.l_2_1))); 30 | console.log(util.format('ring2 %s %s %s', _p(piGlowConfiguration.l_0_2), _p(piGlowConfiguration.l_1_2), _p(piGlowConfiguration.l_2_2))); 31 | console.log(util.format('ring3 %s %s %s', _p(piGlowConfiguration.l_0_3), _p(piGlowConfiguration.l_1_3), _p(piGlowConfiguration.l_2_3))); 32 | console.log(util.format('ring4 %s %s %s', _p(piGlowConfiguration.l_0_4), _p(piGlowConfiguration.l_1_4), _p(piGlowConfiguration.l_2_4))); 33 | console.log(util.format('ring5 %s %s %s', _p(piGlowConfiguration.l_0_5), _p(piGlowConfiguration.l_1_5), _p(piGlowConfiguration.l_2_5))); 34 | }; 35 | 36 | function _p(subject) { 37 | subject = subject + ''; 38 | if(subject.length == 1) return subject + ' '; 39 | if(subject.length == 2) return subject + ' '; 40 | return subject; 41 | } 42 | 43 | module.exports = PiGlowMockPrettyPrint; -------------------------------------------------------------------------------- /lib/interface.js: -------------------------------------------------------------------------------- 1 | var processValue = require('./util/valueProcessor'); 2 | 3 | /** 4 | * the piglow interfaces that is used to map led identifier and led group identifier to hardware adresses 5 | * usage: 6 | * var pi = interface(); //creates a interface object without a backend. mapped values can be read from the 'values' property 7 | * var pi = interface(backend); //injects a backend, can be used for unit testing or mocked execution in non raspi environment 8 | * var pi = interface({'ring_0': 100}); //creates a piglow interface without a backend, preinitializes the LEDs belonging to ring 0 with the brightness of 100 9 | * var pi = interface(['ring_0']); //creates a piglow interface without a backend, preinitializes the LEDs belonging to ring 0 with the maximum brightness 10 | * var pi = interface(backend, ['ring_0']); //creates a piglow interface with a backend, preinitializes the LEDs belonging to ring 0 with the maximum brightness 11 | * var pi = interface(backend, {'ring_0':100}); //creates a piglow interface with a backend, preinitializes the LEDs belonging to ring 0 with the brightness of 100 12 | * 13 | * @param backend 14 | * @param predefined 15 | * @return {Object} 16 | */ 17 | function create(backend, predefined) { 18 | var _backend, _predefined; 19 | 20 | if (backend) { 21 | if (backend.update) { 22 | _predefined = predefined || {}; 23 | _backend = backend; 24 | } else { 25 | _backend = null; 26 | _predefined = backend; 27 | } 28 | } else { 29 | _predefined = {}; 30 | _backend = null; 31 | } 32 | 33 | function random(prob) { 34 | prob = prob || (0.4 + Math.random() * 0.2); 35 | 36 | Object.keys(piGlow.values).forEach(function (key) { 37 | if (Math.random() > prob) { 38 | var brightness = processValue.MAX_VALUE / 2 + (processValue.MAX_VALUE / 2 * Math.random()); 39 | 40 | piGlow.values[key] = processValue(brightness); 41 | } else { 42 | piGlow.values[key] = 0; 43 | } 44 | }); 45 | 46 | piGlow.update(); 47 | } 48 | 49 | function _writePredefinds(piGlow, predefined) { 50 | predefined = _normalizePredefined(predefined); 51 | 52 | var keys = Object.keys(predefined); 53 | 54 | if (keys.length == 0) return; 55 | 56 | piGlow.startTransaction(); 57 | keys.forEach(function (key) { 58 | piGlow[key] = predefined[key]; 59 | }); 60 | piGlow.commitTransaction(); 61 | } 62 | 63 | function _normalizePredefined(predefined) { 64 | if (Array.isArray(predefined)) { 65 | predefined = predefined.reduce(function (memo, key) { 66 | memo[key] = processValue.MAX_VALUE; 67 | 68 | return memo; 69 | }, {}); 70 | } 71 | 72 | return predefined; 73 | } 74 | 75 | var piGlow = { 76 | values: { 77 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 78 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 79 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 80 | }, 81 | 82 | transactionLevel: 0, 83 | 84 | update: function () { 85 | if (this.transactionLevel === 0 && _backend) { 86 | _backend.update(this.values, function () { 87 | }); 88 | } 89 | }, 90 | 91 | startTransaction: function () { 92 | this.transactionLevel++; 93 | }, 94 | 95 | commitTransaction: function () { 96 | this.transactionLevel--; 97 | this.update(); 98 | } 99 | }; 100 | 101 | Object.defineProperties(piGlow, { 102 | //adressing single LEDs 103 | "l_0_0": { 104 | set: function (v) { 105 | this.values.l_0_0 = processValue(v); 106 | this.update(); 107 | }, 108 | get: function () { 109 | this.l_0_0 = processValue.MAX_VALUE; 110 | } 111 | }, 112 | "l_0_1": { 113 | set: function (v) { 114 | this.values.l_0_1 = processValue(v); 115 | this.update(); 116 | }, 117 | get: function () { 118 | this.l_0_1 = processValue.MAX_VALUE; 119 | } 120 | }, 121 | "l_0_2": { 122 | set: function (v) { 123 | this.values.l_0_2 = processValue(v); 124 | this.update(); 125 | }, 126 | get: function () { 127 | this.l_0_2 = processValue.MAX_VALUE; 128 | } 129 | }, 130 | "l_0_3": { 131 | set: function (v) { 132 | this.values.l_0_3 = processValue(v); 133 | this.update(); 134 | }, 135 | get: function () { 136 | this.l_0_3 = processValue.MAX_VALUE; 137 | } 138 | }, 139 | "l_0_4": { 140 | set: function (v) { 141 | this.values.l_0_4 = processValue(v); 142 | this.update(); 143 | }, 144 | get: function () { 145 | this.l_0_4 = processValue.MAX_VALUE; 146 | } 147 | }, 148 | "l_0_5": { 149 | set: function (v) { 150 | this.values.l_0_5 = processValue(v); 151 | this.update(); 152 | }, 153 | get: function () { 154 | this.l_0_5 = processValue.MAX_VALUE; 155 | } 156 | }, 157 | "l_1_0": { 158 | set: function (v) { 159 | this.values.l_1_0 = processValue(v); 160 | this.update(); 161 | }, 162 | get: function () { 163 | this.l_1_0 = processValue.MAX_VALUE; 164 | } 165 | }, 166 | "l_1_1": { 167 | set: function (v) { 168 | this.values.l_1_1 = processValue(v); 169 | this.update(); 170 | }, 171 | get: function () { 172 | this.l_1_1 = processValue.MAX_VALUE; 173 | } 174 | }, 175 | "l_1_2": { 176 | set: function (v) { 177 | this.values.l_1_2 = processValue(v); 178 | this.update(); 179 | }, 180 | get: function () { 181 | this.l_1_2 = processValue.MAX_VALUE; 182 | } 183 | }, 184 | "l_1_3": { 185 | set: function (v) { 186 | this.values.l_1_3 = processValue(v); 187 | this.update(); 188 | }, 189 | get: function () { 190 | this.l_1_3 = processValue.MAX_VALUE; 191 | } 192 | }, 193 | "l_1_4": { 194 | set: function (v) { 195 | this.values.l_1_4 = processValue(v); 196 | this.update(); 197 | }, 198 | get: function () { 199 | this.l_1_4 = processValue.MAX_VALUE; 200 | } 201 | }, 202 | "l_1_5": { 203 | set: function (v) { 204 | this.values.l_1_5 = processValue(v); 205 | this.update(); 206 | }, 207 | get: function () { 208 | this.l_1_5 = processValue.MAX_VALUE; 209 | } 210 | }, 211 | "l_2_0": { 212 | set: function (v) { 213 | this.values.l_2_0 = processValue(v); 214 | this.update(); 215 | }, 216 | get: function () { 217 | this.l_2_0 = processValue.MAX_VALUE; 218 | } 219 | }, 220 | "l_2_1": { 221 | set: function (v) { 222 | this.values.l_2_1 = processValue(v); 223 | this.update(); 224 | }, 225 | get: function () { 226 | this.l_2_1 = processValue.MAX_VALUE; 227 | } 228 | }, 229 | "l_2_2": { 230 | set: function (v) { 231 | this.values.l_2_2 = processValue(v); 232 | this.update(); 233 | }, 234 | get: function () { 235 | this.l_2_2 = processValue.MAX_VALUE; 236 | } 237 | }, 238 | "l_2_3": { 239 | set: function (v) { 240 | this.values.l_2_3 = processValue(v); 241 | this.update(); 242 | }, 243 | get: function () { 244 | this.l_2_3 = processValue.MAX_VALUE; 245 | } 246 | }, 247 | "l_2_4": { 248 | set: function (v) { 249 | this.values.l_2_4 = processValue(v); 250 | this.update(); 251 | }, 252 | get: function () { 253 | this.l_2_4 = processValue.MAX_VALUE; 254 | } 255 | }, 256 | "l_2_5": { 257 | set: function (v) { 258 | this.values.l_2_5 = processValue(v); 259 | this.update(); 260 | }, 261 | get: function () { 262 | this.l_2_5 = processValue.MAX_VALUE; 263 | } 264 | }, 265 | 266 | //adressing complete legs of the piglow 267 | "leg_0": { 268 | set: function (v) { 269 | this.startTransaction(); 270 | this.l_0_0 = v; 271 | this.l_0_1 = v; 272 | this.l_0_2 = v; 273 | this.l_0_3 = v; 274 | this.l_0_4 = v; 275 | this.l_0_5 = v; 276 | this.commitTransaction(); 277 | }, 278 | get: function () { 279 | this.leg_0 = processValue.MAX_VALUE; 280 | } 281 | }, 282 | "leg_1": { 283 | set: function (v) { 284 | this.startTransaction(); 285 | this.l_1_0 = v; 286 | this.l_1_1 = v; 287 | this.l_1_2 = v; 288 | this.l_1_3 = v; 289 | this.l_1_4 = v; 290 | this.l_1_5 = v; 291 | this.commitTransaction(); 292 | }, 293 | get: function () { 294 | this.leg_1 = processValue.MAX_VALUE; 295 | } 296 | }, 297 | "leg_2": { 298 | set: function (v) { 299 | this.startTransaction(); 300 | this.l_2_0 = v; 301 | this.l_2_1 = v; 302 | this.l_2_2 = v; 303 | this.l_2_3 = v; 304 | this.l_2_4 = v; 305 | this.l_2_5 = v; 306 | this.commitTransaction(); 307 | }, 308 | get: function () { 309 | this.leg_2 = processValue.MAX_VALUE; 310 | } 311 | }, 312 | 313 | //the first LED of each leg (red) 314 | "ring_0": { 315 | set: function (v) { 316 | this.startTransaction(); 317 | this.l_0_0 = v; 318 | this.l_1_0 = v; 319 | this.l_2_0 = v; 320 | this.commitTransaction(); 321 | }, 322 | get: function () { 323 | this.ring_0 = processValue.MAX_VALUE; 324 | } 325 | }, 326 | "red": { 327 | set: function (v) { 328 | this.ring_0 = v; 329 | }, 330 | get: function () { 331 | this.ring_0; 332 | } 333 | }, 334 | 335 | //the second LED of each leg (orange) 336 | "ring_1": { 337 | set: function (v) { 338 | this.startTransaction(); 339 | this.l_0_1 = v; 340 | this.l_1_1 = v; 341 | this.l_2_1 = v; 342 | this.commitTransaction(); 343 | }, 344 | get: function () { 345 | this.ring_1 = processValue.MAX_VALUE; 346 | } 347 | }, 348 | "orange": { 349 | set: function (v) { 350 | this.ring_1 = v; 351 | }, 352 | get: function () { 353 | this.ring_1; 354 | } 355 | }, 356 | 357 | //the third LED of each leg (yellow) 358 | "ring_2": { 359 | set: function (v) { 360 | this.startTransaction(); 361 | this.l_0_2 = v; 362 | this.l_1_2 = v; 363 | this.l_2_2 = v; 364 | this.commitTransaction(); 365 | }, 366 | get: function () { 367 | this.ring_2 = processValue.MAX_VALUE; 368 | } 369 | }, 370 | "yellow": { 371 | set: function (v) { 372 | this.ring_2 = v; 373 | }, 374 | get: function () { 375 | this.ring_2; 376 | } 377 | }, 378 | 379 | //the fourth LED of each leg (green) 380 | "ring_3": { 381 | set: function (v) { 382 | this.startTransaction(); 383 | this.l_0_3 = v; 384 | this.l_1_3 = v; 385 | this.l_2_3 = v; 386 | this.commitTransaction(); 387 | }, 388 | get: function () { 389 | this.ring_3 = processValue.MAX_VALUE; 390 | } 391 | }, 392 | "green": { 393 | set: function (v) { 394 | this.ring_3 = v; 395 | }, 396 | get: function () { 397 | this.ring_3; 398 | } 399 | }, 400 | 401 | //the fifth LED of each leg (blue) 402 | "ring_4": { 403 | set: function (v) { 404 | this.startTransaction(); 405 | this.l_0_4 = v; 406 | this.l_1_4 = v; 407 | this.l_2_4 = v; 408 | this.commitTransaction(); 409 | }, 410 | get: function () { 411 | this.ring_4 = processValue.MAX_VALUE; 412 | } 413 | }, 414 | "blue": { 415 | set: function (v) { 416 | this.ring_4 = v; 417 | }, 418 | get: function () { 419 | this.ring_4; 420 | } 421 | }, 422 | 423 | //the sixth LED of each leg (white) 424 | "ring_5": { 425 | set: function (v) { 426 | this.startTransaction(); 427 | this.l_0_5 = v; 428 | this.l_1_5 = v; 429 | this.l_2_5 = v; 430 | this.commitTransaction(); 431 | }, 432 | get: function () { 433 | this.ring_5 = processValue.MAX_VALUE; 434 | } 435 | }, 436 | "white": { 437 | set: function (v) { 438 | this.ring_5 = v; 439 | }, 440 | get: function () { 441 | this.ring_5; 442 | } 443 | }, 444 | 445 | //adress all LEDs 446 | "all": { 447 | set: function (v) { 448 | this.startTransaction(); 449 | this.leg_0 = v; 450 | this.leg_1 = v; 451 | this.leg_2 = v; 452 | this.commitTransaction(); 453 | }, 454 | get: function () { 455 | this.all = processValue.MAX_VALUE; 456 | } 457 | }, 458 | 459 | //set all LEDs to off 460 | "reset": { 461 | get: function () { 462 | piGlow.all = 0; 463 | } 464 | }, 465 | 466 | //random adressing 467 | "random": { 468 | get: random, 469 | set: random 470 | } 471 | }); 472 | 473 | _writePredefinds(piGlow, _predefined); 474 | 475 | return piGlow; 476 | } 477 | 478 | module.exports = create; -------------------------------------------------------------------------------- /lib/util/gammaCorrection.js: -------------------------------------------------------------------------------- 1 | /** 2 | * gamma correction table 3 | * used to map brightness values to bit values 4 | * borrowed from: https://github.com/benleb/PyGlow and jon@pimoroni 5 | * @type {Array} 6 | */ 7 | var GAMMA_TABLE = [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 8 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 9 | 10, 11, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 18, 18, 18, 19, 19, 20, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 10 | 25, 26, 26, 27, 27, 28, 29, 29, 30, 31, 31, 32, 33, 33, 34, 35, 36, 36, 37, 38, 39, 40, 41, 42, 42, 43, 44, 45, 46, 47, 48, 50, 51, 52, 53, 54, 55, 57, 58, 11 | 59, 60, 62, 63, 64, 66, 67, 69, 70, 72, 74, 75, 77, 79, 80, 82, 84, 86, 88, 90, 91, 94, 96, 98, 100, 102, 104, 107, 109, 111, 114, 116, 119, 122, 124, 127, 12 | 130, 133, 136, 139, 142, 145, 148, 151, 155, 158, 161, 165, 169, 172, 176, 180, 184, 188, 192, 196, 201, 205, 210, 214, 219, 224, 229, 234, 239, 244, 250, 255]; 13 | 14 | /** 15 | * mapper that uses the gamma correction table 16 | * @param value 17 | * @return integer 18 | */ 19 | module.exports = function (value) { 20 | return GAMMA_TABLE[value]; 21 | }; -------------------------------------------------------------------------------- /lib/util/ledToAddress.js: -------------------------------------------------------------------------------- 1 | var lookupTable = { 2 | l_0_0: 0, l_0_1: 1, l_0_2: 2, l_0_3: 3, l_0_4: 14, l_0_5: 12, 3 | l_1_0: 6, l_1_1: 7, l_1_2: 8, l_1_3: 5, l_1_4: 4, l_1_5: 9, 4 | l_2_0: 17, l_2_1: 16, l_2_2: 15, l_2_3: 13, l_2_4: 11, l_2_5: 10 5 | }; 6 | 7 | function map(key) { 8 | if (lookupTable[key] !== undefined) return lookupTable[key]; 9 | 10 | return null; 11 | } 12 | 13 | function mapAll(definition) { 14 | var result = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; 15 | 16 | Object.keys(definition).forEach(function (key) { 17 | var index; 18 | if ((index = map(key)) !== null) { 19 | result[index] = definition[key]; 20 | } 21 | }); 22 | 23 | return result; 24 | } 25 | 26 | module.exports = { 27 | map: map, 28 | mapAll: mapAll 29 | }; -------------------------------------------------------------------------------- /lib/util/valueProcessor.js: -------------------------------------------------------------------------------- 1 | var MAX_VALUE = 255; 2 | var MIN_VALUE = 0; 3 | 4 | /** 5 | * sanitizes brightness values and does a gamma correction mapping 6 | * @param value 7 | * @return {*} 8 | */ 9 | function processValue(value) { 10 | if (isNaN(value)) return 0; 11 | 12 | value = Math.max(MIN_VALUE, Math.min(value, MAX_VALUE)); 13 | 14 | //value is between 0 and 1, thus is interpreted as percentage 15 | if (value < 1) value = value * MAX_VALUE; 16 | 17 | value = parseInt(value, 10); 18 | 19 | return value; 20 | } 21 | 22 | processValue.MAX_VALUE = MAX_VALUE; 23 | processValue.MIN_VALUE = MIN_VALUE; 24 | 25 | module.exports = processValue; 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "piglow", 3 | "version": "3.0.1", 4 | "description": "javascript interface for the piglow", 5 | "main": "index.js", 6 | "author": "Manuel Ernst ", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/seriousManual/node-piglow" 10 | }, 11 | "license": "MIT", 12 | "dependencies": { 13 | "i2c": "0.2.3", 14 | "sigmund": "^1.0.0" 15 | }, 16 | "devDependencies": { 17 | "mocha": "^3.0.2", 18 | "chai": "^3.5.0", 19 | "sandboxed-module": "^2.0.3" 20 | }, 21 | "keywords": [ 22 | "pimoroni", 23 | "piglow", 24 | "raspberry pi", 25 | "led", 26 | "i2c" 27 | ], 28 | "scripts": { 29 | "test": "./node_modules/.bin/mocha tests --timeout 5000" 30 | }, 31 | "engine": { 32 | "node": ">=4" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /pics/piglow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seriousManual/node-piglow/2175fda7d56a779adb4aaec29e86cbc7745809ef/pics/piglow.jpg -------------------------------------------------------------------------------- /pics/piglow_leds.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seriousManual/node-piglow/2175fda7d56a779adb4aaec29e86cbc7745809ef/pics/piglow_leds.jpg -------------------------------------------------------------------------------- /pics/piglow_legs.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seriousManual/node-piglow/2175fda7d56a779adb4aaec29e86cbc7745809ef/pics/piglow_legs.jpg -------------------------------------------------------------------------------- /pics/piglow_rings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seriousManual/node-piglow/2175fda7d56a779adb4aaec29e86cbc7745809ef/pics/piglow_rings.jpg -------------------------------------------------------------------------------- /tests/piglowBackend.tests.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var sand = require('sandboxed-module'); 3 | 4 | function createI2cMock(throwError) { 5 | return function I2cMock(address, options) { 6 | this._addr = address; 7 | this._options = options; 8 | this._adresses = []; 9 | this._written = []; 10 | 11 | this.setAddress = function (address) { 12 | if (throwError) throw new Error('foo'); 13 | 14 | this._adresses.push(address); 15 | }; 16 | 17 | this.writeBytes = function (address, values, callback) { 18 | this._written.push([address, values]); 19 | 20 | process.nextTick(callback); 21 | }; 22 | }; 23 | } 24 | 25 | describe('piGlowBackend', function () { 26 | it('should initialize correctly', function (done) { 27 | var Backend = sand.require('../lib/PiGlowBackend', { 28 | requires: { 29 | 'i2c': createI2cMock() 30 | } 31 | }); 32 | 33 | new Backend() 34 | .on('initialize', function () { 35 | var data = this._wire; 36 | 37 | expect(data._addr).to.equal(84); 38 | expect(data._options).to.deep.equal({device: '/dev/i2c-1'}); 39 | expect(data._written).to.deep.equal([ 40 | [0, [1]], 41 | [19, [255, 255, 255]] 42 | ]); 43 | 44 | done(); 45 | }); 46 | }); 47 | 48 | it('should initialize and write bytes, should remap values, should do gamma correction', function (done) { 49 | var Backend = sand.require('../lib/PiGlowBackend', { 50 | requires: { 51 | 'i2c': createI2cMock() 52 | } 53 | }); 54 | 55 | new Backend() 56 | .on('initialize', function () { 57 | var that = this; 58 | 59 | this.update({ 60 | l_0_0: 100, l_0_1: 101, l_0_2: 102, l_0_3: 103, l_0_4: 104, l_0_5: 105, 61 | l_1_0: 150, l_1_1: 151, l_1_2: 152, l_1_3: 153, l_1_4: 154, l_1_5: 155, 62 | l_2_0: 200, l_2_1: 201, l_2_2: 202, l_2_3: 203, l_2_4: 204, l_2_5: 205 63 | }, function () { 64 | var data = that._wire; 65 | 66 | expect(data._addr).to.equal(84); 67 | expect(data._options).to.deep.equal({device: '/dev/i2c-1'}); 68 | expect(data._written).to.deep.equal([ 69 | [0, [1]], 70 | [19, [255, 255, 255]], 71 | [1, [8, 8, 9, 9, 28, 27, 26, 26, 27, 29, 86, 84, 9, 82, 9, 80, 79, 77 ]], 72 | [22, [255]] 73 | ]); 74 | 75 | done(); 76 | }); 77 | }); 78 | }); 79 | 80 | it('should initialize and write bytes, should remap values only once', function (done) { 81 | var Backend = sand.require('../lib/PiGlowBackend', { 82 | requires: { 83 | 'i2c': createI2cMock() 84 | } 85 | }); 86 | 87 | new Backend() 88 | .on('initialize', function () { 89 | var that = this; 90 | 91 | that.update({ 92 | l_0_0: 100, l_0_1: 101, l_0_2: 102, l_0_3: 103, l_0_4: 104, l_0_5: 105, 93 | l_1_0: 150, l_1_1: 151, l_1_2: 152, l_1_3: 153, l_1_4: 154, l_1_5: 155, 94 | l_2_0: 200, l_2_1: 201, l_2_2: 202, l_2_3: 203, l_2_4: 204, l_2_5: 205 95 | }, function () { 96 | that.update({ 97 | l_0_0: 100, l_0_1: 101, l_0_2: 102, l_0_3: 103, l_0_4: 104, l_0_5: 105, 98 | l_1_0: 150, l_1_1: 151, l_1_2: 152, l_1_3: 153, l_1_4: 154, l_1_5: 155, 99 | l_2_0: 200, l_2_1: 201, l_2_2: 202, l_2_3: 203, l_2_4: 204, l_2_5: 205 100 | }, function() { 101 | var data = that._wire; 102 | 103 | expect(data._addr).to.equal(84); 104 | expect(data._options).to.deep.equal({device: '/dev/i2c-1'}); 105 | expect(data._written).to.deep.equal([ 106 | [0, [1]], 107 | [19, [255, 255, 255]], 108 | [1, [8, 8, 9, 9, 28, 27, 26, 26, 27, 29, 86, 84, 9, 82, 9, 80, 79, 77 ]], 109 | [22, [255]] 110 | ]); 111 | 112 | done(); 113 | }); 114 | }); 115 | }); 116 | }); 117 | 118 | it('should throw', function (done) { 119 | var Backend = sand.require('../lib/PiGlowBackend', { 120 | requires: { 121 | 'i2c': createI2cMock(true) 122 | } 123 | }); 124 | 125 | new Backend() 126 | .on('error', function(error) { 127 | expect(error).not.to.be.null; 128 | expect(error.message).to.equal('foo'); 129 | 130 | done(); 131 | }); 132 | }); 133 | }); -------------------------------------------------------------------------------- /tests/piglowInterface.tests.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | 3 | var piGlowInterface = require('../lib/interface'); 4 | 5 | function createBackendMock() { 6 | return { 7 | values: [], 8 | update: function (bytes) { 9 | this.values.push(clone(bytes)); 10 | } 11 | }; 12 | } 13 | 14 | describe('interface', function () { 15 | var ti; 16 | 17 | beforeEach(function () { 18 | ti = piGlowInterface(); 19 | }); 20 | 21 | describe('single leds', function () { 22 | it('l_0_0 (shorthand)', function () { 23 | ti.l_0_0; 24 | expect(ti.values).to.deep.equal({ 25 | l_0_0: 255, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 26 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 27 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 28 | }); 29 | }); 30 | 31 | it('l_0_0', function () { 32 | ti.l_0_0 = 100; 33 | expect(ti.values).to.deep.equal({ 34 | l_0_0: 100, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 35 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 36 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 37 | }); 38 | }); 39 | 40 | it('l_0_1 (shorthand)', function () { 41 | ti.l_0_1; 42 | expect(ti.values).to.deep.equal({ 43 | l_0_0: 0, l_0_1: 255, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 44 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 45 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 46 | }); 47 | }); 48 | 49 | it('l_0_1', function () { 50 | ti.l_0_1 = 100; 51 | expect(ti.values).to.deep.equal({ 52 | l_0_0: 0, l_0_1: 100, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 53 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 54 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 55 | }); 56 | }); 57 | 58 | it('l_0_2 (shorthand)', function () { 59 | ti.l_0_2; 60 | expect(ti.values).to.deep.equal({ 61 | l_0_0: 0, l_0_1: 0, l_0_2: 255, l_0_3: 0, l_0_4: 0, l_0_5: 0, 62 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 63 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 64 | }); 65 | }); 66 | 67 | it('l_0_2', function () { 68 | ti.l_0_2 = 100; 69 | expect(ti.values).to.deep.equal({ 70 | l_0_0: 0, l_0_1: 0, l_0_2: 100, l_0_3: 0, l_0_4: 0, l_0_5: 0, 71 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 72 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 73 | }); 74 | }); 75 | 76 | it('l_0_3 (shorthand)', function () { 77 | ti.l_0_3; 78 | expect(ti.values).to.deep.equal({ 79 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 255, l_0_4: 0, l_0_5: 0, 80 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 81 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 82 | }); 83 | }); 84 | 85 | it('l_0_3', function () { 86 | ti.l_0_3 = 100; 87 | expect(ti.values).to.deep.equal({ 88 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 100, l_0_4: 0, l_0_5: 0, 89 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 90 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 91 | }); 92 | }); 93 | 94 | it('l_0_4 (shorthand)', function () { 95 | ti.l_0_4; 96 | expect(ti.values).to.deep.equal({ 97 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 255, l_0_5: 0, 98 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 99 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 100 | }); 101 | }); 102 | 103 | it('l_0_4', function () { 104 | ti.l_0_4 = 100; 105 | expect(ti.values).to.deep.equal({ 106 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 100, l_0_5: 0, 107 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 108 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 109 | }); 110 | }); 111 | 112 | it('l_0_5 (shorthand)', function () { 113 | ti.l_0_5; 114 | expect(ti.values).to.deep.equal({ 115 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 255, 116 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 117 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 118 | }); 119 | }); 120 | 121 | it('l_0_5', function () { 122 | ti.l_0_5 = 100; 123 | expect(ti.values).to.deep.equal({ 124 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 100, 125 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 126 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 127 | }); 128 | }); 129 | 130 | it('l_1_0 (shorthand)', function () { 131 | ti.l_1_0; 132 | expect(ti.values).to.deep.equal({ 133 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 134 | l_1_0: 255, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 135 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 136 | }); 137 | }); 138 | 139 | it('l_1_0', function () { 140 | ti.l_1_0 = 100; 141 | expect(ti.values).to.deep.equal({ 142 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 143 | l_1_0: 100, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 144 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 145 | }); 146 | }); 147 | 148 | it('l_1_1 (shorthand)', function () { 149 | ti.l_1_1; 150 | expect(ti.values).to.deep.equal({ 151 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 152 | l_1_0: 0, l_1_1: 255, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 153 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 154 | }); 155 | }); 156 | 157 | it('l_1_1', function () { 158 | ti.l_1_1 = 100; 159 | expect(ti.values).to.deep.equal({ 160 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 161 | l_1_0: 0, l_1_1: 100, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 162 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 163 | }); 164 | }); 165 | 166 | it('l_1_2 (shorthand)', function () { 167 | ti.l_1_2; 168 | expect(ti.values).to.deep.equal({ 169 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 170 | l_1_0: 0, l_1_1: 0, l_1_2: 255, l_1_3: 0, l_1_4: 0, l_1_5: 0, 171 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 172 | }); 173 | }); 174 | 175 | it('l_1_2', function () { 176 | ti.l_1_2 = 100; 177 | expect(ti.values).to.deep.equal({ 178 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 179 | l_1_0: 0, l_1_1: 0, l_1_2: 100, l_1_3: 0, l_1_4: 0, l_1_5: 0, 180 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 181 | }); 182 | }); 183 | 184 | it('l_1_3 (shorthand)', function () { 185 | ti.l_1_3; 186 | expect(ti.values).to.deep.equal({ 187 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 188 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 255, l_1_4: 0, l_1_5: 0, 189 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 190 | }); 191 | }); 192 | 193 | it('l_1_3', function () { 194 | ti.l_1_3 = 100; 195 | expect(ti.values).to.deep.equal({ 196 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 197 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 100, l_1_4: 0, l_1_5: 0, 198 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 199 | }); 200 | }); 201 | 202 | it('l_1_4 (shorthand)', function () { 203 | ti.l_1_4; 204 | expect(ti.values).to.deep.equal({ 205 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 206 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 255, l_1_5: 0, 207 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 208 | }); 209 | }); 210 | 211 | it('l_1_4', function () { 212 | ti.l_1_4 = 100; 213 | expect(ti.values).to.deep.equal({ 214 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 215 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 100, l_1_5: 0, 216 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 217 | }); 218 | }); 219 | 220 | it('l_1_5 (shorthand)', function () { 221 | ti.l_1_5; 222 | expect(ti.values).to.deep.equal({ 223 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 224 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 255, 225 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 226 | }); 227 | }); 228 | 229 | it('l_1_5', function () { 230 | ti.l_1_5 = 100; 231 | expect(ti.values).to.deep.equal({ 232 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 233 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 100, 234 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 235 | }); 236 | }); 237 | 238 | it('l_2_0 (shorthand)', function () { 239 | ti.l_2_0; 240 | expect(ti.values).to.deep.equal({ 241 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 242 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 243 | l_2_0: 255, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 244 | }); 245 | }); 246 | 247 | it('l_2_0', function () { 248 | ti.l_2_0 = 100; 249 | expect(ti.values).to.deep.equal({ 250 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 251 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 252 | l_2_0: 100, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 253 | }); 254 | }); 255 | 256 | it('l_2_1 (shorthand)', function () { 257 | ti.l_2_1; 258 | expect(ti.values).to.deep.equal({ 259 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 260 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 261 | l_2_0: 0, l_2_1: 255, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 262 | }); 263 | }); 264 | 265 | it('l_2_1', function () { 266 | ti.l_2_1 = 100; 267 | expect(ti.values).to.deep.equal({ 268 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 269 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 270 | l_2_0: 0, l_2_1: 100, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 271 | }); 272 | }); 273 | 274 | it('l_2_2 (shorthand)', function () { 275 | ti.l_2_2; 276 | expect(ti.values).to.deep.equal({ 277 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 278 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 279 | l_2_0: 0, l_2_1: 0, l_2_2: 255, l_2_3: 0, l_2_4: 0, l_2_5: 0 280 | }); 281 | }); 282 | 283 | it('l_2_2', function () { 284 | ti.l_2_2 = 100; 285 | expect(ti.values).to.deep.equal({ 286 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 287 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 288 | l_2_0: 0, l_2_1: 0, l_2_2: 100, l_2_3: 0, l_2_4: 0, l_2_5: 0 289 | }); 290 | }); 291 | 292 | it('l_2_3 (shorthand)', function () { 293 | ti.l_2_3; 294 | expect(ti.values).to.deep.equal({ 295 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 296 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 297 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 255, l_2_4: 0, l_2_5: 0 298 | }); 299 | }); 300 | 301 | it('l_2_3', function () { 302 | ti.l_2_3 = 100; 303 | expect(ti.values).to.deep.equal({ 304 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 305 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 306 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 100, l_2_4: 0, l_2_5: 0 307 | }); 308 | }); 309 | 310 | it('l_2_4 (shorthand)', function () { 311 | ti.l_2_4; 312 | expect(ti.values).to.deep.equal({ 313 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 314 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 315 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 255, l_2_5: 0 316 | }); 317 | }); 318 | 319 | it('l_2_4', function () { 320 | ti.l_2_4 = 100; 321 | expect(ti.values).to.deep.equal({ 322 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 323 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 324 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 100, l_2_5: 0 325 | }); 326 | }); 327 | 328 | it('l_2_5 (shorthand)', function () { 329 | ti.l_2_5; 330 | expect(ti.values).to.deep.equal({ 331 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 332 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 333 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 255 334 | }); 335 | }); 336 | 337 | it('l_2_5', function () { 338 | ti.l_2_5 = 100; 339 | expect(ti.values).to.deep.equal({ 340 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 341 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 342 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 100 343 | }); 344 | }); 345 | }); 346 | 347 | describe('legs', function () { 348 | it('leg_0 (shorthand)', function () { 349 | ti.leg_0; 350 | expect(ti.values).to.deep.equal({ 351 | l_0_0: 255, l_0_1: 255, l_0_2: 255, l_0_3: 255, l_0_4: 255, l_0_5: 255, 352 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 353 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 354 | }); 355 | }); 356 | 357 | it('leg_0', function () { 358 | ti.leg_0 = 100; 359 | expect(ti.values).to.deep.equal({ 360 | l_0_0: 100, l_0_1: 100, l_0_2: 100, l_0_3: 100, l_0_4: 100, l_0_5: 100, 361 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 362 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 363 | }); 364 | }); 365 | 366 | it('leg_1 (shorthand)', function () { 367 | ti.leg_1; 368 | expect(ti.values).to.deep.equal({ 369 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 370 | l_1_0: 255, l_1_1: 255, l_1_2: 255, l_1_3: 255, l_1_4: 255, l_1_5: 255, 371 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 372 | }); 373 | }); 374 | 375 | it('leg_1', function () { 376 | ti.leg_1 = 100; 377 | expect(ti.values).to.deep.equal({ 378 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 379 | l_1_0: 100, l_1_1: 100, l_1_2: 100, l_1_3: 100, l_1_4: 100, l_1_5: 100, 380 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 381 | }); 382 | }); 383 | 384 | it('leg_2 (shorthand)', function () { 385 | ti.leg_2; 386 | expect(ti.values).to.deep.equal({ 387 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 388 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 389 | l_2_0: 255, l_2_1: 255, l_2_2: 255, l_2_3: 255, l_2_4: 255, l_2_5: 255 390 | }); 391 | }); 392 | 393 | it('leg_2', function () { 394 | ti.leg_2 = 100; 395 | expect(ti.values).to.deep.equal({ 396 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 397 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 398 | l_2_0: 100, l_2_1: 100, l_2_2: 100, l_2_3: 100, l_2_4: 100, l_2_5: 100 399 | }); 400 | }); 401 | }); 402 | 403 | describe('rings', function () { 404 | it('ring_0 (shorthand)', function () { 405 | ti.ring_0; 406 | expect(ti.values).to.deep.equal({ 407 | l_0_0: 255, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 408 | l_1_0: 255, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 409 | l_2_0: 255, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 410 | }); 411 | }); 412 | it('ring_0', function () { 413 | ti.ring_0 = 100; 414 | expect(ti.values).to.deep.equal({ 415 | l_0_0: 100, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 416 | l_1_0: 100, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 417 | l_2_0: 100, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 418 | }); 419 | }); 420 | it('red (shorthand)', function () { 421 | ti.red; 422 | expect(ti.values).to.deep.equal({ 423 | l_0_0: 255, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 424 | l_1_0: 255, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 425 | l_2_0: 255, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 426 | }); 427 | }); 428 | it('red', function () { 429 | ti.red = 100; 430 | expect(ti.values).to.deep.equal({ 431 | l_0_0: 100, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 432 | l_1_0: 100, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 433 | l_2_0: 100, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 434 | }); 435 | }); 436 | 437 | 438 | it('ring_1 (shorthand)', function () { 439 | ti.ring_1; 440 | expect(ti.values).to.deep.equal({ 441 | l_0_0: 0, l_0_1: 255, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 442 | l_1_0: 0, l_1_1: 255, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 443 | l_2_0: 0, l_2_1: 255, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 444 | }); 445 | }); 446 | it('ring_1', function () { 447 | ti.ring_1 = 100; 448 | expect(ti.values).to.deep.equal({ 449 | l_0_0: 0, l_0_1: 100, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 450 | l_1_0: 0, l_1_1: 100, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 451 | l_2_0: 0, l_2_1: 100, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 452 | }); 453 | }); 454 | it('orange (shorthand)', function () { 455 | ti.orange; 456 | expect(ti.values).to.deep.equal({ 457 | l_0_0: 0, l_0_1: 255, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 458 | l_1_0: 0, l_1_1: 255, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 459 | l_2_0: 0, l_2_1: 255, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 460 | }); 461 | }); 462 | it('orange', function () { 463 | ti.orange = 100; 464 | expect(ti.values).to.deep.equal({ 465 | l_0_0: 0, l_0_1: 100, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 466 | l_1_0: 0, l_1_1: 100, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 467 | l_2_0: 0, l_2_1: 100, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 468 | }); 469 | }); 470 | 471 | 472 | it('ring_2 (shorthand)', function () { 473 | ti.ring_2; 474 | expect(ti.values).to.deep.equal({ 475 | l_0_0: 0, l_0_1: 0, l_0_2: 255, l_0_3: 0, l_0_4: 0, l_0_5: 0, 476 | l_1_0: 0, l_1_1: 0, l_1_2: 255, l_1_3: 0, l_1_4: 0, l_1_5: 0, 477 | l_2_0: 0, l_2_1: 0, l_2_2: 255, l_2_3: 0, l_2_4: 0, l_2_5: 0 478 | }); 479 | }); 480 | it('ring_2', function () { 481 | ti.ring_2 = 100; 482 | expect(ti.values).to.deep.equal({ 483 | l_0_0: 0, l_0_1: 0, l_0_2: 100, l_0_3: 0, l_0_4: 0, l_0_5: 0, 484 | l_1_0: 0, l_1_1: 0, l_1_2: 100, l_1_3: 0, l_1_4: 0, l_1_5: 0, 485 | l_2_0: 0, l_2_1: 0, l_2_2: 100, l_2_3: 0, l_2_4: 0, l_2_5: 0 486 | }); 487 | }); 488 | it('yellow (shorthand)', function () { 489 | ti.yellow; 490 | expect(ti.values).to.deep.equal({ 491 | l_0_0: 0, l_0_1: 0, l_0_2: 255, l_0_3: 0, l_0_4: 0, l_0_5: 0, 492 | l_1_0: 0, l_1_1: 0, l_1_2: 255, l_1_3: 0, l_1_4: 0, l_1_5: 0, 493 | l_2_0: 0, l_2_1: 0, l_2_2: 255, l_2_3: 0, l_2_4: 0, l_2_5: 0 494 | }); 495 | }); 496 | it('yellow', function () { 497 | ti.yellow = 100; 498 | expect(ti.values).to.deep.equal({ 499 | l_0_0: 0, l_0_1: 0, l_0_2: 100, l_0_3: 0, l_0_4: 0, l_0_5: 0, 500 | l_1_0: 0, l_1_1: 0, l_1_2: 100, l_1_3: 0, l_1_4: 0, l_1_5: 0, 501 | l_2_0: 0, l_2_1: 0, l_2_2: 100, l_2_3: 0, l_2_4: 0, l_2_5: 0 502 | }); 503 | }); 504 | 505 | 506 | it('ring_3 (shorthand)', function () { 507 | ti.ring_3; 508 | expect(ti.values).to.deep.equal({ 509 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 255, l_0_4: 0, l_0_5: 0, 510 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 255, l_1_4: 0, l_1_5: 0, 511 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 255, l_2_4: 0, l_2_5: 0 512 | }); 513 | }); 514 | it('ring_3', function () { 515 | ti.ring_3 = 100; 516 | expect(ti.values).to.deep.equal({ 517 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 100, l_0_4: 0, l_0_5: 0, 518 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 100, l_1_4: 0, l_1_5: 0, 519 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 100, l_2_4: 0, l_2_5: 0 520 | }); 521 | }); 522 | it('green (shorthand)', function () { 523 | ti.green; 524 | expect(ti.values).to.deep.equal({ 525 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 255, l_0_4: 0, l_0_5: 0, 526 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 255, l_1_4: 0, l_1_5: 0, 527 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 255, l_2_4: 0, l_2_5: 0 528 | }); 529 | }); 530 | it('green', function () { 531 | ti.green = 100; 532 | expect(ti.values).to.deep.equal({ 533 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 100, l_0_4: 0, l_0_5: 0, 534 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 100, l_1_4: 0, l_1_5: 0, 535 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 100, l_2_4: 0, l_2_5: 0 536 | }); 537 | }); 538 | 539 | 540 | it('ring_4 (shorthand)', function () { 541 | ti.ring_4; 542 | expect(ti.values).to.deep.equal({ 543 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 255, l_0_5: 0, 544 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 255, l_1_5: 0, 545 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 255, l_2_5: 0 546 | }); 547 | }); 548 | it('ring_4', function () { 549 | ti.ring_4 = 100; 550 | expect(ti.values).to.deep.equal({ 551 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 100, l_0_5: 0, 552 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 100, l_1_5: 0, 553 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 100, l_2_5: 0 554 | }); 555 | }); 556 | it('blue (shorthand)', function () { 557 | ti.blue; 558 | expect(ti.values).to.deep.equal({ 559 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 255, l_0_5: 0, 560 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 255, l_1_5: 0, 561 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 255, l_2_5: 0 562 | }); 563 | }); 564 | it('blue', function () { 565 | ti.blue = 100; 566 | expect(ti.values).to.deep.equal({ 567 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 100, l_0_5: 0, 568 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 100, l_1_5: 0, 569 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 100, l_2_5: 0 570 | }); 571 | }); 572 | 573 | 574 | it('ring_5 (shorthand)', function () { 575 | ti.ring_5; 576 | expect(ti.values).to.deep.equal({ 577 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 255, 578 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 255, 579 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 255 580 | }); 581 | }); 582 | it('ring_5', function () { 583 | ti.ring_5 = 100; 584 | expect(ti.values).to.deep.equal({ 585 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 100, 586 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 100, 587 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 100 588 | }); 589 | }); 590 | it('white (shorthand)', function () { 591 | ti.white; 592 | expect(ti.values).to.deep.equal({ 593 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 255, 594 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 255, 595 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 255 596 | }); 597 | }); 598 | it('white', function () { 599 | ti.white = 100; 600 | expect(ti.values).to.deep.equal({ 601 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 100, 602 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 100, 603 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 100 604 | }); 605 | }); 606 | }); 607 | 608 | describe('all', function () { 609 | it('all', function () { 610 | ti.all = 100; 611 | expect(ti.values).to.deep.equal({ 612 | l_0_0: 100, l_0_1: 100, l_0_2: 100, l_0_3: 100, l_0_4: 100, l_0_5: 100, 613 | l_1_0: 100, l_1_1: 100, l_1_2: 100, l_1_3: 100, l_1_4: 100, l_1_5: 100, 614 | l_2_0: 100, l_2_1: 100, l_2_2: 100, l_2_3: 100, l_2_4: 100, l_2_5: 100 615 | }); 616 | }); 617 | 618 | it('all (shorthand)', function () { 619 | ti.all; 620 | expect(ti.values).to.deep.equal({ 621 | l_0_0: 255, l_0_1: 255, l_0_2: 255, l_0_3: 255, l_0_4: 255, l_0_5: 255, 622 | l_1_0: 255, l_1_1: 255, l_1_2: 255, l_1_3: 255, l_1_4: 255, l_1_5: 255, 623 | l_2_0: 255, l_2_1: 255, l_2_2: 255, l_2_3: 255, l_2_4: 255, l_2_5: 255 624 | }); 625 | }); 626 | 627 | it('reset', function () { 628 | ti.all = 100; 629 | expect(ti.values).to.deep.equal({ 630 | l_0_0: 100, l_0_1: 100, l_0_2: 100, l_0_3: 100, l_0_4: 100, l_0_5: 100, 631 | l_1_0: 100, l_1_1: 100, l_1_2: 100, l_1_3: 100, l_1_4: 100, l_1_5: 100, 632 | l_2_0: 100, l_2_1: 100, l_2_2: 100, l_2_3: 100, l_2_4: 100, l_2_5: 100 633 | }); 634 | ti.reset; 635 | expect(ti.values).to.deep.equal({ 636 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 637 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 638 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 639 | }); 640 | }); 641 | }); 642 | 643 | describe('backend', function () { 644 | it('should write to the backend', function () { 645 | var mock = createBackendMock(); 646 | 647 | var ti = piGlowInterface(mock); 648 | ti.all = 100; 649 | 650 | expect(mock.values).to.deep.equal([ 651 | { 652 | l_0_0: 100, l_0_1: 100, l_0_2: 100, l_0_3: 100, l_0_4: 100, l_0_5: 100, 653 | l_1_0: 100, l_1_1: 100, l_1_2: 100, l_1_3: 100, l_1_4: 100, l_1_5: 100, 654 | l_2_0: 100, l_2_1: 100, l_2_2: 100, l_2_3: 100, l_2_4: 100, l_2_5: 100 655 | } 656 | ]); 657 | }); 658 | 659 | it('should write to the backend (multiple times)', function () { 660 | var mock = createBackendMock(); 661 | 662 | var ti = piGlowInterface(mock); 663 | ti.leg_0 = 100; 664 | ti.leg_1 = 100; 665 | ti.leg_2 = 100; 666 | 667 | expect(mock.values).to.deep.equal([ 668 | { 669 | l_0_0: 100, l_0_1: 100, l_0_2: 100, l_0_3: 100, l_0_4: 100, l_0_5: 100, 670 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 671 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 672 | }, 673 | { 674 | l_0_0: 100, l_0_1: 100, l_0_2: 100, l_0_3: 100, l_0_4: 100, l_0_5: 100, 675 | l_1_0: 100, l_1_1: 100, l_1_2: 100, l_1_3: 100, l_1_4: 100, l_1_5: 100, 676 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 677 | }, 678 | { 679 | l_0_0: 100, l_0_1: 100, l_0_2: 100, l_0_3: 100, l_0_4: 100, l_0_5: 100, 680 | l_1_0: 100, l_1_1: 100, l_1_2: 100, l_1_3: 100, l_1_4: 100, l_1_5: 100, 681 | l_2_0: 100, l_2_1: 100, l_2_2: 100, l_2_3: 100, l_2_4: 100, l_2_5: 100 682 | } 683 | ]); 684 | }); 685 | 686 | it('should write to the backend (one time)', function () { 687 | var mock = createBackendMock(); 688 | 689 | var ti = piGlowInterface(mock); 690 | ti.startTransaction(); 691 | ti.leg_0 = 100; 692 | ti.leg_1 = 100; 693 | ti.leg_2 = 100; 694 | ti.commitTransaction(); 695 | 696 | expect(mock.values).to.deep.equal([ 697 | { 698 | l_0_0: 100, l_0_1: 100, l_0_2: 100, l_0_3: 100, l_0_4: 100, l_0_5: 100, 699 | l_1_0: 100, l_1_1: 100, l_1_2: 100, l_1_3: 100, l_1_4: 100, l_1_5: 100, 700 | l_2_0: 100, l_2_1: 100, l_2_2: 100, l_2_3: 100, l_2_4: 100, l_2_5: 100 701 | } 702 | ]); 703 | }); 704 | 705 | //TODO: add tests for mulitple transaction levels 706 | }); 707 | 708 | describe('predefined', function () { 709 | it('should write to the backend, the predefined stuff (object)', function () { 710 | var mock = createBackendMock(); 711 | 712 | piGlowInterface(mock, {ring_1: 100}); 713 | 714 | expect(mock.values).to.deep.equal([ 715 | { 716 | l_0_0: 0, l_0_1: 100, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 717 | l_1_0: 0, l_1_1: 100, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 718 | l_2_0: 0, l_2_1: 100, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 719 | } 720 | ]); 721 | }); 722 | 723 | it('should write to the backend, the predefined stuff (array)', function () { 724 | var mock = createBackendMock(); 725 | 726 | piGlowInterface(mock, ['ring_2']); 727 | 728 | expect(mock.values).to.deep.equal([ 729 | { 730 | l_0_0: 0, l_0_1: 0, l_0_2: 255, l_0_3: 0, l_0_4: 0, l_0_5: 0, 731 | l_1_0: 0, l_1_1: 0, l_1_2: 255, l_1_3: 0, l_1_4: 0, l_1_5: 0, 732 | l_2_0: 0, l_2_1: 0, l_2_2: 255, l_2_3: 0, l_2_4: 0, l_2_5: 0 733 | } 734 | ]); 735 | }); 736 | 737 | it('should write multiple predefineds encased in a transaction', function () { 738 | var mock = createBackendMock(); 739 | 740 | piGlowInterface(mock, ['ring_2', 'ring_5']); 741 | 742 | expect(mock.values).to.deep.equal([ 743 | { 744 | l_0_0: 0, l_0_1: 0, l_0_2: 255, l_0_3: 0, l_0_4: 0, l_0_5: 255, 745 | l_1_0: 0, l_1_1: 0, l_1_2: 255, l_1_3: 0, l_1_4: 0, l_1_5: 255, 746 | l_2_0: 0, l_2_1: 0, l_2_2: 255, l_2_3: 0, l_2_4: 0, l_2_5: 255 747 | } 748 | ]); 749 | }); 750 | }); 751 | 752 | describe('random', function () { 753 | it('should output random data', function () { 754 | ti.random = 0.5; 755 | 756 | expect(ti.values).to.satisfy(function (values) { 757 | var a = Object.keys(values).reduce(function (memo, key) { 758 | var value = ti.values[key]; 759 | 760 | if (value > 0) { 761 | memo.a++; 762 | } else { 763 | memo.z++; 764 | } 765 | 766 | return memo; 767 | }, {z: 0, a: 0}); 768 | 769 | return a.z > 0 && a.a > 0; 770 | }); 771 | }); 772 | 773 | it('should set unchoosen values to zero', function () { 774 | ti.all = 123; 775 | ti.random = 0.999999999; 776 | 777 | expect(ti.values).to.deep.equal({ 778 | l_0_0: 0, l_0_1: 0, l_0_2: 0, l_0_3: 0, l_0_4: 0, l_0_5: 0, 779 | l_1_0: 0, l_1_1: 0, l_1_2: 0, l_1_3: 0, l_1_4: 0, l_1_5: 0, 780 | l_2_0: 0, l_2_1: 0, l_2_2: 0, l_2_3: 0, l_2_4: 0, l_2_5: 0 781 | }); 782 | }); 783 | }); 784 | }); 785 | 786 | function clone(obj) { 787 | var res = {}; 788 | 789 | Object.keys(obj).forEach(function(key) { 790 | res[key] = obj[key]; 791 | }); 792 | 793 | return res; 794 | } 795 | -------------------------------------------------------------------------------- /tests/util.tests.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | 3 | var gammaCorrection = require('../lib/util/gammaCorrection'); 4 | var processValue = require('../lib/util/valueProcessor'); 5 | var ledMapper = require('../lib/util/ledToAddress'); 6 | 7 | describe('util', function () { 8 | describe('gamma', function () { 9 | it('should map the gamma value (1)', function () { 10 | expect(gammaCorrection(0)).to.equal(0); 11 | }); 12 | 13 | it('should map the gamma value (10)', function () { 14 | expect(gammaCorrection(10)).to.equal(1); 15 | }); 16 | 17 | it('should map the gamma value (50)', function () { 18 | expect(gammaCorrection(50)).to.equal(2); 19 | }); 20 | 21 | it('should map the gamma value (100)', function () { 22 | expect(gammaCorrection(100)).to.equal(8); 23 | }); 24 | 25 | it('should map the gamma value (150)', function () { 26 | expect(gammaCorrection(150)).to.equal(26); 27 | }); 28 | 29 | it('should map the gamma value (200)', function () { 30 | expect(gammaCorrection(200)).to.equal(77); 31 | }); 32 | 33 | it('should map the gamma value (220)', function () { 34 | expect(gammaCorrection(220)).to.equal(119); 35 | }); 36 | 37 | it('should map the gamma value (230)', function () { 38 | expect(gammaCorrection(230)).to.equal(148); 39 | }); 40 | 41 | it('should map the gamma value (255)', function () { 42 | expect(gammaCorrection(255)).to.equal(255); 43 | }); 44 | 45 | }); 46 | 47 | describe('valueProcess', function () { 48 | 49 | it('should clamp value, max', function () { 50 | expect(processValue(1000)).to.equal(processValue.MAX_VALUE); 51 | }); 52 | 53 | it('should clamp value, min', function () { 54 | expect(processValue(-999)).to.equal(processValue.MIN_VALUE); 55 | }); 56 | 57 | it('should only allow integers (>1)', function () { 58 | expect(processValue(1.337)).to.equal(1); 59 | }); 60 | 61 | describe('percentages', function () { 62 | it('should interprete numbers < 1 as percents, 10%', function () { 63 | expect(processValue(0.1)).to.equal(25); 64 | }); 65 | 66 | it('should interprete numbers < 1 as percents, 50%', function () { 67 | expect(processValue(0.5)).to.equal(127); 68 | }); 69 | 70 | it('should interprete numbers < 1 as percents, 99%', function () { 71 | expect(processValue(0.99)).to.equal(252); 72 | }); 73 | 74 | it('should not interprete 1 as an percentage value', function () { 75 | expect(processValue(1)).to.equal(1); 76 | }); 77 | }); 78 | 79 | describe('errors', function () { 80 | it('should only allow numbers (no string)', function () { 81 | expect(processValue('foo')).to.equal(0); 82 | }); 83 | 84 | it('should only allow integers (no objects)', function () { 85 | expect(processValue({})).to.equal(0); 86 | }); 87 | 88 | it('should only allow integers (no arrays)', function () { 89 | expect(processValue([])).to.equal(0); 90 | }); 91 | }); 92 | 93 | }); 94 | 95 | describe('ledMapper', function () { 96 | it('should map', function () { 97 | expect(ledMapper.map('l_0_0')).to.equal(0); 98 | expect(ledMapper.map('l_0_1')).to.equal(1); 99 | expect(ledMapper.map('l_0_2')).to.equal(2); 100 | expect(ledMapper.map('l_0_3')).to.equal(3); 101 | expect(ledMapper.map('l_0_4')).to.equal(14); 102 | expect(ledMapper.map('l_0_5')).to.equal(12); 103 | expect(ledMapper.map('l_1_0')).to.equal(6); 104 | expect(ledMapper.map('l_1_1')).to.equal(7); 105 | expect(ledMapper.map('l_1_2')).to.equal(8); 106 | expect(ledMapper.map('l_1_3')).to.equal(5); 107 | expect(ledMapper.map('l_1_4')).to.equal(4); 108 | expect(ledMapper.map('l_1_5')).to.equal(9); 109 | expect(ledMapper.map('l_2_0')).to.equal(17); 110 | expect(ledMapper.map('l_2_1')).to.equal(16); 111 | expect(ledMapper.map('l_2_2')).to.equal(15); 112 | expect(ledMapper.map('l_2_3')).to.equal(13); 113 | expect(ledMapper.map('l_2_4')).to.equal(11); 114 | expect(ledMapper.map('l_2_5')).to.equal(10); 115 | }); 116 | 117 | it('should return null', function () { 118 | expect(ledMapper.map('foo')).to.be.null; 119 | }); 120 | 121 | it('should map complete configuration', function () { 122 | expect(ledMapper.mapAll({ 123 | l_0_0: 1, l_0_1: 2, l_0_2: 3, l_0_3: 4, l_0_4: 5, l_0_5: 6, 124 | l_1_0: 7, l_1_1: 8, l_1_2: 9, l_1_3: 10, l_1_4: 11, l_1_5: 12, 125 | l_2_0: 13, l_2_1: 14, l_2_2: 15, l_2_3: 16, l_2_4: 17, l_2_5: 18 126 | })).to.deep.equal([1, 2, 3, 4, 11, 10, 7, 8, 9, 12, 18, 17, 6, 16, 5, 15, 14, 13]); 127 | }); 128 | }); 129 | }); --------------------------------------------------------------------------------