zigbee-herdsman-converters 25.104.0 → 25.105.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.
- package/CHANGELOG.md +26 -0
- package/dist/converters/actions.d.ts.map +1 -1
- package/dist/converters/actions.js +0 -2
- package/dist/converters/actions.js.map +1 -1
- package/dist/devices/envilar.js +1 -1
- package/dist/devices/istar.d.ts.map +1 -1
- package/dist/devices/istar.js +7 -0
- package/dist/devices/istar.js.map +1 -1
- package/dist/devices/lumi.d.ts.map +1 -1
- package/dist/devices/lumi.js +1 -0
- package/dist/devices/lumi.js.map +1 -1
- package/dist/devices/moes.js +1 -1
- package/dist/devices/moes.js.map +1 -1
- package/dist/devices/namron.d.ts.map +1 -1
- package/dist/devices/namron.js +9 -0
- package/dist/devices/namron.js.map +1 -1
- package/dist/devices/niko.d.ts.map +1 -1
- package/dist/devices/niko.js +8 -4
- package/dist/devices/niko.js.map +1 -1
- package/dist/devices/nous.js +2 -2
- package/dist/devices/nous.js.map +1 -1
- package/dist/devices/shelly.d.ts.map +1 -1
- package/dist/devices/shelly.js +21 -0
- package/dist/devices/shelly.js.map +1 -1
- package/dist/devices/sunricher.d.ts.map +1 -1
- package/dist/devices/sunricher.js +31 -84
- package/dist/devices/sunricher.js.map +1 -1
- package/dist/devices/tuya.d.ts.map +1 -1
- package/dist/devices/tuya.js +153 -86
- package/dist/devices/tuya.js.map +1 -1
- package/dist/lib/ubisys.d.ts.map +1 -1
- package/dist/lib/ubisys.js +2 -2
- package/dist/lib/ubisys.js.map +1 -1
- package/dist/models-index.json +1 -1
- package/package.json +1 -1
package/dist/devices/tuya.js
CHANGED
|
@@ -4311,6 +4311,33 @@ exports.definitions = [
|
|
|
4311
4311
|
],
|
|
4312
4312
|
},
|
|
4313
4313
|
},
|
|
4314
|
+
{
|
|
4315
|
+
fingerprint: tuya.fingerprint("TS0301", ["_TZE210_inpjmc0h"]),
|
|
4316
|
+
model: "TS0301_dual_rail",
|
|
4317
|
+
vendor: "Tuya",
|
|
4318
|
+
description: "Top-down bottom-up dual motor shade",
|
|
4319
|
+
extend: [tuya.modernExtend.tuyaBase({ dp: true }), m.deviceEndpoints({ endpoints: { bottom: 1, top: 1 } })],
|
|
4320
|
+
exposes: [
|
|
4321
|
+
e.cover_position().withEndpoint("bottom").withDescription("Bottom rail"),
|
|
4322
|
+
e.cover_position().withEndpoint("top").withDescription("Top rail"),
|
|
4323
|
+
e.battery(),
|
|
4324
|
+
],
|
|
4325
|
+
meta: {
|
|
4326
|
+
tuyaDatapoints: [
|
|
4327
|
+
// Bottom rail - DP109 is control, DP101 is set position, DP102 is current position
|
|
4328
|
+
[109, "state_bottom", tuya.valueConverterBasic.lookup({ OPEN: tuya.enum(0), CLOSE: tuya.enum(1), STOP: tuya.enum(2) })],
|
|
4329
|
+
[101, "position_bottom", tuya.valueConverter.coverPositionInverted],
|
|
4330
|
+
[102, "position_bottom", tuya.valueConverter.coverPositionInverted],
|
|
4331
|
+
// Top rail - DP1 is control, DP2 is set position, DP3 is current position
|
|
4332
|
+
// Note: State commands are reversed for Home Assistant compatibility with top-down operation
|
|
4333
|
+
[1, "state_top", tuya.valueConverterBasic.lookup({ OPEN: tuya.enum(1), CLOSE: tuya.enum(0), STOP: tuya.enum(2) })],
|
|
4334
|
+
[2, "position_top", tuya.valueConverter.coverPosition],
|
|
4335
|
+
[3, "position_top", tuya.valueConverter.coverPosition],
|
|
4336
|
+
// Battery
|
|
4337
|
+
[13, "battery", tuya.valueConverter.raw],
|
|
4338
|
+
],
|
|
4339
|
+
},
|
|
4340
|
+
},
|
|
4314
4341
|
{
|
|
4315
4342
|
fingerprint: tuya.fingerprint("TS0601", [
|
|
4316
4343
|
"_TZE200_aqnazj70",
|
|
@@ -5210,24 +5237,30 @@ exports.definitions = [
|
|
|
5210
5237
|
},
|
|
5211
5238
|
{
|
|
5212
5239
|
fingerprint: tuya.fingerprint("TS0601", ["_TZE200_dzuqwsyg", "_TZE204_dzuqwsyg"]),
|
|
5213
|
-
model: "BAC-
|
|
5240
|
+
model: "BAC-002-ALZB",
|
|
5214
5241
|
vendor: "Tuya",
|
|
5215
5242
|
description: "FCU thermostat temperature controller",
|
|
5216
5243
|
extend: [tuya.modernExtend.tuyaBase({ dp: true, forceTimeUpdates: true, timeStart: "1970" })],
|
|
5217
5244
|
options: [
|
|
5218
5245
|
e
|
|
5219
|
-
.enum("control_sequence_of_operation", ea.SET, ["cooling_only", "
|
|
5220
|
-
.
|
|
5221
|
-
|
|
5246
|
+
.enum("control_sequence_of_operation", ea.SET, ["cooling_only", "cooling_and_heating"])
|
|
5247
|
+
.withLabel("Device Configuration")
|
|
5248
|
+
.withDescription("Report either cooling and fan or cooling, heating and fan capability."),
|
|
5249
|
+
e
|
|
5250
|
+
.binary("expose_device_state", ea.SET, true, false)
|
|
5251
|
+
.withLabel("Expose device switch")
|
|
5252
|
+
.withDescription("Expose a separate on/off switch, instead of including it in system mode."),
|
|
5253
|
+
e
|
|
5254
|
+
.binary("wake_before_power_transition", ea.SET, true, false)
|
|
5255
|
+
.withLabel("Wake before Power Transition")
|
|
5256
|
+
.withDescription("Send a wake-up command before turning the device on or/off, required for some firmware revisions."),
|
|
5222
5257
|
],
|
|
5223
5258
|
exposes: (device, options) => {
|
|
5224
5259
|
const system_modes = ["off", "cool", "heat", "fan_only"];
|
|
5225
|
-
// Device can operate either in
|
|
5226
|
-
// For
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
system_modes.splice(2, 1);
|
|
5230
|
-
break;
|
|
5260
|
+
// Device can operate either in cooling or heating/cooling configuration
|
|
5261
|
+
// For cooling only configurations remove 'heat' mode
|
|
5262
|
+
if (options.control_sequence_of_operation === "cooling_only") {
|
|
5263
|
+
system_modes.splice(2, 1);
|
|
5231
5264
|
}
|
|
5232
5265
|
const exposes = [
|
|
5233
5266
|
e
|
|
@@ -5237,25 +5270,19 @@ exports.definitions = [
|
|
|
5237
5270
|
.withFanMode(["low", "medium", "high", "auto"], ea.STATE_SET)
|
|
5238
5271
|
.withSetpoint("current_heating_setpoint", 5, 35, 1, ea.STATE_SET)
|
|
5239
5272
|
.withPreset(["auto", "manual"])
|
|
5240
|
-
.withLocalTemperatureCalibration(-
|
|
5273
|
+
.withLocalTemperatureCalibration(-9, 9, 1, ea.STATE_SET),
|
|
5241
5274
|
e.child_lock(),
|
|
5242
|
-
e
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
.withUnit("°C")
|
|
5252
|
-
.withValueMax(5)
|
|
5253
|
-
.withValueMin(1)
|
|
5254
|
-
.withValueStep(1)
|
|
5255
|
-
.withPreset("default", 1, "Default value")
|
|
5256
|
-
.withDescription("The delta between local_temperature and current_heating_setpoint to trigger activity"),
|
|
5275
|
+
e.max_temperature().withValueMin(35).withValueMax(45),
|
|
5276
|
+
e.numeric("deadzone_temperature", ea.STATE_SET).withUnit("°C").withValueMax(5).withValueMin(0),
|
|
5277
|
+
e.text("schedule_text", ea.STATE_SET).withDescription(`Weekly schedule in the format "HH:MM/TT HH:MM/TT ...".
|
|
5278
|
+
Example for 12 segments:
|
|
5279
|
+
"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".
|
|
5280
|
+
Each segment contains:
|
|
5281
|
+
- HH:MM: Time in 24-hour format.
|
|
5282
|
+
- TT: Temperature in °C.
|
|
5283
|
+
Ensure all 12 segments are defined and separated by spaces.`),
|
|
5257
5284
|
];
|
|
5258
|
-
if (options
|
|
5285
|
+
if (options.expose_device_state === true) {
|
|
5259
5286
|
exposes.unshift(e.binary("state", ea.STATE_SET, "ON", "OFF").withDescription("Turn the thermostat ON or OFF"));
|
|
5260
5287
|
}
|
|
5261
5288
|
return exposes;
|
|
@@ -5268,15 +5295,14 @@ exports.definitions = [
|
|
|
5268
5295
|
"state",
|
|
5269
5296
|
{
|
|
5270
5297
|
to: async (v, meta) => {
|
|
5271
|
-
if (meta.options
|
|
5298
|
+
if (meta.options.expose_device_state === true) {
|
|
5272
5299
|
await tuya.sendDataPointBool(meta.device.endpoints[0], 1, utils.getFromLookup(v, { on: true, off: false }), "dataRequest", 1);
|
|
5273
5300
|
}
|
|
5274
5301
|
},
|
|
5275
5302
|
from: (v, meta, options) => {
|
|
5276
5303
|
meta.state.system_mode = v === true ? (meta.state.system_mode_device ?? "cool") : "off";
|
|
5277
|
-
if (options
|
|
5304
|
+
if (options.expose_device_state === true)
|
|
5278
5305
|
return v === true ? "ON" : "OFF";
|
|
5279
|
-
}
|
|
5280
5306
|
delete meta.state.state;
|
|
5281
5307
|
},
|
|
5282
5308
|
},
|
|
@@ -5285,22 +5311,29 @@ exports.definitions = [
|
|
|
5285
5311
|
2,
|
|
5286
5312
|
"system_mode",
|
|
5287
5313
|
{
|
|
5288
|
-
// Extend system_mode to support 'off' in addition to 'cool', 'heat' and 'fan_only'
|
|
5289
5314
|
to: async (v, meta) => {
|
|
5290
|
-
const
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
await tuya.
|
|
5302
|
-
|
|
5315
|
+
const ep = meta.device.endpoints[0];
|
|
5316
|
+
if (v === "off") {
|
|
5317
|
+
if (meta.options.wake_before_power_transition === true) {
|
|
5318
|
+
await tuya.sendDataPointBool(ep, 1, true, "dataRequest", 1);
|
|
5319
|
+
await new Promise((r) => setTimeout(r, 120));
|
|
5320
|
+
}
|
|
5321
|
+
await tuya.sendDataPointBool(ep, 1, false, "dataRequest", 1);
|
|
5322
|
+
return;
|
|
5323
|
+
}
|
|
5324
|
+
if (meta.options.wake_before_power_transition === true) {
|
|
5325
|
+
if (meta.state.system_mode === "off") {
|
|
5326
|
+
await tuya.sendDataPointBool(ep, 1, true, "dataRequest", 1);
|
|
5327
|
+
await new Promise((r) => setTimeout(r, 120));
|
|
5328
|
+
}
|
|
5303
5329
|
}
|
|
5330
|
+
await tuya.sendDataPointBool(ep, 1, true, "dataRequest", 1);
|
|
5331
|
+
if (v === "cool")
|
|
5332
|
+
await tuya.sendDataPointEnum(ep, 2, 0, "dataRequest", 1);
|
|
5333
|
+
if (v === "heat")
|
|
5334
|
+
await tuya.sendDataPointEnum(ep, 2, 1, "dataRequest", 1);
|
|
5335
|
+
if (v === "fan_only")
|
|
5336
|
+
await tuya.sendDataPointEnum(ep, 2, 2, "dataRequest", 1);
|
|
5304
5337
|
},
|
|
5305
5338
|
from: (v, meta) => {
|
|
5306
5339
|
const modes = ["cool", "heat", "fan_only"];
|
|
@@ -5309,7 +5342,21 @@ exports.definitions = [
|
|
|
5309
5342
|
},
|
|
5310
5343
|
},
|
|
5311
5344
|
],
|
|
5312
|
-
[
|
|
5345
|
+
[
|
|
5346
|
+
4,
|
|
5347
|
+
"preset",
|
|
5348
|
+
{
|
|
5349
|
+
to: async (v, meta) => {
|
|
5350
|
+
const ep = meta.device.endpoints[0];
|
|
5351
|
+
await tuya.sendDataPointBool(ep, 4, v === "manual");
|
|
5352
|
+
},
|
|
5353
|
+
from: (v, meta) => {
|
|
5354
|
+
const preset = v ? "manual" : "auto";
|
|
5355
|
+
meta.state.preset = preset;
|
|
5356
|
+
return preset;
|
|
5357
|
+
},
|
|
5358
|
+
},
|
|
5359
|
+
],
|
|
5313
5360
|
[16, "current_heating_setpoint", tuya.valueConverter.raw],
|
|
5314
5361
|
[19, "max_temperature", tuya.valueConverter.raw],
|
|
5315
5362
|
[24, "local_temperature", tuya.valueConverter.divideBy10],
|
|
@@ -5330,52 +5377,45 @@ exports.definitions = [
|
|
|
5330
5377
|
101,
|
|
5331
5378
|
"schedule",
|
|
5332
5379
|
{
|
|
5333
|
-
to: (v, meta) => {
|
|
5334
|
-
const periods = (value) => {
|
|
5335
|
-
const regex = /((?<h>[01][0-9]|2[0-3]):(?<m>[0-5][0-9])\/(?<t>[0-3][0-9](\.[0,5]|)))/gm;
|
|
5336
|
-
const matches = [...value.matchAll(regex)];
|
|
5337
|
-
if (matches.length === 4) {
|
|
5338
|
-
return matches.reduce((arr, m) => {
|
|
5339
|
-
arr.push(Number.parseInt(m.groups.h, 10));
|
|
5340
|
-
arr.push(Number.parseInt(m.groups.m, 10));
|
|
5341
|
-
arr.push(Number.parseFloat(m.groups.t) * 2);
|
|
5342
|
-
return arr;
|
|
5343
|
-
}, []);
|
|
5344
|
-
}
|
|
5345
|
-
logger_1.logger.warning("Ignoring invalid or incomplete schedule", NS);
|
|
5346
|
-
};
|
|
5347
|
-
const schedule = [...periods(v.weekdays), ...periods(v.saturday), ...periods(v.sunday)];
|
|
5348
|
-
return schedule;
|
|
5349
|
-
},
|
|
5350
5380
|
from: (v, meta) => {
|
|
5351
|
-
const format = (data) => {
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5381
|
+
const format = (data) => data.reduce((txt, val, i) => {
|
|
5382
|
+
if (i % 3 === 0)
|
|
5383
|
+
return `${txt}${i > 0 ? " " : ""}${val.toString().padStart(2, "0")}`;
|
|
5384
|
+
if (i % 3 === 1)
|
|
5385
|
+
return `${txt}:${val.toString().padStart(2, "0")}`;
|
|
5386
|
+
return `${txt}/${val / 2}`;
|
|
5387
|
+
}, "");
|
|
5388
|
+
const weekdays = format(v.slice(0, 12));
|
|
5389
|
+
const saturday = format(v.slice(12, 24));
|
|
5390
|
+
const sunday = format(v.slice(24, 36));
|
|
5391
|
+
const full = `${weekdays} ${saturday} ${sunday}`.trim();
|
|
5392
|
+
meta.state.schedule_text = full;
|
|
5393
|
+
return full;
|
|
5394
|
+
},
|
|
5395
|
+
},
|
|
5396
|
+
],
|
|
5397
|
+
[
|
|
5398
|
+
202,
|
|
5399
|
+
"schedule_text",
|
|
5400
|
+
{
|
|
5401
|
+
to: async (v, meta) => {
|
|
5402
|
+
const regex = /((?<h>[01][0-9]|2[0-3]):(?<m>[0-5][0-9])\/(?<t>[0-3]?[0-9](\.[0,5])?))/gm;
|
|
5403
|
+
const matches = [...v.matchAll(regex)];
|
|
5404
|
+
if (matches.length !== 12)
|
|
5405
|
+
return;
|
|
5406
|
+
const result = [];
|
|
5407
|
+
for (const m of matches) {
|
|
5408
|
+
result.push(Number(m.groups?.h));
|
|
5409
|
+
result.push(Number(m.groups?.m));
|
|
5410
|
+
result.push(Number(m.groups?.t) * 2);
|
|
5411
|
+
}
|
|
5412
|
+
await tuya.sendDataPointRaw(meta.device.endpoints[0], 101, Buffer.from(result));
|
|
5373
5413
|
},
|
|
5374
5414
|
},
|
|
5375
5415
|
],
|
|
5376
5416
|
],
|
|
5377
5417
|
},
|
|
5378
|
-
whiteLabel: [tuya.whitelabel("Tuya", "BAC-
|
|
5418
|
+
whiteLabel: [tuya.whitelabel("Tuya", "BAC-003", "FCU thermostat temperature controller", ["_TZE204_dzuqwsyg"])],
|
|
5379
5419
|
},
|
|
5380
5420
|
{
|
|
5381
5421
|
fingerprint: tuya.fingerprint("TS0601", ["_TZE200_qq9mpfhw"]),
|
|
@@ -16042,7 +16082,10 @@ exports.definitions = [
|
|
|
16042
16082
|
model: "BLE-YL01",
|
|
16043
16083
|
vendor: "Tuya",
|
|
16044
16084
|
description: "Smart WiFi Zigbee chlorine meter",
|
|
16045
|
-
whiteLabel: [
|
|
16085
|
+
whiteLabel: [
|
|
16086
|
+
tuya.whitelabel("Tuya", "YK-S03", "Smart pH and Chlorine Tester for Swimming Pool", ["_TZE200_d9mzkhoq"]),
|
|
16087
|
+
{ model: "YY-1099L", vendor: "Tuya" },
|
|
16088
|
+
],
|
|
16046
16089
|
// Don't query too often. Values are not always updated. https://github.com/Koenkk/zigbee2mqtt/issues/18704
|
|
16047
16090
|
extend: [
|
|
16048
16091
|
tuya.modernExtend.tuyaBase({
|
|
@@ -22790,6 +22833,30 @@ exports.definitions = [
|
|
|
22790
22833
|
],
|
|
22791
22834
|
},
|
|
22792
22835
|
},
|
|
22836
|
+
{
|
|
22837
|
+
fingerprint: tuya.fingerprint("TS0601", ["_TZE200_fphxkxue"]),
|
|
22838
|
+
model: "ZVL-PRO",
|
|
22839
|
+
vendor: "Nova Digital",
|
|
22840
|
+
description: "Water walve",
|
|
22841
|
+
extend: [tuya.modernExtend.tuyaBase({ dp: true })],
|
|
22842
|
+
exposes: [
|
|
22843
|
+
e.switch().setAccess("state", ea.STATE_SET),
|
|
22844
|
+
e.battery(),
|
|
22845
|
+
e.numeric("countdown", ea.STATE_SET).withUnit("s").withValueMin(0).withValueMax(86400).withDescription("Countdown time in seconds"),
|
|
22846
|
+
e.enum("work_state", ea.STATE, ["auto", "manual", "idle"]).withDescription("Current state of operation"),
|
|
22847
|
+
e.numeric("water_once", ea.STATE).withUnit("L").withDescription("Consumption from the last watering"),
|
|
22848
|
+
],
|
|
22849
|
+
meta: {
|
|
22850
|
+
tuyaDatapoints: [
|
|
22851
|
+
[1, "state", tuya.valueConverter.onOff],
|
|
22852
|
+
[7, "battery", tuya.valueConverter.raw],
|
|
22853
|
+
[11, "countdown", tuya.valueConverter.raw],
|
|
22854
|
+
[12, "work_state", tuya.valueConverter.raw],
|
|
22855
|
+
[5, "water_once", tuya.valueConverter.raw],
|
|
22856
|
+
[4, "fault", tuya.valueConverter.raw],
|
|
22857
|
+
],
|
|
22858
|
+
},
|
|
22859
|
+
},
|
|
22793
22860
|
{
|
|
22794
22861
|
fingerprint: tuya.fingerprint("TS0601", ["_TZE204_wc2w9t1s"]),
|
|
22795
22862
|
model: "BOT-R9V-ZB",
|