Files
devicemanager/ts/interfaces/feature.interfaces.ts

360 lines
9.7 KiB
TypeScript
Raw Normal View History

/**
* Feature Type Definitions
* Features are composable capabilities that can be attached to devices
*/
import type { IRetryOptions } from './index.js';
// ============================================================================
// Feature Types
// ============================================================================
/**
* All supported feature types
*/
export type TFeatureType =
// Document handling
| 'scan' // Can scan documents (eSCL, SANE)
| 'print' // Can print documents (IPP, JetDirect)
| 'fax' // Can send/receive fax
| 'copy' // Can copy (scan + print combined)
// Media playback
| 'playback' // Can play media (audio/video)
| 'volume' // Has volume control
// Infrastructure
| 'power' // Has power status (UPS, smart plug)
| 'snmp' // SNMP queryable
// DLNA
| 'dlna-render' // DLNA renderer
| 'dlna-serve' // DLNA server (content provider)
// Smart home (protocol-agnostic: home-assistant, hue, mqtt, etc.)
| 'light' // Brightness, color, effects
| 'climate' // Temperature, HVAC modes
| 'sensor' // Read-only state values
| 'camera' // Snapshots, streams
| 'cover' // Blinds, garage doors
| 'switch' // Binary on/off
| 'lock' // Lock/unlock
| 'fan' // Speed, oscillation
;
/**
* Feature connection state
*/
export type TFeatureState = 'disconnected' | 'connecting' | 'connected' | 'error';
// ============================================================================
// Base Feature Interface
// ============================================================================
/**
* Base interface for all features
*/
export interface IFeature {
/** Feature type identifier */
readonly type: TFeatureType;
/** Protocol used by this feature */
readonly protocol: string;
/** Current feature state */
readonly state: TFeatureState;
/** Port used by this feature (may differ from device port) */
readonly port: number;
/** Connect to the feature endpoint */
connect(): Promise<void>;
/** Disconnect from the feature endpoint */
disconnect(): Promise<void>;
}
/**
* Feature info for serialization
*/
export interface IFeatureInfo {
type: TFeatureType;
protocol: string;
port: number;
state: TFeatureState;
}
// ============================================================================
// Scan Feature
// ============================================================================
export type TScanProtocol = 'escl' | 'sane' | 'wia';
export type TScanFormat = 'png' | 'jpeg' | 'pdf' | 'tiff';
export type TColorMode = 'color' | 'grayscale' | 'blackwhite';
export type TScanSource = 'flatbed' | 'adf' | 'adf-duplex';
export interface IScanCapabilities {
resolutions: number[];
formats: TScanFormat[];
colorModes: TColorMode[];
sources: TScanSource[];
maxWidth: number; // mm
maxHeight: number; // mm
minWidth: number; // mm
minHeight: number; // mm
}
export interface IScanArea {
x: number; // X offset in mm
y: number; // Y offset in mm
width: number; // Width in mm
height: number; // Height in mm
}
export interface IScanOptions {
resolution?: number;
format?: TScanFormat;
colorMode?: TColorMode;
source?: TScanSource;
area?: IScanArea;
intent?: 'document' | 'photo' | 'preview';
quality?: number; // 1-100 for JPEG
}
export interface IScanResult {
data: Buffer;
format: TScanFormat;
width: number;
height: number;
resolution: number;
colorMode: TColorMode;
mimeType: string;
}
export interface IScanFeatureInfo extends IFeatureInfo {
type: 'scan';
protocol: TScanProtocol;
supportedFormats: TScanFormat[];
supportedResolutions: number[];
supportedColorModes: TColorMode[];
supportedSources: TScanSource[];
hasAdf: boolean;
hasDuplex: boolean;
}
// ============================================================================
// Print Feature
// ============================================================================
export type TPrintProtocol = 'ipp' | 'jetdirect' | 'lpd';
export type TPrintSides = 'one-sided' | 'two-sided-long-edge' | 'two-sided-short-edge';
export type TPrintQuality = 'draft' | 'normal' | 'high';
export type TPrintColorMode = 'color' | 'monochrome';
export interface IPrintCapabilities {
colorSupported: boolean;
duplexSupported: boolean;
mediaSizes: string[];
mediaTypes: string[];
resolutions: number[];
maxCopies: number;
sidesSupported: TPrintSides[];
qualitySupported: TPrintQuality[];
}
export interface IPrintOptions {
copies?: number;
mediaSize?: string;
mediaType?: string;
sides?: TPrintSides;
quality?: TPrintQuality;
colorMode?: TPrintColorMode;
jobName?: string;
}
export interface IPrintJob {
id: number;
name: string;
state: 'pending' | 'processing' | 'completed' | 'canceled' | 'aborted';
stateReason?: string;
createdAt: Date;
completedAt?: Date;
pagesPrinted?: number;
pagesTotal?: number;
}
export interface IPrintFeatureInfo extends IFeatureInfo {
type: 'print';
protocol: TPrintProtocol;
supportsColor: boolean;
supportsDuplex: boolean;
supportedMediaSizes: string[];
}
// ============================================================================
// Playback Feature
// ============================================================================
export type TPlaybackProtocol = 'sonos' | 'airplay' | 'chromecast' | 'dlna';
export type TPlaybackState = 'playing' | 'paused' | 'stopped' | 'buffering' | 'unknown';
export interface ITrackInfo {
title?: string;
artist?: string;
album?: string;
albumArtUri?: string;
duration?: number; // seconds
uri?: string;
}
export interface IPlaybackStatus {
state: TPlaybackState;
position: number; // seconds
duration: number; // seconds
track?: ITrackInfo;
}
export interface IPlaybackFeatureInfo extends IFeatureInfo {
type: 'playback';
protocol: TPlaybackProtocol;
supportsQueue: boolean;
supportsSeek: boolean;
}
// ============================================================================
// Volume Feature
// ============================================================================
export interface IVolumeFeatureInfo extends IFeatureInfo {
type: 'volume';
minVolume: number;
maxVolume: number;
volumeStep: number;
supportsMute: boolean;
}
// ============================================================================
// Power Feature (UPS, Smart Plugs)
// ============================================================================
export type TPowerProtocol = 'nut' | 'snmp' | 'smart-plug';
export type TPowerStatus = 'online' | 'onbattery' | 'lowbattery' | 'charging' | 'discharging' | 'bypass' | 'offline' | 'error' | 'unknown';
export interface IBatteryInfo {
charge: number; // 0-100%
runtime: number; // seconds remaining
voltage?: number; // volts
temperature?: number; // celsius
health?: 'good' | 'weak' | 'replace';
}
export interface IPowerInfo {
inputVoltage?: number;
outputVoltage?: number;
inputFrequency?: number;
outputFrequency?: number;
load?: number; // 0-100%
power?: number; // watts
}
export interface IPowerFeatureInfo extends IFeatureInfo {
type: 'power';
protocol: TPowerProtocol;
hasBattery: boolean;
supportsShutdown: boolean;
supportsTest: boolean;
}
// ============================================================================
// SNMP Feature
// ============================================================================
export type TSnmpVersion = 'v1' | 'v2c' | 'v3';
export interface ISnmpVarbind {
oid: string;
type: number;
value: unknown;
}
export interface ISnmpFeatureInfo extends IFeatureInfo {
type: 'snmp';
version: TSnmpVersion;
community?: string; // for v1/v2c
sysDescr?: string;
sysName?: string;
sysLocation?: string;
}
// ============================================================================
// DLNA Render Feature
// ============================================================================
export interface IDlnaTransportInfo {
state: 'STOPPED' | 'PLAYING' | 'PAUSED' | 'TRANSITIONING' | 'NO_MEDIA_PRESENT';
status: string;
speed: string;
}
export interface IDlnaPositionInfo {
track: number;
trackDuration: string;
trackMetaData?: string;
trackUri?: string;
relTime: string;
absTime: string;
}
export interface IDlnaRenderFeatureInfo extends IFeatureInfo {
type: 'dlna-render';
udn: string;
friendlyName: string;
supportsVolume: boolean;
supportedProtocols: string[];
}
// ============================================================================
// DLNA Server Feature
// ============================================================================
export interface IDlnaContentItem {
id: string;
parentId: string;
title: string;
class: string;
restricted: boolean;
uri?: string;
albumArtUri?: string;
duration?: string;
size?: number;
isContainer: boolean;
childCount?: number;
}
export interface IDlnaBrowseResult {
items: IDlnaContentItem[];
numberReturned: number;
totalMatches: number;
updateId: number;
}
export interface IDlnaServeFeatureInfo extends IFeatureInfo {
type: 'dlna-serve';
udn: string;
friendlyName: string;
contentCount?: number;
}
// ============================================================================
// Discovery Types
// ============================================================================
/**
* Feature discovered during network scan or mDNS/SSDP
*/
export interface IDiscoveredFeature {
type: TFeatureType;
protocol: string;
port: number;
metadata: Record<string, unknown>;
}
/**
* Options for creating a feature instance
*/
export interface IFeatureOptions {
retryOptions?: IRetryOptions;
metadata?: Record<string, unknown>;
}