1
0

some internal changes

This commit is contained in:
2026-02-22 10:30:42 +01:00
parent 8d8167dbd1
commit 596df82d28

78
xrd.py
View File

@@ -11,26 +11,27 @@ import time
from tef import TEF6686 from tef import TEF6686
from protocol import I2CPCClient from protocol import I2CPCClient
import os import os
from functools import wraps
from typing import Callable
HOST = os.getenv("HOST") or '0.0.0.0' HOST = os.getenv("HOST") or '0.0.0.0'
PORT = int(os.getenv("PORT") or 0) or 7373 PORT = int(os.getenv("PORT") or 0) or 7373
DEVICE = os.getenv("DEV") or "COM6" DEVICE = os.getenv("DEV") or "COM6"
FREQ_NOT_ALLOWED_RANGE = [9482, 9518] FREQ_NOT_ALLOWED_RANGE = []
FREQ_NOT_ALLOWED_LIST = [10090]
PASSWORD = os.getenv("PW") or "test" PASSWORD = os.getenv("PW") or "test"
CLOCK = 12000000 # DP-666 CLOCK = 12000000 # DP-666
SALT_LENGTH = 16 SALT_LENGTH = 16
SS_UPDATE_INTERVAL = 0.125 SS_UPDATE_INTERVAL = 0.115
RDS_UPDATE_INTERVAL = 0.086 RDS_UPDATE_INTERVAL = 0.086
def generate_salt(length=SALT_LENGTH) -> str: def freq_allowed(freq: int):
return "".join(secrets.choice(string.ascii_lowercase) for _ in range(length)) if not FREQ_NOT_ALLOWED_RANGE: return True
for (lower, upper) in FREQ_NOT_ALLOWED_RANGE:
def compute_hash(salt: str, password: str): if freq >= lower and freq <= upper: return False
return hashlib.sha1((salt + password).encode()).hexdigest().encode() return True
def init_tef(): def init_tef():
p = I2CPCClient(DEVICE) p = I2CPCClient(DEVICE)
@@ -46,9 +47,9 @@ def init_tef():
return tef return tef
def authenticate(conn: socket.socket): def authenticate(conn: socket.socket):
salt = generate_salt() salt = "".join(secrets.choice(string.ascii_lowercase) for _ in range(SALT_LENGTH))
conn.sendall(salt.encode() + b"\n") conn.sendall(salt.encode() + b"\n")
expected_hash = compute_hash(salt, PASSWORD) expected_hash = hashlib.sha1((salt + PASSWORD).encode()).hexdigest().encode()
while True: while True:
data = conn.recv(1024) data = conn.recv(1024)
@@ -60,11 +61,10 @@ def process_command(tef: TEF6686, data: bytes, state: dict, conn: socket.socket)
for cmd in data.splitlines(): for cmd in data.splitlines():
if cmd.startswith(b"T"): if cmd.startswith(b"T"):
freq = int(cmd.decode().removeprefix("T").strip()) // 10 freq = int(cmd.decode().removeprefix("T").strip()) // 10
if freq < 6500: continue if freq < 6500 or freq > 10800: continue
if freq > 10800: continue
state['last_tune'] = freq state['last_tune'] = freq
tef.FM_Tune_To(1, freq) tef.FM_Tune_To(1, freq)
if (FREQ_NOT_ALLOWED_RANGE and freq >= FREQ_NOT_ALLOWED_RANGE[0] and freq <= FREQ_NOT_ALLOWED_RANGE[1]) or (FREQ_NOT_ALLOWED_LIST and freq in FREQ_NOT_ALLOWED_LIST): tef.AUDIO_Set_Mute(True) if not freq_allowed(freq): tef.AUDIO_Set_Mute(True)
else: tef.AUDIO_Set_Mute(False) else: tef.AUDIO_Set_Mute(False)
out += f"T{freq*10}\n".encode() out += f"T{freq*10}\n".encode()
elif cmd.startswith(b"G"): elif cmd.startswith(b"G"):
@@ -88,7 +88,7 @@ def process_command(tef: TEF6686, data: bytes, state: dict, conn: socket.socket)
out += b"OK\n" out += b"OK\n"
tef.APPL_Set_OperationMode(False) tef.APPL_Set_OperationMode(False)
tef.FM_Tune_To(1, state["last_tune"]) tef.FM_Tune_To(1, state["last_tune"])
if (FREQ_NOT_ALLOWED_RANGE and state["last_tune"] >= FREQ_NOT_ALLOWED_RANGE[0] and state["last_tune"] <= FREQ_NOT_ALLOWED_RANGE[1]) or (FREQ_NOT_ALLOWED_LIST and state["last_tune"] in FREQ_NOT_ALLOWED_LIST): tef.AUDIO_Set_Mute(True) if not freq_allowed(state["last_tune"]): tef.AUDIO_Set_Mute(True)
else: tef.AUDIO_Set_Mute(False) else: tef.AUDIO_Set_Mute(False)
elif cmd.startswith(b"X"): elif cmd.startswith(b"X"):
tef.APPL_Set_OperationMode(True) tef.APPL_Set_OperationMode(True)
@@ -115,8 +115,8 @@ def process_command(tef: TEF6686, data: bytes, state: dict, conn: socket.socket)
for freq in range(state["scan_start"], state["scan_stop"] + state["scan_step"], state["scan_step"]): for freq in range(state["scan_start"], state["scan_stop"] + state["scan_step"], state["scan_step"]):
tef.FM_Tune_To(2, freq) # Auto mutes, less commands sent tef.FM_Tune_To(2, freq) # Auto mutes, less commands sent
time.sleep(0.0064) time.sleep(0.0064)
if (FREQ_NOT_ALLOWED_RANGE and freq >= FREQ_NOT_ALLOWED_RANGE[0] and freq <= FREQ_NOT_ALLOWED_RANGE[1]) or (FREQ_NOT_ALLOWED_LIST and freq in FREQ_NOT_ALLOWED_LIST): if freq_allowed(freq):
conn.sendall(f"{freq * 10} = 0, ".encode()) conn.sendall(f"{freq * 10} = -11.25, ".encode())
continue continue
_, level, *_ = d if (d := tef.FM_Get_Quality_Data()) else (None, None) _, level, *_ = d if (d := tef.FM_Get_Quality_Data()) else (None, None)
if level is None: continue if level is None: continue
@@ -124,14 +124,34 @@ def process_command(tef: TEF6686, data: bytes, state: dict, conn: socket.socket)
conn.sendall(b"\n") conn.sendall(b"\n")
tef.FM_Tune_To(1, state["last_tune"]) tef.FM_Tune_To(1, state["last_tune"])
if (FREQ_NOT_ALLOWED_RANGE and freq >= FREQ_NOT_ALLOWED_RANGE[0] and freq <= FREQ_NOT_ALLOWED_RANGE[1]) or (FREQ_NOT_ALLOWED_LIST and freq in FREQ_NOT_ALLOWED_LIST): tef.AUDIO_Set_Mute(True) if not freq_allowed(state["last_tune"]): tef.AUDIO_Set_Mute(True)
else: tef.AUDIO_Set_Mute(False) else: tef.AUDIO_Set_Mute(False)
tef.FM_Set_Bandwidth((state["bw"] == 0), 2360 if (state["bw"] == 0) else (state["bw"] // 100)) tef.FM_Set_Bandwidth((state["bw"] == 0), 2360 if (state["bw"] == 0) else (state["bw"] // 100))
return out return out
PERIODIC_FUNCTIONS: list[tuple[Callable, float, libtimer.Timer]] = []
def periodic(t: float):
def decorator(func):
PERIODIC_FUNCTIONS.append((func, t, libtimer.Timer()))
@wraps(func)
def wrapper(*args, **kwargs): return func(*args, **kwargs)
return wrapper
return decorator
def reset_periodic():
for (_, _, timer) in PERIODIC_FUNCTIONS: timer.reset()
def run_periodic(*args, **kwargs):
for (func, t, timer) in PERIODIC_FUNCTIONS:
if timer.get_time() > t:
func(*args, **kwargs)
timer.reset()
@periodic(SS_UPDATE_INTERVAL)
def send_signal_status(tef: TEF6686, conn: socket.socket, state: dict): def send_signal_status(tef: TEF6686, conn: socket.socket, state: dict):
if (FREQ_NOT_ALLOWED_RANGE and state["last_tune"] >= FREQ_NOT_ALLOWED_RANGE[0] and state["last_tune"] <= FREQ_NOT_ALLOWED_RANGE[1]) or (FREQ_NOT_ALLOWED_LIST and state["last_tune"] in FREQ_NOT_ALLOWED_LIST): if not freq_allowed(state["last_tune"]):
conn.sendall(b"Sm11.25,0,0,0\n\n") conn.sendall(b"Sm11.25,0,0,0\n\n")
return return
_, _, stereo, _ = d if (d := tef.FM_Get_Processing_Status()) else (None, None, 1000, None) _, _, stereo, _ = d if (d := tef.FM_Get_Processing_Status()) else (None, None, 1000, None)
@@ -150,8 +170,9 @@ def send_signal_status(tef: TEF6686, conn: socket.socket, state: dict):
data += f"{level + 11.25},{wam//10},{usn//10},{bandwidth}\n\n".encode() data += f"{level + 11.25},{wam//10},{usn//10},{bandwidth}\n\n".encode()
conn.sendall(data) conn.sendall(data)
@periodic(RDS_UPDATE_INTERVAL)
def send_rds_data(tef: TEF6686, conn: socket.socket, state: dict): def send_rds_data(tef: TEF6686, conn: socket.socket, state: dict):
if (FREQ_NOT_ALLOWED_RANGE and state["last_tune"] >= FREQ_NOT_ALLOWED_RANGE[0] and state["last_tune"] <= FREQ_NOT_ALLOWED_RANGE[1]) or (FREQ_NOT_ALLOWED_LIST or state["last_tune"] in FREQ_NOT_ALLOWED_LIST): return if not freq_allowed(state["last_tune"]): return
res = tef.FM_Get_RDS_Data__decoder() res = tef.FM_Get_RDS_Data__decoder()
if res is None: return if res is None: return
@@ -193,10 +214,10 @@ def run_server():
variant_str = "TEF6686" variant_str = "TEF6686"
if variant == 1: variant_str = "TEF6687" if variant == 1: variant_str = "TEF6687"
if variant == 9: variant_str = "TEF6688" elif variant == 9: variant_str = "TEF6688"
if variant == 3: variant_str = "TEF6689" elif variant == 3: variant_str = "TEF6689"
print(f"Got {variant_str} (V{hw_major}{hw_minor}{sw_major})") print(f"{variant_str} (V{hw_major}{hw_minor}{sw_major})")
state = { state = {
'last_tune': 9500, 'last_tune': 9500,
@@ -210,7 +231,7 @@ def run_server():
'scan_bw': 0, 'scan_bw': 0,
} }
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: with socket.socket() as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT)) s.bind((HOST, PORT))
s.listen() s.listen()
@@ -219,6 +240,7 @@ def run_server():
while True: while True:
conn, addr = s.accept() conn, addr = s.accept()
with conn: with conn:
reset_periodic()
print(f"Connected by {addr}") print(f"Connected by {addr}")
if not authenticate(conn): if not authenticate(conn):
print("Authentication failed.") print("Authentication failed.")
@@ -233,9 +255,6 @@ def run_server():
conn.sendall(f"M0\n".encode()) conn.sendall(f"M0\n".encode())
conn.setblocking(False) conn.setblocking(False)
ss_timer = libtimer.Timer()
rds_timer = libtimer.Timer()
while True: while True:
try: try:
if not (data := conn.recv(1024)): break if not (data := conn.recv(1024)): break
@@ -244,12 +263,7 @@ def run_server():
except ConnectionResetError: break except ConnectionResetError: break
except ConnectionAbortedError: break except ConnectionAbortedError: break
except BlockingIOError: except BlockingIOError:
if ss_timer.get_time() > SS_UPDATE_INTERVAL: run_periodic()
send_signal_status(tef, conn, state)
ss_timer.reset()
if rds_timer.get_time() > RDS_UPDATE_INTERVAL:
send_rds_data(tef, conn, state)
rds_timer.reset()
time.sleep(0.015) time.sleep(0.015)
if __name__ == "__main__": run_server() if __name__ == "__main__": run_server()