tsvesync 1.3.9 → 1.3.11

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.
@@ -3,6 +3,11 @@
3
3
  */
4
4
  import { VeSyncBaseDevice } from './vesyncBaseDevice';
5
5
  import { VeSync } from './vesync';
6
+ interface RgbValues {
7
+ red: number;
8
+ green: number;
9
+ blue: number;
10
+ }
6
11
  interface BulbConfig {
7
12
  [key: string]: {
8
13
  module: string;
@@ -22,12 +27,11 @@ export declare abstract class VeSyncBulb extends VeSyncBaseDevice {
22
27
  protected colorSaturation: number;
23
28
  protected colorMode: string;
24
29
  protected features: string[];
25
- protected rgbValues: {
26
- red: number;
27
- green: number;
28
- blue: number;
29
- };
30
+ protected rgbValues: RgbValues;
30
31
  constructor(details: Record<string, any>, manager: VeSync);
32
+ hasFeature(feature: string): boolean;
33
+ getColorModel(): string;
34
+ getBrightness(): number;
31
35
  /**
32
36
  * Get bulb details
33
37
  */
@@ -51,7 +55,6 @@ export declare abstract class VeSyncBulb extends VeSyncBaseDevice {
51
55
  /**
52
56
  * Get bulb brightness
53
57
  */
54
- getBrightness(): number;
55
58
  /**
56
59
  * Get color temperature in Kelvin
57
60
  */
@@ -80,9 +83,23 @@ export declare abstract class VeSyncBulb extends VeSyncBaseDevice {
80
83
  green: number;
81
84
  blue: number;
82
85
  };
86
+ /**
87
+ * Set color temperature wrapper to maintain compatibility with consumers
88
+ */
89
+ setColorTemperature(colorTemp: number): Promise<boolean>;
90
+ /**
91
+ * Set color via hue/saturation/value when supported
92
+ */
93
+ setColor(hue: number, saturation: number, value?: number): Promise<boolean>;
94
+ /**
95
+ * Process standard bypass (v1) detail responses shared by multiple bulbs
96
+ */
97
+ protected processStandardBypassDetails(response: any, statusCode: number): boolean;
83
98
  /**
84
99
  * Set color temperature - Abstract method to be implemented by subclasses
85
100
  */
86
101
  abstract setColorTemp(colorTemp: number): Promise<boolean>;
102
+ protected static clamp(value: number, min: number, max: number): number;
103
+ protected static hsvToRgb(h: number, s: number, v: number): RgbValues;
87
104
  }
88
105
  export {};
@@ -50,6 +50,16 @@ class VeSyncBulb extends vesyncBaseDevice_1.VeSyncBaseDevice {
50
50
  blue: 0
51
51
  };
52
52
  }
53
+ hasFeature(feature) {
54
+ return this.features.includes(feature);
55
+ }
56
+ getColorModel() {
57
+ var _a, _b;
58
+ return (_b = (_a = exports.bulbConfig[this.deviceType]) === null || _a === void 0 ? void 0 : _a.colorModel) !== null && _b !== void 0 ? _b : 'none';
59
+ }
60
+ getBrightness() {
61
+ return this.brightness;
62
+ }
53
63
  /**
54
64
  * Get bulb details
55
65
  */
@@ -75,30 +85,7 @@ class VeSyncBulb extends vesyncBaseDevice_1.VeSyncBaseDevice {
75
85
  }
76
86
  };
77
87
  const [response, statusCode] = await this.callApi(endpoint, 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
78
- const success = this.checkResponse([response, statusCode], 'getDetails');
79
- if (success && (response === null || response === void 0 ? void 0 : response.result)) {
80
- this.deviceStatus = response.result.enabled ? 'on' : 'off';
81
- this.brightness = response.result.brightness || this.brightness;
82
- if (this.features.includes('color_temp')) {
83
- this.colorTemp = response.result.colorTemp || this.colorTemp;
84
- }
85
- if (this.features.includes('rgb_shift')) {
86
- if (exports.bulbConfig[this.deviceType].colorModel === 'rgb') {
87
- this.rgbValues = {
88
- red: response.result.red || this.rgbValues.red,
89
- green: response.result.green || this.rgbValues.green,
90
- blue: response.result.blue || this.rgbValues.blue
91
- };
92
- }
93
- else {
94
- this.colorHue = response.result.hue || this.colorHue;
95
- this.colorSaturation = response.result.saturation || this.colorSaturation;
96
- this.colorValue = response.result.value || this.colorValue;
97
- }
98
- }
99
- logger_1.logger.debug(`[${this.deviceName}] Successfully retrieved bulb details`);
100
- }
101
- return success;
88
+ return this.processStandardBypassDetails(response, statusCode);
102
89
  }
103
90
  /**
104
91
  * Update bulb details
@@ -193,7 +180,8 @@ class VeSyncBulb extends vesyncBaseDevice_1.VeSyncBaseDevice {
193
180
  logger_1.logger.error(`[${this.deviceName}] Dimming not supported`);
194
181
  return false;
195
182
  }
196
- logger_1.logger.debug(`[${this.deviceName}] Setting brightness to ${brightness}`);
183
+ const brightnessLevel = VeSyncBulb.clamp(Math.round(brightness), 0, 100);
184
+ logger_1.logger.debug(`[${this.deviceName}] Setting brightness to ${brightnessLevel}`);
197
185
  const isV2Device = this.deviceType === 'XYD0001';
198
186
  const endpoint = isV2Device ? '/cloud/v2/deviceManaged/bypassV2' : '/cloud/v1/deviceManaged/bypass';
199
187
  const body = isV2Device ? {
@@ -202,7 +190,7 @@ class VeSyncBulb extends vesyncBaseDevice_1.VeSyncBaseDevice {
202
190
  configModule: this.configModule,
203
191
  payload: {
204
192
  data: {
205
- brightness: brightness,
193
+ brightness: brightnessLevel,
206
194
  colorMode: '',
207
195
  colorTemp: '',
208
196
  force: 0,
@@ -219,14 +207,14 @@ class VeSyncBulb extends vesyncBaseDevice_1.VeSyncBaseDevice {
219
207
  configModule: this.configModule,
220
208
  jsonCmd: {
221
209
  light: {
222
- brightness: brightness
210
+ brightness: brightnessLevel
223
211
  }
224
212
  }
225
213
  };
226
214
  const [response] = await this.callApi(endpoint, 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
227
215
  if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
228
- this.brightness = brightness;
229
- logger_1.logger.info(`[${this.deviceName}] Successfully set brightness to ${brightness}`);
216
+ this.brightness = brightnessLevel;
217
+ logger_1.logger.info(`[${this.deviceName}] Successfully set brightness to ${brightnessLevel}`);
230
218
  return true;
231
219
  }
232
220
  logger_1.logger.error(`[${this.deviceName}] Failed to set brightness: ${JSON.stringify(response)}`);
@@ -235,9 +223,6 @@ class VeSyncBulb extends vesyncBaseDevice_1.VeSyncBaseDevice {
235
223
  /**
236
224
  * Get bulb brightness
237
225
  */
238
- getBrightness() {
239
- return this.brightness;
240
- }
241
226
  /**
242
227
  * Get color temperature in Kelvin
243
228
  */
@@ -292,5 +277,132 @@ class VeSyncBulb extends vesyncBaseDevice_1.VeSyncBaseDevice {
292
277
  }
293
278
  return this.rgbValues;
294
279
  }
280
+ /**
281
+ * Set color temperature wrapper to maintain compatibility with consumers
282
+ */
283
+ async setColorTemperature(colorTemp) {
284
+ return this.setColorTemp(colorTemp);
285
+ }
286
+ /**
287
+ * Set color via hue/saturation/value when supported
288
+ */
289
+ async setColor(hue, saturation, value = 100) {
290
+ var _a;
291
+ if (!this.features.includes('rgb_shift')) {
292
+ logger_1.logger.error(`[${this.deviceName}] Color control not supported`);
293
+ return false;
294
+ }
295
+ const colorModel = (_a = exports.bulbConfig[this.deviceType]) === null || _a === void 0 ? void 0 : _a.colorModel;
296
+ if (colorModel === 'rgb' && typeof this.setRgb === 'function') {
297
+ const rgb = VeSyncBulb.hsvToRgb(hue, saturation, value);
298
+ return this.setRgb(rgb.red, rgb.green, rgb.blue);
299
+ }
300
+ if (typeof this.setHsv === 'function') {
301
+ return this.setHsv(hue, saturation, value);
302
+ }
303
+ logger_1.logger.error(`[${this.deviceName}] No compatible color handler found`);
304
+ return false;
305
+ }
306
+ /**
307
+ * Process standard bypass (v1) detail responses shared by multiple bulbs
308
+ */
309
+ processStandardBypassDetails(response, statusCode) {
310
+ var _a, _b, _c, _d, _e, _f, _g, _h;
311
+ const success = this.checkResponse([response, statusCode], 'getDetails');
312
+ if (success && (response === null || response === void 0 ? void 0 : response.result)) {
313
+ const innerResult = ((_a = response.result) === null || _a === void 0 ? void 0 : _a.result) || response.result;
314
+ if (innerResult) {
315
+ if (typeof innerResult.enabled === 'boolean') {
316
+ this.deviceStatus = innerResult.enabled ? 'on' : 'off';
317
+ }
318
+ else if (innerResult.action) {
319
+ this.deviceStatus = innerResult.action === 'on' ? 'on' : 'off';
320
+ }
321
+ if (innerResult.connectionStatus) {
322
+ this.connectionStatus = innerResult.connectionStatus;
323
+ }
324
+ if (this.features.includes('dimmable') && innerResult.brightness !== undefined) {
325
+ this.brightness = Number(innerResult.brightness);
326
+ }
327
+ if (this.features.includes('color_temp')) {
328
+ if (innerResult.colorTemp !== undefined) {
329
+ this.colorTemp = Number(innerResult.colorTemp);
330
+ }
331
+ else if (innerResult.colorTempe !== undefined) {
332
+ this.colorTemp = Number(innerResult.colorTempe);
333
+ }
334
+ }
335
+ if (this.features.includes('rgb_shift')) {
336
+ if (((_b = exports.bulbConfig[this.deviceType]) === null || _b === void 0 ? void 0 : _b.colorModel) === 'rgb') {
337
+ this.rgbValues = {
338
+ red: Number((_c = innerResult.red) !== null && _c !== void 0 ? _c : this.rgbValues.red),
339
+ green: Number((_d = innerResult.green) !== null && _d !== void 0 ? _d : this.rgbValues.green),
340
+ blue: Number((_e = innerResult.blue) !== null && _e !== void 0 ? _e : this.rgbValues.blue)
341
+ };
342
+ }
343
+ else {
344
+ this.colorHue = Number((_f = innerResult.hue) !== null && _f !== void 0 ? _f : this.colorHue);
345
+ this.colorSaturation = Number((_g = innerResult.saturation) !== null && _g !== void 0 ? _g : this.colorSaturation);
346
+ this.colorValue = Number((_h = innerResult.value) !== null && _h !== void 0 ? _h : this.colorValue);
347
+ }
348
+ }
349
+ }
350
+ logger_1.logger.debug(`[${this.deviceName}] Successfully retrieved bulb details`);
351
+ }
352
+ return success;
353
+ }
354
+ static clamp(value, min, max) {
355
+ return Math.min(Math.max(value, min), max);
356
+ }
357
+ static hsvToRgb(h, s, v) {
358
+ const saturation = VeSyncBulb.clamp(s, 0, 100) / 100;
359
+ const value = VeSyncBulb.clamp(v, 0, 100) / 100;
360
+ const hue = ((h % 360) + 360) % 360 / 60;
361
+ const i = Math.floor(hue);
362
+ const f = hue - i;
363
+ const p = value * (1 - saturation);
364
+ const q = value * (1 - saturation * f);
365
+ const t = value * (1 - saturation * (1 - f));
366
+ let r = 0;
367
+ let g = 0;
368
+ let b = 0;
369
+ switch (i) {
370
+ case 0:
371
+ r = value;
372
+ g = t;
373
+ b = p;
374
+ break;
375
+ case 1:
376
+ r = q;
377
+ g = value;
378
+ b = p;
379
+ break;
380
+ case 2:
381
+ r = p;
382
+ g = value;
383
+ b = t;
384
+ break;
385
+ case 3:
386
+ r = p;
387
+ g = q;
388
+ b = value;
389
+ break;
390
+ case 4:
391
+ r = t;
392
+ g = p;
393
+ b = value;
394
+ break;
395
+ default:
396
+ r = value;
397
+ g = p;
398
+ b = q;
399
+ break;
400
+ }
401
+ return {
402
+ red: Math.round(r * 255),
403
+ green: Math.round(g * 255),
404
+ blue: Math.round(b * 255)
405
+ };
406
+ }
295
407
  }
296
408
  exports.VeSyncBulb = VeSyncBulb;
@@ -8,6 +8,10 @@ import { VeSync } from './vesync';
8
8
  */
9
9
  export declare class VeSyncBulbESL100 extends VeSyncBulb {
10
10
  constructor(details: Record<string, any>, manager: VeSync);
11
+ getDetails(): Promise<boolean>;
12
+ turnOn(): Promise<boolean>;
13
+ turnOff(): Promise<boolean>;
14
+ setBrightness(brightness: number): Promise<boolean>;
11
15
  setColorTemp(colorTemp: number): Promise<boolean>;
12
16
  }
13
17
  /**
@@ -15,6 +19,11 @@ export declare class VeSyncBulbESL100 extends VeSyncBulb {
15
19
  */
16
20
  export declare class VeSyncBulbESL100CW extends VeSyncBulb {
17
21
  constructor(details: Record<string, any>, manager: VeSync);
22
+ private buildBypassBody;
23
+ getDetails(): Promise<boolean>;
24
+ turnOn(): Promise<boolean>;
25
+ turnOff(): Promise<boolean>;
26
+ setBrightness(brightness: number): Promise<boolean>;
18
27
  setColorTemp(colorTemp: number): Promise<boolean>;
19
28
  }
20
29
  /**
@@ -31,8 +40,14 @@ export declare class VeSyncBulbXYD0001 extends VeSyncBulb {
31
40
  */
32
41
  export declare class VeSyncBulbESL100MC extends VeSyncBulb {
33
42
  constructor(details: Record<string, any>, manager: VeSync);
34
- setColorTemp(colorTemp: number): Promise<boolean>;
43
+ private buildBypassV2Payload;
44
+ private handleBypassV2Response;
45
+ getDetails(): Promise<boolean>;
46
+ turnOn(): Promise<boolean>;
47
+ turnOff(): Promise<boolean>;
48
+ setBrightness(brightness: number): Promise<boolean>;
35
49
  setRgb(red: number, green: number, blue: number): Promise<boolean>;
36
50
  enableWhiteMode(): Promise<boolean>;
51
+ setColorTemp(colorTemp: number): Promise<boolean>;
37
52
  }
38
53
  export declare const bulbModules: Record<string, new (details: Record<string, any>, manager: VeSync) => VeSyncBulb>;