feat: add empty and refill unit machine actions

fix: remove certain actions from the state middleware after being consumed by the poller
This commit is contained in:
Sérgio Salgado 2023-05-03 18:26:46 +01:00
parent 2e9bb3c7df
commit 797f074898
10 changed files with 163 additions and 2 deletions

View file

@ -182,7 +182,7 @@ const dynamicConfig = ({ deviceId, operatorId, pid, pq, settings, }) => {
state.pids = _.update(operatorId, _.set(deviceId, { pid, ts: Date.now() }), state.pids)
return _.flow(
const res = _.flow(
_.pick(['areThereAvailablePromoCodes', 'balances', 'cassettes', 'stackers', 'coins', 'rates']),
_.update('cassettes', massageCassettes),
@ -225,7 +225,20 @@ const dynamicConfig = ({ deviceId, operatorId, pid, pq, settings, }) => {
_.set('reboot', !!pid && state.reboots?.[operatorId]?.[deviceId] === pid),
_.set('shutdown', !!pid && state.shutdowns?.[operatorId]?.[deviceId] === pid),
_.set('restartServices', !!pid && state.restartServicesMap?.[operatorId]?.[deviceId] === pid),
_.set('emptyUnit', !!pid && state.emptyUnit?.[operatorId]?.[deviceId] === pid),
_.set('refillUnit', !!pid && state.refillUnit?.[operatorId]?.[deviceId] === pid),
)(pq)
// Clean up the state middleware and prevent commands from being issued more than once
if (!_.isNil(state.emptyUnit?.[operatorId]?.[deviceId])) {
delete state.emptyUnit?.[operatorId]?.[deviceId]
}
if (!_.isNil(state.refillUnit?.[operatorId]?.[deviceId])) {
delete state.refillUnit?.[operatorId]?.[deviceId]
}
return res
}

View file

@ -196,6 +196,8 @@ type DynamicConfig {
reboot: Boolean!
shutdown: Boolean!
restartServices: Boolean!
emptyUnit: Boolean!
refillUnit: Boolean!
}
type Configs {

View file

@ -173,6 +173,42 @@ function setCassetteBills (rec) {
})
}
function emptyMachineUnits (deviceId, units) {
return Promise.all([getMachine(deviceId), configManager.getCashOut(deviceId, getConfig())])
.then(([machine, cashoutSettings]) => {
const movedBills = _.reduce(
(acc, value) => ({
...acc,
[value]: {
delta: machine[value] - units[value],
denomination: cashoutSettings[value]
}
}),
{},
_.keys(units)
)
const sql = `UPDATE devices SET cassette1=$2, cassette2=$3, cassette3=$4, cassette4=$5, stacker1f=$6, stacker1r=$7, stacker2f=$8, stacker2r=$9, stacker3f=$10, stacker3r=$11 WHERE device_id=$1`
return db.none(sql, [
deviceId,
_.defaultTo(0, units.cassette1),
_.defaultTo(0, units.cassette2),
_.defaultTo(0, units.cassette3),
_.defaultTo(0, units.cassette4),
_.defaultTo(0, units.stacker1f),
_.defaultTo(0, units.stacker1r),
_.defaultTo(0, units.stacker2f),
_.defaultTo(0, units.stacker2r),
_.defaultTo(0, units.stacker3f),
_.defaultTo(0, units.stacker3r)
])
})
}
function refillMachineUnits (deviceId, units) {
return Promise.resolve()
}
function unpair (rec) {
return pairing.unpair(rec.deviceId)
}
@ -204,6 +240,24 @@ function restartServices (rec) {
)])
}
function emptyUnit (rec) {
return db.none('NOTIFY $1:name, $2', ['machineAction', JSON.stringify(
{
action: 'emptyUnit',
value: _.pick(['deviceId', 'operatorId', 'action'], rec)
}
)])
}
function refillUnit (rec) {
return db.none('NOTIFY $1:name, $2', ['machineAction', JSON.stringify(
{
action: 'refillUnit',
value: _.pick(['deviceId', 'operatorId', 'action'], rec)
}
)])
}
function setMachine (rec, operatorId) {
rec.operatorId = operatorId
switch (rec.action) {
@ -215,6 +269,8 @@ function setMachine (rec, operatorId) {
case 'reboot': return reboot(rec)
case 'shutdown': return shutdown(rec)
case 'restartServices': return restartServices(rec)
case 'emptyUnit': return emptyUnit(rec)
case 'refillUnit': return refillUnit(rec)
default: throw new Error('No such action: ' + rec.action)
}
}
@ -288,5 +344,7 @@ module.exports = {
updateNetworkHeartbeat,
getNetworkPerformance,
getNetworkHeartbeat,
getConfig
getConfig,
emptyMachineUnits,
refillMachineUnits
}

View file

@ -37,6 +37,14 @@ function machineAction (type, value) {
logger.debug(`Restarting services of machine '${deviceId}' from operator ${operatorId}`)
state.restartServicesMap[operatorId] = { [deviceId]: pid }
break
case 'emptyUnit':
logger.debug(`Emptying units from machine '${deviceId}' from operator ${operatorId}`)
state.emptyUnit[operatorId] = { [deviceId]: pid }
break
case 'refillUnit':
logger.debug(`Refilling stackers from machine '${deviceId}' from operator ${operatorId}`)
state.refillUnit[operatorId] = { [deviceId]: pid }
break
default:
break
}

View file

@ -15,6 +15,8 @@ module.exports = (function () {
reboots: {},
shutdowns: {},
restartServicesMap: {},
emptyUnit: {},
refillUnit: {},
mnemonic: null
}
}())

View file

@ -80,6 +80,8 @@ const typeDef = gql`
reboot
shutdown
restartServices
emptyUnit
refillUnit
}
type Query {

View file

@ -16,6 +16,7 @@ const populateDeviceId = require('./middlewares/populateDeviceId')
const populateSettings = require('./middlewares/populateSettings')
const recordPing = require('./middlewares/recordPing')
const unitsRoutes = require('./routes/unitsRoutes')
const cashboxRoutes = require('./routes/cashboxRoutes')
const customerRoutes = require('./routes/customerRoutes')
const logsRoutes = require('./routes/logsRoutes')
@ -82,6 +83,7 @@ app.use('/customer', customerRoutes)
app.use('/tx', txRoutes)
app.use('/logs', logsRoutes)
app.use('/units', unitsRoutes)
graphQLServer.applyMiddleware({ app })

View file

@ -96,6 +96,8 @@ function poll (req, res, next) {
const reboot = pid && state.reboots?.[operatorId]?.[deviceId] === pid
const shutdown = pid && state.shutdowns?.[operatorId]?.[deviceId] === pid
const restartServices = pid && state.restartServicesMap?.[operatorId]?.[deviceId] === pid
const emptyUnit = pid && state.emptyUnit?.[operatorId]?.[deviceId] === pid
const refillUnit = pid && state.refillUnit?.[operatorId]?.[deviceId] === pid
const langs = localeConfig.languages
const locale = {
@ -119,6 +121,8 @@ function poll (req, res, next) {
reboot,
shutdown,
restartServices,
emptyUnit,
refillUnit,
hasLightning,
receipt,
operatorInfo,

34
lib/routes/unitsRoutes.js Normal file
View file

@ -0,0 +1,34 @@
const express = require('express')
const { emptyMachineUnits, refillMachineUnits } = require('../machine-loader')
const router = express.Router()
const emptyUnitUpdateCounts = (req, res, next) => {
const deviceId = req.deviceId
const newUnits = req.body.newUnits
return emptyMachineUnits({ deviceId, cashUnits: newUnits })
.then(() => res.sendStatus(200))
.catch(e => {
console.error(e)
return res.sendStatus(500)
})
.finally(next)
}
const refillUnitUpdateCounts = (req, res, next) => {
const deviceId = req.deviceId
const newUnits = req.body.newUnits
return refillMachineUnits({ deviceId, cashUnits: newUnits })
.then(() => res.sendStatus(200))
.catch(e => {
console.error(e)
return res.sendStatus(500)
})
.finally(next)
}
router.post('/empty', emptyUnitUpdateCounts)
router.post('/refill', refillUnitUpdateCounts)
module.exports = router