From e544653fe361ab23d66680519da6281b5a8c4957 Mon Sep 17 00:00:00 2001 From: Sean Teague Date: Sun, 14 Jan 2018 23:46:21 -0800 Subject: [PATCH 1/5] Reworked API to use Promises instead of callbacks --- blink1.js | 615 ++++++++++++++++------------ package.json | 1 + unit-tests.js | 1072 +++++++++++++++++++++++++++++++++++-------------- 3 files changed, 1120 insertions(+), 568 deletions(-) diff --git a/blink1.js b/blink1.js index ae09bbc..6b3ed27 100644 --- a/blink1.js +++ b/blink1.js @@ -1,321 +1,422 @@ -var HID = require('node-hid'); +const HID = require('node-hid'); +const _ = require('lodash'); -var VENDOR_ID = 0x27B8; -var PRODUCT_ID = 0x01ED; +const VENDOR_ID = 0x27B8; +const PRODUCT_ID = 0x01ED; -var REPORT_ID = 1; -var REPORT_LENGTH = 9; +const REPORT_ID = 1; +const REPORT_LENGTH = 9; -var _blink1HIDdevices = function() { - return HID.devices(VENDOR_ID, PRODUCT_ID); +let _blink1HIDdevices = () => { + return HID.devices(VENDOR_ID, PRODUCT_ID); }; -var devices = function() { - var serialNumbers = []; - - _blink1HIDdevices().forEach(function(device) { - serialNumbers.push(device.serialNumber); - }); - - return serialNumbers; +let devices = () => { + return _.map(_blink1HIDdevices(), ({ serialNumber }) => serialNumber); }; -function Blink1(serialNumber) { - var blink1HIDdevices = _blink1HIDdevices(); - - if (blink1HIDdevices.length === 0) { - throw new Error('No blink(1)\'s could be found'); - } - - var blink1HIDdevicePath = null; - - if (serialNumber === undefined) { - serialNumber = blink1HIDdevices[0].serialNumber; - } - - blink1HIDdevices.some(function(blink1HIDdevice) { - if (serialNumber === blink1HIDdevice.serialNumber) { - blink1HIDdevicePath = blink1HIDdevice.path; - } - - return (blink1HIDdevicePath !== null); - }); - - if (blink1HIDdevicePath === null) { - throw new Error('No blink(1)\'s with serial number ' + serialNumber + ' could be found'); - } +class Blink1 { + constructor(serialNumber) { + let blink1HIDdevices = _blink1HIDdevices(); - this.serialNumber = serialNumber; - this.hidDevice = new HID.HID(blink1HIDdevicePath); -} - -Blink1.prototype._sendCommand = function(/* command [, args ...]*/) { - var featureReport = [REPORT_ID, 0, 0, 0, 0, 0, 0, 0, 0]; + if (blink1HIDdevices.length === 0) { + throw new Error('No blink(1)\'s could be found'); + } - featureReport[1] = arguments[0].charCodeAt(0); + var blink1HIDdevicePath = null; - for (var i = 1; i < arguments.length; i++) { - featureReport[i + 1] = arguments[i]; - } + if (serialNumber === undefined) { + serialNumber = blink1HIDdevices[0].serialNumber; + } - this.hidDevice.sendFeatureReport(featureReport); -}; - -Blink1.prototype._isValidCallback = function(callback) { - return (typeof callback === 'function'); -}; - -Blink1.prototype._validateNumber = function(number, name, min, max) { - if (typeof number !== 'number') { - throw new Error(name + ' must be a number'); - } - - if (number < min || number > max) { - throw new Error(name + ' must be between ' + min + ' and ' + max); - } -}; - -Blink1.prototype._validateAddress = function(address) { - this._validateNumber(address, 'address', 0, 0xffff); -}; - -Blink1.prototype._validateValue = function(value) { - this._validateNumber(value, 'value', 0, 0xff); -}; - -Blink1.prototype._validateCount = function(value) { - this._validateNumber(value, 'count', 0, 0xff); -}; + _.find(blink1HIDdevices, (blink1HIDdevice) => { + if (serialNumber === blink1HIDdevice.serialNumber) { + blink1HIDdevicePath = blink1HIDdevice.path; + } -Blink1.prototype._validateFadeMillis = function(fadeMillis) { - this._validateNumber(fadeMillis, 'fadeMillis', 0, 0x9FFF6); -}; + return (blink1HIDdevicePath !== null); + }); -Blink1.prototype._validateRGB = function(r, g, b) { - this._validateNumber(r, 'r', 0, 0xff); - this._validateNumber(g, 'g', 0, 0xff); - this._validateNumber(b, 'b', 0, 0xff); -}; + if (blink1HIDdevicePath === null) { + throw new Error('No blink(1)\'s with serial number ' + serialNumber + ' could be found'); + } -Blink1.prototype._validateMillis = function(millis) { - this._validateNumber(millis, 'millis', 0, 0x9FFF6); -}; + this.serialNumber = serialNumber; + this.hidDevice = new HID.HID(blink1HIDdevicePath); -Blink1.prototype._validatePosition = function(position) { - this._validateNumber(position, 'position', 0, 11); -}; + this.doDegamma = true; + } -Blink1.prototype._validateIndex = function(index) { - this._validateNumber(index, 'index', 0, 2); -}; + // Hardware API -Blink1.prototype._readResponse = function(callback) { - if (this._isValidCallback(callback)) { - callback.apply(this, [this.hidDevice.getFeatureReport(REPORT_ID, REPORT_LENGTH)]); - } -}; + _sendCommand(/* command [, args ...]*/) { + var featureReport = [REPORT_ID, 0, 0, 0, 0, 0, 0, 0, 0]; -Blink1.prototype.version = function(callback) { - this._sendCommand('v'); + _.forEach(arguments, (argument, k) => { + if (k === 0) { + featureReport[1] = argument.charCodeAt(0); + return; + } - this._readResponse(function(response) { - var version = String.fromCharCode(response[3]) + '.' + String.fromCharCode(response[4]); + featureReport[k + 1] = argument; + }); - if(this._isValidCallback(callback)) { - callback(version); + this.hidDevice.sendFeatureReport(featureReport); } - }); -}; - -Blink1.prototype.eeRead = function(address, callback) { - this._validateAddress(address); - this._sendCommand('e', address); - - this._readResponse(function(response) { - var value = response[3]; - - if(this._isValidCallback(callback)) { - callback(value); + _readResponse() { + return new Promise(resolve => { + resolve(this.hidDevice.getFeatureReport(REPORT_ID, REPORT_LENGTH)); + }); } - }); -}; - -Blink1.prototype.eeWrite = function(address, value, callback) { - this._validateAddress(address); - this._validateValue(value); - - this._sendCommand('E', address, value); - - if(this._isValidCallback(callback)) { - callback(); - } -}; - -Blink1.prototype.degamma = function(n) { - return Math.floor(((1 << Math.floor(n / 32)) - 1) + - Math.floor((1 << Math.floor(n / 32)) * Math.floor((n % 32) + 1) + 15) / 32); -}; - - -Blink1.prototype.fadeToRGB = function(fadeMillis, r, g, b, index, callback) { - this._validateFadeMillis(fadeMillis); - this._validateRGB(r, g, b); - - var dms = fadeMillis / 10; - - if (this._isValidCallback(index)) { - // backwards compatible API, no index - callback = index; - index = 0; - } else if (index === undefined) { - index = 0; - } - - this._validateIndex(index); - this._sendCommand('c', this.degamma(r), this.degamma(g), this.degamma(b), dms >> 8, dms % 0xff, index); + // Helpers - if(this._isValidCallback(callback)) { - setTimeout(callback, fadeMillis); - } -}; - -Blink1.prototype.setRGB = function(r, g, b, callback) { - this._validateRGB(r, g, b); + _isValidCallback(callback) { + return (typeof callback === 'function'); + } - this._sendCommand('n', this.degamma(r), this.degamma(g), this.degamma(b)); + _serverDown(on, delay) { + return new Promise(resolve => { + let dms = delay / 10; + this._sendCommand('D', on, dms >> 8, dms % 0xff); - if(this._isValidCallback(callback)) { - callback(); - } -}; + setTimeout(resolve, delay); + }); + } + _play(play, position) { + return new Promise(resolve => { + this._sendCommand('p', play, position); + resolve(); + }); + } -Blink1.prototype.off = function(callback) { - this.setRGB(0, 0, 0, callback); -}; + _playLoop({ + play, + start, + end, + count + }) { + return new Promise(resolve => { + this._sendCommand('p', play, start, end, count); + resolve(); + }); + } -Blink1.prototype.rgb = function(index, callback) { - if (this._isValidCallback(index)) { - callback = index; - index = 0; - } else if (index === undefined) { - index = 0; - } + // Validators - this._sendCommand('r', index, 0, 0, 0, 0, index); + _validateNumber(number, name, min, max) { + if (typeof number !== 'number') { + throw new Error(name + ' must be a number'); + } - this._readResponse(function(response) { - var r = response[2]; - var g = response[3]; - var b = response[4]; + if (number < min || number > max) { + throw new Error(name + ' must be between ' + min + ' and ' + max); + } + } - if(this._isValidCallback(callback)) { - callback(r, g, b); + _validateAddress(address) { + this._validateNumber(address, 'address', 0, 0xffff); // Decimal 0 - 65535 } - }); -}; -Blink1.prototype._serverDown = function(on, millis, callback) { - var dms = millis / 10; + _validateValue(value) { + this._validateNumber(value, 'value', 0, 0xff); // Decimal 0 - 255 + } - this._sendCommand('D', on, dms >> 8, dms % 0xff); + _validateCount(value) { + this._validateNumber(value, 'count', 0, 0xff); // Decimal 0 - 255 + } - if(this._isValidCallback(callback)) { - setTimeout(callback, millis); - } -}; + _validateFadeMillis(fadeMillis) { + this._validateNumber(fadeMillis, 'fadeMillis', 0, 0x9FFF6); // Decimal 0 - 655350 + } -Blink1.prototype.enableServerDown = function(millis, callback) { - this._validateMillis(millis); + _validateRGB(r, g, b) { + this._validateNumber(r, 'r', 0, 0xff); // Decimal 0 - 255 + this._validateNumber(g, 'g', 0, 0xff); // Decimal 0 - 255 + this._validateNumber(b, 'b', 0, 0xff); // Decimal 0 - 255 + } - this._serverDown(1, millis, callback); -}; + _validateMillis(millis) { + this._validateNumber(millis, 'millis', 0, 0x9FFF6); // Decimal 0 - 655350 + } -Blink1.prototype.disableServerDown = function(millis, callback) { - this._validateMillis(millis); + _validatePosition(position) { + this._validateNumber(position, 'position', 0, 11); + } - this._serverDown(0, millis, callback); -}; + _validateIndex(index) { + this._validateNumber(index, 'index', 0, 2); + } -Blink1.prototype._play = function(play, position, callback) { - this._sendCommand('p', play, position); + // API - if(this._isValidCallback(callback)) { - callback(); - } -}; + version() { + return new Promise(resolve => { + this._sendCommand('v'); -Blink1.prototype.play = function(position, callback) { - this._validatePosition(position); + this._readResponse().then(response => { + resolve(String.fromCharCode(response[3]) + '.' + String.fromCharCode(response[4])); + }); + }); + } - this._play(1, position, callback); -}; + eeRead(address) { + return new Promise((resolve, reject) => { + try { + this._validateAddress(address); + } catch(error) { + reject(error); + } -Blink1.prototype._playLoop = function(play, position, endPosition, count, callback) { - this._sendCommand('p', play, position, endPosition, count); + this._sendCommand('e', address); - if(this._isValidCallback(callback)) { - callback(); - } -}; + this._readResponse().then(response => { + resolve(response[3]); + }); + }); + } -Blink1.prototype.playLoop = function(startPosition, endPosition, count, callback) { - this._validatePosition(startPosition); - this._validatePosition(endPosition); - this._validateCount(count); + eeWrite(address, value) { + return new Promise((resolve, reject) => { + try { + this._validateAddress(address); + this._validateValue(value); + } catch(error) { + reject(error); + } + + this._sendCommand('E', address, value); + + this._readResponse().then(() => { + resolve(); + }); + }); + } - this._playLoop(1, startPosition, endPosition, count, callback); -}; + degamma(n) { + // Allow pass-through r,g,b values + if (!this.doDegamma) { + return n; + } + + return Math.floor( + ((1 << Math.floor(n / 32)) - 1) + + Math.floor( + (1 << Math.floor(n / 32)) * Math.floor((n % 32) + 1) + 15 + ) / 32); + } -Blink1.prototype.pause = function(callback) { - this._play(0, 0, callback); -}; + fadeToRGB({ + delay, + red, + green, + blue, + index = 0 + }) { + return new Promise((resolve, reject) => { + try { + this._validateFadeMillis(delay); + this._validateRGB(red, green, blue); + this._validateIndex(index); + } catch(error) { + reject(JSON.stringify({ + error, + delay, + red, + green, + blue, + index + })); + } + + let dms = delay / 10; + this._sendCommand('c', this.degamma(red), this.degamma(green), this.degamma(blue), dms >> 8, dms % 0xff, index); + + setTimeout(() => resolve({ + red, + green, + blue, + index + }), delay); + }); + } -Blink1.prototype.writePatternLine = function(fadeMillis, r, g, b, position, callback) { - this._validateFadeMillis(fadeMillis); - this._validateRGB(r, g, b); - this._validatePosition(position); + setRGB({ + red, + green, + blue + }) { + return new Promise((resolve, reject) => { + try { + this._validateRGB(red, green, blue); + } catch(error) { + reject(error); + } + + this._sendCommand('n', this.degamma(red), this.degamma(green), this.degamma(blue)); + resolve({ + red, + green, + blue + }); + }); + } - var dms = fadeMillis / 10; + off() { + return new Promise(resolve => { + this.setRGB({ + red : 0, + green : 0, + blue : 0 + }).then(response => { + resolve(response); + }); + }); + } - this._sendCommand('P', this.degamma(r), this.degamma(g), this.degamma(b), dms >> 8, dms % 0xff, position, 0); + getRGB(index = 0) { + return new Promise(resolve => { + this._sendCommand('r', index, 0, 0, 0, 0, index); + + this._readResponse().then(response => { + var red = response[2]; + var green = response[3]; + var blue = response[4]; + + resolve({ + red, + green, + blue + }); + }); + }); + } - if(this._isValidCallback(callback)) { - callback(); - } -}; + enableServerDown(delay) { + return new Promise((resolve, reject) => { + try { + this._validateMillis(delay); + } catch(error) { + reject(error); + } + + this._serverDown(1, delay).then(response => { + resolve(); + }); + }); + } -Blink1.prototype.readPatternLine = function(position, callback) { - this._validatePosition(position); + disableServerDown(delay) { + return new Promise((resolve, reject) => { + try { + this._validateMillis(delay); + } catch(error) { + reject(error); + } + + this._serverDown(0, delay).then(response => { + resolve(); + }); + }); + } - this._sendCommand('R', 0, 0, 0, 0, 0, position, 0); + play(position) { + return new Promise((resolve, reject) => { + try { + this._validatePosition(position); + } catch(error) { + reject(error); + } + + this._play(1, position).then(response => { + resolve(); + }); + }); + } - this._readResponse(function(response) { - var value = { - r: response[2], - g: response[3], - b: response[4], - fadeMillis: ((response[5] << 8) + (response[6] & 0xff)) * 10 - }; + playLoop({ + start, + end, + count + }) { + return new Promise((resolve, reject) => { + try { + this._validatePosition(start); + this._validatePosition(end); + this._validateCount(count); + } catch(error) { + reject(error); + } + + this._playLoop(1, start, end, count).then(() => { + resolve(); + }).catch(error => { + reject(error); + }); + }); + } - if(this._isValidCallback(callback)) { - callback(value); + pause() { + return new Promise(resolve => { + this._play(0, 0).then(() => { + resolve(); + }); + }); } - }); -}; -Blink1.prototype.close = function(callback) { - this.hidDevice.close(); + writePatternLine({ + delay, + red, + green, + blue, + position + }) { + return new Promise((resolve, reject) => { + try { + this._validateFadeMillis(delay); + this._validateRGB(red, green, blue); + this._validatePosition(position); + } catch(error) { + reject(error); + } + + let dms = delay / 10; + this._sendCommand('P', this.degamma(red), this.degamma(green), this.degamma(blue), dms >> 8, dms % 0xff, position, 0); + resolve(); + }); + } - if(this._isValidCallback(callback)) { - callback(); - } -}; + readPatternLine(position) { + return new Promise((resolve, reject) => { + try { + this._validatePosition(position); + } catch(error) { + reject(error); + } + + this._sendCommand('R', 0, 0, 0, 0, 0, position, 0); + + this._readResponse().then(response => { + resolve({ + red : response[2], + green : response[3], + blue : response[4], + delay : ((response[5] << 8) + (response[6] & 0xff)) * 10 + }); + }); + }); + } -Blink1.devices = devices; + close() { + return new Promise(resolve => { + this.hidDevice.close(); + resolve(); + }); + } +} module.exports = Blink1; -module.exports.Blink1 = Blink1; // backwards compatibility with older version - +module.exports.Blink1 = Blink1; // backwards compatibility with older version +module.exports.devices = devices; diff --git a/package.json b/package.json index 56e229f..7ac9556 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "blink1" ], "dependencies": { + "lodash": "^4.17.4", "node-hid": "~0.5.0" }, "devDependencies": { diff --git a/unit-tests.js b/unit-tests.js index c1bb408..2d57b7f 100644 --- a/unit-tests.js +++ b/unit-tests.js @@ -2,7 +2,7 @@ var should = require('should'); var mockery = require('mockery'); -describe('blink(1)', function() { +describe('blink(1)', () => { var BLINK1_SRC_PATH = './blink1'; var VENDOR_ID = 0x27B8; @@ -78,24 +78,24 @@ describe('blink(1)', function() { sentFeatureReport = null; }); - describe('#devices', function() { + describe('#devices', () => { - it('should return no serial numbers when there are no blink(1) HID devices', function() { + it('should return no serial numbers when there are no blink(1) HID devices', () => { mockHIDdevices = []; Blink1.devices().should.have.length(0); }); - it('should return two serial numbers when there are two blink(1) HID devices', function() { + it('should return two serial numbers when there are two blink(1) HID devices', () => { mockHIDdevices = [MOCK_HID_DEVICE_1, MOCK_HID_DEVICE_2]; Blink1.devices().should.eql([MOCK_HID_DEVICE_1_SERIAL_NUMBER, MOCK_HID_DEVICE_2_SERIAL_NUMBER]); }); }); - describe('#Blink1', function() { + describe('#Blink1', () => { - it('should throw an error when there are no blink(1) HID devices', function() { + it('should reject (catch) promise when there are no blink(1) HID devices', () => { mockHIDdevices = []; (function(){ @@ -103,13 +103,13 @@ describe('blink(1)', function() { }).should.throwError('No blink(1)\'s could be found'); }); - it('should not throw an error when there are blink(1) HID devices', function() { + it('should not throw an error when there are blink(1) HID devices', () => { mockHIDdevices = [MOCK_HID_DEVICE_1]; new Blink1(); }); - it('should throw an error when there are no blink(1) HID devices with the supplied serial number', function() { + it('should reject (catch) promise when there are no blink(1) HID devices with the supplied serial number', () => { mockHIDdevices = [MOCK_HID_DEVICE_1]; (function(){ @@ -117,27 +117,27 @@ describe('blink(1)', function() { }).should.throwError('No blink(1)\'s with serial number ' + MOCK_HID_DEVICE_2_SERIAL_NUMBER + ' could be found'); }); - it('should not throw an error when there are blink(1) HID devices with the supplied serial number', function() { + it('should not throw an error when there are blink(1) HID devices with the supplied serial number', () => { mockHIDdevices = [MOCK_HID_DEVICE_1]; new Blink1(MOCK_HID_DEVICE_1_SERIAL_NUMBER); }); - it('should store correct serial number', function() { + it('should store correct serial number', () => { mockHIDdevices = [MOCK_HID_DEVICE_1]; var blink1 = new Blink1(MOCK_HID_DEVICE_1_SERIAL_NUMBER); blink1.serialNumber.should.eql(MOCK_HID_DEVICE_1_SERIAL_NUMBER); }); - it('should select first blink(1) HID device when no serial number is supplied', function() { + it('should select first blink(1) HID device when no serial number is supplied', () => { mockHIDdevices = [MOCK_HID_DEVICE_1, MOCK_HID_DEVICE_2]; var blink1 = new Blink1(); blink1.serialNumber.should.eql(MOCK_HID_DEVICE_1_SERIAL_NUMBER); }); - it('should open correct HID device path', function() { + it('should open correct HID device path', () => { mockHIDdevices = [MOCK_HID_DEVICE_1, MOCK_HID_DEVICE_2]; var blink1 = new Blink1(MOCK_HID_DEVICE_1_SERIAL_NUMBER); @@ -158,7 +158,7 @@ describe('blink(1)', function() { blink1 = null; }; - describe('#Blink1.version', function() { + describe('#Blink1.version', () => { beforeEach(function() { setupBlink1(); @@ -167,28 +167,28 @@ describe('blink(1)', function() { }); afterEach(teardownBlink1); - it('should send version feature report', function() { + it('should send version feature report', () => { blink1.version(); sentFeatureReport.should.eql([FEATURE_REPORT_ID, 0x76, 0, 0, 0, 0, 0, 0, 0]); }); - it('should call back with version', function(done) { - blink1.version(function(version) { + it('should resolve promise with version', (done) => { + blink1.version().then(version => { done(); }); }); - it('should call back with correct version', function(done) { + it('should resolve promise with correct version', (done) => { - blink1.version(function(version) { + blink1.version().then(version => { version.should.eql('1.0'); done(); }); }); }); - describe('#Blink1.eeRead', function() { + describe('#Blink1.eeRead', () => { var ADDRESS = 1; var VALUE = 5; @@ -200,46 +200,52 @@ describe('blink(1)', function() { }); afterEach(teardownBlink1); - it('should throw an error when address is not a number', function() { + it('should reject (catch) promise when address is not a number', () => { (function(){ - blink1.eeRead('Bad address'); - }).should.throwError('address must be a number'); + blink1.eeRead('Bad address').catch((error) => { + error.should.eql("Bad address must be a number") + }); + }) }); - it('should throw an error when address is less than 0', function() { + it('should reject (catch) promise when address is less than 0', () => { (function(){ - blink1.eeRead(-1); - }).should.throwError('address must be between 0 and 65535'); + blink1.eeRead(-1).catch((error) => { + error.should.eql("address must be between 0 and 65535") + }); + }) }); - it('should throw an error when address is greater than 65535', function() { + it('should reject (catch) promise when address is greater than 65535', () => { (function(){ - blink1.eeRead(65536); - }).should.throwError('address must be between 0 and 65535'); + blink1.eeRead(65536).catch((error) => { + error.should.eql("address must be between 0 and 65535") + }); + }) }); - it('should send eeread feature report', function() { + it('should send eeread feature report', () => { blink1.eeRead(ADDRESS); sentFeatureReport.should.eql([FEATURE_REPORT_ID, 0x65, 1, 0, 0, 0, 0, 0, 0]); }); - it('should call back with value', function(done) { - blink1.eeRead(ADDRESS, function(value) { + it('should resolve promise with value', (done) => { + blink1.eeRead(ADDRESS).then(value => { done(); }); }); - it('should call back with correct value', function(done) { + it('should resolve promise with correct value', (done) => { - blink1.eeRead(ADDRESS, function(value) { + blink1.eeRead(ADDRESS).then(value => { value.should.eql(VALUE); done(); }); }); }); - describe('#Blink1.eeWrite', function() { + describe('#Blink1.eeWrite', () => { var ADDRESS = 1; var VALUE = 5; @@ -247,54 +253,68 @@ describe('blink(1)', function() { beforeEach(setupBlink1); afterEach(teardownBlink1); - it('should throw an error when address is not a number', function() { + it('should reject (catch) promise when address is not a number', () => { (function(){ - blink1.eeWrite('Bad address', VALUE); - }).should.throwError('address must be a number'); + blink1.eeWrite('Bad address', VALUE).catch(error => { + error.should.eql("bad address must be a number"); + }); + }) }); - it('should throw an error when address is less than 0', function() { + it('should reject (catch) promise when address is less than 0', () => { (function(){ - blink1.eeWrite(-1, VALUE); - }).should.throwError('address must be between 0 and 65535'); + blink1.eeWrite(-1, VALUE).catch(error => { + error.should.eql("address must be between 0 and 65535"); + }); + }) }); - it('should throw an error when address is greater than 65535', function() { + it('should reject (catch) promise when address is greater than 65535', () => { (function(){ - blink1.eeWrite(65536, VALUE); - }).should.throwError('address must be between 0 and 65535'); + blink1.eeWrite(65536, VALUE).catch(error => { + error.should.eql("address must be between 0 and 65535"); + }); + }) }); - it('should throw an error when value is not a number', function() { + it('should reject (catch) promise when value is not a number', () => { (function(){ - blink1.eeWrite(ADDRESS, 'Bad value'); - }).should.throwError('value must be a number'); + blink1.eeWrite(ADDRESS, 'Bad value').catch(error => { + error.should.eql("Bad value must be a number"); + }); + }) }); - it('should throw an error when value is less than 0', function() { + it('should reject (catch) promise when value is less than 0', () => { (function(){ - blink1.eeWrite(ADDRESS, -1); - }).should.throwError('value must be between 0 and 255'); + blink1.eeWrite(ADDRESS, -1).catch(error => { + error.should.eql("value must be between 0 and 255"); + }); + }) }); - it('should throw an error when value is greater than 255', function() { + it('should reject (catch) promise when value is greater than 255', () => { (function(){ - blink1.eeWrite(ADDRESS, 256); - }).should.throwError('value must be between 0 and 255'); + blink1.eeWrite(ADDRESS, 256).catch(error => { + error.should.eql("value must be between 0 and 255"); + }); + }) }); - it('should send eewrite feature report', function() { + it('should send eewrite feature report', () => { blink1.eeWrite(ADDRESS, VALUE); sentFeatureReport.should.eql([FEATURE_REPORT_ID, 0x45, ADDRESS, VALUE, 0, 0, 0, 0, 0]); }); - it('should call back', function(done) { - blink1.eeWrite(ADDRESS, VALUE, done); + it('should resolve promise', (done) => { + blink1.eeWrite(ADDRESS, VALUE).then(() => { + done(); + }); }); }); - describe('#Blink1.fadeToRGB', function() { + describe('#Blink1.fadeToRGB', () => { var FADE_MILLIS = 10; var R = 10; var G = 20; @@ -304,112 +324,238 @@ describe('blink(1)', function() { beforeEach(setupBlink1); afterEach(teardownBlink1); - it('should throw an error when fadeMillis is not a number', function() { + it('should reject (catch) promise when fadeMillis is not a number', () => { (function(){ - blink1.fadeToRGB('Bad fadeMillis', R, G, B); - }).should.throwError('fadeMillis must be a number'); + blink1.fadeToRGB({ + delay : 'Bad fadeMillis', + red : R, + green : G, + blue : B + }).catch(error => { + error.should.eql("fadeMillis must be a number"); + }); + }); }); - it('should throw an error when fadeMillis is less than 0', function() { + it('should reject (catch) promise when fadeMillis is less than 0', () => { (function(){ - blink1.fadeToRGB(-1, R, G, B); - }).should.throwError('fadeMillis must be between 0 and 655350'); + blink1.fadeToRGB({ + delay : -1, + red : R, + green : G, + blue : B + }).catch(error => { + error.should.eql("fadeMillis must be between 0 and 655350"); + }); + }); }); - it('should throw an error when fadeMillis is greater than 655350', function() { + it('should reject (catch) promise when fadeMillis is greater than 655350', () => { (function(){ - blink1.fadeToRGB(655351, R, G, B); - }).should.throwError('fadeMillis must be between 0 and 655350'); + blink1.fadeToRGB({ + delay : 655351, + red : R, + green : G, + blue : B + }).catch(error => { + error.should.eql("fadeMillis must be between 0 and 655350"); + }); + }); }); - it('should throw an error when r is not a number', function() { + it('should reject (catch) promise when r is not a number', () => { (function(){ - blink1.fadeToRGB(FADE_MILLIS, 'Bad r', G, B); - }).should.throwError('r must be a number'); + blink1.fadeToRGB({ + delay : FADE_MILLIS, + red : 'Bad r', + green : G, + blue : B + }).catch(error => { + error.should.eql("r must be a number"); + }); + }); }); - it('should throw an error when r is less than 0', function() { + it('should reject (catch) promise when r is less than 0', () => { (function(){ - blink1.fadeToRGB(FADE_MILLIS, -1, G, B); - }).should.throwError('r must be between 0 and 255'); + blink1.fadeToRGB({ + delay : FADE_MILLIS, + red : -1, + green : G, + blue : B + }).catch(error => { + error.should.eql("r must be between 0 and 255"); + }); + }); }); - it('should throw an error when r is greater than 255', function() { + it('should reject (catch) promise when r is greater than 255', () => { (function(){ - blink1.fadeToRGB(FADE_MILLIS, 256, G, B); - }).should.throwError('r must be between 0 and 255'); + blink1.fadeToRGB({ + delay : FADE_MILLIS, + red : 256, + green : G, + blue : B + }).catch(error => { + error.should.eql("r must be between 0 and 255"); + }); + }); }); - it('should throw an error when g is not a number', function() { + it('should reject (catch) promise when g is not a number', () => { (function(){ - blink1.fadeToRGB(FADE_MILLIS, R, 'Bad g', B); - }).should.throwError('g must be a number'); + blink1.fadeToRGB({ + delay : FADE_MILLIS, + red : R, + green : 'Bad g', + blue : B + }).catch(error => { + error.should.eql("g must be a number"); + }); + }); }); - it('should throw an error when g is less than 0', function() { + it('should reject (catch) promise when g is less than 0', () => { (function(){ - blink1.fadeToRGB(FADE_MILLIS, R, -1, B); - }).should.throwError('g must be between 0 and 255'); + blink1.fadeToRGB({ + delay : FADE_MILLIS, + red : R, + green : -1, + blue : B + }).catch(error => { + error.should.eql("g must be between 0 and 255"); + }); + }); }); - it('should throw an error when g is greater than 255', function() { + it('should reject (catch) promise when g is greater than 255', () => { (function(){ - blink1.fadeToRGB(FADE_MILLIS, R, 256, B); - }).should.throwError('g must be between 0 and 255'); + blink1.fadeToRGB({ + delay : FADE_MILLIS, + red : R, + green : 256, + blue : B + }).catch(error => { + error.should.eql("g must be between 0 and 255"); + }); + }); }); - it('should throw an error when b is not a number', function() { + it('should reject (catch) promise when b is not a number', () => { (function(){ - blink1.fadeToRGB(FADE_MILLIS, R, G, 'Bad b'); - }).should.throwError('b must be a number'); + blink1.fadeToRGB({ + delay : FADE_MILLIS, + red : R, + green : G, + blue : 'Bad b' + }).catch(error => { + error.should.eql("b must be a number"); + }); + }); }); - it('should throw an error when b is less than 0', function() { + it('should reject (catch) promise when b is less than 0', () => { (function(){ - blink1.fadeToRGB(FADE_MILLIS, R, G, -1); - }).should.throwError('b must be between 0 and 255'); + blink1.fadeToRGB({ + delay : FADE_MILLIS, + red : R, + green : G, + blue : -1 + }).catch(error => { + error.should.eql("b must be between 0 and 255"); + }); + }); }); - it('should throw an error when b is greater than 255', function() { + it('should reject (catch) promise when b is greater than 255', () => { (function(){ - blink1.fadeToRGB(FADE_MILLIS, R, G, 256); - }).should.throwError('b must be between 0 and 255'); + blink1.fadeToRGB({ + delay : FADE_MILLIS, + red : R, + green : G, + blue : 256 + }).catch(error => { + error.should.eql("b must be between 0 and 255"); + }); + }); }); - it('should send fadetorgb feature report', function() { - blink1.fadeToRGB(FADE_MILLIS, R, G, B); + it('should send fadetorgb feature report', () => { + blink1.fadeToRGB({ + delay : FADE_MILLIS, + red : R, + green : G, + blue : B + }); sentFeatureReport.should.eql([FEATURE_REPORT_ID, 0x63, blink1.degamma(R), blink1.degamma(G), blink1.degamma(B), (FADE_MILLIS / 10) >> 8, (FADE_MILLIS / 10) % 0xff, 0, 0]); }); - it('should call back', function(done) { - blink1.fadeToRGB(FADE_MILLIS, blink1.degamma(R), blink1.degamma(G), blink1.degamma(B), done); + it('should resolve promise', (done) => { + blink1.fadeToRGB({ + delay : FADE_MILLIS, + red : R, + green : G, + blue : B + }).then(() => { + done(); + }); }); - it('should throw an error when index is less than 0', function() { + it('should reject (catch) promise when index is less than 0', () => { (function(){ - blink1.fadeToRGB(FADE_MILLIS, R, G, B, -1); - }).should.throwError('index must be between 0 and 2'); + blink1.fadeToRGB({ + delay : FADE_MILLIS, + red : R, + green : G, + blue : B, + index : -1 + }).catch(error => { + error.should.eql("index must be between 0 and 2"); + }); + }); }); - it('should throw an error when index is greater than 2', function() { + it('should reject (catch) promise when index is greater than 2', () => { (function(){ - blink1.fadeToRGB(FADE_MILLIS, R, G, B, 3); - }).should.throwError('index must be between 0 and 2'); + blink1.fadeToRGB({ + delay : FADE_MILLIS, + red : R, + green : G, + blue : B, + index : 3 + }).catch(error => { + error.should.eql("index must be between 0 and 2"); + }); + }); }); - it('should send fadetorgb index feature report', function() { - blink1.fadeToRGB(FADE_MILLIS, R, G, B, INDEX); + it('should send fadetorgb index feature report', () => { + blink1.fadeToRGB({ + delay : FADE_MILLIS, + red : R, + green : G, + blue : B, + index : INDEX + }); sentFeatureReport.should.eql([FEATURE_REPORT_ID, 0x63, blink1.degamma(R), blink1.degamma(G), blink1.degamma(B), (FADE_MILLIS / 10) >> 8, (FADE_MILLIS / 10) % 0xff, INDEX, 0]); }); - it('should call back (index)', function(done) { - blink1.fadeToRGB(FADE_MILLIS, blink1.degamma(R), blink1.degamma(G), blink1.degamma(B), INDEX, done); + it('should resolve promise (index)', (done) => { + blink1.fadeToRGB({ + delay : FADE_MILLIS, + red : R, + green : G, + blue : B, + index : INDEX + }).then(() => { + done(); + }); }); }); - describe('#Blink1.setRGB', function() { + describe('#Blink1.setRGB', () => { var R = 10; var G = 20; var B = 40; @@ -417,88 +563,154 @@ describe('blink(1)', function() { beforeEach(setupBlink1); afterEach(teardownBlink1); - it('should throw an error when r is not a number', function() { + it('should reject (catch) promise when r is not a number', () => { (function(){ - blink1.setRGB('Bad r', G, B); - }).should.throwError('r must be a number'); + blink1.setRGB({ + red : 'Bad r', + green : G, + blue : B + }).catch(error => { + error.should.eql("r must be a number"); + }); + }); }); - it('should throw an error when r is less than 0', function() { + it('should reject (catch) promise when r is less than 0', () => { (function(){ - blink1.setRGB(-1, G, B); - }).should.throwError('r must be between 0 and 255'); + blink1.setRGB({ + red : -1, + green : G, + blue : B + }).catch(error => { + error.should.eql("r must be between 0 and 255"); + }); + }); }); - it('should throw an error when r is greater than 255', function() { + it('should reject (catch) promise when r is greater than 255', () => { (function(){ - blink1.setRGB(256, G, B); - }).should.throwError('r must be between 0 and 255'); + blink1.setRGB({ + red : 256, + green : G, + blue : B + }).catch(error => { + error.should.eql("r must be between 0 and 255"); + }); + }); }); - it('should throw an error when g is not a number', function() { + it('should reject (catch) promise when g is not a number', () => { (function(){ - blink1.setRGB(R, 'Bad g', B); - }).should.throwError('g must be a number'); + blink1.setRGB({ + red : R, + green : 'Bad g', + blue : B + }).catch(error => { + error.should.eql("g must be a number"); + }); + }); }); - it('should throw an error when g is less than 0', function() { + it('should reject (catch) promise when g is less than 0', () => { (function(){ - blink1.setRGB(R, -1, B); - }).should.throwError('g must be between 0 and 255'); + blink1.setRGB({ + red : R, + green : -1, + blue : B + }).catch(error => { + error.should.eql("g must be between 0 and 255"); + }); + }); }); - it('should throw an error when g is greater than 255', function() { + it('should reject (catch) promise when g is greater than 255', () => { (function(){ - blink1.setRGB(R, 256, B); - }).should.throwError('g must be between 0 and 255'); + blink1.setRGB({ + red : R, + green : 256, + blue : B + }).catch(error => { + error.should.eql("g must be between 0 and 255"); + }); + }); }); - it('should throw an error when b is not a number', function() { + it('should reject (catch) promise when b is not a number', () => { (function(){ - blink1.setRGB(R, G, 'Bad b'); - }).should.throwError('b must be a number'); + blink1.setRGB({ + red : R, + green : G, + blue : 'Bad b' + }).catch(error => { + error.should.eql("b must be a number"); + }); + }); }); - it('should throw an error when b is less than 0', function() { + it('should reject (catch) promise when b is less than 0', () => { (function(){ - blink1.setRGB(R, G, -1); - }).should.throwError('b must be between 0 and 255'); + blink1.setRGB({ + red : R, + green : G, + blue : -1 + }).catch(error => { + error.should.eql("b must be between 0 and 255"); + }); + }); }); - it('should throw an error when b is greater than 255', function() { + it('should reject (catch) promise when b is greater than 255', () => { (function(){ - blink1.setRGB(R, G, 256); - }).should.throwError('b must be between 0 and 255'); + blink1.setRGB({ + red : R, + green : G, + blue : 256 + }).catch(error => { + error.should.eql("b must be between 0 and 255"); + }); + }); }); - it('should send setrgb feature report', function() { - blink1.setRGB(R, G, B); + it('should send setrgb feature report', () => { + blink1.setRGB({ + red : R, + green : G, + blue : B + }); sentFeatureReport.should.eql([FEATURE_REPORT_ID, 0x6e, blink1.degamma(R), blink1.degamma(G), blink1.degamma(B), 0, 0, 0, 0]); }); - it('should call back', function(done) { - blink1.setRGB(R, G, B, done); + it('should resolve promise', (done) => { + blink1.setRGB({ + red : R, + green : G, + blue : B + }).then(() => { + done(); + }); }); }); - describe('#Blink1.off', function() { + describe('#Blink1.off', () => { beforeEach(setupBlink1); afterEach(teardownBlink1); - it('should send setrgb 0, 0, 0 feature report', function() { + it('should send setrgb 0, 0, 0 feature report', () => { blink1.off(); sentFeatureReport.should.eql([FEATURE_REPORT_ID, 0x6e, 0, 0, 0, 0, 0, 0, 0]); }); - it('should call back', function(done) { - blink1.off(done); + it('should resolve promise', (done) => { + blink1.off().then(() => { + done(); + }); }); }); - describe('#Blink1.rgb', function() { + describe('#Blink1.getRGB', () => { var INDEX = 1; var R = 1; var G = 2; @@ -511,156 +723,180 @@ describe('blink(1)', function() { }); afterEach(teardownBlink1); - it('should send rgb feature report', function() { - blink1.rgb(); + it('should send rgb feature report', () => { + blink1.getRGB(); sentFeatureReport.should.eql([FEATURE_REPORT_ID, 0x72, 0, 0, 0, 0, 0, 0, 0]); }); - it('should call back with r, g, b', function(done) { - blink1.rgb(function(r, g, b) { + it('should resolve promise with r, g, b', (done) => { + blink1.getRGB().then(({red, green, blue}) => { done(); }); }); - it('should call back with correct r, g, b', function(done) { - blink1.rgb(function(r, g, b) { - r.should.eql(R); - g.should.eql(G); - b.should.eql(B); + it('should resolve promise with correct r, g, b', (done) => { + blink1.getRGB().then(({red, green, blue}) => { + red.should.eql(R); + green.should.eql(G); + blue.should.eql(B); done(); }); }); - it('should send rgb index feature report', function() { - blink1.rgb(INDEX); + it('should send rgb index feature report', () => { + blink1.getRGB(INDEX); sentFeatureReport.should.eql([FEATURE_REPORT_ID, 0x72, INDEX, 0, 0, 0, 0, INDEX, 0]); }); - it('should call back with r, g, b (index)', function(done) { - blink1.rgb(INDEX, function(r, g, b) { + it('should resolve promise with r, g, b (index)', (done) => { + blink1.getRGB(INDEX).then(({red, green, blue}) => { done(); }); }); - it('should call back with correct r, g, b (index)', function(done) { - blink1.rgb(INDEX, function(r, g, b) { - r.should.eql(R); - g.should.eql(G); - b.should.eql(B); + it('should resolve promise with correct r, g, b (index)', (done) => { + blink1.getRGB(INDEX).then(({red, green, blue}) => { + red.should.eql(R); + green.should.eql(G); + blue.should.eql(B); done(); }); }); }); - describe('#Blink1.enableServerDown', function() { + describe('#Blink1.enableServerDown', () => { var MILLIS = 10; beforeEach(setupBlink1); afterEach(teardownBlink1); - it('should throw an error when millis is not a number', function() { + it('should reject (catch) promise when millis is not a number', () => { (function(){ - blink1.enableServerDown('Bad millis'); - }).should.throwError('millis must be a number'); + blink1.enableServerDown('Bad millis').catch(error => { + error.should.eql("millis must be a number"); + }); + }); }); - it('should throw an error when millis is less than 0', function() { + it('should reject (catch) promise when millis is less than 0', () => { (function(){ - blink1.enableServerDown(-1); - }).should.throwError('millis must be between 0 and 655350'); + blink1.enableServerDown(-1).catch(error => { + error.should.eql("millis must be between 0 and 655350"); + }); + }); }); - it('should throw an error when millis is greater than 655350', function() { + it('should reject (catch) promise when millis is greater than 655350', () => { (function(){ - blink1.enableServerDown(655351); - }).should.throwError('millis must be between 0 and 655350'); + blink1.enableServerDown(655351).catch(error => { + error.should.eql("millis must be between 0 and 655350"); + }); + }); }); - it('should send serverdown on feature report', function() { + it('should send serverdown on feature report', () => { blink1.enableServerDown(MILLIS); sentFeatureReport.should.eql([FEATURE_REPORT_ID, 0x44, 1, (MILLIS / 10) >> 8, (MILLIS / 10) % 0xff, 0, 0, 0, 0]); }); - it('should call back', function(done) { - blink1.enableServerDown(0, done); + it('should resolve promise', (done) => { + blink1.enableServerDown(0).then(() => { + done(); + }); }); }); - describe('#Blink1.disableServerDown', function() { + describe('#Blink1.disableServerDown', () => { var MILLIS = 10; beforeEach(setupBlink1); afterEach(teardownBlink1); - it('should throw an error when millis is not a number', function() { + it('should reject (catch) promise when millis is not a number', () => { (function(){ - blink1.disableServerDown('Bad millis'); - }).should.throwError('millis must be a number'); + blink1.disableServerDown('Bad millis').catch(error => { + error.should.eql("millis must be a number"); + }); + }); }); - it('should throw an error when millis is less than 0', function() { + it('should reject (catch) promise when millis is less than 0', () => { (function(){ - blink1.disableServerDown(-1); - }).should.throwError('millis must be between 0 and 655350'); + blink1.disableServerDown(-1).catch(error => { + error.should.eql("millis must be between 0 and 655350"); + }); + }); }); - it('should throw an error when millis is greater than 655350', function() { + it('should reject (catch) promise when millis is greater than 655350', () => { (function(){ - blink1.disableServerDown(655351); - }).should.throwError('millis must be between 0 and 655350'); + blink1.disableServerDown(-1).catch(error => { + error.should.eql("millis must be between 0 and 655350"); + }); + }); }); - it('should send serverdown off feature report', function() { + it('should send serverdown off feature report', () => { blink1.disableServerDown(0); sentFeatureReport.should.eql([FEATURE_REPORT_ID, 0x44, 0, 0, 0, 0, 0, 0, 0]); }); - it('should call back', function(done) { - blink1.disableServerDown(0, done); + it('should resolve promise', (done) => { + blink1.disableServerDown(0).then(() => { + done(); + }); }); }); - describe('#Blink1.play', function() { + describe('#Blink1.play', () => { var POSITION = 5; beforeEach(setupBlink1); afterEach(teardownBlink1); - it('should throw an error when position is not a number', function() { + it('should reject (catch) promise when position is not a number', () => { (function(){ - blink1.play('Bad position'); - }).should.throwError('position must be a number'); + blink1.play('Bad position').catch(error => { + error.should.eql('position must be a number'); + }); + }); }); - it('should throw an error when position is less than 0', function() { + it('should reject (catch) promise when position is less than 0', () => { (function(){ - blink1.play(-1); - }).should.throwError('position must be between 0 and 11'); + blink1.play(-1).catch(error => { + error.should.eql('position must be between 0 and 11'); + }); + }); }); - it('should throw an error when position is greater than 11', function() { + it('should reject (catch) promise when position is greater than 11', () => { (function(){ - blink1.play(12); - }).should.throwError('position must be between 0 and 11'); + blink1.play(12).catch(error => { + error.should.eql('position must be between 0 and 11'); + }); + }); }); - it('should send play on feature report', function() { + it('should send play on feature report', () => { blink1.play(POSITION); sentFeatureReport.should.eql([FEATURE_REPORT_ID, 0x70, 1, POSITION, 0, 0, 0, 0, 0]); }); - it('should call back', function(done) { - blink1.play(0, done); + it('should resolve promise', (done) => { + blink1.play(0).then(() => { + done(); + }); }); }); - describe('#Blink1.playLoop', function() { + describe('#Blink1.playLoop', () => { var STARTPOSITION = 5; var ENDPOSITION = 8; var COUNT = 1; @@ -669,81 +905,143 @@ describe('blink(1)', function() { afterEach(teardownBlink1); - it('should throw an error when start position is not a number', function() { + it('should reject (catch) promise when start position is not a number', () => { (function(){ - blink1.playLoop('Bad position', 2, 2); - }).should.throwError('position must be a number'); + blink1.playLoop({ + start : 'Bad position', + end : 2, + count : 2 + }).catch(error => { + error.should.eql('position must be a number'); + }); + }); }); - it('should throw an error when end position is not a number', function() { + it('should reject (catch) promise when end position is not a number', () => { (function(){ - blink1.playLoop(1, 'Bad position', 2); - }).should.throwError('position must be a number'); + blink1.playLoop({ + start : 1, + end : 'Bad position', + count : 2 + }).catch(error => { + error.should.eql('position must be a number'); + }); + }); }); - it('should throw an error when count is not a number', function() { + it('should reject (catch) promise when count is not a number', () => { (function(){ - blink1.playLoop(1, 2, 'Bad count'); - }).should.throwError('count must be a number'); + blink1.playLoop({ + start : 1, + end : 2, + count : 'Bad count' + }).catch(error => { + error.should.eql('count must be a number'); + }); + }); }); - it('should throw an error when start position is less than 0', function() { + it('should reject (catch) promise when start position is less than 0', () => { (function(){ - blink1.playLoop(-1, 2, 2); - }).should.throwError('position must be between 0 and 11'); + blink1.playLoop({ + start : -1, + end : 2, + count : 2 + }).catch(error => { + error.should.eql('position must be between 0 and 11'); + }); + }); }); - it('should throw an error when end position is less than 0', function() { + it('should reject (catch) promise when end position is less than 0', () => { (function(){ - blink1.playLoop(1, -1, 2); - }).should.throwError('position must be between 0 and 11'); + blink1.playLoop({ + start : 1, + end : -1, + count : 2 + }).catch(error => { + error.should.eql('position must be between 0 and 11'); + }); + }); }); - it('should throw an error when count is less than 0', function() { + it('should reject (catch) promise when count is less than 0', () => { (function(){ - blink1.playLoop(1, 1, -1); - }).should.throwError('count must be between 0 and 255'); + blink1.playLoop({ + start : 1, + end : 1, + count : -1 + }).catch(error => { + error.should.eql('count must be between 0 and 255'); + }); + }); }); - it('should throw an error when start position is greater than 11', function() { + it('should reject (catch) promise when start position is greater than 11', () => { (function(){ - blink1.playLoop(12, 2, 2); - }).should.throwError('position must be between 0 and 11'); + blink1.playLoop({ + start : 12, + end : 2, + count : 2 + }).catch(error => { + error.should.eql('position must be between 0 and 11'); + }); + }); }); - it('should throw an error when end position is greater than 11', function() { + it('should reject (catch) promise when end position is greater than 11', () => { (function(){ - blink1.playLoop(2, 12, 2); - }).should.throwError('position must be between 0 and 11'); + blink1.playLoop({ + start : 2, + end : 12, + count : 2 + }).catch(error => { + error.should.eql('position must be between 0 and 11'); + }); + }); }); - it('should send play on feature report', function() { - blink1.playLoop(STARTPOSITION, ENDPOSITION, COUNT ); + it('should send play on feature report', () => { + (function(){ + blink1.playLoop({ + start : STARTPOSITION, + end : ENDPOSITION, + count : COUNT + }); - sentFeatureReport.should.eql([FEATURE_REPORT_ID, 0x70, 1, STARTPOSITION, ENDPOSITION, COUNT, 0, 0, 0]); + sentFeatureReport.should.eql([FEATURE_REPORT_ID, 0x70, 1, STARTPOSITION, ENDPOSITION, COUNT, 0, 0, 0]); + }); }); - it('should call back', function(done) { - blink1.playLoop(0, 1, 1, done); + it('should resolve promise', (done) => { + blink1.playLoop({ + start : 0, + end : 1, + count : 1 + }).then(() => { + done(); + }); }); }); - describe('#Blink1.pause', function() { + describe('#Blink1.pause', () => { beforeEach(setupBlink1); afterEach(teardownBlink1); - it('should send play off feature report', function() { + it('should send play off feature report', () => { blink1.pause(); sentFeatureReport.should.eql([FEATURE_REPORT_ID, 0x70, 0, 0, 0, 0, 0, 0, 0]); }); - it('should call back', function(done) { - blink1.pause(done); + it('should resolve promise', (done) => { + blink1.pause().then(() => { + done(); + }); }); }); - describe('#Blink1.writePatternLine', function() { + describe('#Blink1.writePatternLine', () => { var FADE_MILLIS = 10; var R = 10; var G = 20; @@ -753,108 +1051,242 @@ describe('blink(1)', function() { beforeEach(setupBlink1); afterEach(teardownBlink1); - it('should throw an error when fadeMillis is not a number', function() { - (function(){ - blink1.writePatternLine('Bad fadeMillis', R, G, B, POSITION); - }).should.throwError('fadeMillis must be a number'); + it('should reject (catch) promise when fadeMillis is not a number', () => { + (function(){ + blink1.writePatternLine({ + delay : 'Bad fadeMillis', + red : R, + green : G, + blue : B, + position : POSITION + }).catch(error => { + error.should.eql('fadeMillis must be a number'); + }); + }); }); - it('should throw an error when fadeMillis is less than 0', function() { + it('should reject (catch) promise when fadeMillis is less than 0', () => { (function(){ - blink1.writePatternLine(-1, R, G, B, POSITION); - }).should.throwError('fadeMillis must be between 0 and 655350'); + blink1.writePatternLine({ + delay : -1, + red : R, + green : G, + blue : B, + position : POSITION + }).catch(error => { + error.should.eql('fadeMillis must be between 0 and 655350'); + }); + }); }); - it('should throw an error when fadeMillis is greater than 655350', function() { + it('should reject (catch) promise when fadeMillis is greater than 655350', () => { (function(){ - blink1.writePatternLine(655351, R, G, B, POSITION); - }).should.throwError('fadeMillis must be between 0 and 655350'); + blink1.writePatternLine({ + delay : 655351, + red : R, + green : G, + blue : B, + position : POSITION + }).catch(error => { + error.should.eql('fadeMillis must be between 0 and 655350'); + }); + }); }); - it('should throw an error when r is not a number', function() { + it('should reject (catch) promise when r is not a number', () => { (function(){ - blink1.writePatternLine(FADE_MILLIS, 'Bad r', G, B, POSITION); - }).should.throwError('r must be a number'); + blink1.writePatternLine({ + delay : FADE_MILLIS, + red : 'Bad r', + green : G, + blue : B, + position : POSITION + }).catch(error => { + error.should.eql('r must be a number'); + }); + }); }); - it('should throw an error when r is less than 0', function() { + it('should reject (catch) promise when r is less than 0', () => { (function(){ - blink1.writePatternLine(FADE_MILLIS, -1, G, B, POSITION); - }).should.throwError('r must be between 0 and 255'); + blink1.writePatternLine({ + delay : FADE_MILLIS, + red : -1, + green : G, + blue : B, + position : POSITION + }).catch(error => { + error.should.eql('r must be between 0 and 255'); + }); + }); }); - it('should throw an error when r is greater than 255', function() { + it('should reject (catch) promise when r is greater than 255', () => { (function(){ - blink1.writePatternLine(FADE_MILLIS, 256, G, B, POSITION); - }).should.throwError('r must be between 0 and 255'); + blink1.writePatternLine({ + delay : FADE_MILLIS, + red : 256, + green : G, + blue : B, + position : POSITION + }).catch(error => { + error.should.eql('r must be between 0 and 255'); + }); + }); }); - it('should throw an error when g is not a number', function() { + it('should reject (catch) promise when g is not a number', () => { (function(){ - blink1.writePatternLine(FADE_MILLIS, R, 'Bad g', B, POSITION); - }).should.throwError('g must be a number'); + blink1.writePatternLine({ + delay : FADE_MILLIS, + red : R, + green : 'Bad g', + blue : B, + position : POSITION + }).catch(error => { + error.should.eql('g must be a number'); + }); + }); }); - it('should throw an error when g is less than 0', function() { + it('should reject (catch) promise when g is less than 0', () => { (function(){ - blink1.writePatternLine(FADE_MILLIS, R, -1, B, POSITION); - }).should.throwError('g must be between 0 and 255'); + blink1.writePatternLine({ + delay : FADE_MILLIS, + red : R, + green : -1, + blue : B, + position : POSITION + }).catch(error => { + error.should.eql('g must be between 0 and 255'); + }); + }); }); - it('should throw an error when g is greater than 255', function() { + it('should reject (catch) promise when g is greater than 255', () => { (function(){ - blink1.writePatternLine(FADE_MILLIS, R, 256, B, POSITION); - }).should.throwError('g must be between 0 and 255'); + blink1.writePatternLine({ + delay : FADE_MILLIS, + red : R, + green : 256, + blue : B, + position : POSITION + }).catch(error => { + error.should.eql('g must be between 0 and 255'); + }); + }); }); - it('should throw an error when b is not a number', function() { + it('should reject (catch) promise when b is not a number', () => { (function(){ - blink1.writePatternLine(FADE_MILLIS, R, G, 'Bad b', POSITION); - }).should.throwError('b must be a number'); + blink1.writePatternLine({ + delay : FADE_MILLIS, + red : R, + green : G, + blue : 'Bad b', + position : POSITION + }).catch(error => { + error.should.eql('b must be a number'); + }); + }); }); - it('should throw an error when b is less than 0', function() { + it('should reject (catch) promise when b is less than 0', () => { (function(){ - blink1.writePatternLine(FADE_MILLIS, R, G, -1, POSITION); - }).should.throwError('b must be between 0 and 255'); + blink1.writePatternLine({ + delay : FADE_MILLIS, + red : R, + green : G, + blue : -1, + position : POSITION + }).catch(error => { + error.should.eql('b must be between 0 and 255'); + }); + }); }); - it('should throw an error when b is greater than 255', function() { + it('should reject (catch) promise when b is greater than 255', () => { (function(){ - blink1.writePatternLine(FADE_MILLIS, R, G, 256, POSITION); - }).should.throwError('b must be between 0 and 255'); + blink1.writePatternLine({ + delay : FADE_MILLIS, + red : R, + green : G, + blue : 256, + position : POSITION + }).catch(error => { + error.should.eql('b must be between 0 and 255'); + }); + }); }); - it('should throw an error when position is not a number', function() { + it('should reject (catch) promise when position is not a number', () => { (function(){ - blink1.writePatternLine(FADE_MILLIS, R, G, B, 'Bad position'); - }).should.throwError('position must be a number'); + blink1.writePatternLine({ + delay : FADE_MILLIS, + red : R, + green : G, + blue : B, + position : 'Bad position' + }).catch(error => { + error.should.eql('position must be a number'); + }); + }); }); - it('should throw an error when position is less than 0', function() { + it('should reject (catch) promise when position is less than 0', () => { (function(){ - blink1.writePatternLine(FADE_MILLIS, R, G, B, -1); - }).should.throwError('position must be between 0 and 11'); + blink1.writePatternLine({ + delay : FADE_MILLIS, + red : R, + green : G, + blue : B, + position : -1 + }).catch(error => { + error.should.eql('position must be between 0 and 11'); + }); + }); }); - it('should throw an error when position is greater than 11', function() { + it('should reject (catch) promise when position is greater than 11', () => { (function(){ - blink1.writePatternLine(FADE_MILLIS, R, G, B, 12); - }).should.throwError('position must be between 0 and 11'); + blink1.writePatternLine({ + delay : FADE_MILLIS, + red : R, + green : G, + blue : B, + position : 12 + }).catch(error => { + error.should.eql('position must be between 0 and 11'); + }); + }); }); - it('should send writepatternline feature report', function() { - blink1.writePatternLine(FADE_MILLIS, R, G, B, POSITION); + it('should send writepatternline feature report', () => { + blink1.writePatternLine({ + delay : FADE_MILLIS, + red : R, + green : G, + blue : B, + position : POSITION + }); sentFeatureReport.should.eql([FEATURE_REPORT_ID, 0x50, blink1.degamma(R), blink1.degamma(G), blink1.degamma(B), (FADE_MILLIS / 10) >> 8, (FADE_MILLIS / 10) % 0xff, POSITION, 0]); }); - it('should call back', function(done) { - blink1.writePatternLine(FADE_MILLIS, R, G, B, POSITION, done); + it('should resolve promise', (done) => { + blink1.writePatternLine({ + delay : FADE_MILLIS, + red : R, + green : G, + blue : B, + position : POSITION + }).then(() => { + done(); + }); }); }); - describe('#Blink1.readPatternLine', function() { + describe('#Blink1.readPatternLine', () => { var POSITION = 5; var FADE_MILLIS = 1000; @@ -869,61 +1301,79 @@ describe('blink(1)', function() { }); afterEach(teardownBlink1); - it('should throw an error when position is not a number', function() { + it('should reject (catch) promise when position is not a number', () => { (function(){ - blink1.readPatternLine('Bad position'); - }).should.throwError('position must be a number'); + blink1.readPatternLine('Bad position').catch(error => { + error.should.eql('position must be a number'); + }); + }); }); - it('should throw an error when position is less than 0', function() { + it('should reject (catch) promise when position is less than 0', () => { (function(){ - blink1.readPatternLine(-1); - }).should.throwError('position must be between 0 and 11'); + blink1.readPatternLine(-1).catch(error => { + error.should.eql('position must be between 0 and 11'); + }); + }); }); - it('should throw an error when position is greater than 11', function() { + it('should reject (catch) promise when position is greater than 11', () => { (function(){ - blink1.readPatternLine(12); - }).should.throwError('position must be between 0 and 11'); + blink1.readPatternLine(12).catch(error => { + error.should.eql('position must be between 0 and 11'); + }); + }); }); - it('should send readpatternline feature report', function() { + it('should send readpatternline feature report', () => { blink1.readPatternLine(POSITION); sentFeatureReport.should.eql([FEATURE_REPORT_ID, 0x52, 0, 0, 0, 0, 0, POSITION, 0]); }); - it('should call back with value', function(done) { - blink1.readPatternLine(POSITION, function(value) { - done(); + it('should resolve promise with value', (done) => { + blink1.readPatternLine(POSITION).then(({ + red, + green, + blue, + delay + }) => { + done(); }); }); - it('should call back with correct value', function(done) { + it('should resolve promise with correct value', (done) => { - blink1.readPatternLine(POSITION, function(value) { - value.r.should.eql(R); - value.g.should.eql(G); - value.b.should.eql(B); - value.fadeMillis.should.eql(FADE_MILLIS); + blink1.readPatternLine(POSITION).then(({ + red, + green, + blue, + delay + }) => { + red.should.eql(R); + green.should.eql(G); + blue.should.eql(B); + delay.should.eql(FADE_MILLIS); - done(); + done(); }); }); }); - describe('#Blink1.close', function() { + describe('#Blink1.close', () => { beforeEach(setupBlink1); afterEach(teardownBlink1); - it('should close HID device', function(done) { - blink1.close(done); + it('should close HID device', (done) => { + blink1.close().then(() => { + done(); + }); closed.should.eql(true); }); - it('should callback', function(done) { - blink1.close(function() { + it('should resolve promise', (done) => { + blink1.close().then(() => { closed.should.eql(true); done(); From 720d052c1eeaba56cc84209089a99cb56dd08267 Mon Sep 17 00:00:00 2001 From: Sean Teague Date: Mon, 15 Jan 2018 00:21:45 -0800 Subject: [PATCH 2/5] Removed erroneous promise catch error. Also updated the README --- README.md | 132 +++++++++++++++++++++++++++++++++++++++++------------- blink1.js | 9 +--- 2 files changed, 102 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 0623b54..2302be8 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,13 @@ See [node-hid's compiling from source instructions](https://github.com/node-hid/ ## Usage ```javascript -var Blink1 = require('node-blink1'); +const { Blink1, devices } = require('node-blink1'); ``` Get list of blink(1) devices connected: ```javascript -Blink1.devices(); // returns array of serial numbers +devices(); // returns array of serial numbers ``` Create blink(1) object without serial number, uses first device: @@ -37,7 +37,7 @@ var blink1 = new Blink1(); ``` Create blink(1) object with serial number, to get list of serial numbers use -`Blink1.devices()`: +`devices()`: ```javascript var blink1 = new Blink1(serialNumber); @@ -45,91 +45,161 @@ var blink1 = new Blink1(serialNumber); ### Get version +Returns Promise + ```javascript -blink1.version(callback(version)); +blink1.version().then*(version => { + // version +}); ``` ### Set colors -Fade to RGB, optional callback called after `fadeMillis` ms: +Fade to RGB, returns Promise after `delay` ms: ```javascript -blink1.fadeToRGB(fadeMillis, r, g, b, [callback]); // r, g, b: 0 - 255 +let blinkObject = { + delay : 1000, // Optional # or ms + red : 128, // Required 0 - 255 + green : 128, // Required 0 - 255 + blue : 128 // Required 0 - 255 + index : 0 // Optionsl 0 - 2 (mk2 Only) +}; +blink1.fadeToRGB(blinkObject); +``` + +#### Extended Fade example -blink1.fadeToRGB(fadeMillis, r, g, b, [index, callback]); // r, g, b: 0 - 255 - // index (mk2 only): 0 - 2 +Because most functions return promises, you can now chain actions together. + +This example will cause the device to fade to red over 2.5s, once complete, the device will then fade to green over another 2.5s. + +```javascript +let blinkObject = { + delay : 2500, + red : 255, + green : 0, + blue : 0 +}; +blink1.fadeToRGB(blinkObject).then(({red, green, blue}) => { + let blinkObject = { + delay : 2500, + red : 0, + green : 255, + blue : 0 + }; + blink1.fadeToRGB(blinkObject); +}); ``` -Set RGB: +Set RGB, returns Promise: ```javascript -blink1.setRGB(r, g, b, [callback]); // r, g, b: 0 - 255 +let blinkObject = { + red : 128, // Required 0 - 255 + green : 128, // Required 0 - 255 + blue : 128 // Required 0 - 255 +}; +blink1.setRGB(blinkObject); ``` -Get RGB (mk2 only): +Get RGB, returns Promise (mk2 only): ```javascript -blink1.rgb([index,] callback(r, g, b)); +blink1.getRGB(index); // index defaults to 0 ``` -Off: +Off, returns Promise: ```javascript -blink1.off([callback]); +blink1.off(); ``` ### Other methods -Set server down (enable, disable), optional callback called after `millis` ms: +Set server down (enable, disable), , returns Promise after `delay` ms: ```javascript -blink1.enableServerDown(millis, [callback]); // tickle +blink1.enableServerDown(delay); // tickle -blink1.disableServerDown(millis, [callback]); // off +blink1.disableServerDown(delay); // off ``` -Play (start playing the pattern lines at the specified position): +Play (start playing the pattern lines at the specified position), returns Promise: ```javascript -blink1.play(position, [callback]); +blink1.play(position); ``` -Play Loop (start playing a subset of the pattern lines at specified start and end positions. Specifying count = 0 will loop pattern forever): +Play Loop (start playing a subset of the pattern lines at specified start and end positions. Specifying count = 0 will loop pattern forever), returns Promise: ```javascript -blink1.playLoop(startPosition, endPosition, count, [callback]); +let blinkObject = { + start : 1, // Required + end : 2, // Required + count : 2 // Required +}; +blink1.playLoop(blinkObject); ``` -Pause (stop playing the pattern line): +Pause (stop playing the pattern line), returns Promise: ```javascript -blink1.pause([callback]); +blink1.pause(); ``` -Write pattern line (set the parameters for a pattern line, at the specified position): +Write pattern line (set the parameters for a pattern line, at the specified position), returns Promise: ```javascript -blink1.writePatternLine(fadeMillis, r, g, b, position, [callback]) // r, g, b: 0 - 255 +let blinkObject = { + delay : 100, // Required # of ms + red : 128, // Required 0 - 255 + green : 128, // Required 0 - 255 + blue : 128, // Required 0 - 255 + position : 2 // Required +}; +blink1.writePatternLine(blinkObject); ```` A simple example of this, used to flash red on & off is: ```javascript -blink1.writePatternLine(200, 255, 0, 0, 0); -blink1.writePatternLine(200, 0, 0, 0, 1); +let blinkObject = { + delay : 200, + red : 255, + green : 0, + blue : 0, + position : 0 +}; +let blinkObject2 = { + delay : 200, + red : 0, + green : 0, + blue : 0, + position : 1 +}; +blink1.writePatternLine(blinkObject); +blink1.writePatternLine(blinkObject2); blink1.play(0); ``` -Read pattern line (at the position): +Read pattern line (at the position), returns Promise: ```javascript -blink1.readPatternLine(position, [callback]) +blink1.readPatternLine(position).then(({ + red, + green, + blue, + delay +}) => { + // readPatternLine values +}); ``` -Close (the underlying HID device): +Close (the underlying HID device), returns Promise: ```javascript -blink1.close([callback]); +blink1.close(); ``` ## License diff --git a/blink1.js b/blink1.js index 6b3ed27..2d0bfc4 100644 --- a/blink1.js +++ b/blink1.js @@ -221,14 +221,7 @@ class Blink1 { this._validateRGB(red, green, blue); this._validateIndex(index); } catch(error) { - reject(JSON.stringify({ - error, - delay, - red, - green, - blue, - index - })); + reject(error); } let dms = delay / 10; From 27c92ecd66d04637c5e1eceb0647ca287cebc584 Mon Sep 17 00:00:00 2001 From: Sean Teague Date: Mon, 22 Jan 2018 00:47:30 -0800 Subject: [PATCH 3/5] Moved logic around to separate files. Added optional callbacks to API --- README.md | 171 ++++++++++++++++-------- base.js | 76 +++++++++++ blink1.js | 339 +++++++++++++++++------------------------------ examples/cops.js | 25 ++++ helpers.js | 50 +++++++ package.json | 17 +-- unit-tests.js | 241 +++++++++------------------------ validators.js | 66 +++++++++ 8 files changed, 521 insertions(+), 464 deletions(-) create mode 100644 base.js create mode 100644 examples/cops.js create mode 100644 helpers.js create mode 100644 validators.js diff --git a/README.md b/README.md index 2302be8..f0057e1 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,15 @@ See [node-hid's compiling from source instructions](https://github.com/node-hid/ ## Usage ```javascript -const { Blink1, devices } = require('node-blink1'); +const Blink1 = require('node-blink1'); ``` Get list of blink(1) devices connected: +* Returns an array of serial numbers + ```javascript -devices(); // returns array of serial numbers +Blink1.devices(); ``` Create blink(1) object without serial number, uses first device: @@ -37,7 +39,9 @@ var blink1 = new Blink1(); ``` Create blink(1) object with serial number, to get list of serial numbers use -`devices()`: +`Blink1.devices()`: + +* Accepts an optional Serial Number parameter ```javascript var blink1 = new Blink1(serialNumber); @@ -45,11 +49,12 @@ var blink1 = new Blink1(serialNumber); ### Get version -Returns Promise +* Accepts an optional callback function parameter +* Returns Promise; automatically calls optional callback ```javascript -blink1.version().then*(version => { - // version +blink1.version([callback]).then*(version => { + console.log("Version:", version); }); ``` @@ -57,13 +62,20 @@ blink1.version().then*(version => { Fade to RGB, returns Promise after `delay` ms: +* Accepts an object containing: + - Required RGBColor object + - Optional delay in ms + - Optional index 0 - 2 (only Mk2 supported) + - Optional callback function +* Returns Promise; automatically calls optional callback + ```javascript +const Color = require('rgbcolor'); let blinkObject = { - delay : 1000, // Optional # or ms - red : 128, // Required 0 - 255 - green : 128, // Required 0 - 255 - blue : 128 // Required 0 - 255 - index : 0 // Optionsl 0 - 2 (mk2 Only) + color : new Color('orange'), + delay : 1000, + index : 0, + callback : () => {} }; blink1.fadeToRGB(blinkObject); ``` @@ -77,16 +89,12 @@ This example will cause the device to fade to red over 2.5s, once complete, the ```javascript let blinkObject = { delay : 2500, - red : 255, - green : 0, - blue : 0 + color : new Color('red') }; blink1.fadeToRGB(blinkObject).then(({red, green, blue}) => { let blinkObject = { delay : 2500, - red : 0, - green : 255, - blue : 0 + color : new Color('green') }; blink1.fadeToRGB(blinkObject); }); @@ -94,69 +102,112 @@ blink1.fadeToRGB(blinkObject).then(({red, green, blue}) => { Set RGB, returns Promise: +* Accepts a required RGBColor object +* Accepts an optional callback function +* Returns Promise; automatically calls optional callback + ```javascript -let blinkObject = { - red : 128, // Required 0 - 255 - green : 128, // Required 0 - 255 - blue : 128 // Required 0 - 255 -}; -blink1.setRGB(blinkObject); +blink1.setRGB(new Color('red')[, callback]); ``` -Get RGB, returns Promise (mk2 only): +Get current RGB (mk2 only): + +* Accepts an optional index (default is 0) +* Accepts an optional callback function +* Returns Promise; automatically calls optional callback ```javascript -blink1.getRGB(index); // index defaults to 0 +blink1.getRGB([index][, callback]); ``` -Off, returns Promise: +### Turn device off + +Off: + +* Accepts an optional callback function +* Returns Promise; automatically calls optional callback ```javascript -blink1.off(); +blink1.off([callback]); ``` ### Other methods -Set server down (enable, disable), , returns Promise after `delay` ms: +#### enableServerDown() & disableServerDown() + +Set server down (enable, disable) after `delay` ms: + +* Accepts required delay in ms +* Accepts an optional callback function +* Returns Promise; automatically calls optional callback ```javascript -blink1.enableServerDown(delay); // tickle +blink1.enableServerDown(delay[, callback]); // tickle -blink1.disableServerDown(delay); // off +blink1.disableServerDown(delay[, callback]); // off ``` -Play (start playing the pattern lines at the specified position), returns Promise: +#### play() + +Play (start playing the pattern lines at the specified position): + +* Accepts required play position +* Accepts an optional callback function +* Returns Promise; automatically calls optional callback ```javascript -blink1.play(position); +blink1.play(position[, callback]); ``` -Play Loop (start playing a subset of the pattern lines at specified start and end positions. Specifying count = 0 will loop pattern forever), returns Promise: +#### playLoop() + +Play Loop (start playing a subset of the pattern lines at specified start and end positions. Specifying count = 0 will loop pattern forever): + +* Accepts an object containing: + - Required start position + - Required end position + - Required count + - Optional callback function +* Returns Promise; automatically calls optional callback ```javascript let blinkObject = { - start : 1, // Required - end : 2, // Required - count : 2 // Required + start : 1, + end : 2, + count : 2, + callback : () => {} }; blink1.playLoop(blinkObject); ``` -Pause (stop playing the pattern line), returns Promise: +#### pause() + +Pause (stop playing the pattern line): + +* Accepts an optional callback function +* Returns Promise; automatically calls optional callback ```javascript -blink1.pause(); +blink1.pause([callback]); ``` -Write pattern line (set the parameters for a pattern line, at the specified position), returns Promise: +#### writePatternLine() + +Write pattern line (set the parameters for a pattern line, at the specified position): + +* Accepts an object containing: + - Required RGBColor object + - Required delay in ms + - Required position + - Optional callback function +* Returns Promise; automatically calls optional callback ```javascript let blinkObject = { - delay : 100, // Required # of ms - red : 128, // Required 0 - 255 - green : 128, // Required 0 - 255 - blue : 128, // Required 0 - 255 - position : 2 // Required + color : new Color('red'), + delay : 100, + position : 2, + callback : () => {} }; blink1.writePatternLine(blinkObject); ```` @@ -166,16 +217,12 @@ A simple example of this, used to flash red on & off is: ```javascript let blinkObject = { delay : 200, - red : 255, - green : 0, - blue : 0, + color : new Color('red') position : 0 }; let blinkObject2 = { delay : 200, - red : 0, - green : 0, - blue : 0, + color : new Color('black') position : 1 }; blink1.writePatternLine(blinkObject); @@ -183,23 +230,33 @@ blink1.writePatternLine(blinkObject2); blink1.play(0); ``` -Read pattern line (at the position), returns Promise: +#### readPatternLine() + +Read pattern line (at the position): + +* Accepts a required position +* Accepts an optional callback function +* Returns Promise; automatically calls optional callback ```javascript -blink1.readPatternLine(position).then(({ - red, - green, - blue, +blink1.readPatternLine(position[, callback]).then(({ + color, delay }) => { // readPatternLine values }); ``` -Close (the underlying HID device), returns Promise: +#### close() + +Close (the underlying HID device): + +* Accepts an optional callback function +* Returns Promise; automatically calls optional callback + ```javascript -blink1.close(); +blink1.close([callback]); ``` ## License diff --git a/base.js b/base.js new file mode 100644 index 0000000..da05b04 --- /dev/null +++ b/base.js @@ -0,0 +1,76 @@ +const HID = require('node-hid'); +const _ = require('lodash'); + +/********** + * CONFIG * + **********/ + +const VENDOR_ID = 0x27B8; +const PRODUCT_ID = 0x01ED; + +const REPORT_ID = 1; +const REPORT_LENGTH = 9; + +class Blink1_Base { + constructor(serialNumber) { + let blink1HIDdevices = Blink1_Base._blink1HIDdevices(); + + if (blink1HIDdevices.length === 0) { + throw new Error('No blink(1)\'s could be found'); + } + + var blink1HIDdevicePath = null; + + if (serialNumber === undefined) { + serialNumber = blink1HIDdevices[0].serialNumber; + } + + _.find(blink1HIDdevices, (blink1HIDdevice) => { + if (serialNumber === blink1HIDdevice.serialNumber) { + blink1HIDdevicePath = blink1HIDdevice.path; + } + + return (blink1HIDdevicePath !== null); + }); + + if (blink1HIDdevicePath === null) { + throw new Error('No blink(1)\'s with serial number ' + serialNumber + ' could be found'); + } + + this.serialNumber = serialNumber; + this.hidDevice = new HID.HID(blink1HIDdevicePath); + } + + static _blink1HIDdevices() { + return HID.devices(VENDOR_ID, PRODUCT_ID); + }; + + static devices() { + return _.map(Blink1_Base._blink1HIDdevices(), ({ serialNumber }) => serialNumber); + }; + + // Hardware API + + _sendCommand(/* command [, args ...]*/) { + var featureReport = [REPORT_ID, 0, 0, 0, 0, 0, 0, 0, 0]; + + _.forEach(arguments, (argument, k) => { + if (k === 0) { + featureReport[1] = argument.charCodeAt(0); + return; + } + + featureReport[k + 1] = argument; + }); + + this.hidDevice.sendFeatureReport(featureReport); + } + + _readResponse() { + return new Promise((resolve, reject) => { + resolve(this.hidDevice.getFeatureReport(REPORT_ID, REPORT_LENGTH)); + }); + } +} + +module.exports = Blink1_Base; diff --git a/blink1.js b/blink1.js index 2d0bfc4..c3c774e 100644 --- a/blink1.js +++ b/blink1.js @@ -1,171 +1,36 @@ -const HID = require('node-hid'); -const _ = require('lodash'); +const Color = require('rgbcolor'); +const Blink1_Validators = require('./validators'); -const VENDOR_ID = 0x27B8; -const PRODUCT_ID = 0x01ED; - -const REPORT_ID = 1; -const REPORT_LENGTH = 9; - -let _blink1HIDdevices = () => { - return HID.devices(VENDOR_ID, PRODUCT_ID); -}; - -let devices = () => { - return _.map(_blink1HIDdevices(), ({ serialNumber }) => serialNumber); -}; - -class Blink1 { +class Blink1 extends Blink1_Validators { constructor(serialNumber) { - let blink1HIDdevices = _blink1HIDdevices(); - - if (blink1HIDdevices.length === 0) { - throw new Error('No blink(1)\'s could be found'); - } - - var blink1HIDdevicePath = null; - - if (serialNumber === undefined) { - serialNumber = blink1HIDdevices[0].serialNumber; - } - - _.find(blink1HIDdevices, (blink1HIDdevice) => { - if (serialNumber === blink1HIDdevice.serialNumber) { - blink1HIDdevicePath = blink1HIDdevice.path; - } - - return (blink1HIDdevicePath !== null); - }); - - if (blink1HIDdevicePath === null) { - throw new Error('No blink(1)\'s with serial number ' + serialNumber + ' could be found'); - } - - this.serialNumber = serialNumber; - this.hidDevice = new HID.HID(blink1HIDdevicePath); - - this.doDegamma = true; + super(serialNumber); } - // Hardware API - - _sendCommand(/* command [, args ...]*/) { - var featureReport = [REPORT_ID, 0, 0, 0, 0, 0, 0, 0, 0]; + // API - _.forEach(arguments, (argument, k) => { - if (k === 0) { - featureReport[1] = argument.charCodeAt(0); - return; + version(callback = () => {}) { + const promise = new Promise((resolve, reject) => { + try { + this._isValidCallback(callback); + } catch(error) { + reject(error); } - featureReport[k + 1] = argument; - }); - - this.hidDevice.sendFeatureReport(featureReport); - } - - _readResponse() { - return new Promise(resolve => { - resolve(this.hidDevice.getFeatureReport(REPORT_ID, REPORT_LENGTH)); - }); - } - - // Helpers - - _isValidCallback(callback) { - return (typeof callback === 'function'); - } - - _serverDown(on, delay) { - return new Promise(resolve => { - let dms = delay / 10; - this._sendCommand('D', on, dms >> 8, dms % 0xff); - - setTimeout(resolve, delay); - }); - } - - _play(play, position) { - return new Promise(resolve => { - this._sendCommand('p', play, position); - resolve(); - }); - } - - _playLoop({ - play, - start, - end, - count - }) { - return new Promise(resolve => { - this._sendCommand('p', play, start, end, count); - resolve(); - }); - } - - // Validators - - _validateNumber(number, name, min, max) { - if (typeof number !== 'number') { - throw new Error(name + ' must be a number'); - } - - if (number < min || number > max) { - throw new Error(name + ' must be between ' + min + ' and ' + max); - } - } - - _validateAddress(address) { - this._validateNumber(address, 'address', 0, 0xffff); // Decimal 0 - 65535 - } - - _validateValue(value) { - this._validateNumber(value, 'value', 0, 0xff); // Decimal 0 - 255 - } - - _validateCount(value) { - this._validateNumber(value, 'count', 0, 0xff); // Decimal 0 - 255 - } - - _validateFadeMillis(fadeMillis) { - this._validateNumber(fadeMillis, 'fadeMillis', 0, 0x9FFF6); // Decimal 0 - 655350 - } - - _validateRGB(r, g, b) { - this._validateNumber(r, 'r', 0, 0xff); // Decimal 0 - 255 - this._validateNumber(g, 'g', 0, 0xff); // Decimal 0 - 255 - this._validateNumber(b, 'b', 0, 0xff); // Decimal 0 - 255 - } - - _validateMillis(millis) { - this._validateNumber(millis, 'millis', 0, 0x9FFF6); // Decimal 0 - 655350 - } - - _validatePosition(position) { - this._validateNumber(position, 'position', 0, 11); - } - - _validateIndex(index) { - this._validateNumber(index, 'index', 0, 2); - } - - // API - - version() { - return new Promise(resolve => { this._sendCommand('v'); this._readResponse().then(response => { resolve(String.fromCharCode(response[3]) + '.' + String.fromCharCode(response[4])); }); }); + + return this._returnCallbackPromise(promise, callback); } - eeRead(address) { - return new Promise((resolve, reject) => { + eeRead(address, callback = () => {}) { + const promise = new Promise((resolve, reject) => { try { this._validateAddress(address); + this._isValidCallback(callback); } catch(error) { reject(error); } @@ -176,13 +41,16 @@ class Blink1 { resolve(response[3]); }); }); + + return this._returnCallbackPromise(promise, callback); } - eeWrite(address, value) { - return new Promise((resolve, reject) => { + eeWrite(address, value, callback = () => {}) { + const promise = new Promise((resolve, reject) => { try { this._validateAddress(address); this._validateValue(value); + this._isValidCallback(callback); } catch(error) { reject(error); } @@ -193,6 +61,8 @@ class Blink1 { resolve(); }); }); + + return this._returnCallbackPromise(promise, callback); } degamma(n) { @@ -210,87 +80,87 @@ class Blink1 { fadeToRGB({ delay, - red, - green, - blue, - index = 0 + color, + index = 0, + callback = () => {} }) { - return new Promise((resolve, reject) => { + const promise = new Promise((resolve, reject) => { try { this._validateFadeMillis(delay); - this._validateRGB(red, green, blue); + this._validateRGB(color); this._validateIndex(index); + this._isValidCallback(callback); } catch(error) { reject(error); } let dms = delay / 10; - this._sendCommand('c', this.degamma(red), this.degamma(green), this.degamma(blue), dms >> 8, dms % 0xff, index); + this._sendCommand('c', this.degamma(color.r), this.degamma(color.g), this.degamma(color.b), dms >> 8, dms % 0xff, index); setTimeout(() => resolve({ - red, - green, - blue, + color, index }), delay); }); + + return this._returnCallbackPromise(promise, callback); } - setRGB({ - red, - green, - blue - }) { - return new Promise((resolve, reject) => { + setRGB(color, callback = () => {}) { + const promise = new Promise((resolve, reject) => { try { - this._validateRGB(red, green, blue); + this._validateRGB(color); + this._isValidCallback(callback); } catch(error) { reject(error); } - this._sendCommand('n', this.degamma(red), this.degamma(green), this.degamma(blue)); - resolve({ - red, - green, - blue - }); + this._sendCommand('n', this.degamma(color.r), this.degamma(color.g), this.degamma(color.b)); + resolve(color); }); + + return this._returnCallbackPromise(promise, callback); } - off() { - return new Promise(resolve => { - this.setRGB({ - red : 0, - green : 0, - blue : 0 - }).then(response => { + off(callback = () => {}) { + const promise = new Promise((resolve, reject) => { + try { + this._isValidCallback(callback); + } catch(error) { + reject(error); + } + + this.setRGB(new Color('black')).then(response => { resolve(response); }); }); + + return this._returnCallbackPromise(promise, callback); } - getRGB(index = 0) { - return new Promise(resolve => { + getRGB(index = 0, callback = () => {}) { + const promise = new Promise((resolve, reject) => { + try { + this._isValidCallback(callback); + } catch(error) { + reject(error); + } + this._sendCommand('r', index, 0, 0, 0, 0, index); this._readResponse().then(response => { - var red = response[2]; - var green = response[3]; - var blue = response[4]; - - resolve({ - red, - green, - blue - }); + resolve(new Color('rgb('+response[2]+','+response[3]+','+response[4]+')')); }); }); + + return this._returnCallbackPromise(promise, callback); } - enableServerDown(delay) { - return new Promise((resolve, reject) => { + enableServerDown(delay, callback = () => {}) { + const promise = new Promise((resolve, reject) => { try { this._validateMillis(delay); + this._isValidCallback(callback); } catch(error) { reject(error); } @@ -299,12 +169,15 @@ class Blink1 { resolve(); }); }); + + return this._returnCallbackPromise(promise, callback); } - disableServerDown(delay) { - return new Promise((resolve, reject) => { + disableServerDown(delay, callback = () => {}) { + const promise = new Promise((resolve, reject) => { try { this._validateMillis(delay); + this._isValidCallback(callback); } catch(error) { reject(error); } @@ -313,12 +186,15 @@ class Blink1 { resolve(); }); }); + + return this._returnCallbackPromise(promise, callback); } - play(position) { - return new Promise((resolve, reject) => { + play(position, callback = () => {}) { + const promise = new Promise((resolve, reject) => { try { this._validatePosition(position); + this._isValidCallback(callback); } catch(error) { reject(error); } @@ -327,18 +203,22 @@ class Blink1 { resolve(); }); }); + + return this._returnCallbackPromise(promise, callback); } playLoop({ start, end, - count + count, + callback = () => {} }) { - return new Promise((resolve, reject) => { + const promise = new Promise((resolve, reject) => { try { this._validatePosition(start); this._validatePosition(end); this._validateCount(count); + this._isValidCallback(callback); } catch(error) { reject(error); } @@ -349,42 +229,55 @@ class Blink1 { reject(error); }); }); + + return this._returnCallbackPromise(promise, callback); } - pause() { - return new Promise(resolve => { + pause(callback = () => {}) { + const promise = new Promise((resolve, reject) => { + try { + this._isValidCallback(callback); + } catch(error) { + reject(error); + } + this._play(0, 0).then(() => { resolve(); }); }); + + return this._returnCallbackPromise(promise, callback); } writePatternLine({ delay, - red, - green, - blue, - position + color, + position, + callback = () => {} }) { - return new Promise((resolve, reject) => { + const promise = new Promise((resolve, reject) => { try { this._validateFadeMillis(delay); - this._validateRGB(red, green, blue); + this._validateRGB(color); this._validatePosition(position); + this._isValidCallback(callback); } catch(error) { reject(error); } let dms = delay / 10; - this._sendCommand('P', this.degamma(red), this.degamma(green), this.degamma(blue), dms >> 8, dms % 0xff, position, 0); + this._sendCommand('P', this.degamma(color.r), this.degamma(color.g), this.degamma(color.b), dms >> 8, dms % 0xff, position, 0); resolve(); }); + + return this._returnCallbackPromise(promise, callback); } - readPatternLine(position) { - return new Promise((resolve, reject) => { + readPatternLine(position, callback = () => {}) { + const promise = new Promise((resolve, reject) => { try { this._validatePosition(position); + this._isValidCallback(callback); } catch(error) { reject(error); } @@ -393,23 +286,29 @@ class Blink1 { this._readResponse().then(response => { resolve({ - red : response[2], - green : response[3], - blue : response[4], + color: new Color('rgb('+response[2]+','+response[3]+','+response[4]+')'), delay : ((response[5] << 8) + (response[6] & 0xff)) * 10 }); }); }); + + return this._returnCallbackPromise(promise, callback); } - close() { - return new Promise(resolve => { + close(callback = () => {}) { + const promise = new Promise((resolve, reject) => { + try { + this._isValidCallback(callback); + } catch(error) { + reject(error); + } + this.hidDevice.close(); resolve(); }); + + return this._returnCallbackPromise(promise, callback); } } module.exports = Blink1; -module.exports.Blink1 = Blink1; // backwards compatibility with older version -module.exports.devices = devices; diff --git a/examples/cops.js b/examples/cops.js new file mode 100644 index 0000000..ffdf3d0 --- /dev/null +++ b/examples/cops.js @@ -0,0 +1,25 @@ +const Blink1 = require('../blink1'); +const Color = require('rgbcolor'); + +let d = Blink1.devices()[0]; +let b = new Blink1(d); +callTheCops(new Color('red'), 1); +callTheCops(new Color('blue'), 2); + +function callTheCops(color, index) { + b.fadeToRGB({ + color, + delay: 100, + index, + callback: (data) => { + console.log("finished", data); + } + }).then(data => { + if (data.color.r == 255) { + newColor = new Color('blue'); + } else { + newColor = new Color('red'); + } + callTheCops(newColor, index); + }); +} diff --git a/helpers.js b/helpers.js new file mode 100644 index 0000000..8bc8a2c --- /dev/null +++ b/helpers.js @@ -0,0 +1,50 @@ +const Blink1_Base = require('./base'); + +class Blink1_Helpers extends Blink1_Base { + constructor(serialNumber) { + super(serialNumber); + } + + // Helpers + + _returnCallbackPromise(promise, callback) { + try { + this._isValidCallback(callback); + } catch(error) { + return promise; + } + + promise.then(callback); + return promise; + } + + _serverDown(on, delay) { + return new Promise(resolve => { + let dms = delay / 10; + this._sendCommand('D', on, dms >> 8, dms % 0xff); + + setTimeout(resolve, delay); + }); + } + + _play(play, position) { + return new Promise(resolve => { + this._sendCommand('p', play, position); + resolve(); + }); + } + + _playLoop({ + play, + start, + end, + count + }) { + return new Promise(resolve => { + this._sendCommand('p', play, start, end, count); + resolve(); + }); + } +} + +module.exports = Blink1_Helpers; diff --git a/package.json b/package.json index 7ac9556..f800a06 100644 --- a/package.json +++ b/package.json @@ -19,16 +19,17 @@ "blink(1)", "blink1" ], + "devDependencies": { + "async": "^2.6.0", + "jshint": "^2.9.5", + "mocha": "^5.0.0", + "mockery": "^2.1.0", + "should": "^13.2.1" + }, "dependencies": { "lodash": "^4.17.4", - "node-hid": "~0.5.0" - }, - "devDependencies": { - "jshint": "latest", - "mocha": "latest", - "should": "latest", - "mockery": "latest", - "async": "~0.9.0" + "node-hid": "^0.7.2", + "rgbcolor": "^1.0.1" }, "scripts": { "pretest": "jshint *.js", diff --git a/unit-tests.js b/unit-tests.js index 2d57b7f..7367582 100644 --- a/unit-tests.js +++ b/unit-tests.js @@ -1,3 +1,4 @@ +var Color = require('rgbcolor'); var should = require('should'); var mockery = require('mockery'); @@ -328,9 +329,7 @@ describe('blink(1)', () => { (function(){ blink1.fadeToRGB({ delay : 'Bad fadeMillis', - red : R, - green : G, - blue : B + color : new Color('rgb('+R+','+G+','+B+')') }).catch(error => { error.should.eql("fadeMillis must be a number"); }); @@ -341,9 +340,7 @@ describe('blink(1)', () => { (function(){ blink1.fadeToRGB({ delay : -1, - red : R, - green : G, - blue : B + color : new Color('rgb('+R+','+G+','+B+')') }).catch(error => { error.should.eql("fadeMillis must be between 0 and 655350"); }); @@ -354,9 +351,7 @@ describe('blink(1)', () => { (function(){ blink1.fadeToRGB({ delay : 655351, - red : R, - green : G, - blue : B + color : new Color('rgb('+R+','+G+','+B+')') }).catch(error => { error.should.eql("fadeMillis must be between 0 and 655350"); }); @@ -367,9 +362,7 @@ describe('blink(1)', () => { (function(){ blink1.fadeToRGB({ delay : FADE_MILLIS, - red : 'Bad r', - green : G, - blue : B + color : new Color('rgb('+R+','+G+','+B+')') }).catch(error => { error.should.eql("r must be a number"); }); @@ -380,9 +373,7 @@ describe('blink(1)', () => { (function(){ blink1.fadeToRGB({ delay : FADE_MILLIS, - red : -1, - green : G, - blue : B + color : new Color('rgb('+-1+','+G+','+B+')') }).catch(error => { error.should.eql("r must be between 0 and 255"); }); @@ -393,9 +384,7 @@ describe('blink(1)', () => { (function(){ blink1.fadeToRGB({ delay : FADE_MILLIS, - red : 256, - green : G, - blue : B + color : new Color('rgb('+256+','+G+','+B+')') }).catch(error => { error.should.eql("r must be between 0 and 255"); }); @@ -406,9 +395,7 @@ describe('blink(1)', () => { (function(){ blink1.fadeToRGB({ delay : FADE_MILLIS, - red : R, - green : 'Bad g', - blue : B + color : new Color('rgb('+R+',Bad g,'+B+')') }).catch(error => { error.should.eql("g must be a number"); }); @@ -419,9 +406,7 @@ describe('blink(1)', () => { (function(){ blink1.fadeToRGB({ delay : FADE_MILLIS, - red : R, - green : -1, - blue : B + color : new Color('rgb('+R+','+-1+','+B+')') }).catch(error => { error.should.eql("g must be between 0 and 255"); }); @@ -432,9 +417,7 @@ describe('blink(1)', () => { (function(){ blink1.fadeToRGB({ delay : FADE_MILLIS, - red : R, - green : 256, - blue : B + color : new Color('rgb('+R+','+256+','+B+')') }).catch(error => { error.should.eql("g must be between 0 and 255"); }); @@ -445,9 +428,7 @@ describe('blink(1)', () => { (function(){ blink1.fadeToRGB({ delay : FADE_MILLIS, - red : R, - green : G, - blue : 'Bad b' + color : new Color('rgb('+R+','+G+',Bad b)') }).catch(error => { error.should.eql("b must be a number"); }); @@ -458,9 +439,7 @@ describe('blink(1)', () => { (function(){ blink1.fadeToRGB({ delay : FADE_MILLIS, - red : R, - green : G, - blue : -1 + color : new Color('rgb('+R+','+G+','+-1+')') }).catch(error => { error.should.eql("b must be between 0 and 255"); }); @@ -471,9 +450,7 @@ describe('blink(1)', () => { (function(){ blink1.fadeToRGB({ delay : FADE_MILLIS, - red : R, - green : G, - blue : 256 + color : new Color('rgb('+R+','+G+','+256+')') }).catch(error => { error.should.eql("b must be between 0 and 255"); }); @@ -483,9 +460,7 @@ describe('blink(1)', () => { it('should send fadetorgb feature report', () => { blink1.fadeToRGB({ delay : FADE_MILLIS, - red : R, - green : G, - blue : B + color : new Color('rgb('+R+','+G+','+B+')') }); sentFeatureReport.should.eql([FEATURE_REPORT_ID, 0x63, blink1.degamma(R), blink1.degamma(G), blink1.degamma(B), (FADE_MILLIS / 10) >> 8, (FADE_MILLIS / 10) % 0xff, 0, 0]); @@ -494,9 +469,7 @@ describe('blink(1)', () => { it('should resolve promise', (done) => { blink1.fadeToRGB({ delay : FADE_MILLIS, - red : R, - green : G, - blue : B + color : new Color('rgb('+R+','+G+','+B+')') }).then(() => { done(); }); @@ -506,9 +479,7 @@ describe('blink(1)', () => { (function(){ blink1.fadeToRGB({ delay : FADE_MILLIS, - red : R, - green : G, - blue : B, + color : new Color('rgb('+R+','+G+','+B+')'), index : -1 }).catch(error => { error.should.eql("index must be between 0 and 2"); @@ -520,9 +491,7 @@ describe('blink(1)', () => { (function(){ blink1.fadeToRGB({ delay : FADE_MILLIS, - red : R, - green : G, - blue : B, + color : new Color('rgb('+R+','+G+','+B+')'), index : 3 }).catch(error => { error.should.eql("index must be between 0 and 2"); @@ -533,9 +502,7 @@ describe('blink(1)', () => { it('should send fadetorgb index feature report', () => { blink1.fadeToRGB({ delay : FADE_MILLIS, - red : R, - green : G, - blue : B, + color : new Color('rgb('+R+','+G+','+B+')'), index : INDEX }); @@ -545,9 +512,7 @@ describe('blink(1)', () => { it('should resolve promise (index)', (done) => { blink1.fadeToRGB({ delay : FADE_MILLIS, - red : R, - green : G, - blue : B, + color : new Color('rgb('+R+','+G+','+B+')'), index : INDEX }).then(() => { done(); @@ -565,11 +530,7 @@ describe('blink(1)', () => { it('should reject (catch) promise when r is not a number', () => { (function(){ - blink1.setRGB({ - red : 'Bad r', - green : G, - blue : B - }).catch(error => { + blink1.setRGB(new Color('rgb(bad r,'+G+','+B+')')).catch(error => { error.should.eql("r must be a number"); }); }); @@ -577,11 +538,7 @@ describe('blink(1)', () => { it('should reject (catch) promise when r is less than 0', () => { (function(){ - blink1.setRGB({ - red : -1, - green : G, - blue : B - }).catch(error => { + blink1.setRGB(new Color('rgb('+-1+','+G+','+B+')')).catch(error => { error.should.eql("r must be between 0 and 255"); }); }); @@ -589,11 +546,7 @@ describe('blink(1)', () => { it('should reject (catch) promise when r is greater than 255', () => { (function(){ - blink1.setRGB({ - red : 256, - green : G, - blue : B - }).catch(error => { + blink1.setRGB(new Color('rgb('+256+','+G+','+B+')')).catch(error => { error.should.eql("r must be between 0 and 255"); }); }); @@ -601,11 +554,7 @@ describe('blink(1)', () => { it('should reject (catch) promise when g is not a number', () => { (function(){ - blink1.setRGB({ - red : R, - green : 'Bad g', - blue : B - }).catch(error => { + blink1.setRGB(new Color('rgb('+R+',Bad g,'+B+')')).catch(error => { error.should.eql("g must be a number"); }); }); @@ -613,11 +562,7 @@ describe('blink(1)', () => { it('should reject (catch) promise when g is less than 0', () => { (function(){ - blink1.setRGB({ - red : R, - green : -1, - blue : B - }).catch(error => { + blink1.setRGB(new Color('rgb('+R+','+-1+','+B+')')).catch(error => { error.should.eql("g must be between 0 and 255"); }); }); @@ -625,11 +570,7 @@ describe('blink(1)', () => { it('should reject (catch) promise when g is greater than 255', () => { (function(){ - blink1.setRGB({ - red : R, - green : 256, - blue : B - }).catch(error => { + blink1.setRGB(new Color('rgb('+R+','+256+','+B+')')).catch(error => { error.should.eql("g must be between 0 and 255"); }); }); @@ -637,11 +578,7 @@ describe('blink(1)', () => { it('should reject (catch) promise when b is not a number', () => { (function(){ - blink1.setRGB({ - red : R, - green : G, - blue : 'Bad b' - }).catch(error => { + blink1.setRGB(new Color('rgb('+R+','+G+',Bad b)')).catch(error => { error.should.eql("b must be a number"); }); }); @@ -649,11 +586,7 @@ describe('blink(1)', () => { it('should reject (catch) promise when b is less than 0', () => { (function(){ - blink1.setRGB({ - red : R, - green : G, - blue : -1 - }).catch(error => { + blink1.setRGB(new Color('rgb('+R+','+G+','+-1+')')).catch(error => { error.should.eql("b must be between 0 and 255"); }); }); @@ -661,32 +594,20 @@ describe('blink(1)', () => { it('should reject (catch) promise when b is greater than 255', () => { (function(){ - blink1.setRGB({ - red : R, - green : G, - blue : 256 - }).catch(error => { + blink1.setRGB(new Color('rgb('+R+','+G+','+256+')')).catch(error => { error.should.eql("b must be between 0 and 255"); }); }); }); it('should send setrgb feature report', () => { - blink1.setRGB({ - red : R, - green : G, - blue : B - }); + blink1.setRGB(new Color('rgb('+R+','+G+','+B+')')); sentFeatureReport.should.eql([FEATURE_REPORT_ID, 0x6e, blink1.degamma(R), blink1.degamma(G), blink1.degamma(B), 0, 0, 0, 0]); }); it('should resolve promise', (done) => { - blink1.setRGB({ - red : R, - green : G, - blue : B - }).then(() => { + blink1.setRGB(new Color('rgb('+R+','+G+','+B+')')).then(() => { done(); }); }); @@ -730,16 +651,16 @@ describe('blink(1)', () => { }); it('should resolve promise with r, g, b', (done) => { - blink1.getRGB().then(({red, green, blue}) => { + blink1.getRGB().then(({r, g, b}) => { done(); }); }); it('should resolve promise with correct r, g, b', (done) => { - blink1.getRGB().then(({red, green, blue}) => { - red.should.eql(R); - green.should.eql(G); - blue.should.eql(B); + blink1.getRGB().then(({r, g, b}) => { + r.should.eql(R); + g.should.eql(G); + b.should.eql(B); done(); }); }); @@ -751,16 +672,16 @@ describe('blink(1)', () => { }); it('should resolve promise with r, g, b (index)', (done) => { - blink1.getRGB(INDEX).then(({red, green, blue}) => { + blink1.getRGB(INDEX).then(({r, g, b}) => { done(); }); }); it('should resolve promise with correct r, g, b (index)', (done) => { - blink1.getRGB(INDEX).then(({red, green, blue}) => { - red.should.eql(R); - green.should.eql(G); - blue.should.eql(B); + blink1.getRGB(INDEX).then(({r, g, b}) => { + r.should.eql(R); + g.should.eql(G); + b.should.eql(B); done(); }); }); @@ -1055,9 +976,7 @@ describe('blink(1)', () => { (function(){ blink1.writePatternLine({ delay : 'Bad fadeMillis', - red : R, - green : G, - blue : B, + color : new Color('rgb('+R+','+G+','+B+')'), position : POSITION }).catch(error => { error.should.eql('fadeMillis must be a number'); @@ -1069,9 +988,7 @@ describe('blink(1)', () => { (function(){ blink1.writePatternLine({ delay : -1, - red : R, - green : G, - blue : B, + color : new Color('rgb('+R+','+G+','+B+')'), position : POSITION }).catch(error => { error.should.eql('fadeMillis must be between 0 and 655350'); @@ -1083,9 +1000,7 @@ describe('blink(1)', () => { (function(){ blink1.writePatternLine({ delay : 655351, - red : R, - green : G, - blue : B, + color : new Color('rgb('+R+','+G+','+B+')'), position : POSITION }).catch(error => { error.should.eql('fadeMillis must be between 0 and 655350'); @@ -1097,9 +1012,7 @@ describe('blink(1)', () => { (function(){ blink1.writePatternLine({ delay : FADE_MILLIS, - red : 'Bad r', - green : G, - blue : B, + color : new Color('rgb(Bad r,'+G+','+B+')'), position : POSITION }).catch(error => { error.should.eql('r must be a number'); @@ -1111,9 +1024,7 @@ describe('blink(1)', () => { (function(){ blink1.writePatternLine({ delay : FADE_MILLIS, - red : -1, - green : G, - blue : B, + color : new Color('rgb('+-1+','+G+','+B+')'), position : POSITION }).catch(error => { error.should.eql('r must be between 0 and 255'); @@ -1125,9 +1036,7 @@ describe('blink(1)', () => { (function(){ blink1.writePatternLine({ delay : FADE_MILLIS, - red : 256, - green : G, - blue : B, + color : new Color('rgb('+256+','+G+','+B+')'), position : POSITION }).catch(error => { error.should.eql('r must be between 0 and 255'); @@ -1139,9 +1048,7 @@ describe('blink(1)', () => { (function(){ blink1.writePatternLine({ delay : FADE_MILLIS, - red : R, - green : 'Bad g', - blue : B, + color : new Color('rgb('+R+',Bad g,'+B+')'), position : POSITION }).catch(error => { error.should.eql('g must be a number'); @@ -1153,9 +1060,7 @@ describe('blink(1)', () => { (function(){ blink1.writePatternLine({ delay : FADE_MILLIS, - red : R, - green : -1, - blue : B, + color : new Color('rgb('+R+','+-1+','+B+')'), position : POSITION }).catch(error => { error.should.eql('g must be between 0 and 255'); @@ -1167,9 +1072,7 @@ describe('blink(1)', () => { (function(){ blink1.writePatternLine({ delay : FADE_MILLIS, - red : R, - green : 256, - blue : B, + color : new Color('rgb('+R+','+256+','+B+')'), position : POSITION }).catch(error => { error.should.eql('g must be between 0 and 255'); @@ -1181,9 +1084,7 @@ describe('blink(1)', () => { (function(){ blink1.writePatternLine({ delay : FADE_MILLIS, - red : R, - green : G, - blue : 'Bad b', + color : new Color('rgb('+R+','+G+',Bad b)'), position : POSITION }).catch(error => { error.should.eql('b must be a number'); @@ -1195,9 +1096,7 @@ describe('blink(1)', () => { (function(){ blink1.writePatternLine({ delay : FADE_MILLIS, - red : R, - green : G, - blue : -1, + color : new Color('rgb('+R+','+G+','+-1+')'), position : POSITION }).catch(error => { error.should.eql('b must be between 0 and 255'); @@ -1209,9 +1108,7 @@ describe('blink(1)', () => { (function(){ blink1.writePatternLine({ delay : FADE_MILLIS, - red : R, - green : G, - blue : 256, + color : new Color('rgb('+R+','+G+','+256+')'), position : POSITION }).catch(error => { error.should.eql('b must be between 0 and 255'); @@ -1223,9 +1120,7 @@ describe('blink(1)', () => { (function(){ blink1.writePatternLine({ delay : FADE_MILLIS, - red : R, - green : G, - blue : B, + color : new Color('rgb('+R+','+G+','+B+')'), position : 'Bad position' }).catch(error => { error.should.eql('position must be a number'); @@ -1237,9 +1132,7 @@ describe('blink(1)', () => { (function(){ blink1.writePatternLine({ delay : FADE_MILLIS, - red : R, - green : G, - blue : B, + color : new Color('rgb('+R+','+G+','+B+')'), position : -1 }).catch(error => { error.should.eql('position must be between 0 and 11'); @@ -1251,9 +1144,7 @@ describe('blink(1)', () => { (function(){ blink1.writePatternLine({ delay : FADE_MILLIS, - red : R, - green : G, - blue : B, + color : new Color('rgb('+R+','+G+','+B+')'), position : 12 }).catch(error => { error.should.eql('position must be between 0 and 11'); @@ -1264,9 +1155,7 @@ describe('blink(1)', () => { it('should send writepatternline feature report', () => { blink1.writePatternLine({ delay : FADE_MILLIS, - red : R, - green : G, - blue : B, + color : new Color('rgb('+R+','+G+','+B+')'), position : POSITION }); @@ -1276,9 +1165,7 @@ describe('blink(1)', () => { it('should resolve promise', (done) => { blink1.writePatternLine({ delay : FADE_MILLIS, - red : R, - green : G, - blue : B, + color : new Color('rgb('+R+','+G+','+B+')'), position : POSITION }).then(() => { done(); @@ -1333,9 +1220,7 @@ describe('blink(1)', () => { it('should resolve promise with value', (done) => { blink1.readPatternLine(POSITION).then(({ - red, - green, - blue, + color, delay }) => { done(); @@ -1345,14 +1230,12 @@ describe('blink(1)', () => { it('should resolve promise with correct value', (done) => { blink1.readPatternLine(POSITION).then(({ - red, - green, - blue, + color, delay }) => { - red.should.eql(R); - green.should.eql(G); - blue.should.eql(B); + color.r.should.eql(R); + color.g.should.eql(G); + color.b.should.eql(B); delay.should.eql(FADE_MILLIS); done(); diff --git a/validators.js b/validators.js new file mode 100644 index 0000000..25ebb32 --- /dev/null +++ b/validators.js @@ -0,0 +1,66 @@ +const Blink1_Helpers = require('./helpers'); + +class Blink1_Validators extends Blink1_Helpers { + constructor(serialNumber) { + super(serialNumber); + } + + // Validators + + _isValidCallback(callback) { + return (typeof callback === 'function'); + } + + _validateNumber(number, name, min, max) { + if (typeof number !== 'number') { + throw new Error(name + ' must be a number'); + } + + if (number < min || number > max) { + throw new Error(name + ' must be between ' + min + ' and ' + max); + } + } + + _validateAddress(address) { + this._validateNumber(address, 'address', 0, 0xffff); // Decimal 0 - 65535 + } + + _validateValue(value) { + this._validateNumber(value, 'value', 0, 0xff); // Decimal 0 - 255 + } + + _validateCount(value) { + this._validateNumber(value, 'count', 0, 0xff); // Decimal 0 - 255 + } + + _validateFadeMillis(fadeMillis) { + this._validateNumber(fadeMillis, 'fadeMillis', 0, 0x9FFF6); // Decimal 0 - 655350 + } + + _validateColor(color) { + if (!color.ok) { + throw new Error('color ('+color+')is invalid'); + } + } + + _validateRGB(color) { + this._validateColor(color); + this._validateNumber(color.r, 'r', 0, 0xff); // Decimal 0 - 255 + this._validateNumber(color.g, 'g', 0, 0xff); // Decimal 0 - 255 + this._validateNumber(color.b, 'b', 0, 0xff); // Decimal 0 - 255 + } + + _validateMillis(millis) { + this._validateNumber(millis, 'millis', 0, 0x9FFF6); // Decimal 0 - 655350 + } + + _validatePosition(position) { + this._validateNumber(position, 'position', 0, 11); + } + + _validateIndex(index) { + this._validateNumber(index, 'index', 0, 2); + } +} + +module.exports = Blink1_Validators; From ca90befd52704e87b612c8928ca8a1eecdf90ff8 Mon Sep 17 00:00:00 2001 From: Sean Teague Date: Mon, 22 Jan 2018 00:48:07 -0800 Subject: [PATCH 4/5] Updated yarn lock file --- yarn.lock | 580 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 580 insertions(+) create mode 100644 yarn.lock diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..2dc849c --- /dev/null +++ b/yarn.lock @@ -0,0 +1,580 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + +are-we-there-yet@~1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +async@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" + dependencies: + lodash "^4.14.0" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + +bindings@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.0.tgz#b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7" + +bl@^1.0.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e" + dependencies: + readable-stream "^2.0.5" + +brace-expansion@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +browser-stdout@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" + +chownr@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" + +cli@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cli/-/cli-1.0.1.tgz#22817534f24bfa4950c34d532d48ecbc621b8c14" + dependencies: + exit "0.1.2" + glob "^7.1.1" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +commander@2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +console-browserify@1.1.x: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" + dependencies: + date-now "^0.1.4" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +date-now@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" + +debug@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + dependencies: + ms "2.0.0" + +deep-extend@~0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + +diff@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" + +dom-serializer@0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" + dependencies: + domelementtype "~1.1.1" + entities "~1.1.1" + +domelementtype@1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" + +domelementtype@~1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" + +domhandler@2.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.3.0.tgz#2de59a0822d5027fabff6f032c2b25a2a8abe738" + dependencies: + domelementtype "1" + +domutils@1.5: + version "1.5.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" + dependencies: + dom-serializer "0" + domelementtype "1" + +end-of-stream@^1.0.0, end-of-stream@^1.1.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" + dependencies: + once "^1.4.0" + +entities@1.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26" + +entities@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" + +escape-string-regexp@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +exit@0.1.2, exit@0.1.x: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + +expand-template@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-1.1.0.tgz#e09efba977bf98f9ee0ed25abd0c692e02aec3fc" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +github-from-package@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" + +glob@7.1.2, glob@^7.1.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +growl@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" + +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + +he@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + +htmlparser2@3.8.x: + version "3.8.3" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.8.3.tgz#996c28b191516a8be86501a7d79757e5c70c1068" + dependencies: + domelementtype "1" + domhandler "2.3" + domutils "1.5" + entities "1.0" + readable-stream "1.1" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +ini@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +jshint@^2.9.5: + version "2.9.5" + resolved "https://registry.yarnpkg.com/jshint/-/jshint-2.9.5.tgz#1e7252915ce681b40827ee14248c46d34e9aa62c" + dependencies: + cli "~1.0.0" + console-browserify "1.1.x" + exit "0.1.x" + htmlparser2 "3.8.x" + lodash "3.7.x" + minimatch "~3.0.2" + shelljs "0.3.x" + strip-json-comments "1.0.x" + +lodash@3.7.x: + version "3.7.0" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.7.0.tgz#3678bd8ab995057c07ade836ed2ef087da811d45" + +lodash@^4.14.0, lodash@^4.17.4: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + +minimatch@^3.0.4, minimatch@~3.0.2: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +mkdirp@0.5.1, mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +mocha@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.0.0.tgz#cccac988b0bc5477119cba0e43de7af6d6ad8f4e" + dependencies: + browser-stdout "1.3.0" + commander "2.11.0" + debug "3.1.0" + diff "3.3.1" + escape-string-regexp "1.0.5" + glob "7.1.2" + growl "1.10.3" + he "1.1.1" + mkdirp "0.5.1" + supports-color "4.4.0" + +mockery@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mockery/-/mockery-2.1.0.tgz#5b0aef1ff564f0f8139445e165536c7909713470" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + +nan@^2.6.2: + version "2.8.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a" + +node-abi@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.1.2.tgz#4da6caceb6685fcd31e7dd1994ef6bb7d0a9c0b2" + dependencies: + semver "^5.4.1" + +node-hid@^0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/node-hid/-/node-hid-0.7.2.tgz#15025cdea2e9756aca2de7266529996d40e52c56" + dependencies: + bindings "^1.3.0" + nan "^2.6.2" + prebuild-install "^2.2.2" + +noop-logger@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" + +npmlog@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +os-homedir@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +prebuild-install@^2.2.2: + version "2.4.1" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-2.4.1.tgz#c28ba1d1eedc17fbd6b3229a657ffc0fba479b49" + dependencies: + expand-template "^1.0.2" + github-from-package "0.0.0" + minimist "^1.2.0" + mkdirp "^0.5.1" + node-abi "^2.1.1" + noop-logger "^0.1.1" + npmlog "^4.0.1" + os-homedir "^1.0.1" + pump "^1.0.1" + rc "^1.1.6" + simple-get "^1.4.2" + tar-fs "^1.13.0" + tunnel-agent "^0.6.0" + xtend "4.0.1" + +process-nextick-args@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + +pump@^1.0.0, pump@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954" + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +rc@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.4.tgz#a0f606caae2a3b862bbd0ef85482c0125b315fa3" + dependencies: + deep-extend "~0.4.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +readable-stream@1.1: + version "1.1.13" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.0.6: + version "2.3.3" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + safe-buffer "~5.1.1" + string_decoder "~1.0.3" + util-deprecate "~1.0.1" + +rgbcolor@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rgbcolor/-/rgbcolor-1.0.1.tgz#d6505ecdb304a6595da26fa4b43307306775945d" + +safe-buffer@^5.0.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" + +semver@^5.4.1: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + +set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +shelljs@0.3.x: + version "0.3.0" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.3.0.tgz#3596e6307a781544f591f37da618360f31db57b1" + +should-equal@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/should-equal/-/should-equal-2.0.0.tgz#6072cf83047360867e68e98b09d71143d04ee0c3" + dependencies: + should-type "^1.4.0" + +should-format@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/should-format/-/should-format-3.0.3.tgz#9bfc8f74fa39205c53d38c34d717303e277124f1" + dependencies: + should-type "^1.3.0" + should-type-adaptors "^1.0.1" + +should-type-adaptors@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz#401e7f33b5533033944d5cd8bf2b65027792e27a" + dependencies: + should-type "^1.3.0" + should-util "^1.0.0" + +should-type@^1.3.0, should-type@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/should-type/-/should-type-1.4.0.tgz#0756d8ce846dfd09843a6947719dfa0d4cff5cf3" + +should-util@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/should-util/-/should-util-1.0.0.tgz#c98cda374aa6b190df8ba87c9889c2b4db620063" + +should@^13.2.1: + version "13.2.1" + resolved "https://registry.yarnpkg.com/should/-/should-13.2.1.tgz#84e6ebfbb145c79e0ae42307b25b3f62dcaf574e" + dependencies: + should-equal "^2.0.0" + should-format "^3.0.3" + should-type "^1.4.0" + should-type-adaptors "^1.0.1" + should-util "^1.0.0" + +signal-exit@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +simple-get@^1.4.2: + version "1.4.3" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-1.4.3.tgz#e9755eda407e96da40c5e5158c9ea37b33becbeb" + dependencies: + once "^1.3.1" + unzip-response "^1.0.0" + xtend "^4.0.0" + +string-width@^1.0.1, string-width@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +string_decoder@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-json-comments@1.0.x: + version "1.0.4" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + +supports-color@4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" + dependencies: + has-flag "^2.0.0" + +tar-fs@^1.13.0: + version "1.16.0" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.0.tgz#e877a25acbcc51d8c790da1c57c9cf439817b896" + dependencies: + chownr "^1.0.1" + mkdirp "^0.5.1" + pump "^1.0.0" + tar-stream "^1.1.2" + +tar-stream@^1.1.2: + version "1.5.5" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.5.tgz#5cad84779f45c83b1f2508d96b09d88c7218af55" + dependencies: + bl "^1.0.0" + end-of-stream "^1.0.0" + readable-stream "^2.0.0" + xtend "^4.0.0" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + dependencies: + safe-buffer "^5.0.1" + +unzip-response@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-1.0.2.tgz#b984f0877fc0a89c2c773cc1ef7b5b232b5b06fe" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +wide-align@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710" + dependencies: + string-width "^1.0.2" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +xtend@4.0.1, xtend@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" From f52e012326e6f640dc51a4fa231bec9f1b7d2eb2 Mon Sep 17 00:00:00 2001 From: Sean Teague Date: Mon, 22 Jan 2018 01:04:23 -0800 Subject: [PATCH 5/5] Added explaination of the rgbcolor package to the README --- README.md | 24 ++++++++++++++++++++++++ examples/cops.js | 8 ++++---- validators.js | 3 ++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f0057e1..1861b4d 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,26 @@ Create blink(1) object with serial number, to get list of serial numbers use var blink1 = new Blink1(serialNumber); ``` +### rgbcolor package usage + +This blink1 package natively supports the [rgbcolor package](https://www.npmjs.com/package/rgbcolor). It is not required if you just pass an object containing RGB properties. At any point you see `new Color()` in the example code below, you can replace it with an RGB color object as shown: + +```javascript +// An example color object for the color red +var red = { + r: 255, + g: 0, + b: 0 +}; + +// An few example rgbcolor objects for the color red +const Color = require('rgbcolor'); +var red = new Color('red'); +var red = new Color('rgb(255,0,0)'); +var red = new Color('#FF0000'); +var red = new Color('#F00'); +``` + ### Get version * Accepts an optional callback function parameter @@ -87,6 +107,7 @@ Because most functions return promises, you can now chain actions together. This example will cause the device to fade to red over 2.5s, once complete, the device will then fade to green over another 2.5s. ```javascript +const Color = require('rgbcolor'); let blinkObject = { delay : 2500, color : new Color('red') @@ -107,6 +128,7 @@ Set RGB, returns Promise: * Returns Promise; automatically calls optional callback ```javascript +const Color = require('rgbcolor'); blink1.setRGB(new Color('red')[, callback]); ``` @@ -203,6 +225,7 @@ Write pattern line (set the parameters for a pattern line, at the specified posi * Returns Promise; automatically calls optional callback ```javascript +const Color = require('rgbcolor'); let blinkObject = { color : new Color('red'), delay : 100, @@ -215,6 +238,7 @@ blink1.writePatternLine(blinkObject); A simple example of this, used to flash red on & off is: ```javascript +const Color = require('rgbcolor'); let blinkObject = { delay : 200, color : new Color('red') diff --git a/examples/cops.js b/examples/cops.js index ffdf3d0..3697522 100644 --- a/examples/cops.js +++ b/examples/cops.js @@ -3,8 +3,8 @@ const Color = require('rgbcolor'); let d = Blink1.devices()[0]; let b = new Blink1(d); -callTheCops(new Color('red'), 1); -callTheCops(new Color('blue'), 2); +callTheCops({r: 255, g: 0, b: 0}, 1); +callTheCops({r: 0, g: 0, b: 255}, 2); function callTheCops(color, index) { b.fadeToRGB({ @@ -16,9 +16,9 @@ function callTheCops(color, index) { } }).then(data => { if (data.color.r == 255) { - newColor = new Color('blue'); + newColor = {r: 0, g: 0, b: 255}; } else { - newColor = new Color('red'); + newColor = {r: 255, g: 0, b: 0}; } callTheCops(newColor, index); }); diff --git a/validators.js b/validators.js index 25ebb32..9d94811 100644 --- a/validators.js +++ b/validators.js @@ -1,4 +1,5 @@ const Blink1_Helpers = require('./helpers'); +const Color = require('rgbcolor'); class Blink1_Validators extends Blink1_Helpers { constructor(serialNumber) { @@ -38,7 +39,7 @@ class Blink1_Validators extends Blink1_Helpers { } _validateColor(color) { - if (!color.ok) { + if (color instanceof Color && !color.ok) { throw new Error('color ('+color+')is invalid'); } }