58 lines
No EOL
2 KiB
Python
58 lines
No EOL
2 KiB
Python
# main.py
|
|
#!/usr/bin/env python3
|
|
import argparse
|
|
import socket
|
|
import numpy as np
|
|
import channel_helper as ch
|
|
from encoder import make_codebook, encode_message
|
|
from decoder import decode_blocks, count_errors
|
|
from channel import channel as external_channel
|
|
|
|
|
|
def send_and_recv(x: np.ndarray, host: str, port: int) -> np.ndarray:
|
|
"""Send samples x to server and receive output via TCP"""
|
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
|
sock.connect((host, port))
|
|
header = b'0' + b'dUV'
|
|
ch.send_msg(sock, header, x)
|
|
_, Y = ch.recv_msg(sock)
|
|
return Y
|
|
|
|
|
|
def main():
|
|
p = argparse.ArgumentParser(description="PDC Tx/Rx local or server")
|
|
p.add_argument("--message", required=True, help="40-character message to send")
|
|
p.add_argument("--srv_hostname", help="Server hostname")
|
|
p.add_argument("--srv_port", type=int, help="Server port")
|
|
p.add_argument("--local", action='store_true', help="Use local channel simulation")
|
|
args = p.parse_args()
|
|
|
|
msg = args.message
|
|
if len(msg) != 40:
|
|
raise ValueError("Message must be exactly 40 characters.")
|
|
num_blocks = len(msg)
|
|
C = make_codebook(r=5, num_blocks=num_blocks, margin=0.95)
|
|
x = encode_message(msg, C)
|
|
print(f"→ Total samples = {x.size}, total energy = {np.sum(x*x):.1f}")
|
|
|
|
if args.local:
|
|
print("-- Local simulation mode --")
|
|
Y = external_channel(x)
|
|
else:
|
|
if not args.srv_hostname or not args.srv_port:
|
|
raise ValueError("Must specify --srv_hostname and --srv_port unless --local")
|
|
Y = send_and_recv(x, args.srv_hostname, args.srv_port)
|
|
|
|
msg_hat = decode_blocks(Y, C)
|
|
print(f"↓ Decoded message: {msg_hat}")
|
|
|
|
errors = count_errors(msg, msg_hat)
|
|
print(f"Errors: {len(errors)} / {len(msg)} characters differ")
|
|
if errors:
|
|
for i, o, e in errors:
|
|
print(f" Pos {i}: sent '{o}' but got '{e}'")
|
|
else:
|
|
print("✔️ No decoding errors!")
|
|
|
|
if __name__ == "__main__":
|
|
main() |