# Generated driver for knauer_pump # vim: ft=tcl tabstop=8 softtabstop=2 shiftwidth=2 nocindent smartindent # namespace eval ::scobj::knauer_pump { set debug_threshold 5 } proc ::scobj::knauer_pump::debug_log {tc_root debug_level debug_string} { set catch_status [ catch { set debug_threshold [hgetpropval ${tc_root} debug_threshold] if {${debug_level} >= ${debug_threshold}} { set fd [open "../log/knauer_pump_[basename ${tc_root}].log" "a"] set line "[clock format [clock seconds] -format "%T"] ${debug_string}" puts ${fd} "${line}" close ${fd} } } catch_message ] } proc ::scobj::knauer_pump::sics_log {debug_level debug_string} { set catch_status [ catch { set debug_threshold ${::scobj::knauer_pump::debug_threshold} if {${debug_level} >= ${debug_threshold}} { sicslog "::scobj::knauer_pump::${debug_string}" } } catch_message ] } # checklimits function for driveable interface proc ::scobj::knauer_pump::checklimits {tc_root} { set catch_status [ catch { debug_log ${tc_root} 1 "checklimits tc_root=${tc_root} sct=[sct] target=[sct target]" set setpoint [sct target] if { [hpropexists [sct] lowerlimit] } { set lolimit [sct lowerlimit] } else { # lowerlimit not set, use target set lolimit [sct target] } if { [hpropexists [sct] upperlimit] } { set hilimit [sct upperlimit] } else { # upperlimit not set, use target set hilimit [sct target] } # checklimits hook code goes here if { ${setpoint} < ${lolimit} || ${setpoint} > ${hilimit} } { sct driving 0 error "setpoint ${setpoint} violates limits (${lolimit}..${hilimit}) on [sct]" } return OK } catch_message ] handle_exception ${catch_status} ${catch_message} } # check function for hset change proc ::scobj::knauer_pump::checkrange {tc_root} { set catch_status [ catch { debug_log ${tc_root} 1 "checkrange tc_root=${tc_root} sct=[sct] target=[sct target]" set setpoint [sct target] if { [hpropexists [sct] lowerlimit] } { set lolimit [sct lowerlimit] } else { # lowerlimit not set, use target set lolimit [sct target] } if { [hpropexists [sct] upperlimit] } { set hilimit [sct upperlimit] } else { # upperlimit not set, use target set hilimit [sct target] } # checkrange hook code goes here if { ${setpoint} < ${lolimit} || ${setpoint} > ${hilimit} } { error "setpoint ${setpoint} violates limits (${lolimit}..${hilimit}) on [sct]" } return OK } catch_message ] handle_exception ${catch_status} ${catch_message} } # function to request the read of a parameter on a device proc ::scobj::knauer_pump::flow_fetch {tc_root nextState cmd_str} { set catch_status [ catch { debug_log ${tc_root} 1 "flow_fetch tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" if { [hpropexists [sct] geterror] } { hdelprop [sct] geterror } set cmd "${cmd_str}" # flow_fetch hook code starts set index 4 set data [hgetpropval ${tc_root}/dummy/status real_data] set dlist [split ${data} ","] if { [llength ${dlist}] > ${index} } { set flow_pv [lindex ${dlist} 4] } else { set flow_pv 0.0 } sct result [expr {0.001 * ${flow_pv}}] set cmd "@@NOSEND@@" # flow_fetch hook code ends if { [hpropexists [sct] geterror] } { debug_log ${tc_root} 9 "[sct] error: [sct geterror]" error "[sct geterror]" } debug_log ${tc_root} 1 "flow_fetch sct send ${cmd}" if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { sct send "${cmd}" } return ${nextState} } catch_message ] handle_exception ${catch_status} ${catch_message} } # function to write a parameter value on a device proc ::scobj::knauer_pump::flow_write {tc_root nextState cmd_str} { set catch_status [ catch { debug_log ${tc_root} 1 "flow_write tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" if { [hpropexists [sct] geterror] } { hdelprop [sct] geterror } set par [sct target] set cmd "${cmd_str}${par}" # flow_write hook code starts set data [sct target] set cmd "@@NOSEND@@" set nextState idle if { ${data} != [sct oldval] } { debug_log ${tc_root} 1 "[sct] changed to new:${data}, from old:[sct oldval]" sct oldval ${data} sct update ${data} sct utime readtime } # flow_write hook code ends if { [hpropexists [sct] geterror] } { debug_log ${tc_root} 9 "[sct] error: [sct geterror]" error "[sct geterror]" } if { [hpropexists [sct] driving] } { if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } { sct driving 1 } } debug_log ${tc_root} 1 "flow_write sct send ${cmd}" if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { sct send "${cmd}" } return ${nextState} } catch_message ] handle_exception ${catch_status} ${catch_message} } # function to request the read of a parameter on a device proc ::scobj::knauer_pump::getValue {tc_root nextState cmd_str} { set catch_status [ catch { debug_log ${tc_root} 1 "getValue tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" if { [hpropexists [sct] geterror] } { hdelprop [sct] geterror } set cmd "${cmd_str}" # getValue hook code goes here debug_log ${tc_root} 1 "getValue sct send ${cmd}" if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { sct send "${cmd}" } return ${nextState} } catch_message ] handle_exception ${catch_status} ${catch_message} } # function to check the write parameter on a device proc ::scobj::knauer_pump::noResponse {tc_root} { set catch_status [ catch { debug_log ${tc_root} 1 "noResponse tc_root=${tc_root} sct=[sct] resp=[sct result]" # noResponse hook code goes here return "idle" } catch_message ] handle_exception ${catch_status} ${catch_message} } # check function for hset change proc ::scobj::knauer_pump::ratio_check {tc_root} { set catch_status [ catch { debug_log ${tc_root} 1 "ratio_check tc_root=${tc_root} sct=[sct] target=[sct target]" set setpoint [sct target] if { [hpropexists [sct] lowerlimit] } { set lolimit [sct lowerlimit] } else { # lowerlimit not set, use target set lolimit [sct target] } if { [hpropexists [sct] upperlimit] } { set hilimit [sct upperlimit] } else { # upperlimit not set, use target set hilimit [sct target] } # ratio_check hook code starts set rlist [split ${setpoint} /] if { [llength ${rlist}] != 4 } { sct geterror "${setpoint} has [llength ${rlist}] components, needs 4" error [sct geterror] } set sum 0 for {set i 0} {$i < 4} {incr i} { set cmp [lindex ${rlist} ${i}] if { ![string is integer -strict ${cmp}] } { sct geterror "component [expr {${i} + 1}] is not integer: \"${cmp}\"" error [sct geterror] } if { !(${cmp} >= 0 && ${cmp} <= 100) } { sct geterror "component [expr {${i} + 1}] is not between 0 and 100: \"${cmp}\"" error [sct geterror] } set sum [expr {${sum} + ${cmp}}] } if { ${sum} != 100 } { sct geterror "sum of components is ${sum}, must be 100" error [sct geterror] } # ratio_check hook code ends if { ${setpoint} < ${lolimit} || ${setpoint} > ${hilimit} } { error "setpoint ${setpoint} violates limits (${lolimit}..${hilimit}) on [sct]" } return OK } catch_message ] handle_exception ${catch_status} ${catch_message} } # function to request the read of a parameter on a device proc ::scobj::knauer_pump::ratio_fetch {tc_root nextState cmd_str} { set catch_status [ catch { debug_log ${tc_root} 1 "ratio_fetch tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" if { [hpropexists [sct] geterror] } { hdelprop [sct] geterror } set cmd "${cmd_str}" # ratio_fetch hook code starts set data [hgetpropval ${tc_root}/dummy/status real_data] set dlist [split ${data} ","] set ratio_vals "[lindex ${dlist} 5]/[lindex ${dlist} 6]/[lindex ${dlist} 7]/[lindex ${dlist} 8]" sct result ${ratio_vals} set cmd "@@NOSEND@@" # ratio_fetch hook code ends if { [hpropexists [sct] geterror] } { debug_log ${tc_root} 9 "[sct] error: [sct geterror]" error "[sct geterror]" } debug_log ${tc_root} 1 "ratio_fetch sct send ${cmd}" if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { sct send "${cmd}" } return ${nextState} } catch_message ] handle_exception ${catch_status} ${catch_message} } # function to write a parameter value on a device proc ::scobj::knauer_pump::ratio_write {tc_root nextState cmd_str} { set catch_status [ catch { debug_log ${tc_root} 1 "ratio_write tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" if { [hpropexists [sct] geterror] } { hdelprop [sct] geterror } set par [sct target] set cmd "${cmd_str}${par}" # ratio_write hook code starts set data [sct target] set cmd "@@NOSEND@@" set nextState idle if { ${data} != [sct oldval] } { debug_log ${tc_root} 1 "[sct] changed to new:${data}, from old:[sct oldval]" sct oldval ${data} sct update ${data} sct utime readtime } # ratio_write hook code ends if { [hpropexists [sct] geterror] } { debug_log ${tc_root} 9 "[sct] error: [sct geterror]" error "[sct geterror]" } if { [hpropexists [sct] driving] } { if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } { sct driving 1 } } debug_log ${tc_root} 1 "ratio_write sct send ${cmd}" if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { sct send "${cmd}" } return ${nextState} } catch_message ] handle_exception ${catch_status} ${catch_message} } # function to parse the read of a parameter on a device proc ::scobj::knauer_pump::rdValue {tc_root} { set catch_status [ catch { debug_log ${tc_root} 1 "rdValue tc_root=${tc_root} sct=[sct] result=[sct result]" if { [hpropexists [sct] geterror] } { hdelprop [sct] geterror } set data [sct result] set nextState "idle" if {[string equal -nocase -length 7 ${data} "ASCERR:"]} { # the protocol driver has reported an error sct geterror "${data}" error "[sct geterror]" } # rdValue hook code goes here if { ${data} != [sct oldval] } { debug_log ${tc_root} 1 "[sct] changed to new:${data}, from old:[sct oldval]" sct oldval ${data} sct update ${data} sct utime readtime } return ${nextState} } catch_message ] handle_exception ${catch_status} ${catch_message} } # function to parse the read of a parameter on a device proc ::scobj::knauer_pump::read_glp {tc_root} { set catch_status [ catch { debug_log ${tc_root} 1 "read_glp tc_root=${tc_root} sct=[sct] result=[sct result]" if { [hpropexists [sct] geterror] } { hdelprop [sct] geterror } set data [sct result] set nextState "idle" if {[string equal -nocase -length 7 ${data} "ASCERR:"]} { # the protocol driver has reported an error sct geterror "${data}" error "[sct geterror]" } # read_glp hook code starts if { [string equal -nocase -length 6 ${data} "ERROR:"] } { } else { set dlist [split [lindex [split ${data} ":"] 1] ","] sct real_data "[join [lrange ${dlist} 0 end] ,]" set data "Hidden in real_data property" } # read_glp hook code ends if { [hpropexists [sct] geterror] } { debug_log ${tc_root} 9 "[sct] error: [sct geterror]" error "[sct geterror]" } if { ${data} != [sct oldval] } { debug_log ${tc_root} 1 "[sct] changed to new:${data}, from old:[sct oldval]" sct oldval ${data} sct update ${data} sct utime readtime } return ${nextState} } catch_message ] handle_exception ${catch_status} ${catch_message} } # function to parse the read of a parameter on a device proc ::scobj::knauer_pump::read_status {tc_root} { set catch_status [ catch { debug_log ${tc_root} 1 "read_status tc_root=${tc_root} sct=[sct] result=[sct result]" if { [hpropexists [sct] geterror] } { hdelprop [sct] geterror } set data [sct result] set nextState "idle" if {[string equal -nocase -length 7 ${data} "ASCERR:"]} { # the protocol driver has reported an error sct geterror "${data}" error "[sct geterror]" } # read_status hook code starts set dlist [split [lindex [split ${data} ":"] 1] ","] sct real_data "[join [lrange ${dlist} 0 end] ,]" set data "Hidden in real_data property" # read_status hook code ends if { [hpropexists [sct] geterror] } { debug_log ${tc_root} 9 "[sct] error: [sct geterror]" error "[sct geterror]" } if { ${data} != [sct oldval] } { debug_log ${tc_root} 1 "[sct] changed to new:${data}, from old:[sct oldval]" sct oldval ${data} sct update ${data} sct utime readtime } return ${nextState} } catch_message ] handle_exception ${catch_status} ${catch_message} } # function to parse the read of a parameter on a device proc ::scobj::knauer_pump::remote_read {tc_root} { set catch_status [ catch { debug_log ${tc_root} 1 "remote_read tc_root=${tc_root} sct=[sct] result=[sct result]" if { [hpropexists [sct] geterror] } { hdelprop [sct] geterror } set data [sct result] set nextState "idle" if {[string equal -nocase -length 7 ${data} "ASCERR:"]} { # the protocol driver has reported an error sct geterror "${data}" error "[sct geterror]" } # remote_read hook code starts if { [string equal -length 7 ${data} "REMOTE:"] } { set data [lindex [split ${data} :] 1] } else { sct geterror "bad response" error "[sct geterror]" } # remote_read hook code ends if { [hpropexists [sct] geterror] } { debug_log ${tc_root} 9 "[sct] error: [sct geterror]" error "[sct geterror]" } if { ${data} != [sct oldval] } { debug_log ${tc_root} 1 "[sct] changed to new:${data}, from old:[sct oldval]" sct oldval ${data} sct update ${data} sct utime readtime } return ${nextState} } catch_message ] handle_exception ${catch_status} ${catch_message} } # function to write a parameter value on a device proc ::scobj::knauer_pump::remote_write {tc_root nextState cmd_str} { set catch_status [ catch { debug_log ${tc_root} 1 "remote_write tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" if { [hpropexists [sct] geterror] } { hdelprop [sct] geterror } set par [sct target] set cmd "${cmd_str}${par}" # remote_write hook code starts if { ${par} == 0 } { set cmd "LOCAL" } else { set cmd "REMOTE" } # remote_write hook code ends if { [hpropexists [sct] geterror] } { debug_log ${tc_root} 9 "[sct] error: [sct geterror]" error "[sct geterror]" } if { [hpropexists [sct] driving] } { if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } { sct driving 1 } } debug_log ${tc_root} 1 "remote_write sct send ${cmd}" if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { sct send "${cmd}" } return ${nextState} } catch_message ] handle_exception ${catch_status} ${catch_message} } # function to write a parameter value on a device proc ::scobj::knauer_pump::setValue {tc_root nextState cmd_str} { set catch_status [ catch { debug_log ${tc_root} 1 "setValue tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" if { [hpropexists [sct] geterror] } { hdelprop [sct] geterror } set par [sct target] set cmd "${cmd_str}${par}" # setValue hook code goes here if { [hpropexists [sct] driving] } { if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } { sct driving 1 } } debug_log ${tc_root} 1 "setValue sct send ${cmd}" if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { sct send "${cmd}" } return ${nextState} } catch_message ] handle_exception ${catch_status} ${catch_message} } # function to request the read of a parameter on a device proc ::scobj::knauer_pump::state_fetch {tc_root nextState cmd_str} { set catch_status [ catch { debug_log ${tc_root} 1 "state_fetch tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" if { [hpropexists [sct] geterror] } { hdelprop [sct] geterror } set cmd "${cmd_str}" # state_fetch hook code starts set index 1 set data [hgetpropval ${tc_root}/dummy/status real_data] set dlist [split ${data} ","] if { [llength ${dlist}] > ${index} } { set state_code [lindex ${dlist} ${index}] } else { set state_code "0" } set cmd "@@NOSEND@@" if { ${state_code} < 0 || ${state_code} > 9 } { sct geterror "Invalid device_state ${state_code}" error "[sct geterror]" } set slist [list "SYS_ST_INITIALIZING" \ "SYS_ST_OFF" \ "SYS_ST_IDLE" \ "SYS_ST_RUN" \ "SYS_ST_HOLD" \ "SYS_ST_PURGE" \ "SYS_ST_STANDBY" \ "SYS_ST_SEVEN" \ "SYS_ST_FAILED" \ "SYS_ST_RUNATEND" \ ] sct result [lindex ${slist} ${state_code}] # state_fetch hook code ends if { [hpropexists [sct] geterror] } { debug_log ${tc_root} 9 "[sct] error: [sct geterror]" error "[sct geterror]" } debug_log ${tc_root} 1 "state_fetch sct send ${cmd}" if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { sct send "${cmd}" } return ${nextState} } catch_message ] handle_exception ${catch_status} ${catch_message} } # function to request the read of a parameter on a device proc ::scobj::knauer_pump::status_fetch {tc_root nextState cmd_str} { set catch_status [ catch { debug_log ${tc_root} 1 "status_fetch tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" if { [hpropexists [sct] geterror] } { hdelprop [sct] geterror } set cmd "${cmd_str}" # status_fetch hook code starts set index 1 set data [hgetpropval ${tc_root}/dummy/status real_data] set dlist [split ${data} ","] set status_code [lindex ${dlist} ${index}] set cmd "@@NOSEND@@" if { ${status_code} == 3 } { sct result "PUMPING" } else { sct result "IDLE" } # status_fetch hook code ends if { [hpropexists [sct] geterror] } { debug_log ${tc_root} 9 "[sct] error: [sct geterror]" error "[sct geterror]" } debug_log ${tc_root} 1 "status_fetch sct send ${cmd}" if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { sct send "${cmd}" } return ${nextState} } catch_message ] handle_exception ${catch_status} ${catch_message} } # function to check the write parameter on a device proc ::scobj::knauer_pump::volume_check {tc_root} { set catch_status [ catch { debug_log ${tc_root} 1 "volume_check tc_root=${tc_root} sct=[sct] resp=[sct result]" # volume_check hook code goes here return "idle" } catch_message ] handle_exception ${catch_status} ${catch_message} } # checkstatus function for driveable interface proc ::scobj::knauer_pump::volume_checkstatus {tc_root} { set catch_status [ catch { # volume_checkstatus hook code goes here if {[sct driving]} { set sp "[sct target]" set pv "[hval ${tc_root}/[sct driveable]]" if { abs(${pv} - ${sp}) <= [sct tolerance] } { if { [hpropexists [sct] settle_time] } { if { [hpropexists [sct] settle_time_start] } { if { [sct utime] - [sct settle_time_start] >= [sct settle_time]} { sct driving 0 return "idle" } return "busy" } else { sct utime settle_time_start return "busy" } } sct driving 0 return "idle" } if { [hpropexists [sct] settle_time_start] } { hdelprop [sct] settle_time_start } return "busy" } else { return "idle" } } catch_message ] handle_exception ${catch_status} ${catch_message} } # function to request the read of a parameter on a device proc ::scobj::knauer_pump::volume_fetch {tc_root nextState cmd_str} { set catch_status [ catch { debug_log ${tc_root} 1 "volume_fetch tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" if { [hpropexists [sct] geterror] } { hdelprop [sct] geterror } set cmd "${cmd_str}" # volume_fetch hook code starts set data [hgetpropval ${tc_root}/dummy/glp real_data] set dlist [split ${data} ","] if { [llength ${dlist}] > 11 } { set pump_volm [lindex ${dlist} 10] set pump_voln [lindex ${dlist} 11] set pump_volume [expr {${pump_volm} + 0.000001 * ${pump_voln}}] } else { set pump_volume 0.0 } sct raw_volume ${pump_volume} if { [hpropexists [sct] base_volume] } { set pump_volume [expr {${pump_volume} - [sct base_volume]}] } elseif { [hpropexists [sct] raw_volume] } { sct base_volume [sct raw_volume] } sct result [format "%.2f" ${pump_volume}] set cmd "@@NOSEND@@" # volume_fetch hook code ends if { [hpropexists [sct] geterror] } { debug_log ${tc_root} 9 "[sct] error: [sct geterror]" error "[sct geterror]" } debug_log ${tc_root} 1 "volume_fetch sct send ${cmd}" if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { sct send "${cmd}" } return ${nextState} } catch_message ] handle_exception ${catch_status} ${catch_message} } # function to request the read of a parameter on a device proc ::scobj::knauer_pump::volume_fsm {tc_root nextState cmd_str} { set catch_status [ catch { debug_log ${tc_root} 1 "volume_fsm tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" if { [hpropexists [sct] geterror] } { hdelprop [sct] geterror } set cmd "${cmd_str}" # volume_fsm hook code starts if { [sct this_state] > 0 } { set flow_tgt [expr {int(1000.0 * [hval ${tc_root}/pump/flow/setp])}] set ratio_tgt [join [split [hval ${tc_root}/pump/ratio/setp] /] ,] set time_tgt [expr {int(60000.0 * 1000.0 * [sct target] / ${flow_tgt})}] set time_1 [expr {${time_tgt} - 500}] set time_2 [expr {${time_tgt} + 500}] set saveState ${nextState} set nextState "noResponse" if { [sct this_state] == 1 } { set cmd "GLP?" set nextState ${saveState} sct this_state [expr {[sct this_state] + 1}] } elseif { [sct this_state] == 2 } { set cmd "TT_LOAD:1" sct this_state [expr {[sct this_state] + 1}] } elseif { [sct this_state] == 3 } { set cmd "TT_SET:0,0,${flow_tgt},${ratio_tgt},0,0,0,0,0,0,0,0" sct this_state [expr {[sct this_state] + 1}] } elseif { [sct this_state] == 4 } { set cmd "TT_SET:1,${time_1},${flow_tgt},${ratio_tgt},0,0,0,0,0,0,0,0" sct this_state [expr {[sct this_state] + 1}] } elseif { [sct this_state] == 5 } { set cmd "TT_SET:2,${time_2},0,${ratio_tgt},0,0,0,0,0,0,0,0" sct this_state [expr {[sct this_state] + 1}] } elseif { [sct this_state] == 6 } { set cmd "START:1,0" sct this_state 0 } elseif { [sct this_state] == 91 } { set cmd "STOP:1,0" sct this_state 92 } elseif { [sct this_state] == 92 } { set cmd "STOP:0,0" sct this_state 93 } elseif { [sct this_state] == 93 } { if { !([hpropexists ${tc_root}/pump/remote target] && [hgetpropval ${tc_root}/pump/remote target] == 1) } { set cmd "LOCAL" } else { set cmd "@@NOSEND@@" } sct this_state 0 } else { sct this_state 0 set cmd "@@NOSEND@@" set nextState idle } } else { set cmd "@@NOSEND@@" set nextState idle if { [hpropexists [sct] pumping] && [sct pumping] } { set new_value [hval ${tc_root}/pump/status] set old_value [sct oldval] if {${new_value} != ${old_value}} { sct oldval ${new_value} if {${old_value} == "PUMPING" && ${new_value} == "IDLE"} { set cmd "STOP:0,0" sct this_state 91 set nextState noResponse sct result "" sct driving 0 sct pumping 0 } } } } # volume_fsm hook code ends if { [hpropexists [sct] geterror] } { debug_log ${tc_root} 9 "[sct] error: [sct geterror]" error "[sct geterror]" } debug_log ${tc_root} 1 "volume_fsm sct send ${cmd}" if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { sct send "${cmd}" } return ${nextState} } catch_message ] handle_exception ${catch_status} ${catch_message} } # halt function for driveable interface proc ::scobj::knauer_pump::volume_halt {tc_root} { set catch_status [ catch { debug_log ${tc_root} 1 "volume_halt tc_root=${tc_root} sct=[sct] driving=[sct driving]" ### TODO hset [sct] [hval [sct]] # volume_halt hook code starts set cmd "STOP:0,0" sct this_state 91 debug_log ${tc_root} 1 "volume_halt sct send ${cmd}" sct send ${cmd} # volume_halt hook code ends sct driving 0 return "idle" } catch_message ] handle_exception ${catch_status} ${catch_message} } # function to parse the read of a parameter on a device proc ::scobj::knauer_pump::volume_read {tc_root} { set catch_status [ catch { debug_log ${tc_root} 1 "volume_read tc_root=${tc_root} sct=[sct] result=[sct result]" if { [hpropexists [sct] geterror] } { hdelprop [sct] geterror } set data [sct result] set nextState "idle" if {[string equal -nocase -length 7 ${data} "ASCERR:"]} { # the protocol driver has reported an error sct geterror "${data}" error "[sct geterror]" } # volume_read hook code goes here if { ${data} != [sct oldval] } { debug_log ${tc_root} 1 "[sct] changed to new:${data}, from old:[sct oldval]" sct oldval ${data} sct update ${data} sct utime readtime } return ${nextState} } catch_message ] handle_exception ${catch_status} ${catch_message} } # function to parse the read of a parameter on a device proc ::scobj::knauer_pump::volume_store {tc_root} { set catch_status [ catch { debug_log ${tc_root} 1 "volume_store tc_root=${tc_root} sct=[sct] result=[sct result]" if { [hpropexists [sct] geterror] } { hdelprop [sct] geterror } set data [sct result] set nextState "idle" if {[string equal -nocase -length 7 ${data} "ASCERR:"]} { # the protocol driver has reported an error sct geterror "${data}" error "[sct geterror]" } # volume_store hook code starts if { [sct this_state] == 2 } { set ns [namespace current] # store the GLP result hsetprop ${tc_root}/dummy/glp result "${data}" sct with ${tc_root}/dummy/glp "${ns}::read_glp ${tc_root}" # extract the volume sct with ${tc_root}/[sct driveable] "${ns}::volume_fetch ${tc_root} ${nextState} @@NOSEND@@" sct with ${tc_root}/[sct driveable] "${ns}::volume_read ${tc_root}" # copy it to base_volume hsetprop ${tc_root}/[sct driveable] base_volume [hgetpropval ${tc_root}/[sct driveable] raw_volume] } if { [hpropexists [sct] target] } { set data [sct target] } else { set data 0.0 } # volume_store hook code ends if { [hpropexists [sct] geterror] } { debug_log ${tc_root} 9 "[sct] error: [sct geterror]" error "[sct geterror]" } if { ${data} != [sct oldval] } { debug_log ${tc_root} 1 "[sct] changed to new:${data}, from old:[sct oldval]" sct oldval ${data} sct update ${data} sct utime readtime } return ${nextState} } catch_message ] handle_exception ${catch_status} ${catch_message} } # function to write a parameter value on a device proc ::scobj::knauer_pump::volume_write {tc_root nextState cmd_str} { set catch_status [ catch { debug_log ${tc_root} 1 "volume_write tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" if { [hpropexists [sct] geterror] } { hdelprop [sct] geterror } set par [sct target] set cmd "${cmd_str}${par}" # volume_write hook code starts hset ${tc_root}/[sct driveable] 0.0 set cmd "REMOTE" sct this_state 1 sct pumping 1 set data ${par} if { ${data} != [sct oldval] } { debug_log ${tc_root} 1 "[sct] changed to new:${data}, from old:[sct oldval]" sct oldval ${data} sct update ${data} sct utime readtime } # volume_write hook code ends if { [hpropexists [sct] geterror] } { debug_log ${tc_root} 9 "[sct] error: [sct geterror]" error "[sct geterror]" } if { [hpropexists [sct] driving] } { if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } { sct driving 1 } } debug_log ${tc_root} 1 "volume_write sct send ${cmd}" if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { sct send "${cmd}" } return ${nextState} } catch_message ] handle_exception ${catch_status} ${catch_message} } proc ::scobj::knauer_pump::mkDriver { sct_controller name device_class simulation_flag ip_address tcp_port } { ::scobj::knauer_pump::sics_log 9 "::scobj::knauer_pump::mkDriver ${sct_controller} ${name} ${device_class} ${simulation_flag} ${ip_address} ${tcp_port}" set ns "[namespace current]" set catch_status [ catch { MakeSICSObj ${name} SCT_OBJECT sicslist setatt ${name} klass ${device_class} sicslist setatt ${name} long_name ${name} set scobj_hpath /sics/${name} hfactory ${scobj_hpath}/dummy plain spy none hsetprop ${scobj_hpath}/dummy data "false" hsetprop ${scobj_hpath}/dummy klass "@none" hsetprop ${scobj_hpath}/dummy type "part" hfactory ${scobj_hpath}/dummy/glp plain user text hsetprop ${scobj_hpath}/dummy/glp read ${ns}::getValue ${scobj_hpath} read_glp {GLP?} hsetprop ${scobj_hpath}/dummy/glp read_glp ${ns}::read_glp ${scobj_hpath} hsetprop ${scobj_hpath}/dummy/glp control false hsetprop ${scobj_hpath}/dummy/glp data false hsetprop ${scobj_hpath}/dummy/glp mutable true hsetprop ${scobj_hpath}/dummy/glp nxsave false hsetprop ${scobj_hpath}/dummy/glp oldval UNKNOWN hsetprop ${scobj_hpath}/dummy/glp real_data " " hsetprop ${scobj_hpath}/dummy/glp sdsinfo "::nexus::scobj::sdsinfo" hsetprop ${scobj_hpath}/dummy/glp type "part" hsetprop ${scobj_hpath}/dummy/glp nxalias "${name}_dummy_glp" hfactory ${scobj_hpath}/dummy/status plain user text hsetprop ${scobj_hpath}/dummy/status read ${ns}::getValue ${scobj_hpath} read_status {STATUS?} hsetprop ${scobj_hpath}/dummy/status read_status ${ns}::read_status ${scobj_hpath} hsetprop ${scobj_hpath}/dummy/status control false hsetprop ${scobj_hpath}/dummy/status data false hsetprop ${scobj_hpath}/dummy/status mutable true hsetprop ${scobj_hpath}/dummy/status nxsave false hsetprop ${scobj_hpath}/dummy/status oldval UNKNOWN hsetprop ${scobj_hpath}/dummy/status real_data " " hsetprop ${scobj_hpath}/dummy/status sdsinfo "::nexus::scobj::sdsinfo" hsetprop ${scobj_hpath}/dummy/status type "part" hsetprop ${scobj_hpath}/dummy/status nxalias "${name}_dummy_status" if {[string equal -nocase "${simulation_flag}" "false"]} { ${sct_controller} poll ${scobj_hpath}/dummy/glp 1 ${sct_controller} poll ${scobj_hpath}/dummy/status 1 } else { ::scobj::knauer_pump::sics_log 9 "simulation_flag=${simulation_flag} => No poll/write for knauer_pump" } hfactory ${scobj_hpath}/pump plain spy none hsetprop ${scobj_hpath}/pump data "true" hsetprop ${scobj_hpath}/pump klass "@none" hsetprop ${scobj_hpath}/pump type "part" hfactory ${scobj_hpath}/pump/remote plain user int hsetprop ${scobj_hpath}/pump/remote read ${ns}::getValue ${scobj_hpath} remote_read {REMOTE?} hsetprop ${scobj_hpath}/pump/remote remote_read ${ns}::remote_read ${scobj_hpath} hsetprop ${scobj_hpath}/pump/remote write ${ns}::remote_write ${scobj_hpath} noResponse {} hsetprop ${scobj_hpath}/pump/remote noResponse ${ns}::noResponse ${scobj_hpath} hsetprop ${scobj_hpath}/pump/remote check ${ns}::checkrange ${scobj_hpath} hsetprop ${scobj_hpath}/pump/remote control true hsetprop ${scobj_hpath}/pump/remote data true hsetprop ${scobj_hpath}/pump/remote mutable true hsetprop ${scobj_hpath}/pump/remote nxsave true hsetprop ${scobj_hpath}/pump/remote values 0,1 hsetprop ${scobj_hpath}/pump/remote oldval 0 hsetprop ${scobj_hpath}/pump/remote klass "parameter" hsetprop ${scobj_hpath}/pump/remote sdsinfo "::nexus::scobj::sdsinfo" hsetprop ${scobj_hpath}/pump/remote type "part" hsetprop ${scobj_hpath}/pump/remote nxalias "${name}_pump_remote" hfactory ${scobj_hpath}/pump/state plain user text hsetprop ${scobj_hpath}/pump/state read ${ns}::state_fetch ${scobj_hpath} rdValue { } hsetprop ${scobj_hpath}/pump/state rdValue ${ns}::rdValue ${scobj_hpath} hsetprop ${scobj_hpath}/pump/state control true hsetprop ${scobj_hpath}/pump/state data true hsetprop ${scobj_hpath}/pump/state mutable true hsetprop ${scobj_hpath}/pump/state nxsave true hsetprop ${scobj_hpath}/pump/state oldval UNKNOWN hsetprop ${scobj_hpath}/pump/state klass "parameter" hsetprop ${scobj_hpath}/pump/state sdsinfo "::nexus::scobj::sdsinfo" hsetprop ${scobj_hpath}/pump/state type "part" hsetprop ${scobj_hpath}/pump/state nxalias "${name}_pump_state" hfactory ${scobj_hpath}/pump/status plain user text hsetprop ${scobj_hpath}/pump/status read ${ns}::status_fetch ${scobj_hpath} rdValue { } hsetprop ${scobj_hpath}/pump/status rdValue ${ns}::rdValue ${scobj_hpath} hsetprop ${scobj_hpath}/pump/status control true hsetprop ${scobj_hpath}/pump/status data true hsetprop ${scobj_hpath}/pump/status mutable true hsetprop ${scobj_hpath}/pump/status nxsave true hsetprop ${scobj_hpath}/pump/status oldval UNKNOWN hsetprop ${scobj_hpath}/pump/status klass "parameter" hsetprop ${scobj_hpath}/pump/status sdsinfo "::nexus::scobj::sdsinfo" hsetprop ${scobj_hpath}/pump/status type "part" hsetprop ${scobj_hpath}/pump/status nxalias "${name}_pump_status" if {[string equal -nocase "${simulation_flag}" "false"]} { ${sct_controller} poll ${scobj_hpath}/pump/remote 1 ${sct_controller} poll ${scobj_hpath}/pump/state 1 ${sct_controller} poll ${scobj_hpath}/pump/status 1 ${sct_controller} write ${scobj_hpath}/pump/remote } else { ::scobj::knauer_pump::sics_log 9 "simulation_flag=${simulation_flag} => No poll/write for knauer_pump" } hfactory ${scobj_hpath}/pump/flow plain spy none hsetprop ${scobj_hpath}/pump/flow data "true" hsetprop ${scobj_hpath}/pump/flow klass "@none" hsetprop ${scobj_hpath}/pump/flow type "part" hfactory ${scobj_hpath}/pump/flow/pval plain user float hsetprop ${scobj_hpath}/pump/flow/pval read ${ns}::flow_fetch ${scobj_hpath} rdValue { } hsetprop ${scobj_hpath}/pump/flow/pval rdValue ${ns}::rdValue ${scobj_hpath} hsetprop ${scobj_hpath}/pump/flow/pval control true hsetprop ${scobj_hpath}/pump/flow/pval data true hsetprop ${scobj_hpath}/pump/flow/pval mutable true hsetprop ${scobj_hpath}/pump/flow/pval nxsave true hsetprop ${scobj_hpath}/pump/flow/pval oldval 0.0 hsetprop ${scobj_hpath}/pump/flow/pval klass "parameter" hsetprop ${scobj_hpath}/pump/flow/pval sdsinfo "::nexus::scobj::sdsinfo" hsetprop ${scobj_hpath}/pump/flow/pval type "part" hsetprop ${scobj_hpath}/pump/flow/pval units "mL/min" hsetprop ${scobj_hpath}/pump/flow/pval nxalias "${name}_pump_flow_pval" hfactory ${scobj_hpath}/pump/flow/setp plain user float hsetprop ${scobj_hpath}/pump/flow/setp write ${ns}::flow_write ${scobj_hpath} noResponse { } hsetprop ${scobj_hpath}/pump/flow/setp noResponse ${ns}::noResponse ${scobj_hpath} hsetprop ${scobj_hpath}/pump/flow/setp check ${ns}::checkrange ${scobj_hpath} hsetprop ${scobj_hpath}/pump/flow/setp control true hsetprop ${scobj_hpath}/pump/flow/setp data true hsetprop ${scobj_hpath}/pump/flow/setp mutable true hsetprop ${scobj_hpath}/pump/flow/setp nxsave true hsetprop ${scobj_hpath}/pump/flow/setp lowerlimit 0 hsetprop ${scobj_hpath}/pump/flow/setp upperlimit 9.999 hsetprop ${scobj_hpath}/pump/flow/setp oldval 1.0 hset ${scobj_hpath}/pump/flow/setp 1.0 hsetprop ${scobj_hpath}/pump/flow/setp klass "parameter" hsetprop ${scobj_hpath}/pump/flow/setp sdsinfo "::nexus::scobj::sdsinfo" hsetprop ${scobj_hpath}/pump/flow/setp type "part" hsetprop ${scobj_hpath}/pump/flow/setp units "mL/min" hsetprop ${scobj_hpath}/pump/flow/setp nxalias "${name}_pump_flow_setp" if {[string equal -nocase "${simulation_flag}" "false"]} { ${sct_controller} poll ${scobj_hpath}/pump/flow/pval 1 ${sct_controller} write ${scobj_hpath}/pump/flow/setp } else { ::scobj::knauer_pump::sics_log 9 "simulation_flag=${simulation_flag} => No poll/write for knauer_pump" } hfactory ${scobj_hpath}/pump/ratio plain spy none hsetprop ${scobj_hpath}/pump/ratio data "true" hsetprop ${scobj_hpath}/pump/ratio klass "@none" hsetprop ${scobj_hpath}/pump/ratio type "part" hfactory ${scobj_hpath}/pump/ratio/pval plain user text hsetprop ${scobj_hpath}/pump/ratio/pval read ${ns}::ratio_fetch ${scobj_hpath} rdValue { } hsetprop ${scobj_hpath}/pump/ratio/pval rdValue ${ns}::rdValue ${scobj_hpath} hsetprop ${scobj_hpath}/pump/ratio/pval control true hsetprop ${scobj_hpath}/pump/ratio/pval data true hsetprop ${scobj_hpath}/pump/ratio/pval mutable true hsetprop ${scobj_hpath}/pump/ratio/pval nxsave true hsetprop ${scobj_hpath}/pump/ratio/pval oldval UNKNOWN hsetprop ${scobj_hpath}/pump/ratio/pval klass "parameter" hsetprop ${scobj_hpath}/pump/ratio/pval sdsinfo "::nexus::scobj::sdsinfo" hsetprop ${scobj_hpath}/pump/ratio/pval type "part" hsetprop ${scobj_hpath}/pump/ratio/pval units "percent" hsetprop ${scobj_hpath}/pump/ratio/pval nxalias "${name}_pump_ratio_pval" hfactory ${scobj_hpath}/pump/ratio/setp plain user text hsetprop ${scobj_hpath}/pump/ratio/setp write ${ns}::ratio_write ${scobj_hpath} noResponse { } hsetprop ${scobj_hpath}/pump/ratio/setp noResponse ${ns}::noResponse ${scobj_hpath} hsetprop ${scobj_hpath}/pump/ratio/setp check ${ns}::ratio_check ${scobj_hpath} hsetprop ${scobj_hpath}/pump/ratio/setp control true hsetprop ${scobj_hpath}/pump/ratio/setp data true hsetprop ${scobj_hpath}/pump/ratio/setp mutable true hsetprop ${scobj_hpath}/pump/ratio/setp nxsave true hsetprop ${scobj_hpath}/pump/ratio/setp oldval 25/25/25/25 hset ${scobj_hpath}/pump/ratio/setp 25/25/25/25 hsetprop ${scobj_hpath}/pump/ratio/setp klass "parameter" hsetprop ${scobj_hpath}/pump/ratio/setp sdsinfo "::nexus::scobj::sdsinfo" hsetprop ${scobj_hpath}/pump/ratio/setp type "part" hsetprop ${scobj_hpath}/pump/ratio/setp units "percent" hsetprop ${scobj_hpath}/pump/ratio/setp nxalias "${name}_pump_ratio_setp" if {[string equal -nocase "${simulation_flag}" "false"]} { ${sct_controller} poll ${scobj_hpath}/pump/ratio/pval 1 ${sct_controller} write ${scobj_hpath}/pump/ratio/setp } else { ::scobj::knauer_pump::sics_log 9 "simulation_flag=${simulation_flag} => No poll/write for knauer_pump" } hfactory ${scobj_hpath}/pump/volume plain spy none hsetprop ${scobj_hpath}/pump/volume data "true" hsetprop ${scobj_hpath}/pump/volume klass "@none" hsetprop ${scobj_hpath}/pump/volume type "part" hfactory ${scobj_hpath}/pump/volume/pval plain user float hsetprop ${scobj_hpath}/pump/volume/pval read ${ns}::volume_fetch ${scobj_hpath} volume_read { } hsetprop ${scobj_hpath}/pump/volume/pval volume_read ${ns}::volume_read ${scobj_hpath} hsetprop ${scobj_hpath}/pump/volume/pval control true hsetprop ${scobj_hpath}/pump/volume/pval data true hsetprop ${scobj_hpath}/pump/volume/pval mutable true hsetprop ${scobj_hpath}/pump/volume/pval nxsave true hsetprop ${scobj_hpath}/pump/volume/pval oldval 0.0 hsetprop ${scobj_hpath}/pump/volume/pval klass "parameter" hsetprop ${scobj_hpath}/pump/volume/pval sdsinfo "::nexus::scobj::sdsinfo" hsetprop ${scobj_hpath}/pump/volume/pval type "part" hsetprop ${scobj_hpath}/pump/volume/pval units "mL" hsetprop ${scobj_hpath}/pump/volume/pval nxalias "${name}_pump_volume_pval" hfactory ${scobj_hpath}/pump/volume/setp plain user float hsetprop ${scobj_hpath}/pump/volume/setp read ${ns}::volume_fsm ${scobj_hpath} volume_store { } hsetprop ${scobj_hpath}/pump/volume/setp volume_store ${ns}::volume_store ${scobj_hpath} hsetprop ${scobj_hpath}/pump/volume/setp write ${ns}::volume_write ${scobj_hpath} volume_check { } hsetprop ${scobj_hpath}/pump/volume/setp volume_check ${ns}::volume_check ${scobj_hpath} hsetprop ${scobj_hpath}/pump/volume/setp check ${ns}::checkrange ${scobj_hpath} hsetprop ${scobj_hpath}/pump/volume/setp driving 0 hsetprop ${scobj_hpath}/pump/volume/setp checklimits ${ns}::checklimits ${scobj_hpath} hsetprop ${scobj_hpath}/pump/volume/setp checkstatus ${ns}::volume_checkstatus ${scobj_hpath} hsetprop ${scobj_hpath}/pump/volume/setp halt ${ns}::volume_halt ${scobj_hpath} hsetprop ${scobj_hpath}/pump/volume/setp driveable pump/volume/pval hsetprop ${scobj_hpath}/pump/volume/setp control true hsetprop ${scobj_hpath}/pump/volume/setp data true hsetprop ${scobj_hpath}/pump/volume/setp mutable true hsetprop ${scobj_hpath}/pump/volume/setp nxsave true hsetprop ${scobj_hpath}/pump/volume/setp lowerlimit 0 hsetprop ${scobj_hpath}/pump/volume/setp upperlimit 100 hsetprop ${scobj_hpath}/pump/volume/setp tolerance 0.01 hsetprop ${scobj_hpath}/pump/volume/setp oldval 0.0 hsetprop ${scobj_hpath}/pump/volume/setp klass "parameter" hsetprop ${scobj_hpath}/pump/volume/setp sdsinfo "::nexus::scobj::sdsinfo" hsetprop ${scobj_hpath}/pump/volume/setp this_state "0" hsetprop ${scobj_hpath}/pump/volume/setp type "drivable" hsetprop ${scobj_hpath}/pump/volume/setp units "mL" hsetprop ${scobj_hpath}/pump/volume/setp nxalias "${name}_pump_volume_setp" if {[string equal -nocase "${simulation_flag}" "false"]} { ${sct_controller} poll ${scobj_hpath}/pump/volume/pval 1 ${sct_controller} poll ${scobj_hpath}/pump/volume/setp 1 ${sct_controller} write ${scobj_hpath}/pump/volume/setp } else { ::scobj::knauer_pump::sics_log 9 "simulation_flag=${simulation_flag} => No poll/write for knauer_pump" } hsetprop ${scobj_hpath} klass ${device_class} hsetprop ${scobj_hpath} data true hsetprop ${scobj_hpath} debug_threshold 5 if {[string equal -nocase "${simulation_flag}" "false"]} { ansto_makesctdrive ${name}_pump_volume_setp ${scobj_hpath}/pump/volume/setp ${scobj_hpath}/pump/volume/pval ${sct_controller} } # mkDriver hook code starts #hset ${scobj_hpath}/pump/remote 1 # mkDriver hook code ends } catch_message ] handle_exception ${catch_status} ${catch_message} } proc ::scobj::knauer_pump::add_driver {name device_class simulation_flag ip_address tcp_port} { set catch_status [ catch { ::scobj::knauer_pump::sics_log 9 "::scobj::knauer_pump::add_driver ${name} ${device_class} ${simulation_flag} ${ip_address} ${tcp_port}" if {[string equal -nocase "${simulation_flag}" "false"]} { if {[string equal -nocase "aqadapter" "${ip_address}"]} { ::scobj::knauer_pump::sics_log 9 "makesctcontroller sct_${name} aqadapter ${tcp_port}" makesctcontroller sct_${name} aqadapter ${tcp_port} } else { ::scobj::knauer_pump::sics_log 9 "makesctcontroller sct_${name} knauer_ap ${ip_address}:${tcp_port}" makesctcontroller sct_${name} knauer_ap ${ip_address}:${tcp_port} } } else { ::scobj::knauer_pump::sics_log 9 "simulation_flag={simulation_flag} => No sctcontroller for knauer_pump" } ::scobj::knauer_pump::sics_log 1 "::scobj::knauer_pump::mkDriver sct_${name} ${name} ${device_class} ${simulation_flag} ${ip_address} ${tcp_port}" ::scobj::knauer_pump::mkDriver sct_${name} ${name} ${device_class} ${simulation_flag} ${ip_address} ${tcp_port} } catch_message ] handle_exception ${catch_status} ${catch_message} } namespace eval ::scobj::knauer_pump { namespace export debug_threshold namespace export debug_log namespace export sics_log namespace export mkDriver namespace export add_driver } proc add_knauer_pump {name ip_address tcp_port} { set simulation_flag "[string tolower [SplitReply [environment_simulation]]]" ::scobj::knauer_pump::add_driver ${name} "environment" "${simulation_flag}" ${ip_address} ${tcp_port} } clientput "file evaluation of sct_knauer_pump.tcl" ::scobj::knauer_pump::sics_log 9 "file evaluation of sct_knauer_pump.tcl" proc ::scobj::knauer_pump::read_config {} { set catch_status [ catch { set ns "::scobj::knauer_pump" dict for {k u} $::config_dict { if { [dict exists $u "implementation"] } { set simulation_flag "[string tolower [SplitReply [environment_simulation]]]" set device_class "environment" if { !([dict exists $u "name"] && [dict exists $u "enabled"]) } { continue } set enabled [string tolower [dict get $u "enabled"]] if { ! ([string equal -nocase $enabled "true" ] || [string equal -nocase $enabled "always"]) } { continue } if { [dict exists $u "simulation_group"] } { set simulation_flag [SplitReply [[string tolower [dict get $u "simulation_group"]]]] } if { [dict exists $u "device_class"] } { set device_class "[dict get $u "device_class"]" } set name [dict get $u name] set implementation [dict get $u "implementation"] if { !([dict exists $::config_dict $implementation]) } { continue } set v [dict get $::config_dict $implementation] if { !([dict exists $v "driver"]) } { continue } if { [string equal -nocase [dict get $v "driver"] "knauer_pump"] } { if { ![string equal -nocase "${simulation_flag}" "false"] } { set asyncqueue "null" ${ns}::sics_log 9 "simulation_flag=${simulation_flag} => using null asyncqueue" } elseif { [dict exists $v "asyncqueue"] } { set asyncqueue [dict get $v "asyncqueue"] if { [string equal -nocase ${asyncqueue} "sct"] } { set ip_address [dict get $v ip] set tcp_port [dict get $v port] } } else { if { [dict exists $v "asyncprotocol"] } { set asyncprotocol [dict get $v "asyncprotocol"] } else { set asyncprotocol ${name}_protocol MakeAsyncProtocol ${asyncprotocol} if { [dict exists $v "terminator"] } { ${asyncprotocol} sendterminator "[dict get $v "terminator"]" ${asyncprotocol} replyterminator "[dict get $v "terminator"]" } } set asyncqueue ${name}_queue set ip_address [dict get $v ip] set tcp_port [dict get $v port] MakeAsyncQueue ${asyncqueue} ${asyncprotocol} ${ip_address} ${tcp_port} if { [dict exists $v "timeout"] } { ${asyncqueue} timeout "[dict get $v "timeout"]" } } if { [string equal -nocase ${asyncqueue} "sct"] } { ${ns}::add_driver ${name} ${device_class} ${simulation_flag} ${ip_address} ${tcp_port} } else { ${ns}::add_driver ${name} ${device_class} ${simulation_flag} "aqadapter" ${asyncqueue} } } } } } catch_message ] handle_exception ${catch_status} ${catch_message} } if { [info exists ::config_dict] } { ::scobj::knauer_pump::read_config } else { ::scobj::knauer_pump::sics_log 5 "No config dict" }