5 The ``driver/m31`` package defines one host and up to fifteen expansion
6 modules. A module's slice index is its slot. The host has eight digital
7 inputs and eight digital outputs. Mixed expansions add eight of each,
8 input expansions add sixteen inputs, output expansions add sixteen
9 outputs, and analog expansions add eight voltage outputs.
11 Each point uses ``m{slot}.di{channel}``, ``m{slot}.do{channel}``, or
12 ``m{slot}.ao{channel}``. Inputs, coils, and analog registers have
13 independent zero-based address ranges that continue across modules.
14 Analog registers represent zero through ten volts as zero through 10000.
15 Hardware pulse widths are whole milliseconds from 50 through 65535.
16 Their width registers start at ``0x30d4`` and their output-mode
17 registers start at ``0x32c8``, both indexed by coil address. Mode zero
18 is level control and mode one is pulse control.
20 Descriptors use manufacturer ``ebyte`` and firmware ``unknown``. The
21 package does not read the host identity registers. Pulse capabilities
22 accept commands but do not report transient coil state. Input
23 capabilities are read-only.
25 Tests verify topology and descriptor values without a physical module.
26 They do not confirm physical expansion limits or relay timing under
27 load. The conservative sixteen-module limit includes the host.
33 ``NewTCPClient`` supplies a caller-owned, serialized connection through
34 ``Client``. Connect selects the configured unit and has a two-second
35 timeout. A request has a one-second write deadline and a two-second
36 response deadline, both measured from its start. Caller deadlines and
37 cancellation can stop it earlier. Each response must match the
38 transaction, unit, function, length, and write acknowledgement.
39 Supported functions are 01, 02, 03, 05, 15, and 16. No external Modbus
42 In-memory stream tests check request bytes, response validation,
43 exceptions, truncation, cancellation, and timeouts. They do not verify a
44 physical host or TCP network behavior.
50 ``New`` validates ``Settings`` and takes a shared publisher and a
51 client. The caller runs both the publisher and the integration through
52 ``driver.Run``. The command keeps its explicit driver list empty and
53 does not open hardware connections.
55 Every connection writes and reads back all digital output modes. Pulse
56 outputs also write and verify their widths before online. The first
57 complete read establishes a baseline without events. A later input
58 change sends retained state followed by a pressed or released event. All
59 events from one input read share its completion time, before coil and
60 analog reads. A steady output or analog change sends reported state.
61 Pulse coils do not send transient feedback.
63 A device error publishes offline and retries after one second, doubling
64 to thirty seconds until a complete baseline succeeds. Device failures do
65 not log inside the integration. Publication and cleanup failures return
66 to the runner. Cancellation closes the client without a false offline
67 publication. Refresh requests cached snapshots through the shared
68 publisher without repeating events or physical work.
70 Polling can miss an edge that starts and ends between reads. It does not
71 expose input counters. A configured poll interval is a target, not a
72 guaranteed edge latency. Tests use fake clients and simulated time for
73 baseline, transitions, pulse verification, reconnect, refresh, shutdown,
74 and error propagation. Physical timing remains unverified.
80 The shared router supplies one device FIFO for singles and batches. The
81 driver checks ownership, output access, value type, and expiry before
82 physical work. Steady outputs accept Boolean values. Pulse outputs
83 accept only true and complete after the function 05 acknowledgement,
84 without coil readback or transient reports. Analog outputs accept JSON
85 numbers from zero through ten volts and round them to millivolts. Exact
86 range checks precede floating-point conversion.
88 A batch accepts steady digital outputs only. It sorts eligible targets
89 by coil address, writes each contiguous range with function 15, and uses
90 function 05 for an isolated target. Gaps remain unchanged. It reads the
91 complete coil range once after all writes. A transport failure fails all
92 pending members, including those in an earlier successful range. A
93 mismatch fails only that member. Commands that expire before their write
94 are rejected. Physical writes also have the earliest member deadline.
96 Changed feedback is sent before results. Each changed commanded point
97 has its command ID as causation. Unrelated output changes have no
98 command cause. Equal feedback needs no second report. The framework
99 ledger records all outcomes before feedback or result publication, so a
100 failed send cannot cause another physical action on replay. A repeated
101 command reuses its first result ID, time, status, and reason. The ledger
102 is memory-only and bounded to 256 records for the assembly. An eviction
103 or process restart removes that duplicate protection.
105 Commands received during device backoff are rejected if invalid or
106 expired, and fail as unavailable otherwise. No command executes before
107 the connection setup and baseline complete. Shutdown does not retry a
108 physical action. Results use fixed failure reasons without transport
109 addresses or untrusted response data. Drivers return errors and do not
110 log them. Publication and independent cleanup failures stop the driver
113 Fake tests cover single writes, cross-bank batches, gaps, partial
114 transport failure, mismatches, pulses, analog boundaries, expired work,
115 cancellation, duplicate replay, and failed feedback or result sends.
116 They do not verify electrical simultaneity, contact timing, hardware
117 interlocks, or physical pulse width. Local motor protection remains
118 necessary when network commands control moving equipment.
120 A caller cancellation interrupts blocked transport work through its
121 deadline. A timeout caused only by that interruption is a context stop
122 for the runner. A joined independent transport or cleanup failure stays
123 a failure. Operation timeouts while the worker context is active remain
124 device failures and enter reconnect recovery.