zigbee-herdsman-converters 23.38.0 → 23.40.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 (81) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/converters/fromZigbee.js +11 -11
  3. package/dist/converters/fromZigbee.js.map +1 -1
  4. package/dist/converters/toZigbee.js +48 -48
  5. package/dist/converters/toZigbee.js.map +1 -1
  6. package/dist/devices/avatto.js +2 -2
  7. package/dist/devices/avatto.js.map +1 -1
  8. package/dist/devices/bitron.js +2 -2
  9. package/dist/devices/bitron.js.map +1 -1
  10. package/dist/devices/bosch.js +1 -1
  11. package/dist/devices/bosch.js.map +1 -1
  12. package/dist/devices/efekta.d.ts.map +1 -1
  13. package/dist/devices/efekta.js +0 -18
  14. package/dist/devices/efekta.js.map +1 -1
  15. package/dist/devices/gmmts.js +6 -6
  16. package/dist/devices/gmmts.js.map +1 -1
  17. package/dist/devices/iluminize.d.ts.map +1 -1
  18. package/dist/devices/iluminize.js +0 -23
  19. package/dist/devices/iluminize.js.map +1 -1
  20. package/dist/devices/index.d.ts.map +1 -1
  21. package/dist/devices/index.js +2 -0
  22. package/dist/devices/index.js.map +1 -1
  23. package/dist/devices/innr.d.ts.map +1 -1
  24. package/dist/devices/innr.js +2 -0
  25. package/dist/devices/innr.js.map +1 -1
  26. package/dist/devices/inovelli.js +14 -14
  27. package/dist/devices/inovelli.js.map +1 -1
  28. package/dist/devices/kmpcil.js +2 -2
  29. package/dist/devices/kmpcil.js.map +1 -1
  30. package/dist/devices/lixee.js +3 -3
  31. package/dist/devices/lixee.js.map +1 -1
  32. package/dist/devices/perenio.js +4 -4
  33. package/dist/devices/perenio.js.map +1 -1
  34. package/dist/devices/philips.js +1 -1
  35. package/dist/devices/philips.js.map +1 -1
  36. package/dist/devices/robb.d.ts.map +1 -1
  37. package/dist/devices/robb.js +1 -2
  38. package/dist/devices/robb.js.map +1 -1
  39. package/dist/devices/siglis.js +1 -1
  40. package/dist/devices/siglis.js.map +1 -1
  41. package/dist/devices/slacky_diy.js +3 -3
  42. package/dist/devices/slacky_diy.js.map +1 -1
  43. package/dist/devices/sonoff.js +4 -4
  44. package/dist/devices/sonoff.js.map +1 -1
  45. package/dist/devices/stello.d.ts +3 -0
  46. package/dist/devices/stello.d.ts.map +1 -0
  47. package/dist/devices/stello.js +106 -0
  48. package/dist/devices/stello.js.map +1 -0
  49. package/dist/devices/sunricher.d.ts.map +1 -1
  50. package/dist/devices/sunricher.js +96 -17
  51. package/dist/devices/sunricher.js.map +1 -1
  52. package/dist/devices/superled.js +1 -1
  53. package/dist/devices/superled.js.map +1 -1
  54. package/dist/devices/tuya.d.ts.map +1 -1
  55. package/dist/devices/tuya.js +7 -9
  56. package/dist/devices/tuya.js.map +1 -1
  57. package/dist/devices/ubisys.js +4 -4
  58. package/dist/devices/ubisys.js.map +1 -1
  59. package/dist/devices/xyzroe.js +3 -3
  60. package/dist/devices/xyzroe.js.map +1 -1
  61. package/dist/lib/color.js +16 -16
  62. package/dist/lib/color.js.map +1 -1
  63. package/dist/lib/ikea.js +1 -1
  64. package/dist/lib/ikea.js.map +1 -1
  65. package/dist/lib/legacy.js +5 -5
  66. package/dist/lib/legacy.js.map +1 -1
  67. package/dist/lib/light.js +4 -4
  68. package/dist/lib/light.js.map +1 -1
  69. package/dist/lib/lumi.d.ts.map +1 -1
  70. package/dist/lib/lumi.js +14 -16
  71. package/dist/lib/lumi.js.map +1 -1
  72. package/dist/lib/modernExtend.js +5 -5
  73. package/dist/lib/modernExtend.js.map +1 -1
  74. package/dist/lib/philips.js +6 -6
  75. package/dist/lib/philips.js.map +1 -1
  76. package/dist/lib/tuya.js +4 -4
  77. package/dist/lib/tuya.js.map +1 -1
  78. package/dist/lib/utils.js +5 -5
  79. package/dist/lib/utils.js.map +1 -1
  80. package/dist/models-index.json +1 -1
  81. package/package.json +2 -2
@@ -66,9 +66,9 @@ exports.on_off = {
66
66
  convertSet: async (entity, key, value, meta) => {
67
67
  const state = utils.isString(meta.message.state) ? meta.message.state.toLowerCase() : null;
68
68
  utils.validateValue(state, ["toggle", "off", "on"]);
69
- if (state === "on" && (meta.message.on_time !== undefined || meta.message.off_wait_time !== undefined)) {
70
- const onTime = meta.message.on_time !== undefined ? meta.message.on_time : 0;
71
- const offWaitTime = meta.message.off_wait_time !== undefined ? meta.message.off_wait_time : 0;
69
+ if (state === "on" && (meta.message.on_time != null || meta.message.off_wait_time != null)) {
70
+ const onTime = meta.message.on_time != null ? meta.message.on_time : 0;
71
+ const offWaitTime = meta.message.off_wait_time != null ? meta.message.off_wait_time : 0;
72
72
  if (typeof onTime !== "number") {
73
73
  throw Error("The on_time value must be a number!");
74
74
  }
@@ -166,7 +166,7 @@ exports.light_color = {
166
166
  command = "moveToSaturation";
167
167
  }
168
168
  }
169
- if (utils.isObject(value) && value.brightness !== undefined) {
169
+ if (utils.isObject(value) && value.brightness != null) {
170
170
  await entity.command("genLevelCtrl", "moveToLevelWithOnOff", { level: Number(value.brightness), transtime: utils.getTransition(entity, key, meta).time }, utils.getOptions(meta.mapped, entity));
171
171
  }
172
172
  await entity.command("lightingColorCtrl", command, zclData, utils.getOptions(meta.mapped, entity));
@@ -214,9 +214,9 @@ exports.read = {
214
214
  key: ["read"],
215
215
  convertSet: async (entity, key, value, meta) => {
216
216
  utils.assertObject(value, key);
217
- const result = await entity.read(value.cluster, value.attributes, value.options !== undefined ? value.options : {});
217
+ const result = await entity.read(value.cluster, value.attributes, value.options != null ? value.options : {});
218
218
  logger_1.logger.info(`Read result of '${value.cluster}': ${JSON.stringify(result)}`, NS);
219
- if (value.state_property !== undefined) {
219
+ if (value.state_property != null) {
220
220
  return { state: { [value.state_property]: result } };
221
221
  }
222
222
  },
@@ -226,7 +226,7 @@ exports.write = {
226
226
  convertSet: async (entity, key, value, meta) => {
227
227
  utils.assertObject(value, key);
228
228
  const options = utils.getOptions(meta.mapped, entity);
229
- if (value.options !== undefined) {
229
+ if (value.options != null) {
230
230
  Object.assign(options, value.options);
231
231
  }
232
232
  await entity.write(value.cluster, value.payload, options);
@@ -238,7 +238,7 @@ exports.command = {
238
238
  convertSet: async (entity, key, value, meta) => {
239
239
  utils.assertObject(value, key);
240
240
  const options = utils.getOptions(meta.mapped, entity);
241
- await entity.command(value.cluster, value.command, value.payload !== undefined ? value.payload : {}, options);
241
+ await entity.command(value.cluster, value.command, value.payload != null ? value.payload : {}, options);
242
242
  logger_1.logger.info(`Invoked '${value.cluster}.${value.command}' with payload '${JSON.stringify(value.payload)}'`, NS);
243
243
  },
244
244
  };
@@ -261,9 +261,9 @@ exports.zcl_command = {
261
261
  key: ["zclcommand"],
262
262
  convertSet: async (entity, key, value, meta) => {
263
263
  utils.assertObject(value, key);
264
- const payload = value.payload !== undefined ? value.payload : {};
264
+ const payload = value.payload != null ? value.payload : {};
265
265
  utils.assertEndpoint(entity);
266
- await entity.zclCommand(value.cluster, value.command, payload, value.options !== undefined ? value.options : {}, value.log_payload ?? {}, value.check_status ?? false, value.frametype ?? zigbee_herdsman_1.Zcl.FrameType.SPECIFIC);
266
+ await entity.zclCommand(value.cluster, value.command, payload, value.options ?? {}, value.log_payload ?? {}, value.check_status ?? false, value.frametype ?? zigbee_herdsman_1.Zcl.FrameType.SPECIFIC);
267
267
  if (value.logging ?? false) {
268
268
  logger_1.logger.info(`Invoked ZCL command ${value.cluster}.${value.command} with payload '${JSON.stringify(payload)}'`, NS);
269
269
  }
@@ -276,7 +276,7 @@ exports.arm_mode = {
276
276
  utils.assertObject(value, key);
277
277
  if (Array.isArray(meta.mapped))
278
278
  throw new Error("Not supported for groups");
279
- const isNotification = value.transaction !== undefined;
279
+ const isNotification = value.transaction != null;
280
280
  const modeSrc = isNotification ? constants.armNotification : constants.armMode;
281
281
  const mode = utils.getKey(modeSrc, value.mode, undefined, Number);
282
282
  if (mode === undefined) {
@@ -342,7 +342,7 @@ exports.light_color_options = {
342
342
  key: ["color_options"],
343
343
  convertSet: async (entity, key, value, meta) => {
344
344
  utils.assertObject(value, key);
345
- const options = value.execute_if_off !== undefined && value.execute_if_off ? 1 : 0;
345
+ const options = value.execute_if_off != null && value.execute_if_off ? 1 : 0;
346
346
  await entity.write("lightingColorCtrl", { options }, utils.getOptions(meta.mapped, entity));
347
347
  return { state: { color_options: value } };
348
348
  },
@@ -400,7 +400,7 @@ exports.pincode_lock = {
400
400
  utils.assertObject(value, key);
401
401
  const user = value.user;
402
402
  const userType = value.user_type || "unrestricted";
403
- const userEnabled = value.user_enabled !== undefined ? value.user_enabled : true;
403
+ const userEnabled = value.user_enabled != null ? value.user_enabled : true;
404
404
  const pinCode = value.pin_code;
405
405
  if (Number.isNaN(user))
406
406
  throw new Error("user must be numbers");
@@ -530,13 +530,13 @@ exports.warning = {
530
530
  // @ts-expect-error ignore
531
531
  level: value.level || "medium",
532
532
  // @ts-expect-error ignore
533
- strobe: value.strobe !== undefined ? value.strobe : true,
533
+ strobe: value.strobe != null ? value.strobe : true,
534
534
  // @ts-expect-error ignore
535
- duration: value.duration !== undefined ? value.duration : 10,
535
+ duration: value.duration != null ? value.duration : 10,
536
536
  // @ts-expect-error ignore
537
- strobeDutyCycle: value.strobe_duty_cycle !== undefined ? value.strobe_duty_cycle * 10 : 0,
537
+ strobeDutyCycle: value.strobe_duty_cycle != null ? value.strobe_duty_cycle * 10 : 0,
538
538
  // @ts-expect-error ignore
539
- strobeLevel: value.strobe_level !== undefined ? utils.getFromLookup(value.strobe_level, strobeLevel) : 1,
539
+ strobeLevel: value.strobe_level != null ? utils.getFromLookup(value.strobe_level, strobeLevel) : 1,
540
540
  };
541
541
  // biome-ignore lint/suspicious/noImplicitAnyLet: ignored using `--suppress`
542
542
  let info;
@@ -589,7 +589,7 @@ exports.squawk = {
589
589
  const values = {
590
590
  state: value.state,
591
591
  level: value.level || "very_high",
592
- strobe: value.strobe !== undefined ? value.strobe : false,
592
+ strobe: value.strobe != null ? value.strobe : false,
593
593
  };
594
594
  const info = utils.getFromLookup(values.state, state) + ((values.strobe ? 1 : 0) << 4) + (utils.getFromLookup(values.level, level) << 6);
595
595
  await entity.command("ssIasWd", "squawk", { squawkinfo: info }, utils.getOptions(meta.mapped, entity));
@@ -674,7 +674,7 @@ exports.level_config = {
674
674
  }
675
675
  utils.assertObject(value, key);
676
676
  // onOffTransitionTime - range 0x0000 to 0xffff - optional
677
- if (value.on_off_transition_time !== undefined) {
677
+ if (value.on_off_transition_time != null) {
678
678
  let onOffTransitionTimeValue = Number(value.on_off_transition_time);
679
679
  if (onOffTransitionTimeValue > 65535)
680
680
  onOffTransitionTimeValue = 65535;
@@ -685,7 +685,7 @@ exports.level_config = {
685
685
  }
686
686
  // onTransitionTime - range 0x0000 to 0xffff - optional
687
687
  // 0xffff = use onOffTransitionTime
688
- if (value.on_transition_time !== undefined) {
688
+ if (value.on_transition_time != null) {
689
689
  let onTransitionTimeValue = value.on_transition_time;
690
690
  if (typeof onTransitionTimeValue === "string" && onTransitionTimeValue.toLowerCase() === "disabled") {
691
691
  onTransitionTimeValue = 65535;
@@ -706,7 +706,7 @@ exports.level_config = {
706
706
  }
707
707
  // offTransitionTime - range 0x0000 to 0xffff - optional
708
708
  // 0xffff = use onOffTransitionTime
709
- if (value.off_transition_time !== undefined) {
709
+ if (value.off_transition_time != null) {
710
710
  let offTransitionTimeValue = value.off_transition_time;
711
711
  if (typeof offTransitionTimeValue === "string" && offTransitionTimeValue.toLowerCase() === "disabled") {
712
712
  offTransitionTimeValue = 65535;
@@ -728,7 +728,7 @@ exports.level_config = {
728
728
  // startUpCurrentLevel - range 0x00 to 0xff - optional
729
729
  // 0x00 = return to minimum supported level
730
730
  // 0xff = return to previous previous
731
- if (value.current_level_startup !== undefined) {
731
+ if (value.current_level_startup != null) {
732
732
  let startUpCurrentLevelValue = value.current_level_startup;
733
733
  if (typeof startUpCurrentLevelValue === "string" && startUpCurrentLevelValue.toLowerCase() === "previous") {
734
734
  startUpCurrentLevelValue = 255;
@@ -755,7 +755,7 @@ exports.level_config = {
755
755
  }
756
756
  // onLevel - range 0x00 to 0xff - optional
757
757
  // Any value outside of MinLevel to MaxLevel, including 0xff and 0x00, is interpreted as "previous".
758
- if (value.on_level !== undefined) {
758
+ if (value.on_level != null) {
759
759
  let onLevel = value.on_level;
760
760
  if (typeof onLevel === "string" && onLevel.toLowerCase() === "previous") {
761
761
  onLevel = 255;
@@ -775,7 +775,7 @@ exports.level_config = {
775
775
  // when 1, CurrentLevel can be changed while the device is off.
776
776
  // bit 1: CoupleColorTempToLevel - when 1, changes to level also change color temperature.
777
777
  // (What this means is not defined, but it's most likely to be "dim to warm".)
778
- if (value.execute_if_off !== undefined) {
778
+ if (value.execute_if_off != null) {
779
779
  const executeIfOffValue = !!value.execute_if_off;
780
780
  await entity.write("genLevelCtrl", { options: executeIfOffValue ? 1 : 0 }, utils.getOptions(meta.mapped, entity));
781
781
  Object.assign(state, { execute_if_off: executeIfOffValue });
@@ -959,7 +959,7 @@ exports.light_colortemp_move = {
959
959
  const stop = (val) => ["stop", "release", "0"].some((el) => val.includes(el));
960
960
  const up = (val) => ["1", "up"].some((el) => val.includes(el));
961
961
  const arr = [value.toString()];
962
- const moverate = meta.message.rate !== undefined ? Number(meta.message.rate) : 55;
962
+ const moverate = meta.message.rate != null ? Number(meta.message.rate) : 55;
963
963
  payload.rate = moverate;
964
964
  if (arr.filter(stop).length) {
965
965
  payload.movemode = 0;
@@ -1054,12 +1054,12 @@ exports.light_onoff_brightness = {
1054
1054
  const { message } = meta;
1055
1055
  const transition = utils.getTransition(entity, "brightness", meta);
1056
1056
  const turnsOffAtBrightness1 = utils.getMetaValue(entity, meta.mapped, "turnsOffAtBrightness1", "allEqual", false);
1057
- let state = message.state !== undefined ? (typeof message.state === "string" ? message.state.toLowerCase() : null) : undefined;
1057
+ let state = message.state != null ? (typeof message.state === "string" ? message.state.toLowerCase() : null) : undefined;
1058
1058
  let brightness = undefined;
1059
- if (message.brightness !== undefined) {
1059
+ if (message.brightness != null) {
1060
1060
  brightness = Number(message.brightness);
1061
1061
  }
1062
- else if (message.brightness_percent !== undefined) {
1062
+ else if (message.brightness_percent != null) {
1063
1063
  brightness = utils.mapNumberRange(Number(message.brightness_percent), 0, 100, 0, 255);
1064
1064
  }
1065
1065
  if (brightness === 255) {
@@ -1333,10 +1333,10 @@ exports.thermostat_weekly_schedule = {
1333
1333
  // transform transition payload values if needed
1334
1334
  for (const elem of payload.transitions) {
1335
1335
  // update payload.mode if needed
1336
- if (elem.heatSetpoint !== undefined && !payload.mode.includes("heat")) {
1336
+ if (elem.heatSetpoint != null && !payload.mode.includes("heat")) {
1337
1337
  payload.mode.push("heat");
1338
1338
  }
1339
- if (elem.coolSetpoint !== undefined && !payload.mode.includes("cool")) {
1339
+ if (elem.coolSetpoint != null && !payload.mode.includes("cool")) {
1340
1340
  payload.mode.push("cool");
1341
1341
  }
1342
1342
  // transform setpoint values if numeric
@@ -1359,7 +1359,7 @@ exports.thermostat_weekly_schedule = {
1359
1359
  }
1360
1360
  }
1361
1361
  else if (typeof elem.transitionTime === "object") {
1362
- if (elem.transitionTime.hour === undefined || elem.transitionTime.minute === undefined) {
1362
+ if (elem.transitionTime.hour == null || elem.transitionTime.minute == null) {
1363
1363
  throw new Error(`weekly_schedule: expected 24h time object (e.g. {"hour": 19, "minute": 30}), but got '${JSON.stringify(elem.transitionTime)}'!`);
1364
1364
  }
1365
1365
  if (Number.isNaN(elem.transitionTime.hour)) {
@@ -1391,7 +1391,7 @@ exports.thermostat_weekly_schedule = {
1391
1391
  let dayofweek = 0;
1392
1392
  for (let d of payload.dayofweek) {
1393
1393
  if (typeof d === "object") {
1394
- if (d.day === undefined) {
1394
+ if (d.day == null) {
1395
1395
  throw new Error(`weekly_schedule: expected dayofweek to be string or {"day": "str"}, but got '${JSON.stringify(d)}'!`);
1396
1396
  }
1397
1397
  d = d.day;
@@ -2169,7 +2169,7 @@ exports.livolo_cover_options = {
2169
2169
  writeUndiv: true,
2170
2170
  transactionSequenceNumber: 0xe9,
2171
2171
  };
2172
- if (value.motor_direction !== undefined) {
2172
+ if (value.motor_direction != null) {
2173
2173
  // biome-ignore lint/suspicious/noImplicitAnyLet: ignored using `--suppress`
2174
2174
  let direction;
2175
2175
  switch (value.motor_direction) {
@@ -2186,7 +2186,7 @@ exports.livolo_cover_options = {
2186
2186
  const payload = { 4865: { value: [direction, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] } };
2187
2187
  await entity.write("genPowerCfg", payload, options);
2188
2188
  }
2189
- if (value.motor_speed !== undefined) {
2189
+ if (value.motor_speed != null) {
2190
2190
  if (value.motor_speed < 20 || value.motor_speed > 40) {
2191
2191
  throw new Error("livolo_cover_options: Motor speed is out of range (20-40)");
2192
2192
  }
@@ -2572,7 +2572,7 @@ exports.ZMCSW032D_cover_position = {
2572
2572
  key: ["position", "tilt"],
2573
2573
  convertSet: async (entity, key, value, meta) => {
2574
2574
  utils.assertNumber(value, key);
2575
- if (meta.options.time_close !== undefined && meta.options.time_open !== undefined) {
2575
+ if (meta.options.time_close != null && meta.options.time_open != null) {
2576
2576
  const sleepSeconds = async (s) => {
2577
2577
  return await new Promise((resolve) => setTimeout(resolve, s * 1000));
2578
2578
  };
@@ -2770,8 +2770,8 @@ exports.tuya_led_control = {
2770
2770
  convertSet: async (entity, key, value, meta) => {
2771
2771
  if (key === "brightness" &&
2772
2772
  meta.state.color_mode === constants.colorModeLookup[2] &&
2773
- meta.message.color === undefined &&
2774
- meta.message.color_temp === undefined) {
2773
+ meta.message.color == null &&
2774
+ meta.message.color_temp == null) {
2775
2775
  const zclData = { level: Number(value), transtime: 0 };
2776
2776
  await entity.command("genLevelCtrl", "moveToLevel", zclData, utils.getOptions(meta.mapped, entity));
2777
2777
  globalStore.putValue(entity, "brightness", zclData.level);
@@ -2836,7 +2836,7 @@ exports.tuya_led_control = {
2836
2836
  zclData.brightness = value;
2837
2837
  }
2838
2838
  }
2839
- if (meta.message.color !== undefined) {
2839
+ if (meta.message.color != null) {
2840
2840
  if (utils.isObject(meta.message.color)) {
2841
2841
  if (meta.message.color.h) {
2842
2842
  zclData.hue = utils.mapNumberRange(meta.message.color.h, 0, 360, 0, 254);
@@ -3548,7 +3548,7 @@ exports.scene_store = {
3548
3548
  key: ["scene_store"],
3549
3549
  convertSet: async (entity, key, value, meta) => {
3550
3550
  const isGroup = utils.isGroup(entity);
3551
- const groupid = isGroup ? entity.groupID : value.group_id !== undefined ? value.group_id : 0;
3551
+ const groupid = isGroup ? entity.groupID : value.group_id != null ? value.group_id : 0;
3552
3552
  let sceneid = value;
3553
3553
  let scenename = null;
3554
3554
  if (typeof value === "object") {
@@ -3641,14 +3641,14 @@ exports.scene_add = {
3641
3641
  convertSet: async (entity, key, value, meta) => {
3642
3642
  utils.assertObject(value);
3643
3643
  utils.assertNumber(value.ID, "ID");
3644
- if (value.color_temp !== undefined && value.color !== undefined) {
3644
+ if (value.color_temp != null && value.color != null) {
3645
3645
  throw new Error(`Don't specify both 'color_temp' and 'color'`);
3646
3646
  }
3647
3647
  const isGroup = utils.isGroup(entity);
3648
- const groupid = isGroup ? entity.groupID : value.group_id !== undefined ? value.group_id : 0;
3648
+ const groupid = isGroup ? entity.groupID : value.group_id != null ? value.group_id : 0;
3649
3649
  const sceneid = value.ID;
3650
3650
  const scenename = value.name;
3651
- const transtime = value.transition !== undefined ? value.transition : 0;
3651
+ const transtime = value.transition != null ? value.transition : 0;
3652
3652
  if (groupid === 0 && sceneid === 0) {
3653
3653
  // From Zigbee spec:
3654
3654
  // "Scene identifier 0x00, along with group identifier 0x0000, is reserved for the global scene used by the OnOff cluster"
@@ -3838,7 +3838,7 @@ exports.scene_rename = {
3838
3838
  const isGroup = utils.isGroup(entity);
3839
3839
  const sceneid = value.ID;
3840
3840
  const scenename = value.name;
3841
- const groupid = isGroup ? entity.groupID : value.group_id !== undefined ? value.group_id : 0;
3841
+ const groupid = isGroup ? entity.groupID : value.group_id != null ? value.group_id : 0;
3842
3842
  if (isGroup) {
3843
3843
  if (meta.membersState) {
3844
3844
  for (const member of entity.members) {
@@ -4324,7 +4324,7 @@ exports.light_onoff_restorable_brightness = {
4324
4324
  const deviceState = meta.state || {};
4325
4325
  const message = meta.message;
4326
4326
  const state = utils.isString(message.state) ? message.state.toLowerCase() : null;
4327
- const hasBrightness = message.brightness !== undefined || message.brightness_percent !== undefined;
4327
+ const hasBrightness = message.brightness != null || message.brightness_percent != null;
4328
4328
  // Add brightness if command is 'on' and we can restore previous value
4329
4329
  if (state === "on" && !hasBrightness && utils.isNumber(deviceState.brightness) && deviceState.brightness > 0) {
4330
4330
  message.brightness = deviceState.brightness;
@@ -4347,10 +4347,10 @@ exports.ptvo_switch_light_brightness = {
4347
4347
  if (entity.supportsInputCluster(cluster) || entity.supportsOutputCluster(cluster)) {
4348
4348
  const message = meta.message;
4349
4349
  let brightness = undefined;
4350
- if (message.brightness !== undefined) {
4350
+ if (message.brightness != null) {
4351
4351
  brightness = Number(message.brightness);
4352
4352
  }
4353
- else if (message.brightness_percent !== undefined)
4353
+ else if (message.brightness_percent != null)
4354
4354
  brightness = Math.round(Number(message.brightness_percent) * 2.55);
4355
4355
  if (brightness !== undefined && brightness === 0) {
4356
4356
  message.state = "off";
@@ -4402,10 +4402,10 @@ exports.TS110E_onoff_brightness = {
4402
4402
  key: ["state", "brightness"],
4403
4403
  convertSet: async (entity, key, value, meta) => {
4404
4404
  const { message, state } = meta;
4405
- if (message.state === "OFF" || (message.state !== undefined && message.brightness === undefined)) {
4405
+ if (message.state === "OFF" || (message.state != null && message.brightness == null)) {
4406
4406
  return await exports.on_off.convertSet(entity, key, value, meta);
4407
4407
  }
4408
- if (message.brightness !== undefined) {
4408
+ if (message.brightness != null) {
4409
4409
  // set brightness
4410
4410
  if (state.state === "OFF") {
4411
4411
  await entity.command("genOnOff", "on", {}, utils.getOptions(meta.mapped, entity));