文章目录
- 1、变量
- 1.1、数组类型
- 1.2、获取数据
- 1.3、设置数据
- 1.4、编码/解码
- 1.5、Array
- 1.6、List
- 1.7、动态变量
- 2、Items
- 2.1、 Item types
- 2.2、 Creating items
- 2.1.1、 From value
- 2.1.2、From SML text
- 2.1.3、 From protocol text
- 2.3、 Getting data
- 2.3.1、 Python value
- 2.3.2、 SML text
- 2.1.3、 Protocol text
- 3、Functions
- 4、Handler
1、变量
SECS 定义了几种用于传输数据的类型。
Data Type | Class | Code |
---|---|---|
List | {py:class}secsgem.secs.variables.Array | L |
List | {py:class}secsgem.secs.variables.List | L |
Binary | {py:class}secsgem.secs.variables.Binary | B |
Boolean | {py:class}secsgem.secs.variables.Boolean | TF |
ASCII | {py:class}secsgem.secs.variables.String | A |
8-Byte integer | {py:class}secsgem.secs.variables.I8 | I8 |
1-Byte integer | {py:class}secsgem.secs.variables.I1 | I1 |
2-Byte integer | {py:class}secsgem.secs.variables.I2 | I2 |
4-Byte integer | {py:class}secsgem.secs.variables.I4 | I4 |
8-Byte float | {py:class}secsgem.secs.variables.F8 | F8 |
4-Byte float | {py:class}secsgem.secs.variables.F4 | F8 |
8-Byte unsigned integer | {py:class}secsgem.secs.variables.U8 | U8 |
1-Byte unsigned integer | {py:class}secsgem.secs.variables.U1 | U1 |
2-Byte unsigned integer | {py:class}secsgem.secs.variables.U2 | U2 |
4-Byte unsigned integer | {py:class}secsgem.secs.variables.U4 | U4 |
Example:
>>> import secsgem.secs
>>> secsgem.secs.variables.String("TESTString")
<A "TESTString">
>>> secsgem.secs.variables.Boolean(True)
<BOOLEAN True >
>>> secsgem.secs.variables.U4(1337)
<U4 1337 >
1.1、数组类型
numeric 类型也可以是该类型的数组:
>>> secsgem.secs.variables.U1([1, 2, 3, 4])
<U1 1 2 3 4 >
>>> secsgem.secs.variables.Boolean([True, False, False, True])
<BOOLEAN True False False True >
这个数组的长度可以用 length 参数来固定:
>>> secsgem.secs.variables.U1([1, 2, 3], count=3)
<U1 1 2 3 >
>>> secsgem.secs.variables.U1([1, 2, 3, 4], count=3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/ext005207/Development/secsgem/secsgem/secs/variables.py", line 1439, in __init__
self.set(value)
File "/home/ext005207/Development/secsgem/secsgem/secs/variables.py", line 1537, in set
raise ValueError("Value longer than {} chars".format(self.count))
ValueError: Value longer than 3 chars
>>> secsgem.secs.variables.String("Hello", count=3).get()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/ext005207/Development/secsgem/secsgem/secs/variables.py", line 1220, in __init__
self.set(value)
File "/home/ext005207/Development/secsgem/secsgem/secs/variables.py", line 1337, in set
raise ValueError("Value longer than {} chars ({} chars)".format(self.count, len(value)))
ValueError: Value longer than 3 chars (5 chars)
1.2、获取数据
该数据可通过 {py:func}
secsgem.secs.variables.U1.get` 方法进行访问,数组则可通过索引运算符进行访问:
>>> secsgem.secs.variables.U1(1).get()
1
>>> secsgem.secs.variables.U1([1, 2, 3], count=3).get()
[1, 2, 3]
>>> secsgem.secs.variables.U1(1)[0]
1
>>> secsgem.secs.variables.U1([1, 2, 3])[1]
2
1.3、设置数据
数据可以通过 {py:func}secsgem.secs.variables.String.set
方法进行设置,数组可以通过索引运算符进行更新:
>>> v=secsgem.secs.variables.U1([1, 2, 3], count=3)
>>> v.set([3, 2, 1])
>>> v
<U1 3 2 1 >
>>> v[0] = 1
>>> v
<U1 1 2 1 >
1.4、编码/解码
这些变量类型本身可以使用 {py:func}secsgem.secs.variables.Array.encode
和 {py:func}secsgem.secs.variables.String.decode
方法将数据转换为可与 HSMS 协议进行传输的 ASCII 数据:
>>> v=secsgem.secs.variables.String("Hello")
>>> d=v.encode()
>>> d
'A\x05Hello'
>>> secsgem.common.format_hex(d)
'41:05:48:65:6c:6c:6f'
>>> v.set("NewText")
>>> v
<A "NewText">
>>> v.decode(d)
7
>>> v
<A "Hello">
1.5、Array
{py:class}secsgem.secs.variables.Array
是一种用于表示同类型列表的特殊类型。数组中的各项可以通过索引运算符进行访问。
>>> v=secsgem.secs.variables.Array(secsgem.secs.variables.U4)
>>> v.set([1, 2, 3])
>>> v
<L [3]
<U4 1 >
<U4 2 >
<U4 3 >
>
>>> v.get()
[1, 2, 3]
>>> v[1]
<U4 2 >
可以使用 {py:func}secsgem.secs.variables.Array.append
方法向数组添加新元素。
1.6、List
{py:func}secsgem.secs.variables.List
是一种用于不同类型列表的特殊类型。
列表中的各项可以通过像访问对象属性那样进行访问。
创建有序字典是必需的,因为 Python 的默认字典是随机排序的。排序是必不可少的,因为双方都需要数据保持相同的顺序。
>>> v=secsgem.secs.variables.List([secsgem.secs.data_items.OBJACK, secsgem.secs.data_items.SOFTREV])
>>> v.OBJACK=3
>>> v.SOFTREV="Hallo"
>>> v
<L [2]
<U1 3 >
<A "Hallo">
>
>>> v.SOFTREV
<A "Hallo">
>>> secsgem.common.format_hex(v.encode())
'01:02:a5:01:03:41:05:48:61:6c:6c:6f'
1.7、动态变量
{py:class}secsgem.secs.variables.Dynamic
类型可变,若指定为特定的一组类型,则可取不同的类型。
>>> v=secsgem.secs.variables.Dynamic([secsgem.secs.variables.String, secsgem.secs.variables.U1])
>>> v.set(secsgem.secs.variables.String("Hello"))
>>> v
<A "Hello">
>>> v.set(secsgem.secs.variables.U1(10))
>>> v
<U1 10 >
>>> v.set(secsgem.secs.variables.U4(10))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/ext005207/Development/secsgem/secsgem/secs/variables.py", line 255, in set
raise ValueError("Unsupported type {} for this instance of Dynamic, allowed {}".format(value.__class__.__name__, self.types))
ValueError: Unsupported type U4 for this instance of Dynamic, allowed [<class 'secsgem.secs.variables.String'>, <class 'secsgem.secs.variables.U1'>]
2、Items
项目是构成 SECS 消息结构的实体。
就本包而言,列表也被假定为项目。
2.1、 Item types
Type | Class | Code |
---|---|---|
List | {py:class}secsgem.secs.items.ItemL | L |
Binary | {py:class}secsgem.secs.items.ItemB | B |
Boolean | {py:class}secsgem.secs.items.ItemBOOLEAN | TF |
ASCII | {py:class}secsgem.secs.items.ItemA | A |
JIS-8 | {py:class}secsgem.secs.items.ItemJ | J |
8-Byte integer | {py:class}secsgem.secs.items.ItemI8 | I8 |
1-Byte integer | {py:class}secsgem.secs.items.ItemI1 | I1 |
2-Byte integer | {py:class}secsgem.secs.items.ItemI2 | I2 |
4-Byte integer | {py:class}secsgem.secs.items.ItemI4 | I4 |
8-Byte float | {py:class}secsgem.secs.items.ItemF8 | F8 |
4-Byte float | {py:class}secsgem.secs.items.ItemF4 | F8 |
8-Byte unsigned integer | {py:class}secsgem.secs.items.ItemU8 | U8 |
1-Byte unsigned integer | {py:class}secsgem.secs.items.ItemU1 | U1 |
2-Byte unsigned integer | {py:class}secsgem.secs.items.ItemU2 | U2 |
4-Byte unsigned integer | {py:class}secsgem.secs.items.ItemU4 | U4 |
2.2、 Creating items
2.1.1、 From value
可以通过 Item
类的 from_value
方法来创建项目对象。
>>> import secsgem.secs.items
>>>
>>> secsgem.secs.items.Item.from_value(10)
< U1 10 >
>>>
>>> secsgem.secs.items.Item.from_value([["Hallo", b"Welt"], 10, 2.5])
< L [3]
< L [2]
< A "Hallo">
< B 0x57 0x65 0x6c 0x74 >
>
< U1 10 >
< F4 2.5 >
>
这将自动为传递的 Python 值选择相应的项类型。
但可以通过传入一个项对象而非 Python 值来对其进行覆盖。
>>> secsgem.secs.items.Item.from_value([secsgem.secs.items.ItemU4(10)])
< L [1]
< U4 10 >
>
特定的项类型可以通过在构造函数中使用 Python 值来进行初始化。
>>> secsgem.secs.items.ItemI4(10)
< I4 10 >
>>>
>>> secsgem.secs.items.ItemI4([10, 20])
< I4 10 20 >
>>>
>>> secsgem.secs.items.ItemL([10, 20])
< L [2]
< U1 10 >
< U1 20 >
>
>>>
>>> secsgem.secs.items.ItemI4("text")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/secsgem/secs/item.py", line 132, in __init__
self._value = self.validate_value(value)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/secsgem/secs/item_number.py", line 77, in validate_value
raise self._invalid_type_exception(value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/secsgem/secs/item.py", line 508, in _invalid_type_exception
raise TypeError(f"Invalid value '{data}' of '{data.__class__.__name__}' for '{cls.__name__}'")
TypeError: Invalid value 'text' of 'str' for 'ItemI4'
2.1.2、From SML text
还可以通过 SML 字符串创建一个项目。
>>> secsgem.secs.items.Item.from_sml("< U4 10 >")
< U4 10 >
>>>
>>> type(secsgem.secs.items.Item.from_sml("< U4 10 >"))
<class 'secsgem.secs.item_number.ItemU4'>
>>>
>>> secsgem.secs.items.Item.from_sml("""
< L [3]
< L [2]
< A "Hallo">
< B 0x57 0x65 0x6c 0x74 >
>
< U4 10 >
< F4 2.5 >
>
""")
< L [3]
< L [2]
< A "Hallo">
< B 0x57 0x65 0x6c 0x74 >
>
< U4 10 >
< F4 2.5 >
>
2.1.3、 From protocol text
通过 SECS-I/HSMS 接收的二进制数据可以使用 decode 方法进行解码。
>>> secsgem.secs.items.Item.decode(b'\x01\x03\x01\x02A\x05Hallo!\x04Welt\xa5\x01\n\x91\x04@ \x00\x00')
< L [3]
< L [2]
< A "Hallo">
< B 0x57 0x65 0x6c 0x74 >
>
< U1 10 >
< F4 2.5 >
>
2.3、 Getting data
2.3.1、 Python value
通过使用 value
属性,可以获取一个项目的 Python 值。
>>> item = secsgem.secs.items.Item.from_value([["Hallo", b"Welt"], 10, 2.5])
>>> item.value
[['Hallo', b'Welt'], 10, 2.5]
2.3.2、 SML text
通过使用 sml
属性可以生成一个 SML 字符串。
>>> item = secsgem.secs.items.Item.from_value([["Hallo", b"Welt"], 10, 2.5])
>>> item.sml
'< L [3]\n < L [2]\n < A "Hallo">\n < B 0x57 0x65 0x6c 0x74 >\n >\n < U1 10 >\n < F4 2.5 >\n>'
该条目对象的 Python 输出还会打印出 SML 文本。
>>> item = secsgem.secs.items.Item.from_value([["Hallo", b"Welt"], 10, 2.5])
>>> item
< L [3]
< L [2]
< A "Hallo">
< B 0x57 0x65 0x6c 0x74 >
>
< U1 10 >
< F4 2.5 >
>
2.1.3、 Protocol text
SECS-I/HSMS 协议文本可以通过 encode
方法生成。
>>> item = secsgem.secs.items.Item.from_value([["Hallo", b"Welt"], 10, 2.5])
>>> item.encode()
b'\x01\x03\x01\x02A\x05Hallo!\x04Welt\xa5\x01\n\x91\x04@ \x00\x00'
3、Functions
该函数是从 {py:class}secsgem.secs.functionbase.SecsStreamFunction
继承而来的。
示例:
class SecsS02F33(SecsStreamFunction):
_stream = 2
_function = 33
_data_format = [
DATAID,
[
[
RPTID,
[VID]
]
]
]
_to_host = False
_to_equipment = True
_has_reply = True
_is_reply_required = True
_is_multi_block = True
函数的数据可以通过与变量相同的功能进行读取和操作。
{py:func}secsgem.secs.functionbase.SecsStreamFunction.set
、{py:func}secsgem.secs.functionbase.SecsStreamFunction.get
、{py:func}secsgem.secs.functionbase.SecsStreamFunction.append
、索引运算符以及对象属性。
这些对象还可以自行编码和解码。
Usage:
>>> f=secsgem.secs.functions.SecsS02F33()
>>> f.DATAID=10
>>> f.DATA.append({"RPTID": 5, "VID": ["Hello", "Hallo"]})
>>> f.DATA.append({"RPTID": 6, "VID": ["1", "2"]})
>>> f
S2F33 W
<L [2]
<U1 10 >
<L [2]
<L [2]
<U1 5 >
<L [2]
<A "Hello">
<A "Hallo">
>
>
<L [2]
<U1 6 >
<L [2]
<A "1">
<A "2">
>
>
>
> .
>>> f.DATA[1].VID[0]="Goodbye"
>>> f.DATA[1].VID[1]="Auf Wiedersehen"
>>> f
S2F33 W
<L [2]
<U1 10 >
<L [2]
<L [2]
<U1 5 >
<L [2]
<A "Hello">
<A "Hallo">
>
>
<L [2]
<U1 6 >
<L [2]
<A "Goodbye">
<A "Auf Wiedersehen">
>
>
>
> .
>>> secsgem.common.format_hex(f.encode())
'01:02:a5:01:0a:01:02:01:02:a5:01:05:01:02:41:05:48:65:6c:6c:6f:41:05:48:61:6c:6c:6f:01:02:a5:01:06:01:02:41:07:47:6f:6f:64:62:79:65:41:0f:41:75:66:20:57:69:65:64:65:72:73:65:68:65:6e'
编码后的数据可作为数据字符串与 {py:class}secsgem.hsms.HsmsMessage
中的 {py:class}secsgem.hsms.HsmsStreamFunctionHeader
一同使用。
请参阅 {doc}/hsms/messages
。
4、Handler
SecsHandler 具有为特定流和函数添加回调的功能。
>>> def s01f13_handler(connection, packet):
... print "S1F13 received"
...
>>> def on_connect(event, data):
... print "Connected"
...
>>> settings = secsgem.hsms.Settings(address="127.0.0.1", port=5000, connect_mode=secsgem.hsms.HsmsConnectMode.PASSIVE, device_type=secsgem.common.DeviceType.HOST)
>>> client = secsgem.secs.SecsHandler(settings)
>>> client.events.connected += on_connect
>>> client.register_stream_function(1, 13, s01f13_handler)
>>>
>>> client.enable()
Connected
S1F13 received
>>> client.disable()
此外,还涉及有关收集事件、服务变量和设备常量的其他功能。