From f2df542cb1c8d20102af3d752b6487f49aac038c Mon Sep 17 00:00:00 2001 From: Jan Grewe Date: Thu, 22 Dec 2022 08:14:11 +0100 Subject: [PATCH] Allow ignoring of failed Modbus response CRC (#3930) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/modbus/__init__.py | 6 ++++-- esphome/components/modbus/modbus.cpp | 9 +++++++-- esphome/components/modbus/modbus.h | 2 ++ esphome/const.py | 1 + 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/esphome/components/modbus/__init__.py b/esphome/components/modbus/__init__.py index 254322d097..6fea7033f2 100644 --- a/esphome/components/modbus/__init__.py +++ b/esphome/components/modbus/__init__.py @@ -6,6 +6,7 @@ from esphome.const import ( CONF_FLOW_CONTROL_PIN, CONF_ID, CONF_ADDRESS, + CONF_DISABLE_CRC, ) from esphome import pins @@ -27,6 +28,7 @@ CONFIG_SCHEMA = ( cv.Optional( CONF_SEND_WAIT_TIME, default="250ms" ): cv.positive_time_period_milliseconds, + cv.Optional(CONF_DISABLE_CRC, default=False): cv.boolean, } ) .extend(cv.COMPONENT_SCHEMA) @@ -45,8 +47,8 @@ async def to_code(config): pin = await gpio_pin_expression(config[CONF_FLOW_CONTROL_PIN]) cg.add(var.set_flow_control_pin(pin)) - if CONF_SEND_WAIT_TIME in config: - cg.add(var.set_send_wait_time(config[CONF_SEND_WAIT_TIME])) + cg.add(var.set_send_wait_time(config[CONF_SEND_WAIT_TIME])) + cg.add(var.set_disable_crc(config[CONF_DISABLE_CRC])) def modbus_device_schema(default_address): diff --git a/esphome/components/modbus/modbus.cpp b/esphome/components/modbus/modbus.cpp index 4d75675d0f..137fb0b26b 100644 --- a/esphome/components/modbus/modbus.cpp +++ b/esphome/components/modbus/modbus.cpp @@ -102,8 +102,12 @@ bool Modbus::parse_modbus_byte_(uint8_t byte) { uint16_t computed_crc = crc16(raw, data_offset + data_len); uint16_t remote_crc = uint16_t(raw[data_offset + data_len]) | (uint16_t(raw[data_offset + data_len + 1]) << 8); if (computed_crc != remote_crc) { - ESP_LOGW(TAG, "Modbus CRC Check failed! %02X!=%02X", computed_crc, remote_crc); - return false; + if (this->disable_crc_) { + ESP_LOGD(TAG, "Modbus CRC Check failed, but ignored! %02X!=%02X", computed_crc, remote_crc); + } else { + ESP_LOGW(TAG, "Modbus CRC Check failed! %02X!=%02X", computed_crc, remote_crc); + return false; + } } } std::vector data(this->rx_buffer_.begin() + data_offset, this->rx_buffer_.begin() + data_offset + data_len); @@ -139,6 +143,7 @@ void Modbus::dump_config() { ESP_LOGCONFIG(TAG, "Modbus:"); LOG_PIN(" Flow Control Pin: ", this->flow_control_pin_); ESP_LOGCONFIG(TAG, " Send Wait Time: %d ms", this->send_wait_time_); + ESP_LOGCONFIG(TAG, " CRC Disabled: %s", YESNO(this->disable_crc_)); } float Modbus::get_setup_priority() const { // After UART bus diff --git a/esphome/components/modbus/modbus.h b/esphome/components/modbus/modbus.h index 95414ba090..dd8732c6e9 100644 --- a/esphome/components/modbus/modbus.h +++ b/esphome/components/modbus/modbus.h @@ -30,12 +30,14 @@ class Modbus : public uart::UARTDevice, public Component { void set_flow_control_pin(GPIOPin *flow_control_pin) { this->flow_control_pin_ = flow_control_pin; } uint8_t waiting_for_response{0}; void set_send_wait_time(uint16_t time_in_ms) { send_wait_time_ = time_in_ms; } + void set_disable_crc(bool disable_crc) { disable_crc_ = disable_crc; } protected: GPIOPin *flow_control_pin_{nullptr}; bool parse_modbus_byte_(uint8_t byte); uint16_t send_wait_time_{250}; + bool disable_crc_; std::vector rx_buffer_; uint32_t last_modbus_byte_{0}; uint32_t last_send_{0}; diff --git a/esphome/const.py b/esphome/const.py index 19fc226dd9..f0b0c089bf 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -175,6 +175,7 @@ CONF_DIO_PIN = "dio_pin" CONF_DIR_PIN = "dir_pin" CONF_DIRECTION = "direction" CONF_DIRECTION_OUTPUT = "direction_output" +CONF_DISABLE_CRC = "disable_crc" CONF_DISABLED_BY_DEFAULT = "disabled_by_default" CONF_DISCONNECT_DELAY = "disconnect_delay" CONF_DISCOVERY = "discovery"