zigbee-herdsman-converters 25.100.0 → 25.102.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.
@@ -1 +1 @@
1
- {"version":3,"file":"tuya.d.ts","sourceRoot":"","sources":["../../src/devices/tuya.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAC,oBAAoB,EAA4D,MAAM,cAAc,CAAC;AAq2ClH,eAAO,MAAM,WAAW,EAAE,oBAAoB,EA2rqB7C,CAAC"}
1
+ {"version":3,"file":"tuya.d.ts","sourceRoot":"","sources":["../../src/devices/tuya.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAC,oBAAoB,EAA4D,MAAM,cAAc,CAAC;AAq2ClH,eAAO,MAAM,WAAW,EAAE,oBAAoB,EAgxqB7C,CAAC"}
@@ -2471,6 +2471,23 @@ exports.definitions = [
2471
2471
  toZigbee: [],
2472
2472
  exposes: [e.temperature(), e.humidity(), e.co2(), e.voc().withUnit("ppb"), e.formaldehyd().withUnit("µg/m³")],
2473
2473
  },
2474
+ {
2475
+ fingerprint: tuya.fingerprint("TS0601", ["_TZE284_8b9zpaav"]),
2476
+ model: "TS0601_airbox",
2477
+ vendor: "Tuya",
2478
+ description: "zigbee air quality sensor",
2479
+ extend: [tuya.modernExtend.tuyaBase({ dp: true })],
2480
+ exposes: [e.temperature(), e.humidity(), e.co2(), e.voc().withUnit("ppb"), e.formaldehyd().withUnit("µg/m³")],
2481
+ meta: {
2482
+ tuyaDatapoints: [
2483
+ [2, "co2", tuya.valueConverter.raw],
2484
+ [18, "temperature", tuya.valueConverter.divideBy10],
2485
+ [19, "humidity", tuya.valueConverter.raw],
2486
+ [21, "voc", tuya.valueConverter.divideBy100],
2487
+ [22, "formaldehyd", tuya.valueConverter.divideBy100],
2488
+ ],
2489
+ },
2490
+ },
2474
2491
  {
2475
2492
  fingerprint: tuya.fingerprint("TS0601", ["_TZE200_rbbx5mfq", "_TZE204_rbbx5mfq"]),
2476
2493
  model: "TS0601_illuminance_temperature_humidity_sensor_2",
@@ -3328,7 +3345,7 @@ exports.definitions = [
3328
3345
  "_TZ3000_n0lphcok",
3329
3346
  "_TZ3000_r80pzsb9",
3330
3347
  ]),
3331
- ...tuya.fingerprint("TS0001", ["_TZ3000_n0lphcok", "_TZ3000_wn65ixz9", "_TZ3000_trdx8uxs"]),
3348
+ ...tuya.fingerprint("TS0001", ["_TZ3000_n0lphcok", "_TZ3000_wn65ixz9", "_TZ3000_trdx8uxs", "_TZ3000_gdsvhfao"]),
3332
3349
  ],
3333
3350
  model: "TS0207_repeater",
3334
3351
  vendor: "Tuya",
@@ -3336,7 +3353,12 @@ exports.definitions = [
3336
3353
  fromZigbee: [fz.linkquality_from_basic],
3337
3354
  toZigbee: [],
3338
3355
  whiteLabel: [
3339
- tuya.whitelabel("Tuya", "TS0001_repeater", "Zigbee signal repeater", ["_TZ3000_n0lphcok", "_TZ3000_wn65ixz9", "_TZ3000_trdx8uxs"]),
3356
+ tuya.whitelabel("Tuya", "TS0001_repeater", "Zigbee signal repeater", [
3357
+ "_TZ3000_n0lphcok",
3358
+ "_TZ3000_wn65ixz9",
3359
+ "_TZ3000_trdx8uxs",
3360
+ "_TZ3000_gdsvhfao",
3361
+ ]),
3340
3362
  ],
3341
3363
  exposes: [],
3342
3364
  },
@@ -3937,7 +3959,7 @@ exports.definitions = [
3937
3959
  ],
3938
3960
  },
3939
3961
  {
3940
- fingerprint: tuya.fingerprint("TS0601", ["_TZE204_dcnsggvz", "_TZE200_dcnsggv"]),
3962
+ fingerprint: tuya.fingerprint("TS0601", ["_TZE204_dcnsggvz", "_TZE200_dcnsggv", "_TZE200_dcnsggvz"]),
3941
3963
  model: "TS0601_dimmer_5",
3942
3964
  vendor: "Tuya",
3943
3965
  description: "1 gang smart dimmer module",
@@ -5186,34 +5208,56 @@ exports.definitions = [
5186
5208
  },
5187
5209
  {
5188
5210
  fingerprint: tuya.fingerprint("TS0601", ["_TZE200_dzuqwsyg", "_TZE204_dzuqwsyg"]),
5189
- model: "BAC-002",
5211
+ model: "BAC-003",
5190
5212
  vendor: "Tuya",
5191
5213
  description: "FCU thermostat temperature controller",
5192
5214
  extend: [tuya.modernExtend.tuyaBase({ dp: true, forceTimeUpdates: true, timeStart: "1970" })],
5193
5215
  options: [
5194
- e.enum("control_sequence_of_operation", ea.SET, ["cooling_only", "cooling_and_heating_4-pipes"]),
5195
- e.binary("expose_device_state", ea.SET, true, false),
5196
- ],
5197
- exposes: [
5198
5216
  e
5199
- .climate()
5200
- .withLocalTemperature(ea.STATE)
5201
- .withSystemMode(["off", "cool", "heat", "fan_only"], ea.STATE_SET)
5202
- .withFanMode(["low", "medium", "high", "auto"], ea.STATE_SET)
5203
- .withSetpoint("current_heating_setpoint", 5, 35, 1, ea.STATE_SET)
5204
- .withPreset(["auto", "manual"])
5205
- .withLocalTemperatureCalibration(-9, 9, 1, ea.STATE_SET),
5206
- e.child_lock(),
5207
- e.max_temperature().withValueMin(35).withValueMax(45),
5208
- e.numeric("deadzone_temperature", ea.STATE_SET).withUnit("°C").withValueMax(5).withValueMin(1),
5209
- e.text("schedule_text", ea.STATE_SET).withDescription(`Weekly schedule in the format "HH:MM/TT HH:MM/TT ...".
5210
- Example for 12 segments:
5211
- "06:00/20 11:30/21 13:30/22 17:30/23 06:00/24 12:00/23 14:30/22 17:30/21 06:00/19 12:30/20 14:30/21 18:30/20".
5212
- Each segment contains:
5213
- - HH:MM: Time in 24-hour format.
5214
- - TT: Temperature in °C.
5215
- Ensure all 12 segments are defined and separated by spaces.`),
5217
+ .enum("control_sequence_of_operation", ea.SET, ["cooling_only", "cooling_and_heating_4-pipes"])
5218
+ .withDescription("Operating environment of the thermostat"),
5219
+ e.binary("expose_device_state", ea.SET, true, false).withDescription("Expose device power state as a separate property when enabled."),
5216
5220
  ],
5221
+ exposes: (device, options) => {
5222
+ const system_modes = ["off", "cool", "heat", "fan_only"];
5223
+ // Device can operate either in 2-pipe or 4-pipe configuration
5224
+ // For 2-pipe configurations remove 'heat' mode
5225
+ switch (options?.control_sequence_of_operation) {
5226
+ case "cooling_only":
5227
+ system_modes.splice(2, 1);
5228
+ break;
5229
+ }
5230
+ const exposes = [
5231
+ e
5232
+ .climate()
5233
+ .withLocalTemperature(ea.STATE)
5234
+ .withSystemMode(system_modes, ea.STATE_SET)
5235
+ .withFanMode(["low", "medium", "high", "auto"], ea.STATE_SET)
5236
+ .withSetpoint("current_heating_setpoint", 5, 35, 1, ea.STATE_SET)
5237
+ .withPreset(["auto", "manual"])
5238
+ .withLocalTemperatureCalibration(-3, 3, 1, ea.STATE_SET),
5239
+ e.child_lock(),
5240
+ e
5241
+ .composite("schedule", "schedule", ea.STATE_SET)
5242
+ .withFeature(e.text("weekdays", ea.SET).withDescription('Schedule (1-5), 4 periods in format "hh:mm/tt".'))
5243
+ .withFeature(e.text("saturday", ea.SET).withDescription('Schedule (6), 4 periods in format "hh:mm/tt".'))
5244
+ .withFeature(e.text("sunday", ea.SET).withDescription('Schedule (7), 4 periods in format "hh:mm/tt".'))
5245
+ .withDescription('Auto-mode schedule, 4 periods each per category. Example: "06:00/20 11:30/21 13:30/22 17:30/23.5".'),
5246
+ e.max_temperature().withValueMin(35).withValueMax(45).withPreset("default", 35, "Default value"),
5247
+ e
5248
+ .numeric("deadzone_temperature", ea.STATE_SET)
5249
+ .withUnit("°C")
5250
+ .withValueMax(5)
5251
+ .withValueMin(1)
5252
+ .withValueStep(1)
5253
+ .withPreset("default", 1, "Default value")
5254
+ .withDescription("The delta between local_temperature and current_heating_setpoint to trigger activity"),
5255
+ ];
5256
+ if (options?.expose_device_state === true) {
5257
+ exposes.unshift(e.binary("state", ea.STATE_SET, "ON", "OFF").withDescription("Turn the thermostat ON or OFF"));
5258
+ }
5259
+ return exposes;
5260
+ },
5217
5261
  meta: {
5218
5262
  publishDuplicateTransaction: true,
5219
5263
  tuyaDatapoints: [
@@ -5228,8 +5272,9 @@ Ensure all 12 segments are defined and separated by spaces.`),
5228
5272
  },
5229
5273
  from: (v, meta, options) => {
5230
5274
  meta.state.system_mode = v === true ? (meta.state.system_mode_device ?? "cool") : "off";
5231
- if (options?.expose_device_state === true)
5275
+ if (options?.expose_device_state === true) {
5232
5276
  return v === true ? "ON" : "OFF";
5277
+ }
5233
5278
  delete meta.state.state;
5234
5279
  },
5235
5280
  },
@@ -5238,22 +5283,22 @@ Ensure all 12 segments are defined and separated by spaces.`),
5238
5283
  2,
5239
5284
  "system_mode",
5240
5285
  {
5286
+ // Extend system_mode to support 'off' in addition to 'cool', 'heat' and 'fan_only'
5241
5287
  to: async (v, meta) => {
5242
- const ep = meta.device.endpoints[0];
5243
- if (v === "off") {
5244
- await tuya.sendDataPointBool(ep, 1, true, "dataRequest", 1);
5245
- await new Promise((r) => setTimeout(r, 120));
5246
- await tuya.sendDataPointBool(ep, 1, false, "dataRequest", 1);
5247
- await tuya.sendDataPointEnum(ep, 2, 0, "dataRequest", 1);
5248
- return;
5288
+ const entity = meta.device.endpoints[0];
5289
+ // Power State
5290
+ await tuya.sendDataPointBool(entity, 1, v !== "off", "dataRequest", 1);
5291
+ switch (v) {
5292
+ case "cool":
5293
+ await tuya.sendDataPointEnum(entity, 2, 0, "dataRequest", 1);
5294
+ break;
5295
+ case "heat":
5296
+ await tuya.sendDataPointEnum(entity, 2, 1, "dataRequest", 1);
5297
+ break;
5298
+ case "fan_only":
5299
+ await tuya.sendDataPointEnum(entity, 2, 2, "dataRequest", 1);
5300
+ break;
5249
5301
  }
5250
- await tuya.sendDataPointBool(ep, 1, true, "dataRequest", 1);
5251
- if (v === "cool")
5252
- await tuya.sendDataPointEnum(ep, 2, 0, "dataRequest", 1);
5253
- if (v === "heat")
5254
- await tuya.sendDataPointEnum(ep, 2, 1, "dataRequest", 1);
5255
- if (v === "fan_only")
5256
- await tuya.sendDataPointEnum(ep, 2, 2, "dataRequest", 1);
5257
5302
  },
5258
5303
  from: (v, meta) => {
5259
5304
  const modes = ["cool", "heat", "fan_only"];
@@ -5262,21 +5307,7 @@ Ensure all 12 segments are defined and separated by spaces.`),
5262
5307
  },
5263
5308
  },
5264
5309
  ],
5265
- [
5266
- 4,
5267
- "preset",
5268
- {
5269
- to: async (v, meta) => {
5270
- const ep = meta.device.endpoints[0];
5271
- await tuya.sendDataPointBool(ep, 4, v === "manual");
5272
- },
5273
- from: (v, meta) => {
5274
- const preset = v ? "manual" : "auto";
5275
- meta.state.preset = preset;
5276
- return preset;
5277
- },
5278
- },
5279
- ],
5310
+ [4, "preset", tuya.valueConverterBasic.lookup({ manual: true, auto: false })],
5280
5311
  [16, "current_heating_setpoint", tuya.valueConverter.raw],
5281
5312
  [19, "max_temperature", tuya.valueConverter.raw],
5282
5313
  [24, "local_temperature", tuya.valueConverter.divideBy10],
@@ -5297,39 +5328,46 @@ Ensure all 12 segments are defined and separated by spaces.`),
5297
5328
  101,
5298
5329
  "schedule",
5299
5330
  {
5300
- from: (v, meta) => {
5301
- const format = (data) => data.reduce((txt, val, i) => {
5302
- if (i % 3 === 0)
5303
- return `${txt}${i > 0 ? " " : ""}${val.toString().padStart(2, "0")}`;
5304
- if (i % 3 === 1)
5305
- return `${txt}:${val.toString().padStart(2, "0")}`;
5306
- return `${txt}/${val / 2}`;
5307
- }, "");
5308
- const weekdays = format(v.slice(0, 12));
5309
- const saturday = format(v.slice(12, 24));
5310
- const sunday = format(v.slice(24, 36));
5311
- const full = `${weekdays} ${saturday} ${sunday}`.trim();
5312
- meta.state.schedule_text = full;
5313
- return full;
5331
+ to: (v, meta) => {
5332
+ const periods = (value) => {
5333
+ const regex = /((?<h>[01][0-9]|2[0-3]):(?<m>[0-5][0-9])\/(?<t>[0-3][0-9](\.[0,5]|)))/gm;
5334
+ const matches = [...value.matchAll(regex)];
5335
+ if (matches.length === 4) {
5336
+ return matches.reduce((arr, m) => {
5337
+ arr.push(Number.parseInt(m.groups.h, 10));
5338
+ arr.push(Number.parseInt(m.groups.m, 10));
5339
+ arr.push(Number.parseFloat(m.groups.t) * 2);
5340
+ return arr;
5341
+ }, []);
5342
+ }
5343
+ logger_1.logger.warning("Ignoring invalid or incomplete schedule", NS);
5344
+ };
5345
+ const schedule = [...periods(v.weekdays), ...periods(v.saturday), ...periods(v.sunday)];
5346
+ return schedule;
5314
5347
  },
5315
- },
5316
- ],
5317
- [
5318
- 202,
5319
- "schedule_text",
5320
- {
5321
- to: async (v, meta) => {
5322
- const regex = /((?<h>[01][0-9]|2[0-3]):(?<m>[0-5][0-9])\/(?<t>[0-3]?[0-9](\.[0,5])?))/gm;
5323
- const matches = [...v.matchAll(regex)];
5324
- if (matches.length !== 12)
5325
- return;
5326
- const result = [];
5327
- for (const m of matches) {
5328
- result.push(Number(m.groups?.h));
5329
- result.push(Number(m.groups?.m));
5330
- result.push(Number(m.groups?.t) * 2);
5331
- }
5332
- await tuya.sendDataPointRaw(meta.device.endpoints[0], 101, Buffer.from(result));
5348
+ from: (v, meta) => {
5349
+ const format = (data) => {
5350
+ return data.reduce((a, v, i) => {
5351
+ switch (i % 3) {
5352
+ // Hour
5353
+ case 0:
5354
+ return `${a}${i > 0 ? " " : ""}${v.toString().padStart(2, "0")}`;
5355
+ // Minute
5356
+ case 1:
5357
+ return `${a}:${v.toString().padStart(2, "0")}`;
5358
+ // Setpoint
5359
+ case 2:
5360
+ return `${a}/${v / 2}`;
5361
+ default:
5362
+ throw new Error(`Unexpected index ${i} in schedule data`);
5363
+ }
5364
+ }, "");
5365
+ };
5366
+ return {
5367
+ weekdays: format(v.slice(0, 12)),
5368
+ saturday: format(v.slice(1 * 12, 2 * 12)),
5369
+ sunday: format(v.slice(2 * 12, 3 * 12)),
5370
+ };
5333
5371
  },
5334
5372
  },
5335
5373
  ],
@@ -5584,9 +5622,6 @@ Ensure all 12 segments are defined and separated by spaces.`),
5584
5622
  "_TZ3000_eei0ubpy",
5585
5623
  "_TZ3000_qaa59zqd",
5586
5624
  "_TZ3000_lmlsduws",
5587
- "_TZ3000_lugaswf8",
5588
- "_TZ3000_nuenzetq",
5589
- "_TZ3000_ruldv5dt",
5590
5625
  "_TZ3000_fbjdkph9",
5591
5626
  "_TZ3000_zbfya6h0",
5592
5627
  "_TZ3000_hznzbl0x",
@@ -5599,7 +5634,6 @@ Ensure all 12 segments are defined and separated by spaces.`),
5599
5634
  tuya.whitelabel("Moes", "ZM-104B-M", "2 gang switch", ["_TZ3000_qaa59zqd"]),
5600
5635
  tuya.whitelabel("pcblab.io", "RR620ZB", "2 gang Zigbee switch module", ["_TZ3000_4xfqlgqo"]),
5601
5636
  tuya.whitelabel("Nous", "L13Z", "2 gang switch", ["_TZ3000_ruxexjfz", "_TZ3000_hojntt34"]),
5602
- tuya.whitelabel("Tuya", "ZG-2002-RF", "Three mode Zigbee Switch", ["_TZ3000_lugaswf8", "_TZ3000_nuenzetq", "_TZ3000_ruldv5dt"]),
5603
5637
  tuya.whitelabel("Mercator Ikuü", "SSW02", "2 gang switch", ["_TZ3000_fbjdkph9"]),
5604
5638
  tuya.whitelabel("Aubess", "TMZ02", "2 gang switch", ["_TZ3000_lmlsduws"]),
5605
5639
  tuya.whitelabel("RSH", "TS0002_basic_2", "2 gang switch", ["_TZ3000_zbfya6h0"]),
@@ -5700,6 +5734,7 @@ Ensure all 12 segments are defined and separated by spaces.`),
5700
5734
  tuya.whitelabel("PSMART", "T462", "2 Gang switch with backlight, countdown, inching", ["_TZ3000_wnzoyohq"]),
5701
5735
  tuya.whitelabel("Nova Digital", "FZB-2", "2-Gang switch with backlight, countdown and inching", ["_TZ3000_5ksufhqi"]),
5702
5736
  tuya.whitelabel("iHseno", "_TZ3000_zxrfobzw", "2-gang touch switch", ["_TZ3000_zxrfobzw"]),
5737
+ tuya.whitelabel("Tuya", "ZG-2002-RF", "Three mode Zigbee Switch", ["_TZ3000_lugaswf8", "_TZ3000_nuenzetq", "_TZ3000_ruldv5dt"]),
5703
5738
  ],
5704
5739
  },
5705
5740
  {
@@ -16175,7 +16210,7 @@ Ensure all 12 segments are defined and separated by spaces.`),
16175
16210
  },
16176
16211
  },
16177
16212
  {
16178
- fingerprint: tuya.fingerprint("TS0004", ["_TZ3000_5ajpkyq6", "_TZ3000_knoj8lpk"]),
16213
+ fingerprint: tuya.fingerprint("TS0004", ["_TZ3000_5ajpkyq6", "_TZ3000_knoj8lpk", "_TZ3000_3n2minvf"]),
16179
16214
  model: "TS0004_switch_module_2",
16180
16215
  vendor: "Tuya",
16181
16216
  description: "4 gang switch module",
@@ -16199,7 +16234,7 @@ Ensure all 12 segments are defined and separated by spaces.`),
16199
16234
  await reporting.bind(device.getEndpoint(4), coordinatorEndpoint, ["genOnOff"]);
16200
16235
  },
16201
16236
  whiteLabel: [
16202
- tuya.whitelabel("AVATTO", "ZWSM16-4-Zigbee", "4 gang switch module", ["_TZ3000_5ajpkyq6"]),
16237
+ tuya.whitelabel("AVATTO", "ZWSM16-4-Zigbee", "4 gang switch module", ["_TZ3000_5ajpkyq6", "_TZ3000_3n2minvf"]),
16203
16238
  tuya.whitelabel("iHseno", "_TZ3000_knoj8lpk", "4 gang switch module", ["_TZ3000_knoj8lpk"]),
16204
16239
  ],
16205
16240
  },
@@ -18670,6 +18705,61 @@ Ensure all 12 segments are defined and separated by spaces.`),
18670
18705
  ],
18671
18706
  },
18672
18707
  },
18708
+ {
18709
+ fingerprint: tuya.fingerprint("TS0601", ["_TZE284_mxujdmxo"]),
18710
+ model: "ME202WZ",
18711
+ vendor: "Tuya",
18712
+ description: "Water level sensor",
18713
+ extend: [tuya.modernExtend.tuyaBase({ dp: true, forceTimeUpdates: true })],
18714
+ exposes: [
18715
+ e.enum("liquid_state", ea.STATE, ["low", "normal", "high"]).withDescription("Liquid level status"),
18716
+ e.numeric("liquid_depth", ea.STATE).withUnit("m").withDescription("Liquid Depth"),
18717
+ e.numeric("power_level", ea.STATE).withUnit("V").withDescription("Power supply voltage"),
18718
+ e
18719
+ .numeric("max_set", ea.STATE_SET)
18720
+ .withUnit("%")
18721
+ .withDescription("Liquid max percentage")
18722
+ .withValueMin(0)
18723
+ .withValueMax(100)
18724
+ .withValueStep(1),
18725
+ e
18726
+ .numeric("mini_set", ea.STATE_SET)
18727
+ .withUnit("%")
18728
+ .withDescription("Liquid minimal percentage")
18729
+ .withValueMin(0)
18730
+ .withValueMax(100)
18731
+ .withValueStep(1),
18732
+ e
18733
+ .numeric("liquid_depth_max", ea.STATE_SET)
18734
+ .withUnit("m")
18735
+ .withDescription("Height from sensor to liquid level")
18736
+ .withValueMin(0.1)
18737
+ .withValueMax(4)
18738
+ .withValueStep(0.01),
18739
+ e.numeric("liquid_level_percent", ea.STATE).withUnit("%").withDescription("Liquid level ratio"),
18740
+ e.text("version", ea.STATE_GET).withDescription("Device version"),
18741
+ ],
18742
+ meta: {
18743
+ tuyaDatapoints: [
18744
+ [
18745
+ 1,
18746
+ "liquid_state",
18747
+ tuya.valueConverterBasic.lookup({
18748
+ low: tuya.enum(1),
18749
+ normal: tuya.enum(0),
18750
+ high: tuya.enum(2),
18751
+ }),
18752
+ ],
18753
+ [2, "liquid_depth", tuya.valueConverter.divideBy100],
18754
+ [5, "power_level", tuya.valueConverter.divideBy10],
18755
+ [7, "max_set", tuya.valueConverter.raw],
18756
+ [8, "mini_set", tuya.valueConverter.raw],
18757
+ [21, "liquid_depth_max", tuya.valueConverter.divideBy100],
18758
+ [22, "liquid_level_percent", tuya.valueConverter.raw],
18759
+ [103, "version", tuya.valueConverter.raw],
18760
+ ],
18761
+ },
18762
+ },
18673
18763
  {
18674
18764
  fingerprint: [{ modelID: "TS0601", manufacturerName: "_TZE200_lvkk0hdg" }],
18675
18765
  model: "TLC2206",
@@ -22657,8 +22747,8 @@ Ensure all 12 segments are defined and separated by spaces.`),
22657
22747
  .withLocalTemperature(ea.STATE)
22658
22748
  .withLocalTemperatureCalibration(-9.9, 9.9, 0.1, ea.STATE_SET)
22659
22749
  .withSystemMode(["off", "heat"], ea.STATE_SET)
22660
- .withRunningState(["idle", "heat"], ea.STATE),
22661
- e.enum("preset", ea.STATE_SET, ["manual", "auto", "eco"]).withDescription("Preset mode: manual, auto or eco"),
22750
+ .withRunningState(["idle", "heat"], ea.STATE)
22751
+ .withPreset(["auto", "manual", "eco"]),
22662
22752
  e.child_lock(),
22663
22753
  e.battery(),
22664
22754
  e.enum("valve_state", ea.STATE, ["open", "close"]).withDescription("Valve state (open/close)"),