DLMS-SPODES-client 0.19.35__py3-none-any.whl → 0.19.37__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- DLMS_SPODES_client/FCS16.py +39 -39
- DLMS_SPODES_client/__init__.py +12 -12
- DLMS_SPODES_client/client.py +2093 -2093
- DLMS_SPODES_client/gurux_common/enums/TraceLevel.py +21 -21
- DLMS_SPODES_client/gurux_dlms/AesGcmParameter.py +37 -37
- DLMS_SPODES_client/gurux_dlms/CountType.py +16 -16
- DLMS_SPODES_client/gurux_dlms/GXByteBuffer.py +545 -545
- DLMS_SPODES_client/gurux_dlms/GXCiphering.py +196 -196
- DLMS_SPODES_client/gurux_dlms/GXDLMS.py +426 -426
- DLMS_SPODES_client/gurux_dlms/GXDLMSChippering.py +237 -237
- DLMS_SPODES_client/gurux_dlms/GXDLMSChipperingStream.py +977 -977
- DLMS_SPODES_client/gurux_dlms/GXDLMSConfirmedServiceError.py +90 -90
- DLMS_SPODES_client/gurux_dlms/GXDLMSException.py +139 -139
- DLMS_SPODES_client/gurux_dlms/GXDLMSLNParameters.py +33 -33
- DLMS_SPODES_client/gurux_dlms/GXDLMSSNParameters.py +21 -21
- DLMS_SPODES_client/gurux_dlms/GXDLMSSettings.py +254 -254
- DLMS_SPODES_client/gurux_dlms/GXReplyData.py +87 -87
- DLMS_SPODES_client/gurux_dlms/HdlcControlFrame.py +9 -9
- DLMS_SPODES_client/gurux_dlms/MBusCommand.py +8 -8
- DLMS_SPODES_client/gurux_dlms/MBusEncryptionMode.py +27 -27
- DLMS_SPODES_client/gurux_dlms/ResponseType.py +8 -8
- DLMS_SPODES_client/gurux_dlms/SetResponseType.py +29 -29
- DLMS_SPODES_client/gurux_dlms/_HDLCInfo.py +9 -9
- DLMS_SPODES_client/gurux_dlms/__init__.py +75 -75
- DLMS_SPODES_client/gurux_dlms/enums/Access.py +12 -12
- DLMS_SPODES_client/gurux_dlms/enums/ApplicationReference.py +14 -14
- DLMS_SPODES_client/gurux_dlms/enums/Authentication.py +41 -41
- DLMS_SPODES_client/gurux_dlms/enums/BerType.py +35 -35
- DLMS_SPODES_client/gurux_dlms/enums/Command.py +285 -285
- DLMS_SPODES_client/gurux_dlms/enums/Definition.py +9 -9
- DLMS_SPODES_client/gurux_dlms/enums/ErrorCode.py +46 -46
- DLMS_SPODES_client/gurux_dlms/enums/ExceptionServiceError.py +12 -12
- DLMS_SPODES_client/gurux_dlms/enums/HardwareResource.py +10 -10
- DLMS_SPODES_client/gurux_dlms/enums/HdlcFrameType.py +9 -9
- DLMS_SPODES_client/gurux_dlms/enums/Initiate.py +10 -10
- DLMS_SPODES_client/gurux_dlms/enums/LoadDataSet.py +13 -13
- DLMS_SPODES_client/gurux_dlms/enums/ObjectType.py +306 -306
- DLMS_SPODES_client/gurux_dlms/enums/Priority.py +7 -7
- DLMS_SPODES_client/gurux_dlms/enums/RequestTypes.py +9 -9
- DLMS_SPODES_client/gurux_dlms/enums/Security.py +14 -14
- DLMS_SPODES_client/gurux_dlms/enums/Service.py +16 -16
- DLMS_SPODES_client/gurux_dlms/enums/ServiceClass.py +9 -9
- DLMS_SPODES_client/gurux_dlms/enums/ServiceError.py +8 -8
- DLMS_SPODES_client/gurux_dlms/enums/Standard.py +18 -18
- DLMS_SPODES_client/gurux_dlms/enums/StateError.py +7 -7
- DLMS_SPODES_client/gurux_dlms/enums/Task.py +10 -10
- DLMS_SPODES_client/gurux_dlms/enums/VdeStateError.py +10 -10
- DLMS_SPODES_client/gurux_dlms/enums/__init__.py +33 -33
- DLMS_SPODES_client/gurux_dlms/internal/_GXCommon.py +1673 -1673
- DLMS_SPODES_client/logger.py +56 -56
- DLMS_SPODES_client/services.py +90 -90
- DLMS_SPODES_client/session.py +363 -363
- DLMS_SPODES_client/settings.py +48 -48
- DLMS_SPODES_client/task.py +1884 -1884
- {dlms_spodes_client-0.19.35.dist-info → dlms_spodes_client-0.19.37.dist-info}/METADATA +29 -29
- dlms_spodes_client-0.19.37.dist-info/RECORD +61 -0
- {dlms_spodes_client-0.19.35.dist-info → dlms_spodes_client-0.19.37.dist-info}/WHEEL +1 -1
- dlms_spodes_client-0.19.35.dist-info/RECORD +0 -61
- {dlms_spodes_client-0.19.35.dist-info → dlms_spodes_client-0.19.37.dist-info}/entry_points.txt +0 -0
- {dlms_spodes_client-0.19.35.dist-info → dlms_spodes_client-0.19.37.dist-info}/top_level.txt +0 -0
|
@@ -1,545 +1,545 @@
|
|
|
1
|
-
import struct
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class GXByteBuffer:
|
|
5
|
-
""" Byte array class is used to save received bytes. """
|
|
6
|
-
info = 'gurux' # gurux object flag
|
|
7
|
-
__HEX_ARRAY = "0123456789ABCDEFGH"
|
|
8
|
-
__NIBBLE = 4
|
|
9
|
-
__LOW_BYTE_PART = 0x0F
|
|
10
|
-
__ARRAY_CAPACITY = 10
|
|
11
|
-
|
|
12
|
-
def __init__(self, value=None):
|
|
13
|
-
"""
|
|
14
|
-
Constructor.
|
|
15
|
-
value: Buffer or capacity.
|
|
16
|
-
"""
|
|
17
|
-
self._data = bytearray()
|
|
18
|
-
self.__size = 0
|
|
19
|
-
self.__position = 0
|
|
20
|
-
match value:
|
|
21
|
-
case bytearray() | bytes():
|
|
22
|
-
self.setCapacity(len(value))
|
|
23
|
-
self.set(value)
|
|
24
|
-
case GXByteBuffer():
|
|
25
|
-
self.setCapacity(value.size - value.position)
|
|
26
|
-
self.set(value)
|
|
27
|
-
case int(): self.setCapacity(value)
|
|
28
|
-
case str(): self.setHexString(value)
|
|
29
|
-
case _: self.setCapacity(0)
|
|
30
|
-
|
|
31
|
-
def clear(self):
|
|
32
|
-
""" Clear buffer but do not release memory. """
|
|
33
|
-
self.position = 0
|
|
34
|
-
self.size = 0
|
|
35
|
-
|
|
36
|
-
def getCapacity(self):
|
|
37
|
-
if not self._data:
|
|
38
|
-
return 0
|
|
39
|
-
return len(self._data)
|
|
40
|
-
|
|
41
|
-
#
|
|
42
|
-
# Allocate new size for the array in bytes.
|
|
43
|
-
#
|
|
44
|
-
# @param capacity
|
|
45
|
-
# Buffer capacity.
|
|
46
|
-
#
|
|
47
|
-
def setCapacity(self, capacity):
|
|
48
|
-
if capacity == 0:
|
|
49
|
-
self._data = bytearray()
|
|
50
|
-
self.__size = 0
|
|
51
|
-
self.__position = 0
|
|
52
|
-
else:
|
|
53
|
-
if not self._data:
|
|
54
|
-
self._data = bytearray(capacity)
|
|
55
|
-
else:
|
|
56
|
-
tmp = self._data
|
|
57
|
-
self._data = bytearray(capacity)
|
|
58
|
-
if self.size < capacity:
|
|
59
|
-
self._data[0:self.size] = tmp
|
|
60
|
-
else:
|
|
61
|
-
self._data[0:capacity] = self._data
|
|
62
|
-
self.__size = capacity
|
|
63
|
-
|
|
64
|
-
capacity = property(getCapacity, setCapacity)
|
|
65
|
-
"""Buffer capacity."""
|
|
66
|
-
|
|
67
|
-
def getPosition(self):
|
|
68
|
-
return self.__position
|
|
69
|
-
|
|
70
|
-
def setPosition(self, value):
|
|
71
|
-
if value < 0 or value > len(self):
|
|
72
|
-
raise ValueError("position")
|
|
73
|
-
self.__position = value
|
|
74
|
-
|
|
75
|
-
position = property(getPosition, setPosition)
|
|
76
|
-
"""Buffer position."""
|
|
77
|
-
|
|
78
|
-
def getSize(self):
|
|
79
|
-
return self.__size
|
|
80
|
-
|
|
81
|
-
def setsize(self, value):
|
|
82
|
-
if value < 0 or value > self.capacity:
|
|
83
|
-
raise ValueError("size")
|
|
84
|
-
self.__size = value
|
|
85
|
-
if self.__position > self.__size:
|
|
86
|
-
self.__position = self.__size
|
|
87
|
-
|
|
88
|
-
size = property(getSize, setsize)
|
|
89
|
-
"""Buffer size."""
|
|
90
|
-
|
|
91
|
-
def __len__(self) -> int:
|
|
92
|
-
"""Buffer size."""
|
|
93
|
-
return self.__size
|
|
94
|
-
|
|
95
|
-
def __getitem__(self, i):
|
|
96
|
-
return self._data[i]
|
|
97
|
-
|
|
98
|
-
def available(self) -> int:
|
|
99
|
-
"""Amount of non read bytes in the buffer."""
|
|
100
|
-
return self.size - self.position
|
|
101
|
-
|
|
102
|
-
#
|
|
103
|
-
# Get buffer data as byte array.
|
|
104
|
-
#
|
|
105
|
-
def array(self) -> bytearray:
|
|
106
|
-
return self.subArray(0, self.size)
|
|
107
|
-
|
|
108
|
-
#
|
|
109
|
-
# Returns sub array from byte buffer.
|
|
110
|
-
#
|
|
111
|
-
# @param index
|
|
112
|
-
# Start index.
|
|
113
|
-
# @param count
|
|
114
|
-
# Byte count.
|
|
115
|
-
# Sub array.
|
|
116
|
-
#
|
|
117
|
-
def subArray(self, index: int, count: int) -> bytearray:
|
|
118
|
-
if count != 0:
|
|
119
|
-
tmp = bytearray(count)
|
|
120
|
-
tmp[0:count] = self._data[index:index + count]
|
|
121
|
-
return tmp
|
|
122
|
-
return bytearray(0)
|
|
123
|
-
|
|
124
|
-
#
|
|
125
|
-
# Move content from source to destination.
|
|
126
|
-
#
|
|
127
|
-
# @param srcPos
|
|
128
|
-
# Source position.
|
|
129
|
-
# @param destPos
|
|
130
|
-
# Destination position.
|
|
131
|
-
# @param count
|
|
132
|
-
# Item count.
|
|
133
|
-
#
|
|
134
|
-
def move(self, srcPos, destPos, count):
|
|
135
|
-
if count < 0:
|
|
136
|
-
raise ValueError("count")
|
|
137
|
-
if count != 0:
|
|
138
|
-
self._data[destPos:destPos + count] = self._data[srcPos:srcPos + count]
|
|
139
|
-
self.size = destPos + count
|
|
140
|
-
if self.position > self.size:
|
|
141
|
-
self.position = self.size
|
|
142
|
-
|
|
143
|
-
#
|
|
144
|
-
# Remove handled bytes. This can be used in debugging to remove
|
|
145
|
-
# handled
|
|
146
|
-
# bytes.
|
|
147
|
-
#
|
|
148
|
-
def trim(self):
|
|
149
|
-
if self.size == self.position:
|
|
150
|
-
self.size = 0
|
|
151
|
-
else:
|
|
152
|
-
self.move(self.position, 0, self.size - self.position)
|
|
153
|
-
self.position = 0
|
|
154
|
-
|
|
155
|
-
#
|
|
156
|
-
# Push the given byte into this buffer at the current position, and
|
|
157
|
-
# then
|
|
158
|
-
# increments the position.
|
|
159
|
-
#
|
|
160
|
-
# @param item
|
|
161
|
-
# The byte to be added.
|
|
162
|
-
#
|
|
163
|
-
def setUInt8(self, item, index=None):
|
|
164
|
-
if index is None:
|
|
165
|
-
self.setUInt8(item, self.size)
|
|
166
|
-
self.size += 1
|
|
167
|
-
else:
|
|
168
|
-
if index >= self.capacity:
|
|
169
|
-
self.capacity = index + self.__ARRAY_CAPACITY
|
|
170
|
-
self._data[index] = item
|
|
171
|
-
|
|
172
|
-
#
|
|
173
|
-
# Push the given byte into this buffer at the current position, and
|
|
174
|
-
# then
|
|
175
|
-
# increments the position.
|
|
176
|
-
#
|
|
177
|
-
# @param item
|
|
178
|
-
# The byte to be added.
|
|
179
|
-
#
|
|
180
|
-
def setInt8(self, item, index=None):
|
|
181
|
-
self.setUInt8(item & 0xFF, index)
|
|
182
|
-
|
|
183
|
-
def setUInt16(self, item, index=None):
|
|
184
|
-
if index is None:
|
|
185
|
-
self.setUInt16(item, self.size)
|
|
186
|
-
self.size += 2
|
|
187
|
-
else:
|
|
188
|
-
if index + 2 >= self.capacity:
|
|
189
|
-
self.capacity = (index + self.__ARRAY_CAPACITY)
|
|
190
|
-
self._data[index] = int(((item >> 8) & 0xFF))
|
|
191
|
-
self._data[index + 1] = int((item & 0xFF))
|
|
192
|
-
|
|
193
|
-
def setUInt32(self, item, index=None):
|
|
194
|
-
if index is None:
|
|
195
|
-
self.setUInt32(item, self.size)
|
|
196
|
-
self.size += 4
|
|
197
|
-
else:
|
|
198
|
-
if index + 4 >= self.capacity:
|
|
199
|
-
self.capacity = index + self.__ARRAY_CAPACITY
|
|
200
|
-
self._data[index] = int(((item >> 24) & 0xFF))
|
|
201
|
-
self._data[index + 1] = int(((item >> 16) & 0xFF))
|
|
202
|
-
self._data[index + 2] = int(((item >> 8) & 0xFF))
|
|
203
|
-
self._data[index + 3] = int((item & 0xFF))
|
|
204
|
-
|
|
205
|
-
def setUInt64(self, item, index=None):
|
|
206
|
-
if index is None:
|
|
207
|
-
self.setUInt64(item, self.size)
|
|
208
|
-
self.size += 8
|
|
209
|
-
else:
|
|
210
|
-
if index + 8 >= self.capacity:
|
|
211
|
-
self.capacity = (index + self.__ARRAY_CAPACITY)
|
|
212
|
-
self._data[self.size] = int(((item >> 56) & 0xFF))
|
|
213
|
-
self._data[self.size + 1] = int(((item >> 48) & 0xFF))
|
|
214
|
-
self._data[self.size + 2] = int(((item >> 40) & 0xFF))
|
|
215
|
-
self._data[self.size + 3] = int(((item >> 32) & 0xFF))
|
|
216
|
-
self._data[self.size + 4] = int(((item >> 24) & 0xFF))
|
|
217
|
-
self._data[self.size + 5] = int(((item >> 16) & 0xFF))
|
|
218
|
-
self._data[self.size + 6] = int(((item >> 8) & 0xFF))
|
|
219
|
-
self._data[self.size + 7] = int((item & 0xFF))
|
|
220
|
-
|
|
221
|
-
def setFloat(self, value, index=None):
|
|
222
|
-
if index is None:
|
|
223
|
-
self.setFloat(value, self.size)
|
|
224
|
-
self.size += 4
|
|
225
|
-
else:
|
|
226
|
-
self.set(struct.pack("f", value), index)
|
|
227
|
-
|
|
228
|
-
def setDouble(self, value, index=None):
|
|
229
|
-
if index is None:
|
|
230
|
-
self.setDouble(value, self.size)
|
|
231
|
-
self.size += 8
|
|
232
|
-
else:
|
|
233
|
-
self.set(struct.pack("d", value), index)
|
|
234
|
-
|
|
235
|
-
def getUInt8(self, index: int = None) -> int:
|
|
236
|
-
if index is None:
|
|
237
|
-
index = self.position
|
|
238
|
-
value: int = self._data[index] & 0xFF
|
|
239
|
-
value = value % 2 ** 8
|
|
240
|
-
self.position += 1
|
|
241
|
-
return value
|
|
242
|
-
elif index >= self.size:
|
|
243
|
-
raise ValueError("getUInt8")
|
|
244
|
-
else:
|
|
245
|
-
value = self._data[index] & 0xFF
|
|
246
|
-
value = value % 2 ** 8
|
|
247
|
-
return value
|
|
248
|
-
|
|
249
|
-
def getInt8(self, index=None):
|
|
250
|
-
if index is None:
|
|
251
|
-
index = self.position
|
|
252
|
-
value = self._data[index]
|
|
253
|
-
value = (value + 2 ** 7) % 2 ** 8 - 2 ** 7
|
|
254
|
-
self.position += 1
|
|
255
|
-
return value
|
|
256
|
-
if index >= self.size:
|
|
257
|
-
raise ValueError("getInt8")
|
|
258
|
-
value = self._data[index]
|
|
259
|
-
value = (value + 2 ** 7) % 2 ** 8 - 2 ** 7
|
|
260
|
-
return value
|
|
261
|
-
|
|
262
|
-
def getUInt16(self, index=None):
|
|
263
|
-
if index is None:
|
|
264
|
-
index = self.position
|
|
265
|
-
value = ((self._data[index] & 0xFF) << 8) | (self._data[index + 1] & 0xFF)
|
|
266
|
-
value = value % 2 ** 16
|
|
267
|
-
self.position += 2
|
|
268
|
-
return value
|
|
269
|
-
if index + 2 > self.size:
|
|
270
|
-
raise ValueError("getUInt16")
|
|
271
|
-
value = ((self._data[index] & 0xFF) << 8) | (self._data[index + 1] & 0xFF)
|
|
272
|
-
value = value % 2 ** 16
|
|
273
|
-
return value
|
|
274
|
-
|
|
275
|
-
def getInt16(self):
|
|
276
|
-
return (self.getUInt16() + 2 ** 15) % 2 ** 16 - 2 ** 15
|
|
277
|
-
|
|
278
|
-
def getInt32(self, index=None):
|
|
279
|
-
if index is None:
|
|
280
|
-
index = self.position
|
|
281
|
-
if index + 4 > self.size:
|
|
282
|
-
raise ValueError("getInt32")
|
|
283
|
-
value = (self._data[index] & 0xFF) << 24 | (self._data[index + 1] & 0xFF) << 16 | (self._data[index + 2] & 0xFF) << 8 | (self._data[index + 3] & 0xFF)
|
|
284
|
-
value = (value + 2 ** 31) % 2 ** 32 - 2 ** 31
|
|
285
|
-
self.position += 4
|
|
286
|
-
return value
|
|
287
|
-
|
|
288
|
-
if index + 4 > self.size:
|
|
289
|
-
raise ValueError("getInt32")
|
|
290
|
-
value = (self._data[index] & 0xFF) << 24 | (self._data[index + 1] & 0xFF) << 16 | (self._data[index + 2] & 0xFF) << 8 | (self._data[index + 3] & 0xFF)
|
|
291
|
-
value = (value + 2 ** 31) % 2 ** 32 - 2 ** 31
|
|
292
|
-
return value
|
|
293
|
-
|
|
294
|
-
def getUInt32(self, index=None):
|
|
295
|
-
if index is None:
|
|
296
|
-
index = self.position
|
|
297
|
-
self.position += 4
|
|
298
|
-
if index + 4 > self.size:
|
|
299
|
-
raise ValueError("getUInt32")
|
|
300
|
-
value = self._data[index] & 0xFF
|
|
301
|
-
value = value << 24
|
|
302
|
-
value |= (self._data[index + 1] & 0xFF) << 16
|
|
303
|
-
value |= (self._data[index + 2] & 0xFF) << 8
|
|
304
|
-
value |= (self._data[index + 3] & 0xFF)
|
|
305
|
-
value = value % 2 ** 32
|
|
306
|
-
return value
|
|
307
|
-
|
|
308
|
-
def getFloat(self):
|
|
309
|
-
tmp = bytearray(4)
|
|
310
|
-
self.get(tmp)
|
|
311
|
-
# Swap bytes.
|
|
312
|
-
tmp2 = tmp[0]
|
|
313
|
-
tmp[0] = tmp[3]
|
|
314
|
-
tmp[3] = tmp2
|
|
315
|
-
tmp2 = tmp[1]
|
|
316
|
-
tmp[1] = tmp[2]
|
|
317
|
-
tmp[2] = tmp2
|
|
318
|
-
return struct.unpack("f", tmp)[0]
|
|
319
|
-
|
|
320
|
-
def getDouble(self):
|
|
321
|
-
tmp = bytearray(8)
|
|
322
|
-
self.get(tmp)
|
|
323
|
-
# Swap bytes.
|
|
324
|
-
tmp2 = tmp[0]
|
|
325
|
-
tmp[0] = tmp[7]
|
|
326
|
-
tmp[7] = tmp2
|
|
327
|
-
tmp2 = tmp[1]
|
|
328
|
-
tmp[1] = tmp[6]
|
|
329
|
-
tmp[6] = tmp2
|
|
330
|
-
tmp2 = tmp[2]
|
|
331
|
-
tmp[2] = tmp[5]
|
|
332
|
-
tmp[5] = tmp2
|
|
333
|
-
tmp2 = tmp[3]
|
|
334
|
-
tmp[3] = tmp[4]
|
|
335
|
-
tmp[4] = tmp2
|
|
336
|
-
return struct.unpack("d", tmp)[0]
|
|
337
|
-
|
|
338
|
-
def getInt64(self, index=None):
|
|
339
|
-
if index is None:
|
|
340
|
-
index = self.position
|
|
341
|
-
self.position += 8
|
|
342
|
-
value = ((self._data[index] & 0xFF)) << 56
|
|
343
|
-
value |= ((self._data[index + 1] & 0xFF)) << 48
|
|
344
|
-
value |= ((self._data[index + 2] & 0xFF)) << 40
|
|
345
|
-
value |= ((self._data[index + 3] & 0xFF)) << 32
|
|
346
|
-
value |= ((self._data[index + 4] & 0xFF)) << 24
|
|
347
|
-
value |= (self._data[index + 5] & 0xFF) << 16
|
|
348
|
-
value |= (self._data[index + 6] & 0xFF) << 8
|
|
349
|
-
value |= (self._data[index + 7] & 0xFF)
|
|
350
|
-
value = (value + 2 ** 63) % 2 ** 64 - 2 ** 63
|
|
351
|
-
return value
|
|
352
|
-
|
|
353
|
-
def getUInt64(self, index=None):
|
|
354
|
-
value = self.getInt64(index)
|
|
355
|
-
return value % 2 ** 64
|
|
356
|
-
|
|
357
|
-
#
|
|
358
|
-
# Check is byte buffer ASCII string.
|
|
359
|
-
#
|
|
360
|
-
# @param value
|
|
361
|
-
# Byte array.
|
|
362
|
-
# Is ASCII string.
|
|
363
|
-
#
|
|
364
|
-
@classmethod
|
|
365
|
-
def isAsciiString(cls, value):
|
|
366
|
-
# pylint: disable=too-many-boolean-expressions
|
|
367
|
-
if value:
|
|
368
|
-
for it in value:
|
|
369
|
-
if (it < 32 or it > 127) and it != '\r' and it != '\n' and it != '\t' and it != 0:
|
|
370
|
-
return False
|
|
371
|
-
return True
|
|
372
|
-
|
|
373
|
-
def getString(self, index, count):
|
|
374
|
-
if index is None and count is None:
|
|
375
|
-
tmp = self._data[0:self.size]
|
|
376
|
-
if self.isAsciiString(tmp):
|
|
377
|
-
str_ = tmp.decode("utf-8").rstrip('\x00')
|
|
378
|
-
else:
|
|
379
|
-
str_ = tmp.hex(sep=' ')
|
|
380
|
-
self.position += count
|
|
381
|
-
return str_
|
|
382
|
-
|
|
383
|
-
if index + count > self.size:
|
|
384
|
-
raise ValueError("getString")
|
|
385
|
-
tmp = self._data[index:index + count]
|
|
386
|
-
if self.isAsciiString(tmp):
|
|
387
|
-
return tmp.decode("utf-8").rstrip('\x00')
|
|
388
|
-
return tmp.hex(sep=' ')
|
|
389
|
-
|
|
390
|
-
def set(self, value, index=None, count=None):
|
|
391
|
-
if isinstance(value, str):
|
|
392
|
-
value = value.encode()
|
|
393
|
-
if value:
|
|
394
|
-
if index is None:
|
|
395
|
-
if isinstance(value, GXByteBuffer):
|
|
396
|
-
index = value.position
|
|
397
|
-
else:
|
|
398
|
-
index = 0
|
|
399
|
-
if count is None:
|
|
400
|
-
count = len(value) - index
|
|
401
|
-
if isinstance(value, GXByteBuffer):
|
|
402
|
-
self.set(value._data, index, count)
|
|
403
|
-
value.position = index + count
|
|
404
|
-
elif value and count != 0:
|
|
405
|
-
if self.size + count > self.capacity:
|
|
406
|
-
self.capacity = self.size + count + self.__ARRAY_CAPACITY
|
|
407
|
-
self._data[self.size:self.size + count] = value[index:index + count]
|
|
408
|
-
self.size += count
|
|
409
|
-
|
|
410
|
-
def get(self, target):
|
|
411
|
-
len1 = len(target)
|
|
412
|
-
if self.size - self.position < len1:
|
|
413
|
-
raise ValueError("get")
|
|
414
|
-
index = 0
|
|
415
|
-
for index in range(0, len1):
|
|
416
|
-
target[index] = self._data[self.position]
|
|
417
|
-
self.position = self.position + 1
|
|
418
|
-
|
|
419
|
-
#
|
|
420
|
-
# Compares, whether two given arrays are similar starting from current
|
|
421
|
-
# position.
|
|
422
|
-
#
|
|
423
|
-
# @param arr
|
|
424
|
-
# Array to compare.
|
|
425
|
-
# True, if arrays are similar. False, if the arrays differ.
|
|
426
|
-
#
|
|
427
|
-
def compare(self, arr):
|
|
428
|
-
len1 = len(arr)
|
|
429
|
-
if not arr or (self.size - self.position < len1):
|
|
430
|
-
return False
|
|
431
|
-
bytes_ = bytearray(len1)
|
|
432
|
-
self.get(bytes_)
|
|
433
|
-
ret = arr == bytes_
|
|
434
|
-
if not ret:
|
|
435
|
-
self.position -= len1
|
|
436
|
-
return ret
|
|
437
|
-
|
|
438
|
-
#
|
|
439
|
-
# Reverses the order of the given array.
|
|
440
|
-
#
|
|
441
|
-
def reverse(self):
|
|
442
|
-
first = self.position
|
|
443
|
-
last = self.size - 1
|
|
444
|
-
tmp = int()
|
|
445
|
-
while last > first:
|
|
446
|
-
tmp = self._data[last]
|
|
447
|
-
self._data[last] = self._data[first]
|
|
448
|
-
self._data[first] = tmp
|
|
449
|
-
last -= 1
|
|
450
|
-
first += 1
|
|
451
|
-
|
|
452
|
-
#
|
|
453
|
-
# Push the given hex string as byte array into this buffer at the
|
|
454
|
-
# current
|
|
455
|
-
# position, and then increments the position.
|
|
456
|
-
#
|
|
457
|
-
# @param value
|
|
458
|
-
# Byte array to add.
|
|
459
|
-
# @param index
|
|
460
|
-
# Byte index.
|
|
461
|
-
# @param count
|
|
462
|
-
# Byte count.
|
|
463
|
-
#
|
|
464
|
-
def setHexString(self, value, index=0, count=None):
|
|
465
|
-
tmp = self.hexToBytes(value)
|
|
466
|
-
if count is None:
|
|
467
|
-
count = len(tmp)
|
|
468
|
-
self.set(tmp, index, count)
|
|
469
|
-
|
|
470
|
-
def __str__(self):
|
|
471
|
-
return self._data[:self.size].hex(sep=' ')
|
|
472
|
-
|
|
473
|
-
#
|
|
474
|
-
# Get remaining data.
|
|
475
|
-
#
|
|
476
|
-
# Remaining data as byte array.
|
|
477
|
-
#
|
|
478
|
-
def remaining(self):
|
|
479
|
-
return self.subArray(self.position, self.size - self.position)
|
|
480
|
-
|
|
481
|
-
#
|
|
482
|
-
# Get remaining data as a hex string.
|
|
483
|
-
#
|
|
484
|
-
# @param addSpace
|
|
485
|
-
# Add space between bytes.
|
|
486
|
-
# Remaining data as a hex string.
|
|
487
|
-
#
|
|
488
|
-
def remainingHexString(self, addSpace=True):
|
|
489
|
-
return self.hex(self._data, addSpace, self.position, self.size - self.position)
|
|
490
|
-
|
|
491
|
-
#
|
|
492
|
-
# Get data as hex string.
|
|
493
|
-
#
|
|
494
|
-
# @param addSpace
|
|
495
|
-
# Add space between bytes.
|
|
496
|
-
# @param index
|
|
497
|
-
# Byte index.
|
|
498
|
-
# @param count
|
|
499
|
-
# Byte count.
|
|
500
|
-
# Data as hex string.
|
|
501
|
-
#
|
|
502
|
-
def toHex(self, addSpace=True, index=0, count=None):
|
|
503
|
-
if count is None:
|
|
504
|
-
count = len(self) - index
|
|
505
|
-
return self.hex(self._data, addSpace, index, count)
|
|
506
|
-
|
|
507
|
-
#Convert char hex value to byte value.
|
|
508
|
-
@classmethod
|
|
509
|
-
def ___getValue(cls, c):
|
|
510
|
-
#Id char.
|
|
511
|
-
if c.islower():
|
|
512
|
-
c = c.upper()
|
|
513
|
-
pos = GXByteBuffer.__HEX_ARRAY.find(c)
|
|
514
|
-
if pos == -1:
|
|
515
|
-
raise Exception("Invalid hex string")
|
|
516
|
-
return pos
|
|
517
|
-
|
|
518
|
-
@classmethod
|
|
519
|
-
def hexToBytes(cls, value):
|
|
520
|
-
"""Convert string to byte array.
|
|
521
|
-
value: Hex string.
|
|
522
|
-
Returns byte array.
|
|
523
|
-
"""
|
|
524
|
-
buff = bytearray()
|
|
525
|
-
if value:
|
|
526
|
-
lastValue = -1
|
|
527
|
-
for ch in value:
|
|
528
|
-
if ch != ' ':
|
|
529
|
-
if lastValue == -1:
|
|
530
|
-
lastValue = cls.___getValue(ch)
|
|
531
|
-
elif lastValue != -1:
|
|
532
|
-
buff.append(lastValue << GXByteBuffer.__NIBBLE | cls.___getValue(ch))
|
|
533
|
-
lastValue = -1
|
|
534
|
-
elif lastValue != -1:
|
|
535
|
-
buff.append(cls.___getValue(ch))
|
|
536
|
-
lastValue = -1
|
|
537
|
-
return buff
|
|
538
|
-
|
|
539
|
-
@classmethod
|
|
540
|
-
def hex(cls, value, addSpace=True, index=0, count=None):
|
|
541
|
-
""" Convert byte array to hex string. """
|
|
542
|
-
return value[index:count].hex(sep=' ' if addSpace else '')
|
|
543
|
-
|
|
544
|
-
def get_data(self) -> bytes:
|
|
545
|
-
return bytes(self._data)[:self.size]
|
|
1
|
+
import struct
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class GXByteBuffer:
|
|
5
|
+
""" Byte array class is used to save received bytes. """
|
|
6
|
+
info = 'gurux' # gurux object flag
|
|
7
|
+
__HEX_ARRAY = "0123456789ABCDEFGH"
|
|
8
|
+
__NIBBLE = 4
|
|
9
|
+
__LOW_BYTE_PART = 0x0F
|
|
10
|
+
__ARRAY_CAPACITY = 10
|
|
11
|
+
|
|
12
|
+
def __init__(self, value=None):
|
|
13
|
+
"""
|
|
14
|
+
Constructor.
|
|
15
|
+
value: Buffer or capacity.
|
|
16
|
+
"""
|
|
17
|
+
self._data = bytearray()
|
|
18
|
+
self.__size = 0
|
|
19
|
+
self.__position = 0
|
|
20
|
+
match value:
|
|
21
|
+
case bytearray() | bytes():
|
|
22
|
+
self.setCapacity(len(value))
|
|
23
|
+
self.set(value)
|
|
24
|
+
case GXByteBuffer():
|
|
25
|
+
self.setCapacity(value.size - value.position)
|
|
26
|
+
self.set(value)
|
|
27
|
+
case int(): self.setCapacity(value)
|
|
28
|
+
case str(): self.setHexString(value)
|
|
29
|
+
case _: self.setCapacity(0)
|
|
30
|
+
|
|
31
|
+
def clear(self):
|
|
32
|
+
""" Clear buffer but do not release memory. """
|
|
33
|
+
self.position = 0
|
|
34
|
+
self.size = 0
|
|
35
|
+
|
|
36
|
+
def getCapacity(self):
|
|
37
|
+
if not self._data:
|
|
38
|
+
return 0
|
|
39
|
+
return len(self._data)
|
|
40
|
+
|
|
41
|
+
#
|
|
42
|
+
# Allocate new size for the array in bytes.
|
|
43
|
+
#
|
|
44
|
+
# @param capacity
|
|
45
|
+
# Buffer capacity.
|
|
46
|
+
#
|
|
47
|
+
def setCapacity(self, capacity):
|
|
48
|
+
if capacity == 0:
|
|
49
|
+
self._data = bytearray()
|
|
50
|
+
self.__size = 0
|
|
51
|
+
self.__position = 0
|
|
52
|
+
else:
|
|
53
|
+
if not self._data:
|
|
54
|
+
self._data = bytearray(capacity)
|
|
55
|
+
else:
|
|
56
|
+
tmp = self._data
|
|
57
|
+
self._data = bytearray(capacity)
|
|
58
|
+
if self.size < capacity:
|
|
59
|
+
self._data[0:self.size] = tmp
|
|
60
|
+
else:
|
|
61
|
+
self._data[0:capacity] = self._data
|
|
62
|
+
self.__size = capacity
|
|
63
|
+
|
|
64
|
+
capacity = property(getCapacity, setCapacity)
|
|
65
|
+
"""Buffer capacity."""
|
|
66
|
+
|
|
67
|
+
def getPosition(self):
|
|
68
|
+
return self.__position
|
|
69
|
+
|
|
70
|
+
def setPosition(self, value):
|
|
71
|
+
if value < 0 or value > len(self):
|
|
72
|
+
raise ValueError("position")
|
|
73
|
+
self.__position = value
|
|
74
|
+
|
|
75
|
+
position = property(getPosition, setPosition)
|
|
76
|
+
"""Buffer position."""
|
|
77
|
+
|
|
78
|
+
def getSize(self):
|
|
79
|
+
return self.__size
|
|
80
|
+
|
|
81
|
+
def setsize(self, value):
|
|
82
|
+
if value < 0 or value > self.capacity:
|
|
83
|
+
raise ValueError("size")
|
|
84
|
+
self.__size = value
|
|
85
|
+
if self.__position > self.__size:
|
|
86
|
+
self.__position = self.__size
|
|
87
|
+
|
|
88
|
+
size = property(getSize, setsize)
|
|
89
|
+
"""Buffer size."""
|
|
90
|
+
|
|
91
|
+
def __len__(self) -> int:
|
|
92
|
+
"""Buffer size."""
|
|
93
|
+
return self.__size
|
|
94
|
+
|
|
95
|
+
def __getitem__(self, i):
|
|
96
|
+
return self._data[i]
|
|
97
|
+
|
|
98
|
+
def available(self) -> int:
|
|
99
|
+
"""Amount of non read bytes in the buffer."""
|
|
100
|
+
return self.size - self.position
|
|
101
|
+
|
|
102
|
+
#
|
|
103
|
+
# Get buffer data as byte array.
|
|
104
|
+
#
|
|
105
|
+
def array(self) -> bytearray:
|
|
106
|
+
return self.subArray(0, self.size)
|
|
107
|
+
|
|
108
|
+
#
|
|
109
|
+
# Returns sub array from byte buffer.
|
|
110
|
+
#
|
|
111
|
+
# @param index
|
|
112
|
+
# Start index.
|
|
113
|
+
# @param count
|
|
114
|
+
# Byte count.
|
|
115
|
+
# Sub array.
|
|
116
|
+
#
|
|
117
|
+
def subArray(self, index: int, count: int) -> bytearray:
|
|
118
|
+
if count != 0:
|
|
119
|
+
tmp = bytearray(count)
|
|
120
|
+
tmp[0:count] = self._data[index:index + count]
|
|
121
|
+
return tmp
|
|
122
|
+
return bytearray(0)
|
|
123
|
+
|
|
124
|
+
#
|
|
125
|
+
# Move content from source to destination.
|
|
126
|
+
#
|
|
127
|
+
# @param srcPos
|
|
128
|
+
# Source position.
|
|
129
|
+
# @param destPos
|
|
130
|
+
# Destination position.
|
|
131
|
+
# @param count
|
|
132
|
+
# Item count.
|
|
133
|
+
#
|
|
134
|
+
def move(self, srcPos, destPos, count):
|
|
135
|
+
if count < 0:
|
|
136
|
+
raise ValueError("count")
|
|
137
|
+
if count != 0:
|
|
138
|
+
self._data[destPos:destPos + count] = self._data[srcPos:srcPos + count]
|
|
139
|
+
self.size = destPos + count
|
|
140
|
+
if self.position > self.size:
|
|
141
|
+
self.position = self.size
|
|
142
|
+
|
|
143
|
+
#
|
|
144
|
+
# Remove handled bytes. This can be used in debugging to remove
|
|
145
|
+
# handled
|
|
146
|
+
# bytes.
|
|
147
|
+
#
|
|
148
|
+
def trim(self):
|
|
149
|
+
if self.size == self.position:
|
|
150
|
+
self.size = 0
|
|
151
|
+
else:
|
|
152
|
+
self.move(self.position, 0, self.size - self.position)
|
|
153
|
+
self.position = 0
|
|
154
|
+
|
|
155
|
+
#
|
|
156
|
+
# Push the given byte into this buffer at the current position, and
|
|
157
|
+
# then
|
|
158
|
+
# increments the position.
|
|
159
|
+
#
|
|
160
|
+
# @param item
|
|
161
|
+
# The byte to be added.
|
|
162
|
+
#
|
|
163
|
+
def setUInt8(self, item, index=None):
|
|
164
|
+
if index is None:
|
|
165
|
+
self.setUInt8(item, self.size)
|
|
166
|
+
self.size += 1
|
|
167
|
+
else:
|
|
168
|
+
if index >= self.capacity:
|
|
169
|
+
self.capacity = index + self.__ARRAY_CAPACITY
|
|
170
|
+
self._data[index] = item
|
|
171
|
+
|
|
172
|
+
#
|
|
173
|
+
# Push the given byte into this buffer at the current position, and
|
|
174
|
+
# then
|
|
175
|
+
# increments the position.
|
|
176
|
+
#
|
|
177
|
+
# @param item
|
|
178
|
+
# The byte to be added.
|
|
179
|
+
#
|
|
180
|
+
def setInt8(self, item, index=None):
|
|
181
|
+
self.setUInt8(item & 0xFF, index)
|
|
182
|
+
|
|
183
|
+
def setUInt16(self, item, index=None):
|
|
184
|
+
if index is None:
|
|
185
|
+
self.setUInt16(item, self.size)
|
|
186
|
+
self.size += 2
|
|
187
|
+
else:
|
|
188
|
+
if index + 2 >= self.capacity:
|
|
189
|
+
self.capacity = (index + self.__ARRAY_CAPACITY)
|
|
190
|
+
self._data[index] = int(((item >> 8) & 0xFF))
|
|
191
|
+
self._data[index + 1] = int((item & 0xFF))
|
|
192
|
+
|
|
193
|
+
def setUInt32(self, item, index=None):
|
|
194
|
+
if index is None:
|
|
195
|
+
self.setUInt32(item, self.size)
|
|
196
|
+
self.size += 4
|
|
197
|
+
else:
|
|
198
|
+
if index + 4 >= self.capacity:
|
|
199
|
+
self.capacity = index + self.__ARRAY_CAPACITY
|
|
200
|
+
self._data[index] = int(((item >> 24) & 0xFF))
|
|
201
|
+
self._data[index + 1] = int(((item >> 16) & 0xFF))
|
|
202
|
+
self._data[index + 2] = int(((item >> 8) & 0xFF))
|
|
203
|
+
self._data[index + 3] = int((item & 0xFF))
|
|
204
|
+
|
|
205
|
+
def setUInt64(self, item, index=None):
|
|
206
|
+
if index is None:
|
|
207
|
+
self.setUInt64(item, self.size)
|
|
208
|
+
self.size += 8
|
|
209
|
+
else:
|
|
210
|
+
if index + 8 >= self.capacity:
|
|
211
|
+
self.capacity = (index + self.__ARRAY_CAPACITY)
|
|
212
|
+
self._data[self.size] = int(((item >> 56) & 0xFF))
|
|
213
|
+
self._data[self.size + 1] = int(((item >> 48) & 0xFF))
|
|
214
|
+
self._data[self.size + 2] = int(((item >> 40) & 0xFF))
|
|
215
|
+
self._data[self.size + 3] = int(((item >> 32) & 0xFF))
|
|
216
|
+
self._data[self.size + 4] = int(((item >> 24) & 0xFF))
|
|
217
|
+
self._data[self.size + 5] = int(((item >> 16) & 0xFF))
|
|
218
|
+
self._data[self.size + 6] = int(((item >> 8) & 0xFF))
|
|
219
|
+
self._data[self.size + 7] = int((item & 0xFF))
|
|
220
|
+
|
|
221
|
+
def setFloat(self, value, index=None):
|
|
222
|
+
if index is None:
|
|
223
|
+
self.setFloat(value, self.size)
|
|
224
|
+
self.size += 4
|
|
225
|
+
else:
|
|
226
|
+
self.set(struct.pack("f", value), index)
|
|
227
|
+
|
|
228
|
+
def setDouble(self, value, index=None):
|
|
229
|
+
if index is None:
|
|
230
|
+
self.setDouble(value, self.size)
|
|
231
|
+
self.size += 8
|
|
232
|
+
else:
|
|
233
|
+
self.set(struct.pack("d", value), index)
|
|
234
|
+
|
|
235
|
+
def getUInt8(self, index: int = None) -> int:
|
|
236
|
+
if index is None:
|
|
237
|
+
index = self.position
|
|
238
|
+
value: int = self._data[index] & 0xFF
|
|
239
|
+
value = value % 2 ** 8
|
|
240
|
+
self.position += 1
|
|
241
|
+
return value
|
|
242
|
+
elif index >= self.size:
|
|
243
|
+
raise ValueError("getUInt8")
|
|
244
|
+
else:
|
|
245
|
+
value = self._data[index] & 0xFF
|
|
246
|
+
value = value % 2 ** 8
|
|
247
|
+
return value
|
|
248
|
+
|
|
249
|
+
def getInt8(self, index=None):
|
|
250
|
+
if index is None:
|
|
251
|
+
index = self.position
|
|
252
|
+
value = self._data[index]
|
|
253
|
+
value = (value + 2 ** 7) % 2 ** 8 - 2 ** 7
|
|
254
|
+
self.position += 1
|
|
255
|
+
return value
|
|
256
|
+
if index >= self.size:
|
|
257
|
+
raise ValueError("getInt8")
|
|
258
|
+
value = self._data[index]
|
|
259
|
+
value = (value + 2 ** 7) % 2 ** 8 - 2 ** 7
|
|
260
|
+
return value
|
|
261
|
+
|
|
262
|
+
def getUInt16(self, index=None):
|
|
263
|
+
if index is None:
|
|
264
|
+
index = self.position
|
|
265
|
+
value = ((self._data[index] & 0xFF) << 8) | (self._data[index + 1] & 0xFF)
|
|
266
|
+
value = value % 2 ** 16
|
|
267
|
+
self.position += 2
|
|
268
|
+
return value
|
|
269
|
+
if index + 2 > self.size:
|
|
270
|
+
raise ValueError("getUInt16")
|
|
271
|
+
value = ((self._data[index] & 0xFF) << 8) | (self._data[index + 1] & 0xFF)
|
|
272
|
+
value = value % 2 ** 16
|
|
273
|
+
return value
|
|
274
|
+
|
|
275
|
+
def getInt16(self):
|
|
276
|
+
return (self.getUInt16() + 2 ** 15) % 2 ** 16 - 2 ** 15
|
|
277
|
+
|
|
278
|
+
def getInt32(self, index=None):
|
|
279
|
+
if index is None:
|
|
280
|
+
index = self.position
|
|
281
|
+
if index + 4 > self.size:
|
|
282
|
+
raise ValueError("getInt32")
|
|
283
|
+
value = (self._data[index] & 0xFF) << 24 | (self._data[index + 1] & 0xFF) << 16 | (self._data[index + 2] & 0xFF) << 8 | (self._data[index + 3] & 0xFF)
|
|
284
|
+
value = (value + 2 ** 31) % 2 ** 32 - 2 ** 31
|
|
285
|
+
self.position += 4
|
|
286
|
+
return value
|
|
287
|
+
|
|
288
|
+
if index + 4 > self.size:
|
|
289
|
+
raise ValueError("getInt32")
|
|
290
|
+
value = (self._data[index] & 0xFF) << 24 | (self._data[index + 1] & 0xFF) << 16 | (self._data[index + 2] & 0xFF) << 8 | (self._data[index + 3] & 0xFF)
|
|
291
|
+
value = (value + 2 ** 31) % 2 ** 32 - 2 ** 31
|
|
292
|
+
return value
|
|
293
|
+
|
|
294
|
+
def getUInt32(self, index=None):
|
|
295
|
+
if index is None:
|
|
296
|
+
index = self.position
|
|
297
|
+
self.position += 4
|
|
298
|
+
if index + 4 > self.size:
|
|
299
|
+
raise ValueError("getUInt32")
|
|
300
|
+
value = self._data[index] & 0xFF
|
|
301
|
+
value = value << 24
|
|
302
|
+
value |= (self._data[index + 1] & 0xFF) << 16
|
|
303
|
+
value |= (self._data[index + 2] & 0xFF) << 8
|
|
304
|
+
value |= (self._data[index + 3] & 0xFF)
|
|
305
|
+
value = value % 2 ** 32
|
|
306
|
+
return value
|
|
307
|
+
|
|
308
|
+
def getFloat(self):
|
|
309
|
+
tmp = bytearray(4)
|
|
310
|
+
self.get(tmp)
|
|
311
|
+
# Swap bytes.
|
|
312
|
+
tmp2 = tmp[0]
|
|
313
|
+
tmp[0] = tmp[3]
|
|
314
|
+
tmp[3] = tmp2
|
|
315
|
+
tmp2 = tmp[1]
|
|
316
|
+
tmp[1] = tmp[2]
|
|
317
|
+
tmp[2] = tmp2
|
|
318
|
+
return struct.unpack("f", tmp)[0]
|
|
319
|
+
|
|
320
|
+
def getDouble(self):
|
|
321
|
+
tmp = bytearray(8)
|
|
322
|
+
self.get(tmp)
|
|
323
|
+
# Swap bytes.
|
|
324
|
+
tmp2 = tmp[0]
|
|
325
|
+
tmp[0] = tmp[7]
|
|
326
|
+
tmp[7] = tmp2
|
|
327
|
+
tmp2 = tmp[1]
|
|
328
|
+
tmp[1] = tmp[6]
|
|
329
|
+
tmp[6] = tmp2
|
|
330
|
+
tmp2 = tmp[2]
|
|
331
|
+
tmp[2] = tmp[5]
|
|
332
|
+
tmp[5] = tmp2
|
|
333
|
+
tmp2 = tmp[3]
|
|
334
|
+
tmp[3] = tmp[4]
|
|
335
|
+
tmp[4] = tmp2
|
|
336
|
+
return struct.unpack("d", tmp)[0]
|
|
337
|
+
|
|
338
|
+
def getInt64(self, index=None):
|
|
339
|
+
if index is None:
|
|
340
|
+
index = self.position
|
|
341
|
+
self.position += 8
|
|
342
|
+
value = ((self._data[index] & 0xFF)) << 56
|
|
343
|
+
value |= ((self._data[index + 1] & 0xFF)) << 48
|
|
344
|
+
value |= ((self._data[index + 2] & 0xFF)) << 40
|
|
345
|
+
value |= ((self._data[index + 3] & 0xFF)) << 32
|
|
346
|
+
value |= ((self._data[index + 4] & 0xFF)) << 24
|
|
347
|
+
value |= (self._data[index + 5] & 0xFF) << 16
|
|
348
|
+
value |= (self._data[index + 6] & 0xFF) << 8
|
|
349
|
+
value |= (self._data[index + 7] & 0xFF)
|
|
350
|
+
value = (value + 2 ** 63) % 2 ** 64 - 2 ** 63
|
|
351
|
+
return value
|
|
352
|
+
|
|
353
|
+
def getUInt64(self, index=None):
|
|
354
|
+
value = self.getInt64(index)
|
|
355
|
+
return value % 2 ** 64
|
|
356
|
+
|
|
357
|
+
#
|
|
358
|
+
# Check is byte buffer ASCII string.
|
|
359
|
+
#
|
|
360
|
+
# @param value
|
|
361
|
+
# Byte array.
|
|
362
|
+
# Is ASCII string.
|
|
363
|
+
#
|
|
364
|
+
@classmethod
|
|
365
|
+
def isAsciiString(cls, value):
|
|
366
|
+
# pylint: disable=too-many-boolean-expressions
|
|
367
|
+
if value:
|
|
368
|
+
for it in value:
|
|
369
|
+
if (it < 32 or it > 127) and it != '\r' and it != '\n' and it != '\t' and it != 0:
|
|
370
|
+
return False
|
|
371
|
+
return True
|
|
372
|
+
|
|
373
|
+
def getString(self, index, count):
|
|
374
|
+
if index is None and count is None:
|
|
375
|
+
tmp = self._data[0:self.size]
|
|
376
|
+
if self.isAsciiString(tmp):
|
|
377
|
+
str_ = tmp.decode("utf-8").rstrip('\x00')
|
|
378
|
+
else:
|
|
379
|
+
str_ = tmp.hex(sep=' ')
|
|
380
|
+
self.position += count
|
|
381
|
+
return str_
|
|
382
|
+
|
|
383
|
+
if index + count > self.size:
|
|
384
|
+
raise ValueError("getString")
|
|
385
|
+
tmp = self._data[index:index + count]
|
|
386
|
+
if self.isAsciiString(tmp):
|
|
387
|
+
return tmp.decode("utf-8").rstrip('\x00')
|
|
388
|
+
return tmp.hex(sep=' ')
|
|
389
|
+
|
|
390
|
+
def set(self, value, index=None, count=None):
|
|
391
|
+
if isinstance(value, str):
|
|
392
|
+
value = value.encode()
|
|
393
|
+
if value:
|
|
394
|
+
if index is None:
|
|
395
|
+
if isinstance(value, GXByteBuffer):
|
|
396
|
+
index = value.position
|
|
397
|
+
else:
|
|
398
|
+
index = 0
|
|
399
|
+
if count is None:
|
|
400
|
+
count = len(value) - index
|
|
401
|
+
if isinstance(value, GXByteBuffer):
|
|
402
|
+
self.set(value._data, index, count)
|
|
403
|
+
value.position = index + count
|
|
404
|
+
elif value and count != 0:
|
|
405
|
+
if self.size + count > self.capacity:
|
|
406
|
+
self.capacity = self.size + count + self.__ARRAY_CAPACITY
|
|
407
|
+
self._data[self.size:self.size + count] = value[index:index + count]
|
|
408
|
+
self.size += count
|
|
409
|
+
|
|
410
|
+
def get(self, target):
|
|
411
|
+
len1 = len(target)
|
|
412
|
+
if self.size - self.position < len1:
|
|
413
|
+
raise ValueError("get")
|
|
414
|
+
index = 0
|
|
415
|
+
for index in range(0, len1):
|
|
416
|
+
target[index] = self._data[self.position]
|
|
417
|
+
self.position = self.position + 1
|
|
418
|
+
|
|
419
|
+
#
|
|
420
|
+
# Compares, whether two given arrays are similar starting from current
|
|
421
|
+
# position.
|
|
422
|
+
#
|
|
423
|
+
# @param arr
|
|
424
|
+
# Array to compare.
|
|
425
|
+
# True, if arrays are similar. False, if the arrays differ.
|
|
426
|
+
#
|
|
427
|
+
def compare(self, arr):
|
|
428
|
+
len1 = len(arr)
|
|
429
|
+
if not arr or (self.size - self.position < len1):
|
|
430
|
+
return False
|
|
431
|
+
bytes_ = bytearray(len1)
|
|
432
|
+
self.get(bytes_)
|
|
433
|
+
ret = arr == bytes_
|
|
434
|
+
if not ret:
|
|
435
|
+
self.position -= len1
|
|
436
|
+
return ret
|
|
437
|
+
|
|
438
|
+
#
|
|
439
|
+
# Reverses the order of the given array.
|
|
440
|
+
#
|
|
441
|
+
def reverse(self):
|
|
442
|
+
first = self.position
|
|
443
|
+
last = self.size - 1
|
|
444
|
+
tmp = int()
|
|
445
|
+
while last > first:
|
|
446
|
+
tmp = self._data[last]
|
|
447
|
+
self._data[last] = self._data[first]
|
|
448
|
+
self._data[first] = tmp
|
|
449
|
+
last -= 1
|
|
450
|
+
first += 1
|
|
451
|
+
|
|
452
|
+
#
|
|
453
|
+
# Push the given hex string as byte array into this buffer at the
|
|
454
|
+
# current
|
|
455
|
+
# position, and then increments the position.
|
|
456
|
+
#
|
|
457
|
+
# @param value
|
|
458
|
+
# Byte array to add.
|
|
459
|
+
# @param index
|
|
460
|
+
# Byte index.
|
|
461
|
+
# @param count
|
|
462
|
+
# Byte count.
|
|
463
|
+
#
|
|
464
|
+
def setHexString(self, value, index=0, count=None):
|
|
465
|
+
tmp = self.hexToBytes(value)
|
|
466
|
+
if count is None:
|
|
467
|
+
count = len(tmp)
|
|
468
|
+
self.set(tmp, index, count)
|
|
469
|
+
|
|
470
|
+
def __str__(self):
|
|
471
|
+
return self._data[:self.size].hex(sep=' ')
|
|
472
|
+
|
|
473
|
+
#
|
|
474
|
+
# Get remaining data.
|
|
475
|
+
#
|
|
476
|
+
# Remaining data as byte array.
|
|
477
|
+
#
|
|
478
|
+
def remaining(self):
|
|
479
|
+
return self.subArray(self.position, self.size - self.position)
|
|
480
|
+
|
|
481
|
+
#
|
|
482
|
+
# Get remaining data as a hex string.
|
|
483
|
+
#
|
|
484
|
+
# @param addSpace
|
|
485
|
+
# Add space between bytes.
|
|
486
|
+
# Remaining data as a hex string.
|
|
487
|
+
#
|
|
488
|
+
def remainingHexString(self, addSpace=True):
|
|
489
|
+
return self.hex(self._data, addSpace, self.position, self.size - self.position)
|
|
490
|
+
|
|
491
|
+
#
|
|
492
|
+
# Get data as hex string.
|
|
493
|
+
#
|
|
494
|
+
# @param addSpace
|
|
495
|
+
# Add space between bytes.
|
|
496
|
+
# @param index
|
|
497
|
+
# Byte index.
|
|
498
|
+
# @param count
|
|
499
|
+
# Byte count.
|
|
500
|
+
# Data as hex string.
|
|
501
|
+
#
|
|
502
|
+
def toHex(self, addSpace=True, index=0, count=None):
|
|
503
|
+
if count is None:
|
|
504
|
+
count = len(self) - index
|
|
505
|
+
return self.hex(self._data, addSpace, index, count)
|
|
506
|
+
|
|
507
|
+
#Convert char hex value to byte value.
|
|
508
|
+
@classmethod
|
|
509
|
+
def ___getValue(cls, c):
|
|
510
|
+
#Id char.
|
|
511
|
+
if c.islower():
|
|
512
|
+
c = c.upper()
|
|
513
|
+
pos = GXByteBuffer.__HEX_ARRAY.find(c)
|
|
514
|
+
if pos == -1:
|
|
515
|
+
raise Exception("Invalid hex string")
|
|
516
|
+
return pos
|
|
517
|
+
|
|
518
|
+
@classmethod
|
|
519
|
+
def hexToBytes(cls, value):
|
|
520
|
+
"""Convert string to byte array.
|
|
521
|
+
value: Hex string.
|
|
522
|
+
Returns byte array.
|
|
523
|
+
"""
|
|
524
|
+
buff = bytearray()
|
|
525
|
+
if value:
|
|
526
|
+
lastValue = -1
|
|
527
|
+
for ch in value:
|
|
528
|
+
if ch != ' ':
|
|
529
|
+
if lastValue == -1:
|
|
530
|
+
lastValue = cls.___getValue(ch)
|
|
531
|
+
elif lastValue != -1:
|
|
532
|
+
buff.append(lastValue << GXByteBuffer.__NIBBLE | cls.___getValue(ch))
|
|
533
|
+
lastValue = -1
|
|
534
|
+
elif lastValue != -1:
|
|
535
|
+
buff.append(cls.___getValue(ch))
|
|
536
|
+
lastValue = -1
|
|
537
|
+
return buff
|
|
538
|
+
|
|
539
|
+
@classmethod
|
|
540
|
+
def hex(cls, value, addSpace=True, index=0, count=None):
|
|
541
|
+
""" Convert byte array to hex string. """
|
|
542
|
+
return value[index:count].hex(sep=' ' if addSpace else '')
|
|
543
|
+
|
|
544
|
+
def get_data(self) -> bytes:
|
|
545
|
+
return bytes(self._data)[:self.size]
|