Files
sea/tcl/drivers/ccu4.tcl
l_samenv f5a129b6d9 improve autodevice deature
for autodevice to work, it is not necessary to be unplugged
for 60 seconds, only for a short time.
fixed this behaviour
2024-11-11 16:41:41 +01:00

724 lines
17 KiB
Tcl

# CCU 4
namespace eval ccu4 {} {
# 1=remote
variable deviceaction 1
variable newdevice ""
}
proc stdConfig::ccu4 {{title CCU4} args} {
variable name
variable node
set ins [string toupper [result instrument]]
if {$ins eq "SEAMAN"} {
set ins free
}
controller std "\n" 5
prop startcmd "cid csf cir cic=$ins"
hsetprop $node/tasks complete "ccu4::completeStart $name"
prop write ccu4::write
prop commerror ccu4::errorScript
prop freelist 0
prop obj /$name
pollperiod 0.5 0.5 5
obj ccu4 rd -int
prop enum 1
prop label on
prop read ccu4::read
prop cfgtablefile config/ccu4device.list
prop layoutpos 99
# if {[info exists ::rack_in_use]} {
prop instrument $ins
# }
default 1
kids $title {
node autodevice par -int [expr [llength $args] == 0]
prop enum 1
node fav out -int
prop newline 1
prop enum 1
prop label "flow available"
node f upd
prop label flow
prop avnode fav
node fs out -int
prop enum ok,no_sens
prop avnode fav
node mav out -int
prop newline 1
prop enum 1
prop label "n.v. motor available"
node fm upd -int
prop enum idle,opening,closing,opened,closed,no_motor
prop avnode mav
node fa out -int
prop enum fixed,controlled,automatic,offline
prop avnode mav
node mp out
prop label "motor pulse"
prop avnode mav
node msp upd
prop label "motor speed"
prop avnode mav
node mmp upd
prop label "measured pulse"
prop avnode mav
node mc out
prop label "motor current"
prop avnode mav
node mfc out
prop label "free current"
prop avnode mav
#obsolete
node moc out
prop label "overrun const"
prop avnode mav
node mtc out
prop label "torque const"
prop avnode mav
node mtl upd
prop label "torque limit"
prop avnode mav
node mft out
prop label "flow target"
prop avnode mav
node mt upd
prop label "torque"
prop avnode mav
#obsolete
node mo upd
prop label "overrun"
prop avnode mav
node mcr upd
prop label "read current"
prop avnode mav
node mot upd
prop label "open time"
prop avnode mav
node mw out
prop label "wiggle"
prop help "correction pulse after automatic open"
prop avnode mav
node hav out
prop newline 1
prop enum none,int,ext
prop label "He lev. available"
node h upd -secop=helev
prop label "he level"
prop avnode hav
prop errvar hsf
node hr upd
prop label "he sensor mm"
prop avnode hav
node hc upd
prop label "He meas. current"
prop avnode hav
node hu upd
prop label "He meas. volt"
prop avnode hav
node hh out
prop label "He full level"
prop avnode hav
node hl out
prop label "He fill level"
prop avnode hav
node htf out
prop label "fast period"
prop help "meas. period in fast mode"
prop avnode hav
node hts out
prop label "slow period"
prop help "meas. period in slow mode"
prop avnode hav
node hd out
prop label "He driv. current"
prop avnode hav
node hwr out
prop label "He wire res."
prop avnode hav
node hem out
prop label "empty"
prop help "sensor length in mm from top to empty pos."
prop avnode hav
node hfu out
prop label "full"
prop help "sensor length in mm from top to full pos."
prop avnode hav
node hcd out -int
prop enum stop,fill,off,auto,manual=7
prop avnode hav
node hv upd -int
prop enum fill_valve_off,filling,no_fill_valve,timeout,timeout1
prop avnode hav
node hsf upd -int
prop enum sens_ok,sens_warm,no_sens,timeout,not_yet_read,disabled
prop avnode hav
node ha out -int
prop enum 1
prop label "He auto fill"
prop avnode hav
node hm upd -int
prop enum 1
prop label measure
prop avnode hav
node hf out -int
prop enum slow,fast
prop avnode hav
node hbe out -int
prop enum 1
prop label LHe 48V enabled
prop avnode hav
node hmf upd
prop label "meas first"
prop avnode hav
node hms upd
prop label "meas speed"
prop avnode hav
node hit out
prop label "increase tolerance"
prop avnode hav
node hft out -int
prop label "fast/fill timeout"
prop avnode hav
node hea out
prop label "add. He channels"
prop enum 0,1,6=6
node hch out -int
prop label "LHe channel"
prop avnode hea
node hwr0 out
prop label "ext. He wire res."
prop avnode hea
node hem0 out
prop label "ext. empty"
prop help "sensor length in mm from top to empty pos."
prop avnode hea
node hfu0 out
prop label "ext. full"
prop help "sensor length in mm from top to full pos."
prop avnode hea
node hd0 out
prop label "ext. drive"
prop help "external sensor drive current (mA)"
prop avnode hea
for {set ch 0} {$ch < 6} {incr ch} {
node h$ch upd
prop errvar hs$ch
prop newline 1
prop avnode hea
node hs$ch upd -int
prop enum sens_ok,sens_warm,no_sens,timeout,not_yet_read,disabled
prop nonewline 1
prop avnode hea
}
node hfb upd
prop label He v. feedb.
prop avnode hav
node nav out -int
prop newline 1
prop enum 1
prop label "N2 available"
node nu upd -secop=n2upper
prop label "N2 upper"
prop avnode nav
node nl upd -secop=n2lower
prop label "N2 lower"
prop avnode nav
node nth out
prop label "N2 threshold"
prop avnode nav
node ntc out
prop label "N2 tube cool delay"
prop avnode nav
node ntm out
prop label "N2 fill timeout"
prop avnode nav
node ns upd -int
prop enum sens_ok,no_sens,short_circuit,upside_down,sens_warm,empty
prop avnode nav
node na out -int
prop enum 1
prop label "N2 auto fill"
prop avnode nav
node nv upd -int
prop enum fill_valve_off,filling,no_fill_valve,timeout,timeout1,boost
prop avnode nav
node nc out -int
prop enum stop,fill,off,auto
prop avnode nav
node nfb upd
prop label LN2 v. feedb.
prop avnode nav
node cda upd
prop newline 1
prop label "code res. a"
node cdb upd
prop label "code res. b"
node cba upd
prop label "code a invalid"
node cbb upd
prop label "code b invalid"
node cvs -int upd
prop label "config version"
node csp -int upd
prop label "hardware type"
node cdv out -text
prop label "device"
node cic out -text
prop label "connected to"
node cin upd -text
prop label "connect to"
node cds out
prop label "device state"
prop enum local,remote,loading,by_code,by_touch
node timing par 0
prop newline 1
prop enum 1
node tc upd
prop avnode timing
node tn upd
prop avnode timing
node th upd
prop avnode timing
node tf upd
prop avnode timing
node tm upd
prop avnode timing
node tv upd
prop avnode timing
node tq upd
prop avnode timing
node bdl out
prop label "valve boost delay"
foreach a $args {
if {$a eq "aux"} {
node axa upd -int
node ax upd
node axs upd
node axd upd -int
} elseif {[string match valve* $a]} {
set nvalve [string range $a 5 end]
for {set ch 1} {$ch <= 12} {incr ch} {
node v$ch rd -int 10
prop read ccu4::readValve v$ch
prop enum valve_off,valve_on,no_valve,timeout,timeout1,boost
if {$ch > $nvalve} {
prop visible false
}
node vc$ch out -int
prop write ccu4::writeValve v$ch
prop enum valve_off,valve_on
if {$ch > $nvalve} {
prop visible false
}
}
} elseif {$a ne "multiHe"} {
error "ERROR: unknown argument '$a' to ccu4"
}
}
}
return "CCU4"
}
proc ccu4::readValve {valve} {
# for some strange reason, v... are not queried with '?'
# we have to do it here
sct send $valve
return ccu4::complete
}
proc ccu4::writeValve {valve} {
set res [ccu4::write]
# update readback value immediately
hupdate [sct parent]/$valve [sct target]
return $res
}
proc ccu4::completeStart {name} {
set resval(cid) 0
set resval(cir) ""
set resval(csf) ""
foreach res [split [sct result]] {
lassign [split $res =] cmd val
set resval($cmd) $val
}
sct result $resval(cid)
if {$name eq "cc"} {
hsetprop [sct parent] freelist ""
set old [silent 0 result device ccu4version]
if {$old ne $resval(csf)} {
catch {device makeitem ccu4version $resval(csf)}
error "WARNING: CCU4 version has changed from $old to $resval(csf), please make 'samenv reload'"
}
set rack [silent other result device rack]
if {$rack ne "other" && $resval(cir) ne $rack && $resval(cir) ne "undef"} {
# force config download (including rack name 'cir')
hupdate [hgetpropval [sct parent] obj]/cvs 1
}
}
return [stdSct::completeStart]
}
proc ccu4::errorScript {} {
if {[sct result] eq "ASCERR: disconnected"} {
hupdate [sct obj]/status disconnected
return idle
} else {
hupdate [sct obj]/status [sct result]
stdSct::errorScript
}
}
proc ccu4::read {} {
if {![silent 1 hvali [sct]]} {
sct update 0
return idle
}
sct update 1
sct send "?"
return ccu4::update
}
proc ccu4::loadcodes {} {
if {[sct codeidx] >= [sct codelen]} {
# set version and save
sct send "cir=[silent {} result device rack] cvs=[sct codeversion] c=s"
clientput "CCU4: updated cfgtable to version from [clock format [sct codeversion] -format {%Y-%m-%d %H:%M}]"
if {[hvali [sct]/hea]} {
set hv a
} else {
set hv no
}
clientput "CCU4: this CCU has $hv He vessel channel"
return ccu4::loadcomplete
}
# add item to device list
sct send "c=[lindex [sct codelist] [sct codeidx]]"
sct codeidx [expr [sct codeidx] + 1]
return stdSct::complete
}
proc ccu4::loadcomplete {} {
hupdate [sct]/cvs [sct codeversion]
return unpoll
}
proc ccu4::update {} {
variable deviceaction
variable newdevice
hupdate [sct]/status ""
set fdone 0
set hidecmd ""
foreach item [sct result] {
set item [split $item "="]
set name [lindex $item 0]
set value [lindex $item 1]
hsetprop [sct]/$name done 1
switch $name {
f {
set fdone 1
}
cds {
if {$value >= 3 || $value == 0} { # device changed (local, by_code, by_touch)
set deviceaction $value
}
set newdevice ""
}
cdv {
if {$deviceaction >= 3} { # by_code, by_touch
set newdevice $value
}
}
cin {
if {[info exists ::rack_in_use] && $value eq "free"} {
clientput "disconnect requested from CCU touch display"
sct send "cic="
return "ccu4::completeDisconnect"
}
}
csp {
# check for not updated nodes
foreach node [hlist [sct]] {
set avnode [silent 0 hgetpropval [sct]/$node avnode]
if {$avnode ne "0"} {
set vis [hvali [sct]/$avnode]
if {$vis} {
set vistxt true
} else {
set vistxt false
}
if {[silent true hgetpropval [sct]/$node visible] ne $vistxt} {
hsetprop [sct]/$node visible $vistxt
if {! $vis} {
logsetup [sct]/$node clear
}
}
if {$vis && [silent 1 hgetpropval [sct]/$node done] == 0} {
append hidecmd "$node "
}
hsetprop [sct]/$node done 0
}
}
}
cda - cdb {
set cda [hval [sct]/cda]
set cdb [hval [sct]/cdb]
set $name $value
if {$cda == 999999 && $cdb == 999999} {
device makeitem was_unplugged 1
}
}
}
set visible [silent true hgetpropval [sct]/$name visible]
if {[silent notFound hlist [sct]/$name] eq "notFound"} {
if {[silent notFound sct notFound_$name] eq "notFound"} {
clientput "ERROR: [sct]/$name not found"
sct notFound_$name 1
}
} elseif {$visible eq "false"} {
append hidecmd "$name:"
logsetup [sct]/$name clear
} else {
set errvar [silent "" hgetpropval [sct]/$name errvar]
if {$errvar ne ""} {
set errval [hvali [sct]/$errvar]
if {$errval == 1} {
# sens warm
updateval [sct]/$name -11
} elseif {$errval == 3} {
# timeout
updateval [sct]/$name 111
} elseif {$errval > 0} {
hsetprop [sct]/$name geterror [lindex [split [hgetpropval [sct]/$errvar enum] ,] $errval]
hupdate [sct]/$name $value
} else {
updateval [sct]/$name $value
}
} else {
updateval [sct]/$name $value
}
}
}
# update flow anyway, as this triggers control
if {!$fdone && [silent true hgetpropval [sct]/f visible] ne "false"} {
hupdate [sct]/f [hvali [sct]/f]
}
hdelprop [sct] geterror
set cvs [hvali [sct]/cvs]
if {$cvs != 0 && [file exists [sct cfgtablefile]]} {
sct codeversion [file mtime [sct cfgtablefile]]
if {$cvs != [sct codeversion]} {
clientput "CCU4: replace cfgtable version from [clock format $cvs -format {%Y-%m-%d %H:%M}]"
hupdate [sct]/cvs 0
set cfgtbl [split [read_file [sct cfgtablefile]] \n]
set codelist [list ]
foreach line $cfgtbl {
if {[string index $line 0] ne "#" && [string length $line] > 1} {
set lline [split $line "\t"]
while {[llength $lline] < 6} {
lappend lline {}
}
lappend codelist [join $lline ","]
}
}
sct codelist $codelist
sct codeidx 0
sct codelen [llength [sct codelist]]
sct send "cvs=0 c=c"
[sct controller] poll [sct] 0.1 slow ccu4::loadcodes
return stdSct::complete
}
}
if {$deviceaction == 0} {
# CCU4 was restarted
# if {[info exists instrument]} {
# set ins [string toupper [sct instrument]]
# if {$instrument eq $ins} {
# clientput "this rack is ours"
# } elseif {$instrument eq ""} {
# clientput "assume this rack is ours"
# }
clientlog RENEW
device makeitem action renew
set deviceaction 1
sct send cds=1
return stdSct::complete
}
}
if {$deviceaction >= 3} {
if {$newdevice eq ""} {
# get new device name
sct send cdv
return ccu4::update
}
if {[sctval [sct]/autodevice]} {
set newdevice [string tolower $newdevice]
if {![file exists ${newdevice}.config]} {
set guess [glob ${newdevice}*.config]
if {[llength $guess] == 1} {
set newdevice [lindex [split $guess .] 0]
}
}
if {$newdevice eq "none"} {
device makeitem was_unplugged 1
}
device makeitem newdevice $newdevice
if {$deviceaction == 3} {
clientlog "PLUGGED $newdevice"
device makeitem action "plugged"
} else {
clientlog "SELECTED $newdevice"
device makeitem action "selected on touch display"
}
# set device state to "loading"
sct send cds=2
} elseif {$deviceaction == 3} {
# clientput "plugged [string tolower $newdevice] but autodevice off"
# set device state to "remote"
sct send cds=1
} else {
# clientput "[string tolower $newdevice] selected on CCU4, but autodevice off"
# set device state to "remote"
sct send cds=1
}
set deviceaction 1
return stdSct::complete
}
if {$hidecmd ne ""} {
sct send [lrange $hidecmd 0 10]
return stdSct::complete
}
# on seaman:
set fi [string toupper [silent 0 free_instruments]]
if {$fi ne "0"} {
if {[silent 0 sct freelist] ne $fi} {
sct freelist $fi
sct send cil=$fi
return stdSct::complete
}
}
return idle
}
proc ccu4::getdevice {old} {
variable deviceaction
catch {
set cdv [string toupper [hval /cc/cdv]]
set old [string toupper $old]
if {$cdv ne "NONE" && $cdv ne $old} {
set deviceaction 3
}
}
}
proc ccu4::write {} {
if {![hvali [sct parent]]} {
sct update [sct target]
return idle
}
set name [lindex [split [sct] "/"] 2]
#clientput "[expr [clock seconds] % 60] $name=[sct target]"
sct send "$name=[sct target]"
return ccu4::complete
}
proc ccu4::complete {} {
set res [split [sct result] "="]
sct update [lindex $res 1]
return idle
}
proc ccu4::completeDisconnect args {
dolater 0 rack_disconnect
return idle
}