72 lines
2.1 KiB
Python
72 lines
2.1 KiB
Python
"""
|
||
Виртуальный канал связи SDR Rover Link.
|
||
|
||
Имитирует:
|
||
1. Полную потерю пакета.
|
||
2. Случайное изменение отдельных битов.
|
||
"""
|
||
|
||
import random
|
||
|
||
|
||
def transmit(
|
||
packet: bytes,
|
||
drop_probability: float,
|
||
bit_error_probability: float,
|
||
random_generator: random.Random,
|
||
):
|
||
"""
|
||
Передать пакет через виртуальный канал.
|
||
|
||
Возвращает:
|
||
received_packet:
|
||
Пакет после прохождения канала.
|
||
None означает полную потерю пакета.
|
||
|
||
flipped_bits:
|
||
Количество изменённых битов.
|
||
"""
|
||
|
||
if not isinstance(packet, (bytes, bytearray)):
|
||
raise TypeError(
|
||
"packet должен иметь тип bytes или bytearray"
|
||
)
|
||
|
||
if not 0.0 <= drop_probability <= 1.0:
|
||
raise ValueError(
|
||
"drop_probability должен находиться "
|
||
"в диапазоне 0.0...1.0"
|
||
)
|
||
|
||
if not 0.0 <= bit_error_probability <= 1.0:
|
||
raise ValueError(
|
||
"bit_error_probability должен находиться "
|
||
"в диапазоне 0.0...1.0"
|
||
)
|
||
|
||
# Решаем, потерян ли пакет полностью.
|
||
if random_generator.random() < drop_probability:
|
||
return None, 0
|
||
|
||
corrupted_packet = bytearray(packet)
|
||
flipped_bits = 0
|
||
|
||
# Перебираем каждый байт.
|
||
for byte_index in range(len(corrupted_packet)):
|
||
|
||
# В каждом байте восемь битов.
|
||
for bit_index in range(8):
|
||
|
||
if (
|
||
random_generator.random()
|
||
< bit_error_probability
|
||
):
|
||
bit_mask = 1 << bit_index
|
||
|
||
# XOR меняет выбранный бит:
|
||
# 0 → 1 или 1 → 0.
|
||
corrupted_packet[byte_index] ^= bit_mask
|
||
|
||
flipped_bits += 1
|
||
|
||
return bytes(corrupted_packet), flipped_bits |