ws2801-pi
Version:
WS2801-Pi is a module for controlling WS2801 LED strips with a Raspberry Pi via SPI.
202 lines • 7.55 kB
JavaScript
"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