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

mavlink / MAVSDK / 4505821829

pending completion
4505821829

push

github

GitHub
Merge pull request #2006 from mavlink/pr-wait-for-info

10 of 10 new or added lines in 1 file covered. (100.0%)

7419 of 24203 relevant lines covered (30.65%)

22.02 hits per line

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

47.54
/src/mavsdk/core/mavlink_parameters.cpp
1
#include "mavlink_parameters.h"
2
#include "mavlink_message_handler.h"
3
#include "timeout_handler.h"
4
#include "system_impl.h"
5
#include <algorithm>
6
#include <cstring>
7
#include <future>
8

9
namespace mavsdk {
10

11
MAVLinkParameters::MAVLinkParameters(
28✔
12
    Sender& sender,
13
    MavlinkMessageHandler& message_handler,
14
    TimeoutHandler& timeout_handler,
15
    TimeoutSCallback timeout_s_callback,
16
    bool is_server) :
28✔
17
    _sender(sender),
18
    _message_handler(message_handler),
19
    _timeout_handler(timeout_handler),
20
    _timeout_s_callback(timeout_s_callback),
21
    _is_server(is_server)
28✔
22
{
23
    if (const char* env_p = std::getenv("MAVSDK_PARAMETER_DEBUGGING")) {
28✔
24
        if (std::string(env_p) == "1") {
×
25
            LogDebug() << "Parameter debugging is on.";
×
26
            _parameter_debugging = true;
×
27
        }
28
    }
29

30
    if (!_is_server) {
28✔
31
        _message_handler.register_one(
14✔
32
            MAVLINK_MSG_ID_PARAM_VALUE,
33
            [this](const mavlink_message_t& message) { process_param_value(message); },
206✔
34
            this);
35

36
        _message_handler.register_one(
14✔
37
            MAVLINK_MSG_ID_PARAM_EXT_VALUE,
38
            [this](const mavlink_message_t& message) { process_param_ext_value(message); },
2✔
39
            this);
40

41
        _message_handler.register_one(
14✔
42
            MAVLINK_MSG_ID_PARAM_EXT_ACK,
43
            [this](const mavlink_message_t& message) { process_param_ext_ack(message); },
1✔
44
            this);
45
    }
46

47
    if (_is_server) {
28✔
48
        _message_handler.register_one(
14✔
49
            MAVLINK_MSG_ID_PARAM_SET,
50
            [this](const mavlink_message_t& message) { process_param_set(message); },
2✔
51
            this);
52

53
        _message_handler.register_one(
14✔
54
            MAVLINK_MSG_ID_PARAM_EXT_SET,
55
            [this](const mavlink_message_t& message) { process_param_ext_set(message); },
1✔
56
            this);
57

58
        // Parameter Server Callbacks
59
        _message_handler.register_one(
14✔
60
            MAVLINK_MSG_ID_PARAM_REQUEST_READ,
61
            [this](const mavlink_message_t& message) { process_param_request_read(message); },
4✔
62
            this);
63

64
        _message_handler.register_one(
14✔
65
            MAVLINK_MSG_ID_PARAM_REQUEST_LIST,
66
            [this](const mavlink_message_t& message) { process_param_request_list(message); },
1✔
67
            this);
68

69
        _message_handler.register_one(
14✔
70
            MAVLINK_MSG_ID_PARAM_EXT_REQUEST_READ,
71
            [this](const mavlink_message_t& message) { process_param_ext_request_read(message); },
2✔
72
            this);
73
    }
74
}
28✔
75

76
MAVLinkParameters::~MAVLinkParameters()
28✔
77
{
78
    _message_handler.unregister_all(this);
28✔
79
}
28✔
80

81
MAVLinkParameters::Result
82
MAVLinkParameters::provide_server_param_float(const std::string& name, float value)
101✔
83
{
84
    if (name.size() > PARAM_ID_LEN) {
101✔
85
        LogErr() << "Error: param name too long";
×
86
        return Result::ParamNameTooLong;
×
87
    }
88

89
    ParamValue param_value;
101✔
90
    param_value.set(value);
101✔
91
    _all_params.insert_or_assign(name, param_value);
101✔
92
    return Result::Success;
101✔
93
}
94

95
MAVLinkParameters::Result
96
MAVLinkParameters::provide_server_param_int(const std::string& name, int value)
101✔
97
{
98
    if (name.size() > PARAM_ID_LEN) {
101✔
99
        LogErr() << "Error: param name too long";
×
100
        return Result::ParamNameTooLong;
×
101
    }
102

103
    ParamValue param_value;
101✔
104
    param_value.set(value);
101✔
105
    _all_params.insert_or_assign(name, param_value);
101✔
106
    return Result::Success;
101✔
107
}
108

109
MAVLinkParameters::Result
110
MAVLinkParameters::provide_server_param_custom(const std::string& name, const std::string& value)
1✔
111
{
112
    if (name.size() > PARAM_ID_LEN) {
1✔
113
        LogErr() << "Error: param name too long";
×
114
        return Result::ParamNameTooLong;
×
115
    }
116

117
    if (value.size() > sizeof(mavlink_param_ext_set_t::param_value)) {
1✔
118
        LogErr() << "Error: param value too long";
×
119
        return Result::ParamValueTooLong;
×
120
    }
121

122
    ParamValue param_value;
1✔
123
    param_value.set(value);
1✔
124
    _all_params.insert_or_assign(name, param_value);
1✔
125
    return Result::Success;
1✔
126
}
127

128
MAVLinkParameters::Result MAVLinkParameters::set_param(
×
129
    const std::string& name,
130
    ParamValue value,
131

132
    std::optional<uint8_t> maybe_component_id,
133
    bool extended)
134
{
135
    auto prom = std::promise<Result>();
×
136
    auto res = prom.get_future();
×
137

138
    set_param_async(
×
139
        name,
140
        value,
141
        [&prom](Result result) { prom.set_value(result); },
×
142
        this,
143
        maybe_component_id,
144
        extended);
145

146
    return res.get();
×
147
}
148

149
void MAVLinkParameters::set_param_async(
×
150
    const std::string& name,
151
    ParamValue value,
152
    const SetParamCallback& callback,
153
    const void* cookie,
154
    std::optional<uint8_t> maybe_component_id,
155
    bool extended)
156
{
157
    if (name.size() > PARAM_ID_LEN) {
×
158
        LogErr() << "Error: param name too long";
×
159
        if (callback) {
×
160
            callback(Result::ParamNameTooLong);
×
161
        }
162
        return;
×
163
    }
164

165
    auto new_work = std::make_shared<WorkItem>(_timeout_s_callback());
×
166

167
    new_work->type = WorkItem::Type::Set;
×
168
    new_work->callback = callback;
×
169
    new_work->maybe_component_id = maybe_component_id;
×
170
    new_work->param_name = name;
×
171
    new_work->param_value = value;
×
172
    new_work->extended = extended;
×
173
    new_work->exact_type_known = true;
×
174
    new_work->cookie = cookie;
×
175
    _work_queue.push_back(new_work);
×
176
}
177

178
void MAVLinkParameters::set_param_int_async(
1✔
179
    const std::string& name,
180
    int32_t value,
181
    const SetParamCallback& callback,
182
    const void* cookie,
183
    std::optional<uint8_t> maybe_component_id,
184
    bool extended)
185
{
186
    if (name.size() > PARAM_ID_LEN) {
1✔
187
        LogErr() << "Error: param name too long";
×
188
        if (callback) {
×
189
            callback(Result::ParamNameTooLong);
×
190
        }
191
        return;
×
192
    }
193

194
    // PX4 only uses int32_t, so we can be sure and don't need to check the exact type first
195
    // by getting the param, or checking the cache.
196
    const bool exact_int_type_known = (_sender.autopilot() == SystemImpl::Autopilot::Px4);
1✔
197

198
    const auto set_step = [=]() {
1✔
199
        auto new_work = std::make_shared<WorkItem>(_timeout_s_callback());
2✔
200

201
        MAVLinkParameters::ParamValue value_to_set;
2✔
202
        value_to_set.set(value);
1✔
203

204
        new_work->type = WorkItem::Type::Set;
1✔
205
        new_work->callback = callback;
1✔
206
        new_work->param_name = name;
1✔
207
        new_work->param_value = value_to_set;
1✔
208
        new_work->extended = extended;
1✔
209
        new_work->exact_type_known = exact_int_type_known;
1✔
210
        new_work->cookie = cookie;
1✔
211
        _work_queue.push_back(new_work);
1✔
212
    };
2✔
213

214
    // We need to know the exact int type first.
215
    if (exact_int_type_known || _all_params.find(name) != _all_params.end()) {
1✔
216
        // We are sure about the type, or we have it cached, we'll be able to use it.
217
        set_step();
1✔
218
    } else {
219
        // We don't know the exact type, so we need to get it first.
220
        get_param_int_async(name, nullptr, cookie, maybe_component_id, extended);
×
221
        set_step();
×
222
    }
223
}
224

225
MAVLinkParameters::Result MAVLinkParameters::set_param_int(
1✔
226
    const std::string& name,
227
    int32_t value,
228
    std::optional<uint8_t> maybe_component_id,
229
    bool extended)
230
{
231
    auto prom = std::promise<Result>();
2✔
232
    auto res = prom.get_future();
2✔
233

234
    set_param_int_async(
1✔
235
        name,
236
        value,
237
        [&prom](Result result) { prom.set_value(result); },
1✔
238
        this,
239
        maybe_component_id,
240
        extended);
241

242
    return res.get();
1✔
243
}
244

245
void MAVLinkParameters::set_param_float_async(
1✔
246
    const std::string& name,
247
    float value,
248
    const SetParamCallback& callback,
249
    const void* cookie,
250
    std::optional<uint8_t> maybe_component_id,
251
    bool extended)
252
{
253
    if (name.size() > PARAM_ID_LEN) {
1✔
254
        LogErr() << "Error: param name too long";
×
255
        if (callback) {
×
256
            callback(Result::ParamNameTooLong);
×
257
        }
258
        return;
×
259
    }
260

261
    auto new_work = std::make_shared<WorkItem>(_timeout_s_callback());
2✔
262

263
    MAVLinkParameters::ParamValue value_to_set;
2✔
264
    value_to_set.set_float(value);
1✔
265

266
    new_work->type = WorkItem::Type::Set;
1✔
267
    new_work->callback = callback;
1✔
268
    new_work->maybe_component_id = maybe_component_id;
1✔
269
    new_work->param_name = name;
1✔
270
    new_work->param_value = value_to_set;
1✔
271
    new_work->extended = extended;
1✔
272
    new_work->exact_type_known = true;
1✔
273
    new_work->cookie = cookie;
1✔
274
    _work_queue.push_back(new_work);
1✔
275
}
276

277
MAVLinkParameters::Result MAVLinkParameters::set_param_float(
1✔
278
    const std::string& name, float value, std::optional<uint8_t> maybe_component_id, bool extended)
279
{
280
    auto prom = std::promise<Result>();
2✔
281
    auto res = prom.get_future();
2✔
282

283
    set_param_float_async(
1✔
284
        name,
285
        value,
286
        [&prom](Result result) { prom.set_value(result); },
1✔
287
        this,
288
        maybe_component_id,
289
        extended);
290

291
    return res.get();
1✔
292
}
293

294
void MAVLinkParameters::get_param_float_async(
2✔
295
    const std::string& name,
296
    const GetParamFloatCallback& callback,
297
    const void* cookie,
298
    std::optional<uint8_t> maybe_component_id,
299
    bool extended)
300
{
301
    if (_parameter_debugging) {
2✔
302
        LogDebug() << "getting param " << name << ", extended: " << (extended ? "yes" : "no");
×
303
    }
304

305
    if (name.size() > PARAM_ID_LEN) {
2✔
306
        LogErr() << "Error: param name too long";
×
307
        if (callback) {
×
308
            callback(MAVLinkParameters::Result::ParamNameTooLong, NAN);
×
309
        }
310
        return;
×
311
    }
312

313
    ParamValue value_type;
4✔
314
    value_type.set(NAN);
2✔
315

316
    // Otherwise, push work onto queue.
317
    auto new_work = std::make_shared<WorkItem>(_timeout_s_callback());
4✔
318
    new_work->type = WorkItem::Type::Get;
2✔
319
    new_work->callback = callback;
2✔
320
    new_work->maybe_component_id = maybe_component_id;
2✔
321
    new_work->param_name = name;
2✔
322
    new_work->param_value = value_type;
2✔
323
    new_work->extended = extended;
2✔
324
    new_work->cookie = cookie;
2✔
325

326
    _work_queue.push_back(new_work);
2✔
327
}
328

329
void MAVLinkParameters::get_param_async(
×
330
    const std::string& name,
331
    ParamValue value,
332
    const GetParamAnyCallback& callback,
333
    const void* cookie,
334
    std::optional<uint8_t> maybe_component_id,
335
    bool extended)
336
{
337
    if (_parameter_debugging) {
×
338
        LogDebug() << "getting param " << name << ", extended: " << (extended ? "yes" : "no");
×
339
    }
340

341
    if (name.size() > PARAM_ID_LEN) {
×
342
        LogErr() << "Error: param name too long";
×
343
        if (callback) {
×
344
            callback(Result::ParamNameTooLong, ParamValue{});
×
345
        }
346
        return;
×
347
    }
348

349
    // Otherwise, push work onto queue.
350
    auto new_work = std::make_shared<WorkItem>(_timeout_s_callback());
×
351
    new_work->type = WorkItem::Type::Get;
×
352
    new_work->callback = callback;
×
353
    new_work->maybe_component_id = maybe_component_id;
×
354
    new_work->param_name = name;
×
355
    new_work->param_value = value;
×
356
    new_work->extended = extended;
×
357
    new_work->exact_type_known = true;
×
358
    new_work->cookie = cookie;
×
359

360
    _work_queue.push_back(new_work);
×
361
}
362

363
void MAVLinkParameters::get_param_int_async(
2✔
364
    const std::string& name,
365
    const GetParamIntCallback& callback,
366
    const void* cookie,
367
    std::optional<uint8_t> maybe_component_id,
368
    bool extended)
369
{
370
    if (_parameter_debugging) {
2✔
371
        LogDebug() << "getting param " << name << ", extended: " << (extended ? "yes" : "no");
×
372
    }
373

374
    if (name.size() > PARAM_ID_LEN) {
2✔
375
        LogErr() << "Error: param name too long";
×
376
        if (callback) {
×
377
            callback(MAVLinkParameters::Result::ParamNameTooLong, 0);
×
378
        }
379
        return;
×
380
    }
381

382
    // Otherwise, push work onto queue.
383
    auto new_work = std::make_shared<WorkItem>(_timeout_s_callback());
4✔
384
    new_work->type = WorkItem::Type::Get;
2✔
385
    new_work->callback = callback;
2✔
386
    new_work->maybe_component_id = maybe_component_id;
2✔
387
    new_work->param_name = name;
2✔
388
    new_work->param_value = {};
2✔
389
    new_work->extended = extended;
2✔
390
    new_work->cookie = cookie;
2✔
391

392
    _work_queue.push_back(new_work);
2✔
393
}
394

395
MAVLinkParameters::Result
396
MAVLinkParameters::set_param_custom(const std::string& name, const std::string& value)
1✔
397
{
398
    auto prom = std::promise<Result>();
2✔
399
    auto res = prom.get_future();
2✔
400

401
    set_param_custom_async(
1✔
402
        name, value, [&prom](Result result) { prom.set_value(result); }, this);
1✔
403

404
    return res.get();
1✔
405
}
406

407
void MAVLinkParameters::get_param_custom_async(
2✔
408
    const std::string& name, const GetParamCustomCallback& callback, const void* cookie)
409
{
410
    if (_parameter_debugging) {
2✔
411
        LogDebug() << "getting param " << name;
×
412
    }
413

414
    if (name.size() > PARAM_ID_LEN) {
2✔
415
        LogErr() << "Error: param name too long";
×
416
        if (callback) {
×
417
            callback(MAVLinkParameters::Result::ParamNameTooLong, 0);
×
418
        }
419
        return;
×
420
    }
421

422
    // Otherwise, push work onto queue.
423
    auto new_work = std::make_shared<WorkItem>(_timeout_s_callback());
4✔
424
    new_work->type = WorkItem::Type::Get;
2✔
425
    new_work->callback = callback;
2✔
426
    new_work->param_name = name;
2✔
427
    new_work->param_value.set_custom(std::string());
2✔
428
    new_work->extended = true;
2✔
429
    new_work->cookie = cookie;
2✔
430

431
    _work_queue.push_back(new_work);
2✔
432
}
433

434
void MAVLinkParameters::set_param_custom_async(
1✔
435
    const std::string& name,
436
    const std::string& value,
437
    const SetParamCallback& callback,
438
    const void* cookie)
439
{
440
    if (name.size() > PARAM_ID_LEN) {
1✔
441
        LogErr() << "Error: param name too long";
×
442
        if (callback) {
×
443
            callback(Result::ParamNameTooLong);
×
444
        }
445
        return;
×
446
    }
447

448
    if (value.size() > sizeof(mavlink_param_ext_set_t::param_value)) {
1✔
449
        LogErr() << "Error: param value too long";
×
450
        if (callback) {
×
451
            callback(Result::ParamValueTooLong);
×
452
        }
453
        return;
×
454
    }
455

456
    auto new_work = std::make_shared<WorkItem>(_timeout_s_callback());
2✔
457

458
    MAVLinkParameters::ParamValue value_to_set;
2✔
459
    value_to_set.set_custom(value);
1✔
460

461
    new_work->type = WorkItem::Type::Set;
1✔
462
    new_work->callback = callback;
1✔
463
    new_work->param_name = name;
1✔
464
    new_work->param_value = value_to_set;
1✔
465
    new_work->extended = true;
1✔
466
    new_work->exact_type_known = true;
1✔
467
    new_work->cookie = cookie;
1✔
468
    _work_queue.push_back(new_work);
1✔
469
}
470

471
std::map<std::string, MAVLinkParameters::ParamValue> MAVLinkParameters::retrieve_all_server_params()
1✔
472
{
473
    std::lock_guard<std::mutex> lock(_all_params_mutex);
2✔
474
    return _all_params;
1✔
475
}
476

477
std::pair<MAVLinkParameters::Result, MAVLinkParameters::ParamValue>
478
MAVLinkParameters::retrieve_server_param(const std::string& name, ParamValue value_type)
×
479
{
480
    if (_all_params.find(name) != _all_params.end()) {
×
481
        auto value = _all_params.at(name);
×
482
        if (value.is_same_type(value_type))
×
483
            return {MAVLinkParameters::Result::Success, value};
×
484
        else
485
            return {MAVLinkParameters::Result::WrongType, {}};
×
486
    }
487
    return {MAVLinkParameters::Result::NotFound, {}};
×
488
}
489

490
std::pair<MAVLinkParameters::Result, float>
491
MAVLinkParameters::retrieve_server_param_float(const std::string& name)
1✔
492
{
493
    if (_all_params.find(name) != _all_params.end()) {
1✔
494
        const auto maybe_value = _all_params.at(name).get_float();
1✔
495
        if (maybe_value)
1✔
496
            return {MAVLinkParameters::Result::Success, maybe_value.value()};
1✔
497
        else
498
            return {MAVLinkParameters::Result::WrongType, {}};
×
499
    }
500
    return {MAVLinkParameters::Result::NotFound, {}};
×
501
}
502

503
std::pair<MAVLinkParameters::Result, std::string>
504
MAVLinkParameters::retrieve_server_param_custom(const std::string& name)
1✔
505
{
506
    if (_all_params.find(name) != _all_params.end()) {
1✔
507
        const auto maybe_value = _all_params.at(name).get_custom();
2✔
508
        if (maybe_value)
1✔
509
            return {MAVLinkParameters::Result::Success, maybe_value.value()};
1✔
510
        else
511
            return {MAVLinkParameters::Result::WrongType, {}};
×
512
    }
513
    return {MAVLinkParameters::Result::NotFound, {}};
×
514
}
515

516
std::pair<MAVLinkParameters::Result, int>
517
MAVLinkParameters::retrieve_server_param_int(const std::string& name)
1✔
518
{
519
    if (_all_params.find(name) != _all_params.end()) {
1✔
520
        const auto maybe_value = _all_params.at(name).get_int();
1✔
521
        if (maybe_value)
1✔
522
            return {MAVLinkParameters::Result::Success, maybe_value.value()};
1✔
523
        else
524
            return {MAVLinkParameters::Result::WrongType, {}};
×
525
    }
526
    return {MAVLinkParameters::Result::NotFound, {}};
×
527
}
528

529
std::pair<MAVLinkParameters::Result, MAVLinkParameters::ParamValue> MAVLinkParameters::get_param(
×
530
    const std::string& name, MAVLinkParameters::ParamValue value, bool extended)
531
{
532
    auto prom = std::promise<std::pair<Result, ParamValue>>();
×
533
    auto res = prom.get_future();
×
534

535
    get_param_async(
×
536
        name,
537
        value,
538
        [&prom](Result result, ParamValue new_value) {
×
539
            prom.set_value(std::make_pair<>(result, new_value));
×
540
        },
×
541
        this,
542
        extended);
543

544
    return res.get();
×
545
}
546

547
std::pair<MAVLinkParameters::Result, int32_t> MAVLinkParameters::get_param_int(
2✔
548
    const std::string& name, std::optional<uint8_t> maybe_component_id, bool extended)
549
{
550
    auto prom = std::promise<std::pair<Result, int32_t>>();
4✔
551
    auto res = prom.get_future();
4✔
552

553
    get_param_int_async(
2✔
554
        name,
555
        [&prom](Result result, int32_t value) { prom.set_value(std::make_pair<>(result, value)); },
2✔
556
        this,
557
        maybe_component_id,
558
        extended);
559

560
    return res.get();
2✔
561
}
562

563
std::pair<MAVLinkParameters::Result, float> MAVLinkParameters::get_param_float(
2✔
564
    const std::string& name, std::optional<uint8_t> maybe_component_id, bool extended)
565
{
566
    auto prom = std::promise<std::pair<Result, float>>();
4✔
567
    auto res = prom.get_future();
4✔
568

569
    get_param_float_async(
2✔
570
        name,
571
        [&prom](Result result, float value) { prom.set_value(std::make_pair<>(result, value)); },
2✔
572
        this,
573
        maybe_component_id,
574
        extended);
575

576
    return res.get();
2✔
577
}
578

579
std::pair<MAVLinkParameters::Result, std::string>
580
MAVLinkParameters::get_param_custom(const std::string& name)
2✔
581
{
582
    auto prom = std::promise<std::pair<Result, std::string>>();
4✔
583
    auto res = prom.get_future();
4✔
584

585
    get_param_custom_async(
2✔
586
        name,
587
        [&prom](Result result, const std::string& value) {
2✔
588
            prom.set_value(std::make_pair<>(result, value));
2✔
589
        },
2✔
590
        this);
591

592
    return res.get();
2✔
593
}
594

595
void MAVLinkParameters::get_all_params_async(const GetAllParamsCallback& callback)
1✔
596
{
597
    std::lock_guard<std::mutex> lock(_all_params_mutex);
2✔
598

599
    _all_params_callback = callback;
1✔
600

601
    mavlink_message_t msg;
1✔
602

603
    mavlink_msg_param_request_list_pack(
1✔
604
        _sender.get_own_system_id(),
1✔
605
        _sender.get_own_component_id(),
1✔
606
        &msg,
607
        _sender.get_system_id(),
1✔
608
        MAV_COMP_ID_AUTOPILOT1); // FIXME: what should the component be?
609

610
    if (!_sender.send_message(msg)) {
1✔
611
        LogErr() << "Failed to send param list request!";
×
612
        callback(std::map<std::string, ParamValue>{});
×
613
    }
614

615
    _timeout_handler.add(
1✔
616
        [this] { receive_timeout(); }, _timeout_s_callback(), &_all_params_timeout_cookie);
×
617
}
1✔
618

619
std::map<std::string, MAVLinkParameters::ParamValue> MAVLinkParameters::get_all_params()
1✔
620
{
621
    std::promise<std::map<std::string, ParamValue>> prom;
2✔
622
    auto res = prom.get_future();
2✔
623

624
    get_all_params_async(
1✔
625
        [&prom](const std::map<std::string, MAVLinkParameters::ParamValue>& all_params) {
1✔
626
            prom.set_value(all_params);
1✔
627
        });
1✔
628

629
    return res.get();
1✔
630
}
631

632
void MAVLinkParameters::cancel_all_param(const void* cookie)
2✔
633
{
634
    LockedQueue<WorkItem>::Guard work_queue_guard(_work_queue);
4✔
635

636
    for (auto item = _work_queue.begin(); item != _work_queue.end(); /* manual incrementation */) {
2✔
637
        if ((*item)->cookie == cookie) {
×
638
            item = _work_queue.erase(item);
×
639
        } else {
640
            ++item;
×
641
        }
642
    }
643
}
2✔
644

645
void MAVLinkParameters::subscribe_param_float_changed(
×
646
    const std::string& name,
647
    const MAVLinkParameters::ParamFloatChangedCallback& callback,
648
    const void* cookie)
649
{
650
    std::lock_guard<std::mutex> lock(_param_changed_subscriptions_mutex);
×
651

652
    if (callback != nullptr) {
×
653
        ParamChangedSubscription subscription{};
×
654
        subscription.param_name = name;
×
655
        subscription.callback = callback;
×
656
        subscription.cookie = cookie;
×
657
        subscription.any_type = false;
×
658
        ParamValue value_type;
×
659
        value_type.set_float(NAN);
×
660
        subscription.value_type = value_type;
×
661
        _param_changed_subscriptions.push_back(subscription);
×
662

663
    } else {
664
        for (auto it = _param_changed_subscriptions.begin();
×
665
             it != _param_changed_subscriptions.end();
×
666
             /* ++it */) {
667
            if (it->param_name == name && it->cookie == cookie) {
×
668
                it = _param_changed_subscriptions.erase(it);
×
669
            } else {
670
                ++it;
×
671
            }
672
        }
673
    }
674
}
×
675

676
void MAVLinkParameters::subscribe_param_int_changed(
×
677
    const std::string& name,
678
    const MAVLinkParameters::ParamIntChangedCallback& callback,
679
    const void* cookie)
680
{
681
    std::lock_guard<std::mutex> lock(_param_changed_subscriptions_mutex);
×
682

683
    if (callback != nullptr) {
×
684
        ParamChangedSubscription subscription{};
×
685
        subscription.param_name = name;
×
686
        subscription.callback = callback;
×
687
        subscription.cookie = cookie;
×
688
        subscription.any_type = false;
×
689
        ParamValue value_type;
×
690
        value_type.set_int(0);
×
691
        subscription.value_type = value_type;
×
692
        _param_changed_subscriptions.push_back(subscription);
×
693

694
    } else {
695
        for (auto it = _param_changed_subscriptions.begin();
×
696
             it != _param_changed_subscriptions.end();
×
697
             /* ++it */) {
698
            if (it->param_name == name && it->cookie == cookie) {
×
699
                it = _param_changed_subscriptions.erase(it);
×
700
            } else {
701
                ++it;
×
702
            }
703
        }
704
    }
705
}
×
706

707
void MAVLinkParameters::subscribe_param_custom_changed(
×
708
    const std::string& name,
709
    const MAVLinkParameters::ParamCustomChangedCallback& callback,
710
    const void* cookie)
711
{
712
    std::lock_guard<std::mutex> lock(_param_changed_subscriptions_mutex);
×
713

714
    if (callback != nullptr) {
×
715
        ParamChangedSubscription subscription{};
×
716
        subscription.param_name = name;
×
717
        subscription.callback = callback;
×
718
        subscription.cookie = cookie;
×
719
        subscription.any_type = false;
×
720
        ParamValue value_type;
×
721
        value_type.set_custom("");
×
722
        subscription.value_type = value_type;
×
723
        _param_changed_subscriptions.push_back(subscription);
×
724

725
    } else {
726
        for (auto it = _param_changed_subscriptions.begin();
×
727
             it != _param_changed_subscriptions.end();
×
728
             /* ++it */) {
729
            if (it->param_name == name && it->cookie == cookie) {
×
730
                it = _param_changed_subscriptions.erase(it);
×
731
            } else {
732
                ++it;
×
733
            }
734
        }
735
    }
736
}
×
737

738
void MAVLinkParameters::do_work()
1,791✔
739
{
740
    LockedQueue<WorkItem>::Guard work_queue_guard(_work_queue);
1,791✔
741
    auto work = work_queue_guard.get_front();
1,791✔
742

743
    if (!work) {
1,791✔
744
        return;
1,573✔
745
    }
746

747
    if (work->already_requested) {
218✔
748
        return;
×
749
    }
750

751
    char param_id[PARAM_ID_LEN + 1] = {};
218✔
752
    strncpy(param_id, work->param_name.c_str(), sizeof(param_id) - 1);
218✔
753

754
    uint8_t component_id = [&]() {
218✔
755
        if (work->maybe_component_id) {
218✔
756
            return work->maybe_component_id.value();
×
757
        } else {
758
            if (work->extended) {
218✔
759
                return static_cast<uint8_t>(MAV_COMP_ID_CAMERA);
6✔
760
            } else {
761
                return static_cast<uint8_t>(MAV_COMP_ID_AUTOPILOT1);
212✔
762
            }
763
        }
764
    }();
218✔
765

766
    switch (work->type) {
218✔
767
        case WorkItem::Type::Set: {
3✔
768
            if (!work->exact_type_known) {
3✔
769
                std::lock_guard<std::mutex> lock(_all_params_mutex);
1✔
770
                const auto it = _all_params.find(work->param_name);
1✔
771
                if (it == _all_params.end()) {
1✔
772
                    LogErr() << "Don't know the type of param_set";
×
773
                    if (std::get_if<SetParamCallback>(&work->callback)) {
×
774
                        const auto& callback = std::get<SetParamCallback>(work->callback);
×
775
                        if (callback) {
×
776
                            callback(MAVLinkParameters::Result::Failed);
×
777
                        }
778
                    }
779
                    work_queue_guard.pop_front();
×
780
                    return;
×
781
                }
782

783
                auto maybe_temp_int = work->param_value.get_int();
1✔
784
                if (!maybe_temp_int) {
1✔
785
                    // Not sure what to think when this happens.
786
                    LogErr() << "Error: this should definitely be an int";
×
787
                } else {
788
                    // First we copy over the type
789
                    work->param_value = it->second;
1✔
790
                    // And then fill in the value.
791
                    work->param_value.set_int(maybe_temp_int.value());
1✔
792
                }
793
            }
794

795
            if (work->extended) {
3✔
796
                auto param_value_buf = work->param_value.get_128_bytes();
1✔
797

798
                // FIXME: extended currently always go to the camera component
799
                mavlink_msg_param_ext_set_pack(
1✔
800
                    _sender.get_own_system_id(),
1✔
801
                    _sender.get_own_component_id(),
1✔
802
                    &work->mavlink_message,
1✔
803
                    _sender.get_system_id(),
1✔
804
                    component_id,
805
                    param_id,
806
                    param_value_buf.data(),
1✔
807
                    work->param_value.get_mav_param_ext_type());
1✔
808
            } else {
809
                float value_set = (_sender.autopilot() == SystemImpl::Autopilot::ArduPilot) ?
2✔
810
                                      work->param_value.get_4_float_bytes_cast() :
×
811
                                      work->param_value.get_4_float_bytes_bytewise();
2✔
812

813
                mavlink_msg_param_set_pack(
2✔
814
                    _sender.get_own_system_id(),
2✔
815
                    _sender.get_own_component_id(),
2✔
816
                    &work->mavlink_message,
2✔
817
                    _sender.get_system_id(),
2✔
818
                    component_id,
819
                    param_id,
820
                    value_set,
821
                    work->param_value.get_mav_param_type());
2✔
822
            }
823

824
            if (!_sender.send_message(work->mavlink_message)) {
3✔
825
                LogErr() << "Error: Send message failed";
×
826
                if (std::get_if<SetParamCallback>(&work->callback)) {
×
827
                    const auto& callback = std::get<SetParamCallback>(work->callback);
×
828
                    if (callback) {
×
829
                        callback(MAVLinkParameters::Result::ConnectionError);
×
830
                    }
831
                }
832
                work_queue_guard.pop_front();
×
833
                return;
×
834
            }
835

836
            work->already_requested = true;
3✔
837
            // _last_request_time = _sender.get_time().steady_time();
838

839
            // We want to get notified if a timeout happens
840
            _timeout_handler.add([this] { receive_timeout(); }, work->timeout_s, &_timeout_cookie);
3✔
841

842
        } break;
3✔
843

844
        case WorkItem::Type::Get: {
6✔
845
            // LogDebug() << "now getting: " << work->param_name;
846
            if (work->extended) {
6✔
847
                mavlink_msg_param_ext_request_read_pack(
2✔
848
                    _sender.get_own_system_id(),
2✔
849
                    _sender.get_own_component_id(),
2✔
850
                    &work->mavlink_message,
2✔
851
                    _sender.get_system_id(),
2✔
852
                    component_id,
853
                    param_id,
854
                    -1);
855

856
            } else {
857
                // LogDebug() << "request read: "
858
                //    << (int)_sender.get_own_system_id() << ":"
859
                //    << (int)_sender.get_own_component_id() <<
860
                //    " to "
861
                //    << (int)_sender.get_system_id() << ":"
862
                //    << (int)_sender.get_autopilot_id();
863

864
                mavlink_msg_param_request_read_pack(
4✔
865
                    _sender.get_own_system_id(),
4✔
866
                    _sender.get_own_component_id(),
4✔
867
                    &work->mavlink_message,
4✔
868
                    _sender.get_system_id(),
4✔
869
                    component_id,
870
                    param_id,
871
                    -1);
872
            }
873

874
            if (!_sender.send_message(work->mavlink_message)) {
6✔
875
                LogErr() << "Error: Send message failed";
×
876

877
                if (std::get_if<GetParamIntCallback>(&work->callback)) {
×
878
                    if (const auto& callback = std::get<GetParamIntCallback>(work->callback)) {
×
879
                        callback(Result::ConnectionError, 0);
×
880
                    }
881
                } else if (std::get_if<GetParamFloatCallback>(&work->callback)) {
×
882
                    if (const auto& callback = std::get<GetParamFloatCallback>(work->callback)) {
×
883
                        (callback)(Result::ConnectionError, NAN);
×
884
                    }
885
                } else if (std::get_if<GetParamAnyCallback>(&work->callback)) {
×
886
                    if (const auto& callback = std::get<GetParamAnyCallback>(work->callback)) {
×
887
                        (callback)(Result::ConnectionError, ParamValue{});
×
888
                    }
889
                }
890
                work_queue_guard.pop_front();
×
891
                return;
×
892
            }
893

894
            work->already_requested = true;
6✔
895

896
            // _last_request_time = _sender.get_time().steady_time();
897

898
            // We want to get notified if a timeout happens
899
            _timeout_handler.add([this] { receive_timeout(); }, work->timeout_s, &_timeout_cookie);
6✔
900

901
        } break;
6✔
902

903
        case WorkItem::Type::Value: {
208✔
904
            if (work->extended) {
208✔
905
                auto buf = work->param_value.get_128_bytes();
2✔
906
                mavlink_msg_param_ext_value_pack(
2✔
907
                    _sender.get_own_system_id(),
2✔
908
                    _sender.get_own_component_id(),
2✔
909
                    &work->mavlink_message,
2✔
910
                    param_id,
911
                    buf.data(),
2✔
912
                    work->param_value.get_mav_param_ext_type(),
2✔
913
                    work->param_count,
2✔
914
                    work->param_index);
2✔
915
            } else {
916
                float param_value;
917
                if (_sender.autopilot() == SystemImpl::Autopilot::ArduPilot) {
206✔
918
                    param_value = work->param_value.get_4_float_bytes_cast();
×
919
                } else {
920
                    param_value = work->param_value.get_4_float_bytes_bytewise();
206✔
921
                }
922
                mavlink_msg_param_value_pack(
206✔
923
                    _sender.get_own_system_id(),
206✔
924
                    _sender.get_own_component_id(),
206✔
925
                    &work->mavlink_message,
206✔
926
                    param_id,
927
                    param_value,
928
                    work->param_value.get_mav_param_type(),
206✔
929
                    work->param_count,
206✔
930
                    work->param_index);
206✔
931
            }
932

933
            if (!_sender.send_message(work->mavlink_message)) {
208✔
934
                LogErr() << "Error: Send message failed";
×
935
                work_queue_guard.pop_front();
×
936
                return;
×
937
            }
938

939
            // As we're a server in this case we don't need any response
940
            work_queue_guard.pop_front();
208✔
941
        } break;
208✔
942

943
        case WorkItem::Type::Ack: {
1✔
944
            if (work->extended) {
1✔
945
                auto buf = work->param_value.get_128_bytes();
1✔
946
                mavlink_msg_param_ext_ack_pack(
1✔
947
                    _sender.get_own_system_id(),
1✔
948
                    _sender.get_own_component_id(),
1✔
949
                    &work->mavlink_message,
1✔
950
                    param_id,
951
                    buf.data(),
1✔
952
                    work->param_value.get_mav_param_ext_type(),
1✔
953
                    PARAM_ACK_ACCEPTED);
954
            }
955

956
            if (!work->extended || !_sender.send_message(work->mavlink_message)) {
1✔
957
                LogErr() << "Error: Send message failed";
×
958
                work_queue_guard.pop_front();
×
959
                return;
×
960
            }
961

962
            // As we're a server in this case we don't need any response
963
            work_queue_guard.pop_front();
1✔
964
        } break;
1✔
965
    }
966
}
967

968
void MAVLinkParameters::process_param_value(const mavlink_message_t& message)
206✔
969
{
970
    mavlink_param_value_t param_value;
206✔
971
    mavlink_msg_param_value_decode(&message, &param_value);
206✔
972

973
    if (_parameter_debugging) {
206✔
974
        LogDebug() << "getting param value: " << extract_safe_param_id(param_value.param_id);
×
975
    }
976

977
    ParamValue received_value;
206✔
978
    if (_sender.autopilot() == SystemImpl::Autopilot::ArduPilot) {
206✔
979
        received_value.set_from_mavlink_param_value_cast(param_value);
×
980
    } else {
981
        received_value.set_from_mavlink_param_value_bytewise(param_value);
206✔
982
    }
983

984
    std::string param_id = extract_safe_param_id(param_value.param_id);
206✔
985

986
    {
987
        std::lock_guard<std::mutex> lock(_all_params_mutex);
206✔
988
        _all_params[param_id] = received_value;
206✔
989

990
        // check if we are looking for param list
991
        if (_all_params_callback) {
206✔
992
            if (param_value.param_index + 1 == param_value.param_count) {
200✔
993
                _timeout_handler.remove(_all_params_timeout_cookie);
1✔
994
                _all_params_callback(_all_params);
1✔
995
                _all_params_callback = nullptr;
1✔
996
            } else {
997
                _timeout_handler.remove(_all_params_timeout_cookie);
199✔
998

999
                _timeout_handler.add(
199✔
1000
                    [this] { receive_timeout(); },
×
1001
                    _timeout_s_callback(),
1002
                    &_all_params_timeout_cookie);
1003
            }
1004

1005
            return;
200✔
1006
        }
1007
    }
1008

1009
    notify_param_subscriptions(param_value);
6✔
1010

1011
    LockedQueue<WorkItem>::Guard work_queue_guard(_work_queue);
6✔
1012
    auto work = work_queue_guard.get_front();
6✔
1013

1014
    if (!work) {
6✔
1015
        return;
×
1016
    }
1017

1018
    if (!work->already_requested) {
6✔
1019
        return;
×
1020
    }
1021

1022
    if (work->param_name != extract_safe_param_id(param_value.param_id)) {
6✔
1023
        // No match, let's just return the borrowed work item.
1024
        return;
×
1025
    }
1026

1027
    switch (work->type) {
6✔
1028
        case WorkItem::Type::Get: {
4✔
1029
            if (std::get_if<GetParamIntCallback>(&work->callback)) {
4✔
1030
                const auto& callback = std::get<GetParamIntCallback>(work->callback);
2✔
1031
                if (received_value.get_int()) {
2✔
1032
                    if (callback) {
2✔
1033
                        callback(Result::Success, received_value.get_int().value());
2✔
1034
                    }
1035
                } else {
1036
                    LogErr() << "Wrong get callback type";
×
1037
                    if (callback) {
×
1038
                        callback(Result::WrongType, 0);
×
1039
                    }
1040
                }
1041
            } else if (std::get<GetParamFloatCallback>(work->callback)) {
2✔
1042
                const auto& callback = std::get<GetParamFloatCallback>(work->callback);
2✔
1043
                if (received_value.get_float()) {
2✔
1044
                    if (callback) {
2✔
1045
                        callback(Result::Success, received_value.get_float().value());
2✔
1046
                    }
1047
                } else {
1048
                    LogErr() << "Wrong get callback type";
×
1049
                    if (callback) {
×
1050
                        callback(Result::WrongType, NAN);
×
1051
                    }
1052
                }
1053
            } else if (std::get<GetParamCustomCallback>(work->callback)) {
×
1054
                const auto& callback = std::get<GetParamCustomCallback>(work->callback);
×
1055
                if (received_value.get_custom()) {
×
1056
                    if (callback) {
×
1057
                        callback(Result::Success, received_value.get_custom().value());
×
1058
                    }
1059
                } else {
1060
                    LogErr() << "Wrong get callback type";
×
1061
                    if (callback) {
×
1062
                        callback(Result::WrongType, {});
×
1063
                    }
1064
                }
1065
            }
1066
            _timeout_handler.remove(_timeout_cookie);
4✔
1067
            // LogDebug() << "time taken: " <<
1068
            // _sender.get_time().elapsed_since_s(_last_request_time);
1069
            work_queue_guard.pop_front();
4✔
1070
        } break;
4✔
1071
        case WorkItem::Type::Set: {
2✔
1072
            // We are done, inform caller and go back to idle
1073
            if (std::get_if<SetParamCallback>(&work->callback)) {
2✔
1074
                const auto& callback = std::get<SetParamCallback>(work->callback);
2✔
1075
                if (callback) {
2✔
1076
                    callback(MAVLinkParameters::Result::Success);
2✔
1077
                }
1078
            }
1079

1080
            _timeout_handler.remove(_timeout_cookie);
2✔
1081
            // LogDebug() << "time taken: " <<
1082
            // _sender.get_time().elapsed_since_s(_last_request_time);
1083
            work_queue_guard.pop_front();
2✔
1084
        } break;
2✔
1085
        default:
×
1086
            break;
×
1087
    }
1088
}
1089

1090
void MAVLinkParameters::notify_param_subscriptions(const mavlink_param_value_t& param_value)
6✔
1091
{
1092
    std::lock_guard<std::mutex> lock(_param_changed_subscriptions_mutex);
12✔
1093

1094
    for (const auto& subscription : _param_changed_subscriptions) {
6✔
1095
        if (subscription.param_name != extract_safe_param_id(param_value.param_id)) {
×
1096
            continue;
×
1097
        }
1098

1099
        ParamValue value;
×
1100

1101
        if (_sender.autopilot() == SystemImpl::Autopilot::ArduPilot) {
×
1102
            value.set_from_mavlink_param_value_cast(param_value);
×
1103
        } else {
1104
            value.set_from_mavlink_param_value_bytewise(param_value);
×
1105
        }
1106

1107
        if (!subscription.any_type && !subscription.value_type.is_same_type(value)) {
×
1108
            LogErr() << "Received wrong param type in subscription for " << subscription.param_name;
×
1109
            continue;
×
1110
        }
1111

1112
        call_param_changed_callback(subscription.callback, value);
×
1113
    }
1114
}
6✔
1115

1116
void MAVLinkParameters::process_param_ext_value(const mavlink_message_t& message)
2✔
1117
{
1118
    if (_parameter_debugging) {
2✔
1119
        LogDebug() << "getting param ext value";
×
1120
    }
1121

1122
    mavlink_param_ext_value_t param_ext_value{};
2✔
1123
    mavlink_msg_param_ext_value_decode(&message, &param_ext_value);
2✔
1124

1125
    LockedQueue<WorkItem>::Guard work_queue_guard(_work_queue);
2✔
1126
    auto work = work_queue_guard.get_front();
2✔
1127

1128
    if (!work) {
2✔
1129
        return;
×
1130
    }
1131

1132
    if (!work->already_requested) {
2✔
1133
        return;
×
1134
    }
1135

1136
    if (work->param_name != extract_safe_param_id(param_ext_value.param_id)) {
2✔
1137
        return;
×
1138
    }
1139

1140
    switch (work->type) {
2✔
1141
        case WorkItem::Type::Get: {
2✔
1142
            ParamValue value;
4✔
1143
            value.set_from_mavlink_param_ext_value(param_ext_value);
2✔
1144

1145
            if (value.is_same_type(work->param_value)) {
2✔
1146
                if (std::get_if<GetParamFloatCallback>(&work->callback)) {
2✔
1147
                    const auto& callback = std::get<GetParamFloatCallback>(work->callback);
×
1148
                    if (callback) {
×
1149
                        if (value.get_float()) {
×
1150
                            callback(MAVLinkParameters::Result::Success, value.get_float().value());
×
1151
                        } else {
1152
                            callback(MAVLinkParameters::Result::WrongType, NAN);
×
1153
                        }
1154
                    }
1155
                } else if (std::get_if<GetParamIntCallback>(&work->callback)) {
2✔
1156
                    const auto& callback = std::get<GetParamIntCallback>(work->callback);
×
1157
                    if (callback) {
×
1158
                        if (value.get_int()) {
×
1159
                            callback(MAVLinkParameters::Result::Success, value.get_int().value());
×
1160
                        } else {
1161
                            callback(MAVLinkParameters::Result::WrongType, 0);
×
1162
                        }
1163
                    }
1164
                } else if (std::get_if<GetParamCustomCallback>(&work->callback)) {
2✔
1165
                    const auto& callback = std::get<GetParamCustomCallback>(work->callback);
2✔
1166
                    if (callback) {
2✔
1167
                        if (value.get_custom()) {
2✔
1168
                            callback(
4✔
1169
                                MAVLinkParameters::Result::Success, value.get_custom().value());
4✔
1170
                        } else {
1171
                            callback(MAVLinkParameters::Result::WrongType, 0);
×
1172
                        }
1173
                    }
1174
                } else if (std::get_if<GetParamAnyCallback>(&work->callback)) {
×
1175
                    const auto& callback = std::get<GetParamAnyCallback>(work->callback);
×
1176
                    if (callback) {
×
1177
                        callback(MAVLinkParameters::Result::Success, value);
×
1178
                    }
1179
                }
1180
            } else {
1181
                LogErr() << "Param types don't match for " << work->param_name;
×
1182

1183
                if (std::get_if<GetParamFloatCallback>(&work->callback)) {
×
1184
                    const auto& callback = std::get<GetParamFloatCallback>(work->callback);
×
1185
                    if (callback) {
×
1186
                        callback(MAVLinkParameters::Result::WrongType, NAN);
×
1187
                    }
1188
                } else if (std::get_if<GetParamIntCallback>(&work->callback)) {
×
1189
                    const auto& callback = std::get<GetParamIntCallback>(work->callback);
×
1190
                    if (callback) {
×
1191
                        callback(MAVLinkParameters::Result::WrongType, 0);
×
1192
                    }
1193
                } else if (std::get_if<GetParamCustomCallback>(&work->callback)) {
×
1194
                    const auto& callback = std::get<GetParamCustomCallback>(work->callback);
×
1195
                    if (callback) {
×
1196
                        callback(MAVLinkParameters::Result::WrongType, {});
×
1197
                    }
1198
                } else if (std::get_if<GetParamAnyCallback>(&work->callback)) {
×
1199
                    const auto& callback = std::get<GetParamAnyCallback>(work->callback);
×
1200
                    if (callback) {
×
1201
                        callback(MAVLinkParameters::Result::WrongType, ParamValue{});
×
1202
                    }
1203
                }
1204
            }
1205

1206
            _timeout_handler.remove(_timeout_cookie);
2✔
1207
            // LogDebug() << "time taken: " <<
1208
            // _sender.get_time().elapsed_since_s(_last_request_time);
1209
            work_queue_guard.pop_front();
2✔
1210
        } break;
1211

1212
        case WorkItem::Type::Set:
×
1213
            LogWarn() << "Unexpected ParamExtValue response";
×
1214
            break;
×
1215
        default:
×
1216
            break;
×
1217
    }
1218
}
1219

1220
void MAVLinkParameters::process_param_ext_ack(const mavlink_message_t& message)
1✔
1221
{
1222
    // LogDebug() << "getting param ext ack";
1223

1224
    mavlink_param_ext_ack_t param_ext_ack;
1✔
1225
    mavlink_msg_param_ext_ack_decode(&message, &param_ext_ack);
1✔
1226

1227
    LockedQueue<WorkItem>::Guard work_queue_guard(_work_queue);
1✔
1228
    auto work = work_queue_guard.get_front();
1✔
1229

1230
    if (!work) {
1✔
1231
        return;
×
1232
    }
1233

1234
    if (!work->already_requested) {
1✔
1235
        return;
×
1236
    }
1237

1238
    // Now it still needs to match the param name
1239
    if (work->param_name != extract_safe_param_id(param_ext_ack.param_id)) {
1✔
1240
        return;
×
1241
    }
1242

1243
    switch (work->type) {
1✔
1244
        case WorkItem::Type::Get: {
×
1245
            LogWarn() << "Unexpected ParamExtAck response.";
×
1246
        } break;
×
1247

1248
        case WorkItem::Type::Set: {
1✔
1249
            if (param_ext_ack.param_result == PARAM_ACK_ACCEPTED) {
1✔
1250
                // We are done, inform caller and go back to idle
1251
                if (std::get_if<SetParamCallback>(&work->callback)) {
1✔
1252
                    const auto& callback = std::get<SetParamCallback>(work->callback);
1✔
1253
                    if (callback) {
1✔
1254
                        callback(MAVLinkParameters::Result::Success);
1✔
1255
                    }
1256
                }
1257

1258
                _timeout_handler.remove(_timeout_cookie);
1✔
1259
                // LogDebug() << "time taken: " <<
1260
                // _sender.get_time().elapsed_since_s(_last_request_time);
1261
                work_queue_guard.pop_front();
1✔
1262

1263
            } else if (param_ext_ack.param_result == PARAM_ACK_IN_PROGRESS) {
×
1264
                // Reset timeout and wait again.
1265
                _timeout_handler.refresh(_timeout_cookie);
×
1266

1267
            } else {
1268
                LogErr() << "Somehow we did not get an ack, we got: "
×
1269
                         << int(param_ext_ack.param_result);
×
1270

1271
                if (std::get_if<SetParamCallback>(&work->callback)) {
×
1272
                    const auto& callback = std::get<SetParamCallback>(work->callback);
×
1273
                    if (callback) {
×
1274
                        auto result = [&]() {
×
1275
                            switch (param_ext_ack.param_result) {
×
1276
                                case PARAM_ACK_FAILED:
×
1277
                                    return MAVLinkParameters::Result::Failed;
×
1278
                                case PARAM_ACK_VALUE_UNSUPPORTED:
×
1279
                                    return MAVLinkParameters::Result::ValueUnsupported;
×
1280
                                default:
×
1281
                                    return MAVLinkParameters::Result::UnknownError;
×
1282
                            }
1283
                        }();
×
1284
                        callback(result);
×
1285
                    }
1286
                }
1287

1288
                _timeout_handler.remove(_timeout_cookie);
×
1289
                // LogDebug() << "time taken: " <<
1290
                // _sender.get_time().elapsed_since_s(_last_request_time);
1291
                work_queue_guard.pop_front();
×
1292
            }
1293
        } break;
1✔
1294
        default:
×
1295
            break;
×
1296
    }
1297
}
1298

1299
void MAVLinkParameters::process_param_ext_set(const mavlink_message_t& message)
1✔
1300
{
1301
    mavlink_param_ext_set_t set_request{};
1✔
1302
    mavlink_msg_param_ext_set_decode(&message, &set_request);
1✔
1303

1304
    std::string safe_param_id = extract_safe_param_id(set_request.param_id);
1✔
1305
    if (!safe_param_id.empty()) {
1✔
1306
        LogDebug() << "Set Param Request: " << safe_param_id;
1✔
1307
        {
1308
            // Use the ID
1309
            std::lock_guard<std::mutex> lock(_all_params_mutex);
1✔
1310
            ParamValue value{};
1✔
1311
            if (!value.set_from_mavlink_param_ext_set(set_request)) {
1✔
1312
                LogWarn() << "Invalid Param Ext Set Request: " << safe_param_id;
×
1313
                return;
×
1314
            }
1315
            _all_params[safe_param_id] = value;
1✔
1316
        }
1317

1318
        auto new_work = std::make_shared<WorkItem>(_timeout_s_callback());
2✔
1319
        new_work->type = WorkItem::Type::Ack;
1✔
1320
        new_work->param_name = safe_param_id;
1✔
1321
        new_work->param_value = _all_params[safe_param_id];
1✔
1322
        new_work->extended = true;
1✔
1323
        _work_queue.push_back(new_work);
1✔
1324
        std::lock_guard<std::mutex> lock(_param_changed_subscriptions_mutex);
2✔
1325

1326
        for (const auto& subscription : _param_changed_subscriptions) {
1✔
1327
            if (subscription.param_name != safe_param_id) {
×
1328
                continue;
×
1329
            }
1330

1331
            if (!subscription.any_type &&
×
1332
                !subscription.value_type.is_same_type(new_work->param_value)) {
×
1333
                LogErr() << "Received wrong param type in subscription for "
×
1334
                         << subscription.param_name;
×
1335
                continue;
×
1336
            }
1337

1338
            call_param_changed_callback(subscription.callback, new_work->param_value);
×
1339
        }
1340
    } else {
1341
        LogWarn() << "Invalid Param Ext Set ID Request: " << safe_param_id;
×
1342
    }
1343
}
1344

1345
void MAVLinkParameters::receive_timeout()
×
1346
{
1347
    {
1348
        std::lock_guard<std::mutex> lock(_all_params_mutex);
×
1349
        // first check if we are waiting for param list response
1350
        if (_all_params_callback) {
×
1351
            _all_params_callback({});
×
1352
            return;
×
1353
        }
1354
    }
1355

1356
    LockedQueue<WorkItem>::Guard work_queue_guard(_work_queue);
×
1357
    auto work = work_queue_guard.get_front();
×
1358

1359
    if (!work) {
×
1360
        LogErr() << "Received timeout without work";
×
1361
        return;
×
1362
    }
1363

1364
    if (!work->already_requested) {
×
1365
        return;
×
1366
    }
1367

1368
    switch (work->type) {
×
1369
        case WorkItem::Type::Get: {
×
1370
            ParamValue empty_value;
×
1371
            if (work->retries_to_do > 0) {
×
1372
                // We're not sure the command arrived, let's retransmit.
1373
                LogWarn() << "sending again, retries to do: " << work->retries_to_do << "  ("
×
1374
                          << work->param_name << ").";
×
1375
                if (!_sender.send_message(work->mavlink_message)) {
×
1376
                    LogErr() << "connection send error in retransmit (" << work->param_name << ").";
×
1377
                    work_queue_guard.pop_front();
×
1378

1379
                    if (std::get_if<GetParamFloatCallback>(&work->callback)) {
×
1380
                        const auto& callback = std::get<GetParamFloatCallback>(work->callback);
×
1381
                        if (callback) {
×
1382
                            callback(Result::ConnectionError, NAN);
×
1383
                        }
1384
                    } else if (std::get_if<GetParamIntCallback>(&work->callback)) {
×
1385
                        const auto& callback = std::get<GetParamIntCallback>(work->callback);
×
1386
                        if (callback) {
×
1387
                            callback(Result::ConnectionError, 0);
×
1388
                        }
1389
                    } else if (std::get_if<GetParamAnyCallback>(&work->callback)) {
×
1390
                        const auto& callback = std::get<GetParamAnyCallback>(work->callback);
×
1391
                        if (callback) {
×
1392
                            callback(Result::ConnectionError, ParamValue{});
×
1393
                        }
1394
                    }
1395
                } else {
1396
                    --work->retries_to_do;
×
1397
                    _timeout_handler.add(
×
1398
                        [this] { receive_timeout(); }, work->timeout_s, &_timeout_cookie);
×
1399
                }
1400
            } else {
1401
                // We have tried retransmitting, giving up now.
1402
                LogErr() << "Error: Retrying failed get param busy timeout: " << work->param_name;
×
1403

1404
                work_queue_guard.pop_front();
×
1405

1406
                if (std::get_if<GetParamFloatCallback>(&work->callback)) {
×
1407
                    const auto& callback = std::get<GetParamFloatCallback>(work->callback);
×
1408
                    if (callback) {
×
1409
                        callback(MAVLinkParameters::Result::Timeout, NAN);
×
1410
                    }
1411
                } else if (std::get_if<GetParamIntCallback>(&work->callback)) {
×
1412
                    const auto& callback = std::get<GetParamIntCallback>(work->callback);
×
1413
                    if (callback) {
×
1414
                        callback(MAVLinkParameters::Result::Timeout, 0);
×
1415
                    }
1416
                }
1417
            }
1418
        } break;
1419
        case WorkItem::Type::Set: {
×
1420
            if (work->retries_to_do > 0) {
×
1421
                // We're not sure the command arrived, let's retransmit.
1422
                LogWarn() << "sending again, retries to do: " << work->retries_to_do << "  ("
×
1423
                          << work->param_name << ").";
×
1424
                if (!_sender.send_message(work->mavlink_message)) {
×
1425
                    LogErr() << "connection send error in retransmit (" << work->param_name << ").";
×
1426
                    work_queue_guard.pop_front();
×
1427
                    if (std::get_if<SetParamCallback>(&work->callback)) {
×
1428
                        const auto& callback = std::get<SetParamCallback>(work->callback);
×
1429
                        if (callback) {
×
1430
                            callback(MAVLinkParameters::Result::ConnectionError);
×
1431
                        }
1432
                    }
1433
                } else {
1434
                    --work->retries_to_do;
×
1435
                    _timeout_handler.add(
×
1436
                        [this] { receive_timeout(); }, work->timeout_s, &_timeout_cookie);
×
1437
                }
1438
            } else {
1439
                // We have tried retransmitting, giving up now.
1440
                LogErr() << "Error: Retrying failed get param busy timeout: " << work->param_name;
×
1441

1442
                work_queue_guard.pop_front();
×
1443
                if (std::get_if<SetParamCallback>(&work->callback)) {
×
1444
                    const auto& callback = std::get<SetParamCallback>(work->callback);
×
1445
                    if (callback) {
×
1446
                        callback(MAVLinkParameters::Result::Timeout);
×
1447
                    }
1448
                }
1449
            }
1450
        } break;
×
1451
        default:
×
1452
            break;
×
1453
    }
1454
}
1455

1456
std::string MAVLinkParameters::extract_safe_param_id(const char param_id[])
230✔
1457
{
1458
    // The param_id field of the MAVLink struct has length 16 and is not 0 terminated.
1459
    // Therefore, we make a 0 terminated copy first.
1460
    char param_id_long_enough[PARAM_ID_LEN + 1] = {};
230✔
1461
    std::memcpy(param_id_long_enough, param_id, PARAM_ID_LEN);
230✔
1462
    return {param_id_long_enough};
230✔
1463
}
1464

1465
std::ostream& operator<<(std::ostream& strm, const MAVLinkParameters::ParamValue& obj)
82✔
1466
{
1467
    strm << obj.get_string();
82✔
1468
    return strm;
82✔
1469
}
1470

1471
void MAVLinkParameters::process_param_set(const mavlink_message_t& message)
2✔
1472
{
1473
    mavlink_param_set_t set_request{};
2✔
1474
    mavlink_msg_param_set_decode(&message, &set_request);
2✔
1475

1476
    std::string safe_param_id = extract_safe_param_id(set_request.param_id);
2✔
1477
    if (!safe_param_id.empty()) {
2✔
1478
        LogDebug() << "Set Param Request: " << safe_param_id << " with value "
4✔
1479
                   << *(int32_t*)(&set_request.param_value);
4✔
1480

1481
        // Use the ID
1482
        if (_all_params.find(safe_param_id) != _all_params.end()) {
2✔
1483
            ParamValue value{};
2✔
1484
            if (!value.set_from_mavlink_param_set_bytewise(set_request)) {
2✔
1485
                LogWarn() << "Invalid Param Set Request: " << safe_param_id;
×
1486
                return;
×
1487
            }
1488

1489
            LogDebug() << "Changing param from " << _all_params[safe_param_id] << " to " << value;
2✔
1490
            _all_params[safe_param_id] = value;
2✔
1491

1492
            auto new_work = std::make_shared<WorkItem>(_timeout_s_callback());
4✔
1493
            new_work->type = WorkItem::Type::Value;
2✔
1494
            new_work->param_name = safe_param_id;
2✔
1495
            new_work->param_value = _all_params.at(safe_param_id);
2✔
1496
            new_work->extended = false;
2✔
1497
            _work_queue.push_back(new_work);
2✔
1498
            std::lock_guard<std::mutex> lock(_param_changed_subscriptions_mutex);
4✔
1499
            for (const auto& subscription : _param_changed_subscriptions) {
2✔
1500
                if (subscription.param_name != safe_param_id) {
×
1501
                    continue;
×
1502
                }
1503
                if (!subscription.any_type && !subscription.value_type.is_same_type(value)) {
×
1504
                    LogErr() << "Received wrong param type in subscription for "
×
1505
                             << subscription.param_name;
×
1506
                    continue;
×
1507
                }
1508

1509
                call_param_changed_callback(subscription.callback, value);
×
1510
            }
1511
        } else {
1512
            LogDebug() << "Missing Param: " << safe_param_id << "(this: " << this << ")";
×
1513
        }
1514
    } else {
1515
        LogWarn() << "Invalid Param Set ID Request: " << safe_param_id;
×
1516
    }
1517
}
1518

1519
void MAVLinkParameters::call_param_changed_callback(
×
1520
    const ParamChangedCallbacks& callback, const ParamValue& value)
1521
{
1522
    if (std::get_if<ParamFloatChangedCallback>(&callback) && value.get_float()) {
×
1523
        std::get<ParamFloatChangedCallback>(callback)(value.get_float().value());
×
1524

1525
    } else if (std::get_if<ParamIntChangedCallback>(&callback) && value.get_int()) {
×
1526
        std::get<ParamIntChangedCallback>(callback)(value.get_int().value());
×
1527

1528
    } else if (std::get_if<ParamCustomChangedCallback>(&callback) && value.get_custom()) {
×
1529
        std::get<ParamCustomChangedCallback>(callback)(value.get_custom().value());
×
1530
    } else {
1531
        LogErr() << "Type and callback mismatch";
×
1532
    }
1533
}
×
1534

1535
void MAVLinkParameters::process_param_request_read(const mavlink_message_t& message)
4✔
1536
{
1537
    mavlink_param_request_read_t read_request{};
4✔
1538
    mavlink_msg_param_request_read_decode(&message, &read_request);
4✔
1539

1540
    std::string param_id = extract_safe_param_id(read_request.param_id);
8✔
1541

1542
    if (read_request.param_index == -1) {
4✔
1543
        auto safe_param_id = extract_safe_param_id(read_request.param_id);
8✔
1544
        LogDebug() << "Request Param " << safe_param_id;
4✔
1545

1546
        // Use the ID
1547
        if (_all_params.find(safe_param_id) != _all_params.end()) {
4✔
1548
            auto new_work = std::make_shared<WorkItem>(_timeout_s_callback());
8✔
1549
            new_work->type = WorkItem::Type::Value;
4✔
1550
            new_work->param_name = safe_param_id;
4✔
1551
            new_work->param_value = _all_params.at(safe_param_id);
4✔
1552
            new_work->extended = false;
4✔
1553
            _work_queue.push_back(new_work);
4✔
1554
        } else {
1555
            LogDebug() << "Missing Param " << safe_param_id;
×
1556
        }
1557
    }
1558
}
4✔
1559

1560
void MAVLinkParameters::process_param_request_list(const mavlink_message_t& message)
1✔
1561
{
1562
    mavlink_param_request_list_t list_request{};
1✔
1563
    mavlink_msg_param_request_list_decode(&message, &list_request);
1✔
1564

1565
    auto idx = 0;
1✔
1566
    for (const auto& pair : _all_params) {
201✔
1567
        auto new_work = std::make_shared<WorkItem>(_timeout_s_callback());
400✔
1568
        new_work->type = WorkItem::Type::Value;
200✔
1569
        new_work->param_name = pair.first;
200✔
1570
        new_work->param_value = pair.second;
200✔
1571
        new_work->extended = false;
200✔
1572
        new_work->param_count = static_cast<int>(_all_params.size());
200✔
1573
        new_work->param_index = idx++;
200✔
1574
        _work_queue.push_back(new_work);
200✔
1575
    }
1576
}
1✔
1577

1578
void MAVLinkParameters::process_param_ext_request_read(const mavlink_message_t& message)
2✔
1579
{
1580
    mavlink_param_request_read_t read_request{};
2✔
1581
    mavlink_msg_param_request_read_decode(&message, &read_request);
2✔
1582

1583
    std::string param_id = extract_safe_param_id(read_request.param_id);
4✔
1584

1585
    if (read_request.param_index == -1) {
2✔
1586
        auto safe_param_id = extract_safe_param_id(read_request.param_id);
4✔
1587
        LogDebug() << "Request Param " << safe_param_id;
2✔
1588
        // Use the ID
1589
        if (_all_params.find(safe_param_id) != _all_params.end()) {
2✔
1590
            auto new_work = std::make_shared<WorkItem>(_timeout_s_callback());
4✔
1591
            new_work->type = WorkItem::Type::Value;
2✔
1592
            new_work->param_name = safe_param_id;
2✔
1593
            new_work->param_value = _all_params.at(safe_param_id);
2✔
1594
            new_work->extended = true;
2✔
1595
            _work_queue.push_back(new_work);
2✔
1596
        } else {
1597
            LogDebug() << "Missing Param " << safe_param_id;
×
1598
        }
1599
    }
1600
}
2✔
1601

1602
bool MAVLinkParameters::ParamValue::set_from_mavlink_param_value_bytewise(
208✔
1603
    const mavlink_param_value_t& mavlink_value)
1604
{
1605
    switch (mavlink_value.param_type) {
208✔
1606
        case MAV_PARAM_TYPE_UINT8: {
×
1607
            uint8_t temp;
×
1608
            memcpy(&temp, &mavlink_value.param_value, sizeof(temp));
×
1609
            _value = temp;
×
1610
        } break;
1611

1612
        case MAV_PARAM_TYPE_INT8: {
×
1613
            int8_t temp;
×
1614
            memcpy(&temp, &mavlink_value.param_value, sizeof(temp));
×
1615
            _value = temp;
×
1616
        } break;
1617

1618
        case MAV_PARAM_TYPE_UINT16: {
×
1619
            uint16_t temp;
×
1620
            memcpy(&temp, &mavlink_value.param_value, sizeof(temp));
×
1621
            _value = temp;
×
1622
        } break;
1623

1624
        case MAV_PARAM_TYPE_INT16: {
×
1625
            int16_t temp;
×
1626
            memcpy(&temp, &mavlink_value.param_value, sizeof(temp));
×
1627
            _value = temp;
×
1628
        } break;
1629

1630
        case MAV_PARAM_TYPE_UINT32: {
×
1631
            uint32_t temp;
×
1632
            memcpy(&temp, &mavlink_value.param_value, sizeof(temp));
×
1633
            _value = temp;
×
1634
        } break;
1635

1636
        case MAV_PARAM_TYPE_INT32: {
104✔
1637
            int32_t temp;
104✔
1638
            memcpy(&temp, &mavlink_value.param_value, sizeof(temp));
104✔
1639
            _value = temp;
104✔
1640
        } break;
1641

1642
        case MAV_PARAM_TYPE_REAL32: {
104✔
1643
            _value = mavlink_value.param_value;
104✔
1644
        } break;
104✔
1645

1646
        default:
×
1647
            // This would be worrying
1648
            LogErr() << "Error: unknown mavlink param type: "
×
1649
                     << std::to_string(mavlink_value.param_type);
×
1650
            return false;
×
1651
    }
1652
    return true;
208✔
1653
}
1654

1655
bool MAVLinkParameters::ParamValue::set_from_mavlink_param_value_cast(
×
1656
    const mavlink_param_value_t& mavlink_value)
1657
{
1658
    switch (mavlink_value.param_type) {
×
1659
        case MAV_PARAM_TYPE_UINT8: {
×
1660
            _value = static_cast<uint8_t>(mavlink_value.param_value);
×
1661
        } break;
×
1662

1663
        case MAV_PARAM_TYPE_INT8: {
×
1664
            _value = static_cast<int8_t>(mavlink_value.param_value);
×
1665
        } break;
×
1666

1667
        case MAV_PARAM_TYPE_UINT16: {
×
1668
            _value = static_cast<uint16_t>(mavlink_value.param_value);
×
1669
        } break;
×
1670

1671
        case MAV_PARAM_TYPE_INT16: {
×
1672
            _value = static_cast<int16_t>(mavlink_value.param_value);
×
1673
        } break;
×
1674

1675
        case MAV_PARAM_TYPE_UINT32: {
×
1676
            _value = static_cast<uint32_t>(mavlink_value.param_value);
×
1677
        } break;
×
1678

1679
        case MAV_PARAM_TYPE_INT32: {
×
1680
            _value = static_cast<int32_t>(mavlink_value.param_value);
×
1681
        } break;
×
1682

1683
        case MAV_PARAM_TYPE_REAL32: {
×
1684
            float temp = mavlink_value.param_value;
×
1685
            _value = temp;
×
1686
        } break;
1687

1688
        default:
×
1689
            // This would be worrying
1690
            LogErr() << "Error: unknown mavlink param type: "
×
1691
                     << std::to_string(mavlink_value.param_type);
×
1692
            return false;
×
1693
    }
1694
    return true;
×
1695
}
1696

1697
bool MAVLinkParameters::ParamValue::set_from_mavlink_param_set_bytewise(
2✔
1698
    const mavlink_param_set_t& mavlink_set)
1699
{
1700
    mavlink_param_value_t mavlink_value{};
2✔
1701
    mavlink_value.param_value = mavlink_set.param_value;
2✔
1702
    mavlink_value.param_type = mavlink_set.param_type;
2✔
1703

1704
    return set_from_mavlink_param_value_bytewise(mavlink_value);
2✔
1705
}
1706

1707
bool MAVLinkParameters::ParamValue::set_from_mavlink_param_ext_set(
1✔
1708
    const mavlink_param_ext_set_t& mavlink_ext_set)
1709
{
1710
    switch (mavlink_ext_set.param_type) {
1✔
1711
        case MAV_PARAM_EXT_TYPE_UINT8: {
×
1712
            uint8_t temp;
×
1713
            memcpy(&temp, &mavlink_ext_set.param_value[0], sizeof(temp));
×
1714
            _value = temp;
×
1715
        } break;
1716
        case MAV_PARAM_EXT_TYPE_INT8: {
×
1717
            int8_t temp;
×
1718
            memcpy(&temp, &mavlink_ext_set.param_value[0], sizeof(temp));
×
1719
            _value = temp;
×
1720
        } break;
1721
        case MAV_PARAM_EXT_TYPE_UINT16: {
×
1722
            uint16_t temp;
×
1723
            memcpy(&temp, &mavlink_ext_set.param_value[0], sizeof(temp));
×
1724
            _value = temp;
×
1725
        } break;
1726
        case MAV_PARAM_EXT_TYPE_INT16: {
×
1727
            int16_t temp;
×
1728
            memcpy(&temp, &mavlink_ext_set.param_value[0], sizeof(temp));
×
1729
            _value = temp;
×
1730
        } break;
1731
        case MAV_PARAM_EXT_TYPE_UINT32: {
×
1732
            uint32_t temp;
×
1733
            memcpy(&temp, &mavlink_ext_set.param_value[0], sizeof(temp));
×
1734
            _value = temp;
×
1735
        } break;
1736
        case MAV_PARAM_EXT_TYPE_INT32: {
×
1737
            int32_t temp;
×
1738
            memcpy(&temp, &mavlink_ext_set.param_value[0], sizeof(temp));
×
1739
            _value = temp;
×
1740
        } break;
1741
        case MAV_PARAM_EXT_TYPE_UINT64: {
×
1742
            uint64_t temp;
×
1743
            memcpy(&temp, &mavlink_ext_set.param_value[0], sizeof(temp));
×
1744
            _value = temp;
×
1745
        } break;
1746
        case MAV_PARAM_EXT_TYPE_INT64: {
×
1747
            int64_t temp;
×
1748
            memcpy(&temp, &mavlink_ext_set.param_value[0], sizeof(temp));
×
1749
            _value = temp;
×
1750
        } break;
1751
        case MAV_PARAM_EXT_TYPE_REAL32: {
×
1752
            float temp;
×
1753
            memcpy(&temp, &mavlink_ext_set.param_value[0], sizeof(temp));
×
1754
            _value = temp;
×
1755
        } break;
1756
        case MAV_PARAM_EXT_TYPE_REAL64: {
×
1757
            double temp;
×
1758
            memcpy(&temp, &mavlink_ext_set.param_value[0], sizeof(temp));
×
1759
            _value = temp;
×
1760
        } break;
1761
        case MAV_PARAM_EXT_TYPE_CUSTOM: {
1✔
1762
            std::size_t len = std::min(std::size_t(128), strlen(mavlink_ext_set.param_value));
1✔
1763
            _value = std::string(mavlink_ext_set.param_value, mavlink_ext_set.param_value + len);
1✔
1764
        } break;
1✔
1765
        default:
×
1766
            // This would be worrying
1767
            LogErr() << "Error: unknown mavlink ext param type";
×
1768
            assert(false);
×
1769
            return false;
1770
    }
1771
    return true;
1✔
1772
}
1773

1774
// FIXME: this function can collapse with the one above.
1775
bool MAVLinkParameters::ParamValue::set_from_mavlink_param_ext_value(
2✔
1776
    const mavlink_param_ext_value_t& mavlink_ext_value)
1777
{
1778
    switch (mavlink_ext_value.param_type) {
2✔
1779
        case MAV_PARAM_EXT_TYPE_UINT8: {
×
1780
            uint8_t temp;
×
1781
            memcpy(&temp, &mavlink_ext_value.param_value[0], sizeof(temp));
×
1782
            _value = temp;
×
1783
        } break;
1784
        case MAV_PARAM_EXT_TYPE_INT8: {
×
1785
            int8_t temp;
×
1786
            memcpy(&temp, &mavlink_ext_value.param_value[0], sizeof(temp));
×
1787
            _value = temp;
×
1788
        } break;
1789
        case MAV_PARAM_EXT_TYPE_UINT16: {
×
1790
            uint16_t temp;
×
1791
            memcpy(&temp, &mavlink_ext_value.param_value[0], sizeof(temp));
×
1792
            _value = temp;
×
1793
        } break;
1794
        case MAV_PARAM_EXT_TYPE_INT16: {
×
1795
            int16_t temp;
×
1796
            memcpy(&temp, &mavlink_ext_value.param_value[0], sizeof(temp));
×
1797
            _value = temp;
×
1798
        } break;
1799
        case MAV_PARAM_EXT_TYPE_UINT32: {
×
1800
            uint32_t temp;
×
1801
            memcpy(&temp, &mavlink_ext_value.param_value[0], sizeof(temp));
×
1802
            _value = temp;
×
1803
        } break;
1804
        case MAV_PARAM_EXT_TYPE_INT32: {
×
1805
            int32_t temp;
×
1806
            memcpy(&temp, &mavlink_ext_value.param_value[0], sizeof(temp));
×
1807
            _value = temp;
×
1808
        } break;
1809
        case MAV_PARAM_EXT_TYPE_UINT64: {
×
1810
            uint64_t temp;
×
1811
            memcpy(&temp, &mavlink_ext_value.param_value[0], sizeof(temp));
×
1812
            _value = temp;
×
1813
        } break;
1814
        case MAV_PARAM_EXT_TYPE_INT64: {
×
1815
            int64_t temp;
×
1816
            memcpy(&temp, &mavlink_ext_value.param_value[0], sizeof(temp));
×
1817
            _value = temp;
×
1818
        } break;
1819
        case MAV_PARAM_EXT_TYPE_REAL32: {
×
1820
            float temp;
×
1821
            memcpy(&temp, &mavlink_ext_value.param_value[0], sizeof(temp));
×
1822
            _value = temp;
×
1823
        } break;
1824
        case MAV_PARAM_EXT_TYPE_REAL64: {
×
1825
            double temp;
×
1826
            memcpy(&temp, &mavlink_ext_value.param_value[0], sizeof(temp));
×
1827
            _value = temp;
×
1828
        } break;
1829
        case MAV_PARAM_EXT_TYPE_CUSTOM: {
2✔
1830
            std::size_t len = std::min(std::size_t(128), strlen(mavlink_ext_value.param_value));
2✔
1831
            _value =
2✔
1832
                std::string(mavlink_ext_value.param_value, mavlink_ext_value.param_value + len);
2✔
1833
        } break;
2✔
1834
        default:
×
1835
            // This would be worrying
1836
            LogErr() << "Error: unknown mavlink ext param type";
×
1837
            assert(false);
×
1838
            return false;
1839
    }
1840
    return true;
2✔
1841
}
1842

1843
bool MAVLinkParameters::ParamValue::set_from_xml(
6,091✔
1844
    const std::string& type_str, const std::string& value_str)
1845
{
1846
    if (strcmp(type_str.c_str(), "uint8") == 0) {
6,091✔
1847
        _value = static_cast<uint8_t>(std::stoi(value_str));
50✔
1848
    } else if (strcmp(type_str.c_str(), "int8") == 0) {
6,041✔
1849
        _value = static_cast<int8_t>(std::stoi(value_str));
×
1850
    } else if (strcmp(type_str.c_str(), "uint16") == 0) {
6,041✔
1851
        _value = static_cast<uint16_t>(std::stoi(value_str));
30✔
1852
    } else if (strcmp(type_str.c_str(), "int16") == 0) {
6,011✔
1853
        _value = static_cast<int16_t>(std::stoi(value_str));
×
1854
    } else if (strcmp(type_str.c_str(), "uint32") == 0) {
6,011✔
1855
        _value = static_cast<uint32_t>(std::stoi(value_str));
1,114✔
1856
    } else if (strcmp(type_str.c_str(), "int32") == 0) {
4,897✔
1857
        _value = static_cast<int32_t>(std::stoi(value_str));
287✔
1858
    } else if (strcmp(type_str.c_str(), "uint64") == 0) {
4,610✔
1859
        _value = static_cast<uint64_t>(std::stoll(value_str));
×
1860
    } else if (strcmp(type_str.c_str(), "int64") == 0) {
4,610✔
1861
        _value = static_cast<int64_t>(std::stoll(value_str));
×
1862
    } else if (strcmp(type_str.c_str(), "float") == 0) {
4,610✔
1863
        _value = static_cast<float>(std::stof(value_str));
4,610✔
1864
    } else if (strcmp(type_str.c_str(), "double") == 0) {
×
1865
        _value = static_cast<double>(std::stod(value_str));
×
1866
    } else {
1867
        LogErr() << "Unknown type: " << type_str;
×
1868
        return false;
×
1869
    }
1870
    return true;
6,091✔
1871
}
1872

1873
bool MAVLinkParameters::ParamValue::set_empty_type_from_xml(const std::string& type_str)
291✔
1874
{
1875
    if (strcmp(type_str.c_str(), "uint8") == 0) {
291✔
1876
        _value = uint8_t(0);
20✔
1877
    } else if (strcmp(type_str.c_str(), "int8") == 0) {
271✔
1878
        _value = int8_t(0);
×
1879
    } else if (strcmp(type_str.c_str(), "uint16") == 0) {
271✔
1880
        _value = uint16_t(0);
20✔
1881
    } else if (strcmp(type_str.c_str(), "int16") == 0) {
251✔
1882
        _value = int16_t(0);
×
1883
    } else if (strcmp(type_str.c_str(), "uint32") == 0) {
251✔
1884
        _value = uint32_t(0);
127✔
1885
    } else if (strcmp(type_str.c_str(), "int32") == 0) {
124✔
1886
        _value = int32_t(0);
84✔
1887
    } else if (strcmp(type_str.c_str(), "uint64") == 0) {
40✔
1888
        _value = uint64_t(0);
10✔
1889
    } else if (strcmp(type_str.c_str(), "int64") == 0) {
30✔
1890
        _value = int64_t(0);
×
1891
    } else if (strcmp(type_str.c_str(), "float") == 0) {
30✔
1892
        _value = 0.0f;
30✔
1893
    } else if (strcmp(type_str.c_str(), "double") == 0) {
×
1894
        _value = 0.0;
×
1895
    } else {
1896
        LogErr() << "Unknown type: " << type_str;
×
1897
        return false;
×
1898
    }
1899
    return true;
291✔
1900
}
1901

1902
[[nodiscard]] MAV_PARAM_TYPE MAVLinkParameters::ParamValue::get_mav_param_type() const
208✔
1903
{
1904
    if (std::get_if<uint8_t>(&_value)) {
208✔
1905
        return MAV_PARAM_TYPE_UINT8;
×
1906
    } else if (std::get_if<int8_t>(&_value)) {
208✔
1907
        return MAV_PARAM_TYPE_INT8;
×
1908
    } else if (std::get_if<uint16_t>(&_value)) {
208✔
1909
        return MAV_PARAM_TYPE_UINT16;
×
1910
    } else if (std::get_if<int16_t>(&_value)) {
208✔
1911
        return MAV_PARAM_TYPE_INT16;
×
1912
    } else if (std::get_if<uint32_t>(&_value)) {
208✔
1913
        return MAV_PARAM_TYPE_UINT32;
×
1914
    } else if (std::get_if<int32_t>(&_value)) {
208✔
1915
        return MAV_PARAM_TYPE_INT32;
104✔
1916
    } else if (std::get_if<uint64_t>(&_value)) {
104✔
1917
        return MAV_PARAM_TYPE_UINT64;
×
1918
    } else if (std::get_if<int64_t>(&_value)) {
104✔
1919
        return MAV_PARAM_TYPE_INT64;
×
1920
    } else if (std::get_if<float>(&_value)) {
104✔
1921
        return MAV_PARAM_TYPE_REAL32;
104✔
1922
    } else if (std::get_if<double>(&_value)) {
×
1923
        return MAV_PARAM_TYPE_REAL64;
×
1924
    } else {
1925
        LogErr() << "Unknown data type for param.";
×
1926
        assert(false);
×
1927
        return MAV_PARAM_TYPE_INT32;
1928
    }
1929
}
1930

1931
[[nodiscard]] MAV_PARAM_EXT_TYPE MAVLinkParameters::ParamValue::get_mav_param_ext_type() const
4✔
1932
{
1933
    if (std::get_if<uint8_t>(&_value)) {
4✔
1934
        return MAV_PARAM_EXT_TYPE_UINT8;
×
1935
    } else if (std::get_if<int8_t>(&_value)) {
4✔
1936
        return MAV_PARAM_EXT_TYPE_INT8;
×
1937
    } else if (std::get_if<uint16_t>(&_value)) {
4✔
1938
        return MAV_PARAM_EXT_TYPE_UINT16;
×
1939
    } else if (std::get_if<int16_t>(&_value)) {
4✔
1940
        return MAV_PARAM_EXT_TYPE_INT16;
×
1941
    } else if (std::get_if<uint32_t>(&_value)) {
4✔
1942
        return MAV_PARAM_EXT_TYPE_UINT32;
×
1943
    } else if (std::get_if<int32_t>(&_value)) {
4✔
1944
        return MAV_PARAM_EXT_TYPE_INT32;
×
1945
    } else if (std::get_if<uint64_t>(&_value)) {
4✔
1946
        return MAV_PARAM_EXT_TYPE_UINT64;
×
1947
    } else if (std::get_if<int64_t>(&_value)) {
4✔
1948
        return MAV_PARAM_EXT_TYPE_INT64;
×
1949
    } else if (std::get_if<float>(&_value)) {
4✔
1950
        return MAV_PARAM_EXT_TYPE_REAL32;
×
1951
    } else if (std::get_if<double>(&_value)) {
4✔
1952
        return MAV_PARAM_EXT_TYPE_REAL64;
×
1953
    } else if (std::get_if<std::string>(&_value)) {
4✔
1954
        return MAV_PARAM_EXT_TYPE_CUSTOM;
4✔
1955
    } else {
1956
        LogErr() << "Unknown data type for param.";
×
1957
        assert(false);
×
1958
        return MAV_PARAM_EXT_TYPE_INT32;
1959
    }
1960
}
1961

1962
bool MAVLinkParameters::ParamValue::set_as_same_type(const std::string& value_str)
×
1963
{
1964
    if (std::get_if<uint8_t>(&_value)) {
×
1965
        _value = uint8_t(std::stoi(value_str));
×
1966
    } else if (std::get_if<int8_t>(&_value)) {
×
1967
        _value = int8_t(std::stoi(value_str));
×
1968
    } else if (std::get_if<uint16_t>(&_value)) {
×
1969
        _value = uint16_t(std::stoi(value_str));
×
1970
    } else if (std::get_if<int16_t>(&_value)) {
×
1971
        _value = int16_t(std::stoi(value_str));
×
1972
    } else if (std::get_if<uint32_t>(&_value)) {
×
1973
        _value = uint32_t(std::stoi(value_str));
×
1974
    } else if (std::get_if<int32_t>(&_value)) {
×
1975
        _value = int32_t(std::stoi(value_str));
×
1976
    } else if (std::get_if<uint64_t>(&_value)) {
×
1977
        _value = uint64_t(std::stoll(value_str));
×
1978
    } else if (std::get_if<int64_t>(&_value)) {
×
1979
        _value = int64_t(std::stoll(value_str));
×
1980
    } else if (std::get_if<float>(&_value)) {
×
1981
        _value = float(std::stof(value_str));
×
1982
    } else if (std::get_if<double>(&_value)) {
×
1983
        _value = double(std::stod(value_str));
×
1984
    } else {
1985
        LogErr() << "Unknown type";
×
1986
        return false;
×
1987
    }
1988
    return true;
×
1989
}
1990

1991
[[nodiscard]] float MAVLinkParameters::ParamValue::get_4_float_bytes_bytewise() const
208✔
1992
{
1993
    if (std::get_if<float>(&_value)) {
208✔
1994
        return std::get<float>(_value);
104✔
1995
    } else if (std::get_if<int32_t>(&_value)) {
104✔
1996
        return *(reinterpret_cast<const float*>(&std::get<int32_t>(_value)));
104✔
1997
    } else {
1998
        LogErr() << "Unknown type";
×
1999
        assert(false);
×
2000
        return NAN;
2001
    }
2002
}
2003

2004
[[nodiscard]] float MAVLinkParameters::ParamValue::get_4_float_bytes_cast() const
×
2005
{
2006
    if (std::get_if<float>(&_value)) {
×
2007
        return std::get<float>(_value);
×
2008
    } else if (std::get_if<uint32_t>(&_value)) {
×
2009
        return static_cast<float>(std::get<uint32_t>(_value));
×
2010
    } else if (std::get_if<int32_t>(&_value)) {
×
2011
        return static_cast<float>(std::get<int32_t>(_value));
×
2012
    } else if (std::get_if<uint16_t>(&_value)) {
×
2013
        return static_cast<float>(std::get<uint16_t>(_value));
×
2014
    } else if (std::get_if<int16_t>(&_value)) {
×
2015
        return static_cast<float>(std::get<int16_t>(_value));
×
2016
    } else if (std::get_if<uint8_t>(&_value)) {
×
2017
        return static_cast<float>(std::get<uint8_t>(_value));
×
2018
    } else if (std::get_if<int8_t>(&_value)) {
×
2019
        return static_cast<float>(std::get<int8_t>(_value));
×
2020
    } else {
2021
        LogErr() << "Unknown type";
×
2022
        assert(false);
×
2023
        return NAN;
2024
    }
2025
}
2026

2027
[[nodiscard]] std::optional<int> MAVLinkParameters::ParamValue::get_int() const
6✔
2028
{
2029
    if (std::get_if<uint32_t>(&_value)) {
6✔
2030
        return static_cast<int>(std::get<uint32_t>(_value));
×
2031
    } else if (std::get_if<int32_t>(&_value)) {
6✔
2032
        return static_cast<int>(std::get<int32_t>(_value));
6✔
2033
    } else if (std::get_if<uint16_t>(&_value)) {
×
2034
        return static_cast<int>(std::get<uint16_t>(_value));
×
2035
    } else if (std::get_if<int16_t>(&_value)) {
×
2036
        return static_cast<int>(std::get<int16_t>(_value));
×
2037
    } else if (std::get_if<uint8_t>(&_value)) {
×
2038
        return static_cast<int>(std::get<uint8_t>(_value));
×
2039
    } else if (std::get_if<int8_t>(&_value)) {
×
2040
        return static_cast<int>(std::get<int8_t>(_value));
×
2041
    } else {
2042
        LogErr() << "Not int type";
×
2043
        return {};
×
2044
    }
2045
}
2046

2047
bool MAVLinkParameters::ParamValue::set_int(int new_value)
1✔
2048
{
2049
    if (std::get_if<uint8_t>(&_value)) {
1✔
2050
        _value = static_cast<uint8_t>(new_value);
×
2051
        return true;
×
2052
    } else if (std::get_if<int8_t>(&_value)) {
1✔
2053
        _value = static_cast<int8_t>(new_value);
×
2054
        return true;
×
2055
    } else if (std::get_if<uint16_t>(&_value)) {
1✔
2056
        _value = static_cast<uint16_t>(new_value);
×
2057
        return true;
×
2058
    } else if (std::get_if<int16_t>(&_value)) {
1✔
2059
        _value = static_cast<int16_t>(new_value);
×
2060
        return true;
×
2061
    } else if (std::get_if<uint32_t>(&_value)) {
1✔
2062
        _value = static_cast<uint32_t>(new_value);
×
2063
        return true;
×
2064
    } else if (std::get_if<int32_t>(&_value)) {
1✔
2065
        _value = static_cast<int32_t>(new_value);
1✔
2066
        return true;
1✔
2067
    } else {
2068
        return false;
×
2069
    }
2070
}
2071

2072
void MAVLinkParameters::ParamValue::set_float(float new_value)
1✔
2073
{
2074
    _value = new_value;
1✔
2075
}
1✔
2076

2077
void MAVLinkParameters::ParamValue::set_custom(const std::string& new_value)
3✔
2078
{
2079
    _value = new_value;
3✔
2080
}
3✔
2081

2082
[[nodiscard]] std::optional<float> MAVLinkParameters::ParamValue::get_float() const
5✔
2083
{
2084
    if (std::get_if<float>(&_value)) {
5✔
2085
        return std::get<float>(_value);
5✔
2086
    } else {
2087
        LogErr() << "Not float type";
×
2088
        return {};
×
2089
    }
2090
}
2091

2092
[[nodiscard]] std::optional<std::string> MAVLinkParameters::ParamValue::get_custom() const
5✔
2093
{
2094
    if (std::get_if<std::string>(&_value)) {
5✔
2095
        return std::get<std::string>(_value);
5✔
2096
    } else {
2097
        LogErr() << "Not custom type";
×
2098
        return {};
×
2099
    }
2100
}
2101

2102
std::array<char, 128> MAVLinkParameters::ParamValue::get_128_bytes() const
4✔
2103
{
2104
    std::array<char, 128> bytes{};
4✔
2105

2106
    if (std::get_if<uint8_t>(&_value)) {
4✔
2107
        memcpy(bytes.data(), &std::get<uint8_t>(_value), sizeof(uint8_t));
×
2108
    } else if (std::get_if<int8_t>(&_value)) {
4✔
2109
        memcpy(bytes.data(), &std::get<int8_t>(_value), sizeof(int8_t));
×
2110
    } else if (std::get_if<uint16_t>(&_value)) {
4✔
2111
        memcpy(bytes.data(), &std::get<uint16_t>(_value), sizeof(uint16_t));
×
2112
    } else if (std::get_if<int16_t>(&_value)) {
4✔
2113
        memcpy(bytes.data(), &std::get<int16_t>(_value), sizeof(int16_t));
×
2114
    } else if (std::get_if<uint32_t>(&_value)) {
4✔
2115
        memcpy(bytes.data(), &std::get<uint32_t>(_value), sizeof(uint32_t));
×
2116
    } else if (std::get_if<int32_t>(&_value)) {
4✔
2117
        memcpy(bytes.data(), &std::get<int32_t>(_value), sizeof(int32_t));
×
2118
    } else if (std::get_if<uint64_t>(&_value)) {
4✔
2119
        memcpy(bytes.data(), &std::get<uint64_t>(_value), sizeof(uint64_t));
×
2120
    } else if (std::get_if<int64_t>(&_value)) {
4✔
2121
        memcpy(bytes.data(), &std::get<int64_t>(_value), sizeof(int64_t));
×
2122
    } else if (std::get_if<float>(&_value)) {
4✔
2123
        memcpy(bytes.data(), &std::get<float>(_value), sizeof(float));
×
2124
    } else if (std::get_if<double>(&_value)) {
4✔
2125
        memcpy(bytes.data(), &std::get<double>(_value), sizeof(double));
×
2126
    } else if (std::get_if<std::string>(&_value)) {
4✔
2127
        auto str_ptr = &std::get<std::string>(_value);
4✔
2128
        // Copy all data in string, max 128 bytes
2129
        memcpy(bytes.data(), str_ptr->data(), std::min(bytes.size(), str_ptr->size()));
4✔
2130
    } else {
2131
        LogErr() << "Unknown type";
×
2132
        assert(false);
×
2133
    }
2134

2135
    return bytes;
4✔
2136
}
2137

2138
[[nodiscard]] std::string MAVLinkParameters::ParamValue::get_string() const
82✔
2139
{
2140
    return std::visit([](auto value) { return to_string(value); }, _value);
82✔
2141
}
2142

2143
[[nodiscard]] bool MAVLinkParameters::ParamValue::is_same_type(const ParamValue& rhs) const
2,333✔
2144
{
2145
    if ((std::get_if<uint8_t>(&_value) && std::get_if<uint8_t>(&rhs._value)) ||
4,666✔
2146
        (std::get_if<int8_t>(&_value) && std::get_if<int8_t>(&rhs._value)) ||
4,540✔
2147
        (std::get_if<uint16_t>(&_value) && std::get_if<uint16_t>(&rhs._value)) ||
4,540✔
2148
        (std::get_if<int16_t>(&_value) && std::get_if<int16_t>(&rhs._value)) ||
4,496✔
2149
        (std::get_if<uint32_t>(&_value) && std::get_if<uint32_t>(&rhs._value)) ||
4,496✔
2150
        (std::get_if<int32_t>(&_value) && std::get_if<int32_t>(&rhs._value)) ||
1,162✔
2151
        (std::get_if<uint64_t>(&_value) && std::get_if<uint64_t>(&rhs._value)) ||
1,020✔
2152
        (std::get_if<int64_t>(&_value) && std::get_if<int64_t>(&rhs._value)) ||
1,020✔
2153
        (std::get_if<float>(&_value) && std::get_if<float>(&rhs._value)) ||
1,020✔
2154
        (std::get_if<double>(&_value) && std::get_if<double>(&rhs._value)) ||
4,670✔
2155
        (std::get_if<std::string>(&_value) && std::get_if<std::string>(&rhs._value))) {
4✔
2156
        return true;
2,333✔
2157
    } else {
2158
        LogWarn() << "Comparison type mismatch between " << typestr() << " and " << rhs.typestr();
×
2159
        return false;
×
2160
    }
2161
}
2162

2163
bool MAVLinkParameters::ParamValue::operator==(const std::string& value_str) const
1,332✔
2164
{
2165
    // LogDebug() << "Compare " << value_str() << " and " << rhs.value_str();
2166
    if (std::get_if<uint8_t>(&_value)) {
1,332✔
2167
        return std::get<uint8_t>(_value) == std::stoi(value_str);
50✔
2168
    } else if (std::get_if<int8_t>(&_value)) {
1,282✔
2169
        return std::get<int8_t>(_value) == std::stoi(value_str);
×
2170
    } else if (std::get_if<uint16_t>(&_value)) {
1,282✔
2171
        return std::get<uint16_t>(_value) == std::stoi(value_str);
×
2172
    } else if (std::get_if<int16_t>(&_value)) {
1,282✔
2173
        return std::get<int16_t>(_value) == std::stoi(value_str);
×
2174
    } else if (std::get_if<uint32_t>(&_value)) {
1,282✔
2175
        return std::get<uint32_t>(_value) == std::stoul(value_str);
781✔
2176
    } else if (std::get_if<int32_t>(&_value)) {
501✔
2177
        return std::get<int32_t>(_value) == std::stol(value_str);
72✔
2178
    } else if (std::get_if<uint64_t>(&_value)) {
429✔
2179
        return std::get<uint64_t>(_value) == std::stoull(value_str);
×
2180
    } else if (std::get_if<int64_t>(&_value)) {
429✔
2181
        return std::get<int64_t>(_value) == std::stoll(value_str);
×
2182
    } else if (std::get_if<float>(&_value)) {
429✔
2183
        return std::get<float>(_value) == std::stof(value_str);
429✔
2184
    } else if (std::get_if<double>(&_value)) {
×
2185
        return std::get<double>(_value) == std::stod(value_str);
×
2186
    } else {
2187
        // This also covers custom_type_t
2188
        return false;
×
2189
    }
2190
}
2191

2192
[[nodiscard]] std::string MAVLinkParameters::ParamValue::typestr() const
×
2193
{
2194
    if (std::get_if<uint8_t>(&_value)) {
×
2195
        return "uint8_t";
×
2196
    } else if (std::get_if<int8_t>(&_value)) {
×
2197
        return "int8_t";
×
2198
    } else if (std::get_if<uint16_t>(&_value)) {
×
2199
        return "uint16_t";
×
2200
    } else if (std::get_if<int16_t>(&_value)) {
×
2201
        return "int16_t";
×
2202
    } else if (std::get_if<uint32_t>(&_value)) {
×
2203
        return "uint32_t";
×
2204
    } else if (std::get_if<int32_t>(&_value)) {
×
2205
        return "int32_t";
×
2206
    } else if (std::get_if<uint64_t>(&_value)) {
×
2207
        return "uint64_t";
×
2208
    } else if (std::get_if<int64_t>(&_value)) {
×
2209
        return "int64_t";
×
2210
    } else if (std::get_if<float>(&_value)) {
×
2211
        return "float";
×
2212
    } else if (std::get_if<double>(&_value)) {
×
2213
        return "double";
×
2214
    } else if (std::get_if<std::string>(&_value)) {
×
2215
        return "custom";
×
2216
    }
2217
    // FIXME: Added to fix CI error (control reading end of non-void function)
2218
    return "unknown";
×
2219
}
2220

2221
std::ostream& operator<<(std::ostream& str, const MAVLinkParameters::Result& result)
×
2222
{
2223
    switch (result) {
×
2224
        case MAVLinkParameters::Result::Success:
×
2225
            return str << "Success";
×
2226
        case MAVLinkParameters::Result::Timeout:
×
2227
            return str << "Timeout";
×
2228
        case MAVLinkParameters::Result::ConnectionError:
×
2229
            return str << "ConnectionError";
×
2230
        case MAVLinkParameters::Result::WrongType:
×
2231
            return str << "WrongType";
×
2232
        case MAVLinkParameters::Result::ParamNameTooLong:
×
2233
            return str << "ParamNameTooLong";
×
2234
        case MAVLinkParameters::Result::NotFound:
×
2235
            return str << "NotFound";
×
2236
        case MAVLinkParameters::Result::ValueUnsupported:
×
2237
            return str << "ValueUnsupported";
×
2238
        case MAVLinkParameters::Result::Failed:
×
2239
            return str << "Failed";
×
2240
        case MAVLinkParameters::Result::UnknownError:
×
2241
            // Fallthrough
2242
        default:
2243
            return str << "UnknownError";
×
2244
    }
2245
}
2246

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