
# $Log: not supported by cvs2svn $
# Revision 1.16  2006/05/16 21:11:10  soliday
# Updated PV names because they have been renamed.
#
# Revision 1.15  2003/10/30 16:44:10  soliday
# Two acis PV names changed which required a change to the code.
#
# Revision 1.14  2000/04/26 15:46:53  soliday
# Added APSMpStep descriptions.
#
# Revision 1.13  1997/04/24 14:59:16  borland
# Changed lower limit for septum setpoints to make it correspond better
# to new running values.  Change PV names to reflect use of RF4 instead
# of RF1.
#
# Revision 1.12  1996/10/10 22:12:48  borland
# Some minor changes to make diagnosis script work with injection tuneup.
#
# Revision 1.11  1996/10/10 21:35:44  borland
# Added includeBTS option to APSMpSRCheckInjection.
#
# Revision 1.10  1996/10/10 19:38:02  borland
# Added check of DACs and setpoints for kickers and septa.  Added checks of
# BTS valves.  Made more consistent error returns.
#
# Revision 1.9  1996/09/22 15:15:35  borland
# Improved an error message from BTS check procedure.
#
# Revision 1.8  1996/08/21 15:42:18  borland
# Added code to check RF cavities for significant variation among the cavities
# belonging to one sector.  Not tested with live RF yet.
#
# Revision 1.7  1996/08/08 19:31:08  borland
# Put catch statements in APSMpSRCheckInjection around calls to individual check
# procedures.  Also fixed a problem with APSMpSRCheckKickerPS (wrong readback values
# were being assumed).
#
# Revision 1.6  1996/06/28  17:43:46  borland
# Now checking many items in BTS.
#
# Revision 1.5  1996/06/26  22:35:32  borland
# Fixed bug in APSMpSRCheckMPS (wasn't setting errorInfoVar).
#
# Revision 1.4  1996/06/26  22:26:29  borland
# Added RF system tests.
#
# Revision 1.3  1996/06/26  22:07:24  borland
# Put in routine for info for APSMpSRCheckInjection.
#
# Revision 1.2  1996/06/26  21:59:58  borland
# Greatly expanded, with more tests and fewer bugs.
#
# Revision 1.1  1996/06/24  14:48:42  borland
# First version.
#
#

proc APSMpSRCheckInjectionInfo {} {
    return "This procedure diagnoses storage ring injection problems."
}

proc APSMpSRCheckInjection {args} {
    global status mpInterface
    set includeBTS 1
    set includeMPS 1
    set includeFlags 1
    APSStrictParseArguments {includeBTS includeMPS includeFlags}

    set problemList ""
    
    if $includeMPS {
        APSMpStep CheckMPS -desc "Check MPS" -proc "APSMpSRCheckMPS"
        if [catch {APSMpSRCheckMPS -desiredState reset -errorInfoVar status} result] {
            lappend problemList $result
        }
    }


    if $includeFlags {
        APSMpStep CheckFlags -desc "Check flags" -proc "APSMpSRCheckFlags"
        if [catch {APSMpSRCheckFlags -desiredState out -errorInfoVar status} result] {
            lappend problemList $result
        }
    }

    APSMpStep CheckValves -desc "Check values" -proc "APSMpSRCCheckValues"
    if [catch {APSMpSRCheckValves -desiredState open -errorInfoVar status} result] {
        lappend problemList $result
    }

    APSMpStep CheckKickerPS -desc "Check Kicker power supply" -proc "APSMpSRCheckKickerPS"
    if [catch {APSMpSRCheckKickerPS -desiredState on -errorInfoVar status} result] {
        lappend problemList $result
    }

    APSMpStep CheckSeptumPS -desc "Check Septum power supply" -proc "APSMpSRCheckSeptumPS"
    if [catch {APSMpSRCheckSeptumPS -desiredState on -errorInfoVar status} result] {
        lappend problemList $result
    }

    APSMpStep CheckRF -desc "Check rf systems" -proc "APSMpSRCheckRfSystems"
    if [catch {APSMpSRCheckRfSystems -desiredState on -errorInfoVar status} result] {
        lappend problemList $result
    }

    if $includeBTS {
        APSMpStep CheckBTS -desc "Check BTS" -proc "APSMpBTSCheckInjection"
        if [catch {APSMpBTSCheckInjection -desiredState toRing} result] {
            lappend problemList $result
        }
    }

    APSMpStep CheckBend -desc "Check bend" -proc "APSMpSRCheckDCPSFamily"
    if [catch {APSMpSRCheckDCPSFamily -family BM \
                 -desiredState 0 -errorInfoVar status \
                 -errorDescription "bad status"} result] {
        lappend problemList $result
    }
    
    APSMpStep CheckQuads -desc "Check quads" -proc "APSMpSRCheckDCPSFamily"
    if [catch {APSMpSRCheckDCPSFamily -family Q \
                 -desiredState 0 -errorInfoVar status \
                 -errorDescription "bad status"} result] {
        lappend problemList $result
    }
    
    APSMpStep CheckHCorr -desc "Check horizontal correctors" -proc "APSMpSRCheckDCPSFamily"
    if [catch {APSMpSRCheckDCPSFamily -family H \
                 -desiredState 0 -errorInfoVar status \
                 -errorDescription "bad status"} result] {
        lappend problemList $result
    }
    
    APSMpStep CheckVCorr -desc "Check vertical correctors" -proc "APSMpSRCheckDCPSFamily"
    if [catch {APSMpSRCheckDCPSFamily -family V -desiredState 0 -errorInfoVar status \
                 -errorDescription "bad status"} result] {
        lappend problemList $result
    }
    
    APSMpStep CheckSkew -desc "Check skew" -proc "APSMpSRCheckDCPSFamily"
    if [catch {APSMpSRCheckDCPSFamily -family QS -desiredState 0 -errorInfoVar status \
                 -errorDescription "bad status"} result] {
        lappend problemList $result
    }
    
    if [llength $problemList] {
        set status "Problem(s) found with injection."
        APSMpReturn error
    }
    APSMpReturn ok
}

proc APSMpSRDiagnoseInjectionDialog {frame} {
}

proc APSMpSRCheckDCPS {args} {
    set desiredState 0
    if [APSStrictParseArguments {desiredState}]==-1 {
        APSMpReturn error "Invalid arguments to APSMpSRCheckDCPS"
    }

    APSMpStep CheckQuads -desc "Check quads" -proc "APSMpSRCheckDCPSFamily"
    if [catch {APSMpSRCheckDCPSFamily -family Q -desiredState 0 -errorInfoVar status \
                 -errorDescription "bad status"} result] {
        lappend problemList $result
    }
    
    APSMpStep CheckBend -desc "Check bend" -proc "APSMpSRCheckDCPSFamily"
    if [catch {APSMpSRCheckDCPSFamily -family BM -desiredState 0 -errorInfoVar status \
                 -errorDescription "bad status"} result] {
        lappend problemList $result
    }
    
    APSMpStep CheckHCorr -desc "Check horizontal correctors" -proc "APSMpSRCheckDCPSFamily"
    if [catch {APSMpSRCheckDCPSFamily -family H -desiredState 0 -errorInfoVar status \
                 -errorDescription "bad status"} result] {
        lappend problemList $result
    }
    
    APSMpStep CheckVCorr -desc "Check vertical correctors" -proc "APSMpSRCheckDCPSFamily"
    if [catch {APSMpSRCheckDCPSFamily -family V -desiredState 0 -errorInfoVar status \
                 -errorDescription "bad status"} result] {
        lappend problemList $result
    }
    
    APSMpStep CheckSkew -desc "Check skew" -proc "APSMpSRCheckDCPSFamily"
    if [catch {APSMpSRCheckDCPSFamily -family QS -desiredState 0 -errorInfoVar status \
                 -errorDescription "bad status"} result] {
        lappend problemList $result
    }
    
    if [llength $problemList] {
        APSMpReturn error "Problem(s) found with injection."
    }
    APSMpReturn ok
}

proc APSMpSRCheckDCPSFamily {args} {
    set family Q
    set desiredState 0
    set errorInfoVar ""
    set errorDescription "bad status"

    if [APSStrictParseArguments {family desiredState errorInfoVar errorDescription}]==-1 {
        APSMpReturn error "Invalid arguments to APSMpSRCheckDCPSFamily"
    }
    if [string length $errorInfoVar] { 
        global $errorInfoVar
    }
    switch $family {
        Q {
            set code [catch {exec cavget -list=S -range=begin=1,end=40 -list=A:Q,B:Q -range=begin=1,end=5 \
                               -list=:StatusCALC -pend=30 -label "-delim= "} result]
        }
        S {
            set code [catch {exec cavget -list=S -range=begin=1,end=40 -list=A:S1,A:S2,A:S3,A:S4,B:S3,B:S2,B:S1 \
                               -list=:StatusCALC -pend=30 -label "-delim= "} result]
        }
        H {
            set code [catch {exec cavget -list=S -range=begin=1,end=40 -list=A:H,B:H -range=begin=1,end=4 \
                               -list=:StatusCALC -pend=30 -label "-delim= "} result]
        }
        V {
            set code [catch {exec cavget -list=S -range=begin=1,end=40 -list=A:V,B:V -range=begin=1,end=4 \
                               -list=:StatusCALC -pend=30 -label "-delim= "} result]
        }
        QS {
            set code [catch {exec cavget -list=S \
                               -list=1B,3A,5B,7A,9B,11A,13B,15A,17B,19A,21B,23A,25B,27A,29B,31A,33B,35A,37B,39A \
                               -list=:QS:StatusCALC -pend=30 -label "-delim= "} result]
        }
        BM {
            set code [catch {exec cavget -list=S:BM:StatusCALC -label "-delim= "} result]
        }
    }
    if $code {
        if [string length $errorInfoVar] { 
            set errorInfoVar "Problem getting DCPS status for $family family."
        }
        APSMpReturn error "Problem getting DCPS status for $family family."
    }
    array set statusArray $result
    set problemList ""
    set psStatus(0) on
    set psStatus(1) tol
    set psStatus(2) off
    set psStatus(3) inv
    foreach elem [array names statusArray] {
        if [string compare $statusArray($elem) $desiredState] {
            if $statusArray($elem)>3 {
                set statusArray($elem) 3
            }
            switch $statusArray($elem) {
                0 - 
                1 -
                2 -
                3 {
                    set problem $psStatus($statusArray($elem))
                }
                default {
                    set problem ?
                }
            }
            regsub :StatusCALC $elem "" tmp
            lappend problemList $tmp:$problem
        }
    }
    if [llength $problemList] {
        if [string length $errorInfoVar] { 
            APSSetVarAndUpdate $errorInfoVar "$errorDescription: $problemList"
        }
        APSMpReturn error "$errorDescription:  $problemList"
    }
    APSMpReturn ok
}


proc APSMpSRCheckMPS {args} {
    global status

    set desiredState reset
    set errorInfoVar ""
    if [APSStrictParseArguments {desiredState errorInfoVar}]==-1 {
        APSMpReturn error "Invalid arguments to APSMpSRCheckMPS"
    }

    if [string compare $desiredState reset]==0 {
        set desiredState 0
    } else {
        set desiredState 1
    }

    if [catch {exec cavget -list=S:MPS:readyCC} result] {
        if [string length $errorInfoVar] { 
            APSSetVarAndUpdate $errorInfoVar "Problem getting MPS ready status: $result"
        }
        APSMpReturn error "Problem getting MPS ready status." 
    }

    if [string compare $result $desiredState] {
        APSMpReturn ok
    }
    if [string length $errorInfoVar] {
        APSSetVarAndUpdate $errorInfoVar "MPS is tripped."
    }
    APSMpReturn error "MPS is tripped."
}

proc APSMpSRCheckKickerPS {args} {
    set desiredState on
    set errorInfoVar ""
    if [APSStrictParseArguments {desiredState errorInfoVar}]==-1 {
        APSMpReturn error "Invalid arguments to APSMpSRCheckKickerPS"
    }

    lappend pvList S:IK1:StatusCALC S:IK2:StatusCALC S:IK3:StatusCALC \
      S:IK4:StatusCALC Mt:Ddg3chan4.GATE
    lappend descripList "IK1 Status" "IK2 Status" "IK3 Status" "IK4 Status"  \
      "IK Charge"
    if [string compare $desiredState on] {
        lappend desiredStateList 1 1 1 1 Disabled
    } else {
        lappend desiredStateList 0 0 0 0 Enabled
    }

    set problemList ""
    if [catch {APSMpCheckPVListValues -pvList $pvList -positiveMessage 1 \
                 -descriptionList $descripList \
                 -desiredStateList $desiredStateList} result] {
        if [string length $errorInfoVar] {
            APSSetVarAndUpdate $errorInfoVar "$result"
        }
        lappend problemList $result
    }
    if [string compare $desiredState on]==0 {
        # check setpoints and DACs
        if [catch {exec cavget -pend=4 -list=S:IK -list=1,2,3,4 \
                     -list=:VoltageSetSendAO,:DacAI "-delim= "} \
              result] {
            APSMpReturn error $result
        }
        for {set index 0} {$index<8} {incr index 2} {
            set setpoint [lindex $result $index]
            set dac      [lindex $result [expr $index+1]]
            set problem ""
            if [expr $setpoint<4.0] {
                set problem \
                  [format "IK%ld setpoint only %.3f" [expr ($index+2)/2] $setpoint]
            } elseif [expr abs($setpoint-$dac)>0.01] {
                set problem \
                  [format "IK%ld DAC differs from setpoint." [expr ($index+2)/2]]
            }
            if [string length $problem] {
                if [string length $errorInfoVar] {
                    APSSetVarAndUpdate $errorInfoVar $problem
                } 
                lappend problemList $problem
            }
        }
    }
    if [llength $problemList] {
        APSMpReturn error [join $problemList "\n"]
    }
    APSMpReturn ok
}

proc APSMpSRCheckSeptumPS {args} {
    set desiredState on
    set errorInfoVar ""
    if [APSStrictParseArguments {desiredState errorInfoVar}]==-1 {
        APSMpReturn error "Invalid arguments to APSMpSRCheckSeptumPS"
    }

    lappend pvList S:IS1:StatusCALC S:IS2:StatusCALC \
      Mt:Ddg3chan0StatCC.SEVR Mt:Ddg3chan1StatCC.SEVR \
      Mt:Ddg3chan2StatCC.SEVR Mt:Ddg3chan3StatCC.SEVR
    lappend descripList "IS1 Status" "IS2 Status" \
      "IS1 Charge"    "IS2 Charge" \
      "IS1 Discharge" "IS2 Discharge"
    if [string compare $desiredState on] {
        lappend desiredStateList 1 1 MAJOR MAJOR MAJOR MAJOR
    } else {
        lappend desiredStateList 0 0 NO_ALARM NO_ALARM NO_ALARM NO_ALARM
    }

    set problemList ""
    if [catch {APSMpCheckPVListValues -pvList $pvList -positiveMessage 1 \
                 -descriptionList $descripList \
                 -desiredStateList $desiredStateList} result] {
        if [string length $errorInfoVar] {
            APSSetVarAndUpdate $errorInfoVar $result
        }
        lappend problemList $result
    }

    if [string compare $desiredState on]==0 {
        # check setpoints and DACs
        if [catch {exec cavget -pend=4 -list=S:IS -list=1,2,3,4 \
                     -list=:VoltageSetSendAO,:DacAI "-delim= "} \
              result] {
            APSMpReturn error $result
        }
        for {set index 0} {$index<4} {incr index 2} {
            set setpoint [lindex $result $index]
            set dac      [lindex $result [expr $index+1]]
            set problem ""
            if [expr $setpoint<510.0] {
                set problem \
                  [format "IS%ld setpoint only %.3f" [expr ($index+2)/2] $setpoint]
            } elseif [expr abs($setpoint-$dac)>0.01] {
                set problem \
                  [format "IS%ld DAC differs from setpoint." [expr ($index+2)/2]]
            }
            if [string length $problem] {
                if [string length $errorInfoVar] {
                    APSSetVarAndUpdate $errorInfoVar $problem
                } 
                lappend problemList $problem
            }
        }
    }

    if [llength $problemList] {
        APSMpReturn error [join $problemList "\n"]
    }
    APSMpReturn ok
}

proc APSMpSRCheckFlags {args} {
    set desiredState out
    set errorInfoVar ""
    if [APSStrictParseArguments {desiredState errorInfoVar}]==-1 {
        APSMpReturn error "Invalid arguments to APSMpSRCheckFlags"
    }
    
    lappend pvList S40AFL:act_out_bi S40BFL:act_out_bi S01AFL:act_out_bi \
      S07BFL:act_out_bi  \
      S33IRBFL:act_out_bi S35BFL:act_out_bi S39BFL:act_out_bi 
    lappend descripList S40AFL S40BFL S01AFL \
      S07BFL S33BFL S35BFL S39BFL 
    if [string compare $desiredState out]==0 {
        lappend desiredStateList CLOSED CLOSED CLOSED CLOSED CLOSED \
           CLOSED CLOSED
    } else {
        lappend desiredStateList OPEN OPEN OPEN OPEN OPEN OPEN OPEN
    }

    if [catch {APSMpCheckPVListValues -pvList $pvList \
                 -descriptionList $descripList \
                 -desiredStateList $desiredStateList} result] {
        if [string length $errorInfoVar] {
            APSSetVarAndUpdate $errorInfoVar $result
        }
        APSMpReturn error $result
    }
    APSMpReturn ok
}

proc APSMpSRCheckRfSystems {args} {
    set desiredState on
    set errorInfoVar ""
    if [APSStrictParseArguments {desiredState errorInfoVar}]==-1 {
        APSMpReturn error "Invalid arguments to APSMpSRCheckRfSystems"
    }

    set tmpFile /tmp/[APSTmpString]
    if [catch \
          {exec sddsstatmon \
             /home/helios/oagData/sr/sddsmonitorFiles/SRCavityVoltage.mon \
             $tmpFile -steps=1 -samples=10 -interval=0.5,s} result] {
        APSMpReturn error "Problem logging cavity voltages: $result"
    }

    set tmpFile1 /tmp/[APSTmpString]
    set rpnDefs /usr/local/oag/apps/src/appconfig/rpn/defns.rpn
    if {[catch \
           {exec sddsconvert $tmpFile -pipe=out \
              -retain=col,S??C?GapVoltageMean \
              -edit=col,S??C?GapVoltageMean,%/GapVoltageMean// \
              | sddscollect -pipe -collect=prefix=S36 -collect=prefix=S37  \
              -collect=prefix=S38 -collect=prefix=S40 \
              | sddsprocess -pipe -rpndef=$rpnDefs \
              -process=S??,median,%sMedian \
              "-define=col,%sDeviation,%s %sMedian - abs chs,select=S??" \
              | sddsprocess -pipe \
              "-process=*Deviation,count,%sFarOut,toplimit=-15" \
              | sddscollapse -pipe \
              | sddsconvert -dele=col,OriginalPage -dele=param,OriginalPage -pipe \
              | sddscollect -pipe=in $tmpFile1 -collect=suffix=FarOut} result]} {
        APSMpReturn error "Problem processing cavity voltage data: $result"
    }
    set SectorNames [APSGetSDDSColumn -fileName $tmpFile1 -column Rootname]
    set FarOut [APSGetSDDSColumn -fileName $tmpFile1 -column FarOut]
    set problems ""
    for {set index 0} {$index<4} {incr index} {
        if [expr [lindex $FarOut $index]>10.0] {
            lappend problems "[lindex $SectorNames $index] cavities vary by more than 10kV"
        }
    }
    if [llength $problems] {
        if [string length $errorInfoVar] {
            APSSetVarAndUpdate $errorInfoVar $problems
        }
    }

    lappend pvList SRF:P4:faultInterlock SRF:P2:faultInterlock \
      S4:K:rfInterlock S2:K:rfInterlock
    lappend descripList S4:HVPS S2:HVPS S4:RF S2:RF
    if [string compare $desiredState on]==0 {
        lappend desiredStateList READY READY OK OK
    } else {
        lappend desiredStateList "NOT READY" "NOT READY" FAULT FAULT
    }
    if [catch {APSMpCheckPVListValues -pvList $pvList \
                 -descriptionList $descripList \
                 -desiredStateList $desiredStateList} result] {
        if [string length $errorInfoVar] {
            APSSetVarAndUpdate $errorInfoVar $result
        }
        lappend problems $result
    }
    if [llength $problems] {
        APSMpReturn error "$problems"
    }
    APSMpReturn ok
}



proc APSMpSRCheckValves {args} {
    set desiredState open
    set errorInfoVar ""
    if [APSStrictParseArguments {desiredState errorInfoVar}]==-1 {
        APSMpReturn error "Invalid arguments to APSMpSRCheckValves"
    }

    if [catch {exec cavget -list=VM: -range=begin=1,end=40,format=%02ld \
                 -list=:VV -list=01,02 -list=:openBI -pend=10} result] {
        APSMpReturn error "Unable to read valve open status"
    }

    set notOkList ""
    set index 1
    foreach elem [split $result] {
        if [string compare $elem $desiredState] {
            lappend notOkList $elem
        }
    }
    if [llength $notOkList] {
        if [string length $errorInfoVar] {
            APSSetVarAndUpdate $errorInfoVar [join $notOkList]
        }
        APSMpReturn error "Valves not open: [join $notOkList]"
    }
    APSMpReturn ok
}

proc APSMpCheckPVListValues {args} {
    global status

    set pvList ""
    set descriptionList ""
    set desiredStateList ""
    set positiveMessage 0
    if [APSStrictParseArguments {pvList descriptionList desiredStateList positiveMessage}]==-1 {
        return -code error "Invalid arguments to APSMpCheckPVListValues"
    }

    set problemList ""
    if [catch {exec cavget -list=[join $pvList ,] -pend=[llength $pvList]} result] {
        return -code error "Unable to read status data: $pvList\n$result" 
    }

    set index 0
    foreach readback [split $result] {
        if [string compare $readback [lindex $desiredStateList $index]]!=0 {
            if !$positiveMessage {
                lappend problemList "[lindex $descriptionList $index] is not [lindex $desiredStateList $index]\n"
            } else {
                lappend problemList "[lindex $descriptionList $index] is $readback\n"
            }
        }
        incr index
    }
    if [llength $problemList] {
        return -code error [join $problemList]
    }
    return -code ok
}

proc APSMpBTSCheckInjection {args} {
    set desiredState toRing
    set errorInfoVar ""
    if [APSStrictParseArguments {desiredState errorInfoVar}]==-1 {
        APSMpReturn error "Invalid arguments to APSMpSRCheckBTS"
    }

    set problemList ""
    APSMpStep CheckBTSDCPS -desc "Check BTS DCPS" -proc "APSMpBTSCheckDCPS"
    if [catch {APSMpBTSCheckDCPS -desiredState 0 -errorInfoVar $errorInfoVar} result] {
        lappend problemList $result
    }

    APSMpStep CheckBTSMode -desc "Check BTS mode" -proc "APSMpBTSCheckMode"
    if [catch {APSMpBTSCheckMode -desiredState $desiredState -errorInfoVar $errorInfoVar} result] {
        lappend problemList $result
    }
    
    APSMpStep CheckBTSFlags -desc "Check BTS flags" -proc "APSMpBTSCheckFlags"
    if [catch {APSMpBTSCheckFlags -desiredState out -errorInfoVar $errorInfoVar} result] {
        lappend problemList $result
    }
    
    APSMpStep CheckBTSValves -desc "Check BTS values" -proc "APSMpBTSCheckValues"
    if [catch {APSMpBTSCheckValves -desiredState open -errorInfoVar $errorInfoVar} result] {
        lappend problemList $result
    }

    if [llength $problemList] {
        if [string length $errorInfoVar] {
            APSSetVarAndUpdate $errorInfoVar "Problem(s) found with BTS: $problemList"
        }
        APSMpReturn error "Problem(s) found with BTS: [join $problemList \n]"
    }
    APSMpReturn ok
}

proc APSMpBTSCheckMode {args} {
    set desiredState toRing
    set errorInfoVar ""
    if [APSStrictParseArguments {desiredState errorInfoVar}]==-1 {
        APSMpReturn error "Invalid arguments to APSMpBTSCheckDCPS"
    }

    lappend pvList ACIS:FAI_BX_GAP_ON ACIS:FAI_AB_GAP_ON
    lappend descripList BTS:BX:Switch BTS:AB:Switch
    if [string compare $desiredState toRing] {
        lappend desiredStateList ON OFF
    } else { 
        lappend desiredStateList OFF ON
    }

    if [catch {APSMpCheckPVListValues -pvList $pvList \
                 -descriptionList $descripList \
                 -desiredStateList $desiredStateList} result] {
        if [string length $errorInfoVar] {
            APSSetVarAndUpdate $errorInfoVar $result
        }
        APSMpReturn error $result
    }
    APSMpReturn ok
}    

proc APSMpBTSCheckDCPS {args} {
    set desiredState 0
    set errorInfoVar ""
    if [APSStrictParseArguments {desiredState errorInfoVar}]==-1 {
        APSMpReturn error "Invalid arguments to APSMpBTSCheckDCPS"
    }

    set problemList ""

    APSMpStep CheckQuads -desc "Check quads" -proc "APSMpSRCheckDCPSFamily"
    if [catch {APSMpBTSCheckDCPSFamily -family Q -desiredState 0 -errorInfoVar $errorInfoVar \
                 -errorDescription "bad status"} result] {
        lappend problemList $result
    }
    
    APSMpStep CheckBend -desc "Check bend" -proc "APSMpSRCheckDCPSFamily"
    if [catch {APSMpBTSCheckDCPSFamily -family B -desiredState 0 -errorInfoVar $errorInfoVar \
                 -errorDescription "bad status"} result] {
        lappend problemList $result
    }
    
    APSMpStep CheckHCorr -desc "Check horizontal correctors" -proc "APSMpSRCheckDCPSFamily"
    if [catch {APSMpBTSCheckDCPSFamily -family H -desiredState 0 -errorInfoVar $errorInfoVar \
                 -errorDescription "bad status"} result] {
        lappend problemList $result
    }
    
    APSMpStep CheckVCorr -desc "Check vertical correctors" -proc "APSMpSRCheckDCPSFamily"
    if [catch {APSMpBTSCheckDCPSFamily -family V -desiredState 0 -errorInfoVar $errorInfoVar \
                 -errorDescription "bad status"} result] {
        lappend problemList $result
    }

    if [llength $problemList] {
        if [string length $errorInfoVar] {
            APSSetVarAndUpdate $errorInfoVar "Problem(s) found with BTS DCPS: $problemList"
        }
        APSMpReturn error "Problem(s) found with BTS DCPS: $problemList"
    }
    APSMpReturn ok
}

proc APSMpBTSCheckDCPSFamily {args} {
    set family Q
    set desiredState 0
    set errorInfoVar ""
    set errorDescription "bad status"

    if [APSStrictParseArguments {family desiredState errorInfoVar errorDescription}]==-1 {
        APSMpReturn error "Invalid arguments to APSMpSRCheckDCPSFamily"
    }
    if [string length $errorInfoVar] { 
        global $errorInfoVar
    }
    switch $family {
        Q {
            set code [catch {exec cavget -list=BTS: \
                               -list=AQ1,AQ2,AQ3,AQ4,AQ5,BQ1,BQ2,BQ3,BQ4,CQ1,CQ2,CQ3 \
                               -list=:StatusCALC -pend=10 -label "-delim= "} result]
        }
        H {
            set code [catch {exec cavget -list=BTS: \
                               -list=AH1,AH2,AH3,BH1,BH2,CH1,R \
                               -list=:StatusCALC -pend=10 -label "-delim= "} result]
        }
        V {
            set code [catch {exec cavget -list=BTS: \
                               -list=AV1,AV2,AV3,BV1,CV1,R \
                               -list=:StatusCALC -pend=10 -label "-delim= "} result]
        }
        B {
            set code [catch {exec cavget -list=BTS: \
                               -list=BX,AB,BB \
                               -list=:StatusCALC -pend=10 -label "-delim= "} result]
        }
    }
    if $code {
        if [string length $errorInfoVar] { 
            set errorInfoVar "Problem getting DCPS status for BTS $family family."
        }
        APSMpReturn error "Problem getting DCPS status for BTS $family family."
    }
    array set statusArray $result
    set problemList ""
    set psStatus(0) on
    set psStatus(1) tol
    set psStatus(2) off
    set psStatus(3) inv
    foreach elem [array names statusArray] {
        if [string compare $statusArray($elem) $desiredState] {
            if $statusArray($elem)>3 {
                set statusArray($elem) 3
            }
            switch $statusArray($elem) {
                0 - 
                1 -
                2 -
                3 {
                    set problem $psStatus($statusArray($elem))
                }
                default {
                    set problem ?
                }
            }
            regsub :StatusCALC $elem "" tmp
            lappend problemList $tmp:$problem
        }
    }
    if [llength $problemList] {
        if [string length $errorInfoVar] { 
            APSSetVarAndUpdate $errorInfoVar "$errorDescription: $problemList"
        }
        APSMpReturn error "$errorDescription:  $problemList"
    }
    APSMpReturn ok
}
proc APSMpBTSCheckFlags {args} {
    set desiredState out
    set errorInfoVar ""
    if [APSStrictParseArguments {desiredState errorInfoVar}]==-1 {
        APSMpReturn error "Invalid arguments to APSMpBTSCheckFlags"
    }
    
    lappend pvList BTS:FS1:act_out_bi BTS:FS2:act_out_bi BTS:FS3:act_out_bi \
      BTS:FS4:act_out_bi BTS:FS5:act_out_bi BTS:FS5:act_out_bi 
    lappend descripList BTS:FS1 BTS:FS2 BTS:FS3 \
      BTS:FS4 BTS:FS5 BTS:FS5 
    if [string compare $desiredState out]==0 {
        lappend desiredStateList OPEN CLOSED CLOSED CLOSED CLOSED CLOSED 
    } else {
        lappend desiredStateList CLOSED OPEN OPEN OPEN OPEN OPEN 
    }

    if [catch {APSMpCheckPVListValues -pvList $pvList \
                 -descriptionList $descripList \
                 -desiredStateList $desiredStateList} result] {
        if [string length $errorInfoVar] {
            APSSetVarAndUpdate $errorInfoVar $result
        }
        APSMpReturn error $result
    }
    APSMpReturn ok
}

proc APSMpBTSCheckValves {args} {
    set desiredState open
    set errorInfoVar ""
    if [APSStrictParseArguments {desiredState errorInfoVar}]==-1 {
        APSMpReturn error "Invalid arguments to APSMpBTSCheckValves"
    }
    lappend pvList VM:BS:VAL1:openBI VM:BS:VAL2:openBI
    lappend descripList "BTS Valve 1" "BTS Valve 2"
    if [string compare $desiredState open]==0 {
        lappend desiredStateList open open
    } else {
        lappend desiredStateList "not open" "not open"
    }

    if [catch {APSMpCheckPVListValues -pvList $pvList \
                 -descriptionList $descripList \
                 -desiredStateList $desiredStateList} result] {
        if [string length $errorInfoVar] {
            APSSetVarAndUpdate $errorInfoVar $result
        }
        APSMpReturn error $result
    }
    APSMpReturn ok
}

