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 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 = 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); 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 repetitions function parseRepetitions(repeats, index) { 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 = parseHexColor(value); if (parsedColor !== undefined) { return parsedColor; } return parseRGBColor(value) || COLOR_RANDOM; } function parseRGBColor(value) { if (value.indexOf(',') === -1 && isRGBValue(value)) { value = parseInt(value); return convertRGBToHex(value, value, value); } 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 !== 7) { return; } if (!hexcolor({strict: true}).test(value)) { return; } return value; } // exports module.exports = { parseRequest, };