sync
This commit is contained in:
@@ -120,6 +120,40 @@ class SerialBus:
|
||||
full_frame += payload
|
||||
self.send_binary(full_frame)
|
||||
|
||||
def send_stream(self, data: bytes, chunk_size: int = 4096, progress_callback=None):
|
||||
"""Sendet einen Datenstrom in Chunks und wartet auf die Bestätigung (CRC)."""
|
||||
start_time = time.time()
|
||||
size = len(data)
|
||||
sent_size = 0
|
||||
|
||||
while sent_size < size:
|
||||
chunk = data[sent_size:sent_size+chunk_size]
|
||||
self.connection.write(chunk)
|
||||
sent_size += len(chunk)
|
||||
|
||||
if progress_callback:
|
||||
progress_callback(sent_size, size)
|
||||
|
||||
if not self.wait_for_sync(SYNC_SEQ, max_time=self.timeout + 5.0):
|
||||
raise TimeoutError("Timeout beim Warten auf Stream-Ende (Flash ist evtl. noch beschäftigt).")
|
||||
|
||||
ftype = self._read_exact(1, "Frame-Typ")[0]
|
||||
|
||||
if ftype == FRAME_TYPES['stream_end']:
|
||||
end_time = time.time()
|
||||
crc32 = struct.unpack('<I', self._read_exact(4, "CRC32"))[0]
|
||||
return {
|
||||
'crc32': crc32,
|
||||
'duration': end_time - start_time
|
||||
}
|
||||
elif ftype == FRAME_TYPES['error']:
|
||||
err_code_raw = self.connection.read(1)
|
||||
err_code = err_code_raw[0] if err_code_raw else 0xFF
|
||||
err_name = ERRORS.get(err_code, "UNKNOWN")
|
||||
raise ControllerError(err_code, err_name)
|
||||
else:
|
||||
raise ValueError(f"Unerwarteter Frame-Typ nach Stream-Upload: 0x{ftype:02X}")
|
||||
|
||||
def receive_ack(self, timeout: float = None):
|
||||
wait_time = timeout if timeout is not None else self.timeout
|
||||
|
||||
@@ -212,42 +246,46 @@ class SerialBus:
|
||||
err_name = ERRORS.get(err_code, "UNKNOWN")
|
||||
raise ControllerError(err_code, err_name)
|
||||
|
||||
def receive_stream(self, chunk_size: int = 1024):
|
||||
def receive_stream(self, chunk_size: int = 1024, progress_callback=None):
|
||||
"""Liest einen Datenstrom in Chunks, bis ein Fehler oder Ende-Signal kommt."""
|
||||
is_stream = False
|
||||
data_chunks = []
|
||||
start_time = None
|
||||
|
||||
while True:
|
||||
if not self.wait_for_sync(SYNC_SEQ):
|
||||
raise TimeoutError("Timeout beim Warten auf Sync im Stream-Modus.")
|
||||
|
||||
ftype = self._read_exact(1, "Frame-Typ")[0]
|
||||
if self.debug: console.print(f"Empfangener Frame-Typ: 0x{ftype:02X} (start: 0x{FRAME_TYPES['stream_start']:02X}, chunk: 0x{FRAME_TYPES['stream_chunk']:02X}, end: 0x{FRAME_TYPES['stream_end']:02X})")
|
||||
|
||||
if ftype == FRAME_TYPES['stream_start']:
|
||||
is_stream = True
|
||||
data_chunks = []
|
||||
size = struct.unpack('<I', self._read_exact(4, "Stream-Größe"))[0]
|
||||
if self.debug: console.print(f"Stream gestartet, erwartete Gesamtgröße: {size} Bytes")
|
||||
|
||||
start_time = time.time()
|
||||
|
||||
received_size = 0
|
||||
while received_size < size:
|
||||
chunk_length = min(chunk_size, size - received_size)
|
||||
try:
|
||||
chunk_data = self._read_exact(chunk_length, f"Daten-Chunk @ {received_size}/{size}")
|
||||
except Exception as e:
|
||||
raise IOError(f"Stream-Abbruch bei {received_size}/{size} Bytes: {e}") from e
|
||||
chunk_data = self._read_exact(chunk_length, f"Daten-Chunk @ {received_size}/{size}")
|
||||
data_chunks.append(chunk_data)
|
||||
received_size += len(chunk_data)
|
||||
if self.debug: console.print(f"Empfangen: {received_size}/{size} Bytes ({(received_size/size)*100:.2f}%)")
|
||||
|
||||
# Callback für UI-Update (z.B. Progress Bar)
|
||||
if progress_callback:
|
||||
progress_callback(received_size, size)
|
||||
|
||||
if self.debug: console.print("Stream vollständig empfangen.")
|
||||
|
||||
elif ftype == FRAME_TYPES['stream_end']:
|
||||
end_time = time.time()
|
||||
if not is_stream: raise ValueError("Ende ohne Start.")
|
||||
crc32 = struct.unpack('<I', self._read_exact(4, "CRC32"))[0]
|
||||
if self.debug: console.print(f"Stream-Ende empfangen, CRC32: 0x{crc32:08X}")
|
||||
|
||||
return {'data': b''.join(data_chunks), 'crc32': crc32}
|
||||
return {
|
||||
'data': b''.join(data_chunks),
|
||||
'crc32': crc32,
|
||||
'duration': end_time - start_time if start_time and end_time else None
|
||||
}
|
||||
|
||||
# elif ftype == FRAME_TYPES['list_chunk']:
|
||||
# if not is_list: raise ValueError("Chunk ohne Start.")
|
||||
|
||||
Reference in New Issue
Block a user