Changed from ISA88 to PackML

- Added PackML Base FB's
- Added Unit Tests for PackML Base State Machine
- Added Robot job numbers according to new interface
- Added PLC job number for robot to call according to new interface
- Change Robot to PackML interface
This commit is contained in:
2026-01-23 22:55:49 +01:00
parent 2d11c43579
commit 3946e45c65
26 changed files with 1615 additions and 421 deletions

View File

@@ -0,0 +1,569 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<POU Name="FB_PackMLStateMachine_Test" Id="{6fbfd066-a6ec-4393-8e2f-9c56726e94be}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FB_PackMLStateMachine_Test EXTENDS FB_TestSuite
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[// Normal commands
M_InitialState();
M_StoppedToIdle();
M_IdleToExecute();
M_HoldUnholdCycle();
M_SuspendUnsuspendCycle();
M_ExecuteToComplete();
M_ResetFromComplete();
// Full cycle
M_FullProductionCycle();
// Stop tests
M_StopFromIdle();
M_StopFromExecute();
M_StopFromComplete();
// Abort tests
M_AbortFromExecute();
M_AbortDuringStarting();
M_AbortDuringHolding();
M_AbortDuringClearing();
// Clearing
M_ClearFromAborted();
// Mode switching
M_ModeSwitchInStopped();
M_ModeSwitchNotAllowedInIdle();
M_ModeSwitchAbortedToManual();
M_ModeSwitchAbortedToNonManualNotAllowed();
]]></ST>
</Implementation>
<Method Name="M_AbortDuringClearing" Id="{35f8c603-4e33-4f68-9e15-218d78d5c03b}">
<Declaration><![CDATA[METHOD M_AbortDuringClearing
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('AbortDuringClearing');
// Setup: Get to CLEARING
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.ABORT);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.CLEAR);
AssertEquals_DINT(E_PackMLState.CLEARING, fbPackML.eState, 'Setup: Should be CLEARING');
// Test ABORT during CLEARING
fbPackML(eCmd := E_PackMLCmd.ABORT);
AssertEquals_DINT(E_PackMLState.ABORTING, fbPackML.eState, 'Should abort from CLEARING');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_AbortDuringHolding" Id="{aaa6bed5-41ed-40eb-8168-11c14ad58832}">
<Declaration><![CDATA[METHOD M_AbortDuringHolding
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('AbortDuringHolding');
// Setup: Get to HOLDING
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.HOLD);
AssertEquals_DINT(E_PackMLState.HOLDING, fbPackML.eState, 'Setup: Should be HOLDING');
// Test ABORT during HOLDING
fbPackML(eCmd := E_PackMLCmd.ABORT);
AssertEquals_DINT(E_PackMLState.ABORTING, fbPackML.eState, 'Should abort from HOLDING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.ABORTED, fbPackML.eState, 'Should reach ABORTED');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_AbortDuringStarting" Id="{fbb52ff0-3ecb-4984-be10-32efaf2d1f2b}">
<Declaration><![CDATA[METHOD M_AbortDuringStarting
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('AbortDuringStarting');
// Setup: Get to STARTING
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
AssertEquals_DINT(E_PackMLState.STARTING, fbPackML.eState, 'Setup: Should be STARTING');
// Test ABORT during STARTING
fbPackML(eCmd := E_PackMLCmd.ABORT);
AssertEquals_DINT(E_PackMLState.ABORTING, fbPackML.eState, 'Should abort from STARTING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.ABORTED, fbPackML.eState, 'Should reach ABORTED');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_AbortFromExecute" Id="{6eaecb2f-7c92-492a-8635-8d91354de462}">
<Declaration><![CDATA[METHOD M_AbortFromExecute
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('AbortFromExecute');
// Setup: Get to EXECUTE
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
// Test ABORT
fbPackML(eCmd := E_PackMLCmd.ABORT);
AssertEquals_DINT(E_PackMLState.ABORTING, fbPackML.eState, 'Should transition to ABORTING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.ABORTED, fbPackML.eState, 'Should transition to ABORTED');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_ClearFromAborted" Id="{672532be-23ab-4162-bb1f-60f23d043e3f}">
<Declaration><![CDATA[METHOD M_ClearFromAborted
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('ClearFromAborted');
// Setup: Get to ABORTED
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.ABORT);
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.ABORTED, fbPackML.eState, 'Setup: Should be ABORTED');
// Test CLEAR
fbPackML(eCmd := E_PackMLCmd.CLEAR);
AssertEquals_DINT(E_PackMLState.CLEARING, fbPackML.eState, 'Should transition to CLEARING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.STOPPED, fbPackML.eState, 'Should transition to STOPPED');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_ExecuteToComplete" Id="{d180915d-5230-4918-a72f-7d7b60cb333e}">
<Declaration><![CDATA[METHOD M_ExecuteToComplete
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('ExecuteToComplete');
// Setup: Get to EXECUTE
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.EXECUTE, fbPackML.eState, 'Setup: Should be in EXECUTE');
// Test completion
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.COMPLETING, fbPackML.eState, 'Should transition to COMPLETING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.COMPLETE, fbPackML.eState, 'Should transition to COMPLETE');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_FullProductionCycle" Id="{e11b3300-6857-4b29-8000-595d07539eed}">
<Declaration><![CDATA[METHOD M_FullProductionCycle
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('FullProductionCycle');
// STOPPED -> RESETTING -> IDLE
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.IDLE, fbPackML.eState, 'Should reach IDLE');
// IDLE -> STARTING -> EXECUTE
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.EXECUTE, fbPackML.eState, 'Should reach EXECUTE');
// EXECUTE -> COMPLETING -> COMPLETE
fbPackML.M_StateComplete();
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.COMPLETE, fbPackML.eState, 'Should reach COMPLETE');
// COMPLETE -> RESETTING -> IDLE
fbPackML(eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.IDLE, fbPackML.eState, 'Should return to IDLE');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_HoldUnholdCycle" Id="{01b950b4-a901-4c0f-8993-5e8c46b75e11}">
<Declaration><![CDATA[METHOD M_HoldUnholdCycle
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('HoldUnholdCycle');
// Setup: Get to EXECUTE
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
// Test HOLD
fbPackML(eCmd := E_PackMLCmd.HOLD);
AssertEquals_DINT(E_PackMLState.HOLDING, fbPackML.eState, 'Should transition to HOLDING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.HELD, fbPackML.eState, 'Should transition to HELD');
// Test UNHOLD
fbPackML(eCmd := E_PackMLCmd.UNHOLD);
AssertEquals_DINT(E_PackMLState.UNHOLDING, fbPackML.eState, 'Should transition to UNHOLDING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.EXECUTE, fbPackML.eState, 'Should return to EXECUTE');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_IdleToExecute" Id="{e39d1646-a140-445b-a77a-a4b3ecb6a68b}">
<Declaration><![CDATA[METHOD M_IdleToExecute
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('IdleToExecute');
// Setup: Get to IDLE
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.IDLE, fbPackML.eState, 'Setup: Should be IDLE');
// Test START command
fbPackML(eCmd := E_PackMLCmd.START);
AssertEquals_DINT(E_PackMLState.STARTING, fbPackML.eState, 'Should transition to STARTING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.EXECUTE, fbPackML.eState, 'Should transition to EXECUTE');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_InitialState" Id="{abbdf72f-ef98-4943-bd47-30822864724d}">
<Declaration><![CDATA[METHOD M_InitialState
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('InitialState');
AssertEquals_DINT(
Expected := E_PackMLState.STOPPED,
Actual := fbPackML.eState,
Message := 'Initial state should be STOPPED'
);
AssertEquals_DINT(
Expected := E_PackMLUnitMode.PRODUCTION,
Actual := fbPackML.eCurrentMode,
Message := 'Initial mode should be PRODUCTION'
);
AssertFalse(
Condition := fbPackML.xError,
Message := 'No error should be present initially'
);
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_ModeSwitchAbortedToManual" Id="{16d80727-dea0-4822-8ac2-bb785dfb8fd9}">
<Declaration><![CDATA[METHOD M_ModeSwitchAbortedToManual
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('ModeSwitchAbortedToManual');
// Setup: Get to ABORTED in PRODUCTION mode
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.ABORT);
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.ABORTED, fbPackML.eState, 'Setup: Should be ABORTED');
AssertEquals_DINT(E_PackMLUnitMode.PRODUCTION, fbPackML.eCurrentMode, 'Mode should be PRODUCTION');
// Switch to MANUAL mode - should be allowed
fbPackML(eMode := E_PackMLUnitMode.MANUAL);
AssertEquals_DINT(E_PackMLUnitMode.MANUAL, fbPackML.eCurrentMode, 'Mode should switch to MANUAL');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_ModeSwitchAbortedToNonManualNotAllowed" Id="{814f1869-6786-43ba-944f-eec48a900610}">
<Declaration><![CDATA[METHOD M_ModeSwitchAbortedToNonManualNotAllowed : REFERENCE TO FB_Test
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('ModeSwitchAbortedToNonManualNotAllowed');
// Setup: Get to ABORTED in PRODUCTION mode
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.ABORT);
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.ABORTED, fbPackML.eState, 'Setup: Should be ABORTED');
// Try to switch to MAINTENANCE - should be rejected
fbPackML(eMode := E_PackMLUnitMode.MAINTENANCE);
AssertEquals_DINT(E_PackMLUnitMode.PRODUCTION, fbPackML.eCurrentMode, 'Mode should remain PRODUCTION');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_ModeSwitchInStopped" Id="{438c169a-3232-4ff5-8d39-6d4748bb8e0c}">
<Declaration><![CDATA[METHOD M_ModeSwitchInStopped
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('ModeSwitchInStopped');
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION);
AssertEquals_DINT(E_PackMLState.STOPPED, fbPackML.eState, 'Should be in STOPPED');
AssertEquals_DINT(E_PackMLUnitMode.PRODUCTION, fbPackML.eCurrentMode, 'Mode should be PRODUCTION');
// Mode switch should be accepted
fbPackML(eMode := E_PackMLUnitMode.MAINTENANCE);
AssertEquals_DINT(E_PackMLUnitMode.MAINTENANCE, fbPackML.eCurrentMode, 'Mode should switch to MAINTENANCE');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_ModeSwitchNotAllowedInIdle" Id="{a1275023-bc44-4cde-b6cb-9ba394083234}">
<Declaration><![CDATA[METHOD M_ModeSwitchNotAllowedInIdle
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('ModeSwitchNotAllowedInIdle');
// Setup: Get to IDLE in PRODUCTION mode
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.IDLE, fbPackML.eState, 'Setup: Should be in IDLE');
AssertEquals_DINT(E_PackMLUnitMode.PRODUCTION, fbPackML.eCurrentMode, 'Mode should be PRODUCTION');
// Try to switch mode - should be rejected
fbPackML(eMode := E_PackMLUnitMode.MANUAL);
AssertEquals_DINT(E_PackMLUnitMode.PRODUCTION, fbPackML.eCurrentMode, 'Mode should remain PRODUCTION');
AssertEquals_DINT(E_PackMLState.IDLE, fbPackML.eState, 'Should remain in IDLE');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_ResetFromComplete" Id="{cbdb2a33-12a7-489c-a968-e416c0488e4f}">
<Declaration><![CDATA[METHOD M_ResetFromComplete
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('ResetFromComplete');
// Setup: Get to COMPLETE
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
fbPackML.M_StateComplete();
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.COMPLETE, fbPackML.eState, 'Setup: Should be COMPLETE');
// Test RESET from COMPLETE
fbPackML(eCmd := E_PackMLCmd.RESET);
AssertEquals_DINT(E_PackMLState.RESETTING, fbPackML.eState, 'Should transition to RESETTING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.IDLE, fbPackML.eState, 'Should transition to IDLE');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_StopFromComplete" Id="{6f2c0387-41ef-426f-869c-ddae93a70046}">
<Declaration><![CDATA[METHOD M_StopFromComplete
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('StopFromComplete');
// Setup: Get to COMPLETE
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
fbPackML.M_StateComplete();
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.COMPLETE, fbPackML.eState, 'Setup: Should be COMPLETE');
// Test STOP from COMPLETE
fbPackML(eCmd := E_PackMLCmd.STOP);
AssertEquals_DINT(E_PackMLState.STOPPING, fbPackML.eState, 'Should transition to STOPPING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.STOPPED, fbPackML.eState, 'Should transition to STOPPED');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_StopFromExecute" Id="{2399ead6-3273-4524-990f-02be84126c6a}">
<Declaration><![CDATA[METHOD M_StopFromExecute
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('StopFromExecute');
// Setup: Get to EXECUTE
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
// Test STOP from EXECUTE
fbPackML(eCmd := E_PackMLCmd.STOP);
AssertEquals_DINT(E_PackMLState.STOPPING, fbPackML.eState, 'Should transition to STOPPING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.STOPPED, fbPackML.eState, 'Should transition to STOPPED');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_StopFromIdle" Id="{15984370-8f4c-4823-af08-97c9f70546cd}">
<Declaration><![CDATA[METHOD M_StopFromIdle
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('StopFromIdle');
// Setup: Get to IDLE
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
// Test STOP from IDLE
fbPackML(eCmd := E_PackMLCmd.STOP);
AssertEquals_DINT(E_PackMLState.STOPPING, fbPackML.eState, 'Should transition to STOPPING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.STOPPED, fbPackML.eState, 'Should transition to STOPPED');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_StoppedToIdle" Id="{4e29286e-7cd6-4d2e-89db-08104750a1c6}">
<Declaration><![CDATA[METHOD M_StoppedToIdle
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('StoppedToIdle');
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION);
AssertEquals_DINT(E_PackMLState.STOPPED, fbPackML.eState, 'Should be in STOPPED');
fbPackML(eCmd := E_PackMLCmd.RESET);
AssertEquals_DINT(E_PackMLState.RESETTING, fbPackML.eState, 'Should transition to RESETTING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.IDLE, fbPackML.eState, 'Should transition to IDLE');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_SuspendUnsuspendCycle" Id="{78311aa6-53b9-4c6e-8c1c-a43729a514d1}">
<Declaration><![CDATA[METHOD M_SuspendUnsuspendCycle
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('SuspendUnsuspendCycle');
// Setup: Get to EXECUTE
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
// Test SUSPEND
fbPackML(eCmd := E_PackMLCmd.SUSPEND);
AssertEquals_DINT(E_PackMLState.SUSPENDING, fbPackML.eState, 'Should transition to SUSPENDING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.SUSPENDED, fbPackML.eState, 'Should transition to SUSPENDED');
// Test UNSUSPEND
fbPackML(eCmd := E_PackMLCmd.UNSUSPEND);
AssertEquals_DINT(E_PackMLState.UNSUSPENDING, fbPackML.eState, 'Should transition to UNSUSPENDING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.EXECUTE, fbPackML.eState, 'Should return to EXECUTE');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
</POU>
</TcPlcObject>