Skip to content

Commit

Permalink
add dds config tool
Browse files Browse the repository at this point in the history
  • Loading branch information
Noy-Zini committed Dec 25, 2024
1 parent e18af41 commit 7e2db73
Show file tree
Hide file tree
Showing 13 changed files with 412 additions and 2 deletions.
2 changes: 2 additions & 0 deletions common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ set(COMMON_SRC
"${CMAKE_CURRENT_LIST_DIR}/stream-model.cpp"
"${CMAKE_CURRENT_LIST_DIR}/post-processing-filters.h"
"${CMAKE_CURRENT_LIST_DIR}/post-processing-filters.cpp"
"${CMAKE_CURRENT_LIST_DIR}/dds-model.h"
"${CMAKE_CURRENT_LIST_DIR}/dds-model.cpp"
)

set(SW_UPDATE_FILES
Expand Down
319 changes: 319 additions & 0 deletions common/dds-model.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,319 @@
#include "dds-model.h"
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2024 Intel Corporation. All Rights Reserved.

#include "device-model.h"
#include "ux-window.h"
#include <rsutils/json.h>
#include <rsutils/json-config.h>
#include <rsutils/os/special-folder.h>

#include <iostream>
#include <fstream>

using namespace rs2;
using rsutils::json;

dds_model::dds_model(rs2::device dev)
: _device(dev), _window_open(false)
{
if (supports_DDS()) {
_defult_config = get_eth_config(_device, DEFULT_VALUES);
_current_config = get_eth_config(_device, ACTUAL_VALUES);
_changed_config = _current_config;
}

}

eth_config dds_model::get_eth_config(rs2::debug_protocol dev, bool defult_val)
{
auto cmd = dev.build_command(GET_ETH_CONFIG, defult_val ? 0 : 1);
auto data = dev.send_and_receive_raw_data(cmd);
int32_t const& code = *reinterpret_cast<int32_t const*>(data.data());
data.erase(data.begin(), data.begin() + sizeof(code));
return eth_config(data);
}

void rs2::dds_model::set_eth_config(eth_config &new_config , std::string& error_message)
{
rs2::debug_protocol hwm(_device);
auto cmd = hwm.build_command(SET_ETH_CONFIG, 0, 0, 0, 0, new_config.build_command());
auto data = hwm.send_and_receive_raw_data(cmd);
int32_t const& code = *reinterpret_cast<int32_t const*>(data.data());
if (data.size() != sizeof(code)) {
error_message = rsutils::string::from()<< "Failed to change: bad response size " << data.size() << ' '<< rsutils::string::hexdump(data.data(), data.size());
close_window();
}
if (code != SET_ETH_CONFIG) {
error_message = rsutils::string::from() << "Failed to change: bad response " << code;
close_window();
}
if (!_no_reset)
{
close_window();
_device.hardware_reset();
}
}

void rs2::dds_model::enable_dds(std::string& error_message)
{
if (_device.get_type() == "DDS")
{
auto const filename
= rsutils::os::get_special_folder(rsutils::os::special_folder::app_data) + RS2_CONFIG_FILENAME;
auto config = rsutils::json_config::load_from_file(filename);

bool enabled;
if (!config.nested("context", "dds", "enabled").get_ex(enabled))
{
config["context"]["dds"]["enabled"] = true;
try
{
std::ofstream out(filename);
out << std::setw(2) << config;
out.close();
}
catch (std::exception const& e)
{
error_message = e.what();
close_window();
}
}
}
}

priority rs2::dds_model::classifyPriority(link_priority &pr)
{
if (pr == link_priority::usb_only || pr == link_priority::usb_first)
{
return priority::USB_FIRST;
}
else if (pr == link_priority::eth_first || pr == link_priority::eth_only)
{
return priority::ETH_FIRST;
}
return priority::DYNAMIC;
}

bool dds_model::supports_DDS()
{
auto dev = debug_protocol(_device);
auto cmd = dev.build_command(GET_ETH_CONFIG , ACTUAL_VALUES );
auto data = dev.send_and_receive_raw_data(cmd);
int32_t const& code = *reinterpret_cast<int32_t const*>(data.data());
if (code != GET_ETH_CONFIG)
return false;
return true;
}

void rs2::dds_model::ipInputText(std::string label ,rsutils::type::ip_address &ip)
{
char buffer[16];
std::string ip_str = ip.to_string();
std::snprintf(buffer, sizeof(buffer), "%s", ip_str.c_str());
std::string label_name = "##" + label;

if (ImGui::InputText(label_name.c_str(), buffer, sizeof(buffer))) {
std::string new_ip_str(buffer);
if (rsutils::type::ip_address(new_ip_str).is_valid()) {
ip = rsutils::type::ip_address(new_ip_str);
}
else {
std::snprintf(buffer, sizeof(buffer), "%s", ip.to_string().c_str());
}
}
}

void dds_model::render_dds_config_window(ux_window& window , std::string& error_message)
{
if (_window_open)
{
const auto window_name = "DDS Configuration";

// Calculate window position and size
const float w = 620;
const float h = 500;
const float x0 = std::max(window.width() - w, 0.f) / 2;
const float y0 = std::max(window.height() - h, 0.f) / 2;
ImGui::SetNextWindowPos({ x0, y0 });
ImGui::SetNextWindowSize({ w, h });

auto flags = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar |
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings;

ImGui::PushStyleColor(ImGuiCol_PopupBg, sensor_bg);
ImGui::PushStyleColor(ImGuiCol_TextSelectedBg, light_grey);
ImGui::PushStyleColor(ImGuiCol_Text, light_grey);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(5, 5));
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 1);
ImGui::PushStyleColor(ImGuiCol_Button, button_color);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, button_color + 0.1f);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, button_color + 0.1f);


ImGui::Begin(window_name, &_window_open, flags);

// Title
const char* title_message = window_name;
ImVec2 title_size = ImGui::CalcTextSize(title_message);
float title_x = (w - title_size.x-10) / 2.0f;
ImGui::SetCursorPos({ title_x, 10.0f });
ImGui::PushFont(window.get_large_font());
ImGui::PushStyleColor(ImGuiCol_Text, white);
ImGui::Text("%s", title_message);
ImGui::PopStyleColor();
ImGui::PopFont();
ImGui::Separator();
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 15);

// Version Display
ImGui::Text("Version: %s" , RS2_API_FULL_VERSION_STR);

// Main Scrollable Section
ImGui::BeginChild("MainContent", ImVec2(w-10, h - 120), true);
ImGui::PushItemWidth(150.0f);

// Connection Priority Section
priority connection_priority = classifyPriority(_changed_config.link.priority);
if (ImGui::CollapsingHeader("Connection Priority")) {
ImGui::Text("Select connection priority:");
ImGui::RadioButton("Ethernet First", reinterpret_cast<int*>(&connection_priority), 0);
if (static_cast<int>(connection_priority) == 0) {
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 50);
ImGui::Text("Link Timeout (seconds)");
ImGui::SameLine();
int tempTimeout = static_cast<int>(_changed_config.link.timeout);
if (ImGui::InputInt("##Link Timeout (seconds)", &tempTimeout)) {
_changed_config.link.timeout = static_cast<uint16_t>(std::max(0, tempTimeout));
}
}
ImGui::RadioButton("USB First", reinterpret_cast<int*>(&connection_priority), 1);
ImGui::RadioButton("Dynamic Priority", reinterpret_cast<int*>(&connection_priority), 2);
switch (connection_priority) {
case ETH_FIRST:
_changed_config.link.priority = link_priority::eth_first;
break;
case USB_FIRST:
_changed_config.link.priority = link_priority::usb_first;
break;
case DYNAMIC:
_changed_config.link.priority = _current_config.link.speed ? link_priority::dynamic_eth_first : link_priority::dynamic_usb_first;
break;
}
}

// Network Configuration Section
if (ImGui::CollapsingHeader("Network Configuration")) {
ImGui::Checkbox("Enable DHCP", &_changed_config.dhcp.on);
if (!_changed_config.dhcp.on) {
ImGui::Text("Static IP Address");
ImGui::SameLine();
float textbox_align = ImGui::GetCursorPosX();
ipInputText("Static IP Address", _changed_config.configured.ip);
ImGui::Text("Subnet Mask");
ImGui::SameLine();
ImGui::SetCursorPosX(textbox_align);
bool maskStylePushed = false;
ipInputText("Subnet Mask", _changed_config.configured.netmask);
ImGui::Text("Gateway");
ImGui::SameLine();
ImGui::SetCursorPosX(textbox_align);
ipInputText("Gateway", _changed_config.configured.gateway);
}
ImGui::Text("DHCP Timeout (seconds)");
ImGui::SameLine();
int tempTimeout = static_cast<int>(_changed_config.dhcp.timeout);
if (ImGui::InputInt("##DHCP Timeout (seconds)", &tempTimeout)) {
_changed_config.dhcp.timeout = static_cast<uint16_t>(std::max(0, tempTimeout));
}
}

ImGui::Text("Domain ID");
ImGui::SameLine();
if (ImGui::InputInt("##Domain ID", &_changed_config.dds.domain_id)) {
if (_changed_config.dds.domain_id < 0)
_changed_config.dds.domain_id = 0;
else if(_changed_config.dds.domain_id > 232)
_changed_config.dds.domain_id = 232;
}
ImGui::Checkbox("No Reset after changes", &_no_reset);

if (ImGui::Checkbox("Set to defult values", &_set_defult)) {
if (_set_defult)
_changed_config = _defult_config;
else
_changed_config = _current_config;
}

ImGui::PopItemWidth();
ImGui::EndChild();

//window buttons
float button_width = 105.0f;
float spacing = 10.0f;
float total_buttons_width = button_width * 4 + spacing * 2;
float start_x = (w - total_buttons_width) / 2.0f;
bool hasChanges = (_changed_config != _current_config);

ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 8);

ImGui::SetCursorPosX(start_x);

if (ImGui::Button("Cancel", ImVec2(button_width, 25))) {
close_window();
}
if (ImGui::IsItemHovered()) {
window.link_hovered();
ImGui::SetTooltip("%s", "Close without saving any changes");
}
ImGui::SameLine();
if (ImGui::Button("Factory Reset", ImVec2(button_width, 25))) {
enable_dds(error_message);
set_eth_config(_defult_config , error_message);
close_window();
}
if (ImGui::IsItemHovered()) {
window.link_hovered();
ImGui::SetTooltip("%s", "Reset settings back to defult values");
}
ImGui::SameLine();
RsImGui::RsImButton([&]() {if (ImGui::ButtonEx("Revert changes", ImVec2(button_width, 25))) {
_changed_config = _current_config;
};}, hasChanges);
if (ImGui::IsItemHovered()) {
window.link_hovered();
ImGui::SetTooltip("%s", "Revert to current configuration values");
}
ImGui::SameLine();
RsImGui::RsImButton([&]() {if (ImGui::ButtonEx("Apply", ImVec2(button_width, 25))) {
enable_dds(error_message);
set_eth_config(_changed_config, error_message);
close_window();
};}, hasChanges);
if (ImGui::IsItemHovered()) {
window.link_hovered();
ImGui::SetTooltip("%s", "Apply changes");
}
if (ImGui::BeginPopupModal("No Changes Needed", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("No changes were made to the configuration.");

if (ImGui::Button("OK", ImVec2(100, 25))) {
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
ImGui::End();
ImGui::PopStyleColor(6);
ImGui::PopStyleVar(2);
}

}

void rs2::dds_model::open_dds_tool_window()
{
_current_config = get_eth_config(_device, ACTUAL_VALUES);
_changed_config = _current_config;
_window_open = true;
}

66 changes: 66 additions & 0 deletions common/dds-model.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2024 Intel Corporation. All Rights Reserved.
#pragma once

#include <librealsense2/rs.hpp>
#include <imgui.h>
#include <realsense_imgui.h>
#include <set>
#include <rsutils/type/ip-address.h>
#include <rsutils/string/hexdump.h>
#include "../third-party/rsutils/include/rsutils/type/eth-config.h"
#include <rsutils/json.h>
#include <rsutils/json-config.h>

uint32_t const GET_ETH_CONFIG = 0xBB;
uint32_t const SET_ETH_CONFIG = 0xBA;

bool const ACTUAL_VALUES = 0;
bool const DEFULT_VALUES = 1;

enum priority {
ETH_FIRST,
USB_FIRST,
DYNAMIC
};

namespace rs2
{
class ux_window;

class dds_model
{

public:
dds_model(rs2::device dev);

bool supports_DDS();

void render_dds_config_window(ux_window& window, std::string& error_message);

void open_dds_tool_window();

void close_window() { _window_open = false; }

eth_config get_eth_config(rs2::debug_protocol dev, bool defult_val);

void set_eth_config(eth_config &new_config , std::string& error_message);

void enable_dds(std::string& error_message);


private:
rs2::device _device;

eth_config _defult_config;
eth_config _current_config;
eth_config _changed_config;

bool _window_open;
bool _no_reset = false;
bool _set_defult = false;

void ipInputText(std::string label, rsutils::type::ip_address &ip);
priority classifyPriority(link_priority &pr);
};
}
Loading

0 comments on commit 7e2db73

Please sign in to comment.