From 1cc8c48315111b6cbdc3d0b5dacda3e95977e82e Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Mon, 12 Jan 2026 09:13:22 +0000 Subject: [PATCH] fix(release): add npm registries to release config and expand documentation for UniversalDevice architecture and smart-home features --- changelog.md | 7 +++ npmextra.json | 8 ++- readme.hints.md | 107 ++++++++++++++++++++++++++++----------- readme.md | 39 ++++++++++++-- ts/00_commitinfo_data.ts | 2 +- 5 files changed, 127 insertions(+), 36 deletions(-) diff --git a/changelog.md b/changelog.md index d499deb..dc59947 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,12 @@ # Changelog +## 2026-01-12 - 3.0.1 - fix(release) +add npm registries to release config and expand documentation for UniversalDevice architecture and smart-home features + +- npmextra.json: add "registries" to release configuration to publish to both Verdaccio (https://verdaccio.lossless.digital) and the npm registry +- readme.hints.md: rewritten/expanded implementation notes to describe the UniversalDevice architecture, composable features (including smart-home types like light, switch, sensor, climate, cover, lock, fan, camera), protocols, discovery, factories, interfaces, and testing guidance +- readme.md: add factory usage examples including smart-home factory functions, update txtRecords usage (rp) in examples, and small copy/emoji edits + ## 2026-01-10 - 3.0.0 - BREAKING CHANGE(devicemanager) migrate tests to new UniversalDevice/feature-based API, add device factories, SNMP protocol/feature and IP helper utilities diff --git a/npmextra.json b/npmextra.json index ef18d57..1652d2f 100644 --- a/npmextra.json +++ b/npmextra.json @@ -11,10 +11,14 @@ "projectDomain": "ecobridge.xyz" }, "release": { - "accessLevel": "public" + "accessLevel": "public", + "registries": [ + "https://verdaccio.lossless.digital", + "https://registry.npmjs.org" + ] } }, "@ship.zone/szci": { "npmGlobalTools": [] } -} +} \ No newline at end of file diff --git a/readme.hints.md b/readme.hints.md index 5efeb7c..60fed03 100644 --- a/readme.hints.md +++ b/readme.hints.md @@ -2,20 +2,20 @@ ## Architecture Overview -The device manager supports two architectures: +The device manager uses a **UniversalDevice** architecture with composable features. -### Legacy Architecture (Still Supported) -- Separate device classes: `Scanner`, `Printer`, `Speaker`, `SnmpDevice`, `UpsDevice`, `DlnaRenderer`, `DlnaServer` -- Type-specific collections in DeviceManager -- Type-based queries: `getScanners()`, `getPrinters()`, `getSpeakers()` +### Key Concepts -### New Universal Device Architecture -- Single `UniversalDevice` class with composable features -- Features are capabilities that can be attached to any device -- Supports multifunction devices naturally (e.g., printer+scanner) +- **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 @@ -24,43 +24,92 @@ The device manager supports two architectures: - `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 -### Device (`ts/device/`) -- `device.classes.device.ts` - UniversalDevice class with feature management +### 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 -- `index.ts` - Re-exports feature 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'; + | 'dlna-render' | 'dlna-serve' + | 'light' | 'climate' | 'sensor' | 'camera' + | 'cover' | 'switch' | 'lock' | 'fan'; ``` -## DeviceManager Feature API +## DeviceManager API + ```typescript // Query by features -dm.getDevicesWithFeature('scan'); // Devices with scan feature +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 -// Manage universal devices -dm.addUniversalDevice(device); -dm.addFeatureToDevice(deviceId, feature); -dm.removeFeatureFromDevice(deviceId, featureType); +// 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(); ``` -## Protocol Implementations -- `EsclProtocol` - eSCL/AirScan scanner protocol -- `SaneProtocol` - SANE network scanner protocol -- `IppProtocol` - IPP printer protocol -- `SnmpProtocol` - SNMP queries -- `NutProtocol` - Network UPS Tools protocol +## UniversalDevice API -## Type Notes -- `TScanFormat` includes 'tiff' (added for compatibility) -- `IPrinterCapabilities` (from index.ts) has `string[]` for sides/quality -- `IPrintCapabilities` (from feature.interfaces.ts) has typed arrays +```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` diff --git a/readme.md b/readme.md index 500d5ca..bde1759 100644 --- a/readme.md +++ b/readme.md @@ -468,6 +468,8 @@ type TFeatureType = ### Custom Device Creation +Use the factory functions for creating devices with specific features: + ```typescript import { createScanner, createPrinter, createSpeaker } from '@ecobridge.xyz/devicemanager'; @@ -487,8 +489,7 @@ const printer = createPrinter({ name: 'Office Printer', address: '192.168.1.51', port: 631, - ippPath: '/ipp/print', - txtRecords: {}, + txtRecords: { rp: '/ipp/print' }, }); // Create a Sonos speaker @@ -498,7 +499,37 @@ const speaker = createSpeaker({ address: '192.168.1.52', port: 1400, protocol: 'sonos', - txtRecords: {}, +}); +``` + +### Smart Home Factory Functions + +```typescript +import { + createSmartLight, + createSmartSwitch, + createSmartSensor, + createSmartClimate, + createSmartCover, + createSmartLock, + createSmartFan, + createSmartCamera, +} from '@ecobridge.xyz/devicemanager'; + +// Create devices with Home Assistant integration +const light = createSmartLight({ + id: 'living-room-light', + name: 'Living Room Light', + address: 'homeassistant.local', + port: 8123, + entityId: 'light.living_room', + protocol: 'home-assistant', + protocolClient: haClient, // Your HomeAssistantProtocol instance + capabilities: { + supportsBrightness: true, + supportsColorTemp: true, + supportsRgb: true, + }, }); ``` @@ -563,7 +594,7 @@ const maybePrint = device.getFeature('print'); // undefined ## 🙏 Credits -Built with love using: +Built with ❤️ using: - [bonjour-service](https://github.com/onlxltd/bonjour-service) - mDNS discovery - [node-ssdp](https://github.com/diversario/node-ssdp) - SSDP/UPnP discovery - [net-snmp](https://github.com/markabrahams/node-net-snmp) - SNMP protocol diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 1a26208..c90d6a7 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@ecobridge.xyz/devicemanager', - version: '3.0.0', + version: '3.0.1', description: 'a device manager for talking to devices on network and over usb' }