ESPHome 2026.10.0-dev
Loading...
Searching...
No Matches
havells_solar.cpp
Go to the documentation of this file.
1#include "havells_solar.h"
3#include "esphome/core/log.h"
4
6
7namespace helpers = modbus::helpers;
8
9static const char *const TAG = "havells_solar";
10
11static const uint8_t MODBUS_REGISTER_COUNT = 48; // 48 x 16-bit registers
12
13void HavellsSolar::on_read_holding_registers(uint16_t start_address, std::span<const uint16_t> registers,
16 return; // the hub already logs exception responses
17
18 // Publish a sensor if its register(s) are in this response; skipping absent registers keeps this
19 // correct for any read range, so the poll may be split into multiple requests.
20 auto publish_1_register = [&](sensor::Sensor *sensor, uint16_t reg, float unit) -> void {
21 if (sensor == nullptr)
22 return;
24 sensor->publish_state(*value * unit);
25 };
26
27 auto publish_2_registers = [&](sensor::Sensor *sensor, uint16_t reg, float unit) -> void {
28 if (sensor == nullptr)
29 return;
31 sensor->publish_state(*value * unit);
32 };
33
34 for (uint8_t i = 0; i < 3; i++) {
35 auto &phase = this->phases_[i];
36 if (!phase.setup)
37 continue;
38 publish_1_register(phase.voltage_sensor_, HAVELLS_PHASE_1_VOLTAGE + i * 2, ONE_DEC_UNIT);
39 publish_1_register(phase.current_sensor_, HAVELLS_PHASE_1_CURRENT + i * 2, TWO_DEC_UNIT);
40 }
41
42 for (uint8_t i = 0; i < 2; i++) {
43 auto &pv = this->pvs_[i];
44 if (!pv.setup)
45 continue;
46 publish_1_register(pv.voltage_sensor_, HAVELLS_PV_1_VOLTAGE + i * 2, ONE_DEC_UNIT);
47 publish_1_register(pv.current_sensor_, HAVELLS_PV_1_CURRENT + i * 2, TWO_DEC_UNIT);
48 publish_1_register(pv.active_power_sensor_, HAVELLS_PV_1_POWER + i, MULTIPLY_TEN_UNIT);
49 publish_1_register(pv.voltage_sampled_by_secondary_cpu_sensor_, HAVELLS_PV1_VOLTAGE_SAMPLED_BY_SECONDARY_CPU + i,
50 ONE_DEC_UNIT);
51 publish_1_register(pv.insulation_of_p_to_ground_sensor_, HAVELLS_PV1_INSULATION_OF_P_TO_GROUND + i, NO_DEC_UNIT);
52 }
53
54 publish_1_register(this->frequency_sensor_, HAVELLS_GRID_FREQUENCY, TWO_DEC_UNIT);
55 publish_1_register(this->active_power_sensor_, HAVELLS_SYSTEM_ACTIVE_POWER, MULTIPLY_TEN_UNIT);
56 publish_1_register(this->reactive_power_sensor_, HAVELLS_SYSTEM_REACTIVE_POWER, TWO_DEC_UNIT);
57 publish_1_register(this->today_production_sensor_, HAVELLS_TODAY_PRODUCTION, TWO_DEC_UNIT);
58 publish_2_registers(this->total_energy_production_sensor_, HAVELLS_TOTAL_ENERGY_PRODUCTION, NO_DEC_UNIT);
59 publish_2_registers(this->total_generation_time_sensor_, HAVELLS_TOTAL_GENERATION_TIME, NO_DEC_UNIT);
60 publish_1_register(this->today_generation_time_sensor_, HAVELLS_TODAY_GENERATION_TIME, NO_DEC_UNIT);
61 publish_1_register(this->inverter_module_temp_sensor_, HAVELLS_INVERTER_MODULE_TEMP, NO_DEC_UNIT);
62 publish_1_register(this->inverter_inner_temp_sensor_, HAVELLS_INVERTER_INNER_TEMP, NO_DEC_UNIT);
63 publish_1_register(this->inverter_bus_voltage_sensor_, HAVELLS_INVERTER_BUS_VOLTAGE, NO_DEC_UNIT);
64 publish_1_register(this->insulation_pv_n_to_ground_sensor_, HAVELLS_INSULATION_OF_PV_N_TO_GROUND, NO_DEC_UNIT);
65 publish_1_register(this->gfci_value_sensor_, HAVELLS_GFCI_VALUE, NO_DEC_UNIT);
66 publish_1_register(this->dci_of_r_sensor_, HAVELLS_DCI_OF_R, NO_DEC_UNIT);
67 publish_1_register(this->dci_of_s_sensor_, HAVELLS_DCI_OF_S, NO_DEC_UNIT);
68 publish_1_register(this->dci_of_t_sensor_, HAVELLS_DCI_OF_T, NO_DEC_UNIT);
69}
70
71void HavellsSolar::update() { this->read_holding_registers(0, MODBUS_REGISTER_COUNT); }
73 ESP_LOGCONFIG(TAG,
74 "HAVELLS Solar:\n"
75 " Address: 0x%02X",
76 this->address_);
77 for (uint8_t i = 0; i < 3; i++) {
78 auto phase = this->phases_[i];
79 if (!phase.setup)
80 continue;
81 ESP_LOGCONFIG(TAG, " Phase %c", i + 'A');
82 LOG_SENSOR(" ", "Voltage", phase.voltage_sensor_);
83 LOG_SENSOR(" ", "Current", phase.current_sensor_);
84 }
85 for (uint8_t i = 0; i < 2; i++) {
86 auto pv = this->pvs_[i];
87 if (!pv.setup)
88 continue;
89 ESP_LOGCONFIG(TAG, " PV %d", i + 1);
90 LOG_SENSOR(" ", "Voltage", pv.voltage_sensor_);
91 LOG_SENSOR(" ", "Current", pv.current_sensor_);
92 LOG_SENSOR(" ", "Active Power", pv.active_power_sensor_);
93 LOG_SENSOR(" ", "Voltage Sampled By Secondary CPU", pv.voltage_sampled_by_secondary_cpu_sensor_);
94 LOG_SENSOR(" ", "Insulation Of PV+ To Ground", pv.insulation_of_p_to_ground_sensor_);
95 }
96 LOG_SENSOR(" ", "Frequency", this->frequency_sensor_);
97 LOG_SENSOR(" ", "Active Power", this->active_power_sensor_);
98 LOG_SENSOR(" ", "Reactive Power", this->reactive_power_sensor_);
99 LOG_SENSOR(" ", "Today Generation", this->today_production_sensor_);
100 LOG_SENSOR(" ", "Total Generation", this->total_energy_production_sensor_);
101 LOG_SENSOR(" ", "Total Generation Time", this->total_generation_time_sensor_);
102 LOG_SENSOR(" ", "Today Generation Time", this->today_generation_time_sensor_);
103 LOG_SENSOR(" ", "Inverter Module Temp", this->inverter_module_temp_sensor_);
104 LOG_SENSOR(" ", "Inverter Inner Temp", this->inverter_inner_temp_sensor_);
105 LOG_SENSOR(" ", "Inverter Bus Voltage", this->inverter_bus_voltage_sensor_);
106 LOG_SENSOR(" ", "Insulation Of PV- To Ground", this->insulation_pv_n_to_ground_sensor_);
107 LOG_SENSOR(" ", "GFCI Value", this->gfci_value_sensor_);
108 LOG_SENSOR(" ", "DCI Of R", this->dci_of_r_sensor_);
109 LOG_SENSOR(" ", "DCI Of S", this->dci_of_s_sensor_);
110 LOG_SENSOR(" ", "DCI Of T", this->dci_of_t_sensor_);
111}
112
113} // namespace esphome::havells_solar
uint8_t status
Definition bl0942.h:8
void on_read_holding_registers(uint16_t start_address, std::span< const uint16_t > registers, modbus::ResponseStatus status) override
sensor::Sensor * insulation_pv_n_to_ground_sensor_
sensor::Sensor * total_energy_production_sensor_
struct esphome::havells_solar::HavellsSolar::HAVELLSPV pvs_[2]
struct esphome::havells_solar::HavellsSolar::HAVELLSPhase phases_[3]
Base-class for all sensors.
Definition sensor.h:47
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:68
constexpr std::optional< RegisterValueType< VALUE_TYPE > > value_at(std::span< const uint16_t > registers, uint16_t start_address, uint16_t address)
The value stored at an absolute register address, or nullopt when it is not wholly inside this respon...
std::optional< ExceptionCode > ResponseStatus
Definition modbus.h:306
bool succeeded(ResponseStatus status)
True when a transaction carried no exception.
Definition modbus.h:309