zigbee-herdsman-converters 25.2.0 → 25.3.0

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 (184) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/converters/toZigbee.d.ts.map +1 -1
  3. package/dist/converters/toZigbee.js +129 -143
  4. package/dist/converters/toZigbee.js.map +1 -1
  5. package/dist/devices/amina.d.ts.map +1 -1
  6. package/dist/devices/amina.js +7 -37
  7. package/dist/devices/amina.js.map +1 -1
  8. package/dist/devices/aurora_lighting.d.ts.map +1 -1
  9. package/dist/devices/aurora_lighting.js +1 -0
  10. package/dist/devices/aurora_lighting.js.map +1 -1
  11. package/dist/devices/bacchus.d.ts.map +1 -1
  12. package/dist/devices/bacchus.js +6 -2
  13. package/dist/devices/bacchus.js.map +1 -1
  14. package/dist/devices/bosch.d.ts.map +1 -1
  15. package/dist/devices/bosch.js +38 -25
  16. package/dist/devices/bosch.js.map +1 -1
  17. package/dist/devices/centralite.js.map +1 -1
  18. package/dist/devices/ctm.js.map +1 -1
  19. package/dist/devices/custom_devices_diy.d.ts.map +1 -1
  20. package/dist/devices/custom_devices_diy.js +2 -3
  21. package/dist/devices/custom_devices_diy.js.map +1 -1
  22. package/dist/devices/danfoss.d.ts.map +1 -1
  23. package/dist/devices/danfoss.js +2 -9
  24. package/dist/devices/danfoss.js.map +1 -1
  25. package/dist/devices/dawon_dns.js.map +1 -1
  26. package/dist/devices/develco.d.ts.map +1 -1
  27. package/dist/devices/develco.js.map +1 -1
  28. package/dist/devices/diyruz.js.map +1 -1
  29. package/dist/devices/ewelink.d.ts.map +1 -1
  30. package/dist/devices/ewelink.js +1 -5
  31. package/dist/devices/ewelink.js.map +1 -1
  32. package/dist/devices/gmmts.d.ts.map +1 -1
  33. package/dist/devices/gmmts.js +15 -5
  34. package/dist/devices/gmmts.js.map +1 -1
  35. package/dist/devices/heiman.d.ts.map +1 -1
  36. package/dist/devices/heiman.js +5 -1
  37. package/dist/devices/heiman.js.map +1 -1
  38. package/dist/devices/imhotepcreation.js.map +1 -1
  39. package/dist/devices/immax.js.map +1 -1
  40. package/dist/devices/inovelli.d.ts.map +1 -1
  41. package/dist/devices/inovelli.js +5 -6
  42. package/dist/devices/inovelli.js.map +1 -1
  43. package/dist/devices/keen_home.js.map +1 -1
  44. package/dist/devices/kmpcil.js.map +1 -1
  45. package/dist/devices/legrand.d.ts.map +1 -1
  46. package/dist/devices/legrand.js +2 -0
  47. package/dist/devices/legrand.js.map +1 -1
  48. package/dist/devices/lincukoo.d.ts.map +1 -1
  49. package/dist/devices/lincukoo.js +77 -1
  50. package/dist/devices/lincukoo.js.map +1 -1
  51. package/dist/devices/livolo.d.ts.map +1 -1
  52. package/dist/devices/livolo.js.map +1 -1
  53. package/dist/devices/lixee.d.ts.map +1 -1
  54. package/dist/devices/lixee.js +9 -4
  55. package/dist/devices/lixee.js.map +1 -1
  56. package/dist/devices/lytko.d.ts.map +1 -1
  57. package/dist/devices/lytko.js +12 -10
  58. package/dist/devices/lytko.js.map +1 -1
  59. package/dist/devices/moes.js.map +1 -1
  60. package/dist/devices/niko.d.ts.map +1 -1
  61. package/dist/devices/niko.js +23 -7
  62. package/dist/devices/niko.js.map +1 -1
  63. package/dist/devices/nodon.js.map +1 -1
  64. package/dist/devices/orvibo.d.ts.map +1 -1
  65. package/dist/devices/orvibo.js +9 -3
  66. package/dist/devices/orvibo.js.map +1 -1
  67. package/dist/devices/owon.d.ts.map +1 -1
  68. package/dist/devices/owon.js +2 -3
  69. package/dist/devices/owon.js.map +1 -1
  70. package/dist/devices/perenio.d.ts.map +1 -1
  71. package/dist/devices/perenio.js +1 -1
  72. package/dist/devices/perenio.js.map +1 -1
  73. package/dist/devices/pushok.js.map +1 -1
  74. package/dist/devices/qa.js.map +1 -1
  75. package/dist/devices/salus_controls.d.ts.map +1 -1
  76. package/dist/devices/salus_controls.js.map +1 -1
  77. package/dist/devices/sber.d.ts.map +1 -1
  78. package/dist/devices/sber.js +12 -8
  79. package/dist/devices/sber.js.map +1 -1
  80. package/dist/devices/schneider_electric.d.ts.map +1 -1
  81. package/dist/devices/schneider_electric.js +7 -6
  82. package/dist/devices/schneider_electric.js.map +1 -1
  83. package/dist/devices/sengled.d.ts.map +1 -1
  84. package/dist/devices/sengled.js.map +1 -1
  85. package/dist/devices/shinasystem.js +4 -4
  86. package/dist/devices/shinasystem.js.map +1 -1
  87. package/dist/devices/siglis.js +10 -10
  88. package/dist/devices/siglis.js.map +1 -1
  89. package/dist/devices/simpla_home.d.ts +1 -1
  90. package/dist/devices/simpla_home.d.ts.map +1 -1
  91. package/dist/devices/simpla_home.js.map +1 -1
  92. package/dist/devices/sinope.js.map +1 -1
  93. package/dist/devices/slacky_diy.d.ts.map +1 -1
  94. package/dist/devices/slacky_diy.js +3 -1
  95. package/dist/devices/slacky_diy.js.map +1 -1
  96. package/dist/devices/smartthings.js.map +1 -1
  97. package/dist/devices/sonoff.d.ts +29 -0
  98. package/dist/devices/sonoff.d.ts.map +1 -1
  99. package/dist/devices/sonoff.js +14 -13
  100. package/dist/devices/sonoff.js.map +1 -1
  101. package/dist/devices/sunricher.d.ts +15 -0
  102. package/dist/devices/sunricher.d.ts.map +1 -1
  103. package/dist/devices/sunricher.js +3 -3
  104. package/dist/devices/sunricher.js.map +1 -1
  105. package/dist/devices/tubeszb.js.map +1 -1
  106. package/dist/devices/tuya.d.ts.map +1 -1
  107. package/dist/devices/tuya.js +7 -10
  108. package/dist/devices/tuya.js.map +1 -1
  109. package/dist/devices/ubisys.d.ts.map +1 -1
  110. package/dist/devices/ubisys.js +4 -7
  111. package/dist/devices/ubisys.js.map +1 -1
  112. package/dist/devices/wirenboard.d.ts.map +1 -1
  113. package/dist/devices/wirenboard.js +5 -3
  114. package/dist/devices/wirenboard.js.map +1 -1
  115. package/dist/devices/xyzroe.d.ts.map +1 -1
  116. package/dist/devices/xyzroe.js +2 -4
  117. package/dist/devices/xyzroe.js.map +1 -1
  118. package/dist/devices/yandex.d.ts.map +1 -1
  119. package/dist/devices/yandex.js +18 -6
  120. package/dist/devices/yandex.js.map +1 -1
  121. package/dist/devices/yokis.d.ts.map +1 -1
  122. package/dist/devices/yokis.js +4 -6
  123. package/dist/devices/yokis.js.map +1 -1
  124. package/dist/lib/develco.d.ts +24 -5
  125. package/dist/lib/develco.d.ts.map +1 -1
  126. package/dist/lib/develco.js +1 -1
  127. package/dist/lib/develco.js.map +1 -1
  128. package/dist/lib/ewelink.d.ts +4 -4
  129. package/dist/lib/ewelink.d.ts.map +1 -1
  130. package/dist/lib/ewelink.js.map +1 -1
  131. package/dist/lib/generateDefinition.js.map +1 -1
  132. package/dist/lib/ikea.d.ts +30 -1
  133. package/dist/lib/ikea.d.ts.map +1 -1
  134. package/dist/lib/ikea.js +6 -1
  135. package/dist/lib/ikea.js.map +1 -1
  136. package/dist/lib/legacy.d.ts +33 -1
  137. package/dist/lib/legacy.d.ts.map +1 -1
  138. package/dist/lib/legacy.js +21 -23
  139. package/dist/lib/legacy.js.map +1 -1
  140. package/dist/lib/legrand.d.ts.map +1 -1
  141. package/dist/lib/legrand.js +5 -6
  142. package/dist/lib/legrand.js.map +1 -1
  143. package/dist/lib/light.d.ts +2 -1
  144. package/dist/lib/light.d.ts.map +1 -1
  145. package/dist/lib/light.js.map +1 -1
  146. package/dist/lib/lumi.d.ts +33 -33
  147. package/dist/lib/lumi.d.ts.map +1 -1
  148. package/dist/lib/lumi.js +8 -9
  149. package/dist/lib/lumi.js.map +1 -1
  150. package/dist/lib/modernExtend.d.ts +41 -58
  151. package/dist/lib/modernExtend.d.ts.map +1 -1
  152. package/dist/lib/modernExtend.js +70 -15
  153. package/dist/lib/modernExtend.js.map +1 -1
  154. package/dist/lib/namron.d.ts +25 -25
  155. package/dist/lib/namron.d.ts.map +1 -1
  156. package/dist/lib/namron.js +5 -6
  157. package/dist/lib/namron.js.map +1 -1
  158. package/dist/lib/nodon.d.ts.map +1 -1
  159. package/dist/lib/nodon.js.map +1 -1
  160. package/dist/lib/philips.d.ts.map +1 -1
  161. package/dist/lib/philips.js +9 -10
  162. package/dist/lib/philips.js.map +1 -1
  163. package/dist/lib/reporting.d.ts +4 -7
  164. package/dist/lib/reporting.d.ts.map +1 -1
  165. package/dist/lib/reporting.js.map +1 -1
  166. package/dist/lib/sunricher.d.ts.map +1 -1
  167. package/dist/lib/sunricher.js +6 -4
  168. package/dist/lib/sunricher.js.map +1 -1
  169. package/dist/lib/tuya.d.ts +4 -4
  170. package/dist/lib/tuya.d.ts.map +1 -1
  171. package/dist/lib/tuya.js +32 -30
  172. package/dist/lib/tuya.js.map +1 -1
  173. package/dist/lib/types.d.ts +1 -1
  174. package/dist/lib/types.d.ts.map +1 -1
  175. package/dist/lib/ubisys.d.ts +88 -8
  176. package/dist/lib/ubisys.d.ts.map +1 -1
  177. package/dist/lib/ubisys.js +0 -3
  178. package/dist/lib/ubisys.js.map +1 -1
  179. package/dist/lib/utils.d.ts +10 -8
  180. package/dist/lib/utils.d.ts.map +1 -1
  181. package/dist/lib/utils.js +8 -5
  182. package/dist/lib/utils.js.map +1 -1
  183. package/dist/models-index.json +1 -1
  184. package/package.json +2 -2
@@ -76,7 +76,8 @@ exports.on_off = {
76
76
  throw Error("The off_wait_time value must be a number!");
77
77
  }
78
78
  const payload = meta.converterOptions
79
- ? meta.converterOptions
79
+ ? // TODO: better typing? currently used in a single place??
80
+ meta.converterOptions
80
81
  : { ctrlbits: 0, ontime: Math.round(onTime * 10), offwaittime: Math.round(offWaitTime * 10) };
81
82
  await entity.command("genOnOff", "onWithTimedOff", payload, utils.getOptions(meta.mapped, entity));
82
83
  }
@@ -97,11 +98,9 @@ exports.light_color = {
97
98
  key: ["color"],
98
99
  options: [exposes.options.color_sync(), exposes.options.transition()],
99
100
  convertSet: async (entity, key, value, meta) => {
100
- // biome-ignore lint/suspicious/noImplicitAnyLet: ignored using `--suppress`
101
- let command;
102
101
  const newColor = libColor.Color.fromConverterArg(value);
103
102
  const newState = {};
104
- const zclData = { transtime: utils.getTransition(entity, key, meta).time };
103
+ const transtime = utils.getTransition(entity, key, meta).time;
105
104
  const supportsHueAndSaturation = utils.getMetaValue(entity, meta.mapped, "supportsHueAndSaturation", "allEqual", true);
106
105
  const supportsEnhancedHue = utils.getMetaValue(entity, meta.mapped, "supportsEnhancedHue", "allEqual", true);
107
106
  if (newColor.isHSV() && !supportsHueAndSaturation) {
@@ -121,57 +120,48 @@ exports.light_color = {
121
120
  }
122
121
  newState.color_mode = constants.colorModeLookup[1];
123
122
  newState.color = xy.toObject();
124
- zclData.colorx = utils.mapNumberRange(xy.x, 0, 1, 0, 65535);
125
- zclData.colory = utils.mapNumberRange(xy.y, 0, 1, 0, 65535);
126
- command = "moveToColor";
123
+ const colorx = utils.mapNumberRange(xy.x, 0, 1, 0, 65535);
124
+ const colory = utils.mapNumberRange(xy.y, 0, 1, 0, 65535);
125
+ await entity.command("lightingColorCtrl", "moveToColor", { transtime, colorx, colory }, utils.getOptions(meta.mapped, entity));
127
126
  }
128
127
  else if (newColor.isHSV()) {
129
128
  const hsv = newColor.hsv;
130
129
  const hsvCorrected = hsv.colorCorrected(meta);
131
130
  newState.color_mode = constants.colorModeLookup[0];
132
131
  newState.color = hsv.toObject(false);
133
- if (hsv.hue !== null) {
134
- if (supportsEnhancedHue) {
135
- zclData.enhancehue = utils.mapNumberRange(hsvCorrected.hue, 0, 360, 0, 65535);
136
- }
137
- else {
138
- zclData.hue = utils.mapNumberRange(hsvCorrected.hue, 0, 360, 0, 254);
139
- }
140
- // @ts-expect-error ignore
141
- zclData.direction = value.direction || 0;
142
- }
143
- if (hsv.saturation != null) {
144
- zclData.saturation = utils.mapNumberRange(hsvCorrected.saturation, 0, 100, 0, 254);
145
- }
146
- if (hsv.value !== null) {
147
- // fallthrough to genLevelCtrl
148
- // @ts-expect-error ignore
149
- value.brightness = utils.mapNumberRange(hsvCorrected.value, 0, 100, 0, 254);
132
+ if (hsv.value !== null && utils.isObject(value)) {
133
+ await entity.command("genLevelCtrl", "moveToLevelWithOnOff", { level: utils.mapNumberRange(hsvCorrected.value, 0, 100, 0, 254), transtime }, utils.getOptions(meta.mapped, entity));
150
134
  }
151
135
  if (hsv.hue !== null && hsv.saturation !== null) {
136
+ const saturation = utils.mapNumberRange(hsvCorrected.saturation, 0, 100, 0, 254);
152
137
  if (supportsEnhancedHue) {
153
- command = "enhancedMoveToHueAndSaturation";
138
+ const enhancehue = utils.mapNumberRange(hsvCorrected.hue, 0, 360, 0, 65535);
139
+ await entity.command("lightingColorCtrl", "enhancedMoveToHueAndSaturation", { transtime, enhancehue, saturation }, utils.getOptions(meta.mapped, entity));
154
140
  }
155
141
  else {
156
- command = "moveToHueAndSaturation";
142
+ const hue = utils.mapNumberRange(hsvCorrected.hue, 0, 360, 0, 254);
143
+ await entity.command("lightingColorCtrl", "moveToHueAndSaturation", { transtime, hue, saturation }, utils.getOptions(meta.mapped, entity));
157
144
  }
158
145
  }
159
146
  else if (hsv.hue !== null) {
147
+ const direction = value.direction || 0;
160
148
  if (supportsEnhancedHue) {
161
- command = "enhancedMoveToHue";
149
+ const enhancehue = utils.mapNumberRange(hsvCorrected.hue, 0, 360, 0, 65535);
150
+ await entity.command("lightingColorCtrl", "enhancedMoveToHue", { transtime, enhancehue, direction }, utils.getOptions(meta.mapped, entity));
162
151
  }
163
152
  else {
164
- command = "moveToHue";
153
+ const hue = utils.mapNumberRange(hsvCorrected.hue, 0, 360, 0, 254);
154
+ await entity.command("lightingColorCtrl", "moveToHue", { transtime, hue, direction }, utils.getOptions(meta.mapped, entity));
165
155
  }
166
156
  }
167
157
  else if (hsv.saturation !== null) {
168
- command = "moveToSaturation";
158
+ const saturation = utils.mapNumberRange(hsvCorrected.saturation, 0, 100, 0, 254);
159
+ await entity.command("lightingColorCtrl", "moveToSaturation", { transtime, saturation }, utils.getOptions(meta.mapped, entity));
169
160
  }
170
161
  }
171
- if (utils.isObject(value) && value.brightness != null) {
172
- await entity.command("genLevelCtrl", "moveToLevelWithOnOff", { level: Number(value.brightness), transtime: utils.getTransition(entity, key, meta).time }, utils.getOptions(meta.mapped, entity));
162
+ else {
163
+ throw new Error("Invalid color");
173
164
  }
174
- await entity.command("lightingColorCtrl", command, zclData, utils.getOptions(meta.mapped, entity));
175
165
  return { state: libColor.syncColorState(newState, meta.state, entity, meta.options) };
176
166
  },
177
167
  convertGet: async (entity, key, meta) => {
@@ -513,7 +503,7 @@ exports.cover_via_brightness = {
513
503
  : meta.options.invert_cover;
514
504
  utils.assertNumber(value);
515
505
  const position = invert ? 100 - value : value;
516
- await entity.command("genLevelCtrl", "moveToLevelWithOnOff", { level: utils.mapNumberRange(Number(position), 0, 100, 0, 255).toString(), transtime: 0 }, utils.getOptions(meta.mapped, entity));
506
+ await entity.command("genLevelCtrl", "moveToLevelWithOnOff", { level: utils.mapNumberRange(Number(position), 0, 100, 0, 255), transtime: 0 }, utils.getOptions(meta.mapped, entity));
517
507
  return { state: { position: value } };
518
508
  },
519
509
  convertGet: async (entity, key, meta) => {
@@ -600,11 +590,15 @@ exports.squawk = {
600
590
  exports.cover_state = {
601
591
  key: ["state"],
602
592
  convertSet: async (entity, key, value, meta) => {
603
- const lookup = { open: "upOpen", close: "downClose", stop: "stop", on: "upOpen", off: "downClose" };
593
+ const lookup = {
594
+ open: "upOpen",
595
+ close: "downClose",
596
+ stop: "stop",
597
+ on: "upOpen",
598
+ off: "downClose",
599
+ };
604
600
  utils.assertString(value, key);
605
- // biome-ignore lint/style/noParameterAssign: ignored using `--suppress`
606
- value = value.toLowerCase();
607
- await entity.command("closuresWindowCovering", utils.getFromLookup(value, lookup), {}, utils.getOptions(meta.mapped, entity));
601
+ await entity.command("closuresWindowCovering", utils.getFromLookup(value.toLowerCase(), lookup), {}, utils.getOptions(meta.mapped, entity));
608
602
  },
609
603
  };
610
604
  exports.cover_position_tilt = {
@@ -787,7 +781,14 @@ exports.level_config = {
787
781
  }
788
782
  },
789
783
  convertGet: async (entity, key, meta) => {
790
- for (const attribute of ["onOffTransitionTime", "onTransitionTime", "offTransitionTime", "startUpCurrentLevel", "onLevel", "options"]) {
784
+ for (const attribute of [
785
+ "onOffTransitionTime",
786
+ "onTransitionTime",
787
+ "offTransitionTime",
788
+ "startUpCurrentLevel",
789
+ "onLevel",
790
+ "options",
791
+ ]) {
791
792
  try {
792
793
  await entity.read("genLevelCtrl", [attribute]);
793
794
  }
@@ -823,24 +824,23 @@ exports.ballast_config = {
823
824
  convertGet: async (entity, key, meta) => {
824
825
  let result = {};
825
826
  for (const attrName of [
826
- "ballast_status",
827
- "min_level",
828
- "max_level",
829
- "power_on_level",
830
- "power_on_fade_time",
831
- "intrinsic_ballast_factor",
832
- "ballast_factor_adjustment",
833
- "lamp_quantity",
834
- "lamp_type",
835
- "lamp_manufacturer",
836
- "lamp_rated_hours",
837
- "lamp_burn_hours",
838
- "lamp_alarm_mode",
839
- "lamp_burn_hours_trip_point",
827
+ "ballastStatus",
828
+ "minLevel",
829
+ "maxLevel",
830
+ "powerOnLevel",
831
+ "powerOnFadeTime",
832
+ "intrinsicBallastFactor",
833
+ "ballastFactorAdjustment",
834
+ "lampQuantity",
835
+ "lampType",
836
+ "lampManufacturer",
837
+ "lampRatedHours",
838
+ "lampBurnHours",
839
+ "lampAlarmMode",
840
+ "lampBurnHoursTripPoint",
840
841
  ]) {
841
842
  try {
842
- // @ts-expect-error ignore
843
- result = { ...result, ...(await entity.read("lightingBallastCfg", [utils.toCamelCase(attrName)])) };
843
+ result = { ...result, ...(await entity.read("lightingBallastCfg", [attrName])) };
844
844
  }
845
845
  catch {
846
846
  // continue regardless of error
@@ -932,7 +932,8 @@ exports.light_colortemp_move = {
932
932
  key: ["colortemp_move", "color_temp_move"],
933
933
  convertSet: async (entity, key, value, meta) => {
934
934
  // Initialize payload with default constraints
935
- const payload = { minimum: 0, maximum: 600 };
935
+ let minimum = 0;
936
+ let maximum = 600;
936
937
  let rate;
937
938
  let movemode;
938
939
  // Handle different input formats
@@ -955,8 +956,8 @@ exports.light_colortemp_move = {
955
956
  throw new Error(`${key}: invalid string value "${value}". Expected "stop", "release", "0", "up", "1", or "down"`);
956
957
  }
957
958
  // Use legacy constraints for string-based commands
958
- payload.minimum = 153;
959
- payload.maximum = 370;
959
+ minimum = 153;
960
+ maximum = 370;
960
961
  }
961
962
  else if (utils.isNumber(value)) {
962
963
  // Simple number input
@@ -994,26 +995,23 @@ exports.light_colortemp_move = {
994
995
  if (value.minimum != null) {
995
996
  const minValue = Number(value.minimum);
996
997
  utils.assertNumber(minValue, `${key}.minimum`);
997
- payload.minimum = minValue;
998
+ minimum = minValue;
998
999
  }
999
1000
  if (value.maximum != null) {
1000
1001
  const maxValue = Number(value.maximum);
1001
1002
  utils.assertNumber(maxValue, `${key}.maximum`);
1002
- payload.maximum = maxValue;
1003
+ maximum = maxValue;
1003
1004
  }
1004
1005
  // Validate constraints
1005
- if (payload.minimum >= payload.maximum) {
1006
- throw new Error(`${key}: minimum (${payload.minimum}) must be less than maximum (${payload.maximum})`);
1006
+ if (minimum >= maximum) {
1007
+ throw new Error(`${key}: minimum (${minimum}) must be less than maximum (${maximum})`);
1007
1008
  }
1008
1009
  }
1009
1010
  else {
1010
1011
  throw new Error(`${key}: invalid value type. Expected number, string, or object with rate property`);
1011
1012
  }
1012
- // Set final payload values
1013
- payload.rate = rate;
1014
- payload.movemode = movemode;
1015
1013
  // Send command
1016
- await entity.command("lightingColorCtrl", "moveColorTemp", payload, utils.getOptions(meta.mapped, entity));
1014
+ await entity.command("lightingColorCtrl", "moveColorTemp", { minimum, maximum, rate, movemode }, utils.getOptions(meta.mapped, entity));
1017
1015
  // Read current color temperature if stopping
1018
1016
  if (movemode === 0) {
1019
1017
  const entityToRead = utils.getEntityOrFirstGroupMember(entity);
@@ -1078,17 +1076,18 @@ exports.light_hue_saturation_move = {
1078
1076
  value = value === "stop" ? value : Number(value);
1079
1077
  const command = key === "hue_move" ? "moveHue" : "moveSaturation";
1080
1078
  const attribute = key === "hue_move" ? "currentHue" : "currentSaturation";
1081
- const payload = {};
1079
+ let rate = 0;
1080
+ let movemode = 0;
1082
1081
  if (value === "stop" || value === 0) {
1083
- payload.rate = 1;
1084
- payload.movemode = 0;
1082
+ rate = 1;
1083
+ movemode = 0;
1085
1084
  }
1086
1085
  else {
1087
1086
  utils.assertNumber(value, key);
1088
- payload.rate = Math.abs(value);
1089
- payload.movemode = value > 0 ? 1 : 3;
1087
+ rate = Math.abs(value);
1088
+ movemode = value > 0 ? 1 : 3;
1090
1089
  }
1091
- await entity.command("lightingColorCtrl", command, payload, utils.getOptions(meta.mapped, entity));
1090
+ await entity.command("lightingColorCtrl", command, { rate, movemode }, utils.getOptions(meta.mapped, entity));
1092
1091
  // We cannot determine the hue/saturation from the current state so we read it, because
1093
1092
  // - Color mode could have been switched (x/y or colortemp)
1094
1093
  if (value === "stop" || value === 0) {
@@ -1174,7 +1173,6 @@ exports.light_onoff_brightness = {
1174
1173
  try {
1175
1174
  const attributeRead = await entity.read("genLevelCtrl", ["onLevel"]);
1176
1175
  if (attributeRead !== undefined) {
1177
- // @ts-expect-error ignore
1178
1176
  onLevel = attributeRead.onLevel;
1179
1177
  }
1180
1178
  }
@@ -1254,7 +1252,7 @@ exports.light_colortemp_startup = {
1254
1252
  // biome-ignore lint/style/noParameterAssign: ignored using `--suppress`
1255
1253
  value = light.clampColorTemp(value, colorTempMin, colorTempMax);
1256
1254
  }
1257
- await entity.write("lightingColorCtrl", { startUpColorTemperature: value }, utils.getOptions(meta.mapped, entity));
1255
+ await entity.write("lightingColorCtrl", { startUpColorTemperature: value /* type failure? */ }, utils.getOptions(meta.mapped, entity));
1258
1256
  return { state: { color_temp_startup: value } };
1259
1257
  },
1260
1258
  convertGet: async (entity, key, meta) => {
@@ -1368,29 +1366,28 @@ exports.thermostat_weekly_schedule = {
1368
1366
  ]}}
1369
1367
  */
1370
1368
  utils.assertObject(value, key);
1371
- const payload = {
1372
- dayofweek: value.dayofweek,
1373
- transitions: value.transitions,
1374
- };
1375
- if (Array.isArray(payload.transitions)) {
1369
+ let daysofweek = value.dayofweek;
1370
+ const transitions = value.transitions;
1371
+ let numoftrans = 0;
1372
+ const modes = [];
1373
+ if (Array.isArray(transitions)) {
1376
1374
  // calculate numoftrans
1377
1375
  if (typeof value.numoftrans !== "undefined") {
1378
1376
  logger_1.logger.warning(`weekly_schedule: ignoring provided numoftrans value (${JSON.stringify(value.numoftrans)}), this is now calculated automatically`, NS);
1379
1377
  }
1380
- payload.numoftrans = payload.transitions.length;
1378
+ numoftrans = transitions.length;
1381
1379
  // mode is calculated below
1382
1380
  if (typeof value.mode !== "undefined") {
1383
1381
  logger_1.logger.warning(`weekly_schedule: ignoring provided mode value (${JSON.stringify(value.mode)}), this is now calculated automatically`, NS);
1384
1382
  }
1385
- payload.mode = [];
1386
1383
  // transform transition payload values if needed
1387
- for (const elem of payload.transitions) {
1388
- // update payload.mode if needed
1389
- if (elem.heatSetpoint != null && !payload.mode.includes("heat")) {
1390
- payload.mode.push("heat");
1384
+ for (const elem of transitions) {
1385
+ // update mode if needed
1386
+ if (elem.heatSetpoint != null && !modes.includes("heat")) {
1387
+ modes.push("heat");
1391
1388
  }
1392
- if (elem.coolSetpoint != null && !payload.mode.includes("cool")) {
1393
- payload.mode.push("cool");
1389
+ if (elem.coolSetpoint != null && !modes.includes("cool")) {
1390
+ modes.push("cool");
1394
1391
  }
1395
1392
  // transform setpoint values if numeric
1396
1393
  if (typeof elem.heatSetpoint === "number") {
@@ -1431,18 +1428,17 @@ exports.thermostat_weekly_schedule = {
1431
1428
  }
1432
1429
  // map array of desired modes to bitmask
1433
1430
  let mode = 0;
1434
- for (let m of payload.mode) {
1431
+ for (const m of modes) {
1435
1432
  // lookup mode bit
1436
- m = utils.getKey(constants.thermostatScheduleMode, m.toLowerCase(), m, Number);
1437
- mode |= 1 << m;
1433
+ mode |= 1 << utils.getKey(constants.thermostatScheduleMode, m, 0, Number);
1438
1434
  }
1439
- payload.mode = mode;
1440
1435
  // map array of days to desired dayofweek bitmask
1441
- if (typeof payload.dayofweek === "string")
1442
- payload.dayofweek = [payload.dayofweek];
1443
- if (Array.isArray(payload.dayofweek)) {
1444
- let dayofweek = 0;
1445
- for (let d of payload.dayofweek) {
1436
+ if (typeof daysofweek === "string") {
1437
+ daysofweek = [daysofweek];
1438
+ }
1439
+ let dayofweek = 0;
1440
+ if (Array.isArray(daysofweek)) {
1441
+ for (let d of daysofweek) {
1446
1442
  if (typeof d === "object") {
1447
1443
  if (d.day == null) {
1448
1444
  throw new Error(`weekly_schedule: expected dayofweek to be string or {"day": "str"}, but got '${JSON.stringify(d)}'!`);
@@ -1453,9 +1449,8 @@ exports.thermostat_weekly_schedule = {
1453
1449
  d = utils.getKey(constants.thermostatDayOfWeek, d.toLowerCase(), d, Number);
1454
1450
  dayofweek |= 1 << d;
1455
1451
  }
1456
- payload.dayofweek = dayofweek;
1457
1452
  }
1458
- await entity.command("hvacThermostat", "setWeeklySchedule", payload, utils.getOptions(meta.mapped, entity));
1453
+ await entity.command("hvacThermostat", "setWeeklySchedule", { dayofweek, numoftrans, transitions, mode }, utils.getOptions(meta.mapped, entity));
1459
1454
  },
1460
1455
  convertGet: async (entity, key, meta) => {
1461
1456
  const payload = {
@@ -1551,8 +1546,7 @@ exports.thermostat_keypad_lockout = {
1551
1546
  exports.thermostat_temperature_setpoint_hold = {
1552
1547
  key: ["temperature_setpoint_hold"],
1553
1548
  convertSet: async (entity, key, value, meta) => {
1554
- const tempSetpointHold = value;
1555
- await entity.write("hvacThermostat", { tempSetpointHold });
1549
+ await entity.write("hvacThermostat", { tempSetpointHold: value });
1556
1550
  },
1557
1551
  convertGet: async (entity, key, meta) => {
1558
1552
  await entity.read("hvacThermostat", ["tempSetpointHold"]);
@@ -1561,8 +1555,7 @@ exports.thermostat_temperature_setpoint_hold = {
1561
1555
  exports.thermostat_temperature_setpoint_hold_duration = {
1562
1556
  key: ["temperature_setpoint_hold_duration"],
1563
1557
  convertSet: async (entity, key, value, meta) => {
1564
- const tempSetpointHoldDuration = value;
1565
- await entity.write("hvacThermostat", { tempSetpointHoldDuration });
1558
+ await entity.write("hvacThermostat", { tempSetpointHoldDuration: value });
1566
1559
  },
1567
1560
  convertGet: async (entity, key, meta) => {
1568
1561
  await entity.read("hvacThermostat", ["tempSetpointHoldDuration"]);
@@ -1584,7 +1577,7 @@ exports.fan_speed = {
1584
1577
  key: ["speed"],
1585
1578
  convertSet: async (entity, key, value, meta) => {
1586
1579
  utils.assertNumber(value);
1587
- await entity.command("genLevelCtrl", "moveToLevel", { level: value.toString(), transtime: 0 }, utils.getOptions(meta.mapped, entity));
1580
+ await entity.command("genLevelCtrl", "moveToLevel", { level: value, transtime: 0 }, utils.getOptions(meta.mapped, entity));
1588
1581
  return { state: { speed: value } };
1589
1582
  },
1590
1583
  convertGet: async (entity, key, meta) => {
@@ -1980,7 +1973,7 @@ exports.humidity = {
1980
1973
  exports.elko_power_status = {
1981
1974
  key: ["system_mode"],
1982
1975
  convertSet: async (entity, key, value, meta) => {
1983
- await entity.write("hvacThermostat", { elkoPowerStatus: value === "heat" });
1976
+ await entity.write("hvacThermostat", { elkoPowerStatus: value === "heat" ? 1 : 0 });
1984
1977
  return { state: { system_mode: value } };
1985
1978
  },
1986
1979
  convertGet: async (entity, key, meta) => {
@@ -2183,7 +2176,9 @@ exports.livolo_cover_state = {
2183
2176
  default:
2184
2177
  throw new Error(`Value '${value}' is not a valid cover position (must be one of 'OPEN' or 'CLOSE')`);
2185
2178
  }
2186
- await entity.writeStructured("genPowerCfg", [payload], options);
2179
+ await entity.writeStructured("genPowerCfg",
2180
+ // @ts-expect-error workaround write custom payload
2181
+ [payload], options);
2187
2182
  return {
2188
2183
  state: {
2189
2184
  moving: true,
@@ -2244,14 +2239,18 @@ exports.livolo_cover_options = {
2244
2239
  (must be one of 'FORWARD' or 'REVERSE')`);
2245
2240
  }
2246
2241
  const payload = { 4865: { value: [direction, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] } };
2247
- await entity.write("genPowerCfg", payload, options);
2242
+ await entity.write("genPowerCfg",
2243
+ // @ts-expect-error workaround write custom payload
2244
+ payload, options);
2248
2245
  }
2249
2246
  if (value.motor_speed != null) {
2250
2247
  if (value.motor_speed < 20 || value.motor_speed > 40) {
2251
2248
  throw new Error("livolo_cover_options: Motor speed is out of range (20-40)");
2252
2249
  }
2253
2250
  const payload = { 4609: { value: [value.motor_speed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] } };
2254
- await entity.write("genPowerCfg", payload, options);
2251
+ await entity.write("genPowerCfg",
2252
+ // @ts-expect-error workaround write custom payload
2253
+ payload, options);
2255
2254
  }
2256
2255
  },
2257
2256
  };
@@ -2548,8 +2547,7 @@ exports.danfoss_adaptation_settings = {
2548
2547
  exports.danfoss_adaptation_control = {
2549
2548
  key: ["adaptation_run_control"],
2550
2549
  convertSet: async (entity, key, value, meta) => {
2551
- const payload = { danfossAdaptionRunControl: utils.getKey(constants.danfossAdaptionRunControl, value, value, Number) };
2552
- await entity.write("hvacThermostat", payload, manufacturerOptions.danfoss);
2550
+ await entity.write("hvacThermostat", { danfossAdaptionRunControl: utils.getKey(constants.danfossAdaptionRunControl, value, value, Number) }, manufacturerOptions.danfoss);
2553
2551
  return { state: { adaptation_run_control: value } };
2554
2552
  },
2555
2553
  convertGet: async (entity, key, meta) => {
@@ -2559,8 +2557,7 @@ exports.danfoss_adaptation_control = {
2559
2557
  exports.danfoss_regulation_setpoint_offset = {
2560
2558
  key: ["regulation_setpoint_offset"],
2561
2559
  convertSet: async (entity, key, value, meta) => {
2562
- const payload = { danfossRegulationSetpointOffset: value };
2563
- await entity.write("hvacThermostat", payload, manufacturerOptions.danfoss);
2560
+ await entity.write("hvacThermostat", { danfossRegulationSetpointOffset: value }, manufacturerOptions.danfoss);
2564
2561
  return { state: { regulation_setpoint_offset: value } };
2565
2562
  },
2566
2563
  convertGet: async (entity, key, meta) => {
@@ -2636,7 +2633,7 @@ exports.danfoss_system_status_code = {
2636
2633
  exports.danfoss_heat_supply_request = {
2637
2634
  key: ["heat_supply_request"],
2638
2635
  convertGet: async (entity, key, meta) => {
2639
- await entity.read("haDiagnostic", ["danfossHeatsupplyRequest"], manufacturerOptions.danfoss);
2636
+ await entity.read("haDiagnostic", ["danfossHeatSupplyRequest"], manufacturerOptions.danfoss);
2640
2637
  },
2641
2638
  };
2642
2639
  exports.danfoss_system_status_water = {
@@ -2982,15 +2979,13 @@ exports.tuya_led_controller = {
2982
2979
  return { state: { state: value.toUpperCase() } };
2983
2980
  }
2984
2981
  if (key === "color") {
2985
- const hue = {};
2986
- const saturation = {};
2987
2982
  utils.assertObject(value);
2988
- hue.hue = utils.mapNumberRange(value.h, 0, 360, 0, 254);
2989
- saturation.saturation = utils.mapNumberRange(value.s, 0, 100, 0, 254);
2990
- hue.transtime = saturation.transtime = 0;
2991
- hue.direction = 0;
2992
- await entity.command("lightingColorCtrl", "moveToHue", hue, utils.getOptions(meta.mapped, entity));
2993
- await entity.command("lightingColorCtrl", "moveToSaturation", saturation, utils.getOptions(meta.mapped, entity));
2983
+ const hue = utils.mapNumberRange(value.h, 0, 360, 0, 254);
2984
+ const saturation = utils.mapNumberRange(value.s, 0, 100, 0, 254);
2985
+ const transtime = 0;
2986
+ const direction = 0;
2987
+ await entity.command("lightingColorCtrl", "moveToHue", { hue, transtime, direction }, utils.getOptions(meta.mapped, entity));
2988
+ await entity.command("lightingColorCtrl", "moveToSaturation", { saturation, transtime }, utils.getOptions(meta.mapped, entity));
2994
2989
  }
2995
2990
  },
2996
2991
  convertGet: async (entity, key, meta) => {
@@ -3561,16 +3556,16 @@ exports.diyruz_zintercom_config = {
3561
3556
  },
3562
3557
  convertGet: async (entity, key, meta) => {
3563
3558
  const payloads = {
3564
- mode: ["closuresDoorLock", 0x0051],
3565
- sound: ["closuresDoorLock", 0x0052],
3566
- time_ring: ["closuresDoorLock", 0x0053],
3567
- time_talk: ["closuresDoorLock", 0x0054],
3568
- time_open: ["closuresDoorLock", 0x0055],
3569
- time_bell: ["closuresDoorLock", 0x0057],
3570
- time_report: ["closuresDoorLock", 0x0056],
3559
+ mode: 0x0051,
3560
+ sound: 0x0052,
3561
+ time_ring: 0x0053,
3562
+ time_talk: 0x0054,
3563
+ time_open: 0x0055,
3564
+ time_bell: 0x0057,
3565
+ time_report: 0x0056,
3571
3566
  };
3572
3567
  const v = utils.getFromLookup(key, payloads);
3573
- await entity.read(v[0], [v[1]]);
3568
+ await entity.read("closuresDoorLock", [v]);
3574
3569
  },
3575
3570
  };
3576
3571
  exports.power_source = {
@@ -3664,13 +3659,11 @@ exports.scene_store = {
3664
3659
  utils.saveSceneState(member, sceneid, groupid, meta.membersState[member.getDevice().ieeeAddr], scenename);
3665
3660
  }
3666
3661
  }
3667
- // @ts-expect-error ignore
3668
3662
  }
3669
3663
  else if (response.status === 0) {
3670
3664
  utils.saveSceneState(entity, sceneid, groupid, meta.state, scenename);
3671
3665
  }
3672
3666
  else {
3673
- // @ts-expect-error ignore
3674
3667
  throw new Error(`Scene add not successful ('${zigbee_herdsman_1.Zcl.Status[response.status]}')`);
3675
3668
  }
3676
3669
  logger_1.logger.info("Successfully stored scene", NS);
@@ -3892,13 +3885,11 @@ exports.scene_remove = {
3892
3885
  utils.deleteSceneState(member, sceneid, groupid);
3893
3886
  }
3894
3887
  }
3895
- // @ts-expect-error ignore
3896
3888
  }
3897
3889
  else if (response.status === 0) {
3898
3890
  utils.deleteSceneState(entity, sceneid, groupid);
3899
3891
  }
3900
3892
  else {
3901
- // @ts-expect-error ignore
3902
3893
  throw new Error(`Scene remove not successful ('${zigbee_herdsman_1.Zcl.Status[response.status]}')`);
3903
3894
  }
3904
3895
  logger_1.logger.info("Successfully removed scene", NS);
@@ -4109,7 +4100,7 @@ exports.viessmann_window_open_force = {
4109
4100
  key: ["window_open_force"],
4110
4101
  convertSet: async (entity, key, value, meta) => {
4111
4102
  if (typeof value === "boolean") {
4112
- await entity.write("hvacThermostat", { viessmannWindowOpenForce: value }, manufacturerOptions.viessmann);
4103
+ await entity.write("hvacThermostat", { viessmannWindowOpenForce: value ? 1 : 0 }, manufacturerOptions.viessmann);
4113
4104
  return { state: { window_open_force: value } };
4114
4105
  }
4115
4106
  logger_1.logger.error("window_open_force must be a boolean!", NS);
@@ -4128,11 +4119,9 @@ exports.dawondns_only_off = {
4128
4119
  key: ["state"],
4129
4120
  convertSet: async (entity, key, value, meta) => {
4130
4121
  utils.assertString(value, key);
4131
- // biome-ignore lint/style/noParameterAssign: ignored using `--suppress`
4132
- value = value.toLowerCase();
4133
- utils.assertString(value, key);
4134
- utils.validateValue(value, ["off"]);
4135
- await entity.command("genOnOff", value, {}, utils.getOptions(meta.mapped, entity));
4122
+ const lowerValue = value.toLowerCase();
4123
+ utils.validateValue(lowerValue, ["off"]);
4124
+ await entity.command("genOnOff", lowerValue, {}, utils.getOptions(meta.mapped, entity));
4136
4125
  },
4137
4126
  convertGet: async (entity, key, meta) => {
4138
4127
  await entity.read("genOnOff", ["onOff"]);
@@ -4220,8 +4209,7 @@ exports.schneider_dimmer_mode = {
4220
4209
  exports.wiser_dimmer_mode = {
4221
4210
  key: ["dimmer_mode"],
4222
4211
  convertSet: async (entity, key, value, meta) => {
4223
- const controlMode = utils.getKey(constants.wiserDimmerControlMode, value, value, Number);
4224
- await entity.write("lightingBallastCfg", { wiserControlMode: controlMode }, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC });
4212
+ await entity.write("lightingBallastCfg", { wiserControlMode: utils.getKey(constants.wiserDimmerControlMode, value, value, Number) }, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC });
4225
4213
  return { state: { dimmer_mode: value } };
4226
4214
  },
4227
4215
  convertGet: async (entity, key, meta) => {
@@ -4366,17 +4354,15 @@ exports.wiser_sed_thermostat_local_temperature_calibration = {
4366
4354
  exports.wiser_sed_thermostat_keypad_lockout = {
4367
4355
  key: ["keypad_lockout"],
4368
4356
  convertSet: async (entity, key, value, meta) => {
4369
- const keypadLockout = utils.getKey(constants.keypadLockoutMode, value, value, Number);
4370
- await entity.write("hvacUserInterfaceCfg", { keypadLockout }, { srcEndpoint: 11, disableDefaultResponse: true });
4357
+ await entity.write("hvacUserInterfaceCfg", { keypadLockout: utils.getKey(constants.keypadLockoutMode, value, value, Number) }, { srcEndpoint: 11, disableDefaultResponse: true });
4371
4358
  return { state: { keypad_lockout: value } };
4372
4359
  },
4373
4360
  };
4374
4361
  exports.sihas_set_people = {
4375
4362
  key: ["people"],
4376
4363
  convertSet: async (entity, key, value, meta) => {
4377
- const payload = { presentValue: value };
4378
4364
  const endpoint = meta.device.endpoints.find((e) => e.supportsInputCluster("genAnalogInput"));
4379
- await endpoint.write("genAnalogInput", payload);
4365
+ await endpoint.write("genAnalogInput", { presentValue: value });
4380
4366
  },
4381
4367
  convertGet: async (entity, key, meta) => {
4382
4368
  const endpoint = meta.device.endpoints.find((e) => e.supportsInputCluster("genAnalogInput"));