[modbus] Make sure we log on no accepting device (#18187)

This commit is contained in:
Josef Zweck
2026-08-08 09:34:59 -05:00
committed by GitHub
parent 68acc055bf
commit 747c5c3e40
2 changed files with 24 additions and 2 deletions
+20 -2
View File
@@ -15,6 +15,9 @@ static constexpr uint32_t MODBUS_BITS_PER_CHAR = 11;
// Milliseconds per second
static constexpr uint32_t MS_PER_SEC = 1000;
// Shortest gap between two "no device accepted broadcast" warnings
static constexpr uint32_t UNACCEPTED_BROADCAST_WARN_INTERVAL_MS = 60 * MS_PER_SEC;
void Modbus::setup() {
if (this->flow_control_pin_ != nullptr) {
this->flow_control_pin_->setup();
@@ -445,13 +448,28 @@ void ModbusServerHub::process_broadcast_frame_(uint8_t function_code, std::span<
if (status.has_value()) {
return;
}
// A broadcast is never answered, so a rejecting device has no other feedback channel: report the
// per-device outcome at V, and warn if the write reached nobody at all.
bool accepted = false;
for (auto *device : this->devices_) {
// A broadcast is never answered, so a rejecting device has no other feedback channel; log it so a
// misconfigured register map is diagnosable instead of looking identical to a successful write.
if (ResponseStatus device_status = device->on_broadcast_write_registers(start_address, registers);
device_status.has_value()) {
ESP_LOGV(TAG, "Device %" PRIu8 " rejected broadcast write with exception %" PRIu8, device->get_address(),
static_cast<uint8_t>(device_status.value()));
} else {
accepted = true;
}
}
if (!accepted && !this->devices_.empty()) {
// Warn at most once per interval, then drop to VERBOSE: on a shared bus a broadcast aimed at other nodes
// repeats forever, so warning per frame would flood the log.
const uint32_t now = millis();
if (this->last_unaccepted_broadcast_warn_ == 0 ||
now - this->last_unaccepted_broadcast_warn_ > UNACCEPTED_BROADCAST_WARN_INTERVAL_MS) {
this->last_unaccepted_broadcast_warn_ = now;
ESP_LOGW(TAG, "No device accepted broadcast write of %zu registers at 0x%04X", registers.size(), start_address);
} else {
ESP_LOGV(TAG, "No device accepted broadcast write of %zu registers at 0x%04X", registers.size(), start_address);
}
}
}
+4
View File
@@ -361,6 +361,10 @@ class ModbusServerHub : public Modbus {
uint8_t expecting_peer_response_{0};
std::vector<ModbusServerDevice *> devices_;
// Stamp of the last "broadcast reached no device" warning, 0 until the first one is logged. Rate limiting
// on time rather than on address keeps the log bounded no matter how many addresses a shared bus carries.
uint32_t last_unaccepted_broadcast_warn_{0};
// Holds the raw payload of a single reply deferred for sending when tx was blocked at send time.
// Only one server reply can be waiting at once, so a single fixed buffer avoids heap allocation.
std::array<uint8_t, MAX_RAW_SIZE> deferred_payload_;