Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for machine enabling/disabling #1392

Open
wants to merge 1 commit into
base: future-stuff-old-dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/graphql/resolvers.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,14 @@ 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('isEnabled', pq.machine.isEnabled),
)(pq)
}


const configs = (parent, { currentConfigVersion }, { deviceId, deviceName, operatorId, pid, settings }, info) =>
plugins(settings, deviceId)
.pollQueries()
.pollQueries(deviceId)
.then(pq => ({
static: staticConfig({
currentConfigVersion,
Expand Down
1 change: 1 addition & 0 deletions lib/graphql/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ type DynamicConfig {
reboot: Boolean!
shutdown: Boolean!
restartServices: Boolean!
isEnabled: Boolean!
}

type Configs {
Expand Down
35 changes: 31 additions & 4 deletions lib/machine-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ const configManager = require('./new-config-manager')
const settingsLoader = require('./new-settings-loader')
const notifierUtils = require('./notifier/utils')
const notifierQueries = require('./notifier/queries')
const { ApolloError } = require('apollo-server-errors');
const { ApolloError } = require('apollo-server-errors')

const fullyFunctionalStatus = { label: 'Fully functional', type: 'success' }
const unresponsiveStatus = { label: 'Unresponsive', type: 'error' }
const stuckStatus = { label: 'Stuck', type: 'error' }
const disabledStatus = { label: 'Disabled by operator', type: 'warning' }

function toMachineObject (r) {
return {
Expand All @@ -32,7 +33,8 @@ function toMachineObject (r) {
pairedAt: new Date(r.created),
lastPing: new Date(r.last_online),
name: r.name,
paired: r.paired
paired: r.paired,
isEnabled: r.is_enabled
// TODO: we shall start using this JSON field at some point
// location: r.location,
}
Expand All @@ -59,7 +61,9 @@ function getConfig (defaultConfig) {
return settingsLoader.loadLatest().config
}

const getStatus = (ping, stuck) => {
const getStatus = (ping, stuck, isEnabled) => {
if (!isEnabled) return disabledStatus

if (ping && ping.age) return unresponsiveStatus

if (stuck && stuck.age) return stuckStatus
Expand All @@ -76,7 +80,8 @@ function addName (pings, events, config) {
const statuses = [
getStatus(
_.first(pings[machine.deviceId]),
_.first(checkStuckScreen(events, machine))
_.first(checkStuckScreen(events, machine)),
machine.isEnabled
)
]

Expand Down Expand Up @@ -175,6 +180,26 @@ function reboot (rec) {
)])
}

function disable (rec) {
return db.none('NOTIFY $1:name, $2', ['machineAction', JSON.stringify(
{
action: 'disable',
value: _.pick(['deviceId', 'operatorId', 'action'], rec)
}
)])
.then(() => db.none(`UPDATE devices SET is_enabled = false WHERE device_id = $1`, [rec.deviceId]))
}

function enable (rec) {
return db.none('NOTIFY $1:name, $2', ['machineAction', JSON.stringify(
{
action: 'enable',
value: _.pick(['deviceId', 'operatorId', 'action'], rec)
}
)])
.then(() => db.none(`UPDATE devices SET is_enabled = true WHERE device_id = $1`, [rec.deviceId]))
}

function shutdown (rec) {
return db.none('NOTIFY $1:name, $2', ['machineAction', JSON.stringify(
{
Expand Down Expand Up @@ -202,6 +227,8 @@ function setMachine (rec, operatorId) {
case 'setCassetteBills': return setCassetteBills(rec)
case 'unpair': return unpair(rec)
case 'reboot': return reboot(rec)
case 'disable': return disable(rec)
case 'enable': return enable(rec)
case 'shutdown': return shutdown(rec)
case 'restartServices': return restartServices(rec)
default: throw new Error('No such action: ' + rec.action)
Expand Down
6 changes: 6 additions & 0 deletions lib/middlewares/populateSettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ function machineAction (type, value) {
logger.debug(`Restarting services of machine '${deviceId}' from operator ${operatorId}`)
state.restartServicesMap[operatorId] = { [deviceId]: pid }
break
case 'disable':
logger.debug(`Disabling machine '${deviceId}' from operator ${operatorId}`)
break
case 'enable':
logger.debug(`Enabling machine '${deviceId}' from operator ${operatorId}`)
break
default:
break
}
Expand Down
3 changes: 3 additions & 0 deletions lib/new-admin/graphql/types/machine.type.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const typeDef = gql`
downloadSpeed: String
responseTime: String
packetLoss: String
isEnabled: Boolean
}

type UnpairedMachine {
Expand Down Expand Up @@ -53,6 +54,8 @@ const typeDef = gql`
setCassetteBills
unpair
reboot
disable
enable
shutdown
restartServices
}
Expand Down
2 changes: 2 additions & 0 deletions lib/notifier/codes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const T = require('../time')

const PING = 'PING'
const STALE = 'STALE'
const DISABLED = 'DISABLED'
const LOW_CRYPTO_BALANCE = 'LOW_CRYPTO_BALANCE'
const HIGH_CRYPTO_BALANCE = 'HIGH_CRYPTO_BALANCE'
const CASH_BOX_FULL = 'CASH_BOX_FULL'
Expand Down Expand Up @@ -35,6 +36,7 @@ const NOTIFICATION_TYPES = {
module.exports = {
PING,
STALE,
DISABLED,
LOW_CRYPTO_BALANCE,
HIGH_CRYPTO_BALANCE,
CASH_BOX_FULL,
Expand Down
4 changes: 3 additions & 1 deletion lib/notifier/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const notificationCenter = require('./notificationCenter')
const utils = require('./utils')
const emailFuncs = require('./email')
const smsFuncs = require('./sms')
const { STALE, STALE_STATE } = require('./codes')
const { DISABLED, STALE, STALE_STATE } = require('./codes')

function buildMessage (alerts, notifications) {
const smsEnabled = utils.isActive(notifications.sms)
Expand Down Expand Up @@ -123,6 +123,8 @@ function checkStuckScreen (deviceEvents, machine) {

const age = Math.floor(lastEvent.age)
const machineName = machine.name

if (!machine.isEnabled) return [{ code: DISABLED, state, age, machineName }]
if (age > STALE_STATE) return [{ code: STALE, state, age, machineName }]

return []
Expand Down
7 changes: 5 additions & 2 deletions lib/plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ function plugins (settings, deviceId, schema) {
}
}

function pollQueries () {
function pollQueries (deviceId) {
const localeConfig = configManager.getLocale(deviceId, settings.config)
const fiatCode = localeConfig.fiatCurrency
const cryptoCodes = localeConfig.cryptoCurrencies
Expand All @@ -243,6 +243,7 @@ function plugins (settings, deviceId, schema) {
fetchCurrentConfigVersion(),
millisecondsToMinutes(getTimezoneOffset(localeConfig.timezone)),
loyalty.getNumberOfAvailablePromoCodes(),
machineLoader.getMachine(deviceId),
Promise.all(supportsBatchingPromise),
Promise.all(tickerPromises),
Promise.all(balancePromises),
Expand All @@ -253,6 +254,7 @@ function plugins (settings, deviceId, schema) {
configVersion,
timezone,
numberOfAvailablePromoCodes,
machine,
batchableCoins,
tickers,
balances,
Expand All @@ -278,7 +280,8 @@ function plugins (settings, deviceId, schema) {
coins,
configVersion,
areThereAvailablePromoCodes: numberOfAvailablePromoCodes > 0,
timezone
timezone,
machine
}
})
}
Expand Down
4 changes: 3 additions & 1 deletion lib/routes/pollingRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ function poll (req, res, next) {

return Promise.all([
pi.recordPing(deviceTime, machineVersion, machineModel),
pi.pollQueries(),
pi.pollQueries(deviceId),
buildTriggers(configManager.getTriggers(settings.config)),
configManager.getTriggersAutomation(getCustomInfoRequests(true), settings.config),
])
Expand All @@ -92,6 +92,7 @@ function poll (req, res, next) {
const shutdown = pid && state.shutdowns?.[operatorId]?.[deviceId] === pid
const restartServices = pid && state.restartServicesMap?.[operatorId]?.[deviceId] === pid
const langs = localeConfig.languages
const isEnabled = results.machine.isEnabled

const locale = {
fiatCode: localeConfig.fiatCurrency,
Expand All @@ -111,6 +112,7 @@ function poll (req, res, next) {
enablePaperWalletOnly,
twoWayMode: cashOutConfig.active,
zeroConfLimits,
isEnabled,
reboot,
shutdown,
restartServices,
Expand Down
13 changes: 13 additions & 0 deletions migrations/1664325129303-allow-machine-disabling.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
var db = require('./db')

exports.up = function (next) {
var sql = [
`ALTER TABLE devices ADD COLUMN is_enabled BOOLEAN DEFAULT true`
]

db.multi(sql, next)
}

exports.down = function (next) {
next()
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ const isStaticState = machineState => {
'unpaired',
'maintenance',
'virgin',
'wifiList'
'wifiList',
'disabled'
]
return staticStates.includes(machineState)
}
Expand Down Expand Up @@ -155,6 +156,25 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
}>
Reboot
</ActionButton>
<ActionButton
color="primary"
className={classes.mr}
Icon={ShutdownIcon}
InverseIcon={ShutdownReversedIcon}
disabled={loading}
onClick={() =>
!machine.isEnabled
? setAction({
command: 'enable',
display: 'Enable'
})
: setAction({
command: 'disable',
display: 'Disable'
})
}>
{!machine.isEnabled ? `Enable` : `Disable`}
</ActionButton>
<ActionButton
color="primary"
className={classes.mr}
Expand Down
1 change: 1 addition & 0 deletions new-lamassu-admin/src/pages/Maintenance/MachineStatus.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const GET_MACHINES = gql`
downloadSpeed
responseTime
packetLoss
isEnabled
}
}
`
Expand Down