Function create_cot_track

Source
pub fn create_cot_track(
    speed_over_ground: f64,
    course_over_ground: f64,
) -> Element
Expand description

Creates a CoT <track> element.

§Arguments

  • speed_over_ground: Speed over ground, typically in knots but the unit isn’t enforced by this primitive. CoT standard often implies m/s, but TAK clients might interpret based on context or preferences.
  • course_over_ground: Course over ground in decimal degrees from True North.

§Returns

An xmltree::Element representing the CoT track.

Examples found in repository?
examples/cot_sender_example.rs (line 86)
14async fn main() -> Result<(), Box<dyn std::error::Error>> {
15    let listen_addr_str = "127.0.0.1:8087"; // Address for our mock server
16    let target_addr: SocketAddr = listen_addr_str.parse()?;
17
18    println!(
19        "[Sender Example] Will send a CoT message to a mock server at: {}",
20        target_addr
21    );
22
23    // 1. Spawn a mock TCP server to receive the message
24    let server_handle = tokio::spawn(async move {
25        match TcpListener::bind(target_addr).await {
26            Ok(listener) => {
27                println!(
28                    "[Mock Server] Listening on {} for one connection...",
29                    target_addr
30                );
31                match timeout(Duration::from_secs(10), listener.accept()).await {
32                    Ok(Ok((mut stream, client_addr))) => {
33                        println!("[Mock Server] Accepted connection from: {}", client_addr);
34                        let mut buffer = Vec::new();
35                        match timeout(Duration::from_secs(5), stream.read_to_end(&mut buffer)).await
36                        {
37                            Ok(Ok(_bytes_read)) => {
38                                if let Ok(received_str) = String::from_utf8(buffer) {
39                                    println!(
40                                        "[Mock Server] Received data:\n{}",
41                                        received_str.trim()
42                                    );
43                                } else {
44                                    eprintln!("[Mock Server] Received non-UTF8 data.");
45                                }
46                            }
47                            Ok(Err(e)) => {
48                                eprintln!("[Mock Server] Error reading from stream: {}", e);
49                            }
50                            Err(_) => {
51                                eprintln!("[Mock Server] Timeout reading from stream.");
52                            }
53                        }
54                    }
55                    Ok(Err(e)) => {
56                        eprintln!("[Mock Server] Error accepting connection: {}", e);
57                    }
58                    Err(_) => {
59                        eprintln!("[Mock Server] Timeout accepting connection.");
60                    }
61                }
62            }
63            Err(e) => {
64                eprintln!("[Mock Server] Error binding listener: {}", e);
65            }
66        }
67    });
68
69    // Give the server a moment to start (especially in CI or slower environments)
70    tokio::time::sleep(Duration::from_millis(100)).await;
71
72    // 2. Construct a CoT message
73    let callsign = "RusTAKClient";
74    let uid = "RusTAK-Sender-01";
75    let current_time = cot_time(None);
76    let stale_time_offset = Some(120); // 2 minutes
77
78    let root = create_cot_root_fields(
79        uid,
80        &current_time,
81        &current_time, // Assuming start time is current time for a PLI
82        stale_time_offset,
83        "a-f-G-E-V-C", // Friendly, Ground, Emitter, Vehicle, Combat Vehicle
84    );
85    let point = create_cot_point(34.0522, -118.2437, 100.0, 10.0, 10.0); // Lat, Lon, HAE, CE, LE
86    let track = create_cot_track(25.0, 45.0); // Speed (e.g., m/s), Course (degrees)
87
88    let mut uid_map = HashMap::new();
89    uid_map.insert("Droid".to_string(), callsign.to_string());
90
91    let cot_event_element = create_cot_atom_message(callsign, root, point, track, uid_map.clone());
92
93    // Serialize the Element to XML bytes
94    let mut cot_xml_bytes = Vec::new();
95    let mut config = EmitterConfig::new();
96    config.perform_indent = true; // Make it readable if printed
97    cot_event_element.write_with_config(&mut cot_xml_bytes, config)?;
98
99    println!(
100        "[Sender Example] Constructed CoT message:\n{}",
101        String::from_utf8_lossy(&cot_xml_bytes)
102    );
103
104    // 3. Set up MPSC channel for the tcp_sender
105    let (tx_cot_bytes, rx_cot_bytes) = mpsc::channel::<Vec<u8>>(32);
106
107    // 4. Spawn the tcp_sender
108    println!(
109        "[Sender Example] Spawning tcp_sender to connect to {}",
110        target_addr
111    );
112    let sender_task = tokio::spawn(tcp_sender(target_addr, rx_cot_bytes));
113
114    // 5. Send the CoT message bytes
115    if tx_cot_bytes.send(cot_xml_bytes.clone()).await.is_err() {
116        eprintln!(
117            "[Sender Example] Failed to send CoT message to tcp_sender channel. Receiver dropped?"
118        );
119        // If the send fails, the sender_task might not have started correctly or exited early.
120    } else {
121        println!("[Sender Example] CoT message sent to tcp_sender channel.");
122    }
123
124    // Close the sender channel to signal tcp_sender to complete its work and shut down.
125    drop(tx_cot_bytes);
126
127    // 6. Wait for tasks to complete (optional, but good for clean exit)
128    match timeout(Duration::from_secs(5), sender_task).await {
129        Ok(Ok(Ok(()))) => println!("[Sender Example] tcp_sender task completed successfully."),
130        Ok(Ok(Err(e))) => eprintln!("[Sender Example] tcp_sender task failed: {}", e),
131        Ok(Err(e)) => eprintln!(
132            "[Sender Example] tcp_sender task panicked or was cancelled: {}",
133            e
134        ),
135        Err(_) => eprintln!("[Sender Example] Timeout waiting for tcp_sender task."),
136    }
137
138    match timeout(Duration::from_secs(15), server_handle).await {
139        // Give server more time
140        Ok(Ok(())) => println!("[Sender Example] Mock server task completed."),
141        Ok(Err(e)) => eprintln!(
142            "[Sender Example] Mock server task panicked or was cancelled: {}",
143            e
144        ),
145        Err(_) => eprintln!("[Sender Example] Timeout waiting for mock server task."),
146    }
147
148    println!("[Sender Example] Done.");
149    Ok(())
150}