From c3b3957fbf520921db48a5652d4809793a832d6f Mon Sep 17 00:00:00 2001 From: Alexis Svinartchouk Date: Wed, 26 Jun 2019 14:59:18 +0200 Subject: [PATCH] Led module prototype Change-type: patch --- lib/gui/app/models/leds.ts | 70 ++++++++++++++++++++++++++++++++++++++ npm-shrinkwrap.json | 33 ++++++++++++++++++ package.json | 2 ++ 3 files changed, 105 insertions(+) create mode 100644 lib/gui/app/models/leds.ts diff --git a/lib/gui/app/models/leds.ts b/lib/gui/app/models/leds.ts new file mode 100644 index 00000000..72a9f19f --- /dev/null +++ b/lib/gui/app/models/leds.ts @@ -0,0 +1,70 @@ +import { delay } from 'bluebird'; +import { Gpio } from 'pigpio'; + +class Led { + private gpio: Gpio; + + constructor(gpioNumber: number) { + this.gpio = new Gpio(gpioNumber, { mode: Gpio.OUTPUT }); + } + + public set intensity(value: number) { + // TODO: check that 0 <= value <= 1 + this.gpio.pwmWrite(Math.round(value * 255)); + } +} + +export type Color = [number, number, number]; +export type AnimationFunction = (t: number) => Color; + +export class RGBLed { + private leds: [Led, Led, Led]; + private currentAnimation?: AnimationFunction; + private static animations: Map = new Map(); + + constructor(gpioNumbers: [number, number, number], public frequency = 60) { + this.leds = gpioNumbers.map(n => new Led(n)) as [Led, Led, Led]; + } + + private async loop() { + while (this.currentAnimation !== undefined) { + this.$setColor(...this.currentAnimation(new Date().getTime())); + await delay(1000 / this.frequency); + } + } + + private $setColor(red: number, green: number, blue: number) { + this.leds[0].intensity = red; + this.leds[1].intensity = green; + this.leds[2].intensity = blue; + } + + public setColor(red: number, green: number, blue: number) { + // stop any running animation + this.setAnimation(); + this.$setColor(red, green, blue); + } + + public static registerAnimation(name: string, animation: AnimationFunction) { + RGBLed.animations.set(name, animation); + } + + public setAnimation(name?: string) { + const hadAnimation = this.currentAnimation !== undefined; + this.currentAnimation = name ? RGBLed.animations.get(name) : undefined; + // Don't launch the loop a second time + if (!hadAnimation) { + this.loop(); + } + } +} + +RGBLed.registerAnimation('breathe-white', (t: number) => { + const intensity = Math.sin(t / 1000); + return [intensity, intensity, intensity]; +}); + +RGBLed.registerAnimation('blink-white', (t: number) => { + const intensity = Math.floor(t / 1000) % 2; + return [intensity, intensity, intensity]; +}); diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 5e3c1a0a..36368bf0 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1085,6 +1085,15 @@ "integrity": "sha1-qIc1gLOoS2msHmhzI7Ffu+uQR5o=", "dev": true }, + "@types/pigpio": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/pigpio/-/pigpio-1.2.1.tgz", + "integrity": "sha512-R0czS/QbWS/vU7rSp6MMcRu+zCZENcrYo/aDNDkF6RNSaKax6J+H45E9183AQtjJVb2N9VOCGrUfnHgyZ19WvQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/prettier": { "version": "1.16.4", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-1.16.4.tgz", @@ -9376,6 +9385,30 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, + "pigpio": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/pigpio/-/pigpio-1.2.3.tgz", + "integrity": "sha512-3ySsqR2Dxvl8p/vY1MMwF6dVYXTNnK4uuGaYy7gQvQ65GIOtiqpU4N4Ylq1MoKJbfXY9SJbW2PLhkprzQks3dA==", + "requires": { + "bindings": "^1.5.0", + "nan": "^2.14.0" + }, + "dependencies": { + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" + } + } + }, "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", diff --git a/package.json b/package.json index 5631b114..22f373d5 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "nan": "^2.9.2", "node-ipc": "^9.1.1", "path-is-inside": "^1.0.2", + "pigpio": "^1.2.3", "pretty-bytes": "^1.0.4", "prop-types": "^15.5.9", "react": "^16.8.5", @@ -88,6 +89,7 @@ "@babel/preset-react": "^7.0.0", "@types/debug": "^4.1.4", "@types/node": "^10.14.9", + "@types/pigpio": "^1.2.1", "@types/react-dom": "^16.8.4", "@types/request": "^2.48.1", "@types/tmp": "^0.1.0",