fixed modes 'set' and 'morph' with random color for all indexes

This commit is contained in:
Daniel Sommer 2022-03-01 22:14:36 +01:00
parent 37d5fdcd9b
commit 6ede57f7ff
6 changed files with 88 additions and 103 deletions

View file

@ -1,17 +1,8 @@
const logger = require('./logger.js'); const logger = require('./logger.js');
const util = require('./util.js'); const util = require('./util.js');
const constants = require('./constants.js');
const blinkstick = require('blinkstick'); const blinkstick = require('blinkstick');
const RANDOM = require('./parser').COLOR_RANDOM;
const ALL = 'all';
const MODE_SET = 'set';
const MODE_MORPH = 'morph';
const MODE_BLINK = 'blink';
const MODE_PULSE = 'pulse';
const MODE_POWEROFF = 'poweroff';
const LEDAnimations = new Map(); const LEDAnimations = new Map();
let blinksticks; let blinksticks;
@ -34,7 +25,7 @@ async function findBlinkstick(index, ignoreFilter) {
} }
if (index === undefined) { if (index === undefined) {
index = 0; index = 0;
} else if (index !== ALL) { } else if (index !== constants.ALL) {
index = parseInt(index); index = parseInt(index);
} }
if (isNaN(index)) { if (isNaN(index)) {
@ -43,7 +34,7 @@ async function findBlinkstick(index, ignoreFilter) {
if (index > blinksticks.length - 1) { if (index > blinksticks.length - 1) {
throw new Error('there is no blinkstick for index \'' + index + '\''); throw new Error('there is no blinkstick for index \'' + index + '\'');
} }
if (index === ALL) { if (index === constants.ALL) {
return blinksticks; return blinksticks;
} }
return blinksticks[index]; return blinksticks[index];
@ -58,7 +49,7 @@ async function simple(config) {
const tmpConfig = JSON.parse(JSON.stringify(config)); const tmpConfig = JSON.parse(JSON.stringify(config));
await singleAnimation(tmpConfig, indices[index]); await singleAnimation(tmpConfig, indices[index]);
if (index === 0) { if (index === 0) {
config = setColorIfRandom(config); await setColorIfRandom(config);
} }
} }
return { return {
@ -83,9 +74,6 @@ async function complex(config) {
} }
const tmpConfig = JSON.parse(JSON.stringify(config)); const tmpConfig = JSON.parse(JSON.stringify(config));
await singleAnimation(tmpConfig, indices[index]); await singleAnimation(tmpConfig, indices[index]);
if (index === 0) {
config = await setColorIfRandom(config);
}
config.repetitions.done++; config.repetitions.done++;
} }
return await complex(config); return await complex(config);
@ -95,15 +83,15 @@ async function complex(config) {
async function powerOff(config) { async function powerOff(config) {
config.timestamp = new Date().getTime(); config.timestamp = new Date().getTime();
let indices = getIndices(config); let indices = getIndices(config);
if (config.options.index === ALL) { if (config.options.index === constants.ALL) {
LEDAnimations.set(ALL, { stop: new Date().getTime() }); LEDAnimations.set(constants.ALL, { stop: new Date().getTime() });
} }
for (let index = 0; index < indices.length; index++) { for (let index = 0; index < indices.length; index++) {
await stopLEDAnimation(indices[index]); await stopLEDAnimation(indices[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');
} }
if (config.options.index === ALL) { if (config.options.index === constants.ALL) {
const blinkstick = await findBlinkstick(); const blinkstick = await findBlinkstick();
blinkstick.turnOff(); blinkstick.turnOff();
LEDAnimations.clear(); LEDAnimations.clear();
@ -121,13 +109,13 @@ async function singleAnimation(config, index) {
setLEDAnimated(config.options.index); setLEDAnimated(config.options.index);
blinkstick.animationsEnabled = true; blinkstick.animationsEnabled = true;
switch (config.mode) { switch (config.mode) {
case MODE_MORPH: case constants.MODE_MORPH:
blinkstick.morph(config.color, config.options, callback); blinkstick.morph(config.color, config.options, callback);
break; break;
case MODE_BLINK: case constants.MODE_BLINK:
blinkstick.blink(config.color, config.options, callback); blinkstick.blink(config.color, config.options, callback);
break; break;
case MODE_PULSE: case constants.MODE_PULSE:
blinkstick.pulse(config.color, config.options, callback); blinkstick.pulse(config.color, config.options, callback);
break; break;
default: default:
@ -136,7 +124,7 @@ async function singleAnimation(config, index) {
} }
function callback(err) { function callback(err) {
if (config.mode !== MODE_BLINK && config.mode !== MODE_PULSE) { if (config.mode !== constants.MODE_BLINK && config.mode !== constants.MODE_PULSE) {
clearLedState(config.options.index); clearLedState(config.options.index);
} }
if (err) { if (err) {
@ -150,7 +138,7 @@ async function singleAnimation(config, index) {
// led / index helper functions // led / index helper functions
function getIndices(blinkstickConfig) { function getIndices(blinkstickConfig) {
if (blinkstickConfig.options.index === ALL) { if (blinkstickConfig.options.index === constants.ALL) {
return [0, 1, 2, 3, 4, 5, 6, 7]; return [0, 1, 2, 3, 4, 5, 6, 7];
} }
return [blinkstickConfig.options.index]; return [blinkstickConfig.options.index];
@ -163,7 +151,10 @@ async function getColor(index) {
logger.debug('getting color for led with index \'' + index + '\''); logger.debug('getting color for led with index \'' + index + '\'');
const blinkstick = await findBlinkstick(); const blinkstick = await findBlinkstick();
return await new Promise((resolve, reject) => { return await new Promise((resolve, reject) => {
blinkstick.getColorString(index, (color) => { blinkstick.getColorString(index, (err, color) => {
if (err) {
reject(err);
}
logger.debug('led with index \'' + index + '\' is set to color \'' + color + '\''); logger.debug('led with index \'' + index + '\' is set to color \'' + color + '\'');
resolve(color); resolve(color);
}); });
@ -171,34 +162,34 @@ async function getColor(index) {
} }
async function setColorIfRandom(config) { async function setColorIfRandom(config) {
if (config.options.index === ALL && config.color === RANDOM) { if (config.options.index !== constants.ALL || config.color !== constants.RANDOM) {
config.color = await getColor(0); return;
} }
return config; config.color = await getColor(0);
} }
async function stopLEDsAccordingly(config) { async function stopLEDsAccordingly(config) {
if (LEDAnimations.size === 0) { if (LEDAnimations.size === 0) {
return; return;
} }
if (config.options.index === ALL) { if (config.options.index === constants.ALL) {
logger.debug('stopping all leds...'); logger.debug('stopping all leds...');
return await powerOff({ return await powerOff({
id: Math.random(), id: Math.random(),
mode: MODE_POWEROFF, mode: constants.MODE_POWEROFF,
color: '#000000', color: '#000000',
options: { index: ALL } options: { index: constants.ALL }
}); });
} }
return stopLEDAnimation(config.options.index); return stopLEDAnimation(config.options.index);
} }
function shouldLEDFinish(config) { function shouldLEDFinish(config) {
if (LEDAnimations.has(ALL) || (isLEDAnimated(config.options.index) && isLEDStopping(config.options.index))) { if (LEDAnimations.has(constants.ALL) || (isLEDAnimated(config.options.index) && isLEDStopping(config.options.index))) {
logger.debug('led \'' + config.options.index + '\' is set to \'stop\' and should finish now'); logger.debug('led \'' + config.options.index + '\' is set to \'stop\' and should finish now');
return true; return true;
} }
if (config.mode === MODE_BLINK || config.mode === MODE_PULSE) { if (config.mode === constants.MODE_BLINK || config.mode === constants.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;
@ -223,7 +214,7 @@ function setLEDStopping(index) {
} }
function clearLedState(index) { function clearLedState(index) {
if (index === ALL) { if (index === constants.ALL) {
LEDAnimations.clear(); LEDAnimations.clear();
logger.debug('cleared animation state of all leds'); logger.debug('cleared animation state of all leds');
return; return;
@ -237,7 +228,7 @@ function isLEDAnimated(index) {
} }
function isLEDStopping(index) { function isLEDStopping(index) {
if (LEDAnimations.has(ALL) && LEDAnimations.get(ALL).stop !== undefined) { if (LEDAnimations.has(constants.ALL) && LEDAnimations.get(constants.ALL).stop !== undefined) {
return true; return true;
} }
if (LEDAnimations.has(index) && LEDAnimations.get(index).stop !== undefined) { if (LEDAnimations.has(index) && LEDAnimations.get(index).stop !== undefined) {
@ -247,7 +238,7 @@ function isLEDStopping(index) {
} }
async function stopLEDAnimation(index) { async function stopLEDAnimation(index) {
if (index === ALL) { if (index === constants.ALL) {
for (const [key, value] of LEDAnimations) { for (const [key, value] of LEDAnimations) {
setLEDStopping(key); setLEDStopping(key);
} }
@ -282,7 +273,7 @@ async function waitForAllAnimationsEnd(callback, timestamp) {
} }
function isInfiniteAnimation(config) { function isInfiniteAnimation(config) {
if (config.mode !== MODE_BLINK && config.mode !== MODE_PULSE) { if (config.mode !== constants.MODE_BLINK && config.mode !== constants.MODE_PULSE) {
return false; return false;
} }
return config.repetitions.max === 0; return config.repetitions.max === 0;
@ -294,11 +285,5 @@ module.exports = {
simple, simple,
complex, complex,
powerOff, powerOff,
isInfiniteAnimation, isInfiniteAnimation
ALL, }
MODE_SET,
MODE_MORPH,
MODE_BLINK,
MODE_PULSE,
MODE_POWEROFF
};

View file

@ -1,17 +1,15 @@
const logger = require('./logger.js'); const logger = require('./logger.js');
const blinkstick = require('./blinkstick.js'); const blinkstick = require('./blinkstick.js');
const constants = require('./constants.js');
const ARG_CONFIG = '--config';
const ARG_GET_SERIALS = '--get-blinksticks';
async function handleArguments() { async function handleArguments() {
let handled = 0; let handled = 0;
for (let index = 0; index < process.argv.length; index++) { for (let index = 0; index < process.argv.length; index++) {
switch (process.argv[index]) { switch (process.argv[index]) {
case ARG_CONFIG: case constants.ARG_CONFIG:
continue; continue;
case ARG_GET_SERIALS: case constants.ARG_GET_SERIALS:
logger.info('blinksticks: ' + JSON.stringify(await blinkstick.findBlinkstick(blinkstick.ALL))); logger.info('blinksticks: ' + JSON.stringify(await blinkstick.findBlinkstick(constants.ALL)));
handled++; handled++;
break; break;
} }
@ -20,6 +18,5 @@ async function handleArguments() {
} }
module.exports = { module.exports = {
handleArguments, handleArguments
ARG_CONFIG
}; };

16
libs/constants.js Normal file
View file

@ -0,0 +1,16 @@
module.exports = {
ALL: 'all',
RANDOM: 'random',
MODE_SET: 'set',
MODE_MORPH: 'morph',
MODE_BLINK: 'blink',
MODE_PULSE: 'pulse',
MODE_POWEROFF: 'poweroff',
ARG_CONFIG: '--config',
ARG_GET_SERIALS: '--get-blinksticks',
DURATION_DEFAULT: require('../config.json').api.post.duration.default || 1000,
DELAY_DEFAULT: require('../config.json').api.post.delay.default || 500
}

View file

@ -95,6 +95,10 @@ function error(message) {
if (loglevel > LOGLEVEL_ERROR) { if (loglevel > LOGLEVEL_ERROR) {
return; return;
} }
if (message.stack) {
trace(message.stack, 'error');
return;
}
if (message.errors !== undefined) { if (message.errors !== undefined) {
for (let index = 0; index < message.errors.length; index++) { for (let index = 0; index < message.errors.length; index++) {
trace(message.errors[index], 'error'); trace(message.errors[index], 'error');
@ -103,7 +107,7 @@ function error(message) {
} }
if (message.message) { if (message.message) {
trace(message.message, 'error'); trace(message.message, 'error');
return return;
} }
trace(message, 'error'); trace(message, 'error');
} }

View file

@ -1,21 +1,10 @@
const constants = require('./constants.js');
const hexcolor = require('hex-color-regex'); const hexcolor = require('hex-color-regex');
const LEDS_ALL = require('./blinkstick.js').ALL;
const MODE_SET = require('./blinkstick.js').MODE_SET;
const MODE_MORPH = require('./blinkstick.js').MODE_MORPH;
const MODE_BLINK = require('./blinkstick.js').MODE_BLINK;
const MODE_PULSE = require('./blinkstick.js').MODE_PULSE;
const MODE_POWEROFF = require('./blinkstick.js').MODE_POWEROFF;
const DURATION_DEFAULT = require('../config.json').api.post.duration.default || 1000;
const DELAY_DEFAULT = require('../config.json').api.post.delay.default || 500;
const COLOR_RANDOM = 'random';
// parse a http post and return an object with sane defaults // parse a http post and return an object with sane defaults
function parseRequest(requestBody, mode) { function parseRequest(requestBody, mode) {
if (mode === undefined) { if (mode === undefined) {
mode = MODE_SET; mode = constants.MODE_SET;
} }
let config = { let config = {
'id': Math.random(), 'id': Math.random(),
@ -24,26 +13,26 @@ function parseRequest(requestBody, mode) {
'index': parseIndex(requestBody.index), 'index': parseIndex(requestBody.index),
} }
}; };
if (config.mode === MODE_POWEROFF) { if (config.mode === constants.MODE_POWEROFF) {
config.color = '#000000'; config.color = '#000000';
return config; return config;
} else { } else {
config.color = parseColor(requestBody.color); config.color = parseColor(requestBody.color);
} }
switch (config.mode) { switch (config.mode) {
case MODE_MORPH: case constants.MODE_MORPH:
config.options.duration = parseDuration(requestBody.duration, config.options.index); config.options.duration = parseDuration(requestBody.duration, config.options.index);
config.options.steps = parseSteps(requestBody.steps, config.options.duration); config.options.steps = parseSteps(requestBody.steps, config.options.duration);
break; break;
case MODE_BLINK: case constants.MODE_BLINK:
config.options.repeats = 1; 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 constants.MODE_PULSE:
config.options.repeats = 1; config.options.repeats = 1;
config.repetitions = parseRepetitions(requestBody.repeats, config.options.index); 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, constants.MODE_PULSE);
config.options.steps = parseSteps(requestBody.steps, config.options.duration); config.options.steps = parseSteps(requestBody.steps, config.options.duration);
break; break;
} }
@ -53,11 +42,11 @@ function parseRequest(requestBody, mode) {
// parse the index // parse the index
function parseIndex(index) { function parseIndex(index) {
if (index === undefined) { if (index === undefined) {
return LEDS_ALL; return constants.ALL;
} }
index = parseInt(index); index = parseInt(index);
if (index !== index) { if (index !== index) {
return LEDS_ALL; return constants.ALL;
} }
if (index < 0) { if (index < 0) {
index = 0; index = 0;
@ -70,9 +59,9 @@ function parseIndex(index) {
// parse the duration // parse the duration
function parseDuration(duration, index, mode) { function parseDuration(duration, index, mode) {
if (duration === undefined) { if (duration === undefined) {
duration = DURATION_DEFAULT; duration = constants.DURATION_DEFAULT;
} }
if (index === LEDS_ALL && mode !== MODE_PULSE) { if (index === constants.ALL && mode !== constants.MODE_PULSE) {
duration = duration / 8; duration = duration / 8;
} }
if (duration < 100) { if (duration < 100) {
@ -84,7 +73,7 @@ function parseDuration(duration, index, mode) {
// parse the steps // parse the steps
function parseSteps(steps, duration) { function parseSteps(steps, duration) {
if (duration === undefined) { if (duration === undefined) {
duration = DURATION_DEFAULT; duration = constants.DURATION_DEFAULT;
} }
if (steps === undefined || steps === 0) { if (steps === undefined || steps === 0) {
steps = duration / 10; steps = duration / 10;
@ -104,21 +93,21 @@ function parseRepetitions(repeats, index) {
// parse the delay // parse the delay
function parseDelay(delay) { function parseDelay(delay) {
if (delay === undefined) { if (delay === undefined) {
delay = DELAY_DEFAULT; delay = constants.DELAY_DEFAULT;
} }
return delay; return delay;
} }
// color / parser functions // color / parser functions
function parseColor(value) { function parseColor(value) {
if (value === undefined || value === COLOR_RANDOM) { if (value === undefined || value === constants.RANDOM) {
return COLOR_RANDOM; return constants.RANDOM;
} }
let parsedColor = parseHexColor(value); let parsedColor = parseHexColor(value);
if (parsedColor !== undefined) { if (parsedColor !== undefined) {
return parsedColor; return parsedColor;
} }
return parseRGBColor(value) || COLOR_RANDOM; return parseRGBColor(value) || constants.RANDOM;
} }
function parseRGBColor(value) { function parseRGBColor(value) {
@ -166,6 +155,5 @@ function parseHexColor(value) {
// exports // exports
module.exports = { module.exports = {
parseRequest, parseRequest
COLOR_RANDOM
}; };

View file

@ -1,8 +1,9 @@
const path = require('path'); const config = require('../config.json');
const config = require('../config'); const logger = require('./logger.js');
const logger = require('./logger'); const blinkstick = require('./blinkstick.js');
const blinkstick = require('./blinkstick');
const parser = require('./parser.js'); const parser = require('./parser.js');
const constants = require('./constants.js');
const path = require('path');
const express = require('express'); const express = require('express');
const favicon = require('serve-favicon'); const favicon = require('serve-favicon');
@ -13,12 +14,6 @@ app.use(favicon(path.join(path.dirname(__dirname), 'public', 'favicon.ico')));
app.use(bodyparser.json()); app.use(bodyparser.json());
app.use(bodyparser.urlencoded({extended: true})); app.use(bodyparser.urlencoded({extended: true}));
const MODE_SET = require('./blinkstick.js').MODE_SET;
const MODE_MORPH = require('./blinkstick.js').MODE_MORPH;
const MODE_BLINK = require('./blinkstick.js').MODE_BLINK;
const MODE_PULSE = require('./blinkstick.js').MODE_PULSE;
const MODE_POWEROFF = require('./blinkstick.js').MODE_POWEROFF;
const html = require('./index.js').get(); const html = require('./index.js').get();
// run the express http server and handle gets/posts // run the express http server and handle gets/posts
@ -42,29 +37,29 @@ function handleRequests() {
response.end(); response.end();
}); });
// POST '/set' // POST '/set'
app.post('/' + MODE_SET, (request, response) => { app.post('/' + constants.MODE_SET, (request, response) => {
logger.http(request); logger.http(request);
handleSimpleAnimation(parser.parseRequest(request.body, MODE_SET), response); handleSimpleAnimation(parser.parseRequest(request.body, constants.MODE_SET), response);
}); });
// POST '/morph' // POST '/morph'
app.post('/' + MODE_MORPH, (request, response) => { app.post('/' + constants.MODE_MORPH, (request, response) => {
logger.http(request); logger.http(request);
handleSimpleAnimation(parser.parseRequest(request.body, MODE_MORPH), response); handleSimpleAnimation(parser.parseRequest(request.body, constants.MODE_MORPH), response);
}); });
// POST '/blink' // POST '/blink'
app.post('/' + MODE_BLINK, (request, response) => { app.post('/' + constants.MODE_BLINK, (request, response) => {
logger.http(request); logger.http(request);
handleComplexAnimation(parser.parseRequest(request.body, MODE_BLINK), response); handleComplexAnimation(parser.parseRequest(request.body, constants.MODE_BLINK), response);
}); });
// POST '/pulse' // POST '/pulse'
app.post('/' + MODE_PULSE, (request, response) => { app.post('/' + constants.MODE_PULSE, (request, response) => {
logger.http(request); logger.http(request);
handleComplexAnimation(parser.parseRequest(request.body, MODE_PULSE), response); handleComplexAnimation(parser.parseRequest(request.body, constants.MODE_PULSE), response);
}); });
// POST '/poweroff' // POST '/poweroff'
app.post('/' + MODE_POWEROFF, (request, response) => { app.post('/' + constants.MODE_POWEROFF, (request, response) => {
logger.http(request); logger.http(request);
handlePowerOff(parser.parseRequest(request.body, MODE_POWEROFF), response); handlePowerOff(parser.parseRequest(request.body, constants.MODE_POWEROFF), response);
}); });
} }