# Device Manager - Implementation Notes ## Architecture Overview The device manager uses a **UniversalDevice** architecture with composable features. ### Key Concepts - **UniversalDevice**: A single device class that can have multiple features attached - **Features**: Composable capabilities (scan, print, playback, volume, power, snmp, smart home, etc.) - **Protocols**: Low-level protocol implementations (eSCL, SANE, IPP, SNMP, NUT, UPnP, Home Assistant) ## Key Files ### Core (`ts/`) - `devicemanager.classes.devicemanager.ts` - Main DeviceManager class with discovery and device registry - `device/device.classes.device.ts` - UniversalDevice class with feature management ### Features (`ts/features/`) - `feature.abstract.ts` - Base Feature class with connection management and retry logic - `feature.scan.ts` - Scanning via eSCL/SANE protocols - `feature.print.ts` - Printing via IPP protocol - `feature.playback.ts` - Media playback (Sonos, AirPlay, Chromecast, DLNA) - `feature.volume.ts` - Volume control (separate from playback) - `feature.power.ts` - UPS/power monitoring via NUT/SNMP - `feature.snmp.ts` - SNMP queries - `feature.light.ts` - Smart light control - `feature.switch.ts` - Smart switch control - `feature.sensor.ts` - Smart sensors - `feature.climate.ts` - Climate/HVAC control - `feature.cover.ts` - Blinds, garage doors - `feature.lock.ts` - Smart locks - `feature.fan.ts` - Fan control - `feature.camera.ts` - Camera control ### Protocols (`ts/protocols/`) - `protocol.escl.ts` - eSCL/AirScan scanner protocol - `protocol.sane.ts` - SANE network scanner protocol - `protocol.ipp.ts` - IPP printer protocol - `protocol.snmp.ts` - SNMP queries - `protocol.nut.ts` - Network UPS Tools protocol - `protocol.upnp.ts` - UPnP/SOAP client - `protocol.upssnmp.ts` - UPS-specific SNMP - `protocol.homeassistant.ts` - Home Assistant WebSocket API ### Discovery (`ts/discovery/`) - `discovery.classes.mdns.ts` - mDNS discovery (Bonjour) - `discovery.classes.ssdp.ts` - SSDP/UPnP discovery - `discovery.classes.networkscanner.ts` - Active network scanning - `discovery.classes.homeassistant.ts` - Home Assistant instance discovery ### Factories (`ts/factories/`) - `index.ts` - Device factory functions for creating pre-configured devices: - `createScanner`, `createPrinter`, `createSpeaker`, `createDlnaRenderer` - `createSnmpDevice`, `createUpsDevice` - Smart home: `createSmartLight`, `createSmartSwitch`, `createSmartSensor`, etc. ### Interfaces (`ts/interfaces/`) - `feature.interfaces.ts` - All feature-related types and interfaces - `smarthome.interfaces.ts` - Smart home specific interfaces - `homeassistant.interfaces.ts` - Home Assistant API types - `index.ts` - Re-exports all interfaces ## Feature Types ```typescript type TFeatureType = | 'scan' | 'print' | 'fax' | 'copy' | 'playback' | 'volume' | 'power' | 'snmp' | 'dlna-render' | 'dlna-serve' | 'light' | 'climate' | 'sensor' | 'camera' | 'cover' | 'switch' | 'lock' | 'fan'; ``` ## DeviceManager API ```typescript // Query by features dm.getDevices(); // All devices dm.getDevices({ hasFeature: 'scan' }); // Devices with scan feature dm.getDevices({ name: 'Brother' }); // Devices matching name dm.getDevicesWithFeatures(['scan', 'print']); // Devices with ALL features dm.getDevicesWithAnyFeature(['playback', 'volume']); // Devices with ANY feature // Select (throws if not found) dm.selectDevice({ address: '192.168.1.100' }); // Discovery dm.discoverScanners('192.168.1.0/24'); dm.discoverPrinters('192.168.1.0/24'); dm.scanNetwork({ ipRange: '...', probeEscl: true, ... }); dm.startDiscovery(); // mDNS/SSDP dm.stopDiscovery(); ``` ## UniversalDevice API ```typescript // Feature access device.hasFeature('scan'); device.getFeature('scan'); // Returns undefined if not found device.selectFeature('scan'); // Throws if not found device.getFeatureTypes(); // ['scan', 'print', ...] // Connection await device.connect(); // Connect all features await device.disconnect(); // Disconnect all features ``` ## Testing Notes - Test files use `@git.zone/tstest` with tap-based assertions - Import `expect` from `@git.zone/tstest/tapbundle` - Tests are in `test/` directory - Run with `pnpm test` or `tstest test/test.some.ts --verbose`