Hi everyone. I faced the same problem. I bought a TS004F switch and it did not work with zigbee2mqtt. So I spent a little time and wrote an external conveter for it. But I couldn’t get everything to work. Single press events work for all 4 buttons, and hold event works only for the 2 right side buttons. No other events (like double click) appear in the console in debug mode so I can’t write a converter for them.
To use my converter add the following lines to your configuration.yaml:
external_converters:
- TS004F.js
And save the code below in the file data/TS004F.js
next to the file configuration.yaml
:
(UPD: the data
dir is the dir where the configuration.yaml
file is located and may have a different name for you)
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 reporting = require('zigbee-herdsman-converters/lib/reporting');
const extend = require('zigbee-herdsman-converters/lib/extend');
const e = exposes.presets;
const ea = exposes.access;
const bind = async (endpoint, target, clusters) => {
for (const cluster of clusters) {
await endpoint.bind(cluster, target);
}
};
/*
Buttons numbers:
-------
| 1 | 3 |
|-------|
| 2 | 4 |
-------
*/
const leftButtonsConverter = {
cluster: 'genOnOff',
type: ['commandOn', 'commandOff', 'commandToggle'],
convert: (model, msg, publish, options, meta) => {
if (msg.type === 'commandOn') {
return { action: '1_single' };
}
if (msg.type === 'commandOff') {
return { action: '2_single' };
}
},
};
const rightButtonsConverter = {
cluster: 'genLevelCtrl',
type: ['commandStep', 'commandMove', 'commandStop'],
convert: (model, msg, publish, options, meta) => {
if (msg.type === 'commandStep') {
if (msg.data.stepmode === 0) {
return { action: '3_single' };
}
else if (msg.data.stepmode === 1) {
return { action: '4_single' };
}
}
else if (msg.type === 'commandMove') {
if (msg.data.movemode === 0) {
return { action: '3_hold' };
}
else if (msg.data.movemode === 1) {
return { action: '4_hold' };
}
}
else if (msg.type === 'commandStop') {
// No data available to determine which button was released
return { action: 'release' };
}
// No 'double' events are fired
},
};
const definition = {
zigbeeModel: ['TS004F'],
model: 'TS004F',
vendor: 'TuYa',
description: 'Wireless switch with 4 buttons',
whiteLabel: [{vendor: '_TZ3000_xabckq1v', model: 'TS004F'}],
// Exposed commands are similar to the Tuya TS0044 switch
exposes: [
e.battery(),
e.action([
'1_single',
'2_single',
'3_single', '3_hold',
'4_single', '4_hold'
/*
'1_single', '1_double', '1_hold',
'2_single', '2_double', '2_hold',
'3_single', '3_double', '3_hold',
'4_single', '4_double', '4_hold'
*/
])
],
fingerprint: [
{
modelID: 'TS004F',
manufacturerName: '_TZ3000_xabckq1v'
},
],
fromZigbee: [
fz.battery,
leftButtonsConverter,
rightButtonsConverter,
],
toZigbee: [
],
meta: {
configureKey: 1,
},
configure: async (device, coordinatorEndpoint, logger) => {
const endpoint = device.getEndpoint(1);
await bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
await bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
const payload = [{
attribute: 'batteryPercentageRemaining',
minimumReportInterval: 0,
maximumReportInterval: 3600,
reportableChange: 1,
}, {
attribute: 'batteryVoltage',
minimumReportInterval: 0,
maximumReportInterval: 3600,
reportableChange: 1,
}];
await endpoint.configureReporting('genPowerCfg', payload);
},
};
module.exports = definition;
Then you can use the blueprint described here.