forked from canopen-python/canopen
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathdatatypes.py
More file actions
126 lines (110 loc) · 2.86 KB
/
datatypes.py
File metadata and controls
126 lines (110 loc) · 2.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import struct
BOOLEAN = 0x1
INTEGER8 = 0x2
INTEGER16 = 0x3
INTEGER32 = 0x4
UNSIGNED8 = 0x5
UNSIGNED16 = 0x6
UNSIGNED32 = 0x7
REAL32 = 0x8
VISIBLE_STRING = 0x9
OCTET_STRING = 0xA
UNICODE_STRING = 0xB
TIME_OF_DAY = 0xC
TIME_DIFFERENCE = 0xD
DOMAIN = 0xF
INTEGER24 = 0x10
REAL64 = 0x11
INTEGER40 = 0x12
INTEGER48 = 0x13
INTEGER56 = 0x14
INTEGER64 = 0x15
UNSIGNED24 = 0x16
UNSIGNED40 = 0x18
UNSIGNED48 = 0x19
UNSIGNED56 = 0x1A
UNSIGNED64 = 0x1B
PDO_COMMUNICATION_PARAMETER = 0x20
PDO_MAPPING = 0x21
SDO_PARAMETER = 0x22
IDENTITY = 0x23
SIGNED_TYPES = (
INTEGER8,
INTEGER16,
INTEGER24,
INTEGER32,
INTEGER40,
INTEGER48,
INTEGER56,
INTEGER64,
)
UNSIGNED_TYPES = (
UNSIGNED8,
UNSIGNED16,
UNSIGNED24,
UNSIGNED32,
UNSIGNED40,
UNSIGNED48,
UNSIGNED56,
UNSIGNED64,
)
INTEGER_TYPES = SIGNED_TYPES + UNSIGNED_TYPES
FLOAT_TYPES = (REAL32, REAL64)
NUMBER_TYPES = INTEGER_TYPES + FLOAT_TYPES
DATA_TYPES = (VISIBLE_STRING, OCTET_STRING, UNICODE_STRING, DOMAIN)
class UnsignedN(struct.Struct):
"""Packing and unpacking unsigned integers of arbitrary width, like struct.Struct.
The width must be a multiple of 8 and must be between 8 and 64.
"""
def __init__(self, width: int):
self.width = width
if width % 8 != 0:
raise ValueError("Width must be a multiple of 8")
if width <= 0 or width > 64:
raise ValueError("Invalid width for UnsignedN")
elif width <= 8:
fmt = "B"
elif width <= 16:
fmt = "<H"
elif width <= 32:
fmt = "<L"
else:
fmt = "<Q"
super().__init__(fmt)
def unpack(self, buffer):
return super().unpack(buffer + b'\x00' * (super().size - self.size))
def pack(self, *v):
return super().pack(*v)[:self.size]
@property
def size(self) -> int:
return self.width // 8
class IntegerN(struct.Struct):
"""Packing and unpacking integers of arbitrary width, like struct.Struct.
The width must be a multiple of 8 and must be between 8 and 64.
"""
def __init__(self, width: int):
self.width = width
if width % 8 != 0:
raise ValueError("Width must be a multiple of 8")
if width <= 0 or width > 64:
raise ValueError("Invalid width for IntegerN")
elif width <= 8:
fmt = "b"
elif width <= 16:
fmt = "<h"
elif width <= 32:
fmt = "<l"
else:
fmt = "<q"
super().__init__(fmt)
def unpack(self, buffer):
mask = 0x80
neg = (buffer[self.size - 1] & mask) > 0
return super().unpack(
buffer + (b'\xff' if neg else b'\x00') * (super().size - self.size)
)
def pack(self, *v):
return super().pack(*v)[:self.size]
@property
def size(self) -> int:
return self.width // 8