intval3/index.js

666 lines
14 KiB
JavaScript

'use strict'
const restify = require('restify')
const log = require('./lib/log')('main')
const { readFile } = require('fs-extra')
const { exec } = require('child_process')
const BLE = require('./lib/ble')
const Intval = require('./lib/intval')
const intval = new Intval()
const Sequence = require('./lib/sequence')
const sequence = new Sequence(intval)
const PACKAGE = require('./package.json')
const PORT = process.env.PORT || 6699
const APPNAME = PACKAGE.name
const INDEXPATH = './app/www/index.html'
let app = restify.createServer({
name: APPNAME,
version: PACKAGE.version
})
let ble
async function execAsync (cmd) {
return new Promise((resolve, reject) => {
return exec(cmd, (err, stdio, stderr) => {
if (err) {
return reject(err)
}
return resolve(stdio)
})
})
}
async function info () {
const data = {
version : PACKAGE.version,
node : null,
npm : null,
os : null,
kernel : null
}
try {
data.node = await execAsync('node -v')
data.node = data.node.replace(/(\r\n|\n|\r)/gm, '')
} catch (err) {
log.error(err)
}
try {
data.npm = await execAsync('npm -v')
data.npm = data.npm.replace(/(\r\n|\n|\r)/gm, '')
} catch (err) {
log.error(err)
}
try {
data.kernel = await execAsync('uname -r')
data.kernel = data.kernel.replace(/(\r\n|\n|\r)/gm, '')
} catch (err) {
log.error(err)
}
try {
data.os = await execAsync('lsb_release -a | grep "Description"')
data.os = data.os.replace('Description:', '').replace(/(\r\n|\n|\r)/gm, '').trim()
} catch (err) {
log.error(err)
}
return data
}
function createServer () {
app.use(restify.plugins.queryParser())
app.use(restify.plugins.bodyParser({ mapParams: false }))
app.get( '/', index)
app.get( '/dir', rDir)
app.post('/dir', rDir)
app.get( '/exposure', rExposure)
app.post('/exposure', rExposure)
app.get( '/delay', rDelay)
app.post('/delay', rDelay)
app.get( '/counter', rCounter)
app.post('/counter', rCounter)
app.get( '/frame', rFrame)
app.post('/frame', rFrame)
app.get( '/sequence', rSequence)
app.post('/sequence', rSequence)
app.get( '/status', rStatus)
app.get( '/info', rInfo)
app.post('/reset', rReset)
app.post('/update', rUpdate)
app.post('/restart', rRestart)
app.listen(PORT, () => {
log.info('server', { name : APPNAME, port : PORT })
})
}
function createBLE () {
ble = new BLE(() => {
return intval.status()
})
ble.on('frame', bFrame)
ble.on('dir', bDir)
ble.on('exposure', bExposure)
ble.on('delay', bDelay)
ble.on('counter', bCounter)
ble.on('sequence', bSequence)
ble.on('reset', bReset)
ble.on('update', bUpdate)
ble.on('restart', bRestart)
}
async function rInfo (req, res, next) {
let data = {}
try {
data = await info()
} catch (err) {
log.error(err)
return next(err)
}
res.send(data)
return next()
}
//Restify functions
function rDir (req, res, next) {
let dir = true
let set = false
if (req.query && typeof req.query.dir !== 'undefined') {
if (typeof req.query.dir === 'string') {
dir = (req.query.dir === 'true')
} else {
dir = req.query.dir
}
set = true
} else if (req.body && typeof req.body.dir !== 'undefined') {
if (typeof req.body.dir === 'string') {
dir = (req.body.dir === 'true')
} else {
dir = req.body.dir
}
set = true
}
if (set) {
intval.setDir(dir)
} else {
dir = intval._state.frame.dir
}
log.info('/dir', { method: req.method, set : set, dir : dir})
res.send({ dir : dir })
return next()
}
function rExposure (req, res, next) {
let exposure = 0
let set = false
if (req.query && typeof req.query.exposure !== 'undefined') {
if (typeof req.query.exposure === 'string') {
exposure = parseInt(req.query.exposure)
} else {
exposure = req.query.exposure
}
set = true
} else if (req.body && typeof req.body.exposure !== 'undefined') {
if (typeof req.body.exposure === 'string') {
exposure = parseInt(req.body.exposure)
} else {
exposure = req.body.exposure
}
set = true
}
if (set) {
if (exposure <= intval._frame.expected) {
exposure = 0;
}
intval.setExposure(exposure)
} else {
exposure = intval._state.frame.exposure
}
log.info('/exposure', { method: req.method, set : set, exposure : exposure })
res.send({ exposure : exposure })
return next()
}
function rDelay (req, res, next) {
let delay = 0
let set = false
if (req.query && typeof req.query.delay !== 'undefined') {
if (typeof req.query.delay === 'string') {
delay = parseInt(req.query.delay)
} else {
delay = req.query.delay
}
set = true
}
if (req.body && typeof req.body.delay !== 'undefined') {
if (typeof req.body.delay === 'string') {
delay = parseInt(req.body.delay)
} else {
delay = req.body.delay
}
set = true
}
if (set) {
intval.setDelay(delay)
} else {
delay = intval._state.frame.delay
}
log.info('/delay', { method: req.method, set : set, delay : delay })
res.send({ delay : delay })
return next()
}
function rCounter (req, res, next) {
let counter = 0
let set = false
if (req.query && typeof req.query.counter !== 'undefined') {
if (typeof req.query.counter === 'string') {
counter = parseInt(req.query.counter)
} else {
counter = req.query.counter
}
set = true
}
if (req.body && typeof req.body.counter !== 'undefined') {
if (typeof req.body.counter !== 'string') {
counter = parseInt(req.body.counter)
} else {
counter = req.body.counter
}
set = true
}
if (set) {
intval.setCounter(counter)
} else {
counter = intval._state.counter
}
log.info('/counter', { method : req.method, set : set, counter : counter })
res.send({ counter : counter })
return next()
}
async function rFrame (req, res, next) {
let dir = true
let exposure = 0
let success = false
if (intval._state.frame.dir !== true) {
dir = false
}
if (intval._state.frame.exposure !== 0) {
exposure = intval._state.frame.exposure
}
if (req.query && typeof req.query.dir !== 'undefined') {
if (typeof req.query.dir === 'string') {
dir = (req.query.dir === 'true')
} else {
dir = req.query.dir
}
}
if (req.body && typeof req.body.dir !== 'undefined') {
if (typeof req.body.dir === 'string') {
dir = (req.body.dir === 'true')
} else {
dir = req.body.dir
}
}
if (req.query && typeof req.query.exposure !== 'undefined') {
if (typeof req.query.exposure === 'string') {
exposure = parseInt(req.query.exposure)
} else {
exposure = req.query.exposure
}
}
if (req.body && typeof req.body.exposure !== 'undefined') {
if (typeof req.body.exposure === 'string') {
exposure = parseInt(req.body.exposure)
} else {
exposure = req.body.exposure
}
}
log.info('/frame', { method : req.method, dir : dir, exposure : exposure })
if (exposure < 30000) {
success = await intval.frame(dir, exposure)
res.send({ dir : dir, len : exposure, success })
return next()
} else {
intval.frame(dir, exposure)
res.send({ dir : dir, len : exposure, delaying : true })
return next()
}
}
function rStatus (req, res, next) {
const obj = intval.status()
res.send(obj)
return next()
}
async function rSequence (req, res, next) {
let dir = true
let exposure = 0
let delay = 0
let options = {}
if (intval._state.frame.dir !== true) {
dir = false
}
if (intval._state.frame.exposure !== 0) {
exposure = intval._state.frame.exposure
}
if (intval._state.frame.delay !== 0) {
options.delay = intval._state.frame.delay
}
if (req.query && typeof req.query.dir !== 'undefined') {
if (typeof req.query.dir === 'string') {
dir = (req.query.dir === 'true')
} else {
dir = req.query.dir
}
}
if (req.body && typeof req.body.dir !== 'undefined') {
if (typeof req.body.dir === 'string') {
dir = (req.body.dir === 'true')
} else {
dir = req.body.dir
}
}
if (req.query && typeof req.query.exposure !== 'undefined') {
if (typeof req.query.exposure === 'string') {
exposure = parseInt(req.query.exposure)
} else {
exposure = req.query.exposure
}
}
if (req.body && typeof req.body.exposure !== 'undefined') {
if (typeof req.body.exposure === 'string') {
exposure = parseInt(req.body.exposure)
} else {
exposure = req.body.exposure
}
}
if (req.query && typeof req.query.delay !== 'undefined') {
if (typeof req.query.delay === 'string') {
delay = parseInt(req.query.delay)
} else {
delay = req.query.delay
}
}
if (req.body && typeof req.body.delay !== 'undefined') {
if (typeof req.body.delay === 'string') {
delay = parseInt(req.body.delay)
} else {
delay = req.body.delay
}
}
if (req.query && typeof req.query.len !== 'undefined') {
if (typeof req.query.len === 'string') {
options.len = parseInt(req.query.len)
} else {
options.len = req.query.len
}
}
if (req.body && typeof req.body.len !== 'undefined') {
if (typeof req.body.len === 'string') {
options.len = parseInt(req.body.len)
} else {
options.len = req.body.len
}
}
if (req.query && typeof req.query.multiple !== 'undefined') {
if (typeof req.query.multiple === 'string') {
options.multiple = parseInt(req.query.multiple)
} else {
options.multiple = req.query.multiple
}
}
if (req.body && typeof req.body.multiple !== 'undefined') {
if (typeof req.body.multiple === 'string') {
options.multiple = parseInt(req.body.multiple)
} else {
options.multiple = req.body.multiple
}
}
if (intval._state.sequence && sequence.active) {
intval._state.sequence = false
sequence.stop()
res.send({ stopped : true })
return next()
} else {
intval._state.sequence = true
sequence.start(options)
res.send({ started : true })
return next()
}
}
function rReset (req, res, next) {
log.info(`/reset`, {time : +new Date()})
intval.reset()
setTimeout(() => {
const obj = intval.status()
res.send(obj)
return next()
}, 10)
}
function rUpdate (req, res, next) {
log.info(`/update`, { time : +new Date() })
exec('sh ./scripts/update.sh', (err, stdio, stderr) => {
if (err) {
log.error(err)
}
log.info(`/update`, { git : stdio })
res.send({ success : true, action : 'update', output : stdio })
res.end()
next()
setTimeout(() => {
process.exit(0)
}, 100)
})
}
function rRestart (req, res, next) {
log.info(`/restart`, { time : +new Date() })
res.send({ success : true, action : 'restart' })
res.end()
next()
setTimeout(() => {
process.exit(0)
}, 100)
}
//Ble functions
async function bFrame (obj, cb) {
let dir = true
let exposure = 0
let success = false
if (sequence.active) {
return cb()
}
if (intval._state.frame.dir !== true) {
dir = false
}
if (intval._state.frame.exposure !== 0) {
exposure = intval._state.frame.exposure
}
if (typeof obj.dir !== 'undefined') {
if (typeof obj.dir === 'string') {
dir = (obj.dir === 'true')
} else {
dir = obj.dir
}
}
if (typeof obj.exposure !== 'undefined') {
if (typeof obj.exposure === 'string') {
exposure = parseInt(obj.exposure)
} else {
exposure = obj.exposure
}
}
log.info('frame', { method : 'ble', dir : dir, exposure : exposure })
if (exposure < 5000) {
success = await intval.frame(dir, exposure)
return cb()
} else {
intval.frame(dir, exposure)
return cb()
}
//setTimeout(cb, exposure === 0 ? 630 : exposure)
}
function bDir (obj, cb) {
let dir = true
let set = false
if (obj.dir !== 'undefined') {
if (typeof obj.dir === 'string') {
dir = (obj.dir === 'true')
} else {
dir = obj.dir
}
}
intval.setDir(dir)
log.info('dir', { method: 'ble', dir : dir })
cb()
}
function bExposure (obj, cb) {
let exposure = 0
if (typeof obj.exposure !== 'undefined') {
if (typeof obj.exposure === 'string') {
exposure = parseInt(obj.exposure)
} else {
exposure = obj.exposure
}
}
intval.setExposure(exposure)
log.info('exposure', { method: 'ble', exposure : exposure })
return cb()
}
function bDelay (obj, cb) {
let delay = 0
let set = false
if (typeof obj.delay !== 'undefined') {
if (typeof obj.delay === 'string') {
delay = parseInt(obj.delay)
} else {
delay = obj.delay
}
set = true
}
intval.setDelay(delay)
log.info('delay', { method: 'ble', delay : delay })
return cb()
}
function bCounter (obj, cb) {
let counter = 0
if (typeof obj.counter !== 'undefined') {
if (typeof obj.counter !== 'string') {
counter = parseInt(obj.counter)
} else {
counter = obj.counter
}
}
intval.setCounter(counter)
log.info('counter', { method : 'ble', counter : counter })
return cb()
}
function bSequence (obj, cb) {
let dir = true
let exposure = 0
let delay = 0
let options = {}
if (intval._state.frame.dir !== true) {
dir = false
}
if (intval._state.frame.exposure !== 0) {
exposure = intval._state.frame.exposure
}
if (intval._state.frame.delay !== 0) {
delay = intval._state.frame.delay
}
if (typeof obj.dir !== 'undefined') {
if (typeof obj.dir === 'string') {
dir = (obj.dir === 'true')
} else {
dir = obj.dir
}
}
if (typeof obj.exposure !== 'undefined') {
if (typeof obj.exposure === 'string') {
exposure = parseInt(obj.exposure)
} else {
exposure = obj.exposure
}
}
if (typeof obj.len !== 'undefined') {
if (typeof obj.len === 'string') {
options.len = parseInt(obj.len)
} else {
options.len = obj.len
}
}
if (typeof obj.multiple !== 'undefined') {
if (typeof obj.multiple === 'string') {
options.multiple = parseInt(obj.multiple)
} else {
options.multiple = obj.multiple
}
}
if (intval._state.sequence && sequence.active) {
//should not occur with single client
intval._state.sequence = false
sequence.stop()
log.info('sequence stop', { method : 'ble' })
return cb()
} else {
intval._state.sequence = true
sequence.start(options)
log.info('sequence start', { method : 'ble' })
return cb()
}
}
function bSequenceStop (obj, cb) {
if (intval._state.sequence && sequence.active) {
sequence.stop()
intval._state.sequence = false
log.info('sequence stop', { method : 'ble' })
return cb()
}
}
function bReset (obj, cb) {
log.info(`reset`, { method: 'ble' })
intval.reset()
setTimeout(cb, 10)
}
function bUpdate (obj, cb) {
log.info('update', { method : 'ble' })
exec('sh ./scripts/update.sh', (err, stdio, stderr) => {
if (err) {
log.error('update', err)
}
log.info('update', { stdio : stdio })
cb()
setTimeout(() => {
process.exit(0)
}, 20)
})
}
function bRestart (obj, cb) {
log.info('restart', { method : 'ble' })
cb()
setTimeout(() => {
process.exit(0)
}, 20)
}
async function index (req, res, next) {
let data
try {
data = await readFile(INDEXPATH, 'utf8')
} catch (err) {
return next(err)
}
}
function init () {
createServer()
createBLE()
}
init()