A Making tea and coffee

 A.1 Making tea
 A.2 Making coffee
 A.3 Controlling tea and coffee making

A.1 Making tea

  interface test_tea
  #  Test tea task
      parameter param
          type ’_integer’
          range 1,10
          vpath ’internal’
          default 2
      endparameter
      action lapsang1
          obey
          endobey
      endaction
      action lapsang2
          obey
          endobey
      endaction
      action lapsang3
          obey
          endobey
      endaction
      action lapsang4
          obey
          endobey
      endaction
      action lapsang5
          obey
          endobey
      endaction
  endinterface
  
        SUBROUTINE TEST_TEA (STATUS)
  
  *     Test D-task that is run from a rescheduling control task
  
        IMPLICIT NONE
        INTEGER   STATUS          ! Modified STATUS
  
        INCLUDE   ’SAE_PAR’
        INCLUDE   ’ADAMDEFNS’
        INCLUDE   ’ACT_ERR’
  
        INTEGER   SEQ             ! Action sequence number
        INTEGER   CONTEXT         ! Context (OBEY or CANCEL)
        INTEGER   PARAM           ! Arbitrary integer parameter
        INTEGER   DELAY           ! Delay between initial and final entries
        CHARACTER NAME*24         ! Action name
        CHARACTER VALUE*80        ! Value string
  
        SAVE PARAM                ! Value must be saved
  
        IF (STATUS .NE. SAI__OK) RETURN
  
  *  Pick up required "ACT parameters"
  
        CALL TASK_GET_NAME (NAME,STATUS)
        CALL TASK_GET_CONTEXT (CONTEXT,STATUS)
        CALL TASK_GET_SEQ (SEQ,STATUS)
  
  *  Loop through possible OBEYs
  
        IF (NAME(1:7) .EQ. ’LAPSANG’) THEN
           IF (SEQ .EQ. 0) THEN
  *         Produce error - undefined parameter on LAPSANG2
              IF (NAME(8:8) .EQ. ’2’) THEN
                 CALL PAR_GET0I (’X’,PARAM,STATUS)
                 IF (STATUS .NE. SAI__OK) THEN
                    CALL ERR_REP (’ ’,
       :            ’TEA: LAPSANG1 Deliberate error - ’//
       :            ’No parameter X: ^STATUS’, STATUS)
  *               Flush the error messages and allow task to continue
                    CALL ERR_FLUSH ( STATUS )
                 ENDIF
  
  *         Get parameter value on LAPSANG3
  *         to be used as a count of TRIGGERS
              ELSE IF (NAME(8:8) .EQ. ’3’) THEN
                 CALL PAR_GET0I (’PARAM’,PARAM,STATUS)
                 IF (STATUS .NE. SAI__OK) THEN
                    CALL ERR_REP (’ ’,
       :            ’TEA: LAPSANG3 Failed to get PARAM: ^STATUS’,
       :             STATUS)
  *              Set harmless value for PARAM
                    PARAM = -1
                    RETURN
                 ENDIF
              ENDIF
              CALL MSG_SETC (’NAME’,NAME)
              CALL MSG_OUT (’ ’,’TEA: Starting ^NAME action’,STATUS)
              DELAY = 1000 * (ICHAR(NAME(8:8)) - ICHAR(’0’))
              CALL TASK_PUT_DELAY (DELAY,STATUS)
              CALL TASK_PUT_REQUEST ( ACT__WAIT, STATUS )
           ELSE IF (NAME(8:8) .EQ. ’4’ .AND. SEQ .LE. PARAM) THEN
              VALUE = NAME(1:8)//’ is paging you ...’
              CALL TASK_TRIGGER (NAME,VALUE,STATUS)
              IF (STATUS .NE. SAI__OK) THEN
                 CALL ERR_REP (’ ’,
       :         ’TEA: LAPSANG4 Failed to trigger control task: ^STATUS’,
       :          STATUS)
              ENDIF
              CALL TASK_PUT_DELAY (2000,STATUS)
              CALL TASK_PUT_REQUEST ( ACT__WAIT, STATUS )
           ELSE
              CALL MSG_SETC (’NAME’,NAME)
              CALL MSG_OUT (’ ’,’TEA: Finishing ^NAME action’,STATUS)
              CALL TASK_PUT_VALUE (’Lapsang’’s ready!’,STATUS)
           ENDIF
  
        ENDIF
        END
  
  

A.2 Making coffee

  interface test_coffee
  #  Test coffee task
      action mocha1
          obey
          endobey
      endaction
      action mocha2
          obey
          endobey
      endaction
      action mocha3
          obey
          endobey
      endaction
      action mocha4
          obey
          endobey
      endaction
      action mocha5
          obey
          endobey
      endaction
  endinterface
  
        SUBROUTINE TEST_COFFEE (STATUS)
  
  *     Test D-task that is run from a rescheduling control task
  
        IMPLICIT NONE
        INTEGER   STATUS          ! Modified STATUS
  
        INCLUDE   ’SAE_PAR’
        INCLUDE   ’ACT_ERR’
  
        INTEGER   SEQ             ! Action sequence number
        INTEGER   DELAY           ! Delay between initial and final entries
        CHARACTER NAME*24         ! Action name
  
        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(1:5) .EQ. ’MOCHA’) THEN
           IF (SEQ .EQ. 0) THEN
              CALL MSG_SETC (’NAME’,NAME)
              CALL MSG_OUT (’ ’,’COFFEE: Starting ^NAME action’,STATUS)
              DELAY = 1000 * (ICHAR(NAME(6:6)) - ICHAR(’0’))
              CALL TASK_PUT_DELAY (DELAY,STATUS)
              CALL TASK_PUT_REQUEST ( ACT__WAIT, STATUS )
           ELSE
              CALL MSG_SETC (’NAME’,NAME)
              CALL MSG_OUT (’ ’,’COFFEE: Finishing ^NAME action’,STATUS)
              CALL TASK_PUT_VALUE (’Mocha’’s ready!’,STATUS)
           ENDIF
        ENDIF
        END
  

A.3 Controlling tea and coffee making

  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