mirror of
https://github.com/esphome/esphome.git
synced 2024-11-29 18:24:13 +01:00
Make growatt play nicer with other modbus components. (#4947)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
parent
8bd9f50659
commit
9e7e3708e3
2 changed files with 35 additions and 0 deletions
|
@ -9,11 +9,42 @@ static const char *const TAG = "growatt_solar";
|
||||||
static const uint8_t MODBUS_CMD_READ_IN_REGISTERS = 0x04;
|
static const uint8_t MODBUS_CMD_READ_IN_REGISTERS = 0x04;
|
||||||
static const uint8_t MODBUS_REGISTER_COUNT[] = {33, 95}; // indexed with enum GrowattProtocolVersion
|
static const uint8_t MODBUS_REGISTER_COUNT[] = {33, 95}; // indexed with enum GrowattProtocolVersion
|
||||||
|
|
||||||
|
void GrowattSolar::loop() {
|
||||||
|
// If update() was unable to send we retry until we can send.
|
||||||
|
if (!this->waiting_to_update_)
|
||||||
|
return;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
void GrowattSolar::update() {
|
void GrowattSolar::update() {
|
||||||
|
// If our last send has had no reply yet, and it wasn't that long ago, do nothing.
|
||||||
|
uint32_t now = millis();
|
||||||
|
if (now - this->last_send_ < this->get_update_interval() / 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The bus might be slow, or there might be other devices, or other components might be talking to our device.
|
||||||
|
if (this->waiting_for_response()) {
|
||||||
|
this->waiting_to_update_ = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->waiting_to_update_ = false;
|
||||||
this->send(MODBUS_CMD_READ_IN_REGISTERS, 0, MODBUS_REGISTER_COUNT[this->protocol_version_]);
|
this->send(MODBUS_CMD_READ_IN_REGISTERS, 0, MODBUS_REGISTER_COUNT[this->protocol_version_]);
|
||||||
|
this->last_send_ = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrowattSolar::on_modbus_data(const std::vector<uint8_t> &data) {
|
void GrowattSolar::on_modbus_data(const std::vector<uint8_t> &data) {
|
||||||
|
// Other components might be sending commands to our device. But we don't get called with enough
|
||||||
|
// context to know what is what. So if we didn't do a send, we ignore the data.
|
||||||
|
if (!this->last_send_)
|
||||||
|
return;
|
||||||
|
this->last_send_ = 0;
|
||||||
|
|
||||||
|
// Also ignore the data if the message is too short. Otherwise we will publish invalid values.
|
||||||
|
if (data.size() < MODBUS_REGISTER_COUNT[this->protocol_version_] * 2)
|
||||||
|
return;
|
||||||
|
|
||||||
auto publish_1_reg_sensor_state = [&](sensor::Sensor *sensor, size_t i, float unit) -> void {
|
auto publish_1_reg_sensor_state = [&](sensor::Sensor *sensor, size_t i, float unit) -> void {
|
||||||
if (sensor == nullptr)
|
if (sensor == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -19,6 +19,7 @@ enum GrowattProtocolVersion {
|
||||||
|
|
||||||
class GrowattSolar : public PollingComponent, public modbus::ModbusDevice {
|
class GrowattSolar : public PollingComponent, public modbus::ModbusDevice {
|
||||||
public:
|
public:
|
||||||
|
void loop() override;
|
||||||
void update() override;
|
void update() override;
|
||||||
void on_modbus_data(const std::vector<uint8_t> &data) override;
|
void on_modbus_data(const std::vector<uint8_t> &data) override;
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
|
@ -55,6 +56,9 @@ class GrowattSolar : public PollingComponent, public modbus::ModbusDevice {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool waiting_to_update_;
|
||||||
|
uint32_t last_send_;
|
||||||
|
|
||||||
struct GrowattPhase {
|
struct GrowattPhase {
|
||||||
sensor::Sensor *voltage_sensor_{nullptr};
|
sensor::Sensor *voltage_sensor_{nullptr};
|
||||||
sensor::Sensor *current_sensor_{nullptr};
|
sensor::Sensor *current_sensor_{nullptr};
|
||||||
|
|
Loading…
Reference in a new issue