支持模块
大部分记录类型的EPICS记录定义包括设置DTYP和INP或OUT字段。一个用longin的示例是:
record(longin, "instance:name") {
field(DTYP, "Python Device")
field(INP , "@pymodule some other string")
}
或等价的:
record(longin, "instance:name") {
field(DTYP, "Python Device")
field(INP , "@some other string")
info("pySupportMod", "pymodule")
}
这个最小示例将尝试导入一个名为'pymodule'的Python模块。预计这个模块提供一个build()函数。用记录实例和字符串"some other thing"调用它。
build()函数
build(record, args)
当IOC请求指定记录的设备支持实例时被调用。这个函数应该返回一个提供一个DeviceSupport方法的对象。
参数:
1)record:这个支持将被连接到的记录实例。可能被用于检查和请求初始字段值。
2)args:INP或OUT字段字符串的剩余部分。
def build(record, args):
print('Need device support for', record.name())
print('Provided:', args)
raise RuntimeError("Not support found!")
DeviceSupport接口
class DeviceSupport
DeviceSupport不是一个类。它而是一个所有Python设备支持实例都必须提供的方法的描述。在IOC process运行中,这些方法将被调用。
由这些方法产生的异常被输出到IOC console,但否则将被忽略。
模块devsup.interfaces提供了一个Zope接口定义,通过这个名称,其可以被引用。
1) raw:一个表明这个设备支持是否使用"raw"访问的布尔值。即使记录类型有一个RVAL字段(例如:ai/ao, mbbi/mbbo),一个Raw支持模块将更新VAL字段。忽略这个属性与False相同。
2)process(record, reason):
参数:
- record:请求源自的那个记录。
- reason:None或当请求process运行时,提供的一个对象。
当相关联的记录需要被更新来响应一个请求时,调用这个方法。这个请求的来源一般由这个记录的SCAN字段确定。
这个方法采取的动作严重依赖这个程序。一般这将包括从字段读取或写值。通过提供的记录实例,记录字段可以访问。
3)detach(record)
参数:
record:这个请求来自的记录。当IOC关闭时或者一个记录的INP或OUT字段被修改时,这将发生。根据记录,不再对这个对象进一步调用。
4)allowScan(record)
参数:
record:请求来源的那个记录。
返回类型:bool或Callable
当在启动后者在运行中进行设置记录的SCAN字段为"I/O Intr"尝试时,被调用。要允许这个,此方法返回一个计算结果为True的对象。如果不是,尝试将出错并且SCAN加ing恢复为"Passive"。
如果返回了一个可调用对象,则在再次更改SCAN时或者旧在detach()被调用前,它将被调用。
一般使用一个I/O扫描列表对象的add方法实现实现这个方法。(IOScanListBlock或IOScanListThread)。
class MySup(object):
def __init__(self):
self.a_scan = devsup.db.IOScanListThread()
def allowScan(self, record):
return self.a_scan.add(record)
在大多数情况下,它被简写为
class MySup(object):
def __init__(self):
self.a_scan = devsup.db.IOScanListThread()
self.allowScan = self.a_scan.add
示例
一个简单的计数器。process运行操作是增加VAL字段的值。以下代码应该被放在一个名为counter.py的文件,它被放置在Python模块导入路径。
class MySupport(object):
def detach(self, record):
pass # no cleanup needed
def allowScan(self, record):
return False # I/O Intr not supported
def process(self, record, reason):
record.VAL = record.VAL + 1
try:
record.UDF = 0
except AttributeError:
pass # not all record types implement this
def build(record, args):
if not args.startswith('hello'):
raise RuntimeError('%s is not friendly.'%record)
return MySupport()
从记录可以引用这个支持代码。
record(longin, "my:int:counter") {
field(DTYP, "Python Device")
field(INP , "@counter hello world")
}
以下将关联出错。
record(longin, "my:int:counter") {
field(DTYP, "Python Device")
field(INP , "@counter do what I say")
}
如果一个更短的INP链接字符串是必需的,或者防止运行时模块的切换,在pySupportMod info()标签中指定模块名。