esrf

Beamline Instrument Software Support
SPEC Macro documentation: [ Macro Index | BCU Home ]

#%TITLE% XML_utils.mac
#%NAME%
#   Some macros to handle XML  manipulations
#%DESCRIPTION%
#   To do
#

global XML_tmp[]
global  _XML_lp


#%UU% [host hwr]
#%MDESC% defines the host (host) and hardware repository server name (hwr)
#managing the hardware repository xml files
def setHwrHost'{

   global XML_debug
   global HWR_host HWR_server HWR_dev
   global XML_tmp[]
   global  _XML_lp
   
   if($# == 2) {
      HWR_host = "$1"
      HWR_server = "$2"
   }
   else {
      HWR_host = getval("Hardware Repository host ?",HWR_host)
      HWR_server = getval("Hardware Repository server ?",HWR_server)
   }
   HWR_dev = sprintf("%s:%s",HWR_host,HWR_server)
   
#  relative path from HWR location to find the files
# _XML_lp = ""
  _XML_lp = sprintf("/%s",SPEC)
}'


#%UU% (hw_obj)
#%MDESC% dumps an XML object situated from the Hardware Repository Location
#%BR% xml object can be on the form: xxx xxx/xx ...
#with possibly the path from the Hardware Repository Location
#%BR%ex: xml_view("pslit")
#%BR%ACCESS TO XML file
def xml_view(hw_obj)' {

   local mystring 
   
   mystring = sprintf("xml_view(\"%s/%s\")",_XML_lp,hw_obj)
   xml_debug "xml_view: doing: " \'"mystring"\'
   p remote_eval(HWR_dev,mystring)
}'



#%UU%(hw_obj,level,[key])
#%MDESC% reading a hardware object, with a level access,(and possibly
#a key), sets the global associative array XML_tmp.
#%BR% If no key is provided: reurns a 2 dim assocoative array
#%BR%ex: xml_read("pslit","/*/*/blades/device")
#%BR%XML_tmp["0"]["role"] = "vo"
#%BR%XML_tmp["1"]["role"] = "vg"
#%BR%XML_tmp["2"]["role"] = "ho"
#%BR%XML_tmp["3"]["role"] = "hg"
#%BR%XML_tmp["0"]["hwrid"] = "/motors/psvo"
#%BR%XML_tmp["1"]["hwrid"] = "/motors/psvg"
#%BR%XML_tmp["2"]["hwrid"] = "/motors/psho"
#%BR%XML_tmp["3"]["hwrid"] = "/motors/pshg"
#%BR%XML_tmp["0"]["__path__"] = "/equipment[1]/motors[1]/blades[1]/device[1]"
#%BR%XML_tmp["1"]["__path__"] = "/equipment[1]/motors[1]/blades[1]/device[2]"
#%BR%XML_tmp["2"]["__path__"] = "/equipment[1]/motors[1]/blades[1]/device[3]"
#%BR%XML_tmp["3"]["__path__"] = "/equipment[1]/motors[1]/blades[1]/device[4]"
#%BR%XML_tmp["0"]["__value__"] = ""
#%BR%XML_tmp["1"]["__value__"] = ""
#%BR%XML_tmp["2"]["__value__"] = ""
#%BR%XML_tmp["3"]["__value__"] = ""
#%BR%XML_tmp["0"]["__children__"] = ""
#%BR%XML_tmp["1"]["__children__"] = ""
#%BR%XML_tmp["2"]["__children__"] = ""
#%BR%XML_tmp["3"]["__children__"] = ""
#%BR% if a key is provided: provides  a one key associative array
#%BR%ex: xml_read("pslit","/*/*/blades/device","role")
#%BR%XML_tmp["0"] = "vo"
#%BR%XML_tmp["1"] = "vg"
#%BR%XML_tmp["2"] = "ho"
#%BR%XML_tmp["3"] = "hg"
#%BR%....
#%BR%returns 0 if OK
#%BR%returns -1 if NOT OK, in that case XML_tmp["__error__"] contains error message.
#%BR%ACCESS TO XML file
def xml_read(hw_obj,tree,key)'{

   local ii mystring tmp mydim myout mytmp tmperr
   
   unglobal XML_tmp
   global XML_tmp
    
   mystring = sprintf("xml_read(\"%s/%s\",\"%s\")",_XML_lp,hw_obj,tree)
   xml_debug "xml_read: doing: " \'"mystring"\'

   mytmp =  remote_eval(HWR_dev,mystring)
   tmperr = mytmp["__error__"]
   if ( "__error__" in mytmp) {
      xml_debug "xml_read: error: " \'"tmperr"\'
      XML_tmp["__error__"] = mytmp["__error__"]
      return(-1)
   }
   else {
      if (key == "") {
	  for (ii in mytmp) {
	      XML_tmp[ii] = mytmp[ii]
	  }
      }
      else {
          mydim = asso_len(mytmp)

          for (ii=0; ii<mydim; ii++) {
             XML_tmp[ii]= mytmp[ii][key]
          }	
      }
      return(0)
   }
}'


#%UU% (hw_obj)
#%MDESC% From an hardware object, set the global XML_tmp associative
#array, first indexed by the roles
#This is a quick way to get an information without giving the path to it.
#%BR%ex: xml_readroles("pslit")
#%BR%returns 0 if OK, and:
#%BR%XML_tmp will have:
#%BR%XML_tmp["down"]["__children__"] = ""
#%BR%XML_tmp["down"]["__path__"] = "/equipment[1]/motors[1]/slits[1]/device[2]"
#%BR%XML_tmp["down"]["__value__"] = ""
#%BR%XML_tmp["down"]["hwrid"] = "/demo/psd"
#%BR%XML_tmp["down"]["role"] = "down"
#%BR%XML_tmp["hg"]["__children__"] = ""
#%BR%XML_tmp["hg"]["__path__"] = "/equipment[1]/motors[1]/blades[1]/device[4]"
#%BR%XML_tmp["hg"]["__value__"] = ""
#%BR%XML_tmp["hg"]["hwrid"] = "/demo/pshg"
#%BR%XML_tmp["hg"]["role"] = "hg"
#%BR%....
#%BR%returns -1 if NOT OK and:
#%BR%XML_tmp["__error__"] = "an error string"
#%BR%ACCESS TO XML file
def xml_readRoles(hw_obj)'{

   local mystring tmperr

   mystring = sprintf("xml_readNodesWithRoles(\"%s/%s\")",_XML_lp,hw_obj)
   xml_debug "xml_readRoles: doing " \'"mystring"\'
   
   XML_tmp =  remote_eval(HWR_dev,mystring)

  if ("__error__" in XML_tmp) {
     tmperr = XML_tmp["__error__"]
     xml_debug "xml_readRoles : error: " \'"tmperr"\'
     return(-1)
  }
  else {   
     return(0)
   }
}'


def xml_readMotorsByRoles(ho) '{
  local xmlres[] tmp[] tmp2 motor_ho mot_mne

  if (xml_readRoles(ho) > -1) {
    ass_copy(XML_tmp, tmp)
    tmp2 = asso_keys(XML_tmp)

    for (role in tmp2) {
      motor_ho = tmp[role]["hwrid"]

      if (xml_read(motor_ho, "/device/specname") > -1) {
        mot_mne = XML_tmp[0]["__value__"]

        if (motor_num(mot_mne) > -1) {
          xmlres[role] = mot_mne
        }
      }
    }
  }

  return xmlres
}'


#%UU% (hw_obj)
#%MDESC% From an hardware object, set the global XML_tmp associative
#array, first indexed by the properties
#This is a quick way to get an information without giving the path to it.
#%BR%ex: xml_readProperties("motors/mydac0")
#%BR%returns 0 if OK, and:
#%BR%XML_tmp["dev"]["__path__"] = "/device[1]/dev[1]"
#%BR%XML_tmp["dev"]["__value__"] = "id/icvdac/0"
#%BR%XML_tmp["maxstep"]["__path__"] = "/device[1]/maxstep[1]"
#%BR%XML_tmp["maxstep"]["__value__"] = 3
#%BR%XML_tmp["reading"]["__path__"] = "/device[1]/reading[1]"
#%BR%XML_tmp["reading"]["__value__"] = 1
#%BR%XML_tmp["stepsize"]["__path__"] = "/device[1]/stepsize[1]"
#%BR%XML_tmp["stepsize"]["__value__"] = 0.2
#%BR%....
#%BR%returns -1 if NOT OK, and:
#%BR%XML_tmp["__error__"] = "an error string"
#%BR%ACCESS TO XML file
def xml_readProperties(hw_obj, path)'{
   local mystring tmperr

   if (path == 0) {
	   mystring = sprintf("xml_readProperties(\"%s/%s\")",_XML_lp,hw_obj)
	 } else {
	   mystring = sprintf("xml_readProperties(\"%s/%s\",\"%s\")",_XML_lp,hw_obj,path)
	 }

   #mystring = sprintf("xml_readProperties(\"%s/%s\")",_XML_lp,hw_obj)
   xml_debug "xml_readProperties: doing " \'"mystring"\'
   
   XML_tmp =  remote_eval(HWR_dev,mystring)

   if ("__error__" in XML_tmp) {
     tmperr = XML_tmp["__error__"]
     xml_debug "xml_readProperties : error: " \'"tmperr"\'
     return(-1)
   }
   else {      
     return(0)
   }
}'


def xml_cache_write(hw_obj, path, value) '{
  global _XML_WRITE_CACHE[]
  local n

  n=asso_len(_XML_WRITE_CACHE)

  _XML_WRITE_CACHE[n+1]["ho"]=hw_obj
  _XML_WRITE_CACHE[n+1]["path"]=path
  _XML_WRITE_CACHE[n+1]=value
}'


def xml_do_write() '{
  local tmp[] ho path value update
  local UPDATES[] query res[] result

  result=0
  tmp = asso_keys(_XML_WRITE_CACHE)

  for (i in tmp) {
    ho = _XML_WRITE_CACHE[i]["ho"]
    path = _XML_WRITE_CACHE[i]["path"]
    value = _XML_WRITE_CACHE[i]

    update = sprintf("(\"%s\", \"%s\")", path, value)

    if (UPDATES[ho] == 0) {
      UPDATES[ho] = sprintf("(%s", update)
    } else {
      UPDATES[ho] = sprintf("%s,%s", UPDATES[ho], update)
    }
  }

  for (ho in UPDATES) {
    UPDATES[ho]=sprintf("%s,)", UPDATES[ho])

    query = sprintf("xml_multiwrite(\"%s\", \'%s\')", ho, UPDATES[ho])

    res = remote_eval(HWR_dev, query)

    if ("__error__" in res) {
      print res["__error__"]
      result = -1
    }
  }

  if (result == 0) {
    unglobal _XML_WRITE_CACHE
  }

  return result
}'


#%UU%(db)
#%MDESC% set debug on (0) or off (1)
def xml_setDebug(db)'{
   XML_debug = db
}'


#%IU% <list>
#%MDESC% if debug is set, writes <list>
def xml_debug'{
   if (XML_debug > 0) {
      print "$*"
   }
}'

#%IU% <arr>
#%MDESC% arr being a 2 dimension associative array with numerical first
#key, this function return its length. 
def asso_len(arr)'{
  local len keys_tmp k keys

  keys["__"] = ""
    
  for (ii in arr) {
     split(ii,mysp,"\034")
     if ((mysp[0] in keys) == 0) {
        keys[mysp[0]]=""
     }  
  }
        
  delete keys["__"]

  len = 0
  for (k in keys) {
     len += 1
  }
  
  return len
}'

#%IU% <arr>
#%MDESC% arr being a 2 dimension associative array.
def asso_keys(arr) '{ 
    local ii keys mysp nb
       
    keys["__"] = ""
    
    for (ii in arr) {
       nb = split(ii,mysp,"\034")
#      we want only 2 dimension keys
       if ( ((mysp[0] in keys) == 0) && (nb > 1) ) {
         keys[mysp[0]]=""
       }  
    }
        
    delete keys["__"]
    
    return(keys)
}'


#%UU% (aa,bb)
#%MDESC% makes a copy of array aa to bb
def ass_copy(aa,bb)'{
    local ii
    
    for (ii in aa) {
       bb[ii] = aa[ii]
    }
}'

#%MACROS%
#%IMACROS%
#%DEPENDENCIES%
#  
#%AUTHOR% 
#%TOC%