UNPKG

ws2801-pi

Version:

WS2801-Pi is a module for controlling WS2801 LED strips with a Raspberry Pi via SPI.

202 lines 7.55 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ClockSpeed = void 0; const async_lock_1 = __importDefault(require("async-lock")); const pi_spi_1 = __importDefault(require("pi-spi")); const led_strip_validation_1 = require("./led-strip-validation"); var ClockSpeed; (function (ClockSpeed) { ClockSpeed[ClockSpeed["ZeroPointFiveMHZ"] = 500000] = "ZeroPointFiveMHZ"; ClockSpeed[ClockSpeed["OneMHZ"] = 1000000] = "OneMHZ"; ClockSpeed[ClockSpeed["TwoMHZ"] = 2000000] = "TwoMHZ"; ClockSpeed[ClockSpeed["FourMHZ"] = 4000000] = "FourMHZ"; ClockSpeed[ClockSpeed["EightMHZ"] = 8000000] = "EightMHZ"; ClockSpeed[ClockSpeed["SixteenMHZ"] = 16000000] = "SixteenMHZ"; ClockSpeed[ClockSpeed["ThirtyTwoMHZ"] = 32000000] = "ThirtyTwoMHZ"; })(ClockSpeed = exports.ClockSpeed || (exports.ClockSpeed = {})); var EventNames; (function (EventNames) { EventNames["LedStripChanged"] = "led-strip-changed"; EventNames["BrightnessChanged"] = "brightness-changed"; })(EventNames || (EventNames = {})); const lock = new async_lock_1.default(); const DEFAULT_CLOCK_SPEED = ClockSpeed.TwoMHZ; class LedController { constructor(ledAmount, config = {}) { this.undisplayedLedStrip = []; this.displayedLedStrip = []; this.brightness = 'auto'; this.listeners = {}; this.ledAmount = ledAmount; this.debug = config.debug === true; this.automaticRendering = config.automaticRendering === true; if (!this.debug) { this.spi = pi_spi_1.default.initialize('/dev/spidev0.0'); this.clockSpeed = config.spiClockSpeed ? config.spiClockSpeed : DEFAULT_CLOCK_SPEED; } this.clearLeds(); this.displayedLedStrip = this.undisplayedLedStrip; } set clockSpeed(clockSpeed) { this.spiClockSpeed = clockSpeed; if (!this.debug) { this.spi.clockSpeed(clockSpeed); } } get clockSpeed() { return this.spiClockSpeed; } getLedStrip() { return this.displayedLedStrip; } setLed(ledIndex, color) { this.colorizeLed(ledIndex, color); if (this.automaticRendering) { this.show(); } return this; } fillLeds(color) { for (let ledIndex = 0; ledIndex < this.ledAmount; ledIndex++) { this.colorizeLed(ledIndex, color); } if (this.automaticRendering) { this.show(); } return this; } setBrightness(brightness) { if ((typeof brightness !== 'number' && brightness !== 'auto') || brightness < 0 || brightness > 100) { throw new Error(`The brightness must be between 0 and 100 or 'auto'.`); } this.brightness = brightness; this.brightnessChanged(); return this; } getBrightness() { return this.brightness; } clearLeds() { const black = { red: 0, green: 0, blue: 0 }; this.fillLeds(black); if (this.automaticRendering) { this.show(); } return this; } setLedStrip(ledStrip) { led_strip_validation_1.validateLedStrip(this.ledAmount, ledStrip); for (let ledIndex = 0; ledIndex < this.ledAmount; ledIndex++) { this.colorizeLed(ledIndex, ledStrip[ledIndex]); } if (this.automaticRendering) { this.show(); } return this; } show() { const ledsToFill = this.undisplayedLedStrip.slice(); const ledBufferToWrite = this.getLedStripAsBuffer(ledsToFill); this.renderPromise = lock.acquire('render', async (done) => { const doneWriting = async () => { this.displayedLedStrip = ledsToFill; this.ledStripChanged(ledsToFill); done(); }; if (this.debug) { setTimeout(() => { doneWriting(); }, 60); return; } this.spi.write(ledBufferToWrite, doneWriting); }); return this.renderPromise; } onLedStripChanged(callback) { const id = this.generateId(5); this.listeners[id] = { event: EventNames.LedStripChanged, callback: callback, }; return id; } onBrightnessChanged(callback) { const id = this.generateId(5); this.listeners[id] = { event: EventNames.BrightnessChanged, callback: callback, }; return id; } removeEventListener(id) { delete this.listeners[id]; } ledStripChanged(ledStrip) { const ledStripChangedListeners = Object.values(this.listeners).filter((listener) => listener.event === EventNames.LedStripChanged); for (const listener of ledStripChangedListeners) { listener.callback(ledStrip); } } brightnessChanged() { const brightnessChangedListeners = Object.values(this.listeners).filter((listener) => listener.event === EventNames.BrightnessChanged); for (const listener of brightnessChangedListeners) { listener.callback(this.brightness); } } colorizeLed(ledNumber, color) { const fixedColor = { red: Math.max(0, Math.min(color.red, 255)), green: Math.max(0, Math.min(color.green, 255)), blue: Math.max(0, Math.min(color.blue, 255)), }; this.undisplayedLedStrip[ledNumber] = fixedColor; } getLedStripAsBuffer(ledStrip) { const ledStripBuffer = Buffer.alloc(this.ledAmount * 3); for (let ledNumber = 0; ledNumber < this.ledAmount; ledNumber++) { const brightnessAdjustedColor = this.getBrightnessAdjustedColor(ledStrip[ledNumber]); const ledBufferIndex = ledNumber * 3; ledStripBuffer[ledBufferIndex] = brightnessAdjustedColor.red; ledStripBuffer[ledBufferIndex + 1] = brightnessAdjustedColor.green; ledStripBuffer[ledBufferIndex + 2] = brightnessAdjustedColor.blue; } return ledStripBuffer; } getBrightnessAdjustedColor(color) { if (this.brightness === 'auto') { return color; } const brightnessMultiplier = this.brightness / 100 * 255; const highestColorValue = this.getHighestColorValue(color); const brightnessAdjustedColor = { red: color.red / highestColorValue * brightnessMultiplier, green: color.green / highestColorValue * brightnessMultiplier, blue: color.blue / highestColorValue * brightnessMultiplier, }; return brightnessAdjustedColor; } getHighestColorValue(color) { if (color.red >= color.green && color.red >= color.blue) { return color.red; } if (color.green >= color.blue) { return color.green; } return color.blue; } generateId(idLength) { let result = ''; const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; const charactersLength = characters.length; for (let index = 0; index < idLength; index++) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } return result; } } exports.default = LedController; //# sourceMappingURL=index.js.map