当前位置: 首页 > news >正文

半导体设备通信标准—secsgem v0.3.0版本使用说明文档(1)之概述、如何安装及使用方法

文章目录

  • secsgem概述
  • 如何安装
  • 1 使用方法
    • 1.1、回调函数和事件
      • 1.1.1、回调函数
        • 1.1.1.1、继承的处理程序
        • 1.1.1.2、目标对象
        • 1.1.1.3、注册回调函数
      • 1.1.2、事件
        • 1.1.2.1、继承式处理程序
        • 1.1.2.2、目标对象
        • 1.1.2.3、注册事件
    • 1.2、实施一套 GEM 设备
      • 1.2.1、使用你自己的名字
      • 1.2.2、添加状态变量
      • 1.2.3、添加设备常数
      • 1.2.4、添加收集事件
      • 1.2.5、添加警报
      • 1.2.6、添加远程命令
    • 1.3、自定义流和函数
      • 1.3.1、自定义数据项
      • 1.3.2、 自定义流函数
      • 1.3.3、 整合流函数
    • 1.4、Secs 函数定义语言
      • 1.4.1、数据项
      • 1.4.2、 列表
        • 1.4.2.1、 固定长度列表
        • 1.4.2.2、 打开长度列表
        • 1.4.2.3、 嵌套
          • 1.4.2.1.1、 在固定长度列表中嵌套开放长度列表
      • 1.4.3、 注释
      • 1.4.4、 为什么要创建自定义函数定义语言?
      • 1.4.5、 为什么不创建一个全新的定义语言呢?
    • 1.5、测试

secsgem概述

secsgem 是一个用于与半导体行业中的主机或设备系统进行通信的 Python 包。

这些用例涵盖了从为实现或功能编写测试、开发环境中的模拟到完整的主机/设备实现等多个方面。该软件包的部分内容可以单独使用,例如 HSMS 可以在没有 SECS-II 的情况下单独使用,或者流和功能可以与不同的网络栈一起使用。

目前尚无支持通过串行端口进行通信的功能(SECS-I、SEMI E04)。只有以太网(HSMS、SEMI E37)是可用的。

HSMS、SECS 和 GEM 均为来自 SEMI 的标准。

如何安装

官方发布版本可通过
Pypi 仓库获取。安装这些版本最简单的方法是使用像 pip 这样的包管理器:

$ pip install secsgem

为了使用当前的开发代码(有时可能会不稳定),请直接使用 Git 代码库:
(注:原文中的“instable”意为“不稳定的”,“git repository”意为“Git 代码库”)

$ pip install git+git://github.com/bparzella/secsgem

1 使用方法

secsgem 可以有多种使用方式。您可以将其用于创建针对设备端和主机端的 GEM 实现。此外,在 SECS-II 和 HSMS 层面上实现也是可行的。还有另一种使用方式,即通过使用 Python 单元测试来测试您的主机或设备实现。

1.1、回调函数和事件

  • 回调函数
    用于处理来自远程系统的请求,并返回用户定义的结果(例如,已收到警报且需要作出响应)。
  • 事件
    可以向实现程序通知已发生的情况(例如,已选择 HSMS 连接)。事件不会向远程系统返回任何结果,并且是在后台执行的。

1.1.1、回调函数

回调函数用于向特定实现请求信息。
它们可用于处理传递过来的信息并向对方呈现结果。
对于一个回调函数而言,只能注册一个函数。

该过程会等待回调函数返回计算结果。
因此,回调函数应当尽可能高效地运行。

定义回调函数有三种方式,分别是:在 继承的处理程序 中创建它们;设置一个 目标对象 ;以及 注册回调 。
注册的回调函数会取代目标对象和被覆盖的函数。

1.1.1.1、继承的处理程序

在使用继承类时,可以通过创建具有特定名称的回调成员来实现回调功能:

class SampleEquipment(secsgem.gem.GemEquipmentHandler):def __init__(self, settings: secsgem.common.Settings):super().__init__(settings)def _on_alarm_received(self, handler, ALID, ALCD, ALTX):return ACKC5.ACCEPTED

在这个示例中,当接收到警报(回调名称为 alarm_received)时,会调用 _on_alarm_received 方法。
结果(在本例中为 ACKC5.ACCEPTED)将传递给发送警报的主机。

该函数的通用表述为:

def _on_<callback_name>(self, handler, <parameters>):return <result>

对于流/函数的回调函数也可以通过遵循特定的命名方式来实现重写:这种方式可以实现对回调函数的覆盖。

def _on_s05f01(self, handler, message):return self.stream_function(5, 2)(ACKC5.ACCEPTED)

请注意,流和函数编号会格式化为在它们仅有一个字符长时带有前导零。
在这种情况下,必须返回回复流/函数。

1.1.1.2、目标对象

这些方法无需在处理程序自身上实现。
还可以使用处理程序的回调成员名称注册另一个对象。
然后会在该对象中搜索 _on_<callback_name> 方法:

class TestClass:def _on_alarm_received(self, handler, ALID, ALCD, ALTX):return ACKC5.ACCEPTEDt = TestClass()handler.callbacks.target = t
1.1.1.3、注册回调函数

回调函数也可以从类之外进行注册:

Callbacks can also be registered from outside a class:

def f_alarm_received(handler, ALID, ALCD, ALTX):return ACKC5.ACCEPTED

要取消注册,请直接清除会员信息即可。

handler.callbacks.alarm_received = None

1.1.2、事件

事件会通知执行者事情已经发生了。
它们是异步触发的,执行结果会被忽略掉。

定义事件有三种方式,分别是:在 继承式处理程序 中创建事件;在处理程序的事件属性中设置 目标对象 ;以及注册事件 [#registering-events] 。

1.1.2.1、继承式处理程序

在使用继承类时,可以通过创建具有特定名称的成员来实现事件:

class SampleEquipment(secsgem.gem.GemEquipmentHandler):def __init__(self, settings: secsgem.common.Settings):super().__init__(settings)def _on_event_communicating(self, connection):pass

在这个示例中,当 HSMS 连接状态发生变化时,会调用 _on_event_communicating 方法。

该函数的通用表述为:

def _on_event_<event_name>(self, <parameters>):pass

若要捕获所有事件,可以重写 _on_event 方法:

class SampleEquipment(secsgem.gem.GemEquipmentHandler):def __init__(self, settings: secsgem.common.Settings):super().__init__(settings)def _on_event(self, *args):pass
1.1.2.2、目标对象

这些方法无需在处理程序自身上实现。
还可以使用处理程序的事件成员名称来注册其他对象。
然后会在该对象中搜索 _on_event_<event_name>_on_event 方法:

class TestClass:def _on_event_communicating(self, connection):passt = TestClass()handler.events.targets += t

该事件处理程序能够处理多个目标对象。

1.1.2.3、注册事件

事件也可以从类外进行注册:

def f_communicating(connection):passhandler.events.communicating += f_communicating

要取消注册,请直接删除会员信息即可。

handler.events.communicating -= f_communicating

1.2、实施一套 GEM 设备

此包可用于创建 GEM 设备实现。
这是通过继承 {py:class}secsgem.gem.equipmenthandler.GemEquipmentHandler 类来完成的:

import secsgem.gem
import codeclass SampleEquipment(secsgem.gem.GemEquipmentHandler):def __init__(self, settings: secsgem.common.Settings):super().__init__(settings)h = SampleEquipment("127.0.0.1", 5000, False, 0, "sampleequipment")
h.enable()code.interact("equipment object is available as variable 'h', press ctrl-d to stop", local=locals())h.disable()

1.2.1、使用你自己的名字

如果您要使用自己的模型名称和版本来回复 S1F14,可以重写 GemHandler 类中的 {py:attr}secsgem.gem.handler.GemHandler.MDLN 和 {py:attr}secsgem.gem.handler.GemHandler.SOFTREV 成员:

class SampleEquipment(secsgem.gem.GemEquipmentHandler):def __init__(self, settings: secsgem.common.Settings):super().__init__(settings)self.MDLN = "gemequp"self.SOFTREV = "1.0.0"

1.2.2、添加状态变量

可以通过向 {py:attr}secsgem.gem.equipmenthandler.GemEquipmentHandler.status_variables 字典中插入一个 {py:class}secsgem.gem.equipmenthandler.StatusVariable 类的实例来添加一个状态变量:

class SampleEquipment(secsgem.gem.GemEquipmentHandler):def __init__(self, settings: secsgem.common.Settings):super().__init__(settings)self.status_variables.update({10: secsgem.gem.StatusVariable(10, "sample1, numeric SVID, SecsVarU4", "meters", secsgem.secs.variables.U4, False),"SV2": secsgem.gem.StatusVariable("SV2", "sample2, text SVID, SecsVarString", "chars", secsgem.secs.variables.String, False),})self.status_variables[10].value = 123self.status_variables["SV2"].value = "sample sv"

或者,也可以通过将构造函数的 use_callback 参数设置为 True 来使用回调函数获取这些值:

class SampleEquipment(secsgem.gem.GemEquipmentHandler):def __init__(self, settings: secsgem.common.Settings):super().__init__(settings)self.sv1 = 123self.sv2 = "sample sv"self.status_variables.update({10: secsgem.gem.StatusVariable(10, "sample1, numeric SVID, SecsVarU4", "meters", secsgem.secs.variables.U4, True),"SV2": secsgem.gem.StatusVariable("SV2", "sample2, text SVID, SecsVarString", "chars", secsgem.secs.variables.String, True),})def on_sv_value_request(self, svid, sv):if sv.svid == 10:return sv.value_type(value=self.sv1)elif sv.svid == "SV2":return sv.value_type(value=self.sv2)return []

1.2.3、添加设备常数

可以通过向 {py:attr}secsgem.gem.equipmenthandler.GemEquipmentHandler.status_variables 字典中插入一个 {py:class}secsgem.gem.equipmenthandler.EquipmentConstant 类的实例来添加一个设备常量:

class SampleEquipment(secsgem.gem.GemEquipmentHandler):def __init__(self, settings: secsgem.common.Settings):super().__init__(settings)self.equipment_constants.update({20: secsgem.gem.EquipmentConstant(20, "sample1, numeric ECID, SecsVarU4", 0, 500, 50, "degrees", secsgem.secs.variables.U4, False),"EC2": secsgem.gem.EquipmentConstant("EC2", "sample2, text ECID, SecsVarString", "", "", "", "chars", secsgem.secs.variables.String, False),})self.status_variables[20].value = 321self.status_variables["EC2"].value = "sample ec"

或者,也可以通过将构造函数的 use_callback 参数设置为 True 来使用回调函数来获取和更新这些值:

class SampleEquipment(secsgem.gem.GemEquipmentHandler):def __init__(self, settings: secsgem.common.Settings):super().__init__(settings)self.ec1 = 321self.ec2 = "sample ec"self.equipment_constants.update({20: secsgem.gem.EquipmentConstant(20, "sample1, numeric ECID, SecsVarU4", 0, 500, 50, "degrees", secsgem.secs.variables.U4, True),"EC2": secsgem.gem.EquipmentConstant("EC2", "sample2, text ECID, SecsVarString", "", "", "", "chars", secsgem.secs.variables.String, True),})def on_ec_value_request(self, ecid, ec):if ec.ecid == 20:return ec.value_type(value=self.ec1)elif ec.ecid == "EC2":return ec.value_type(value=self.ec2)return []def on_ec_value_update(self, ecid, ec, value):if ec.ecid == 20:self.ec1 = valueelif ec.ecid == "EC2":self.ec2 = value

1.2.4、添加收集事件

可以通过向 {py:attr}secsgem.gem.equipmenthandler.GemEquipmentHandler.collection_events 字典中插入一个 {py:class}secsgem.gem.equipmenthandler.CollectionEvent 类的实例来添加一个集合事件。
可以通过向 {py:attr}secsgem.gem.equipmenthandler.GemEquipmentHandler.data_values 字典中插入一个 {py:class}secsgem.gem.DataValue 类的实例来添加数据值。
在创建 {py:class}secsgem.gem.equipmenthandler.CollectionEvent 实例时,可以传递集合事件的数据值:

class SampleEquipment(secsgem.gem.GemEquipmentHandler):def __init__(self, settings: secsgem.common.Settings):super().__init__(settings)self.dv1 = 31337self.data_values.update({30: secsgem.gem.DataValue(30, "sample1, numeric DV, SecsVarU4", secsgem.secs.variables.U4, True),})self.collection_events.update({50: secsgem.gem.CollectionEvent(50, "test collection event", [30]),})def on_dv_value_request(self, dvid, dv):if dv.dvid == 30:return dv.value_type(value=self.dv1)return []def trigger_sample_collection_event():self.trigger_collection_events([50])

1.2.5、添加警报

可以通过向 {py:attr}secsgem.gem.equipmenthandler.GemEquipmentHandler.alarms 字典中插入一个 {py:class}secsgem.gem.equipmenthandler.Alarm 类的实例来添加警报。
添加警报时必须提供警报的集合事件。
有关示例,请参见上述部分:

class SampleEquipment(secsgem.gem.GemEquipmentHandler):def __init__(self, settings: secsgem.common.Settings):super().__init__(settings)self.collection_events.update({100025: secsgem.gem.CollectionEvent(100025, "test collection event alarm set", []),200025: secsgem.gem.CollectionEvent(200025, "test collection event alarm clear", []),})self.alarms.update({25: secsgem.gem.Alarm(25, "test alarm", "test text", self.data_items.ALCD.PERSONAL_SAFETY | self.data_items.ALCD.EQUIPMENT_SAFETY, 100025, 200025),})def set_sample_alarm():self.set_alarm(25)def clear_sample_alarm():self.clear_alarm(25)

1.2.6、添加远程命令

可以通过将 {py:class}secsgem.gem.equipmenthandler.RemoteCommand 类的一个实例插入到 {py:attr}secsgem.gem.equipmenthandler.GemEquipmentHandler.remote_commands 字典中来添加远程命令。
添加远程命令时必须提供集合事件和参数。
有关示例,请参见上述部分:

class SampleEquipment(secsgem.gem.GemEquipmentHandler):def __init__(self, settings: secsgem.common.Settings):super().__init__(settings)self.collection_events.update({5001: secsgem.gem.CollectionEvent(5001, "TEST_RCMD complete", []),})self.remote_commands.update({"TEST_RCMD": secsgem.gem.RemoteCommand("TEST_RCMD", "test rcmd", ["TEST_PARAMETER"], 5001),})def on_rcmd_TEST_RCMD(self, TEST_PARAMETER):print "remote command TEST_RCMD received"

1.3、自定义流和函数

1.3.1、自定义数据项

通过重写 {py:class}secsgem.secs.data_items.DataItemBase 类,可以创建一个新的数据项:

class UNITS_New(DataItemBase):__type__ = SecsVarDynamic__allowedtypes__ = [SecsVarArray, SecsVarBoolean, SecsVarU1, SecsVarU2, SecsVarU4, SecsVarU8, SecsVarI1, SecsVarI2, SecsVarI4, SecsVarI8, \SecsVarF4, SecsVarF8, SecsVarString, SecsVarBinary]

In this case the UNITS field allows all types instead only a string.

1.3.2、 自定义流函数

若要在流函数中整合这个新数据项,那么您就需要继承 {py:class}secsgem.secs.functions.SecsStreamFunction

class SecsS01F12_New(secsgem.secs.functions.SecsStreamFunction):_stream = 1_function = 12_data_format = """<L<L<SVID><SVNAME><UNITS_New>>>"""_to_host = True_to_equipment = False_has_reply = False_is_reply_required = False_is_multi_block = True

数据格式是在基于 SML 的定义语言中定义的。
有关该定义语言的更多信息,请参阅 Secs 函数定义语言 。

数据也可以通过一种古老的基于 Python 类型的格式来定义。
这是最初编写这些函数所依据的格式。
该格式仍然有效,但不久之后将会被弃用。

class SecsS01F12_New(secsgem.secs.functions.SecsStreamFunction):_stream = 1_function = 12_data_format = [[SVID,SVNAME,UNITS_New]]_to_host = True_to_equipment = False_has_reply = False_is_reply_required = False_is_multi_block = True

1.3.3、 整合流函数

现在我们要将这个流/功能整合到 {py:class}secsgem.gem.handler.GemHandler 中。
您需要创建一个新的类,该类继承自它,并更新该类的功能列表:

class NewHandler(secsgem.gem.GemHostHandler):def __init__(self, settings: secsgem.common.Settings):super().__init__(settings)self.settings.streams_functions.update(SecsS01F12_New)

You can also add new methods and properties to the class if required.

The streams functions list can also be updated outside of the Handler:

settings = secsgem.hsms.HsmsSettings()
settings.streams_functions.update(SecsS01F12_New)handler = NewHandler(settings)

1.4、Secs 函数定义语言

SFDL 派生自 SML,但它允许定义函数时无需使用混淆、冗余的类型定义。

1.4.1、数据项

数据项是通过在其所在的一组尖括号中给出其名称来定义的。

标准 S6F2 的结构定义

< ACKC6 >

标准 S2F36 的结构定义

< LRACK >

1.4.2、 列表

列表在一组尖括号中的左括号中用 ‘L’ 进行描述。

1.4.2.1、 固定长度列表

具有多个不同数据项的列表映射到 dict 或 object。 这可以通过数据项名称作为 key 来访问。

标准 S5F1 的结构定义

< L< ALCD >< ALID >< ALTX >
>
1.4.2.2、 打开长度列表

打开的列表仅使用一个数据项进行定义。 它们可以保存具有相同数据类型的多个值。

标准 S1F3 的结构定义

< L< SVID >
>
1.4.2.3、 嵌套

列表可以相互嵌套。

标准 S1F22 的结构定义

< L< L< VID >< DVVALNAME >< UNITS >>
>
1.4.2.1.1、 在固定长度列表中嵌套开放长度列表

如果包含单个数据项的打开列表嵌套在固定长度列表(映射到 dict/object)中,则嵌套数据项的名称将用于覆盖父列表的键。

标准 S2F23 的结构定义

< L< TRID >< DSPER >< TOTSMP >< REPGSZ >< L < SVID >>
>

这将使 SVID 列表可用于键/属性 SVID。

如果固定长度的开放列表嵌套在固定长度列表 (oof) 中,则解析名称不会像上一个示例那样工作。 在这种情况下,该项被简单地命名为 “DATA”。 但是可以通过在 L 标记后传递名称来覆盖此名称

标准 S2F33 的结构定义

< L< DATAID >< L REPORTS<L< RPTID >< L< VID >>>>
>

在这种情况下,报表列表将可通过键/属性 REPORTS.

但其他嵌套列表也可以这样命名

标准 S2F23 的结构定义

< L< TRID >< DSPER >< TOTSMP >< REPGSZ >< L SVIDS< SVID >>
>

这将使 SVID 列表可用于键/属性 SVIDS。

标准 S6F8 的结构定义

< L< DATAID >< CEID >< L DS< L< DSID >< L DV< L< DVNAME >< DVVAL >>>>>
>

1.4.3、 注释

注释以 # 开头,以换行符结尾。

< L  # Sample list< DATAID >  # The data id< CEID >    # The collection event id
>

1.4.4、 为什么要创建自定义函数定义语言?

虽然有一种名为 SML 的函数定义语言,但它并不满足定义泛型函数格式本身的要求。 在可视化消息中发送/接收的实际数据时,它会大放异彩。

该规范缺少开放列表(n 个元素)的定义。 此外,规范中未描述为数据项定义多个数据格式。(例如)

1.4.5、 为什么不创建一个全新的定义语言呢?

SML 在半导体行业非常普遍,很多人都接触过它。 因此,最好坚持使用至少与已知格式相似的格式。

1.5、测试

secsgem 可用于对您所实现的 SEMI 标准进行单元测试。

示例:

import unittestimport secsgem.common
import secsgem.gem
import secsgem.hsmsclass TestExampleSecsGem(unittest.TestCase):def setUp(self):settings = secsgem.hsms.Settings(address="127.0.0.1",port=5000,connect_mode=secsgem.hsms.HsmsConnectMode.PASSIVE,device_type=secsgem.common.DeviceType.HOST)self.handler = secsgem.gem.GemHostHandler.hsms(settings)self.handler.enable()self.handler.waitfor_communicating()def tearDown(self):self.handler.disable()def testLinktest(self):result_packet = self.handler.send_linktest_req()self.assertEqual(result_packet.header.s_type.value, 6)self.assertEqual(result_packet.header.device_id, 65535)

见测试用例文件:/testExample.py


http://www.mrgr.cn/news/98542.html

相关文章:

  • 【Bluedroid】A2DP Sink播放流程源码分析(二)
  • VGA显示
  • vue3环境搭建、nodejs22.x安装、yarn 1全局安装、npm切换yarn 1、yarn 1 切换npm
  • Jenkins插件下载慢解决办法
  • RAGFlow本地部署教程 :多模态检索+动态生成,用AI重构企业知识生产力
  • 第3篇:深入 Framer Motion Variants:掌握组件动画编排的艺术
  • Android掉帧分析
  • 利用pnpm patch命令实现依赖包热更新:精准打补丁指南
  • hadoop执行sqoop任务找不到jar
  • HTTP HTTPS RSA
  • idea如何使用git
  • MCP服务,阿里云百炼,Cline,mysql-mcp-server,MCP通信原理
  • 【HD-RK3576-PI】定制用户升级固件
  • GPIO _OUTPUT-NORMAL 模式
  • OpenAI发布GPT-4.1系列模型——开发者可免费使用
  • XSS漏洞及常见处理方案
  • 旅游特种兵迪士尼大作战:DeepSeek高精准路径优化
  • C++进程间通信开发实战:高效解决项目中的IPC问题
  • WINUI——Background颜色使用小结
  • Java EE(8)——线程安全总结(翻新版)——定时器(Timer)线程池(ThreadPoolExecutor)