ModbusDevice#
- class ModbusDevice(
- config: ModbusConfig | dict | Path | str,
- connection: ModbusTransport | dict | None = None,
- name: str | None = None,
- publishers: list[Publisher] | None = None,
- autostart: bool = False,
- unit_id: int | None = None,
- **kwargs,
Bases:
InstrumentConfig-driven Modbus client. Semantic access by register alias from a
ModbusConfig.Initialize a ModbusDevice.
- Parameters:
config
A
ModbusConfig, a dict (validated via Pydantic), or a path to a JSON config.connection
Overrides
config.connection. Accepts aModbusTransport(pass the same instance to several devices to share one line;unit_idis then required), or a dict (withtransport="tcp"/"rtu"), which builds a private transport. Required if the config has noconnectionsection.name
Channel-name prefix; falls back to
config.device.name.publishers
Publishers that receive emitted Measurement/Command data.
autostart
When True, open the connection and start background polling. Requires a
timingsection (withpoll_interval) — passingautostart=Truewithout one is an error.unit_id
Modbus unit/slave address (0-255; 0-247 on serial). May also come from the connection block’s
unit_idfield; values given in both places must agree. Required alongside a shared transport; defaults to 1 when this device builds its own private transport.**kwargs
Default tags applied to every emitted Measurement/Command.
- Raises:
ValueError – No connection in args or config, an address that is missing, conflicting, or out of range, or
autostart=Truewith notimingsection.
Attributes
Seconds between background daemon iterations (0 = no wait).
Return an insertion-ordered snapshot of all published channel names.
set once at construction, via the constructor kwarg or the config.
Methods
Append
methodto the daemon's call list.Register a publisher to receive this instrument's Measurement/Command data.
Release this device's hold on the transport and stop the daemon; the line closes when the last device leaves.
Replace all daemon functions with a single
method(called with the given args).Return the most recent
lengthsamples forchannel_namefrom the in-memory buffer.Return the most recent sample for
channel_namefrom the in-memory buffer.Open the Modbus TCP/RTU connection, registering this device as an owner of the transport.
Fan
dataout to every configured publisher;kwargspass through.Read the register named
aliasand return the scaled value.Start the background daemon thread.
Signal the background daemon to stop and join it.
Write
valueto the register namedalias.- property background_interval#
Seconds between background daemon iterations (0 = no wait).
- property unit_id: int#
set once at construction, via the constructor kwarg or the config.
- Type:
Modbus unit/slave address this device is bound to. Read-only
- open() None[source]#
Open the Modbus TCP/RTU connection, registering this device as an owner of the transport.
- close() None[source]#
Release this device’s hold on the transport and stop the daemon; the line closes when the last device leaves.
- read(alias: str, **kwargs) Measurement[source]#
Read the register named
aliasand return the scaled value.
- write( ) Command[source]#
Write
valueto the register namedalias.valueis in physical units when ascaleis configured. For coils, passTrue/False. For registers with awrite_value_map, pass the string key to look up the mapped value.- Raises:
TypeError – Value type does not match the register’s data type.
KeyError – String value not found in
write_value_map.ValueError – Read-only register, value violates
write_min/write_max, or scaled raw is out of range for the data type.
- add_background_daemon_function(
- method: Callable,
- *args,
- **kwargs,
Append
methodto the daemon’s call list. Usedefine_background_daemonto replace instead.
- add_publisher(
- publisher: Publisher,
Register a publisher to receive this instrument’s Measurement/Command data.
- property channel_names: tuple[str, ...]#
Return an insertion-ordered snapshot of all published channel names.
Names are complete after one full daemon iteration: {name}.loop_time publishes every iteration, so call get_channel(“loop_time”, wait_for_new_samples=True) then read channel_names to ensure the complete set has arrived.
- Raises:
RuntimeError – No background buffer;
start()was not called.
- define_background_daemon(
- method: Callable,
- *args,
- **kwargs,
Replace all daemon functions with a single
method(called with the given args).
- get_channel( ) Measurement#
Return the most recent
lengthsamples forchannel_namefrom the in-memory buffer.If the channel does not exist yet, or no sample is available, the code will always block until
timeoutexpires.- Parameters:
channel_name
Name of the channel to retrieve.
length
Number of trailing samples to return.
wait_for_new_samples
Block until at least
lengthnew values arrive.timeout
Seconds to wait when insufficient data exists or
wait_for_new_samples=True.
- Raises:
RuntimeError – No background buffer;
start()was not called.ChannelNotFoundError – channel had no values and no data appeared before
timeout.wait_for_new_samples=Trueand channel did not appear withintimeout.ChannelValueTimeoutError –
wait_for_new_samples=Trueand values did not arrive withintimeout.
- get_single_channel_value(
- channel_name: str,
Return the most recent sample for
channel_namefrom the in-memory buffer.This will not wait, if data is not available then
Noneis returned.- Parameters:
channel_name
Name of the channel to retrieve.
- Raises:
RuntimeError – No background buffer;
start()was not called.
- publish(
- data: Measurement | Command,
- **kwargs,
Fan
dataout to every configured publisher;kwargspass through.
- start()#
Start the background daemon thread. No-op if already running.
- stop()#
Signal the background daemon to stop and join it. No-op if not running.