@ecobridge.xyz/devicemanager 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitea/workflows/default_nottags.yaml +66 -0
- package/.gitea/workflows/default_tags.yaml +124 -0
- package/.vscode/launch.json +11 -0
- package/.vscode/settings.json +26 -0
- package/changelog.md +91 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/device/device.classes.device.d.ts +205 -0
- package/dist_ts/device/device.classes.device.js +344 -0
- package/dist_ts/devicemanager.classes.devicemanager.d.ts +210 -0
- package/dist_ts/devicemanager.classes.devicemanager.js +835 -0
- package/dist_ts/discovery/discovery.classes.homeassistant.d.ts +101 -0
- package/dist_ts/discovery/discovery.classes.homeassistant.js +313 -0
- package/dist_ts/discovery/discovery.classes.mdns.d.ts +90 -0
- package/dist_ts/discovery/discovery.classes.mdns.js +291 -0
- package/dist_ts/discovery/discovery.classes.networkscanner.d.ts +64 -0
- package/dist_ts/discovery/discovery.classes.networkscanner.js +535 -0
- package/dist_ts/discovery/discovery.classes.ssdp.d.ts +112 -0
- package/dist_ts/discovery/discovery.classes.ssdp.js +255 -0
- package/dist_ts/factories/index.d.ts +190 -0
- package/dist_ts/factories/index.js +350 -0
- package/dist_ts/features/feature.abstract.d.ts +118 -0
- package/dist_ts/features/feature.abstract.js +172 -0
- package/dist_ts/features/feature.camera.d.ts +95 -0
- package/dist_ts/features/feature.camera.js +162 -0
- package/dist_ts/features/feature.climate.d.ts +174 -0
- package/dist_ts/features/feature.climate.js +328 -0
- package/dist_ts/features/feature.cover.d.ts +121 -0
- package/dist_ts/features/feature.cover.js +217 -0
- package/dist_ts/features/feature.fan.d.ts +127 -0
- package/dist_ts/features/feature.fan.js +235 -0
- package/dist_ts/features/feature.light.d.ts +156 -0
- package/dist_ts/features/feature.light.js +296 -0
- package/dist_ts/features/feature.lock.d.ts +103 -0
- package/dist_ts/features/feature.lock.js +170 -0
- package/dist_ts/features/feature.playback.d.ts +98 -0
- package/dist_ts/features/feature.playback.js +191 -0
- package/dist_ts/features/feature.power.d.ts +79 -0
- package/dist_ts/features/feature.power.js +173 -0
- package/dist_ts/features/feature.print.d.ts +78 -0
- package/dist_ts/features/feature.print.js +226 -0
- package/dist_ts/features/feature.scan.d.ts +79 -0
- package/dist_ts/features/feature.scan.js +315 -0
- package/dist_ts/features/feature.sensor.d.ts +95 -0
- package/dist_ts/features/feature.sensor.js +147 -0
- package/dist_ts/features/feature.snmp.d.ts +88 -0
- package/dist_ts/features/feature.snmp.js +175 -0
- package/dist_ts/features/feature.switch.d.ts +75 -0
- package/dist_ts/features/feature.switch.js +126 -0
- package/dist_ts/features/feature.volume.d.ts +104 -0
- package/dist_ts/features/feature.volume.js +186 -0
- package/dist_ts/features/index.d.ts +19 -0
- package/dist_ts/features/index.js +23 -0
- package/dist_ts/helpers/helpers.iprange.d.ts +35 -0
- package/dist_ts/helpers/helpers.iprange.js +151 -0
- package/dist_ts/helpers/helpers.retry.d.ts +25 -0
- package/dist_ts/helpers/helpers.retry.js +69 -0
- package/dist_ts/index.d.ts +15 -0
- package/dist_ts/index.js +40 -0
- package/dist_ts/interfaces/feature.interfaces.d.ts +255 -0
- package/dist_ts/interfaces/feature.interfaces.js +6 -0
- package/dist_ts/interfaces/homeassistant.interfaces.d.ts +550 -0
- package/dist_ts/interfaces/homeassistant.interfaces.js +111 -0
- package/dist_ts/interfaces/index.d.ts +330 -0
- package/dist_ts/interfaces/index.js +16 -0
- package/dist_ts/interfaces/smarthome.interfaces.d.ts +282 -0
- package/dist_ts/interfaces/smarthome.interfaces.js +7 -0
- package/dist_ts/paths.d.ts +1 -0
- package/dist_ts/paths.js +3 -0
- package/dist_ts/plugins.d.ts +23 -0
- package/dist_ts/plugins.js +30 -0
- package/dist_ts/protocols/index.d.ts +12 -0
- package/dist_ts/protocols/index.js +21 -0
- package/dist_ts/protocols/protocol.escl.d.ts +58 -0
- package/dist_ts/protocols/protocol.escl.js +364 -0
- package/dist_ts/protocols/protocol.homeassistant.d.ts +248 -0
- package/dist_ts/protocols/protocol.homeassistant.js +611 -0
- package/dist_ts/protocols/protocol.ipp.d.ts +45 -0
- package/dist_ts/protocols/protocol.ipp.js +284 -0
- package/dist_ts/protocols/protocol.nut.d.ts +160 -0
- package/dist_ts/protocols/protocol.nut.js +364 -0
- package/dist_ts/protocols/protocol.sane.d.ts +104 -0
- package/dist_ts/protocols/protocol.sane.js +597 -0
- package/dist_ts/protocols/protocol.snmp.d.ts +133 -0
- package/dist_ts/protocols/protocol.snmp.js +333 -0
- package/dist_ts/protocols/protocol.upnp.d.ts +207 -0
- package/dist_ts/protocols/protocol.upnp.js +442 -0
- package/dist_ts/protocols/protocol.upssnmp.d.ts +160 -0
- package/dist_ts/protocols/protocol.upssnmp.js +263 -0
- package/npmextra.json +24 -0
- package/package.json +39 -0
- package/readme.hints.md +115 -0
- package/readme.md +624 -0
- package/test/test.ts +261 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/device/device.classes.device.ts +454 -0
- package/ts/devicemanager.classes.devicemanager.ts +1219 -0
- package/ts/discovery/discovery.classes.homeassistant.ts +376 -0
- package/ts/discovery/discovery.classes.mdns.ts +347 -0
- package/ts/discovery/discovery.classes.networkscanner.ts +648 -0
- package/ts/discovery/discovery.classes.ssdp.ts +357 -0
- package/ts/factories/index.ts +696 -0
- package/ts/features/feature.abstract.ts +251 -0
- package/ts/features/feature.camera.ts +214 -0
- package/ts/features/feature.climate.ts +407 -0
- package/ts/features/feature.cover.ts +278 -0
- package/ts/features/feature.fan.ts +296 -0
- package/ts/features/feature.light.ts +369 -0
- package/ts/features/feature.lock.ts +223 -0
- package/ts/features/feature.playback.ts +246 -0
- package/ts/features/feature.power.ts +231 -0
- package/ts/features/feature.print.ts +297 -0
- package/ts/features/feature.scan.ts +370 -0
- package/ts/features/feature.sensor.ts +202 -0
- package/ts/features/feature.snmp.ts +235 -0
- package/ts/features/feature.switch.ts +170 -0
- package/ts/features/feature.volume.ts +256 -0
- package/ts/features/index.ts +25 -0
- package/ts/helpers/helpers.iprange.ts +172 -0
- package/ts/helpers/helpers.retry.ts +100 -0
- package/ts/index.ts +165 -0
- package/ts/interfaces/feature.interfaces.ts +359 -0
- package/ts/interfaces/homeassistant.interfaces.ts +666 -0
- package/ts/interfaces/index.ts +421 -0
- package/ts/interfaces/smarthome.interfaces.ts +421 -0
- package/ts/paths.ts +5 -0
- package/ts/plugins.ts +41 -0
- package/ts/protocols/index.ts +59 -0
- package/ts/protocols/protocol.escl.ts +439 -0
- package/ts/protocols/protocol.homeassistant.ts +737 -0
- package/ts/protocols/protocol.ipp.ts +329 -0
- package/ts/protocols/protocol.nut.ts +471 -0
- package/ts/protocols/protocol.sane.ts +694 -0
- package/ts/protocols/protocol.snmp.ts +439 -0
- package/ts/protocols/protocol.upnp.ts +627 -0
- package/ts/protocols/protocol.upssnmp.ts +377 -0
- package/tsconfig.json +12 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Playback Feature
|
|
3
|
+
* Provides media playback control capability
|
|
4
|
+
*/
|
|
5
|
+
import { Feature } from './feature.abstract.js';
|
|
6
|
+
/**
|
|
7
|
+
* Playback Feature - provides media playback control
|
|
8
|
+
*
|
|
9
|
+
* Abstract feature that can be backed by different protocols (Sonos, AirPlay, Chromecast, DLNA).
|
|
10
|
+
* Concrete implementations should extend this class for protocol-specific behavior.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const playback = device.getFeature<PlaybackFeature>('playback');
|
|
15
|
+
* if (playback) {
|
|
16
|
+
* await playback.play('spotify:track:123');
|
|
17
|
+
* const status = await playback.getPlaybackStatus();
|
|
18
|
+
* console.log(`Playing: ${status.track?.title}`);
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export class PlaybackFeature extends Feature {
|
|
23
|
+
type = 'playback';
|
|
24
|
+
protocol;
|
|
25
|
+
// Capabilities
|
|
26
|
+
supportsQueue = true;
|
|
27
|
+
supportsSeek = true;
|
|
28
|
+
// Current state
|
|
29
|
+
_playbackState = 'stopped';
|
|
30
|
+
_currentTrack = null;
|
|
31
|
+
_position = 0;
|
|
32
|
+
_duration = 0;
|
|
33
|
+
// Protocol client (set by subclass or passed in options)
|
|
34
|
+
protocolClient = null;
|
|
35
|
+
constructor(device, port, options) {
|
|
36
|
+
super(device, port, options);
|
|
37
|
+
this.protocol = options.protocol;
|
|
38
|
+
if (options.supportsQueue !== undefined)
|
|
39
|
+
this.supportsQueue = options.supportsQueue;
|
|
40
|
+
if (options.supportsSeek !== undefined)
|
|
41
|
+
this.supportsSeek = options.supportsSeek;
|
|
42
|
+
if (options.protocolClient)
|
|
43
|
+
this.protocolClient = options.protocolClient;
|
|
44
|
+
}
|
|
45
|
+
// ============================================================================
|
|
46
|
+
// Properties
|
|
47
|
+
// ============================================================================
|
|
48
|
+
get playbackState() {
|
|
49
|
+
return this._playbackState;
|
|
50
|
+
}
|
|
51
|
+
get currentTrack() {
|
|
52
|
+
return this._currentTrack;
|
|
53
|
+
}
|
|
54
|
+
get position() {
|
|
55
|
+
return this._position;
|
|
56
|
+
}
|
|
57
|
+
get duration() {
|
|
58
|
+
return this._duration;
|
|
59
|
+
}
|
|
60
|
+
get isPlaying() {
|
|
61
|
+
return this._playbackState === 'playing';
|
|
62
|
+
}
|
|
63
|
+
// ============================================================================
|
|
64
|
+
// Connection (to be overridden by protocol-specific subclasses)
|
|
65
|
+
// ============================================================================
|
|
66
|
+
async doConnect() {
|
|
67
|
+
// Base implementation - protocol-specific subclasses should override
|
|
68
|
+
// and establish their protocol connection
|
|
69
|
+
}
|
|
70
|
+
async doDisconnect() {
|
|
71
|
+
// Base implementation - protocol-specific subclasses should override
|
|
72
|
+
this.protocolClient = null;
|
|
73
|
+
}
|
|
74
|
+
// ============================================================================
|
|
75
|
+
// Playback Control
|
|
76
|
+
// ============================================================================
|
|
77
|
+
/**
|
|
78
|
+
* Start playback
|
|
79
|
+
* @param uri Optional URI to play. If not provided, resumes current playback.
|
|
80
|
+
*/
|
|
81
|
+
async play(uri) {
|
|
82
|
+
this.emit('playback:play', { uri });
|
|
83
|
+
// Protocol-specific implementation should be provided by subclass
|
|
84
|
+
this._playbackState = 'playing';
|
|
85
|
+
this.emit('playback:state:changed', this._playbackState);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Pause playback
|
|
89
|
+
*/
|
|
90
|
+
async pause() {
|
|
91
|
+
this.emit('playback:pause');
|
|
92
|
+
this._playbackState = 'paused';
|
|
93
|
+
this.emit('playback:state:changed', this._playbackState);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Stop playback
|
|
97
|
+
*/
|
|
98
|
+
async stop() {
|
|
99
|
+
this.emit('playback:stop');
|
|
100
|
+
this._playbackState = 'stopped';
|
|
101
|
+
this._position = 0;
|
|
102
|
+
this.emit('playback:state:changed', this._playbackState);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Skip to next track
|
|
106
|
+
*/
|
|
107
|
+
async next() {
|
|
108
|
+
this.emit('playback:next');
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Go to previous track
|
|
112
|
+
*/
|
|
113
|
+
async previous() {
|
|
114
|
+
this.emit('playback:previous');
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Seek to position
|
|
118
|
+
* @param seconds Position in seconds
|
|
119
|
+
*/
|
|
120
|
+
async seek(seconds) {
|
|
121
|
+
if (!this.supportsSeek) {
|
|
122
|
+
throw new Error('Seek not supported');
|
|
123
|
+
}
|
|
124
|
+
this._position = seconds;
|
|
125
|
+
this.emit('playback:seek', seconds);
|
|
126
|
+
}
|
|
127
|
+
// ============================================================================
|
|
128
|
+
// Status
|
|
129
|
+
// ============================================================================
|
|
130
|
+
/**
|
|
131
|
+
* Get current track info
|
|
132
|
+
*/
|
|
133
|
+
async getCurrentTrack() {
|
|
134
|
+
return this._currentTrack;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Get playback status
|
|
138
|
+
*/
|
|
139
|
+
async getPlaybackStatus() {
|
|
140
|
+
return {
|
|
141
|
+
state: this._playbackState,
|
|
142
|
+
position: this._position,
|
|
143
|
+
duration: this._duration,
|
|
144
|
+
track: this._currentTrack ?? undefined,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Update track info (called by protocol-specific implementations)
|
|
149
|
+
*/
|
|
150
|
+
updateTrack(track) {
|
|
151
|
+
const oldTrack = this._currentTrack;
|
|
152
|
+
this._currentTrack = track;
|
|
153
|
+
if (track?.title !== oldTrack?.title || track?.uri !== oldTrack?.uri) {
|
|
154
|
+
this.emit('playback:track:changed', track);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Update position (called by protocol-specific implementations)
|
|
159
|
+
*/
|
|
160
|
+
updatePosition(position, duration) {
|
|
161
|
+
this._position = position;
|
|
162
|
+
this._duration = duration;
|
|
163
|
+
this.emit('playback:position:changed', { position, duration });
|
|
164
|
+
}
|
|
165
|
+
// ============================================================================
|
|
166
|
+
// Serialization
|
|
167
|
+
// ============================================================================
|
|
168
|
+
getFeatureInfo() {
|
|
169
|
+
return {
|
|
170
|
+
...this.getBaseFeatureInfo(),
|
|
171
|
+
type: 'playback',
|
|
172
|
+
protocol: this.protocol,
|
|
173
|
+
supportsQueue: this.supportsQueue,
|
|
174
|
+
supportsSeek: this.supportsSeek,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
// ============================================================================
|
|
178
|
+
// Static Factory
|
|
179
|
+
// ============================================================================
|
|
180
|
+
/**
|
|
181
|
+
* Create from discovery metadata
|
|
182
|
+
*/
|
|
183
|
+
static fromDiscovery(device, port, protocol, metadata) {
|
|
184
|
+
return new PlaybackFeature(device, port, {
|
|
185
|
+
protocol,
|
|
186
|
+
supportsQueue: metadata.supportsQueue ?? true,
|
|
187
|
+
supportsSeek: metadata.supportsSeek ?? true,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmVhdHVyZS5wbGF5YmFjay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2ZlYXR1cmVzL2ZlYXR1cmUucGxheWJhY2sudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBRUgsT0FBTyxFQUFFLE9BQU8sRUFBeUIsTUFBTSx1QkFBdUIsQ0FBQztBQXFCdkU7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBQ0gsTUFBTSxPQUFPLGVBQWdCLFNBQVEsT0FBTztJQUMxQixJQUFJLEdBQUcsVUFBbUIsQ0FBQztJQUMzQixRQUFRLENBQW9CO0lBRTVDLGVBQWU7SUFDUixhQUFhLEdBQVksSUFBSSxDQUFDO0lBQzlCLFlBQVksR0FBWSxJQUFJLENBQUM7SUFFcEMsZ0JBQWdCO0lBQ04sY0FBYyxHQUFtQixTQUFTLENBQUM7SUFDM0MsYUFBYSxHQUFzQixJQUFJLENBQUM7SUFDeEMsU0FBUyxHQUFXLENBQUMsQ0FBQztJQUN0QixTQUFTLEdBQVcsQ0FBQyxDQUFDO0lBRWhDLHlEQUF5RDtJQUMvQyxjQUFjLEdBQVksSUFBSSxDQUFDO0lBRXpDLFlBQ0UsTUFBd0IsRUFDeEIsSUFBWSxFQUNaLE9BQWdDO1FBRWhDLEtBQUssQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzdCLElBQUksQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQztRQUNqQyxJQUFJLE9BQU8sQ0FBQyxhQUFhLEtBQUssU0FBUztZQUFFLElBQUksQ0FBQyxhQUFhLEdBQUcsT0FBTyxDQUFDLGFBQWEsQ0FBQztRQUNwRixJQUFJLE9BQU8sQ0FBQyxZQUFZLEtBQUssU0FBUztZQUFFLElBQUksQ0FBQyxZQUFZLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQztRQUNqRixJQUFJLE9BQU8sQ0FBQyxjQUFjO1lBQUUsSUFBSSxDQUFDLGNBQWMsR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDO0lBQzNFLENBQUM7SUFFRCwrRUFBK0U7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
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Power Feature
|
|
3
|
+
* Provides UPS/power monitoring and control capability
|
|
4
|
+
*/
|
|
5
|
+
import { Feature, type TDeviceReference } from './feature.abstract.js';
|
|
6
|
+
import type { TPowerProtocol, TPowerStatus, IBatteryInfo, IPowerInfo, IPowerFeatureInfo, IFeatureOptions } from '../interfaces/feature.interfaces.js';
|
|
7
|
+
/**
|
|
8
|
+
* Options for creating a PowerFeature
|
|
9
|
+
*/
|
|
10
|
+
export interface IPowerFeatureOptions extends IFeatureOptions {
|
|
11
|
+
protocol: TPowerProtocol;
|
|
12
|
+
hasBattery?: boolean;
|
|
13
|
+
supportsShutdown?: boolean;
|
|
14
|
+
supportsTest?: boolean;
|
|
15
|
+
/** For NUT protocol: UPS name */
|
|
16
|
+
upsName?: string;
|
|
17
|
+
/** For SNMP: community string */
|
|
18
|
+
community?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Power Feature - provides UPS/power monitoring and control
|
|
22
|
+
*
|
|
23
|
+
* Supports NUT (Network UPS Tools) and SNMP protocols for monitoring
|
|
24
|
+
* UPS devices and smart power equipment.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const power = device.getFeature<PowerFeature>('power');
|
|
29
|
+
* if (power) {
|
|
30
|
+
* const status = await power.getStatus();
|
|
31
|
+
* const battery = await power.getBatteryInfo();
|
|
32
|
+
* console.log(`Status: ${status}, Battery: ${battery.charge}%`);
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare class PowerFeature extends Feature {
|
|
37
|
+
readonly type: "power";
|
|
38
|
+
readonly protocol: TPowerProtocol;
|
|
39
|
+
readonly upsName: string;
|
|
40
|
+
readonly community: string;
|
|
41
|
+
readonly hasBattery: boolean;
|
|
42
|
+
readonly supportsShutdown: boolean;
|
|
43
|
+
readonly supportsTest: boolean;
|
|
44
|
+
protected _status: TPowerStatus;
|
|
45
|
+
protected _batteryCharge: number;
|
|
46
|
+
protected _batteryRuntime: number;
|
|
47
|
+
protected _load: number;
|
|
48
|
+
constructor(device: TDeviceReference, port: number, options: IPowerFeatureOptions);
|
|
49
|
+
get powerStatus(): TPowerStatus;
|
|
50
|
+
get batteryCharge(): number;
|
|
51
|
+
get batteryRuntime(): number;
|
|
52
|
+
get load(): number;
|
|
53
|
+
protected doConnect(): Promise<void>;
|
|
54
|
+
protected doDisconnect(): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Get current power status
|
|
57
|
+
*/
|
|
58
|
+
getStatus(): Promise<TPowerStatus>;
|
|
59
|
+
/**
|
|
60
|
+
* Get battery information
|
|
61
|
+
*/
|
|
62
|
+
getBatteryInfo(): Promise<IBatteryInfo>;
|
|
63
|
+
/**
|
|
64
|
+
* Get power information
|
|
65
|
+
*/
|
|
66
|
+
getPowerInfo(): Promise<IPowerInfo>;
|
|
67
|
+
/**
|
|
68
|
+
* Initiate shutdown
|
|
69
|
+
*/
|
|
70
|
+
shutdown(delay?: number): Promise<void>;
|
|
71
|
+
/**
|
|
72
|
+
* Start battery test
|
|
73
|
+
*/
|
|
74
|
+
testBattery(): Promise<void>;
|
|
75
|
+
protected updateStatus(status: TPowerStatus): void;
|
|
76
|
+
protected updateBattery(charge: number, runtime: number): void;
|
|
77
|
+
getFeatureInfo(): IPowerFeatureInfo;
|
|
78
|
+
static fromDiscovery(device: TDeviceReference, port: number, protocol: TPowerProtocol, metadata: Record<string, unknown>): PowerFeature;
|
|
79
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Power Feature
|
|
3
|
+
* Provides UPS/power monitoring and control capability
|
|
4
|
+
*/
|
|
5
|
+
import { Feature } from './feature.abstract.js';
|
|
6
|
+
/**
|
|
7
|
+
* Power Feature - provides UPS/power monitoring and control
|
|
8
|
+
*
|
|
9
|
+
* Supports NUT (Network UPS Tools) and SNMP protocols for monitoring
|
|
10
|
+
* UPS devices and smart power equipment.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const power = device.getFeature<PowerFeature>('power');
|
|
15
|
+
* if (power) {
|
|
16
|
+
* const status = await power.getStatus();
|
|
17
|
+
* const battery = await power.getBatteryInfo();
|
|
18
|
+
* console.log(`Status: ${status}, Battery: ${battery.charge}%`);
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export class PowerFeature extends Feature {
|
|
23
|
+
type = 'power';
|
|
24
|
+
protocol;
|
|
25
|
+
// Configuration
|
|
26
|
+
upsName;
|
|
27
|
+
community;
|
|
28
|
+
// Capabilities
|
|
29
|
+
hasBattery;
|
|
30
|
+
supportsShutdown;
|
|
31
|
+
supportsTest;
|
|
32
|
+
// Current state
|
|
33
|
+
_status = 'unknown';
|
|
34
|
+
_batteryCharge = 0;
|
|
35
|
+
_batteryRuntime = 0;
|
|
36
|
+
_load = 0;
|
|
37
|
+
constructor(device, port, options) {
|
|
38
|
+
super(device, port, options);
|
|
39
|
+
this.protocol = options.protocol;
|
|
40
|
+
this.upsName = options.upsName ?? 'ups';
|
|
41
|
+
this.community = options.community ?? 'public';
|
|
42
|
+
this.hasBattery = options.hasBattery ?? true;
|
|
43
|
+
this.supportsShutdown = options.supportsShutdown ?? false;
|
|
44
|
+
this.supportsTest = options.supportsTest ?? false;
|
|
45
|
+
}
|
|
46
|
+
// ============================================================================
|
|
47
|
+
// Properties
|
|
48
|
+
// ============================================================================
|
|
49
|
+
get powerStatus() {
|
|
50
|
+
return this._status;
|
|
51
|
+
}
|
|
52
|
+
get batteryCharge() {
|
|
53
|
+
return this._batteryCharge;
|
|
54
|
+
}
|
|
55
|
+
get batteryRuntime() {
|
|
56
|
+
return this._batteryRuntime;
|
|
57
|
+
}
|
|
58
|
+
get load() {
|
|
59
|
+
return this._load;
|
|
60
|
+
}
|
|
61
|
+
// ============================================================================
|
|
62
|
+
// Connection
|
|
63
|
+
// ============================================================================
|
|
64
|
+
async doConnect() {
|
|
65
|
+
// Protocol-specific connection would be implemented here
|
|
66
|
+
// For now, just verify the port is reachable
|
|
67
|
+
}
|
|
68
|
+
async doDisconnect() {
|
|
69
|
+
// Protocol-specific disconnection
|
|
70
|
+
}
|
|
71
|
+
// ============================================================================
|
|
72
|
+
// Status Monitoring
|
|
73
|
+
// ============================================================================
|
|
74
|
+
/**
|
|
75
|
+
* Get current power status
|
|
76
|
+
*/
|
|
77
|
+
async getStatus() {
|
|
78
|
+
// Protocol-specific implementation would fetch status
|
|
79
|
+
return this._status;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get battery information
|
|
83
|
+
*/
|
|
84
|
+
async getBatteryInfo() {
|
|
85
|
+
return {
|
|
86
|
+
charge: this._batteryCharge,
|
|
87
|
+
runtime: this._batteryRuntime,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Get power information
|
|
92
|
+
*/
|
|
93
|
+
async getPowerInfo() {
|
|
94
|
+
return {
|
|
95
|
+
load: this._load,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
// ============================================================================
|
|
99
|
+
// Control Commands
|
|
100
|
+
// ============================================================================
|
|
101
|
+
/**
|
|
102
|
+
* Initiate shutdown
|
|
103
|
+
*/
|
|
104
|
+
async shutdown(delay) {
|
|
105
|
+
if (!this.supportsShutdown) {
|
|
106
|
+
throw new Error('Shutdown not supported');
|
|
107
|
+
}
|
|
108
|
+
this.emit('power:shutdown', { delay });
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Start battery test
|
|
112
|
+
*/
|
|
113
|
+
async testBattery() {
|
|
114
|
+
if (!this.supportsTest) {
|
|
115
|
+
throw new Error('Battery test not supported');
|
|
116
|
+
}
|
|
117
|
+
this.emit('power:test:started');
|
|
118
|
+
}
|
|
119
|
+
// ============================================================================
|
|
120
|
+
// State Updates
|
|
121
|
+
// ============================================================================
|
|
122
|
+
updateStatus(status) {
|
|
123
|
+
const oldStatus = this._status;
|
|
124
|
+
this._status = status;
|
|
125
|
+
if (oldStatus !== status) {
|
|
126
|
+
this.emit('power:status:changed', { oldStatus, newStatus: status });
|
|
127
|
+
// Emit specific events
|
|
128
|
+
if (status === 'onbattery') {
|
|
129
|
+
this.emit('power:onbattery');
|
|
130
|
+
}
|
|
131
|
+
else if (status === 'online' && oldStatus === 'onbattery') {
|
|
132
|
+
this.emit('power:restored');
|
|
133
|
+
}
|
|
134
|
+
else if (status === 'lowbattery') {
|
|
135
|
+
this.emit('power:lowbattery');
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
updateBattery(charge, runtime) {
|
|
140
|
+
const oldCharge = this._batteryCharge;
|
|
141
|
+
this._batteryCharge = charge;
|
|
142
|
+
this._batteryRuntime = runtime;
|
|
143
|
+
if (oldCharge !== charge) {
|
|
144
|
+
this.emit('battery:changed', { charge, runtime });
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// ============================================================================
|
|
148
|
+
// Serialization
|
|
149
|
+
// ============================================================================
|
|
150
|
+
getFeatureInfo() {
|
|
151
|
+
return {
|
|
152
|
+
...this.getBaseFeatureInfo(),
|
|
153
|
+
type: 'power',
|
|
154
|
+
protocol: this.protocol,
|
|
155
|
+
hasBattery: this.hasBattery,
|
|
156
|
+
supportsShutdown: this.supportsShutdown,
|
|
157
|
+
supportsTest: this.supportsTest,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
// ============================================================================
|
|
161
|
+
// Static Factory
|
|
162
|
+
// ============================================================================
|
|
163
|
+
static fromDiscovery(device, port, protocol, metadata) {
|
|
164
|
+
return new PowerFeature(device, port, {
|
|
165
|
+
protocol,
|
|
166
|
+
upsName: metadata.upsName,
|
|
167
|
+
hasBattery: metadata.hasBattery ?? true,
|
|
168
|
+
supportsShutdown: metadata.supportsShutdown ?? false,
|
|
169
|
+
supportsTest: metadata.supportsTest ?? false,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmVhdHVyZS5wb3dlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2ZlYXR1cmVzL2ZlYXR1cmUucG93ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBRUgsT0FBTyxFQUFFLE9BQU8sRUFBeUIsTUFBTSx1QkFBdUIsQ0FBQztBQXdCdkU7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBQ0gsTUFBTSxPQUFPLFlBQWEsU0FBUSxPQUFPO0lBQ3ZCLElBQUksR0FBRyxPQUFnQixDQUFDO0lBQ3hCLFFBQVEsQ0FBaUI7SUFFekMsZ0JBQWdCO0lBQ0EsT0FBTyxDQUFTO0lBQ2hCLFNBQVMsQ0FBUztJQUVsQyxlQUFlO0lBQ0MsVUFBVSxDQUFVO0lBQ3BCLGdCQUFnQixDQUFVO0lBQzFCLFlBQVksQ0FBVTtJQUV0QyxnQkFBZ0I7SUFDTixPQUFPLEdBQWlCLFNBQVMsQ0FBQztJQUNsQyxjQUFjLEdBQVcsQ0FBQyxDQUFDO0lBQzNCLGVBQWUsR0FBVyxDQUFDLENBQUM7SUFDNUIsS0FBSyxHQUFXLENBQUMsQ0FBQztJQUU1QixZQUNFLE1BQXdCLEVBQ3hCLElBQVksRUFDWixPQUE2QjtRQUU3QixLQUFLLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztRQUM3QixJQUFJLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUM7UUFDakMsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsT0FBTyxJQUFJLEtBQUssQ0FBQztRQUN4QyxJQUFJLENBQUMsU0FBUyxHQUFHLE9BQU8sQ0FBQyxTQUFTLElBQUksUUFBUSxDQUFDO1FBQy9DLElBQUksQ0FBQyxVQUFVLEdBQUcsT0FBTyxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUM7UUFDN0MsSUFBSSxDQUFDLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxnQkFBZ0IsSUFBSSxLQUFLLENBQUM7UUFDMUQsSUFBSSxDQUFDLFlBQVksR0FBRyxPQUFPLENB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
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Print Feature
|
|
3
|
+
* Provides document printing capability using IPP protocol
|
|
4
|
+
*/
|
|
5
|
+
import { Feature, type TDeviceReference } from './feature.abstract.js';
|
|
6
|
+
import type { TPrintProtocol, TPrintSides, TPrintQuality, IPrintCapabilities, IPrintOptions, IPrintJob, IPrintFeatureInfo, IFeatureOptions } from '../interfaces/feature.interfaces.js';
|
|
7
|
+
/**
|
|
8
|
+
* Options for creating a PrintFeature
|
|
9
|
+
*/
|
|
10
|
+
export interface IPrintFeatureOptions extends IFeatureOptions {
|
|
11
|
+
protocol?: TPrintProtocol;
|
|
12
|
+
uri?: string;
|
|
13
|
+
supportsColor?: boolean;
|
|
14
|
+
supportsDuplex?: boolean;
|
|
15
|
+
supportedMediaSizes?: string[];
|
|
16
|
+
supportedMediaTypes?: string[];
|
|
17
|
+
maxCopies?: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Print Feature - provides document printing capability
|
|
21
|
+
*
|
|
22
|
+
* Wraps the IPP protocol to provide a unified printing interface.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const printFeature = device.getFeature<PrintFeature>('print');
|
|
27
|
+
* if (printFeature) {
|
|
28
|
+
* await printFeature.connect();
|
|
29
|
+
* const job = await printFeature.print(pdfBuffer, { copies: 2 });
|
|
30
|
+
* console.log(`Print job ${job.id} created`);
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare class PrintFeature extends Feature {
|
|
35
|
+
readonly type: "print";
|
|
36
|
+
readonly protocol: TPrintProtocol;
|
|
37
|
+
private ippClient;
|
|
38
|
+
readonly uri: string;
|
|
39
|
+
supportsColor: boolean;
|
|
40
|
+
supportsDuplex: boolean;
|
|
41
|
+
supportedMediaSizes: string[];
|
|
42
|
+
supportedMediaTypes: string[];
|
|
43
|
+
maxCopies: number;
|
|
44
|
+
supportedSides: TPrintSides[];
|
|
45
|
+
supportedQualities: TPrintQuality[];
|
|
46
|
+
constructor(device: TDeviceReference, port: number, options?: IPrintFeatureOptions);
|
|
47
|
+
protected doConnect(): Promise<void>;
|
|
48
|
+
protected doDisconnect(): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Get printer capabilities
|
|
51
|
+
*/
|
|
52
|
+
getCapabilities(): Promise<IPrintCapabilities>;
|
|
53
|
+
/**
|
|
54
|
+
* Print a document
|
|
55
|
+
*/
|
|
56
|
+
print(data: Buffer, options?: IPrintOptions): Promise<IPrintJob>;
|
|
57
|
+
/**
|
|
58
|
+
* Get active print jobs
|
|
59
|
+
*/
|
|
60
|
+
getJobs(): Promise<IPrintJob[]>;
|
|
61
|
+
/**
|
|
62
|
+
* Get info about a specific job
|
|
63
|
+
*/
|
|
64
|
+
getJobInfo(jobId: number): Promise<IPrintJob>;
|
|
65
|
+
/**
|
|
66
|
+
* Cancel a print job
|
|
67
|
+
*/
|
|
68
|
+
cancelJob(jobId: number): Promise<void>;
|
|
69
|
+
private printWithIpp;
|
|
70
|
+
private updateCapabilitiesFromIpp;
|
|
71
|
+
private qualityToIpp;
|
|
72
|
+
private mapIppJob;
|
|
73
|
+
getFeatureInfo(): IPrintFeatureInfo;
|
|
74
|
+
/**
|
|
75
|
+
* Create from discovery metadata
|
|
76
|
+
*/
|
|
77
|
+
static fromDiscovery(device: TDeviceReference, port: number, protocol: TPrintProtocol, metadata: Record<string, unknown>): PrintFeature;
|
|
78
|
+
}
|