Files
adam-acs/app/controllers/pages_controller.ts
T
Kevin L'Hereec 8969355688
Build & Deploy / build (push) Successful in 34s
Build & Deploy / docker (push) Successful in 1m4s
Build & Deploy / deploy (push) Successful in 32s
feat: improve critical reads, device list and modelPaths bug fix
- main_state_machine.ts: add to CriticalReadsState GPV:
  ProvisioningCode (confirm CPE persisted value), UpTime (detect reboots),
  ManagementServer.URL (verify ACS URL), ConnectionRequestUsername/Password
  (ensure wake credentials are always available)
- Home.vue: add Last Seen column (device.updatedAt)
- pages_controller.ts: fix modelPaths bug — was never passed to DeviceDetail,
  now auto-detected from dataModel and passed as predefined TR-181/TR-098 paths
2026-07-17 16:57:08 +02:00

153 lines
5.5 KiB
TypeScript

import type { HttpContext } from '@adonisjs/core/http'
import DeviceService from '#services/device_service'
import CommandService from '#services/command_service'
export default class PagesController {
private deviceService = new DeviceService()
private commandService = new CommandService()
async home({ inertia }: HttpContext) {
const { data } = await this.deviceService.getDevices(0, 200)
return (inertia as any).render('Home', { devices: data, message: '' })
}
async deviceDetail({ params, inertia, response }: HttpContext) {
const device = await this.deviceService.getDeviceByIdentifier(params.identifier)
if (!device) {
return response.status(404).json({ message: 'Device not found' })
}
// Get pending commands (max 5) + last processed command
const allCommands = await this.commandService.getCommandsByDevice(params.identifier)
const pending = allCommands
.filter((c: any) => ['PENDING', 'WAITING', 'SENT'].includes(c.status))
.slice(0, 5)
const lastProcessed = allCommands
.filter((c: any) => ['COMPLETED', 'FAILED'].includes(c.status))
.sort(
(a: any, b: any) =>
new Date(b.updatedAt || b.createdAt).getTime() -
new Date(a.updatedAt || a.createdAt).getTime()
)[0]
const commands = lastProcessed ? [...pending, lastProcessed] : pending
// Predefined model paths for the "Get Model" modal
// Detect data model from device properties to suggest the right root
const isTr181 = (device as any).dataModel === 'tr-181' ||
(device as any).properties?.some((p: any) => p.name?.startsWith('Device.'))
const modelPaths = isTr181
? ['Device.', 'Device.DeviceInfo.', 'Device.IP.', 'Device.WiFi.', 'Device.ManagementServer.', 'Device.Hosts.']
: ['InternetGatewayDevice.', 'InternetGatewayDevice.DeviceInfo.', 'InternetGatewayDevice.LANDevice.', 'InternetGatewayDevice.WANDevice.', 'InternetGatewayDevice.ManagementServer.']
return (inertia as any).render('DeviceDetail', { device, commands, modelPaths })
}
async commands({ inertia, request }: HttpContext) {
const deviceFilter = request.qs().device || ''
const statusFilter = request.qs().status || ''
const actionFilter = request.qs().action || ''
const modeFilter = request.qs().mode || ''
let commands: any[] = await this.commandService.getCommands()
if (deviceFilter) {
commands = commands.filter((c: any) => c.deviceIdentifier === deviceFilter)
}
if (statusFilter) {
commands = commands.filter((c: any) => c.status === statusFilter)
}
if (actionFilter) {
commands = commands.filter((c: any) => c.action === actionFilter)
}
if (modeFilter) {
commands = commands.filter((c: any) => c.mode === modeFilter)
}
return (inertia as any).render('Commands', {
commands,
filters: {
device: deviceFilter,
status: statusFilter,
action: actionFilter,
mode: modeFilter,
},
})
}
async commandsFleet({ inertia, session }: HttpContext) {
const devices = (session as any).get('fleetDevices', [])
const commands = await this.commandService.getCommands()
return (inertia as any).render('CommandsFleet', { devices, commands })
}
async tr069Trace({ inertia }: HttpContext) {
return (inertia as any).render('Tr069Trace')
}
async storeFleetDevices({ request, response, session }: HttpContext) {
const { devices } = request.body()
;(session as any).put('fleetDevices', devices || [])
return response.redirect().toPath('/commands/fleet')
}
async refreshDevice({ params, response }: HttpContext) {
// Create a REFRESH command and send Connection Request to wake the CPE
await this.deviceService.refreshDevice(params.identifier)
return response.redirect().back()
}
async getModel({ params, request }: HttpContext) {
const { modelPath } = request.body()
await this.deviceService.executeCommand(params.identifier, {
action: 'GET_PARAMETER_NAMES' as any,
parameters: { parameterPath: modelPath, nextLevel: true },
mode: 'I',
})
}
async storeFleetCommand({ request, response, session }: HttpContext) {
const { action, parameters, mode, priority, devices } = request.body()
const deviceList = devices || session.get('fleetDevices', [])
for (const deviceIdentifier of deviceList) {
await this.commandService.createCommand({
deviceIdentifier,
action,
parameters: parameters || {},
mode,
priority,
})
}
return response.redirect().toPath('/commands/fleet')
}
async configurationsList({ inertia }: HttpContext) {
return (inertia as any).render('configurations/ConfigurationsList')
}
async configurationCreate({ inertia }: HttpContext) {
return (inertia as any).render('configurations/ConfigurationCreate')
}
async configurationEdit({ params, inertia }: HttpContext) {
return (inertia as any).render('configurations/ConfigurationEdit', { id: params.id })
}
async configurationDetail({ params, inertia }: HttpContext) {
return (inertia as any).render('configurations/ConfigurationDetail', { id: params.id })
}
async firmwareCatalog({ inertia }: HttpContext) {
return (inertia as any).render('firmware_catalog/FirmwareCatalog')
}
async firmwareCatalogCreate({ inertia }: HttpContext) {
return (inertia as any).render('firmware_catalog/FirmwareCatalogCreate')
}
async firmwareCatalogEdit({ params, inertia }: HttpContext) {
return (inertia as any).render('firmware_catalog/FirmwareCatalogEdit', { id: params.id })
}
}