Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[New device support]: VA4220ZB / VA4221ZB Sinopé Smart Water Valve #15433

Closed
alray31 opened this issue Dec 7, 2022 · 12 comments
Closed

[New device support]: VA4220ZB / VA4221ZB Sinopé Smart Water Valve #15433

alray31 opened this issue Dec 7, 2022 · 12 comments
Labels
new device support New device support request stale Stale issues

Comments

@alray31
Copy link

alray31 commented Dec 7, 2022

Link

https://support.sinopetech.com/en/1.5.7.3/

Database entry

{"id":3,"type":"Router","ieeeAddr":"0x500b91400003e680","nwkAddr":973,"manufId":4508,"manufName":"Sinope Technologies\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000","powerSource":"Mains (single phase)","modelId":"VA4220ZB\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000","epList":[1],"endpoints":{"1":{"profId":260,"epId":1,"devId":3,"inClusterList":[0,1,3,4,5,6,8,1026,1280,1794,2821,65281],"outClusterList":[3,6,25],"clusters":{"genBasic":{"attributes":{"modelId":"VA4220ZB\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000","manufacturerName":"Sinope Technologies\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000","powerSource":129,"zclVersion":2,"appVersion":12,"stackVersion":3,"hwVersion":0,"dateCode":"20201104\u0000\u0000\u0000\u0000\u0000\u0000\u0000","swBuildId":"3405\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"}},"ssIasZone":{"attributes":{"iasCieAddr":"0x00124b0026b6a0f8","zoneState":1}},"genLevelCtrl":{"attributes":{"currentLevel":254}}},"binds":[],"configuredReportings":[],"meta":{}}},"appVersion":12,"stackVersion":3,"hwVersion":0,"dateCode":"20201104\u0000\u0000\u0000\u0000\u0000\u0000\u0000","swBuildId":"3405\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000","zclVersion":2,"interviewCompleted":true,"meta":{},"lastSeen":1670446481691,"defaultSendRequestWhen":"immediate"}

External converter

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

const definition = {
    zigbeeModel: ['VA4220ZB'], // The model ID
    model: 'VA4220ZB', // Vendor model number
    vendor: 'Sinopé', // Vendor of the device
    description: 'Sedna smart water valve', // Description 
    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()],
    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
        try {
            await reporting.batteryVoltage(endpoint);
        } catch (error) {/* Do Nothing */}
        try {
            await reportingbatteryAlarmState(endpoint);
        } catch (error) {/* Do Nothing */}
    },
};

module.exports = definition;

image
image

@alray31 alray31 added the new device support New device support request label Dec 7, 2022
@MattL0
Copy link

MattL0 commented Dec 7, 2022

On the "console dev" tab you can try to poll each attribute . First select the cluster , after the attribute (there is one for battery percentage), then press read .

Sorry I do not have a computer with me right now.

@alray31
Copy link
Author

alray31 commented Dec 8, 2022

@MattL0 ,

Thank you for taking time to answer. I did as mentioned and polled the batteryPercentageRemaining and also batteryVoltage attributes from the PowerCfg cluster and it returned a value of 0% and a battery voltage value of 65
Read result of 'genPowerCfg': {"batteryVoltage":65,"batteryPercentageRemaining":0}

The battery % value in the expose tab changed from ''null'' % to ''0'' % after polling.

I'm positive that the batteries are good, these are 4 new AAA lithium batteries. The valve operates flawlessly with the AC adapter unplugged using only battery power. In fact, the valve make a higher pitched noise when operating from the batteries compared to AC power adapter which makes me believe the batteries are providing even a bit more power than what the AC power adapter can deliver.

Here are all the attributes I was able to poll from genPowerCfg:
Read result of 'genPowerCfg': {"batterySize":4,"batteryAlarmState":0,"batteryVoltage":65,"batteryPercentageRemaining":0,"batteryQuantity":4,"batteryAlarmMask":15,"batteryVoltMinThres":54}

Any ideas?

@MattL0
Copy link

MattL0 commented Dec 8, 2022

I am not a bettery expert in zigbee2mqtt, but seems like battery voltage would be a good way to monitor the battery.

you have 4 aaa 1.5volts battery so this means 6 volts in serial. Not sure if i'm right, but 65 / 10 seems to be near that number (6.5 volt). This would make your theory about the voltage of the battery higher right!

You are getting theses battery_low, etc messages because of the fz.ias_siren, :

{
cluster: 'ssIasZone',
type: 'commandStatusChangeNotification',
convert: (model, msg, publish, options, meta) => {
const zoneStatus = msg.data.zonestatus;
return {
alarm: (zoneStatus & 1) > 0,
tamper: (zoneStatus & 1<<2) > 0,
battery_low: (zoneStatus & 1<<3) > 0,
supervision_reports: (zoneStatus & 1<<4) > 0,
restore_reports: (zoneStatus & 1<<5) > 0,
ac_status: (zoneStatus & 1<<7) > 0,
test: (zoneStatus & 1<<8) > 0,
};
},
},

@MattL0
Copy link

MattL0 commented Dec 8, 2022

It seems like you also have the seMetering cluster. Could you try to poll the remainingBattLife attribute with the same method on the dev tool tab?

There are ways to convert voltage to battery percentage but i am not uses to that.

@MattL0
Copy link

MattL0 commented Dec 8, 2022

I would try with this first :

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

const definition = {
    zigbeeModel: ['VA4220ZB'], // The model ID from: Device with modelID 'lumi.sens' is not supported.
    model: 'VA4220ZB', // Vendor model number, look on the device for a model number
    vendor: 'Sinopé', // Vendor of the device (only used for documentation and startup logging)
    description: 'Sedna smart water valve', // Description 
    fromZigbee: [fz.ignore_iaszone_statuschange, fz.cover_position_via_brightness, fz.cover_state_via_onoff, fz.battery, fz.metering],
    toZigbee: [tz.cover_via_brightness],
    exposes: [e.valve_switch(), e.valve_position(), e.battery_low(), e.battery()],
    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
        try {
            await reporting.batteryVoltage(endpoint);
        } catch (error) {/* Do Nothing */}
        try {
            await reportingbatteryAlarmState(endpoint);
        } catch (error) {/* Do Nothing */}
    },
};

module.exports = definition;

Please post a picture of the repport tab (rapports) of the device, after this

@alray31
Copy link
Author

alray31 commented Dec 8, 2022

I replaced the external converter with the one you provided and restarted Z2M. Tried to poll seMetering remainingBattlife and the log reported an unsupported attribute error:
Error 2022-12-08 13:16:32Publish 'set' 'read' to 'Main Water Valve' failed: 'Error: Read 0x500b91400003e680/1 seMetering(["remainingBattLife"], {"sendWhen":"immediate","timeout":10000,"disableResponse":false,"disableRecovery":false,"disableDefaultResponse":true,"direction":0,"srcEndpoint":null,"reservedBits":0,"manufacturerCode":null,"transactionSequenceNumber":null,"writeUndiv":false}) failed (Status 'UNSUPPORTED_ATTRIBUTE')'

I also polled seMetering UnitofMesure and it reported the value ''7''. I checked in the zigbee cluster librabry and according to section 10.4.2.2.4.1, value 7 is for ''Liters & l/h (Liters per Hour) in pure binary format''. Then polled MeteringDeviceType and it returned ''2' for ''Water Metering''. Sounds to me that the presence of the seMetering cluster is solely for the optional FS4220/FS4221 flow meters that can be physically connected to the valve.

image
image

Another remark about battery voltage, I own a few of Sinope's water leak sensors, each are using the same AAA batteries but only 2 of them. When polling battery voltage of these sensors, they are all reporting between 2400 et 2600. I find it strange that the Sinope valve reports only a 2 digit values of 65 (well 64 now), shouldn't it be reporting a 4 digits values like the water sensors, i.e: 6500 instead of 65? I wish I knew how to multiply this value by by 100 so Z2M sees it as 6500 and then see what battery % is.

image
image
image
image
image

@alray31
Copy link
Author

alray31 commented Dec 8, 2022

So I'm reading the zigbee cluster library. Pwrcfg is under section 3.3

3.3.2.2.1.1 MainsVoltage Attribute
The MainsVoltage attribute is 16 bits in length and specifies the actual (measured) RMS voltage (or DC
voltage in the case of a DC supply) currently applied to the device, measured in units of 100mV.

When I poll batteryVoltage it returns a value between 64 and 68. According to the specs of the Energizer lithium AAA batteries that cames with the valve, the nominal battery voltage is 1.5V but they can peak as high as 1.72V when not under load. So 4 of these batteries connected in series should provide anywhere between 6.0 and 6.88 V. Polled battery voltage of 68 would make sense since 68 * 0.100mV = 6.8V.

@alray31
Copy link
Author

alray31 commented Dec 10, 2022

With some research, it looks like the valve can't natively report battery percentage, even on the official Sinopé's app, Neviweb. batteryPercentageRemaining attribute from genPwrCfg always report 0% and remainingBattLife attribute from seMeterting is unsupported.

For now, I removed e.battery from the exposed attributes list since it was useless and replaced it with batteryVoltage. I updated my first post with the external converter I'm using and updated screenshots. Everything works fine and no error in the logs. I can't test all the seMetering attributes since I do not own the external flow sensor.

Would still be nice to use batteryVoltage to convert it to battery percentage but I dont know how to add this piece to my external converter.

I know that:

  • BatteryVoltage when batteries are new is 6800mV.
  • According to the manufacturer, the valve will stop working at 5400mV
  • So 6800mV = 100%, 5400mV = 0%

We could use something like:
If batteryVoltage >= 5600mV then battery = 100%
if batteryVoltage < 5600mV then battery = ((batteryVoltage - 5400mv)/(5600mV - 5400mV) x 100)

But I don't know if possible and how to integrate this logic and to inject the result in the payload. I saw some example in libs/utils.js so it looks like its somehow possible.

@MattL0
Copy link

MattL0 commented Dec 13, 2022

@alray31 Can you try this? Firs time I try a meta function

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

const definition = {
    zigbeeModel: ['VA4220ZB'], // The model ID from: Device with modelID 'lumi.sens' is not supported.
    model: 'VA4220ZB', // Vendor model number, look on the device for a model number
    vendor: 'Sinopé', // Vendor of the device (only used for documentation and startup logging)
    description: 'Sedna smart water valve', // Description 
    
    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: 54, max: 68}}},
    exposes: [e.valve_switch(), e.valve_position(), e.battery_low(), e.battery()],
    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
        try {
            await reporting.batteryVoltage(endpoint);
        } catch (error) {/* Do Nothing */}
        try {
            await reportingbatteryAlarmState(endpoint);
        } catch (error) {/* Do Nothing */}
    },
};

module.exports = definition;

@alray31
Copy link
Author

alray31 commented Dec 13, 2022

Thanks Matt,

Looks like its working! It was first showing 100% battery but I had a doubt cause when polling batt voltage from pwrcfg, I get a 2 digit value.
image

But when looking at batt voltage in the exposed tab, I get a 4 digits value (6800 instead of 68)
image

The log also show a 4 digits value:
Zigbee2MQTT:info 2022-12-13 17:22:58: MQTT publish: topic 'zigbee2mqtt/Main water valve', payload '{"battery":0,"battery_low":false,"linkquality":132,"position":100,"state":"OPEN","*voltage":6800*}'

So I played with the min/max value just to confirm what range I should be using cause if it's using the 4 digits, 5400-6800 will always be more than 68 and so always show a 100% value. I set a min of 5400 and a max of 7200 just to see what effect it would have on the batt% with battvoltage showing 6800. Rebooted Z2M and battery % showed 78% for a voltage of 6800, I was expecting a value of 77.7% so its working with a 4 digits values.

I'll now follow the step 4 of the guide to add the picture to public/images/devices, the markdown file to docs/devices and finally add this converter to sinope.js.

Converter updated at first post

Thanks for all your help

image

@MattL0
Copy link

MattL0 commented Dec 13, 2022

ok thank. I've sent the pr part. ( added it to sinope.js)

@github-actions
Copy link
Contributor

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days

@github-actions github-actions bot added the stale Stale issues label Jan 13, 2023
@alray31 alray31 closed this as completed Jan 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new device support New device support request stale Stale issues
Projects
None yet
Development

No branches or pull requests

2 participants