interface test_control # Test control task parameter max type '_integer' range 1,10 prompt 'Number of actions' vpath 'prompt' default 1 endparameter parameter time type '_integer' range -1,3600 prompt 'Timeout in seconds' vpath 'prompt' default 10 endparameter action brew obey needs max needs time endobey endaction endinterface SUBROUTINE TEST_CONTROL (STATUS) * Test control task that controls and reschedules multiple actions * in multiple subsidiary tasks IMPLICIT NONE INTEGER STATUS ! Modified STATUS INCLUDE 'ADAMDEFNS' INCLUDE 'SAE_PAR' INCLUDE 'MESSYS_ERR' INCLUDE 'ACT_ERR' INCLUDE 'DTASK_ERR' INTEGER I ! Counter INTEGER MAX ! Number of TEA/COFFEE actions to start INTEGER TIME ! Timeout in seconds INTEGER SEQ ! Action sequence number INTEGER PATH ! Path to task in which OBEY completed INTEGER MESSID ! Message id of OBEY that completed INTEGER TEA_PATH ! Path to TEA task INTEGER TEA_MESSID ! Message ID of TEA's LAPSANG action INTEGER TEA_ACTIVE ! Number of active LAPSANG actions INTEGER COFFEE_PATH ! Path to COFFEE task INTEGER COFFEE_MESSID ! Message ID of COFFEE's MOCHA action INTEGER COFFEE_ACTIVE ! Number of active MOCHA actions INTEGER CONTEXT ! Context (OBEY or CANCEL) CHARACTER NAME*24 ! Action name CHARACTER VALUE*200 ! Action returned value CHARACTER INVAL*1 ! Action input value (unused) CHARACTER OUTVAL*1 ! Action output value (unused) INTEGER EVENT ! Event which caused reschedule SAVE TEA_ACTIVE,COFFEE_ACTIVE,TIME ! Retain these values IF (STATUS .NE. SAI__OK) RETURN * Pick up required "ACT parameters" CALL TASK_GET_NAME (NAME,STATUS) CALL TASK_GET_SEQ (SEQ,STATUS) * Loop through possible OBEYs IF (NAME .EQ. 'BREW') THEN * First time through, initiate the actions ... IF (SEQ .EQ. 0) THEN * ... actions LAPSANG1 .. LAPSANG'MAX etc are initiated with a timeout * of TIME seconds ... CALL PAR_GET0I ('MAX',MAX,STATUS) CALL PAR_GET0I ('TIME',TIME,STATUS) * ... in the tea-maker ... TEA_ACTIVE = 0 DO I = 1,MAX NAME = 'LAPSANG'//CHAR(48+I) INVAL = ' ' CALL TASK_OBEY ('TEST_TEA',NAME,INVAL, : OUTVAL,TEA_PATH,TEA_MESSID,STATUS) IF (STATUS .EQ. DTASK__ACTSTART) THEN STATUS = SAI__OK CALL TASK_ADD_MESSINFO (TEA_PATH,TEA_MESSID, : STATUS) TEA_ACTIVE = TEA_ACTIVE + 1 ELSE CALL MSG_SETC ('NAME',NAME) CALL ERR_REP (' ', : 'CONTROL: Failed to start ^NAME: '// : '^STATUS',STATUS) * Output reports associated with this failed OBEY * and try next CALL ERR_FLUSH ( STATUS ) ENDIF ENDDO * ... and in the coffee-maker ... COFFEE_ACTIVE = 0 DO I = 1,MAX NAME = 'MOCHA'//CHAR(48+I) INVAL = ' ' CALL TASK_OBEY ('TEST_COFFEE',NAME,INVAL, : OUTVAL,COFFEE_PATH,COFFEE_MESSID,STATUS) IF (STATUS .EQ. DTASK__ACTSTART) THEN STATUS = SAI__OK CALL TASK_ADD_MESSINFO (COFFEE_PATH,COFFEE_MESSID, : STATUS) COFFEE_ACTIVE = COFFEE_ACTIVE + 1 ELSE CALL MSG_SETC ('NAME',NAME) CALL ERR_REP (' ', : 'CONTROL: Failed to start ^NAME: '// : '^STATUS',STATUS) * Output reports associated with this failed OBEY * and try next CALL ERR_FLUSH ( STATUS ) ENDIF ENDDO * ... and, if OK, set time-out period and set ACT__MESSAGE request. IF (TEA_ACTIVE .GT. 0 .OR. COFFEE_ACTIVE .GT. 0) THEN IF (TIME .NE. -1) THEN CALL TASK_PUT_DELAY ( 1000*TIME, STATUS ) ENDIF CALL TASK_PUT_REQUEST ( ACT__MESSAGE, STATUS ) ENDIF * On subsequent entries, get the details of the message that has * caused this entry (it should either correspond to a subsidiary * action completion, TRIGGER or a timeout). ELSE CALL TASK_GET_MESSINFO (PATH,CONTEXT,NAME,VALUE,MESSID, : EVENT,STATUS) * First check for timeout in which case abort the action ... IF (EVENT .EQ. MESSYS__RESCHED) THEN CALL MSG_SETI ('TIME',TIME) CALL ERR_REP (' ', : 'CONTROL: Timeout occurred after ^TIME '// : 'seconds',EVENT) * ... or check whether this is a triggering message, in which case * simply report and set ACT__MESSAGE request ELSE IF (EVENT .EQ. MESSYS__TRIGGER) THEN CALL MSG_SETC ('NAME',NAME) CALL MSG_SETC ('VALUE',VALUE) CALL MSG_OUT (' ', : 'CONTROL: Triggered by ^NAME: ^VALUE', : STATUS) IF (TIME .NE. -1) THEN CALL TASK_PUT_DELAY ( 1000*TIME, STATUS ) ENDIF CALL TASK_PUT_REQUEST ( ACT__MESSAGE, STATUS ) * ... or determine which action has completed. Set ACT__MESSAGE request * if more remain. Otherwise the BREW action is complete. ELSE IF (NAME(1:7) .EQ. 'LAPSANG') THEN TEA_ACTIVE = TEA_ACTIVE - 1 ELSE IF (NAME(1:5) .EQ. 'MOCHA') THEN COFFEE_ACTIVE = COFFEE_ACTIVE - 1 ENDIF * Report normal subsidiary action completion ... CALL MSG_SETC ('NAME',NAME) IF (EVENT .EQ. DTASK__ACTCOMPLETE) THEN CALL MSG_OUT (' ', : 'CONTROL: Action ^NAME completed normally',STATUS) * including VALUE returned. IF ( VALUE .NE. ' ' ) THEN CALL MSG_SETC( 'VALUE', VALUE ) CALL MSG_OUT (' ', : 'CONTROL: Value string: ^VALUE', STATUS) ENDIF * or failure ... ELSE CALL ERR_REP (' ', : 'CONTROL: Action ^NAME completed: ^STATUS',EVENT) * including VALUE returned. IF ( VALUE .NE. ' ' ) THEN CALL MSG_SETC( 'VALUE', VALUE ) CALL ERR_REP (' ', : 'CONTROL: Value string: ^VALUE', EVENT) ENDIF * Flush CALL ERR_FLUSH ( EVENT ) ENDIF IF (TEA_ACTIVE .GT. 0 .OR. COFFEE_ACTIVE .GT. 0) THEN IF (TIME .NE. -1) THEN CALL TASK_PUT_DELAY ( 1000*TIME, STATUS ) ENDIF CALL TASK_PUT_REQUEST ( ACT__MESSAGE, STATUS ) ENDIF ENDIF ENDIF ENDIF END
ADAM Guide to Writing Instrumentation Tasks