Open ia1gerebec opened 4 months ago
I'm waiting for support for this device too. There is Custom quirk for this device available for ZHA but I can't convert it to Z2M (lack of skills). But may be it will help for someone skilled _TZE204_fhvdgeuh
Datapoint from tuya cloud, i am waiting too: {"1":"Total forward energy","6":"Phase A","9":"Fault","11":"Switch prepayment","12":"Clear energy","13":"Balance energy (kWh)","14":"charge energy","15":"Leakage current","16":"Switch","17":"Alarm set1","18":"Alarm set2","101":"合闸恢复时间(弃用)","102":"reclosing allowed times","103":"Temp Current","104":"reclosing enable","105":"Timer","106":"Cycle Schedule","107":"reclose recover seconds","108":"Random Timing","109":"Switch Inching","119":"Power-on delay power-on time","124":"Overcurrent Event Threshold Time","125":"Time Threshold of Lost Flow Event","126":"alarm set3","127":"status","134":"relay status for power on"}
Another one waiting too. Thanks.
I create this one, but how parse this data i don't know, can someone help, please: Alarm set1 {"0":4,"1":1,"2":0,"3":50,"4":5,"5":1,"6":0,"7":80} Alarm set2 {"0":1,"1":1,"2":2,"3":118,"4":3,"5":1,"6":0,"7":252,"8":4,"9":1,"10":0,"11":210}
const fz = require('zigbee-herdsman-converters/converters/fromZigbee');
const tz = require('zigbee-herdsman-converters/converters/toZigbee');
const exposes = require('zigbee-herdsman-converters/lib/exposes');
const tuya = require('zigbee-herdsman-converters/lib/tuya');
const e = exposes.presets;
const ea = exposes.access;
const tz_settings = {
key: ['reclose_recover_seconds','clear_energy'],
convertSet: async (entity, key, value, meta) => {
const settingType = {'trip': 2, 'alarm': 1, 'closed': 0};
// const typeswitch = {'ON':true, 'OFF':false}
let dp_key = -1; // value if not found
// identify dp.
const tuyadatapoints_list = meta.mapped.meta.tuyaDatapoints
for (let i = 0; i < tuyadatapoints_list.length; i++) {
if (tuyadatapoints_list[i][1] === key) {
dp_key = tuyadatapoints_list[i][0];
break;
}
}
switch (key) {
case 'reclose_recover_seconds': {
await tuya.sendDataPointValue(entity, dp_key, value);
break;
}
case 'clear_energy': {
await tuya.sendDataPointValue(entity, dp_key, value);
break;
}
default: // Unknown key
meta.logger.warn(`Unhandled key ${key}`);
}
},
}
const customTrueFalseConverter = {
key: ['state'],
convertSet: (entity, key, value, meta) => {
// Your conversion logic
const presence = value === 1 ? true : false;
return {state: {presence}};
},
convertGet: (entity, key, meta) => {
// Convert the state value from Home Assistant to the appropriate Zigbee value
const zigbeeValue = meta.state.presence ? 1 : 0;
return {state: zigbeeValue};
},
};
const definition = {
fingerprint: [
{
modelID: 'TS0601',
manufacturerName: '_TZE204_fhvdgeuh',
},
],
model: 'TZE204_fhvdgeuh',
vendor: 'Tuya',
description: 'Tuya multi-function energy monitor',
fromZigbee: [
tuya.fz.datapoints,
// Дополнительные преобразователи, если необходимо
],
toZigbee: [tuya.tz.datapoints,tz_settings],
onEvent: tuya.onEvent({respondToMcuVersionResponse:false, queryIntervalSeconds: 3 * 60}),
configure: tuya.configureMagicPacket,
exposes: [
tuya.exposes.switch(),
e.energy(),
e.power(),
e.voltage(),
e.current(),
e.temperature(),
e.numeric('leakage_current', ea.STATE).withUnit('mA').withDescription('Leakage current'),
e.text('fault', ea.STATE).withDescription('Fault indication'),
e.numeric('balance_energy', ea.STATE).withUnit('kWh').withDescription('Balance energy (kWh)'),
e.numeric('charge_energy', ea.STATE).withDescription('Charge energy'),
e.binary('clear_energy', ea.STATE_SET, 'ON', 'OFF').withDescription('Clear energy data'),
e.binary('switch_prepayment', ea.STATE_SET, 'ON', 'OFF').withDescription('Switch prepayment'),
e.numeric('reclosing_allowed_times', ea.STATE).withDescription('Reclosing allowed times'),
e.binary('reclosing_enable', ea.STATE_SET, 'ON', 'OFF').withDescription('Reclosing enable'),
e.numeric('timer', ea.STATE).withDescription('Timer'),
e.numeric('cycle_schedule', ea.STATE).withDescription('Cycle Schedule'),
e.numeric('reclose_recover_seconds', ea.STATE_SET).withDescription('Reclose recover seconds').withValueMin(10).withValueMax(99).withValueStep(1),
e.numeric('random_timing', ea.STATE).withDescription('Random Timing'),
e.numeric('switch_inching', ea.STATE).withDescription('Switch Inching'),
e.numeric('power_on_delay', ea.STATE).withDescription('Power-on delay power-on time'),
e.numeric('overcurrent_event_threshold_time', ea.STATE).withDescription('Overcurrent Event Threshold Time'),
e.numeric('time_threshold_lost_flow', ea.STATE).withDescription('Time Threshold of Lost Flow Event'),
e.numeric('alarm_set1', ea.STATE).withDescription('Alarm set1'),
e.numeric('alarm_set2', ea.STATE).withDescription('Alarm set2'),
e.numeric('alarm_set3', ea.STATE).withDescription('Alarm set3'),
//e.numeric('status', ea.STATE).withDescription('Device status'),
e.binary('status', ea.STATE, 'ON', 'OFF').withDescription('Device status'),
e.numeric('relay_status_power_on', ea.STATE).withDescription('Relay status for power on'),
//e.binary('relay_status_power_on', ea.STATE, 'ON', 'OFF').withDescription('Relay status for power on'),
],
meta: {
tuyaDatapoints: [
[1, 'total_forward_energy', tuya.valueConverter.divideBy100],
[6, null, tuya.valueConverter.phaseVariant2],
[9, 'fault', tuya.valueConverter.raw],
[11, 'switch_prepayment', tuya.valueConverter.onOff],
[12, 'clear_energy', tuya.valueConverter.onOff],
[13, 'balance_energy', tuya.valueConverter.divideBy100],
[14, 'charge_energy', tuya.valueConverter.divideBy100],
[15, 'leakage_current', tuya.valueConverter.raw],
[16, 'state', tuya.valueConverter.onOff],
[17, 'alarm_set1', tuya.valueConverter.raw],
[18, 'alarm_set2', tuya.valueConverter.raw],
[101, 'restore_time', tuya.valueConverter.raw], // Deprecated
[102, 'reclosing_allowed_times', tuya.valueConverter.raw],
[103, 'temperature', tuya.valueConverter.raw],
[104, 'reclosing_enable', tuya.valueConverter.onOff],
[105, 'timer', tuya.valueConverter.raw],
[106, 'cycle_schedule', tuya.valueConverter.raw],
[107, 'reclose_recover_seconds', tuya.valueConverter.raw],
[108, 'random_timing', tuya.valueConverter.raw],
[109, 'switch_inching', tuya.valueConverter.raw],
[119, 'power_on_delay', tuya.valueConverter.raw],
[124, 'overcurrent_event_threshold_time', tuya.valueConverter.raw],
[125, 'time_threshold_lost_flow', tuya.valueConverter.raw],
[126, 'alarm_set3', tuya.valueConverter.raw],
//[127, 'status', tuya.valueConverter.raw],
[127, 'status', tuya.valueConverter.onOff],
[134, 'relay_status_power_on', tuya.valueConverter.raw],
//[134, 'relay_status_power_on', tuya.valueConverter.onOff],
],
},
};
module.exports = definition;
I find already supported _TZ3000_cayepv1a, and if i right understand it's same, but how connect it to this device i don't khow
@Koenkk , hi can i ask you to add _TZE204_fhvdgeuh to already realized _TZ3000_cayepv1a or i can do it by myself?
If you stop z2m, in the data/database.db
change _TZ3000_cayepv1a
to _TZE204_fhvdgeuh
and start z2m, does it work?
_TZE204_fhvdgeuh Unfortunately no, but I almost got a normal converter
const fz = require('zigbee-herdsman-converters/converters/fromZigbee'); const tz = require('zigbee-herdsman-converters/converters/toZigbee'); const exposes = require('zigbee-herdsman-converters/lib/exposes'); const tuya = require('zigbee-herdsman-converters/lib/tuya'); const legacy = require('zigbee-herdsman-converters/lib/legacy'); const e = exposes.presets; const ea = exposes.access;
const fzLocal = {
value: {
cluster: 'manuSpecificTuya',
type: ['commandDataResponse', 'commandDataReport'],
convert: (model, msg, publish, options, meta) => {
payload = {};
for (const dpValue of msg.data.dpValues) {
const dp = dpValue.dp;
switch (dp) {
case 18:
{
payload['under_voltage'] = legacy.getDataValue(dpValue)[11];
payload['over_voltage'] = legacy.getDataValue(dpValue)[7];
return payload;
};
};
};
},
},
};
const tz_settings = {
key: ['reclose_recover_seconds','clear_energy','under_voltage','over_voltage'],
convertSet: async (entity, key, value, meta) => {
const settingType = {'trip': 2, 'alarm': 1, 'closed': 0};
// const typeswitch = {'ON':true, 'OFF':false}
let dp_key = -1; // value if not found
// identify dp.
const tuyadatapoints_list = meta.mapped.meta.tuyaDatapoints
for (let i = 0; i < tuyadatapoints_list.length; i++) {
if (tuyadatapoints_list[i][1] === key) {
dp_key = tuyadatapoints_list[i][0];
break;
}
}
switch (key) {
case 'reclose_recover_seconds': {
await tuya.sendDataPointValue(entity, dp_key, value);
break;
}
case 'clear_energy': {
await tuya.sendDataPointValue(entity, dp_key, value);
break;
}
case 'over_voltage': {
//Data not updated
const value_send = meta.state['alarm2'];
value_send['7']=value;
await tuya.sendDataPointValue(entity, 18, value_send);
break;
}
case 'under_voltage': {
//Data not updated
const value_send = meta.state['alarm2'];
value_send['11']=value;
await tuya.sendDataPointValue(entity, 18, value_send);
break;
}
default: // Unknown key
meta.logger.warn(Unhandled key ${key}
);
}
},
}
const customTrueFalseConverter = { key: ['state'], convertSet: (entity, key, value, meta) => { // Your conversion logic const presence = value === 1 ? true : false; return {state: {presence}}; }, convertGet: (entity, key, meta) => { // Convert the state value from Home Assistant to the appropriate Zigbee value const zigbeeValue = meta.state.presence ? 1 : 0; return {state: zigbeeValue}; }, };
const definition = { fingerprint: [ { modelID: 'TS0601', manufacturerName: '_TZE204_fhvdgeuh', }, ], model: 'TZE204_fhvdgeuh', vendor: 'Tuya', description: 'Tuya multi-function energy monitor', fromZigbee: [ tuya.fz.datapoints, fzLocal.value, // Дополнительные преобразователи, если необходимо ], toZigbee: [tuya.tz.datapoints,tz_settings], onEvent: tuya.onEvent({respondToMcuVersionResponse:false, queryIntervalSeconds: 3 * 60}), configure: tuya.configureMagicPacket, exposes: [ tuya.exposes.switch(), e.energy(), e.power(), e.voltage(), e.current(), e.temperature(), e.numeric('leakage_current', ea.STATE).withUnit('mA').withDescription('Leakage current'), e.text('fault', ea.STATE).withDescription('Fault indication'), e.numeric('balance_energy', ea.STATE).withUnit('kWh').withDescription('Balance energy (kWh)'), e.numeric('charge_energy', ea.STATE).withDescription('Charge energy'), e.binary('clear_energy', ea.STATE_SET, 'ON', 'OFF').withDescription('Clear energy data'), e.binary('switch_prepayment', ea.STATE_SET, 'ON', 'OFF').withDescription('Switch prepayment'), e.numeric('reclosing_allowed_times', ea.STATE).withDescription('Reclosing allowed times'), e.binary('reclosing_enable', ea.STATE_SET, 'ON', 'OFF').withDescription('Reclosing enable'), e.numeric('timer', ea.STATE).withDescription('Timer'), e.numeric('cycle_schedule', ea.STATE).withDescription('Cycle Schedule'), e.numeric('reclose_recover_seconds', ea.STATE_SET).withDescription('Reclose recover seconds').withValueMin(10).withValueMax(99).withValueStep(1), e.numeric('random_timing', ea.STATE).withDescription('Random Timing'), e.numeric('switch_inching', ea.STATE).withDescription('Switch Inching'), e.numeric('power_on_delay', ea.STATE).withDescription('Power-on delay power-on time'), e.numeric('overcurrent_event_threshold_time', ea.STATE).withDescription('Overcurrent Event Threshold Time'), e.numeric('time_threshold_lost_flow', ea.STATE).withDescription('Time Threshold of Lost Flow Event'), e.numeric('alarm_set1', ea.STATE).withDescription('Alarm set1'), e.numeric('alarm2', ea.STATE).withDescription('Alarm set2'), e.numeric('alarm_set3', ea.STATE).withDescription('Alarm set3'), e.numeric('status', ea.STATE).withDescription('Device status'), //e.binary('status', ea.STATE, 'ON', 'OFF').withDescription('Device status'), e.numeric('relay_status_power_on', ea.STATE).withDescription('Relay status for power on'), //e.binary('relay_status_power_on', ea.STATE, 'ON', 'OFF').withDescription('Relay status for power on'), exposes.numeric('over_voltage', ea.STATE_ALL).withDescription('Low Voltage Cut Off').withValueMin(120).withValueMax(300).withValueStep(1), exposes.numeric('under_voltage', ea.STATE_ALL).withDescription('Low Voltage Cut Off').withValueMin(80).withValueMax(210).withValueStep(1),
],
meta: {
tuyaDatapoints: [
[1, 'total_forward_energy', tuya.valueConverter.divideBy100],
[6, null, tuya.valueConverter.phaseVariant2],
[9, 'fault', tuya.valueConverter.raw],
[11, 'switch_prepayment', tuya.valueConverter.onOff],
[12, 'clear_energy', tuya.valueConverter.onOff],
[13, 'balance_energy', tuya.valueConverter.divideBy100],
[14, 'charge_energy', tuya.valueConverter.divideBy100],
[15, 'leakage_current', tuya.valueConverter.raw],
[16, 'state', tuya.valueConverter.onOff],
[17, 'alarm_set1', tuya.valueConverter.raw],
[18, 'alarm2', tuya.valueConverter.raw],
[101, 'restore_time', tuya.valueConverter.raw], // Deprecated
[102, 'reclosing_allowed_times', tuya.valueConverter.raw],
[103, 'temperature', tuya.valueConverter.raw],
[104, 'reclosing_enable', tuya.valueConverter.onOff],
[105, 'timer', tuya.valueConverter.raw],
[106, 'cycle_schedule', tuya.valueConverter.raw],
[107, 'reclose_recover_seconds', tuya.valueConverter.raw],
[108, 'random_timing', tuya.valueConverter.raw],
[109, 'switch_inching', tuya.valueConverter.raw],
[119, 'power_on_delay', tuya.valueConverter.raw],
[124, 'overcurrent_event_threshold_time', tuya.valueConverter.raw],
[125, 'time_threshold_lost_flow', tuya.valueConverter.raw],
[126, 'alarm_set3', tuya.valueConverter.raw],
[127, 'status', tuya.valueConverter.raw],
//[127, 'status', customTrueFalseConverter],
[134, 'relay_status_power_on', tuya.valueConverter.raw],
//[134, 'relay_status_power_on', tuya.valueConverter.onOff],
],
},
};
module.exports = definition;
I created something like this, not all function add, but almost needed Edit me if needed @Koenkk
const fz = require('zigbee-herdsman-converters/converters/fromZigbee');
const tz = require('zigbee-herdsman-converters/converters/toZigbee');
const exposes = require('zigbee-herdsman-converters/lib/exposes');
const tuya = require('zigbee-herdsman-converters/lib/tuya');
const legacy = require('zigbee-herdsman-converters/lib/legacy');
const e = exposes.presets;
const ea = exposes.access;
const fzLocal = {
value: {
cluster: 'manuSpecificTuya',
type: ['commandDataResponse', 'commandDataReport'],
convert: (model, msg, publish, options, meta) => {
payload = {};
for (const dpValue of msg.data.dpValues) {
const dp = dpValue.dp;
switch (dp) {
case 17:
{
payload['over_leakage_current'] = legacy.getDataValue(dpValue)[3];
payload['over_temperature'] = legacy.getDataValue(dpValue)[7];
return payload;
};
case 18:
{
payload['under_voltage'] = legacy.getDataValue(dpValue)[11];
payload['over_voltage'] = legacy.getDataValue(dpValue)[7];
overcurrent=legacy.getDataValue(dpValue)[2]*256+legacy.getDataValue(dpValue)[3];
payload['over_current']=overcurrent/10.0;
return payload;
};
};
};
},
},
};
const tz_settings = {
key: ['reclose_recover_seconds','clear_energy','under_voltage','over_voltage','reclosing_allowed_times','over_leakage_current','over_temperature','over_current'],
convertSet: async (entity, key, value, meta) => {
const settingType = {'trip': 2, 'alarm': 1, 'closed': 0};
// const typeswitch = {'ON':true, 'OFF':false}
let dp_key = -1; // value if not found
// identify dp.
const tuyadatapoints_list = meta.mapped.meta.tuyaDatapoints
for (let i = 0; i < tuyadatapoints_list.length; i++) {
if (tuyadatapoints_list[i][1] === key) {
dp_key = tuyadatapoints_list[i][0];
break;
}
}
switch (key) {
case 'reclose_recover_seconds': {
await tuya.sendDataPointValue(entity, dp_key, value);
break;
}
case 'reclosing_allowed_times': {
await tuya.sendDataPointValue(entity, dp_key, value);
break;
}
case 'clear_energy': {
await tuya.sendDataPointValue(entity, dp_key, value);
break;
}
case 'over_leakage_current': {
const value_send = meta.state['alarm1'];
value_send['3']=value;
const payload = [value_send['0'],value_send['1'],value_send['2'],value_send['3'],value_send['4'],value_send['5'],value_send['6'],value_send['7']];
await tuya.sendDataPointRaw(entity, 17, payload);
break;
}
case 'over_temperature': {
const value_send = meta.state['alarm1'];
value_send['7']=value;
const payload = [value_send['0'],value_send['1'],value_send['2'],value_send['3'],value_send['4'],value_send['5'],value_send['6'],value_send['7']];
await tuya.sendDataPointRaw(entity, 17, payload);
break;
}
case 'over_current': {
const value_send = meta.state['alarm2'];
value_send['2']=value*10/256;
value_send['3']=value*10%256;
const payload = [value_send['0'],value_send['1'],value_send['2'],value_send['3'],value_send['4'],value_send['5'],value_send['6'],value_send['7'],value_send['8'],value_send['9'],value_send['10'],value_send['11']];
await tuya.sendDataPointRaw(entity, 18, payload);
break;
}
case 'over_voltage': {
const value_send = meta.state['alarm2'];
value_send['7']=value;
const payload = [value_send['0'],value_send['1'],value_send['2'],value_send['3'],value_send['4'],value_send['5'],value_send['6'],value_send['7'],value_send['8'],value_send['9'],value_send['10'],value_send['11']];
await tuya.sendDataPointRaw(entity, 18, payload);
break;
}
case 'under_voltage': {
const value_send = meta.state['alarm2'];
value_send['11']=value;
const payload = [value_send['0'],value_send['1'],value_send['2'],value_send['3'],value_send['4'],value_send['5'],value_send['6'],value_send['7'],value_send['8'],value_send['9'],value_send['10'],value_send['11']];
await tuya.sendDataPointRaw(entity, 18, payload);
break;
}
default: // Unknown key
meta.logger.warn(`Unhandled key ${key}`);
}
},
}
const customTrueFalseConverter = {
key: ['state'],
convertSet: (entity, key, value, meta) => {
// Your conversion logic
const presence = value === 1 ? true : false;
return {state: {presence}};
},
convertGet: (entity, key, meta) => {
// Convert the state value from Home Assistant to the appropriate Zigbee value
const zigbeeValue = meta.state.presence ? 1 : 0;
return {state: zigbeeValue};
},
};
const definition = {
fingerprint: [
{
modelID: 'TS0601',
manufacturerName: '_TZE204_fhvdgeuh',
},
],
model: 'TZE204_fhvdgeuh',
vendor: 'Tuya',
description: 'Tuya multi-function energy monitor',
fromZigbee: [
tuya.fz.datapoints,
fzLocal.value,
// Дополнительные преобразователи, если необходимо
],
toZigbee: [tuya.tz.datapoints,tz_settings],
onEvent: tuya.onEvent({respondToMcuVersionResponse:false, queryIntervalSeconds: 3 * 60}),
configure: tuya.configureMagicPacket,
exposes: [
tuya.exposes.switch(),
e.energy(),
e.power(),
e.voltage(),
e.current(),
e.temperature(),
e.numeric('leakage_current', ea.STATE).withUnit('mA').withDescription('Leakage current'),
e.text('fault', ea.STATE).withDescription('Fault indication'),
e.numeric('balance_energy', ea.STATE).withUnit('kWh').withDescription('Balance energy (kWh)'),
exposes.numeric('over_leakage_current', ea.STATE_ALL).withDescription('Over Leakage Current Cut Off').withValueMin(0).withValueMax(99).withValueStep(1),
exposes.numeric('over_temperature', ea.STATE_ALL).withDescription('Over Temperature Cut Off').withValueMin(0).withValueMax(100).withValueStep(1),
exposes.numeric('over_voltage', ea.STATE_ALL).withDescription('Over Voltage Cut Off').withValueMin(120).withValueMax(300).withValueStep(1),
exposes.numeric('under_voltage', ea.STATE_ALL).withDescription('Under Voltage Cut Off').withValueMin(80).withValueMax(210).withValueStep(1),
e.numeric('reclose_recover_seconds', ea.STATE_SET).withDescription('Reclose recover seconds').withValueMin(10).withValueMax(99).withValueStep(1),
exposes.numeric('over_current', ea.STATE_ALL).withDescription('Over Current Cut Off').withValueMin(1).withValueMax(63).withValueStep(0.1),
e.numeric('reclosing_allowed_times', ea.STATE_ALL).withDescription('Time Restore After Over Current').withValueMin(0).withValueMax(30).withValueStep(1),
e.numeric('charge_energy', ea.STATE).withDescription('Charge energy'),
e.binary('clear_energy', ea.STATE_SET, 'ON', 'OFF').withDescription('Clear energy data'),
e.binary('switch_prepayment', ea.STATE_SET, 'ON', 'OFF').withDescription('Switch prepayment'),
//e.numeric('reclosing_allowed_times', ea.STATE).withDescription('Reclosing allowed times'),
e.binary('reclosing_enable', ea.STATE_SET, 'ON', 'OFF').withDescription('Reclosing enable'),
e.numeric('timer', ea.STATE).withDescription('Timer'),
e.numeric('cycle_schedule', ea.STATE).withDescription('Cycle Schedule'),
e.numeric('random_timing', ea.STATE).withDescription('Random Timing'),
e.numeric('switch_inching', ea.STATE).withDescription('Switch Inching'),
e.numeric('power_on_delay', ea.STATE).withDescription('Power-on delay power-on time'),
e.numeric('overcurrent_event_threshold_time', ea.STATE).withDescription('Overcurrent Event Threshold Time'),
e.numeric('time_threshold_lost_flow', ea.STATE).withDescription('Time Threshold of Lost Flow Event'),
e.numeric('alarm1', ea.STATE).withDescription('Alarm set1'),
e.numeric('alarm2', ea.STATE).withDescription('Alarm set2'),
e.numeric('alarm_set3', ea.STATE).withDescription('Alarm set3'),
e.numeric('status', ea.STATE).withDescription('Device status'),
//e.binary('status', ea.STATE, 'ON', 'OFF').withDescription('Device status'),
e.numeric('relay_status_power_on', ea.STATE).withDescription('Relay status for power on'),
//e.binary('relay_status_power_on', ea.STATE, 'ON', 'OFF').withDescription('Relay status for power on'),
],
meta: {
tuyaDatapoints: [
[1, 'total_forward_energy', tuya.valueConverter.divideBy100],
[6, null, tuya.valueConverter.phaseVariant2],
[9, 'fault', tuya.valueConverter.raw],
[11, 'switch_prepayment', tuya.valueConverter.onOff],
[12, 'clear_energy', tuya.valueConverter.onOff],
[13, 'balance_energy', tuya.valueConverter.divideBy100],
[14, 'charge_energy', tuya.valueConverter.divideBy100],
[15, 'leakage_current', tuya.valueConverter.raw],
[16, 'state', tuya.valueConverter.onOff],
[17, 'alarm1', tuya.valueConverter.raw],
[18, 'alarm2', tuya.valueConverter.raw],
[101, 'restore_time', tuya.valueConverter.raw], // Deprecated
[102, 'reclosing_allowed_times', tuya.valueConverter.raw],
[103, 'temperature', tuya.valueConverter.raw],
[104, 'reclosing_enable', tuya.valueConverter.onOff],
[105, 'timer', tuya.valueConverter.raw],
[106, 'cycle_schedule', tuya.valueConverter.raw],
[107, 'reclose_recover_seconds', tuya.valueConverter.raw],
[108, 'random_timing', tuya.valueConverter.raw],
[109, 'switch_inching', tuya.valueConverter.raw],
[119, 'power_on_delay', tuya.valueConverter.raw],
[124, 'overcurrent_event_threshold_time', tuya.valueConverter.raw],
[125, 'time_threshold_lost_flow', tuya.valueConverter.raw],
[126, 'alarm_set3', tuya.valueConverter.raw],
[127, 'status', tuya.valueConverter.raw],
//[127, 'status', customTrueFalseConverter],
[134, 'relay_status_power_on', tuya.valueConverter.raw],
//[134, 'relay_status_power_on', tuya.valueConverter.onOff],
],
},
};
module.exports = definition;
Bug Fix
const fz = require('zigbee-herdsman-converters/converters/fromZigbee');
const tz = require('zigbee-herdsman-converters/converters/toZigbee');
const exposes = require('zigbee-herdsman-converters/lib/exposes');
const tuya = require('zigbee-herdsman-converters/lib/tuya');
const legacy = require('zigbee-herdsman-converters/lib/legacy');
const e = exposes.presets;
const ea = exposes.access;
const fzLocal = {
value: {
cluster: 'manuSpecificTuya',
type: ['commandDataResponse', 'commandDataReport'],
convert: (model, msg, publish, options, meta) => {
payload = {};
for (const dpValue of msg.data.dpValues) {
const dp = dpValue.dp;
switch (dp) {
case 17:
{
payload['over_leakage_current'] = legacy.getDataValue(dpValue)[3];
payload['over_temperature'] = legacy.getDataValue(dpValue)[7];
return payload;
};
case 18:
{
payload['under_voltage'] = legacy.getDataValue(dpValue)[11];
overvoltage=legacy.getDataValue(dpValue)[6]*256+legacy.getDataValue(dpValue)[7]
payload['over_voltage'] = overvoltage;
overcurrent=legacy.getDataValue(dpValue)[2]*256+legacy.getDataValue(dpValue)[3];
payload['over_current']=overcurrent/10.0;
return payload;
};
};
};
},
},
};
const tz_settings = {
key: ['reclose_recover_seconds','clear_energy','under_voltage','over_voltage','reclosing_allowed_times','over_leakage_current','over_temperature','over_current'],
convertSet: async (entity, key, value, meta) => {
const settingType = {'trip': 2, 'alarm': 1, 'closed': 0};
// const typeswitch = {'ON':true, 'OFF':false}
let dp_key = -1; // value if not found
// identify dp.
const tuyadatapoints_list = meta.mapped.meta.tuyaDatapoints
for (let i = 0; i < tuyadatapoints_list.length; i++) {
if (tuyadatapoints_list[i][1] === key) {
dp_key = tuyadatapoints_list[i][0];
break;
}
}
switch (key) {
case 'reclose_recover_seconds': {
await tuya.sendDataPointValue(entity, dp_key, value);
break;
}
case 'reclosing_allowed_times': {
await tuya.sendDataPointValue(entity, dp_key, value);
break;
}
case 'clear_energy': {
await tuya.sendDataPointBool(entity, dp_key, value === 'ON');
break;
}
case 'over_leakage_current': {
const value_send = meta.state['alarm1'];
value_send['3']=value;
const payload = [value_send['0'],value_send['1'],value_send['2'],value_send['3'],value_send['4'],value_send['5'],value_send['6'],value_send['7']];
await tuya.sendDataPointRaw(entity, 17, payload);
break;
}
case 'over_temperature': {
const value_send = meta.state['alarm1'];
value_send['7']=value;
const payload = [value_send['0'],value_send['1'],value_send['2'],value_send['3'],value_send['4'],value_send['5'],value_send['6'],value_send['7']];
await tuya.sendDataPointRaw(entity, 17, payload);
break;
}
case 'over_current': {
const value_send = meta.state['alarm2'];
value_send['2']=value*10/256;
value_send['3']=value*10%256;
const payload = [value_send['0'],value_send['1'],value_send['2'],value_send['3'],value_send['4'],value_send['5'],value_send['6'],value_send['7'],value_send['8'],value_send['9'],value_send['10'],value_send['11']];
await tuya.sendDataPointRaw(entity, 18, payload);
break;
}
case 'over_voltage': {
const value_send = meta.state['alarm2'];
value_send['6']=value*10/256;
value_send['7']=value*10%256;
const payload = [value_send['0'],value_send['1'],value_send['2'],value_send['3'],value_send['4'],value_send['5'],value_send['6'],value_send['7'],value_send['8'],value_send['9'],value_send['10'],value_send['11']];
await tuya.sendDataPointRaw(entity, 18, payload);
break;
}
case 'under_voltage': {
const value_send = meta.state['alarm2'];
value_send['11']=value;
const payload = [value_send['0'],value_send['1'],value_send['2'],value_send['3'],value_send['4'],value_send['5'],value_send['6'],value_send['7'],value_send['8'],value_send['9'],value_send['10'],value_send['11']];
await tuya.sendDataPointRaw(entity, 18, payload);
break;
}
default: // Unknown key
meta.logger.warn(`Unhandled key ${key}`);
}
},
}
const customTrueFalseConverter = {
key: ['state'],
convertSet: (entity, key, value, meta) => {
// Your conversion logic
const presence = value === 1 ? true : false;
return {state: {presence}};
},
convertGet: (entity, key, meta) => {
// Convert the state value from Home Assistant to the appropriate Zigbee value
const zigbeeValue = meta.state.presence ? 1 : 0;
return {state: zigbeeValue};
},
};
const definition = {
fingerprint: [
{
modelID: 'TS0601',
manufacturerName: '_TZE204_fhvdgeuh',
},
],
model: 'TZE204_fhvdgeuh',
vendor: 'Tuya',
description: 'Tuya multi-function energy monitor',
fromZigbee: [
tuya.fz.datapoints,
fzLocal.value,
// Дополнительные преобразователи, если необходимо
],
toZigbee: [tuya.tz.datapoints,tz_settings],
onEvent: tuya.onEvent({respondToMcuVersionResponse:false, queryIntervalSeconds: 3 * 60}),
configure: tuya.configureMagicPacket,
exposes: [
tuya.exposes.switch(),
e.energy(),
e.power(),
e.voltage(),
e.current(),
e.temperature(),
e.numeric('leakage_current', ea.STATE).withUnit('mA').withDescription('Leakage current'),
e.text('fault', ea.STATE).withDescription('Fault indication'),
e.numeric('balance_energy', ea.STATE).withUnit('kWh').withDescription('Balance energy (kWh)'),
e.numeric('over_leakage_current', ea.STATE_SET).withDescription('Over Leakage Current Cut Off').withValueMin(0).withValueMax(99).withValueStep(1).withUnit('mA'),
e.numeric('over_temperature', ea.STATE_SET).withDescription('Over Temperature Cut Off').withValueMin(0).withValueMax(100).withValueStep(1).withUnit('°C'),
e.numeric('over_voltage', ea.STATE_SET).withDescription('Over Voltage Cut Off').withValueMin(120).withValueMax(300).withValueStep(1).withUnit('V'),
e.numeric('under_voltage', ea.STATE_SET).withDescription('Under Voltage Cut Off').withValueMin(80).withValueMax(210).withValueStep(1).withUnit('V'),
e.numeric('reclose_recover_seconds', ea.STATE_SET).withDescription('Reclose recover seconds').withValueMin(10).withValueMax(99).withValueStep(1),
e.numeric('over_current', ea.STATE_SET).withDescription('Over Current Cut Off').withValueMin(1).withValueMax(63).withValueStep(0.1).withUnit('A'),
e.numeric('reclosing_allowed_times', ea.STATE_SET).withDescription('Time Restore After Over Current').withValueMin(0).withValueMax(30).withValueStep(1),
e.numeric('charge_energy', ea.STATE).withDescription('Charge energy'),
e.binary('clear_energy', ea.STATE_SET, 'ON', 'OFF').withDescription('Clear energy data'),
e.binary('switch_prepayment', ea.STATE_SET, 'ON', 'OFF').withDescription('Switch prepayment'),
//e.numeric('reclosing_allowed_times', ea.STATE).withDescription('Reclosing allowed times'),
e.binary('reclosing_enable', ea.STATE_SET, 'ON', 'OFF').withDescription('Reclosing enable'),
e.numeric('timer', ea.STATE).withDescription('Timer'),
e.numeric('cycle_schedule', ea.STATE).withDescription('Cycle Schedule'),
e.numeric('random_timing', ea.STATE).withDescription('Random Timing'),
e.numeric('switch_inching', ea.STATE).withDescription('Switch Inching'),
e.numeric('power_on_delay', ea.STATE).withDescription('Power-on delay power-on time'),
e.numeric('overcurrent_event_threshold_time', ea.STATE).withDescription('Overcurrent Event Threshold Time'),
e.numeric('time_threshold_lost_flow', ea.STATE).withDescription('Time Threshold of Lost Flow Event'),
e.numeric('alarm1', ea.STATE).withDescription('Alarm set1'),
e.numeric('alarm2', ea.STATE).withDescription('Alarm set2'),
e.numeric('alarm_set3', ea.STATE).withDescription('Alarm set3'),
e.numeric('status', ea.STATE).withDescription('Device status'),
//e.binary('status', ea.STATE, 'ON', 'OFF').withDescription('Device status'),
e.numeric('relay_status_power_on', ea.STATE).withDescription('Relay status for power on'),
//e.binary('relay_status_power_on', ea.STATE, 'ON', 'OFF').withDescription('Relay status for power on'),
],
meta: {
tuyaDatapoints: [
[1, 'total_forward_energy', tuya.valueConverter.divideBy100],
[6, null, tuya.valueConverter.phaseVariant2],
[9, 'fault', tuya.valueConverter.raw],
[11, 'switch_prepayment', tuya.valueConverter.onOff],
[12, 'clear_energy', tuya.valueConverter.onOff],
[13, 'balance_energy', tuya.valueConverter.divideBy100],
[14, 'charge_energy', tuya.valueConverter.divideBy100],
[15, 'leakage_current', tuya.valueConverter.raw],
[16, 'state', tuya.valueConverter.onOff],
[17, 'alarm1', tuya.valueConverter.raw],
[18, 'alarm2', tuya.valueConverter.raw],
[101, 'restore_time', tuya.valueConverter.raw], // Deprecated
[102, 'reclosing_allowed_times', tuya.valueConverter.raw],
[103, 'temperature', tuya.valueConverter.raw],
[104, 'reclosing_enable', tuya.valueConverter.onOff],
[105, 'timer', tuya.valueConverter.raw],
[106, 'cycle_schedule', tuya.valueConverter.raw],
[107, 'reclose_recover_seconds', tuya.valueConverter.raw],
[108, 'random_timing', tuya.valueConverter.raw],
[109, 'switch_inching', tuya.valueConverter.raw],
[119, 'power_on_delay', tuya.valueConverter.raw],
[124, 'overcurrent_event_threshold_time', tuya.valueConverter.raw],
[125, 'time_threshold_lost_flow', tuya.valueConverter.raw],
[126, 'alarm_set3', tuya.valueConverter.raw],
[127, 'status', tuya.valueConverter.raw],
//[127, 'status', customTrueFalseConverter],
[134, 'relay_status_power_on', tuya.valueConverter.raw],
//[134, 'relay_status_power_on', tuya.valueConverter.onOff],
],
},
};
module.exports = definition;
Hot Fix
const fz = require('zigbee-herdsman-converters/converters/fromZigbee');
const tz = require('zigbee-herdsman-converters/converters/toZigbee');
const exposes = require('zigbee-herdsman-converters/lib/exposes');
const tuya = require('zigbee-herdsman-converters/lib/tuya');
const legacy = require('zigbee-herdsman-converters/lib/legacy');
const e = exposes.presets;
const ea = exposes.access;
const fzLocal = {
value: {
cluster: 'manuSpecificTuya',
type: ['commandDataResponse', 'commandDataReport'],
convert: (model, msg, publish, options, meta) => {
payload = {};
for (const dpValue of msg.data.dpValues) {
const dp = dpValue.dp;
switch (dp) {
case 17:
{
payload['over_leakage_current'] = legacy.getDataValue(dpValue)[3];
payload['over_temperature'] = legacy.getDataValue(dpValue)[7];
return payload;
};
case 18:
{
payload['under_voltage'] = legacy.getDataValue(dpValue)[11];
overvoltage=legacy.getDataValue(dpValue)[6]*256+legacy.getDataValue(dpValue)[7]
payload['over_voltage'] = overvoltage;
overcurrent=legacy.getDataValue(dpValue)[2]*256+legacy.getDataValue(dpValue)[3];
payload['over_current']=overcurrent/10.0;
return payload;
};
};
};
},
},
};
const tz_settings = {
key: ['reclose_recover_seconds','clear_energy','under_voltage','over_voltage','reclosing_allowed_times','over_leakage_current','over_temperature','over_current'],
convertSet: async (entity, key, value, meta) => {
const settingType = {'trip': 2, 'alarm': 1, 'closed': 0};
// const typeswitch = {'ON':true, 'OFF':false}
let dp_key = -1; // value if not found
// identify dp.
const tuyadatapoints_list = meta.mapped.meta.tuyaDatapoints
for (let i = 0; i < tuyadatapoints_list.length; i++) {
if (tuyadatapoints_list[i][1] === key) {
dp_key = tuyadatapoints_list[i][0];
break;
}
}
switch (key) {
case 'reclose_recover_seconds': {
await tuya.sendDataPointValue(entity, dp_key, value);
break;
}
case 'reclosing_allowed_times': {
await tuya.sendDataPointValue(entity, dp_key, value);
break;
}
case 'clear_energy': {
await tuya.sendDataPointBool(entity, dp_key, value === 'ON');
break;
}
case 'over_leakage_current': {
const value_send = meta.state['alarm1'];
value_send['3']=value;
const payload = [value_send['0'],value_send['1'],value_send['2'],value_send['3'],value_send['4'],value_send['5'],value_send['6'],value_send['7']];
await tuya.sendDataPointRaw(entity, 17, payload);
break;
}
case 'over_temperature': {
const value_send = meta.state['alarm1'];
value_send['7']=value;
const payload = [value_send['0'],value_send['1'],value_send['2'],value_send['3'],value_send['4'],value_send['5'],value_send['6'],value_send['7']];
await tuya.sendDataPointRaw(entity, 17, payload);
break;
}
case 'over_current': {
const value_send = meta.state['alarm2'];
value_send['2']=value*10/256;
value_send['3']=value*10%256;
const payload = [value_send['0'],value_send['1'],value_send['2'],value_send['3'],value_send['4'],value_send['5'],value_send['6'],value_send['7'],value_send['8'],value_send['9'],value_send['10'],value_send['11']];
await tuya.sendDataPointRaw(entity, 18, payload);
break;
}
case 'over_voltage': {
const value_send = meta.state['alarm2'];
value_send['6']=value/256;
value_send['7']=value%256;
const payload = [value_send['0'],value_send['1'],value_send['2'],value_send['3'],value_send['4'],value_send['5'],value_send['6'],value_send['7'],value_send['8'],value_send['9'],value_send['10'],value_send['11']];
await tuya.sendDataPointRaw(entity, 18, payload);
break;
}
case 'under_voltage': {
const value_send = meta.state['alarm2'];
value_send['11']=value;
const payload = [value_send['0'],value_send['1'],value_send['2'],value_send['3'],value_send['4'],value_send['5'],value_send['6'],value_send['7'],value_send['8'],value_send['9'],value_send['10'],value_send['11']];
await tuya.sendDataPointRaw(entity, 18, payload);
break;
}
default: // Unknown key
meta.logger.warn(`Unhandled key ${key}`);
}
},
}
const customTrueFalseConverter = {
key: ['state'],
convertSet: (entity, key, value, meta) => {
// Your conversion logic
const presence = value === 1 ? true : false;
return {state: {presence}};
},
convertGet: (entity, key, meta) => {
// Convert the state value from Home Assistant to the appropriate Zigbee value
const zigbeeValue = meta.state.presence ? 1 : 0;
return {state: zigbeeValue};
},
};
const definition = {
fingerprint: [
{
modelID: 'TS0601',
manufacturerName: '_TZE204_fhvdgeuh',
},
],
model: 'TZE204_fhvdgeuh',
vendor: 'Tuya',
description: 'Tuya multi-function energy monitor',
fromZigbee: [
tuya.fz.datapoints,
fzLocal.value,
// Дополнительные преобразователи, если необходимо
],
toZigbee: [tuya.tz.datapoints,tz_settings],
onEvent: tuya.onEvent({respondToMcuVersionResponse:false, queryIntervalSeconds: 3 * 60}),
configure: tuya.configureMagicPacket,
exposes: [
tuya.exposes.switch(),
e.energy(),
e.power(),
e.voltage(),
e.current(),
e.temperature(),
e.numeric('leakage_current', ea.STATE).withUnit('mA').withDescription('Leakage current'),
e.text('fault', ea.STATE).withDescription('Fault indication'),
e.numeric('balance_energy', ea.STATE).withUnit('kWh').withDescription('Balance energy (kWh)'),
e.numeric('over_leakage_current', ea.STATE_SET).withDescription('Over Leakage Current Cut Off').withValueMin(0).withValueMax(99).withValueStep(1).withUnit('mA'),
e.numeric('over_temperature', ea.STATE_SET).withDescription('Over Temperature Cut Off').withValueMin(0).withValueMax(100).withValueStep(1).withUnit('°C'),
e.numeric('over_voltage', ea.STATE_SET).withDescription('Over Voltage Cut Off').withValueMin(120).withValueMax(300).withValueStep(1).withUnit('V'),
e.numeric('under_voltage', ea.STATE_SET).withDescription('Under Voltage Cut Off').withValueMin(80).withValueMax(210).withValueStep(1).withUnit('V'),
e.numeric('reclose_recover_seconds', ea.STATE_SET).withDescription('Reclose recover seconds').withValueMin(10).withValueMax(99).withValueStep(1),
e.numeric('over_current', ea.STATE_SET).withDescription('Over Current Cut Off').withValueMin(1).withValueMax(63).withValueStep(0.1).withUnit('A'),
e.numeric('reclosing_allowed_times', ea.STATE_SET).withDescription('Time Restore After Over Current').withValueMin(0).withValueMax(30).withValueStep(1),
e.numeric('charge_energy', ea.STATE).withDescription('Charge energy'),
e.binary('clear_energy', ea.STATE_SET, 'ON', 'OFF').withDescription('Clear energy data'),
e.binary('switch_prepayment', ea.STATE_SET, 'ON', 'OFF').withDescription('Switch prepayment'),
//e.numeric('reclosing_allowed_times', ea.STATE).withDescription('Reclosing allowed times'),
e.binary('reclosing_enable', ea.STATE_SET, 'ON', 'OFF').withDescription('Reclosing enable'),
e.numeric('timer', ea.STATE).withDescription('Timer'),
e.numeric('cycle_schedule', ea.STATE).withDescription('Cycle Schedule'),
e.numeric('random_timing', ea.STATE).withDescription('Random Timing'),
e.numeric('switch_inching', ea.STATE).withDescription('Switch Inching'),
e.numeric('power_on_delay', ea.STATE).withDescription('Power-on delay power-on time'),
e.numeric('overcurrent_event_threshold_time', ea.STATE).withDescription('Overcurrent Event Threshold Time'),
e.numeric('time_threshold_lost_flow', ea.STATE).withDescription('Time Threshold of Lost Flow Event'),
e.numeric('alarm1', ea.STATE).withDescription('Alarm set1'),
e.numeric('alarm2', ea.STATE).withDescription('Alarm set2'),
e.numeric('alarm_set3', ea.STATE).withDescription('Alarm set3'),
e.numeric('status', ea.STATE).withDescription('Device status'),
//e.binary('status', ea.STATE, 'ON', 'OFF').withDescription('Device status'),
e.numeric('relay_status_power_on', ea.STATE).withDescription('Relay status for power on'),
//e.binary('relay_status_power_on', ea.STATE, 'ON', 'OFF').withDescription('Relay status for power on'),
],
meta: {
tuyaDatapoints: [
[1, 'total_forward_energy', tuya.valueConverter.divideBy100],
[6, null, tuya.valueConverter.phaseVariant2],
[9, 'fault', tuya.valueConverter.raw],
[11, 'switch_prepayment', tuya.valueConverter.onOff],
[12, 'clear_energy', tuya.valueConverter.onOff],
[13, 'balance_energy', tuya.valueConverter.divideBy100],
[14, 'charge_energy', tuya.valueConverter.divideBy100],
[15, 'leakage_current', tuya.valueConverter.raw],
[16, 'state', tuya.valueConverter.onOff],
[17, 'alarm1', tuya.valueConverter.raw],
[18, 'alarm2', tuya.valueConverter.raw],
[101, 'restore_time', tuya.valueConverter.raw], // Deprecated
[102, 'reclosing_allowed_times', tuya.valueConverter.raw],
[103, 'temperature', tuya.valueConverter.raw],
[104, 'reclosing_enable', tuya.valueConverter.onOff],
[105, 'timer', tuya.valueConverter.raw],
[106, 'cycle_schedule', tuya.valueConverter.raw],
[107, 'reclose_recover_seconds', tuya.valueConverter.raw],
[108, 'random_timing', tuya.valueConverter.raw],
[109, 'switch_inching', tuya.valueConverter.raw],
[119, 'power_on_delay', tuya.valueConverter.raw],
[124, 'overcurrent_event_threshold_time', tuya.valueConverter.raw],
[125, 'time_threshold_lost_flow', tuya.valueConverter.raw],
[126, 'alarm_set3', tuya.valueConverter.raw],
[127, 'status', tuya.valueConverter.raw],
//[127, 'status', customTrueFalseConverter],
[134, 'relay_status_power_on', tuya.valueConverter.raw],
//[134, 'relay_status_power_on', tuya.valueConverter.onOff],
],
},
};
module.exports = definition;
Thank you very much @peekayn84, I'm trying it and it works, but I don't receive data on the energy.
I don't know what mean at energy, but interface realised it and i show it too, but parametr at down "Power" work correcty, if i understand you right this is what you need
Thank you very much @peekayn84, I'm trying it and it works, but I don't receive data on the energy.
I talk about this paramater:
I will check it, i have same problem
I talk about this paramater:
Fixed
const fz = require('zigbee-herdsman-converters/converters/fromZigbee');
const tz = require('zigbee-herdsman-converters/converters/toZigbee');
const exposes = require('zigbee-herdsman-converters/lib/exposes');
const tuya = require('zigbee-herdsman-converters/lib/tuya');
const legacy = require('zigbee-herdsman-converters/lib/legacy');
const e = exposes.presets;
const ea = exposes.access;
const fzLocal = {
value: {
cluster: 'manuSpecificTuya',
type: ['commandDataResponse', 'commandDataReport'],
convert: (model, msg, publish, options, meta) => {
payload = {};
for (const dpValue of msg.data.dpValues) {
const dp = dpValue.dp;
switch (dp) {
case 17:
{
payload['over_leakage_current'] = legacy.getDataValue(dpValue)[3];
payload['over_temperature'] = legacy.getDataValue(dpValue)[7];
return payload;
};
case 18:
{
payload['under_voltage'] = legacy.getDataValue(dpValue)[11];
overvoltage=legacy.getDataValue(dpValue)[6]*256+legacy.getDataValue(dpValue)[7]
payload['over_voltage'] = overvoltage;
overcurrent=legacy.getDataValue(dpValue)[2]*256+legacy.getDataValue(dpValue)[3];
payload['over_current']=overcurrent/10.0;
return payload;
};
};
};
},
},
};
const tz_settings = {
key: ['reclose_recover_seconds','clear_energy','under_voltage','over_voltage','reclosing_allowed_times','over_leakage_current','over_temperature','over_current'],
convertSet: async (entity, key, value, meta) => {
const settingType = {'trip': 2, 'alarm': 1, 'closed': 0};
// const typeswitch = {'ON':true, 'OFF':false}
let dp_key = -1; // value if not found
// identify dp.
const tuyadatapoints_list = meta.mapped.meta.tuyaDatapoints
for (let i = 0; i < tuyadatapoints_list.length; i++) {
if (tuyadatapoints_list[i][1] === key) {
dp_key = tuyadatapoints_list[i][0];
break;
}
}
switch (key) {
case 'reclose_recover_seconds': {
await tuya.sendDataPointValue(entity, dp_key, value);
break;
}
case 'reclosing_allowed_times': {
await tuya.sendDataPointValue(entity, dp_key, value);
break;
}
case 'clear_energy': {
await tuya.sendDataPointBool(entity, dp_key, value === 'ON');
break;
}
case 'over_leakage_current': {
const value_send = meta.state['alarm1'];
value_send['3']=value;
const payload = [value_send['0'],value_send['1'],value_send['2'],value_send['3'],value_send['4'],value_send['5'],value_send['6'],value_send['7']];
await tuya.sendDataPointRaw(entity, 17, payload);
break;
}
case 'over_temperature': {
const value_send = meta.state['alarm1'];
value_send['7']=value;
const payload = [value_send['0'],value_send['1'],value_send['2'],value_send['3'],value_send['4'],value_send['5'],value_send['6'],value_send['7']];
await tuya.sendDataPointRaw(entity, 17, payload);
break;
}
case 'over_current': {
const value_send = meta.state['alarm2'];
value_send['2']=value*10/256;
value_send['3']=value*10%256;
const payload = [value_send['0'],value_send['1'],value_send['2'],value_send['3'],value_send['4'],value_send['5'],value_send['6'],value_send['7'],value_send['8'],value_send['9'],value_send['10'],value_send['11']];
await tuya.sendDataPointRaw(entity, 18, payload);
break;
}
case 'over_voltage': {
const value_send = meta.state['alarm2'];
value_send['6']=value/256;
value_send['7']=value%256;
const payload = [value_send['0'],value_send['1'],value_send['2'],value_send['3'],value_send['4'],value_send['5'],value_send['6'],value_send['7'],value_send['8'],value_send['9'],value_send['10'],value_send['11']];
await tuya.sendDataPointRaw(entity, 18, payload);
break;
}
case 'under_voltage': {
const value_send = meta.state['alarm2'];
value_send['11']=value;
const payload = [value_send['0'],value_send['1'],value_send['2'],value_send['3'],value_send['4'],value_send['5'],value_send['6'],value_send['7'],value_send['8'],value_send['9'],value_send['10'],value_send['11']];
await tuya.sendDataPointRaw(entity, 18, payload);
break;
}
default: // Unknown key
meta.logger.warn(`Unhandled key ${key}`);
}
},
}
const customTrueFalseConverter = {
key: ['state'],
convertSet: (entity, key, value, meta) => {
// Your conversion logic
const presence = value === 1 ? true : false;
return {state: {presence}};
},
convertGet: (entity, key, meta) => {
// Convert the state value from Home Assistant to the appropriate Zigbee value
const zigbeeValue = meta.state.presence ? 1 : 0;
return {state: zigbeeValue};
},
};
const definition = {
fingerprint: [
{
modelID: 'TS0601',
manufacturerName: '_TZE204_fhvdgeuh',
},
],
model: 'TZE204_fhvdgeuh',
vendor: 'Tuya',
description: 'Tuya multi-function energy monitor',
fromZigbee: [
tuya.fz.datapoints,
fzLocal.value,
// Дополнительные преобразователи, если необходимо
],
toZigbee: [tuya.tz.datapoints,tz_settings],
onEvent: tuya.onEvent({respondToMcuVersionResponse:false, queryIntervalSeconds: 3 * 60}),
configure: tuya.configureMagicPacket,
exposes: [
tuya.exposes.switch(),
e.energy(),
e.power(),
e.voltage(),
e.current(),
e.temperature(),
e.numeric('leakage_current', ea.STATE).withUnit('mA').withDescription('Leakage current'),
e.text('fault', ea.STATE).withDescription('Fault indication'),
e.numeric('balance_energy', ea.STATE).withUnit('kWh').withDescription('Balance energy (kWh)'),
e.numeric('over_leakage_current', ea.STATE_SET).withDescription('Over Leakage Current Cut Off').withValueMin(0).withValueMax(99).withValueStep(1).withUnit('mA'),
e.numeric('over_temperature', ea.STATE_SET).withDescription('Over Temperature Cut Off').withValueMin(0).withValueMax(100).withValueStep(1).withUnit('°C'),
e.numeric('over_voltage', ea.STATE_SET).withDescription('Over Voltage Cut Off').withValueMin(120).withValueMax(300).withValueStep(1).withUnit('V'),
e.numeric('under_voltage', ea.STATE_SET).withDescription('Under Voltage Cut Off').withValueMin(80).withValueMax(210).withValueStep(1).withUnit('V'),
e.numeric('reclose_recover_seconds', ea.STATE_SET).withDescription('Reclose recover seconds').withValueMin(10).withValueMax(99).withValueStep(1),
e.numeric('over_current', ea.STATE_SET).withDescription('Over Current Cut Off').withValueMin(1).withValueMax(63).withValueStep(0.1).withUnit('A'),
e.numeric('reclosing_allowed_times', ea.STATE_SET).withDescription('Time Restore After Over Current').withValueMin(0).withValueMax(30).withValueStep(1),
exposes.numeric('charge_energy', ea.STATE).withDescription('Charge energy'),
exposes.binary('clear_energy', ea.STATE_SET, 'ON', 'OFF').withDescription('Clear energy data'),
exposes.binary('switch_prepayment', ea.STATE_SET, 'ON', 'OFF').withDescription('Switch prepayment'),
//e.numeric('reclosing_allowed_times', ea.STATE).withDescription('Reclosing allowed times'),
exposes.binary('reclosing_enable', ea.STATE_SET, 'ON', 'OFF').withDescription('Reclosing enable'),
exposes.numeric('timer', ea.STATE).withDescription('Timer'),
exposes.numeric('cycle_schedule', ea.STATE).withDescription('Cycle Schedule'),
exposes.numeric('random_timing', ea.STATE).withDescription('Random Timing'),
exposes.numeric('switch_inching', ea.STATE).withDescription('Switch Inching'),
exposes.numeric('power_on_delay', ea.STATE).withDescription('Power-on delay power-on time'),
exposes.numeric('overcurrent_event_threshold_time', ea.STATE).withDescription('Overcurrent Event Threshold Time'),
exposes.numeric('time_threshold_lost_flow', ea.STATE).withDescription('Time Threshold of Lost Flow Event'),
exposes.numeric('alarm1', ea.STATE).withDescription('Alarm set1'),
exposes.numeric('alarm2', ea.STATE).withDescription('Alarm set2'),
exposes.numeric('alarm_set3', ea.STATE).withDescription('Alarm set3'),
exposes.numeric('status', ea.STATE).withDescription('Device status'),
//e.binary('status', ea.STATE, 'ON', 'OFF').withDescription('Device status'),
exposes.numeric('relay_status_power_on', ea.STATE).withDescription('Relay status for power on'),
//e.binary('relay_status_power_on', ea.STATE, 'ON', 'OFF').withDescription('Relay status for power on'),
],
meta: {
tuyaDatapoints: [
[1, 'energy', tuya.valueConverter.raw],
[6, null, tuya.valueConverter.phaseVariant2],
[9, 'fault', tuya.valueConverter.raw],
[11, 'switch_prepayment', tuya.valueConverter.onOff],
[12, 'clear_energy', tuya.valueConverter.onOff],
[13, 'balance_energy', tuya.valueConverter.divideBy100],
[14, 'charge_energy', tuya.valueConverter.divideBy100],
[15, 'leakage_current', tuya.valueConverter.raw],
[16, 'state', tuya.valueConverter.onOff],
[17, 'alarm1', tuya.valueConverter.raw],
[18, 'alarm2', tuya.valueConverter.raw],
[101, 'restore_time', tuya.valueConverter.raw], // Deprecated
[102, 'reclosing_allowed_times', tuya.valueConverter.raw],
[103, 'temperature', tuya.valueConverter.raw],
[104, 'reclosing_enable', tuya.valueConverter.onOff],
[105, 'timer', tuya.valueConverter.raw],
[106, 'cycle_schedule', tuya.valueConverter.raw],
[107, 'reclose_recover_seconds', tuya.valueConverter.raw],
[108, 'random_timing', tuya.valueConverter.raw],
[109, 'switch_inching', tuya.valueConverter.raw],
[119, 'power_on_delay', tuya.valueConverter.raw],
[124, 'overcurrent_event_threshold_time', tuya.valueConverter.raw],
[125, 'time_threshold_lost_flow', tuya.valueConverter.raw],
[126, 'alarm_set3', tuya.valueConverter.raw],
[127, 'status', tuya.valueConverter.raw],
//[127, 'status', customTrueFalseConverter],
[134, 'relay_status_power_on', tuya.valueConverter.raw],
//[134, 'relay_status_power_on', tuya.valueConverter.onOff],
],
},
};
module.exports = definition;
Excellent work, thank you very much.
Could someone submit a pull request to add of the box support for this device?
I can, but i don't know what do you mean at "pull request". Where and how can i do it?
And all function not realized in this version here. Must have as i think it's clear data energy button: In tuya app need write pass, and in real life too. But i don't know where and how. Cause wipe "Clear energy" button not work and as i think it cause without pass. PS I applologize for my english. I am from Ukraine.
Ok, i check it, and as i understand right, it can't reset Energy remotly, not in tuya app, not through zigbee2mqtt
So it's maybe final version of this
@peekayn84 the converter is not yet in a state that I can integrate it. We should e.g. get rid of the tz_settings
. I guess you redefined it because some keys are missing. I've fixed that now in https://github.com/Koenkk/zigbee-herdsman-converters/commit/36e7440a4fa34b6757ce534771408d5fa0360db5 . Can you check with the latest dev?
Changes will be available in the dev branch in a few hours from now.
I use it cause i don't know how change complex value like over_voltage, it part of 18 datapoit, i delete tz_setting and get this error
@peekayn84 misunderstood @Koenkk, I tried your variant as external converter. Notice that all values remain 'Null'. I noticed the same "Cannot read properties..." error.
after a while:
...I am surprised about the 2kWh used, since the device isn't connected to anything.
@peekayn84 is this on the latest dev branch? For more complex value converters, see e.g. https://github.com/Koenkk/zigbee-herdsman-converters/blob/b3169739e07ee6ffa90da93d21eefe78bb046d07/src/lib/tuya.ts#L587
Seems fixed by TZE204_fhvdgeuh definition and released in 1.40.1-1
новое обновление1.40.1-1 решило но есть проблемы по отображению вольт и ампер в пользовательской карточке
Link
https://aliexpress.ru/item/1005005984673866.html?spm=a2g2w.orderdetail.0.0.42154aa6JzNYVB&sku_id=12000038280422974
Database entry
{"id":12,"type":"Router","ieeeAddr":"0xa4c1382762a38dd1","nwkAddr":58462,"manufId":4417,"manufName":"_TZE204_fhvdgeuh","powerSource":"Mains (single phase)","modelId":"TS0601","epList":[1,242],"endpoints":{"1":{"profId":260,"epId":1,"devId":81,"inClusterList":[4,5,61184,0],"outClusterList":[25,10],"clusters":{"genBasic":{"attributes":{"65503":"&�?.i��?.i��?.i��?.i��?.i��?.i��?.i","65506":56,"65508":0,"modelId":"TS0601","manufacturerName":"_TZE204_fhvdgeuh","powerSource":1,"zclVersion":3,"appVersion":74,"stackVersion":0,"hwVersion":1,"dateCode":""}}},"binds":[],"configuredReportings":[],"meta":{}},"242":{"profId":41440,"epId":242,"devId":97,"inClusterList":[],"outClusterList":[33],"clusters":{},"binds":[],"configuredReportings":[],"meta":{}}},"appVersion":74,"stackVersion":0,"hwVersion":1,"dateCode":"","zclVersion":3,"interviewCompleted":true,"meta":{},"lastSeen":1722618429404}
Comments
Устройство -Умный автоматический выключатель Tuya https://aliexpress.ru/item/1005005984673866.html?spm=a2g2w.orderdetail.0.0.42154aa6JzNYVB&sku_id=12000038280422974
External definition