protobin 0.0.24__tar.gz → 0.0.26__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: protobin
3
- Version: 0.0.24
3
+ Version: 0.0.26
4
4
  Summary: Python library for encode and decode data in protobin format
5
5
  Project-URL: Homepage, https://github.com/drmelectronic/protobin-python
6
6
  Project-URL: Bug Tracker, https://github.com/drmelectronic/protobin-python/issues
@@ -6,6 +6,7 @@ from typing import Union, List
6
6
  from protobin.errors import ParserError, FormatError
7
7
 
8
8
 
9
+ # removed for python 3.8
9
10
  # class FieldEnum(enum.StrEnum):
10
11
  # ARRAY = 'array'
11
12
  # BITS = 'bits'
@@ -24,9 +25,10 @@ from protobin.errors import ParserError, FormatError
24
25
 
25
26
 
26
27
  class FieldBase:
27
- bytes: int | None
28
- keys: List[str] | None
29
- key: str
28
+ # removed for python 3.8
29
+ # bytes: int | None
30
+ # keys: List[str] | None
31
+ # key: str
30
32
  # type: FieldEnum
31
33
 
32
34
  def __init__(self, k, js):
@@ -231,7 +233,9 @@ class DateField(FieldBase):
231
233
  def __repr__(self):
232
234
  return f'DateField<key: {self.key}>'
233
235
 
234
- def to_binary(self, val: datetime.datetime | str):
236
+ # removed for python 3.8
237
+ # def to_binary(self, val: datetime.datetime | str):
238
+ def to_binary(self, val):
235
239
  if val is None:
236
240
  return bytes([0] * 3)
237
241
  elif isinstance(val, str):
@@ -260,7 +264,9 @@ class DateTimeField(FieldBase):
260
264
  def __repr__(self):
261
265
  return f'DateTimeField<key: {self.key}>'
262
266
 
263
- def to_binary(self, val: datetime.datetime | str):
267
+ # removed for python 3.8
268
+ # def to_binary(self, val: datetime.datetime | str):
269
+ def to_binary(self, val):
264
270
  if val is None:
265
271
  return bytes([0] * 6)
266
272
  elif not isinstance(val, datetime.datetime):
@@ -420,7 +426,9 @@ class TimeField(FieldBase):
420
426
  def __repr__(self):
421
427
  return f'TimeField<key: {self.key}, bytes: {self.bytes}>'
422
428
 
423
- def to_binary(self, val: datetime.datetime | datetime.time | str):
429
+ # removed for python 3.8
430
+ # def to_binary(self, val: datetime.datetime | datetime.time | str):
431
+ def to_binary(self, val):
424
432
  if val is None:
425
433
  return bytes([0] * 2)
426
434
  elif isinstance(val, str):
@@ -455,7 +463,9 @@ class TimestampField(FieldBase):
455
463
  def __repr__(self):
456
464
  return f'TimestampField<key: {self.key}>'
457
465
 
458
- def to_binary(self, val: datetime.datetime | str):
466
+ # removed for python 3.8
467
+ # def to_binary(self, val: datetime.datetime | str):
468
+ def to_binary(self, val):
459
469
  if val is None:
460
470
  return bytes([0] * 8)
461
471
  timestamp = val.timestamp() * (10 ** self.decimals)
@@ -42,7 +42,9 @@ class Format:
42
42
  if self.header:
43
43
  binary += self.header.encode('utf') + b'='
44
44
  elif self.codec:
45
- binary += self.codec.to_bytes()
45
+ # added for python 3.8
46
+ # binary += self.codec.to_bytes()
47
+ binary += self.codec.to_bytes(1, 'big')
46
48
  for f in self.output_fields:
47
49
  binary += f.encode(data)
48
50
  return binary
@@ -99,7 +101,9 @@ class Protocol:
99
101
  return self.formats[self.headers[h.decode('utf')]]
100
102
 
101
103
  def get_codec(self, h):
102
- return self.formats[self.codecs[int.from_bytes(h)]]
104
+ # added for python 3.8
105
+ # return self.formats[self.codecs[int.from_bytes(h)]]
106
+ return self.formats[self.codecs[int.from_bytes(h, 'big')]]
103
107
 
104
108
  def encode(self, data, format_key):
105
109
  if format_key not in self.formats:
@@ -110,21 +114,30 @@ class Protocol:
110
114
  binary = len(binary).to_bytes(self.length, 'big', signed=False) + binary + self.get_crc(binary)
111
115
  return binary
112
116
 
113
- def decode(self, binary, codec=None):
114
- if codec is None:
115
- n = binary.find(b'=')
116
- if n == -1:
117
+ def get_header(self, binary):
118
+ n = binary.find(b'=')
119
+ if n == -1:
120
+ binary = self.check_crc(binary)
121
+ h = binary[:1]
122
+ binary = binary[1:]
123
+ format = self.get_codec(h)
124
+ else:
125
+ if n > 4:
117
126
  binary = self.check_crc(binary)
118
- h = binary[:1]
119
- binary = binary[1:]
120
- format = self.get_codec(h)
121
- else:
127
+ n = binary.find(b'=')
122
128
  if n > 4:
123
- binary = self.check_crc(binary)
124
- n = binary.find(b'=')
125
- h = binary[0:n]
126
- binary = binary[n + 1:]
127
- format = self.get_format(h)
129
+ h = binary[:1]
130
+ binary = binary[1:]
131
+ format = self.get_codec(h)
132
+ return format, binary
133
+ h = binary[0:n]
134
+ binary = binary[n + 1:]
135
+ format = self.get_format(h)
136
+ return format, binary
137
+
138
+ def decode(self, binary, codec=None):
139
+ if codec is None:
140
+ format, binary = self.get_header(binary)
128
141
  else:
129
142
  format = self.formats[codec]
130
143
  if format.crc and self.crc16:
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "protobin"
7
- version = "0.0.24"
7
+ version = "0.0.26"
8
8
  authors = [
9
9
  { name="Daniel Robles", email="drm.electronic@gmail.com" },
10
10
  ]
@@ -45,9 +45,9 @@
45
45
  "events8b": {"type": "array", "array": {
46
46
  "id": {"type": "id", "bytes": 1},
47
47
  "value": {"type": "unsigned", "bytes": 8}
48
- }},
49
- "#reports": {"type": "unsigned", "bytes": 1}
50
- }}
48
+ }}
49
+ }},
50
+ "#reports": {"type": "unsigned", "bytes": 1}
51
51
  }
52
52
  },
53
53
  "status3": {
@@ -563,7 +563,6 @@ report:
563
563
  header, recv = server.decode(binary)
564
564
  self.assertEqual(recv, data)
565
565
 
566
-
567
566
  def test_teltonika_position_hex(self):
568
567
  hexdata = '000000000000003608010000016B40D8EA30010000000000000000000000000000000105021503010101425E0F01F10000601A014E0000000000000000010000C7CF'
569
568
  binary = bytes.fromhex(hexdata)
@@ -571,31 +570,32 @@ report:
571
570
  header, recv = client.decode(binary)
572
571
  self.assertEqual(recv, {
573
572
  'positions': [{
574
- 'time': datetime.datetime(2019, 6, 10, 5, 4, 46),
575
- 'priority': 1,
576
- 'lng': 0.0,
577
- 'lat': 0.0,
578
- 'alt': 0,
579
- 'angle': 0,
580
- 'satellites': 0,
581
- 'speed': 0,
582
- 'event_io': 1,
583
- '#events': 5,
584
- 'events1b': [
585
- {'id': 21, 'value': 3},
586
- {'id': 1, 'value': 1}
587
- ],
588
- 'events2b': [
589
- {'id': 66, 'value': 24079}
590
- ],
591
- 'events4b': [
592
- {'id': 241, 'value': 24602}
593
- ],
594
- 'events8b': [
595
- {'id': 78, 'value': 0}
573
+ 'time': datetime.datetime(2019, 6, 10, 5, 4, 46),
574
+ 'priority': 1,
575
+ 'lng': 0.0,
576
+ 'lat': 0.0,
577
+ 'alt': 0,
578
+ 'angle': 0,
579
+ 'satellites': 0,
580
+ 'speed': 0,
581
+ 'event_io': 1,
582
+ '#events': 5,
583
+ 'events1b': [
584
+ {'id': 21, 'value': 3},
585
+ {'id': 1, 'value': 1}
586
+ ],
587
+ 'events2b': [
588
+ {'id': 66, 'value': 24079}
589
+ ],
590
+ 'events4b': [
591
+ {'id': 241, 'value': 24602}
592
+ ],
593
+ 'events8b': [
594
+ {'id': 78, 'value': 0}
595
+ ]}
596
596
  ],
597
- '#reports': 1,
598
- }]})
597
+ '#reports': 1
598
+ })
599
599
 
600
600
  def test_login_keyerror(self):
601
601
  client = Protocol(file='demo.json', server=False)
@@ -612,7 +612,7 @@ report:
612
612
  self.assertEqual(data, recv)
613
613
 
614
614
  def test_crc(self):
615
- data = {'positions': [{'time': datetime.datetime(2024, 10, 19, 9, 37, 57, 555000), 'priority': 1, 'lng': -77.0155334, 'lat': -12.0613651, 'alt': 0, 'angle': 0, 'satellites': 3, 'speed': 105, 'event_io': 0, '#events': 0, 'events1b': [], 'events2b': [], 'events4b': [], 'events8b': [], '#reports': 1}]}
615
+ data = {'positions': [{'time': datetime.datetime(2024, 10, 19, 9, 37, 57, 555000), 'priority': 1, 'lng': -77.0155334, 'lat': -12.0613651, 'alt': 0, 'angle': 0, 'satellites': 3, 'speed': 105, 'event_io': 0, '#events': 0, 'events1b': [], 'events2b': [], 'events4b': [], 'events8b': []}], '#reports': 1}
616
616
  client = Protocol(file='codec8.json')
617
617
  binary = client.encode(data, 'report')
618
618
  self.assertEqual(b'\x00\x00\x00\x00\x00\x00\x00!\x08\x01\x00\x00\x01\x92\xa56\xaf\xb3\x01\xd2\x18\\\xba\xf8\xcf\x94\xed\x00\x00\x00\x00\x03\x00i\x00\x00\x00\x00\x00\x00\x01\x00\x00\xa3\xe4', binary)
@@ -635,3 +635,10 @@ report:
635
635
  data = {'positions': 1}
636
636
  binary = protocol.encode(data, 'report_ack')
637
637
  self.assertEqual(binary, b'\x00\x00\x00\x01')
638
+
639
+ def test_decode_codec8(self):
640
+ # binary = b'\xfe\x0f350424068858891\x00\x00\x01\x06CBF541\x04\x00\x02R\x00\x00\x00\x00\x01\x00\x00\x1e\n\x04\x00)\x11$\x100\x00R\xff\x00\x00\x00\x02'
641
+ binary = b'\x00\x00\x00\x00\x00\x00\x01\x11\x08\t\x00\x00\x01\x93x\xd74\xf0\x00\xd2\x15\x19\xe6\xf8\xc6\xe8\x9e\x00Z\x01b\x0e\x00\r\x00\x00\x00\x00\x00\x00\x00\x00\x01\x93x\xd7_\xe8\x00\xd2\x15\x1b#\xf8\xc6\xfau\x00W\x00\x06\x0f\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x01\x93x\xd7\x86\xf8\x00\xd2\x15\x19\xf7\xf8\xc7\x0c~\x00S\x01e\x10\x00\x14\x00\x00\x00\x00\x00\x00\x00\x00\x01\x93x\xd7\xd5\x18\x00\xd2\x15\x19\xf7\xf8\xc7\x14=\x00U\x00\x02\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x93x\xd8#8\x00\xd2\x15\x19\xf7\xf8\xc7\x14=\x00U\x00\x02\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x93x\xd8qX\x00\xd2\x15\x19\xf7\xf8\xc7\x14=\x00U\x00\x02\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x93x\xd8\xb3\xc0\x00\xd2\x15\x1bU\xf8\xc7%\xe2\x00R\x01g\x10\x00\x19\x00\x00\x00\x00\x00\x00\x00\x00\x01\x93x\xd8\xcf\x18\x00\xd2\x15\x1a\xe0\xf8\xc79\x8b\x00T\x01g\x0f\x00\x17\x00\x00\x00\x00\x00\x00\x00\x00\x01\x93x\xd8\xeeX\x00\xd2\x15\x1al\xf8\xc7K\x1f\x00Y\x00\x01\x0e\x00\x17\x00\x00\x00\x00\x00\x00\t\x00\x00\x13x'
642
+ client = Protocol(file='codec8.json')
643
+ header, recv = client.decode(binary)
644
+ print(header, recv)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes