ESPHome  2023.5.5
growatt_solar.cpp
Go to the documentation of this file.
1 #include "growatt_solar.h"
2 #include "esphome/core/log.h"
3 
4 namespace esphome {
5 namespace growatt_solar {
6 
7 static const char *const TAG = "growatt_solar";
8 
9 static const uint8_t MODBUS_CMD_READ_IN_REGISTERS = 0x04;
10 static const uint8_t MODBUS_REGISTER_COUNT[] = {33, 95}; // indexed with enum GrowattProtocolVersion
11 
13  this->send(MODBUS_CMD_READ_IN_REGISTERS, 0, MODBUS_REGISTER_COUNT[this->protocol_version_]);
14 }
15 
16 void GrowattSolar::on_modbus_data(const std::vector<uint8_t> &data) {
17  auto publish_1_reg_sensor_state = [&](sensor::Sensor *sensor, size_t i, float unit) -> void {
18  if (sensor == nullptr)
19  return;
20  float value = encode_uint16(data[i * 2], data[i * 2 + 1]) * unit;
21  sensor->publish_state(value);
22  };
23 
24  auto publish_2_reg_sensor_state = [&](sensor::Sensor *sensor, size_t reg1, size_t reg2, float unit) -> void {
25  float value = ((encode_uint16(data[reg1 * 2], data[reg1 * 2 + 1]) << 16) +
26  encode_uint16(data[reg2 * 2], data[reg2 * 2 + 1])) *
27  unit;
28  if (sensor != nullptr)
29  sensor->publish_state(value);
30  };
31 
32  switch (this->protocol_version_) {
33  case RTU: {
34  publish_1_reg_sensor_state(this->inverter_status_, 0, 1);
35 
36  publish_2_reg_sensor_state(this->pv_active_power_sensor_, 1, 2, ONE_DEC_UNIT);
37 
38  publish_1_reg_sensor_state(this->pvs_[0].voltage_sensor_, 3, ONE_DEC_UNIT);
39  publish_1_reg_sensor_state(this->pvs_[0].current_sensor_, 4, ONE_DEC_UNIT);
40  publish_2_reg_sensor_state(this->pvs_[0].active_power_sensor_, 5, 6, ONE_DEC_UNIT);
41 
42  publish_1_reg_sensor_state(this->pvs_[1].voltage_sensor_, 7, ONE_DEC_UNIT);
43  publish_1_reg_sensor_state(this->pvs_[1].current_sensor_, 8, ONE_DEC_UNIT);
44  publish_2_reg_sensor_state(this->pvs_[1].active_power_sensor_, 9, 10, ONE_DEC_UNIT);
45 
46  publish_2_reg_sensor_state(this->grid_active_power_sensor_, 11, 12, ONE_DEC_UNIT);
47  publish_1_reg_sensor_state(this->grid_frequency_sensor_, 13, TWO_DEC_UNIT);
48 
49  publish_1_reg_sensor_state(this->phases_[0].voltage_sensor_, 14, ONE_DEC_UNIT);
50  publish_1_reg_sensor_state(this->phases_[0].current_sensor_, 15, ONE_DEC_UNIT);
51  publish_2_reg_sensor_state(this->phases_[0].active_power_sensor_, 16, 17, ONE_DEC_UNIT);
52 
53  publish_1_reg_sensor_state(this->phases_[1].voltage_sensor_, 18, ONE_DEC_UNIT);
54  publish_1_reg_sensor_state(this->phases_[1].current_sensor_, 19, ONE_DEC_UNIT);
55  publish_2_reg_sensor_state(this->phases_[1].active_power_sensor_, 20, 21, ONE_DEC_UNIT);
56 
57  publish_1_reg_sensor_state(this->phases_[2].voltage_sensor_, 22, ONE_DEC_UNIT);
58  publish_1_reg_sensor_state(this->phases_[2].current_sensor_, 23, ONE_DEC_UNIT);
59  publish_2_reg_sensor_state(this->phases_[2].active_power_sensor_, 24, 25, ONE_DEC_UNIT);
60 
61  publish_2_reg_sensor_state(this->today_production_, 26, 27, ONE_DEC_UNIT);
62  publish_2_reg_sensor_state(this->total_energy_production_, 28, 29, ONE_DEC_UNIT);
63 
64  publish_1_reg_sensor_state(this->inverter_module_temp_, 32, ONE_DEC_UNIT);
65  break;
66  }
67  case RTU2: {
68  publish_1_reg_sensor_state(this->inverter_status_, 0, 1);
69 
70  publish_2_reg_sensor_state(this->pv_active_power_sensor_, 1, 2, ONE_DEC_UNIT);
71 
72  publish_1_reg_sensor_state(this->pvs_[0].voltage_sensor_, 3, ONE_DEC_UNIT);
73  publish_1_reg_sensor_state(this->pvs_[0].current_sensor_, 4, ONE_DEC_UNIT);
74  publish_2_reg_sensor_state(this->pvs_[0].active_power_sensor_, 5, 6, ONE_DEC_UNIT);
75 
76  publish_1_reg_sensor_state(this->pvs_[1].voltage_sensor_, 7, ONE_DEC_UNIT);
77  publish_1_reg_sensor_state(this->pvs_[1].current_sensor_, 8, ONE_DEC_UNIT);
78  publish_2_reg_sensor_state(this->pvs_[1].active_power_sensor_, 9, 10, ONE_DEC_UNIT);
79 
80  publish_2_reg_sensor_state(this->grid_active_power_sensor_, 35, 36, ONE_DEC_UNIT);
81  publish_1_reg_sensor_state(this->grid_frequency_sensor_, 37, TWO_DEC_UNIT);
82 
83  publish_1_reg_sensor_state(this->phases_[0].voltage_sensor_, 38, ONE_DEC_UNIT);
84  publish_1_reg_sensor_state(this->phases_[0].current_sensor_, 39, ONE_DEC_UNIT);
85  publish_2_reg_sensor_state(this->phases_[0].active_power_sensor_, 40, 41, ONE_DEC_UNIT);
86 
87  publish_1_reg_sensor_state(this->phases_[1].voltage_sensor_, 42, ONE_DEC_UNIT);
88  publish_1_reg_sensor_state(this->phases_[1].current_sensor_, 43, ONE_DEC_UNIT);
89  publish_2_reg_sensor_state(this->phases_[1].active_power_sensor_, 44, 45, ONE_DEC_UNIT);
90 
91  publish_1_reg_sensor_state(this->phases_[2].voltage_sensor_, 46, ONE_DEC_UNIT);
92  publish_1_reg_sensor_state(this->phases_[2].current_sensor_, 47, ONE_DEC_UNIT);
93  publish_2_reg_sensor_state(this->phases_[2].active_power_sensor_, 48, 49, ONE_DEC_UNIT);
94 
95  publish_2_reg_sensor_state(this->today_production_, 53, 54, ONE_DEC_UNIT);
96  publish_2_reg_sensor_state(this->total_energy_production_, 55, 56, ONE_DEC_UNIT);
97 
98  publish_1_reg_sensor_state(this->inverter_module_temp_, 93, ONE_DEC_UNIT);
99  break;
100  }
101  }
102 }
103 
105  ESP_LOGCONFIG(TAG, "GROWATT Solar:");
106  ESP_LOGCONFIG(TAG, " Address: 0x%02X", this->address_);
107 }
108 
109 } // namespace growatt_solar
110 } // namespace esphome
struct esphome::growatt_solar::GrowattSolar::GrowattPhase phases_[3]
struct esphome::growatt_solar::GrowattSolar::GrowattPV pvs_[2]
sensor::Sensor * grid_active_power_sensor_
Definition: growatt_solar.h:72
void publish_state(float state)
Publish a new state to the front-end.
Definition: sensor.cpp:39
constexpr uint16_t encode_uint16(uint8_t msb, uint8_t lsb)
Encode a 16-bit value given the most and least significant byte.
Definition: helpers.h:176
GrowattProtocolVersion protocol_version_
Definition: growatt_solar.h:79
void on_modbus_data(const std::vector< uint8_t > &data) override
Definition: a4988.cpp:4
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
Base-class for all sensors.
Definition: sensor.h:57