Files
devicemanager/readme.hints.md

4.3 KiB

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

type TFeatureType =
  | 'scan' | 'print' | 'fax' | 'copy'
  | 'playback' | 'volume' | 'power' | 'snmp'
  | 'dlna-render' | 'dlna-serve'
  | 'light' | 'climate' | 'sensor' | 'camera'
  | 'cover' | 'switch' | 'lock' | 'fan';

DeviceManager API

// 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

// Feature access
device.hasFeature('scan');
device.getFeature<ScanFeature>('scan');       // Returns undefined if not found
device.selectFeature<ScanFeature>('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