mirror of
https://github.com/esphome/esphome.git
synced 2026-10-01 17:00:21 +00:00
[modbus] Build single-value register writes on a right-sized stack buffer (#18844)
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
co-authored by
J. Nick Koston
parent
768ab5b672
commit
59397b4e28
@@ -485,9 +485,12 @@ static bool register_block_in_range(const LogString *role, uint16_t start_addres
|
||||
return true;
|
||||
}
|
||||
|
||||
PduBuffer create_write_registers_pdu(uint16_t start_address, std::span<const uint16_t> values) {
|
||||
PduBuffer pdu; // declared before every return so NRVO fires (all paths return the same object)
|
||||
if (!register_block_in_range(LOG_STR("Write"), start_address, values.size(), MAX_NUM_OF_REGISTERS_TO_WRITE)) {
|
||||
// The ceiling comes from the buffer itself: push_back() drops silently, so a bound wider than the buffer
|
||||
// would put a truncated frame on the wire.
|
||||
template<typename Pdu> static Pdu build_write_registers_pdu(uint16_t start_address, std::span<const uint16_t> values) {
|
||||
constexpr auto max_registers = static_cast<uint16_t>((Pdu::capacity() - WRITE_MULTIPLE_HEADER_SIZE) / 2);
|
||||
Pdu pdu; // declared before every return so NRVO fires (all paths return the same object)
|
||||
if (!register_block_in_range(LOG_STR("Write"), start_address, values.size(), max_registers)) {
|
||||
return pdu;
|
||||
}
|
||||
append_pdu_header(pdu, FunctionCode::WRITE_MULTIPLE_REGISTERS, start_address, values.size());
|
||||
@@ -498,6 +501,19 @@ PduBuffer create_write_registers_pdu(uint16_t start_address, std::span<const uin
|
||||
return pdu;
|
||||
}
|
||||
|
||||
static_assert((PduBuffer::capacity() - WRITE_MULTIPLE_HEADER_SIZE) / 2 == MAX_NUM_OF_REGISTERS_TO_WRITE,
|
||||
"a full-frame PDU must hold exactly MAX_NUM_OF_REGISTERS_TO_WRITE registers");
|
||||
static_assert((WriteFewRegistersPdu::capacity() - WRITE_MULTIPLE_HEADER_SIZE) / 2 == MAX_FEW_REGISTERS,
|
||||
"the small write buffer must hold exactly MAX_FEW_REGISTERS registers");
|
||||
|
||||
PduBuffer create_write_registers_pdu(uint16_t start_address, std::span<const uint16_t> values) {
|
||||
return build_write_registers_pdu<PduBuffer>(start_address, values);
|
||||
}
|
||||
|
||||
WriteFewRegistersPdu create_write_few_registers_pdu(uint16_t start_address, std::span<const uint16_t> values) {
|
||||
return build_write_registers_pdu<WriteFewRegistersPdu>(start_address, values);
|
||||
}
|
||||
|
||||
PduBuffer create_read_write_multiple_registers_pdu(uint16_t read_start_address, uint16_t read_count,
|
||||
uint16_t write_start_address,
|
||||
std::span<const uint16_t> write_values) {
|
||||
|
||||
Reference in New Issue
Block a user