protobin 0.0.3__tar.gz → 0.0.5__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.
- {protobin-0.0.3 → protobin-0.0.5}/PKG-INFO +1 -1
- {protobin-0.0.3 → protobin-0.0.5}/protobin/fields.py +23 -19
- {protobin-0.0.3 → protobin-0.0.5}/pyproject.toml +1 -1
- {protobin-0.0.3 → protobin-0.0.5}/tests/demo.json +7 -7
- {protobin-0.0.3 → protobin-0.0.5}/tests/tests.py +30 -7
- {protobin-0.0.3 → protobin-0.0.5}/.gitignore +0 -0
- {protobin-0.0.3 → protobin-0.0.5}/LICENSE.txt +0 -0
- {protobin-0.0.3 → protobin-0.0.5}/README.md +0 -0
- {protobin-0.0.3 → protobin-0.0.5}/protobin/__init__.py +0 -0
- {protobin-0.0.3 → protobin-0.0.5}/protobin/errors.py +0 -0
- {protobin-0.0.3 → protobin-0.0.5}/protobin/protocol.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: protobin
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.5
|
|
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
|
|
@@ -75,8 +75,7 @@ class FieldBase:
|
|
|
75
75
|
def split(self, binary):
|
|
76
76
|
if self.bytes:
|
|
77
77
|
return binary[:self.bytes], binary[self.bytes:]
|
|
78
|
-
|
|
79
|
-
return binary[1:self.bytes + 1], binary[self.bytes + 1:]
|
|
78
|
+
return binary[1:binary[0] + 1], binary[binary[0] + 1:]
|
|
80
79
|
|
|
81
80
|
def to_dict(self):
|
|
82
81
|
return {
|
|
@@ -134,11 +133,18 @@ class FieldBits(FieldBase):
|
|
|
134
133
|
self.length = js.get('length', 0)
|
|
135
134
|
self.bytes = math.ceil(self.length / 8)
|
|
136
135
|
|
|
136
|
+
def decode(self, binary):
|
|
137
|
+
self.ensure_length(binary)
|
|
138
|
+
a, b, length = self.split(binary)
|
|
139
|
+
val = self.from_binary_bits(a, length)
|
|
140
|
+
return val, b
|
|
141
|
+
|
|
137
142
|
def split(self, binary):
|
|
138
|
-
if
|
|
139
|
-
self.
|
|
140
|
-
|
|
141
|
-
|
|
143
|
+
if self.length:
|
|
144
|
+
return binary[:self.bytes], binary[self.bytes:], self.length
|
|
145
|
+
length = binary[0]
|
|
146
|
+
bts = math.ceil(length / 8)
|
|
147
|
+
return binary[1:bts + 1], binary[bts + 1:], length
|
|
142
148
|
|
|
143
149
|
def to_binary(self, val: List[bool]):
|
|
144
150
|
if len(val) == 0:
|
|
@@ -150,18 +156,19 @@ class FieldBits(FieldBase):
|
|
|
150
156
|
bits = ''
|
|
151
157
|
for b in val:
|
|
152
158
|
bits += '1' if b else '0'
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
159
|
+
bts = int(len(bits) / 8)
|
|
160
|
+
if not self.length:
|
|
161
|
+
binary += len(val).to_bytes(1, 'big', signed=False)
|
|
162
|
+
binary += int(bits, 2).to_bytes(bts, 'big', signed=False)
|
|
156
163
|
return binary
|
|
157
164
|
|
|
158
|
-
def
|
|
165
|
+
def from_binary_bits(self, binary, length):
|
|
159
166
|
numero = int.from_bytes(binary, 'big', signed=False)
|
|
160
167
|
bits = bin(numero)[2:]
|
|
161
168
|
val = [False] * 8
|
|
162
169
|
for b in bits:
|
|
163
170
|
val.append(b == '1')
|
|
164
|
-
val = val[-
|
|
171
|
+
val = val[-length:]
|
|
165
172
|
return val
|
|
166
173
|
|
|
167
174
|
|
|
@@ -274,18 +281,18 @@ class FieldFloat(FieldBase):
|
|
|
274
281
|
|
|
275
282
|
def __init__(self, js):
|
|
276
283
|
super().__init__(js)
|
|
277
|
-
self.
|
|
284
|
+
self.decimals = js['decimals']
|
|
278
285
|
|
|
279
286
|
def from_binary(self, binary):
|
|
280
287
|
val = int.from_bytes(binary[:self.bytes], 'big', signed=True)
|
|
281
|
-
return val / (10 ** self.
|
|
288
|
+
return val / (10 ** self.decimals)
|
|
282
289
|
|
|
283
290
|
def to_binary(self, val):
|
|
284
|
-
return int(round(val * (10 ** self.
|
|
291
|
+
return int(round(val * (10 ** self.decimals))).to_bytes(self.bytes, 'big', signed=True)
|
|
285
292
|
|
|
286
293
|
def to_dict(self):
|
|
287
294
|
d = super().to_dict()
|
|
288
|
-
d['
|
|
295
|
+
d['decimals'] = self.decimals
|
|
289
296
|
return d
|
|
290
297
|
|
|
291
298
|
|
|
@@ -313,10 +320,7 @@ class FieldString(FieldBase):
|
|
|
313
320
|
return len(utf).to_bytes(1, 'big') + utf
|
|
314
321
|
|
|
315
322
|
def from_binary(self, binary):
|
|
316
|
-
|
|
317
|
-
self.bytes = int.from_bytes(binary[:1], 'big', signed=False)
|
|
318
|
-
binary = binary[1:]
|
|
319
|
-
return binary[:self.bytes].decode('utf')
|
|
323
|
+
return binary.decode('utf')
|
|
320
324
|
|
|
321
325
|
|
|
322
326
|
class FieldTime(FieldBase):
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
{"keys": ["activo", "reintegro"], "bytes": 1, "type": "flags"},
|
|
8
8
|
{"keys": ["lunes", "martes", "miercoles", "jueves", "viernes", "sabado", "domingo", "feriado"], "bytes": 1, "type": "flags"},
|
|
9
9
|
{"key": "ruta", "bytes": 2, "type": "unsigned"},
|
|
10
|
-
{"key": "tarifa", "bytes": 2, "type": "float", "
|
|
10
|
+
{"key": "tarifa", "bytes": 2, "type": "float", "decimals": 2},
|
|
11
11
|
{"key": "timestamp", "bytes": 6, "type": "datetime"}
|
|
12
12
|
],
|
|
13
13
|
"command": [
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"geocerca": [
|
|
46
46
|
{"key": "id", "bytes": 2, "type": "unsigned"},
|
|
47
47
|
{"key": "orden", "bytes": 1, "type": "unsigned"},
|
|
48
|
-
{"key": "longitud", "bytes": 4, "type": "float", "
|
|
49
|
-
{"key": "latitud", "bytes": 4, "type": "float", "
|
|
48
|
+
{"key": "longitud", "bytes": 4, "type": "float", "decimals": 6},
|
|
49
|
+
{"key": "latitud", "bytes": 4, "type": "float", "decimals": 6},
|
|
50
50
|
{"key": "radio", "bytes": 2, "type": "unsigned"},
|
|
51
51
|
{"key": "ruta", "bytes": 1, "type": "unsigned"},
|
|
52
52
|
{"keys": ["lado", "control", "datear", "activo"], "bytes": 1, "type": "flags"},
|
|
@@ -146,8 +146,8 @@
|
|
|
146
146
|
"busstop": [
|
|
147
147
|
{"key": "id", "bytes": 2, "type": "unsigned"},
|
|
148
148
|
{"key": "orden", "bytes": 1, "type": "unsigned"},
|
|
149
|
-
{"key": "longitud", "bytes": 4, "type": "float", "
|
|
150
|
-
{"key": "latitud", "bytes": 4, "type": "float", "
|
|
149
|
+
{"key": "longitud", "bytes": 4, "type": "float", "decimals": 6},
|
|
150
|
+
{"key": "latitud", "bytes": 4, "type": "float", "decimals": 6},
|
|
151
151
|
{"key": "radio", "bytes": 2, "type": "unsigned"},
|
|
152
152
|
{"key": "ruta", "bytes": 1, "type": "unsigned"},
|
|
153
153
|
{"keys": ["liquidar", "lado", "terminal", "activo"], "bytes": 1, "type": "flags"},
|
|
@@ -167,8 +167,8 @@
|
|
|
167
167
|
"report": [
|
|
168
168
|
{"key": "positions", "bytes": 19, "type": "array", "array": [
|
|
169
169
|
{"key": "time", "bytes": 6, "type": "datetime"},
|
|
170
|
-
{"key": "lng", "bytes": 4, "type": "float", "
|
|
171
|
-
{"key": "lat", "bytes": 4, "type": "float", "
|
|
170
|
+
{"key": "lng", "bytes": 4, "type": "float", "decimals": 6},
|
|
171
|
+
{"key": "lat", "bytes": 4, "type": "float", "decimals": 6},
|
|
172
172
|
{"key": "speed", "bytes": 1, "type": "unsigned"},
|
|
173
173
|
{"key": "mark", "bytes": 2, "type": "unsigned"},
|
|
174
174
|
{"key": "busstop", "bytes": 2, "type": "unsigned"}
|
|
@@ -99,7 +99,7 @@ class FormatTest(unittest.TestCase):
|
|
|
99
99
|
'date': [{'key': 'test', 'bytes': 3, 'type': 'date'}],
|
|
100
100
|
'datetime': [{'key': 'test', 'bytes': 6, 'type': 'datetime'}],
|
|
101
101
|
'flags': [{'keys': ['f1', 'f2', 'f3', 'f4'], 'bytes': 1, 'type': 'flags'}],
|
|
102
|
-
'float': [{'key': 'test', 'bytes': 4, '
|
|
102
|
+
'float': [{'key': 'test', 'bytes': 4, 'decimals': 6, 'type': 'float'}],
|
|
103
103
|
'signed': [{'key': 'test', 'bytes': 2, 'type': 'signed'}],
|
|
104
104
|
'string': [{'key': 'test', 'bytes': 0, 'type': 'string'}],
|
|
105
105
|
'time': [{'key': 'test', 'bytes': 1, 'type': 'time'}],
|
|
@@ -116,12 +116,13 @@ class BasicTest(unittest.TestCase):
|
|
|
116
116
|
{'key': 'test', 'bytes': 0, 'type': 'string'}
|
|
117
117
|
]}],
|
|
118
118
|
'bits': [{'key': 'test', 'type': 'bits'}],
|
|
119
|
+
'bits_fixed': [{'key': 'test', 'type': 'bits', 'length': 7}],
|
|
119
120
|
'bool': [{'key': 'test', 'bytes': 1, 'type': 'bool'}],
|
|
120
121
|
'char': [{'key': 'test', 'bytes': 1, 'type': 'char'}],
|
|
121
122
|
'date': [{'key': 'test', 'bytes': 1, 'type': 'date'}],
|
|
122
123
|
'datetime': [{'key': 'test', 'bytes': 1, 'type': 'datetime'}],
|
|
123
124
|
'flags': [{'keys': ['f1', 'f2', 'f3', 'f4'], 'type': 'flags'}],
|
|
124
|
-
'float': [{'key': 'test', 'bytes': 4, '
|
|
125
|
+
'float': [{'key': 'test', 'bytes': 4, 'decimals': 6, 'type': 'float'}],
|
|
125
126
|
'signed': [{'key': 'test', 'bytes': 2, 'type': 'signed'}],
|
|
126
127
|
'string': [{'key': 'test', 'bytes': 0, 'type': 'string'}],
|
|
127
128
|
'time': [{'key': 'test', 'bytes': 2, 'type': 'time'}],
|
|
@@ -138,14 +139,30 @@ class BasicTest(unittest.TestCase):
|
|
|
138
139
|
binary = self.protocol.encode(data, 'array')
|
|
139
140
|
recv = self.protocol.decode(binary, 'array')
|
|
140
141
|
self.assertEqual(data, recv)
|
|
142
|
+
data = {'test': [
|
|
143
|
+
{'test': 'texto2 de prueba'},
|
|
144
|
+
{'test': 'segunda prueba4'},
|
|
145
|
+
{'test': 'otra más3'},
|
|
146
|
+
{'test': 'y una última'}]
|
|
147
|
+
}
|
|
148
|
+
binary = self.protocol.encode(data, 'array')
|
|
149
|
+
recv = self.protocol.decode(binary, 'array')
|
|
150
|
+
self.assertEqual(data, recv)
|
|
141
151
|
|
|
142
152
|
def test_bits(self):
|
|
143
153
|
data = {'test': [True, False, True, False, False] * 3}
|
|
144
|
-
print('data', data)
|
|
145
154
|
binary = self.protocol.encode(data, 'bits')
|
|
146
|
-
print('binary', binary)
|
|
147
155
|
recv = self.protocol.decode(binary, 'bits')
|
|
148
|
-
|
|
156
|
+
self.assertEqual(data, recv)
|
|
157
|
+
data = {'test': [True, False, True, False, False] * 5}
|
|
158
|
+
binary = self.protocol.encode(data, 'bits')
|
|
159
|
+
recv = self.protocol.decode(binary, 'bits')
|
|
160
|
+
self.assertEqual(data, recv)
|
|
161
|
+
|
|
162
|
+
def test_bits_fixed(self):
|
|
163
|
+
data = {'test': [True, False, True, False, False, True, True]}
|
|
164
|
+
binary = self.protocol.encode(data, 'bits_fixed')
|
|
165
|
+
recv = self.protocol.decode(binary, 'bits_fixed')
|
|
149
166
|
self.assertEqual(data, recv)
|
|
150
167
|
|
|
151
168
|
def test_bool(self):
|
|
@@ -207,6 +224,10 @@ class BasicTest(unittest.TestCase):
|
|
|
207
224
|
binary = self.protocol.encode(data, 'string')
|
|
208
225
|
recv = self.protocol.decode(binary, 'string')
|
|
209
226
|
self.assertEqual(data, recv)
|
|
227
|
+
data = {'test': 'otro texto de prueba más largo'}
|
|
228
|
+
binary = self.protocol.encode(data, 'string')
|
|
229
|
+
recv = self.protocol.decode(binary, 'string')
|
|
230
|
+
self.assertEqual(data, recv)
|
|
210
231
|
|
|
211
232
|
def test_timestamp(self):
|
|
212
233
|
data = {'test': datetime.datetime(2024, 9, 13, 15, 23, 51, 265981)}
|
|
@@ -231,9 +252,11 @@ class AdvancedTest(unittest.TestCase):
|
|
|
231
252
|
]})
|
|
232
253
|
data = {'id': 2, 'nombre': 'Voltaje', 'valor': -20}
|
|
233
254
|
binary = protocol.encode(data, 'medida')
|
|
234
|
-
print('binary', binary)
|
|
235
255
|
recv = protocol.decode(binary, 'medida')
|
|
236
|
-
|
|
256
|
+
self.assertEqual(data, recv)
|
|
257
|
+
data = {'id': 4, 'nombre': 'Corriente', 'valor': 240}
|
|
258
|
+
binary = protocol.encode(data, 'medida')
|
|
259
|
+
recv = protocol.decode(binary, 'medida')
|
|
237
260
|
self.assertEqual(data, recv)
|
|
238
261
|
|
|
239
262
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|