############### Ebyte M31 I/O ############### The ``driver/m31`` package defines one host and up to fifteen expansion modules. A module's slice index is its slot. The host has eight digital inputs and eight digital outputs. Mixed expansions add eight of each, input expansions add sixteen inputs, output expansions add sixteen outputs, and analog expansions add eight voltage outputs. Each point uses ``m{slot}.di{channel}``, ``m{slot}.do{channel}``, or ``m{slot}.ao{channel}``. Inputs, coils, and analog registers have independent zero-based address ranges that continue across modules. Analog registers represent zero through ten volts as zero through 10000. Hardware pulse widths are whole milliseconds from 50 through 65535. Their width registers start at ``0x30d4`` and their output-mode registers start at ``0x32c8``, both indexed by coil address. Mode zero is level control and mode one is pulse control. Descriptors use manufacturer ``ebyte`` and firmware ``unknown``. The package does not read the host identity registers. Pulse capabilities accept commands but do not report transient coil state. Input capabilities are read-only. Tests verify topology and descriptor values without a physical module. They do not confirm physical expansion limits or relay timing under load. The conservative sixteen-module limit includes the host. *************** Modbus client *************** ``NewTCPClient`` supplies a caller-owned, serialized connection through ``Client``. Connect selects the configured unit and has a two-second timeout. A request has a one-second write deadline and a two-second response deadline, both measured from its start. Caller deadlines and cancellation can stop it earlier. Each response must match the transaction, unit, function, length, and write acknowledgement. Supported functions are 01, 02, 03, 05, 15, and 16. No external Modbus package is required. In-memory stream tests check request bytes, response validation, exceptions, truncation, cancellation, and timeouts. They do not verify a physical host or TCP network behavior. ******************* Polling lifecycle ******************* ``New`` validates ``Settings`` and takes a shared publisher and a client. The caller runs both the publisher and the integration through ``driver.Run``. The command keeps its explicit driver list empty and does not open hardware connections. Every connection writes and reads back all digital output modes. Pulse outputs also write and verify their widths before online. The first complete read establishes a baseline without events. A later input change sends retained state followed by a pressed or released event. All events from one input read share its completion time, before coil and analog reads. A steady output or analog change sends reported state. Pulse coils do not send transient feedback. A device error publishes offline and retries after one second, doubling to thirty seconds until a complete baseline succeeds. Device failures do not log inside the integration. Publication and cleanup failures return to the runner. Cancellation closes the client without a false offline publication. Refresh requests cached snapshots through the shared publisher without repeating events or physical work. Polling can miss an edge that starts and ends between reads. It does not expose input counters. A configured poll interval is a target, not a guaranteed edge latency. Tests use fake clients and simulated time for baseline, transitions, pulse verification, reconnect, refresh, shutdown, and error propagation. Physical timing remains unverified.