1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-14 17:22:20 +01:00

Add support for SDMXXX energy meters (#1260)

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
polyfaces
2021-05-31 12:05:49 +08:00
committed by GitHub
parent 9a2cf05c5f
commit bb759d52c8
12 changed files with 525 additions and 2 deletions

View File

View File

@@ -0,0 +1,106 @@
#include "sdm_meter.h"
#include "sdm_meter_registers.h"
#include "esphome/core/log.h"
namespace esphome {
namespace sdm_meter {
static const char *TAG = "sdm_meter";
static const uint8_t MODBUS_CMD_READ_IN_REGISTERS = 0x04;
static const uint8_t MODBUS_REGISTER_COUNT = 80; // 74 x 16-bit registers
void SDMMeter::on_modbus_data(const std::vector<uint8_t> &data) {
if (data.size() < MODBUS_REGISTER_COUNT * 2) {
ESP_LOGW(TAG, "Invalid size for SDMMeter!");
return;
}
auto sdm_meter_get_float = [&](size_t i) -> float {
uint32_t temp = encode_uint32(data[i], data[i + 1], data[i + 2], data[i + 3]);
float f;
memcpy(&f, &temp, sizeof(f));
return f;
};
for (uint8_t i = 0; i < 3; i++) {
auto phase = this->phases_[i];
if (!phase.setup)
continue;
float voltage = sdm_meter_get_float(SDM_PHASE_1_VOLTAGE * 2 + (i * 4));
float current = sdm_meter_get_float(SDM_PHASE_1_CURRENT * 2 + (i * 4));
float active_power = sdm_meter_get_float(SDM_PHASE_1_ACTIVE_POWER * 2 + (i * 4));
float apparent_power = sdm_meter_get_float(SDM_PHASE_1_APPARENT_POWER * 2 + (i * 4));
float reactive_power = sdm_meter_get_float(SDM_PHASE_1_REACTIVE_POWER * 2 + (i * 4));
float power_factor = sdm_meter_get_float(SDM_PHASE_1_POWER_FACTOR * 2 + (i * 4));
float phase_angle = sdm_meter_get_float(SDM_PHASE_1_ANGLE * 2 + (i * 4));
ESP_LOGD(
TAG,
"SDMMeter Phase %c: V=%.3f V, I=%.3f A, Active P=%.3f W, Apparent P=%.3f VA, Reactive P=%.3f VAR, PF=%.3f, "
"PA=%.3f °",
i + 'A', voltage, current, active_power, apparent_power, reactive_power, power_factor, phase_angle);
if (phase.voltage_sensor_ != nullptr)
phase.voltage_sensor_->publish_state(voltage);
if (phase.current_sensor_ != nullptr)
phase.current_sensor_->publish_state(current);
if (phase.active_power_sensor_ != nullptr)
phase.active_power_sensor_->publish_state(active_power);
if (phase.apparent_power_sensor_ != nullptr)
phase.apparent_power_sensor_->publish_state(apparent_power);
if (phase.reactive_power_sensor_ != nullptr)
phase.reactive_power_sensor_->publish_state(reactive_power);
if (phase.power_factor_sensor_ != nullptr)
phase.power_factor_sensor_->publish_state(power_factor);
if (phase.phase_angle_sensor_ != nullptr)
phase.phase_angle_sensor_->publish_state(phase_angle);
}
float frequency = sdm_meter_get_float(SDM_FREQUENCY * 2);
float import_active_energy = sdm_meter_get_float(SDM_IMPORT_ACTIVE_ENERGY * 2);
float export_active_energy = sdm_meter_get_float(SDM_EXPORT_ACTIVE_ENERGY * 2);
float import_reactive_energy = sdm_meter_get_float(SDM_IMPORT_REACTIVE_ENERGY * 2);
float export_reactive_energy = sdm_meter_get_float(SDM_EXPORT_REACTIVE_ENERGY * 2);
ESP_LOGD(TAG, "SDMMeter: F=%.3f Hz, Im.A.E=%.3f Wh, Ex.A.E=%.3f Wh, Im.R.E=%.3f VARh, Ex.R.E=%.3f VARh", frequency,
import_active_energy, export_active_energy, import_reactive_energy, export_reactive_energy);
if (this->frequency_sensor_ != nullptr)
this->frequency_sensor_->publish_state(frequency);
if (this->import_active_energy_sensor_ != nullptr)
this->import_active_energy_sensor_->publish_state(import_active_energy);
if (this->export_active_energy_sensor_ != nullptr)
this->export_active_energy_sensor_->publish_state(export_active_energy);
if (this->import_reactive_energy_sensor_ != nullptr)
this->import_reactive_energy_sensor_->publish_state(import_reactive_energy);
if (this->export_reactive_energy_sensor_ != nullptr)
this->export_reactive_energy_sensor_->publish_state(export_reactive_energy);
}
void SDMMeter::update() { this->send(MODBUS_CMD_READ_IN_REGISTERS, 0, MODBUS_REGISTER_COUNT); }
void SDMMeter::dump_config() {
ESP_LOGCONFIG(TAG, "SDM Meter:");
ESP_LOGCONFIG(TAG, " Address: 0x%02X", this->address_);
for (uint8_t i = 0; i < 3; i++) {
auto phase = this->phases_[i];
if (!phase.setup)
continue;
ESP_LOGCONFIG(TAG, " Phase %c", i + 'A');
LOG_SENSOR(" ", "Voltage", phase.voltage_sensor_);
LOG_SENSOR(" ", "Current", phase.current_sensor_);
LOG_SENSOR(" ", "Active Power", phase.active_power_sensor_);
LOG_SENSOR(" ", "Apparent Power", phase.apparent_power_sensor_);
LOG_SENSOR(" ", "Reactive Power", phase.reactive_power_sensor_);
LOG_SENSOR(" ", "Power Factor", phase.power_factor_sensor_);
LOG_SENSOR(" ", "Phase Angle", phase.phase_angle_sensor_);
}
LOG_SENSOR(" ", "Frequency", this->frequency_sensor_);
LOG_SENSOR(" ", "Import Active Energy", this->import_active_energy_sensor_);
LOG_SENSOR(" ", "Export Active Energy", this->export_active_energy_sensor_);
LOG_SENSOR(" ", "Import Reactive Energy", this->import_reactive_energy_sensor_);
LOG_SENSOR(" ", "Export Reactive Energy", this->export_reactive_energy_sensor_);
}
} // namespace sdm_meter
} // namespace esphome

View File

@@ -0,0 +1,79 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/modbus/modbus.h"
namespace esphome {
namespace sdm_meter {
class SDMMeter : public PollingComponent, public modbus::ModbusDevice {
public:
void set_voltage_sensor(uint8_t phase, sensor::Sensor *voltage_sensor) {
this->phases_[phase].setup = true;
this->phases_[phase].voltage_sensor_ = voltage_sensor;
}
void set_current_sensor(uint8_t phase, sensor::Sensor *current_sensor) {
this->phases_[phase].setup = true;
this->phases_[phase].current_sensor_ = current_sensor;
}
void set_active_power_sensor(uint8_t phase, sensor::Sensor *active_power_sensor) {
this->phases_[phase].setup = true;
this->phases_[phase].active_power_sensor_ = active_power_sensor;
}
void set_apparent_power_sensor(uint8_t phase, sensor::Sensor *apparent_power_sensor) {
this->phases_[phase].setup = true;
this->phases_[phase].apparent_power_sensor_ = apparent_power_sensor;
}
void set_reactive_power_sensor(uint8_t phase, sensor::Sensor *reactive_power_sensor) {
this->phases_[phase].setup = true;
this->phases_[phase].reactive_power_sensor_ = reactive_power_sensor;
}
void set_power_factor_sensor(uint8_t phase, sensor::Sensor *power_factor_sensor) {
this->phases_[phase].setup = true;
this->phases_[phase].power_factor_sensor_ = power_factor_sensor;
}
void set_phase_angle_sensor(uint8_t phase, sensor::Sensor *phase_angle_sensor) {
this->phases_[phase].setup = true;
this->phases_[phase].phase_angle_sensor_ = phase_angle_sensor;
}
void set_frequency_sensor(sensor::Sensor *frequency_sensor) { this->frequency_sensor_ = frequency_sensor; }
void set_import_active_energy_sensor(sensor::Sensor *import_active_energy_sensor) {
this->import_active_energy_sensor_ = import_active_energy_sensor;
}
void set_export_active_energy_sensor(sensor::Sensor *export_active_energy_sensor) {
this->export_active_energy_sensor_ = export_active_energy_sensor;
}
void set_import_reactive_energy_sensor(sensor::Sensor *import_reactive_energy_sensor) {
this->import_reactive_energy_sensor_ = import_reactive_energy_sensor;
}
void set_export_reactive_energy_sensor(sensor::Sensor *export_reactive_energy_sensor) {
this->export_reactive_energy_sensor_ = export_reactive_energy_sensor;
}
void update() override;
void on_modbus_data(const std::vector<uint8_t> &data) override;
void dump_config() override;
protected:
struct SDMPhase {
bool setup{false};
sensor::Sensor *voltage_sensor_{nullptr};
sensor::Sensor *current_sensor_{nullptr};
sensor::Sensor *active_power_sensor_{nullptr};
sensor::Sensor *apparent_power_sensor_{nullptr};
sensor::Sensor *reactive_power_sensor_{nullptr};
sensor::Sensor *power_factor_sensor_{nullptr};
sensor::Sensor *phase_angle_sensor_{nullptr};
} phases_[3];
sensor::Sensor *frequency_sensor_{nullptr};
sensor::Sensor *import_active_energy_sensor_{nullptr};
sensor::Sensor *export_active_energy_sensor_{nullptr};
sensor::Sensor *import_reactive_energy_sensor_{nullptr};
sensor::Sensor *export_reactive_energy_sensor_{nullptr};
};
} // namespace sdm_meter
} // namespace esphome

View File

@@ -0,0 +1,114 @@
#pragma once
namespace esphome {
namespace sdm_meter {
/* PHASE STATUS REGISTERS */
static const uint16_t SDM_PHASE_1_VOLTAGE = 0x0000;
static const uint16_t SDM_PHASE_2_VOLTAGE = 0x0002;
static const uint16_t SDM_PHASE_3_VOLTAGE = 0x0004;
static const uint16_t SDM_PHASE_1_CURRENT = 0x0006;
static const uint16_t SDM_PHASE_2_CURRENT = 0x0008;
static const uint16_t SDM_PHASE_3_CURRENT = 0x000A;
static const uint16_t SDM_PHASE_1_ACTIVE_POWER = 0x000C;
static const uint16_t SDM_PHASE_2_ACTIVE_POWER = 0x000E;
static const uint16_t SDM_PHASE_3_ACTIVE_POWER = 0x0010;
static const uint16_t SDM_PHASE_1_APPARENT_POWER = 0x0012;
static const uint16_t SDM_PHASE_2_APPARENT_POWER = 0x0014;
static const uint16_t SDM_PHASE_3_APPARENT_POWER = 0x0016;
static const uint16_t SDM_PHASE_1_REACTIVE_POWER = 0x0018;
static const uint16_t SDM_PHASE_2_REACTIVE_POWER = 0x001A;
static const uint16_t SDM_PHASE_3_REACTIVE_POWER = 0x001C;
static const uint16_t SDM_PHASE_1_POWER_FACTOR = 0x001E;
static const uint16_t SDM_PHASE_2_POWER_FACTOR = 0x0020;
static const uint16_t SDM_PHASE_3_POWER_FACTOR = 0x0022;
static const uint16_t SDM_PHASE_1_ANGLE = 0x0024;
static const uint16_t SDM_PHASE_2_ANGLE = 0x0026;
static const uint16_t SDM_PHASE_3_ANGLE = 0x0028;
static const uint16_t SDM_AVERAGE_L_TO_N_VOLTS = 0x002A;
static const uint16_t SDM_AVERAGE_LINE_CURRENT = 0x002E;
static const uint16_t SDM_SUM_LINE_CURRENT = 0x0030;
static const uint16_t SDM_TOTAL_SYSTEM_POWER = 0x0034;
static const uint16_t SDM_TOTAL_SYSTEM_APPARENT_POWER = 0x0038;
static const uint16_t SDM_TOTAL_SYSTEM_REACTIVE_POWER = 0x003C;
static const uint16_t SDM_TOTAL_SYSTEM_POWER_FACTOR = 0x003E;
static const uint16_t SDM_TOTAL_SYSTEM_PHASE_ANGLE = 0x0042;
static const uint16_t SDM_FREQUENCY = 0x0046;
static const uint16_t SDM_IMPORT_ACTIVE_ENERGY = 0x0048;
static const uint16_t SDM_EXPORT_ACTIVE_ENERGY = 0x004A;
static const uint16_t SDM_IMPORT_REACTIVE_ENERGY = 0x004C;
static const uint16_t SDM_EXPORT_REACTIVE_ENERGY = 0x004E;
static const uint16_t SDM_VAH_SINCE_LAST_RESET = 0x0050;
static const uint16_t SDM_AH_SINCE_LAST_RESET = 0x0052;
static const uint16_t SDM_TOTAL_SYSTEM_POWER_DEMAND = 0x0054;
static const uint16_t SDM_MAXIMUM_TOTAL_SYSTEM_POWER_DEMAND = 0x0056;
static const uint16_t SDM_CURRENT_SYSTEM_POSITIVE_POWER_DEMAND = 0x0058;
static const uint16_t SDM_MAXIMUM_SYSTEM_POSITIVE_POWER_DEMAND = 0x005A;
static const uint16_t SDM_CURRENT_SYSTEM_REVERSE_POWER_DEMAND = 0x005C;
static const uint16_t SDM_MAXIMUM_SYSTEM_REVERSE_POWER_DEMAND = 0x005E;
static const uint16_t SDM_TOTAL_SYSTEM_VA_DEMAND = 0x0064;
static const uint16_t SDM_MAXIMUM_TOTAL_SYSTEM_VA_DEMAND = 0x0066;
static const uint16_t SDM_NEUTRAL_CURRENT_DEMAND = 0x0068;
static const uint16_t SDM_MAXIMUM_NEUTRAL_CURRENT = 0x006A;
static const uint16_t SDM_LINE_1_TO_LINE_2_VOLTS = 0x00C8;
static const uint16_t SDM_LINE_2_TO_LINE_3_VOLTS = 0x00CA;
static const uint16_t SDM_LINE_3_TO_LINE_1_VOLTS = 0x00CC;
static const uint16_t SDM_AVERAGE_LINE_TO_LINE_VOLTS = 0x00CE;
static const uint16_t SDM_NEUTRAL_CURRENT = 0x00E0;
static const uint16_t SDM_PHASE_1_LN_VOLTS_THD = 0x00EA;
static const uint16_t SDM_PHASE_2_LN_VOLTS_THD = 0x00EC;
static const uint16_t SDM_PHASE_3_LN_VOLTS_THD = 0x00EE;
static const uint16_t SDM_PHASE_1_CURRENT_THD = 0x00F0;
static const uint16_t SDM_PHASE_2_CURRENT_THD = 0x00F2;
static const uint16_t SDM_PHASE_3_CURRENT_THD = 0x00F4;
static const uint16_t SDM_AVERAGE_LINE_TO_NEUTRAL_VOLTS_THD = 0x00F8;
static const uint16_t SDM_AVERAGE_LINE_CURRENT_THD = 0x00FA;
static const uint16_t SDM_TOTAL_SYSTEM_POWER_FACTOR_INV = 0x00FE;
static const uint16_t SDM_PHASE_1_CURRENT_DEMAND = 0x0102;
static const uint16_t SDM_PHASE_2_CURRENT_DEMAND = 0x0104;
static const uint16_t SDM_PHASE_3_CURRENT_DEMAND = 0x0106;
static const uint16_t SDM_MAXIMUM_PHASE_1_CURRENT_DEMAND = 0x0108;
static const uint16_t SDM_MAXIMUM_PHASE_2_CURRENT_DEMAND = 0x010A;
static const uint16_t SDM_MAXIMUM_PHASE_3_CURRENT_DEMAND = 0x010C;
static const uint16_t SDM_LINE_1_TO_LINE_2_VOLTS_THD = 0x014E;
static const uint16_t SDM_LINE_2_TO_LINE_3_VOLTS_THD = 0x0150;
static const uint16_t SDM_LINE_3_TO_LINE_1_VOLTS_THD = 0x0152;
static const uint16_t SDM_AVERAGE_LINE_TO_LINE_VOLTS_THD = 0x0154;
static const uint16_t SDM_TOTAL_ACTIVE_ENERGY = 0x0156;
static const uint16_t SDM_TOTAL_REACTIVE_ENERGY = 0x0158;
static const uint16_t SDM_L1_IMPORT_ACTIVE_ENERGY = 0x015A;
static const uint16_t SDM_L2_IMPORT_ACTIVE_ENERGY = 0x015C;
static const uint16_t SDM_L3_IMPORT_ACTIVE_ENERGY = 0x015E;
static const uint16_t SDM_L1_EXPORT_ACTIVE_ENERGY = 0x0160;
static const uint16_t SDM_L2_EXPORT_ACTIVE_ENERGY = 0x0162;
static const uint16_t SDM_L3_EXPORT_ACTIVE_ENERGY = 0x0164;
static const uint16_t SDM_L1_TOTAL_ACTIVE_ENERGY = 0x0166;
static const uint16_t SDM_L2_TOTAL_ACTIVE_ENERGY = 0x0168;
static const uint16_t SDM_L3_TOTAL_ACTIVE_ENERGY = 0x016a;
static const uint16_t SDM_L1_IMPORT_REACTIVE_ENERGY = 0x016C;
static const uint16_t SDM_L2_IMPORT_REACTIVE_ENERGY = 0x016E;
static const uint16_t SDM_L3_IMPORT_REACTIVE_ENERGY = 0x0170;
static const uint16_t SDM_L1_EXPORT_REACTIVE_ENERGY = 0x0172;
static const uint16_t SDM_L2_EXPORT_REACTIVE_ENERGY = 0x0174;
static const uint16_t SDM_L3_EXPORT_REACTIVE_ENERGY = 0x0176;
static const uint16_t SDM_L1_TOTAL_REACTIVE_ENERGY = 0x0178;
static const uint16_t SDM_L2_TOTAL_REACTIVE_ENERGY = 0x017A;
static const uint16_t SDM_L3_TOTAL_REACTIVE_ENERGY = 0x017C;
static const uint16_t SDM_CURRENT_RESETTABLE_TOTAL_ACTIVE_ENERGY = 0x0180;
static const uint16_t SDM_CURRENT_RESETTABLE_TOTAL_REACTIVE_ENERGY = 0x0182;
static const uint16_t SDM_CURRENT_RESETTABLE_IMPORT_ENERGY = 0x0184;
static const uint16_t SDM_CURRENT_RESETTABLE_EXPORT_ENERGY = 0x0186;
static const uint16_t SDM_IMPORT_POWER = 0x0500;
static const uint16_t SDM_EXPORT_POWER = 0x0502;
} // namespace sdm_meter
} // namespace esphome

View File

@@ -0,0 +1,131 @@
from esphome.components.atm90e32.sensor import CONF_PHASE_A, CONF_PHASE_B, CONF_PHASE_C
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor, modbus
from esphome.const import (
CONF_ACTIVE_POWER,
CONF_APPARENT_POWER,
CONF_CURRENT,
CONF_EXPORT_ACTIVE_ENERGY,
CONF_EXPORT_REACTIVE_ENERGY,
CONF_FREQUENCY,
CONF_ID,
CONF_IMPORT_ACTIVE_ENERGY,
CONF_IMPORT_REACTIVE_ENERGY,
CONF_PHASE_ANGLE,
CONF_POWER_FACTOR,
CONF_REACTIVE_POWER,
CONF_VOLTAGE,
DEVICE_CLASS_CURRENT,
DEVICE_CLASS_ENERGY,
DEVICE_CLASS_POWER,
DEVICE_CLASS_POWER_FACTOR,
DEVICE_CLASS_VOLTAGE,
ICON_CURRENT_AC,
ICON_EMPTY,
ICON_FLASH,
UNIT_AMPERE,
UNIT_DEGREES,
UNIT_EMPTY,
UNIT_HERTZ,
UNIT_VOLT,
UNIT_VOLT_AMPS,
UNIT_VOLT_AMPS_REACTIVE,
UNIT_VOLT_AMPS_REACTIVE_HOURS,
UNIT_WATT,
UNIT_WATT_HOURS,
)
AUTO_LOAD = ["modbus"]
CODEOWNERS = ["@polyfaces", "@jesserockz"]
sdm_meter_ns = cg.esphome_ns.namespace("sdm_meter")
SDMMeter = sdm_meter_ns.class_("SDMMeter", cg.PollingComponent, modbus.ModbusDevice)
PHASE_SENSORS = {
CONF_VOLTAGE: sensor.sensor_schema(UNIT_VOLT, ICON_EMPTY, 2, DEVICE_CLASS_VOLTAGE),
CONF_CURRENT: sensor.sensor_schema(
UNIT_AMPERE, ICON_EMPTY, 3, DEVICE_CLASS_CURRENT
),
CONF_ACTIVE_POWER: sensor.sensor_schema(
UNIT_WATT, ICON_EMPTY, 2, DEVICE_CLASS_POWER
),
CONF_APPARENT_POWER: sensor.sensor_schema(
UNIT_VOLT_AMPS, ICON_EMPTY, 2, DEVICE_CLASS_POWER
),
CONF_REACTIVE_POWER: sensor.sensor_schema(
UNIT_VOLT_AMPS_REACTIVE, ICON_EMPTY, 2, DEVICE_CLASS_POWER
),
CONF_POWER_FACTOR: sensor.sensor_schema(
UNIT_EMPTY, ICON_EMPTY, 3, DEVICE_CLASS_POWER_FACTOR
),
CONF_PHASE_ANGLE: sensor.sensor_schema(UNIT_DEGREES, ICON_FLASH, 3),
}
PHASE_SCHEMA = cv.Schema(
{cv.Optional(sensor): schema for sensor, schema in PHASE_SENSORS.items()}
)
CONFIG_SCHEMA = (
cv.Schema(
{
cv.GenerateID(): cv.declare_id(SDMMeter),
cv.Optional(CONF_PHASE_A): PHASE_SCHEMA,
cv.Optional(CONF_PHASE_B): PHASE_SCHEMA,
cv.Optional(CONF_PHASE_C): PHASE_SCHEMA,
cv.Optional(CONF_FREQUENCY): sensor.sensor_schema(
UNIT_HERTZ, ICON_CURRENT_AC, 3
),
cv.Optional(CONF_IMPORT_ACTIVE_ENERGY): sensor.sensor_schema(
UNIT_WATT_HOURS, ICON_EMPTY, 2, DEVICE_CLASS_ENERGY
),
cv.Optional(CONF_EXPORT_ACTIVE_ENERGY): sensor.sensor_schema(
UNIT_WATT_HOURS, ICON_EMPTY, 2, DEVICE_CLASS_ENERGY
),
cv.Optional(CONF_IMPORT_REACTIVE_ENERGY): sensor.sensor_schema(
UNIT_VOLT_AMPS_REACTIVE_HOURS, ICON_EMPTY, 2, DEVICE_CLASS_ENERGY
),
cv.Optional(CONF_EXPORT_REACTIVE_ENERGY): sensor.sensor_schema(
UNIT_VOLT_AMPS_REACTIVE_HOURS, ICON_EMPTY, 2, DEVICE_CLASS_ENERGY
),
}
)
.extend(cv.polling_component_schema("10s"))
.extend(modbus.modbus_device_schema(0x01))
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await modbus.register_modbus_device(var, config)
if CONF_FREQUENCY in config:
sens = await sensor.new_sensor(config[CONF_FREQUENCY])
cg.add(var.set_frequency_sensor(sens))
if CONF_IMPORT_ACTIVE_ENERGY in config:
sens = await sensor.new_sensor(config[CONF_IMPORT_ACTIVE_ENERGY])
cg.add(var.set_import_active_energy_sensor(sens))
if CONF_EXPORT_ACTIVE_ENERGY in config:
sens = await sensor.new_sensor(config[CONF_EXPORT_ACTIVE_ENERGY])
cg.add(var.set_export_active_energy_sensor(sens))
if CONF_IMPORT_REACTIVE_ENERGY in config:
sens = await sensor.new_sensor(config[CONF_IMPORT_REACTIVE_ENERGY])
cg.add(var.set_import_reactive_energy_sensor(sens))
if CONF_EXPORT_REACTIVE_ENERGY in config:
sens = await sensor.new_sensor(config[CONF_EXPORT_REACTIVE_ENERGY])
cg.add(var.set_export_reactive_energy_sensor(sens))
for i, phase in enumerate([CONF_PHASE_A, CONF_PHASE_B, CONF_PHASE_C]):
if phase not in config:
continue
phase_config = config[phase]
for sensor_type in PHASE_SENSORS:
if sensor_type in phase_config:
sens = await sensor.new_sensor(phase_config[sensor_type])
cg.add(getattr(var, f"set_{sensor_type}_sensor")(i, sens))