171 lines
5.4 KiB
TypeScript
171 lines
5.4 KiB
TypeScript
/**
|
|
* Base classes and interfaces for the NUPST action system
|
|
*
|
|
* Actions are triggered on:
|
|
* 1. Power status changes (online ↔ onBattery)
|
|
* 2. Threshold violations (battery/runtime cross below configured thresholds)
|
|
*/
|
|
|
|
export type TPowerStatus = 'online' | 'onBattery' | 'unknown';
|
|
|
|
/**
|
|
* Context provided to actions when they execute
|
|
* Contains all relevant UPS state and trigger information
|
|
*/
|
|
export interface IActionContext {
|
|
// UPS identification
|
|
/** Unique ID of the UPS */
|
|
upsId: string;
|
|
/** Human-readable name of the UPS */
|
|
upsName: string;
|
|
|
|
// Current state
|
|
/** Current power status */
|
|
powerStatus: TPowerStatus;
|
|
/** Current battery capacity percentage (0-100) */
|
|
batteryCapacity: number;
|
|
/** Estimated battery runtime in minutes */
|
|
batteryRuntime: number;
|
|
|
|
// State tracking
|
|
/** Previous power status before this trigger */
|
|
previousPowerStatus: TPowerStatus;
|
|
|
|
// Metadata
|
|
/** Timestamp when this action was triggered (milliseconds since epoch) */
|
|
timestamp: number;
|
|
/** Reason this action was triggered */
|
|
triggerReason: 'powerStatusChange' | 'thresholdViolation';
|
|
}
|
|
|
|
/**
|
|
* Action trigger mode - determines when an action executes
|
|
*/
|
|
export type TActionTriggerMode =
|
|
| 'onlyPowerChanges' // Only on power status changes (online ↔ onBattery)
|
|
| 'onlyThresholds' // Only when action's thresholds are exceeded
|
|
| 'powerChangesAndThresholds' // On power changes OR threshold violations
|
|
| 'anyChange'; // On every UPS poll/check (every ~30s)
|
|
|
|
/**
|
|
* Configuration for an action
|
|
*/
|
|
export interface IActionConfig {
|
|
/** Type of action to execute */
|
|
type: 'shutdown' | 'webhook' | 'script';
|
|
|
|
// Trigger configuration
|
|
/**
|
|
* When should this action be triggered?
|
|
* - onlyPowerChanges: Only on power status changes
|
|
* - onlyThresholds: Only when thresholds exceeded
|
|
* - powerChangesAndThresholds: On both (default)
|
|
* - anyChange: On every check
|
|
*/
|
|
triggerMode?: TActionTriggerMode;
|
|
|
|
// Threshold configuration (applies to all action types)
|
|
/** Threshold settings for this action */
|
|
thresholds?: {
|
|
/** Battery percentage threshold (0-100) */
|
|
battery: number;
|
|
/** Runtime threshold in minutes */
|
|
runtime: number;
|
|
};
|
|
|
|
// Shutdown action configuration
|
|
/** Delay before shutdown in minutes (default: 5) */
|
|
shutdownDelay?: number;
|
|
/** Only execute shutdown on threshold violation, not power status changes */
|
|
onlyOnThresholdViolation?: boolean;
|
|
|
|
// Webhook action configuration
|
|
/** URL to call for webhook */
|
|
webhookUrl?: string;
|
|
/** HTTP method to use (default: POST) */
|
|
webhookMethod?: 'GET' | 'POST';
|
|
/** Timeout for webhook request in milliseconds (default: 10000) */
|
|
webhookTimeout?: number;
|
|
/** Only execute webhook on threshold violation */
|
|
webhookOnlyOnThresholdViolation?: boolean;
|
|
|
|
// Script action configuration
|
|
/** Path to script relative to /etc/nupst (e.g., "myaction.sh") */
|
|
scriptPath?: string;
|
|
/** Timeout for script execution in milliseconds (default: 60000) */
|
|
scriptTimeout?: number;
|
|
/** Only execute script on threshold violation */
|
|
scriptOnlyOnThresholdViolation?: boolean;
|
|
}
|
|
|
|
/**
|
|
* Abstract base class for all actions
|
|
* Each action type must extend this class and implement execute()
|
|
*/
|
|
export abstract class Action {
|
|
/** Type identifier for this action */
|
|
abstract readonly type: string;
|
|
|
|
/**
|
|
* Create a new action with the given configuration
|
|
* @param config Action configuration
|
|
*/
|
|
constructor(protected config: IActionConfig) {}
|
|
|
|
/**
|
|
* Execute this action with the given context
|
|
* @param context Current UPS state and trigger information
|
|
*/
|
|
abstract execute(context: IActionContext): Promise<void>;
|
|
|
|
/**
|
|
* Helper to check if this action should execute based on trigger mode
|
|
* @param context Action context with current UPS state
|
|
* @returns True if action should execute
|
|
*/
|
|
protected shouldExecute(context: IActionContext): boolean {
|
|
const mode = this.config.triggerMode || 'powerChangesAndThresholds'; // Default
|
|
|
|
switch (mode) {
|
|
case 'onlyPowerChanges':
|
|
// Only execute on power status changes
|
|
return context.triggerReason === 'powerStatusChange';
|
|
|
|
case 'onlyThresholds':
|
|
// Only execute when this action's thresholds are exceeded
|
|
if (!this.config.thresholds) return false; // No thresholds = never execute
|
|
return this.areThresholdsExceeded(context.batteryCapacity, context.batteryRuntime);
|
|
|
|
case 'powerChangesAndThresholds':
|
|
// Execute on power changes OR when thresholds exceeded
|
|
if (context.triggerReason === 'powerStatusChange') return true;
|
|
if (!this.config.thresholds) return false;
|
|
return this.areThresholdsExceeded(context.batteryCapacity, context.batteryRuntime);
|
|
|
|
case 'anyChange':
|
|
// Execute on every trigger (power change or threshold check)
|
|
return true;
|
|
|
|
default:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if current battery/runtime exceeds this action's thresholds
|
|
* @param batteryCapacity Current battery percentage
|
|
* @param batteryRuntime Current runtime in minutes
|
|
* @returns True if thresholds are exceeded
|
|
*/
|
|
protected areThresholdsExceeded(batteryCapacity: number, batteryRuntime: number): boolean {
|
|
if (!this.config.thresholds) {
|
|
return false; // No thresholds configured
|
|
}
|
|
|
|
return (
|
|
batteryCapacity < this.config.thresholds.battery ||
|
|
batteryRuntime < this.config.thresholds.runtime
|
|
);
|
|
}
|
|
}
|