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

mavlink / MAVSDK / 11962955425

21 Nov 2024 10:45PM UTC coverage: 43.573% (+4.9%) from 38.691%
11962955425

Pull #2386

github

web-flow
Merge b41070aab into c963c5161
Pull Request #2386: camera: support multiple cameras within one instance

1353 of 2024 new or added lines in 47 files covered. (66.85%)

47 existing lines in 7 files now uncovered.

13858 of 31804 relevant lines covered (43.57%)

289.11 hits per line

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

70.48
/src/mavsdk/core/mavlink_parameter_server.cpp
1
#include "mavlink_parameter_server.h"
2
#include "mavlink_address.h"
3
#include "mavlink_parameter_helper.h"
4
#include "plugin_base.h"
5
#include <cassert>
6
#include <limits>
7

8
namespace mavsdk {
9

10
MavlinkParameterServer::MavlinkParameterServer(
88✔
11
    Sender& sender,
12
    MavlinkMessageHandler& message_handler,
13
    std::optional<std::map<std::string, ParamValue>> optional_param_values) :
88✔
14
    _sender(sender),
88✔
15
    _message_handler(message_handler)
88✔
16
{
17
    if (const char* env_p = std::getenv("MAVSDK_PARAMETER_DEBUGGING")) {
88✔
18
        if (std::string(env_p) == "1") {
×
19
            LogDebug() << "Parameter debugging is on.";
×
20
            _parameter_debugging = true;
×
21
        }
22
    }
23

24
    // Populate the parameter set before the first communication, if provided by the user.
25
    if (optional_param_values.has_value()) {
88✔
26
        const auto& param_values = optional_param_values.value();
×
27
        for (const auto& [key, value] : param_values) {
×
28
            const auto result = provide_server_param(key, value);
×
NEW
29
            if (result != Result::Ok) {
×
30
                LogDebug() << "Cannot add parameter:" << key << ":" << value << " " << result;
×
31
            }
32
        }
33
    }
34

35
    _message_handler.register_one(
88✔
36
        MAVLINK_MSG_ID_PARAM_SET,
37
        [this](const mavlink_message_t& message) { process_param_set(message); },
4✔
38
        this);
39

40
    _message_handler.register_one(
88✔
41
        MAVLINK_MSG_ID_PARAM_EXT_SET,
42
        [this](const mavlink_message_t& message) { process_param_ext_set(message); },
6✔
43
        this);
44

45
    _message_handler.register_one(
88✔
46
        MAVLINK_MSG_ID_PARAM_REQUEST_READ,
47
        [this](const mavlink_message_t& message) { process_param_request_read(message); },
26✔
48
        this);
49

50
    _message_handler.register_one(
88✔
51
        MAVLINK_MSG_ID_PARAM_REQUEST_LIST,
52
        [this](const mavlink_message_t& message) { process_param_request_list(message); },
2✔
53
        this);
54

55
    _message_handler.register_one(
88✔
56
        MAVLINK_MSG_ID_PARAM_EXT_REQUEST_READ,
57
        [this](const mavlink_message_t& message) { process_param_ext_request_read(message); },
32✔
58
        this);
59

60
    _message_handler.register_one(
88✔
61
        MAVLINK_MSG_ID_PARAM_EXT_REQUEST_LIST,
62
        [this](const mavlink_message_t& message) { process_param_ext_request_list(message); },
2✔
63
        this);
64
}
88✔
65

66
MavlinkParameterServer::~MavlinkParameterServer()
88✔
67
{
68
    _message_handler.unregister_all(this);
88✔
69
}
88✔
70

71
MavlinkParameterServer::Result
72
MavlinkParameterServer::provide_server_param(const std::string& name, const ParamValue& param_value)
65✔
73
{
74
    if (name.size() > PARAM_ID_LEN) {
65✔
75
        LogErr() << "Error: param name too long";
×
76
        return Result::ParamNameTooLong;
×
77
    }
78
    if (param_value.is<std::string>()) {
65✔
79
        const auto s = param_value.get<std::string>();
8✔
80
        if (s.size() > sizeof(mavlink_param_ext_set_t::param_value)) {
8✔
81
            LogErr() << "Error: param value too long";
×
82
            return Result::ParamValueTooLong;
×
83
        }
84
    }
8✔
85
    std::lock_guard<std::mutex> lock(_all_params_mutex);
65✔
86
    // first we try to add it as a new parameter
87
    switch (_param_cache.add_new_param(name, param_value)) {
65✔
88
        case MavlinkParameterCache::AddNewParamResult::Ok:
50✔
89
            return Result::Ok;
50✔
90
        case MavlinkParameterCache::AddNewParamResult::AlreadyExists:
15✔
91
            // then, to not change the public api behaviour, try updating its value.
92
            switch (_param_cache.update_existing_param(name, param_value)) {
15✔
93
                case MavlinkParameterCache::UpdateExistingParamResult::Ok:
15✔
94
                    find_and_call_subscriptions_value_changed(name, param_value);
15✔
95
                    {
96
                        auto new_work = std::make_shared<WorkItem>(
15✔
97
                            name,
98
                            param_value,
99
                            WorkItemValue{
15✔
100
                                std::numeric_limits<std::uint16_t>::max(),
101
                                std::numeric_limits<std::uint16_t>::max(),
102
                                _last_extended});
15✔
103
                        _work_queue.push_back(new_work);
15✔
104
                    }
15✔
105
                    return Result::OkExistsAlready;
15✔
NEW
106
                case MavlinkParameterCache::UpdateExistingParamResult::MissingParam:
×
NEW
107
                    return Result::ParamNotFound;
×
NEW
108
                case MavlinkParameterCache::UpdateExistingParamResult::WrongType:
×
NEW
109
                    return Result::WrongType;
×
NEW
110
                default:
×
NEW
111
                    LogErr() << "Unknown update_existing_param result";
×
NEW
112
                    assert(false);
×
113
                    return Result::Unknown;
114
            }
115
        case MavlinkParameterCache::AddNewParamResult::TooManyParams:
×
116
            return Result::TooManyParams;
×
117
        default:
×
118
            LogErr() << "Unknown add_new_param result";
×
119
            assert(false);
×
120
            return Result::Unknown;
121
    }
122
}
65✔
123

124
MavlinkParameterServer::Result
125
MavlinkParameterServer::provide_server_param_float(const std::string& name, float value)
8✔
126
{
127
    ParamValue param_value;
8✔
128
    param_value.set(value);
8✔
129
    return provide_server_param(name, param_value);
8✔
130
}
8✔
131

132
MavlinkParameterServer::Result
133
MavlinkParameterServer::provide_server_param_int(const std::string& name, int32_t value)
49✔
134
{
135
    ParamValue param_value;
49✔
136
    param_value.set(value);
49✔
137
    return provide_server_param(name, param_value);
49✔
138
}
49✔
139

140
MavlinkParameterServer::Result MavlinkParameterServer::provide_server_param_custom(
8✔
141
    const std::string& name, const std::string& value)
142
{
143
    ParamValue param_value;
8✔
144
    param_value.set(value);
8✔
145
    return provide_server_param(name, param_value);
8✔
146
}
8✔
147

148
std::map<std::string, ParamValue> MavlinkParameterServer::retrieve_all_server_params()
2✔
149
{
150
    std::lock_guard<std::mutex> lock(_all_params_mutex);
2✔
151
    std::map<std::string, ParamValue> map_copy;
2✔
152
    for (auto entry : _param_cache.all_parameters(true)) {
6✔
153
        map_copy[entry.id] = entry.value;
4✔
154
    }
6✔
155
    return map_copy;
2✔
156
}
2✔
157

158
template<class T>
159
std::pair<MavlinkParameterServer::Result, T>
160
MavlinkParameterServer::retrieve_server_param(const std::string& name)
6✔
161
{
162
    std::lock_guard<std::mutex> lock(_all_params_mutex);
6✔
163
    const auto param_opt = _param_cache.param_by_id(name, true);
6✔
164
    if (!param_opt.has_value()) {
6✔
165
        return {Result::NotFound, {}};
×
166
    }
167
    // This parameter exists, check its type
168
    const auto& param = param_opt.value();
6✔
169
    if (param.value.is<T>()) {
6✔
170
        return {Result::Ok, param.value.get<T>()};
6✔
171
    }
172
    return {Result::WrongType, {}};
×
173
}
6✔
174

175
std::pair<MavlinkParameterServer::Result, float>
176
MavlinkParameterServer::retrieve_server_param_float(const std::string& name)
2✔
177
{
178
    return retrieve_server_param<float>(name);
2✔
179
}
180

181
std::pair<MavlinkParameterServer::Result, std::string>
182
MavlinkParameterServer::retrieve_server_param_custom(const std::string& name)
2✔
183
{
184
    return retrieve_server_param<std::string>(name);
2✔
185
}
186

187
std::pair<MavlinkParameterServer::Result, int32_t>
188
MavlinkParameterServer::retrieve_server_param_int(const std::string& name)
2✔
189
{
190
    return retrieve_server_param<int32_t>(name);
2✔
191
}
192

193
void MavlinkParameterServer::process_param_set_internally(
10✔
194
    const std::string& param_id, const ParamValue& value_to_set, bool extended)
195
{
196
    if (_parameter_debugging) {
10✔
NEW
197
        LogDebug() << "Param set request" << (extended ? " extended" : "") << ": " << param_id
×
NEW
198
                   << " with " << value_to_set;
×
199
    }
200
    std::lock_guard<std::mutex> lock(_all_params_mutex);
10✔
201
    // for checking if the update actually changed the value
202
    const auto opt_before_update = _param_cache.param_by_id(param_id, extended);
10✔
203
    const auto result = _param_cache.update_existing_param(param_id, value_to_set);
10✔
204
    const auto param_count = _param_cache.count(extended);
10✔
205

206
    switch (result) {
10✔
207
        case MavlinkParameterCache::UpdateExistingParamResult::MissingParam: {
×
208
            // We do not allow clients to add a new parameter to the parameter set, only to update
209
            // existing parameters. In this case, we cannot even respond with anything, since this
210
            // parameter simply does not exist.
211
            LogErr() << "Got param_set for non-existing parameter:" << param_id;
×
212
            return;
×
213
        }
214
        case MavlinkParameterCache::UpdateExistingParamResult::WrongType: {
×
215
            // Non-extended: we respond with the unchanged parameter.
216
            // Extended: we nack with failed.
217

218
            LogErr() << "Got param_set with wrong type for parameter: " << param_id;
×
219

220
            const auto curr_param = _param_cache.param_by_id(param_id, extended).value();
×
221

222
            if (extended) {
×
223
                auto new_work = std::make_shared<WorkItem>(
×
224
                    curr_param.id, curr_param.value, WorkItemAck{PARAM_ACK_FAILED});
×
225
                _work_queue.push_back(new_work);
×
226

227
            } else {
×
228
                auto new_work = std::make_shared<WorkItem>(
×
229
                    curr_param.id,
230
                    curr_param.value,
231
                    WorkItemValue{curr_param.index, param_count, extended});
×
232
                _work_queue.push_back(new_work);
×
233
            }
×
234
            return;
×
235
        }
×
236
        case MavlinkParameterCache::UpdateExistingParamResult::Ok: {
10✔
237
            LogWarn() << "Update existing params!";
10✔
238
            const auto updated_parameter = _param_cache.param_by_id(param_id, extended).value();
20✔
239
            // The param set doesn't differentiate between an update that actually changed the value
240
            // e.g. 0 to 1 and an update that had no effect e.g. 0 to 0.
241
            if (opt_before_update.has_value() &&
20✔
242
                opt_before_update.value().value == updated_parameter.value) {
10✔
243
                LogDebug() << "Update had no effect: " << updated_parameter.value;
1✔
244
            } else {
245
                LogDebug() << "Updated param to :" << updated_parameter.value;
9✔
246
                find_and_call_subscriptions_value_changed(
9✔
247
                    updated_parameter.id, updated_parameter.value);
248
            }
249
            if (extended) {
10✔
250
                auto new_work = std::make_shared<WorkItem>(
6✔
251
                    updated_parameter.id, updated_parameter.value, WorkItemAck{PARAM_ACK_ACCEPTED});
6✔
252
                _work_queue.push_back(new_work);
6✔
253
            } else {
6✔
254
                auto new_work = std::make_shared<WorkItem>(
4✔
255
                    updated_parameter.id,
256
                    updated_parameter.value,
257
                    WorkItemValue{updated_parameter.index, param_count, extended});
4✔
258
                _work_queue.push_back(new_work);
4✔
259
            }
4✔
260
        } break;
10✔
261
    }
262
}
10✔
263

264
void MavlinkParameterServer::process_param_set(const mavlink_message_t& message)
4✔
265
{
266
    mavlink_param_set_t set_request{};
4✔
267
    mavlink_msg_param_set_decode(&message, &set_request);
4✔
268
    if (!target_matches(set_request.target_system, set_request.target_component, false)) {
4✔
269
        log_target_mismatch(set_request.target_system, set_request.target_component);
×
270
        return;
×
271
    }
272
    const std::string safe_param_id = extract_safe_param_id(set_request.param_id);
4✔
273

274
    if (safe_param_id.empty()) {
4✔
275
        LogWarn() << "Got ill-formed param_set message (param_id empty)";
×
276
        return;
×
277
    }
278

279
    ParamValue value_to_set;
4✔
280
    if (!value_to_set.set_from_mavlink_param_set_bytewise(set_request)) {
4✔
281
        // This should never happen, the type enum in the message is unknown.
282
        LogWarn() << "Invalid Param Set Request: " << safe_param_id;
×
283
        return;
×
284
    }
285
    process_param_set_internally(safe_param_id, value_to_set, false);
4✔
286
}
4✔
287

288
void MavlinkParameterServer::process_param_ext_set(const mavlink_message_t& message)
6✔
289
{
290
    mavlink_param_ext_set_t set_request{};
6✔
291
    mavlink_msg_param_ext_set_decode(&message, &set_request);
6✔
292
    if (!target_matches(set_request.target_system, set_request.target_component, false)) {
6✔
293
        log_target_mismatch(set_request.target_system, set_request.target_component);
×
294
        return;
×
295
    }
296
    const std::string safe_param_id = extract_safe_param_id(set_request.param_id);
6✔
297

298
    if (safe_param_id.empty()) {
6✔
299
        LogWarn() << "Got ill-formed param_ext_set message (param_id empty)";
×
300
        return;
×
301
    }
302

303
    ParamValue value_to_set;
6✔
304
    if (!value_to_set.set_from_mavlink_param_ext_set(set_request)) {
6✔
305
        // This should never happen, the type enum in the message is unknown.
306
        LogWarn() << "Invalid Param Set ext Request: " << safe_param_id;
×
307
        return;
×
308
    }
309

310
    process_param_set_internally(safe_param_id, value_to_set, true);
6✔
311
}
6✔
312

313
void MavlinkParameterServer::process_param_request_read(const mavlink_message_t& message)
26✔
314
{
315
    if (_parameter_debugging) {
26✔
316
        LogDebug() << "process param_request_read";
×
317
    }
318
    mavlink_param_request_read_t read_request{};
26✔
319
    mavlink_msg_param_request_read_decode(&message, &read_request);
26✔
320
    if (!target_matches(read_request.target_system, read_request.target_component, true)) {
26✔
321
        log_target_mismatch(read_request.target_system, read_request.target_component);
×
322
        return;
×
323
    }
324

325
    const auto param_id_or_index =
26✔
326
        extract_request_read_param_identifier(read_request.param_index, read_request.param_id);
26✔
327

328
    std::visit(
26✔
329
        overloaded{
26✔
330
            [&](std::monostate) { LogWarn() << "Ill-formed param_request_read message"; },
×
331
            [&](std::uint16_t index) {
1✔
332
                if (_parameter_debugging) {
1✔
333
                    LogDebug() << "found index: " << index;
×
334
                }
335
                internal_process_param_request_read_by_index(index, false);
1✔
336
            },
1✔
337
            [&](const std::string& id) {
25✔
338
                if (_parameter_debugging) {
25✔
339
                    LogDebug() << "found id: " << id;
×
340
                }
341
                internal_process_param_request_read_by_id(id, false);
25✔
342
            }},
25✔
343
        param_id_or_index);
344
}
26✔
345

346
void MavlinkParameterServer::process_param_ext_request_read(const mavlink_message_t& message)
32✔
347
{
348
    mavlink_param_ext_request_read_t read_request{};
32✔
349
    mavlink_msg_param_ext_request_read_decode(&message, &read_request);
32✔
350
    if (!target_matches(read_request.target_system, read_request.target_component, true)) {
32✔
351
        log_target_mismatch(read_request.target_system, read_request.target_component);
×
352
        return;
×
353
    }
354
    const auto param_id_or_index =
32✔
355
        extract_request_read_param_identifier(read_request.param_index, read_request.param_id);
32✔
356

357
    std::visit(
32✔
358
        overloaded{
32✔
359
            [&](std::monostate) { LogWarn() << "Ill-formed param_request_read message"; },
×
360
            [&](std::uint16_t index) {
2✔
361
                if (_parameter_debugging) {
2✔
362
                    LogDebug() << "found index: " << index;
×
363
                }
364
                internal_process_param_request_read_by_index(index, true);
2✔
365
            },
2✔
366
            [&](const std::string& id) {
30✔
367
                if (_parameter_debugging) {
30✔
368
                    LogDebug() << "found id: " << id;
×
369
                }
370
                internal_process_param_request_read_by_id(id, true);
30✔
371
            }},
30✔
372
        param_id_or_index);
373
}
32✔
374

375
void MavlinkParameterServer::internal_process_param_request_read_by_id(
55✔
376
    const std::string& id, const bool extended)
377
{
378
    std::lock_guard<std::mutex> lock(_all_params_mutex);
55✔
379
    const auto param_opt = _param_cache.param_by_id(id, extended);
55✔
380

381
    if (!param_opt.has_value()) {
55✔
382
        LogWarn() << "Ignoring request_read message " << (extended ? "extended " : "")
36✔
383
                  << "- param name not found: " << id;
36✔
384
        return;
12✔
385
    }
386
    const auto& param = param_opt.value();
43✔
387
    const auto param_count = _param_cache.count(extended);
43✔
388
    assert(param.index < param_count);
43✔
389
    auto new_work = std::make_shared<WorkItem>(
43✔
390
        param.id, param.value, WorkItemValue{param.index, param_count, extended});
43✔
391
    _work_queue.push_back(new_work);
43✔
392

393
    _last_extended = extended;
43✔
394
}
67✔
395

396
void MavlinkParameterServer::internal_process_param_request_read_by_index(
3✔
397
    std::uint16_t index, bool extended)
398
{
399
    std::lock_guard<std::mutex> lock(_all_params_mutex);
3✔
400
    const auto param_opt = _param_cache.param_by_index(index, extended);
3✔
401

402
    if (!param_opt.has_value()) {
3✔
403
        LogWarn() << "Ignoring request_read message " << (extended ? "extended " : "")
×
404
                  << "- param index not found: " << index;
×
405
        return;
×
406
    }
407
    const auto& param = param_opt.value();
3✔
408
    const auto param_count = _param_cache.count(extended);
3✔
409

410
    assert(param.index < param_count);
3✔
411
    auto new_work = std::make_shared<WorkItem>(
3✔
412
        param.id, param.value, WorkItemValue{param.index, param_count, extended});
3✔
413
    _work_queue.push_back(new_work);
3✔
414
}
3✔
415

416
void MavlinkParameterServer::process_param_request_list(const mavlink_message_t& message)
2✔
417
{
418
    mavlink_param_request_list_t list_request{};
2✔
419
    mavlink_msg_param_request_list_decode(&message, &list_request);
2✔
420
    if (!target_matches(list_request.target_system, list_request.target_component, true)) {
2✔
421
        log_target_mismatch(list_request.target_system, list_request.target_component);
×
422
        return;
×
423
    }
424
    broadcast_all_parameters(false);
2✔
425
}
426

427
void MavlinkParameterServer::process_param_ext_request_list(const mavlink_message_t& message)
2✔
428
{
429
    if (_parameter_debugging) {
2✔
430
        LogDebug() << "process param_ext_request_list";
×
431
    }
432

433
    mavlink_param_ext_request_list_t ext_list_request{};
2✔
434
    mavlink_msg_param_ext_request_list_decode(&message, &ext_list_request);
2✔
435
    if (!target_matches(ext_list_request.target_system, ext_list_request.target_component, true)) {
2✔
436
        log_target_mismatch(ext_list_request.target_system, ext_list_request.target_component);
×
437
        return;
×
438
    }
439
    broadcast_all_parameters(true);
2✔
440
}
441

442
void MavlinkParameterServer::broadcast_all_parameters(const bool extended)
4✔
443
{
444
    std::lock_guard<std::mutex> lock(_all_params_mutex);
4✔
445
    const auto all_params = _param_cache.all_parameters(extended);
4✔
446
    if (_parameter_debugging) {
4✔
447
        LogDebug() << "broadcast_all_parameters " << (extended ? "extended" : "") << ": "
×
448
                   << all_params.size();
×
449
    }
450
    for (const auto& parameter : all_params) {
34✔
451
        if (_parameter_debugging) {
30✔
452
            LogDebug() << "sending param:" << parameter.id;
×
453
        }
454
        auto new_work = std::make_shared<WorkItem>(
30✔
455
            parameter.id,
30✔
456
            parameter.value,
30✔
457
            WorkItemValue{parameter.index, static_cast<uint16_t>(all_params.size()), extended});
30✔
458
        _work_queue.push_back(new_work);
30✔
459
    }
30✔
460
}
4✔
461

462
void MavlinkParameterServer::do_work()
19,894✔
463
{
464
    LockedQueue<WorkItem>::Guard work_queue_guard(_work_queue);
19,894✔
465
    auto work = work_queue_guard.get_front();
19,757✔
466
    if (!work) {
19,679✔
467
        return;
19,633✔
468
    }
469
    const auto param_id_message_buffer = param_id_to_message_buffer(work->param_id);
101✔
470

471
    std::visit(
202✔
472
        overloaded{
101✔
473
            [&](const WorkItemValue& specific) {
95✔
474
                if (specific.extended) {
95✔
475
                    const auto buf = work->param_value.get_128_bytes();
65✔
476
                    if (!_sender.queue_message(
130✔
477
                            [&](MavlinkAddress mavlink_address, uint8_t channel) {
65✔
478
                                mavlink_message_t message;
479
                                mavlink_msg_param_ext_value_pack_chan(
260✔
480
                                    mavlink_address.system_id,
65✔
481
                                    mavlink_address.component_id,
65✔
482
                                    channel,
483
                                    &message,
484
                                    param_id_message_buffer.data(),
130✔
485
                                    buf.data(),
65✔
486
                                    work->param_value.get_mav_param_ext_type(),
65✔
487
                                    specific.param_count,
65✔
488
                                    specific.param_index);
65✔
489
                                return message;
65✔
490
                            })) {
491
                        LogErr() << "Error: Send message failed";
×
492
                        work_queue_guard.pop_front();
×
493
                        return;
×
494
                    }
495
                } else {
496
                    LogWarn() << "sending not extended message";
30✔
497
                    float param_value;
30✔
498
                    if (_sender.autopilot() == Autopilot::ArduPilot) {
30✔
499
                        param_value = work->param_value.get_4_float_bytes_cast();
×
500
                    } else {
501
                        param_value = work->param_value.get_4_float_bytes_bytewise();
30✔
502
                    }
503
                    if (!_sender.queue_message(
30✔
504
                            [&](MavlinkAddress mavlink_address, uint8_t channel) {
30✔
505
                                mavlink_message_t message;
506
                                mavlink_msg_param_value_pack_chan(
90✔
507
                                    mavlink_address.system_id,
30✔
508
                                    mavlink_address.component_id,
30✔
509
                                    channel,
510
                                    &message,
511
                                    param_id_message_buffer.data(),
30✔
512
                                    param_value,
30✔
513
                                    work->param_value.get_mav_param_type(),
30✔
514
                                    specific.param_count,
30✔
515
                                    specific.param_index);
30✔
516
                                return message;
30✔
517
                            })) {
518
                        LogErr() << "Error: Send message failed";
×
519
                        work_queue_guard.pop_front();
×
520
                        return;
×
521
                    }
522
                }
523
                work_queue_guard.pop_front();
95✔
524
            },
525
            [&](const WorkItemAck& specific) {
6✔
526
                auto buf = work->param_value.get_128_bytes();
6✔
527
                if (!_sender.queue_message([&](MavlinkAddress mavlink_address, uint8_t channel) {
12✔
528
                        mavlink_message_t message;
529
                        mavlink_msg_param_ext_ack_pack_chan(
24✔
530
                            mavlink_address.system_id,
6✔
531
                            mavlink_address.component_id,
6✔
532
                            channel,
533
                            &message,
534
                            param_id_message_buffer.data(),
12✔
535
                            buf.data(),
6✔
536
                            work->param_value.get_mav_param_ext_type(),
6✔
537
                            specific.param_ack);
6✔
538
                        return message;
6✔
539
                    })) {
540
                    LogErr() << "Error: Send message failed";
×
541
                    work_queue_guard.pop_front();
×
542
                    return;
×
543
                }
544
                work_queue_guard.pop_front();
6✔
545
            }},
546
        work->work_item_variant);
101✔
547
}
39,424✔
548

549
std::ostream& operator<<(std::ostream& str, const MavlinkParameterServer::Result& result)
×
550
{
551
    switch (result) {
×
NEW
552
        case MavlinkParameterServer::Result::Ok:
×
NEW
553
            return str << "Ok";
×
NEW
554
        case MavlinkParameterServer::Result::OkExistsAlready:
×
NEW
555
            return str << "OkExistsAlready";
×
556
        case MavlinkParameterServer::Result::WrongType:
×
557
            return str << "WrongType";
×
558
        case MavlinkParameterServer::Result::ParamNameTooLong:
×
559
            return str << "ParamNameTooLong";
×
560
        case MavlinkParameterServer::Result::NotFound:
×
561
            return str << "NotFound";
×
562
        case MavlinkParameterServer::Result::ParamValueTooLong:
×
563
            return str << ":ParamValueTooLong";
×
564
        default:
×
565
            return str << "UnknownError";
×
566
    }
567
}
568

569
bool MavlinkParameterServer::target_matches(
72✔
570
    const uint16_t target_sys_id, const uint16_t target_comp_id, bool is_request)
571
{
572
    // See: https://mavlink.io/en/services/parameter.html#multi-system-and-multi-component-support
573

574
    if (target_sys_id != _sender.get_own_system_id()) {
72✔
575
        return false;
×
576
    }
577
    if (is_request) {
72✔
578
        return target_comp_id == _sender.get_own_component_id() ||
62✔
579
               target_comp_id == MAV_COMP_ID_ALL;
62✔
580
    }
581
    return target_comp_id == _sender.get_own_component_id();
10✔
582
}
583

584
void MavlinkParameterServer::log_target_mismatch(uint16_t target_sys_id, uint16_t target_comp_id)
×
585
{
586
    if (!_parameter_debugging) {
×
587
        return;
×
588
    }
589

590
    LogDebug() << "Ignoring message - wrong target id. Got:" << (int)target_sys_id << ":"
×
591
               << (int)target_comp_id << " Wanted:" << (int)_sender.get_own_system_id() << ":"
×
592
               << (int)_sender.get_own_component_id();
×
593
}
594

595
std::variant<std::monostate, std::string, std::uint16_t>
596
MavlinkParameterServer::extract_request_read_param_identifier(
58✔
597
    int16_t param_index, const char* param_id)
598
{
599
    // Helper for safely handling a request_read or ext_request_read message (which have the exact
600
    // same layout). returns the identifier that should be used or nothing if the message is
601
    // ill-formed. See https://mavlink.io/en/messages/common.html#PARAM_REQUEST_READ and
602
    // https://mavlink.io/en/messages/common.html#PARAM_EXT_REQUEST_READ
603

604
    if (param_index == -1) {
58✔
605
        // use param_id if index == -1
606
        const auto safe_param_id = extract_safe_param_id(param_id);
55✔
607
        if (safe_param_id.empty()) {
55✔
608
            LogErr() << "Message with param_index=-1 but no empty param id";
×
609
            return std::monostate{};
×
610
        }
611
        return {safe_param_id};
55✔
612
    } else {
55✔
613
        // if index is not -1, it should be a valid parameter index (>=0)
614
        if (param_index < 0) {
3✔
615
            LogErr() << "Param_index " << param_index << " is not a valid param index";
×
616
            return std::monostate{};
×
617
        }
618
        return {static_cast<std::uint16_t>(param_index)};
3✔
619
    }
620
}
621

622
} // 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

© 2025 Coveralls, Inc