tsvesync 1.4.8 → 1.4.10

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.
@@ -11,6 +11,7 @@ export declare class VeSyncHumidifier extends VeSyncFan {
11
11
  min: number;
12
12
  max: number;
13
13
  };
14
+ protected bypassWriteMethod: 'post' | 'put';
14
15
  constructor(details: Record<string, any>, manager: VeSync);
15
16
  /**
16
17
  * Get device details
@@ -13,13 +13,19 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
13
13
  this.modes = ['auto', 'manual', 'sleep'];
14
14
  this.displayModes = ['on', 'off'];
15
15
  this.humidityRange = { min: 30, max: 80 };
16
- // Set mist levels based on model
16
+ this.bypassWriteMethod = 'post';
17
+ // Set mist levels and write method based on model
17
18
  switch (this.deviceType) {
18
19
  case 'Dual200S':
19
20
  case 'LUH-D301S-WUSR':
20
21
  case 'LUH-D301S-WJP':
21
22
  case 'LUH-D301S-WEU':
22
23
  this.mistLevels = [1, 2];
24
+ // Dual200S requires HTTP PUT for setHumidityMode and setTargetHumidity.
25
+ // POST returns code: 0 but the device silently ignores the command.
26
+ // Diverges from pyvesync (POST). Verified on physical Dual200S (US, Mar 2026).
27
+ // See: https://github.com/mickgiles/tsvesync/issues/1
28
+ this.bypassWriteMethod = 'put';
23
29
  break;
24
30
  default:
25
31
  // All other models support levels 1-9
@@ -157,7 +163,7 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
157
163
  throw new Error(error);
158
164
  }
159
165
  logger_1.logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
160
- const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
166
+ const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', this.bypassWriteMethod, {
161
167
  ...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
162
168
  cid: this.cid,
163
169
  configModule: this.configModule,
@@ -193,7 +199,7 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
193
199
  throw new Error(error);
194
200
  }
195
201
  logger_1.logger.debug(`Setting target humidity to ${humidity}% for device: ${this.deviceName}`);
196
- const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
202
+ const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', this.bypassWriteMethod, {
197
203
  ...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
198
204
  cid: this.cid,
199
205
  configModule: this.configModule,
@@ -859,12 +859,15 @@ class VeSync {
859
859
  for (const deviceList of Object.values(this._devList)) {
860
860
  for (const device of deviceList) {
861
861
  try {
862
- if (!this.shouldExcludeDevice(device)) {
863
- await device.getDetails();
864
- }
865
- else {
862
+ if (this.shouldExcludeDevice(device)) {
866
863
  logger_1.logger.debug(`Skipping details update for excluded device: ${device.deviceName}`);
864
+ continue;
865
+ }
866
+ if (String(device.connectionStatus || '').toLowerCase() === 'offline') {
867
+ logger_1.logger.debug(`Skipping details update for offline device: ${device.deviceName}`);
868
+ continue;
867
869
  }
870
+ await device.getDetails();
868
871
  }
869
872
  catch (error) {
870
873
  logger_1.logger.error(`Error updating ${device.deviceName}:`, error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsvesync",
3
- "version": "1.4.8",
3
+ "version": "1.4.10",
4
4
  "description": "A TypeScript library for interacting with VeSync smart home devices",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -11,16 +11,22 @@ export class VeSyncHumidifier extends VeSyncFan {
11
11
  protected readonly mistLevels: number[];
12
12
  protected readonly displayModes = ['on', 'off'] as const;
13
13
  protected readonly humidityRange = { min: 30, max: 80 };
14
+ protected bypassWriteMethod: 'post' | 'put' = 'post';
14
15
 
15
16
  constructor(details: Record<string, any>, manager: VeSync) {
16
17
  super(details, manager);
17
- // Set mist levels based on model
18
+ // Set mist levels and write method based on model
18
19
  switch (this.deviceType) {
19
20
  case 'Dual200S':
20
21
  case 'LUH-D301S-WUSR':
21
22
  case 'LUH-D301S-WJP':
22
23
  case 'LUH-D301S-WEU':
23
24
  this.mistLevels = [1, 2];
25
+ // Dual200S requires HTTP PUT for setHumidityMode and setTargetHumidity.
26
+ // POST returns code: 0 but the device silently ignores the command.
27
+ // Diverges from pyvesync (POST). Verified on physical Dual200S (US, Mar 2026).
28
+ // See: https://github.com/mickgiles/tsvesync/issues/1
29
+ this.bypassWriteMethod = 'put';
24
30
  break;
25
31
  default:
26
32
  // All other models support levels 1-9
@@ -186,7 +192,7 @@ export class VeSyncHumidifier extends VeSyncFan {
186
192
  logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
187
193
  const [response, status] = await this.callApi(
188
194
  '/cloud/v2/deviceManaged/bypassV2',
189
- 'post',
195
+ this.bypassWriteMethod,
190
196
  {
191
197
  ...Helpers.reqBody(this.manager, 'bypassV2'),
192
198
  cid: this.cid,
@@ -230,7 +236,7 @@ export class VeSyncHumidifier extends VeSyncFan {
230
236
  logger.debug(`Setting target humidity to ${humidity}% for device: ${this.deviceName}`);
231
237
  const [response, status] = await this.callApi(
232
238
  '/cloud/v2/deviceManaged/bypassV2',
233
- 'post',
239
+ this.bypassWriteMethod,
234
240
  {
235
241
  ...Helpers.reqBody(this.manager, 'bypassV2'),
236
242
  cid: this.cid,
package/src/lib/vesync.ts CHANGED
@@ -1028,11 +1028,15 @@ export class VeSync {
1028
1028
  for (const deviceList of Object.values(this._devList)) {
1029
1029
  for (const device of deviceList) {
1030
1030
  try {
1031
- if (!this.shouldExcludeDevice(device)) {
1032
- await device.getDetails();
1033
- } else {
1031
+ if (this.shouldExcludeDevice(device)) {
1034
1032
  logger.debug(`Skipping details update for excluded device: ${device.deviceName}`);
1033
+ continue;
1035
1034
  }
1035
+ if (String(device.connectionStatus || '').toLowerCase() === 'offline') {
1036
+ logger.debug(`Skipping details update for offline device: ${device.deviceName}`);
1037
+ continue;
1038
+ }
1039
+ await device.getDetails();
1036
1040
  } catch (error) {
1037
1041
  logger.error(`Error updating ${device.deviceName}:`, error);
1038
1042
  }