feat: camera diagnostics (#1681)

This commit is contained in:
Rafael Taranto 2024-05-28 21:42:05 +01:00 committed by GitHub
parent 5ae9b76c3b
commit e1c2cc8619
13 changed files with 395 additions and 3 deletions

View file

@ -1,6 +1,9 @@
const fsPromises = require('fs').promises
const path = require('path')
const _ = require('lodash/fp')
const pgp = require('pg-promise')()
const uuid = require('uuid')
const makeDir = require('make-dir')
const batching = require('./cashbox-batches')
const db = require('./db')
@ -13,10 +16,12 @@ const notifierUtils = require('./notifier/utils')
const notifierQueries = require('./notifier/queries')
const { ApolloError } = require('apollo-server-errors');
const { loadLatestConfig } = require('./new-settings-loader')
const logger = require('./logger')
const fullyFunctionalStatus = { label: 'Fully functional', type: 'success' }
const unresponsiveStatus = { label: 'Unresponsive', type: 'error' }
const stuckStatus = { label: 'Stuck', type: 'error' }
const OPERATOR_DATA_DIR = process.env.OPERATOR_DATA_DIR
const MACHINE_WITH_CALCULATED_FIELD_SQL = `
select d.*, COALESCE(emptybills, 0) + COALESCE(regularbills, 0) as cashbox from devices d
@ -53,6 +58,11 @@ function toMachineObject (r) {
numberOfRecyclers: r.number_of_recyclers,
version: r.version,
model: r.model,
diagnostics: {
timestamp: r.diagnostics_timestamp? new Date(r.diagnostics_timestamp) : null,
scanTimestamp: r.diagnostics_scan_timestamp? new Date(r.diagnostics_scan_timestamp) : null,
frontTimestamp: r.diagnostics_front_timestamp? new Date(r.diagnostics_front_timestamp) : null
},
pairedAt: new Date(r.created),
lastPing: new Date(r.last_online),
name: r.name,
@ -362,6 +372,36 @@ function refillUnit (rec) {
)])
}
function diagnostics (rec) {
const directory = `${OPERATOR_DATA_DIR}/diagnostics/${rec.deviceId}/`
const sql = `UPDATE devices
SET diagnostics_timestamp = NULL,
diagnostics_scan_updated_at = NULL,
diagnostics_front_updated_at = NULL
WHERE device_id = $1`
const scanPath = path.join(directory, 'scan.jpg')
const frontPath = path.join(directory, 'front.jpg')
const removeFiles = [scanPath, frontPath].map(filePath => {
return fsPromises.unlink(filePath).catch(err => {
if (err.code !== 'ENOENT') {
throw err
}
// File doesn't exist, no problem
})
})
return Promise.all(removeFiles)
.then(() => db.none(sql, [rec.deviceId]))
.then(() => db.none('NOTIFY $1:name, $2', ['machineAction', JSON.stringify(
{
action: 'diagnostics',
value: _.pick(['deviceId', 'operatorId', 'action'], rec)
}
)]))
}
function setMachine (rec, operatorId) {
rec.operatorId = operatorId
switch (rec.action) {
@ -374,6 +414,7 @@ function setMachine (rec, operatorId) {
case 'restartServices': return restartServices(rec)
case 'emptyUnit': return emptyUnit(rec)
case 'refillUnit': return refillUnit(rec)
case 'diagnostics': return diagnostics(rec)
default: throw new Error('No such action: ' + rec.action)
}
}
@ -436,6 +477,44 @@ function getNetworkHeartbeatByDevice (deviceId) {
.then(res => _.mapKeys(_.camelCase, _.find(it => it.device_id === deviceId, res)))
}
function updateDiagnostics (deviceId, images) {
const sql = `UPDATE devices
SET diagnostics_timestamp = NOW(),
diagnostics_scan_updated_at = CASE WHEN $2 THEN NOW() ELSE diagnostics_scan_updated_at END,
diagnostics_front_updated_at = CASE WHEN $3 THEN NOW() ELSE diagnostics_front_updated_at END
WHERE device_id = $1`
const directory = `${OPERATOR_DATA_DIR}/diagnostics/${deviceId}/`
const { scan, front } = images
return updatePhotos(scan, front, directory)
.then(() => db.none(sql, [deviceId, !!scan, !!front]))
.catch(err => logger.error('while running machine diagnostics: ', err))
}
function createPhoto (name, data, dir) {
if (!data) {
logger.error(`Diagnostics error: No data to save for ${name} photo`)
return Promise.resolve()
}
const decodedImageData = Buffer.from(data, 'base64')
const filename = path.join(dir, name)
return fsPromises.writeFile(filename, decodedImageData)
}
function updatePhotos (scan, front, dir) {
const dirname = path.join(dir)
_.attempt(() => makeDir.sync(dirname))
const promises = [
createPhoto('scan.jpg', scan, dirname),
createPhoto('front.jpg', front, dirname)
]
return Promise.all(promises)
}
module.exports = {
getMachineName,
getMachines,
@ -450,5 +529,6 @@ module.exports = {
getConfig,
getMachineIds,
emptyMachineUnits,
refillMachineUnits
refillMachineUnits,
updateDiagnostics
}