Koenkk / zigbee2mqtt

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

[New device support]: Tuya 213E Ultrasonic water meter (_TZE200_zlwr0raf) #24016

Open Takacsk76 opened 2 months ago

Takacsk76 commented 2 months ago

Link

https://www.aliexpress.com/item/1005007308058989.html?spm=a2g0o.order_list.order_list_main.5.79851802N0tQyH

Other: https://www.tuyaexpo.com/product/1105384

What I learned

Factory name of the device: Zigbee阀控超声波水表-vdevo In English: Zigbee valve controlled ultrasonic water meter-vdevo

Data points in the Tuya app: Tuya Smart datapoints

Database entry

{"id":56,"type":"EndDevice","ieeeAddr":"0xa4c1389cbaf936cd","nwkAddr":807,"manufId":4417,"manufName":"_TZE200_zlwr0raf","powerSource":"Battery","modelId":"TS0601","epList":[1],"endpoints":{"1":{"profId":260,"epId":1,"devId":81,"inClusterList":[4,5,61184,0],"outClusterList":[25,10],"clusters":{"genBasic":{"attributes":{"65503":"��|.i��|.i��|.i\u0004�|.f\u0005�|.\u0012","65506":56,"65508":0,"stackVersion":0,"dateCode":"","appVersion":72,"modelId":"TS0601","manufacturerName":"_TZE200_zlwr0raf","powerSource":3,"zclVersion":3,"hwVersion":1}}},"binds":[],"configuredReportings":[],"meta":{}}},"appVersion":72,"stackVersion":0,"hwVersion":1,"dateCode":"","zclVersion":3,"interviewCompleted":true,"meta":{},"lastSeen":1726666275707}

Zigbee2MQTT version

1.40.1

Comments (starting point)

I tried to make the configuration based on another type: https://github.com/Koenkk/zigbee2mqtt/issues/21255

ZHA has exactly this configuration, but it should be transferred to Z2M: https://github.com/zigpy/zha-device-handlers/issues/3301

Tuya development

develop1 develop2

Output from the script in tuya_dev:

{
"1":"Water consumption",
"2":"Month consumption",
"3":"Daily consumption",
"4":"Report period set",
"5":"Warning",
"6":"Month and daily frozen time set",
"16":"Meter ID",
"18":"Reverse Water Consumption",
"21":"Instantaneous Flow Rate",
"22":"Working temperature",
"26":"Power supply voltage"
}

Results:

About Exposes State

I don't really understand how Zigbee and Tuya clusters work.

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 = {
    fingerprint: [
        {
            modelID: 'TS0601',
            manufacturerName: '_TZE200_zlwr0raf',
        },
    ],
    model: 'TS0601_v12',
    vendor: 'Tuya',
    description: 'Water meter',
    fromZigbee: [tuya.fz.datapoints],
    toZigbee: [tuya.tz.datapoints],
    onEvent: tuya.onEventSetTime,
    configure: tuya.configureMagicPacket,
    exposes: [
        e.numeric('water_consumption', ea.STATE).withUnit('L').withDescription('Total water consumed'),
        e.numeric('month_consumption', ea.STATE).withDescription('Month consumption'),
        e.numeric('daily_consumption', ea.STATE).withDescription('Daily consumption'),
        e.numeric('month_and_daily_frozen_time_set', ea.STATE).withDescription('Month Daily Frozen Set'),
        e.enum('report_period', ea.STATE_SET, ['1h', '2h', '3h', '4h', '6h', '8h', '12h', '24h']).withDescription('Report interval'),
        e.numeric('warning', ea.STATE).withDescription('Fault code'),
        e.text('meter_id', ea.STATE).withDescription('Meter ID (ID of device)'),
        e.numeric('reverse_water_consumption', ea.STATE).withDescription('Reverse water flow'),
        e.numeric('instantaneous_flow_rate', ea.STATE).withDescription('Inst flow rate'),
        e.numeric('working_temperature', ea.STATE).withUnit('°C').withDescription('Water Temperature'),
        e.numeric('power_supply_voltage', ea.STATE).withUnit('V').withDescription('Battery voltage'),
    ],
    meta: {
        // All datapoints go in here
        tuyaDatapoints: [
            [1,'water_consumption', tuya.valueConverter.raw],
            [2,'month_consumption', tuya.valueConverter.raw],
            [3,'daily_consumption', tuya.valueConverter.raw],
            [4,'report_period', tuya.valueConverterBasic.lookup({'1h': tuya.enum(0), '2h': tuya.enum(1), '3h': tuya.enum(2),
                                                                '4h': tuya.enum(3), '6h': tuya.enum(4), '8h': tuya.enum(5),
                                                                '12h': tuya.enum(6), '24h': tuya.enum(7) })],
            [5,'warning', tuya.valueConverter.raw],
            [6,'month_and_daily_frozen_time_set', tuya.valueConverter.raw],
            [16,'meter_id', tuya.valueConverter.raw],
            [18,'reverse_water_consumption', tuya.valueConverter.raw],
            [21,'instantaneous_flow_rate', tuya.valueConverter.raw],
            [22,'working_temperature', tuya.valueConverter.divideBy100],
            [26,'power_supply_voltage', tuya.valueConverter.divideBy100]
        ],
    },
    extend: [
        // A preferred new way of extending functionality.
    ],
};

module.exports = definition;

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

What works with external definition:

What doesn't work with the external definition:

Template binary sensors

Processing of "Warning" statuses "state": "{{ '{:013b}'.format(state_attr('sensor.water_meter_warning', 'warning') | int)[-1] == '1' }}", [-1]: the sequence number of the bit

      {
        "created_at": "2024-10-02T10:34:55.948720+00:00",
        "data": {},
        "disabled_by": null,
        "domain": "template",
        "entry_id": "01J96CR52CE0F3MK6QW02PAX75",
        "minor_version": 1,
        "modified_at": "2024-10-02T10:34:55.948723+00:00",
        "options": {
          "template_type": "binary_sensor",
          "name": "Water meter battery alarm",
          "state": "{{ '{:013b}'.format(state_attr('sensor.water_meter_warning', 'warning') | int)[-1] == '1' }}",
          "device_class": "problem",
          "device_id": "e88e4ca5742993c7b66d24a10fa3fdee"
        },
        "pref_disable_new_entities": false,
        "pref_disable_polling": false,
        "source": "user",
        "title": "Water meter battery alarm",
        "unique_id": null,
        "version": 1
      }
      {
        "created_at": "2024-10-02T10:34:15.140108+00:00",
        "data": {},
        "disabled_by": null,
        "domain": "template",
        "entry_id": "01J96CPX747X3PDNE0WK1Y1GBG",
        "minor_version": 1,
        "modified_at": "2024-10-02T10:34:15.140112+00:00",
        "options": {
          "template_type": "binary_sensor",
          "name": "Water meter magnetism alarm",
          "state": "{{ '{:013b}'.format(state_attr('sensor.water_meter_warning', 'warning') | int)[-2] == '1' }}",
          "device_class": "problem",
          "device_id": "e88e4ca5742993c7b66d24a10fa3fdee"
        },
        "pref_disable_new_entities": false,
        "pref_disable_polling": false,
        "source": "user",
        "title": "Water meter magnetism alarm",
        "unique_id": null,
        "version": 1
      },

etc...

HA device data: HA-device

Request:

///If anyone could help me create a working config file I would greatly appreciate it. I'm just trying, but I have no scientific basis. Thanks/// I managed to put something together

atanesmarc commented 1 month ago

Thank you very much! after a couple of months your post gave me light! I'm also struggling with decoding the JSON in month_consumption and daily_consumption but with no success. AFAIK the last position in the buffer is the current state but I had no success implementing it on the external converter.

Takacsk76 commented 1 month ago

Thank you very much! after a couple of months your post gave me light! I'm also struggling with decoding the JSON in month_consumption and daily_consumption but with no success. AFAIK the last position in the buffer is the current state but I had no success implementing it on the external converter.

I have not yet installed the device in its final location, but it is expected to be ready this week. I didn't know what to do with the JSON data yet, because there is nothing to compare it to. In my opinion, the data could be statistics for the last 7 days and the last 7 months, but this is just a guess (but why only 7 months?).

danielewyss commented 3 weeks ago

Is there something already available to add manually ?

Takacsk76 commented 3 weeks ago

As far as I know, there isn't.

senrabyar commented 2 weeks ago

I have just acquired a 214C and have just managed to get it paired (the supplied manual described using a Hall Effect button with a magnet - it doesn't exist - you have to long-press when the date is shown) I can see the device OK in Tuya, but unsupported in Z2M. Not yet plumbed in. But hopefully I can contribute or at least test anything others find.

Takacsk76 commented 2 weeks ago

Hi, I received a video from the seller for zigbee pairing:

User Manual===https://drive.google.com/file/d/1BZ7b_sgXukM0FRVaEws1VgDZbckWVEoa/view?usp=sharing

213E===https://drive.google.com/file/d/1q-v2mhXkvjOclElcICHZBHT3yqfJ9d_G/view?usp=sharing

214C===https://drive.google.com/file/d/1gM6k_ndeKYNl9mXyKixQ_uLA6TiDvyAa/view?usp=sharing

senrabyar commented 2 weeks ago

Ah thanks, now I have the full manual - after question to the supplier they had sent me just the two relevant pages. The manual in the box is totally different. Your info will certainly help anyone else who discovers this. But that's really outside of this thread on Z2M !

Takacsk76 commented 2 weeks ago

Very welcome. I would also be happy to help implement the integration into Z2M, but no such request has been received so far.

Takacsk76 commented 1 week ago

I just need to figure out how to calculate the battery percentage. I'm trying, but I can't.