(* Paste in IMPLEMENTATION pane. This only issues FC03 reads. Leave run FALSE until the component is loaded and target is configured. Set run FALSE and allow scans to execute before stopping/downloading. This bench program does not implement automatic disposal on online change. *) readDone := FALSE; requestError := FALSE; timeResult := SysTimeGetUs(nowUs); IF timeResult <> 0 THEN RETURN; END_IF; nowMs := nowUs / 1000; dataStale := NOT hasValidData; IF hasValidData THEN dataStale := (nowMs - lastReadMs) > 2000; END_IF; pollDelay(IN := (command = 5) AND (status[1] = 3) AND (status[2] = 0), PT := T#200MS); IF NOT run THEN IF handle <> 0 THEN command := 2; (* Close *) ELSE command := 0; END_IF; ELSIF (handle = 0) AND (command = 0) THEN command := 1; (* Open *) END_IF; IF command = 0 THEN RETURN; END_IF; callResult := atMbCall_cext( command := command, handle := handle, ipAddress := ipAddress, port := tcpPort, unitId := unitId, functionCode := 3, startAddress := startAddress, quantity := 10, pData := ADR(registers[0]), dataCapacity := 10, pStatus := ADR(status[0]), statusCapacity := 24, nowMs := nowMs, connectTimeoutMs := 2000, responseTimeoutMs := 1000, retryDelayMs := 1000 ); IF callResult <> 0 THEN IF callResult = 256 THEN (* Stale handle: obtain a fresh context. *) handle := 0; command := 0; ELSIF (command = 6) AND ((callResult = 2) OR (callResult = 3)) THEN command := 5; (* Busy/offline: return to tick. *) ELSE (* Preserve callResult for diagnostics. Turning run off closes context. *) run := FALSE; END_IF; RETURN; END_IF; CASE command OF 1: handle := status[0]; command := 9; (* Configure *) 9: command := 3; (* Enable *) 3: command := 5; (* Tick *) 5: IF status[3] <> 0 THEN command := 7; (* Copy validated read result before acknowledge. *) ELSIF status[4] <> 0 THEN lastRequestResult := status[5]; lastException := status[8]; lastSocketError := status[7]; requestErrorCount := requestErrorCount + 1; requestError := TRUE; command := 10; ELSIF (status[1] = 3) AND pollDelay.Q THEN command := 6; (* Submit *) END_IF; 6: command := 5; 7: lastReadMs := nowMs; hasValidData := TRUE; dataStale := FALSE; readDone := TRUE; successfulReadCount := successfulReadCount + 1; command := 10; (* Acknowledge *) 10: command := 5; 2: handle := 0; command := 0; hasValidData := FALSE; dataStale := TRUE; END_CASE;