Files
adam-acs/app/domain/commands/command.ts
T
Kevin L'HereecandCopilot d1c65dbf1e chore: initial commit — AdonisJS v7 TR-069 ACS
- Docker infrastructure (Dockerfile, docker-compose.yml, genieacs-sim)
- AdonisJS v7 app with Inertia.js + Vue 3
- MongoDB integration
- CWMP/TR-069 state machine engine
- Configuration engine with compliance tracking
- Branding: ADAM ACS (favicon, navbar, locales)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-29 16:46:37 +02:00

146 lines
3.7 KiB
TypeScript

import { DeviceId } from '../device/device_id.js'
import { ModeType } from '../shared/mode.js'
import { ObjectId } from 'mongodb'
export type CommandId = string
export enum CommandType {
SET_PARAMETER_VALUES = 'SET_PARAMETER_VALUES',
GET_PARAMETER_VALUES = 'GET_PARAMETER_VALUES',
GET_PARAMETER_NAMES = 'GET_PARAMETER_NAMES',
SET_PARAMETER_ATTRIBUTES = 'SET_PARAMETER_ATTRIBUTES',
GET_PARAMETER_ATTRIBUTES = 'GET_PARAMETER_ATTRIBUTES',
DOWNLOAD = 'DOWNLOAD',
UPLOAD = 'UPLOAD',
REBOOT = 'REBOOT',
FACTORY_RESET = 'FACTORY_RESET',
SCHEDULE_INFORM = 'SCHEDULE_INFORM',
REFRESH = 'REFRESH',
}
export enum CommandStatus {
PENDING = 'PENDING',
SENT = 'SENT',
WAITING = 'WAITING',
FAILED = 'FAILED',
CANCELLED = 'CANCELLED',
COMPLETED = 'COMPLETED',
}
export enum Priority {
LOW = 0,
NORMAL = 1,
HIGH = 2,
CRITICAL = 3,
}
export type CommandParameters = Record<string, any>
export interface CommandResult {
success: boolean
data?: any
message?: string
timestamp: Date
}
export interface CommandRecord {
_id?: ObjectId
deviceIdentifier: string
mode: ModeType
action: CommandType
parameters: Record<string, any>
status: CommandStatus
createdAt: Date
updatedAt: Date
executedAt?: Date
completedAt?: Date
priority: number
}
export class Command {
private _status: CommandStatus
private _executedAt: Date | null = null
private _result: CommandResult | null = null
private _error: string | null = null
constructor(
public readonly id: CommandId,
public readonly deviceId: DeviceId,
public readonly type: CommandType,
public readonly parameters: CommandParameters = {},
public readonly priority: Priority = Priority.NORMAL,
public readonly createdAt: Date = new Date(),
status: CommandStatus = CommandStatus.PENDING
) {
this._status = status
}
public get status(): CommandStatus {
return this._status
}
public get executedAt(): Date | null {
return this._executedAt
}
public get result(): CommandResult | null {
return this._result
}
public get error(): string | null {
return this._error
}
public markAsSent(): void {
if (this._status !== CommandStatus.PENDING) {
throw new Error(`Cannot mark command as sent. Current status: ${this._status}`)
}
this._status = CommandStatus.SENT
this._executedAt = new Date()
}
public markAsWaiting(): void {
if (this._status !== CommandStatus.SENT) {
throw new Error(`Cannot mark command as waiting. Current status: ${this._status}`)
}
this._status = CommandStatus.WAITING
}
public complete(result: CommandResult): void {
if (![CommandStatus.SENT, CommandStatus.WAITING].includes(this._status)) {
throw new Error(`Cannot complete command. Current status: ${this._status}`)
}
this._status = CommandStatus.COMPLETED
this._result = result
this._executedAt = new Date()
}
public fail(error: string): void {
if (this._status === CommandStatus.COMPLETED) {
throw new Error('Cannot fail a successful command')
}
this._status = CommandStatus.FAILED
this._error = error
this._executedAt = new Date()
}
public cancel(): void {
if ([CommandStatus.COMPLETED, CommandStatus.FAILED].includes(this._status)) {
throw new Error(`Cannot cancel command with status: ${this._status}`)
}
this._status = CommandStatus.CANCELLED
}
public canExecute(): boolean {
return this._status === CommandStatus.PENDING
}
public isCompleted(): boolean {
return [CommandStatus.COMPLETED, CommandStatus.FAILED, CommandStatus.CANCELLED].includes(this._status)
}
public hasExpired(timeoutMinutes: number = 30): boolean {
return (Date.now() - this.createdAt.getTime()) / (1000 * 60) > timeoutMinutes
}
}