You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
3.7 KiB
152 lines
3.7 KiB
const express = require('express'); |
|
const bodyParser = require('body-parser'); |
|
const axios = require('axios'); |
|
const app = express(); |
|
|
|
const DEBUG_LOGGING = false; |
|
|
|
const AUTH_SERVER_URL = 'http://localhost:8000'; |
|
|
|
const log = (string) => { |
|
date = new Date().toISOString().replace('T', ' ').split('.')[0]; |
|
console.log(date, '-', string); |
|
} |
|
|
|
// Enums |
|
const lockStates = { |
|
LOCK_OFF: 0, |
|
LOCK_PREARM: 1, |
|
LOCK_ARMED: 2, |
|
LOCK_ON_PRESSED: 3, |
|
LOCK_ON: 4, |
|
}; |
|
|
|
let toolStatus = null; |
|
|
|
const server = app.listen(8080, () => { |
|
log('Lockout socket server listening on port 8080!'); |
|
}); |
|
const io = require('socket.io')(server); |
|
|
|
// Express http server stuff: |
|
|
|
// TODO : remove on prod |
|
app.use((req, res, next) => { |
|
res.header('Access-Control-Allow-Origin', '*'); |
|
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); |
|
next(); |
|
}); |
|
|
|
app.use(bodyParser.json()); |
|
|
|
app.post('/api/lockout/:mac', (req, res) => { |
|
if (toolStatus) { |
|
const mac = req.params.mac; |
|
DEBUG_LOGGING && log(`${mac} - Lock state: ${Object.keys(lockStates)[req.body.lockState]}`); |
|
|
|
const tmp = Object.entries(toolStatus).find(x => x[1].mac == mac) |
|
const toolSlug = tmp ? tmp[0] : null; |
|
|
|
if (toolSlug) { |
|
let clearAction = false; |
|
let tool = toolStatus[toolSlug]; |
|
tool.lastState = tool.state; |
|
|
|
switch (req.body.lockState) { |
|
case lockStates.LOCK_OFF: |
|
tool.state = 'off'; |
|
if (tool.action == 'disarm') clearAction = true; |
|
break; |
|
case lockStates.LOCK_ARMED: |
|
tool.state = 'armed'; |
|
if (tool.action == 'arm') clearAction = true; |
|
break; |
|
case lockStates.LOCK_ON: |
|
tool.state = 'on'; |
|
break; |
|
default: |
|
break; |
|
} |
|
|
|
// Track in case state is switched from elsewhere |
|
if (tool.state != tool.lastState) clearAction = true; |
|
|
|
if (clearAction) { |
|
log(`${mac} - Report | Previous state: ${tool.lastState} | New state: ${tool.state} | Website action: ${tool.action || 'N/A'}`); |
|
|
|
tool.action = ''; |
|
io.sockets.emit('toolStatus', toolStatus); |
|
} |
|
|
|
res.setHeader('Content-Type', 'application/json'); |
|
res.send(JSON.stringify({ action: tool.action })); |
|
|
|
toolStatus[toolSlug] = tool; |
|
} else { |
|
res.sendStatus(404); |
|
} |
|
} else { |
|
res.sendStatus(503); |
|
} |
|
}); |
|
|
|
app.get('*', (req, res) => { |
|
res.sendStatus(404); |
|
}); |
|
|
|
// Socket.io websocket stuff: |
|
|
|
// TODO : remove on prod |
|
io.origins('*:*'); |
|
|
|
io.on('connection', socket => { |
|
socket.emit('toolStatus', toolStatus); |
|
|
|
socket.on('log', string => { |
|
log(string); |
|
}); |
|
|
|
socket.on('requestInterlock', data => { |
|
const username = data.username; |
|
const token = data.token; |
|
const toolSlug = data.change.toolSlug; |
|
const action = data.change.action; |
|
|
|
log(`${username} - Request | Tool: ${toolSlug} | Action: ${action}`); |
|
|
|
axios.get(AUTH_SERVER_URL + '/user/', { |
|
headers: {'Authorization': 'Token ' + token}, |
|
}) |
|
.then(res => { |
|
const profile = res.data[0].profile || null; |
|
if (profile && profile.authorized_tools.includes(toolSlug)) { |
|
toolStatus[toolSlug].action = action; |
|
|
|
log(`${username} - Allowed | Tool: ${toolSlug} | Action: ${action}`); |
|
io.sockets.emit('toolStatus', toolStatus); |
|
} else { |
|
log(`${username} - DISALLOWED | Tool: ${toolSlug} | Action: ${action}`); |
|
} |
|
}) |
|
.catch(err => |
|
log(err.message) |
|
); |
|
}); |
|
}); |
|
|
|
setInterval(() => { |
|
axios.get(AUTH_SERVER_URL + '/tooldata/') |
|
.then(res => { |
|
toolStatus = res.data.categories |
|
.reduce((a, x) => a.concat(x.tools), []) |
|
.reduce((a, x) => ({...a, [x.slug]: a[x.slug] ? { |
|
...a[x.slug], mac: x.mac |
|
} : { |
|
mac: x.mac, action: '', state: 'off', lastState: 'n/a' |
|
}}), toolStatus || {}); |
|
io.sockets.emit('toolStatus', toolStatus); |
|
}) |
|
.catch(err => |
|
log(err.message) |
|
); |
|
}, 10000);
|
|
|