@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.
Files changed (137) hide show
  1. package/.gitea/workflows/default_nottags.yaml +66 -0
  2. package/.gitea/workflows/default_tags.yaml +124 -0
  3. package/.vscode/launch.json +11 -0
  4. package/.vscode/settings.json +26 -0
  5. package/changelog.md +91 -0
  6. package/dist_ts/00_commitinfo_data.d.ts +8 -0
  7. package/dist_ts/00_commitinfo_data.js +9 -0
  8. package/dist_ts/device/device.classes.device.d.ts +205 -0
  9. package/dist_ts/device/device.classes.device.js +344 -0
  10. package/dist_ts/devicemanager.classes.devicemanager.d.ts +210 -0
  11. package/dist_ts/devicemanager.classes.devicemanager.js +835 -0
  12. package/dist_ts/discovery/discovery.classes.homeassistant.d.ts +101 -0
  13. package/dist_ts/discovery/discovery.classes.homeassistant.js +313 -0
  14. package/dist_ts/discovery/discovery.classes.mdns.d.ts +90 -0
  15. package/dist_ts/discovery/discovery.classes.mdns.js +291 -0
  16. package/dist_ts/discovery/discovery.classes.networkscanner.d.ts +64 -0
  17. package/dist_ts/discovery/discovery.classes.networkscanner.js +535 -0
  18. package/dist_ts/discovery/discovery.classes.ssdp.d.ts +112 -0
  19. package/dist_ts/discovery/discovery.classes.ssdp.js +255 -0
  20. package/dist_ts/factories/index.d.ts +190 -0
  21. package/dist_ts/factories/index.js +350 -0
  22. package/dist_ts/features/feature.abstract.d.ts +118 -0
  23. package/dist_ts/features/feature.abstract.js +172 -0
  24. package/dist_ts/features/feature.camera.d.ts +95 -0
  25. package/dist_ts/features/feature.camera.js +162 -0
  26. package/dist_ts/features/feature.climate.d.ts +174 -0
  27. package/dist_ts/features/feature.climate.js +328 -0
  28. package/dist_ts/features/feature.cover.d.ts +121 -0
  29. package/dist_ts/features/feature.cover.js +217 -0
  30. package/dist_ts/features/feature.fan.d.ts +127 -0
  31. package/dist_ts/features/feature.fan.js +235 -0
  32. package/dist_ts/features/feature.light.d.ts +156 -0
  33. package/dist_ts/features/feature.light.js +296 -0
  34. package/dist_ts/features/feature.lock.d.ts +103 -0
  35. package/dist_ts/features/feature.lock.js +170 -0
  36. package/dist_ts/features/feature.playback.d.ts +98 -0
  37. package/dist_ts/features/feature.playback.js +191 -0
  38. package/dist_ts/features/feature.power.d.ts +79 -0
  39. package/dist_ts/features/feature.power.js +173 -0
  40. package/dist_ts/features/feature.print.d.ts +78 -0
  41. package/dist_ts/features/feature.print.js +226 -0
  42. package/dist_ts/features/feature.scan.d.ts +79 -0
  43. package/dist_ts/features/feature.scan.js +315 -0
  44. package/dist_ts/features/feature.sensor.d.ts +95 -0
  45. package/dist_ts/features/feature.sensor.js +147 -0
  46. package/dist_ts/features/feature.snmp.d.ts +88 -0
  47. package/dist_ts/features/feature.snmp.js +175 -0
  48. package/dist_ts/features/feature.switch.d.ts +75 -0
  49. package/dist_ts/features/feature.switch.js +126 -0
  50. package/dist_ts/features/feature.volume.d.ts +104 -0
  51. package/dist_ts/features/feature.volume.js +186 -0
  52. package/dist_ts/features/index.d.ts +19 -0
  53. package/dist_ts/features/index.js +23 -0
  54. package/dist_ts/helpers/helpers.iprange.d.ts +35 -0
  55. package/dist_ts/helpers/helpers.iprange.js +151 -0
  56. package/dist_ts/helpers/helpers.retry.d.ts +25 -0
  57. package/dist_ts/helpers/helpers.retry.js +69 -0
  58. package/dist_ts/index.d.ts +15 -0
  59. package/dist_ts/index.js +40 -0
  60. package/dist_ts/interfaces/feature.interfaces.d.ts +255 -0
  61. package/dist_ts/interfaces/feature.interfaces.js +6 -0
  62. package/dist_ts/interfaces/homeassistant.interfaces.d.ts +550 -0
  63. package/dist_ts/interfaces/homeassistant.interfaces.js +111 -0
  64. package/dist_ts/interfaces/index.d.ts +330 -0
  65. package/dist_ts/interfaces/index.js +16 -0
  66. package/dist_ts/interfaces/smarthome.interfaces.d.ts +282 -0
  67. package/dist_ts/interfaces/smarthome.interfaces.js +7 -0
  68. package/dist_ts/paths.d.ts +1 -0
  69. package/dist_ts/paths.js +3 -0
  70. package/dist_ts/plugins.d.ts +23 -0
  71. package/dist_ts/plugins.js +30 -0
  72. package/dist_ts/protocols/index.d.ts +12 -0
  73. package/dist_ts/protocols/index.js +21 -0
  74. package/dist_ts/protocols/protocol.escl.d.ts +58 -0
  75. package/dist_ts/protocols/protocol.escl.js +364 -0
  76. package/dist_ts/protocols/protocol.homeassistant.d.ts +248 -0
  77. package/dist_ts/protocols/protocol.homeassistant.js +611 -0
  78. package/dist_ts/protocols/protocol.ipp.d.ts +45 -0
  79. package/dist_ts/protocols/protocol.ipp.js +284 -0
  80. package/dist_ts/protocols/protocol.nut.d.ts +160 -0
  81. package/dist_ts/protocols/protocol.nut.js +364 -0
  82. package/dist_ts/protocols/protocol.sane.d.ts +104 -0
  83. package/dist_ts/protocols/protocol.sane.js +597 -0
  84. package/dist_ts/protocols/protocol.snmp.d.ts +133 -0
  85. package/dist_ts/protocols/protocol.snmp.js +333 -0
  86. package/dist_ts/protocols/protocol.upnp.d.ts +207 -0
  87. package/dist_ts/protocols/protocol.upnp.js +442 -0
  88. package/dist_ts/protocols/protocol.upssnmp.d.ts +160 -0
  89. package/dist_ts/protocols/protocol.upssnmp.js +263 -0
  90. package/npmextra.json +24 -0
  91. package/package.json +39 -0
  92. package/readme.hints.md +115 -0
  93. package/readme.md +624 -0
  94. package/test/test.ts +261 -0
  95. package/ts/00_commitinfo_data.ts +8 -0
  96. package/ts/device/device.classes.device.ts +454 -0
  97. package/ts/devicemanager.classes.devicemanager.ts +1219 -0
  98. package/ts/discovery/discovery.classes.homeassistant.ts +376 -0
  99. package/ts/discovery/discovery.classes.mdns.ts +347 -0
  100. package/ts/discovery/discovery.classes.networkscanner.ts +648 -0
  101. package/ts/discovery/discovery.classes.ssdp.ts +357 -0
  102. package/ts/factories/index.ts +696 -0
  103. package/ts/features/feature.abstract.ts +251 -0
  104. package/ts/features/feature.camera.ts +214 -0
  105. package/ts/features/feature.climate.ts +407 -0
  106. package/ts/features/feature.cover.ts +278 -0
  107. package/ts/features/feature.fan.ts +296 -0
  108. package/ts/features/feature.light.ts +369 -0
  109. package/ts/features/feature.lock.ts +223 -0
  110. package/ts/features/feature.playback.ts +246 -0
  111. package/ts/features/feature.power.ts +231 -0
  112. package/ts/features/feature.print.ts +297 -0
  113. package/ts/features/feature.scan.ts +370 -0
  114. package/ts/features/feature.sensor.ts +202 -0
  115. package/ts/features/feature.snmp.ts +235 -0
  116. package/ts/features/feature.switch.ts +170 -0
  117. package/ts/features/feature.volume.ts +256 -0
  118. package/ts/features/index.ts +25 -0
  119. package/ts/helpers/helpers.iprange.ts +172 -0
  120. package/ts/helpers/helpers.retry.ts +100 -0
  121. package/ts/index.ts +165 -0
  122. package/ts/interfaces/feature.interfaces.ts +359 -0
  123. package/ts/interfaces/homeassistant.interfaces.ts +666 -0
  124. package/ts/interfaces/index.ts +421 -0
  125. package/ts/interfaces/smarthome.interfaces.ts +421 -0
  126. package/ts/paths.ts +5 -0
  127. package/ts/plugins.ts +41 -0
  128. package/ts/protocols/index.ts +59 -0
  129. package/ts/protocols/protocol.escl.ts +439 -0
  130. package/ts/protocols/protocol.homeassistant.ts +737 -0
  131. package/ts/protocols/protocol.ipp.ts +329 -0
  132. package/ts/protocols/protocol.nut.ts +471 -0
  133. package/ts/protocols/protocol.sane.ts +694 -0
  134. package/ts/protocols/protocol.snmp.ts +439 -0
  135. package/ts/protocols/protocol.upnp.ts +627 -0
  136. package/ts/protocols/protocol.upssnmp.ts +377 -0
  137. package/tsconfig.json +12 -0
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Fan Feature
3
+ * Provides control for fans (speed, oscillation, direction)
4
+ */
5
+ import { Feature, type TDeviceReference } from './feature.abstract.js';
6
+ import type { IFeatureOptions } from '../interfaces/feature.interfaces.js';
7
+ import type { TFanProtocol, TFanDirection, IFanCapabilities, IFanState, IFanFeatureInfo, IFanProtocolClient } from '../interfaces/smarthome.interfaces.js';
8
+ /**
9
+ * Options for creating a FanFeature
10
+ */
11
+ export interface IFanFeatureOptions extends IFeatureOptions {
12
+ /** Protocol type */
13
+ protocol: TFanProtocol;
14
+ /** Entity ID (for Home Assistant) */
15
+ entityId: string;
16
+ /** Protocol client for controlling the fan */
17
+ protocolClient: IFanProtocolClient;
18
+ /** Fan capabilities */
19
+ capabilities?: Partial<IFanCapabilities>;
20
+ }
21
+ /**
22
+ * Fan Feature - speed, oscillation, and direction control
23
+ *
24
+ * Protocol-agnostic: works with Home Assistant, MQTT, Bond, etc.
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * const fan = device.getFeature<FanFeature>('fan');
29
+ * if (fan) {
30
+ * await fan.turnOn(75); // 75% speed
31
+ * await fan.setOscillating(true);
32
+ * }
33
+ * ```
34
+ */
35
+ export declare class FanFeature extends Feature {
36
+ readonly type: "fan";
37
+ readonly protocol: TFanProtocol;
38
+ /** Entity ID (e.g., "fan.bedroom") */
39
+ readonly entityId: string;
40
+ /** Capabilities */
41
+ readonly capabilities: IFanCapabilities;
42
+ /** Current state */
43
+ protected _isOn: boolean;
44
+ protected _percentage?: number;
45
+ protected _presetMode?: string;
46
+ protected _oscillating?: boolean;
47
+ protected _direction?: TFanDirection;
48
+ /** Protocol client for controlling the fan */
49
+ private protocolClient;
50
+ constructor(device: TDeviceReference, port: number, options: IFanFeatureOptions);
51
+ /**
52
+ * Get current on/off state (cached)
53
+ */
54
+ get isOn(): boolean;
55
+ /**
56
+ * Get current speed percentage 0-100 (cached)
57
+ */
58
+ get percentage(): number | undefined;
59
+ /**
60
+ * Get current preset mode (cached)
61
+ */
62
+ get presetMode(): string | undefined;
63
+ /**
64
+ * Get oscillating state (cached)
65
+ */
66
+ get oscillating(): boolean | undefined;
67
+ /**
68
+ * Get direction (cached)
69
+ */
70
+ get direction(): TFanDirection | undefined;
71
+ /**
72
+ * Get available preset modes
73
+ */
74
+ get presetModes(): string[] | undefined;
75
+ protected doConnect(): Promise<void>;
76
+ protected doDisconnect(): Promise<void>;
77
+ /**
78
+ * Turn on the fan
79
+ * @param percentage Optional speed percentage
80
+ */
81
+ turnOn(percentage?: number): Promise<void>;
82
+ /**
83
+ * Turn off the fan
84
+ */
85
+ turnOff(): Promise<void>;
86
+ /**
87
+ * Toggle the fan
88
+ */
89
+ toggle(): Promise<void>;
90
+ /**
91
+ * Set speed percentage
92
+ * @param percentage Speed 0-100
93
+ */
94
+ setPercentage(percentage: number): Promise<void>;
95
+ /**
96
+ * Set preset mode
97
+ * @param mode Preset mode name
98
+ */
99
+ setPresetMode(mode: string): Promise<void>;
100
+ /**
101
+ * Set oscillating state
102
+ * @param oscillating Whether to oscillate
103
+ */
104
+ setOscillating(oscillating: boolean): Promise<void>;
105
+ /**
106
+ * Set direction
107
+ * @param direction forward or reverse
108
+ */
109
+ setDirection(direction: TFanDirection): Promise<void>;
110
+ /**
111
+ * Get current state as object
112
+ */
113
+ getState(): IFanState;
114
+ /**
115
+ * Refresh state from the device
116
+ */
117
+ refreshState(): Promise<IFanState>;
118
+ /**
119
+ * Update state from external source
120
+ */
121
+ updateState(state: IFanState): void;
122
+ /**
123
+ * Internal state update
124
+ */
125
+ private updateStateInternal;
126
+ getFeatureInfo(): IFanFeatureInfo;
127
+ }
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Fan Feature
3
+ * Provides control for fans (speed, oscillation, direction)
4
+ */
5
+ import { Feature } from './feature.abstract.js';
6
+ /**
7
+ * Fan Feature - speed, oscillation, and direction control
8
+ *
9
+ * Protocol-agnostic: works with Home Assistant, MQTT, Bond, etc.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const fan = device.getFeature<FanFeature>('fan');
14
+ * if (fan) {
15
+ * await fan.turnOn(75); // 75% speed
16
+ * await fan.setOscillating(true);
17
+ * }
18
+ * ```
19
+ */
20
+ export class FanFeature extends Feature {
21
+ type = 'fan';
22
+ protocol;
23
+ /** Entity ID (e.g., "fan.bedroom") */
24
+ entityId;
25
+ /** Capabilities */
26
+ capabilities;
27
+ /** Current state */
28
+ _isOn = false;
29
+ _percentage;
30
+ _presetMode;
31
+ _oscillating;
32
+ _direction;
33
+ /** Protocol client for controlling the fan */
34
+ protocolClient;
35
+ constructor(device, port, options) {
36
+ super(device, port, options);
37
+ this.protocol = options.protocol;
38
+ this.entityId = options.entityId;
39
+ this.protocolClient = options.protocolClient;
40
+ this.capabilities = {
41
+ supportsSpeed: options.capabilities?.supportsSpeed ?? true,
42
+ supportsOscillate: options.capabilities?.supportsOscillate ?? false,
43
+ supportsDirection: options.capabilities?.supportsDirection ?? false,
44
+ supportsPresetModes: options.capabilities?.supportsPresetModes ?? false,
45
+ presetModes: options.capabilities?.presetModes,
46
+ speedCount: options.capabilities?.speedCount,
47
+ };
48
+ }
49
+ // ============================================================================
50
+ // Properties
51
+ // ============================================================================
52
+ /**
53
+ * Get current on/off state (cached)
54
+ */
55
+ get isOn() {
56
+ return this._isOn;
57
+ }
58
+ /**
59
+ * Get current speed percentage 0-100 (cached)
60
+ */
61
+ get percentage() {
62
+ return this._percentage;
63
+ }
64
+ /**
65
+ * Get current preset mode (cached)
66
+ */
67
+ get presetMode() {
68
+ return this._presetMode;
69
+ }
70
+ /**
71
+ * Get oscillating state (cached)
72
+ */
73
+ get oscillating() {
74
+ return this._oscillating;
75
+ }
76
+ /**
77
+ * Get direction (cached)
78
+ */
79
+ get direction() {
80
+ return this._direction;
81
+ }
82
+ /**
83
+ * Get available preset modes
84
+ */
85
+ get presetModes() {
86
+ return this.capabilities.presetModes;
87
+ }
88
+ // ============================================================================
89
+ // Connection
90
+ // ============================================================================
91
+ async doConnect() {
92
+ try {
93
+ const state = await this.protocolClient.getState(this.entityId);
94
+ this.updateStateInternal(state);
95
+ }
96
+ catch {
97
+ // Ignore errors fetching initial state
98
+ }
99
+ }
100
+ async doDisconnect() {
101
+ // Nothing to disconnect
102
+ }
103
+ // ============================================================================
104
+ // Fan Control
105
+ // ============================================================================
106
+ /**
107
+ * Turn on the fan
108
+ * @param percentage Optional speed percentage
109
+ */
110
+ async turnOn(percentage) {
111
+ await this.protocolClient.turnOn(this.entityId, percentage);
112
+ this._isOn = true;
113
+ if (percentage !== undefined) {
114
+ this._percentage = percentage;
115
+ }
116
+ this.emit('state:changed', this.getState());
117
+ }
118
+ /**
119
+ * Turn off the fan
120
+ */
121
+ async turnOff() {
122
+ await this.protocolClient.turnOff(this.entityId);
123
+ this._isOn = false;
124
+ this.emit('state:changed', this.getState());
125
+ }
126
+ /**
127
+ * Toggle the fan
128
+ */
129
+ async toggle() {
130
+ await this.protocolClient.toggle(this.entityId);
131
+ this._isOn = !this._isOn;
132
+ this.emit('state:changed', this.getState());
133
+ }
134
+ /**
135
+ * Set speed percentage
136
+ * @param percentage Speed 0-100
137
+ */
138
+ async setPercentage(percentage) {
139
+ if (!this.capabilities.supportsSpeed) {
140
+ throw new Error('Fan does not support speed control');
141
+ }
142
+ const clamped = Math.max(0, Math.min(100, Math.round(percentage)));
143
+ await this.protocolClient.setPercentage(this.entityId, clamped);
144
+ this._percentage = clamped;
145
+ this._isOn = clamped > 0;
146
+ this.emit('state:changed', this.getState());
147
+ }
148
+ /**
149
+ * Set preset mode
150
+ * @param mode Preset mode name
151
+ */
152
+ async setPresetMode(mode) {
153
+ if (!this.capabilities.supportsPresetModes) {
154
+ throw new Error('Fan does not support preset modes');
155
+ }
156
+ await this.protocolClient.setPresetMode(this.entityId, mode);
157
+ this._presetMode = mode;
158
+ this._isOn = true;
159
+ this.emit('state:changed', this.getState());
160
+ }
161
+ /**
162
+ * Set oscillating state
163
+ * @param oscillating Whether to oscillate
164
+ */
165
+ async setOscillating(oscillating) {
166
+ if (!this.capabilities.supportsOscillate) {
167
+ throw new Error('Fan does not support oscillation');
168
+ }
169
+ await this.protocolClient.setOscillating(this.entityId, oscillating);
170
+ this._oscillating = oscillating;
171
+ this.emit('state:changed', this.getState());
172
+ }
173
+ /**
174
+ * Set direction
175
+ * @param direction forward or reverse
176
+ */
177
+ async setDirection(direction) {
178
+ if (!this.capabilities.supportsDirection) {
179
+ throw new Error('Fan does not support direction control');
180
+ }
181
+ await this.protocolClient.setDirection(this.entityId, direction);
182
+ this._direction = direction;
183
+ this.emit('state:changed', this.getState());
184
+ }
185
+ /**
186
+ * Get current state as object
187
+ */
188
+ getState() {
189
+ return {
190
+ isOn: this._isOn,
191
+ percentage: this._percentage,
192
+ presetMode: this._presetMode,
193
+ oscillating: this._oscillating,
194
+ direction: this._direction,
195
+ };
196
+ }
197
+ /**
198
+ * Refresh state from the device
199
+ */
200
+ async refreshState() {
201
+ const state = await this.protocolClient.getState(this.entityId);
202
+ this.updateStateInternal(state);
203
+ return state;
204
+ }
205
+ /**
206
+ * Update state from external source
207
+ */
208
+ updateState(state) {
209
+ this.updateStateInternal(state);
210
+ this.emit('state:changed', state);
211
+ }
212
+ /**
213
+ * Internal state update
214
+ */
215
+ updateStateInternal(state) {
216
+ this._isOn = state.isOn;
217
+ this._percentage = state.percentage;
218
+ this._presetMode = state.presetMode;
219
+ this._oscillating = state.oscillating;
220
+ this._direction = state.direction;
221
+ }
222
+ // ============================================================================
223
+ // Feature Info
224
+ // ============================================================================
225
+ getFeatureInfo() {
226
+ return {
227
+ ...this.getBaseFeatureInfo(),
228
+ type: 'fan',
229
+ protocol: this.protocol,
230
+ capabilities: this.capabilities,
231
+ currentState: this.getState(),
232
+ };
233
+ }
234
+ }
235
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmVhdHVyZS5mYW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9mZWF0dXJlcy9mZWF0dXJlLmZhbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFFSCxPQUFPLEVBQUUsT0FBTyxFQUF5QixNQUFNLHVCQUF1QixDQUFDO0FBeUJ2RTs7Ozs7Ozs7Ozs7OztHQWFHO0FBQ0gsTUFBTSxPQUFPLFVBQVcsU0FBUSxPQUFPO0lBQ3JCLElBQUksR0FBRyxLQUFjLENBQUM7SUFDdEIsUUFBUSxDQUFlO0lBRXZDLHNDQUFzQztJQUN0QixRQUFRLENBQVM7SUFFakMsbUJBQW1CO0lBQ0gsWUFBWSxDQUFtQjtJQUUvQyxvQkFBb0I7SUFDVixLQUFLLEdBQVksS0FBSyxDQUFDO0lBQ3ZCLFdBQVcsQ0FBVTtJQUNyQixXQUFXLENBQVU7SUFDckIsWUFBWSxDQUFXO0lBQ3ZCLFVBQVUsQ0FBaUI7SUFFckMsOENBQThDO0lBQ3RDLGNBQWMsQ0FBcUI7SUFFM0MsWUFDRSxNQUF3QixFQUN4QixJQUFZLEVBQ1osT0FBMkI7UUFFM0IsS0FBSyxDQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDN0IsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDO1FBQ2pDLElBQUksQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQztRQUNqQyxJQUFJLENBQUMsY0FBYyxHQUFHLE9BQU8sQ0FBQyxjQUFjLENBQUM7UUFFN0MsSUFBSSxDQUFDLFlBQVksR0FBRztZQUNsQixhQUFhLEVBQUUsT0FBTyxDQUFDLFlBQVksRUFBRSxhQUFhLElBQUksSUFBSTtZQUMxRCxpQkFBaUIsRUFBRSxPQUFPLENBQUMsWUFBWSxFQUFFLGlCQUFpQixJQUFJLEtBQUs7WUFDbkUsaUJBQWlCLEVBQUUsT0FBTyxDQUFDLFlBQVksRUFBRSxpQkFBaUIsSUFBSSxLQUFLO1lBQ25FLG1CQUFtQixFQUFFLE9B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
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Light Feature
3
+ * Provides control for smart lights (brightness, color, effects)
4
+ */
5
+ import { Feature, type TDeviceReference } from './feature.abstract.js';
6
+ import type { IFeatureOptions } from '../interfaces/feature.interfaces.js';
7
+ import type { TLightProtocol, ILightCapabilities, ILightState, ILightFeatureInfo, ILightProtocolClient } from '../interfaces/smarthome.interfaces.js';
8
+ /**
9
+ * Options for creating a LightFeature
10
+ */
11
+ export interface ILightFeatureOptions extends IFeatureOptions {
12
+ /** Protocol type */
13
+ protocol: TLightProtocol;
14
+ /** Entity ID (for Home Assistant) */
15
+ entityId: string;
16
+ /** Protocol client for controlling the light */
17
+ protocolClient: ILightProtocolClient;
18
+ /** Light capabilities */
19
+ capabilities?: Partial<ILightCapabilities>;
20
+ }
21
+ /**
22
+ * Light Feature - brightness, color, and effect control
23
+ *
24
+ * Protocol-agnostic: works with Home Assistant, Hue, MQTT, Zigbee, etc.
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * const light = device.getFeature<LightFeature>('light');
29
+ * if (light) {
30
+ * await light.turnOn({ brightness: 200 });
31
+ * await light.setColorTemp(4000); // 4000K warm white
32
+ * await light.setRgbColor(255, 100, 50);
33
+ * }
34
+ * ```
35
+ */
36
+ export declare class LightFeature extends Feature {
37
+ readonly type: "light";
38
+ readonly protocol: TLightProtocol;
39
+ /** Entity ID (e.g., "light.living_room") */
40
+ readonly entityId: string;
41
+ /** Capabilities */
42
+ readonly capabilities: ILightCapabilities;
43
+ /** Current state */
44
+ protected _isOn: boolean;
45
+ protected _brightness?: number;
46
+ protected _colorTemp?: number;
47
+ protected _colorTempMireds?: number;
48
+ protected _rgbColor?: [number, number, number];
49
+ protected _hsColor?: [number, number];
50
+ protected _xyColor?: [number, number];
51
+ protected _effect?: string;
52
+ /** Protocol client for controlling the light */
53
+ private protocolClient;
54
+ constructor(device: TDeviceReference, port: number, options: ILightFeatureOptions);
55
+ /**
56
+ * Get current on/off state (cached)
57
+ */
58
+ get isOn(): boolean;
59
+ /**
60
+ * Get current brightness 0-255 (cached)
61
+ */
62
+ get brightness(): number | undefined;
63
+ /**
64
+ * Get current color temperature in Kelvin (cached)
65
+ */
66
+ get colorTemp(): number | undefined;
67
+ /**
68
+ * Get current color temperature in Mireds (cached)
69
+ */
70
+ get colorTempMireds(): number | undefined;
71
+ /**
72
+ * Get current RGB color (cached)
73
+ */
74
+ get rgbColor(): [number, number, number] | undefined;
75
+ /**
76
+ * Get current HS color [hue 0-360, saturation 0-100] (cached)
77
+ */
78
+ get hsColor(): [number, number] | undefined;
79
+ /**
80
+ * Get current XY color (cached)
81
+ */
82
+ get xyColor(): [number, number] | undefined;
83
+ /**
84
+ * Get current effect (cached)
85
+ */
86
+ get effect(): string | undefined;
87
+ /**
88
+ * Get available effects
89
+ */
90
+ get effects(): string[] | undefined;
91
+ protected doConnect(): Promise<void>;
92
+ protected doDisconnect(): Promise<void>;
93
+ /**
94
+ * Turn on the light
95
+ * @param options Optional settings to apply when turning on
96
+ */
97
+ turnOn(options?: {
98
+ brightness?: number;
99
+ colorTemp?: number;
100
+ rgb?: [number, number, number];
101
+ transition?: number;
102
+ }): Promise<void>;
103
+ /**
104
+ * Turn off the light
105
+ * @param options Optional transition time
106
+ */
107
+ turnOff(options?: {
108
+ transition?: number;
109
+ }): Promise<void>;
110
+ /**
111
+ * Toggle the light
112
+ */
113
+ toggle(): Promise<void>;
114
+ /**
115
+ * Set brightness level
116
+ * @param brightness Brightness 0-255
117
+ * @param transition Optional transition time in seconds
118
+ */
119
+ setBrightness(brightness: number, transition?: number): Promise<void>;
120
+ /**
121
+ * Set color temperature in Kelvin
122
+ * @param kelvin Color temperature in Kelvin (e.g., 2700 warm, 6500 cool)
123
+ * @param transition Optional transition time in seconds
124
+ */
125
+ setColorTemp(kelvin: number, transition?: number): Promise<void>;
126
+ /**
127
+ * Set RGB color
128
+ * @param r Red 0-255
129
+ * @param g Green 0-255
130
+ * @param b Blue 0-255
131
+ * @param transition Optional transition time in seconds
132
+ */
133
+ setRgbColor(r: number, g: number, b: number, transition?: number): Promise<void>;
134
+ /**
135
+ * Set light effect
136
+ * @param effect Effect name from available effects
137
+ */
138
+ setEffect(effect: string): Promise<void>;
139
+ /**
140
+ * Get current state as object
141
+ */
142
+ getState(): ILightState;
143
+ /**
144
+ * Refresh state from the device
145
+ */
146
+ refreshState(): Promise<ILightState>;
147
+ /**
148
+ * Update state from external source (e.g., state change event)
149
+ */
150
+ updateState(state: ILightState): void;
151
+ /**
152
+ * Internal state update
153
+ */
154
+ private updateStateInternal;
155
+ getFeatureInfo(): ILightFeatureInfo;
156
+ }