Last active
May 7, 2023 21:02
-
-
Save jonathandreyer/19a8f3e8f8990973f22984c0ec5c907e to your computer and use it in GitHub Desktop.
New device (Schneider Electric EM4302) for Zigbee2MQTT
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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