added basic support for 'blinky'

This commit is contained in:
Daniel Sommer 2022-03-04 02:38:52 +01:00
parent c394a95d61
commit c5869151a8
6 changed files with 120 additions and 23 deletions

View file

@ -19,5 +19,25 @@
"modep": { "modep": {
"host": "192.168.1.24", "host": "192.168.1.24",
"port": 80 "port": 80
},
"blinky": {
"enabled": true,
"host": "192.168.1.31",
"port": 3000,
"events": {
"started": {
"mode": "set",
"args": {
"blinkstick": "square",
"color": "#0f0f0f"
}
},
"stopped": {
"mode": "poweroff",
"args": {
"blinkstick": "square"
}
}
}
} }
} }

34
libs/blinky.js Normal file
View file

@ -0,0 +1,34 @@
const logger = require('./logger.js');
const { httpPOST } = require('./util.js');
let enabled;
async function initialize() {
enabled = global.config.blinky !== undefined &&
global.config.blinky.enabled &&
global.config.blinky.host !== undefined &&
global.config.blinky.port !== undefined &&
global.config.blinky.events !== undefined;
}
async function handleEvent(eventName) {
if (!enabled || eventName === undefined) {
return;
}
const event = global.config.blinky.events[eventName];
if (event === undefined || event.mode === undefined) {
return;
}
logger.info('handling blinky event \'' + eventName + '\'...');
try {
await httpPOST(global.config.blinky.host, global.config.blinky.port, event.mode, event.args);
logger.debug('blinky event \'' + eventName + '\' successfully handled');
} catch (err) {
logger.error('blinky event \'' + eventName + '\' encountered an error: ' + err);
}
}
module.exports = {
initialize,
handleEvent
}

View file

@ -108,6 +108,20 @@ 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) {
for (let index = 0; index < message.errors.length; index++) {
trace(message.errors[index], 'error');
}
return;
}
if (message.message) {
trace(message.message, 'error');
return;
}
trace(message, 'error'); trace(message, 'error');
} }

View file

@ -1,22 +1,21 @@
const config = require('../config.json'); const config = require('../config.json');
const logger = require('./logger.js'); const logger = require('./logger.js');
const api = require('./api.js') const api = require('./api.js')
const constants = require('./constants.js');
const modep = require('./modep.js'); const modep = require('./modep.js');
const blinky = require('./blinky.js');
const http = require('http'); const http = require('http');
var server; var server;
function start() { async function start() {
return new Promise(function (resolve, reject) {
if (!server) { if (!server) {
server = http.createServer(); server = http.createServer();
} }
server.listen(config.server.port, config.server.listen).on('listening', function () { server.listen(config.server.port, config.server.listen).on('listening', function () {
logger.debug('server listening on ' + config.server.listen + ':' + config.server.port + '...'); logger.debug('server listening on ' + config.server.listen + ':' + config.server.port + '...');
blinky.handleEvent('started');
handleRequests(); handleRequests();
}); });
});
} }
function handleRequests() { function handleRequests() {

View file

@ -2,6 +2,7 @@ const logger = require('./logger.js');
const realpath = require('fs/promises').realpath; const realpath = require('fs/promises').realpath;
const stat = require('fs/promises').stat; const stat = require('fs/promises').stat;
const http = require('http'); const http = require('http');
const querystring = require('querystring');
const { HTTP_GET, HTTP_POST } = require('./constants.js'); const { HTTP_GET, HTTP_POST } = require('./constants.js');
function timeDiff(startTime) { function timeDiff(startTime) {
@ -32,13 +33,20 @@ function httpRequest(host, port, path, method, args) {
if (!path.startsWith("/")) { if (!path.startsWith("/")) {
path = "/" + path; path = "/" + path;
} }
logger.debug('sending http \'' + method + '\' request to \'' + host + ':' + port + path + '\'...'); const options = {
const request = http.request({
hostname: host, hostname: host,
port: port, port: port,
path: path, path: path,
method: method method: method
}, function (response) { };
if (args !== undefined) {
args = new URLSearchParams(args).toString();
options.headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
logger.debug('sending http \'' + method + '\' request to \'' + host + ':' + port + path + '\'...');
const request = http.request(options, function (response) {
if (!response) { if (!response) {
return reject('error: no response from host for http \'' + method + '\' request \'' + host + ':' + port + path + '\''); return reject('error: no response from host for http \'' + method + '\' request \'' + host + ':' + port + path + '\'');
} }
@ -64,8 +72,11 @@ function httpRequest(host, port, path, method, args) {
}); });
}); });
request.on('error', function (err) { request.on('error', function (err) {
return reject('http \'' + method + '\' request \'' + host + ':' + port + path + '\' returned an error >>> ' + err); return reject('http \'' + method + '\' request \'' + host + ':' + port + path + '\' returned an error >>> ' + err.message);
}); });
if (args !== undefined) {
request.write(args);
}
request.end(); request.end();
}); });
} }
@ -110,6 +121,22 @@ function resolvePath(file) {
}); });
} }
function exit(err, code) {
if (code === undefined) {
code = 0;
if (err !== undefined) {
code = 1;
}
}
if (err) {
logger.error(err);
logger.error(global.appName + ' ' + global.appVersion + ' ended due to an error');
} else {
logger.info(global.appName + ' ' + global.appVersion + ' shutting down gracefully')
}
process.exit(code);
}
module.exports = { module.exports = {
timeDiff, timeDiff,
clone, clone,
@ -118,5 +145,6 @@ module.exports = {
toHex, toHex,
sortById, sortById,
fileExists, fileExists,
resolvePath resolvePath,
exit
} }

14
pbc.js
View file

@ -2,10 +2,13 @@ const logger = require('./libs/logger.js');
const api = require('./libs/api.js'); const api = require('./libs/api.js');
const server = require('./libs/server.js') const server = require('./libs/server.js')
const util = require('./libs/util.js'); const util = require('./libs/util.js');
const blinky = require('./libs/blinky.js');
const packageJSON = require('./package.json'); const packageJSON = require('./package.json');
const INTERRUPTS = ['SIGINT', 'SIGTERM']; const INTERRUPTS = ['SIGINT', 'SIGTERM'];
global.appName = packageJSON.name;
global.appVersion = packageJSON.version;
global.config = process.argv[2] || __dirname + '/config.json'; global.config = process.argv[2] || __dirname + '/config.json';
handleInterrupts(); handleInterrupts();
@ -16,22 +19,21 @@ util.fileExists(config)
global.config.path = result.path; global.config.path = result.path;
}) })
.then(logger.initialize) .then(logger.initialize)
.then(blinky.initialize)
.then(() => { .then(() => {
logger.info("launching " + packageJSON.name + " " + packageJSON.version); logger.info("launching " + packageJSON.name + " " + packageJSON.version);
}) })
.then(api.setupEndpoints) .then(api.setupEndpoints)
.then(server.start) .then(server.start)
.catch((err) => { .catch((err) => {
logger.error(err); util.exit(err);
process.exit(1);
}); });
function handleInterrupts() { function handleInterrupts() {
for (var index = 0; index < INTERRUPTS.length; index++) { for (var index = 0; index < INTERRUPTS.length; index++) {
process.once(INTERRUPTS[index], (code) => { process.once(INTERRUPTS[index], async (code) => {
watchers.stop() await blinky.handleEvent('stopped');
.then(exit(code)) util.exit(undefined, code);
.catch(exit(code));
}); });
} }
} }