8 static const char *
const TAG =
"modbus";
16 const uint32_t now =
millis();
26 ESP_LOGV(TAG,
"Clearing buffer of %d bytes - parse failed", at);
35 ESP_LOGV(TAG,
"Clearing buffer of %d bytes - timeout", at);
52 ESP_LOGVV(TAG,
"Modbus received Byte %d (0X%x)", byte, byte);
57 uint8_t function_code = raw[1];
63 uint8_t data_len = raw[2];
64 uint8_t data_offset = 3;
67 if (((function_code >= 65) && (function_code <= 72)) || ((function_code >= 100) && (function_code <= 110))) {
81 uint16_t computed_crc =
crc16(raw, data_offset + data_len);
82 uint16_t remote_crc = uint16_t(raw[data_offset + data_len]) | (uint16_t(raw[data_offset + data_len + 1]) << 8);
84 if (computed_crc != remote_crc)
87 ESP_LOGD(TAG,
"Modbus user-defined function %02X found", function_code);
97 if (function_code == 0x5 || function_code == 0x06 || function_code == 0xF || function_code == 0x10) {
104 if ((function_code & 0x80) == 0x80) {
110 if (at < data_offset + data_len)
114 if (at == data_offset + data_len)
118 uint16_t computed_crc =
crc16(raw, data_offset + data_len);
119 uint16_t remote_crc = uint16_t(raw[data_offset + data_len]) | (uint16_t(raw[data_offset + data_len + 1]) << 8);
120 if (computed_crc != remote_crc) {
122 ESP_LOGD(TAG,
"Modbus CRC Check failed, but ignored! %02X!=%02X", computed_crc, remote_crc);
124 ESP_LOGW(TAG,
"Modbus CRC Check failed! %02X!=%02X", computed_crc, remote_crc);
129 std::vector<uint8_t> data(this->
rx_buffer_.begin() + data_offset, this->
rx_buffer_.begin() + data_offset + data_len);
131 for (
auto *device : this->
devices_) {
132 if (device->address_ == address) {
134 if ((function_code & 0x80) == 0x80) {
135 ESP_LOGD(TAG,
"Modbus error function code: 0x%X exception: %d", function_code, raw[2]);
137 device->on_modbus_error(function_code & 0x7F, raw[2]);
140 ESP_LOGD(TAG,
"Ignoring Modbus error - not expecting a response");
143 device->on_modbus_read_registers(function_code, uint16_t(data[1]) | (uint16_t(data[0]) << 8),
144 uint16_t(data[3]) | (uint16_t(data[2]) << 8));
146 device->on_modbus_data(data);
154 ESP_LOGW(TAG,
"Got Modbus frame from unknown address 0x%02X! ", address);
158 ESP_LOGV(TAG,
"Clearing buffer of %d bytes - parse succeeded", at);
164 ESP_LOGCONFIG(TAG,
"Modbus:");
167 ESP_LOGCONFIG(TAG,
" CRC Disabled: %s", YESNO(this->
disable_crc_));
174 void Modbus::send(uint8_t
address, uint8_t function_code, uint16_t start_address, uint16_t number_of_entities,
175 uint8_t payload_len,
const uint8_t *payload) {
176 static const size_t MAX_VALUES = 128;
180 if (number_of_entities > MAX_VALUES && function_code <= 0x10) {
181 ESP_LOGE(TAG,
"send too many values %d max=%zu", number_of_entities, MAX_VALUES);
185 std::vector<uint8_t> data;
186 data.push_back(address);
187 data.push_back(function_code);
189 data.push_back(start_address >> 8);
190 data.push_back(start_address >> 0);
191 if (function_code != 0x5 && function_code != 0x6) {
192 data.push_back(number_of_entities >> 8);
193 data.push_back(number_of_entities >> 0);
197 if (payload !=
nullptr) {
199 data.push_back(payload_len);
203 for (
int i = 0; i < payload_len; i++) {
204 data.push_back(payload[i]);
208 auto crc =
crc16(data.data(), data.size());
209 data.push_back(
crc >> 0);
210 data.push_back(
crc >> 8);
228 if (payload.empty()) {
235 auto crc =
crc16(payload.data(), payload.size());
virtual void digital_write(bool value)=0
std::string format_hex_pretty(const uint8_t *data, size_t length)
Format the byte array data of length len in pretty-printed, human-readable hex.
void write_array(const uint8_t *data, size_t len)
std::vector< uint8_t > rx_buffer_
bool parse_modbus_byte_(uint8_t byte)
void write_byte(uint8_t data)
void send_raw(const std::vector< uint8_t > &payload)
void send(uint8_t address, uint8_t function_code, uint16_t start_address, uint16_t number_of_entities, uint8_t payload_len=0, const uint8_t *payload=nullptr)
std::vector< ModbusDevice * > devices_
float get_setup_priority() const override
GPIOPin * flow_control_pin_
uint16_t crc16(const uint8_t *data, uint16_t len, uint16_t crc, uint16_t reverse_poly, bool refin, bool refout)
Calculate a CRC-16 checksum of data with size len.
uint32_t IRAM_ATTR HOT millis()
void dump_config() override
const float BUS
For communication buses like i2c/spi.
bool read_byte(uint8_t *data)
uint32_t last_modbus_byte_
uint8_t waiting_for_response
Implementation of SPI Controller mode.