Added UDP Socket, because now i can mock a external GPS on EUD and that's awesome

This commit is contained in:
Valmo Trindade
2025-06-17 01:40:26 -03:00
parent d4f6ddb0fa
commit 9fb8311aca
3 changed files with 143 additions and 15 deletions

View File

@@ -28,4 +28,4 @@ features = ["v4", "fast-rng", "macro-diagnostics"]
[lib] [lib]
name = "armatak" name = "armatak"
crate-type = ["cdylib"] crate-type = ["cdylib"]

View File

@@ -1,8 +1,8 @@
use arma_rs::{arma, Extension, Group}; use arma_rs::{arma, Extension, Group};
mod structs; mod structs;
mod tests; mod tests;
mod websocket; mod udp_socket;
mod cot_router; mod tcp_socket;
mod video_stream; mod video_stream;
mod cot; mod cot;
@@ -32,24 +32,25 @@ pub fn init() -> Extension {
log4rs::init_config(config).unwrap(); log4rs::init_config(config).unwrap();
Extension::build() Extension::build()
.group("websocket", Group::new()
.command("start", websocket::start)
.command("stop", websocket::stop)
.command("message", websocket::message)
.command("location", websocket::location)
)
.command("local_ip", utils::address::get_local_address) .command("local_ip", utils::address::get_local_address)
.command("uuid", utils::uuid::get_uuid) .command("uuid", utils::uuid::get_uuid)
.command("log", utils::log::log_info) .command("log", utils::log::log_info)
.group("udp_socket",
Group::new()
.command("start", udp_socket::start)
.command("send_payload", udp_socket::send_payload)
.command("send_gps_cot", udp_socket::send_gps_cot)
.command("stop", udp_socket::stop)
)
.group( .group(
"tcp_socket", "tcp_socket",
Group::new() Group::new()
.command("start", cot_router::start) .command("start", tcp_socket::start)
.command("send_payload", cot_router::send_payload) .command("send_payload", tcp_socket::send_payload)
.command("send_eud_cot", cot_router::send_eud_cot) .command("send_eud_cot", tcp_socket::send_eud_cot)
.command("send_marker_cot", cot_router::send_marker_cot) .command("send_marker_cot", tcp_socket::send_marker_cot)
.command("send_digital_pointer_cot", cot_router::send_digital_pointer_cot) .command("send_digital_pointer_cot", tcp_socket::send_digital_pointer_cot)
.command("stop", cot_router::stop) .command("stop", tcp_socket::stop)
) )
.group( .group(
"video_stream", "video_stream",

127
src/udp_socket.rs Normal file
View File

@@ -0,0 +1,127 @@
use arma_rs::Context;
use lazy_static::lazy_static;
use log::info;
use std::net::UdpSocket;
use std::sync::mpsc::{self, Receiver, Sender};
use std::sync::{Arc, Mutex};
use std::thread;
use crate::cot;
pub enum UdpCommand {
SendMessage(String, Context),
Stop,
}
pub struct UdpClient {
pub(crate) tx: Sender<UdpCommand>,
}
impl UdpClient {
pub fn start(&self, address: String, rx: Receiver<UdpCommand>, ctx: Context) {
if let Some(ref client) = *UDP_CLIENT.lock().unwrap() {
client.stop();
}
let udp_address = address.clone();
thread::spawn(move || {
let socket = match UdpSocket::bind(udp_address) {
Ok(s) => s,
Err(e) => {
let _ = ctx.callback_data(
"UDP SOCKET ERROR",
"Failed to bind UDP socket",
e.to_string(),
);
info!("Failed to bind UDP socket: {}", e);
return;
}
};
let _ = ctx.callback_data("UDP SOCKET", "UDP Socket ready", address.clone());
let mut running = true;
while running {
match rx.recv() {
Ok(UdpCommand::SendMessage(message, context)) => {
if let Err(e) = socket.send_to(message.as_bytes(), &address) {
info!("Failed to send UDP message: {}", e);
let _ = context.callback_data(
"UDP SOCKET ERROR",
"Failed to send UDP message",
e.to_string(),
);
}
}
Ok(UdpCommand::Stop) => {
running = false;
info!("Stopping UDP client.");
}
Err(error) => {
info!("Error receiving command: {}", error.to_string());
}
}
}
});
}
pub fn send_payload(&self, context: Context, payload: String) {
let tx = self.tx.clone();
thread::spawn(move || {
tx.send(UdpCommand::SendMessage(payload, context)).unwrap();
});
}
pub fn stop(&self) {
let tx = self.tx.clone();
thread::spawn(move || {
tx.send(UdpCommand::Stop).unwrap();
});
}
}
lazy_static! {
static ref UDP_CLIENT: Arc<Mutex<Option<UdpClient>>> = Arc::new(Mutex::new(None));
}
pub fn start(ctx: Context, address: String) -> &'static str {
let (tx, rx): (Sender<UdpCommand>, Receiver<UdpCommand>) = mpsc::channel();
let client = UdpClient { tx };
client.start(address, rx, ctx);
let mut client_guard = UDP_CLIENT.lock().unwrap();
*client_guard = Some(client);
"Starting UDP Client"
}
pub fn send_payload(ctx: Context, payload: String) -> &'static str {
if let Some(ref client) = *UDP_CLIENT.lock().unwrap() {
client.send_payload(ctx, payload);
} else {
let _ = ctx.callback_null("UDP SOCKET ERROR", "UDP Client is not running");
info!("UDP client is not running.");
}
"Sending payload to UDP server"
}
pub fn send_gps_cot(ctx: Context, cursor_over_time: cot::gps::ExternalPositionPayload) -> &'static str {
let payload = cursor_over_time.to_cot().convert_to_xml();
send_payload(ctx, payload);
"Sending GPS Cursor Over Time to UDP server"
}
pub fn stop(ctx: Context) -> &'static str {
if let Some(ref client) = *UDP_CLIENT.lock().unwrap() {
client.stop();
let _ = ctx.callback_null("UDP SOCKET", "UDP client stopped");
} else {
let _ = ctx.callback_null("UDP SOCKET ERROR", "UDP client is not running");
}
"Stopping UDP Client"
}