pvvx / ZigbeeTLc

Custom firmware for Zigbee 3.0 IoT devices on the TLSR825x chip
Other
321 stars 15 forks source link

MHO-C401N-z not supported in Z2M? #83

Closed unmesh59 closed 2 months ago

unmesh59 commented 3 months ago

I just got my MHO-301 and flashed it to v0120 firmware. I'm using it with the Z2M add on in HA and it is reporting temperature and humidity.

However the Z2M GUI (in which is shows up as a MHO-C401N-z) is reporting it as an unsupported device. Is that to be expected or should I be using an external converter?

Thanks

TeHashX commented 3 months ago

I used this converter, just changed the name, I'm not 100% it's ok but it works https://github.com/pvvx/ZigbeeTLc/blob/master/z2m/lywsd03mmc-z.js

// Autor: Markus Bodengriller https://github.com/Bodengriller
// requires zigbee2mqtt v1.34+
// external converter for Xiaomi LYWSD03MMC https://github.com/pvvx/ZigbeeTLc
// based on external converter for devbis-Firmware
// https://raw.githubusercontent.com/devbis/z03mmc/master/converters/lywsd03mmc.js

const {
    battery,
    temperature,
    humidity,
    enumLookup,
    binary,
    numeric,
    quirkAddEndpointCluster,
} = require('zigbee-herdsman-converters/lib/modernExtend');
const reporting = require('zigbee-herdsman-converters/lib/reporting');
const ota = require('zigbee-herdsman-converters/lib/ota');

const dataType = {
    boolean: 0x10,
    uint8: 0x20,
    uint16: 0x21,
    int8: 0x28,
    int16: 0x29,
    enum8: 0x30,
};

const definition = {
    zigbeeModel: ['MHO-C401N-z'],
    model: 'MHO-C401N',
    vendor: 'MiaMiaoCe',
    description: 'E-Ink Temperature & humidity sensor with custom firmware',
    extend: [
        quirkAddEndpointCluster({
            endpointID: 1,
            outputClusters: [],
            inputClusters: [
                'genPowerCfg',
                'msTemperatureMeasurement',
                'msRelativeHumidity',
                'hvacUserInterfaceCfg',
            ],
        }),
        battery({percentage: true}),
        temperature({reporting: {min: 10, max: 300, change: 10}}),
        humidity({reporting: {min: 10, max: 300, change: 50}}),
        enumLookup({
            name: 'temperature_display_mode',
            lookup: {'celsius': 0, 'fahrenheit': 1},
            cluster: 'hvacUserInterfaceCfg',
            attribute: {ID: 0x0000, type: dataType.enum8},
            description: 'The units of the temperature displayed on the device screen.',
        }),
        binary({
            name: 'show_smiley',
            valueOn: ['SHOW', 0],
            valueOff: ['HIDE', 1],
            cluster: 'hvacUserInterfaceCfg',
            attribute: {ID: 0x0002, type: dataType.enum8},
            description: 'Whether to show a smiley on the device screen.',
        }),
        numeric({
            name: 'temperature_calibration',
            unit: 'ºC',
            cluster: 'hvacUserInterfaceCfg',
            attribute: {ID: 0x0100, type: dataType.int8},
            valueMin: -12.7,
            valueMax: 12.7,
            valueStep: 0.1,
            scale: 10,
            description: 'The temperature calibration, in 0.1° steps.',
        }),
        numeric({
            name: 'humidity_calibration',
            unit: '%',
            cluster: 'hvacUserInterfaceCfg',
            attribute: {ID: 0x0101, type: dataType.int8},
            valueMin: -12.7,
            valueMax: 12.7,
            valueStep: 0.1,
            scale: 10,
            description: 'The humidity offset is set in 0.1 % steps.',
        }),
        numeric({
            name: 'comfort_temperature_min',
            unit: 'ºC',
            cluster: 'hvacUserInterfaceCfg',
            attribute: {ID: 0x0102, type: dataType.int8},
            valueMin: -127.0,
            valueMax: 127.0,
            description: 'Comfort parameters/Temperature minimum, in 1°C steps.',
        }),
        numeric({
            name: 'comfort_temperature_max',
            unit: 'ºC',
            cluster: 'hvacUserInterfaceCfg',
            attribute: {ID: 0x0103, type: dataType.int8},
            valueMin: -127.0,
            valueMax: 127.0,
            description: 'Comfort parameters/Temperature maximum, in 1°C steps.',
        }),
        numeric({
            name: 'comfort_humidity_min',
            unit: '%',
            cluster: 'hvacUserInterfaceCfg',
            attribute: {ID: 0x0104, type: dataType.uint8},
            valueMin: 0.0,
            valueMax: 100.0,
            description: 'Comfort parameters/Humidity minimum, in 1% steps.',
        }),
        numeric({
            name: 'comfort_humidity_max',
            unit: '%',
            cluster: 'hvacUserInterfaceCfg',
            attribute: {ID: 0x0105, type: dataType.uint8},
            valueMin: 0.0,
            valueMax: 100.0,
            description: 'Comfort parameters/Humidity maximum, in 1% steps.',
        }),
    ],
    ota: ota.zigbeeOTA,
    configure: async (device, coordinatorEndpoint, logger) => {
        const endpoint = device.getEndpoint(1);
        const bindClusters = ['msTemperatureMeasurement', 'msRelativeHumidity', 'genPowerCfg'];
        await reporting.bind(endpoint, coordinatorEndpoint, bindClusters);
        await reporting.temperature(endpoint, {min: 10, max: 300, change: 10});
        await reporting.humidity(endpoint, {min: 10, max: 300, change: 50});
        await reporting.batteryPercentageRemaining(endpoint);
        try {
            await endpoint.read('hvacThermostat', [0x0010, 0x0011, 0x0102, 0x0103, 0x0104, 0x0105]);
            await endpoint.read('msTemperatureMeasurement', [0x0010]);
            await endpoint.read('msRelativeHumidity', [0x0010]);
        } catch (e) {
            /* backward compatibility */
        }
    },
};

module.exports = definition;
unmesh59 commented 2 months ago

That worked great.

Thanks!

On Tue, Apr 9, 2024 at 5:30 AM TeHashX @.***> wrote:

I used this converter, just changed the name, I'm not 100% it's ok but it works https://github.com/pvvx/ZigbeeTLc/blob/master/z2m/lywsd03mmc-z.js

// Autor: Markus Bodengriller https://github.com/Bodengriller // requires zigbee2mqtt v1.34+ // external converter for Xiaomi LYWSD03MMC https://github.com/pvvx/ZigbeeTLc // based on external converter for devbis-Firmware // https://raw.githubusercontent.com/devbis/z03mmc/master/converters/lywsd03mmc.js

const { battery, temperature, humidity, enumLookup, binary, numeric, quirkAddEndpointCluster, } = require('zigbee-herdsman-converters/lib/modernExtend'); const reporting = require('zigbee-herdsman-converters/lib/reporting'); const ota = require('zigbee-herdsman-converters/lib/ota');

const dataType = { boolean: 0x10, uint8: 0x20, uint16: 0x21, int8: 0x28, int16: 0x29, enum8: 0x30, };

const definition = { zigbeeModel: ['MHO-C401N-z'], model: 'MHO-C401N', vendor: 'MiaMiaoCe', description: 'E-Ink Temperature & humidity sensor with custom firmware', extend: [ quirkAddEndpointCluster({ endpointID: 1, outputClusters: [], inputClusters: [ 'genPowerCfg', 'msTemperatureMeasurement', 'msRelativeHumidity', 'hvacUserInterfaceCfg', ], }), battery({percentage: true}), temperature({reporting: {min: 10, max: 300, change: 10}}), humidity({reporting: {min: 10, max: 300, change: 50}}), enumLookup({ name: 'temperature_display_mode', lookup: {'celsius': 0, 'fahrenheit': 1}, cluster: 'hvacUserInterfaceCfg', attribute: {ID: 0x0000, type: dataType.enum8}, description: 'The units of the temperature displayed on the device screen.', }), binary({ name: 'show_smiley', valueOn: ['SHOW', 0], valueOff: ['HIDE', 1], cluster: 'hvacUserInterfaceCfg', attribute: {ID: 0x0002, type: dataType.enum8}, description: 'Whether to show a smiley on the device screen.', }), numeric({ name: 'temperature_calibration', unit: 'ºC', cluster: 'hvacUserInterfaceCfg', attribute: {ID: 0x0100, type: dataType.int8}, valueMin: -12.7, valueMax: 12.7, valueStep: 0.1, scale: 10, description: 'The temperature calibration, in 0.1° steps.', }), numeric({ name: 'humidity_calibration', unit: '%', cluster: 'hvacUserInterfaceCfg', attribute: {ID: 0x0101, type: dataType.int8}, valueMin: -12.7, valueMax: 12.7, valueStep: 0.1, scale: 10, description: 'The humidity offset is set in 0.1 % steps.', }), numeric({ name: 'comfort_temperature_min', unit: 'ºC', cluster: 'hvacUserInterfaceCfg', attribute: {ID: 0x0102, type: dataType.int8}, valueMin: -127.0, valueMax: 127.0, description: 'Comfort parameters/Temperature minimum, in 1°C steps.', }), numeric({ name: 'comfort_temperature_max', unit: 'ºC', cluster: 'hvacUserInterfaceCfg', attribute: {ID: 0x0103, type: dataType.int8}, valueMin: -127.0, valueMax: 127.0, description: 'Comfort parameters/Temperature maximum, in 1°C steps.', }), numeric({ name: 'comfort_humidity_min', unit: '%', cluster: 'hvacUserInterfaceCfg', attribute: {ID: 0x0104, type: dataType.uint8}, valueMin: 0.0, valueMax: 100.0, description: 'Comfort parameters/Humidity minimum, in 1% steps.', }), numeric({ name: 'comfort_humidity_max', unit: '%', cluster: 'hvacUserInterfaceCfg', attribute: {ID: 0x0105, type: dataType.uint8}, valueMin: 0.0, valueMax: 100.0, description: 'Comfort parameters/Humidity maximum, in 1% steps.', }), ], ota: ota.zigbeeOTA, configure: async (device, coordinatorEndpoint, logger) => { const endpoint = device.getEndpoint(1); const bindClusters = ['msTemperatureMeasurement', 'msRelativeHumidity', 'genPowerCfg']; await reporting.bind(endpoint, coordinatorEndpoint, bindClusters); await reporting.temperature(endpoint, {min: 10, max: 300, change: 10}); await reporting.humidity(endpoint, {min: 10, max: 300, change: 50}); await reporting.batteryPercentageRemaining(endpoint); try { await endpoint.read('hvacThermostat', [0x0010, 0x0011, 0x0102, 0x0103, 0x0104, 0x0105]); await endpoint.read('msTemperatureMeasurement', [0x0010]); await endpoint.read('msRelativeHumidity', [0x0010]); } catch (e) { / backward compatibility / } }, };

module.exports = definition;

— Reply to this email directly, view it on GitHub https://github.com/pvvx/ZigbeeTLc/issues/83#issuecomment-2045075616, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIPPFCQBENJAQZRNO3FGMDDY4PNQBAVCNFSM6AAAAABF3ZYDD2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDANBVGA3TKNRRGY . You are receiving this because you authored the thread.Message ID: @.***>

TeHashX commented 2 months ago

Create the file named mho-c401n-z.js in /config/zigbee2mqtt and fill with data provided. Go to Z2M settings / External converters Add mho-c401n-z.js Press Submit Restart Z2M

unmesh59 commented 2 months ago

Thanks much!

TeHashX commented 2 months ago

FW v0.1.2.1 not working with this converter or this one https://github.com/pvvx/ZigbeeTLc/blob/master/z2m/zigbeetlc_v0121.js

robvanoostenrijk commented 2 months ago

Official support for all v0.1.2.1+ ZigbeeTLc devices was merged into Zigbee2MQTT master today: https://github.com/Koenkk/zigbee-herdsman-converters/pull/7457

TeHashX commented 2 months ago

Already updated Z2M to v1.37.0-1 and removed external converters, LYWSD03MMC works just fine but MHO-C401N shows as not supported. Also, I think OTA is broken for both LYWSD03MMC and MHO-C401N, shows update available but then the error:

Update of 'Bath Weather' failed (OTA: Timeout, device did not request any image blocks)

robvanoostenrijk commented 2 months ago

Its looking for MHO-C401N-z or MHO-C401N-bz. Also its LYWSD03MMC-z, LYWSD03MMC is assuming devbis firmware.

TeHashX commented 2 months ago

MHO-C401N-z and LYWSD03MMC-z with v0.1.2.1 on both.

TeHashX commented 2 months ago

Probably MHO-C401N-z don't have something enabled in firmware.

TeHashX commented 2 months ago

Also, I think OTA is broken for both LYWSD03MMC and MHO-C401N, shows update available but then the error:

Update of 'Bath Weather' failed (OTA: Timeout, device did not request any image blocks)

https://github.com/Koenkk/zigbee-herdsman-converters/pull/7457#discussion_r1582037681

Could be this change? Can you please check if you can update a device with v1.37.0-1?

pvvx commented 2 months ago

Probably MHO-C401N-z don't have something enabled in firmware.

All the problems Z2M has are from selecting a device by name, and not by digital identifiers of firmware version, device type and manufacturer number.

Zigbee OTA does not use the device name. https://github.com/pvvx/ZigbeeTLc/blob/master/bin/index.json

Ver 0.1.2.1 has the function of changing the device name. It works without problems with software that supports Zigbee 3.0.

Some Tuya devices have the same names, but the functionality depends on the firmware version. This is not resolved in Z2M.

The ZigbeeTLc firmware will not adapt to the quirks of the Z2M. Firmwares are created for easy use in Home Assistant for users who do not know and do not want to learn programming languages in Z2M. If You want to use Z2M, then you need to be able to independently program special scripts for any new Zigbee device each time.

robvanoostenrijk commented 2 months ago

I double checked the OTA update issue, I believe its an issue in the latest Z2M version.

Both the pre-existing converter (using legacy methods) as well as the modernExtend implementation time out:

[2024-05-03 07:12:18] info:     z2m: Updating 'Ambient - Living' to latest firmware
[2024-05-03 07:14:49] error:    z2m: Update of 'Ambient - Living' failed (OTA: Timeout, device did not request any image blocks)`

This was definitely working before I pulled the newest Z2M.

Note that since this version I have EZSP driver issues as well:

zh:ezsp: Deprecated driver 'ezsp' currently in use, 'ember' will become the officially supported EmberZNet driver in next release. If using Zigbee2MQTT see https://github.com/Koenkk/zigbee2mqtt/discussions/21462

@TeHashX is your deployment on EZSP or different?

TeHashX commented 2 months ago

On Z2M i have Dongle-P with v20230507 firmware. On Z2M-Edge I have SkyConnect with v7.4.0.0, tried with ezsp and ember. On both, I get OTA timeout.

pvvx commented 2 months ago

Have You tried using the index.json file for OTA instead of Koenkk/zigbee-OTA? There may be problems with access or files in Koenkk/zigbee-OTA...

I don't have Z2M, but I just checked OTA in ZHA: image Zigbee OTA in BLE.

TeHashX commented 2 months ago

Have You tried using the index.json file for OTA instead of Koenkk/zigbee-OTA? There may be problems with access or files in Koenkk/zigbee-OTA...

I don't have Z2M, but I just checked OTA in ZHA: image Zigbee OTA in BLE.

The OTA issue is not important, I use local index file and show update available but after clicking update will timeout.

The biggest issue is with MHO-C401N and firmware v0.1.2.1, device is not supported in Z2M, v1.36.1-1 (with external converter https://github.com/pvvx/ZigbeeTLc/issues/83#issuecomment-2045075616 or v1.37.0-1 with included converter https://github.com/Koenkk/zigbee-herdsman-converters/pull/7457

With v1.2.1 and https://github.com/pvvx/ZigbeeTLc/issues/83#issuecomment-2045075616 converter is kind of working but if I try to change calibration values I get a lot of errors in the log like in the screenshot

Screenshot 2024-05-03 at 14 46 56

BTW, nice feature to change device name (works in Z2M too) but unfortunately it's not usable in Z2M because converters.

Screenshot 2024-05-03 at 15 00 06

That's way I ask if all features are enabled in firmware!

pvvx commented 2 months ago

In version 0.1.2.1, the Poll Control cluster was removed. The reason is that some new versions of programs that work with the coordinator set the Poll Control period to 6 seconds or less. Less than specified in the "Poll Control min" parameter. This requires the device to wake up at every set polling interval, resulting in unnecessary battery drain. A few months ago such phenomena were not observed. Something has changed in external programs - someone really wants to drain users’ batteries. In v0.1.2.1 this interval is strictly specified by the user. (ClusterID: 0x0204 (Thermostat User Interface Configuration) ; Attr: 0x0107, UINT8 (id:0x20), Measurement interval, range: 3..255 seconds. Default 10 seconds.)


When setting default values:

Cluster: PollControl (Endpoint id: 1, Id: 0x0020) Attributes: checkin_interval (id: 0x0000) = 14400 (3600 sec) checkin_interval_min (id: 0x0004) = 80 (20 sec) long_poll_interval (id: 0x0001) = 40 (10 sec) long_poll_interval_min (id: 0x0005) = 40 (10 sec)

But external software sets "long_poll_interval" to 24 (6 sec) (!).


ZigBee Cluster Library Specification 3.16.4.1.6 LongPollIntervalMin Attribute The Poll Control Server MAY optionally provide its own minimum value for the LongPollInterval to protect against another device setting the value to too short a time resulting in an inadvertent power drain on the device.


Therefore, until the Poll Control settings are corrected, will have to disable this cluster.

PS: Z2M, ZHA, etc. have many bugs and incorrect algorithms. No software meets the advertised Zigbee 3.0 specifications.

TeHashX commented 2 months ago

Until some more advanced user will create a good converter, we can use this one, it's compatible with firmware v0.1.2.1 but not with earlier versions. I only changed some int8 to int16.

// Autor: Markus Bodengriller https://github.com/Bodengriller
// requires zigbee2mqtt v1.34+
// external converter for Xiaomi MHO-C401N https://github.com/pvvx/ZigbeeTLc
// based on external converter for devbis-Firmware
// https://raw.githubusercontent.com/devbis/z03mmc/master/converters/lywsd03mmc.js
// requires firmware 0.1.2.1+

const {
    battery,
    temperature,
    humidity,
    enumLookup,
    binary,
    numeric,
    quirkAddEndpointCluster,
} = require('zigbee-herdsman-converters/lib/modernExtend');
const reporting = require('zigbee-herdsman-converters/lib/reporting');
const ota = require('zigbee-herdsman-converters/lib/ota');

const dataType = {
    boolean: 0x10,
    uint8: 0x20,
    uint16: 0x21,
    int8: 0x28,
    int16: 0x29,
    enum8: 0x30,
};

const definition = {
    zigbeeModel: ['MHO-C401N-z'],
    model: 'MHO-C401N',
    vendor: 'Xiaomi',
    description: 'E-Ink Temperature & humidity sensor with custom firmware',
    extend: [
        quirkAddEndpointCluster({
            endpointID: 1,
            outputClusters: [],
            inputClusters: [
                'genPowerCfg',
                'msTemperatureMeasurement',
                'msRelativeHumidity',
                'hvacUserInterfaceCfg',
            ],
        }),
        battery({percentage: true}),
        temperature({reporting: {min: 10, max: 300, change: 10}, access: 'STATE'}),
        humidity({reporting: {min: 2, max: 300, change: 50}, access: 'STATE'}),
        enumLookup({
            name: 'temperature_display_mode',
            lookup: {'celsius': 0, 'fahrenheit': 1},
            cluster: 'hvacUserInterfaceCfg',
            attribute: {ID: 0x0000, type: dataType.enum8},
            description: 'The units of the temperature displayed on the device screen.',
        }),
        binary({
            name: 'smiley',
            valueOn: ['SHOW', 0],
            valueOff: ['HIDE', 1],
            cluster: 'hvacUserInterfaceCfg',
            attribute: {ID: 0x0002, type: dataType.enum8},
            description: 'Whether to show a smiley on the device screen.',
        }),
        numeric({
            name: 'temperature_calibration',
            unit: 'ºC',
            cluster: 'hvacUserInterfaceCfg',
            attribute: {ID: 0x0100, type: dataType.int16},
            valueMin: -12.7,
            valueMax: 12.7,
            valueStep: 0.01,
            scale: 10,
            description: 'The temperature calibration, in 0.01° steps.',
        }),
        numeric({
            name: 'humidity_calibration',
            unit: '%',
            cluster: 'hvacUserInterfaceCfg',
            attribute: {ID: 0x0101, type: dataType.int16},
            valueMin: -12.7,
            valueMax: 12.7,
            valueStep: 0.01,
            scale: 10,
            description: 'The humidity offset is set in 0.01 % steps.',
        }),
        numeric({
            name: 'comfort_temperature_min',
            unit: 'ºC',
            cluster: 'hvacUserInterfaceCfg',
            attribute: {ID: 0x0102, type: dataType.int16},
            valueMin: -127.0,
            valueMax: 127.0,
            scale: 100,
            description: 'Comfort parameters/Temperature minimum, in 1°C steps.',
        }),
        numeric({
            name: 'comfort_temperature_max',
            unit: 'ºC',
            cluster: 'hvacUserInterfaceCfg',
            attribute: {ID: 0x0103, type: dataType.int16},
            valueMin: -127.0,
            valueMax: 127.0,
            scale: 100,
            description: 'Comfort parameters/Temperature maximum, in 1°C steps.',
        }),
        numeric({
            name: 'comfort_humidity_min',
            unit: '%',
            cluster: 'hvacUserInterfaceCfg',
            attribute: {ID: 0x0104, type: dataType.uint16},
            valueMin: 0.0,
            valueMax: 100.0,
            scale: 100,
            description: 'Comfort parameters/Humidity minimum, in 1% steps.',
        }),
        numeric({
            name: 'comfort_humidity_max',
            unit: '%',
            cluster: 'hvacUserInterfaceCfg',
            attribute: {ID: 0x0105, type: dataType.uint16},
            valueMin: 0.0,
            valueMax: 100.0,
            scale: 100,
            description: 'Comfort parameters/Humidity maximum, in 1% steps.',
        }),
        numeric({
            name: 'measurement_interval',
            unit: 's',
            cluster: 'hvacUserInterfaceCfg',
            attribute: {ID: 0x0107, type: dataType.uint8},
            valueMin: 3,
            valueMax: 255,
            description: 'Measurement interval, default 10 seconds.',
        }),
    ],
    ota: ota.zigbeeOTA,
    configure: async (device, coordinatorEndpoint, logger) => {
        const endpoint = device.getEndpoint(1);
        const bindClusters = ['msTemperatureMeasurement', 'msRelativeHumidity', 'genPowerCfg'];
        await reporting.bind(endpoint, coordinatorEndpoint, bindClusters);
        await reporting.temperature(endpoint, {min: 10, max: 300, change: 10});
        await reporting.humidity(endpoint, {min: 10, max: 300, change: 50});
        await reporting.batteryPercentageRemaining(endpoint);
        try {
            await endpoint.read('hvacThermostat', [0x0010, 0x0011, 0x0102, 0x0103, 0x0104, 0x0105, 0x0107]);
            await endpoint.read('msTemperatureMeasurement', [0x0010]);
            await endpoint.read('msRelativeHumidity', [0x0010]);
        } catch (e) {
            /* backward compatibility */
        }
    },
};

module.exports = definition;
pvvx commented 2 months ago

The only drawback is smiley which is always sad, no matter what values are selected.

'Comfort parameters' in 0.01 °C or % steps.

image

heldchen commented 1 month ago

Until some more advanced user will create a good converter, we can use this one, it's compatible with firmware v0.1.2.1 but not with earlier versions. I only changed some int8 to int16.

thanks alot, that worked for me - the MHO-C401N-z is now properly recognized!

TeHashX commented 1 month ago

Until some more advanced user will create a good converter, we can use this one, it's compatible with firmware v0.1.2.1 but not with earlier versions. I only changed some int8 to int16.

thanks alot, that worked for me - the MHO-C401N-z is now properly recognized!

A pull request is created and will be included in the next Z2M release.

Wolfscowl commented 1 month ago

Until some more advanced user will create a good converter, we can use this one, it's compatible with firmware v0.1.2.1 but not with earlier versions. I only changed some int8 to int16.


// Autor: Markus Bodengriller https://github.com/Bodengriller
// requires zigbee2mqtt v1.34+

I am completely new, how can I add the converter in Z2M?

TeHashX commented 1 month ago

Until some more advanced user will create a good converter, we can use this one, it's compatible with firmware v0.1.2.1 but not with earlier versions. I only changed some int8 to int16.

// Autor: Markus Bodengriller https://github.com/Bodengriller
// requires zigbee2mqtt v1.34+

I am completely new, how can I add the converter in Z2M?

Use Z2M Edge addon or follow this steps: 1 - Create a file named mho-c401n-z.js in /config/zigbee2mqtt and paste the converter code 2 - In Z2M settings / External converters add mho-c401n-z.js and press Submit 3 - Restart Z2M addon 4 - Enjoy!

Wolfscowl commented 1 month ago

Use Z2M Edge addon or follow this steps: 1 - Create a file named mho-c401n-z.js in /config/zigbee2mqtt and paste the converter code 2 - In Z2M settings / External converters add mho-c401n-z.js and press Submit 3 - Restart Z2M addon 4 - Enjoy!

Thank you :) works perfectly