Demion
Здравствуйте, увидел Ваше сообщения о созданию пакета данных с CRC. Не могли бы Вы помочь в разборе пакета приходящего от счетчика?
Счетчик Пульсар с rs485. Запрос “08 56 16 18 01 0E 03 00 00 00 01 00 FE 71”.
Получаю ответ: “085616180112a3e8103c0000000001005fab”.
Вручную (согласно протокола от Пульсар) разбираю: “08561618” - ADDR (номер счетчика), “01” - код функции запроса, “12” - общая длина пакета, “a3e8103c00000000” - данные, “01 00” - ID (идентификатор запроса (любые 2 байта))
“5fab” - CRC16.
Но как это сделать на Python? Просьба помочь!
Можешь составить кортеж из частей:
>>> def get_data():
... text = '085616180112a3e8103c0000000001005fab'
... out = bytes.fromhex(text)
... return out
...
>>> def parse_data(data):
... addr = data[:4]
... func = data[4:5]
... code = data[5:6]
... payload = data[6:-4]
... ident = data[-4:-2]
... crc = data[-2:]
... out = (
... addr,
... func,
... code,
... payload,
... ident,
... crc
... )
... return out
...
>>> data = get_data()
>>>
>>> data_parsed = parse_data(data)
>>> print(data_parsed)
(b'\x08V\x16\x18', b'\x01', b'\x12', b'\xa3\xe8\x10<\x00\x00\x00\x00', b'\x01\x00', b'_\xab')
>>>
>>> print(list(data_parsed[0]))
[8, 86, 22, 24]
>>> print(list(data_parsed[1]))
[1]
>>> print(list(data_parsed[2]))
[18]
>>> print(list(data_parsed[3]))
[163, 232, 16, 60, 0, 0, 0, 0]
>>> print(list(data_parsed[4]))
[1, 0]
>>> print(list(data_parsed[5]))
[95, 171]
>>>
Можешь составить словарь из частей:
>>> def get_data():
... text = '085616180112a3e8103c0000000001005fab'
... out = bytes.fromhex(text)
... return out
...
>>> def parse_data(data):
... addr = data[:4]
... func = data[4:5]
... code = data[5:6]
... payload = data[6:-4]
... ident = data[-4:-2]
... crc16 = data[-2:]
... out = {
... 'address': addr,
... 'function': func,
... 'code': code,
... 'payload': payload,
... 'id': ident,
... 'crc': crc16
... }
... return out
...
>>> data = get_data()
>>>
>>> data_parsed = parse_data(data)
>>> print(data_parsed)
{'address': b'\x08V\x16\x18', 'function': b'\x01', 'code': b'\x12', 'payload': b'\xa3\xe8\x10<\x00\x00\x00\x00', 'id': b'\x01\x00', 'crc': b'_\xab'}
>>>
>>> print(list(data_parsed['address']))
[8, 86, 22, 24]
>>> print(list(data_parsed['function']))
[1]
>>> print(list(data_parsed['code']))
[18]
>>> print(list(data_parsed['payload']))
[163, 232, 16, 60, 0, 0, 0, 0]
>>> print(list(data_parsed['id']))
[1, 0]
>>> print(list(data_parsed['crc']))
[95, 171]
>>>
Можешь составить объект из частей:
>>> class Data:
... def __init__(self, addr, func, code,
... payload, ident, crc16):
... self._addr = addr
... self._func = func
... self._code = code
... self._payload = payload
... self._ident = ident
... self._crc16 = crc16
... def __str__(self):
... t = (self._addr, self._func, self._code,
... self._payload, self._ident, self._crc16)
... return '{}{}'.format(__class__.__name__, t)
... def addr(self):
... return self._addr
... def func(self):
... return self._func
... def code(self):
... return self._code
... def payload(self):
... return self._payload
... def ident(self):
... return self._ident
... def crc16(self):
... return self._crc16
...
>>> def get_data():
... text = '085616180112a3e8103c0000000001005fab'
... out = bytes.fromhex(text)
... return out
...
>>> def parse_data(data):
... addr = data[:4]
... func = data[4:5]
... code = data[5:6]
... payload = data[6:-4]
... ident = data[-4:-2]
... crc16 = data[-2:]
... out = Data(
... addr,
... func,
... code,
... payload,
... ident,
... crc16
... )
... return out
...
>>> data = get_data()
>>>
>>> data_parsed = parse_data(data)
>>> print(data_parsed)
Data(b'\x08V\x16\x18', b'\x01', b'\x12', b'\xa3\xe8\x10<\x00\x00\x00\x00', b'\x01\x00', b'_\xab')
>>>
>>> print(list(data_parsed.addr()))
[8, 86, 22, 24]
>>> print(list(data_parsed.func()))
[1]
>>> print(list(data_parsed.code()))
[18]
>>> print(list(data_parsed.payload()))
[163, 232, 16, 60, 0, 0, 0, 0]
>>> print(list(data_parsed.ident()))
[1, 0]
>>> print(list(data_parsed.crc16()))
[95, 171]
>>>
Что нужно составлять и что не нужно составлять, зависит от задачи. Задача определяет наилучший вариант.
Например, у тебя есть три инструмента: молоток, шуруповёрт и болгарка. Какой из этих инструментов наилучший, если нужно забить гвоздь? Какой из этих инструментов наилучший, если нужно закрутить шуруп? Какой из этих инструментов наилучший, если нужно разделить железную трубу на части? Какой из этих инструментов наилучший, если нужно разжечь костёр? То есть задача определяет, что хорошо и что плохо в данном конкретном случае, в рамках, границах, в области этой задачи.
Бери вариант со словарём, чтобы не путаться. Внутри словаря этим полям можно давать любые имена.
Также вместо bytes() можно применить bytearray(), так как он даёт больше возможностей для работы с бинарными данными. В нём, в отличие от bytes(), можно менять набор значений, добавлять к ним что-то, удалять из них что-то, менять в них что-то с одного на другое.
Пример:
Это тип bytes(), его можно только читать:
>>> data = bytes([0x01, 0x02, 0x03])
>>> data
b'\x01\x02\x03'
>>>
>>> data[1]
2
>>>
>>> data[1] = 4
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'bytes' object does not support item assignment
>>>
Это тип bytearray(), его можно как читать, так и писать:
>>> data = bytearray([0x01, 0x02, 0x03])
>>> data
bytearray(b'\x01\x02\x03')
>>>
>>> data[1]
2
>>>
>>> data[1] = 4
>>> data
bytearray(b'\x01\x04\x03')
>>>
>>> data[1]
4
>>>
Если тебе нужно что-то создать (сформировать), пиши функцию для создания. Если тебе нужно что-то разобрать (разделить), пиши функцию для разбора. На каждое действие пиши функцию.