blinky/libs/server.js

143 lines
No EOL
4.7 KiB
JavaScript

// requirements
const path = require('path');
const config = require('../config');
const packageJSON = require('../package.json');
const logger = require('./logger');
const blinkstick = require('./blinkstick');
// third party requirements
const express = require('express');
const favicon = require('serve-favicon');
const parser = require('body-parser');
// setup express, blinkstick and other stuff
const app = express();
app.use(favicon(path.join(path.dirname(__dirname), "public", "favicon.ico")));
app.use(parser.json());
app.use(parser.urlencoded({ extended: true }));
// get the html content for get requests
// TODO: replace with template engine (vue.js)
function getHTML() {
let welcomeMessage =
"<html>" +
"<head>" +
"<title>" + packageJSON.name + " " + packageJSON.version + "</title>" +
"<style>" +
"body { background: #2a2a2a; color: #f1f1f1; margin: 1.25% }" +
"th, td { border: 1px solid #919191; padding: 6px; text-align: left }" +
"</style>" +
"</head>" +
"<body>" +
"<div>" +
"<h1>" + packageJSON.name + " " + packageJSON.version + "</h1>" +
"</div>" +
"<hr>";
welcomeMessage +=
"<div>" +
"<h2>get:</h2>" +
"<p>" + config.api.get.description + "</p>" +
"</div>";
welcomeMessage +=
"<div>" +
"<h2>post:</h2>" +
"<table style=\"width:100%\">" +
"<th>argument</th>" +
"<th>available values</th>" +
"<th>default</th>" +
"<th>restrictions</th>" +
"<th>description</th>";
Object.keys(config.api.post).forEach(function (argument) {
let restrictions = config.api.post[argument].restrictions || "";
welcomeMessage +=
"<tr>" +
"<td>" + argument + "</td>" +
"<td>" + config.api.post[argument].available + "</td>" +
"<td>" + config.api.post[argument].default + "</td>" +
"<td>" + restrictions + "</td>" +
"<td>" + config.api.post[argument].description + "</td>" +
"</tr>";
});
welcomeMessage +=
"</table>" +
"</div>" +
"</body>" +
"</html>";
return welcomeMessage;
}
// run the express http server and handle gets/posts
function start() {
return new Promise(function (resolve, reject) {
app.listen(config.server.port, config.server.listen)
.on("listening", function () {
return resolve("server listening on " + config.server.listen + ":" + config.server.port + "...")
})
.on("error", function (err) {
return reject("error starting server (" + err + ")");
});
});
}
function handleRequests() {
// GET methods
app.get('*', (request, response) => {
logger.http(request);
response.send(getHTML());
response.end();
});
app.post('/off', (request, response) => {
logger.http(request);
response.end();
blinkstick.powerOff(parseInt(request.body.index));
});
// POST methods
app.post('*', (request, response) => {
logger.http(request);
response.end();
blinkstick.illuminate(parseRequest(request.body))
.then(logger.info)
.catch(logger.error);
});
}
// parse the request and return an object with sane defaults
function parseRequest(data) {
let blinkstickConfig = {
"id": Math.random(),
"mode": data.mode || config.api.post.mode.default,
"color": blinkstick.parseColor(data.color),
"options": {
"index": blinkstick.LEDS_ALL,
"steps": data.steps,
"duration": data.duration || config.api.post.duration.default,
"pulse": {
"done": 0,
"max": data.pulses || 0
}
}
};
if (data.index !== undefined) {
blinkstickConfig.options.index = parseInt(data.index);
if (blinkstickConfig.options.index < 0) {
blinkstickConfig.options.index = 0;
} else if (blinkstickConfig.options.index > 7) {
blinkstickConfig.options.index = 7;
}
}
if (blinkstickConfig.options.duration < 100) {
blinkstickConfig.options.duration = 100;
}
if (blinkstickConfig.options.index === blinkstick.LEDS_ALL && blinkstickConfig.mode === blinkstick.MODE_MORPH) {
blinkstickConfig.options.duration = blinkstickConfig.options.duration / 8;
}
if (blinkstickConfig.options.steps === undefined || blinkstickConfig.options.steps === 0) {
blinkstickConfig.options.steps = blinkstickConfig.options.duration / 10;
}
return blinkstickConfig;
}
// exports
module.exports = {
start,
handleRequests
};