@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,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Camera Feature
|
|
3
|
+
* Provides control for smart cameras (snapshots, streams)
|
|
4
|
+
*/
|
|
5
|
+
import { Feature, type TDeviceReference } from './feature.abstract.js';
|
|
6
|
+
import type { IFeatureOptions } from '../interfaces/feature.interfaces.js';
|
|
7
|
+
import type { TCameraProtocol, ICameraCapabilities, ICameraState, ICameraFeatureInfo, ICameraProtocolClient } from '../interfaces/smarthome.interfaces.js';
|
|
8
|
+
/**
|
|
9
|
+
* Options for creating a CameraFeature
|
|
10
|
+
*/
|
|
11
|
+
export interface ICameraFeatureOptions extends IFeatureOptions {
|
|
12
|
+
/** Protocol type */
|
|
13
|
+
protocol: TCameraProtocol;
|
|
14
|
+
/** Entity ID (for Home Assistant) */
|
|
15
|
+
entityId: string;
|
|
16
|
+
/** Protocol client for the camera */
|
|
17
|
+
protocolClient: ICameraProtocolClient;
|
|
18
|
+
/** Camera capabilities */
|
|
19
|
+
capabilities?: Partial<ICameraCapabilities>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Camera Feature - snapshot and stream access
|
|
23
|
+
*
|
|
24
|
+
* Protocol-agnostic: works with Home Assistant, ONVIF, RTSP, etc.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const camera = device.getFeature<CameraFeature>('camera');
|
|
29
|
+
* if (camera) {
|
|
30
|
+
* const snapshot = await camera.getSnapshot();
|
|
31
|
+
* const streamUrl = await camera.getStreamUrl();
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare class CameraFeature extends Feature {
|
|
36
|
+
readonly type: "camera";
|
|
37
|
+
readonly protocol: TCameraProtocol;
|
|
38
|
+
/** Entity ID (e.g., "camera.front_door") */
|
|
39
|
+
readonly entityId: string;
|
|
40
|
+
/** Capabilities */
|
|
41
|
+
readonly capabilities: ICameraCapabilities;
|
|
42
|
+
/** Current state */
|
|
43
|
+
protected _isRecording: boolean;
|
|
44
|
+
protected _isStreaming: boolean;
|
|
45
|
+
protected _motionDetected: boolean;
|
|
46
|
+
/** Protocol client for the camera */
|
|
47
|
+
private protocolClient;
|
|
48
|
+
constructor(device: TDeviceReference, port: number, options: ICameraFeatureOptions);
|
|
49
|
+
/**
|
|
50
|
+
* Check if recording (cached)
|
|
51
|
+
*/
|
|
52
|
+
get isRecording(): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Check if streaming (cached)
|
|
55
|
+
*/
|
|
56
|
+
get isStreaming(): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Check if motion detected (cached)
|
|
59
|
+
*/
|
|
60
|
+
get motionDetected(): boolean;
|
|
61
|
+
protected doConnect(): Promise<void>;
|
|
62
|
+
protected doDisconnect(): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Get a snapshot image from the camera
|
|
65
|
+
* @returns Buffer containing image data
|
|
66
|
+
*/
|
|
67
|
+
getSnapshot(): Promise<Buffer>;
|
|
68
|
+
/**
|
|
69
|
+
* Get snapshot URL
|
|
70
|
+
* @returns URL for the snapshot image
|
|
71
|
+
*/
|
|
72
|
+
getSnapshotUrl(): Promise<string>;
|
|
73
|
+
/**
|
|
74
|
+
* Get stream URL
|
|
75
|
+
* @returns URL for the video stream
|
|
76
|
+
*/
|
|
77
|
+
getStreamUrl(): Promise<string>;
|
|
78
|
+
/**
|
|
79
|
+
* Get current state as object
|
|
80
|
+
*/
|
|
81
|
+
getState(): ICameraState;
|
|
82
|
+
/**
|
|
83
|
+
* Refresh state from the device
|
|
84
|
+
*/
|
|
85
|
+
refreshState(): Promise<ICameraState>;
|
|
86
|
+
/**
|
|
87
|
+
* Update state from external source
|
|
88
|
+
*/
|
|
89
|
+
updateState(state: ICameraState): void;
|
|
90
|
+
/**
|
|
91
|
+
* Internal state update
|
|
92
|
+
*/
|
|
93
|
+
private updateStateInternal;
|
|
94
|
+
getFeatureInfo(): ICameraFeatureInfo;
|
|
95
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Camera Feature
|
|
3
|
+
* Provides control for smart cameras (snapshots, streams)
|
|
4
|
+
*/
|
|
5
|
+
import { Feature } from './feature.abstract.js';
|
|
6
|
+
/**
|
|
7
|
+
* Camera Feature - snapshot and stream access
|
|
8
|
+
*
|
|
9
|
+
* Protocol-agnostic: works with Home Assistant, ONVIF, RTSP, etc.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const camera = device.getFeature<CameraFeature>('camera');
|
|
14
|
+
* if (camera) {
|
|
15
|
+
* const snapshot = await camera.getSnapshot();
|
|
16
|
+
* const streamUrl = await camera.getStreamUrl();
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export class CameraFeature extends Feature {
|
|
21
|
+
type = 'camera';
|
|
22
|
+
protocol;
|
|
23
|
+
/** Entity ID (e.g., "camera.front_door") */
|
|
24
|
+
entityId;
|
|
25
|
+
/** Capabilities */
|
|
26
|
+
capabilities;
|
|
27
|
+
/** Current state */
|
|
28
|
+
_isRecording = false;
|
|
29
|
+
_isStreaming = false;
|
|
30
|
+
_motionDetected = false;
|
|
31
|
+
/** Protocol client for the camera */
|
|
32
|
+
protocolClient;
|
|
33
|
+
constructor(device, port, options) {
|
|
34
|
+
super(device, port, options);
|
|
35
|
+
this.protocol = options.protocol;
|
|
36
|
+
this.entityId = options.entityId;
|
|
37
|
+
this.protocolClient = options.protocolClient;
|
|
38
|
+
this.capabilities = {
|
|
39
|
+
supportsStream: options.capabilities?.supportsStream ?? true,
|
|
40
|
+
supportsPtz: options.capabilities?.supportsPtz ?? false,
|
|
41
|
+
supportsSnapshot: options.capabilities?.supportsSnapshot ?? true,
|
|
42
|
+
supportsMotionDetection: options.capabilities?.supportsMotionDetection ?? false,
|
|
43
|
+
frontendStreamType: options.capabilities?.frontendStreamType,
|
|
44
|
+
streamUrl: options.capabilities?.streamUrl,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// Properties
|
|
49
|
+
// ============================================================================
|
|
50
|
+
/**
|
|
51
|
+
* Check if recording (cached)
|
|
52
|
+
*/
|
|
53
|
+
get isRecording() {
|
|
54
|
+
return this._isRecording;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Check if streaming (cached)
|
|
58
|
+
*/
|
|
59
|
+
get isStreaming() {
|
|
60
|
+
return this._isStreaming;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Check if motion detected (cached)
|
|
64
|
+
*/
|
|
65
|
+
get motionDetected() {
|
|
66
|
+
return this._motionDetected;
|
|
67
|
+
}
|
|
68
|
+
// ============================================================================
|
|
69
|
+
// Connection
|
|
70
|
+
// ============================================================================
|
|
71
|
+
async doConnect() {
|
|
72
|
+
try {
|
|
73
|
+
const state = await this.protocolClient.getState(this.entityId);
|
|
74
|
+
this.updateStateInternal(state);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// Ignore errors fetching initial state
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async doDisconnect() {
|
|
81
|
+
// Nothing to disconnect
|
|
82
|
+
}
|
|
83
|
+
// ============================================================================
|
|
84
|
+
// Camera Access
|
|
85
|
+
// ============================================================================
|
|
86
|
+
/**
|
|
87
|
+
* Get a snapshot image from the camera
|
|
88
|
+
* @returns Buffer containing image data
|
|
89
|
+
*/
|
|
90
|
+
async getSnapshot() {
|
|
91
|
+
if (!this.capabilities.supportsSnapshot) {
|
|
92
|
+
throw new Error('Camera does not support snapshots');
|
|
93
|
+
}
|
|
94
|
+
return this.protocolClient.getSnapshot(this.entityId);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Get snapshot URL
|
|
98
|
+
* @returns URL for the snapshot image
|
|
99
|
+
*/
|
|
100
|
+
async getSnapshotUrl() {
|
|
101
|
+
if (!this.capabilities.supportsSnapshot) {
|
|
102
|
+
throw new Error('Camera does not support snapshots');
|
|
103
|
+
}
|
|
104
|
+
return this.protocolClient.getSnapshotUrl(this.entityId);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Get stream URL
|
|
108
|
+
* @returns URL for the video stream
|
|
109
|
+
*/
|
|
110
|
+
async getStreamUrl() {
|
|
111
|
+
if (!this.capabilities.supportsStream) {
|
|
112
|
+
throw new Error('Camera does not support streaming');
|
|
113
|
+
}
|
|
114
|
+
return this.protocolClient.getStreamUrl(this.entityId);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Get current state as object
|
|
118
|
+
*/
|
|
119
|
+
getState() {
|
|
120
|
+
return {
|
|
121
|
+
isRecording: this._isRecording,
|
|
122
|
+
isStreaming: this._isStreaming,
|
|
123
|
+
motionDetected: this._motionDetected,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Refresh state from the device
|
|
128
|
+
*/
|
|
129
|
+
async refreshState() {
|
|
130
|
+
const state = await this.protocolClient.getState(this.entityId);
|
|
131
|
+
this.updateStateInternal(state);
|
|
132
|
+
return state;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Update state from external source
|
|
136
|
+
*/
|
|
137
|
+
updateState(state) {
|
|
138
|
+
this.updateStateInternal(state);
|
|
139
|
+
this.emit('state:changed', state);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Internal state update
|
|
143
|
+
*/
|
|
144
|
+
updateStateInternal(state) {
|
|
145
|
+
this._isRecording = state.isRecording;
|
|
146
|
+
this._isStreaming = state.isStreaming;
|
|
147
|
+
this._motionDetected = state.motionDetected;
|
|
148
|
+
}
|
|
149
|
+
// ============================================================================
|
|
150
|
+
// Feature Info
|
|
151
|
+
// ============================================================================
|
|
152
|
+
getFeatureInfo() {
|
|
153
|
+
return {
|
|
154
|
+
...this.getBaseFeatureInfo(),
|
|
155
|
+
type: 'camera',
|
|
156
|
+
protocol: this.protocol,
|
|
157
|
+
capabilities: this.capabilities,
|
|
158
|
+
currentState: this.getState(),
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmVhdHVyZS5jYW1lcmEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9mZWF0dXJlcy9mZWF0dXJlLmNhbWVyYS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFFSCxPQUFPLEVBQUUsT0FBTyxFQUF5QixNQUFNLHVCQUF1QixDQUFDO0FBd0J2RTs7Ozs7Ozs7Ozs7OztHQWFHO0FBQ0gsTUFBTSxPQUFPLGFBQWMsU0FBUSxPQUFPO0lBQ3hCLElBQUksR0FBRyxRQUFpQixDQUFDO0lBQ3pCLFFBQVEsQ0FBa0I7SUFFMUMsNENBQTRDO0lBQzVCLFFBQVEsQ0FBUztJQUVqQyxtQkFBbUI7SUFDSCxZQUFZLENBQXNCO0lBRWxELG9CQUFvQjtJQUNWLFlBQVksR0FBWSxLQUFLLENBQUM7SUFDOUIsWUFBWSxHQUFZLEtBQUssQ0FBQztJQUM5QixlQUFlLEdBQVksS0FBSyxDQUFDO0lBRTNDLHFDQUFxQztJQUM3QixjQUFjLENBQXdCO0lBRTlDLFlBQ0UsTUFBd0IsRUFDeEIsSUFBWSxFQUNaLE9BQThCO1FBRTlCLEtBQUssQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzdCLElBQUksQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQztRQUNqQyxJQUFJLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUM7UUFDakMsSUFBSSxDQUFDLGNBQWMsR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDO1FBRTdDLElBQUksQ0FBQyxZQUFZLEdBQUc7WUFDbEIsY0FBYyxFQUFFLE9BQU8sQ0FBQyxZQUFZLEVBQUUsY0FBYyxJQUFJLElBQUk7WUFDNUQsV0FBVyxFQUFFLE9BQU8sQ0FBQyxZQUFZLEVBQUUsV0FBVyxJQUFJLEtBQUs7WUFDdkQsZ0JBQWdCLEVBQUUsT0FBTyxDQUFDLFlBQVksRUFBRSxnQkFBZ0IsSUFBSSxJQUFJO1lBQ2hFLHVCQUF1QixFQUFFLE9BQU8sQ0FBQyxZ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
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Climate Feature
|
|
3
|
+
* Provides control for thermostats and HVAC systems
|
|
4
|
+
*/
|
|
5
|
+
import { Feature, type TDeviceReference } from './feature.abstract.js';
|
|
6
|
+
import type { IFeatureOptions } from '../interfaces/feature.interfaces.js';
|
|
7
|
+
import type { TClimateProtocol, THvacMode, THvacAction, IClimateCapabilities, IClimateState, IClimateFeatureInfo, IClimateProtocolClient } from '../interfaces/smarthome.interfaces.js';
|
|
8
|
+
/**
|
|
9
|
+
* Options for creating a ClimateFeature
|
|
10
|
+
*/
|
|
11
|
+
export interface IClimateFeatureOptions extends IFeatureOptions {
|
|
12
|
+
/** Protocol type */
|
|
13
|
+
protocol: TClimateProtocol;
|
|
14
|
+
/** Entity ID (for Home Assistant) */
|
|
15
|
+
entityId: string;
|
|
16
|
+
/** Protocol client for controlling the climate device */
|
|
17
|
+
protocolClient: IClimateProtocolClient;
|
|
18
|
+
/** Climate capabilities */
|
|
19
|
+
capabilities?: Partial<IClimateCapabilities>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Climate Feature - thermostat and HVAC control
|
|
23
|
+
*
|
|
24
|
+
* Protocol-agnostic: works with Home Assistant, Nest, Ecobee, MQTT, etc.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const climate = device.getFeature<ClimateFeature>('climate');
|
|
29
|
+
* if (climate) {
|
|
30
|
+
* await climate.setHvacMode('heat');
|
|
31
|
+
* await climate.setTargetTemp(21);
|
|
32
|
+
* console.log(`Current: ${climate.currentTemp}°C, Target: ${climate.targetTemp}°C`);
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare class ClimateFeature extends Feature {
|
|
37
|
+
readonly type: "climate";
|
|
38
|
+
readonly protocol: TClimateProtocol;
|
|
39
|
+
/** Entity ID (e.g., "climate.living_room") */
|
|
40
|
+
readonly entityId: string;
|
|
41
|
+
/** Capabilities */
|
|
42
|
+
readonly capabilities: IClimateCapabilities;
|
|
43
|
+
/** Current state */
|
|
44
|
+
protected _currentTemp?: number;
|
|
45
|
+
protected _targetTemp?: number;
|
|
46
|
+
protected _targetTempHigh?: number;
|
|
47
|
+
protected _targetTempLow?: number;
|
|
48
|
+
protected _hvacMode: THvacMode;
|
|
49
|
+
protected _hvacAction?: THvacAction;
|
|
50
|
+
protected _presetMode?: string;
|
|
51
|
+
protected _fanMode?: string;
|
|
52
|
+
protected _swingMode?: string;
|
|
53
|
+
protected _humidity?: number;
|
|
54
|
+
protected _targetHumidity?: number;
|
|
55
|
+
protected _auxHeat?: boolean;
|
|
56
|
+
/** Protocol client for controlling the climate device */
|
|
57
|
+
private protocolClient;
|
|
58
|
+
constructor(device: TDeviceReference, port: number, options: IClimateFeatureOptions);
|
|
59
|
+
/**
|
|
60
|
+
* Get current temperature (cached)
|
|
61
|
+
*/
|
|
62
|
+
get currentTemp(): number | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* Get target temperature (cached)
|
|
65
|
+
*/
|
|
66
|
+
get targetTemp(): number | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Get target temperature high (for heat_cool mode, cached)
|
|
69
|
+
*/
|
|
70
|
+
get targetTempHigh(): number | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* Get target temperature low (for heat_cool mode, cached)
|
|
73
|
+
*/
|
|
74
|
+
get targetTempLow(): number | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* Get current HVAC mode (cached)
|
|
77
|
+
*/
|
|
78
|
+
get hvacMode(): THvacMode;
|
|
79
|
+
/**
|
|
80
|
+
* Get current HVAC action (cached)
|
|
81
|
+
*/
|
|
82
|
+
get hvacAction(): THvacAction | undefined;
|
|
83
|
+
/**
|
|
84
|
+
* Get current preset mode (cached)
|
|
85
|
+
*/
|
|
86
|
+
get presetMode(): string | undefined;
|
|
87
|
+
/**
|
|
88
|
+
* Get current fan mode (cached)
|
|
89
|
+
*/
|
|
90
|
+
get fanMode(): string | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* Get current swing mode (cached)
|
|
93
|
+
*/
|
|
94
|
+
get swingMode(): string | undefined;
|
|
95
|
+
/**
|
|
96
|
+
* Get current humidity (cached)
|
|
97
|
+
*/
|
|
98
|
+
get humidity(): number | undefined;
|
|
99
|
+
/**
|
|
100
|
+
* Get target humidity (cached)
|
|
101
|
+
*/
|
|
102
|
+
get targetHumidity(): number | undefined;
|
|
103
|
+
/**
|
|
104
|
+
* Get aux heat state (cached)
|
|
105
|
+
*/
|
|
106
|
+
get auxHeat(): boolean | undefined;
|
|
107
|
+
/**
|
|
108
|
+
* Get available HVAC modes
|
|
109
|
+
*/
|
|
110
|
+
get hvacModes(): THvacMode[];
|
|
111
|
+
/**
|
|
112
|
+
* Get available preset modes
|
|
113
|
+
*/
|
|
114
|
+
get presetModes(): string[] | undefined;
|
|
115
|
+
/**
|
|
116
|
+
* Get available fan modes
|
|
117
|
+
*/
|
|
118
|
+
get fanModes(): string[] | undefined;
|
|
119
|
+
protected doConnect(): Promise<void>;
|
|
120
|
+
protected doDisconnect(): Promise<void>;
|
|
121
|
+
/**
|
|
122
|
+
* Set HVAC mode
|
|
123
|
+
* @param mode HVAC mode (off, heat, cool, etc.)
|
|
124
|
+
*/
|
|
125
|
+
setHvacMode(mode: THvacMode): Promise<void>;
|
|
126
|
+
/**
|
|
127
|
+
* Set target temperature
|
|
128
|
+
* @param temp Target temperature
|
|
129
|
+
*/
|
|
130
|
+
setTargetTemp(temp: number): Promise<void>;
|
|
131
|
+
/**
|
|
132
|
+
* Set target temperature range (for heat_cool mode)
|
|
133
|
+
* @param low Low temperature
|
|
134
|
+
* @param high High temperature
|
|
135
|
+
*/
|
|
136
|
+
setTargetTempRange(low: number, high: number): Promise<void>;
|
|
137
|
+
/**
|
|
138
|
+
* Set preset mode
|
|
139
|
+
* @param preset Preset mode name
|
|
140
|
+
*/
|
|
141
|
+
setPresetMode(preset: string): Promise<void>;
|
|
142
|
+
/**
|
|
143
|
+
* Set fan mode
|
|
144
|
+
* @param mode Fan mode name
|
|
145
|
+
*/
|
|
146
|
+
setFanMode(mode: string): Promise<void>;
|
|
147
|
+
/**
|
|
148
|
+
* Set swing mode
|
|
149
|
+
* @param mode Swing mode name
|
|
150
|
+
*/
|
|
151
|
+
setSwingMode(mode: string): Promise<void>;
|
|
152
|
+
/**
|
|
153
|
+
* Set aux heat
|
|
154
|
+
* @param enabled Whether aux heat is enabled
|
|
155
|
+
*/
|
|
156
|
+
setAuxHeat(enabled: boolean): Promise<void>;
|
|
157
|
+
/**
|
|
158
|
+
* Get current state as object
|
|
159
|
+
*/
|
|
160
|
+
getState(): IClimateState;
|
|
161
|
+
/**
|
|
162
|
+
* Refresh state from the device
|
|
163
|
+
*/
|
|
164
|
+
refreshState(): Promise<IClimateState>;
|
|
165
|
+
/**
|
|
166
|
+
* Update state from external source
|
|
167
|
+
*/
|
|
168
|
+
updateState(state: IClimateState): void;
|
|
169
|
+
/**
|
|
170
|
+
* Internal state update
|
|
171
|
+
*/
|
|
172
|
+
private updateStateInternal;
|
|
173
|
+
getFeatureInfo(): IClimateFeatureInfo;
|
|
174
|
+
}
|