tsvesync 1.0.63 → 1.0.65

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.
@@ -0,0 +1,234 @@
1
+ import { VeSyncWarmHumidifier } from './warmHumidifier';
2
+ import { VeSync } from '../vesync';
3
+ import { Helpers } from '../helpers';
4
+ import { logger } from '../logger';
5
+
6
+ /**
7
+ * VeSync Humidifier 200/300S Class
8
+ */
9
+ export class VeSyncHumid200300S extends VeSyncWarmHumidifier {
10
+ protected readonly modes = ['auto', 'manual', 'sleep'] as const;
11
+ protected readonly features = ['humidity', 'mist', 'display', 'timer', 'auto_mode'];
12
+ protected readonly mistLevels = [1, 2, 3, 4, 5, 6, 7, 8, 9];
13
+ protected readonly humidityRange = { min: 30, max: 80 };
14
+
15
+ constructor(details: Record<string, any>, manager: VeSync) {
16
+ super(details, manager);
17
+ logger.debug(`Initialized VeSyncHumid200300S device: ${this.deviceName}`);
18
+ }
19
+
20
+ /**
21
+ * Get device details
22
+ */
23
+ async getDetails(): Promise<Boolean> {
24
+ logger.debug(`Getting details for device: ${this.deviceName}`);
25
+ const [response, status] = await this.callApi(
26
+ '/cloud/v2/deviceManaged/bypassV2',
27
+ 'post',
28
+ {
29
+ ...Helpers.reqBody(this.manager, 'bypassV2'),
30
+ cid: this.cid,
31
+ configModule: this.configModule,
32
+ payload: {
33
+ data: {},
34
+ method: 'getHumidifierStatus',
35
+ source: 'APP'
36
+ }
37
+ },
38
+ Helpers.reqHeaderBypass()
39
+ );
40
+
41
+ const success = this.checkResponse([response, status], 'getDetails');
42
+ if (success && response?.result?.result) {
43
+ const result = response.result.result;
44
+
45
+ // Update device status based on enabled field
46
+ this.deviceStatus = result.enabled ? 'on' : 'off';
47
+
48
+ this.details = {
49
+ mode: result.mode || '',
50
+ humidity: result.humidity || 0, // Current humidity
51
+ target_humidity: result.target_humidity || result.humidity || 0, // Target humidity
52
+ mist_level: result.mist_level || 0,
53
+ mist_virtual_level: result.mist_virtual_level || 0,
54
+ warm_level: result.warm_level || 0,
55
+ water_lacks: result.water_lacks || false,
56
+ humidity_high: result.humidity_high || false,
57
+ water_tank_lifted: result.water_tank_lifted || false,
58
+ display: result.display || false,
59
+ automatic_stop: result.automatic_stop_reach_target || false,
60
+ configuration: result.configuration || {},
61
+ connection_status: result.connection_status || null,
62
+ night_light_brightness: result.night_light_brightness || 0
63
+ };
64
+
65
+ // Log raw response for debugging
66
+ logger.debug(`Raw API Response: ${JSON.stringify(response)}`);
67
+ logger.debug(`Parsed Result: ${JSON.stringify(result)}`);
68
+ logger.debug(`Successfully got details for device: ${this.deviceName}`);
69
+ }
70
+ return success;
71
+ }
72
+
73
+ /**
74
+ * Set mist level
75
+ */
76
+ async setMistLevel(level: number): Promise<boolean> {
77
+ if (!this.mistLevels.includes(level)) {
78
+ const error = `Invalid mist level: ${level}. Must be one of: ${this.mistLevels.join(', ')}`;
79
+ logger.error(`${error} for device: ${this.deviceName}`);
80
+ throw new Error(error);
81
+ }
82
+
83
+ logger.info(`Setting mist level to ${level} for device: ${this.deviceName}`);
84
+ const [response, status] = await this.callApi(
85
+ '/cloud/v2/deviceManaged/bypassV2',
86
+ 'post',
87
+ {
88
+ ...Helpers.reqBody(this.manager, 'bypassV2'),
89
+ cid: this.cid,
90
+ configModule: this.configModule,
91
+ payload: {
92
+ data: {
93
+ id: 0,
94
+ level: level,
95
+ type: 'mist'
96
+ },
97
+ method: 'setVirtualLevel', // Use setVirtualLevel per YAML spec
98
+ source: 'APP'
99
+ }
100
+ },
101
+ Helpers.reqHeaderBypass()
102
+ );
103
+
104
+ const success = this.checkResponse([response, status], 'setMistLevel');
105
+ logger.debug(`Mist Level API Response: ${JSON.stringify(response)}`);
106
+ logger.debug(`Mist Level API Status: ${status}`);
107
+ if (success) {
108
+ this.details.mist_level = level;
109
+ this.details.mist_virtual_level = level;
110
+ // Get latest state and log it
111
+ await this.getDetails();
112
+ logger.debug(`Device state after mist level change: ${JSON.stringify(this.details)}`);
113
+ } else {
114
+ logger.error(`Failed to set mist level to ${level} for device: ${this.deviceName}`);
115
+ }
116
+ return success;
117
+ }
118
+
119
+ /**
120
+ * Set night light brightness
121
+ */
122
+ async setNightLightBrightness(brightness: number): Promise<boolean> {
123
+ if (brightness < 0 || brightness > 100) {
124
+ const error = `Invalid brightness: ${brightness}. Must be between 0 and 100`;
125
+ logger.error(`${error} for device: ${this.deviceName}`);
126
+ throw new Error(error);
127
+ }
128
+
129
+ logger.debug(`Setting night light brightness to ${brightness} for device: ${this.deviceName}`);
130
+ const [response, status] = await this.callApi(
131
+ '/cloud/v2/deviceManaged/bypassV2',
132
+ 'post',
133
+ {
134
+ ...Helpers.reqBody(this.manager, 'bypassV2'),
135
+ cid: this.cid,
136
+ configModule: this.configModule,
137
+ payload: {
138
+ data: {
139
+ brightness
140
+ },
141
+ method: 'setNightLight',
142
+ source: 'APP'
143
+ }
144
+ },
145
+ Helpers.reqHeaderBypass()
146
+ );
147
+
148
+ const success = this.checkResponse([response, status], 'setNightLightBrightness');
149
+ if (success) {
150
+ this.details.night_light_brightness = brightness;
151
+ } else {
152
+ logger.error(`Failed to set night light brightness to ${brightness} for device: ${this.deviceName}`);
153
+ }
154
+ return success;
155
+ }
156
+
157
+ /**
158
+ * Get night light brightness
159
+ */
160
+ get nightLightBrightness(): number {
161
+ return this.details.night_light_brightness || 0;
162
+ }
163
+
164
+ /**
165
+ * Get configuration
166
+ */
167
+ get configuration(): any {
168
+ return this.details.configuration || {};
169
+ }
170
+
171
+ /**
172
+ * Get mist level
173
+ * Override base class to return virtual level
174
+ */
175
+ get mistLevel(): number {
176
+ return this.details.mist_virtual_level || 0;
177
+ }
178
+
179
+ /**
180
+ * Get target humidity
181
+ * Override base class to return target humidity instead of current humidity
182
+ */
183
+ get humidity(): number {
184
+ return this.details.target_humidity || 0;
185
+ }
186
+
187
+ /**
188
+ * Set target humidity
189
+ * Override base class to properly update target humidity
190
+ */
191
+ async setHumidity(humidity: number): Promise<boolean> {
192
+ if (!this.hasFeature('humidity')) {
193
+ const error = 'Humidity control not supported';
194
+ logger.error(`${error} for device: ${this.deviceName}`);
195
+ throw new Error(error);
196
+ }
197
+
198
+ if (humidity < this.humidityRange.min || humidity > this.humidityRange.max) {
199
+ const error = `Invalid humidity: ${humidity}. Must be between ${this.humidityRange.min} and ${this.humidityRange.max}`;
200
+ logger.error(`${error} for device: ${this.deviceName}`);
201
+ throw new Error(error);
202
+ }
203
+
204
+ logger.debug(`Setting target humidity to ${humidity}% for device: ${this.deviceName}`);
205
+ const [response, status] = await this.callApi(
206
+ '/cloud/v2/deviceManaged/bypassV2',
207
+ 'post',
208
+ {
209
+ ...Helpers.reqBody(this.manager, 'bypassV2'),
210
+ cid: this.cid,
211
+ configModule: this.configModule,
212
+ payload: {
213
+ data: {
214
+ target_humidity: humidity
215
+ },
216
+ method: 'setTargetHumidity',
217
+ source: 'APP'
218
+ }
219
+ },
220
+ Helpers.reqHeaderBypass()
221
+ );
222
+
223
+ const success = this.checkResponse([response, status], 'setHumidity');
224
+ if (success) {
225
+ this.details.target_humidity = humidity;
226
+ // Get latest state and log it
227
+ await this.getDetails();
228
+ logger.debug(`Device state after humidity change: ${JSON.stringify(this.details)}`);
229
+ } else {
230
+ logger.error(`Failed to set target humidity to ${humidity}% for device: ${this.deviceName}`);
231
+ }
232
+ return success;
233
+ }
234
+ }
@@ -0,0 +1,470 @@
1
+ import { VeSyncFan } from '../vesyncFan';
2
+ import { VeSync } from '../vesync';
3
+ import { Helpers } from '../helpers';
4
+ import { logger } from '../logger';
5
+
6
+ /**
7
+ * VeSync Humidifier Base Class
8
+ */
9
+ export class VeSyncHumidifier extends VeSyncFan {
10
+ protected readonly modes = ['auto', 'manual', 'sleep'] as const;
11
+ protected readonly mistLevels: number[];
12
+ protected readonly displayModes = ['on', 'off'] as const;
13
+ protected readonly humidityRange = { min: 30, max: 80 };
14
+
15
+ constructor(details: Record<string, any>, manager: VeSync) {
16
+ super(details, manager);
17
+ // Set mist levels based on model
18
+ switch (this.deviceType) {
19
+ case 'Dual200S':
20
+ case 'LUH-D301S-WUSR':
21
+ case 'LUH-D301S-WJP':
22
+ case 'LUH-D301S-WEU':
23
+ this.mistLevels = [1, 2];
24
+ break;
25
+ default:
26
+ // All other models support levels 1-9
27
+ this.mistLevels = [1, 2, 3, 4, 5, 6, 7, 8, 9];
28
+ }
29
+ logger.debug(`Initialized VeSyncHumidifier device: ${this.deviceName}`);
30
+ }
31
+
32
+ /**
33
+ * Get device details
34
+ */
35
+ async getDetails(): Promise<Boolean> {
36
+ logger.debug(`Getting details for device: ${this.deviceName}`);
37
+ const [response, status] = await this.callApi(
38
+ '/cloud/v2/deviceManaged/bypassV2',
39
+ 'post',
40
+ {
41
+ ...Helpers.reqBody(this.manager, 'bypassV2'),
42
+ cid: this.cid,
43
+ configModule: this.configModule,
44
+ payload: {
45
+ data: {},
46
+ method: 'getHumidifierStatus',
47
+ source: 'APP'
48
+ }
49
+ },
50
+ Helpers.reqHeaderBypass()
51
+ );
52
+
53
+ const success = this.checkResponse([response, status], 'getDetails');
54
+ if (success && response?.result?.result) {
55
+ const result = response.result.result;
56
+
57
+ // Handle model-specific status fields
58
+ if (this.deviceType.startsWith('Classic') || this.deviceType === 'Dual200S') {
59
+ this.deviceStatus = result.enabled ? 'on' : 'off';
60
+ } else {
61
+ this.deviceStatus = result.powerSwitch === 1 ? 'on' : 'off';
62
+ }
63
+
64
+ this.details = {
65
+ mode: result.mode || '',
66
+ humidity: result.humidity || 0,
67
+ mist_level: result.level || 0,
68
+ mist_virtual_level: result.virtualLevel || 0,
69
+ warm_level: result.level || 0,
70
+ water_lacks: result.waterLacks || false,
71
+ humidity_high: result.humidityHigh || false,
72
+ water_tank_lifted: result.waterTankLifted || false,
73
+ display: result.display || false,
74
+ automatic_stop: result.automaticStop || false,
75
+ configuration: result.configuration || {},
76
+ connection_status: result.connectionStatus || null
77
+ };
78
+ logger.debug(`Successfully got details for device: ${this.deviceName}`);
79
+ }
80
+ return success;
81
+ }
82
+
83
+ /**
84
+ * Turn device on
85
+ */
86
+ async turnOn(): Promise<boolean> {
87
+ return this.toggleSwitch(true);
88
+ }
89
+
90
+ /**
91
+ * Turn device off
92
+ */
93
+ async turnOff(): Promise<boolean> {
94
+ return this.toggleSwitch(false);
95
+ }
96
+
97
+ /**
98
+ * Toggle device power
99
+ */
100
+ async toggleSwitch(enabled: boolean): Promise<boolean> {
101
+ logger.info(`Setting device power to ${enabled ? 'on' : 'off'}: ${this.deviceName}`);
102
+ const [response, status] = await this.callApi(
103
+ '/cloud/v2/deviceManaged/bypassV2',
104
+ 'post',
105
+ {
106
+ ...Helpers.reqBody(this.manager, 'bypassV2'),
107
+ cid: this.cid,
108
+ configModule: this.configModule,
109
+ payload: {
110
+ data: {
111
+ enabled: enabled,
112
+ id: 0
113
+ },
114
+ method: 'setSwitch',
115
+ source: 'APP'
116
+ }
117
+ },
118
+ Helpers.reqHeaderBypass()
119
+ );
120
+
121
+ const success = this.checkResponse([response, status], 'toggleSwitch');
122
+ if (success) {
123
+ this.deviceStatus = enabled ? 'on' : 'off';
124
+ } else {
125
+ logger.error(`Failed to set device power to ${enabled ? 'on' : 'off'} for device: ${this.deviceName}`);
126
+ }
127
+ return success;
128
+ }
129
+
130
+ /**
131
+ * Set mist level
132
+ */
133
+ async setMistLevel(level: number): Promise<boolean> {
134
+ if (!this.mistLevels.includes(level)) {
135
+ const error = `Invalid mist level: ${level}. Must be one of: ${this.mistLevels.join(', ')}`;
136
+ logger.error(`${error} for device: ${this.deviceName}`);
137
+ throw new Error(error);
138
+ }
139
+
140
+ logger.info(`Setting mist level to ${level} for device: ${this.deviceName}`);
141
+ const [response, status] = await this.callApi(
142
+ '/cloud/v2/deviceManaged/bypassV2',
143
+ 'post',
144
+ {
145
+ ...Helpers.reqBody(this.manager, 'bypassV2'),
146
+ cid: this.cid,
147
+ configModule: this.configModule,
148
+ payload: {
149
+ data: {
150
+ id: 0,
151
+ level: level,
152
+ type: 'mist'
153
+ },
154
+ method: 'setVirtualLevel',
155
+ source: 'APP'
156
+ }
157
+ },
158
+ Helpers.reqHeaderBypass()
159
+ );
160
+
161
+ const success = this.checkResponse([response, status], 'setMistLevel');
162
+ if (!success) {
163
+ logger.error(`Failed to set mist level to ${level} for device: ${this.deviceName}`);
164
+ }
165
+ return success;
166
+ }
167
+
168
+ /**
169
+ * Change fan speed - Implemented to satisfy interface but redirects to setMistLevel
170
+ */
171
+ async changeFanSpeed(speed: number): Promise<boolean> {
172
+ logger.debug(`Redirecting fan speed change to mist level for device: ${this.deviceName}`);
173
+ return this.setMistLevel(speed);
174
+ }
175
+
176
+ /**
177
+ * Set device mode
178
+ */
179
+ async setMode(mode: string): Promise<boolean> {
180
+ if (!this.modes.includes(mode as any)) {
181
+ const error = `Invalid mode: ${mode}. Must be one of: ${this.modes.join(', ')}`;
182
+ logger.error(`${error} for device: ${this.deviceName}`);
183
+ throw new Error(error);
184
+ }
185
+
186
+ logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
187
+ const [response, status] = await this.callApi(
188
+ '/cloud/v2/deviceManaged/bypassV2',
189
+ 'post',
190
+ {
191
+ ...Helpers.reqBody(this.manager, 'bypassV2'),
192
+ cid: this.cid,
193
+ configModule: this.configModule,
194
+ payload: {
195
+ data: {
196
+ mode
197
+ },
198
+ method: 'setHumidityMode',
199
+ source: 'APP'
200
+ }
201
+ },
202
+ Helpers.reqHeaderBypass()
203
+ );
204
+
205
+ const success = this.checkResponse([response, status], 'setMode');
206
+ if (success) {
207
+ this.details.mode = mode;
208
+ } else {
209
+ logger.error(`Failed to set mode to ${mode} for device: ${this.deviceName}`);
210
+ }
211
+ return success;
212
+ }
213
+
214
+ /**
215
+ * Set target humidity
216
+ */
217
+ async setHumidity(humidity: number): Promise<boolean> {
218
+ if (!this.hasFeature('humidity')) {
219
+ const error = 'Humidity control not supported';
220
+ logger.error(`${error} for device: ${this.deviceName}`);
221
+ throw new Error(error);
222
+ }
223
+
224
+ if (humidity < this.humidityRange.min || humidity > this.humidityRange.max) {
225
+ const error = `Invalid humidity: ${humidity}. Must be between ${this.humidityRange.min} and ${this.humidityRange.max}`;
226
+ logger.error(`${error} for device: ${this.deviceName}`);
227
+ throw new Error(error);
228
+ }
229
+
230
+ logger.debug(`Setting target humidity to ${humidity}% for device: ${this.deviceName}`);
231
+ const [response, status] = await this.callApi(
232
+ '/cloud/v2/deviceManaged/bypassV2',
233
+ 'post',
234
+ {
235
+ ...Helpers.reqBody(this.manager, 'bypassV2'),
236
+ cid: this.cid,
237
+ configModule: this.configModule,
238
+ payload: {
239
+ data: {
240
+ target_humidity: humidity
241
+ },
242
+ method: 'setTargetHumidity',
243
+ source: 'APP'
244
+ }
245
+ },
246
+ Helpers.reqHeaderBypass()
247
+ );
248
+
249
+ const success = this.checkResponse([response, status], 'setHumidity');
250
+ if (!success) {
251
+ logger.error(`Failed to set target humidity to ${humidity}% for device: ${this.deviceName}`);
252
+ }
253
+ return success;
254
+ }
255
+
256
+ /**
257
+ * Set display status
258
+ */
259
+ async setDisplay(enabled: boolean): Promise<boolean> {
260
+ if (!this.hasFeature('display')) {
261
+ const error = 'Display control not supported';
262
+ logger.error(`${error} for device: ${this.deviceName}`);
263
+ throw new Error(error);
264
+ }
265
+
266
+ logger.debug(`Setting display to ${enabled ? 'on' : 'off'} for device: ${this.deviceName}`);
267
+ const [response, status] = await this.callApi(
268
+ '/cloud/v2/deviceManaged/bypassV2',
269
+ 'post',
270
+ {
271
+ ...Helpers.reqBody(this.manager, 'bypassV2'),
272
+ cid: this.cid,
273
+ configModule: this.configModule,
274
+ payload: {
275
+ data: {
276
+ state: enabled
277
+ },
278
+ method: 'setDisplay',
279
+ source: 'APP'
280
+ }
281
+ },
282
+ Helpers.reqHeaderBypass()
283
+ );
284
+
285
+ const success = this.checkResponse([response, status], 'setDisplay');
286
+ if (!success) {
287
+ logger.error(`Failed to set display to ${enabled ? 'on' : 'off'} for device: ${this.deviceName}`);
288
+ }
289
+ return success;
290
+ }
291
+
292
+ /**
293
+ * Set timer
294
+ */
295
+ async setTimer(hours: number): Promise<boolean> {
296
+ if (!this.hasFeature('timer')) {
297
+ const error = 'Timer not supported';
298
+ logger.error(`${error} for device: ${this.deviceName}`);
299
+ throw new Error(error);
300
+ }
301
+
302
+ logger.debug(`Setting timer to ${hours} hours for device: ${this.deviceName}`);
303
+ const [response, status] = await this.callApi(
304
+ '/cloud/v2/deviceManaged/bypassV2',
305
+ 'post',
306
+ {
307
+ ...Helpers.reqBody(this.manager, 'bypassV2'),
308
+ cid: this.cid,
309
+ configModule: this.configModule,
310
+ payload: {
311
+ data: {
312
+ action: 'off',
313
+ total: hours * 3600
314
+ },
315
+ method: 'addTimer',
316
+ source: 'APP'
317
+ }
318
+ },
319
+ Helpers.reqHeaderBypass()
320
+ );
321
+
322
+ const success = this.checkResponse([response, status], 'setTimer');
323
+ if (!success) {
324
+ logger.error(`Failed to set timer to ${hours} hours for device: ${this.deviceName}`);
325
+ }
326
+ return success;
327
+ }
328
+
329
+ /**
330
+ * Clear timer
331
+ */
332
+ async clearTimer(): Promise<boolean> {
333
+ if (!this.hasFeature('timer')) {
334
+ const error = 'Timer not supported';
335
+ logger.error(`${error} for device: ${this.deviceName}`);
336
+ throw new Error(error);
337
+ }
338
+
339
+ logger.debug(`Clearing timer for device: ${this.deviceName}`);
340
+ const [response, status] = await this.callApi(
341
+ '/cloud/v2/deviceManaged/bypassV2',
342
+ 'post',
343
+ {
344
+ ...Helpers.reqBody(this.manager, 'bypassV2'),
345
+ cid: this.cid,
346
+ configModule: this.configModule,
347
+ payload: {
348
+ data: {},
349
+ method: 'deleteTimer',
350
+ source: 'APP'
351
+ }
352
+ },
353
+ Helpers.reqHeaderBypass()
354
+ );
355
+
356
+ const success = this.checkResponse([response, status], 'clearTimer');
357
+ if (!success) {
358
+ logger.error(`Failed to clear timer for device: ${this.deviceName}`);
359
+ }
360
+ return success;
361
+ }
362
+
363
+ /**
364
+ * Turn automatic stop on
365
+ */
366
+ async automaticStopOn(): Promise<boolean> {
367
+ logger.debug(`Setting automatic stop on for device: ${this.deviceName}`);
368
+ const [response, status] = await this.callApi(
369
+ '/cloud/v2/deviceManaged/bypassV2',
370
+ 'post',
371
+ {
372
+ ...Helpers.reqBody(this.manager, 'bypassV2'),
373
+ cid: this.cid,
374
+ configModule: this.configModule,
375
+ payload: {
376
+ data: {
377
+ enabled: true
378
+ },
379
+ method: 'setAutomaticStop',
380
+ source: 'APP'
381
+ }
382
+ },
383
+ Helpers.reqHeaderBypass()
384
+ );
385
+
386
+ const success = this.checkResponse([response, status], 'automaticStopOn');
387
+ if (!success) {
388
+ logger.error(`Failed to set automatic stop on for device: ${this.deviceName}`);
389
+ }
390
+ return success;
391
+ }
392
+
393
+ /**
394
+ * Turn automatic stop off
395
+ */
396
+ async automaticStopOff(): Promise<boolean> {
397
+ logger.debug(`Setting automatic stop off for device: ${this.deviceName}`);
398
+ const [response, status] = await this.callApi(
399
+ '/cloud/v2/deviceManaged/bypassV2',
400
+ 'post',
401
+ {
402
+ ...Helpers.reqBody(this.manager, 'bypassV2'),
403
+ cid: this.cid,
404
+ configModule: this.configModule,
405
+ payload: {
406
+ data: {
407
+ enabled: false
408
+ },
409
+ method: 'setAutomaticStop',
410
+ source: 'APP'
411
+ }
412
+ },
413
+ Helpers.reqHeaderBypass()
414
+ );
415
+
416
+ const success = this.checkResponse([response, status], 'automaticStopOff');
417
+ if (!success) {
418
+ logger.error(`Failed to set automatic stop off for device: ${this.deviceName}`);
419
+ }
420
+ return success;
421
+ }
422
+
423
+ /**
424
+ * Set auto mode
425
+ */
426
+ async setAutoMode(): Promise<boolean> {
427
+ logger.debug(`Setting auto mode for device: ${this.deviceName}`);
428
+ const success = await this.setMode('auto');
429
+ if (!success) {
430
+ logger.error(`Failed to set auto mode for device: ${this.deviceName}`);
431
+ }
432
+ return success;
433
+ }
434
+
435
+ /**
436
+ * Set manual mode
437
+ */
438
+ async setManualMode(): Promise<boolean> {
439
+ logger.debug(`Setting manual mode for device: ${this.deviceName}`);
440
+ const success = await this.setMode('manual');
441
+ if (!success) {
442
+ logger.error(`Failed to set manual mode for device: ${this.deviceName}`);
443
+ }
444
+ return success;
445
+ }
446
+
447
+ /**
448
+ * Turn off display
449
+ */
450
+ async turnOffDisplay(): Promise<boolean> {
451
+ logger.debug(`Turning off display for device: ${this.deviceName}`);
452
+ const success = await this.setDisplay(false);
453
+ if (!success) {
454
+ logger.error(`Failed to turn off display for device: ${this.deviceName}`);
455
+ }
456
+ return success;
457
+ }
458
+
459
+ /**
460
+ * Turn on display
461
+ */
462
+ async turnOnDisplay(): Promise<boolean> {
463
+ logger.debug(`Turning on display for device: ${this.deviceName}`);
464
+ const success = await this.setDisplay(true);
465
+ if (!success) {
466
+ logger.error(`Failed to turn on display for device: ${this.deviceName}`);
467
+ }
468
+ return success;
469
+ }
470
+ }