Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 92 additions & 88 deletions cmd/skyeye/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,57 +31,59 @@ import (
"github.com/dharmab/skyeye/pkg/coalitions"
"github.com/dharmab/skyeye/pkg/encyclopedia"
"github.com/dharmab/skyeye/pkg/locations"
"github.com/dharmab/skyeye/pkg/simpleradio"
"github.com/dharmab/skyeye/pkg/synthesizer/voices"
"github.com/ggerganov/whisper.cpp/bindings/go/pkg/whisper"
)

// Used for CLI configuration values.
var (
configFile string
logLevel string
logFormat string
enableTranscriptionLogging bool
acmiFile string
telemetryAddress string
telemetryConnectionTimeout time.Duration
telemetryPassword string
srsAddress string
srsConnectionTimeout time.Duration
srsExternalAWACSModePassword string
srsFrequencies []string
enableGRPC bool
grpcAddress string
grpcAPIKey string
controllerCallsign string
controllerCallsigns []string
coalitionName string
telemetryUpdateInterval time.Duration
recognizerName string
whisperModelPath string
recognizerLockPath string
openAIAPIKey string
voiceName string
useSystemVoice bool
mute bool
voiceSpeed float64
voiceVolume float64
voicePauseLength time.Duration
voiceLockPath string
enableAutomaticPicture bool
automaticPictureInterval time.Duration
enableThreatMonitoring bool
threatMonitoringInterval time.Duration
threatMonitoringRequiresSRS bool
mandatoryThreatRadiusNM float64
threatBRAABearingSpreadDeg float64
threatBRAARangeSpreadNM float64
enableTracing bool
discordWebhookID string
discordWebhookToken string
exitAfter time.Duration
enableTerrainDetection bool
locationsFile string
aircraftFile string
configFile string
logLevel string
logFormat string
enableTranscriptionLogging bool
acmiFile string
telemetryAddress string
telemetryConnectionTimeout time.Duration
telemetryPassword string
srsAddress string
srsConnectionTimeout time.Duration
srsExternalAWACSModePassword string
srsFrequencies []string
srsSplitTransmissionGracePeriod time.Duration
enableGRPC bool
grpcAddress string
grpcAPIKey string
controllerCallsign string
controllerCallsigns []string
coalitionName string
telemetryUpdateInterval time.Duration
recognizerName string
whisperModelPath string
recognizerLockPath string
openAIAPIKey string
voiceName string
useSystemVoice bool
mute bool
voiceSpeed float64
voiceVolume float64
voicePauseLength time.Duration
voiceLockPath string
enableAutomaticPicture bool
automaticPictureInterval time.Duration
enableThreatMonitoring bool
threatMonitoringInterval time.Duration
threatMonitoringRequiresSRS bool
mandatoryThreatRadiusNM float64
threatBRAABearingSpreadDeg float64
threatBRAARangeSpreadNM float64
enableTracing bool
discordWebhookID string
discordWebhookToken string
exitAfter time.Duration
enableTerrainDetection bool
locationsFile string
aircraftFile string
)

const (
Expand Down Expand Up @@ -114,6 +116,7 @@ func init() {
skyeye.Flags().DurationVar(&srsConnectionTimeout, "srs-connection-timeout", 10*time.Second, "Connection timeout for SRS client")
skyeye.Flags().StringVar(&srsExternalAWACSModePassword, "srs-eam-password", "", "SRS external AWACS mode password")
skyeye.Flags().StringSliceVar(&srsFrequencies, "srs-frequencies", []string{"251.0AM", "133.0AM", "30.0FM"}, "List of SRS frequencies to use")
skyeye.Flags().DurationVar(&srsSplitTransmissionGracePeriod, "srs-split-transmission-grace-period", simpleradio.DefaultSplitTransmissionGracePeriod, "How long to wait for more audio before treating a transmission as finished. Increase this if long transmissions are being split in two on a lossy network")

// DCS-gRPC
skyeye.Flags().BoolVar(&enableGRPC, "enable-grpc", false, "Enable DCS-gRPC features")
Expand Down Expand Up @@ -434,49 +437,50 @@ func run(_ *cobra.Command, _ []string) {
customAircraft := loadAircraft()

config := conf.Configuration{
ACMIFile: acmiFile,
TelemetryAddress: telemetryAddress,
TelemetryConnectionTimeout: telemetryConnectionTimeout,
TelemetryClientName: callsign,
TelemetryPassword: telemetryPassword,
SRSAddress: srsAddress,
SRSConnectionTimeout: srsConnectionTimeout,
SRSClientName: fmt.Sprintf("GCI %s [BOT]", callsign),
SRSExternalAWACSModePassword: srsExternalAWACSModePassword,
SRSFrequencies: parsedSRSFrequencies,
EnableTranscriptionLogging: enableTranscriptionLogging,
Callsign: callsign,
Coalition: coalition,
RadarSweepInterval: telemetryUpdateInterval,
Recognizer: conf.Recognizer(recognizerName),
RecognizerLock: recognizerLock,
WhisperModel: whisperModel,
OpenAIAPIKey: openAIAPIKey,
Voice: voice,
UseSystemVoice: useSystemVoice,
VoiceLock: voiceLock,
Mute: mute,
VoiceSpeed: voiceSpeed,
Volume: volume,
VoicePauseLength: voicePauseLength,
EnableAutomaticPicture: enableAutomaticPicture,
PictureBroadcastInterval: automaticPictureInterval,
EnableThreatMonitoring: enableThreatMonitoring,
ThreatMonitoringInterval: threatMonitoringInterval,
ThreatMonitoringRequiresSRS: threatMonitoringRequiresSRS,
MandatoryThreatRadius: unit.Length(mandatoryThreatRadiusNM) * unit.NauticalMile,
ThreatBRAABearingSpread: unit.Angle(threatBRAABearingSpreadDeg) * unit.Degree,
ThreatBRAARangeSpread: unit.Length(threatBRAARangeSpreadNM) * unit.NauticalMile,
EnableTracing: enableTracing,
DiscordWebhookID: discordWebhookID,
DiscorbWebhookToken: discordWebhookToken,
ExitAfter: exitAfter,
EnableGRPC: enableGRPC,
GRPCAddress: grpcAddress,
GRPCAPIKey: grpcAPIKey,
EnableTerrainDetection: enableTerrainDetection,
Locations: locs,
CustomAircraft: customAircraft,
ACMIFile: acmiFile,
TelemetryAddress: telemetryAddress,
TelemetryConnectionTimeout: telemetryConnectionTimeout,
TelemetryClientName: callsign,
TelemetryPassword: telemetryPassword,
SRSAddress: srsAddress,
SRSConnectionTimeout: srsConnectionTimeout,
SRSClientName: fmt.Sprintf("GCI %s [BOT]", callsign),
SRSExternalAWACSModePassword: srsExternalAWACSModePassword,
SRSFrequencies: parsedSRSFrequencies,
SRSSplitTransmissionGracePeriod: srsSplitTransmissionGracePeriod,
EnableTranscriptionLogging: enableTranscriptionLogging,
Callsign: callsign,
Coalition: coalition,
RadarSweepInterval: telemetryUpdateInterval,
Recognizer: conf.Recognizer(recognizerName),
RecognizerLock: recognizerLock,
WhisperModel: whisperModel,
OpenAIAPIKey: openAIAPIKey,
Voice: voice,
UseSystemVoice: useSystemVoice,
VoiceLock: voiceLock,
Mute: mute,
VoiceSpeed: voiceSpeed,
Volume: volume,
VoicePauseLength: voicePauseLength,
EnableAutomaticPicture: enableAutomaticPicture,
PictureBroadcastInterval: automaticPictureInterval,
EnableThreatMonitoring: enableThreatMonitoring,
ThreatMonitoringInterval: threatMonitoringInterval,
ThreatMonitoringRequiresSRS: threatMonitoringRequiresSRS,
MandatoryThreatRadius: unit.Length(mandatoryThreatRadiusNM) * unit.NauticalMile,
ThreatBRAABearingSpread: unit.Angle(threatBRAABearingSpreadDeg) * unit.Degree,
ThreatBRAARangeSpread: unit.Length(threatBRAARangeSpreadNM) * unit.NauticalMile,
EnableTracing: enableTracing,
DiscordWebhookID: discordWebhookID,
DiscorbWebhookToken: discordWebhookToken,
ExitAfter: exitAfter,
EnableGRPC: enableGRPC,
GRPCAddress: grpcAddress,
GRPCAPIKey: grpcAPIKey,
EnableTerrainDetection: enableTerrainDetection,
Locations: locs,
CustomAircraft: customAircraft,
}

log.Info().Msg("starting application")
Expand Down
9 changes: 9 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,15 @@
# on the aux radio. Meanwhile, the F-16 can only tune 225.000-399.975 on COM1 and
# 108.000-151.975 on COM2.
#srs-frequencies: 251.0AM,133.0AM,30.0FM
#
# How long the GCI waits for more audio before deciding a transmission has
# finished. SRS sends one packet every 40ms, so the default tolerates a fair
# amount of packet loss before a single transmission is split into two.
#
# Raise this if players report the GCI mishearing or ignoring the end of long
# transmissions on a lossy network. The cost is that the GCI waits slightly
# longer before replying.
#srs-split-transmission-grace-period: 300ms

# DCS-gRPC (optional)
# Enable DCS-gRPC features (requires https://github.com/DCS-gRPC/rust-server)
Expand Down
15 changes: 8 additions & 7 deletions internal/application/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,14 @@ func NewApplication(config conf.Configuration) (*Application, error) {
Int("modulationID", int(srs.ModulationAM)).
Msg("constructing SRS client")
srsClient, err := simpleradio.NewClient(srs.ClientConfiguration{
Address: config.SRSAddress,
ConnectionTimeout: config.SRSConnectionTimeout,
ClientName: config.SRSClientName,
ExternalAWACSModePassword: config.SRSExternalAWACSModePassword,
Coalition: config.Coalition,
Radios: radios,
Mute: config.Mute,
Address: config.SRSAddress,
ConnectionTimeout: config.SRSConnectionTimeout,
ClientName: config.SRSClientName,
ExternalAWACSModePassword: config.SRSExternalAWACSModePassword,
Coalition: config.Coalition,
Radios: radios,
Mute: config.Mute,
SplitTransmissionGracePeriod: config.SRSSplitTransmissionGracePeriod,
})
if err != nil {
return nil, fmt.Errorf("failed to construct application: %w", err)
Expand Down
4 changes: 4 additions & 0 deletions internal/conf/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ type Configuration struct {
SRSExternalAWACSModePassword string
// SRSFrequencies that the bot simultaneously receives and transmits on
SRSFrequencies []simpleradio.RadioFrequency
// SRSSplitTransmissionGracePeriod is how long to wait for another voice packet before treating
// a transmission as finished. Raising it makes the bot tolerate more packet loss before
// splitting one transmission into two, at the cost of responding slightly later.
SRSSplitTransmissionGracePeriod time.Duration
// EnableGRPC controls whether DCS-gRPC features are enabled
EnableGRPC bool
// GRPCAddress is the network address of the DCS-gRPC server (including port)
Expand Down
10 changes: 8 additions & 2 deletions pkg/simpleradio/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func NewClient(config types.ClientConfiguration) (*Client, error) {

receivers := make(map[types.Radio]*receiver, len(config.Radios))
for _, radio := range config.Radios {
receivers[radio] = &receiver{}
receivers[radio] = newReceiver(config.SplitTransmissionGracePeriod)
}

client := &Client{
Expand Down Expand Up @@ -208,10 +208,16 @@ func (c *Client) Run(ctx context.Context, wg *sync.WaitGroup) error {
return nil
}

func (c *Client) getPeerName(guid types.GUID) (string, bool) {
// getPeer looks up a peer's client info by GUID.
func (c *Client) getPeer(guid types.GUID) (types.ClientInfo, bool) {
c.clientsLock.RLock()
defer c.clientsLock.RUnlock()
info, ok := c.clients[guid]
return info, ok
}

func (c *Client) getPeerName(guid types.GUID) (string, bool) {
info, ok := c.getPeer(guid)
if ok {
return info.Name, true
}
Expand Down
Loading
Loading