Skip to content

Instantly share code, notes, and snippets.

@jonathandreyer
Last active May 7, 2023 21:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonathandreyer/19a8f3e8f8990973f22984c0ec5c907e to your computer and use it in GitHub Desktop.
Save jonathandreyer/19a8f3e8f8990973f22984c0ec5c907e to your computer and use it in GitHub Desktop.
New device (Schneider Electric EM4302) for Zigbee2MQTT
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 utils = require('zigbee-herdsman-converters/lib/utils');
const e = exposes.presets;
const ea = exposes.access;
/*const attributes_basic = ["schneiderMeterRadioPower"];
const attributes_seMetering = ["readingSnapshotTime","schneiderActiveEnergyTotal","schneiderReactiveEnergyTotal","schneiderApparentEnergyTotal","schneiderPartialActiveEnergyTotal","schneiderPartialReactiveEnergyTotal","schneiderPartialApparentEnergyTotal","schneiderActiveEnergyMultiplier","schneiderPartialActiveEnergyL1Phase","schneiderPartialReactiveEnergyL1Phase","schneiderPartialApparentEnergyL1Phase","schneiderActiveEnergyL1Phase","schneiderReactiveEnergyL1Phase","schneiderApparentEnergyL1Phase","schneiderActiveEnergyDivisor","schneiderPartialActiveEnergyL2Phase","schneiderPartialReactiveEnergyL2Phase","schneiderPartialApparentEnergyL2Phase","schneiderActiveEnergyL2Phase","schneiderReactiveEnergyL2Phase","schneiderApparentEnergyL2Phase","schneiderReactiveEnergyMultiplier","schneiderPartialActiveEnergyL3Phase","schneiderPartialReactiveEnergyL3Phase","schneiderPartialApparentEnergyL3Phase","schneiderActiveEnergyL3Phase","schneiderReactiveEnergyL3Phase","schneiderApparentEnergyL3Phase","schneiderReactiveEnergyDivisor","schneiderApparentEnergyMultiplier","schneiderApparentEnergyDivisor","schneiderEnergyResetDateTime","schneiderEnergyCountersReportingPeriod"];
const attributes_haElectricalMeasurement = ["acFrequency","totalActivePower","totalReactivePower","totalApparentPower","acFrequencyMultiplier","acFrequencyDivisor","powerMultiplier","powerDivisor","rmsVoltage","activePower","reactivePower","apparentPower","powerFactor","acVoltageMultiplier","acVoltageDivisor","acCurrentMultiplier","acCurrentDivisor","acPowerMultiplier","acPowerDivisor","activePowerPhB","reactivePowerPhB","apparentPowerPhB","powerFactorPhB","activePowerPhC","reactivePowerPhC","apparentPowerPhC","powerFactorPhC","schneiderActivePowerDemandTotal","schneiderReactivePowerDemandTotal","schneiderApparentPowerDemandTotal","schneiderDemandIntervalDuration","schneiderDemandDateTime","schneiderActivePowerDemandPhase1","schneiderReactivePowerDemandPhase1","schneiderApparentPowerDemandPhase1","schneiderDemandIntervalMinimalVoltageL1","schneiderDemandIntervalMaximalCurrentI1","schneiderActivePowerDemandPhase2","schneiderReactivePowerDemandPhase2","schneiderApparentPowerDemandPhase2","schneiderDemandIntervalMinimalVoltageL2","schneiderDemandIntervalMaximalCurrentI2","schneiderActivePowerDemandPhase3","schneiderReactivePowerDemandPhase3","schneiderApparentPowerDemandPhase3","schneiderDemandIntervalMinimalVoltageL3","schneiderDemandIntervalMaximalCurrentI3","schneiderCurrentSensorMultiplier"];
const attributes_haDiagnostic = ["schneiderMeterStatus","schneiderDiagnosticRegister1","schneiderCommunicationQuality","lastMessageLqi","lastMessageRssi"];
async function configureReportingAttributes(endpoint, cluster, attributes) {
for (const attr of attributes) {
const payload = [{
attribute: attr,
minimumReportInterval: 10,
maximumReportInterval: 65535,
reportableChange: 0,
}];
await endpoint.configureReporting(cluster, payload);
}
}*/
const exposesLocal = {
meter_radio_power: exposes.numeric('meter_radio_power', ea.ALL).withUnit('dBm').withDescription('Meter Radio Power'),
active_energy_total: exposes.numeric('active_energy_total', ea.STATE).withUnit('kWh').withDescription('Active Energy Total'),
reactive_energy_total: exposes.numeric('reactive_energy_total', ea.STATE).withUnit('kVARh').withDescription('Reactive Energy Total'),
apparent_energy_total: exposes.numeric('apparent_energy_total', ea.STATE).withUnit('kVAh').withDescription('Apparent Energy Total'),
partial_active_energy_total: exposes.numeric('partial_active_energy_total', ea.STATE).withUnit('kWh').withDescription('Partial Active Energy Total'),
partial_reactive_energy_total: exposes.numeric('partial_reactive_energy_total', ea.STATE).withUnit('kVARh').withDescription('Partial Reactive Energy Total'),
partial_apparent_energy_total: exposes.numeric('partial_apparent_energy_total', ea.STATE).withUnit('kVAh').withDescription('Partial Apparent Energy Total'),
partial_active_energy_phase1: exposes.numeric('partial_active_energy_phase1', ea.STATE).withUnit('kWh').withDescription('Partial Active Energy Phase 1'),
partial_reactive_energy_phase1: exposes.numeric('partial_reactive_energy_phase1', ea.STATE).withUnit('kVARh').withDescription('Partial Reactive Energy Phase 1'),
partial_apparent_energy_phase1: exposes.numeric('partial_apparent_energy_phase1', ea.STATE).withUnit('kVAh').withDescription('Partial Apparent Energy Phase 1'),
active_energy_phase1: exposes.numeric('active_energy_phase1', ea.STATE).withUnit('kWh').withDescription('Active Energy Phase 1'),
reactive_energy_phase1: exposes.numeric('reactive_energy_phase1', ea.STATE).withUnit('kVARh').withDescription('Reactive Energy Phase 1'),
apparent_energy_phase1: exposes.numeric('apparent_energy_phase1', ea.STATE).withUnit('kVAh').withDescription('Apparent Energy Phase 1'),
partial_active_energy_phase2: exposes.numeric('partial_active_energy_phase2', ea.STATE).withUnit('kWh').withDescription('Partial Active Energy Phase 2'),
partial_reactive_energy_phase2: exposes.numeric('partial_reactive_energy_phase2', ea.STATE).withUnit('kVARh').withDescription('Partial Reactive Energy Phase 2'),
partial_apparent_energy_phase2: exposes.numeric('partial_apparent_energy_phase2', ea.STATE).withUnit('kVAh').withDescription('Partial Apparent Energy Phase 2'),
active_energy_phase2: exposes.numeric('active_energy_phase2', ea.STATE).withUnit('kWh').withDescription('Active Energy Phase 2'),
reactive_energy_phase2: exposes.numeric('reactive_energy_phase2', ea.STATE).withUnit('kVARh').withDescription('Reactive Energy Phase 2'),
apparent_energy_phase2: exposes.numeric('apparent_energy_phase2', ea.STATE).withUnit('kVAh').withDescription('Apparent Energy Phase 2'),
partial_active_energy_phase3: exposes.numeric('partial_active_energy_phase3', ea.STATE).withUnit('kWh').withDescription('Partial Active Energy Phase 3'),
partial_reactive_energy_phase3: exposes.numeric('partial_reactive_energy_phase3', ea.STATE).withUnit('kVARh').withDescription('Partial Reactive Energy Phase 3'),
partial_apparent_energy_phase3: exposes.numeric('partial_apparent_energy_phase3', ea.STATE).withUnit('kVAh').withDescription('Partial Apparent Energy Phase 3'),
active_energy_phase3: exposes.numeric('active_energy_phase3', ea.STATE).withUnit('kWh').withDescription('Active Energy Phase 3'),
reactive_energy_phase3: exposes.numeric('reactive_energy_phase3', ea.STATE).withUnit('kVARh').withDescription('Reactive Energy Phase 3'),
apparent_energy_phase3: exposes.numeric('apparent_energy_phase3', ea.STATE).withUnit('kVAh').withDescription('Apparent Energy Phase 3'),
reset_date_time: exposes.numeric('energy_reset_date_time', ea.STATE).withDescription('Energy Reset Date Time'),
reporting_period: exposes.numeric('reporting_period', ea.ALL).withUnit('s').withDescription('Energy Counters Reporting Period'),
frequency: exposes.numeric('frequency', ea.STATE).withUnit('Hz').withDescription('Frequency'),
active_power_total: exposes.numeric('active_power_total', ea.STATE).withUnit('kW').withDescription('Active Power Total'),
reactive_power_total: exposes.numeric('reactive_power_total', ea.STATE).withUnit('kVAR').withDescription('Reactive Power Total'),
apparent_power_total: exposes.numeric('apparent_power_total', ea.STATE).withUnit('kVA').withDescription('Apparent Power Total'),
voltage_phase1: exposes.numeric('voltage_phase1', ea.STATE).withUnit('V').withDescription('Voltage L1'),
active_power_phase1: exposes.numeric('active_power_phase1', ea.STATE).withUnit('kW').withDescription('Active Power Phase 1'),
reactive_power_phase1: exposes.numeric('reactive_power_phase1', ea.STATE).withUnit('kVAR').withDescription('Reactive Power Phase 1'),
apparent_power_phase1: exposes.numeric('apparent_power_phase1', ea.STATE).withUnit('kVA').withDescription('Apparent Power Phase 1'),
power_factor_phase1: exposes.numeric('power_factor_phase1', ea.STATE).withDescription('Power Factor Phase 1'),
active_power_phase2: exposes.numeric('active_power_phase2', ea.STATE).withUnit('kW').withDescription('Active Power Phase 2'),
reactive_power_phase2: exposes.numeric('reactive_power_phase2', ea.STATE).withUnit('kVAR').withDescription('Reactive Power Phase 2'),
apparent_power_phase2: exposes.numeric('apparent_power_phase2', ea.STATE).withUnit('kVA').withDescription('Apparent Power Phase 2'),
power_factor_phase2: exposes.numeric('power_factor_phase2', ea.STATE).withDescription('Power Factor Phase 2'),
active_power_phase3: exposes.numeric('active_power_phase3', ea.STATE).withUnit('kW').withDescription('Active Power Phase 3'),
reactive_power_phase3: exposes.numeric('reactive_power_phase3', ea.STATE).withUnit('kVAR').withDescription('Reactive Power Phase 3'),
apparent_power_phase3: exposes.numeric('apparent_power_phase3', ea.STATE).withUnit('kVA').withDescription('Apparent Power Phase 3'),
power_factor_phase3: exposes.numeric('power_factor_phase3', ea.STATE).withDescription('Power Factor Phase 3'),
active_power_demand_total: exposes.numeric('active_power_demand_total', ea.STATE).withUnit('kW').withDescription('Active Power Demand Total'),
reactive_power_demand_total: exposes.numeric('reactive_power_demand_total', ea.STATE).withUnit('kVAR').withDescription('Reactive Power Demand Total'),
apparent_power_demand_total: exposes.numeric('apparent_power_demand_total', ea.STATE).withUnit('kVA').withDescription('Apparent Power Demand Total'),
demand_interval_duration: exposes.numeric('demand_interval_duration', ea.ALL).withUnit('s').withDescription('Demand Interval Duration'),
demand_date_time: exposes.numeric('demand_date_time', ea.STATE).withDescription('Demand Date Time'),
active_power_demand_phase1: exposes.numeric('active_power_demand_phase1', ea.STATE).withUnit('kW').withDescription('Active Power Demand Phase 1'),
reactive_power_demand_phase1: exposes.numeric('reactive_power_demand_phase1', ea.STATE).withUnit('kVAR').withDescription('Reactive Power Demand Phase 1'),
apparent_power_demand_phase1: exposes.numeric('apparent_power_demand_phase1', ea.STATE).withUnit('kVA').withDescription('Apparent Power Demand Phase 1'),
demand_interval_minimal_voltage_phase1: exposes.numeric('demand_interval_minimal_voltage_phase1', ea.STATE).withUnit('V').withDescription('Demand Interval Min. Voltage L1'),
demand_interval_maximal_current_phase1: exposes.numeric('demand_interval_maximal_current_phase1', ea.STATE).withUnit('C').withDescription('Demand Interval Max. Current I1'),
active_power_demand_phase2: exposes.numeric('active_power_demand_phase2', ea.STATE).withUnit('kW').withDescription('Active Power Demand Phase 2'),
reactive_power_demand_phase2: exposes.numeric('reactive_power_demand_phase2', ea.STATE).withUnit('kVAR').withDescription('Reactive Power Demand Phase 2'),
apparent_power_demand_phase2: exposes.numeric('apparent_power_demand_phase2', ea.STATE).withUnit('kVA').withDescription('Apparent Power Demand Phase 2'),
demand_interval_minimal_voltage_phase2: exposes.numeric('demand_interval_minimal_voltage_phase2', ea.STATE).withUnit('V').withDescription('Demand Interval Min. Voltage L2'),
demand_interval_maximal_current_phase2: exposes.numeric('demand_interval_maximal_current_phase2', ea.STATE).withUnit('C').withDescription('Demand Interval Max. Current I2'),
active_power_demand_phase3: exposes.numeric('active_power_demand_phase3', ea.STATE).withUnit('kW').withDescription('Active Power Demand Phase 3'),
reactive_power_demand_phase3: exposes.numeric('reactive_power_demand_phase3', ea.STATE).withUnit('kVAR').withDescription('Reactive Power Demand Phase 3'),
apparent_power_demand_phase3: exposes.numeric('apparent_power_demand_phase3', ea.STATE).withUnit('kVA').withDescription('Apparent Power Demand Phase 3'),
demand_interval_minimal_voltage_phase3: exposes.numeric('demand_interval_minimal_voltage_phase3', ea.STATE).withUnit('V').withDescription('Demand Interval Min. Voltage L3'),
demand_interval_maximal_current_phase3: exposes.numeric('demand_interval_maximal_current_phase3', ea.STATE).withUnit('C').withDescription('Demand Interval Max. Current I3'),
current_sensor_multiplier: exposes.numeric('current_sensor_multiplier', ea.STATE).withDescription('Current Sensor Multiplier'),
meter_status: exposes.numeric('meter_status', ea.STATE).withDescription('Meter Status'),
diagnostic_register_1: exposes.numeric('diagnostic_register_1', ea.STATE).withDescription('Diagnostic Register 1'),
communication_quality: exposes.numeric('communication_quality', ea.STATE).withUnit('%').withDescription('Communication Quality'),
lqi_meter: exposes.numeric('lqi_meter', ea.STATE).withUnit('lqi')
.withDescription('LQI seen by the device').withValueMin(0).withValueMax(255),
rssi_meter: exposes.numeric('rssi_meter', ea.STATE).withUnit('dB')
.withDescription('RSSI seen by the device').withValueMin(-128).withValueMax(127),
};
function getFactor(key, endpoint, cluster) {
const multiplier = endpoint.getClusterAttributeValue(cluster, `${key}Multiplier`);
const divisor = endpoint.getClusterAttributeValue(cluster, `${key}Divisor`);
return multiplier && divisor ? multiplier / divisor : undefined;
}
async function readMeteringMultiplierDivisor(endpoint) {
await endpoint.read('seMetering', ['schneiderActiveEnergyMultiplier', 'schneiderActiveEnergyDivisor']);
await endpoint.read('seMetering', ['schneiderReactiveEnergyMultiplier', 'schneiderReactiveEnergyDivisor']);
await endpoint.read('seMetering', ['schneiderApparentEnergyMultiplier', 'schneiderApparentEnergyDivisor']);
}
async function readElectricalMeasurementMultiplierDivisor(endpoint) {
await endpoint.read('haElectricalMeasurement', ['acFrequencyMultiplier', 'acFrequencyDivisor']);
await endpoint.read('haElectricalMeasurement', ['powerMultiplier', 'powerDivisor']);
await endpoint.read('haElectricalMeasurement', ['acVoltageMultiplier', 'acVoltageDivisor']);
await endpoint.read('haElectricalMeasurement', ['acCurrentMultiplier', 'acCurrentDivisor']);
await endpoint.read('haElectricalMeasurement', ['acPowerMultiplier', 'acPowerDivisor']);
await endpoint.read('haElectricalMeasurement', ['schneiderCurrentSensorMultiplier']);
}
const tzLocal = {
meter_radio_power: {
key: ['meter_radio_power'],
convertSet: async (entity, key, value, meta) => {
await entity.write('genBasic', {schneiderMeterRadioPower: value}, {manufacturerCode: 0x105e});
return {state: {schneiderMeterRadioPower: value}};
},
convertGet: async (entity, key, meta) => {
await entity.read('genBasic', ['schneiderMeterRadioPower']);
},
},
reporting_period: {
key: ['reporting_period'],
convertSet: async (entity, key, value, meta) => {
await entity.write('seMetering', {schneiderEnergyCountersReportingPeriod: value}, {manufacturerCode: 0x105e});
return {state: {schneiderEnergyCountersReportingPeriod: value}};
},
convertGet: async (entity, key, meta) => {
await entity.read('seMetering', ['schneiderEnergyCountersReportingPeriod']);
},
},
demand_interval_duration: {
key: ['demand_interval_duration'],
convertSet: async (entity, key, value, meta) => {
await entity.write('haElectricalMeasurement', {schneiderDemandIntervalDuration: value}, {manufacturerCode: 0x105e});
return {state: {schneiderDemandIntervalDuration: value}};
},
convertGet: async (entity, key, meta) => {
await entity.read('haElectricalMeasurement', ['schneiderDemandIntervalDuration']);
},
},
}
const fzLocal = {
schneider_genBasic: {
cluster: 'genBasic',
type: ['attributeReport', 'readResponse'],
convert: (model, msg, publish, options, meta) => {
if (utils.hasAlreadyProcessedMessage(msg, model)) return;
const payload = {};
if (msg.data.hasOwnProperty('schneiderMeterRadioPower')) {
payload.meter_radio_power = msg.data['schneiderMeterRadioPower'];
}
return payload;
},
},
schneider_seMetering: {
cluster: 'seMetering',
type: ['attributeReport', 'readResponse'],
options: [
exposes.options.calibration('energy', 'percentual'), exposes.options.precision('energy'),
],
convert: (model, msg, publish, options, meta) => {
if (utils.hasAlreadyProcessedMessage(msg, model)) return;
const lookup = [
{key: 'ActiveEnergyTotal', name: 'active_energy_total', factor: 'ActiveEnergy'},
{key: 'ReactiveEnergyTotal', name: 'reactive_energy_total', factor: 'ReactiveEnergy'},
{key: 'ApparentEnergyTotal', name: 'apparent_energy_total', factor: 'ApparentEnergy'},
{key: 'PartialActiveEnergyTotal', name: 'partial_active_energy_total', factor: 'ActiveEnergy'},
{key: 'PartialReactiveEnergyTotal', name: 'partial_reactive_energy_total', factor: 'ReactiveEnergy'},
{key: 'PartialApparentEnergyTotal', name: 'partial_apparent_energy_total', factor: 'ApparentEnergy'},
{key: 'PartialActiveEnergyL1Phase', name: 'partial_active_energy_phase1', factor: 'ActiveEnergy'},
{key: 'PartialReactiveEnergyL1Phase', name: 'partial_reactive_energy_phase1', factor: 'ReactiveEnergy'},
{key: 'PartialApparentEnergyL1Phase', name: 'partial_apparent_energy_phase1', factor: 'ApparentEnergy'},
{key: 'ActiveEnergyL1Phase', name: 'active_energy_phase1', factor: 'ActiveEnergy'},
{key: 'ReactiveEnergyL1Phase', name: 'reactive_energy_phase1', factor: 'ReactiveEnergy'},
{key: 'ApparentEnergyL1Phase', name: 'apparent_energy_phase1', factor: 'ApparentEnergy'},
{key: 'PartialActiveEnergyL2Phase', name: 'partial_active_energy_phase2', factor: 'ActiveEnergy'},
{key: 'PartialReactiveEnergyL2Phase', name: 'partial_reactive_energy_phase2', factor: 'ReactiveEnergy'},
{key: 'PartialApparentEnergyL2Phase', name: 'partial_apparent_energy_phase2', factor: 'ApparentEnergy'},
{key: 'ActiveEnergyL2Phase', name: 'active_energy_phase2', factor: 'ActiveEnergy'},
{key: 'ReactiveEnergyL2Phase', name: 'reactive_energy_phase2', factor: 'ReactiveEnergy'},
{key: 'ApparentEnergyL2Phase', name: 'apparent_energy_phase2', factor: 'ApparentEnergy'},
{key: 'PartialActiveEnergyL3Phase', name: 'partial_active_energy_phase3', factor: 'ActiveEnergy'},
{key: 'PartialReactiveEnergyL3Phase', name: 'partial_reactive_energy_phase3', factor: 'ReactiveEnergy'},
{key: 'PartialApparentEnergyL3Phase', name: 'partial_apparent_energy_phase3', factor: 'ApparentEnergy'},
{key: 'ActiveEnergyL3Phase', name: 'active_energy_phase3', factor: 'ActiveEnergy'},
{key: 'ReactiveEnergyL3Phase', name: 'reactive_energy_phase3', factor: 'ReactiveEnergy'},
{key: 'ApparentEnergyL3Phase', name: 'apparent_energy_phase3', factor: 'ApparentEnergy'},
];
const payload = {};
for (const entry of lookup) {
if (msg.data.hasOwnProperty(`schneider${entry.key}`)) {
const factor = getFactor(`schneider${entry.factor}`, msg.endpoint, 'seMetering');
if (factor === undefined) continue;
const value = msg.data[`schneider${entry.key}`] * factor;
payload[entry.name] = utils.calibrateAndPrecisionRoundOptions(value, options, 'energy');}
}
if (msg.data.hasOwnProperty('schneiderEnergyResetDateTime')) {
payload.energy_reset_date_time = msg.data['schneiderEnergyResetDateTime'];
}
if (msg.data.hasOwnProperty('schneiderEnergyCountersReportingPeriod')) {
payload.reporting_period = msg.data['schneiderEnergyCountersReportingPeriod'];
}
return payload;
},
},
schneider_haElectricalMeasurement: {
cluster: 'haElectricalMeasurement',
type: ['attributeReport', 'readResponse'],
options: [
exposes.options.calibration('power', 'percentual'), exposes.options.precision('power'),
],
convert: (model, msg, publish, options, meta) => {
if (utils.hasAlreadyProcessedMessage(msg, model)) return;
const lookup = [
{key: 'acFrequency', name: 'frequency', factor: 'acFrequency', type: 'frequency'},
{key: 'totalActivePower', name: 'active_power_total', factor: 'power', type: 'power'},
{key: 'totalReactivePower', name: 'reactive_power_total', factor: 'power', type: 'power'},
{key: 'totalApparentPower', name: 'apparent_power_total', factor: 'power', type: 'power'},
{key: 'rmsVoltage', name: 'voltage_phase1', factor: 'acVoltage', type: 'voltage'},
{key: 'activePower', name: 'active_power_phase1', factor: 'acPower', type: 'power'},
{key: 'reactivePower', name: 'reactive_power_phase1', factor: 'acPower', type: 'power'},
{key: 'apparentPower', name: 'apparent_power_phase1', factor: 'acPower', type: 'power'},
{key: 'activePowerPhB', name: 'active_power_phase2', factor: 'acPower', type: 'power'},
{key: 'reactivePowerPhB', name: 'reactive_power_phase2', factor: 'acPower', type: 'power'},
{key: 'apparentPowerPhB', name: 'apparent_power_phase2', factor: 'acPower', type: 'power'},
{key: 'activePowerPhC', name: 'active_power_phase3', factor: 'acPower', type: 'power'},
{key: 'reactivePowerPhC', name: 'reactive_power_phase3', factor: 'acPower', type: 'power'},
{key: 'apparentPowerPhC', name: 'apparent_power_phase3', factor: 'acPower', type: 'power'},
{key: 'schneiderActivePowerDemandTotal', name: 'active_power_demand_total', factor: 'power', type: 'power'},
{key: 'schneiderReactivePowerDemandTotal', name: 'reactive_power_demand_total', factor: 'power', type: 'power'},
{key: 'schneiderApparentPowerDemandTotal', name: 'apparent_power_demand_total', factor: 'power', type: 'power'},
{key: 'schneiderActivePowerDemandPhase1', name: 'active_power_demand_phase1', factor: 'acPower', type: 'power'},
{key: 'schneiderReactivePowerDemandPhase1', name: 'reactive_power_demand_phase1', factor: 'acPower', type: 'power'},
{key: 'schneiderApparentPowerDemandPhase1', name: 'apparent_power_demand_phase1', factor: 'acPower', type: 'power'},
{key: 'schneiderDemandIntervalMinimalVoltageL1', name: 'demand_interval_minimal_voltage_phase1', factor: 'acVoltage', type: 'voltage'},
{key: 'schneiderDemandIntervalMaximalCurrentI1', name: 'demand_interval_maximal_current_phase1', factor: 'acCurrent', type: 'current'},
{key: 'schneiderActivePowerDemandPhase2', name: 'active_power_demand_phase2', factor: 'acPower', type: 'power'},
{key: 'schneiderReactivePowerDemandPhase2', name: 'reactive_power_demand_phase2', factor: 'acPower', type: 'power'},
{key: 'schneiderApparentPowerDemandPhase2', name: 'apparent_power_demand_phase2', factor: 'acPower', type: 'power'},
{key: 'schneiderDemandIntervalMinimalVoltageL2', name: 'demand_interval_minimal_voltage_phase2', factor: 'acVoltage', type: 'voltage'},
{key: 'schneiderDemandIntervalMaximalCurrentI2', name: 'demand_interval_maximal_current_phase2', factor: 'acCurrent', type: 'current'},
{key: 'schneiderActivePowerDemandPhase3', name: 'active_power_demand_phase3', factor: 'acPower', type: 'power'},
{key: 'schneiderReactivePowerDemandPhase3', name: 'reactive_power_demand_phase3', factor: 'acPower', type: 'power'},
{key: 'schneiderApparentPowerDemandPhase3', name: 'apparent_power_demand_phase3', factor: 'acPower', type: 'power'},
{key: 'schneiderDemandIntervalMinimalVoltageL3', name: 'demand_interval_minimal_voltage_phase3', factor: 'acVoltage', type: 'voltage'},
{key: 'schneiderDemandIntervalMaximalCurrentI3', name: 'demand_interval_maximal_current_phase3', factor: 'acCurrent', type: 'current'},
];
const payload = {};
for (const entry of lookup) {
if (msg.data.hasOwnProperty(entry.key)) {
const factor = getFactor(entry.factor, msg.endpoint, 'haElectricalMeasurement');
if (factor === undefined) continue;
const value = msg.data[entry.key] * factor;
if (entry.type === 'power') {
payload[entry.name] = utils.calibrateAndPrecisionRoundOptions(value, options, entry.type);
} else {
payload[entry.name] = value;
}
}
}
if (msg.data.hasOwnProperty('powerFactor')) {
payload.power_factor_phase1 = msg.data['powerFactor'];
}
if (msg.data.hasOwnProperty('powerFactorPhB')) {
payload.power_factor_phase2 = msg.data['powerFactorPhB'];
}
if (msg.data.hasOwnProperty('powerFactorPhC')) {
payload.power_factor_phase3 = msg.data['powerFactorPhC'];
}
if (msg.data.hasOwnProperty('schneiderCurrentSensorMultiplier')) {
payload.current_sensor_multiplier = msg.data['schneiderCurrentSensorMultiplier'];
}
if (msg.data.hasOwnProperty('schneiderDemandIntervalDuration')) {
payload.demand_interval_duration = msg.data['schneiderDemandIntervalDuration'];
}
if (msg.data.hasOwnProperty('schneiderDemandDateTime')) {
payload.demand_date_time = msg.data['schneiderDemandDateTime'];
}
return payload;
},
},
schneider_haDiagnostic: {
cluster: 'haDiagnostic',
type: ['attributeReport', 'readResponse'],
convert: (model, msg, publish, options, meta) => {
if (utils.hasAlreadyProcessedMessage(msg, model)) return;
const payload = {};
if (msg.data.hasOwnProperty('schneiderCommunicationQuality')) {
payload.communication_quality = msg.data['schneiderCommunicationQuality'];
}
if (msg.data.hasOwnProperty('schneiderDiagnosticRegister1')) {
payload.diagnostic_register_1 = msg.data['schneiderDiagnosticRegister1'];
}
if (msg.data.hasOwnProperty('schneiderMeterStatus')) {
payload.meter_status = msg.data['schneiderMeterStatus'];
}
if (msg.data.hasOwnProperty('lastMessageLqi')) {
payload.lqi_meter = msg.data['lastMessageLqi'];
}
if (msg.data.hasOwnProperty('lastMessageRssi')) {
payload.rssi_meter = msg.data['lastMessageRssi'];
}
return payload;
},
},
};
const definition = {
zigbeeModel: ['EM4300'],
model: 'EM4300',
vendor: 'Schneider Electric',
description: 'PowerLogic Wireless Energy Meter',
fromZigbee: [
fzLocal.schneider_genBasic,
fzLocal.schneider_seMetering,
fzLocal.schneider_haElectricalMeasurement,
fzLocal.schneider_haDiagnostic
],
toZigbee: [
tzLocal.meter_radio_power,
tzLocal.reporting_period,
tzLocal.demand_interval_duration
],
exposes: [
exposesLocal.meter_radio_power,
exposesLocal.active_energy_total,
exposesLocal.reactive_energy_total,
exposesLocal.apparent_energy_total,
exposesLocal.partial_active_energy_total,
exposesLocal.partial_reactive_energy_total,
exposesLocal.partial_apparent_energy_total,
exposesLocal.partial_active_energy_phase1,
exposesLocal.partial_reactive_energy_phase1,
exposesLocal.partial_apparent_energy_phase1,
exposesLocal.active_energy_phase1,
exposesLocal.reactive_energy_phase1,
exposesLocal.apparent_energy_phase1,
exposesLocal.partial_active_energy_phase2,
exposesLocal.partial_reactive_energy_phase2,
exposesLocal.partial_apparent_energy_phase2,
exposesLocal.active_energy_phase2,
exposesLocal.reactive_energy_phase2,
exposesLocal.apparent_energy_phase2,
exposesLocal.partial_active_energy_phase3,
exposesLocal.partial_reactive_energy_phase3,
exposesLocal.partial_apparent_energy_phase3,
exposesLocal.active_energy_phase3,
exposesLocal.reactive_energy_phase3,
exposesLocal.apparent_energy_phase3,
exposesLocal.reset_date_time,
exposesLocal.reporting_period,
exposesLocal.frequency,
exposesLocal.active_power_total,
exposesLocal.reactive_power_total,
exposesLocal.apparent_power_total,
exposesLocal.voltage_phase1,
exposesLocal.active_power_phase1,
exposesLocal.reactive_power_phase1,
exposesLocal.apparent_power_phase1,
exposesLocal.power_factor_phase1,
exposesLocal.active_power_phase2,
exposesLocal.reactive_power_phase2,
exposesLocal.apparent_power_phase2,
exposesLocal.power_factor_phase2,
exposesLocal.active_power_phase3,
exposesLocal.reactive_power_phase3,
exposesLocal.apparent_power_phase3,
exposesLocal.power_factor_phase3,
exposesLocal.active_power_demand_total,
exposesLocal.reactive_power_demand_total,
exposesLocal.apparent_power_demand_total,
exposesLocal.demand_interval_duration,
exposesLocal.demand_date_time,
exposesLocal.active_power_demand_phase1,
exposesLocal.reactive_power_demand_phase1,
exposesLocal.apparent_power_demand_phase1,
exposesLocal.demand_interval_minimal_voltage_phase1,
exposesLocal.demand_interval_maximal_current_phase1,
exposesLocal.active_power_demand_phase2,
exposesLocal.reactive_power_demand_phase2,
exposesLocal.apparent_power_demand_phase2,
exposesLocal.demand_interval_minimal_voltage_phase2,
exposesLocal.demand_interval_maximal_current_phase2,
exposesLocal.active_power_demand_phase3,
exposesLocal.reactive_power_demand_phase3,
exposesLocal.apparent_power_demand_phase3,
exposesLocal.demand_interval_minimal_voltage_phase3,
exposesLocal.demand_interval_maximal_current_phase3,
exposesLocal.current_sensor_multiplier,
exposesLocal.meter_status,
exposesLocal.diagnostic_register_1,
exposesLocal.communication_quality,
exposesLocal.lqi_meter,
exposesLocal.rssi_meter,
e.linkquality(),
],
configure: async (device, coordinatorEndpoint, logger) => {
const endpoint = device.getEndpoint(10);
const binds = ['genBasic', 'seMetering', 'haElectricalMeasurement', 'haDiagnostic'];
await reporting.bind(endpoint, coordinatorEndpoint, binds);
/*await configureReportingAttributes(endpoint, 'genBasic', attributes_basic);
await configureReportingAttributes(endpoint, 'seMetering', attributes_seMetering);
await configureReportingAttributes(endpoint, 'haElectricalMeasurement', attributes_haElectricalMeasurement);
await configureReportingAttributes(endpoint, 'haDiagnostic', attributes_haDiagnostic);*/
await readMeteringMultiplierDivisor(endpoint);
await readElectricalMeasurementMultiplierDivisor(endpoint);
await endpoint.write('seMetering', {schneiderEnergyCountersReportingPeriod: 10}, {manufacturerCode: 0x105e});
await endpoint.write('haElectricalMeasurement', {schneiderDemandIntervalDuration: 300}, {manufacturerCode: 0x105e});
},
};
module.exports = definition;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment