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

Support for OWON PC321 3-phase Clamp Power Meter #9525

Closed
FoxConsult opened this issue Nov 5, 2021 · 41 comments
Closed

Support for OWON PC321 3-phase Clamp Power Meter #9525

FoxConsult opened this issue Nov 5, 2021 · 41 comments
Labels
new device support New device support request stale Stale issues

Comments

@FoxConsult
Copy link

FoxConsult commented Nov 5, 2021

Please add the OWON PC321 3-phase Clamp Power Meter

Information about the device + link

Description: ZigBee 3-Phase Clamp Power Meter (80A/120A/200A/300A)
Model: PC321
Vendor: OWON Technology Inc.
ZigBee Profile: ZigBee HA1.2
Exposes: Irms, Vrms, Active Power & Energy, Reactive Power & Energy

Vendors product description:
https://www.owon-smart.com/three-phase-clamp-measuring-equipment-energy-power-clamp-pc321-2-product/

Thanks

Update:

Here is my altered owon.js where i copied WSP404 to PC321, removed the switch stuff like on_off and changed the WSP404 line "exposes: [e.switch(), e.power(), e.energy()]," to "exposes: [e.voltage(), e.power(), e.current(), e.energy()],":

const exposes = require('../lib/exposes');
const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/legacy').fromZigbee};
const tz = require('../converters/toZigbee');
const constants = require('../lib/constants');
const reporting = require('../lib/reporting');
const e = exposes.presets;

module.exports = [
{
zigbeeModel: ['PC321'],
model: 'PC321',
vendor: 'OWON',
description: '3-Phase Clamp Power Meter',
fromZigbee: [fz.metering],
configure: async (device, coordinatorEndpoint, logger) => {
const endpoint = device.getEndpoint(1);
await reporting.bind(endpoint, coordinatorEndpoint, ['seMetering']);
await reporting.readMeteringMultiplierDivisor(endpoint);
await reporting.instantaneousDemand(endpoint, {min: 5, max: constants.repInterval.MINUTES_5, change: 2});
},
exposes: [e.voltage(), e.power(), e.current(), e.energy()],
},

{
zigbeeModel: ['WSP404'],
model: 'WSP404',
vendor: 'OWON',
description: 'Smart plug',
fromZigbee: [fz.on_off, fz.metering],
toZigbee: [tz.on_off],
configure: async (device, coordinatorEndpoint, logger) => {
const endpoint = device.getEndpoint(1);
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'seMetering']);
await reporting.onOff(endpoint);
await reporting.readMeteringMultiplierDivisor(endpoint);
await reporting.instantaneousDemand(endpoint, {min: 5, max: constants.repInterval.MINUTES_5, change: 2});
},
exposes: [e.switch(), e.power(), e.energy()],
},

The data coming back from the PC321 meter is:

Nov 6 20:11:14 raspberrypi-4 npm[32041]: #33[32mZigbee2MQTT:info #33[39m 2021-11-06 20:11:14: MQTT publish: topic 'zigbee2mqtt/0x3c6a2cfffed0d65c', payload '{"linkquality":123,"power":0}'
Nov 6 20:11:14 raspberrypi-4 npm[32041]: #33[34mZigbee2MQTT:debug#033[39m 2021-11-06 20:11:14: Received Zigbee message from '0x3c6a2cfffed0d65c', type 'attributeReport', cluster 'seMetering', data '{"12288":2334,"12544":0,"16384":[0,142],"16640":[0,0],"16644":0,"8192":0,"8448":0}' from endpoint 1 with groupID 0
Nov 6 20:11:15 raspberrypi-4 npm[32041]: #33[34mZigbee2MQTT:debug#033[39m 2021-11-06 20:11:15: Received Zigbee message from '0x3c6a2cfffed0d65c', type 'attributeReport', cluster 'seMetering', data '{"12289":5,"12545":0,"16385":[0,141],"16641":[0,0],"16645":0,"8193":0,"8449":0}' from endpoint 1 with groupID 0
Nov 6 20:11:16 raspberrypi-4 npm[32041]: #33[34mZigbee2MQTT:debug#033[39m 2021-11-06 20:11:16: Received Zigbee message from '0x3c6a2cfffed0d65c', type 'attributeReport', cluster 'seMetering', data '{"12290":5,"12546":0,"16386":[0,142],"16642":[0,0],"16646":0,"8194":0,"8450":0}' from endpoint 1 with groupID 0
Nov 6 20:12:16 raspberrypi-4 npm[32041]: #33[34mZigbee2MQTT:debug#033[39m 2021-11-06 20:12:16: Received Zigbee message from '0x3c6a2cfffed0d65c', type 'attributeReport', cluster 'seMetering', data '{"12547":0,"16643":[0,0],"8451":0,"currentSummDelivered":[0,425],"instantaneousDemand":0,"status":0}' from endpoint 1 with groupID 0

And this is how the PC321 looks in my Domoticz installation:
PC321_in_Domoticz

Unfortunately, I am stuck here not having the neccesary knowledge to make the PC231 Power Meter work.

Added 2021-11-16:

Instead of using t he WSP404 as basis I tried the 'EMIZB-132' from the develco.js file since the 'EMIZB-132' has 3-phase power measurement, added the line const "ea = exposes.access;" to my owon.js file as well as this:

{
    zigbeeModel: ['PC321'],
    model: 'PC321',
    vendor: 'OWON',
    description: '3-Phase Clamp Power Meter',
    supports: 'power measurement',
    fromZigbee: [fz.metering, fz.electrical_measurement, fz.develco_fw],
    toZigbee: [tz.EMIZB_132_mode],
    ota: ota.zigbeeOTA,
    configure: async (device, coordinatorEndpoint, logger) => {
        const endpoint = device.getEndpoint(2);
        const options = {manufacturerCode: 4117};
        await endpoint.read('genBasic', [0x8000, 0x8010, 0x8020], options);
        await reporting.bind(endpoint, coordinatorEndpoint, ['haElectricalMeasurement', 'seMetering']);

        try {
            // Some don't support these attributes
            // https://github.com/Koenkk/zigbee-herdsman-converters/issues/974#issuecomment-621465038
            await reporting.readEletricalMeasurementMultiplierDivisors(endpoint);
            await reporting.rmsVoltage(endpoint);
            await reporting.rmsCurrent(endpoint);
            await reporting.activePower(endpoint);
        } catch (e) {
            e;
        }

        await reporting.readMeteringMultiplierDivisor(endpoint);
        endpoint.saveClusterAttributeKeyValue('seMetering', {divisor: 1000, multiplier: 1});
        await reporting.instantaneousDemand(endpoint);
        await reporting.currentSummDelivered(endpoint);
        await reporting.currentSummReceived(endpoint);
    },
    exposes: [e.power(), e.energy(), e.current(), e.voltage(), e.current_phase_b(), e.voltage_phase_b(), e.current_phase_c(),
        e.voltage_phase_c()],
    onEvent: async (type, data, device) => {
        if (type === 'message' && data.type === 'attributeReport' && data.cluster === 'seMetering' && data.data['divisor']) {
            // Device sends wrong divisior (512) while it should be fixed to 1000
            // https://github.com/Koenkk/zigbee-herdsman-converters/issues/3066
            data.endpoint.saveClusterAttributeKeyValue('seMetering', {divisor: 1000, multiplier: 1});
        }
    },
},
{

but get this error

2021-11-16 13:45:58.052 Error: Zigbee2MQTT: 0x3c6a2cfffed0d65c: can not process numeric item "current_phase_b"
2021-11-16 13:45:58.052 Error: Zigbee2MQTT: 0x3c6a2cfffed0d65c: can not process numeric item "voltage_phase_b"
2021-11-16 13:45:58.052 Error: Zigbee2MQTT: 0x3c6a2cfffed0d65c: can not process numeric item "current_phase_c"
2021-11-16 13:45:58.052 Error: Zigbee2MQTT: 0x3c6a2cfffed0d65c: can not process numeric item "voltage_phase_c"

The device reports energy and power usage, but with a negative value:

owon_clamp_meter

I have emailed Owon and asked for a copy of the protocol, but unfortunately, no answer.

@FoxConsult FoxConsult added the new device support New device support request label Nov 5, 2021
@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 Dec 17, 2021
@FoxConsult
Copy link
Author

Still need support for my OWON Power Meter.

@github-actions github-actions bot removed the stale Stale issues label Dec 18, 2021
@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 17, 2022
@Phil-ibert
Copy link

Hello,

I also own this device but am struggling to configure an external converter for it...
It seems like it reports to the "seMetering" cluster but that the IDs used are unknown by Z2M :

I'd be happy to help, if somebody would be able to provide guidance on this ;)

Received Zigbee message from '0x3c6a2cfffed1a7d2', type 'attributeReport', cluster 'seMetering', data '{"12288":2318,"12544":0,"16384":[0,0],"16640":[0,0],"16644":0,"8192":2,"8448":0}' from endpoint 1 with groupID 0
Debug Received Zigbee message from '0x3c6a2cfffed1a7d2', type 'attributeReport', cluster 'seMetering', data '{"12289":2312,"12545":0,"16385":[0,0],"16641":[0,0],"16645":0,"8193":0,"8449":0}' from endpoint 1 with groupID 0
Debug Received Zigbee message from '0x3c6a2cfffed1a7d2', type 'attributeReport', cluster 'seMetering', data '{"12290":2316,"12546":0,"16386":[0,0],"16642":[0,0],"16646":0,"8194":0,"8450":0}' from endpoint 1 with groupID 0
Debug Received Zigbee message from '0x3c6a2cfffed1a7d2', type 'attributeReport', cluster 'seMetering', data '{"12547":0,"16643":[0,0],"8451":0,"currentSummDelivered":[0,0],"instantaneousDemand":0,"status":0}' from endpoint 1 with groupID 0

@FoxConsult
Copy link
Author

Hello,

I sold my meter since I no longer had any use for it, but before I did, I asked the manufacturer for the protocol spec's which I got, but only after signing a Non Disclosure Agreement which stipulates I cannot share the document with anyone.

My suggestion is that you request the protocol specification from the manufacturer. I sent my request to:

sales@owon.com and info@owon.com and got a reply from their outfit in Canada. I'm not at liberty of sharing their names and e-mail addresses, but I'm sure they will reply to you promptly which they did to me.

@Phil-ibert
Copy link

Hi FoxConsult,

Uon searching on the device, I found the following repository which contains basically all that is needed to integrate the device :
https://github.com/froggyfly/pc321-zigbee

What I don't know however, is how to use the external converters for that, as to me it seems that the seMetering cluster definition of Z2M has to be extended to fully support this device.

Also, to test it I guess I have to (re)compile the whole Z2M project with the updated clusters.ts file ? Or can I simply edit a file on my Z2M instance ?

Hello @Koenkk, sorry to disturb you but if you could shed some light/point me towards the right direction... ;)

@Koenkk
Copy link
Owner

Koenkk commented Apr 3, 2022

It seems the device is using non standard attributes and therefore zigbee2mqtt doesn't know what the device means with e.g. "12547":0,"16643":[0,0],"8451":0. You have to reverse engineer what they do either by asking the manufacturer or by guessing based on their values. Keep in mind that if all functions of the device works correctly, there is no need to do this and the device can be added to z2m.

@Phil-ibert
Copy link

Thank you for your reply,

I have all the attributes definition (ID, name, type, default values...)
image

However I do not know how to proceed with an external converter to make it work...
My guess is that the non standard attributes have to be added to the seMetering cluster definition, and then exposed with an external converter.
But, how to add the seMetering definition ? can it be done from the external converter file? or must it be extended from cluster.ts in the Herdsman project ?

Thank you

@Koenkk
Copy link
Owner

Koenkk commented Apr 3, 2022

I see you added the manufacturer specific attributes, you can create a new converter which converts these to MQTT.

  1. update to the latest-dev (https://www.zigbee2mqtt.io/advanced/more/switch-to-dev-branch.html)
  2. Add the following 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 ota = require('zigbee-herdsman-converters/lib/ota');
const e = exposes.presets;
const ea = exposes.access;

const fzLocal = {
	PC321_metering: {
        cluster: 'seMetering',
        type: ['attributeReport', 'readResponse'],
        convert: (model, msg, publish, options, meta) => {
            const payload = {};

            // TODO: add the other attributes here

            if (msg.data.hasOwnProperty('owonL1Energy')) {
                payload.energy_l1 = msg.data['owonL1Energy'];
            }

            return payload;
        },
    }
}


const definition = {
	zigbeeModel: ['PC321'],
	model: 'PC321',
	vendor: 'OWON',
	description: '3-Phase Clamp Power Meter',
        toZigbee: [],
	fromZigbee: [fz.metering, fzLocal.PC321_metering],
	configure: async (device, coordinatorEndpoint, logger) => {
		const endpoint = device.getEndpoint(1);
		await reporting.bind(endpoint, coordinatorEndpoint, ['seMetering']);
		await reporting.readMeteringMultiplierDivisor(endpoint);
		await reporting.instantaneousDemand(endpoint, {min: 5, max: constants.repInterval.MINUTES_5, change: 2});
	},
	exposes: [e.voltage(), e.power(), e.current(), e.energy()],
};

module.exports = definition;

@Phil-ibert
Copy link

Many thanks Koenkk for the converter template.

I added it and switched to the dev branch, but Z2M fails to start, returning the following error:

(node:28624) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'push' of undefined at Object.addDefinition [as addDeviceDefinition] (/app/node_modules/zigbee-herdsman-converters/index.js:78:25) at new ExternalConverters (/app/lib/extension/externalConverters.ts:15:17) at new Controller (/app/lib/controller.ts:83:58) at start (/app/index.js:100:18) (Use node --trace-warnings ...to show where the warning was created) (node:28624) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag--unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1) (node:28624) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Following the template, if I wanted to expose the phase 1 energy, e.energy_l1() into exposes would be enough ?

Sorry for all those questions, I am not really familiar with nodejs..

@Koenkk
Copy link
Owner

Koenkk commented Apr 3, 2022

Updated #9525 (comment), should be fixed now.

@Phil-ibert
Copy link

It works ! I even managed to have the attributes exposed to Home Assistant using a new numeric() definition in the 'exposes' array.

There are a couple minor issues left, for which I am pretty much clueless for now...
Here they are :

  • voltage is reported with tens of Volts : 2321 for 232.1 V
  • current is reported in milliAmps : 8234 for 8234 A
  • energy is not working, I assume due to the data structure : [0,1239]. The documentation says it is an uint48, but the device reports it in an array? Or is it the ZCL library that does some unexpected transformations ?

I fixed the first two by dividing the data before storing it to the payload, but that does not seem the right way to do :)

Z2M also reports some errors, most likely while trying to get the multiplier/divisor values which could be related to some of the issues faced ?

Here is the error message :
Failed to configure 'Owon Power meter', attempt 2 (ReferenceError: constants is not defined at Object.configure (/app/dist/util/externally-loaded.js:76:69) at Configure.configure (/app/lib/extension/configure.ts:115:13))

And here is my 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 e = exposes.presets;
const ea = exposes.access;

const fzLocal = {
    PC321_metering: {
        cluster: 'seMetering',
        type: ['attributeReport', 'readResponse'],
        convert: (model, msg, publish, options, meta) => {
            const payload = {};
            if (msg.data.hasOwnProperty('owonL2Energy')) {
                payload.energy_l2 = msg.data['owonL2Energy'] / 1000.0;
            }
            if (msg.data.hasOwnProperty('owonL3Energy')) {
                payload.energy_l3 = msg.data['owonL3Energy'] / 1000.0;
            }
            if (msg.data.hasOwnProperty('owonL1PhasePower')) {
                payload.power_l1 = msg.data['owonL1PhasePower'];
            }
            if (msg.data.hasOwnProperty('owonL2PhasePower')) {
                payload.power_l2 = msg.data['owonL2PhasePower'];
            }
            if (msg.data.hasOwnProperty('owonL3PhasePower')) {
                payload.power_l3 = msg.data['owonL3PhasePower'];
            }
            
            if (msg.data.hasOwnProperty('owonL1PhaseVoltage')) {
                payload.voltage_l1 = msg.data['owonL1PhaseVoltage'] / 10.0;
            }
            if (msg.data.hasOwnProperty('owonL2PhaseVoltage')) {
                payload.voltage_l2 = msg.data['owonL2PhaseVoltage'] / 10.0;
            }
            if (msg.data.hasOwnProperty('owonL3PhaseVoltage')) {
                payload.voltage_l3 = msg.data['owonL3PhaseVoltage'] / 10.0;
            }
            
            if (msg.data.hasOwnProperty('owonL1PhaseCurrent')) {
                payload.current_l1 = msg.data['owonL1PhaseCurrent'] / 1000.0;
            }
            
            if (msg.data.hasOwnProperty('owonL2PhaseCurrent')) {
                payload.current_l2 = msg.data['owonL2PhaseCurrent'] / 1000.0;
            }
            if (msg.data.hasOwnProperty('owonL3PhaseCurrent')) {
                payload.current_l3 = msg.data['owonL3PhaseCurrent'] / 1000.0;
            }
            
            
            // TODO: add the other attributes here

            if (msg.data.hasOwnProperty('owonL1Energy')) {
                payload.energy_l1 = msg.data['owonL1Energy'] / 1000.0;
            }

            return payload;
        },
    },
};

const definition = {
    zigbeeModel: ['PC321'], // The model ID from: Device with modelID 'lumi.sens' is not supported.
    model: 'PC321', // Vendor model number, look on the device for a model number
    vendor: 'OWON', // Vendor of the device (only used for documentation and startup logging)
    description: '3-Phase Clamp Power Meter', // Description of the device, copy from vendor site. (only used for documentation and startup logging)
    fromZigbee: [fz.metering, fzLocal.PC321_metering],
    toZigbee: [], // Should be empty, unless device can be controlled (e.g. lights, switches).
    configure: async (device, coordinatorEndpoint, logger) => {
        const endpoint = device.getEndpoint(1);
        await reporting.bind(endpoint, coordinatorEndpoint, ['seMetering']);
        await reporting.readMeteringMultiplierDivisor(endpoint);
        await reporting.instantaneousDemand(endpoint, {min: 5, max: constants.repInterval.MINUTES_5, change: 2});
    },
	exposes: [e.energy(),
	exposes.numeric('voltage_l1',ea.STATE).withUnit('V').withDescription('Phase 1 Voltage'),
	exposes.numeric('voltage_l2',ea.STATE).withUnit('V').withDescription('Phase 2 Voltage'),
	exposes.numeric('voltage_l3',ea.STATE).withUnit('V').withDescription('Phase 3 Voltage'),
	exposes.numeric('current_l1',ea.STATE).withUnit('A').withDescription('Phase 1 Current'),
	exposes.numeric('current_l2',ea.STATE).withUnit('A').withDescription('Phase 2 Current'),
	exposes.numeric('current_l3',ea.STATE).withUnit('A').withDescription('Phase 3 Current'),
	exposes.numeric('energy_l1',ea.STATE).withUnit('kWh').withDescription('Phase 1 Energy'),
	exposes.numeric('energy_l2',ea.STATE).withUnit('kWh').withDescription('Phase 2 Energy'),
	exposes.numeric('energy_l3',ea.STATE).withUnit('kWh').withDescription('Phase 3 Energy'),
	exposes.numeric('power_l1',ea.STATE).withUnit('W').withDescription('Phase 1 Power'),
	exposes.numeric('power_l2',ea.STATE).withUnit('W').withDescription('Phase 2 Power'),
	exposes.numeric('power_l3',ea.STATE).withUnit('W').withDescription('Phase 3 Power'),
	],
	
};

module.exports = definition;

@Koenkk
Copy link
Owner

Koenkk commented Apr 4, 2022

Try adding the following line at the top of your file: const constants = require('zigbee-herdsman-converters/lib/constants');

@Phil-ibert
Copy link

Hi Koenkk,
I thought I posted this last sunday but I didnt... my bad

It improved but now Z2M goes into timeout trying to configure the device, here is the error :

Failed to configure 'Owon Power meter', attempt 2 (Error: ConfigureReporting 0x3c6a2cfffed1a7d2/1 seMetering([{"attribute":"instantaneousDemand","minimumReportInterval":5,"maximumReportInterval":300,"reportableChange":2}], {"sendWhen":"immediate","timeout":10000,"disableResponse":false,"disableRecovery":false,"disableDefaultResponse":true,"direction":0,"srcEndpoint":null,"reservedBits":0,"manufacturerCode":null,"transactionSequenceNumber":null,"writeUndiv":false}) failed (Timeout - 43847 - 1 - 6 - 1794 - 7 after 10000ms) at Timeout._onTimeout (/app/node_modules/zigbee-herdsman/src/utils/waitress.ts:64:35) at listOnTimeout (internal/timers.js:557:17) at processTimers (internal/timers.js:500:7))

I am all ears (and fingers) to try to improve this ;)

@Koenkk
Copy link
Owner

Koenkk commented Apr 7, 2022

What is you replace await reporting.instantaneousDemand(endpoint, {min: 5, max: constants.repInterval.MINUTES_5, change: 2}); with:

            const payload = [{
                attribute: 'owonL2Energy',
                minimumReportInterval: 5,
                maximumReportInterval: 3600,
                reportableChange: 0,
            }];
            await endpoint.configureReporting('haElectricalMeasurement', payload);

@Phil-ibert
Copy link

Hi Koenkk,

it still fails, but with another error

Failed to configure 'Owon Power meter', attempt 2 (Error: ConfigureReporting 0x3c6a2cfffed1a7d2/1 haElectricalMeasurement([{"attribute":"owonL2Energy","minimumReportInterval":5,"maximumReportInterval":3600,"reportableChange":0}], {"sendWhen":"immediate","timeout":10000,"disableResponse":false,"disableRecovery":false,"disableDefaultResponse":true,"direction":0,"srcEndpoint":null,"reservedBits":0,"manufacturerCode":null,"transactionSequenceNumber":null,"writeUndiv":false}) failed (Don't know value type for 'undefined') at Object.IsDataTypeAnalogOrDiscrete (/app/node_modules/zigbee-herdsman/src/zcl/utils.ts:30:15) at /app/node_modules/zigbee-herdsman/src/zcl/zclFrame.ts:354:38 at Array.find (<anonymous>) at Function.conditionsValid (/app/node_modules/zigbee-herdsman/src/zcl/zclFrame.ts:338:58) at ZclFrame.writePayloadGlobal (/app/node_modules/zigbee-herdsman/src/zcl/zclFrame.ts:113:35) at ZclFrame.toBuffer (/app/node_modules/zigbee-herdsman/src/zcl/zclFrame.ts:76:18) at ZStackAdapter.sendZclFrameToEndpointInternal (/app/node_modules/zigbee-herdsman/src/adapter/z-stack/adapter/zStackAdapter.ts:388:22) at Object.func (/app/node_modules/zigbee-herdsman/src/adapter/z-stack/adapter/zStackAdapter.ts:356:25) at Queue.executeNext (/app/node_modules/zigbee-herdsman/src/utils/queue.ts:32:42) at /app/node_modules/zigbee-herdsman/src/utils/queue.ts:21:18)

@Koenkk
Copy link
Owner

Koenkk commented Apr 8, 2022

@Phil-ibert
Copy link

I am currently running 1.25.0-dev commit: 91d80f1

I'll upgrade to the latest, see if there is any improvement

@Phil-ibert
Copy link

After upgrading to the last dev version no error messages anymore, you rock Sir !

@Ano10
Copy link

Ano10 commented Jun 2, 2022

Hi,
I haven't see this device into supported device list. Is it working ?
If so are you planning to add it ?

@Phil-ibert
Copy link

Hi Ano10,

I managed to get most of the data reporting working, only the network frequency is not reported but it seems to be on the device side.

However, I did not know how to configure Z2M in order to set up the writable attributes such as the report frequency or threshold.
Maybe @Koenkk could have a look sometime ? I'll push my custom file to the appropriate repo this week

@Koenkk
Copy link
Owner

Koenkk commented Jun 2, 2022

@Phil-ibert you will be able to write any value via the dev console (frontend -> click on your device)

@zekje
Copy link

zekje commented Jun 6, 2022

Hi, i have tried to install it to Zigbee2Mqtt (into Home Assistant) .

Home assistant 2022.6.2
Zigbee2mqtt Edge 1.25.2-dev commit: [300b297]

i have added a file ( OWONPC321.js ) into the config dir, with the content of post #9525

Item is now 'supported' :)

but i have this errors :
Failed to configure '0x3c6a2cfffed15361', attempt 2 (ReferenceError: constants is not defined at Object.configure (/app/dist/util/externally-loaded.js:40:63) at Configure.configure (/app/lib/extension/configure.ts:115:13) at Configure.onMQTTMessage (/app/lib/extension/configure.ts:55:21))

on the exposed value , i have only ( in french )
voltage Sans valeur V
power 1W
current Sans valeur A
energy 104.4kWh
linkquality 255lqi

(in french , 'sans valeur' is 'no value' in english )
how to measure the 3 phases separately ?

thank's

@Phil-ibert
Copy link

Hi Zekje,

here is my custom 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 e = exposes.presets;
const ea = exposes.access;

const fzLocal = {
    PC321_metering: {
        cluster: 'seMetering',
        type: ['attributeReport', 'readResponse'],
        convert: (model, msg, publish, options, meta) => {
            const payload = {};
            if (msg.data.hasOwnProperty('owonL1Energy')) {
                payload.energy_l1 = msg.data['owonL1Energy'][1] / 1000.0;
            }
            if (msg.data.hasOwnProperty('owonL2Energy')) {
                payload.energy_l2 = msg.data['owonL2Energy'][1] / 1000.0;
            }
            if (msg.data.hasOwnProperty('owonL3Energy')) {
                payload.energy_l3 = msg.data['owonL3Energy'][1] / 1000.0;
            }
            
            if (msg.data.hasOwnProperty('owonL1ReactiveEnergy')) {
                payload.reactive_energy_l1 = msg.data['owonL1ReactiveEnergy'][1] / 1000.0;
            }
            if (msg.data.hasOwnProperty('owonL2ReactiveEnergy')) {
                payload.reactive_energy_l2 = msg.data['owonL2ReactiveEnergy'][1] / 1000.0;
            }
            if (msg.data.hasOwnProperty('owonL3ReactiveEnergy')) {
                payload.reactive_energy_l3 = msg.data['owonL3ReactiveEnergy'][1] / 1000.0;
            }
            
            if (msg.data.hasOwnProperty('owonL1PhasePower')) {
                payload.power_l1 = msg.data['owonL1PhasePower'];
            }
            if (msg.data.hasOwnProperty('owonL2PhasePower')) {
                payload.power_l2 = msg.data['owonL2PhasePower'];
            }
            if (msg.data.hasOwnProperty('owonL3PhasePower')) {
                payload.power_l3 = msg.data['owonL3PhasePower'];
            }
            
             if (msg.data.hasOwnProperty('owonL1PhaseReactivePower')) {
                payload.reactive_power_l1 = msg.data['owonL1PhaseReactivePower'];
            }
            if (msg.data.hasOwnProperty('owonL2PhaseReactivePower')) {
                payload.reactive_power_l2 = msg.data['owonL2PhaseReactivePower'];
            }
            if (msg.data.hasOwnProperty('owonL3PhaseReactivePower')) {
                payload.reactive_power_l3 = msg.data['owonL3PhaseReactivePower'];
            }
            
            if (msg.data.hasOwnProperty('owonL1PhaseVoltage')) {
                payload.voltage_l1 = msg.data['owonL1PhaseVoltage'] / 10.0;
            }
            if (msg.data.hasOwnProperty('owonL2PhaseVoltage')) {
                payload.voltage_l2 = msg.data['owonL2PhaseVoltage'] / 10.0;
            }
            if (msg.data.hasOwnProperty('owonL3PhaseVoltage')) {
                payload.voltage_l3 = msg.data['owonL3PhaseVoltage'] / 10.0;
            }
            
            if (msg.data.hasOwnProperty('owonL1PhaseCurrent')) {
                payload.current_l1 = msg.data['owonL1PhaseCurrent'] / 1000.0;
            }
            
            if (msg.data.hasOwnProperty('owonL2PhaseCurrent')) {
                payload.current_l2 = msg.data['owonL2PhaseCurrent'] / 1000.0;
            }
            
            if (msg.data.hasOwnProperty('owonL3PhaseCurrent')) {
                payload.current_l3 = msg.data['owonL3PhaseCurrent'] / 1000.0;
            }
            
            if (msg.data.hasOwnProperty('owonFrequency')) {
                payload.frequency = msg.data['owonFrequency'];
            }
            
            if (msg.data.hasOwnProperty('owonReactiveEnergySum')) {
                payload.reactive_energy_sum = msg.data['owonReactiveEnergySum'];
            }
            
            
            return payload;
        },
    },
};

const definition = {
    zigbeeModel: ['PC321'], // The model ID from: Device with modelID 'lumi.sens' is not supported.
    model: 'PC321', // Vendor model number, look on the device for a model number
    vendor: 'OWON', // Vendor of the device (only used for documentation and startup logging)
    description: '3-Phase Clamp Power Meter', // Description of the device, copy from vendor site. (only used for documentation and startup logging)
    fromZigbee: [fz.metering, fzLocal.PC321_metering],
    toZigbee: [], // Should be empty, unless device can be controlled (e.g. lights, switches).
    configure: async (device, coordinatorEndpoint, logger) => {
        const endpoint = device.getEndpoint(1);
        await reporting.bind(endpoint, coordinatorEndpoint, ['seMetering']);
        await reporting.readMeteringMultiplierDivisor(endpoint);
        const payload = [{
                attribute: 'owonFrequency',
                minimumReportInterval: 5,
                maximumReportInterval: 3600,
                reportableChange: 0,
            }];
            await endpoint.configureReporting('seMetering', payload);
    },
	exposes: [e.energy(),
	exposes.numeric('voltage_l1',ea.STATE).withUnit('V').withDescription('Phase 1 Voltage'),
	exposes.numeric('voltage_l2',ea.STATE).withUnit('V').withDescription('Phase 2 Voltage'),
	exposes.numeric('voltage_l3',ea.STATE).withUnit('V').withDescription('Phase 3 Voltage'),
	exposes.numeric('current_l1',ea.STATE).withUnit('A').withDescription('Phase 1 Current'),
	exposes.numeric('current_l2',ea.STATE).withUnit('A').withDescription('Phase 2 Current'),
	exposes.numeric('current_l3',ea.STATE).withUnit('A').withDescription('Phase 3 Current'),
	exposes.numeric('energy_l1',ea.STATE).withUnit('kWh').withDescription('Phase 1 Energy'),
	exposes.numeric('energy_l2',ea.STATE).withUnit('kWh').withDescription('Phase 2 Energy'),
	exposes.numeric('energy_l3',ea.STATE).withUnit('kWh').withDescription('Phase 3 Energy'),
	exposes.numeric('reactive_energy_l1',ea.STATE).withUnit('kVArh').withDescription('Phase 1 Reactive Energy'),
	exposes.numeric('reactive_energy_l2',ea.STATE).withUnit('kVArh').withDescription('Phase 2 Reactive Energy'),
	exposes.numeric('reactive_energy_l3',ea.STATE).withUnit('kVArh').withDescription('Phase 3 Reactive Energy'),
	exposes.numeric('power_l1',ea.STATE).withUnit('W').withDescription('Phase 1 Power'),
	exposes.numeric('power_l2',ea.STATE).withUnit('W').withDescription('Phase 2 Power'),
	exposes.numeric('power_l3',ea.STATE).withUnit('W').withDescription('Phase 3 Power'),
	exposes.numeric('reactive_power_l1',ea.STATE).withUnit('VAr').withDescription('Phase 1 Reactive Power'),
	exposes.numeric('reactive_power_l2',ea.STATE).withUnit('VAr').withDescription('Phase 2 Reactive Power'),
	exposes.numeric('reactive_power_l3',ea.STATE).withUnit('VAr').withDescription('Phase 3 Reactive Power'),
	exposes.numeric('frequency',ea.STATE).withUnit('Hz').withDescription('Frequency'),
	exposes.numeric('reactive_energy_sum',ea.STATE).withUnit('kVArh').withDescription('Reactive Energy Sum'),
	],
	
};

module.exports = definition;

I have a pending pull request for the device to be supported natively by Z2M, it may be closed soon ;)

@Phil-ibert
Copy link

@Phil-ibert you will be able to write any value via the dev console (frontend -> click on your device)

Hi Koenkk,

when I try to use the console dev, I get an "Unsupported_attribute" error, even on data items that are already reporting correctly
image

@zekje
Copy link

zekje commented Jun 7, 2022

@Phil-ibert
thank's , all data is show now :)

some adjustement needed , but not important .
( frequency not measured , and the device show with '?' instead of sector (or battery) )

@dokkomp
Copy link

dokkomp commented Oct 28, 2022

@Koenkk
Hi, i have tried to install it to Zigbee2Mqtt (Home Assistant) .

Model: OWON PC321-Z-TY
Home Assistant 2022.10.5
Zigbee2MQTT Current version: 1.28.0-1
Zigbee model 'TS0601' and manufacturer name '_TZE200_nslr42tt'

I have added a file ( 321-z-ty.js ) into the config dir, with the content of post @Phil-ibert :

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 e = exposes.presets;
const ea = exposes.access;

const fzLocal = {
    PC321_metering: {
        cluster: 'seMetering',
        type: ['attributeReport', 'readResponse'],
        convert: (model, msg, publish, options, meta) => {
            const payload = {};
            if (msg.data.hasOwnProperty('owonL1Energy')) {
                payload.energy_l1 = msg.data['owonL1Energy'][1] / 1000.0;
            }
            if (msg.data.hasOwnProperty('owonL2Energy')) {
                payload.energy_l2 = msg.data['owonL2Energy'][1] / 1000.0;
            }
            if (msg.data.hasOwnProperty('owonL3Energy')) {
                payload.energy_l3 = msg.data['owonL3Energy'][1] / 1000.0;
            }
            
            if (msg.data.hasOwnProperty('owonL1ReactiveEnergy')) {
                payload.reactive_energy_l1 = msg.data['owonL1ReactiveEnergy'][1] / 1000.0;
            }
            if (msg.data.hasOwnProperty('owonL2ReactiveEnergy')) {
                payload.reactive_energy_l2 = msg.data['owonL2ReactiveEnergy'][1] / 1000.0;
            }
            if (msg.data.hasOwnProperty('owonL3ReactiveEnergy')) {
                payload.reactive_energy_l3 = msg.data['owonL3ReactiveEnergy'][1] / 1000.0;
            }
            
            if (msg.data.hasOwnProperty('owonL1PhasePower')) {
                payload.power_l1 = msg.data['owonL1PhasePower'];
            }
            if (msg.data.hasOwnProperty('owonL2PhasePower')) {
                payload.power_l2 = msg.data['owonL2PhasePower'];
            }
            if (msg.data.hasOwnProperty('owonL3PhasePower')) {
                payload.power_l3 = msg.data['owonL3PhasePower'];
            }
            
             if (msg.data.hasOwnProperty('owonL1PhaseReactivePower')) {
                payload.reactive_power_l1 = msg.data['owonL1PhaseReactivePower'];
            }
            if (msg.data.hasOwnProperty('owonL2PhaseReactivePower')) {
                payload.reactive_power_l2 = msg.data['owonL2PhaseReactivePower'];
            }
            if (msg.data.hasOwnProperty('owonL3PhaseReactivePower')) {
                payload.reactive_power_l3 = msg.data['owonL3PhaseReactivePower'];
            }
            
            if (msg.data.hasOwnProperty('owonL1PhaseVoltage')) {
                payload.voltage_l1 = msg.data['owonL1PhaseVoltage'] / 10.0;
            }
            if (msg.data.hasOwnProperty('owonL2PhaseVoltage')) {
                payload.voltage_l2 = msg.data['owonL2PhaseVoltage'] / 10.0;
            }
            if (msg.data.hasOwnProperty('owonL3PhaseVoltage')) {
                payload.voltage_l3 = msg.data['owonL3PhaseVoltage'] / 10.0;
            }
            
            if (msg.data.hasOwnProperty('owonL1PhaseCurrent')) {
                payload.current_l1 = msg.data['owonL1PhaseCurrent'] / 1000.0;
            }
            
            if (msg.data.hasOwnProperty('owonL2PhaseCurrent')) {
                payload.current_l2 = msg.data['owonL2PhaseCurrent'] / 1000.0;
            }
            
            if (msg.data.hasOwnProperty('owonL3PhaseCurrent')) {
                payload.current_l3 = msg.data['owonL3PhaseCurrent'] / 1000.0;
            }
            
            if (msg.data.hasOwnProperty('owonFrequency')) {
                payload.frequency = msg.data['owonFrequency'];
            }
            
            if (msg.data.hasOwnProperty('owonReactiveEnergySum')) {
                payload.reactive_energy_sum = msg.data['owonReactiveEnergySum'];
            }
            
            
            return payload;
        },
    },
};

const definition = {
    zigbeeModel: ['TS0601'], // The model ID from: Device with modelID 'lumi.sens' is not supported.
    model: 'TS0601', // Vendor model number, look on the device for a model number
    vendor: 'OWON', // Vendor of the device (only used for documentation and startup logging)
    description: '3-Phase Clamp Power Meter', // Description of the device, copy from vendor site. (only used for documentation and startup logging)
    fromZigbee: [fz.metering, fzLocal.PC321_metering],
    toZigbee: [], // Should be empty, unless device can be controlled (e.g. lights, switches).
    configure: async (device, coordinatorEndpoint, logger) => {
        const endpoint = device.getEndpoint(1);
        await reporting.bind(endpoint, coordinatorEndpoint, ['seMetering']);
        await reporting.readMeteringMultiplierDivisor(endpoint);
        const payload = [{
                attribute: 'owonFrequency',
                minimumReportInterval: 5,
                maximumReportInterval: 3600,
                reportableChange: 0,
            }];
            await endpoint.configureReporting('seMetering', payload);
    },
	exposes: [e.energy(),
	exposes.numeric('voltage_l1',ea.STATE).withUnit('V').withDescription('Phase 1 Voltage'),
	exposes.numeric('voltage_l2',ea.STATE).withUnit('V').withDescription('Phase 2 Voltage'),
	exposes.numeric('voltage_l3',ea.STATE).withUnit('V').withDescription('Phase 3 Voltage'),
	exposes.numeric('current_l1',ea.STATE).withUnit('A').withDescription('Phase 1 Current'),
	exposes.numeric('current_l2',ea.STATE).withUnit('A').withDescription('Phase 2 Current'),
	exposes.numeric('current_l3',ea.STATE).withUnit('A').withDescription('Phase 3 Current'),
	exposes.numeric('energy_l1',ea.STATE).withUnit('kWh').withDescription('Phase 1 Energy'),
	exposes.numeric('energy_l2',ea.STATE).withUnit('kWh').withDescription('Phase 2 Energy'),
	exposes.numeric('energy_l3',ea.STATE).withUnit('kWh').withDescription('Phase 3 Energy'),
	exposes.numeric('reactive_energy_l1',ea.STATE).withUnit('kVArh').withDescription('Phase 1 Reactive Energy'),
	exposes.numeric('reactive_energy_l2',ea.STATE).withUnit('kVArh').withDescription('Phase 2 Reactive Energy'),
	exposes.numeric('reactive_energy_l3',ea.STATE).withUnit('kVArh').withDescription('Phase 3 Reactive Energy'),
	exposes.numeric('power_l1',ea.STATE).withUnit('W').withDescription('Phase 1 Power'),
	exposes.numeric('power_l2',ea.STATE).withUnit('W').withDescription('Phase 2 Power'),
	exposes.numeric('power_l3',ea.STATE).withUnit('W').withDescription('Phase 3 Power'),
	exposes.numeric('reactive_power_l1',ea.STATE).withUnit('VAr').withDescription('Phase 1 Reactive Power'),
	exposes.numeric('reactive_power_l2',ea.STATE).withUnit('VAr').withDescription('Phase 2 Reactive Power'),
	exposes.numeric('reactive_power_l3',ea.STATE).withUnit('VAr').withDescription('Phase 3 Reactive Power'),
	exposes.numeric('frequency',ea.STATE).withUnit('Hz').withDescription('Frequency'),
	exposes.numeric('reactive_energy_sum',ea.STATE).withUnit('kVArh').withDescription('Reactive Energy Sum'),
	],
	
};

module.exports = definition;

but i have this errors :

Zigbee2MQTT:info 2022-10-28 20:09:57: Configuring 'Energy'
Zigbee2MQTT:error 2022-10-28 20:10:17: Failed to configure 'Energy', attempt 2 (Error: Read 0xa4c138129f4abd2e/1 seMetering(["multiplier","divisor"], {"sendWhen":"immediate","timeout":10000,"disableResponse":false,"disableRecovery":false,"disableDefaultResponse":true,"direction":0,"srcEndpoint":null,"reservedBits":0,"manufacturerCode":null,"transactionSequenceNumber":null,"writeUndiv":false}) failed (Timeout - 26610 - 1 - 4 - 1794 - 1 after 10000ms)
at Timeout._onTimeout (/app/node_modules/zigbee-herdsman/src/utils/waitress.ts:64:35)
at listOnTimeout (node:internal/timers:559:17)
at processTimers (node:internal/timers:502:7))

please help me

@Koenkk
Copy link
Owner

Koenkk commented Oct 29, 2022

@dokkomp #9525 (comment)

@zekje @Phil-ibert sorry I did not respond, does the device work well with the external converter?

@dokkomp
Copy link

dokkomp commented Nov 1, 2022

Hi @Koenkk
@zekje @Phil-ibert Guys don't answer(.
Can you help me with my problem?
Please)

@zekje
Copy link

zekje commented Nov 1, 2022 via email

@Phil-ibert
Copy link

Hi @dokkomp,

My apologies for the late reply.

Regarding the frequency, the documentation of the device says it reports it through a specified attribute, but it actually does not report anything for that...

As to the power source, it is actually working into the code I pushed to the official repository.

Today, all you need is to have an up to date Z2M version (1.28 at least ?)

@dokkomp
Copy link

dokkomp commented Nov 2, 2022

I have the latest version now 1.28.1-1
Here is my log:
Zigbee2MQTT:debug 2022-11-02 14:47:22: Received Zigbee message from 'Energy', type 'commandDataReport', cluster 'manuSpecificTuya', data '{"dpValues":[{"data":{"data":[0,0,0,0],"type":"Buffer"},"datatype":2,"dp":122}],"seq":44032}' from endpoint 1 with groupID 0
Zigbee2MQTT:warn 2022-11-02 14:47:22: Received message from unsupported device with Zigbee model 'TS0601' and manufacturer name '_TZE200_nslr42tt'
Zigbee2MQTT:warn 2022-11-02 14:47:22: Please see: https://www.zigbee2mqtt.io/advanced/support-new-devices/01_support_new_devices.html

@Phil-ibert
Copy link

This error is in regard of a Tuya switch, not the OWON PC321

https://fr.aliexpress.com/item/4001181765345.html?spm=a2g0s.9042311.0.0.71ef5c0fxTke0W&gatewayAdapt=glo2fra

You should already see your power meter device, provided that you paired it with Z2M ?

@Phil-ibert
Copy link

You just have to follow the usual pairing process :

  • in Z2M, click the "permit all" to enable pairing
  • On your device, press the button on the back of the device for 5 seconds in order to put it into pairing mode (reset)

Please note that the PC321-TY is wifi and the PC321-Z-TY is Zigbee

@dokkomp
Copy link

dokkomp commented Nov 2, 2022

@Phil-ibert
In z2m I added it
But I am not receiving data from that device.

@Phil-ibert
Copy link

What does the "exposes" tab shows for your device ? How did you wire it in your electrical installation ?

@dokkomp
Copy link

dokkomp commented Nov 2, 2022

@Phil-ibert

Without an external converter:
Empty exposes definition

With the external converter from the post above:
energy
Sum of consumed energy
N/AkWh
voltage_l1
Phase 1 Voltage
N/AV
voltage_l2
Phase 2 Voltage
N/AV
voltage_l3
Phase 3 Voltage
N/AV
current_l1
Phase 1 Current
N/AA
current_l2
Phase 2 Current
N/AA
current_l3
Phase 3 Current
N/AA
energy_l1
Phase 1 Energy
N/AkWh
energy_l2
Phase 2 Energy
N/AkWh
energy_l3
Phase 3 Energy
N/AkWh
reactive_energy_l1
Phase 1 Reactive Energy
N/AkVArh
reactive_energy_l2
Phase 2 Reactive Energy
N/AkVArh
reactive_energy_l3
Phase 3 Reactive Energy
N/AkVArh
power_l1
Phase 1 Power
N/AW
power_l2
Phase 2 Power
N/AW
power_l3
Phase 3 Power
N/AW
reactive_power_l1
Phase 1 Reactive Power
N/AVAr
reactive_power_l2
Phase 2 Reactive Power
N/AVAr
reactive_power_l3
Phase 3 Reactive Power
N/AVAr
frequency
Frequency
N/AHz
reactive_energy_sum
Reactive Energy Sum
N/AkVArh
linkquality
Link quality (signal strength)
255lqi

@Phil-ibert
Copy link

Maybe the PC321-Z-TY is different than the PC321 that I have ?

Because mine is working as expected with the default converter
image

maybe @Koenkk can help out on this, I believe some debug logging of the device could be helpful ?

@Koenkk
Copy link
Owner

Koenkk commented Nov 2, 2022

@dokkomp this is a completely different device, please fill in the "New device support request" https://github.com/Koenkk/zigbee2mqtt/issues/new/choose

@tparvais
Copy link

tparvais commented Feb 1, 2023

Hi, is this pc321 suppose to work well in both direction I’d used to monitor house energy having solar panel ? (We can inject energy to grid , and the opposite when no sun)

I think it’s not ok in energy Dashboard home assistant

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

7 participants