homebridge-tuya-plus 3.14.0-dev.54 → 3.14.0-dev.58

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.
@@ -446,6 +446,16 @@
446
446
  "functionBody": "return model.devices && model.devices[arrayIndices] && ['AirConditioner'].includes(model.devices[arrayIndices].type);"
447
447
  }
448
448
  },
449
+ "fanSpeedValues": {
450
+ "type": "array",
451
+ "description": "Ordered string values used by the device for each fan speed (low → high), e.g. [\"low\", \"middle\", \"high\"]. Overrides fanSpeedSteps.",
452
+ "items": {
453
+ "type": "string"
454
+ },
455
+ "condition": {
456
+ "functionBody": "return model.devices && model.devices[arrayIndices] && ['AirConditioner'].includes(model.devices[arrayIndices].type);"
457
+ }
458
+ },
449
459
  "noChildLock": {
450
460
  "type": "boolean",
451
461
  "condition": {
@@ -27,13 +27,28 @@ class AirConditionerAccessory extends BaseAccessory {
27
27
  }
28
28
 
29
29
  if (!this.device.context.noRotationSpeed) {
30
- const fanSpeedSteps = (this.device.context.fanSpeedSteps && isFinite(this.device.context.fanSpeedSteps) && this.device.context.fanSpeedSteps > 0 && this.device.context.fanSpeedSteps < 100) ? this.device.context.fanSpeedSteps : 100;
31
- this._rotationSteps = [0];
32
- this._rotationStops = {0: 0};
33
- for (let i = 0; i++ < 100;) {
34
- const _rotationStep = Math.floor(fanSpeedSteps * (i - 1) / 100) + 1;
35
- this._rotationSteps.push(_rotationStep);
36
- this._rotationStops[_rotationStep] = i;
30
+ if (Array.isArray(this.device.context.fanSpeedValues) && this.device.context.fanSpeedValues.length) {
31
+ this._rotationSteps = [0];
32
+ this._rotationStops = Object.create(null);
33
+ this._rotationStops[0] = 0;
34
+ const steps = this.device.context.fanSpeedValues;
35
+ const count = steps.length;
36
+ for (let i = 1; i <= 100; i++) {
37
+ const idx = Math.min(Math.floor((i - 1) * count / 100), count - 1);
38
+ this._rotationSteps.push(steps[idx]);
39
+ }
40
+ steps.forEach((step, idx) => {
41
+ this._rotationStops[step] = Math.ceil(((idx + 1) * 100) / count);
42
+ });
43
+ } else {
44
+ const fanSpeedSteps = (this.device.context.fanSpeedSteps && isFinite(this.device.context.fanSpeedSteps) && this.device.context.fanSpeedSteps > 0 && this.device.context.fanSpeedSteps < 100) ? this.device.context.fanSpeedSteps : 100;
45
+ this._rotationSteps = [0];
46
+ this._rotationStops = {0: 0};
47
+ for (let i = 0; i++ < 100;) {
48
+ const _rotationStep = Math.floor(fanSpeedSteps * (i - 1) / 100) + 1;
49
+ this._rotationSteps.push(_rotationStep);
50
+ this._rotationStops[_rotationStep] = i;
51
+ }
37
52
  }
38
53
  }
39
54
  }
@@ -378,10 +393,18 @@ class AirConditionerAccessory extends BaseAccessory {
378
393
  }
379
394
 
380
395
  convertRotationSpeedFromTuyaToHomeKit(value) {
381
- return this._rotationStops[parseInt(value)];
396
+ if (Array.isArray(this.device.context.fanSpeedValues) && this.device.context.fanSpeedValues.length) {
397
+ const hk = this._rotationStops[value];
398
+ return hk === undefined ? 0 : hk;
399
+ }
400
+ const hk = this._rotationStops[parseInt(value)];
401
+ return hk === undefined ? 0 : hk;
382
402
  }
383
403
 
384
404
  convertRotationSpeedFromHomeKitToTuya(value) {
405
+ if (Array.isArray(this.device.context.fanSpeedValues) && this.device.context.fanSpeedValues.length) {
406
+ return this._rotationSteps[value];
407
+ }
385
408
  return this.device.context.fanSpeedSteps ? '' + this._rotationSteps[value] : this._rotationSteps[value];
386
409
  }
387
410
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "homebridge-tuya-plus",
3
- "version": "3.14.0-dev.54",
3
+ "version": "3.14.0-dev.58",
4
4
  "description": "A community-maintained Homebridge plugin for controlling Tuya devices locally over LAN, with an optional Tuya Cloud fallback for whatever the LAN can't reach. Includes new features, fixes, and updated device support. PRs welcome: if it runs, it ships (almost).",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -232,6 +232,24 @@ Tuya devices don't follow a unified pattern for naming the modes, for example co
232
232
 
233
233
  The fan speed data-point (DP `5`, `windspeed`) is usually an **enum of string values** like `"1"`, `"2"`, `"3"`. Set `fanSpeedSteps` to the number of speeds (e.g. `3`); this both maps HomeKit's 0–100 % slider onto the right number of steps and — importantly — sends the speed as a string, which these firmwares require. Without it the fan may silently ignore speed changes.
234
234
 
235
+ For devices that use named string values such as `"low"`, `"middle"` and `"high"`, set `fanSpeedValues` instead:
236
+
237
+ ```json5
238
+ {
239
+ "fanSpeedValues": [
240
+ "low",
241
+ "middle",
242
+ "high"
243
+ ]
244
+ }
245
+ ```
246
+
247
+ This maps HomeKit's 0–100% slider across the configured values in order. For the example above:
248
+ - 0% → Off (turns the AC off)
249
+ - 1–34% → "low"
250
+ - 35–67% → "middle"
251
+ - 68–100% → "high"
252
+
235
253
  Many ACs have no child-lock data-point; if yours doesn't, set `noChildLock: true` so the plugin doesn't add a (non-functional) lock control. Likewise, set `noRotationSpeed: true` if the device has no fan-speed control.
236
254
 
237
255
  Additional parameters can be found in the sample below.