protobin 0.0.38__tar.gz → 0.0.40__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.4
2
2
  Name: protobin
3
- Version: 0.0.38
3
+ Version: 0.0.40
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
@@ -21,7 +21,7 @@ class InputError(BaseError):
21
21
  pass
22
22
 
23
23
 
24
- class ParserError(BaseError):
24
+ class DecodeError(BaseError):
25
25
  pass
26
26
 
27
27
 
@@ -3,7 +3,7 @@ import datetime
3
3
  import math
4
4
  from typing import Union, List
5
5
 
6
- from protobin.errors import ParserError, FormatError
6
+ from protobin.errors import DecodeError, FormatError
7
7
 
8
8
 
9
9
  # removed for python 3.8
@@ -50,7 +50,7 @@ class FieldBase:
50
50
  def ensure_length(self, binary):
51
51
  if self.bytes:
52
52
  if len(binary) < self.bytes:
53
- raise ParserError(f'Binary has not enough data for {self}')
53
+ raise DecodeError(f'Binary has not enough data for {self}')
54
54
 
55
55
  def from_binary(self, binary):
56
56
  raise NotImplementedError()
@@ -398,7 +398,10 @@ class StringField(FieldBase):
398
398
  return f'StringField<key: {self.key}, bytes: {self.bytes}>'
399
399
 
400
400
  def from_binary(self, binary):
401
- return binary.decode('utf')
401
+ try:
402
+ return binary.decode('utf')
403
+ except UnicodeEncodeError:
404
+ raise DecodeError(f"Can't decode string: {binary}")
402
405
 
403
406
  def split(self, binary):
404
407
  if self.bytes:
@@ -460,7 +463,7 @@ class TimestampField(FieldBase):
460
463
 
461
464
  def __init__(self, k, js):
462
465
  super().__init__(k, js)
463
- self.bytes = 8
466
+ self.bytes = js.get('bytes', 6)
464
467
  self.decimals = js.get('decimals', 6)
465
468
 
466
469
  def __repr__(self):
@@ -472,7 +475,7 @@ class TimestampField(FieldBase):
472
475
  if val is None:
473
476
  return bytes([0] * 8)
474
477
  timestamp = val.timestamp() * (10 ** self.decimals)
475
- return int(timestamp).to_bytes(8, 'big', signed=False)
478
+ return int(timestamp).to_bytes(self.bytes, 'big', signed=False)
476
479
 
477
480
  def from_binary(self, binary):
478
481
  d = int.from_bytes(binary, 'big')
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "protobin"
7
- version = "0.0.38"
7
+ version = "0.0.40"
8
8
  authors = [
9
9
  { name="Daniel Robles", email="drm.electronic@gmail.com" },
10
10
  ]
@@ -14,7 +14,7 @@
14
14
  "crc_size": 2,
15
15
  "header": "P",
16
16
  "fields": {
17
- "bus_number": {"type": "string"},
17
+ "padron": {"type": "string"},
18
18
  "company": {"type": "string"},
19
19
  "route": {"type": "string"}
20
20
  }
@@ -64,6 +64,16 @@
64
64
  "id": {"type": "string"},
65
65
  "value": {"type": "string"}
66
66
  }
67
+ },
68
+ "timestamp": {
69
+ "header": "#T",
70
+ "server": {
71
+ "faltantes": {"bytes": 4, "type": "unsigned"},
72
+ "tabla": {"bytes": 1, "type": "char"}
73
+ },
74
+ "client": {
75
+ "timestamp":{"bytes": 6, "decimals": 3, "type": "timestamp"}
76
+ }
67
77
  }
68
78
  }
69
79
  }
@@ -14,7 +14,7 @@
14
14
  "crc_size": 2,
15
15
  "header": "P",
16
16
  "fields": {
17
- "bus_number": {"type": "string"},
17
+ "padron": {"type": "string"},
18
18
  "company": {"type": "string"},
19
19
  "route": {"type": "string"}
20
20
  }
@@ -139,6 +139,14 @@
139
139
  "datero_dif_5": {"type": "unsigned", "bytes": 1}
140
140
  }
141
141
  },
142
+ "message": {
143
+ "crc": false,
144
+ "crc_size": 2,
145
+ "header": "M",
146
+ "fields": {
147
+ "text": {"type": "string"}
148
+ }
149
+ },
142
150
  "command": {
143
151
  "codec": 12,
144
152
  "fields": {
@@ -134,6 +134,10 @@ class BasicTest(unittest.TestCase):
134
134
  "header": "TS",
135
135
  "fields": {'test': {'bytes': 8, 'type': 'timestamp'}}
136
136
  },
137
+ 'timestamp6': {
138
+ "header": "T6",
139
+ "fields": {'test': {'bytes': 6, "decimals": 3, 'type': 'timestamp'}}
140
+ },
137
141
  'unsigned': {
138
142
  "header": "u",
139
143
  "fields": {'test': {'bytes': 3, 'type': 'unsigned'}}
@@ -290,6 +294,31 @@ class BasicTest(unittest.TestCase):
290
294
  with self.assertRaises(ValueError) as er:
291
295
  self.protocol.encode(data, 'unsigned')
292
296
 
297
+ protocol = Protocol(js={'formats': {
298
+ 'unsigned': {
299
+ "header": "u",
300
+ "fields": {
301
+ "geofence": {"bytes": 2, "type": "unsigned"},
302
+ "orden": {"bytes": 1, "type": "unsigned"},
303
+ "delta": {"bytes": 1, "type": "unsigned"},
304
+ "origin": {"bytes": 2, "type": "unsigned"},
305
+ "id": {"bytes": 0, "type": "string"}
306
+ }
307
+ }
308
+ }})
309
+ data = {
310
+ "id": "11",
311
+ "orden": 0,
312
+ "origin": 57,
313
+ "delta": 5,
314
+ "geofence": 200
315
+ }
316
+ binary = protocol.encode(data, 'unsigned')
317
+ print(binary)
318
+ h, recv = protocol.decode(binary)
319
+ print(recv)
320
+ self.assertEqual(data, recv)
321
+
293
322
  def test_id(self):
294
323
  data = {'test': 254}
295
324
  binary = self.protocol.encode(data, 'id')
@@ -318,6 +347,13 @@ class BasicTest(unittest.TestCase):
318
347
  h, recv = self.protocol.decode(binary)
319
348
  self.assertEqual(data, recv)
320
349
 
350
+ def test_timestamp6(self):
351
+ data = {'test': datetime.datetime(2025, 1, 24, 9, 18, 24, 896000)}
352
+ binary = self.protocol.encode(data, 'timestamp6')
353
+ print(binary)
354
+ h, recv = self.protocol.decode(binary)
355
+ self.assertEqual(data, recv)
356
+
321
357
  def test_timestamp_null(self):
322
358
  data = {'test': None}
323
359
  binary = self.protocol.encode(data, 'timestamp')
@@ -635,7 +671,7 @@ report:
635
671
  data = {'status': 'E', 'direction': 'A', 'next_next_control': '', 'next_next_time': ' ', 'next_control': '', 'next_time': ' ', 'previous_control': '', 'delay': 0, 'front_control': '', 'back_control': '', 'back_back_control': '', 'datero_bus_-1': 0, 'datero_dif_-1': 0, 'datero_bus_0': 0, 'datero_dif_0': 0, 'datero_bus_1': 0, 'datero_dif_1': 0, 'datero_bus_2': 0, 'datero_dif_2': 0, 'datero_bus_3': 256, 'datero_dif_3': 0, 'datero_bus_4': 0, 'datero_dif_4': 0, 'datero_bus_5': 0, 'datero_dif_5': 0}
636
672
  client = Protocol(file='codec8.json')
637
673
  binary = client.encode(data, 'status3')
638
- self.assertEqual(b's=EA\x00 \x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb6\xd6', binary)
674
+ self.assertEqual(b's=EA\x00 \x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\xb6\xd6', binary)
639
675
  header, recv = client.decode(binary)
640
676
  self.assertEqual(data, recv)
641
677
 
@@ -723,7 +759,21 @@ report:
723
759
 
724
760
  def test_teltonika_login(self):
725
761
  client = Protocol(file='codec8.json', server=None)
726
- data = {'bus_number': '110', 'company': 'roma', 'route': 'IO37'}
762
+ data = {'padron': '110', 'company': 'roma', 'route': 'IO37'}
727
763
  binary = client.encode(data, 'login_status')
728
764
  print(binary)
729
765
  self.assertEqual(b'P=\x03110\x04roma\x04IO37\x19\x8f', binary)
766
+
767
+ def test_teltonika_login_urbanito(self):
768
+ client = Protocol(file='codec8.json', server=None)
769
+ data = {'company': 'urbanito', 'route': '9802'}
770
+ binary = client.encode(data, 'login_status')
771
+ print(binary)
772
+ self.assertEqual(b'P=\x00\x08urbanito\x049802+\xbf', binary)
773
+
774
+ def test_message_teltonika(self):
775
+ data = {'text': 'prueba de mensaje'}
776
+ client = Protocol(file='teltonika.json', server=None)
777
+ binary = client.encode(data, 'message')
778
+ print(binary)
779
+ self.assertEqual(binary, b'M=\x11prueba de mensaje48')
File without changes
File without changes
File without changes
File without changes