EPICS caputRecorder模块

内容表

一、概要

caputRecorder支持基类和回放caputs序列。它以一条python命令基类每次caput,以及一个在这里被称为宏的python函数基类一个caputs序列。caputReocder也可以用作一个用于发送打包的python函数到终端用户的简单用户接口。caputReocder通过一个EPICS数据库与用户进行通信,因此它允许任何EPICS记录或者通道访问客户端记录和运行python函数,并且等待它们结束。

caput是"通道访问写"的简称。当你按下一个按钮,或者在MEDM(或者其它显示管理器中)进行菜单选择时,你正在进行一次caput。写入EPICS PVs的任何程序通过进行caputs做这件事。

caputRecoder也支持用参数产生记录的宏。(这需要手动编辑python代码)。它提供了一个用户接口,通过它用默认值显示宏参数,这些默认参数可以通过通道访问被修改。

已知这个版本的caputRecoder与python 2.7一起运行。它可能不能与python 3一起使用。

caputRecorder是为了满足以下需求:

1)自动测量包含了用户知道的如何手动做的步骤序列,但还没有为此编写软件。在这个recorder开启时,如果用户能够手动地进行测量步骤,用户将实际上已经编写了自动化那步的软件,并且他们接着能够组合所需的若干这些步骤来执行一个此种测量类型的特定实例。

2)改善了用户和支持他们的软件开发者之间的联系。不是一般地描述所需的软件,或者按所需顺序费力的列出所需操作,用户可以用EPICS以外任何操作地注释简单地记录它们,并且发送给开发者这段python代码。

3)通过记录产生或没有产生问题的caputs的确切顺序,在故障排除中帮助。

4)通过你自己操作一个复杂设备同时记录,然后发邮件给它们这段python代码演示给其它人如何操作它。

5)记录一个用户做的每件事。(但caPutLog是一个用于此目的的更好工具)。

如何它工作?

EPICS访问安全能够在一个满足特定标准的caput被一个IOC接收到时调用一个用户函数。这个函数被称为访问安全捕捉监听程序,并且caputRecorder提供了在一个合格的caput被IOC接收时写一条格式"pvname, value, user@host"的caput通知消息字符串到一个EPICS PV的此类程序。

caputRecoder提供了一个包含了以上提到的EPICS PV和作为caputRecoder的用户接口的其它PVs的EPICS数据库。用户接口PVs被python程序caputRecorder.py监视,并且指挥它的运行。当caputRecorder.py被传一个宏名并且通知开始记录,它开始监视指定IOCs的caput-notification PVs,并且写对应每个通知的python命令到python程序文件macros.py。这是一条代表性命令看起来的样子:

epics.caput("xxx:scan1.P1PV","xxx:m2.VAL", wait=True, timeout=1000000.0)

这写字符串"xxx:m2.VAL"到"xxx:scan1.P1PV",并且大约永远等待由这条命令会导致任何的EPICS运行完成。

caputRecorder.py也检查文件macro.py并且把在此文件中的宏名写到一个EPICS菜单集合(即是:写入mbbo记录的菜单字符串字段)。用户可以从那些菜单选择一个宏名,并且告诉caputRecorder执行那个宏。

因而,每个IOC负责告诉caputRecorder其接收了一个caput,而一个IOC也托管这个数据库,用户通过此数据库告诉caputRecorder要做什么。

要求,配置

caputRecorder数据库使用来自synApps busy和calc模块的记录类型。caputRecorder.py所运行的工作站必须已经安装了pyepics。通过提交它们接收到的caputs,或者通过托管用作caputRecorder的用户接口的数据库加入caputRecorder的EPICS IOCs必须按以下准备。(这些是来自发行包R5-8的synApps xxx模块的摘要,它已经被配置为使用caputRecorder。)

1) 添加CAPUTRECORDER到这个IOC的RELEASE文件。

2) 在这个IOC的dbd文件中包含caputRecorder.dbd。

3) 这个IOC的代码链接caputRecorder库。

4) 装载数据库caputPoster.db

dbLoadRecords("$(CAPUTRECORDER)/caputRecorderApp/Db/caputPoster.db","P=xxx:,N=300")

此处N是这个注释,用户,主机以及前缀字符串的长度。如果你正在使用autosave,你将也可能想要在这个IOC的auto_settings.req文件中包含caputRecorder_settings.req:

file caputRecorder_settings.req P=xxx:,N=100

如果你做了这件事,你也必须添加以下行到save_restore.cmd:

set_requestfile_path("$(CAPUTRECORDER)", "caputRecorderApp/Db")

6) 注册caputRecorder的访问安全捕捉监听器。(注意:这个命令必须在iocInit后立即被执行。)

registerCaputRecorderTrapListener("xxx:caputRecorderCommand")

此处xxx:caputRecorderCommand是PV的名称,其是caput通知消息字符串将被写入的通道。

7)用一个为所需用户和主机指定TRAPWRITE的访问安全文件运行EPICS访问安全。

iocsh
asSetFilename("$(TOP)/iocBoot/accessSecurity.acf")
exit

此处文件accessSecurity.acf会有以下内容:

HAG(workstation) {mooneylinux.aps.anl.gov}
UAG(user) {mooney}
ASG(DEFAULT) {
	RULE(1,READ)
	RULE(1,WRITE,TRAPWRITE) {
		HAG(workstation)
		UAG(user)
	}
	RULE(1,WRITE)
}

这个文件授予写权限给在任何主机上的任何人,并且指定TRAPWRITE实际上只用于在工作站mooneylinux上的用户mooney。出于caputRecorder的目的,你可能实际上不是想要为caputs的TRAPWRITE来自一个IOC,而是想要用于caputs的TRAPWRITE来自通道访问客户端,诸如MEDM,那不在一个IOC中。

注意在文件中规则出现的顺序对TRAPWRITE重要。如果在RULE(1, WRITE, TRAPEWRITE)前遇到RULE(1, WRITE),TRAPWRITE将对任何人不起作用,因为所有人都被RULE(1, WRITE)涵盖。

如果你不能或者不想要使用访问安全规则选择用户和主机,你可以为所有人指定TRAPWRITE,并且用caputRecorder的用户接口选择用户和主机。加ing最caputRecorder有效的最简单可能的访问安全文件如下:

ASG(DEFAULT) {
	RULE(1,WRITE,TRAPWRITE)
}

8) 在运行MEDM(caQtDM等)前,必须设置以下环境变量:

  • STRAT_PUTRECORDER:指向一个启动caputRecorder.py的脚本的路径。这将被以下描述的"!(re)start recorder"使用。在这里这是为Linux做这件事的脚本的示例副本:
    caputRecorder/example_start_putrecorder
    一次只运行(用于指定用户接口的数据库)caputRecorder.py的一个副本是重要的。caputRecorder.py探测使用相同控制PVs的自身新副本,并且退出。
  • MACROS_PY:宏文件的路径,在其中将记录caputs。这里有一个这个文件的示例副本:
    caputRecorder/caputRecorderApp/op/python/example_macros.py
  • EDITOR:调用你首选编辑器的命令,它将被用于以下描述的"edit macros"按钮。

 

如何使用

参考以上从上到下的caputRecorder.adl窗口:

1) 标记着"!(re)start recorder"的按钮启动或重启python程序caputRecorder.py。

2)当caputRecorder.py正在运行并且响应它的控制PVs,"!(re)start recorder"按钮右边的心形符号闪烁。

输入

1) 标签为"caput:"的文本监视字段显示最近被写入到这个IOC的PV名称和值。通过访问安全捕捉监听器写入这个字段,并且根据一个python宏是否正在被记录,被更新。

2) 标记为"comment"的文本输入字段允许你添加注释到正在被记录的宏。只在一个宏正在被记录时,才监视这个字段。

3)标记为"delay"的文本输入字段用秒指定延时命令的延时时间,当你按下"Add"按钮时,它将被加入到正在被记录的宏。用于这条命令的实际python代码将是像time.sleep(1.200)这样的东西。在caputRecorder.py写完这条延时命令,它将按下"Done"按钮。

记录宏

1) 标记为"macro name"的文本输入框制定了你将记录的宏名(python函数)。

默认,不允许你使用一个在macros.py中已经存在的宏名。

也注意:宏名必须以一个字母开始,并且必须由字母数字和下划线组成。caputRecorder将通过在前面添加"a"和/或用下划线替换违反规则的字符。宏名称将被截短刀5个字符;通过一个mbboRecord的菜单字符串字段的长度设置这个限制。

2)标记为"record puts"的选项按钮是用于启动和停止录制。在录制时,你可以通过任何EPICS客户端写到EPICS PVs,并且你可以执行已经被录制的任何宏。

3) 如果你在录制宏B时,执行宏A,并且在宏A仍然执行时,停止录制,caputRecorder将在有允许你启动另一个宏的一个新录制前,使你等待宏A结束。

4) 当你在录制B时,执行宏A,caputRecorder将忽略对由于宏A执行产生的caputs的记录,并且将只录制一个对宏A的函数调用。

选择宏

1) 标签为“edit macros”的按钮调用在文件macros.py文件上环境变量EDITOR命名的命令。

2)灰色框是菜单,它将包含被录制宏的名称,并且它们是宏可以通过其被手动选做回放的方式。当前caputRecorder支持6个菜单,每个菜单可以支持16个宏名。

3)如果有,在"arguments for selected macro"标签下的文本监视和文本输入框是所选宏的参数的名称和默认值。当录制时,宏没有参数,但你可以编辑宏代码来最多添加20个参数。caputeRecorder.adl仅显示10个参数;caRecorderExecutee.adl(从"less"菜单被调用)显示所有20个。如果你添加参数,你必须使用"name=vaue"语法用于定义宏参数。例如,这是一个带有一个字符串参数,和三个数值参数的宏定义:

def motorscan(motor="m1", start=0, end=1, npts=11):

4)通常,你应该不是必须按下"Reload Macros"按钮,因为caputRecorder在一个新宏已经被录制后自动重新装载。但,如果你手动编辑macro.py,你必须按下"Reload Macos"告诉caputRecorder重读文件。(如果你从macros.py删除一个函数定义,重新装载是不够的;你必须使用"!(re)start recorder"按钮来重启caputRecorder。)

5)当菜单发生变化时,必须按下“Refresh Menus”按钮。当宏录制结束时,在你按下"!(re)start recorder"按钮后,在你按下"Reload Menus"按钮后,以及在这个进行控制的IOC重启后,这发生了。caputRecorder将通过显示闪烁的文本"PRESS REFRESH",告诉你菜单何时需要被刷新。当caputRecorder.adl或caputRecorder_small.adl的任何实例被刷新时,这种闪烁文本将消失。

回放宏

1) 文本监视字段包含所选宏的名称。要回放它(是的python执行它),按下"Do"按钮。当这个宏结束时,"Do"按钮将返回"Done"状态。如果你想要重复地执行这个宏,在标签为"times"地字段中输入次数。

2) “Abort”按钮是用于停止一个在执行的宏,并且也做在macros.py中在名为"_abort“的函数中指定的任何其它取消相关的工作。提供的example_macros.py定义了一个取消扫描,停止电机,以及停止名为"scaler1"的scaler的取消函数。

3) 任何EPICS客户端或记录可以通过写一个宏名到"$(P)caputRecorderMacro"并且接着写"Do"(或者数值1)到"$(P)caputRecorderExecuteMacro"能够触发宏执行。在两次写后,客户端应该等待结束,确保在执行前任何默认参数值准备好,并且等待宏执行结束。

选择要录制什么

你可能不想要录制你IOCs和客户端之间发生的所有caputs,但仅由用户做的那些caputs。一种过滤方式如以上所示,在"Requirements, configuration"。用户指定的过滤更简单,并且能够在运行时用caputRecorder的用户接口进行用户指定的过滤。

1) 你通过向caputRecorderUsers指定用户名能够选择哪些用户的caputs将被录制。(见以下图中"Record caputs from whom?")。要禁止对一个特定用户的录制,在一个用户名前加上一个减号。

2)你通过向caputRecorderHosts执行用户名能够选择哪些主机的caputs将被录制。(见以下图中"Record caputs from whom?")。只需要指定一个主机名的第一个元素。(例如:"mooneylinux.aps.anl.gov"被用成"mooneylinux"。)

3) 通过向caputRecordPrefixes指定前缀,你可以选择caputRecorder监视哪些IOCs。(见下图中"Record caputs to which IOCs?")。不同于用户和主机选项,当一个宏正在被录制时,这个选项不起作用。也不同于用户和主机选项,这个选项与一个caput的发送者没有关系,而是与这个接收者有关系。

启动时,caputRecorder监视其前缀在命令行上被指定的iocs。如果caputRecorderPrefixes不是空的,它将覆盖iocs的初始列表。

4)在一个IOC内部的caputs将不被录制,因为它们不经过访问安全。

录制选项

1) 时间:caputs的时间一般在回放时不同于录制时,但你能够告诉caputRecorder尝试重现时间。如果你为"record timing of caputs"选择了"Yes"(见以上图表),caputRecorder将在caput命令之间插入延时。你可以在录制时更改这种设置。注意:如果caputRecorder等待结束,所需的延时时间会是负值,在此种情况下,caputRecorder将不插入延时。

2) 等待结束:通过设置"wait for completion?"(见以上图表),你在执行录制的caputs后,选择caputRecorder是否等待结束。注意:这影响在录制时编写的python代码,并且不是ige执行时选项。你可以在录制时更改这种设置。

如果你告诉caputRecorder等待结束,你可以使用标签为"wait for how long?"的文本输入框告诉它等待多久。你可以在录制时更改这个时间。

3) 根据宏名称已经存在的行为:如果你尝试录制一个其名称已经在macros.py中被定义的宏时,caputRecorder将根据"if macro already exists:"开关的设置,做以下三件事之一:

  • fail:拒绝启动录制,并且设置Stop/Start开关回Stop。
  • append:移动这个宏到这个文件末尾,并且在其后追加命令。
  • replace:删除已有的宏,并且用那个名称开始一个新宏。在这种情况中,caputRecorder将写名为"macros.py_yymdd-HHMMSS"的macros.py的一个备份副本,此处yy时当前日期和时间。

全局变量

caputRecorder维护少量EPICS PVs,它们可以在任何宏中用作全局变量。对应这些变量的EPICS窗口如下显示。

如果wxPython可用,变量"filepath"和"filename"被文件请求者支持。如果wxPython不可用,这些变量仍然能够被使用,但值必须被手动输入。

其它变量是通用的:能够指定一个变量名和其字符串值。通过调用函数_getGlobals(prefix="xxx:"),一个宏可以获取全局变量。_getGlobals()返回一个带有全局变量名和值的python字典。对于以上的窗口,将返回以下字段:

{'varName': 'string value',
'filename': 'abc_0838.mda',
'filepath': '/home/oxygen4/MOONEY/data'}

这是一个演示在一个宏中使用全局变量的示例代码:

def testGlobals():
	g = _getGlobals("xxx:")
	print "globals=%s" % g

	filename = g['filename']
	print "filename = ", filename

讨论

1) 通过导入macros.py文件, caputRecorder "读取"它:

import macros.py

在macros.py已经被更改后,通过重新状态它,caputRecorder ”重读“它:

reload(macros)

重新装载将用来自macro.py来的值重写有效macros模块中的对象,但它不删除任何对象。如果你删除来自macros.py的一个函数定义或者一个全局变量,重新状态不会从macros模块的有效副本删除它;你必须重启python,你可以通过按下"!(re)start recorder"可以做这件事。

2) caputRecorder用以下python代码录制一个caput:

epics.caput("xxx:scan1.P1PV","xxx:m2.VAL", wait=True, timeout=1000000.0)

此代码将请求来自EPICS结束回调,并且一直等待这个回调的到来。

当前,在等待一个回调时,一个宏超时不是一个错误。Python将继续下条命令并且执行它。当前,caputRecorder没有使用PyEpics的执行若干命令并且接着等待所有一起结束的功能(即是,PV类的put()方法的"use_complete"选项)。

3)caPutLog也可以捕获并且写它们到一个PV。caputRecorder的原理实现使用了caPutLog 3.4做这件事,但它不处理长字符串。

4) 在EPICS 3.14.12.4以及更早版本,以及3.15早于3.15.2的版本中,访问安全没有提供数据从caput到asTrapListener,因此caputRecorder使用dbGetField()获取在其被写后的数据。对大部分PVs,这是可以的,但某些PVs(例如:motor记录的tweak字段)在被写后立即更改它们的值,而caputRecorder正在获取最终的值,而非用户实际写的值。Andrew Johnson通过提供数据给asTrapListener修复了这个问题,并且如果它存在,caputRecorder R1-4以及以后版本将使用这个功能。

5)caputRecorder R1-4监视它的PVs中一个PV的连接状态,并且如果PV保存断开超过10秒种时退出。

6)EDM窗口文件转换在这个adl文件的"shell command"时出错,因此我只从这个EDM窗口删除那些项。

7)你可以在一个IOC中运行多个caputRecorder实例(但每个IOC仅支持一个caputPoster.db副本)。要运行caputRecorder的两个实例,你必须赋给它们不同的前缀:

dbLoadRecords("$(CAPUTRECORDER)/caputRecorderApp/Db/caputPoster.db","P=xxx:,N=300")
dbLoadRecords("$(CAPUTRECORDER)/caputRecorderApp/Db/caputRecorder.db","P=xxx:,N=100")
dbLoadRecords("$(CAPUTRECORDER)/caputRecorderApp/Db/caputRecorder.db","P=xxxA:,N=100")
...
iocInit
...
registerCaputRecorderTrapListener('xxx:caputRecorderCommand')

start_putRecorder必须为两个实例对macros.py指定不同的名称。example_start_putRecorder脚本必须按以下做这件事:

MACROS_PY=${MACROS_PY_DIR}/"macros_"${PREFIX}.py
# start caputRecorder.py
$COMMAND ${PREFIX} ${MACROS_PY}&

你也必须通过在"prefixes:"中指定前缀告诉第二个副本查看一个caputPoster.db的一个安装的副本(即是:xxx:caputRecorderCommand PV)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值