UNPKG

ws2801-connect

Version:

A javascript class to control a WS2801 led stripe

221 lines (202 loc) 7.27 kB
/* * Copyright 2017 Armin Junge. */ /* global Symbol */ var colorLib = require("color") /** * Represents your WS2801 led stripe */ class WS2801{ /** * Creates the representation of the led stripe. * @param {Object} options - options for the led stripe representation * @param {Number} options.count - Number of led lights on the stripe (must be greater 0) * @param {WS2801~spiWrite} options.spiWrite - Callback for writing to the SPI * @param {Array} options.rgbIndex - [0] = index of red, [1] = index of green, [2] = index of blue; * in the resulting data array for WS2801; default: [0] = 0, [1] = 1, [2] = 2; red first, green second, blue third * @returns {WS2801} */ constructor(options){ this.count = options.count this.spiWrite = (typeof options.spiWrite === "function")?options.spiWrite:function(){} if(Array.isArray(options.rgbIndex) && options.rgbIndex.length === 3){ WS2801.assert(options.rgbIndex.every(item => item >= 0 && item <= 2), "Wrong index supplied") this.rgbIndex = options.rgbIndex } else this.rgbIndex = [0,1,2] this.rgbMap = Array(3) this.rgbIndex.forEach(function(item, index){ this.rgbMap[item] = index }, this) } /** * Helper method for the assertion of the given expression. * If the expression is false, the method throws the given message as exception. * @private * @param {Boolean} expression - any logical expression * @param {String} message - text, which will be thrown as exception * @returns {undefined} */ static assert(expression, message){ if(!expression) throw message } /** * Sets the number of supported led lights. * @param {Number} number - number of led lights * @returns {undefined} */ set count(number){ WS2801.assert(number > 0, "Only natural numbers are valid") // Each light has three colors, so we need the tripple of count this.rgbLights = Array(3 * number) this.clear() } /** * Returns the number of supported led lights. * @returns {Number} */ get count(){ return this.rgbLights.length / 3 } /** * Static helper method to determine red, green and blue values. * Either from a string like "#fe12a9" * or from the elements of the array, where the elements are red, green and blue * or from an array as once element, which is identical to the returning one. * * Usually this method will be called using a rest parameter. * See {@link ws2801#setLight setLight()} or {@link ws2801#fill fill()} * @example //with String * let r, g, b * [r, g, b] = ws2801.rgbFrom(["#fe12a9"]) * // r = 0xfe, g = 0x12, b = 0xa9 * @example //with Elements * let r, g, b * [r, g, b] = ws2801.rgbFrom([0xfe, 0x12, 0xa9]) * // r = 0xfe, g = 0x12, b = 0xa9 * @example //with Array * let r, g, b * [r, g, b] = ws2801.rgbFrom([[0xfe, 0x12, 0xa9]]) * // r = 0xfe, g = 0x12, b = 0xa9 * @example //with rest parameter * function rgb(...color) { * return ws2801.rgbFrom(color) * } * rgb("#fe12a9") * rgb(0xfe, 0x12, 0xa9) * rgb([0xfe, 0x12, 0xa9]) * @param {Array} color - Having one element with a string or an array * containing red, green and blue as elements or having three elements * representing red, green and blue * @returns {Array} Contains red, green and blue as elements */ static rgbFrom(color){ switch(color.length){ case 1: return (color[0] instanceof Array)?WS2801.rgbFrom(color[0]):colorLib(color[0]).array() case 3: return color default: WS2801.assert(false, "Wrong number of arguments") } } /** * Sets the color of the led light specified by the given index number. * @example //Usage * leds.setLight(0, "#ff0000") //set first light to red * leds.setLight(1, 0, 255, 0) //set second light to green * leds.setLight(2, [0x00, 0x00, 0xff]) //set third light to blue * @param {Number} number - Index of the led light, starting at 0. * Must not exceed number of led lights. * @param {String|...Number|Array} color - Contains a string like "#fe12a9" * or an array with red, green and blue as elements like [0xfe, 0x12, 0xa9] * or a parameter list of three elments as red, green and blue like (..., 0xfe, 0x12, 0xa9) * @returns {WS2801} */ setLight(number, ...color) { WS2801.assert(number >= 0 && number < this.count, "Given Number is out of range") let r, g, b [r, g, b] = WS2801.rgbFrom(color) // set red this.rgbLights[3*number+this.rgbIndex[0]] = r & 0xff // set green this.rgbLights[3*number+this.rgbIndex[1]] = g & 0xff // set blue this.rgbLights[3*number+this.rgbIndex[2]] = b & 0xff return this } /** * Set possibly all lights with given colors. * If the number of given colors is to low, the rest goes black. * Superfluous are ignored. * @param {Array.<String|Array>} colors * @returns {WS2801} */ setAll(colors){ WS2801.assert(colors instanceof Array, "Parameter must be an array") this.clear() colors.forEach(function(item, index){ if(index < this.count) this.setLight(index, item) }, this) return this } /** * Iterator for the supported led lights. Each element is always an array * with three elements representing red, green and blue. * @returns {Generator} */ *[Symbol.iterator]() { for(let n = 0, end = this.count; n < end; ++n) yield [this.rgbLights[3*n+this.rgbIndex[0]],this.rgbLights[3*n+this.rgbIndex[1]],this.rgbLights[3*n+this.rgbIndex[2]]] } /** * Writes the led lights colors to the led stripe using the supplied SPI instance. * You have to call this method everytime you want to see the set colors * on your led stripe. * @returns {WS2801} */ show() { this.spiWrite(this.rgbLights) return this } /** * Sets all supported led lights to black. * @returns {WS2801} */ clear() { this.rgbLights.fill(0) return this } /** * Sets all supported led lights to the given color. * @example //Usage * leds.fill("#ff0000") // set all led lights to red * leds.fill(0, 255, 0) // set all led lights to green * leds.fill([0x00, 0x00, 0xff]) // set all led lights to blue * @param {String|...Number|Array} color - Contains a string like "#fe12a9" * or an array with red, green and blue as elements like [0xfe, 0x12, 0xa9] * or a parameter list of three elments as red, green and blue like (..., 0xfe, 0x12, 0xa9) * @returns {WS2801} */ fill(...color) { let rgb = WS2801.rgbFrom(color) this.rgbLights.forEach(function(item, index, arr){ arr[index] = rgb[this.rgbMap[index % 3]] }, this) return this } } /** * Callback for writing to the SPI * @callback WS2801~spiWrite * @param {Array} data - Data (color information) which has to be transfered to the led stripe */ module.exports = WS2801