Files
SDR-Rover/tests/lab003_crc32.py

198 lines
5.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Lab003. Обнаружение повреждения пакета с помощью CRC-32.
Цель:
1. Сформировать пакет с CRC-32.
2. Проверить исправный пакет.
3. Изменить один бит полезной нагрузки.
4. Убедиться, что CRC обнаруживает повреждение.
"""
import struct
import zlib
# ============================================================
# Константы протокола
# ============================================================
SYNC_WORD = 0xAA55
PROTOCOL_VERSION = 1
MESSAGE_TYPE_TEXT = 1
HEADER_FORMAT = ">HBBHH"
CRC_FORMAT = ">I"
CRC_SIZE = struct.calcsize(CRC_FORMAT)
# ============================================================
# Формирование исходного пакета
# ============================================================
message = "ПРИВЕТ SDR"
payload = message.encode("utf-8")
sequence_number = 1
payload_length = len(payload)
header = struct.pack(
HEADER_FORMAT,
SYNC_WORD,
PROTOCOL_VERSION,
MESSAGE_TYPE_TEXT,
sequence_number,
payload_length,
)
# CRC вычисляется по заголовку и полезной нагрузке.
packet_without_crc = header + payload
crc_value = zlib.crc32(packet_without_crc) & 0xFFFFFFFF
crc_bytes = struct.pack(
CRC_FORMAT,
crc_value,
)
packet = packet_without_crc + crc_bytes
print("Исходное сообщение:")
print(message)
print("\nCRC-32 исходного пакета:")
print(f"0x{crc_value:08X}")
print("\nПолный пакет:")
print(packet.hex(" "))
print("\nДлина полного пакета:")
print(len(packet), "байт")
# ============================================================
# Проверка исправного пакета
# ============================================================
received_data = packet[:-CRC_SIZE]
received_crc_bytes = packet[-CRC_SIZE:]
(received_crc,) = struct.unpack(
CRC_FORMAT,
received_crc_bytes,
)
calculated_crc = zlib.crc32(received_data) & 0xFFFFFFFF
print("\n--- Проверка исправного пакета ---")
print(f"CRC из пакета: 0x{received_crc:08X}")
print(f"CRC вычисленный: 0x{calculated_crc:08X}")
assert received_crc == calculated_crc
print("Результат: пакет не повреждён.")
# ============================================================
# Имитация повреждения одного бита
# ============================================================
corrupted_packet = bytearray(packet)
header_size = struct.calcsize(HEADER_FORMAT)
# Буква S находится по индексу 13 внутри PAYLOAD.
payload_byte_index = 13
packet_byte_index = header_size + payload_byte_index
original_byte = corrupted_packet[packet_byte_index]
# Меняем младший бит:
# S = 0x53
# R = 0x52
corrupted_packet[packet_byte_index] ^= 0x01
corrupted_byte = corrupted_packet[packet_byte_index]
print("\n--- Повреждение одного бита ---")
print(
f"До повреждения: "
f"0x{original_byte:02X} = {original_byte:08b}"
)
print(
f"После повреждения: "
f"0x{corrupted_byte:02X} = {corrupted_byte:08b}"
)
# ============================================================
# Проверка повреждённого пакета
# ============================================================
corrupted_data = bytes(
corrupted_packet[:-CRC_SIZE]
)
corrupted_crc_bytes = bytes(
corrupted_packet[-CRC_SIZE:]
)
(received_crc_after_corruption,) = struct.unpack(
CRC_FORMAT,
corrupted_crc_bytes,
)
calculated_crc_after_corruption = (
zlib.crc32(corrupted_data) & 0xFFFFFFFF
)
print("\n--- Проверка повреждённого пакета ---")
print(
f"CRC из пакета: "
f"0x{received_crc_after_corruption:08X}"
)
print(
f"CRC вычисленный: "
f"0x{calculated_crc_after_corruption:08X}"
)
if received_crc_after_corruption != calculated_crc_after_corruption:
print("\nРезультат: CRC обнаружил повреждение пакета.")
else:
print("\nРезультат: повреждение не обнаружено.")
# ============================================================
# Показываем повреждённое сообщение
# ============================================================
corrupted_payload = corrupted_data[header_size:]
corrupted_message = corrupted_payload.decode("utf-8")
print("\nСообщение внутри повреждённого пакета:")
print(corrupted_message)
# ============================================================
# Автоматические проверки
# ============================================================
assert corrupted_message == "ПРИВЕТ RDR"
assert (
received_crc_after_corruption
!= calculated_crc_after_corruption
)
print("\nПроверка пройдена: CRC-32 обнаружил изменение одного бита.")