import serial
import time
import random
import os

# --- Konfiguracja --- #
SERIAL_PORT = "/dev/ttyUSB0"  # Zmień na odpowiedni port szeregowy ATS mini si4732
BAUD_RATE = 115200

# Zakresy częstotliwości (przykładowe, do dostosowania)
# ATS mini si4732 obsługuje: AM/MW (520-1710 kHz), LW (153-279 kHz), SW (2.3-26.1 MHz), FM (64-108 MHz)
# Dla uproszczenia, skupimy się na FM i AM (MW) dla spirit boxa.
FM_MIN_FREQ = 88000  # 88.0 MHz w kHz
FM_MAX_FREQ = 108000 # 108.0 MHz w kHz
AM_MIN_FREQ = 520    # 520 kHz
AM_MAX_FREQ = 1710   # 1710 kHz

# Prędkość skanowania (zmiany częstotliwości na sekundę)
SWEEP_SPEED_HZ = 10  # 10 zmian częstotliwości na sekundę

# Tryb audio: 'simulation' (symulacja) lub 'radio' (rzeczywiste radio)
AUDIO_MODE = 'simulation'

# --- Moduł komunikacji szeregowej --- #
class SerialCommunicator:
    def __init__(self, port, baud_rate):
        self.port = port
        self.baud_rate = baud_rate
        self.ser = None

    def connect(self):
        try:
            self.ser = serial.Serial(self.port, self.baud_rate, timeout=1)
            print(f"Połączono z portem szeregowym {self.port}")
            return True
        except serial.SerialException as e:
            print(f"Błąd połączenia z portem szeregowym {self.port}: {e}")
            return False

    def disconnect(self):
        if self.ser and self.ser.is_open:
            self.ser.close()
            print(f"Rozłączono z portem szeregowym {self.port}")

    def send_command(self, command):
        if self.ser and self.ser.is_open:
            try:
                self.ser.write(command.encode() + b'\n') # Dodaj znak nowej linii
                # print(f"Wysłano komendę: {command}")
                # response = self.ser.readline().decode().strip()
                # if response:
                #     print(f"Odpowiedź: {response}")
            except serial.SerialException as e:
                print(f"Błąd wysyłania komendy: {e}")
        else:
            print("Błąd: Brak połączenia szeregowego.")

# --- Moduł sterowania częstotliwością (Sweeper) --- #
class FrequencySweeper:
    def __init__(self, communicator, audio_mode):
        self.communicator = communicator
        self.audio_mode = audio_mode
        self.current_freq = 0
        self.direction = 1 # 1 for up, -1 for down

    def set_frequency(self, freq, band):
        if self.audio_mode == 'radio':
            # Komendy do ATS mini si4732 (przykładowe, do weryfikacji)
            # Zgodnie z dokumentacją PU2CLR, komendy to 'F' dla FM, 'A' dla AM, 'U'/'D' dla zmiany częstotliwości
            # Musimy znaleźć komendę do ustawienia konkretnej częstotliwości.
            # Na razie symulujemy wysyłanie komendy.
            if band == 'FM':
                self.communicator.send_command(f"F") # Wybierz tryb FM
                self.communicator.send_command(f"SET_FREQ {freq}") # To jest hipotetyczna komenda
            elif band == 'AM':
                self.communicator.send_command(f"A") # Wybierz tryb AM
                self.communicator.send_command(f"SET_FREQ {freq}") # To jest hipotetyczna komenda
            # print(f"Radio: Ustawiono częstotliwość {freq} kHz w paśmie {band}")
        else:
            pass # W trybie symulacji radio nie jest sterowane

    def sweep(self, min_freq, max_freq, band, sweep_speed_hz):
        self.current_freq = min_freq
        self.direction = 1
        step = (max_freq - min_freq) / (sweep_speed_hz * 10) # Mały krok dla płynniejszego skanowania
        if step == 0: step = 1 # Zapobieganie dzieleniu przez zero

        while True:
            self.set_frequency(int(self.current_freq), band)
            # print(f"Skanowanie: {int(self.current_freq)} kHz ({band})")

            if self.audio_mode == 'simulation':
                AudioSimulator.generate_white_noise()
                if random.random() < 0.05: # 5% szans na fragment mowy
                    AudioSimulator.play_random_speech_fragment()

            self.current_freq += self.direction * step

            if self.direction == 1 and self.current_freq > max_freq:
                self.current_freq = max_freq
                self.direction = -1
            elif self.direction == -1 and self.current_freq < min_freq:
                self.current_freq = min_freq
                self.direction = 1

            time.sleep(1 / sweep_speed_hz)

# --- Moduł symulacji audio --- #
class AudioSimulator:
    @staticmethod
    def generate_white_noise():
        # W rzeczywistości to by odtwarzało biały szum
        # print("Generowanie białego szumu...")
        pass

    @staticmethod
    def play_random_speech_fragment():
        # W rzeczywistości to by odtwarzało krótki, losowy fragment mowy
        print("\n[WYKRYTO FRAGMENT MOWY]\n")

# --- Główna funkcja --- #
def main():
    global AUDIO_MODE
    print("\n--- Symulator Spirit Box dla ATS mini si4732 ---")
    print(f"Tryb audio: {AUDIO_MODE}")

    communicator = None
    if AUDIO_MODE == 'radio':
        communicator = SerialCommunicator(SERIAL_PORT, BAUD_RATE)
        if not communicator.connect():
            print("Nie można połączyć się z radiem. Przełączam na tryb symulacji audio.")
            AUDIO_MODE = 'simulation'

    sweeper = FrequencySweeper(communicator, AUDIO_MODE)

    try:
        while True:
            print("\nRozpoczynam skanowanie pasma FM...")
            sweeper.sweep(FM_MIN_FREQ, FM_MAX_FREQ, 'FM', SWEEP_SPEED_HZ)
            time.sleep(2) # Krótka przerwa między pasmami

            print("\nRozpoczynam skanowanie pasma AM...")
            sweeper.sweep(AM_MIN_FREQ, AM_MAX_FREQ, 'AM', SWEEP_SPEED_HZ)
            time.sleep(2) # Krótka przerwa między pasmami

    except KeyboardInterrupt:
        print("\nZatrzymywanie symulatora...")
    finally:
        if communicator:
            communicator.disconnect()
        print("Symulator zatrzymany.")

if __name__ == "__main__":
    main()


przeanalizuj kod i opisz jak będzie działał oraz czy warto wprowadzić poprawki