Files
hivecore_robot_drivers/librealsense-r-256/common/dds-model.cpp
2026-01-06 18:45:34 +08:00

382 lines
13 KiB
C++

// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2024 Intel Corporation. All Rights Reserved.
#include "dds-model.h"
#include "device-model.h"
#include "ux-window.h"
#include <rsutils/json.h>
#include <rsutils/json-config.h>
#include <rsutils/os/special-folder.h>
#include <rsutils/string/hexdump.h>
#include <imgui.h>
#include <realsense_imgui.h>
#include <iostream>
#include <fstream>
using namespace rs2;
using rsutils::json;
using rsutils::type::ip_address;
namespace rs2 {
uint32_t const GET_ETH_CONFIG = 0xBB;
uint32_t const SET_ETH_CONFIG = 0xBA;
int const CURRENT_VALUES = 0;
int const DEFULT_VALUES = 1;
}
dds_model::dds_model( rs2::device dev )
: _device( dev )
, _window_open( false )
, _no_reset( false )
, _set_defult( false )
, _dds_supported( false )
{
if( check_DDS_support() )
{
_defult_config = get_eth_config( DEFULT_VALUES );
_current_config = get_eth_config( CURRENT_VALUES );
_changed_config = _current_config;
_dds_supported = true;
}
}
eth_config dds_model::get_eth_config( int curr_or_default )
{
rs2::debug_protocol dev( _device );
auto cmd = dev.build_command( GET_ETH_CONFIG, curr_or_default );
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();
}
}
bool rs2::dds_model::supports_DDS()
{
return _dds_supported;
}
rs2::dds_model::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::check_DDS_support()
{
if( _device.is< rs2::debug_protocol >() )
{
if( _device.supports( RS2_CAMERA_INFO_NAME ) )
{
std::string name = _device.get_info( RS2_CAMERA_INFO_NAME );
if( name.find( "Recovery" ) != std::string::npos )
return false; // Recovery devices don't support HWM.
}
try
{
auto dev = debug_protocol( _device );
auto cmd = dev.build_command( GET_ETH_CONFIG, CURRENT_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 true;
}
catch( ... )
{
}
}
return false;
}
void rs2::dds_model::ipInputText( std::string label, 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 );
ip_address new_ip = ip_address( new_ip_str );
if( new_ip.is_valid() )
{
ip = new_ip;
}
else
{
// Initialize the ImGui buffer with the current IP address in case of invalid input
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 )
{
const auto window_name = "DDS Configuration";
if( _window_open )
{
try
{
_current_config = get_eth_config( CURRENT_VALUES );
_changed_config = _current_config;
ImGui::OpenPopup( window_name );
}
catch( std::exception e )
{
error_message = e.what();
}
_window_open = false;
}
// 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 );
if( ImGui::BeginPopupModal( window_name, nullptr, flags ) )
{
if( error_message != "" )
ImGui::CloseCurrentPopup();
// 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 );
// Main Scrollable Section
ImGui::BeginChild( "MainContent", ImVec2( w - 10, h - 100 ), 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; // If link speed is not 0 than we are connected by Ethernet
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 );
}
else
{
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( "Load 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 = 115.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();
RsImGui::CustomTooltip( "%s", "Close without saving any changes" );
}
ImGui::SameLine();
if( ImGui::Button( "Factory Reset", ImVec2( button_width, 25 ) ) )
{
set_eth_config( _defult_config, error_message );
close_window();
}
if( ImGui::IsItemHovered() )
{
window.link_hovered();
RsImGui::CustomTooltip( "%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();
RsImGui::CustomTooltip( "%s", "Revert to current configuration values" );
}
ImGui::SameLine();
RsImGui::RsImButton(
[&]()
{
if( ImGui::ButtonEx( "Apply", ImVec2( button_width, 25 ) ) )
{
set_eth_config( _changed_config, error_message );
close_window();
};
},
! hasChanges );
if( ImGui::IsItemHovered() )
{
window.link_hovered();
RsImGui::CustomTooltip( "%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::EndPopup();
}
ImGui::PopStyleColor( 6 );
ImGui::PopStyleVar( 2 );
}
void rs2::dds_model::open_dds_tool_window()
{
_window_open = true;
}