pyepics PV -- 2

23 篇文章 24 订阅

PV:EPICS过程变量

pv模块提供了一个更高级的类pv.PV,其为一个EPICS过程变量创建一个PV对象。一个PV对象有用于访问它属性(properties)的方法和属性(attributes)。

PV类

class pv.PV(pvname[,callback=None[,form='time',[verbose=False[,auto_monitor=None[,count=None[,connection_callback=None,[connection_timeout=None[,access_callback=None]]]]]]]])

为一个指定名称的EPICS过程变量创建一个PV对象。

参数:

  • pvname:EPICS过程变量的名称
  • callback(callable, tuple, list或None):在PV值或状态变化时用户定义的回调函数
  • form(string,('native','ctrl','time')中之一):要使用哪种数据类型:‘native’,'time'或'ctrl'(control)变体。
  • verbose(True/False):是否打印出调试信息
  • auto_monitor(None, True, False或bitmask(见Automatic Monitoring of a PV))--是否自动监视这个PV的变化。
  • count(int):默认返回数据元素的数目
  • connection_callback(callback或None):在PV连接状态发生变化时被调用的用户定义函数。
  • connection_timeout(float或None):在放弃前等待连接的时间(秒为单位)
  • access_callback(callback或None):PV访问权变化时被调用的用户定义函数

一旦被创建了,一个PV应该(除了任何网络问题)自动连接并且准备使用。

>>> from epics import PV
>>> p = PV('XX:m1.VAL')
>>> print p.get()
>>> print p.count, p.type

pvname是必需的,并且是一个已有过程变量的名称。

callback参数指定一个或多个在变化是被调用的python方法,如在User-supplied Callback functions中更详细地讨论。

connection_callback参数指定一个在这个PV连接状态发生变化时(即是,当它连接或断开连接时)被调用地python方法。这在User-supplied Connection Callback functions中更详细地被讨论。

form参数指定为这个PV使用三种变体'native','ctrl'(control)或'time'(默认)中哪一种。'native'形式只返回值,'time'形式包括来自PV存活所在的服务器的时间戳,在一些情况中这个时间戳有用。也注意即使对于'native'或'time'形式的PVs,可以用get_ctrlvars()获取其它'ctrl'值字段(见Table of Control Attributes)可以用。

auto_monitor参数指定这个PV是否应该被自动监视。对此更加详细地讨论见Automatic Monitoring of a PV。

verbose参数指定在变化时更多详细输出,并且这是用于调试目的。

access_callback参数指定一个在PV访问权变化(读/写访问变化)时要被调用的python方法。

方法

一个PV用于获取和设置其值以及定义在PV变化时要被执行的回调函数的若干方法。

pv.get([count=None[,as_string=False[,as_numpy=True[,timeout=None[,use_monitor=True[,with_ctrlvars=False]]]]]])

获取和返回这个PV的当前值。

参数:

  • count(整数或None):要返回的数组元素的最大个数
  • as_string(True/False):是否返回这个值的字符串表示
  • as_numpy:如果合适,是否尝试返回一个numpy数组
  • timeout(float或None):在返回None前,等待数据的最长时间。
  • use_monitor(True/False):是否依靠监视器回调函数或者现在显式地获取值

有关如何确定字符串表示的详细见String represetation for a PV。

用as_numpy选项,假如numpy模块可用,一个数组PV(即是,一个其值有多个元素的PV)将以一个numpy数组返回。一个如何处理非常大型数组的策略的讨论见Strategies for working with large arrays。

use_monitor选项控制是否使用来自自动监视的最新值还是立即显式地请求这个值。通常,你可以依赖一个被保持更新的值,并且因而这里默认为True。但,由于网络流量不是即刻并且难于预测,用use_monitor=True的返回值可能是过时的。

timeout设置等待这个值被发送多久(秒为单位)。这只和use_monitor=False或者这个PV不是自动被监视的,一起使用。否则将立即发送最近接收的值。

with_ctrlvars选项除了通常被返回的值,还请求DBR_CTRL数据,包括控制限制,精度等等。通过访问诸如lower_ctrl_limit的各种属性,元数据将可获取。

更多有关监视PVs见Automatic Monitor of a PV,有关在一个pv.get()超时时发生什么的更详细情况见The wait and timeout options for get(), ca.get_complete()。

pv.get_with_metadata([form=None[,count=None[,as_string=None[,as_string=False[,as_numpy=True[,timeout=None[,use_monitor=True[,with_ctrlvars=False]]]]]]]])

返回一个当前值和相关联元数据的字典。

参数:

  • form({'native','time','ctrl',None}):要请求的EPICS数据类型:'native'或者'ctrl'(control)或者'time'变体。默认为实例属性form。
  • count(integer或None):要返回的数组元素的最大数目
  • as_string(True/False):是否返回这个值的字符串表示
  • as_numpy:合适处是否返回一个numpy数组
  • timeout(float或None):在返回None前,等待数据的最长时间
  • use_monitor(True/False):是否依赖监视回调函数或者限制显式地获取值。

有关这些参数的进一步注释见以上PV.get。

对EPICS每次请求可以包含于这个值相关联的可选地其它元数据。当PV.get用任何元数据更新这个PV实例,get_with_metadata将用字典返回请求的元数据和值。

例外是当PV设置成自动监视并且在这里设置了use_monitor参数。这意味着值和元数据将使用被缓存的值,而不是进行一次新请求。由于这样,这里返回的元数据和值将是对应这个PV实例的所有已知元数据的完整字典。

pv.put(value[,wait=False[,timeout=30.0[,use_complete=False[,callback=None[,callback_data=None]]]]])

设置PV值,可选地在运行结束前等待返回,或者设置put_complete指示完成。

参数:

  • value:设置PV的值
  • wait(True/False):在返回前是否等待运行结束。
  • timeout(float):在返回前等待完成的最长时间。
  • use_complete(True/False):是否使用一个内建回调函数来设置put_complete
  • callback(None或一个有效python函数):当运行完成时,要运行的用户提供的函数
  • callback_data:传递给一个用户提供的回调函数的额外数据

wait和callback参数以及'use_complete'/put_complete属性给出了一些了解一个put()结束的属性。更多细节见Put with wait, put callbacks, and put_complete。

pv.get_ctrlvars():返回一个对应这个PV的控制值的字典。取决于PV的数据类型,这个字典可能有很多成员。细节见Table of Control Attributes。

pv.get_timevars():返回一个对应PV的时间值的字典,其包含来自这个CA服务器的status, severity和timestamp。

pv.poll([evt=1.e-4[,iot=1.0]]):对变化进行轮询。这只是调用epics.ca.poll()

参数:

  • evt(float):传递给epics.ca.pend_event()的时间
  • iot(float):传递给epics.ca.pend_io()的时间

pv.connect([timeout=None])

这显式地连接一个PV,并且返回它是否已经成功地连接。它可能不是那样有用的,由于连接应该自动发送。见wait_for_connection()。

参数:

timeout(float):最大连接时间,传递给epics.ca.connect_channel()

返回类型:True/False

如果timeout是None,PVs connection_timeout参数将被使用。如果那也是None,将使用epics.ca.DEFAULT_CONNECTION_TIMEOUT

pv.wait_for_connection([timeout=None])

这等待到一个PV被连接,或者超时等待一个连接。返回连接是否发生了。

参数:

timeout(float):最大连接时间

返回类型:True/False

如果timeout是None,将使用PVs connection_timeout参数。如果那也是None,epics.ca.DEFAULT_CONNECTINO_TIMEOUT

pv.disconnect(): 断开一个PV,清除所有回调函数。

pv.reconnect(): 重新连接(或者尝试)一个断开的PV。

pv.clear_auto_monitor():关闭一个PV的自动监视。注意:这将通过调用epics.ca.clear_subscription()在CA层级暂停在一个PV上的所有事件回调函数,但将不清除PVs回调函数的列表。这意味着调用reconnect()将继续包含这个PV任何回调函数的事件处理。

pv.add_callback(callback=None[,index=None[,with_ctrlvars=True[,**kw]]])

添加一个用户定义的回调例程,来用于在这个PV的每次变化事件时运行。返回对应这个回调函数的整数。

参数:

  • callback(None或callable):用户提供的函数,在PV变化时,运行这个函数。
  • index(None(将生成整数)或者不可变):为这个回调函数定义键
  • with_ctrlvars:是否确认将被发送给这个回调函数的准确控制值。
  • kw:要传递给这个回调每次执行的其它键/值参列。

注意:可以定义多个回调函数,每个有它自己的索引(一个字典键,一般一个整数)。当一个PV变化时,将执行所有定义的回调函数。将按顺序(通过排序callbacks字段的键)调用它们。

也见:callbacks attributes,User-supplied Callbacks functions

pv.remove_callback(index=None)

使用提供的索引移除一个用户定义的回调例程。

参数:

index(None或整数):用户提供函数的索引,由add_callback()返回,也对应着在callbacks字段中这个回调函数的键。

返回类型:整数。

如果只定义了一个回调函数,一个index='None',这将清除这个唯一被定义的回调函数。

也见:callbacks attribute, User-suppiled Callback functions

pv.clear_callbacks():移除所有用户定义的回调例程。

pv.run_callbacks():立即执行所有用户定义的回调函数,即使PV未发生变化,对调试有用。

也见:callbacks attribute, User-suppiled Callback functions

pv.run_callback(index)

立即执行一个特定的用户定义的回调函数,即使这个PV未发生变化。对调试有用。

也见:callbacks attribute, User-suppiled Callback functions

pv.force_read_access_rights()

执行一个PV的访问权的读取。通常,一个PV将具有自定确定的访问权并且在访问权中订阅变化。但有时(特别64位Windows),自动报告的值是错误的。这个方法将显式地读取访问权。

属性attributes

一个PV对象有很多属性(attributes),每一个相关联底层PV的某个特性(property):它的值,host,count等等。对于每个能够变化的特性,PV属性将保留对应相应属性的最新值,大部分属性是只读的,并且不能被赋值。此规则的例外是value属性。

pv.value:这个PV的当前值。

注意:value属性可以被赋值。当读取时,将返回最新值,即使那意味着需要调用一个get()。

赋值给value等价于用put()方法设置这个值。

>>> from epics import PV
>>> p1 = PV('xxx.VAL')
>>> print p1.value
1.00
>>> p1.value = 2.00

pv.char_value: 这个值得字符串表示,如get()中描述得。

pv.status:PV 状态,对于一个正常,连接上得PV,着将是0

pv.type:描述PV数据类型的字符串,诸如dobule, float, enum, string, int, long, char或者这些的ctrl或time变体,它们将被命名为ctrl_double, time_enum等等。见Table of DBR TYPES。

pv.ftype:根据Table of DBR Types,指定PV数据类型的整数值(来自底层C库)。

pv.host:提供这个PV的主机的字符串。

pv.count:在一个PV中数据元素的数目。除了waveform PVs外都为1,它给出在waveform中元素数目。对于最新版本EPICS base(3.14.11以及之后),这给出了.NORD字段,其给出了上次写入到这个PV的元素数目,其可能少于允许的最大数目(见以下nelm)。

pv.nelm:在一个PV中数据元素的数目。除了waveform PVs外都为1,它给出了在这个waveform中元素的最大数目。对于最新版本EPICS base(3.14.11以及之后),这给出了.NELM参数。见以上count属性。

pv.read_access:布尔值(True/False)对于PV是否可读

pv.write_access:布尔值(True/False)对于PV是否可写。

pv.access:描述读/写访问的字符串。'read/write','read-only','write-only','no access'之一。

pv.severity:PV的严重性值。对于不是处于警报情况的PVs,通常0。

pv.timestamp:看到这个PV的上次事件的浮点时间戳(相对于POSIX时间原点,非EPICS时间原点)。注意:如果用form='time'选项创建这个PV对象,这将包含来自EPICS服务器的时间戳。否则,根据这个客户端的时间,设置timestamp,表明数据何时来自服务器。

pv.posixseconds:见到这个PV的上次事件的整数秒(相对于POSIX时间原点,非EPICS时间原点)。只在用form='time'选项时才设置这个,并且将反映来自服务区的时间戳。否则,这将是0,这可以用于表示那个timestamp属性是来自客户端。

pv.nanoseconds:对应见到这个PV的上次事件的纳秒数。只在用form='time'创建这个PV对象时,才设置这个,并且将给出比timestamp属性更高时间分辨率。

pv.precision:用于float和double PVs的十进制精度位数。

pv.units:用于PV的工程单位字符串。

pv.enum_strs:一个这个PV枚举状态的字符串的列表(对应枚举PVs)

pv.info:一个字符串段落(即是:包含新行),显示有关这个PV的很多信息。

pv.upper_disp_limit

pv.lower_disp_limit

pv.upper_alarm_limit

pv.upper_alarm_limit

pv.upper_warning_limit

pv.lower_warning_limit

pv.upper_ctrl_limit

pv.lower_ctrl_limit

这些都是对应一个PV的各种限制种类。

pv.put_complete: 一个布尔值(True/False),用于表明最近的put()是否结束了。

pv.callbacks:一个当前定义回调的字典,在这个PV变化时被运行。这个字段有整数键(一般按在定义它们时的升序),这些键设置执行这些回调函数的顺序。这个字段的值是(callback, keyword_arguments)的元组。

注意:可以直接地赋值给或者操作callbacks属性。不推荐这样。使用方法add_callback(), remove_callback()和clear_callbacks而不是直接更改这个字段。

pv.connection_callbacks:一个连接回调函数地简单列表:当PV地连接状态变化时,要被运行地函数。更多细节见User-supplied Connection Callback functions。

pv.access_callbacks:一个访问回调函数地列表:当PV地访问权变化时,要被调用地函数。更多细节见User-supplied Access Rights Callback functions。

对应PV地字符串表示

对应一个PV地字符串表示,要么由用传递给epics.ca.get()的as_string参数或者从char_value属性返回的,需要进一步解释。

字符串表示的值(char_value)将却决于一个PV的本地类型和计数。Table of String Representation

字符串表示的表格:如何为不同的本地数据类型映射原始数据为char_value。

对于带有大型指数的double/float值,格式化将是("%%.%ig" % (precision)) % value。对于字符waveforms(数目大于1的char数据),将根据以下设置char_value:

>>> firstnull  = val.index(0)
>>> if firstnull == -1: firstnull= len(val)
>>> char_value = ''.join([chr(i) for i in val[:firstnull]).rstrip()

PV的自动监视

当创建一个PV时,auto_monitor参数指定PV是否应该被自动监视。自动监视表示将为变化注册一个内部回调函数。由用户定义的任何回调函数将在变化发生时被这个内部回调函数调用。

对于大部分标量值PVs,自动监视是需要的,由于PV将看到所有变化(并且运行回调函数)而无需来自用户的任何其它交互。这个PV的值将总是被更新并且只不需要非必要的网络流量。

用于auto_monitor的可能值是:

  • False:对于一些PVs,尤其变化比你关注的快得多的哪些PVs或者包含了大型数组作为值得哪些PVs,auto_monitoring会增加你不需要的网络阻塞。对于这些,你会希望用auto_monitor=False创建你的PVs。当你这么做时,你将需要调用get()来显式地获取最新值。
  • None:对于auto_monitor的默认值是None,并且如果对应这个PV的元素数目小于epics.ca.AUTOMONITOR_MAXLENGTH(默认65536),被设置成True。要抑制更少数组值得PVs的监视,你必须显式地设置auto_monitor为False。对于有更多元素地waveform数组,除非你显式的设置auto_monitor=True或者一个显式的掩码,否则不会进行自动监视。更多细节见Strategies for working with large arrays。
  • True:当auto_monitor设为True,将使用在epics.ca.DEFAULT_SUBSCRIPTION_MASK中默认的订阅掩码集监视这个值。这个掩码确定哪种类型变化引起PV更新。默认,当PV值变化超过了这个监视死区时或者当PV警报状态变化时这个订阅更新。这个行为与在EPICS的camonitor工具中相同。
  • Mask:通过设置auto_monitor为一个由dbr.DBE_ALARM, dbr.DBE_LOG和/或dbr.DBE_VALUE组成的数值订阅掩码。这个掩码将被直接传递给epics.ca.create_subscription。一个示例如下:
pv1 = PV('AAA', auto_monitor=dbr.DBE_VALUE)
pv2 = PV('BBB', auto_monitor=dbr.DBE_VALUE|dbr.DBE_ALARM)
pv3 = PV('CCC', auto_monitor=dbr.DBE_VALUE|dbr.DBE_ALARM|dbr.DBE_LOG)

这将为pv1生成只在'AAA'的值变化时的回调,而pv2在'BBB'的值或状态变化时接收回调,而pv3将在'CCC'所有变化时接收回调。主语:这些值dbr.DBE_****常数是或到一起作为位掩码。

用户提供的回调函数

这部分描述了用户定义的函数,当PV的值变化时,它们被调用。这些回调函数是有用的,由于它们使得你得到变化的通知,而不必持续请求一个PVs当前值。这大部分信息类似对应ca模块的User-supplied callback函数中的信息,虽然在PV对象上有一些对回调的重要增强。

你可以对每个PV定义多个回调函数,在值变化时被运行。当创建一个PV时,可以指定这些函数,用callback参数,它可以接收单个回调函数或者回调函数的列表或元组。在一个PV被创建后,你可以用add_callback()添加回调函数,用remove_callback()移除它们,并且用run_callback()运行它们。每个回调有一个内部唯一的索引(一个小整数值),其可以用于指定要添加,移除或运行哪一个。

当定义一个回调函数,在一个PV变化时被运行,知道两件事是重要的:

  1. 你的函数将如何被调用
  2. 在你的回调函数内部容许做什么

用若干关键字参数调用回调函数。你应该准备使得它们传递给你的函数,并且应该总是包含**kw来捕获所有参数。你的回调将被发送以下关键字参数:

  • pvname:PV的名称
  • value:最新的值
  • char_value:值得字符串表示
  • count:数据元素数目
  • fytpe:指明数据类型得数值CA类型
  • type:对应数据得python类型
  • status:PV得状态(0对应OK)
  • precision:用于浮点值的十进制精度位数
  • severity:PV严重性
  • timestamp:来自CA服务器的时间戳
  • read_access:读访问(True/False)
  • write_access:写访问(True/False)
  • access:读-和写-访问的字符串
  • host:服务PV的主机和CA端口
  • enum_strs:枚举字符串的列表
  • upper_disp_limit:上显示限制
  • lower_disp_limit:下显示限制
  • upper_alarm_limit:上警报限制
  • lower_alarm_limit:下警报限制
  • lower_warning_limit:上警告限制
  • upper_warning_limit:下警告限制
  • lower_ctrl_limit:上控制限制
  • upper_ctrl_limit:下控制限制
  • chid:整数通道到ID
  • cb_info:包含回调ID和这个PV对象的(index,self)元组

这些中一些可能不直接地应用于所有PV数据类型,并且如果控制参数还未被用get_ctrlvars()获取到,一些值可能是None。

记住回调函数将在一个CA函数内中被运行是重要的,并且不能可靠地进行任何其它CA调用。想一想"这都发生在一个pend_event()调用内部发生",并且在一个可能是或者可能不是你程序的主线程的epics线程中是有帮助的。建议保持回调函数简短并且非资源密集。考虑这样的策略:知堆改变已经发生的记录是哦那个回调并且接着在后面响应那个变化--可能在一个单独线程中,可能在pend_event()已经发生。

提供给回调的cb_info参数需要特殊注意,由于它是传递的唯一非EPICS信息。cb_info参数将是一个包含(index,self)的元组,此处index是对应用于这个PV的callbacks字典的键,self是PV对象。使用这个元组的原则用法是:如果一个错误发生了,要移除这个当前的回调,由于例如在GUI代码中,如果回调打算更新的小部件消失了。

用户体统的连接回调函数

一个connection回调时一个用户定义的函数,当一个PV的链接状态变化时,将被调用。即是,当一个PV初始化连接,由于提供这个P的进程消失了而断开或者重连,或者网络连接丢失。在创建一个PV时,可以指定一个连接回调,或者通过追加到connection_callbacks列表,可以添加连接回调。如果定义有多个连接回调,当连接状态变化时,它们都将被运行。

一个连接回调应该准备接收以下关键字参数:

  • pvname:这个PV的名称
  • conn:连接状态

当conn将是'True'或'False',指定这个PV是否现在被连接。在下面给出一个简单示例:

用户提供的访问权限回调函数

一个访问权限回调函数是用户定义的函数,当一个PV经过访问权-读/写权限的变化时,它被调用。这个回调将在成功初始化以及在更改一个PV的访问权的多有事件时被调用,包括断开连接和重新连接事件。当一个PV被创建时可以指定一个访问权回调,或者通过追加到PV对象的access_callbacks列表,可以添加访问权回调。如果为一个PV定义了多个访问权回调,它们将在访问权事件时被调用。

用了wait, put callbacks和put_complete的put

一些EPICS记录花费一段显著时间完全运行,并且有时你想要在继续前等待到运行结束。有一些方法完成这个。首先,只要简单地等待,直到这个运行结束:

import epics
p = epics.PV('XXX')
p.put(1.0, wait=True)
print 'Done'

在打印'Done'前,这将挂起到这个PV运行完成(电机移动等)。你也可以指定一个最长等待时间--一个timeout(秒为单位)。

p.put(1.0, wait=True, timeout=30)

其将等待到30秒。为了严谨,这个超时不应该被用作准确时间--实际等待时间会稍微更长。

第二种方法是使用'use_complete'选项,并且监视put_complete属性在一次put()后变成了True。这是一种某种程度上比使用以上wait=True更灵活,因为你可以更仔细地控制多久查看一个put()完成,并且在这之间做什么。一个简单地示例:

p.put(1.0, use_complete=True)
waiting = True
while waiting:
    time.sleep(0.001)
    waiting = not p.put_complete

这种方法的另一个优点是你可以用python内建all函数等待多个PVs结束:

pvgroup = (epics.PV('XXX'), epics.PV('YYY'), epics.PV('ZZZ'))
newvals = (1.0, 2.0,  3.0)
for pv, val in zip(pvgroup, newvals):
    pv.put(val, use_complete=True)

waiting = True
while waiting:
    time.sleep(0.001)
    waiting = not all([pv.put_complete for pv in pvgroup])
print 'All puts are done!'

为了最大灵活性,可以都定义一个put回调,当这个put()完成时,要被运行的一个函数。这个函数需要一个pvname关键字参量,但将不接受另外的,除非你用put()的callback_data参量(其应该是一个像字典的)传入数据。一个简单的示例:

pv = epics.PV('XXX')
def onPutComplete(pvname=None, **kws):
    print 'Put done for %s' % pvname

pv.put(1.0, callback=onPutComplete)

get_pv()函数和PVs的_PVcache_

如在先前章节中提到的,为每个使用pyepics的过程维护了PVs的一个缓存。当使用epics.caget(), epics.caput等等时,或者在直接创建一个PV时,对应的PV被保存在一个全局缓存中,在pv._PVcache_中保存。

函数get_pv()将从这个cache获取指定名称的PV,或者如果没有找到,创建一个新PV。在长期运行的或者复杂的过程中,访问一个特定PV多次是经常的,可能调用创建一个PV的函数但只在那个函数生命中保持那个PV对象。使用get_pv()而不是创建一个PV可以提交性能(PV已经连接)并且强烈推荐。

pv.get_pv(pvname[,form='time'[,connect=False[,timeout=5[,context=None[,**kws]]]]])

从_PVcache_获取一个PV或者创建并且返回一个新PV

参数:

  • pvname:EPICS过程变量的名称
  • form((‘native’,'ctrl','time')字符串之一):要使用的epics数据:'naive',或'ctrl(control)'或'time'变体
  • connect(True/False):是否等待PV连接
  • timeout(float或None):在返回None前等待值得最长时间(秒为单位)
  • context(整数或None(默认)):整数线程环境

其它关键字直接被传递给PV。

pv._PVcache_:用于这个过程得PV对象得缓存。

示例

一些使用PV得简单示例如下。

基本使用

最简单的方法是简化创建一个PV并且使用它的value属性:

>>> from epics import PV
>>> p1 = PV('xxx.VAL')
>>> print p1.value
1.00
>>> p1.value = 2.00

print p1.value行自动获取当前PV值。p1.value=2.00行进行一次put()设置这个值,经过网络引起任何必要的运行。

以上示例等价于:

>>> from epics import PV
>>> p1 = PV('xxx.VAL')
>>> print p1.get()
1.00
>>> p1.put(value = 2.00)

要获取这个值的字符串表示,你可以使用以下之一:

>>> print p1.get(as_string=True)   # 方式1
'1.000'

>>> print p1.char_value        # 方式2
'1.000'

请求包含元数据

使用get_with_metadata()获取与单个通道访问相关联的元数据是可能的:

>>> from epics import PV
>>> p1 = PV('xxx.VAL', form='time')

>>> print(p1.get())
1.00

>>> p1.get_with_metadata()
{'status': 0,
 'severity': 0,
 'timestamp': 1543429156.811018,
 'posixseconds': 1543429156.0,
 'nanoseconds': 811018603,
 'value': 1.0}

>>> print(p1.get_with_metadata(form='ctrl'))
{'upper_disp_limit': 100.0,
 'lower_disp_limit': -100.0,
 'upper_alarm_limit': 0.0,
 'upper_warning_limit': 0.0,
 'lower_warning_limit': 0.0,
 'lower_alarm_limit': 0.0,
 'upper_ctrl_limit': 100.0,
 'lower_ctrl_limit': -100.0,
 'precision': 3,
 'units': 'deg',
 'status': 0,
 'severity': 0,
 'value': 1.0}

使用info的示例和更多属性示例

一个PV有很多属性。这可以从它的info段落见到:

>>> import epics
>>> p = epics.PV('13IDA:m3')
>>> print p.info
== 13IDA:m3  (native_double) ==
   value      = 0.2
   char_value = '0.200'
   count      = 1
   type       = double
   units      = mm
   precision  = 3
   host       = ioc13ida.cars.aps.anl.gov:5064
   access     = read/write
   status     = 0
   severity   = 0
   timestamp  = 1274809682.967 (2010-05-25 12:48:02.967364)
   upper_ctrl_limit    = 5.49393415451
   lower_ctrl_limit    = -14.5060658455
   upper_disp_limit    = 5.49393415451
   lower_disp_limit    = -14.5060658455
   upper_alarm_limit   = 0.0
   lower_alarm_limit   = 0.0
   upper_warning_limit = 0.0
   lower_warning_limit = 0.0
   PV is internally monitored, with 0 user-defined callbacks:
=============================

个别属性也可以按以下被访问。在访问info属性或者调用get_ctrlvars()前,这些中很多(控制属性,见Table of Control Attributes)将不被填入。

>>>  print p.type
double
>>> print p.units, p.precision, p.lower_disp_limit
mm 3 -14.5060658455

获取一个字符串值

通常想要一个PVs值得字符串表示,例如,在显示窗口中显示或者要写入到一些报告。对于字符串PVs和整数PVs,这是一项简单工作。对于浮点值,要显示多少重要数字是不明确得。EPICS PVs都有一个precision字段,其设置在描述十进制位后多少位。此外,对于ENUM PVs,需要获取ENUM状态得名称,而不仅它的整数值。

要获取一个PVs值得字符串表示,使用char_value属性或者传递as_string=True给get()。

put()的示例

要写一个一个新值到一个变量,可以使用这两个方法之一:

>>> import epics           # 方法1
>>> p = epics.PV('XXX')
>>> p.put(1.0)

>>> import epics           # 方法2
>>> p = epics.PV('XXX')
>>> p.value = 1.0

简单回调的示例

得到在一个PV变化时的一个通知经常是有用的。一般,必须持续查询一个PV值是否变化是不方便的(并且可能低效)。设置一个回调函数更好:当这个值变化时,要被运行的一个函数。

一个简单示例:

import epics
import time
def onChanges(pvname=None, value=None, char_value=None, **kw):
    print 'PV Changed! ', pvname, char_value, time.ctime()


mypv = epics.PV(pvname)
mypv.add_callback(onChanges)

print 'Now wait for changes'

t0 = time.time()
while time.time() - t0 < 60.0:
    time.sleep(1.e-3)
print 'Done.'

这首先定义一个名为onChange()的回调函数,并且接着只是等待变化发生。注意:回调函数应该接收关键字参量,并且一般使用**kw捕获所有参量。见User-supplied Callback for more details。 

连接回调的示例

一个连接回调:

#
# example of using a connection callback that will be called
# for any change in connection status

import epics
import time
import sys
from  pvnames import motor1

write = sys.stdout.write
def onConnectionChange(pvname=None, conn= None, **kws):
    write('PV connection status changed: %s %s\n' % (pvname,  repr(conn)))
    sys.stdout.flush()

def onValueChange(pvname=None, value=None, host=None, **kws):
    write('PV value changed: %s (%s)  %s\n' % ( pvname, host, repr(value)))
    sys.stdout.flush()
mypv = epics.PV(motor1, 
                connection_callback= onConnectionChange,
                callback= onValueChange)

mypv.get()

write('Now waiting, watching values and connection changes:\n')
t0 = time.time()
while time.time()-t0 < 300:
    time.sleep(0.01)

访问权回调的示例

关联一个访问权回调和一个PV:

import epics
import time

def access_rights_callback(read_access, write_access, pv=None):
    print "%s - read=%s, write=%s" % (pv.pvname, read_access, write_access)

# should immediately see the message upon connection
apv = epics.PV('pvname', access_callback=access_rights_callback)

try:
    start = time.time()
    while (time.time() - start) < 30:
        time.sleep(0.25)
except KeyboardInterrupt:
    pass

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值