# atMb API reference Generated from your working `CmpAtomModbus(1).export`. Documents every code object, including internal methods and property accessors. Runtime implementations, identifiers, declarations and embedded native payloads are preserved in the documented export; additions are comments only. ## atMbCall_cext External C ABI entry point used by the wrappers. Application code should normally call the function blocks. Do not change parameter order/types or external implementation settings. Pointers are accessed synchronously by C; provide distinct valid data/status buffers and truthful capacities. Client status requires 24 UDINT elements. All calls must be owned by one IEC task. ```iecst (* Create FUNCTION atMbCall_cext returning UDINT, paste this declaration. Properties > Build > External implementation must be selected. Library filename and Project Information title: CmpAtomModbus. This declaration is the SINGLE external entry point for the C engine. *) FUNCTION atMbCall_cext : UDINT VAR_INPUT command : UDINT; handle : UDINT; ipAddress : DWORD; port : UINT; unitId : BYTE; functionCode : BYTE; startAddress : UINT; quantity : UINT; pData : POINTER TO WORD; dataCapacity : UDINT; pStatus : POINTER TO UDINT; statusCapacity : UDINT; nowMs : ULINT; connectTimeoutMs : UDINT; responseTimeoutMs : UDINT; retryDelayMs : UDINT; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `command` | VAR_INPUT | `UDINT` | Native command selector. Use wrappers in application code. | | `handle` | VAR_INPUT | `UDINT` | Generation-checked native context handle; 0 for open. | | `ipAddress` | VAR_INPUT | `DWORD` | Packed IPv4 for TCP commands; command 20 overloads this field with RTU baud rate. | | `port` | VAR_INPUT | `UINT` | Slave listening port, default 502, must be nonzero. | | `unitId` | VAR_INPUT | `BYTE` | Transaction unit ID; command 20 overloads it with serial parity. | | `functionCode` | VAR_INPUT | `BYTE` | Modbus FC; command 20 uses data bits, server push/pull use table ID. | | `startAddress` | VAR_INPUT | `UINT` | Protocol start; command 20 uses stop bits. | | `quantity` | VAR_INPUT | `UINT` | Item count; command 20 uses serial path byte count. | | `pData` | VAR_INPUT | `POINTER TO WORD` | WORD buffer; client reads/writes, serial ASCII path, or server table staging. | | `dataCapacity` | VAR_INPUT | `UDINT` | Available WORD elements, not bytes. | | `pStatus` | VAR_INPUT | `POINTER TO UDINT` | UDINT status buffer; requires at least 24 elements. | | `statusCapacity` | VAR_INPUT | `UDINT` | Available UDINT elements, not bytes. | | `nowMs` | VAR_INPUT | `ULINT` | Monotonic time in milliseconds; wrappers use SysTimeGetUs / 1000. | | `connectTimeoutMs` | VAR_INPUT | `UDINT` | TCP connection timeout; command 20 uses kernel RS485 flag. | | `responseTimeoutMs` | VAR_INPUT | `UDINT` | Reply deadline in milliseconds. | | `retryDelayMs` | VAR_INPUT | `UDINT` | Native recovery wait in milliseconds. | ## ModbusMaster.ClientStatus Aggregate request status used by the RTU monitoring property: noneOk=0, someOk=1, allOk=2. This describes request online flags, not the physical connection. The current toString getter compares onlineCnt with all registered requests and reports allOk for an empty registry. ```iecst {attribute 'qualified_only'} {attribute 'strict'} TYPE ClientStatus : ( noneOk := 0, someOk := 1, allOk := 2 ); END_TYPE ``` ## ModbusMaster.Error IEC error classification. TCP-named socket/timeout members are also used for RTU failures. For the precise native reason inspect out_nativeError/out_lastNativeError; for an OS failure inspect out_socketError. ```iecst {attribute 'qualified_only'} TYPE Error : ( OK := 0, RequestParameterError := 1, TcpSocketError := 4, TcpConnectTimeout := 5, ReplyTimeout := 6, InvalidReply := 8, RequestException := 9, RequestCancelled := 10, InternalError := 255 ); END_TYPE ``` ## ModbusMaster.ExceptionCodes Modbus exception response values plus local TIMEOUT=-1. A valid Modbus exception proves communication, but the requested operation failed. In current statistics, non-exception errors can also be classified as TIMEOUT; use native diagnostics to distinguish their actual cause. ```iecst {attribute 'qualified_only'} TYPE ExceptionCodes : ( // Local / transport-level (non-Modbus) result TIMEOUT := -1, // Communication timeout / no response // Modbus exception codes (returned in exception response PDU) RESPONSE_SUCCESS := 16#00, // Everything OK (no exception) ILLEGAL_FUNCTION := 16#01, // Function code not supported by slave ILLEGAL_DATA_ADDRESS := 16#02, // Data address not valid for slave (out of range / not mapped) ILLEGAL_DATA_VALUE := 16#03, // Data value not valid (bad length/value/etc.) SLAVE_DEVICE_FAILURE := 16#04, // Unrecoverable error while performing the requested action ACKNOWLEDGE := 16#05, // Request accepted; processing started (use to avoid master timeout) SLAVE_DEVICE_BUSY := 16#06, // Slave busy (e.g. long operation in progress); retry later MEMORY_PARITY_ERROR := 16#08, // Memory parity error (special case; historically for FC 20/21) GATEWAY_PATH_UNAVAILABLE := 16#0A, // Gateway problem: path unavailable / misconfigured / overloaded GATEWAY_TARGET_DEVICE_FAILED_TO_RESPOND := 16#0B // Gateway problem: target device did not respond ); END_TYPE ``` ## ModbusMaster.ClientBase Abstract shared client scheduler and native transport owner. Use ClientTCP or ClientRTU. Holds up to 100 registered requests and runs one transaction at a time. Call the concrete client once per scan, from the same task as its requests. ```iecst {attribute 'monitoring_display' := 'toString'} {attribute 'no_assign'} FUNCTION_BLOCK ABSTRACT ClientBase VAR_INPUT {attribute 'symbol' := 'none'} in_timeout: TIME := T#0MS; // If this is set, this will be used on requests, otherwise it will be calculated from in_dataRate. {attribute 'symbol' := 'none'} in_resetStats: BOOL; // Set this bool to true to reset statistics. END_VAR VAR_OUTPUT {attribute 'symbol' := 'none'} msgLastSecondCnt: UDINT; //Messages in the last second {attribute 'symbol' := 'none'} msgLastSecondTime: UDINT; //Total amount of time for all messages sent last second in ms {attribute 'symbol' := 'none'} numMsgSent: UDINT; {attribute 'symbol' := 'none'} numMsgReply: UDINT; {attribute 'symbol' := 'none'} allRequestsOnline: BOOL; //All requests are working reqStats: ARRAY[0..99] OF POINTER TO RequestStats; // For debugging modbus requests END_VAR VAR dataRate : DINT; requests : ARRAY[0..99] OF POINTER TO RequestBase; requestCnt : UINT; allRequestsOffline : BOOL; END_VAR VAR nativeMode : BOOL; nativeHandle : UDINT; nativeIP : DWORD; nativePort : UINT; nativeNowMicroseconds : SYSTIME; nativeNowMilliseconds : ULINT; nativeStatus : ARRAY[0..23] OF UDINT; nativeActiveIndex : DINT := -1; nativeSelected : POINTER TO RequestBase; nativeResultReady : BOOL; nativeFinishedIndex : DINT := -1; nativeWindowStartMilliseconds : ULINT; nativeWasConnected : BOOL; nativeEnable : BOOL := TRUE; nativeConnectTimeoutMilliseconds : UDINT := 2000; nativeRetryDelayMilliseconds : UDINT := 100; nativeHoldUncertainWrites : BOOL := FALSE; END_VAR VAR_INPUT {attribute 'symbol' := 'none'} nativeIO : ARRAY[0..1999] OF WORD; {attribute 'symbol' := 'none'} nativeActiveRequest : POINTER TO RequestBase; {attribute 'symbol' := 'none'} nativeArgUnit : BYTE; {attribute 'symbol' := 'none'} nativeArgFunction : BYTE; {attribute 'symbol' := 'none'} nativeArgAddress : UINT; {attribute 'symbol' := 'none'} nativeArgQuantity : UINT; {attribute 'symbol' := 'none'} nativeArgTimeout : UDINT := 1000; {attribute 'symbol' := 'none'} nativeSent : UDINT; {attribute 'symbol' := 'none'} nativeReplied : UDINT; {attribute 'symbol' := 'none'} nativeWindowCount : UDINT; {attribute 'symbol' := 'none'} nativeWindowTime : UDINT; END_VAR VAR_OUTPUT out_connected : BOOL; out_connectionState : UDINT; out_lastNativeError : UDINT; out_socketError : UDINT; out_reconnectCount : UDINT; out_registrationFull : BOOL; END_VAR VAR CONSTANT NATIVE_CMD_OPEN : UDINT := 1; NATIVE_CMD_CLOSE : UDINT := 2; NATIVE_CMD_ENABLE : UDINT := 3; NATIVE_CMD_TICK : UDINT := 5; NATIVE_CMD_SUBMIT : UDINT := 6; NATIVE_CMD_COPY_READ : UDINT := 7; NATIVE_CMD_CONFIGURE : UDINT := 9; NATIVE_CMD_ACKNOWLEDGE : UDINT := 10; NATIVE_CMD_REQUEST_TIMEOUT : UDINT := 11; NATIVE_STATE_DISABLED : UDINT := 0; NATIVE_STATE_READY : UDINT := 3; NATIVE_STATE_RECEIVING : UDINT := 5; NATIVE_ERROR_INVALID_HANDLE : UDINT := 256; NATIVE_ERROR_CANCELLED : UDINT := 10; NATIVE_STATUS_HANDLE : UDINT := 0; NATIVE_STATUS_STATE : UDINT := 1; NATIVE_STATUS_DONE : UDINT := 3; NATIVE_STATUS_ERROR : UDINT := 4; NATIVE_STATUS_RESULT : UDINT := 5; NATIVE_STATUS_LAST_ERROR : UDINT := 6; NATIVE_STATUS_SOCKET_ERROR : UDINT := 7; NATIVE_STATUS_EXCEPTION : UDINT := 8; NATIVE_STATUS_WRITE_UNCERTAIN : UDINT := 9; NATIVE_STATUS_RECONNECTS : UDINT := 11; NATIVE_STATUS_FUNCTION : UDINT := 18; END_VAR VAR nativeOpenCommand : UDINT := 1; nativeDevice : STRING(127); nativeSerialBaud : UDINT; nativeSerialParity : BYTE; nativeSerialBits : BYTE; nativeSerialStops : BYTE; nativeSerialRs485 : UDINT; END_VAR VAR_INPUT in_enable : BOOL := TRUE; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `in_timeout` | VAR_INPUT | `TIME := T#0MS` | Reply timeout override. ClientBase: TIME; RequestBase: SYSTIME numeric milliseconds (not microseconds). Zero selects inherited/calculated timeout. | | `in_resetStats` | VAR_INPUT | `BOOL` | Reset request consumed and cleared by nativeCycle. Supplying TRUE on every call resets statistics every scan; pulse once. | | `msgLastSecondCnt` | VAR_OUTPUT | `UDINT` | Submitted request count in the last completed window of at least 1000 ms, not necessarily an exact sliding second. | | `msgLastSecondTime` | VAR_OUTPUT | `UDINT` | Sum of successful transaction durations in that completed window (ms); excludes failed durations. | | `numMsgSent` | VAR_OUTPUT | `UDINT` | IEC accepted submission count since resetStats; not a count of physical packets. | | `numMsgReply` | VAR_OUTPUT | `UDINT` | IEC successful or Modbus-exception reply count since resetStats. | | `allRequestsOnline` | VAR_OUTPUT | `BOOL` | TRUE when at least one active request exists and onlineCnt equals activeReqCnt. Online can include exception replies. | | `reqStats` | VAR_OUTPUT | `ARRAY[0..99] OF POINTER TO RequestStats` | Pointers to registered request statistics by registry index, populated on client scans. Null entries are unused; validate before dereference. | | `nativeIO` | VAR_INPUT | `ARRAY[0..1999] OF WORD` | Internal wrapper state exposed for compatibility; normally leave under library control. | | `nativeActiveRequest` | VAR_INPUT | `POINTER TO RequestBase` | Internal wrapper state exposed for compatibility; normally leave under library control. | | `nativeArgUnit` | VAR_INPUT | `BYTE` | Internal wrapper state exposed for compatibility; normally leave under library control. | | `nativeArgFunction` | VAR_INPUT | `BYTE` | Internal wrapper state exposed for compatibility; normally leave under library control. | | `nativeArgAddress` | VAR_INPUT | `UINT` | Internal wrapper state exposed for compatibility; normally leave under library control. | | `nativeArgQuantity` | VAR_INPUT | `UINT` | Internal wrapper state exposed for compatibility; normally leave under library control. | | `nativeArgTimeout` | VAR_INPUT | `UDINT := 1000` | Internal wrapper state exposed for compatibility; normally leave under library control. | | `nativeSent` | VAR_INPUT | `UDINT` | Internal wrapper state exposed for compatibility; normally leave under library control. | | `nativeReplied` | VAR_INPUT | `UDINT` | Internal wrapper state exposed for compatibility; normally leave under library control. | | `nativeWindowCount` | VAR_INPUT | `UDINT` | Internal wrapper state exposed for compatibility; normally leave under library control. | | `nativeWindowTime` | VAR_INPUT | `UDINT` | Internal wrapper state exposed for compatibility; normally leave under library control. | | `out_connected` | VAR_OUTPUT | `BOOL` | Transport is in ready/sending/receiving state. Does not prove a request succeeded or data is fresh. | | `out_connectionState` | VAR_OUTPUT | `UDINT` | 0 disabled, 1 retry wait, 2 TCP connecting, 3 ready, 4 sending, 5 receiving. | | `out_lastNativeError` | VAR_OUTPUT | `UDINT` | Native last transport error; may persist after recovery. Check current connection and request diagnostics too. | | `out_socketError` | VAR_OUTPUT | `UDINT` | Native Linux errno snapshot as UDINT; may be historical. Used for both serial and sockets. | | `out_reconnectCount` | VAR_OUTPUT | `UDINT` | Native successful reconnections after the first connection. Context recreation resets its native lifetime counters. | | `out_registrationFull` | VAR_OUTPUT | `BOOL` | Sticky request registry overflow indicator; max 100 requests/client. Client reinitialization clears it. | | `in_enable` | VAR_INPUT | `BOOL := TRUE` | Enable processing; TRUE by default. FALSE releases transport. Continue scanning to refresh state. | ## ModbusMaster.ClientRTU Modbus RTU client using a Linux serial device. Call every scan. Supports 8 data bits, parity 0 none/1 odd/2 even, and 1 or 2 stop bits. Uses unit IDs 1..247; broadcast 0 is unsupported. Serial-setting changes recreate the context. Automatic recovery proceeds while enabled and scanned. ```iecst {attribute 'no_assign'} FUNCTION_BLOCK ClientRTU EXTENDS ClientBase VAR_INPUT in_device : STRING(127) := '/dev/ttyUSB0'; in_baudRate : UDINT := 9600; in_parity : BYTE := 0; // 0 none, 1 odd, 2 even in_dataBits : BYTE := 8; in_stopBits : BYTE := 1; // 1 or 2 in_rs485 : BOOL; // Request Linux kernel RS485 direction control. in_reconnectDelay : TIME := T#100MS; in_holdUncertainWrites : BOOL := FALSE; END_VAR VAR lastDevice : STRING(127); lastBaud : UDINT; lastParity : BYTE; lastBits : BYTE; lastStops : BYTE; lastRs485 : BOOL; lastRetry : TIME; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `in_device` | VAR_INPUT | `STRING(127) := '/dev/ttyUSB0'` | Linux serial device path, default /dev/ttyUSB0, at most 127 ASCII characters. Runtime account needs access. | | `in_baudRate` | VAR_INPUT | `UDINT := 9600` | Serial baud rate, default 9600. Supplied C source accepts 1200,2400,4800,9600,19200,38400,57600,115200. | | `in_parity` | VAR_INPUT | `BYTE := 0` | 0 none, 1 odd, 2 even. Must match the slave. | | `in_dataBits` | VAR_INPUT | `BYTE := 8` | Only 8 supported by supplied native implementation. | | `in_stopBits` | VAR_INPUT | `BYTE := 1` | 1 or 2; must match the slave. | | `in_rs485` | VAR_INPUT | `BOOL` | Request Linux kernel RS485 direction control. Leave FALSE for USB adapters handling direction automatically. Requires driver support. | | `in_reconnectDelay` | VAR_INPUT | `TIME := T#100MS` | Delay before native recovery attempt, default 100 ms; clamped to at least 1 ms. Effective timing also depends on scan interval and failure detection. | | `in_holdUncertainWrites` | VAR_INPUT | `BOOL := FALSE` | FALSE allows normal retries after uncertain writes. TRUE holds affected write requests until writeNow(); read requests can continue. | ## ModbusMaster.ClientTCP Modbus TCP client with automatic retry after connection or transaction failure. Call every scan. Endpoint or timeout/retry configuration changes close the current context and reopen it on subsequent scans. Requests share this connection and execute sequentially. ```iecst {attribute 'no_assign'} FUNCTION_BLOCK ClientTCP EXTENDS ClientBase VAR_INPUT {attribute 'symbol' := 'none'} in_ipAddress: ARRAY[0..3] OF BYTE; // TCP IP Address {attribute 'symbol' := 'none'} in_port: UINT := 502; // TCP port {attribute 'symbol' := 'none'} in_baudrate: UINT := 0; // Set this if using RS485 to TCP Converter, used to calculate timeout. END_VAR VAR_INPUT in_connectTimeout : TIME := T#2S; in_reconnectDelay : TIME := T#100MS; // Delay after a failed TCP connection/transaction. in_holdUncertainWrites : BOOL := FALSE; END_VAR VAR nativeEndpointIP : DWORD; nativeEndpointPort : UINT; nativeConfigConnect : UDINT; nativeConfigRetry : UDINT; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `in_ipAddress` | VAR_INPUT | `ARRAY[0..3] OF BYTE` | ClientTCP: four IPv4 bytes. Slave: packed numeric DWORD, 0 binds all interfaces; e.g. DWORD#16#C0A8321F for 192.168.50.31. | | `in_port` | VAR_INPUT | `UINT := 502` | Remote TCP port, default 502. | | `in_baudrate` | VAR_INPUT | `UINT := 0` | TCP gateway serial baud-rate hint for calculated reply timeout; 0 uses internal dataRate 105200. Does not configure a serial port. | | `in_connectTimeout` | VAR_INPUT | `TIME := T#2S` | TCP connection-attempt deadline, default 2 s; clamped to at least 1 ms. | | `in_reconnectDelay` | VAR_INPUT | `TIME := T#100MS` | Delay before native recovery attempt, default 100 ms; clamped to at least 1 ms. Effective timing also depends on scan interval and failure detection. | | `in_holdUncertainWrites` | VAR_INPUT | `BOOL := FALSE` | FALSE allows normal retries after uncertain writes. TRUE holds affected write requests until writeNow(); read requests can continue. | ## ModbusMaster.ReqReadCoil Modbus FC 1: read BOOL coils. Call every scan with a client reference and data array. Protocol start address is zero-based; in_dataOffset is the actual array index. Maximum transaction length is 2000. Usable length is clamped to array capacity. Only a successful validated reply updates the destination slice. Old values remain after failures; check out_validData and out_stale. ```iecst {attribute 'no_assign'} FUNCTION_BLOCK ReqReadCoil EXTENDS RequestBase VAR_IN_OUT // ARRAY[] OF BOOL to hold received data {attribute 'symbol' := 'none'} data: ARRAY[*] OF BOOL; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `data` | VAR_IN_OUT | `ARRAY[*] OF BOOL` | Open array: BOOL for coils/discretes; UINT for registers. Stable VAR_IN_OUT storage. Writes snapshot values at submission; reads replace only their successful slice. | ## ModbusMaster.ReqReadDiscrete Modbus FC 2: read BOOL discrete inputs. Call every scan with a client reference and data array. Protocol start address is zero-based; in_dataOffset is the actual array index. Maximum transaction length is 2000. Usable length is clamped to array capacity. Only a successful validated reply updates the destination slice. Old values remain after failures; check out_validData and out_stale. ```iecst {attribute 'no_assign'} FUNCTION_BLOCK ReqReadDiscrete EXTENDS RequestBase VAR_IN_OUT // ARRAY[] OF BOOL to hold received data {attribute 'symbol' := 'none'} data: ARRAY[*] OF BOOL; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `data` | VAR_IN_OUT | `ARRAY[*] OF BOOL` | Open array: BOOL for coils/discretes; UINT for registers. Stable VAR_IN_OUT storage. Writes snapshot values at submission; reads replace only their successful slice. | ## ModbusMaster.ReqReadHolding Modbus FC 3: read UINT holding registers. Call every scan with a client reference and data array. Protocol start address is zero-based; in_dataOffset is the actual array index. Maximum transaction length is 125. Usable length is clamped to array capacity. Only a successful validated reply updates the destination slice. Old values remain after failures; check out_validData and out_stale. ```iecst {attribute 'no_assign'} FUNCTION_BLOCK ReqReadHolding EXTENDS RequestBase VAR_IN_OUT // ARRAY[] OF UINT to hold received data {attribute 'symbol' := 'none'} data: ARRAY[*] OF UINT; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `data` | VAR_IN_OUT | `ARRAY[*] OF UINT` | Open array: BOOL for coils/discretes; UINT for registers. Stable VAR_IN_OUT storage. Writes snapshot values at submission; reads replace only their successful slice. | ## ModbusMaster.ReqReadInput Modbus FC 4: read UINT input registers. Call every scan with a client reference and data array. Protocol start address is zero-based; in_dataOffset is the actual array index. Maximum transaction length is 125. Usable length is clamped to array capacity. Only a successful validated reply updates the destination slice. Old values remain after failures; check out_validData and out_stale. ```iecst {attribute 'no_assign'} FUNCTION_BLOCK ReqReadInput EXTENDS RequestBase VAR_IN_OUT // ARRAY[] OF UINT to hold received data {attribute 'symbol' := 'none'} data: ARRAY[*] OF UINT; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `data` | VAR_IN_OUT | `ARRAY[*] OF UINT` | Open array: BOOL for coils/discretes; UINT for registers. Stable VAR_IN_OUT storage. Writes snapshot values at submission; reads replace only their successful slice. | ## ModbusMaster.RequestBase Abstract request binding, scheduling and diagnostics. Derived requests register automatically when called with a valid initialized client. Call each instance every scan with stable array storage. Quantity zero disables this request. Actual length is MIN(in_quantity, remaining array capacity). ```iecst {attribute 'no_assign'} FUNCTION_BLOCK ABSTRACT RequestBase VAR_INPUT {attribute 'symbol' := 'none'} client: REFERENCE TO ClientBase; // Instance of atMBClient {attribute 'symbol' := 'none'} in_startAddr: UINT; {attribute 'symbol' := 'none'} in_quantity: UINT; {attribute 'symbol' := 'none'} in_dataOffset: UINT; // Offset position for data into array. {attribute 'symbol' := 'none'} in_unitId: BYTE := 0; {attribute 'symbol' := 'none'} in_timeout: SYSTIME := 0; // Reply timeout in ms; zero uses client/default calculation. {attribute 'symbol' := 'none'} in_minDelay: TIME := T#10MS; // This is the minimum delay between queries, only relevent if high priority. {attribute 'symbol' := 'none'} in_prioritySetpoint: INT := 50; // this requests priority compared to other requests. Lower value is higher priority. {attribute 'symbol' := 'none'} in_priorityCurrent: INT; //Current priority. This is decrimented and the request is executed when at zero. {attribute 'symbol' := 'none'} stats: RequestStats; //Request stats END_VAR VAR {attribute 'symbol' := 'none'} dataCapacity: UINT; END_VAR VAR nativeFunction : BYTE; nativeTransactionQuantity : UINT; nativeTransactionDataIndex : UINT; nativeInFlight : BOOL; nativeReadComplete : BOOL; nativeCopyAllowed : BOOL; nativeWriteHold : BOOL; nativeRequestStartMilliseconds : ULINT; nativeDataIndex : DINT; nativeCallResult : UDINT; END_VAR VAR_OUTPUT out_nativeError : UDINT; out_socketError : UDINT; out_writeUncertain : BOOL; out_validData : BOOL; out_dataAgeMs : ULINT; out_stale : BOOL := TRUE; out_parameterError : BOOL; END_VAR VAR_INPUT in_staleAfter : TIME := T#2S; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `client` | VAR_INPUT | `REFERENCE TO ClientBase` | Reference to the owning ClientBase concrete instance. Initialize/call client before first registration; retain a stable instance. | | `in_startAddr` | VAR_INPUT | `UINT` | Zero-based Modbus protocol address, not a 40001/30001 display reference. Must fit the transaction into address space. | | `in_quantity` | VAR_INPUT | `UINT` | Requested item count; actual stats.reqLength is MIN(this, available destination/source capacity). Zero makes the request inactive. | | `in_dataOffset` | VAR_INPUT | `UINT` | Actual first index in the application array. For ARRAY[1..10], use 1 to start at the first element; not a relative offset. | | `in_unitId` | VAR_INPUT | `BYTE := 0` | Modbus unit/slave ID, default 0. RTU requires explicit 1..247; TCP/gateway values depend on the target. | | `in_timeout` | VAR_INPUT | `SYSTIME := 0` | Reply timeout override. ClientBase: TIME; RequestBase: SYSTIME numeric milliseconds (not microseconds). Zero selects inherited/calculated timeout. | | `in_minDelay` | VAR_INPUT | `TIME := T#10MS` | Minimum start-to-start time before scheduler eligibility, default 10 ms. Not a fixed polling period. | | `in_prioritySetpoint` | VAR_INPUT | `INT := 50` | Priority restored on success, default 50. Lower values win. Error backoff can replace current priority. | | `in_priorityCurrent` | VAR_INPUT | `INT` | Mutable scheduler priority. Lower values win, equal values use age. WriteNow sets 0. Application need not maintain it each scan. | | `stats` | VAR_INPUT | `RequestStats` | Per-request RequestStats instance maintained by request processing; inspect rather than overwrite. | | `out_nativeError` | VAR_OUTPUT | `UDINT` | Result of the last completed/failed request; 0 success. Precise native code, distinct from IEC Error enum. | | `out_socketError` | VAR_OUTPUT | `UDINT` | Native Linux errno snapshot as UDINT; may be historical. Used for both serial and sockets. | | `out_writeUncertain` | VAR_OUTPUT | `BOOL` | Write may have reached target without a confirmed response. It is not proof of failure or success. Relevant for write requests. | | `out_validData` | VAR_OUTPUT | `BOOL` | TRUE after a successful read; subsequent read failures do not necessarily clear it. Client release or invalidateNativeData clears it. | | `out_dataAgeMs` | VAR_OUTPUT | `ULINT` | Age since last successful read in milliseconds. Updated by normal processing; completion early returns can defer refresh by one scan. | | `out_stale` | VAR_OUTPUT | `BOOL := TRUE` | TRUE before valid read data or when age exceeds in_staleAfter. Array contents are retained. | | `out_parameterError` | VAR_OUTPUT | `BOOL` | Array-offset validation for requests; full transaction validation can instead appear in out_nativeError/stats.lastErrorId. Slave: invalid port/interfaceName/table bounds or capacity. | | `in_staleAfter` | VAR_INPUT | `TIME := T#2S` | Read data age threshold, default 2 s. out_stale becomes TRUE when age is strictly greater; does not stop polling. | ## ModbusMaster.RequestStats Request counters, completion properties, online/offline tracking and 100 ms indicator lights. Normally maintained by RequestBase. Online means a valid response was received, including a Modbus exception; it does not guarantee successful data. Several fields are declared VAR_INPUT for compatibility but are maintained internally. ```iecst {attribute 'monitoring_display' := 'toString'} {attribute 'no_assign'} FUNCTION_BLOCK RequestStats VAR_INPUT lastErrorId: Error; //Last error id lastExceptionCode: ExceptionCodes; //Last modbus exception code. These are the standard modbus exceptions. lastValidDuration: UDINT; // How long last transaction took (ms) longestValidDuration: UDINT; //Longest valid duration (ms) interval: UDINT; // Start-to-start interval (ms) offlineCnt: UINT; //Count of how many times this request has gone offline doneCnt: UDINT; // Count of successful request errorCnt: UDINT; // Count of failed requests doneCntRst: UDINT; // Count of succesful requests, resets on error result errorCntRst: UDINT; // Count of failed requests, resets on succesful request sinceLastExec: UDINT; // Time since the last start (ms) timeoutCnt: UDINT; reqLength: UINT; //Number of registers requested in request, used to calc active. END_VAR VAR_OUTPUT executeLight: BOOL; //Execute that stays on momentarily reqDoneLight: BOOL; //Request done that stays on momentarily reqErrorLight: BOOL; //Request error that stays on momentarily reqBusyLight: BOOL; //Request busy that stays on momentarily online: BOOL; //Online means the requests are being replied to normally or with modbus exceptions. Communications are ok. offline: BOOL; //Opposite of online, but starts out as false on program start. active: BOOL; // This is true if its actually being used, and not having a count of 0 on the request. executeMbFb: BOOL; END_VAR VAR {attribute 'symbol' := 'none'} doneIndicatorDelay: TOF; {attribute 'symbol' := 'none'} errorIndicatorDelay: TOF; {attribute 'symbol' := 'none'} busyIndicatorDelay: TOF; {attribute 'symbol' := 'none'} executeIndicatorDelay: TOF; toString: STRING(20); {attribute 'symbol' := 'none'} executeTrig: R_TRIG; //Execute trigger {attribute 'symbol' := 'none'} offlineTrig: R_TRIG; //Offline trigger {attribute 'symbol' := 'none'} lastRequestStartMicroseconds: SYSTIME; //time of start of last request {attribute 'symbol' := 'none'} currentTimeMicroseconds: SYSTIME; _execute: BOOL; //Execute trigger and status. Turn on to trigger request. Will turn off when request is complete _reqDone: BOOL; //Request done _reqBusy: BOOL; //Request busy _reqError: BOOL; //Request error END_VAR VAR CONSTANT {attribute 'symbol' := 'none'} INDICATOR_HOLD_TIME: TIME:= T#100MS; //Light on time for debug indicators END_VAR VAR_INPUT nativeResponseSeen : BOOL; nativeLastSuccessMs : ULINT; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `lastErrorId` | VAR_INPUT | `Error` | Last mapped IEC error; successful completion resets to OK. | | `lastExceptionCode` | VAR_INPUT | `ExceptionCodes` | Last Modbus exception, success=0; stats may substitute TIMEOUT=-1 for non-exception failures. | | `lastValidDuration` | VAR_INPUT | `UDINT` | Last successful request duration (ms). | | `longestValidDuration` | VAR_INPUT | `UDINT` | Maximum successful duration recorded; resetStats does not clear it. | | `interval` | VAR_INPUT | `UDINT` | Start-to-start execution interval (ms). | | `offlineCnt` | VAR_INPUT | `UINT` | Count of NOT online rising edges; can include initial not-online state, not only a physical disconnect. | | `doneCnt` | VAR_INPUT | `UDINT` | Total successful completions; resetStats clears. | | `errorCnt` | VAR_INPUT | `UDINT` | Total failed completions; resetStats clears. | | `doneCntRst` | VAR_INPUT | `UDINT` | Consecutive successes; reset on error/offline/resetStats. | | `errorCntRst` | VAR_INPUT | `UDINT` | Consecutive errors; reset on successful completion/resetStats. | | `sinceLastExec` | VAR_INPUT | `UDINT` | Age since last execution start (ms), capped around 60000 by the statistics clock logic. | | `timeoutCnt` | VAR_INPUT | `UDINT` | Statistics non-exception error count; can include other native failures. Not exclusively reply timeouts; resetStats does not clear it. | | `reqLength` | VAR_INPUT | `UINT` | Effective transaction length; zero means inactive. | | `executeLight` | VAR_OUTPUT | `BOOL` | Execution indicator with 100 ms off-delay. | | `reqDoneLight` | VAR_OUTPUT | `BOOL` | Completion indicator with 100 ms off-delay. | | `reqErrorLight` | VAR_OUTPUT | `BOOL` | Error indicator with 100 ms off-delay. | | `reqBusyLight` | VAR_OUTPUT | `BOOL` | Busy indicator with 100 ms off-delay. | | `online` | VAR_OUTPUT | `BOOL` | Communication status; valid normal/exception response sets evidence. Distinct from valid data. | | `offline` | VAR_OUTPUT | `BOOL` | Offline status; initialized FALSE, explicitly set on client-offline or repeated failures. | | `active` | VAR_OUTPUT | `BOOL` | TRUE when reqLength is nonzero. | | `executeMbFb` | VAR_OUTPUT | `BOOL` | Legacy retained output; no assignment in current native implementation. Do not use as a trigger. | | `nativeResponseSeen` | VAR_INPUT | `BOOL` | Internal communication-response evidence, maintained by nativeFinish and offline handling. | | `nativeLastSuccessMs` | VAR_INPUT | `ULINT` | Internal successful-read timestamp in monotonic milliseconds. | ## ModbusMaster.ReqWriteCoil Modbus FC 15: write BOOL coils. Call every scan with a client reference and data array. Protocol start address is zero-based; in_dataOffset is the actual array index. Maximum transaction length is 1968. Usable length is clamped to array capacity. Values are copied into native storage at submission. This FB uses the multiple-write FC even for one element. Use writeNow() to release a held uncertain write. ```iecst {attribute 'no_assign'} FUNCTION_BLOCK ReqWriteCoil EXTENDS RequestBase VAR_IN_OUT // ARRAY[] OF BOOL to hold received data {attribute 'symbol' := 'none'} data: ARRAY[*] OF BOOL; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `data` | VAR_IN_OUT | `ARRAY[*] OF BOOL` | Open array: BOOL for coils/discretes; UINT for registers. Stable VAR_IN_OUT storage. Writes snapshot values at submission; reads replace only their successful slice. | ## ModbusMaster.ReqWriteHolding Modbus FC 16: write UINT holding registers. Call every scan with a client reference and data array. Protocol start address is zero-based; in_dataOffset is the actual array index. Maximum transaction length is 123. Usable length is clamped to array capacity. Values are copied into native storage at submission. This FB uses the multiple-write FC even for one element. Use writeNow() to release a held uncertain write. ```iecst {attribute 'no_assign'} FUNCTION_BLOCK ReqWriteHolding EXTENDS RequestBase VAR_IN_OUT // ARRAY[] OF UINT to hold received data {attribute 'symbol' := 'none'} data: ARRAY[*] OF UINT; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `data` | VAR_IN_OUT | `ARRAY[*] OF UINT` | Open array: BOOL for coils/discretes; UINT for registers. Stable VAR_IN_OUT storage. Writes snapshot values at submission; reads replace only their successful slice. | ## ModbusMaster.To_IPAddress Returns the four supplied bytes as ARRAY[0..3] OF BYTE. Example: atMb.To_IPAddress(192,168,50,10). This is the ClientTCP address format; the slave bind address instead uses a packed DWORD. ```iecst FUNCTION To_IPAddress : ARRAY[0..3] OF BYTE VAR_INPUT byte1: BYTE; byte2: BYTE; byte3: BYTE; byte4: BYTE; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `byte1` | VAR_INPUT | `BYTE` | First IPv4 octet. | | `byte2` | VAR_INPUT | `BYTE` | Second IPv4 octet. | | `byte3` | VAR_INPUT | `BYTE` | Third IPv4 octet. | | `byte4` | VAR_INPUT | `BYTE` | Fourth IPv4 octet. | ## ModbusSlave.ModbusSlave Native Modbus TCP server. Same implementation and interface as SlaveTCP. Call once per scan with all four memory arrays. Array bounds are protocol addresses; each table is limited to 2000 elements and addresses 0..65535. Pushes application memory, performs bounded network processing, then copies native memory back. This is TCP only, not an RTU slave. ```iecst {attribute 'no_assign'} FUNCTION_BLOCK ModbusSlave VAR_IN_OUT aDiscreteInputsMemory : ARRAY[*] OF BOOL; aCoilsMemory : ARRAY[*] OF BOOL; aInputRegistersMemory : ARRAY[*] OF UINT; aHoldingRegistersMemory : ARRAY[*] OF UINT; END_VAR VAR_INPUT in_enable : BOOL := TRUE; in_reset : BOOL; in_reconnectDelay : TIME := T#100MS; interfaceName : WSTRING; // Legacy field; nonempty rejected. Use in_ipAddress. in_ipAddress : DWORD; // Numeric bind IP, 0 = all interfaces. port : UINT := 502; END_VAR VAR_OUTPUT out_running : BOOL; out_error : BOOL; out_errorId : Error; out_parameterError : BOOL; out_socketError : UDINT; out_connectedClients : UINT; out_requestsReceived : UDINT; out_repliesSent : UDINT; out_exceptionReplies : UDINT; END_VAR VAR serverHandle : UDINT; serverStatus : ARRAY[0..23] OF UDINT; serverIO : ARRAY[0..1999] OF WORD; nowUs : SYSTIME; nowMs : ULINT; lastIP : DWORD; lastPort : UINT; lastRetry : TIME; callResult : UDINT; tableIndex : BYTE; itemIndex : DINT; tableStart : UINT; tableCount : UINT; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `aDiscreteInputsMemory` | VAR_IN_OUT | `ARRAY[*] OF BOOL` | Read-only from network BOOL input table; FC2 reads. Application updates it. | | `aCoilsMemory` | VAR_IN_OUT | `ARRAY[*] OF BOOL` | Read/write BOOL coil table. Array bounds are protocol addresses; FC1 reads, FC5/15 write. | | `aInputRegistersMemory` | VAR_IN_OUT | `ARRAY[*] OF UINT` | Read-only from network UINT input table; FC4 reads. Application updates it. | | `aHoldingRegistersMemory` | VAR_IN_OUT | `ARRAY[*] OF UINT` | Read/write UINT holding table; FC3 reads, FC6/16 write. | | `in_enable` | VAR_INPUT | `BOOL := TRUE` | Enable processing; TRUE by default. FALSE releases transport. Continue scanning to refresh state. | | `in_reset` | VAR_INPUT | `BOOL` | Slave one-shot recreation input. FB clears it internally; supplying TRUE every scan recreates every scan. | | `in_reconnectDelay` | VAR_INPUT | `TIME := T#100MS` | Delay before native recovery attempt, default 100 ms; clamped to at least 1 ms. Effective timing also depends on scan interval and failure detection. | | `interfaceName` | VAR_INPUT | `WSTRING` | Legacy slave field. Must be empty; nonempty is rejected. Use packed in_ipAddress instead. | | `in_ipAddress` | VAR_INPUT | `DWORD` | ClientTCP: four IPv4 bytes. Slave: packed numeric DWORD, 0 binds all interfaces; e.g. DWORD#16#C0A8321F for 192.168.50.31. | | `port` | VAR_INPUT | `UINT := 502` | Slave listening port, default 502, must be nonzero. | | `out_running` | VAR_OUTPUT | `BOOL` | Native listener is bound and enabled. Does not mean a peer is connected. | | `out_error` | VAR_OUTPUT | `BOOL` | Current server error flag when outputs are refreshed; some early returns leave other diagnostics unchanged. | | `out_errorId` | VAR_OUTPUT | `Error` | IEC server error classification: parameter/internal/native socket class. Consult errno for OS detail. | | `out_parameterError` | VAR_OUTPUT | `BOOL` | Array-offset validation for requests; full transaction validation can instead appear in out_nativeError/stats.lastErrorId. Slave: invalid port/interfaceName/table bounds or capacity. | | `out_socketError` | VAR_OUTPUT | `UDINT` | Native Linux errno snapshot as UDINT; may be historical. Used for both serial and sockets. | | `out_connectedClients` | VAR_OUTPUT | `UINT` | Number of native TCP peers connected (max 8 per server in supplied C source). | | `out_requestsReceived` | VAR_OUTPUT | `UDINT` | Native request count for current server context. | | `out_repliesSent` | VAR_OUTPUT | `UDINT` | Native fully transmitted reply count for current context, including exception replies. | | `out_exceptionReplies` | VAR_OUTPUT | `UDINT` | Number of Modbus exception replies for current server context. | ## ModbusSlave.SlaveTCP Native Modbus TCP server with four separate memory tables. Same implementation and interface as ModbusSlave. FC 1/2/3/4 read the tables; FC 5/6/15/16 write coils/holding registers. Array lower bounds define Modbus addresses. Call every scan and retain array storage. This is TCP only. ```iecst {attribute 'no_assign'} FUNCTION_BLOCK SlaveTCP VAR_IN_OUT aDiscreteInputsMemory : ARRAY[*] OF BOOL; aCoilsMemory : ARRAY[*] OF BOOL; aInputRegistersMemory : ARRAY[*] OF UINT; aHoldingRegistersMemory : ARRAY[*] OF UINT; END_VAR VAR_INPUT in_enable : BOOL := TRUE; in_reset : BOOL; in_reconnectDelay : TIME := T#100MS; interfaceName : WSTRING; // Legacy field; nonempty rejected. Use in_ipAddress. in_ipAddress : DWORD; // Numeric bind IP, 0 = all interfaces. port : UINT := 502; END_VAR VAR_OUTPUT out_running : BOOL; out_error : BOOL; out_errorId : Error; out_parameterError : BOOL; out_socketError : UDINT; out_connectedClients : UINT; out_requestsReceived : UDINT; out_repliesSent : UDINT; out_exceptionReplies : UDINT; END_VAR VAR serverHandle : UDINT; serverStatus : ARRAY[0..23] OF UDINT; serverIO : ARRAY[0..1999] OF WORD; nowUs : SYSTIME; nowMs : ULINT; lastIP : DWORD; lastPort : UINT; lastRetry : TIME; callResult : UDINT; tableIndex : BYTE; itemIndex : DINT; tableStart : UINT; tableCount : UINT; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `aDiscreteInputsMemory` | VAR_IN_OUT | `ARRAY[*] OF BOOL` | Read-only from network BOOL input table; FC2 reads. Application updates it. | | `aCoilsMemory` | VAR_IN_OUT | `ARRAY[*] OF BOOL` | Read/write BOOL coil table. Array bounds are protocol addresses; FC1 reads, FC5/15 write. | | `aInputRegistersMemory` | VAR_IN_OUT | `ARRAY[*] OF UINT` | Read-only from network UINT input table; FC4 reads. Application updates it. | | `aHoldingRegistersMemory` | VAR_IN_OUT | `ARRAY[*] OF UINT` | Read/write UINT holding table; FC3 reads, FC6/16 write. | | `in_enable` | VAR_INPUT | `BOOL := TRUE` | Enable processing; TRUE by default. FALSE releases transport. Continue scanning to refresh state. | | `in_reset` | VAR_INPUT | `BOOL` | Slave one-shot recreation input. FB clears it internally; supplying TRUE every scan recreates every scan. | | `in_reconnectDelay` | VAR_INPUT | `TIME := T#100MS` | Delay before native recovery attempt, default 100 ms; clamped to at least 1 ms. Effective timing also depends on scan interval and failure detection. | | `interfaceName` | VAR_INPUT | `WSTRING` | Legacy slave field. Must be empty; nonempty is rejected. Use packed in_ipAddress instead. | | `in_ipAddress` | VAR_INPUT | `DWORD` | ClientTCP: four IPv4 bytes. Slave: packed numeric DWORD, 0 binds all interfaces; e.g. DWORD#16#C0A8321F for 192.168.50.31. | | `port` | VAR_INPUT | `UINT := 502` | Slave listening port, default 502, must be nonzero. | | `out_running` | VAR_OUTPUT | `BOOL` | Native listener is bound and enabled. Does not mean a peer is connected. | | `out_error` | VAR_OUTPUT | `BOOL` | Current server error flag when outputs are refreshed; some early returns leave other diagnostics unchanged. | | `out_errorId` | VAR_OUTPUT | `Error` | IEC server error classification: parameter/internal/native socket class. Consult errno for OS detail. | | `out_parameterError` | VAR_OUTPUT | `BOOL` | Array-offset validation for requests; full transaction validation can instead appear in out_nativeError/stats.lastErrorId. Slave: invalid port/interfaceName/table bounds or capacity. | | `out_socketError` | VAR_OUTPUT | `UDINT` | Native Linux errno snapshot as UDINT; may be historical. Used for both serial and sockets. | | `out_connectedClients` | VAR_OUTPUT | `UINT` | Number of native TCP peers connected (max 8 per server in supplied C source). | | `out_requestsReceived` | VAR_OUTPUT | `UDINT` | Native request count for current server context. | | `out_repliesSent` | VAR_OUTPUT | `UDINT` | Native fully transmitted reply count for current context, including exception replies. | | `out_exceptionReplies` | VAR_OUTPUT | `UDINT` | Number of Modbus exception replies for current server context. | ## ClientBase.addRequest Register a non-null RequestBase pointer once. Duplicate pointers are ignored. Capacity is 100 requests per client; overflow sets out_registrationFull. No removal API is provided. Normally called automatically by the request FB. ```iecst //Adds the specified request to the global list METHOD PUBLIC addRequest VAR_INPUT request: POINTER TO RequestBase; END_VAR VAR requestIndex : DINT := 0; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `request` | VAR_INPUT | `POINTER TO RequestBase` | Internal wrapper state exposed for compatibility; normally leave under library control. | ## ClientBase.FB_exit CODESYS lifecycle hook releasing owned native resources. Applications should use release/recreateClient rather than call lifecycle hooks manually. Server hooks close the server context; the client hook calls nativeRelease. ```iecst METHOD FB_exit : BOOL VAR_INPUT bInCopyCode : BOOL; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `bInCopyCode` | VAR_INPUT | `BOOL` | Runtime lifecycle copy-code indicator; current implementation does not branch on it. | ## ClientBase.FB_reinit CODESYS lifecycle hook clearing native handles and in-flight state. ClientBase also clears the request registry for re-registration; RequestBase clears execution/completion flags; servers clear their handle. These hooks alone do not establish qualified online-change support. ```iecst METHOD FB_reinit : BOOL VAR requestIndex : DINT; END_VAR ``` ## ClientBase.nativeCall Internal adapter to atMbCall_cext. Command 20 packs the ASCII serial path into WORD storage and passes serial settings in ABI fields; other commands use normal client arguments and status buffers. Return is the native command result, 0 for success. ```iecst METHOD nativeCall : UDINT VAR_INPUT command : UDINT; END_VAR VAR deviceBytes : POINTER TO BYTE; deviceLength : UINT; deviceIndex : DINT; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `command` | VAR_INPUT | `UDINT` | Native command selector. Use wrappers in application code. | ## ClientBase.nativeCycle Internal per-scan engine: acquire context, tick nonblocking I/O, update diagnostics, copy completed read data, process registered requests, acknowledge completion, select the next request, and publish statistics. Invalid native handles are discarded and reopened on a later scan. ```iecst METHOD nativeCycle VAR callResult : UDINT; END_VAR ``` ## ClientBase.nativeEnsureContext Acquire/configure/enable a native context if absent. Returns TRUE when a handle exists or initialization succeeds. A handle does not mean connected; check out_connected. Failure records a native error and closes partially initialized contexts. ```iecst METHOD PROTECTED nativeEnsureContext : BOOL VAR callResult : UDINT; END_VAR ``` ## ClientBase.nativeRelease Close the native context, complete any active request as cancelled, clear selection, set registered requests offline and invalidate cached read data. Returns TRUE. It does not set in_enable FALSE; an enabled scanned client can reopen. ```iecst METHOD nativeRelease : BOOL VAR requestIndex : DINT; END_VAR ``` ## ClientBase.nativeSelectNextRequest Select an active, unheld request that meets in_minDelay and was not just completed this scan. Lowest in_priorityCurrent wins; oldest sinceLastExec breaks ties. Positive priorities are decremented when the best selected priority is positive. The selected request is submitted immediately; zero priority is not a prerequisite for execution. ```iecst METHOD PROTECTED nativeSelectNextRequest VAR requestIndex : DINT; selectedRequestIndex : DINT; selectedPriority : INT; oldestRequestAgeMilliseconds : UDINT; END_VAR ``` ## ClientBase.nativeUpdateDiagnostics Publish native connection state, last error, errno and reconnect count. States 3..5 count as connected. A connected-to-disconnected transition marks registered requests offline. ```iecst METHOD PROTECTED nativeUpdateDiagnostics ``` ## ClientBase.nativeUpdateStatistics Publish IEC send/reply counters, registered statistics pointers and active-request aggregate online flags. Every elapsed window of at least 1000 ms publishes submitted-request count and successful transaction-duration sum, then restarts the window. ```iecst METHOD PROTECTED nativeUpdateStatistics VAR requestIndex : DINT; END_VAR ``` ## ClientBase.processAllRequests Internal loop over registered non-null requests, dispatching processRequest. Returns immediately for an empty or invalid registry. Usually invoked by nativeCycle rather than application code. ```iecst METHOD processAllRequests VAR_INPUT END_VAR VAR requestIndex: DINT; // Request registry index. END_VAR ``` ## ClientBase.recreateClient Close/release the current context so the next enabled scan creates a fresh one with current settings. Cancels an active transaction and invalidates cached read data. Abstract on ClientBase; implemented by both concrete clients. ```iecst METHOD ABSTRACT recreateClient VAR_INPUT END_VAR ``` ## ClientBase.release Stop this client by setting in_enable FALSE, then release its native context. Returns the release result. To resume, set in_enable TRUE and keep calling the client. A call that supplies in_enable := TRUE every scan will re-enable it. ```iecst METHOD release : BOOL ``` ## ClientBase.resetStats Reset IEC send/reply/window counters and call each registered stats.resetStats. Does not clear native errno/reconnect counters or all per-request history. No transport recreation. ```iecst METHOD resetStats VAR requestIndex : DINT; END_VAR ``` ## ClientBase.setAllRequestsOffline Internal helper marking every registered request offline via its statistics FB. Returns TRUE after processing a nonempty valid registry; early return does not explicitly assign the return value. ```iecst METHOD PROTECTED setAllRequestsOffline : BOOL VAR_INPUT END_VAR VAR requestIndex: DINT; END_VAR ``` ## ClientBase.setupClient Returns whether nativeHandle is nonzero. It does not create a context or guarantee transport connectivity. Normal FB scanning performs initialization. ```iecst METHOD setupClient : BOOL VAR_INPUT END_VAR ``` ## ClientBase.activeIndex Get the current active request registry index, or -1 when idle. Setting a valid index sets that request stats.execute TRUE; it does not bypass native scheduler selection or directly submit a transaction. ```iecst PROPERTY activeIndex : DINT ``` ## ClientBase.activeReqCnt Private count of registered requests whose stats.active is TRUE. Zero quantity/usable length requests are inactive. ```iecst PROPERTY PRIVATE activeReqCnt : UINT ``` ## ClientBase.allRequestsComplete Private legacy completion check. TRUE only if none of the registered requests has execute, reqDone, reqBusy or reqError set. Empty registry returns FALSE. This is not a network completion pulse. ```iecst {attribute 'symbol' := 'none'} PROPERTY PRIVATE allRequestsComplete : BOOL ``` ## ClientBase.onlineCnt Count registered requests with stats.online TRUE. Includes any registered request with that flag; used for aggregate reporting. ```iecst {attribute 'symbol' := 'none'} PROPERTY onlineCnt : DINT//Count of requests that are online ``` ## ClientBase.requestExecuting Private property returning activeIndex <> -1. Represents selected/active request state maintained by the scheduler. ```iecst {attribute 'symbol' := 'none'} PROPERTY PRIVATE requestExecuting : BOOL //There is at least one request executing ``` ## ClientRTU.recreateClient Close/release the current context so the next enabled scan creates a fresh one with current settings. Cancels an active transaction and invalidates cached read data. Abstract on ClientBase; implemented by both concrete clients. ```iecst METHOD recreateClient ``` ## ClientRTU.toString ClientRTU monitoring property returning ClientStatus based on onlineCnt versus requestCnt. Reports allOk for an empty registry. RequestStats also has an internal STRING field of this name; these are different values. ```iecst {attribute 'symbol' := 'none'} PROPERTY toString : ClientStatus //Client request status noneOk = no requests working, someOk = some requests are working some are failing, allOk = all requests are working ``` ## ClientTCP.recreateClient Close/release the current context so the next enabled scan creates a fresh one with current settings. Cancels an active transaction and invalidates cached read data. Abstract on ClientBase; implemented by both concrete clients. ```iecst METHOD recreateClient ``` ## ReqReadCoil.processRequest Derived request dispatch: performs ReqReadCoil transaction using shared nativeProcess, validates copy bounds and transfers the configured slice. Called by client scheduler; application calls the request FB body to register/bind its data. ```iecst METHOD processRequest ``` ## ReqReadCoil.recreateRequest Clear this request nativeInFlight. If it is the client active request, recreate the whole client connection first. Returns TRUE. May affect other requests sharing the same connection; this is not an independent transport. ```iecst METHOD recreateRequest : BOOL ``` ## ReqReadDiscrete.processRequest Derived request dispatch: performs ReqReadDiscrete transaction using shared nativeProcess, validates copy bounds and transfers the configured slice. Called by client scheduler; application calls the request FB body to register/bind its data. ```iecst METHOD processRequest ``` ## ReqReadDiscrete.recreateRequest Clear this request nativeInFlight. If it is the client active request, recreate the whole client connection first. Returns TRUE. May affect other requests sharing the same connection; this is not an independent transport. ```iecst METHOD recreateRequest : BOOL ``` ## ReqReadHolding.processRequest Derived request dispatch: performs ReqReadHolding transaction using shared nativeProcess, validates copy bounds and transfers the configured slice. Called by client scheduler; application calls the request FB body to register/bind its data. ```iecst METHOD processRequest ``` ## ReqReadHolding.recreateRequest Clear this request nativeInFlight. If it is the client active request, recreate the whole client connection first. Returns TRUE. May affect other requests sharing the same connection; this is not an independent transport. ```iecst METHOD recreateRequest : BOOL ``` ## ReqReadInput.processRequest Derived request dispatch: performs ReqReadInput transaction using shared nativeProcess, validates copy bounds and transfers the configured slice. Called by client scheduler; application calls the request FB body to register/bind its data. ```iecst METHOD processRequest ``` ## ReqReadInput.recreateRequest Clear this request nativeInFlight. If it is the client active request, recreate the whole client connection first. Returns TRUE. May affect other requests sharing the same connection; this is not an independent transport. ```iecst METHOD recreateRequest : BOOL ``` ## RequestBase.busy Assign stats.reqBusy from input in. Internal request helper. Although declared BOOL, its implementation does not assign a return value; use the side effect rather than the return. ```iecst METHOD busy : BOOL VAR_INPUT in: BOOL; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `in` | VAR_INPUT | `BOOL` | New state to assign. Normally used internally by completion helpers. | ## RequestBase.done Set stats.reqDone. When in is TRUE, restore in_priorityCurrent to in_prioritySetpoint for the next scheduler cycle. Successful completion counters are maintained by the stats property setter. ```iecst METHOD done VAR_INPUT // Done state in: BOOL; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `in` | VAR_INPUT | `BOOL` | New state to assign. Normally used internally by completion helpers. | ## RequestBase.err Set stats.reqError and, on TRUE, record errorId/exceptionCode. Set next priority to 10 * MIN(consecutive errors,3)^2. Lower numeric priority wins, so this backs off repeated failures relative to lower-priority-number requests. ```iecst METHOD err VAR_INPUT // Error state in: BOOL; errorId: Error; exceptionCode: ExceptionCodes; END_VAR VAR priorityMultiplier: INT; //Raise priority when not response END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `in` | VAR_INPUT | `BOOL` | New state to assign. Normally used internally by completion helpers. | | `errorId` | VAR_INPUT | `Error` | Mapped IEC error supplied to the error helper. | | `exceptionCode` | VAR_INPUT | `ExceptionCodes` | Modbus exception classification supplied to the error helper. | ## RequestBase.FB_reinit CODESYS lifecycle hook clearing native handles and in-flight state. ClientBase also clears the request registry for re-registration; RequestBase clears execution/completion flags; servers clear their handle. These hooks alone do not establish qualified online-change support. ```iecst METHOD FB_reinit : BOOL ``` ## RequestBase.invalidateNativeData Mark cached data invalid and stale. Does not erase the application array. Called during client release; applications should gate use of cached values with validity and age flags. ```iecst METHOD PUBLIC invalidateNativeData ``` ## RequestBase.nativeFinish Complete a request from native result. Map errors, copy errno/write uncertainty, clear busy, update response/counters and successful-read freshness. Modbus exceptions count as replies and communication-online evidence. If enabled, uncertain writes are held pending writeNow(). ```iecst METHOD nativeFinish VAR_INPUT result : UDINT; END_VAR VAR mapped : Error; ex : ExceptionCodes; duration : UDINT; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `result` | VAR_INPUT | `UDINT` | Native completion result; 0 success. | ## RequestBase.nativeProcess Shared request processing called by derived processRequest. Completes native results or submits a selected request, sets its timeout and records busy/send counters. Updates data age and stale flags during ordinary processing. Completion branches can return before age refresh, so allow a subsequent scan for freshness diagnostics. ```iecst METHOD nativeProcess VAR_INPUT functionCode : BYTE; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `functionCode` | VAR_INPUT | `BYTE` | Modbus FC; command 20 uses data bits, server push/pull use table ID. | ## RequestBase.processRequest Abstract internal request dispatch implemented by each concrete read/write block. ```iecst METHOD ABSTRACT processRequest VAR_INPUT END_VAR ``` ## RequestBase.recreateRequest Clear this request nativeInFlight. If it is the client active request, recreate the whole client connection first. Returns TRUE. May affect other requests sharing the same connection; this is not an independent transport. ```iecst METHOD ABSTRACT recreateRequest : BOOL ``` ## RequestBase.replyTimeout Protected timeout property expressed internally in microseconds. Request in_timeout is milliseconds and takes precedence, then client TIME in_timeout, then a dataRate formula, then 1 second fallback. Submission rounds up to milliseconds and clamps to at least 1 ms. ```iecst //Calculates the reply timout setting PROPERTY PROTECTED replyTimeout : UDINT ``` ## RequestStats.resetStats Reset only doneCnt, doneCntRst, errorCnt and errorCntRst. Retains durations, offlineCnt, timeoutCnt and timestamps. ```iecst METHOD resetStats VAR_INPUT END_VAR ``` ## RequestStats.setClientOffline Clear nativeResponseSeen and consecutive-success count, force online FALSE/offline TRUE. Does not clear data arrays. Declared BOOL but does not assign a return value. ```iecst METHOD setClientOffline : BOOL VAR_INPUT END_VAR ``` ## RequestStats.setToString Private statistics helper formatting OK:/Er: into STRING(20). Declared BOOL but does not assign a return value. ```iecst METHOD PRIVATE setToString : BOOL VAR_INPUT END_VAR ``` ## RequestStats.execute Statistics execution property. Setting TRUE starts the execution state only when reqDone and reqError are FALSE; otherwise the setter clears execution. Usually controlled by the scheduler. ```iecst PROPERTY execute : BOOL ``` ## RequestStats.reqBusy Get/set the underlying request-busy flag. Normally managed by the native wrapper. The scan-held reqBusyLight provides a more visible monitoring indicator. ```iecst PROPERTY reqBusy : BOOL ``` ## RequestStats.reqDone Get/set completion flag. When TRUE during execution, record duration, increment total/consecutive successes, clear consecutive errors and last error, clear execution and update the monitor string. Do not repeatedly drive this manually. ```iecst PROPERTY reqDone : BOOL ``` ## RequestStats.reqError Get/set error flag. When TRUE during execution, increment total/consecutive errors, clear consecutive successes and execution. If lastExceptionCode is success, increment timeoutCnt and set TIMEOUT even for some non-timeout native errors. ```iecst PROPERTY reqError : BOOL ``` ## ReqWriteCoil.processRequest Derived request dispatch: performs ReqWriteCoil transaction using shared nativeProcess, validates copy bounds and transfers the configured slice. Called by client scheduler; application calls the request FB body to register/bind its data. ```iecst METHOD processRequest ``` ## ReqWriteCoil.recreateRequest Clear this request nativeInFlight. If it is the client active request, recreate the whole client connection first. Returns TRUE. May affect other requests sharing the same connection; this is not an independent transport. ```iecst METHOD recreateRequest : BOOL ``` ## ReqWriteCoil.writeNow Clear uncertain-write hold and out_writeUncertain, then set in_priorityCurrent to 0. Returns TRUE. Requests a prompt opportunity at the next scheduler selection; does not guarantee transmission in this call and does not bypass connection/minimum-delay requirements. ```iecst METHOD writeNow : BOOL VAR_INPUT END_VAR ``` ## ReqWriteHolding.processRequest Derived request dispatch: performs ReqWriteHolding transaction using shared nativeProcess, validates copy bounds and transfers the configured slice. Called by client scheduler; application calls the request FB body to register/bind its data. ```iecst METHOD processRequest ``` ## ReqWriteHolding.recreateRequest Clear this request nativeInFlight. If it is the client active request, recreate the whole client connection first. Returns TRUE. May affect other requests sharing the same connection; this is not an independent transport. ```iecst METHOD recreateRequest : BOOL ``` ## ReqWriteHolding.writeNow Clear uncertain-write hold and out_writeUncertain, then set in_priorityCurrent to 0. Returns TRUE. Requests a prompt opportunity at the next scheduler selection; does not guarantee transmission in this call and does not bypass connection/minimum-delay requirements. ```iecst METHOD writeNow : BOOL VAR_INPUT END_VAR ``` ## ModbusSlave.FB_exit CODESYS lifecycle hook releasing owned native resources. Applications should use release/recreateClient rather than call lifecycle hooks manually. Server hooks close the server context; the client hook calls nativeRelease. ```iecst METHOD FB_exit : BOOL VAR_INPUT bInCopyCode : BOOL; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `bInCopyCode` | VAR_INPUT | `BOOL` | Runtime lifecycle copy-code indicator; current implementation does not branch on it. | ## ModbusSlave.FB_reinit CODESYS lifecycle hook clearing native handles and in-flight state. ClientBase also clears the request registry for re-registration; RequestBase clears execution/completion flags; servers clear their handle. These hooks alone do not establish qualified online-change support. ```iecst METHOD FB_reinit : BOOL ``` ## ModbusSlave.serverCall Private adapter for native server commands. Uses separate server status and WORD staging buffers. Returns the command result; 0 means command accepted, not necessarily that the listener has bound. ```iecst METHOD PRIVATE serverCall : UDINT VAR_INPUT command : UDINT; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `command` | VAR_INPUT | `UDINT` | Native command selector. Use wrappers in application code. | ## SlaveTCP.FB_exit CODESYS lifecycle hook releasing owned native resources. Applications should use release/recreateClient rather than call lifecycle hooks manually. Server hooks close the server context; the client hook calls nativeRelease. ```iecst METHOD FB_exit : BOOL VAR_INPUT bInCopyCode : BOOL; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `bInCopyCode` | VAR_INPUT | `BOOL` | Runtime lifecycle copy-code indicator; current implementation does not branch on it. | ## SlaveTCP.FB_reinit CODESYS lifecycle hook clearing native handles and in-flight state. ClientBase also clears the request registry for re-registration; RequestBase clears execution/completion flags; servers clear their handle. These hooks alone do not establish qualified online-change support. ```iecst METHOD FB_reinit : BOOL ``` ## SlaveTCP.serverCall Private adapter for native server commands. Uses separate server status and WORD staging buffers. Returns the command result; 0 means command accepted, not necessarily that the listener has bound. ```iecst METHOD PRIVATE serverCall : UDINT VAR_INPUT command : UDINT; END_VAR ``` | Member | Direction | Declaration | Meaning | |---|---|---|---| | `command` | VAR_INPUT | `UDINT` | Native command selector. Use wrappers in application code. | ## activeIndex.Get Get accessor for activeIndex; see the owning property reference for side effects. Runtime/property syntax normally invokes this accessor. ```iecst VAR requestIndex: DINT; //Loop variable END_VAR ``` ## activeIndex.Set Set accessor for activeIndex; see the owning property reference for side effects. Runtime/property syntax normally invokes this accessor. ```iecst ``` ## activeReqCnt.Get Get accessor for activeReqCnt; see the owning property reference for side effects. Runtime/property syntax normally invokes this accessor. ```iecst VAR requestIndex : DINT; //Loop variable cnt: UINT; END_VAR ``` ## allRequestsComplete.Get Get accessor for allRequestsComplete; see the owning property reference for side effects. Runtime/property syntax normally invokes this accessor. ```iecst VAR requestIndex : DINT; END_VAR ``` ## onlineCnt.Get Get accessor for onlineCnt; see the owning property reference for side effects. Runtime/property syntax normally invokes this accessor. ```iecst VAR requestIndex : DINT; //Loop variable cnt: UINT; END_VAR ``` ## requestExecuting.Get Get accessor for requestExecuting; see the owning property reference for side effects. Runtime/property syntax normally invokes this accessor. ```iecst ``` ## toString.Get Get accessor for toString; see the owning property reference for side effects. Runtime/property syntax normally invokes this accessor. ```iecst ``` ## replyTimeout.Get Get accessor for replyTimeout; see the owning property reference for side effects. Runtime/property syntax normally invokes this accessor. ```iecst ``` ## execute.Get Get accessor for execute; see the owning property reference for side effects. Runtime/property syntax normally invokes this accessor. ```iecst ``` ## execute.Set Set accessor for execute; see the owning property reference for side effects. Runtime/property syntax normally invokes this accessor. ```iecst ``` ## reqBusy.Get Get accessor for reqBusy; see the owning property reference for side effects. Runtime/property syntax normally invokes this accessor. ```iecst ``` ## reqBusy.Set Set accessor for reqBusy; see the owning property reference for side effects. Runtime/property syntax normally invokes this accessor. ```iecst ``` ## reqDone.Get Get accessor for reqDone; see the owning property reference for side effects. Runtime/property syntax normally invokes this accessor. ```iecst ``` ## reqDone.Set Set accessor for reqDone; see the owning property reference for side effects. Runtime/property syntax normally invokes this accessor. ```iecst ``` ## reqError.Get Get accessor for reqError; see the owning property reference for side effects. Runtime/property syntax normally invokes this accessor. ```iecst ``` ## reqError.Set Set accessor for reqError; see the owning property reference for side effects. Runtime/property syntax normally invokes this accessor. ```iecst ```