ESPHome  2024.4.1
selec_meter.cpp
Go to the documentation of this file.
1 #include "selec_meter.h"
3 #include "esphome/core/log.h"
4 
5 namespace esphome {
6 namespace selec_meter {
7 
8 static const char *const TAG = "selec_meter";
9 
10 static const uint8_t MODBUS_CMD_READ_IN_REGISTERS = 0x04;
11 static const uint8_t MODBUS_REGISTER_COUNT = 34; // 34 x 16-bit registers
12 
13 void SelecMeter::on_modbus_data(const std::vector<uint8_t> &data) {
14  if (data.size() < MODBUS_REGISTER_COUNT * 2) {
15  ESP_LOGW(TAG, "Invalid size for SelecMeter!");
16  return;
17  }
18 
19  auto selec_meter_get_float = [&](size_t i, float unit) -> float {
20  uint32_t temp = encode_uint32(data[i + 2], data[i + 3], data[i], data[i + 1]);
21 
22  float f;
23  memcpy(&f, &temp, sizeof(f));
24  return (f * unit);
25  };
26 
27  float total_active_energy = selec_meter_get_float(SELEC_TOTAL_ACTIVE_ENERGY * 2, NO_DEC_UNIT);
28  float import_active_energy = selec_meter_get_float(SELEC_IMPORT_ACTIVE_ENERGY * 2, NO_DEC_UNIT);
29  float export_active_energy = selec_meter_get_float(SELEC_EXPORT_ACTIVE_ENERGY * 2, NO_DEC_UNIT);
30  float total_reactive_energy = selec_meter_get_float(SELEC_TOTAL_REACTIVE_ENERGY * 2, NO_DEC_UNIT);
31  float import_reactive_energy = selec_meter_get_float(SELEC_IMPORT_REACTIVE_ENERGY * 2, NO_DEC_UNIT);
32  float export_reactive_energy = selec_meter_get_float(SELEC_EXPORT_REACTIVE_ENERGY * 2, NO_DEC_UNIT);
33  float apparent_energy = selec_meter_get_float(SELEC_APPARENT_ENERGY * 2, NO_DEC_UNIT);
34  float active_power = selec_meter_get_float(SELEC_ACTIVE_POWER * 2, MULTIPLY_THOUSAND_UNIT);
35  float reactive_power = selec_meter_get_float(SELEC_REACTIVE_POWER * 2, MULTIPLY_THOUSAND_UNIT);
36  float apparent_power = selec_meter_get_float(SELEC_APPARENT_POWER * 2, MULTIPLY_THOUSAND_UNIT);
37  float voltage = selec_meter_get_float(SELEC_VOLTAGE * 2, NO_DEC_UNIT);
38  float current = selec_meter_get_float(SELEC_CURRENT * 2, NO_DEC_UNIT);
39  float power_factor = selec_meter_get_float(SELEC_POWER_FACTOR * 2, NO_DEC_UNIT);
40  float frequency = selec_meter_get_float(SELEC_FREQUENCY * 2, NO_DEC_UNIT);
41  float maximum_demand_active_power =
42  selec_meter_get_float(SELEC_MAXIMUM_DEMAND_ACTIVE_POWER * 2, MULTIPLY_THOUSAND_UNIT);
43  float maximum_demand_reactive_power =
44  selec_meter_get_float(SELEC_MAXIMUM_DEMAND_REACTIVE_POWER * 2, MULTIPLY_THOUSAND_UNIT);
45  float maximum_demand_apparent_power =
46  selec_meter_get_float(SELEC_MAXIMUM_DEMAND_APPARENT_POWER * 2, MULTIPLY_THOUSAND_UNIT);
47 
48  if (this->total_active_energy_sensor_ != nullptr)
49  this->total_active_energy_sensor_->publish_state(total_active_energy);
50  if (this->import_active_energy_sensor_ != nullptr)
51  this->import_active_energy_sensor_->publish_state(import_active_energy);
52  if (this->export_active_energy_sensor_ != nullptr)
53  this->export_active_energy_sensor_->publish_state(export_active_energy);
54  if (this->total_reactive_energy_sensor_ != nullptr)
55  this->total_reactive_energy_sensor_->publish_state(total_reactive_energy);
56  if (this->import_reactive_energy_sensor_ != nullptr)
57  this->import_reactive_energy_sensor_->publish_state(import_reactive_energy);
58  if (this->export_reactive_energy_sensor_ != nullptr)
59  this->export_reactive_energy_sensor_->publish_state(export_reactive_energy);
60  if (this->apparent_energy_sensor_ != nullptr)
61  this->apparent_energy_sensor_->publish_state(apparent_energy);
62  if (this->active_power_sensor_ != nullptr)
63  this->active_power_sensor_->publish_state(active_power);
64  if (this->reactive_power_sensor_ != nullptr)
65  this->reactive_power_sensor_->publish_state(reactive_power);
66  if (this->apparent_power_sensor_ != nullptr)
67  this->apparent_power_sensor_->publish_state(apparent_power);
68  if (this->voltage_sensor_ != nullptr)
69  this->voltage_sensor_->publish_state(voltage);
70  if (this->current_sensor_ != nullptr)
71  this->current_sensor_->publish_state(current);
72  if (this->power_factor_sensor_ != nullptr)
73  this->power_factor_sensor_->publish_state(power_factor);
74  if (this->frequency_sensor_ != nullptr)
75  this->frequency_sensor_->publish_state(frequency);
76  if (this->maximum_demand_active_power_sensor_ != nullptr)
77  this->maximum_demand_active_power_sensor_->publish_state(maximum_demand_active_power);
78  if (this->maximum_demand_reactive_power_sensor_ != nullptr)
79  this->maximum_demand_reactive_power_sensor_->publish_state(maximum_demand_reactive_power);
80  if (this->maximum_demand_apparent_power_sensor_ != nullptr)
81  this->maximum_demand_apparent_power_sensor_->publish_state(maximum_demand_apparent_power);
82 }
83 
84 void SelecMeter::update() { this->send(MODBUS_CMD_READ_IN_REGISTERS, 0, MODBUS_REGISTER_COUNT); }
86  ESP_LOGCONFIG(TAG, "SELEC Meter:");
87  ESP_LOGCONFIG(TAG, " Address: 0x%02X", this->address_);
88  LOG_SENSOR(" ", "Total Active Energy", this->total_active_energy_sensor_);
89  LOG_SENSOR(" ", "Import Active Energy", this->import_active_energy_sensor_);
90  LOG_SENSOR(" ", "Export Active Energy", this->export_active_energy_sensor_);
91  LOG_SENSOR(" ", "Total Reactive Energy", this->total_reactive_energy_sensor_);
92  LOG_SENSOR(" ", "Import Reactive Energy", this->import_reactive_energy_sensor_);
93  LOG_SENSOR(" ", "Export Reactive Energy", this->export_reactive_energy_sensor_);
94  LOG_SENSOR(" ", "Apparent Energy", this->apparent_energy_sensor_);
95  LOG_SENSOR(" ", "Active Power", this->active_power_sensor_);
96  LOG_SENSOR(" ", "Reactive Power", this->reactive_power_sensor_);
97  LOG_SENSOR(" ", "Apparent Power", this->apparent_power_sensor_);
98  LOG_SENSOR(" ", "Voltage", this->voltage_sensor_);
99  LOG_SENSOR(" ", "Current", this->current_sensor_);
100  LOG_SENSOR(" ", "Power Factor", this->power_factor_sensor_);
101  LOG_SENSOR(" ", "Frequency", this->frequency_sensor_);
102  LOG_SENSOR(" ", "Maximum Demand Active Power", this->maximum_demand_active_power_sensor_);
103  LOG_SENSOR(" ", "Maximum Demand Reactive Power", this->maximum_demand_reactive_power_sensor_);
104  LOG_SENSOR(" ", "Maximum Demand Apparent Power", this->maximum_demand_apparent_power_sensor_);
105 }
106 
107 } // namespace selec_meter
108 } // namespace esphome
constexpr uint32_t encode_uint32(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t byte4)
Encode a 32-bit value given four bytes in most to least significant byte order.
Definition: helpers.h:186
void on_modbus_data(const std::vector< uint8_t > &data) override
Definition: selec_meter.cpp:13
virtual void update()=0
uint16_le_t frequency
Definition: bl0942.h:21
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
void send(uint8_t function, uint16_t start_address, uint16_t number_of_entities, uint8_t payload_len=0, const uint8_t *payload=nullptr)
Definition: modbus.h:53