11#include " log.h"
22#include " mavsdk.h"
3+ #include " plugins/telemetry_server/telemetry_server.h"
34#include " mavlink_include.h"
45#include < atomic>
56#include < chrono>
910
1011using namespace mavsdk ;
1112
12- TEST (SystemTest, RawBytesHeartbeat )
13+ TEST (SystemTest, RawBytesSendReceive )
1314{
14- // Create a MAVSDK instance that will receive and respond to raw bytes
15- Mavsdk mavsdk_responder{Mavsdk::Configuration{ComponentType::Autopilot}};
15+ // Test 1: Verify subscribe_raw_bytes_to_be_sent captures outgoing messages
16+ Mavsdk mavsdk_autopilot{Mavsdk::Configuration{ComponentType::Autopilot}};
17+ ASSERT_EQ (mavsdk_autopilot.add_any_connection (" raw://" ), ConnectionResult::Success);
1618
17- // Add a raw connection - this will automatically enable heartbeats
18- ASSERT_EQ (mavsdk_responder.add_any_connection (" raw://" ), ConnectionResult::Success);
19+ auto telemetry_server = std::make_shared<TelemetryServer>(mavsdk_autopilot.server_component ());
1920
20- // Set up a promise/future to capture the heartbeat response
21+ // Set up to capture outgoing raw bytes
2122 auto prom = std::promise<void >();
2223 auto fut = prom.get_future ();
23- bool heartbeat_received = false ;
24+ std::atomic< bool > message_captured{ false } ;
2425
25- // Subscribe to raw bytes to capture the heartbeat response
26- auto handle = mavsdk_responder.subscribe_raw_bytes_to_be_sent (
27- [&prom, &heartbeat_received](const char * bytes, size_t length) {
28- LogInfo () << " Received " << length << " raw bytes" ;
29-
30- // Parse to check if this is a heartbeat
26+ // Subscribe to outgoing raw bytes
27+ auto handle = mavsdk_autopilot.subscribe_raw_bytes_to_be_sent (
28+ [&prom, &message_captured](const char * bytes, size_t length) {
29+ // Parse the bytes
3130 mavlink_message_t msg = {};
3231 mavlink_status_t status = {};
3332
3433 for (size_t i = 0 ; i < length; ++i) {
3534 if (mavlink_parse_char (
3635 MAVLINK_COMM_0, static_cast <uint8_t >(bytes[i]), &msg, &status)) {
37- if (msg.msgid == MAVLINK_MSG_ID_HEARTBEAT) {
38- LogInfo () << " Captured HEARTBEAT message from system " << (int )msg.sysid
39- << " , component " << (int )msg.compid ;
40- if (!heartbeat_received) {
41- heartbeat_received = true ;
42- prom.set_value ();
43- }
44- return ;
36+ LogInfo () << " Captured outgoing message ID " << msg.msgid ;
37+
38+ // Look for GLOBAL_POSITION_INT message
39+ if (msg.msgid == MAVLINK_MSG_ID_GLOBAL_POSITION_INT &&
40+ !message_captured.exchange (true )) {
41+ LogInfo () << " Captured GLOBAL_POSITION_INT being sent" ;
42+ prom.set_value ();
4543 }
4644 }
4745 }
@@ -50,43 +48,62 @@ TEST(SystemTest, RawBytesHeartbeat)
5048 // Give subscription time to be registered
5149 std::this_thread::sleep_for (std::chrono::milliseconds (100 ));
5250
53- // Create a raw heartbeat message
54- mavlink_message_t heartbeat_msg;
55- mavlink_heartbeat_t heartbeat;
56- heartbeat.type = MAV_TYPE_GCS;
57- heartbeat.autopilot = MAV_AUTOPILOT_INVALID;
58- heartbeat.base_mode = 0 ;
59- heartbeat.custom_mode = 0 ;
60- heartbeat.system_status = MAV_STATE_ACTIVE;
61- heartbeat.mavlink_version = 3 ;
62-
63- mavlink_msg_heartbeat_encode (245 , 190 , &heartbeat_msg, &heartbeat);
64-
65- // Serialize the heartbeat to raw bytes
66- std::vector<uint8_t > heartbeat_bytes (MAVLINK_MAX_PACKET_LEN);
67- uint16_t len = mavlink_msg_to_send_buffer (heartbeat_bytes.data (), &heartbeat_msg);
68- heartbeat_bytes.resize (len);
69-
70- // Send periodic heartbeats at 1 Hz to keep the system alive
71- std::atomic<bool > should_send_heartbeats{true };
72- std::thread heartbeat_thread ([&]() {
73- while (should_send_heartbeats) {
74- LogInfo () << " Sending raw heartbeat (" << len << " bytes)..." ;
75- mavsdk_responder.pass_received_raw_bytes (
76- reinterpret_cast <const char *>(heartbeat_bytes.data ()), len);
77- std::this_thread::sleep_for (std::chrono::seconds (1 ));
78- }
79- });
80-
81- // Wait for heartbeat response (responder should send heartbeats automatically)
82- // The subscription callback should be triggered when heartbeats are sent out
83- auto status = fut.wait_for (std::chrono::seconds (5 ));
84- ASSERT_EQ (status, std::future_status::ready)
85- << " Did not receive heartbeat response within timeout" ;
86-
87- // Stop sending heartbeats and clean up
88- should_send_heartbeats = false ;
89- heartbeat_thread.join ();
90-
91- mavsdk_responder.unsubscribe_raw_bytes_to_be_sent (handle);
51+ // Publish a position which should trigger outgoing message
52+ TelemetryServer::Position position{};
53+ position.latitude_deg = 47.3977 ;
54+ position.longitude_deg = 8.5456 ;
55+ position.absolute_altitude_m = 488 .0f ;
56+ position.relative_altitude_m = 10 .0f ;
57+
58+ TelemetryServer::VelocityNed velocity{};
59+ velocity.north_m_s = 0 .0f ;
60+ velocity.east_m_s = 0 .0f ;
61+ velocity.down_m_s = 0 .0f ;
62+
63+ TelemetryServer::Heading heading{};
64+ heading.heading_deg = 90 .0f ;
65+
66+ LogInfo () << " Publishing position via TelemetryServer..." ;
67+ telemetry_server->publish_position (position, velocity, heading);
68+
69+ // Wait for the message to be captured
70+ auto result = fut.wait_for (std::chrono::seconds (2 ));
71+ ASSERT_EQ (result, std::future_status::ready)
72+ << " Did not capture GLOBAL_POSITION_INT through raw bytes subscription" ;
73+
74+ mavsdk_autopilot.unsubscribe_raw_bytes_to_be_sent (handle);
75+
76+ // Test 2: Verify pass_received_raw_bytes processes incoming messages
77+ Mavsdk mavsdk_gcs{Mavsdk::Configuration{ComponentType::GroundStation}};
78+ ASSERT_EQ (mavsdk_gcs.add_any_connection (" raw://" ), ConnectionResult::Success);
79+
80+ // Create a PING message
81+ mavlink_message_t ping_msg;
82+ mavlink_ping_t ping;
83+ ping.time_usec = 123456 ;
84+ ping.seq = 42 ;
85+ ping.target_system = 0 ; // Broadcast
86+ ping.target_component = 0 ;
87+
88+ mavlink_msg_ping_encode (1 , 1 , &ping_msg, &ping);
89+
90+ // Serialize to bytes
91+ std::vector<uint8_t > ping_bytes (MAVLINK_MAX_PACKET_LEN);
92+ uint16_t len = mavlink_msg_to_send_buffer (ping_bytes.data (), &ping_msg);
93+ ping_bytes.resize (len);
94+
95+ LogInfo () << " Passing " << len << " raw bytes (PING) into MAVSDK..." ;
96+
97+ // This should be processed and create a system
98+ mavsdk_gcs.pass_received_raw_bytes (reinterpret_cast <const char *>(ping_bytes.data ()), len);
99+
100+ // Give it time to process
101+ std::this_thread::sleep_for (std::chrono::milliseconds (200 ));
102+
103+ // Verify a system was created from the ping
104+ auto systems = mavsdk_gcs.systems ();
105+ ASSERT_FALSE (systems.empty ()) << " No system was created from received raw bytes" ;
106+ ASSERT_EQ (systems[0 ]->get_system_id (), 1 ) << " System ID mismatch" ;
107+ LogInfo () << " Successfully created system from raw bytes with ID "
108+ << systems[0 ]->get_system_id ();
92109}
0 commit comments