Koenkk / zigbee2mqtt

Zigbee 🐝 to MQTT bridge 🌉, get rid of your proprietary Zigbee bridges 🔨
https://www.zigbee2mqtt.io
GNU General Public License v3.0
12.16k stars 1.68k forks source link

[New device support]: ZHT-PT01-M-MS #24635

Open barchasse38 opened 1 week ago

barchasse38 commented 1 week ago

Link

https://moeshouse.com/products/smart-thermostat-for-pilot-wire-heating-radiator-support-ecowatt-electricity-monitoring?variant=49571901604155

Database entry

{"id":35,"type":"EndDevice","ieeeAddr":"0xa4c13848355beea0","nwkAddr":34537,"manufId":4417,"manufName":"_TZE204_x9usygq1","powerSource":"Battery","modelId":"TS0601","epList":[1],"endpoints":{"1":{"profId":260,"epId":1,"devId":81,"inClusterList":[0,4,5,61184],"outClusterList":[25,10],"clusters":{"genBasic":{"attributes":{"65487":180,"65503":"\u0013 �.i\u0017 �.i","65506":56,"65508":0,"65534":0,"stackVersion":0,"dateCode":"","appVersion":74,"manufacturerName":"_TZE204_x9usygq1","zclVersion":3,"modelId":"TS0601","powerSource":3}}},"binds":[{"cluster":0,"type":"endpoint","deviceIeeeAddress":"0xe0798dfffe7191ae","endpointID":1}],"configuredReportings":[{"cluster":0,"attrId":4,"minRepIntval":60,"maxRepIntval":3600,"repChange":0},{"cluster":0,"attrId":7,"minRepIntval":60,"maxRepIntval":3600,"repChange":0}],"meta":{}}},"appVersion":74,"stackVersion":0,"hwVersion":1,"dateCode":"","zclVersion":3,"interviewCompleted":true,"meta":{"configured":332242049},"lastSeen":1730736180727}

Zigbee2MQTT version

1.41.0

Comments

I tried to follow the supporting new device page for tuya : https://www.zigbee2mqtt.io/advanced/support-new-devices/02_support_new_tuya_devices.html But that a first for me, and I can't get any information from the module.

External definition

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 modernExtend = require('zigbee-herdsman-converters/lib/modernExtend');
const e = exposes.presets;
const ea = exposes.access;
const tuya = require('zigbee-herdsman-converters/lib/tuya');

const definition = {
    // Since a lot of Tuya devices use the same modelID, but use different datapoints
    // it's necessary to provide a fingerprint instead of a zigbeeModel
    fingerprint: [
        {
            // The model ID from: Device with modelID 'TS0601' is not supported
            // You may need to add \u0000 at the end of the name in some cases
            modelID: 'TS0601',
            // The manufacturer name from: Device with modelID 'TS0601' is not supported.
            manufacturerName: '_TZE204_x9usygq1',
        },
    ],
    model: 'ZHT-PT01-M-MS', // Update this with the real model of the device (written on the device itself or product page)
    vendor: 'Moes', // Update this with the real vendor of the device (written on the device itself or product page)
    description: 'Smart Thermostat For Pilot Wire Heating Radiator', // Description of the device, copy from vendor site. (only used for documentation and startup logging)
    fromZigbee: [tuya.fz.datapoints],
    toZigbee: [tuya.tz.datapoints],
    onEvent: tuya.onEventSetTime, // Add this if you are getting no converter for 'commandMcuSyncTime'
    configure: tuya.configureMagicPacket,
    exposes: [
        e.power(),
        e.energy(),
        e.child_lock(),
    ],
    meta: {
            tuyaDatapoints: [
                [39, 'child_lock', tuya.valueConverter.lockUnlock],
            ],
    },
    extend: [
        // A preferred new way of extending functionality.
    ],
};

module.exports = definition;

What does/doesn't work with the external definition?

Nothing works. For the moment I'm just trying to get the child lock state as a test but I'm unable to get any information.

barchasse38 commented 4 days ago

I just retrieved the data point specifications :

DP ID DP Name Identifier Data Transfer Type Data Type Properties
2 Mode mode Send and Report enum Enum Value: Standby, Comfort, Comfort_1, Comfort_2, ECO, Anti_forst, Programming, Thermostat
16 Current temperature temp_current Report Only value Value Range: -300-9000, Pitch: 1, Scale: 1, Unit:
17 State of the window window_state Report Only enum Enum Value: close, open
18 The lower limit of temperature lower_temp Send and Report value Value Range: 50-3000, Pitch: 10, Scale: 1, Unit:
19 Temperature correction temp_correction Send and Report value Value Range: -100-100, Pitch: 1, Scale: 1, Unit:
20 Fault alarm fault Report Only fault Fault Value: e1, e2
29 Window check window_check Send and Report bool  
34 Set temperature ceiling upper_temp Send and Report value Value Range: 50-3000, Pitch: 10, Scale: 1, Unit:
39 Child lock child_lock Send and Report bool  
46 Temperature Scale temp_unit_convert Send and Report enum Enum Value: c, f
50 Set temperature temp_set Send and Report value Value Range: 50-3000, Pitch: 5, Scale: 1, Unit:
65 Week Program 1 week_program_1 Send and Report raw  
66 Week Program 2 week_program_2 Send and Report raw  
67 Week Program 3 week_program_3 Send and Report raw  
68 Week Program 4 week_program_4 Send and Report raw  
69 Week Program 5 week_program_5 Send and Report raw  
70 Week Program 6 week_program_6 Send and Report raw  
71 Week Program 7 week_program_7 Send and Report raw  
101 Vacation Duration vacation_duration Send and Report value Value Range: 0-364, Pitch: 1, Scale: 0, Unit:
102 Boost mode duration boost_duration Send and Report value Value Range: 0-120, Pitch: 1, Scale: 0, Unit: minute
103 Electricity Usage electricity_statistics Report Only value Value Range: 0-2000000000, Pitch: 1, Scale: 1, Unit: kWh
104 Daily usage elec_statistics_day Report Only raw  
105 Monthly usage elec_statistics_month Report Only raw  
106 Annual usage elec_statistics_year Report Only raw  
107 Avg. Power average_power Report Only value Value Range: 0-2000000000, Pitch: 1, Scale: 1, Unit: w
108 Air pressure index air_pressure_index Report Only raw  
109 Support Features support_features Report Only value Value Range: 0-2147483647, Pitch: 1, Scale: 0, Unit:
110 Window keep time window_keep_time Send and Report value Value Range: 0-120, Pitch: 1, Scale: 0, Unit: min
111 App Featrures app_features Send and Report value Value Range: 0-2147483647, Pitch: 1, Scale: 0, Unit:
112 Switching Hysteresis switch_diff Send and Report value Value Range: 1-100, Pitch: 1, Scale: 1, Unit:
113 Running status running_mode Report Only enum Enum Value: Standby, Comfort, Comfort_1, Comfort_2, ECO, Anti_forst
114 Night LED Config night_led_config Send and Report raw  

I updated my code definition accordingly, but it's not yet very conclusive :

const legacy = require('zigbee-herdsman-converters/lib/legacy');
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 modernExtend = require('zigbee-herdsman-converters/lib/modernExtend');
const e = exposes.presets;
const ea = exposes.access;
const tuya = require('zigbee-herdsman-converters/lib/tuya');

const definition = {
    // Since a lot of Tuya devices use the same modelID, but use different datapoints
    // it's necessary to provide a fingerprint instead of a zigbeeModel
    fingerprint: [
        {
            // The model ID from: Device with modelID 'TS0601' is not supported
            // You may need to add \u0000 at the end of the name in some cases
            modelID: 'TS0601',
            // The manufacturer name from: Device with modelID 'TS0601' is not supported.
            manufacturerName: '_TZE204_x9usygq1',
        },
    ],
    model: 'ZHT-PT01-M-MS', // Update this with the real model of the device (written on the device itself or product page)
    vendor: 'Moes', // Update this with the real vendor of the device (written on the device itself or product page)
    description: 'Smart Thermostat For Pilot Wire Heating Radiator', // Description of the device, copy from vendor site. (only used for documentation and startup logging)
    fromZigbee: [
        tuya.fz.datapoints,
    ],                                                                                                                            
    toZigbee: [
        tuya.tz.datapoints,
    ],                                                                                                                              
    onEvent: tuya.onEventSetLocalTime,                                                                                                                           
    configure: tuya.configureMagicPacket,                                                                                                                        
    exposes: [
        e
            .enum('mode', ea.STATE_SET, ['standby', 'comfort', 'comfort_1', 'comfort_2', 'eco', 'antifrost', 'program', 'thermostat'])
            .withDescription('Working mode'),
        e
            .temperature()
            .withDescription('Current temperature'),
        e
            .binary('window_state', ea.STATE, 'close', 'open')
            .withDescription('Window status (open/close)'),
        e
            .binary('fault', ea.STATE, 'DETECTED', 'NOT_DETECTED')
            .withDescription('Fault status'),
        e.window_detection(),
        e.child_lock(),
        e
            .enum('temp_unit_convert', ea.STATE_SET, ['c', 'f'])
            .withDescription('Temperature unit'),
        e
            .numeric('temp_set', ea.STATE_SET)
            .withUnit('°C')
            .withValueMin(5)
            .withValueMax(30)
            .withDescription('Set temperature'),
        e
            .numeric('electricity_statistics', ea.STATE)
            .withUnit('kWh')
            .withDescription('Electricity usage statistics'),
        e
            .numeric('boost_duration', ea.STATE_SET)
            .withUnit('min')
            .withValueMin(0)
            .withValueMax(120)
            .withDescription('Boost mode duration'),
        e.numeric('elec_statistics_day', ea.STATE).withDescription('Daily energy usage'),
        e.numeric('elec_statistics_month', ea.STATE).withDescription('Monthly energy usage'),
        e.numeric('elec_statistics_year', ea.STATE).withDescription('Annual energy usage'),
        e.numeric('window_keep_time', ea.STATE_SET).withUnit('min').withDescription('Time window should be kept open'),
        e.enum('fault', ea.STATE, ['e1', 'e2']).withDescription('Fault alarm (e1, e2)'),
        e
            .enum('running_mode', ea.STATE, ['standby', 'comfort', 'comfort_1', 'comfort_2', 'eco', 'antifrost'])
            .withDescription('Current running mode'),
         e.numeric('night_led_config', ea.STATE_SET).withDescription('Night LED configuration'),
    ],
    meta: {
        tuyaDatapoints: [
            [
                2,
                'mode',
                tuya.valueConverterBasic.lookup({
                    standby: tuya.enum(0),
                    comfort: tuya.enum(1),
                    comfort_1: tuya.enum(2),
                    comfort_2: tuya.enum(3),
                    eco: tuya.enum(4),
                    antifrost: tuya.enum(5),
                    program: tuya.enum(6),
                    thermostat: tuya.enum(7),
                }),
            ],
            [16, 'temperature', tuya.valueConverter.divideBy10],
            [
                17,
                'window_state',
                tuya.valueConverterBasic.lookup({
                    close: tuya.enum(0),
                    open: tuya.enum(1),
                }),
            ],
            [18, 'lower_temp', tuya.valueConverter.divideBy10],
            [19, 'temp_correction', tuya.valueConverter.divideBy10],
            [20, 'fault', tuya.valueConverter.raw],
            [29, 'window_detection', tuya.valueConverter.onOff],
            [34, 'upper_temp', tuya.valueConverter.divideBy10],
            [39, 'child_lock', tuya.valueConverter.lockUnlock],
            [
                46,
                'temp_unit_convert',
                tuya.valueConverterBasic.lookup({
                    c: tuya.enum(0),
                    f: tuya.enum(1),
                }),
            ],
            [50, 'temp_set', tuya.valueConverter.raw],
            [65, 'week_program_1', tuya.valueConverter.raw],
            [66, 'week_program_2', tuya.valueConverter.raw],
            [67, 'week_program_3', tuya.valueConverter.raw],
            [68, 'week_program_4', tuya.valueConverter.raw],
            [69, 'week_program_5', tuya.valueConverter.raw],
            [70, 'week_program_6', tuya.valueConverter.raw],
            [71, 'week_program_7', tuya.valueConverter.raw],
            [101, 'vacation_duration', tuya.valueConverter.raw],
            [102, 'boost_duration', tuya.valueConverter.raw],
            [103, 'electricity_statistics', tuya.valueConverter.raw],
            [104, 'elec_statistics_day', tuya.valueConverter.raw],
            [105, 'elec_statistics_month', tuya.valueConverter.raw],
            [106, 'elec_statistics_year', tuya.valueConverter.raw],
            [107, 'average_power', tuya.valueConverter.raw],
            [108, 'air_pressure_index', tuya.valueConverter.raw],
            [109, 'support_features', tuya.valueConverter.raw],
            [110, 'window_keep_time', tuya.valueConverter.raw],
            [111, 'app_features', tuya.valueConverter.raw],
            [112, 'switch_diff', tuya.valueConverter.raw],
            [
                113, 
                'running_mode', 
                tuya.valueConverterBasic.lookup({
                    standby: tuya.enum(0),
                    comfort: tuya.enum(1),
                    comfort_1: tuya.enum(2),
                    comfort_2: tuya.enum(3),
                    eco: tuya.enum(4),
                    antifrost: tuya.enum(5),
                }),
            ],
            [114, 'night_led_config', tuya.valueConverter.raw],
        ],
    },
    extend: [
        // A preferred new way of extending functionality.
    ],
};

module.exports = definition;

I really appreciate some help.

barchasse38 commented 2 days ago

My Last definition :

const legacy = require('zigbee-herdsman-converters/lib/legacy');
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 modernExtend = require('zigbee-herdsman-converters/lib/modernExtend');
const e = exposes.presets;
const ea = exposes.access;
const tuya = require('zigbee-herdsman-converters/lib/tuya');

const definition = {
    // Since a lot of Tuya devices use the same modelID, but use different datapoints
    // it's necessary to provide a fingerprint instead of a zigbeeModel
    fingerprint: [
        {
            // The model ID from: Device with modelID 'TS0601' is not supported
            // You may need to add \u0000 at the end of the name in some cases
            modelID: 'TS0601',
            // The manufacturer name from: Device with modelID 'TS0601' is not supported.
            manufacturerName: '_TZE204_x9usygq1',
        },
    ],
    model: 'ZHT-PT01-M-MS', // Update this with the real model of the device (written on the device itself or product page)
    vendor: 'Moes', // Update this with the real vendor of the device (written on the device itself or product page)
    description: 'Smart Thermostat For Pilot Wire Heating Radiator', // Description of the device, copy from vendor site. (only used for documentation and startup logging)
    fromZigbee: [
        tuya.fz.datapoints,
    ],                                                                                                                            
    toZigbee: [
        tuya.tz.datapoints,
    ],                                                                                                                              
    onEvent: tuya.onEventSetLocalTime,                                                                                                                           
    configure: tuya.configureMagicPacket,                                                                                                                        
    exposes: [
        e
            .climate()
            .withSetpoint('current_heating_setpoint', 5, 30, 0.5, ea.STATE_SET)
            .withLocalTemperature(ea.STATE)
            .withPreset(['standby', 'comfort', 'comfort_1', 'comfort_2', 'eco', 'antifrost', 'program', 'thermostat'])
            .withSystemMode(['off', 'heat'], ea.STATE)
            .withLocalTemperatureCalibration(-10, 10, 0.1, ea.STATE_SET),
        e
            .enum('mode', ea.STATE_SET, ['standby', 'comfort', 'comfort_1', 'comfort_2', 'eco', 'antifrost', 'program', 'thermostat'])
            .withDescription('Working mode'),
        e
            .window_open(),
        /*
        e
            .temperature()
            .withDescription('Current temperature'),
        */
        /*
        e
            .binary('window_state', ea.STATE, 'close', 'open')
            .withDescription('Window status (open/close)'),
        */
        e
            .binary('fault', ea.STATE, 'DETECTED', 'NOT_DETECTED')
            .withDescription('Fault status'),
        e
            .window_detection(),
        e
            .child_lock(),
        e
            .enum('temp_unit_convert', ea.STATE_SET, ['c', 'f'])
            .withDescription('Temperature unit'),
        e
            .numeric('temp_set', ea.STATE_SET)
            .withUnit('°C')
            .withValueMin(5)
            .withValueMax(30)
            .withDescription('Set temperature'),
        e
            .numeric('lower_temp', ea.STATE_SET)
            .withUnit('°C')
            .withValueMin(5)
            .withValueMax(30)
            .withDescription('Set min temperature'),
        e
            .numeric('upper_temp', ea.STATE_SET)
            .withUnit('°C')
            .withValueMin(5)
            .withValueMax(30)
            .withDescription('Set max temperature'),
        e
            .numeric('electricity_statistics', ea.STATE)
            .withUnit('kWh')
            .withDescription('Electricity usage statistics'),
        e
            .numeric('boost_duration', ea.STATE_SET)
            .withUnit('min')
            .withValueMin(0)
            .withValueMax(120)
            .withDescription('Boost mode duration'),
        e.numeric('elec_statistics_day', ea.STATE).withDescription('Daily energy usage'),
        e.numeric('elec_statistics_month', ea.STATE).withDescription('Monthly energy usage'),
        e.numeric('elec_statistics_year', ea.STATE).withDescription('Annual energy usage'),
        e.numeric('window_keep_time', ea.STATE_SET).withUnit('min').withDescription('Time window should be kept open'),
        e.enum('fault', ea.STATE, ['e1', 'e2']).withDescription('Fault alarm (e1, e2)'),
        e
            .enum('running_mode', ea.STATE, ['standby', 'comfort', 'comfort_1', 'comfort_2', 'eco', 'antifrost'])
            .withDescription('Current running mode'),
         e.numeric('night_led_config', ea.STATE_SET).withDescription('Night LED configuration'),
    ],
    meta: {
        tuyaDatapoints: [
            [
                2,
                'mode',
                tuya.valueConverterBasic.lookup({
                    standby: tuya.enum(0),
                    comfort: tuya.enum(1),
                    comfort_1: tuya.enum(2),
                    comfort_2: tuya.enum(3),
                    eco: tuya.enum(4),
                    antifrost: tuya.enum(5),
                    program: tuya.enum(6),
                    thermostat: tuya.enum(7),
                }),
            ],
            //[16, 'temp_current', tuya.valueConverter.divideBy10],
            [16, 'local_temperature', tuya.valueConverter.divideBy10],
            //[16, 'temperature', tuya.valueConverter.divideBy10],
            /*
            [
                17,
                'window_state',
                tuya.valueConverterBasic.lookup({
                    close: tuya.enum(0),
                    open: tuya.enum(1),
                }),
            ],
            */
            [
                17,
                'window_open',
                tuya.valueConverterBasic.lookup({
                    close: tuya.enum(0),
                    open: tuya.enum(1),
                }),
            ],
            [18, 'lower_temp', tuya.valueConverter.divideBy10],
            [19, 'temp_correction', tuya.valueConverter.divideBy10],
            [19, 'local_temperature_calibration', tuya.valueConverter.divideBy10],
            [20, 'fault', tuya.valueConverter.raw],
            [29, 'window_detection', tuya.valueConverter.onOff],
            [34, 'upper_temp', tuya.valueConverter.divideBy10],
            [39, 'child_lock', tuya.valueConverter.lockUnlock],
            [
                46,
                'temp_unit_convert',
                tuya.valueConverterBasic.lookup({
                    c: tuya.enum(0),
                    f: tuya.enum(1),
                }),
            ],
            [50, 'temp_set', tuya.valueConverter.divideBy10],
            [50, 'current_heating_setpoint', tuya.valueConverter.divideBy10],
            [65, 'week_program_1', tuya.valueConverter.raw],
            [66, 'week_program_2', tuya.valueConverter.raw],
            [67, 'week_program_3', tuya.valueConverter.raw],
            [68, 'week_program_4', tuya.valueConverter.raw],
            [69, 'week_program_5', tuya.valueConverter.raw],
            [70, 'week_program_6', tuya.valueConverter.raw],
            [71, 'week_program_7', tuya.valueConverter.raw],
            [101, 'vacation_duration', tuya.valueConverter.raw],
            [102, 'boost_duration', tuya.valueConverter.raw],
            [103, 'electricity_statistics', tuya.valueConverter.raw],
            [104, 'elec_statistics_day', tuya.valueConverter.raw],
            [105, 'elec_statistics_month', tuya.valueConverter.raw],
            [106, 'elec_statistics_year', tuya.valueConverter.raw],
            [107, 'average_power', tuya.valueConverter.raw],
            [108, 'air_pressure_index', tuya.valueConverter.raw],
            [109, 'support_features', tuya.valueConverter.raw],
            [110, 'window_keep_time', tuya.valueConverter.raw],
            [111, 'app_features', tuya.valueConverter.raw],
            [112, 'switch_diff', tuya.valueConverter.raw],
            [
                113, 
                'running_mode', 
                tuya.valueConverterBasic.lookup({
                    standby: tuya.enum(0),
                    comfort: tuya.enum(1),
                    comfort_1: tuya.enum(2),
                    comfort_2: tuya.enum(3),
                    eco: tuya.enum(4),
                    antifrost: tuya.enum(5),
                }),
            ],
            [114, 'night_led_config', tuya.valueConverter.raw],
        ],
    },
    extend: [
        // A preferred new way of extending functionality.
    ],
};

module.exports = definition;

I think I'm close but it's not ready yet for production.

ludoviclt commented 2 days ago

i Will test tomorow, thanks a lot for your job

ludoviclt commented 9 hours ago

hello, I have a lot of information coming, the box is not yet in production, so I don't know if there is everything I need to make my radiators work. I think so. If you need help how can I help you?