UNPKG

sys-class-rgb-led

Version:
140 lines 4.5 kB
"use strict"; /* * Copyright 2020 balena.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.blinkWhite = exports.rainbow = exports.breatheGreen = exports.sin01 = exports.Animator = exports.RGBLed = void 0; const fs_1 = require("fs"); const path_1 = require("path"); const LEDS_DIR = '/sys/class/leds'; class Led { constructor(name) { this.name = name; this.ready = this.open(); this.ready.catch(() => { // Avoid unhandled rejections }); } async open() { this.maxBrightness = parseInt(await fs_1.promises.readFile(path_1.join(LEDS_DIR, this.name, 'max_brightness'), 'utf8'), 10); this.handle = await fs_1.promises.open(path_1.join(LEDS_DIR, this.name, 'brightness'), 'w'); } async close() { await this.ready; await this.handle.close(); } async setIntensity(intensity) { await this.ready; if (intensity < 0 || intensity > 1) { throw new Error('Led intensity must be between 0 and 1'); } const value = Math.round(intensity * this.maxBrightness); if (value !== this.lastValue) { await this.handle.write(value.toString(), 0); // On a regular file we would also need to truncate to the written value length but it looks like it's not the case on sysfs files this.lastValue = value; } } } class RGBLed { constructor(names) { this.leds = names.map((name) => new Led(name)); } async close() { await Promise.all(this.leds.map((l) => l.close())); } async setColor(color) { await Promise.all([ this.leds[0].setIntensity(color[0]), this.leds[1].setIntensity(color[1]), this.leds[2].setIntensity(color[2]), ]); } } exports.RGBLed = RGBLed; class Animator { constructor(mapping, frequency = 10) { this.mapping = mapping; this.updating = false; this.setFrequency(frequency); } async setFrequency(frequency) { if (frequency < 0) { throw new Error('frequency must be greater or equal to 0'); } const period = 1000 / frequency; this.stop(); if (period === Infinity) { // frequency is 0 if (this.lastUpdate !== undefined) { await this.lastUpdate; } } else { this.start(period); } } start(period) { if (this.intervalId === undefined) { this.intervalId = setInterval(() => { this.updateOrSkip(); }, period); } } stop() { if (this.intervalId !== undefined) { clearInterval(this.intervalId); this.intervalId = undefined; } } updateOrSkip() { if (!this.updating) { this.lastUpdate = this.update(); } } async update() { this.updating = true; const t = new Date().getTime() / 1000; const promises = []; for (const { animation, rgbLeds } of this.mapping) { const color = animation(t); promises.push(...rgbLeds.map((rgbLed) => rgbLed.setColor(color))); } await Promise.all(promises); this.updating = false; } } exports.Animator = Animator; function sin01(t) { // sin(t) but the output is in the [0, 1] range return (1 + Math.sin(t)) / 2; } exports.sin01 = sin01; // Example animations: function breatheGreen(t) { return [0, sin01(t), 0]; } exports.breatheGreen = breatheGreen; const THIRD_OF_PI = Math.PI / 3; function rainbow(t) { return [sin01(t), sin01(t + 2 * THIRD_OF_PI), sin01(t + 4 * THIRD_OF_PI)]; } exports.rainbow = rainbow; function blinkWhite(t) { const intensity = Math.floor(t) % 2; return [intensity, intensity, intensity]; } exports.blinkWhite = blinkWhite; //# sourceMappingURL=index.js.map