# 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 }