fixed starting and stopping of animations

This commit is contained in:
Daniel Sommer 2022-02-24 14:42:30 +01:00
parent 9ceb501265
commit b6c2e04db2
2 changed files with 51 additions and 42 deletions

View file

@ -1,8 +1,6 @@
const logger = require('./logger'); const logger = require('./logger');
const blinkstick = require('blinkstick'); const blinkstick = require('blinkstick');
const LED_ANIMATED = 0;
const LEDS_ALL = 'all'; const LEDS_ALL = 'all';
const MODE_SET = 'set'; const MODE_SET = 'set';
@ -11,9 +9,9 @@ const MODE_BLINK = 'blink';
const MODE_PULSE = 'pulse'; const MODE_PULSE = 'pulse';
const MODE_POWEROFF = 'poweroff'; const MODE_POWEROFF = 'poweroff';
const LEDS = new Map(); const LEDS_ANIMATED = [];
const LEDS_STOP = [];
let stop = false;
// find connected blinkstick(s) // find connected blinkstick(s)
async function findBlinkstick(index) { async function findBlinkstick(index) {
@ -31,12 +29,12 @@ async function findBlinkstick(index) {
// simple animation (set the color / morph to color) // simple animation (set the color / morph to color)
async function simple(config) { async function simple(config) {
await forceStop(); await stopLedsAccordingly(config);
config.timestamp = new Date().getTime(); config.timestamp = new Date().getTime();
let indices = getIndices(config); let indices = getIndices(config);
for (let index = 0; index < indices.length; index++) { for (let index = 0; index < indices.length; index++) {
try { try {
await setLedState(indices[index], LED_ANIMATED); await setLedAnimated(indices[index]);
await singleAnimation(JSON.parse(JSON.stringify(config)), indices[index]); await singleAnimation(JSON.parse(JSON.stringify(config)), indices[index]);
} finally { } finally {
await clearLedState(indices[index]); await clearLedState(indices[index]);
@ -53,7 +51,7 @@ async function simple(config) {
// complex animation (pulse / blink) // complex animation (pulse / blink)
async function complex(config) { async function complex(config) {
if (config.timestamp === undefined) { if (config.timestamp === undefined) {
await powerOff({id: Math.random(), mode: MODE_POWEROFF, color: '#000000', options: {index: LEDS_ALL}}); await stopLedsAccordingly(config);
config.timestamp = new Date().getTime(); config.timestamp = new Date().getTime();
} }
let indices = getIndices(config); let indices = getIndices(config);
@ -62,7 +60,7 @@ async function complex(config) {
if (shouldLedFinish(config)) { if (shouldLedFinish(config)) {
return {status: 'ok', time: (new Date().getTime() - config.timestamp) + 'ms'}; return {status: 'ok', time: (new Date().getTime() - config.timestamp) + 'ms'};
} }
await setLedState(indices[index], LED_ANIMATED); await setLedAnimated(indices[index]);
await singleAnimation(JSON.parse(JSON.stringify(config)), indices[index]); await singleAnimation(JSON.parse(JSON.stringify(config)), indices[index]);
config.repetitions.done++; config.repetitions.done++;
} finally { } finally {
@ -74,9 +72,9 @@ async function complex(config) {
// power the blinkstick (or just a specific led) off // power the blinkstick (or just a specific led) off
async function powerOff(config) { async function powerOff(config) {
await forceStop();
config.timestamp = new Date().getTime(); config.timestamp = new Date().getTime();
let indices = getIndices(config); let indices = getIndices(config);
await forceStop(indices);
for (let index = 0; index < indices.length; index++) { for (let index = 0; index < indices.length; index++) {
await singleAnimation(JSON.parse(JSON.stringify(config)), indices[index]); await singleAnimation(JSON.parse(JSON.stringify(config)), indices[index]);
logger.info('led \'' + indices[index] + '\' powered off'); logger.info('led \'' + indices[index] + '\' powered off');
@ -121,22 +119,28 @@ async function singleAnimation(config, index) {
}); });
} }
async function stopLedsAccordingly(config) {
if (config.options.index === LEDS_ALL) {
return await powerOff({id: Math.random(), mode: MODE_POWEROFF, color: '#000000', options: {index: LEDS_ALL}});
}
return stopLedAnimation(config.options.index);
}
async function forceStop() { async function forceStop() {
return new Promise((resolve, reject) => { LEDS_STOP.push(LEDS_ALL);
stop = true; return await new Promise((resolve, reject) => {
waitForAllAnimationsEnd(() => { waitForAllAnimationsEnd(() => {
stop = false;
resolve(); resolve();
}); });
}); });
} }
function shouldLedFinish(config) { function shouldLedFinish(config) {
if (stop) { if (isLedStopping(config.options.index)) {
return true; return true;
} }
if (config.mode === MODE_BLINK && config.mode === MODE_PULSE) { if (config.mode === MODE_BLINK || config.mode === MODE_PULSE) {
return config.repetitions.max !== 0 && config.repetitions.done >= config.repetitions.max return config.repetitions.max !== 0 && config.repetitions.done >= config.repetitions.max;
} }
return false; return false;
} }
@ -149,23 +153,41 @@ function getIndices(blinkstickConfig) {
return [blinkstickConfig.options.index]; return [blinkstickConfig.options.index];
} }
async function setLedState(index, state) { function setLedAnimated(index) {
await stopLedAnimation(index); if (isLedAnimated(index)) {
LEDS.set(index, state); return;
}
LEDS_ANIMATED.push(index);
}
function setLedStopping(index) {
if (!isLedAnimated(index) || isLedStopping(index)) {
return;
}
LEDS_STOP.push(index);
} }
function clearLedState(index) { function clearLedState(index) {
return new Promise((resolve, reject) => { if (index === LEDS_ALL) {
LEDS.delete(index); LEDS_ANIMATED.length = 0;
resolve(); return;
}); }
LEDS_ANIMATED.splice(LEDS_ANIMATED.indexOf(index), 1);
} }
function isLedAnimated(index) { function isLedAnimated(index) {
return (LEDS.get(index) || LEDS.get(LEDS_ALL)) !== undefined; return LEDS_ANIMATED.includes(index);
}
function isLedStopping(index) {
if (LEDS_STOP.includes(LEDS_ALL)) {
return true;
}
return LEDS_STOP.includes(index);
} }
function stopLedAnimation(index) { function stopLedAnimation(index) {
setLedStopping(index);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
waitForAnimationEnd(index, () => { waitForAnimationEnd(index, () => {
resolve(); resolve();
@ -175,6 +197,7 @@ function stopLedAnimation(index) {
function waitForAnimationEnd(index, callback) { function waitForAnimationEnd(index, callback) {
if (!isLedAnimated(index)) { if (!isLedAnimated(index)) {
LEDS_STOP.splice(LEDS_STOP.indexOf(index), 1);
return callback(); return callback();
} }
setTimeout(() => { setTimeout(() => {
@ -183,7 +206,8 @@ function waitForAnimationEnd(index, callback) {
} }
function waitForAllAnimationsEnd(callback) { function waitForAllAnimationsEnd(callback) {
if (LEDS.size === 0) { if (LEDS_ANIMATED.length === 0) {
LEDS_STOP.length = 0;
return callback(); return callback();
} }
setTimeout(() => { setTimeout(() => {

View file

@ -37,15 +37,15 @@ function parseRequest(requestBody, mode) {
config.options.steps = parseSteps(requestBody.steps, config.options.duration); config.options.steps = parseSteps(requestBody.steps, config.options.duration);
break; break;
case MODE_BLINK: case MODE_BLINK:
config.options.repeats = parseRepeats(requestBody.repeats, config.options.index); config.options.repeats = 1;
config.repetitions = parseRepetitions(requestBody.repeats, config.options.index); config.repetitions = parseRepetitions(requestBody.repeats, config.options.index);
config.options.delay = parseDelay(requestBody.delay); config.options.delay = parseDelay(requestBody.delay);
break; break;
case MODE_PULSE: case MODE_PULSE:
config.options.repeats = 1;
config.repetitions = parseRepetitions(requestBody.repeats, config.options.index);
config.options.duration = parseDuration(requestBody.duration, config.options.index, MODE_PULSE); config.options.duration = parseDuration(requestBody.duration, config.options.index, MODE_PULSE);
config.options.steps = parseSteps(requestBody.steps, config.options.duration); config.options.steps = parseSteps(requestBody.steps, config.options.duration);
config.options.repeats = parseRepeats(requestBody.repeats, config.options.index);
config.repetitions = parseRepetitions(requestBody.repeats, config.options.index);
break; break;
} }
return config; return config;
@ -93,23 +93,8 @@ function parseSteps(steps, duration) {
return steps; return steps;
} }
// parse the repeats
function parseRepeats(repeats, index) {
if (index === LEDS_ALL) {
return 1;
}
repeats = parseInt(repeats);
if (repeats !== repeats) {
return 0;
}
return repeats;
}
// parse the repetitions // parse the repetitions
function parseRepetitions(repeats, index) { function parseRepetitions(repeats, index) {
if (index !== LEDS_ALL) {
return {done: 0, max: 1};
}
repeats = parseInt(repeats); repeats = parseInt(repeats);
if (repeats !== repeats) { if (repeats !== repeats) {
repeats = 0; repeats = 0;