• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mavlink / MAVSDK / 21724056693

05 Feb 2026 06:42PM UTC coverage: 49.043% (+0.08%) from 48.959%
21724056693

push

github

web-flow
core: fix MAVLink message sequence (#2762)

* core: fix MAVLink message sequence

The MAVLink headers use an inline function to get the mavlink channel,
so we end up having separate sequence numbers in different translation
units. By defining this function ourselves and linking it later, we make
sure to use the same sequence everywhere.

This should fix seq numbering that's invalid (per component).

We also add a system test to actually test this.

* system_tests: fixup thread sanitizer issues

* system_tests: use TCP for seq to avoid drops

51 of 56 new or added lines in 6 files covered. (91.07%)

6 existing lines in 5 files now uncovered.

18367 of 37451 relevant lines covered (49.04%)

672.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/mavsdk/plugins/events/event_handler.cpp
1

2
#include "event_handler.h"
3

4
#include <utility>
5

6
namespace mavsdk {
7

8
EventHandler::EventHandler(
×
9
    const std::string& profile,
10
    handle_event_f handle_event_cb,
11
    health_and_arming_checks_updated_f health_and_arming_checks_updated_cb,
12
    SystemImpl& system_impl,
13
    uint8_t system_id,
14
    uint8_t component_id) :
×
15
    _handle_event_cb(std::move(handle_event_cb)),
×
16
    _health_and_arming_checks_updated_cb(std::move(health_and_arming_checks_updated_cb)),
×
17
    _compid(component_id),
×
18
    _system_impl(system_impl)
×
19
{
20
    auto error_cb = [component_id, this](int num_events_lost) {
×
21
        _health_and_arming_checks.reset();
×
22
        LogWarn() << "Events got lost:" << num_events_lost << "comp_id:" << component_id;
×
23
    };
×
24

25
    const auto timeout_cb = [this](int timeout_ms) {
×
26
        if (_timer_cookie != 0) {
×
27
            _system_impl.unregister_timeout_handler(_timer_cookie);
×
28
            _timer_cookie = 0;
×
29
        }
30
        if (timeout_ms > 0) {
×
31
            _timer_cookie = _system_impl.register_timeout_handler(
×
32
                [this]() {
×
33
                    const std::lock_guard lg{_protocol_mutex};
×
34
                    _protocol->timerEvent();
×
35
                },
×
36
                timeout_ms / 1000.0);
37
        }
38
    };
×
39

40
    const auto send_request_cb = [this](const mavlink_request_event_t& msg) {
×
NEW
41
        _system_impl.queue_message([&](MavlinkAddress mavlink_address, uint8_t channel) {
×
42
            mavlink_message_t message;
NEW
43
            mavlink_msg_request_event_encode_chan(
×
NEW
44
                mavlink_address.system_id, mavlink_address.component_id, channel, &message, &msg);
×
NEW
45
            return message;
×
46
        });
UNCOV
47
    };
×
48

49
    _parser.setProfile(profile);
×
50

51
    _parser.formatters().url = [](const std::string& /*content*/, const std::string& link) {
×
52
        return link;
×
53
    };
×
54

55
    events::ReceiveProtocol::Callbacks callbacks{
56
        error_cb,
57
        send_request_cb,
58
        std::bind(&EventHandler::got_event, this, std::placeholders::_1),
×
59
        timeout_cb};
×
60
    _protocol = std::make_unique<events::ReceiveProtocol>(
×
61
        callbacks,
62
        _system_impl.get_own_system_id(),
×
63
        _system_impl.get_own_component_id(),
×
64
        system_id,
65
        component_id);
×
66

67
    _system_impl.register_mavlink_message_handler_with_compid(
×
68
        MAVLINK_MSG_ID_EVENT,
69
        _compid,
×
70
        std::bind(&EventHandler::handle_mavlink_message, this, std::placeholders::_1),
×
71
        &_message_handler_cookies[0]);
×
72
    _system_impl.register_mavlink_message_handler_with_compid(
×
73
        MAVLINK_MSG_ID_CURRENT_EVENT_SEQUENCE,
74
        _compid,
×
75
        std::bind(&EventHandler::handle_mavlink_message, this, std::placeholders::_1),
×
76
        &_message_handler_cookies[1]);
×
77
    _system_impl.register_mavlink_message_handler_with_compid(
×
78
        MAVLINK_MSG_ID_RESPONSE_EVENT_ERROR,
79
        _compid,
×
80
        std::bind(&EventHandler::handle_mavlink_message, this, std::placeholders::_1),
×
81
        &_message_handler_cookies[2]);
×
82
}
×
83
EventHandler::~EventHandler()
×
84
{
85
    if (_timer_cookie != 0) {
×
86
        _system_impl.unregister_timeout_handler(_timer_cookie);
×
87
    }
88
    // Use blocking version to ensure any in-flight callbacks complete before destruction.
89
    for (size_t i = 0; i < _message_handler_cookies.size(); ++i) {
×
90
        _system_impl.unregister_all_mavlink_message_handlers_blocking(&_message_handler_cookies[i]);
×
91
    }
92
}
×
93
void EventHandler::set_metadata(const std::string& metadata_json)
×
94
{
95
    if (_parser.loadDefinitions(metadata_json)) {
×
96
        if (_parser.hasDefinitions()) {
×
97
            // do we have queued events?
98
            for (const auto& event : _pending_events) {
×
99
                got_event(event);
×
100
            }
101
            _pending_events.clear();
×
102
        }
103
    } else {
104
        LogErr() << "Failed to load events JSON metadata file";
×
105
    }
106
}
×
107

108
std::optional<int> EventHandler::get_mode_group(uint32_t custom_mode) const
×
109
{
110
    events::parser::Parser::NavigationModeGroups groups = _parser.navigationModeGroups(_compid);
×
111
    for (auto group_iter : groups.groups) {
×
112
        if (group_iter.second.find(custom_mode) != group_iter.second.end()) {
×
113
            return group_iter.first;
×
114
        }
115
    }
×
116
    return std::nullopt;
×
117
}
×
118
void EventHandler::handle_mavlink_message(const mavlink_message_t& message)
×
119
{
120
    const std::lock_guard lg{_protocol_mutex};
×
121
    _protocol->processMessage(message);
×
122
}
×
123
void EventHandler::got_event(const mavlink_event_t& event)
×
124
{
125
    if (!_parser.hasDefinitions()) {
×
126
        if (_pending_events.size() > 50) { // Limit size (not expected to hit that limit)
×
127
            _pending_events.clear();
×
128
        }
129
        if (_pending_events.empty()) { // Print only for the first to avoid spamming
×
130
            LogDebug() << "No metadata, queuing event, ID: " << event.id
×
131
                       << ", num pending: " << _pending_events.size();
×
132
        }
133
        _pending_events.push_back(event);
×
134
        return;
×
135
    }
136

137
    std::unique_ptr<events::parser::ParsedEvent> parsed_event =
138
        _parser.parse(events::EventType(event));
×
139
    if (parsed_event == nullptr) {
×
140
        LogWarn() << "Got Event without known metadata: ID:" << event.id << "comp id:" << _compid;
×
141
        return;
×
142
    }
143

144
    //    LogDebug() << "Got Event: ID: " << parsed_event->id() << " namespace: " <<
145
    //    parsed_event->eventNamespace().c_str() <<
146
    //        " name: " << parsed_event->name().c_str() << " msg: " <<
147
    //        parsed_event->message().c_str();
148

149
    if (_health_and_arming_checks.handleEvent(*parsed_event)) {
×
150
        _health_and_arming_checks_valid = true;
×
151
        _health_and_arming_checks_updated_cb();
×
152
    }
153
    _handle_event_cb(std::move(parsed_event));
×
154
}
×
155
} // namespace mavsdk
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc