Modbus Controller Select
The modbus_controller Select platform allows you to create a Select from modbus
registers.
Configuration variables
Section titled “Configuration variables”-
address (Required, int): The start address of the first or only register of the Select (can be decimal or hexadecimal). Note that only Holding registers are supported.
-
optionsmap (Required, Map[str, int]): Provide a mapping from options (str) of this Select to values (int) of the modbus register and vice versa. All options and all values have to be unique.
-
value_type (Optional): The data type of the modbus data. Defaults to
U_WORD.U_WORD(unsigned 16 bit integer from 1 register = 16bit)S_WORD(signed 16 bit integer from 1 register = 16bit)U_WORD_S(unsigned 16 bit integer from 1 register with bytes swapped within the register = 16bit)S_WORD_S(signed 16 bit integer from 1 register with bytes swapped within the register = 16bit)U_DWORD(unsigned 32 bit integer from 2 registers = 32bit)S_DWORD(signed 32 bit integer from 2 registers = 32bit)U_DWORD_R(unsigned 32 bit integer from 2 registers low word first)S_DWORD_R(signed 32 bit integer from 2 registers low word first)U_QWORD(unsigned 64 bit integer from 4 registers = 64bit)S_QWORD(signed 64 bit integer from 4 registers = 64bit)U_QWORD_R(unsigned 64 bit integer from 4 registers low word first)S_QWORD_R(signed 64 bit integer from 4 registers low word first)
WARNING
U_WORD_S and S_WORD_S are a rare, non-standard configuration: the two bytes
within one 16-bit register are reversed (LSB first on the wire within that register).
Modbus registers are big-endian (MSB first) per the specification. The _S suffix is not
the same as _R (word order reversed / low word first across multiple registers).
-
skip_updates (Optional, int): Deprecated and no longer has any effect — every register range is polled on each
update_interval. The key is still accepted (logging a config-time warning) and will be removed in 2027.3.0. To poll some registers less often, place those sensors on a secondmodbus_controllerwith the sameaddress:and a slowerupdate_interval:. -
reuse_previous_range (Optional, boolean or
auto): How this item relates to the register range built just before it (same register type, ascending address order).auto(default) joins when the addresses are adjacent and the item’s position in the reply is exact;truejoins unconditionally, reading across address gaps;falsealways starts a new range here (later items may still extend it). See Register ranges. Replaces the deprecatedforce_new_rangeandregister_countoptions, which will be removed in 2027.3.0 — the linked section covers migration. -
lambda (Optional, lambda): Lambda to be evaluated every update interval to get the current option of the select.
Parameters passed into lambda
-
x (
int64_t): The parsed integer value of the modbus data. -
data (
std::span<const uint8_t>): span containing the complete raw modbus response bytes for this select. Note: because the response contains data for all registers in the same range you have to usedata[item->offset]to get the first response byte for your select. -
item (
ModbusSelect *): The select entity, aSensorItemsubclass, so the configured address,offset,bitmask, etc. are accessible.
Possible return values for the lambda:
return <std::string>;The new option for this Select.return {};Use default mapping (seeoptionsmap).
-
-
write_lambda (Optional, lambda): Lambda to be evaluated on every update of the Select, before the new value is written to the modbus registers.
-
use_write_multiple (Optional, boolean): By default the modbus command Function Code 6 (Preset Single Registers) is used for setting the holding register if only one register is set. If your device only supports Function Code 16 (Preset Multiple Registers) set this option to
true. -
optimistic (Optional, boolean): Whether to operate in optimistic mode - when in this mode, any command sent to the Modbus Select will immediately update the reported state. Defaults to
false. -
All other options from Select.
# examplelambda: |- ESP_LOGD("Reg1000", "Received value %lld", x); ESP_LOGD("Reg1000", "Parsed from bytes 0x%x;0x%x", data[item->offset], data[item->offset + 1]); if (x > 3) { return std::string("Three"); }Parameters passed into write_lambda
Section titled “Parameters passed into write_lambda”- x (
const std::string&): The option value to set for this Select. - value (
int64_t): The mapping value ofxusingoptionsmap. - item (
ModbusSelect *): The entity as its own modbus device: the write helpers andqueue_pdu()are available - for exampleitem->write_single_register(0x1234, 42)oritem->queue_pdu(...)- regardless of the select’s own register type. Also aSensorItemsubclass, so the configured address,offset,bitmask, etc. are accessible. - payload (
RegisterValues &payload): Deprecated, removed in 2027.3.0 - useiteminstead. An empty buffer; the lambda can add (push_back/clear/assign- not the fullstd::vectorAPI) the 16 bit register words to write in place of the mapping value. Unlike the number platform’s buffer, this is data words only - no device address or function code.
Possible return values for the lambda:
return <int64_t>;the value which should be written to the configured modbus registers. If there were data written topayloadthis value is ignored.return {};if the lambda handled (or deliberately skipped) the write itself, for example viaitem->write_*().
# examplewrite_lambda: |- ESP_LOGD("Reg1000", "Set option to %s (%lld)", x.c_str(), value);
// re-use default option value from optionsmap if (value == 0) { return value; }
// return own option value if (x == "One") { return 2; }
// "Two" needs a vendor trigger register instead of the mapped write: // drive it directly through the entity if (x == "Two") { item->write_single_register(0x2000, 1); // the lambda must return something - return empty, the write is already done return {}; }
// {} without an item-> write = skip this update entirely; nothing is sent return {};Example
Section titled “Example”# Example configuration entryselect: - platform: modbus_controller name: "Modbus Select Register 1000" address: 1000 value_type: U_WORD optionsmap: "Zero": 0 "One": 1 "Two": 2 "Three": 3