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.
Files changed (60) hide show
  1. DLMS_SPODES_client/FCS16.py +39 -39
  2. DLMS_SPODES_client/__init__.py +12 -12
  3. DLMS_SPODES_client/client.py +2093 -2093
  4. DLMS_SPODES_client/gurux_common/enums/TraceLevel.py +21 -21
  5. DLMS_SPODES_client/gurux_dlms/AesGcmParameter.py +37 -37
  6. DLMS_SPODES_client/gurux_dlms/CountType.py +16 -16
  7. DLMS_SPODES_client/gurux_dlms/GXByteBuffer.py +545 -545
  8. DLMS_SPODES_client/gurux_dlms/GXCiphering.py +196 -196
  9. DLMS_SPODES_client/gurux_dlms/GXDLMS.py +426 -426
  10. DLMS_SPODES_client/gurux_dlms/GXDLMSChippering.py +237 -237
  11. DLMS_SPODES_client/gurux_dlms/GXDLMSChipperingStream.py +977 -977
  12. DLMS_SPODES_client/gurux_dlms/GXDLMSConfirmedServiceError.py +90 -90
  13. DLMS_SPODES_client/gurux_dlms/GXDLMSException.py +139 -139
  14. DLMS_SPODES_client/gurux_dlms/GXDLMSLNParameters.py +33 -33
  15. DLMS_SPODES_client/gurux_dlms/GXDLMSSNParameters.py +21 -21
  16. DLMS_SPODES_client/gurux_dlms/GXDLMSSettings.py +254 -254
  17. DLMS_SPODES_client/gurux_dlms/GXReplyData.py +87 -87
  18. DLMS_SPODES_client/gurux_dlms/HdlcControlFrame.py +9 -9
  19. DLMS_SPODES_client/gurux_dlms/MBusCommand.py +8 -8
  20. DLMS_SPODES_client/gurux_dlms/MBusEncryptionMode.py +27 -27
  21. DLMS_SPODES_client/gurux_dlms/ResponseType.py +8 -8
  22. DLMS_SPODES_client/gurux_dlms/SetResponseType.py +29 -29
  23. DLMS_SPODES_client/gurux_dlms/_HDLCInfo.py +9 -9
  24. DLMS_SPODES_client/gurux_dlms/__init__.py +75 -75
  25. DLMS_SPODES_client/gurux_dlms/enums/Access.py +12 -12
  26. DLMS_SPODES_client/gurux_dlms/enums/ApplicationReference.py +14 -14
  27. DLMS_SPODES_client/gurux_dlms/enums/Authentication.py +41 -41
  28. DLMS_SPODES_client/gurux_dlms/enums/BerType.py +35 -35
  29. DLMS_SPODES_client/gurux_dlms/enums/Command.py +285 -285
  30. DLMS_SPODES_client/gurux_dlms/enums/Definition.py +9 -9
  31. DLMS_SPODES_client/gurux_dlms/enums/ErrorCode.py +46 -46
  32. DLMS_SPODES_client/gurux_dlms/enums/ExceptionServiceError.py +12 -12
  33. DLMS_SPODES_client/gurux_dlms/enums/HardwareResource.py +10 -10
  34. DLMS_SPODES_client/gurux_dlms/enums/HdlcFrameType.py +9 -9
  35. DLMS_SPODES_client/gurux_dlms/enums/Initiate.py +10 -10
  36. DLMS_SPODES_client/gurux_dlms/enums/LoadDataSet.py +13 -13
  37. DLMS_SPODES_client/gurux_dlms/enums/ObjectType.py +306 -306
  38. DLMS_SPODES_client/gurux_dlms/enums/Priority.py +7 -7
  39. DLMS_SPODES_client/gurux_dlms/enums/RequestTypes.py +9 -9
  40. DLMS_SPODES_client/gurux_dlms/enums/Security.py +14 -14
  41. DLMS_SPODES_client/gurux_dlms/enums/Service.py +16 -16
  42. DLMS_SPODES_client/gurux_dlms/enums/ServiceClass.py +9 -9
  43. DLMS_SPODES_client/gurux_dlms/enums/ServiceError.py +8 -8
  44. DLMS_SPODES_client/gurux_dlms/enums/Standard.py +18 -18
  45. DLMS_SPODES_client/gurux_dlms/enums/StateError.py +7 -7
  46. DLMS_SPODES_client/gurux_dlms/enums/Task.py +10 -10
  47. DLMS_SPODES_client/gurux_dlms/enums/VdeStateError.py +10 -10
  48. DLMS_SPODES_client/gurux_dlms/enums/__init__.py +33 -33
  49. DLMS_SPODES_client/gurux_dlms/internal/_GXCommon.py +1673 -1673
  50. DLMS_SPODES_client/logger.py +56 -56
  51. DLMS_SPODES_client/services.py +90 -90
  52. DLMS_SPODES_client/session.py +363 -363
  53. DLMS_SPODES_client/settings.py +48 -48
  54. DLMS_SPODES_client/task.py +1884 -1884
  55. {dlms_spodes_client-0.19.35.dist-info → dlms_spodes_client-0.19.37.dist-info}/METADATA +29 -29
  56. dlms_spodes_client-0.19.37.dist-info/RECORD +61 -0
  57. {dlms_spodes_client-0.19.35.dist-info → dlms_spodes_client-0.19.37.dist-info}/WHEEL +1 -1
  58. dlms_spodes_client-0.19.35.dist-info/RECORD +0 -61
  59. {dlms_spodes_client-0.19.35.dist-info → dlms_spodes_client-0.19.37.dist-info}/entry_points.txt +0 -0
  60. {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]