[External Converter]: Moes ZM7LT3 3-Phase Energy Power Meter (_TZE284_cf4b5ktf)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 15.7k
- Forks
- 2k
- Avg merge
- 18h 55m
- Merged PRs (30d)
- 35
Description
Link
https://aliexpress.com/item/1005012523225629.html
Database entry
{"id":29,"type":"Router","ieeeAddr":"0xa4c1384da9d1fa61","nwkAddr":24043,"manufId":4417,"manufName":"_TZE284_cf4b5ktf","powerSource":"Mains (single phase)","modelId":"TS0601","epList":[1,242],"endpoints":{"1":{"profId":260,"epId":1,"devId":81,"inClusterList":[4,5,61184,0,60672],"outClusterList":[25,10],"clusters":{"genBasic":{"attributes":{"65503":"��"2i"�"2i'�"2i,�"2i1�"2i6�"2i;�"2i@�"2i","65506":56,"65508":0,"65534":0,"modelId":"TS0601","manufacturerName":"_TZE284_cf4b5ktf","powerSource":1,"zclVersion":3,"appVersion":78,"stackVersion":0,"hwVersion":1,"dateCode":""}}},"binds":[],"configuredReportings":[],"meta":{}},"242":{"profId":41440,"epId":242,"devId":97,"inClusterList":[],"outClusterList":[33],"clusters":{},"binds":[],"configuredReportings":[],"meta":{}}},"appVersion":78,"stackVersion":0,"hwVersion":1,"dateCode":"","zclVersion":3,"interviewCompleted":true,"interviewState":"SUCCESSFUL","meta":{"configured":"0.0.0"},"lastSeen":1787828109955}
Zigbee2MQTT version
2.13.0 (fcbb7ff44bdc05a16e95d3472a81d110646cc17b
)
External converter
const exposes = require('zigbee-herdsman-converters/lib/exposes');
const tuya = require('zigbee-herdsman-converters/lib/tuya');
const globalStore = require('zigbee-herdsman-converters/lib/store');
const e = exposes.presets;
const ea = exposes.access;
// Decodifica um bloco de 18 bytes de uma fase
const decodePhase = (v) => ({
voltage: ((v[2] << 8) | v[3]) / 10,
current: ((v[4] << 16) | (v[5] << 8) | v[6]) / 1000,
power: (v[7] << 16) | (v[8] << 8) | v[9],
power_reactive: (v[10] << 16) | (v[11] << 8) | v[12],
power_apparent: (v[13] << 16) | (v[14] << 8) | v[15],
power_factor: v[16] / 100,
});
// DP 17 - limites de alarme: 3 blocos de 4 bytes [tipo, reservado, valorAlto, valorBaixo]
const decodeAlarmSettings = (v) => ({
over_current_threshold: (v[2] << 8) | v[3],
over_voltage_threshold: (v[6] << 8) | v[7],
under_voltage_threshold: (v[10] << 8) | v[11],
});
const alarmFields = {
over_current_threshold: { offset: 0 },
over_voltage_threshold: { offset: 4 },
under_voltage_threshold: { offset: 8 },
};
const getStoredDp17 = (meta) => {
const stored = globalStore.getValue(meta.device, 'dp17raw');
if (stored) return [...stored];
return [1, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0]; // fallback com os tipos corretos
};
// Cria uma entrada de ESCRITA para um campo específico do DP 17
const makeAlarmWriteEntry = (key) => {
const { offset } = alarmFields[key];
return [17, key, {
from: (v, meta) => {
globalStore.putValue(meta.device, 'dp17raw', v);
return decodeAlarmSettings(v);
},
to: async (value, meta) => {
const buf = getStoredDp17(meta);
buf[offset + 2] = (value >> 8) & 0xFF;
buf[offset + 3] = value & 0xFF;
globalStore.putValue(meta.device, 'dp17raw', buf);
return buf; // array puro, NÃO Buffer
},
}];
};
const definition = {
fingerprint: [{ modelID: 'TS0601', manufacturerName: '_TZE284_cf4b5ktf' }],
model: 'ZM7LT3',
vendor: 'Moes',
description: 'Smart 3-Phase Energy Power Meter',
extend: [
tuya.modernExtend.tuyaBase({
dp: true,
queryOnConfigure: true,
queryIntervalSeconds: 10, // atualização a cada 5 segundos
}),
],
exposes: [
// Fase A
e.numeric('voltage_l1', ea.STATE).withUnit('V').withDescription('Voltage phase A'),
e.numeric('current_l1', ea.STATE).withUnit('A').withDescription('Current phase A'),
e.numeric('power_l1', ea.STATE).withUnit('W').withDescription('Active power phase A'),
e.numeric('power_reactive_l1', ea.STATE).withUnit('VAR').withDescription('Reactive power phase A'),
e.numeric('power_apparent_l1', ea.STATE).withUnit('VA').withDescription('Apparent power phase A'),
e.numeric('power_factor_l1', ea.STATE).withDescription('Power factor phase A'),
// Fase B
e.numeric('voltage_l2', ea.STATE).withUnit('V').withDescription('Voltage phase B'),
e.numeric('current_l2', ea.STATE).withUnit('A').withDescription('Current phase B'),
e.numeric('power_l2', ea.STATE).withUnit('W').withDescription('Active power phase B'),
e.numeric('power_reactive_l2', ea.STATE).withUnit('VAR').withDescription('Reactive power phase B'),
e.numeric('power_apparent_l2', ea.STATE).withUnit('VA').withDescription('Apparent power phase B'),
e.numeric('power_factor_l2', ea.STATE).withDescription('Power factor phase B'),
// Fase C
e.numeric('voltage_l3', ea.STATE).withUnit('V').withDescription('Voltage phase C'),
e.numeric('current_l3', ea.STATE).withUnit('A').withDescription('Current phase C'),
e.numeric('power_l3', ea.STATE).withUnit('W').withDescription('Active power phase C'),
e.numeric('power_reactive_l3', ea.STATE).withUnit('VAR').withDescription('Reactive power phase C'),
e.numeric('power_apparent_l3', ea.STATE).withUnit('VA').withDescription('Apparent power phase C'),
e.numeric('power_factor_l3', ea.STATE).withDescription('Power factor phase C'),
// Limites de alarme (DP 17) - editáveis
e.numeric('over_current_threshold', ea.ALL).withUnit('A')
.withDescription('Overcurrent alarm threshold (any phase)').withCategory('config'),
e.numeric('over_voltage_threshold', ea.ALL).withUnit('V')
.withDescription('Overvoltage alarm threshold').withCategory('config'),
e.numeric('under_voltage_threshold', ea.ALL).withUnit('V')
.withDescription('Undervoltage alarm threshold').withCategory('config'),
],
meta: {
tuyaDatapoints: [
[6, null, { from: (v) => {
const d = decodePhase(v);
return {
voltage_l1: d.voltage, current_l1: d.current, power_l1: d.power,
power_reactive_l1: d.power_reactive, power_apparent_l1: d.power_apparent,
power_factor_l1: d.power_factor,
};
}}],
[7, null, { from: (v) => {
const d = decodePhase(v);
return {
voltage_l2: d.voltage, current_l2: d.current, power_l2: d.power,
power_reactive_l2: d.power_reactive, power_apparent_l2: d.power_apparent,
power_factor_l2: d.power_factor,
};
}}],
[8, null, { from: (v) => {
const d = decodePhase(v);
return {
voltage_l3: d.voltage, current_l3: d.current, power_l3: d.power,
power_reactive_l3: d.power_reactive, power_apparent_l3: d.power_apparent,
power_factor_l3: d.power_factor,
};
}}],
// Entrada "mestra" - roda na LEITURA e popula os 3 campos de uma vez
[17, null, { from: (v, meta) => {
globalStore.putValue(meta.device, 'dp17raw', v);
return decodeAlarmSettings(v);
}}],
// Entradas específicas - usadas só na ESCRITA
makeAlarmWriteEntry('over_current_threshold'),
makeAlarmWriteEntry('over_voltage_threshold'),
makeAlarmWriteEntry('under_voltage_threshold'),
],
},
};
module.exports = definition;
What does/doesn't work with the external definition?
Recently, I purchased a Moes energy measurement module, model ZM7LT3, and was unpleasantly surprised to discover that it is not compatible with Z2M. I then mapped the DataPoints (DPs) with the help of a similar energy measurement module for which someone had posted the converter here (thanks, guys!).
The module returns 3 DPs: DP 6 (Phase A), DP 7 (Phase B), DP 8 (Phase C), and DP 17 (Alarm threshold values). If anyone feels that any information is missing and can help add to it, I would really appreciate it.
Notes
software_build_id: undefined
date_code: ``
endpoints:
{"1":{"clusters":{"input":["genGroups","genScenes","manuSpecificTuya","genBasic","60672"],"output":["genOta","genTime"]}},"242":{"clusters":{"input":[],"output":["greenPower"]}}}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the supplied external converter, especially tuya.modernExtend.tuyaBase and meta.tuyaDatapoints, and compare the DP 6, 7, 8, and 17 mappings with the linked ZHA handler. Confirm the device is supported, phase measurements are exposed, and alarm thresholds can be read and written correctly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- embedded-iot
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100