zigbee-herdsman-converters 25.41.0 → 25.43.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 (54) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/converters/toZigbee.js +1 -1
  3. package/dist/converters/toZigbee.js.map +1 -1
  4. package/dist/devices/hoftronic.d.ts +3 -0
  5. package/dist/devices/hoftronic.d.ts.map +1 -0
  6. package/dist/devices/hoftronic.js +56 -0
  7. package/dist/devices/hoftronic.js.map +1 -0
  8. package/dist/devices/ikea.d.ts.map +1 -1
  9. package/dist/devices/ikea.js +1 -0
  10. package/dist/devices/ikea.js.map +1 -1
  11. package/dist/devices/index.d.ts.map +1 -1
  12. package/dist/devices/index.js +2 -0
  13. package/dist/devices/index.js.map +1 -1
  14. package/dist/devices/innr.d.ts.map +1 -1
  15. package/dist/devices/innr.js +14 -0
  16. package/dist/devices/innr.js.map +1 -1
  17. package/dist/devices/lumi.d.ts.map +1 -1
  18. package/dist/devices/lumi.js +14 -0
  19. package/dist/devices/lumi.js.map +1 -1
  20. package/dist/devices/namron.d.ts.map +1 -1
  21. package/dist/devices/namron.js +32 -15
  22. package/dist/devices/namron.js.map +1 -1
  23. package/dist/devices/nodon.d.ts.map +1 -1
  24. package/dist/devices/nodon.js +2 -0
  25. package/dist/devices/nodon.js.map +1 -1
  26. package/dist/devices/philips.d.ts.map +1 -1
  27. package/dist/devices/philips.js +8 -1
  28. package/dist/devices/philips.js.map +1 -1
  29. package/dist/devices/saswell.d.ts.map +1 -1
  30. package/dist/devices/saswell.js +1 -0
  31. package/dist/devices/saswell.js.map +1 -1
  32. package/dist/devices/shelly.d.ts.map +1 -1
  33. package/dist/devices/shelly.js +186 -6
  34. package/dist/devices/shelly.js.map +1 -1
  35. package/dist/devices/tuya.d.ts.map +1 -1
  36. package/dist/devices/tuya.js +175 -11
  37. package/dist/devices/tuya.js.map +1 -1
  38. package/dist/devices/zemismart.d.ts.map +1 -1
  39. package/dist/devices/zemismart.js +16 -0
  40. package/dist/devices/zemismart.js.map +1 -1
  41. package/dist/lib/exposes.d.ts +1 -1
  42. package/dist/lib/exposes.d.ts.map +1 -1
  43. package/dist/lib/exposes.js +1 -1
  44. package/dist/lib/exposes.js.map +1 -1
  45. package/dist/lib/lumi.d.ts +24 -0
  46. package/dist/lib/lumi.d.ts.map +1 -1
  47. package/dist/lib/lumi.js +191 -1
  48. package/dist/lib/lumi.js.map +1 -1
  49. package/dist/lib/tuya.d.ts +1 -0
  50. package/dist/lib/tuya.d.ts.map +1 -1
  51. package/dist/lib/tuya.js +1 -0
  52. package/dist/lib/tuya.js.map +1 -1
  53. package/dist/models-index.json +1 -1
  54. package/package.json +1 -1
package/dist/lib/lumi.js CHANGED
@@ -319,6 +319,9 @@ msg, meta, model, options, dataObject) => {
319
319
  else if (["RTCGQ15LM"].includes(model.model)) {
320
320
  payload.occupancy = value;
321
321
  }
322
+ else if (["PS-S04D"].includes(model.model)) {
323
+ payload.presence = value === 1;
324
+ }
322
325
  else if (["WSDCGQ01LM", "WSDCGQ11LM", "WSDCGQ12LM", "VOCKQJK11LM"].includes(model.model)) {
323
326
  // https://github.com/Koenkk/zigbee2mqtt/issues/798
324
327
  // Sometimes the sensor publishes non-realistic vales, filter these
@@ -411,7 +414,7 @@ msg, meta, model, options, dataObject) => {
411
414
  const battery = value / 2;
412
415
  payload.battery = (0, utils_1.precisionRound)(battery, 2);
413
416
  }
414
- else if (["RTCZCGQ11LM", "PS-S04D"].includes(model.model)) {
417
+ else if (["RTCZCGQ11LM"].includes(model.model)) {
415
418
  payload.presence = (0, utils_1.getFromLookup)(value, { 0: false, 1: true, 255: null });
416
419
  }
417
420
  else if (["ZNXDD01LM"].includes(model.model)) {
@@ -2337,6 +2340,32 @@ exports.lumiModernExtend = {
2337
2340
  ],
2338
2341
  };
2339
2342
  },
2343
+ fp1eAIInterference: () => {
2344
+ const attribute = { ID: 0x015e, type: 0x20 }; // Attribute: 350
2345
+ return modernExtend.binary({
2346
+ name: "ai_interference_source_selfidentification",
2347
+ valueOn: ["ON", 1],
2348
+ valueOff: ["OFF", 0],
2349
+ cluster: "manuSpecificLumi",
2350
+ attribute: attribute,
2351
+ description: "AI interference source self-identification switch, when enabled can identify fans, air conditioners and other interference sources",
2352
+ access: "ALL",
2353
+ zigbeeCommandOptions: { manufacturerCode: exports.manufacturerCode },
2354
+ });
2355
+ },
2356
+ fp1eAdaptiveSensitivity: () => {
2357
+ const attribute = { ID: 0x015d, type: 0x20 }; // Attribute: 349
2358
+ return modernExtend.binary({
2359
+ name: "ai_sensitivity_adaptive",
2360
+ valueOn: ["ON", 1],
2361
+ valueOff: ["OFF", 0],
2362
+ cluster: "manuSpecificLumi",
2363
+ attribute: attribute,
2364
+ description: "Adaptive sensitivity switch function.",
2365
+ access: "ALL",
2366
+ zigbeeCommandOptions: { manufacturerCode: exports.manufacturerCode },
2367
+ });
2368
+ },
2340
2369
  fp1ePresence: () => {
2341
2370
  const attribute = { ID: 0x0142, type: 0x20 };
2342
2371
  return modernExtend.binary({
@@ -4010,6 +4039,84 @@ exports.fromZigbee = {
4010
4039
  return result;
4011
4040
  },
4012
4041
  },
4042
+ w100_0844_req: {
4043
+ cluster: "manuSpecificLumi",
4044
+ type: ["attributeReport", "readResponse"],
4045
+ convert: (model, msg, publish, options, meta) => {
4046
+ const attr = msg.data[65522];
4047
+ if (!attr || !node_buffer_1.Buffer.isBuffer(attr))
4048
+ return;
4049
+ const endsWith = node_buffer_1.Buffer.from([0x08, 0x00, 0x08, 0x44]);
4050
+ if (attr.slice(-4).equals(endsWith)) {
4051
+ logger_1.logger.info(`Detected PMTSD request from device ${meta.device.ieeeAddr}`, NS);
4052
+ return { action: "data_request" };
4053
+ }
4054
+ },
4055
+ },
4056
+ pmtsd_from_w100: {
4057
+ cluster: "manuSpecificLumi",
4058
+ type: ["attributeReport", "readResponse"],
4059
+ convert: (model, msg, publish, options, meta) => {
4060
+ const data = msg.data[65522];
4061
+ if (!data || !node_buffer_1.Buffer.isBuffer(data))
4062
+ return;
4063
+ const endsWith = node_buffer_1.Buffer.from([0x08, 0x44]);
4064
+ const idx = data.indexOf(endsWith);
4065
+ if (idx === -1 || idx + 2 >= data.length)
4066
+ return;
4067
+ const payloadLen = data[idx + 2];
4068
+ const payloadStart = idx + 3;
4069
+ const payloadEnd = payloadStart + payloadLen;
4070
+ if (payloadEnd > data.length)
4071
+ return;
4072
+ const payloadBytes = data.slice(payloadStart, payloadEnd);
4073
+ let payloadAscii;
4074
+ try {
4075
+ payloadAscii = payloadBytes.toString("ascii");
4076
+ }
4077
+ catch {
4078
+ return;
4079
+ }
4080
+ const result = {};
4081
+ const partsForCombined = [];
4082
+ const pairs = payloadAscii.split("_");
4083
+ pairs.forEach((p) => {
4084
+ if (p.length >= 2) {
4085
+ const key = p[0];
4086
+ const value = p.slice(1);
4087
+ let newKey;
4088
+ switch (key) {
4089
+ case "p":
4090
+ newKey = "PW";
4091
+ break;
4092
+ case "m":
4093
+ newKey = "MW";
4094
+ break;
4095
+ case "t":
4096
+ newKey = "TW";
4097
+ break;
4098
+ case "s":
4099
+ newKey = "SW";
4100
+ break;
4101
+ case "d":
4102
+ newKey = "DW";
4103
+ break;
4104
+ default:
4105
+ newKey = `${key.toUpperCase()}W`;
4106
+ }
4107
+ result[newKey] = value;
4108
+ partsForCombined.push(`${newKey}${value}`);
4109
+ }
4110
+ });
4111
+ const ts = Date.now();
4112
+ const combinedString = partsForCombined.length ? `${ts}_${partsForCombined.join("_")}` : `${ts}`;
4113
+ logger_1.logger.info(`Decoded PMTSD: ${JSON.stringify(result)} from ${meta.device.ieeeAddr}`, NS);
4114
+ return {
4115
+ ...result,
4116
+ data: combinedString,
4117
+ };
4118
+ },
4119
+ },
4013
4120
  };
4014
4121
  exports.toZigbee = {
4015
4122
  // lumi generic
@@ -5554,5 +5661,88 @@ exports.toZigbee = {
5554
5661
  throw new Error(`Not supported: '${key}'`);
5555
5662
  },
5556
5663
  },
5664
+ pmtsd_to_w100: {
5665
+ key: ["PMTSD_to_W100"],
5666
+ convertSet: async (entity, key, value, meta) => {
5667
+ const { p, m, t, s, d } = value;
5668
+ const pmtsdStr = `P${p}_M${m}_T${t}_S${s}_D${d}`;
5669
+ const pmtsdBytes = Array.from(pmtsdStr).map((c) => c.charCodeAt(0));
5670
+ const pmtsdLen = pmtsdBytes.length;
5671
+ const fixedHeader = [
5672
+ 0xaa,
5673
+ 0x71,
5674
+ 0x1f,
5675
+ 0x44,
5676
+ 0x00,
5677
+ 0x00,
5678
+ 0x05,
5679
+ 0x41,
5680
+ 0x1c,
5681
+ 0x00,
5682
+ 0x00,
5683
+ 0x54,
5684
+ 0xef,
5685
+ 0x44,
5686
+ 0x80,
5687
+ 0x71,
5688
+ 0x1a,
5689
+ 0x08,
5690
+ 0x00,
5691
+ 0x08,
5692
+ 0x44,
5693
+ pmtsdLen,
5694
+ ];
5695
+ const counter = Math.floor(Math.random() * 256);
5696
+ fixedHeader[4] = counter;
5697
+ const fullPayload = [...fixedHeader, ...pmtsdBytes];
5698
+ const checksum = fullPayload.reduce((sum, b) => sum + b, 0) & 0xff;
5699
+ fullPayload[5] = checksum;
5700
+ await entity.write(64704, { 65522: { value: node_buffer_1.Buffer.from(fullPayload), type: 65 } }, { manufacturerCode: 4447, disableDefaultResponse: true });
5701
+ logger_1.logger.info(`PMTSD frame sent: ${pmtsdStr} (Counter: ${counter}, Checksum: ${checksum})`, NS);
5702
+ return {};
5703
+ },
5704
+ },
5705
+ thermostat_mode: {
5706
+ key: ["mode"],
5707
+ convertSet: async (entity, key, value, meta) => {
5708
+ const deviceMac = meta.device.ieeeAddr.replace(/^0x/, "").toLowerCase();
5709
+ const hubMac = "54ef4480711a";
5710
+ function cleanMac(mac, expectedLen) {
5711
+ const cleaned = mac.replace(/[:-]/g, "");
5712
+ if (cleaned.length !== expectedLen) {
5713
+ throw new Error(`MAC must be ${expectedLen} hex digits`);
5714
+ }
5715
+ return cleaned;
5716
+ }
5717
+ const dev = node_buffer_1.Buffer.from(cleanMac(deviceMac, 16), "hex");
5718
+ const hub = node_buffer_1.Buffer.from(cleanMac(hubMac, 12), "hex");
5719
+ let frame;
5720
+ if (value === "ON") {
5721
+ const prefix = node_buffer_1.Buffer.concat([
5722
+ node_buffer_1.Buffer.from("aa713244", "hex"),
5723
+ node_buffer_1.Buffer.from([Math.floor(Math.random() * 256), Math.floor(Math.random() * 256)]),
5724
+ ]);
5725
+ const zigbeeHeader = node_buffer_1.Buffer.from("02412f6891", "hex");
5726
+ const messageId = node_buffer_1.Buffer.from([Math.floor(Math.random() * 256), Math.floor(Math.random() * 256)]);
5727
+ const control = node_buffer_1.Buffer.from([0x18]);
5728
+ const payloadMacs = node_buffer_1.Buffer.concat([dev, node_buffer_1.Buffer.from("0000", "hex"), hub]);
5729
+ const payloadTail = node_buffer_1.Buffer.from("08000844150a0109e7a9bae8b083e58a9f000000000001012a40", "hex");
5730
+ frame = node_buffer_1.Buffer.concat([prefix, zigbeeHeader, messageId, control, payloadMacs, payloadTail]);
5731
+ }
5732
+ else {
5733
+ const prefix = node_buffer_1.Buffer.from([0xaa, 0x71, 0x1c, 0x44, 0x69, 0x1c, 0x04, 0x41, 0x19, 0x68, 0x91]);
5734
+ const frameId = node_buffer_1.Buffer.from([Math.floor(Math.random() * 256)]);
5735
+ const seq = node_buffer_1.Buffer.from([Math.floor(Math.random() * 256)]);
5736
+ const control = node_buffer_1.Buffer.from([0x18]);
5737
+ frame = node_buffer_1.Buffer.concat([prefix, frameId, seq, control, dev]);
5738
+ if (frame.length < 34) {
5739
+ frame = node_buffer_1.Buffer.concat([frame, node_buffer_1.Buffer.alloc(34 - frame.length, 0x00)]);
5740
+ }
5741
+ }
5742
+ await entity.write(64704, { 65522: { value: frame, type: 0x41 } }, { manufacturerCode: 4447, disableDefaultResponse: true });
5743
+ logger_1.logger.info(`Thermostat_Mode=${value} payload=${frame.toString("hex")}`, NS);
5744
+ return {};
5745
+ },
5746
+ },
5557
5747
  };
5558
5748
  //# sourceMappingURL=lumi.js.map