## # @file Goniometer controller # # Author: Jing Chen (jgn@ansto.gov.au) June 2010 # # The Goniometer controller can be installed with the following command, # ::scobj::goniometer::mkGoniometer { # name "goniometer" # IP localhost # PORT 62944 # tuning 1 # interval 1 # } # # NOTE: # If tuning=1 this will generate gom/set_gom, gchi/set_gchi and gphi/set_gphi # nodes for the instrument scientists. # The tuning parameter should be set to 0 for the users. # namespace eval ::scobj::goniometer { } proc ::scobj::goniometer::set_gom {basePath} { set newGOM [sct target] hsetprop $basePath targetGom $newGOM return idle } proc ::scobj::goniometer::set_gchi {basePath} { set newGCHI [sct target] hsetprop $basePath targetGchi $newGCHI return idle } proc ::scobj::goniometer::set_gphi {basePath} { set newGPHI [sct target] hsetprop $basePath targetGphi $newGPHI return idle } ## # @brief Request a state report from the PLC controller by sending a get_prop command proc ::scobj::goniometer::rqStatFunc {} { set comm "gom,gchi,gphi\n" sct send $comm return rdState } ## # @brief Read and record the state report from the PLC server proc ::scobj::goniometer::rdStatFunc {basePath} { set replyStr [sct result] #broadcast $replyStr if {[string first "err" $replyStr] != -1} { broadcast "ERROR: cannot get the value to the PLC server, check again!" } else { set s1 [string map { | gom: | gchi: | gphi: | |} $replyStr] set s2 [string trim $s1 "|\n"] set s3 [split $s2 "|:"] array set stateArr $s3 hset $basePath/gom $stateArr(gom) hset $basePath/gchi $stateArr(gchi) hset $basePath/gphi $stateArr(gphi) hsetprop $basePath currGom $stateArr(gom) hsetprop $basePath currGchi $stateArr(gchi) hsetprop $basePath currGphi $stateArr(gphi) #sct update $s3 sct utime readtime } return idle } ## # @Check if any of gom/gchi/gphi has been changed by client proc ::scobj::goniometer::checkStatusFunc {basePath} { set targetGom [hgetpropval $basePath targetGom] set targetGchi [hgetpropval $basePath targetGchi] set targetGphi [hgetpropval $basePath targetGphi] set currGom [hgetpropval $basePath currGom] set currGchi [hgetpropval $basePath currGchi] set currGphi [hgetpropval $basePath currGphi] if {$targetGom != $currGom} { set comm "gom$targetGom\n" } elseif {$targetGchi != $currGchi} { set comm "gchi$targetGchi\n" } elseif {$targetGphi != $currGphi} { set comm "gphi$targetGphi\n" } else { return idle } sct send $comm return CheckReply } proc ::scobj::goniometer::checkReplyFunc {} { set replyStr [sct result] broadcast $replyStr if {[string first "var" $replyStr] != -1} { broadcast "ERROR: the varaible does not exist!" } elseif {[string first "set" $replyStr] != -1} { broadcast "ERROR: PLC cannot write new values for variable due to internal reason!" } else { sct utime readtime } return idle } ## # @brief Make a Goniometer controller # # @param argList, {name "goniometer" IP localhost PORT 62944 tuning 1 interval 1} # # name: name of goniometer controller object # IP: IP address of RF generator moxa box # PORT: Port number assigned to the generator on the moxa-box # tuning: boolean, set tuning=1 to allow instrument scientists to set the axe positions # interval: polling and ramping interval in seconds. proc ::scobj::goniometer::mkGoniometer {argList} { # Generate parameter array from the argument list foreach {k v} $argList { set KEY [string toupper $k] set pa($KEY) $v } MakeSICSObj $pa(NAME) SCT_OBJECT sicslist setatt $pa(NAME) klass instrument sicslist setatt $pa(NAME) long_name $pa(NAME) hfactory /sics/$pa(NAME)/gom plain internal int hfactory /sics/$pa(NAME)/gchi plain internal int hfactory /sics/$pa(NAME)/gphi plain internal int hfactory /sics/$pa(NAME)/set_gom plain user int hfactory /sics/$pa(NAME)/set_gchi plain user int hfactory /sics/$pa(NAME)/set_gphi plain user int makesctcontroller sct_goniometer std $pa(IP):$pa(PORT) hset /sics/$pa(NAME)/gom 0 hset /sics/$pa(NAME)/gchi 0 hset /sics/$pa(NAME)/gphi 0 hsetprop /sics/$pa(NAME) currGom 0 hsetprop /sics/$pa(NAME) currGchi 0 hsetprop /sics/$pa(NAME) currGphi 0 hsetprop /sics/$pa(NAME) targetGom 10 hsetprop /sics/$pa(NAME) targetGchi 15 hsetprop /sics/$pa(NAME) targetGphi 20 hsetprop /sics/$pa(NAME)/gom read ::scobj::goniometer::rqStatFunc hsetprop /sics/$pa(NAME)/gom rdState ::scobj::goniometer::rdStatFunc /sics/$pa(NAME) hsetprop /sics/$pa(NAME)/gchi read ::scobj::goniometer::checkStatusFunc /sics/$pa(NAME) hsetprop /sics/$pa(NAME)/gchi CheckReply ::scobj::goniometer::checkReplyFunc # Initialise properties required for generating the API for GumTree and to save data ::scobj::hinitprops $pa(NAME) gom gchi gphi sct_goniometer poll /sics/$pa(NAME)/gom $pa(INTERVAL) sct_goniometer poll /sics/$pa(NAME)/gchi $pa(INTERVAL) if {$pa(TUNING)} { hsetprop /sics/$pa(NAME)/set_gom write ::scobj::goniometer::set_gom /sics/$pa(NAME) hsetprop /sics/$pa(NAME)/set_gchi write ::scobj::goniometer::set_gchi /sics/$pa(NAME) hsetprop /sics/$pa(NAME)/set_gphi write ::scobj::goniometer::set_gphi /sics/$pa(NAME) sct_goniometer write /sics/$pa(NAME)/set_gom sct_goniometer write /sics/$pa(NAME)/set_gchi sct_goniometer write /sics/$pa(NAME)/set_gphi } }