Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 58 additions & 2 deletions cpp/src/mavsdk/plugins/shell/include/plugins/shell/shell.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ class System;class ShellImpl;

/**
* @brief Allow to communicate with the vehicle's system shell.
*
* Under the hood this uses MAVLink SERIAL_CONTROL. The default device is
* SERIAL_CONTROL_DEV_SHELL; set_device can target other SERIAL_CONTROL_DEV
* ports (for example TELEM2) when the same framing is used for non-nsh
* serial bridges.
*/
class MAVSDK_PUBLIC Shell : public PluginBase {
public:
Expand Down Expand Up @@ -66,6 +71,43 @@ class MAVSDK_PUBLIC Shell : public PluginBase {



/**
* @brief MAVLink SERIAL_CONTROL_DEV values used by the shell plugin.
*/
enum class Device {
Telem1, /**< @brief SERIAL_CONTROL_DEV_TELEM1. */
Telem2, /**< @brief SERIAL_CONTROL_DEV_TELEM2. */
Gps1, /**< @brief SERIAL_CONTROL_DEV_GPS1. */
Gps2, /**< @brief SERIAL_CONTROL_DEV_GPS2. */
Shell, /**< @brief SERIAL_CONTROL_DEV_SHELL (default). */
Serial0, /**< @brief SERIAL_CONTROL_SERIAL0. */
Serial1, /**< @brief SERIAL_CONTROL_SERIAL1. */
Serial2, /**< @brief SERIAL_CONTROL_SERIAL2. */
Serial3, /**< @brief SERIAL_CONTROL_SERIAL3. */
Serial4, /**< @brief SERIAL_CONTROL_SERIAL4. */
Serial5, /**< @brief SERIAL_CONTROL_SERIAL5. */
Serial6, /**< @brief SERIAL_CONTROL_SERIAL6. */
Serial7, /**< @brief SERIAL_CONTROL_SERIAL7. */
Serial8, /**< @brief SERIAL_CONTROL_SERIAL8. */
Serial9, /**< @brief SERIAL_CONTROL_SERIAL9. */
};

/**
* @brief Convert `Shell::Device` to string.
*
* @return A string representation of the enum.
*/
friend MAVSDK_PUBLIC std::string_view to_string(Shell::Device const& device);

/**
* @brief Stream operator to print information about a `Shell::Device`.
*
* @return A reference to the stream.
*/
friend MAVSDK_PUBLIC std::ostream& operator<<(std::ostream& str, Shell::Device const& device);




/**
* @brief Possible results returned for shell requests
Expand All @@ -77,6 +119,7 @@ class MAVSDK_PUBLIC Shell : public PluginBase {
ConnectionError, /**< @brief Connection error. */
NoResponse, /**< @brief Response was not received. */
Busy, /**< @brief Shell busy (transfer in progress). */
InvalidArgument, /**< @brief Invalid device / argument. */
};

/**
Expand Down Expand Up @@ -145,7 +188,20 @@ class MAVSDK_PUBLIC Shell : public PluginBase {




/**
* @brief Select the SERIAL_CONTROL device used for send/receive.
*
* Default is DEVICE_SHELL. Other values map to MAVLink SERIAL_CONTROL_DEV
* (TELEM1/2, GPS1/2, SERIALn). Incoming SERIAL_CONTROL messages for other
* devices are ignored while a device is selected.
*
* This function is blocking.
*

* @return Result of request.

*/
Result set_device(Device device) const;



Expand All @@ -165,4 +221,4 @@ class MAVSDK_PUBLIC Shell : public PluginBase {
std::unique_ptr<ShellImpl> _impl;
};

} // namespace mavsdk
} // namespace mavsdk
52 changes: 51 additions & 1 deletion cpp/src/mavsdk/plugins/shell/shell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,54 @@ void Shell::unsubscribe_receive(ReceiveHandle handle)
_impl->unsubscribe_receive(handle);
}

Shell::Result Shell::set_device(Device device) const
{
return _impl->set_device(device);
}

MAVSDK_PUBLIC std::string_view to_string(Shell::Device const& device)
{
switch (device) {
case Shell::Device::Telem1:
return "Telem1";
case Shell::Device::Telem2:
return "Telem2";
case Shell::Device::Gps1:
return "Gps1";
case Shell::Device::Gps2:
return "Gps2";
case Shell::Device::Shell:
return "Shell";
case Shell::Device::Serial0:
return "Serial0";
case Shell::Device::Serial1:
return "Serial1";
case Shell::Device::Serial2:
return "Serial2";
case Shell::Device::Serial3:
return "Serial3";
case Shell::Device::Serial4:
return "Serial4";
case Shell::Device::Serial5:
return "Serial5";
case Shell::Device::Serial6:
return "Serial6";
case Shell::Device::Serial7:
return "Serial7";
case Shell::Device::Serial8:
return "Serial8";
case Shell::Device::Serial9:
return "Serial9";
default:
return "Unknown";
}
}

MAVSDK_PUBLIC std::ostream& operator<<(std::ostream& str, Shell::Device const& device)
{
return str << to_string(device);
}

MAVSDK_PUBLIC std::string_view to_string(Shell::Result const& result)
{
switch (result) {
Expand All @@ -48,6 +96,8 @@ MAVSDK_PUBLIC std::string_view to_string(Shell::Result const& result)
return "No Response";
case Shell::Result::Busy:
return "Busy";
case Shell::Result::InvalidArgument:
return "Invalid Argument";
default:
return "Unknown";
}
Expand All @@ -58,4 +108,4 @@ MAVSDK_PUBLIC std::ostream& operator<<(std::ostream& str, Shell::Result const& r
return str << to_string(result);
}

} // namespace mavsdk
} // namespace mavsdk
82 changes: 80 additions & 2 deletions cpp/src/mavsdk/plugins/shell/shell_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,72 @@ Shell::Result ShellImpl::send(std::string command)
return Shell::Result::Success;
}

Shell::Result ShellImpl::set_device(Shell::Device device)
{
uint8_t mav_device = 0;
if (!device_to_mavlink(device, mav_device)) {
return Shell::Result::InvalidArgument;
}

std::lock_guard<std::mutex> lock(_device_mutex);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given this is lock is only around ever around _device you can just use std::atomic.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — replaced the mutex with std::atomic<uint8_t> _device and relaxed loads/stores. Pushed in 962ca8a.

_device = mav_device;
return Shell::Result::Success;
}

bool ShellImpl::device_to_mavlink(Shell::Device device, uint8_t& out_device)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally, we don't do out parameters. You can return a pair or an optional if you need result and value.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks — switched device_to_mavlink to return std::optional<uint8_t> (no out-param). Pushed in 962ca8a.

{
// Numeric values match MAVLink SERIAL_CONTROL_DEV (common.xml).
switch (device) {
case Shell::Device::Telem1:
out_device = 0;
return true;
case Shell::Device::Telem2:
out_device = 1;
return true;
case Shell::Device::Gps1:
out_device = 2;
return true;
case Shell::Device::Gps2:
out_device = 3;
return true;
case Shell::Device::Shell:
out_device = 10;
return true;
case Shell::Device::Serial0:
out_device = 100;
return true;
case Shell::Device::Serial1:
out_device = 101;
return true;
case Shell::Device::Serial2:
out_device = 102;
return true;
case Shell::Device::Serial3:
out_device = 103;
return true;
case Shell::Device::Serial4:
out_device = 104;
return true;
case Shell::Device::Serial5:
out_device = 105;
return true;
case Shell::Device::Serial6:
out_device = 106;
return true;
case Shell::Device::Serial7:
out_device = 107;
return true;
case Shell::Device::Serial8:
out_device = 108;
return true;
case Shell::Device::Serial9:
out_device = 109;
return true;
default:
return false;
}
}

Shell::ReceiveHandle ShellImpl::subscribe_receive(const Shell::ReceiveCallback& callback)
{
return _receive.callbacks.subscribe(callback);
Expand All @@ -73,6 +139,11 @@ void ShellImpl::unsubscribe_receive(Shell::ReceiveHandle handle)
bool ShellImpl::send_command_message(std::string command)
{
mavlink_message_t message;
uint8_t device;
{
std::lock_guard<std::mutex> lock(_device_mutex);
device = _device;
}

while (command.length() > MAVLINK_MSG_SERIAL_CONTROL_FIELD_DATA_LEN) {
if (!_system_impl->queue_message([&](MavlinkAddress mavlink_address, uint8_t channel) {
Expand All @@ -81,7 +152,7 @@ bool ShellImpl::send_command_message(std::string command)
mavlink_address.component_id,
channel,
&message,
static_cast<uint8_t>(SERIAL_CONTROL_DEV::SERIAL_CONTROL_DEV_SHELL),
device,
0,
timeout_ms,
0,
Expand Down Expand Up @@ -113,7 +184,7 @@ bool ShellImpl::send_command_message(std::string command)
mavlink_address.component_id,
channel,
&message,
static_cast<uint8_t>(SERIAL_CONTROL_DEV::SERIAL_CONTROL_DEV_SHELL),
device,
flags,
timeout_ms,
0,
Expand All @@ -130,6 +201,13 @@ void ShellImpl::process_shell_message(const mavlink_message_t& message)
mavlink_serial_control_t serial_control;
mavlink_msg_serial_control_decode(&message, &serial_control);

{
std::lock_guard<std::mutex> lock(_device_mutex);
if (serial_control.device != _device) {
return;
}
}

// This adds an additional byte for the null termination.
char str_copy[sizeof(serial_control.data) + 1]{0};

Expand Down
5 changes: 5 additions & 0 deletions cpp/src/mavsdk/plugins/shell/shell_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class ShellImpl : public PluginImplBase {
void disable() override;

Shell::Result send(std::string command);
Shell::Result set_device(Shell::Device device);
Shell::ReceiveHandle subscribe_receive(const Shell::ReceiveCallback& callback);
void unsubscribe_receive(Shell::ReceiveHandle handle);

Expand All @@ -34,12 +35,16 @@ class ShellImpl : public PluginImplBase {
private:
bool send_command_message(std::string command);
void process_shell_message(const mavlink_message_t& message);
static bool device_to_mavlink(Shell::Device device, uint8_t& out_device);

static constexpr uint16_t timeout_ms = 1000;

struct Receive {
explicit Receive(asio::io_context& io_context) : callbacks(io_context) {}
CallbackList<std::string> callbacks;
} _receive;

std::mutex _device_mutex{};
uint8_t _device{10}; // SERIAL_CONTROL_DEV_SHELL

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should have the mavlink enum define available.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now using SERIAL_CONTROL_DEV::* (and SERIAL_CONTROL_SERIAL*) via the mavlink headers instead of magic numbers. Pushed in 962ca8a.

};
} // namespace mavsdk
Loading