Skip to content

Commit 2a47889

Browse files
authored
Merge pull request #2682 from mavlink/pr-raw-bytes
core: add raw connection
2 parents 5379eed + 6d3a34a commit 2a47889

File tree

13 files changed

+524
-2
lines changed

13 files changed

+524
-2
lines changed

docs/en/cpp/api_reference/classmavsdk_1_1_mavsdk.md

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ std::function< void()> [NewSystemCallback](#classmavsdk_1_1_mavsdk_1a7a283c6a75e
3434
[Handle](classmavsdk_1_1_handle.md)<> [NewSystemHandle](#classmavsdk_1_1_mavsdk_1ae0727f2bed9cbf276d161ada0a432b8c) | [Handle](classmavsdk_1_1_handle.md) type to unsubscribe from subscribe_on_new_system.
3535
[Handle](classmavsdk_1_1_handle.md)< bool([MavlinkMessage](structmavsdk_1_1_mavsdk_1_1_mavlink_message.md))> [InterceptJsonHandle](#classmavsdk_1_1_mavsdk_1a3b40ae4fd8af4c4419b61f0ad955812f) | [Handle](classmavsdk_1_1_handle.md) for intercepting messages.
3636
std::function< bool([MavlinkMessage](structmavsdk_1_1_mavsdk_1_1_mavlink_message.md))> [InterceptJsonCallback](#classmavsdk_1_1_mavsdk_1a17923db3b1504e911487729114b68f48) | Callback type for intercepting messages.
37+
std::function< void(const char *bytes, size_t length)> [RawBytesCallback](#classmavsdk_1_1_mavsdk_1acb5be9a1be97d251387ffe87ae8b9eb0) | Callback type for raw bytes subscriptions.
38+
[Handle](classmavsdk_1_1_handle.md)< const char *, size_t > [RawBytesHandle](#classmavsdk_1_1_mavsdk_1ac766258f137aa3e8b0dabb5a66435ea1) | [Handle](classmavsdk_1_1_handle.md) type for raw bytes subscriptions.
3739

3840
## Public Member Functions
3941

@@ -64,6 +66,9 @@ void | [unsubscribe_incoming_messages_json](#classmavsdk_1_1_mavsdk_1a4be244c389
6466
void | [unsubscribe_outgoing_messages_json](#classmavsdk_1_1_mavsdk_1aa3a490358db87cfed617cdad902bb753) ([InterceptJsonHandle](classmavsdk_1_1_mavsdk.md#classmavsdk_1_1_mavsdk_1a3b40ae4fd8af4c4419b61f0ad955812f) handle) | Unsubscribe from outgoing messages as JSON.
6567
void | [intercept_incoming_messages_async](#classmavsdk_1_1_mavsdk_1ac80c8909958533131cbdbc61d061794f) (std::function< bool(mavlink_message_t &)> callback) | Intercept incoming messages.
6668
void | [intercept_outgoing_messages_async](#classmavsdk_1_1_mavsdk_1a040ee5c1d41e71c0d63cf8f76d2db275) (std::function< bool(mavlink_message_t &)> callback) | Intercept outgoing messages.
69+
void | [pass_received_raw_bytes](#classmavsdk_1_1_mavsdk_1a65329315ac07bae110839d9e054fbc05) (const char * bytes, size_t length) | Pass received raw MAVLink bytes.
70+
[RawBytesHandle](classmavsdk_1_1_mavsdk.md#classmavsdk_1_1_mavsdk_1ac766258f137aa3e8b0dabb5a66435ea1) | [subscribe_raw_bytes_to_be_sent](#classmavsdk_1_1_mavsdk_1a116e9bab0efdf7ec90866107ef517b20) ([RawBytesCallback](classmavsdk_1_1_mavsdk.md#classmavsdk_1_1_mavsdk_1acb5be9a1be97d251387ffe87ae8b9eb0) callback) | Subscribe to raw bytes to be sent.
71+
void | [unsubscribe_raw_bytes_to_be_sent](#classmavsdk_1_1_mavsdk_1af6ec813a9728f4258056fa1f5d399eb1) ([RawBytesHandle](classmavsdk_1_1_mavsdk.md#classmavsdk_1_1_mavsdk_1ac766258f137aa3e8b0dabb5a66435ea1) handle) | Unsubscribe from raw bytes to be sent.
6772

6873

6974
## Constructor & Destructor Documentation
@@ -176,6 +181,26 @@ using mavsdk::Mavsdk::InterceptJsonCallback = std::function<bool(MavlinkMessage
176181
Callback type for intercepting messages.
177182

178183

184+
### typedef RawBytesCallback {#classmavsdk_1_1_mavsdk_1acb5be9a1be97d251387ffe87ae8b9eb0}
185+
186+
```cpp
187+
using mavsdk::Mavsdk::RawBytesCallback = std::function<void(const char* bytes, size_t length)>
188+
```
189+
190+
191+
Callback type for raw bytes subscriptions.
192+
193+
194+
### typedef RawBytesHandle {#classmavsdk_1_1_mavsdk_1ac766258f137aa3e8b0dabb5a66435ea1}
195+
196+
```cpp
197+
using mavsdk::Mavsdk::RawBytesHandle = Handle<const char*, size_t>
198+
```
199+
200+
201+
[Handle](classmavsdk_1_1_handle.md) type for raw bytes subscriptions.
202+
203+
179204
## Member Function Documentation
180205

181206

@@ -584,4 +609,64 @@ This functionality is provided primarily for testing in order to simulate packet
584609

585610
**Parameters**
586611

587-
* std::function< bool(mavlink_message_t &)> **callback** - Callback to be called for each outgoing message. To drop a message, return 'false' from the callback.
612+
* std::function< bool(mavlink_message_t &)> **callback** - Callback to be called for each outgoing message. To drop a message, return 'false' from the callback.
613+
614+
### pass_received_raw_bytes() {#classmavsdk_1_1_mavsdk_1a65329315ac07bae110839d9e054fbc05}
615+
```cpp
616+
void mavsdk::Mavsdk::pass_received_raw_bytes(const char *bytes, size_t length)
617+
```
618+
619+
620+
Pass received raw MAVLink bytes.
621+
622+
This allows passing raw MAVLink message bytes into MAVSDK to be processed. The bytes can contain one or more MAVLink messages.
623+
624+
625+
::: info
626+
Before using this, run add_any_connection("raw://")
627+
:::
628+
629+
This goes together with subscribe_raw_bytes_to_be_sent.
630+
631+
**Parameters**
632+
633+
* const char\* **bytes** - Pointer to raw MAVLink message bytes.
634+
* size_t **length** - Number of bytes to send.
635+
636+
### subscribe_raw_bytes_to_be_sent() {#classmavsdk_1_1_mavsdk_1a116e9bab0efdf7ec90866107ef517b20}
637+
```cpp
638+
RawBytesHandle mavsdk::Mavsdk::subscribe_raw_bytes_to_be_sent(RawBytesCallback callback)
639+
```
640+
641+
642+
Subscribe to raw bytes to be sent.
643+
644+
This allows getting MAVLink bytes that need to be sent out.
645+
646+
647+
::: info
648+
Before using this, run add_any_connection("raw://")
649+
:::
650+
651+
This goes together with pass_received_raw_bytes. The bytes contain one mavlink message at a time.
652+
653+
**Parameters**
654+
655+
* [RawBytesCallback](classmavsdk_1_1_mavsdk.md#classmavsdk_1_1_mavsdk_1acb5be9a1be97d251387ffe87ae8b9eb0) **callback** - Callback to be called with outgoing raw bytes.
656+
657+
**Returns**
658+
659+
&emsp;[RawBytesHandle](classmavsdk_1_1_mavsdk.md#classmavsdk_1_1_mavsdk_1ac766258f137aa3e8b0dabb5a66435ea1) - [Handle](classmavsdk_1_1_handle.md) to unsubscribe again.
660+
661+
### unsubscribe_raw_bytes_to_be_sent() {#classmavsdk_1_1_mavsdk_1af6ec813a9728f4258056fa1f5d399eb1}
662+
```cpp
663+
void mavsdk::Mavsdk::unsubscribe_raw_bytes_to_be_sent(RawBytesHandle handle)
664+
```
665+
666+
667+
Unsubscribe from raw bytes to be sent.
668+
669+
670+
**Parameters**
671+
672+
* [RawBytesHandle](classmavsdk_1_1_mavsdk.md#classmavsdk_1_1_mavsdk_1ac766258f137aa3e8b0dabb5a66435ea1) **handle** - [Handle](classmavsdk_1_1_handle.md) from subscribe_raw_bytes_to_be_sent.

src/mavsdk/core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ target_sources(mavsdk
8181
param_value.cpp
8282
ping.cpp
8383
plugin_impl_base.cpp
84+
raw_connection.cpp
8485
serial_connection.cpp
8586
server_component.cpp
8687
server_component_impl.cpp

src/mavsdk/core/cli_arg.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ bool CliArg::parse(const std::string& uri)
5959
std::string_view(uri).substr(serial_flowcontrol.size() + delimiter.size()), true);
6060
}
6161

62+
const std::string raw = "raw";
63+
if (uri.find(raw + delimiter) == 0) {
64+
return parse_raw(std::string_view(uri).substr(raw.size() + delimiter.size()));
65+
}
66+
6267
LogErr() << "Unknown protocol";
6368
return false;
6469
}
@@ -293,4 +298,16 @@ bool CliArg::parse_serial(const std::string_view rest, bool flow_control_enabled
293298
return true;
294299
}
295300

301+
bool CliArg::parse_raw(const std::string_view rest)
302+
{
303+
// raw:// connection has no parameters
304+
if (!rest.empty()) {
305+
LogErr() << "raw:// connection should not have parameters";
306+
return false;
307+
}
308+
309+
protocol = Raw{};
310+
return true;
311+
}
312+
296313
} // namespace mavsdk

src/mavsdk/core/cli_arg.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ class CliArg {
3737
bool flow_control_enabled{false};
3838
};
3939

40-
using Protocol = std::variant<std::monostate, Udp, Tcp, Serial>;
40+
struct Raw {
41+
// No parameters needed for raw connection
42+
};
43+
44+
using Protocol = std::variant<std::monostate, Udp, Tcp, Serial, Raw>;
4145

4246
bool parse(const std::string& uri);
4347

@@ -55,6 +59,7 @@ class CliArg {
5559
bool parse_tcpout(const std::string_view rest);
5660

5761
bool parse_serial(const std::string_view rest, bool flow_control_enabled);
62+
bool parse_raw(const std::string_view rest);
5863
};
5964

6065
} // namespace mavsdk

src/mavsdk/core/cli_arg_test.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,3 +381,22 @@ TEST(CliArg, SerialWrong)
381381
EXPECT_FALSE(ca.parse("serial://COM3:-1"));
382382
EXPECT_FALSE(ca.parse("serial://COM3"));
383383
}
384+
385+
TEST(CliArg, RawConnection)
386+
{
387+
CliArg ca;
388+
389+
EXPECT_TRUE(ca.parse("raw://"));
390+
auto raw = std::get_if<CliArg::Raw>(&ca.protocol);
391+
ASSERT_TRUE(raw);
392+
}
393+
394+
TEST(CliArg, RawConnectionWrong)
395+
{
396+
CliArg ca;
397+
398+
// raw:// should not have any parameters
399+
EXPECT_FALSE(ca.parse("raw://something"));
400+
EXPECT_FALSE(ca.parse("raw://localhost"));
401+
EXPECT_FALSE(ca.parse("raw://127.0.0.1"));
402+
}

src/mavsdk/core/include/mavsdk/mavsdk.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,53 @@ class Mavsdk {
463463
*/
464464
void intercept_outgoing_messages_async(std::function<bool(mavlink_message_t&)> callback);
465465

466+
/**
467+
* @brief Callback type for raw bytes subscriptions.
468+
*/
469+
using RawBytesCallback = std::function<void(const char* bytes, size_t length)>;
470+
471+
/**
472+
* @brief Handle type for raw bytes subscriptions.
473+
*/
474+
using RawBytesHandle = Handle<const char*, size_t>;
475+
476+
/**
477+
* @brief Pass received raw MAVLink bytes.
478+
*
479+
* This allows passing raw MAVLink message bytes into MAVSDK to be processed.
480+
* The bytes can contain one or more MAVLink messages.
481+
*
482+
* @note Before using this, run add_any_connection("raw://")
483+
*
484+
* This goes together with subscribe_raw_bytes_to_be_sent.
485+
*
486+
* @param bytes Pointer to raw MAVLink message bytes.
487+
* @param length Number of bytes to send.
488+
*/
489+
void pass_received_raw_bytes(const char* bytes, size_t length);
490+
491+
/**
492+
* @brief Subscribe to raw bytes to be sent.
493+
*
494+
* This allows getting MAVLink bytes that need to be sent out.
495+
*
496+
* @note Before using this, run add_any_connection("raw://")
497+
*
498+
* This goes together with pass_received_raw_bytes.
499+
* The bytes contain one mavlink message at a time.
500+
*
501+
* @param callback Callback to be called with outgoing raw bytes.
502+
* @return Handle to unsubscribe again.
503+
*/
504+
RawBytesHandle subscribe_raw_bytes_to_be_sent(RawBytesCallback callback);
505+
506+
/**
507+
* @brief Unsubscribe from raw bytes to be sent.
508+
*
509+
* @param handle Handle from subscribe_raw_bytes_to_be_sent.
510+
*/
511+
void unsubscribe_raw_bytes_to_be_sent(RawBytesHandle handle);
512+
466513
private:
467514
static constexpr int DEFAULT_SYSTEM_ID_AUTOPILOT = 1;
468515
static constexpr int DEFAULT_COMPONENT_ID_AUTOPILOT = MAV_COMP_ID_AUTOPILOT1;

src/mavsdk/core/mavsdk.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,21 @@ void Mavsdk::intercept_outgoing_messages_async(std::function<bool(mavlink_messag
234234
_impl->intercept_outgoing_messages_async(callback);
235235
}
236236

237+
void Mavsdk::pass_received_raw_bytes(const char* bytes, size_t length)
238+
{
239+
_impl->pass_received_raw_bytes(bytes, length);
240+
}
241+
242+
Mavsdk::RawBytesHandle Mavsdk::subscribe_raw_bytes_to_be_sent(RawBytesCallback callback)
243+
{
244+
return _impl->subscribe_raw_bytes_to_be_sent(callback);
245+
}
246+
247+
void Mavsdk::unsubscribe_raw_bytes_to_be_sent(RawBytesHandle handle)
248+
{
249+
_impl->unsubscribe_raw_bytes_to_be_sent(handle);
250+
}
251+
237252
Mavsdk::ConnectionErrorHandle
238253
Mavsdk::subscribe_connection_errors(Mavsdk::ConnectionErrorCallback callback)
239254
{

src/mavsdk/core/mavsdk_impl.cpp

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "tcp_client_connection.h"
1010
#include "tcp_server_connection.h"
1111
#include "udp_connection.h"
12+
#include "raw_connection.h"
1213
#include "system.h"
1314
#include "system_impl.h"
1415
#include "serial_connection.h"
@@ -790,6 +791,9 @@ std::pair<ConnectionResult, Mavsdk::ConnectionHandle> MavsdkImpl::add_any_connec
790791
[this, forwarding_option](const CliArg::Serial& serial) {
791792
return add_serial_connection(
792793
serial.path, serial.baudrate, serial.flow_control_enabled, forwarding_option);
794+
},
795+
[this, forwarding_option](const CliArg::Raw&) {
796+
return add_raw_connection(forwarding_option);
793797
}},
794798
cli_arg.protocol);
795799
}
@@ -930,6 +934,44 @@ std::pair<ConnectionResult, Mavsdk::ConnectionHandle> MavsdkImpl::add_serial_con
930934
}
931935
}
932936

937+
std::pair<ConnectionResult, Mavsdk::ConnectionHandle>
938+
MavsdkImpl::add_raw_connection(ForwardingOption forwarding_option)
939+
{
940+
// Check if a raw connection already exists
941+
if (find_raw_connection() != nullptr) {
942+
LogErr() << "Raw connection already exists. Only one raw connection is allowed.";
943+
return {ConnectionResult::ConnectionError, Mavsdk::ConnectionHandle{}};
944+
}
945+
946+
auto new_conn = std::make_unique<RawConnection>(
947+
[this](mavlink_message_t& message, Connection* connection) {
948+
receive_message(message, connection);
949+
},
950+
[this](const Mavsdk::MavlinkMessage& message, Connection* connection) {
951+
receive_libmav_message(message, connection);
952+
},
953+
*this,
954+
forwarding_option);
955+
956+
if (!new_conn) {
957+
return {ConnectionResult::ConnectionError, Mavsdk::ConnectionHandle{}};
958+
}
959+
960+
ConnectionResult ret = new_conn->start();
961+
if (ret != ConnectionResult::Success) {
962+
return {ret, Mavsdk::ConnectionHandle{}};
963+
}
964+
965+
auto handle = add_connection(std::move(new_conn));
966+
967+
// Enable heartbeats for raw connection
968+
auto new_configuration = get_configuration();
969+
new_configuration.set_always_send_heartbeats(true);
970+
set_configuration(new_configuration);
971+
972+
return {ConnectionResult::Success, handle};
973+
}
974+
933975
Mavsdk::ConnectionHandle MavsdkImpl::add_connection(std::unique_ptr<Connection>&& new_connection)
934976
{
935977
std::lock_guard lock(_mutex);
@@ -1318,6 +1360,57 @@ void MavsdkImpl::unsubscribe_outgoing_messages_json(Mavsdk::InterceptJsonHandle
13181360
}
13191361
}
13201362

1363+
RawConnection* MavsdkImpl::find_raw_connection()
1364+
{
1365+
std::lock_guard lock(_mutex);
1366+
1367+
for (auto& entry : _connections) {
1368+
auto* raw_conn = dynamic_cast<RawConnection*>(entry.connection.get());
1369+
if (raw_conn != nullptr) {
1370+
return raw_conn;
1371+
}
1372+
}
1373+
return nullptr;
1374+
}
1375+
1376+
void MavsdkImpl::pass_received_raw_bytes(const char* bytes, size_t length)
1377+
{
1378+
auto* raw_conn = find_raw_connection();
1379+
if (raw_conn == nullptr) {
1380+
LogErr()
1381+
<< "No raw connection available. Please add one using add_any_connection(\"raw://\")";
1382+
return;
1383+
}
1384+
1385+
raw_conn->receive(bytes, length);
1386+
}
1387+
1388+
Mavsdk::RawBytesHandle
1389+
MavsdkImpl::subscribe_raw_bytes_to_be_sent(const Mavsdk::RawBytesCallback& callback)
1390+
{
1391+
if (find_raw_connection() == nullptr) {
1392+
LogWarn() << "No raw connection available. Subscription will only receive bytes after you "
1393+
"add a connection using add_any_connection(\"raw://\")";
1394+
}
1395+
return _raw_bytes_subscriptions.subscribe(callback);
1396+
}
1397+
1398+
void MavsdkImpl::unsubscribe_raw_bytes_to_be_sent(Mavsdk::RawBytesHandle handle)
1399+
{
1400+
_raw_bytes_subscriptions.unsubscribe(handle);
1401+
}
1402+
1403+
bool MavsdkImpl::notify_raw_bytes_sent(const char* bytes, size_t length)
1404+
{
1405+
if (_raw_bytes_subscriptions.empty()) {
1406+
return false;
1407+
}
1408+
1409+
_raw_bytes_subscriptions(bytes, length);
1410+
1411+
return true;
1412+
}
1413+
13211414
Mavsdk::ConnectionErrorHandle
13221415
MavsdkImpl::subscribe_connection_errors(Mavsdk::ConnectionErrorCallback callback)
13231416
{

0 commit comments

Comments
 (0)