I have Protocol Buffer data from a GPS device.
Unfortunately, I am unable to decrypt it.
I downloaded the data from the device via Python pywinusb.hid:
(Note: I have copied the function from the classensturcture of my project and removed the namespace.)
import time
from pathlib import Path
## connection part ##
# self.usb_device = list_of_devices[0]
# self.usb_device.open()
# self.usb_device.set_raw_data_handler(self.data_handler)
# self.out_report = self.usb_device.find_output_reports()[0]
# self.response = None # reset response
def copy_file_from_device(self, file_path: Path, dest_file_path: Path):
data = self.read_file(file_path)
with open(dest_file_path, "wb") as file:
print(f"Copy_file '{str(file_path):>30s}' to '{str(dest_file_path)}'")
file.write(bytearray(data))
# end-of-method copy_file_from_device
def read_file(self, file_path: Path):
"""
Read file from device.
:param file_path: File's path.
:return: Bytes list.
"""
req_msg = get_request_msg(str(file_path), Commands.GET)
resp = self.send(request=req_msg)
return resp
# end-of-method read_file
def get_request_msg(path: str, command: Commands) -> list[int]:
"""
Create FTP operation message.
:param path: Message path.
:param command: command enum value.
:return: Message bytes array.
"""
path = str(path).replace("\", "/")
if not path.startswith("/"):
path = "/" + path
p = Packet()
data = [len(path) + 4, 0x00, 0x08, command, 0x12, len(path)] + [ord(value) for value in path]
p.set_data(data)
return p.get_raw_data()
# end-of-method get_request_msg
def send(self, request, timeout=10000, skip_header=True):
"""
Send
:param request: UsbDevice instance for device to connect.
:param timeout: Timeout value.
:param skip_header: Backward compatibility. If false, raw device response is returned.
:return: Nothing.
"""
resp = []
data = self.__send_wait(request, timeout)
while data is not None:
if data[1] & 3 == 0:
length = data[1] >> 2
resp += data[3:length+1]
break
resp += data[3:]
pckt_no = data[2]
data = self.__send_wait(get_ack_msg(pckt_no), timeout)
if skip_header:
return resp[2:]
else:
return resp
# end-of-method send
def __send_wait(self, request, timeout: int=5000):
"""
This is internal method used for HOST->DEVICE communication.
This method only sends raw request and returns raw response.
:param request: Raw request to send. Array of byte values expected.
:param timeout: Timeout in milliseconds.
:return: Device raw response (array of byte values).
"""
self.response = None
self.out_report.set_raw_data(request)
self.out_report.send()
t = 0
while self.response is None:
time.sleep(0.05) # 0.05 Seconds <-> 50 ms
t += 50 # 50 ms
if t >= timeout:
print("Warning: response timeout")
break
return self.response
# end-of-method send_wait
def get_ack_msg(packet_no):
"""
Create response message byte array to acknowledge incoming packet.
:param packet_no: Number of packet to ack.
:return: Ack packet message bytes array.
"""
p = Packet()
p.set_sequence(packet_no)
p.set_size(1)
p.set_is_last(False)
return p.get_raw_data()
# end-of-method get_ack_msg
class Commands():
GET = 0
PUT = 1
MERGE = 2
REMOVE = 3
# end-of-class Commands
class Packet():
""" Device USB packet.
Packet 64 bytes:
[0] - id
[1] - size(6bits) + is_last(2bits)
[2] - sequence
[3...63] - data
"""
PACKET_SIZE = 64
DATA_SIZE = 61
def __init__(self):
self.buffer = [0] * 64
self.set_id()
self.set_sequence()
self.set_is_last(True)
# end-of-method __init__
def set_id(self, p_id=0x01):
self.buffer[0] = p_id
# end-of-method set_id
def get_id(self):
return self.buffer[0]
# end-of-method get_id
def set_size(self, size: int):
self.buffer[1] &= 0x03
self.buffer[1] = (size << 2)
# end-of-method set_size
def get_size(self):
return ((self.buffer[1] & 0xFC) >> 2)
# end-of-method get_size
def set_is_last(self, is_last: bool):
self.buffer[1] &= 0xFC
self.buffer[1] |= 0 if is_last else 1
# end-of-method set_is_last
def get_is_last(self):
return (self.buffer[1] & 0x03) == 0
# end-of-method get_is_last
def set_sequence(self, sequence_id=0x00):
self.buffer[2] = sequence_id
# end-of-method set_sequence
def get_sequence(self):
return self.buffer[2]
# end-of-method get_sequence
def set_data(self, data: int):
if len(data) <= Packet.DATA_SIZE:
self.buffer[3:3+len(data)] = data
self.set_size(len(data)+2)
else:
raise RuntimeError("Packet data to big!")
# end-of-method set_data
def get_raw_data(self):
return self.buffer
# end-of-method get_packet
pass
# end-of-class Packet
I have been able to find sources for the required *.proto files, but they seem to be outdated. Unfortunately I am not allowed to share the found protofile here due to the guideline of Stackoverflow.
Edited: Proto-File content deleted
For my project I use Python google.protobuf and have therefore generated a .py file via protoc (protocol buffer compiler).
Edited: Proto-py-File content deleted
The content of a GPS binary file “gpsData.GZB” of the device:
1F8B0800000000000203F212E562E778C12FC021212CC4C12128A028A1A1C020C1A8C5C822C4213B3DAEE39083978314C7D9FD0507759E6B3928003172703132E091647AC10E963DB72B721A4436E8AEA7A12E4CF6023F4E59362EA61DE260D9FA7B214B20B2D77F292D84EB5D200F96D5670AD804917D00607AB5410F2CCBC3C5D4A18E5356868BE947284E59292EA607B160D907AADE0720B26BFE170334431FA6F7442A5876D116F31F10D98A93421B0CC0B2002A5C4C1B72C1B2C1378CD80E8365AD22FE3F87C86A7031CD2805CB6E91D75482C87E5E6DE90091D5E1626AA805CBDEF8CA5D0691CDEB4BB800B1D780008BF9450B2358DAD2966912447AF191833B208E36E162BED003915EF3FEE57588F4F55F4A0B75C1D2165CCC3BA640A4CF1F3DA37D042C7D767FC1411D00B0B41517F38239106903DEC300B943A419BF5D5CA90D96B6E162EE5802919E14B23319226DA6633C490B2C6DC7C5FC613544FAF3ECF5F510699D8F0D009B34C1D24E5CCC373643A4D3FCA61F85484B56CB7C56074BBB70311FD80D91D6B8DBFC1722CDC6BAC3580D26BDE23044BA53A54AF22858BA628DCE13001598F484D310E9D9FDD9CE10E954B3132ACA6069372EE61F9720D26B7FC5E442A4CF2EEAFAAA00937E700B22CDE704507027447A978E9A993C58DA83008BF9C42388F4FE54A0D3C1D22BB61D2C9385496F7805916EFC62751E223DD52176BB3458DA8B8B79C62788F4E4789D9F1069B61717D3A560D20DBFD00075FF5D23DF210996F6E1627ED1C80496CEEFF45C0A91DE6FCD73002E7DA19309A76E3F2EE61D1321D2CECDEAECC7C0D2DB18A21E48C0A417CC84482F003D25AB0C91AEE8779380EBEE58089196A865CD449706DAFD01A01510E9CA23BF5B8E613AEDC606887497FEDB75C7D0FC0D943EB00322BD8EF502D37100B0B4EF94E9FCD230E9150720D2070A0EEA40A4A73AC46E874B4F3801916EFABF3605223DAF9A7FBA0C4CFAC77988F463B7250D10E9F749ED727230E90007D721D253B2E6F741A4377E2C0E83487B71319FB80F9176ED9B350722BD4B47CD4C1E26BDE139BA34D3CDD77721D21E5CCC33DEA31BCE2D326FAF02004CBAE13BBAD3000A3A909CAA08937EF10F226DACBCB208223D33479357092CEDC6C57CA18D192CADB863BB0744FA81C4FB2D70E91D7D10E9030507750020D26B1EF59E51064BBB70312F9806918ED73C2D0091366448B751814977CC8348FF7D78E5CB31B074C51A9D271069272EE60F4B21D2BEFB6E3E834800B3B1EE30568349DF580B917E53F6F814447A4AAC73B33A4CFAC056887497FEDB7510E9A72EBBB93461D200ADD80B91D67CF16D12447A235F9492164C007AC25188F489050CE51069FBF4A785DA30E91F6720D2DB4CF97D21D267F7171CD481493FB802910E7D27610891BEFE4B69A12E4CFAC41D8834D0B5EC0010E9D4E0751FF460D21B9E40A41BBF589D3F0A96AE3829B4C100263DE30D447A7FAADF7488F4C90D5DE64630E9862F10E93FD712E321D2923398F61B00C3A45FFC86485B7994AA43A49F262EBC660293BED00C100B583A0D68F611B074567D959B294C7A473744DAA9624B2144FADD9CE06D1069172EE605930021D2E78F9ED1C622DD311B22FDFBF4BB9387C1D2BBD23E9D3583497F580491B6B4659A04913EB270C95A7398F48D5510E9635D523E10E909D9CE472D0060D2073641A4B7C86B2A41A4672EFBBAC41226BD6217443AF886111B445AFD7FC3172BB0B41B17F38443E8D279ABDDE658C3A47F9C84482FDA62FEE300104060E96DE13C2E3630E90717F14A6F7888577AC64B88F4B95D91D320D253A6F34BDBC3A41B3E42A4F7F867E440A46F3B5F3D04977EF10322CDA393001B07915ECE5B72CB01267DA181154DFADD4ECB264798F48E0EBCD20B26A04B6FF450DB0597EE98C18AE63414E90FF321D2F5F742966031FCC6725634007FA3481F588F577AC27EDCD21E5CCC1BEEE1D53DE31944FADAAB190F0E82A54DD3FE6B3AC17437BC83488BC4AC590118445A47DBD70BAEFBC55774E900AC39094270E90B7F21D2C9161B6741A49FD6B52F728049EF6865034B6F16D9D6039156FE302B0B2EBDA0970D4DF772DE925B0E30A7754C45D75D7C5D00E813DCDF1FE6E0953EB0860D0049B0C1526C0B0000
The data was recorded on 2020-08-19 around GPS position lat=“52.50594” and lon=“13.45152”.
Using “parser.ParseFromString(bytes(data))” leading to the error:
google.protobuf.message.DecodeError: Error parsing message
I actually thought that the problem was with the existing *.proto files. However, the execution of “protoc –decode_raw < ROUTE.GZB” leads to the following error:
Failed to parse input.
So I may have made a mistake when downloading the data.
I would be grateful for any solutions, approaches or inspiration.
CodeMonkey is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
2