zigbee2mqtt icon indicating copy to clipboard operation
zigbee2mqtt copied to clipboard

[New device support]: TS0601 _TZE200_lvkk0hdg (EPTTECH Tank Level Monitor Zigbee)

Open rvdlinden opened this issue 2 years ago • 86 comments

Link

https://www.aliexpress.com/item/1005006395402636.html

Database entry

{"id":66,"type":"EndDevice","ieeeAddr":"0x0ceff6fffe4bdda2","nwkAddr":39698,"manufId":4098,"manufName":"_TZE200_lvkk0hdg","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":{"65503":"�ME-\u0019%NE-\u0019aNE-j�NE-j\u000fPE-j�KE-j�KE-\u0019>LE-i","65506":31,"65508":0,"65534":0,"appVersion":65,"modelId":"TS0601","manufacturerName":"_TZE200_lvkk0hdg","powerSource":3,"zclVersion":3,"stackVersion":0,"hwVersion":1,"dateCode":""}}},"binds":[],"configuredReportings":[],"meta":{}}},"appVersion":65,"stackVersion":0,"hwVersion":1,"dateCode":"","zclVersion":3,"interviewCompleted":true,"meta":{"configured":-708457359},"lastSeen":1706198663760,"defaultSendRequestWhen":"immediate"}

Comments

I have followed all the documentation on how to add a new unsupported device, but I got stuck on the configuration file. Only 3 out of the 7 Tuya Data Points are working (the read-only points), but the other 4 data points for configuration of the device are seen in Tuya IOT, but refused to be configured in Zigbee2MQTT

The attached external definition file is an attempt to setup the device, but that all I got and do not know how to continue.

The working Data Points and also the failing Data Points are all described in the definition file for easy reference.

NOTE: There is also an identical device, but then it's a Wifi based device. In the Smart Life app both devices are fully working (all 7 Data Points), but in HA (either via Zigbee2MQTT or LocalTuya) only 3 out of 7 Data Points can be used. See for the TLC2206 Wifi device https://www.aliexpress.com/item/1005005758585356.html

Both devices have equal Data Points {"1":"Liquid level status","2":"Liquid level depth","7":"Set Max","8":"Set Mini","19":"Installation height","21":"Sensor to full line","22":"Liquid level ratio"}

External defintion

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 tuya = require('zigbee-herdsman-converters/lib/tuya');

const definition = {
  fingerprint: [
    {
      modelID: 'TS0601',
      manufacturerName: '_TZE200_lvkk0hdg',
    },
  ],
  model: 'TS0601_tlc2206zb',
  vendor: 'TuYa',
  whiteLabel: [
    {
      vendor: 'EPTTECH',
      model: 'TLC2206-ZB',
    },
  ],
  description: 'EPTTECH Tank Level Monitor Zigbee',
  fromZigbee: [tuya.fz.datapoints],
  toZigbee: [tuya.tz.datapoints],
  onEvent: tuya.onEventSetTime,
  configure: tuya.configureMagicPacket,
  exposes: [
    e.numeric('liquid_level_percent', ea.STATE)
      .withUnit('%')
      .withDescription('Liquid level percentage'),
    e.numeric('liquid_depth', ea.STATE)
      .withUnit('m')
      .withDescription('Liquid Depth'),
    e.enum('liquid_state', ea.STATE, ['low', 'normal', 'high'])
      .withDescription('Liquid State'),
    // =============== Found but non functional ===============
    /*
    e.numeric('max_set', ea.STATE_SET)
      .withUnit('%')
      .withDescription('Liquid max percentage')
      .withValueMin(0)
      .withValueMax(100)
      .withValueStep(1),
    e.numeric('mini_set', ea.STATE_SET)
      .withUnit('%')
      .withDescription('Liquid minimal percentage')
      .withValueMin(0)
      .withValueMax(100)
      .withValueStep(1),
    e.numeric('installation_height', ea.STATE_SET)
      .withUnit('mm')
      .withDescription('Height from sensor to tank bottom')
      .withValueMin(100)
      .withValueMax(2500)
      .withValueStep(1),
    e.numeric('liquid_depth_max', ea.STATE_SET)
      .withUnit('mm')
      .withDescription('Height from sensor to liquid level')
      .withValueMin(100)
      .withValueMax(1000)
      .withValueStep(1),
    */
  ],
  meta: {
    tuyaDatapoints: [
      [1, 'liquid_state', tuya.valueConverterBasic.lookup({'low': 1, 'normal': 0, 'high': 2})],
      [2, 'liquid_depth', tuya.valueConverter.divideBy100],
      [22, 'liquid_level_percent', tuya.valueConverter.raw],
      // =============== Found but non functional ===============
      /*
      [7, 'max_set', tuya.valueConverter.raw],
      [8, 'mini_set', tuya.valueConverter.raw],
      [19, 'installation_height', tuya.valueConverter.raw],
      [21, 'liquid_depth_max', tuya.valueConverter.raw],
      */
    ],
  },
};

module.exports = definition;

rvdlinden avatar Jan 25 '24 21:01 rvdlinden

It is working now ?

NDNELSON avatar Feb 27 '24 04:02 NDNELSON

I only have it working via local tuya and using a tuya zigbee gateway. Directly adding the device to Home Assistant via a zigbee dongle only shows the the depth, percentage and state values, but all configurable fields like height, min and max are failing.

rvdlinden avatar Feb 27 '24 14:02 rvdlinden

Have you tried setup by the new way tuya in the first February home assistant release ? https://www.home-assistant.io/integrations/tuya/

NDNELSON avatar Feb 28 '24 14:02 NDNELSON

Yes, I use that, but the device is still unsupported

Screenshot_20240228_173125_Home Assistant

rvdlinden avatar Feb 28 '24 16:02 rvdlinden

I have the same problem.... unsupported :(

blouinp avatar Apr 12 '24 22:04 blouinp

I only have it working via local tuya and using a tuya zigbee gateway. Directly adding the device to Home Assistant via a zigbee dongle only shows the the depth, percentage and state values, but all configurable fields like height, min and max are failing.

HI how you did it?

blouinp avatar Apr 13 '24 00:04 blouinp

So far I can only use it reliable using a tuya zigbee hub and add the zigbee water tank meter to it as a subdevice.

In Home Assistant using this localtuya fork https://xzetsubou.github.io/hass-localtuya/

With the information in this thread you can configure the various entities in localtuya

rvdlinden avatar Apr 13 '24 14:04 rvdlinden

Hey! Are you still trying to do it directly with zigbee2mqtt or just stayed with local tuya?

TonioClos avatar May 07 '24 08:05 TonioClos

Still local tuya

rvdlinden avatar May 08 '24 17:05 rvdlinden

Okay I´ll stick with HA without local tuya and try then, thank you!

TonioClos avatar May 09 '24 07:05 TonioClos

Hi, I am also also interested in adding support for this device trough Zigbee2MQTT. Same as you, I am struggling with other 4 datapoints. For all four I am getting an error "No converter available". I would love to contribute If someone can point me in the right direction how to even debug in such cases.

gregorobreza avatar May 18 '24 07:05 gregorobreza

Like everyone here, I'd like to get this working and added as an officially supported device!

TheRealWaldo avatar May 21 '24 20:05 TheRealWaldo

I thing I finally figure it out. It took a while for me to better understand how to work with zigbee-herdsman-conversters since it is not really well documented and I am relatively new to Zigbee2MQTT.

I just added custom toZigbee converter at the top of the file and used tuya.sendDataPointValue(). This article on medium really helped me understand converters better. And of course searching trough examples of supported devices to se how its done for similar devices.

So here is my external configuration:

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

const dp = {
  instalationHeight: 19,
  liquidDepthMax: 21,
  maxSet: 7,
  miniSet: 8,
};

const tzdatapoints = {
  key: [
    "installation_height",
    "liquid_depth_max",
    "max_set",
    "mini_set",
  ],
  convertSet: async (entity, key, value, meta) => {
    switch (key) {
      case "installation_height": {
        await tuya.sendDataPointValue(entity, dp.instalationHeight, value);
        break;
      }
      case "liquid_depth_max": {
        await tuya.sendDataPointValue(entity, dp.liquidDepthMax, value);
        break;
      }
      case "max_set": {
        await tuya.sendDataPointValue(entity, dp.maxSet, value);
        break;
      }
      case "mini_set": {
        await tuya.sendDataPointValue(entity, dp.miniSet, value);
        break;
      }
    }
  },
};

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: "_TZE200_lvkk0hdg",
    },
  ],
  model: "TS0601_tlc2206zb",
  vendor: "TuYa",
  whiteLabel: [
    {
      vendor: "EPTTECH",
      model: "TLC2206-ZB",
    },
  ],
  description: "EPTTECH Tank Level Monitor Zigbee",
  fromZigbee: [tuya.fz.datapoints],
  // toZigbee: [tuya.tz.datapoints],
  toZigbee: [tzdatapoints],
  onEvent: tuya.onEventSetTime, // Add this if you are getting no converter for 'commandMcuSyncTime'
  configure: tuya.configureMagicPacket,
  exposes: [
    // Here you should put all functionality that your device exposes
    e
      .numeric("liquid_level_percent", ea.STATE)
      .withUnit("%")
      .withDescription("Liquid level percentage"),
    e
      .numeric("liquid_depth", ea.STATE)
      .withUnit("m")
      .withDescription("Liquid Depth"),
    e
      .enum("liquid_state", ea.STATE, ["low", "normal", "high"])
      .withDescription("Liquid State"),

    e
      .numeric("installation_height", ea.STATE_SET)
      .withUnit("mm")
      .withDescription("Height from sensor to tank bottom")
      .withValueMin(100)
      .withValueMax(3000)
      .withValueStep(1),
    e
      .numeric("mini_set", ea.STATE_SET)
      .withUnit("%")
      .withDescription("Liquid minimal percentage")
      .withValueMin(0)
      .withValueMax(100)
      .withValueStep(1),
    e
      .numeric("max_set", ea.STATE_SET)
      .withUnit("%")
      .withDescription("Liquid max percentage")
      .withValueMin(0)
      .withValueMax(100)
      .withValueStep(1),
    e
      .numeric("liquid_depth_max", ea.STATE_SET)
      .withUnit("mm")
      .withDescription("Height from sensor to liquid level")
      .withValueMin(100)
      .withValueMax(2000)
      .withValueStep(1),
  ],
  meta: {
    // All datapoints go in here
    tuyaDatapoints: [
      [22, "liquid_level_percent", tuya.valueConverter.raw],
      [2, "liquid_depth", tuya.valueConverter.divideBy100],
      [
        1,
        "liquid_state",
        tuya.valueConverterBasic.lookup({ low: 1, normal: 0, high: 2 }),
      ],
      [19, "installation_height", tuya.valueConverter.raw],
      [7, "max_set", tuya.valueConverter.raw],
      [8, "mini_set", tuya.valueConverter.raw],
      [21, "liquid_depth_max", tuya.valueConverter.raw],
    ],
  },
  extend: [
    // A preferred new way of extending functionality.
  ],
};

module.exports = definition;

I would appreciate if someone else could test configuration and give feedback. Then we could maybe move further and suggest it as an officially supported device.

gregorobreza avatar May 25 '24 09:05 gregorobreza

I have removed my tuya gateway and local tuya in HA and connected the TLC ZB directly to HA again.

So far it works like a charm

rvdlinden avatar May 25 '24 11:05 rvdlinden

@gregorobreza I tested it. Seems it's working :+1:

petos avatar May 25 '24 16:05 petos

Working perfectly, thank you so much for the code n_n @gregorobreza

TonioClos avatar May 31 '24 11:05 TonioClos

@gregorobreza it's working fine on my end too. Thanks!

didi3r avatar Jun 09 '24 21:06 didi3r

Hello, @gregorobreza Thanks for the code. Very good job! I have a problem. I’ve created the file and placed it next to the configuration.yaml file of Z2M, but when configuring it in the external converters, I encounter an error: external_converters must be array I’ve also added the following entry to the configuration.yaml file of Z2M, but it still hasn’t worked:

external_converters:
  - bidon.js

ocigam69 avatar Jun 10 '24 18:06 ocigam69

After many tests, I just needed to leave a blank line at the end of the file. 😊 Thanks @gregorobreza !!!

ocigam69 avatar Jun 10 '24 19:06 ocigam69

Hm interesting 🤔. Happy to hear that you solved it!👍

gregorobreza avatar Jun 10 '24 19:06 gregorobreza

Hi!. Somebody knows if this new device is going to be integrated in the native Z2M in a close future?

I have just purchased it and I don't feel very confortable yet touching the guts of Z2M so, if it's comming to Z2M, I will just wait a little.

Thanks in advance!.

SentenciaLaMalice avatar Jun 12 '24 21:06 SentenciaLaMalice

Received sensor today, and was detected fine by @gregorobreza definition https://github.com/Koenkk/zigbee2mqtt/issues/21015#issuecomment-2131168644

ivanfmartinez avatar Jun 14 '24 22:06 ivanfmartinez

I decided to give a try to @gregorobreza code a try (thank you very much sir) and it worked great. The sensor started reporting perfectly. But, sadly, as soon as I configured the levels of my setup using the "Expose" tab on Z2M the device does not report the level anymore. I was not able to fix it, I keep getting zero per cent :(

SentenciaLaMalice avatar Jun 17 '24 20:06 SentenciaLaMalice

Just to add that I just noticed on the debug logs of Z2M that the device is sending a huge ammount of messages per minute with its current status. Didn't count them but I estimate 100 message per minute easily. I let one log line here for if it helps

2024-06-17 23:00:49MQTT publish: topic 'zigbee2mqtt/nivel_gasoil', payload '{"installation_height":1045,"linkquality":87,"liquid_depth":0,"liquid_depth_max":100,"liquid_level_percent":0,"liquid_state":"low","max_set":95,"mini_set":20}'

SentenciaLaMalice avatar Jun 17 '24 21:06 SentenciaLaMalice

Just to add that I just noticed on the debug logs of Z2M that the device is sending a huge ammount of messages per minute with its current status.

I noticed this as well, the Availability reflects this as the device is always 'just now' and doesn't seem to quit. Would be nice to be able to set the report interval if possible.

jtscott avatar Jun 17 '24 21:06 jtscott

I decided to give a try to @gregorobreza code a try (thank you very much sir) and it worked great. The sensor started reporting perfectly. But, sadly, as soon as I configured the levels of my setup using the "Expose" tab on Z2M the device does not report the level anymore. I was not able to fix it, I keep getting zero per cent :(

Thats strange... Are you sure your configured levels make sense and are set correctly based on sensor instructions?

gregorobreza avatar Jun 19 '24 11:06 gregorobreza

Just to add that I just noticed on the debug logs of Z2M that the device is sending a huge ammount of messages per minute with its current status.

I noticed this as well, the Availability reflects this as the device is always 'just now' and doesn't seem to quit. Would be nice to be able to set the report interval if possible.

I am not really sure that device support setting reporting interval. Device behaves in the same manner when used with tuya hub and it seem this is expected behaviour. But definitely worth to dig a bit deeper to check if possible.

gregorobreza avatar Jun 19 '24 11:06 gregorobreza

After some time installed I made more tests and adjusted the definition. But it still have problems.

The parameters that are defined before as min and max, are related to the state, and I have changed the names. low_set and high_set now when percentage is below low_set state becames "low" and percentage over high_set state becomes "high"

The instalation_height is working, changing it changed the liquid_level correctly.

The distance from sensor "liquid_depth_max" are not working, changing it does not affect the liquid level.

And percentage is not correct because of this non working parameter, percentage should consider this parameter to be calculated correctly.

Someone can help to fix this and make sensor correct ?

// based on 
//    https://github.com/Koenkk/zigbee2mqtt/issues/21015#issuecomment-2131168644
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 {} = require("zigbee-herdsman-converters/lib/modernExtend");
const e = exposes.presets;
const ea = exposes.access;
const tuya = require("zigbee-herdsman-converters/lib/tuya");
const utils = require("zigbee-herdsman-converters/lib/utils");

const dp = {
  highSet: 7,
  lowSet: 8,
  instalationHeight: 19,
  liquidDepthMax: 21,
};

const tzdatapoints = {
  key: [
    "installation_height",
    "liquid_depth_max",
    "low_set",
    "high_set",
  ],
  convertSet: async (entity, key, value, meta) => {
    switch (key) {
      case "installation_height": {
        await tuya.sendDataPointValue(entity, dp.instalationHeight, value);
        break;
      }
      case "liquid_depth_max": {
        await tuya.sendDataPointValue(entity, dp.liquidDepthMax, value);
        break;
      }
      case "low_set": {
        await tuya.sendDataPointValue(entity, dp.lowSet, value);
        break;
      }
      case "high_set": {
        await tuya.sendDataPointValue(entity, dp.highSet, value);
        break;
      }
    }
  },
};

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: "_TZE200_lvkk0hdg",
    },
  ],
  model: "TS0601_tlc2206zb_external",
  vendor: "TuYa",
  whiteLabel: [
    {
      vendor: "EPTTECH",
      model: "TLC2206-ZB",
    },
  ],
  description: "EPTTECH Tank Level Monitor Zigbee (external)",
  fromZigbee: [tuya.fz.datapoints],
  // toZigbee: [tuya.tz.datapoints],
  toZigbee: [tzdatapoints],
  onEvent: tuya.onEventSetTime, // Add this if you are getting no converter for 'commandMcuSyncTime'
  configure: tuya.configureMagicPacket,
  exposes: [
    // Here you should put all functionality that your device exposes
    e
      .numeric("liquid_level_percent", ea.STATE)
      .withUnit("%")
      .withDescription("Liquid level percentage"),
    e
      .numeric("liquid_depth", ea.STATE)
      .withUnit("m")
      .withDescription("Liquid Depth"),
    e
      .enum("liquid_state", ea.STATE, ["low", "normal", "high"])
      .withDescription("Liquid State"),
    e
      .numeric("installation_height", ea.STATE_SET)
      .withUnit("mm")
      .withDescription("Height from sensor to tank bottom")
      .withValueMin(100)
      .withValueMax(3000)
      .withValueStep(1),
    e
      .numeric("low_set", ea.STATE_SET)
      .withUnit("%")
      .withDescription("Liquid percentage to set low state (below this value)")
      .withValueMin(0)
      .withValueMax(100)
      .withValueStep(1),
    e
      .numeric("high_set", ea.STATE_SET)
      .withUnit("%")
      .withDescription("Liquid percentage to set high state (above this value)")
      .withValueMin(0)
      .withValueMax(100)
      .withValueStep(1),
    e
      .numeric("liquid_depth_max", ea.STATE_SET)
      .withUnit("mm")
      .withDescription("Distance from sensor to max liquid level")
      .withValueMin(100)
      .withValueMax(2000)
      .withValueStep(1),
  ],
  meta: {
    // All datapoints go in here
    tuyaDatapoints: [
      [1, "liquid_state", tuya.valueConverterBasic.lookup({ low: 1, normal: 0, high: 2 }),],
      [2, "liquid_depth", tuya.valueConverter.divideBy100],
      [7, "high_set", tuya.valueConverter.raw],
      [8, "low_set", tuya.valueConverter.raw],
      [19, "installation_height", tuya.valueConverter.raw],
      [21, "liquid_depth_max", tuya.valueConverter.raw],
      [22, "liquid_level_percent", tuya.valueConverter.raw],
    ],
  },
  extend: [
    // A preferred new way of extending functionality.
  ],
};

module.exports = definition;

ivanfmartinez avatar Aug 01 '24 19:08 ivanfmartinez

I have the Wifi version and also the zigbee version of the tank level monitor.

When I initially used the Wifi device via Tuya app and Tuya, all settings worked as how they were described in the manual of the TLC.

When I later bought the zigbee version, inside the package was the same manual as from the Wifi version, but it worked completely different.

I'm pretty sure that although the device looks identical and you'd only expect the connection to be different, they are actually different devices with completely different firmware and therefore also different behavior.

I think the zigbee version needs a firmware update to fix the issues and make it work like the wifi version does.

rvdlinden avatar Aug 01 '24 20:08 rvdlinden

I dont have a tuya hub to test it and sniff, but apparently if we manage to make the distance of sensor to max liquid level work the other values can be correct.

ivanfmartinez avatar Aug 01 '24 20:08 ivanfmartinez