remote-shack/internal/config/config.go

181 lines
7.2 KiB
Go

// Package config verwaltet das Laden und Parsen der TOML-Konfigurationsdateien
// für den Server-Daemon und alle angeschlossenen GUI-Clients.
package config
import (
"fmt"
"os"
"github.com/BurntSushi/toml"
)
// ============================================================================
// SERVER CONFIGURATION STRUCTURES
// ============================================================================
// ADS1115Module definiert die Hardware-Parameter und Kanal-Labels einer ADC-Platine.
// Wird im Server zur reinen Shack-Betriebsspannungs-Telemetrie genutzt.
type ADS1115Module struct {
Address string `toml:"address"` // I2C-Hardwareadresse (z.B. "0x48" oder "0x49")
Labels []string `toml:"labels"` // Genau 4 Beschriftungen für die Analog-Kanäle A0 bis A3
}
// RigHardwareSettings definiert die Parameter für das CAT-Interface des Transceivers.
type RigHardwareSettings struct {
Type string `toml:"type"` // Hardware-Modell (z.B. "FT897")
Port string `toml:"port"` // Serieller Systempfad (z.B. "/dev/ttyUSB0")
Baud int `toml:"baud"` // Übertragungsgeschwindigkeit (z.B. 38400)
}
// RotorHardwareSettings definiert die Parameter für das serielle Protokoll des Rotors.
type RotorHardwareSettings struct {
Type string `toml:"type"` // Hardware-Modell (z.B. "ProSistel" oder "SPID")
Port string `toml:"port"` // Serieller Systempfad (z.B. "/dev/ttyUSB1")
Baud int `toml:"baud"` // Übertragungsgeschwindigkeit (z.B. 9600)
}
// ServerSettings definiert die Netzwerkparameter des Server-Daemons.
// Beinhaltet alle physischen Hardware-Sektionen auf Server-Ebene.
type ServerSettings struct {
ListenAddress string `toml:"listen_address"` // Netzwerk-Bindung (z.B. "0.0.0.0:50051")
HardwareRig RigHardwareSettings `toml:"hardware_rig"` // Parameter für den Yaesu-Treiber
HardwareRotor RotorHardwareSettings `toml:"hardware_rotor"` // Parameter für den ProSistel/SPID-Treiber
Modules []ADS1115Module `toml:"modules"` // Array für angeschlossene I2C-Spannungssensoren
}
// ServerConfig bündelt alle Konfigurationseinstellungen des Servers als Root-Struktur.
type ServerConfig struct {
Server ServerSettings `toml:"server"`
}
// ============================================================================
// CLIENT CONFIGURATION STRUCTURES
// ============================================================================
// BandSettings definiert die Struktur für ein einzelnes Frequenzband in der TOML.
type BandSettings struct {
Name string `toml:"name"` // Beschriftung des Buttons in der GUI (z.B. "2m")
Frequency int64 `toml:"frequency"` // Exakte Frequenz in Hertz (Hz)
}
// RotorSettings definiert die hardware- und systemspezifischen Parameter eines Rotors aus Client-Sicht.
type RotorSettings struct {
Type string `toml:"type"` // Gewünschter Typ des Rotors (z.B. "G-5500")
Port string `toml:"port"` // Lokaler Client-Port oder virtueller Pfad
HomeAzimuth float64 `toml:"home_azimuth"` // Standard-Ausrichtung für Azimut in Grad
HomeElevation float64 `toml:"home_elevation"` // Standard-Ausrichtung für Elevation in Grad
}
// ClientSettings definiert die Verbindungsparameter für die Fyne-GUIs.
type ClientSettings struct {
ServerAddress string `toml:"server_address"` // IP des gRPC-Servers (z.B. Tailscale-IP)
StationName string `toml:"station_name"` // Eigenes Rufzeichen (z.B. "DL1ABC")
RefreshRateMs int `toml:"refresh_rate_ms"` // UI-Intervall für Status-Updates
Rotor RotorSettings `toml:"rotor"` // Rotorspezifische Client-Einstellungen
Bands []BandSettings `toml:"bands"` // Dynamische Bandliste für die SDR-Schnellwahltasten
}
// ClientConfig bündelt alle Konfigurationseinstellungen des GUI-Clients als Root-Struktur.
type ClientConfig struct {
Client ClientSettings `toml:"client"`
}
// ============================================================================
// CONFIG LOADER FUNCTIONS
// ============================================================================
// LoadServerConfig lädt die Konfiguration für den Server-Daemon aus einer TOML-Datei.
// Falls die Datei fehlt, werden sichere Simulations-Dummys als Rückfallebene geladen.
func LoadServerConfig(path string) (*ServerConfig, error) {
// Erzeugung des Default-Server-Gerüsts (Werkseinstellungen)
cfg := &ServerConfig{
Server: ServerSettings{
ListenAddress: "0.0.0.0:50051",
HardwareRig: RigHardwareSettings{
Type: "Dummy",
Port: "Simulation",
Baud: 4800,
},
HardwareRotor: RotorHardwareSettings{
Type: "Dummy",
Port: "Simulation",
Baud: 9600,
},
Modules: []ADS1115Module{
{
Address: "0x48",
Labels: []string{"Hauptstrom 13.8V", "Logikbus 5V", "Relais-Schiene", "Rauschen (Frei)"},
},
},
},
}
// Falls keine Konfigurationsdatei vorhanden ist, nutzen wir direkt die Dummys
if _, err := os.Stat(path); os.IsNotExist(err) {
return cfg, nil
}
// Datei einlesen und parsen
if _, err := toml.DecodeFile(path, cfg); err != nil {
return nil, fmt.Errorf("fehler beim parsen der server-config.toml: %w", err)
}
return cfg, nil
}
// LoadClientConfig lädt die Konfiguration für die GUI-Clients aus einer TOML-Datei.
// Falls die Datei nicht existiert oder keine Bänder definiert sind, werden die bekannten
// Standardbänder (Default AFU-Bänder) im Speicher erzeugt, um leere GUIs zu verhindern.
func LoadClientConfig(path string) (*ClientConfig, error) {
// Erzeugung des Default-Client-Gerüsts inklusive aller klassischen Bänder
cfg := &ClientConfig{
Client: ClientSettings{
ServerAddress: "127.0.0.1:50051",
StationName: "DL-UNKNOWN",
RefreshRateMs: 250,
Rotor: RotorSettings{
Type: "Standard",
Port: "Simulation",
HomeAzimuth: 180.0, // Standardmäßig Süden
HomeElevation: 0.0, // Standardmäßig Horizont
},
// Fallback-Bänder mit korrigierten, 9-stelligen Hertz-Angaben für das 2m/70cm Band
Bands: []BandSettings{
{Name: "160m", Frequency: 1840000},
{Name: "80m", Frequency: 3600000},
{Name: "40m", Frequency: 7074000},
{Name: "20m", Frequency: 14074000},
{Name: "15m", Frequency: 21074000},
{Name: "10m", Frequency: 28074000},
{Name: "2m", Frequency: 145500000}, // 145.500.000 Hz (VHF)
{Name: "70cm", Frequency: 433500000}, // 433.500.000 Hz (UHF)
},
},
}
// Falls keine Konfigurationsdatei existiert, geben wir die Defaults direkt zurück
if _, err := os.Stat(path); os.IsNotExist(err) {
return cfg, nil
}
// TOML-Datei dekodieren und in unsere Struktur parsen
if _, err := toml.DecodeFile(path, cfg); err != nil {
return nil, fmt.Errorf("fehler beim parsen der client-config.toml: %w", err)
}
// Sicherheitsprüfung: Wenn die Datei existierte, aber die Sektion "bands" leer war,
// stellen wir die Standardbänder wieder her.
if len(cfg.Client.Bands) == 0 {
cfg.Client.Bands = []BandSettings{
{Name: "160m", Frequency: 1840000},
{Name: "80m", Frequency: 3600000},
{Name: "40m", Frequency: 7074000},
{Name: "20m", Frequency: 14074000},
{Name: "15m", Frequency: 21074000},
{Name: "10m", Frequency: 28074000},
{Name: "2m", Frequency: 145500000},
{Name: "70cm", Frequency: 433500000},
}
}
return cfg, nil
}