- 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>
146 lines
3.7 KiB
TypeScript
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
|
|
}
|
|
}
|