fujilib.transport¶
A transport is a thin lifecycle object that exposes the byte stream the Modbus
bus binds to: the real anyserial.SerialPort, so anymodbus keeps its
drain-after-send and input-reset behaviour (design §4.1).
fujilib.transport.base ¶
The transport contract and serial framing settings (design §2.1, §4.1).
The ZP series' serial settings are fixed and cannot be changed: 38400 bps, 8 data bits, no parity, 1 stop bit, no flow control. They are still carried as a value so a session can report what it actually used and a second open with incompatible settings can be refused.
A :class:Transport is a thin lifecycle object that exposes its byte
stream instead of being one. anymodbus keeps its drain-after-send and
input-reset behaviour only when the stream it is given is literally an
anyserial.SerialPort, so the Modbus port binds its bus to
:attr:Transport.stream directly (design §4.1).
SerialSettings
dataclass
¶
SerialSettings(
port,
baudrate=FUJI_BAUDRATE,
bytesize=ByteSize.EIGHT,
parity=Parity.NONE,
stopbits=StopBits.ONE,
rtscts=False,
xonxoff=False,
exclusive=True,
)
Frozen serial framing descriptor. The defaults are the analyzer's fixed 38400 8-N-1.
Transport ¶
Bases: Protocol
An open connection to one serial line.
Implementations: :class:~fujilib.transport.serial.SerialTransport over a
real port (or one end of a test pair), and
:class:~fujilib.transport.fake.FakeTransport for byte-exact fixture replay.
stream
property
¶
The byte stream the Modbus bus binds to; a real SerialPort where there is one.
fujilib.transport.serial ¶
The serial transport: an anyserial.SerialPort and the settings it was opened with.
:attr:SerialTransport.stream is the real SerialPort, never a wrapper, so
anymodbus drains each request before listening and clears stale input
before each request (design §4.1). The same class wraps one end of
anyserial.testing.serial_port_pair(), whose ends are real SerialPort
objects too, so tests exercise the hardware code path.
SerialTransport ¶
An open serial port. Satisfies :class:~fujilib.transport.base.Transport.
Wrap an already open port; :meth:open is the usual constructor.
Source code in src/fujilib/transport/serial.py
aclose
async
¶
Close the port. Idempotent, and completes even when the caller is cancelled.
open
async
classmethod
¶
Open the port named by settings.port, under its canonical name.
The canonical name is anyserial's, so every spelling of one port
agrees: COM8, com8 and \\.\COM8 on Windows, a symlink and
its target elsewhere (design §4.1).
Raises:
| Type | Description |
|---|---|
FujiValidationError
|
|
FujiConfigurationError
|
|
FujiConnectionError
|
the port does not exist, is busy or cannot be opened. |
Source code in src/fujilib/transport/serial.py
serial_config ¶
The anyserial configuration for settings.
Source code in src/fujilib/transport/serial.py
fujilib.transport.fake ¶
A scripted transport for byte-exact fixture replay (design §4.1, §10).
:class:FakeTransport is its own byte stream. Each request the client sends
is looked up in a script of exact request bytes; a match queues the scripted
reply, anything else is recorded and gets no reply. anymodbus sends each
request in a single send call, so the lookup sees whole frames.
It is used only to prove that the client puts the manual's exact bytes on the
wire. It is not a SerialPort, so anymodbus skips drain and input
reset with it; those paths are covered by the simulated analyzer on a real
port pair (:mod:fujilib.testing).
FakeTransport ¶
Bases: ByteStream
Replays scripted replies. Satisfies :class:~fujilib.transport.base.Transport.
Create a transport that answers each request in script with its reply.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
script
|
Mapping[bytes, bytes] | None
|
Exact request bytes mapped to the reply bytes to send back. |
None
|
label
|
str
|
The name reported as the port. |
'fake://fixture'
|
Source code in src/fujilib/transport/fake.py
aclose
async
¶
receive
async
¶
Return up to max_bytes queued reply bytes, waiting until there are some.
Source code in src/fujilib/transport/fake.py
send
async
¶
Record a request and queue its scripted reply, if it has one.