blinky/libs/parser.js

188 lines
No EOL
5.4 KiB
JavaScript

const logger = require('./logger.js');
const hexcolor = require('hex-color-regex');
const LEDS_ALL = require('./blinkstick.js').LEDS_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
function parseRequest(requestBody, mode) {
if (mode === undefined) {
mode = MODE_SET;
}
let config = {
'id': Math.random(),
'mode': mode,
'options': {
'index': parseIndex(requestBody.index),
}
};
if (config.mode === MODE_POWEROFF) {
config.color = '#000000';
return config;
} else {
config.color = parseColor(requestBody.color);
}
switch (config.mode) {
case MODE_MORPH:
config.options.duration = parseDuration(requestBody.duration, config.options.index);
config.options.steps = parseSteps(requestBody.steps, config.options.duration);
break;
case MODE_BLINK:
config.options.repeats = parseRepeats(requestBody.repeats, config.options.index);
config.repetitions = parseRepetitions(requestBody.repeats, config.options.index);
config.options.delay = parseDelay(requestBody.delay);
break;
case MODE_PULSE:
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;
}
// parse the index
function parseIndex(index) {
if (index === undefined) {
return LEDS_ALL;
}
index = parseInt(index);
if (index !== index) {
return LEDS_ALL;
}
if (index < 0) {
index = 0;
} else if (index > 7) {
index = 7;
}
return index;
}
// parse the duration
function parseDuration(duration, index, mode) {
if (duration === undefined) {
duration = DURATION_DEFAULT;
}
if (index === LEDS_ALL && mode !== MODE_PULSE) {
duration = duration / 8;
}
if (duration < 100) {
duration = 100;
}
return duration;
}
// parse the steps
function parseSteps(steps, duration) {
if (duration === undefined) {
duration = DURATION_DEFAULT;
}
if (steps === undefined || steps === 0) {
steps = duration / 10;
}
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;
}
return {done: 0, max: repeats};
}
// parse the delay
function parseDelay(delay) {
if (delay === undefined) {
delay = DELAY_DEFAULT;
}
return delay;
}
// color / parser functions
function parseColor(value) {
if (value === undefined || value === COLOR_RANDOM) {
return COLOR_RANDOM;
}
let parsedColor = parseRGBColor(value);
if (!parsedColor) {
parsedColor = parseHexColor(value);
}
return parsedColor || function () {
logger.warn('could not parse color value \'' + value + '\', defaulting to \'' + COLOR_RANDOM + '\'');
return COLOR_RANDOM;
}();
}
function parseRGBColor(value) {
if (value.indexOf(',') === -1 && isRGBValue(value)) {
return convertRGBToHex(parseInt(value) || 0, 0, 0);
} else {
const splittedValues = value.split(',');
let color = {};
for (let index = 0; index < splittedValues.length; index++) {
const value = splittedValues[index];
if (index === 0) {
color.red = parseInt(value) || 0;
} else if (index === 1) {
color.green = parseInt(value) || 0;
} else if (index === 2) {
color.blue = parseInt(value) || 0;
}
}
if (isRGBValue(color.red) && isRGBValue(color.green) && isRGBValue(color.blue)) {
return convertRGBToHex(color.red, color.green, color.blue);
}
}
}
function isRGBValue(value) {
return value !== undefined && !isNaN(value) && value >= 0 && value <= 255;
}
function convertRGBToHex(red, green, blue) {
return '#' + ((1 << 24) + (red << 16) + (green << 8) + blue).toString(16).slice(1);
}
function parseHexColor(value) {
if (value[0] !== '#') {
value = '#' + value;
}
if (value.length === 4) {
value = (value[0] + value[1] + value[1] + value[2] + value[2] + value[3] + value[3]);
}
if (hexcolor({strict: true}).test(value)) {
return value;
}
}
// exports
module.exports = {
parseRequest,
};