Koenkk / zigbee2mqtt

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

Z2M choosing internal implementation over external converter for Sinope VA4220ZB #22330

Open saucepwn opened 2 months ago

saucepwn commented 2 months ago

What happened?

I have a VA4220ZB with flow sensor. The device is natively supported in Z2M, but does not include flow sensor capability. I created an external converter which adds this, but Z2M appears to be preferring the internal implementation, as it never uses my external converter.

External converter:

const {batteryPercentage, onOff, temperature, electricityMeter, identify, flow} = require('zigbee-herdsman-converters/lib/modernExtend');

const definition = {
    zigbeeModel: ['VA4220ZB'],
    model: 'VA4220ZB',
    vendor: 'Sinope Technologies',
    description: 'Automatically generated definition',
    extend: [batteryPercentage(), onOff({powerOnBehavior: false}), temperature(), electricityMeter({"cluster":"metering"}), identify(), flow()],
};

module.exports = definition;

Settings (external converters): image

Device: image

What did you expect to happen?

Z2M prefers my external converter over its internal implementation.

How to reproduce it (minimal and precise)

No response

Zigbee2MQTT version

1.36.1

Adapter firmware version

7.3.1.0 build 176

Adapter

usb-ITEAD_SONOFF_Zigbee_3.0_USB_Dongle_Plus_V2_20220714145902

Setup

pve container

Debug log

Debug 2024-04-27 21:57:24Received MQTT message on 'zigbee2mqtt/0x500b9140000504a1/1/set' with data '{"read":{"attributes":["measuredValue"],"cluster":"msFlowMeasurement","options":{}}}'

Debug 2024-04-27 21:57:24Publishing 'set' 'read' to '0x500b9140000504a1'

Debug 2024-04-27 21:57:24Received Zigbee message from '0x500b9140000504a1', type 'readResponse', cluster 'msFlowMeasurement', data '{}' from endpoint 1 with groupID 0

Debug 2024-04-27 21:57:24No converter available for 'VA4220ZB' with cluster 'msFlowMeasurement' and type 'readResponse' and data '{}'

Error 2024-04-27 21:57:24Publish 'set' 'read' to '0x500b9140000504a1' failed: 'Error: ZCL command 0x500b9140000504a1/1 msFlowMeasurement.read(["measuredValue"], {"timeout":10000,"disableResponse":false,"disableRecovery":false,"disableDefaultResponse":true,"direction":0,"srcEndpoint":null,"reservedBits":0,"manufacturerCode":null,"transactionSequenceNumber":null,"writeUndiv":false}) failed (Status 'UNSUPPORTED_ATTRIBUTE')'

Debug 2024-04-27 21:57:24Error: ZCL command 0x500b9140000504a1/1 msFlowMeasurement.read(["measuredValue"], {"timeout":10000,"disableResponse":false,"disableRecovery":false,"disableDefaultResponse":true,"direction":0,"srcEndpoint":null,"reservedBits":0,"manufacturerCode":null,"transactionSequenceNumber":null,"writeUndiv":false}) failed (Status 'UNSUPPORTED_ATTRIBUTE') at Endpoint.checkStatus (/opt/zigbee2mqtt/node_modules/zigbee-herdsman/src/controller/model/endpoint.ts:319:28) at Endpoint.zclCommand (/opt/zigbee2mqtt/node_modules/zigbee-herdsman/src/controller/model/endpoint.ts:762:22) at Endpoint.read (/opt/zigbee2mqtt/node_modules/zigbee-herdsman/src/controller/model/endpoint.ts:404:24) at Object.convertSet (/opt/zigbee2mqtt/node_modules/zigbee-herdsman-converters/src/converters/toZigbee.ts:198:28) at Publish.onMQTTMessage (/opt/zigbee2mqtt/lib/extension/publish.ts:259:36) at EventEmitter.wrappedCallback (/opt/zigbee2mqtt/lib/eventBus.ts:174:17)

krokets commented 1 month ago

I can get it detected by changing the line from zigbeeModel: ['VA4220ZB'], to zigbeeModel: ['VA4220ZB\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000'],

I also have the flow sensor but I do not know how to get it works.

krokets commented 1 month ago

As claudegel indicates in his documentation, the valve need to know which flow sensor is connected. To do that, cluster 0xff01, Attributes 0x0240 needs to be configured. In my case for FS4220, I should set [194, 17, 0, 0, 136, 119, 0, 0, 1, 0, 0, 0]. I am trying to write to the endpoint, but it seems not working. I did not find any good example to write an array, maybe I do something wrong. See my external converter below if someone can help.

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

const definition = {
    zigbeeModel: ['VA4220ZB\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000'],
    model: 'VA4220ZB',
    vendor: 'Sinopé',
    description: 'Sedna smart water valve',
    extend: [],
    fromZigbee: [fz.ignore_iaszone_statuschange, fz.cover_position_via_brightness, fz.cover_state_via_onoff,
        fz.battery, fz.metering],
    toZigbee: [tz.cover_via_brightness],
    meta: {battery: {voltageToPercentage: {min: 5400, max: 6800}}},
    exposes: [e.valve_switch(), e.valve_position(), e.battery_low(), e.battery(), e.battery_voltage(), 
        e.energy().withUnit('m³/h').withDescription('Sum of consumed water')],
    configure: async (device, coordinatorEndpoint) => {
        const endpoint = device.getEndpoint(1);
        const binds = [
            'genBasic', 'genGroups', 'genOnOff', 'ssIasZone', 'genLevelCtrl',
            'genPowerCfg', 'seMetering', 'manuSpecificSinope'];
        await reporting.bind(endpoint, coordinatorEndpoint, binds);
        await reporting.batteryPercentageRemaining(endpoint);
        await reporting.onOff(endpoint);
        await reporting.brightness(endpoint); // valve position

        // THIS LINE -->
        await endpoint.write(0xff01, {0x0240: {value: [194, 17, 0, 0, 136, 119, 0, 0, 1, 0, 0, 0], type: 0x48}}, {manufacturerCode: 0x119C});    
        // <---

        try {
            await reporting.batteryVoltage(endpoint);
        } catch (error) {/* Do Nothing */}
        try {
            await reporting.batteryAlarmState(endpoint);
        } catch (error) {/* Do Nothing */}
    },

};

module.exports = definition;
saucepwn commented 1 month ago

I ended up creating a ZHA Zigbee network with an extra Zigbee coordinator I had laying around. I used this ZHA network to write attribute 0x0240 per claudegel's instructions. I'm planning on migrating the Sinope valve back to my Z2M network soon to see if the configuration sticks. If so, with your advice on setting zigbeeModel I should have this completely working in Z2M.