config files
This commit is contained in:
39
Cargo.lock
generated
39
Cargo.lock
generated
@@ -2285,7 +2285,9 @@ dependencies = [
|
|||||||
"clap",
|
"clap",
|
||||||
"guardian_commands",
|
"guardian_commands",
|
||||||
"guardian_core",
|
"guardian_core",
|
||||||
|
"serde",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"toml",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3872,6 +3874,15 @@ dependencies = [
|
|||||||
"syn 2.0.41",
|
"syn 2.0.41",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "0.6.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_urlencoded"
|
name = "serde_urlencoded"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
@@ -4249,11 +4260,26 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.8.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_edit 0.21.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_datetime"
|
name = "toml_datetime"
|
||||||
version = "0.6.5"
|
version = "0.6.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
|
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_edit"
|
name = "toml_edit"
|
||||||
@@ -4277,6 +4303,19 @@ dependencies = [
|
|||||||
"winnow",
|
"winnow",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.21.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap 2.1.0",
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tonic"
|
name = "tonic"
|
||||||
version = "0.10.2"
|
version = "0.10.2"
|
||||||
|
|||||||
@@ -47,5 +47,7 @@ shlex = "1.2"
|
|||||||
bevy.workspace = true
|
bevy.workspace = true
|
||||||
clap.workspace = true
|
clap.workspace = true
|
||||||
tokio.workspace = true
|
tokio.workspace = true
|
||||||
|
serde.workspace = true
|
||||||
guardian_commands.workspace = true
|
guardian_commands.workspace = true
|
||||||
guardian_core.workspace = true
|
guardian_core.workspace = true
|
||||||
|
toml = "0.8"
|
||||||
|
|||||||
13
config.toml
Normal file
13
config.toml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[srs]
|
||||||
|
server = "127.0.0.1:5002"
|
||||||
|
|
||||||
|
[grpc]
|
||||||
|
url = "http://127.0.0.1:50051/"
|
||||||
|
|
||||||
|
[stt]
|
||||||
|
url = "http://192.168.0.2:3000/"
|
||||||
|
|
||||||
|
[channels.Overlord1-1]
|
||||||
|
frequency = 251000000
|
||||||
|
modulation = "Am"
|
||||||
|
voice = "David"
|
||||||
@@ -8,10 +8,12 @@ use bevy::{
|
|||||||
reflect::{std_traits::ReflectDefault, Reflect},
|
reflect::{std_traits::ReflectDefault, Reflect},
|
||||||
utils::AHasher,
|
utils::AHasher,
|
||||||
};
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Reflect, Resource, Clone)]
|
#[derive(Reflect, Resource, Clone, Deserialize, Serialize)]
|
||||||
#[reflect(Resource, Default, Debug)]
|
#[reflect(Resource, Default, Debug)]
|
||||||
pub struct GrpcBaseUrl {
|
pub struct GrpcBaseUrl {
|
||||||
|
#[serde(skip)]
|
||||||
hash: u64,
|
hash: u64,
|
||||||
url: Cow<'static, str>,
|
url: Cow<'static, str>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ mod player;
|
|||||||
mod position;
|
mod position;
|
||||||
mod side;
|
mod side;
|
||||||
mod srs_socket_addr;
|
mod srs_socket_addr;
|
||||||
|
mod stt_base_url;
|
||||||
mod unit_type;
|
mod unit_type;
|
||||||
|
|
||||||
pub use awacs::*;
|
pub use awacs::*;
|
||||||
@@ -20,4 +21,5 @@ pub use player::*;
|
|||||||
pub use position::*;
|
pub use position::*;
|
||||||
pub use side::*;
|
pub use side::*;
|
||||||
pub use srs_socket_addr::*;
|
pub use srs_socket_addr::*;
|
||||||
|
pub use stt_base_url::*;
|
||||||
pub use unit_type::*;
|
pub use unit_type::*;
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
use bevy::ecs::system::Resource;
|
use bevy::ecs::system::Resource;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Resource, Clone)]
|
#[derive(Debug, Resource, Clone, Deserialize, Serialize)]
|
||||||
pub struct SrsSocketAddr(SocketAddr);
|
pub struct SrsSocketAddr(SocketAddr);
|
||||||
|
|
||||||
impl Default for SrsSocketAddr {
|
impl Default for SrsSocketAddr {
|
||||||
|
|||||||
81
crates/guardian_core/src/components/stt_base_url.rs
Normal file
81
crates/guardian_core/src/components/stt_base_url.rs
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
|
hash::{Hash, Hasher},
|
||||||
|
};
|
||||||
|
|
||||||
|
use bevy::{
|
||||||
|
ecs::{reflect::ReflectResource, system::Resource},
|
||||||
|
reflect::{std_traits::ReflectDefault, Reflect},
|
||||||
|
utils::AHasher,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Reflect, Resource, Clone, Deserialize, Serialize)]
|
||||||
|
#[reflect(Resource, Default, Debug)]
|
||||||
|
pub struct SttBaseUrl {
|
||||||
|
#[serde(skip)]
|
||||||
|
hash: u64,
|
||||||
|
url: Cow<'static, str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for SttBaseUrl {
|
||||||
|
fn default() -> Self {
|
||||||
|
SttBaseUrl::new("http://127.0.0.1:3000/")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SttBaseUrl {
|
||||||
|
/// Creates a new [`SttBaseUrl`] from any string-like type.
|
||||||
|
///
|
||||||
|
/// The internal hash will be computed immediately.
|
||||||
|
pub fn new(url: impl Into<Cow<'static, str>>) -> Self {
|
||||||
|
let url = url.into();
|
||||||
|
let mut url = SttBaseUrl { url, hash: 0 };
|
||||||
|
url.update_hash();
|
||||||
|
url
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the entity's url.
|
||||||
|
///
|
||||||
|
/// The internal hash will be re-computed.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn set(&mut self, url: impl Into<Cow<'static, str>>) {
|
||||||
|
*self = SttBaseUrl::new(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates the url of the entity in place.
|
||||||
|
///
|
||||||
|
/// This will allocate a new string if the url was previously
|
||||||
|
/// created from a borrow.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn mutate<F: FnOnce(&mut String)>(&mut self, f: F) {
|
||||||
|
f(self.url.to_mut());
|
||||||
|
self.update_hash();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the url of the entity as a `&str`.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn as_str(&self) -> &str {
|
||||||
|
&self.url
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_hash(&mut self) {
|
||||||
|
let mut hasher = AHasher::default();
|
||||||
|
self.url.hash(&mut hasher);
|
||||||
|
self.hash = hasher.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for SttBaseUrl {
|
||||||
|
#[inline(always)]
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
std::fmt::Display::fmt(&self.url, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for SttBaseUrl {
|
||||||
|
#[inline(always)]
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
std::fmt::Debug::fmt(&self.url, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ mod voice_codec;
|
|||||||
mod voice_command;
|
mod voice_command;
|
||||||
|
|
||||||
use guardian_commands::{call::parse_call, ConsoleCommandEntered, ConsoleConfiguration};
|
use guardian_commands::{call::parse_call, ConsoleCommandEntered, ConsoleConfiguration};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use simsearch::SimSearch;
|
use simsearch::SimSearch;
|
||||||
pub use voice_command::VoiceCommand;
|
pub use voice_command::VoiceCommand;
|
||||||
|
|
||||||
@@ -104,6 +105,7 @@ fn listen_srs(
|
|||||||
>,
|
>,
|
||||||
tokio: Res<TokioResource>,
|
tokio: Res<TokioResource>,
|
||||||
addr: Res<SrsSocketAddr>,
|
addr: Res<SrsSocketAddr>,
|
||||||
|
stt_url: Res<SttBaseUrl>,
|
||||||
) {
|
) {
|
||||||
for (ent, id, callsign, position, mut radio, red, blue) in units.iter_mut() {
|
for (ent, id, callsign, position, mut radio, red, blue) in units.iter_mut() {
|
||||||
let addr: SocketAddr = addr.clone().into();
|
let addr: SocketAddr = addr.clone().into();
|
||||||
@@ -159,6 +161,8 @@ fn listen_srs(
|
|||||||
|
|
||||||
let frequency = radio.frequency;
|
let frequency = radio.frequency;
|
||||||
let id = *id;
|
let id = *id;
|
||||||
|
let voice = radio.voice;
|
||||||
|
let stt_url = stt_url.as_str().to_string();
|
||||||
radio.handle = Some(tokio.0.spawn(async move {
|
radio.handle = Some(tokio.0.spawn(async move {
|
||||||
let tcp = TcpStream::connect(addr).await?;
|
let tcp = TcpStream::connect(addr).await?;
|
||||||
|
|
||||||
@@ -246,7 +250,7 @@ fn listen_srs(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(data) = voice_handle.recv() => {
|
Some(data) = voice_handle.recv() => {
|
||||||
frames.push(synthesize(data.as_str()).await?).await;
|
frames.push(synthesize(data.as_str(), &voice).await?).await;
|
||||||
}
|
}
|
||||||
Some(Ok(data)) = voice_stream.next() => {
|
Some(Ok(data)) = voice_stream.next() => {
|
||||||
// Collect voice packets
|
// Collect voice packets
|
||||||
@@ -280,7 +284,7 @@ fn listen_srs(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(message) = whisper("http://192.168.0.2:3000/", &wav_data).await else {
|
let Some(message) = whisper(&stt_url, &wav_data).await else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -487,6 +491,22 @@ fn handle_voice_command(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone, Copy, Debug, Deserialize, Serialize)]
|
||||||
|
pub enum Voice {
|
||||||
|
#[default]
|
||||||
|
David,
|
||||||
|
Zira,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Voice {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::David => write!(f, "David"),
|
||||||
|
Self::Zira => write!(f, "Zira"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct ClientHandler(Receiver<Client>);
|
pub struct ClientHandler(Receiver<Client>);
|
||||||
|
|
||||||
@@ -494,6 +514,7 @@ pub struct ClientHandler(Receiver<Client>);
|
|||||||
pub struct Radio {
|
pub struct Radio {
|
||||||
pub frequency: u64, // the way srs wants it
|
pub frequency: u64, // the way srs wants it
|
||||||
pub modulation: Modulation,
|
pub modulation: Modulation,
|
||||||
|
pub voice: Voice,
|
||||||
sguid: String,
|
sguid: String,
|
||||||
voice_sink: Option<Sender<VoiceMessage>>,
|
voice_sink: Option<Sender<VoiceMessage>>,
|
||||||
message_sink: Option<Sender<MessageRequest>>,
|
message_sink: Option<Sender<MessageRequest>>,
|
||||||
@@ -501,10 +522,12 @@ pub struct Radio {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Radio {
|
impl Radio {
|
||||||
pub fn new(frequency: u64, modulation: Modulation) -> Self {
|
pub fn new(frequency: u64, modulation: impl Into<Modulation>, voice: Voice) -> Self {
|
||||||
|
let modulation = modulation.into();
|
||||||
Self {
|
Self {
|
||||||
frequency,
|
frequency,
|
||||||
modulation,
|
modulation,
|
||||||
|
voice,
|
||||||
sguid: create_sguid(),
|
sguid: create_sguid(),
|
||||||
voice_sink: None,
|
voice_sink: None,
|
||||||
message_sink: None,
|
message_sink: None,
|
||||||
|
|||||||
@@ -129,9 +129,8 @@ impl Default for Radio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize_repr, Deserialize_repr)]
|
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Serialize_repr, Deserialize_repr)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Default)]
|
|
||||||
pub enum Modulation {
|
pub enum Modulation {
|
||||||
Am = 0,
|
Am = 0,
|
||||||
Fm = 1,
|
Fm = 1,
|
||||||
|
|||||||
@@ -7,14 +7,15 @@ use windows::core::HSTRING;
|
|||||||
use windows::Media::SpeechSynthesis::SpeechSynthesizer;
|
use windows::Media::SpeechSynthesis::SpeechSynthesizer;
|
||||||
use windows::Storage::Streams::DataReader;
|
use windows::Storage::Streams::DataReader;
|
||||||
|
|
||||||
|
use crate::srs::Voice;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct WinConfig {
|
pub struct WinConfig {
|
||||||
pub voice: Option<String>,
|
pub voice: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WinConfig {
|
impl WinConfig {
|
||||||
pub fn new() -> Self {
|
pub fn new(voice: &str) -> Self {
|
||||||
let voice = "David"; // for now
|
|
||||||
Self {
|
Self {
|
||||||
voice: Some(voice.to_string()),
|
voice: Some(voice.to_string()),
|
||||||
}
|
}
|
||||||
@@ -23,8 +24,8 @@ impl WinConfig {
|
|||||||
|
|
||||||
static MUTEX: Mutex<()> = Mutex::const_new(());
|
static MUTEX: Mutex<()> = Mutex::const_new(());
|
||||||
|
|
||||||
pub async fn synthesize(text: &str) -> Result<Vec<Vec<u8>>, WinError> {
|
pub async fn synthesize(text: &str, voice: &Voice) -> Result<Vec<Vec<u8>>, WinError> {
|
||||||
let config = WinConfig::new();
|
let config = WinConfig::new(&voice.to_string());
|
||||||
// Note, there does not seem to be a way to explicitly set 16000kHz, 16 audio bits per
|
// Note, there does not seem to be a way to explicitly set 16000kHz, 16 audio bits per
|
||||||
// sample and mono channel.
|
// sample and mono channel.
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ pub fn set_tripwire(
|
|||||||
callsign: Query<&Callsign>,
|
callsign: Query<&Callsign>,
|
||||||
) {
|
) {
|
||||||
let Some(pilot) = &cmd.pilot else {
|
let Some(pilot) = &cmd.pilot else {
|
||||||
eprintln!("no pilot");
|
|
||||||
return; // no pilot
|
return; // no pilot
|
||||||
};
|
};
|
||||||
let Some(operator) = &cmd.operator else {
|
let Some(operator) = &cmd.operator else {
|
||||||
|
|||||||
95
src/config.rs
Normal file
95
src/config.rs
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
|
use bevy::ecs::system::Resource;
|
||||||
|
use guardian_core::{
|
||||||
|
components::{GrpcBaseUrl, SrsSocketAddr, SttBaseUrl},
|
||||||
|
srs::{Modulation as SrsModulation, Voice},
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Resource, Clone, Debug, Deserialize, Serialize, Default)]
|
||||||
|
pub struct Channels(pub HashMap<String, ChannelConfig>);
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize, Default)]
|
||||||
|
pub struct Config {
|
||||||
|
pub srs: SrsConfig,
|
||||||
|
pub grpc: GrpcBaseUrl,
|
||||||
|
pub stt: SttBaseUrl,
|
||||||
|
pub channels: Channels,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
|
||||||
|
pub struct SrsConfig {
|
||||||
|
pub server: SrsSocketAddr,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize, Default)]
|
||||||
|
pub struct ChannelConfig {
|
||||||
|
pub frequency: u64,
|
||||||
|
pub modulation: Modulation, // 0=AM, 1=FM?
|
||||||
|
pub voice: Voice,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<PathBuf> for Config {
|
||||||
|
type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
|
||||||
|
|
||||||
|
fn try_from(value: PathBuf) -> Result<Self, Self::Error> {
|
||||||
|
use std::io::Read;
|
||||||
|
let mut config = std::fs::File::open(value)?;
|
||||||
|
let mut config_str = String::new();
|
||||||
|
config.read_to_string(&mut config_str)?;
|
||||||
|
Ok(toml::from_str(&config_str)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
pub fn load(file: PathBuf) -> Result<Self, Box<dyn std::error::Error + Send + Sync + 'static>> {
|
||||||
|
if file.exists() {
|
||||||
|
return file.try_into();
|
||||||
|
}
|
||||||
|
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
let mut defaults = Config::default();
|
||||||
|
|
||||||
|
defaults.channels.0.insert(
|
||||||
|
"Overlord1-1".to_string(),
|
||||||
|
ChannelConfig {
|
||||||
|
frequency: 251000000,
|
||||||
|
modulation: Modulation::Am,
|
||||||
|
voice: Voice::David,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// write the file
|
||||||
|
std::fs::File::create(file)?.write_all(toml::to_string_pretty(&defaults)?.as_bytes())?;
|
||||||
|
|
||||||
|
Ok(defaults)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Deserialize, Serialize, Default)]
|
||||||
|
pub enum Modulation {
|
||||||
|
#[default]
|
||||||
|
Am,
|
||||||
|
Fm,
|
||||||
|
Intercom,
|
||||||
|
Disabled,
|
||||||
|
HaveQuick,
|
||||||
|
Satcom,
|
||||||
|
Mids,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Modulation> for SrsModulation {
|
||||||
|
fn from(value: Modulation) -> Self {
|
||||||
|
match value {
|
||||||
|
Modulation::Am => SrsModulation::Am,
|
||||||
|
Modulation::Fm => SrsModulation::Fm,
|
||||||
|
Modulation::Intercom => SrsModulation::Intercom,
|
||||||
|
Modulation::Disabled => SrsModulation::Disabled,
|
||||||
|
Modulation::HaveQuick => SrsModulation::HaveQuick,
|
||||||
|
Modulation::Satcom => SrsModulation::Satcom,
|
||||||
|
Modulation::Mids => SrsModulation::Mids,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
45
src/main.rs
45
src/main.rs
@@ -1,5 +1,6 @@
|
|||||||
mod braa;
|
mod braa;
|
||||||
mod commands;
|
mod commands;
|
||||||
|
mod config;
|
||||||
mod tripwire;
|
mod tripwire;
|
||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
@@ -7,44 +8,62 @@ use bevy::{
|
|||||||
ecs::{
|
ecs::{
|
||||||
entity::Entity,
|
entity::Entity,
|
||||||
query::{With, Without},
|
query::{With, Without},
|
||||||
system::{Commands, Query},
|
system::{Commands, Query, Res},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use commands::CommandsPlugin;
|
use commands::CommandsPlugin;
|
||||||
|
use config::{Channels, Config};
|
||||||
use guardian_core::{
|
use guardian_core::{
|
||||||
components::{Awacs, Callsign},
|
components::{Awacs, Callsign},
|
||||||
srs::{Modulation, Radio},
|
srs::Radio,
|
||||||
DefaultPlugins, TokioResource,
|
DefaultPlugins, TokioResource,
|
||||||
};
|
};
|
||||||
use tokio::runtime::Handle;
|
use tokio::runtime::Handle;
|
||||||
use tripwire::TripwirePlugin;
|
use tripwire::TripwirePlugin;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
|
let config = Config::load("config.toml".into())?;
|
||||||
|
|
||||||
App::new()
|
App::new()
|
||||||
|
.insert_resource(config.srs.server)
|
||||||
|
.insert_resource(config.stt)
|
||||||
|
.insert_resource(config.grpc)
|
||||||
|
.insert_resource(config.channels)
|
||||||
.insert_resource(TokioResource(Handle::current()))
|
.insert_resource(TokioResource(Handle::current()))
|
||||||
.add_plugins(DefaultPlugins)
|
.add_plugins(DefaultPlugins)
|
||||||
.add_plugins(TripwirePlugin)
|
.add_plugins(TripwirePlugin)
|
||||||
.add_plugins(CommandsPlugin)
|
.add_plugins(CommandsPlugin)
|
||||||
.add_systems(Update, give_awacs_radio)
|
.add_systems(Update, give_awacs_radio)
|
||||||
.run();
|
.run();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn give_awacs_radio(
|
fn give_awacs_radio(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
|
channels: Res<Channels>,
|
||||||
units: Query<(Entity, &Callsign), (With<Awacs>, Without<Radio>)>,
|
units: Query<(Entity, &Callsign), (With<Awacs>, Without<Radio>)>,
|
||||||
) {
|
) {
|
||||||
for (ent, callsign) in units.iter() {
|
for (ent, callsign) in units.iter() {
|
||||||
if callsign.as_str() == "Overlord1-1" {
|
let Some(channel) = channels.0.get(callsign.as_str()) else {
|
||||||
commands
|
continue; // not configured for this unit
|
||||||
.entity(ent)
|
};
|
||||||
.insert(Radio::new(251000000, Modulation::Am));
|
|
||||||
}
|
|
||||||
|
|
||||||
if callsign.as_str() == "Magic1-1" {
|
commands.entity(ent).insert(Radio::new(
|
||||||
commands
|
channel.frequency,
|
||||||
.entity(ent)
|
channel.modulation,
|
||||||
.insert(Radio::new(266000000, Modulation::Am));
|
channel.voice,
|
||||||
}
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// // Initial player tripwire? get from some db so player doesnt need to redo it everytime
|
||||||
|
// fn add_tripwire(mut commands: Commands, players: Query<Entity, Added<Player>>) {
|
||||||
|
// for ent in players.iter() {
|
||||||
|
// commands.entity(ent).insert(Tripwire {
|
||||||
|
// range: 2.0,
|
||||||
|
// reported: vec![],
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use bevy::{
|
|||||||
ecs::{
|
ecs::{
|
||||||
component::Component,
|
component::Component,
|
||||||
entity::Entity,
|
entity::Entity,
|
||||||
query::{Added, With, Without},
|
query::{With, Without},
|
||||||
system::{Commands, Query},
|
system::{Commands, Query},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -23,16 +23,6 @@ impl Plugin for TripwirePlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// this will be on a tripwire command event (from srs), instead of Added<Player>, not everyone may want it; opt-in over opt-out
|
|
||||||
// fn add_tripwire(mut commands: Commands, players: Query<Entity, Added<Player>>) {
|
|
||||||
// for ent in players.iter() {
|
|
||||||
// commands.entity(ent).insert(Tripwire {
|
|
||||||
// range: 2.0,
|
|
||||||
// reported: vec![],
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn tripwire(
|
fn tripwire(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
awacs: Query<(Entity, &Callsign, &Radio), (With<Awacs>, With<Blue>, With<Radio>)>,
|
awacs: Query<(Entity, &Callsign, &Radio), (With<Awacs>, With<Blue>, With<Radio>)>,
|
||||||
|
|||||||
Reference in New Issue
Block a user