The following is part of the python script I used to convert our old magnet control panels into CSS phoebus display. The implementation of save and recall can be found within BeamlineXML2bob.
from lxml import etree as ET
def GetMagnetInfo(control):
name=control.attrib["Name"]
dac=control.find("DAC")
dacid=int(dac.attrib["BoardID"])
dacchid=int(dac.attrib["chID"])-1
vmax=float(dac.attrib["VMax"])
smax=int(dac.attrib["SMax"])
smin=int(dac.attrib["SMin"])
vmin=vmax*(smax/smin)
if( smax== 0):
vmin=0.0
adc=control.find("ADC")
adcid=int(adc.attrib["BoardID"])
adcchid=int(adc.attrib["chID"])
eq=control.find("Eq")
eqc=float(eq.attrib["c"])
eqd=float(eq.attrib["d"])
newname=name.replace(".","_")
return [newname, dacid, dacchid,vmax, vmin,adcid,adcchid,eqc,eqd]
def MakeTitle(panelname,width):
w=ET.Element("widget",attrib={"type":"label","version":"2.0.0"})
# w.append(ET.Element("name","Label"))
name=ET.Element("name")
name.text="Title"
w.append(name)
Contents=ET.Element("text")
Contents.text=panelname;
w.append(Contents)
t=ET.Element("x")
t.text="0"
w.append(t)
t=(ET.Element("y"))
t.text="0"
w.append(t)
t=ET.Element("width")
t.text="{}".format(width)
w.append(t)
t=ET.Element("height")
t.text="31"
w.append(t)
f=ET.Element("font",attrib={"use_class":"true"})
f.append(ET.Element("font",attrib={"name":"Header 1","family":"Liberation Sans", "style":"BOLD", "size":"22.0"}))
w.append(f)
fgc=ET.Element("foreground_color",attrib={"use_class":"true"})
fgc.append(ET.Element("color",attrib={"name":"Text","red":"0", "green":"0", "blue":"0"}))
w.append(fgc)
t=ET.Element("transparent",attrib={"use_class":"true"})
t.text="true"
w.append(t)
t=ET.Element("horizontal_alignment")
t.text="1"
w.append(t)
return w
def MakeCtrlWidget(labelid,label,sliderid,textentryid,textupdateid,xref,yref,ctrlpv,rbpv):
w1=ET.Element("widget",attrib={"type":"label","version":"2.0.0"})
t=ET.Element("name")
t.text=labelid
t.tail="\n"
w1.append(t)
t=ET.Element("text")
t.text=label
t.tail="\n"
w1.append(t)
x=10+xref
y=yref+5
t=ET.Element("x")
t.text="{}".format(x)
t.tail="\n"
w1.append(t)
t=ET.Element("y")
t.text="{}".format(y)
t.tail="\n"
w1.append(t)
t=ET.Element("width")
t.text="75"
t.tail="\n"
w1.append(t)
t=ET.Element("height")
t.text="16"
t.tail="\n"
w1.append(t)
t=ET.Element("font")
f=ET.Element("font",attrib={"family":"Liberation Sans","style":"REGULAR","size":"12"})
t.tail="\n"
f.text=""
f.tail="\n"
t.append(f)
w1.append(t)
w1.tail="\n"
w2=ET.Element("widget",attrib={"type":"scaledslider","version":"2.0.0"})
t=ET.Element("name")
t.text=sliderid
t.tail="\n"
w2.append(t)
t=ET.Element("pv_name")
t.text=ctrlpv
t.tail="\n"
w2.append(t)
x=xref+20
y=yref+30
t=ET.Element("x")
t.text="{}".format(x)
t.tail="\n"
w2.append(t)
t=ET.Element("y")
t.text="{}".format(y)
t.tail="\n"
w2.append(t)
t=ET.Element("width")
t.text="30"
t.tail="\n"
w2.append(t)
t=ET.Element("height")
t.text="80"
t.tail="\n"
w2.append(t)
t=ET.Element("horizontal")
t.text="false"
t.tail="\n"
w2.append(t)
w2.tail="\n"
w3=ET.Element("widget",attrib={"type":"spinner","version":"2.0.0"})
t=ET.Element("name")
t.text=textentryid
t.tail="\n"
w3.append(t)
t=ET.Element("pv_name")
t.text=ctrlpv
t.tail="\n"
w3.append(t)
x=xref+10
y=yref+125
t=ET.Element("x")
t.text="{}".format(x)
t.tail="\n"
w3.append(t)
t=ET.Element("y")
t.text="{}".format(y)
t.tail="\n"
w3.append(t)
t=ET.Element("width")
t.text="75"
t.tail="\n"
w3.append(t)
t=ET.Element("precision")
t.text="3"
t.tail="\n"
w3.append(t)
t=ET.Element("increment")
t.text="0.01"
t.tail="\n"
w3.append(t)
w3.tail="\n"
w4=ET.Element("widget",attrib={"type":"textupdate","version":"2.0.0"})
t=ET.Element("name")
t.text=textupdateid
t.tail="\n"
w4.append(t)
t=ET.Element("pv_name")
t.text=rbpv
t.tail="\n"
w4.append(t)
x=xref+10
y=yref+155
t=ET.Element("x")
t.text="{}".format(x)
t.tail="\n"
w4.append(t)
t=ET.Element("y")
t.text="{}".format(y)
t.tail="\n"
w4.append(t)
t=ET.Element("width")
t.text="60"
t.tail="\n"
w4.append(t)
t=ET.Element("precision")
t.text="3"
t.tail="\n"
w4.append(t)
w4.tail="\n"
return [w1,w2,w3,w4]
def BeamlineXML2Bob(beamline,beamlinebob,Title,prefix,pname,width,height):
tree=ET.parse(beamline)
bml=tree.getroot()
bob=ET.ElementTree(ET.Element("display",attrib={'version':"2.0.0"}))
a=ET.Element("name")
a.text=pname
droot=bob.getroot()
droot.append(a)
a=ET.Element("width")
a.text="{}".format(width)
droot.append(a)
a=ET.Element("height")
a.text="{}".format(height)
droot.append(a)
title=MakeTitle(Title,width)
droot.append(title)
i=0
j=0
k=0
nitem=int(width/90)+1
biraps=["AWA:Bira2","AWA:Bira3","AWA:Bira4",""];
for a in bml:
if(a.tag=='control'):
b=GetMagnetInfo(a)
#b=[newname, dacid, dacchid,vmax, vmin,adcid,adcchid,eqc,eqd]:
i=k%nitem
j=int(k/nitem)
k=k+1
if(b[1]>-1):
# realname="AWA:DAC{dac:d}:Ch{ch:02d}".format(dac=b[1],ch=b[2])
ctrlpv="{}:{}:Ctrl".format(prefix,b[0])
else:
ctrlpv="{}Ctrl:Ch{ch:02d}".format(biraps[b[1]+4],ch=(b[2]+1))
if(b[5]>-1):
realname="AWA:ADC{bid:d}:Ch{cid:02d}".format(bid=b[5],cid=b[6])
rbpv="{}:{}:RB".format(prefix,b[0])
else:
rbpv="{}RB:Ch{ch:02d}".format(biraps[b[5]+4],ch=b[6])
lable="lable_{}".format(k)
slider="sl_{}".format(k)
edit="ed_{}".format(k)
txtupdate="txtupdate_{}".format(k)
w=MakeCtrlWidget(lable,b[0],slider,edit,txtupdate,10+i*80,30+j*190,ctrlpv,rbpv)
droot.append(w[0])
droot.append(w[1])
droot.append(w[2])
droot.append(w[3])
#Now make the save and recall button
savebutton=ET.Element("widget", attrib={"type":"action_button","version":"3.0.0"})
t=ET.Element("name")
t.text="savebutton"
savebutton.append(t)
action=ET.Element("actions")
action_type=ET.Element("action", attrib={"type":"execute"})
script=ET.Element("script",attrib={"file":"EmbeddedPy"})
txt=ET.Element("text")
cdata="from org.csstudio.display.builder.runtime.script import ScriptUtil, PVUtil\n"
cdata = cdata + "name=\"filename\"\n"
cdata = cdata + "name = ScriptUtil.showSaveAsDialog(widget, name)\n"
cdata = cdata + "file=open(name,\"wt\")\n"
cdata = cdata + "file.write(\"NItem: {}\\n\")\n".format(k)
cdata = cdata + "for i in range(1,{}):\n".format(k+1)
cdata = cdata + "\tctrl=ScriptUtil.findWidgetByName(widget, \"ed_{}\".format(i))\n"
cdata = cdata + "\tctrlpv=ScriptUtil.getPrimaryPV(ctrl)\n"
cdata = cdata + "\tctrlval=PVUtil.getDouble(ctrlpv)\n"
cdata = cdata + "\tfile.write(\"{}\\n\".format(ctrlval))\n"
cdata = cdata + "file.close()\n"
txt.text=ET.CDATA(cdata)
txt.tail="\n"
script.append(txt)
script.tail="\n"
action_type.append(script)
action_type.tail="\n"
action.append(action_type)
savebutton.append(action)
lable=ET.Element("text")
lable.text="Save"
savebutton.append(lable)
xpos=ET.Element("x")
xpos.text="{}".format(10+80)
ypos=ET.Element("y")
ypos.text="{}".format(30+(j+1)*190)
savebutton.append(xpos)
savebutton.append(ypos)
droot.append(savebutton)
recall=ET.Element("widget",attrib={"type":"fileselector","version":"2.0.0"})
recall.tail="\n"
t=ET.Element("name")
t.text="recall"
t.tail="\n"
recall.append(t)
t=ET.Element("pv_name")
t.text="loc://{}MagnetRecal<VString>(\"\")".format(pname)
t.tail="\n"
recall.append(t)
xpos=ET.Element("x")
xpos.text="{}".format(10+240+100)
ypos=ET.Element("y")
ypos.text="{}".format(30+(j+1)*190)
xpos.tail="\n"
recall.append(xpos)
ypos.tail="\n"
recall.append(ypos)
t=ET.Element("width")
t.text="140"
t.tail="\n"
recall.append(t)
t=ET.Element("height")
t.text="30"
t.tail="\n"
recall.append(t)
t=ET.Element("actions")
t.text=""
t.tail="\n"
recall.append(t)
t=ET.Element("scripts")
t.tail="\n"
script=ET.Element("script",attrib={"file":"EmbeddedPy"})
txt=ET.Element("text")
cdata="from org.csstudio.display.builder.runtime.script import ScriptUtil, PVUtil\n"
cdata = cdata + "v0 = PVUtil.getString(pvs[0])\n"
cdata = cdata + "if( v0 != \"\"):\n"
cdata = cdata + "\tname = v0\n"
cdata = cdata + "\tfile=open(name,\"wt\")\n"
cdata = cdata + "\ta=file.readline()\n"
cdata = cdata + "\tb=a.split(' ')\n"
cdata = cdata + "\tNItem=int(b[1])\n"
cdata = cdata + "\tfor i in range(NItem):\n"
cdata = cdata + "\t\tctrl=ScriptUtil.findWidgetByName(widget, \"ed_{}\".format(i+1))\n"
cdata = cdata + "\t\tctrlpv=ScriptUtil.getPrimaryPV(ctrl)\n"
cdata = cdata + "\t\ta=file.readline()\n"
cdata = cdata + "\t\tctrlval=float(a)\n"
cdata = cdata + "\t\tif (ctrlval == ctrlval):\n"
cdata = cdata + "\t\t\tctrlpv.write(ctrlval)\n"
cdata = cdata + "\tfile.close()\n"
cdata = cdata + "\tpvs[0].write(\"\")\n"
txt.text=ET.CDATA(cdata)
txt.tail="\n"
script.append(txt)
pv=ET.Element("pv_name")
pv.text="$(pv_name)"
pv.tail="\n"
script.append(pv)
t.append(script)
recall.append(t)
droot.append(recall)
rect=ET.Element("widget",attrib={"type":"rectangle","version":"2.0.0"})
t=ET.Element("name")
t.text="rectangle"
rect.append(t)
t=ET.Element("width")
t.text="{}".format(width)
rect.append(t)
t=ET.Element("height")
t.text="{}".format(height)
rect.append(t)
t=ET.Element("transparent")
t.text="true"
rect.append(t)
droot.append(rect)
bob.write(beamlinebob)
Wanming Liu
L112, Bldg 360
HEP,ANL
-----Original Message-----
From: Tech-talk <tech-talk-bounces at aps.anl.gov> On Behalf Of ?? via Tech-talk
Sent: Wednesday, November 16, 2022 1:00 AM
To: Jemian, Pete R. <jemian at anl.gov>
Cc: tech-talk at aps.anl.gov
Subject: Re: Re: [EXTERNAL] Phoebus: Find/Replace and Write XML file
I need to implement a save and restore funciton. When click an action button, then execute the script: find the widget by it's name, get the pv name and then get the pv value, finally write the value into a xml file. I've implement this using java script in CSS 3.2.16. Recently, We try to migrate the project from CSS to Phoebus. There is example about reading xml file but there is not examle about create and write xml file in display builder examples. The java script code as below:
#######################################################
importPackage(Packages.org.csstudio.opibuilder.scriptUtil);
importPackage(Packages.org.csstudio.opibuilder.util);
importPackage(Packages.java.io);
importPackage(Packages.org.jdom);
importPackage(Packages.org.jdom.output);
importPackage(Packages.java.lang);
var i;
var geo;
var temp="";
var macro;
var ISptPV;
var ISpt;
geo = widget.getMacroValue("GEO");
//get the PS name
var configFileName = "./configure/" + geo + "_Main_Config.xml"; var root1 = FileUtil.loadXMLFile(configFileName, widget); var children1 = root1.getChildren(); var mainPSName = children1.get(0).getChildren(); var sizeName = mainPSName.size();
// create root element
var root = new Element(geo);
// add the root node to the doc
var doc = new Document(root);
// create an element
var element1 = new Element("Main");
for(i=0; i<mainPSName.size(); i++)
{
//get macros
macro = mainPSName.get(i);
temp = geo + "_" + macro.getValue();
ISptPV = display.getWidget("Std_Setpoint_"+temp).getPV();
ISpt = PVUtil.getDouble(ISptPV);
// add sub node to the element
element1.addContent(new Element(macro.getValue()).setText(ISpt));
}
// add the element to the root node
root.addContent(element1);
// create XMLOutputter object
var format = Format.getPrettyFormat(); format.setEncoding("UTF-8");
format.setIndent(" ");
var xmlOut = new XMLOutputter(format);
// create file name append current time
var date = new Date();
var time = date.getFullYear() + "." + (date.getMonth() + 1) + "." + date.getDate() + "." +
date.getHours() + "." + date.getMinutes() + "." + date.getSeconds(); var opiFolderPath = ResourceUtil.buildAbsolutePath(display.getModel(), ResourceUtil.getPathFromString("./")).toString()
var fileName = FileUtil.workspacePathToSysPath(opiFolderPath) +"/data/" + geo + "_Main_" + time + ".xml";
//var fileName = FileUtil.workspacePathToSysPath("test/") +"/" + geo + "_" + time;
// output target.xml
xmlOut.output(doc, new FileOutputStream(fileName));
#######################################################
The configuration file is like this:
<LRBT_PS>
<Main>
<PS>LRSWBPS01</PS>
<PS>LDSWBPS01</PS>
<PS>LRBPS01</PS>
<PS>LRQPS01</PS>
<PS>LRQPS02</PS>
<PS>LRQPS03</PS>
</Main>
</LRBT_PS>
#######################################################
And the generated data file is like this:
<?xml version="1.0" encoding="UTF-8"?>
<ACC_LRBT_PS>
<Main>
<LRSWBPS01>150</LRSWBPS01>
<LDSWBPS01>-150</LDSWBPS01>
<LRBPS01>160</LRBPS01>
<LRQPS01>15</LRQPS01>
<LRQPS02>30</LRQPS02>
<LRQPS03>9</LRQPS03>
</Main>
</ACC_LRBT_PS>
I hope I've made it clear. BTW, I know that there is a save and restore service in phoebus, however I haven't test it.
Thanks,
Xuan
> -----原始邮件-----
> 发件人: "Pete Jemian via Tech-talk" <tech-talk at aps.anl.gov>
> 发送时间: 2022-11-16 11:58:30 (星期三)
> 收件人: tech-talk at aps.anl.gov
> 抄送:
> 主题: Re: [EXTERNAL] Phoebus: Find/Replace and Write XML file
>
> Your challenge when writing or replacing a PV value into an xml file is locating _which_ PV value to be replaced, finding the correct the xml node to be edited. Assuming the XML file uses more than a single PV, you'd need a way of finding the correct one.
>
> That complicates the simple example you request. For example, one of the widgets in the synApps/std timer screen has this xml:
>
> <widget type="choice" version="2.0.0">
> <name>choice button #23</name>
> <pv_name>$(P)timer$(N):Go</pv_name>
> <x>5</x>
> <y>34</y>
> <width>70</width>
> <height>35</height>
> <background_color>
> <color red="115" green="223" blue="255">
> </color>
> </background_color>
> <horizontal>false</horizontal>
> <border_alarm_sensitive>false</border_alarm_sensitive>
> <items>
> <item>Item 1</item>
> <item>Item 2</item>
> </items>
> </widget>
>
> The .bob file has these PVs:
>
> (base) ~$ grep pv_name /usr/local/epics/synApps6.1/support/std-R3-6-2/stdApp/op/bob/autoconvert/timer.bob
> <pv_name>$(P)timer$(N):elapsedSecs</pv_name>
> <pv_name>$(P)timer$(N):Go</pv_name>
>
> You could use the findall() (https://lxml.de/tutorial.html#elementpath) method to locate the `pv_name` nodes but you must still decide which to edit. The macros (with definitions unique to this file) are defined elsewhere in the file.
>
> Describe for us what you plan to do (create a new .bob file from an empty file or edit an existing file that you provide us) and it will be simpler to provide you with an example using lxml.
>
> Regards,
> Pete
>
>
> On 11/15/2022 8:48 PM, 吴煊 via Tech-talk wrote:
> > Many thanks for all your tips. It seems that phoebusgen is used to generate widgets.I need to write pv value into a xml file, so using etree maybe better. That would be great if there was an example.
> >
> > Xuan
> >
> > -----原始邮件-----
> > *发件人:*"Tynan Ford" <TFord at lbl.gov>
> > *发送时间:*2022-11-16 00:56:24 (星期三)
> > *收件人:* "Liu, Wanming" <wmliu at anl.gov>
> > *抄送:* "吴煊" <wux at ihep.ac.cn>, "kasemir, kay" <kasemirk at ornl.gov>, tech-talk <tech-talk at aps.anl.gov>
> > *主题:* Re: Re: [EXTERNAL] Phoebus: Find/Replace and Write XML
> > file
> >
> > I would not necessarily recommend doing this but you can see an
> > example (exampleInPhoebus files) of creating XML file in jython
> > here: https://github.com/als-epics/phoebusgen/tree/master/examples
> > <https://github.com/als-epics/phoebusgen/tree/master/examples>
> >
> > On Tue, Nov 15, 2022 at 8:36 AM Liu, Wanming via Tech-talk <tech-talk at aps.anl.gov <mailto:tech-talk at aps.anl.gov>> wrote:
> >
> > The bob file is a xml file. So you can use etree from lxml
> > package to manipulate the file with python. ____
> >
> > __ __
> >
> > *From:* Tech-talk <tech-talk-bounces at aps.anl.gov <mailto:tech-talk-bounces at aps.anl.gov>> *On Behalf Of *?? via Tech-talk
> > *Sent:* Monday, November 14, 2022 7:58 PM
> > *To:* kasemir, kay <kasemirk at ornl.gov <mailto:kasemirk at ornl.gov>>
> > *Cc:* tech-talk <tech-talk at aps.anl.gov <mailto:tech-talk at aps.anl.gov>>
> > *Subject:* Re: Re: [EXTERNAL] Phoebus: Find/Replace and
> > Write XML file____
> >
> > __ __
> >
> > I'm sorry I didn't make myself clear. I wish to know how to
> > create and write XML file using jython/python script in phoebus? Is
> > there a way to find and replace charactors especially pv_names in
> > xxx.bob file? ____
> >
> > Xuan ____
> >
> > -----原始邮件-----
> > *发件人:*"Kasemir, Kay" <kasemirk at ornl.gov <mailto:kasemirk at ornl.gov>>
> > *发送时间:*2022-11-14 22:27:56 (星期一)
> > *收件人:* tech-talk <tech-talk at aps.anl.gov <mailto:tech-talk at aps.anl.gov>>, "吴煊" <wux at ihep.ac.cn <mailto:wux at ihep.ac.cn>>
> > *抄送:*
> > *主**题:* Re: [EXTERNAL] Phoebus: Find/Replace and Write
> > XML file____
> >
> > > Is there "Find/Replace" function still in phoebus?
> > It's very useful for replacing pv names or other things in CSS.
> > Another question I'd like to ask:how to create and write XML file in
> > phoebus? I haven't see it in display builder examples. Any advice or
> > suggestions will be grately appretiated ____
> >
> > __ __
> >
> > __ __
> >
> > Yes, one advantage of the XML file format is that it
> > allows creating or modifying theses files outside of the graphical
> > editor. ____
> >
> > We don't try to include a complete XML editor in
> > phoebus, but you can easily add an OS-specific editor to the context
> > menu so that you can then open a display file from the phoebus file
> > browser via the context menu. ____
> >
> > __ __
> >
> > For example, on Linux you can add a reference to the
> > plain "gedit" text editor like this, so it can then be used to open
> > *.bob or *.opi files and for example perform PV name
> > replacements:____
> >
> > __ __
> >
> > org.phoebus.framework.workbench/external_app_text=Text
> > Editor,txt|dat|tab|py|ini|def|db|xml|xsl|css|cmd|sh|st|log|out|md|te
> > x|shp|bob|opi|pvs|edl,gedit____
> >
> > __ __
> >
> > You could also register VS code or another more
> > XML-aware editor just for *.bob like that. ____
> >
> > __ __
> >
> > __ __
> >
> > For a general python package that generates display
> > files outside of phoebus, see
> > https://github.com/als-epics/phoebusgen
> > <https://github.com/als-epics/phoebusgen>____
> >
> > __ __
> >
> > __ __
> >
> > -Kay ____
> >
> > __ __
> >
>
> --
> ----------------------------------------------------------
> Pete R. Jemian, Ph.D. <jemian at anl.gov>
> Beam line Controls and Data Acquisition (BC, aka BCDA)
> Advanced Photon Source, Argonne National Laboratory
> Argonne, IL 60439 630 - 252 - 3189
> -----------------------------------------------------------
> Education is the one thing for which people
> are willing to pay yet not receive.
> -----------------------------------------------------------
>
- Replies:
- Re: RE: Re: [EXTERNAL] Phoebus: Find/Replace and Write XML file 吴煊 via Tech-talk
- References:
- Phoebus: Find/Replace and Write XML file 吴煊 via Tech-talk
- Re: [EXTERNAL] Phoebus: Find/Replace and Write XML file Kasemir, Kay via Tech-talk
- Re: Re: [EXTERNAL] Phoebus: Find/Replace and Write XML file 吴煊 via Tech-talk
- RE: Re: [EXTERNAL] Phoebus: Find/Replace and Write XML file Liu, Wanming via Tech-talk
- Re: Re: [EXTERNAL] Phoebus: Find/Replace and Write XML file Tynan Ford via Tech-talk
- Re: Re: Re: [EXTERNAL] Phoebus: Find/Replace and Write XML file 吴煊 via Tech-talk
- Re: [EXTERNAL] Phoebus: Find/Replace and Write XML file Pete Jemian via Tech-talk
- Re: Re: [EXTERNAL] Phoebus: Find/Replace and Write XML file 吴煊 via Tech-talk
- Navigate by Date:
- Prev:
Re: Re: [EXTERNAL] Phoebus: Find/Replace and Write XML file 吴煊 via Tech-talk
- Next:
Re: Epics Archiver Appliance requests and DST/Timezones Michael Davidsaver via Tech-talk
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
<2022>
2023
2024
- Navigate by Thread:
- Prev:
Re: Re: [EXTERNAL] Phoebus: Find/Replace and Write XML file 吴煊 via Tech-talk
- Next:
Re: RE: Re: [EXTERNAL] Phoebus: Find/Replace and Write XML file 吴煊 via Tech-talk
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
<2022>
2023
2024
|