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

View file

@ -37,15 +37,15 @@ function parseRequest(requestBody, mode) {
config.options.steps = parseSteps(requestBody.steps, config.options.duration);
break;
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.options.delay = parseDelay(requestBody.delay);
break;
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.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;
}
return config;
@ -93,23 +93,8 @@ function parseSteps(steps, duration) {
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
function parseRepetitions(repeats, index) {
if (index !== LEDS_ALL) {
return {done: 0, max: 1};
}
repeats = parseInt(repeats);
if (repeats !== repeats) {
repeats = 0;