mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-28 11:21:30 +00:00
Merge branch 'feat/printer-agent-infra' into refactor/connect-printer-api
This commit is contained in:
@@ -997,8 +997,8 @@ elseif (WIN32)
|
|||||||
find_library(LIBAVCODEC_LIBRARY NAMES avcodec PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
find_library(LIBAVCODEC_LIBRARY NAMES avcodec PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
||||||
find_library(LIBSWSCALE_LIBRARY NAMES swscale PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
find_library(LIBSWSCALE_LIBRARY NAMES swscale PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
||||||
find_library(LIBAVUTIL_LIBRARY NAMES avutil PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
find_library(LIBAVUTIL_LIBRARY NAMES avutil PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
||||||
if (NOT LIBAVCODEC_LIBRARY OR NOT LIBSWSCALE_LIBRARY OR NOT LIBAVUTIL_LIBRARY)
|
if (NOT LIBAVFORMAT_LIBRARY OR NOT LIBAVCODEC_LIBRARY OR NOT LIBSWSCALE_LIBRARY OR NOT LIBAVUTIL_LIBRARY)
|
||||||
message(FATAL_ERROR "FFmpeg (avcodec/swscale/avutil) not found under ${CMAKE_PREFIX_PATH}/lib. Rebuild the deps.")
|
message(FATAL_ERROR "FFmpeg (avformat/avcodec/swscale/avutil) not found under ${CMAKE_PREFIX_PATH}/lib. Rebuild the deps.")
|
||||||
endif ()
|
endif ()
|
||||||
target_link_libraries(libslic3r_gui ${LIBAVFORMAT_LIBRARY} ${LIBAVCODEC_LIBRARY} ${LIBSWSCALE_LIBRARY} ${LIBAVUTIL_LIBRARY})
|
target_link_libraries(libslic3r_gui ${LIBAVFORMAT_LIBRARY} ${LIBAVCODEC_LIBRARY} ${LIBSWSCALE_LIBRARY} ${LIBAVUTIL_LIBRARY})
|
||||||
target_include_directories(libslic3r_gui SYSTEM PRIVATE ${CMAKE_PREFIX_PATH}/include)
|
target_include_directories(libslic3r_gui SYSTEM PRIVATE ${CMAKE_PREFIX_PATH}/include)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "Widgets/Label.hpp"
|
#include "Widgets/Label.hpp"
|
||||||
#include "MsgDialog.hpp"
|
#include "MsgDialog.hpp"
|
||||||
#include "libslic3r/Print.hpp"
|
#include "libslic3r/Print.hpp"
|
||||||
|
#include "PrePrintChecker.hpp"
|
||||||
|
|
||||||
#include "DeviceCore/DevConfig.h"
|
#include "DeviceCore/DevConfig.h"
|
||||||
#include "DeviceCore/DevConfigUtil.h"
|
#include "DeviceCore/DevConfigUtil.h"
|
||||||
@@ -1639,19 +1640,6 @@ void CalibrationPresetPage::update_combobox_filaments(MachineObject* obj)
|
|||||||
select_default_compatible_filament();
|
select_default_compatible_filament();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CalibrationPresetPage::is_blocking_printing()
|
|
||||||
{
|
|
||||||
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
|
||||||
if (!dev) return true;
|
|
||||||
|
|
||||||
MachineObject* obj_ = dev->get_selected_machine();
|
|
||||||
if (obj_ == nullptr) return true;
|
|
||||||
|
|
||||||
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
|
||||||
const auto source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
|
||||||
return !DevPrinterConfigUtil::is_printer_model_compatible(source_model, *obj_);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CalibrationPresetPage::is_nozzle_info_synced() const
|
bool CalibrationPresetPage::is_nozzle_info_synced() const
|
||||||
{
|
{
|
||||||
if (!curr_obj || !curr_obj->is_info_ready())
|
if (!curr_obj || !curr_obj->is_info_ready())
|
||||||
@@ -1733,11 +1721,13 @@ void CalibrationPresetPage::update_show_status()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (is_blocking_printing()) {
|
bool has_optional_printer_model = DevPrinterConfigUtil::is_optional_printer_model_id(obj_->printer_type);
|
||||||
// show_status(CaliPresetPageStatus::CaliPresetStatusUnsupportedPrinter);
|
if (PresetBundle *preset_bundle = wxGetApp().preset_bundle) {
|
||||||
// return;
|
has_optional_printer_model = has_optional_printer_model ||
|
||||||
//}
|
DevPrinterConfigUtil::is_optional_printer_model_id(
|
||||||
//else
|
preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle));
|
||||||
|
}
|
||||||
|
|
||||||
if (obj_->is_connecting() || !obj_->is_connected()) {
|
if (obj_->is_connecting() || !obj_->is_connected()) {
|
||||||
show_status(CaliPresetPageStatus::CaliPresetStatusInConnecting);
|
show_status(CaliPresetPageStatus::CaliPresetStatusInConnecting);
|
||||||
return;
|
return;
|
||||||
@@ -1789,7 +1779,9 @@ void CalibrationPresetPage::update_show_status()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
show_status(CaliPresetPageStatus::CaliPresetStatusNormal);
|
show_status(has_optional_printer_model ?
|
||||||
|
CaliPresetPageStatus::CaliPresetStatusOptionalPrinterModel :
|
||||||
|
CaliPresetPageStatus::CaliPresetStatusNormal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1843,6 +1835,10 @@ void CalibrationPresetPage::show_status(CaliPresetPageStatus status)
|
|||||||
Layout();
|
Layout();
|
||||||
Fit();
|
Fit();
|
||||||
}
|
}
|
||||||
|
else if (status == CaliPresetPageStatus::CaliPresetStatusOptionalPrinterModel) {
|
||||||
|
update_print_status_msg(PrePrintChecker::get_pre_state_msg(PrintDialogStatus::PrintStatusOptionalPrinterModel), true);
|
||||||
|
Enable_Send_Button(true);
|
||||||
|
}
|
||||||
else if (status == CaliPresetPageStatus::CaliPresetStatusNoUserLogin) {
|
else if (status == CaliPresetPageStatus::CaliPresetStatusNoUserLogin) {
|
||||||
wxString msg_text = _L("No login account, only printers in LAN mode are displayed.");
|
wxString msg_text = _L("No login account, only printers in LAN mode are displayed.");
|
||||||
update_print_status_msg(msg_text, false);
|
update_print_status_msg(msg_text, false);
|
||||||
|
|||||||
@@ -152,7 +152,8 @@ enum CaliPresetPageStatus
|
|||||||
CaliPresetStatusInConnecting,
|
CaliPresetStatusInConnecting,
|
||||||
CaliPresetStatusFilamentIncompatible,
|
CaliPresetStatusFilamentIncompatible,
|
||||||
CaliPresetStatusLanModeSDcardNotAvailable,
|
CaliPresetStatusLanModeSDcardNotAvailable,
|
||||||
CaliPresetStatusDifferentNozzleDiameters
|
CaliPresetStatusDifferentNozzleDiameters,
|
||||||
|
CaliPresetStatusOptionalPrinterModel
|
||||||
};
|
};
|
||||||
|
|
||||||
class CalibrationPresetPage : public CalibrationWizardPage
|
class CalibrationPresetPage : public CalibrationWizardPage
|
||||||
@@ -268,7 +269,6 @@ protected:
|
|||||||
bool is_nozzle_info_synced() const;
|
bool is_nozzle_info_synced() const;
|
||||||
void show_status(CaliPresetPageStatus status);
|
void show_status(CaliPresetPageStatus status);
|
||||||
void Enable_Send_Button(bool enable);
|
void Enable_Send_Button(bool enable);
|
||||||
bool is_blocking_printing();
|
|
||||||
bool need_check_sdcard(MachineObject* obj);
|
bool need_check_sdcard(MachineObject* obj);
|
||||||
|
|
||||||
CaliPresetPageStatus get_status() { return m_page_status; }
|
CaliPresetPageStatus get_status() { return m_page_status; }
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
|
#include "DevManager.h"
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
#include "DevManager.h"
|
#include <libslic3r/AppConfig.hpp>
|
||||||
#include "CloudProvider.hpp"
|
#include "CloudProvider.hpp"
|
||||||
#include "DevUtil.h"
|
#include "DevUtil.h"
|
||||||
|
|
||||||
@@ -48,9 +49,11 @@ namespace {
|
|||||||
|
|
||||||
namespace Slic3r
|
namespace Slic3r
|
||||||
{
|
{
|
||||||
DeviceManager::DeviceManager(NetworkAgent* agent)
|
DeviceManager::DeviceManager(NetworkAgent* agent, bool enable_refresher, AppConfig* app_config)
|
||||||
{
|
{
|
||||||
m_agent = agent;
|
m_agent = agent;
|
||||||
|
m_app_config = app_config;
|
||||||
|
if (enable_refresher)
|
||||||
m_refresher = new DeviceManagerRefresher(this);
|
m_refresher = new DeviceManagerRefresher(this);
|
||||||
|
|
||||||
DevPrinterConfigUtil::InitFilePath(resources_dir());
|
DevPrinterConfigUtil::InitFilePath(resources_dir());
|
||||||
@@ -62,9 +65,14 @@ namespace Slic3r
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AppConfig* DeviceManager::get_app_config() const
|
||||||
|
{
|
||||||
|
return m_app_config ? m_app_config : GUI::wxGetApp().app_config;
|
||||||
|
}
|
||||||
|
|
||||||
void DeviceManager::load_local_machines_from_config()
|
void DeviceManager::load_local_machines_from_config()
|
||||||
{
|
{
|
||||||
AppConfig* config = GUI::wxGetApp().app_config;
|
AppConfig* config = get_app_config();
|
||||||
if (!config)
|
if (!config)
|
||||||
return;
|
return;
|
||||||
const auto local_machines = config->get_local_machines();
|
const auto local_machines = config->get_local_machines();
|
||||||
@@ -90,9 +98,8 @@ namespace Slic3r
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceManager::update_local_machine(const MachineObject& m)
|
void DeviceManager::update_local_machine(const MachineObject& m, AppConfig* config)
|
||||||
{
|
{
|
||||||
AppConfig* config = GUI::wxGetApp().app_config;
|
|
||||||
if (config) {
|
if (config) {
|
||||||
if (m.is_lan_mode_printer()) {
|
if (m.is_lan_mode_printer()) {
|
||||||
if (m.has_access_right()) {
|
if (m.has_access_right()) {
|
||||||
@@ -113,6 +120,7 @@ namespace Slic3r
|
|||||||
|
|
||||||
DeviceManager::~DeviceManager()
|
DeviceManager::~DeviceManager()
|
||||||
{
|
{
|
||||||
|
if (m_refresher)
|
||||||
delete m_refresher;
|
delete m_refresher;
|
||||||
|
|
||||||
for (auto it = localMachineList.begin(); it != localMachineList.end(); it++)
|
for (auto it = localMachineList.begin(); it != localMachineList.end(); it++)
|
||||||
@@ -173,14 +181,22 @@ namespace Slic3r
|
|||||||
return printer_agent ? printer_agent->get_agent_info().id : "";
|
return printer_agent ? printer_agent->get_agent_info().id : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string DeviceManager::get_current_cloud_provider() const
|
||||||
|
{
|
||||||
|
const std::string agent_id = get_current_printer_agent_id();
|
||||||
|
if (!agent_id.empty())
|
||||||
|
return agent_id == BBL_PRINTER_AGENT_ID ? BBL_CLOUD_PROVIDER : ORCA_CLOUD_PROVIDER;
|
||||||
|
return GUI::wxGetApp().get_printer_cloud_provider();
|
||||||
|
}
|
||||||
|
|
||||||
void DeviceManager::EnableMultiMachine(bool enable)
|
void DeviceManager::EnableMultiMachine(bool enable)
|
||||||
{
|
{
|
||||||
m_agent->enable_multi_machine(enable);
|
m_agent->enable_multi_machine(enable);
|
||||||
m_enable_mutil_machine = enable;
|
m_enable_mutil_machine = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceManager::start_refresher() { m_refresher->Start(); }
|
void DeviceManager::start_refresher() { if (m_refresher) m_refresher->Start(); }
|
||||||
void DeviceManager::stop_refresher() { m_refresher->Stop(); }
|
void DeviceManager::stop_refresher() { if (m_refresher) m_refresher->Stop(); }
|
||||||
|
|
||||||
|
|
||||||
void DeviceManager::keep_alive()
|
void DeviceManager::keep_alive()
|
||||||
@@ -297,6 +313,8 @@ namespace Slic3r
|
|||||||
|
|
||||||
/* update localMachineList */
|
/* update localMachineList */
|
||||||
it = localMachineList.find(dev_id);
|
it = localMachineList.find(dev_id);
|
||||||
|
AppConfig* config = get_app_config();
|
||||||
|
|
||||||
if (it != localMachineList.end()) {
|
if (it != localMachineList.end()) {
|
||||||
// update properties
|
// update properties
|
||||||
/* ip changed */
|
/* ip changed */
|
||||||
@@ -386,7 +404,6 @@ namespace Slic3r
|
|||||||
obj->m_is_online = true;
|
obj->m_is_online = true;
|
||||||
|
|
||||||
//load access code
|
//load access code
|
||||||
AppConfig* config = Slic3r::GUI::wxGetApp().app_config;
|
|
||||||
if (config) {
|
if (config) {
|
||||||
obj->set_access_code(get_access_code_with_legacy_fallback(config, dev_id, obj->printer_agent_id), false);
|
obj->set_access_code(get_access_code_with_legacy_fallback(config, dev_id, obj->printer_agent_id), false);
|
||||||
}
|
}
|
||||||
@@ -400,7 +417,7 @@ namespace Slic3r
|
|||||||
<< ", ip = " << dev_ip <<", printer_name = " << dev_name
|
<< ", ip = " << dev_ip <<", printer_name = " << dev_name
|
||||||
<< ", con_type= " << connect_type <<", signal= " << printer_signal << ", bind_state= " << bind_state;
|
<< ", con_type= " << connect_type <<", signal= " << printer_signal << ", bind_state= " << bind_state;
|
||||||
}
|
}
|
||||||
update_local_machine(*obj);
|
update_local_machine(*obj, config);
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
;
|
;
|
||||||
@@ -435,11 +452,16 @@ namespace Slic3r
|
|||||||
obj->last_alive = Slic3r::Utils::get_current_time_utc();
|
obj->last_alive = Slic3r::Utils::get_current_time_utc();
|
||||||
obj->set_access_code(access_code, false);
|
obj->set_access_code(access_code, false);
|
||||||
|
|
||||||
update_local_machine(*obj);
|
update_local_machine(*obj, get_app_config());
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeviceManager::update_local_machine(const MachineObject& m)
|
||||||
|
{
|
||||||
|
update_local_machine(m, GUI::wxGetApp().app_config);
|
||||||
|
}
|
||||||
|
|
||||||
int DeviceManager::query_bind_status(std::string& msg, const std::string& provider)
|
int DeviceManager::query_bind_status(std::string& msg, const std::string& provider)
|
||||||
{
|
{
|
||||||
if (!m_agent)
|
if (!m_agent)
|
||||||
@@ -573,13 +595,13 @@ namespace Slic3r
|
|||||||
<< " cur_selected=" << selected_machine;
|
<< " cur_selected=" << selected_machine;
|
||||||
auto my_machine_list = get_my_machine_list(get_current_printer_agent_id());
|
auto my_machine_list = get_my_machine_list(get_current_printer_agent_id());
|
||||||
auto it = my_machine_list.find(dev_id);
|
auto it = my_machine_list.find(dev_id);
|
||||||
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: set_selected_machine lookup dev_id=" << dev_id
|
BOOST_LOG_TRIVIAL(trace) << "Orca diagnostic: set_selected_machine lookup dev_id=" << dev_id
|
||||||
<< " found=" << (it != my_machine_list.end())
|
<< " found=" << (it != my_machine_list.end())
|
||||||
<< " my_machine_count=" << my_machine_list.size()
|
<< " my_machine_count=" << my_machine_list.size()
|
||||||
<< " current_agent=" << get_current_printer_agent_id()
|
<< " current_agent=" << get_current_printer_agent_id()
|
||||||
<< " provider=" << GUI::wxGetApp().get_printer_cloud_provider();
|
<< " provider=" << GUI::wxGetApp().get_printer_cloud_provider();
|
||||||
if (it != my_machine_list.end() && it->second) {
|
if (it != my_machine_list.end() && it->second) {
|
||||||
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: target machine dev_id=" << it->second->get_dev_id()
|
BOOST_LOG_TRIVIAL(trace) << "Orca diagnostic: target machine dev_id=" << it->second->get_dev_id()
|
||||||
<< " printer_agent_id=" << it->second->printer_agent_id
|
<< " printer_agent_id=" << it->second->printer_agent_id
|
||||||
<< " connection_type=" << it->second->connection_type()
|
<< " connection_type=" << it->second->connection_type()
|
||||||
<< " dev_connection_type=" << it->second->dev_connection_type;
|
<< " dev_connection_type=" << it->second->dev_connection_type;
|
||||||
@@ -598,7 +620,7 @@ namespace Slic3r
|
|||||||
}
|
}
|
||||||
else if (last_selected->second->connection_type() == "cloud") {
|
else if (last_selected->second->connection_type() == "cloud") {
|
||||||
const int result = m_agent->set_user_selected_machine("");
|
const int result = m_agent->set_user_selected_machine("");
|
||||||
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: cleared previous cloud selection dev_id="
|
BOOST_LOG_TRIVIAL(trace) << "Orca diagnostic: cleared previous cloud selection dev_id="
|
||||||
<< selected_machine << " result=" << result;
|
<< selected_machine << " result=" << result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -635,7 +657,8 @@ namespace Slic3r
|
|||||||
it->second->reset();
|
it->second->reset();
|
||||||
|
|
||||||
#if !BBL_RELEASE_TO_PUBLIC
|
#if !BBL_RELEASE_TO_PUBLIC
|
||||||
it->second->connect(Slic3r::GUI::wxGetApp().app_config->get("enable_ssl_for_mqtt") == "true" ? true : false);
|
AppConfig* config = get_app_config();
|
||||||
|
it->second->connect(config && config->get("enable_ssl_for_mqtt") == "true");
|
||||||
#else
|
#else
|
||||||
it->second->connect(it->second->local_use_ssl);
|
it->second->connect(it->second->local_use_ssl);
|
||||||
#endif
|
#endif
|
||||||
@@ -652,7 +675,7 @@ namespace Slic3r
|
|||||||
// diff dev_id, cloud => set_user_selected_machine(new)
|
// diff dev_id, cloud => set_user_selected_machine(new)
|
||||||
BOOST_LOG_TRIVIAL(info) << "set_selected_machine: select new cloud machine, dev_id =" << dev_id;
|
BOOST_LOG_TRIVIAL(info) << "set_selected_machine: select new cloud machine, dev_id =" << dev_id;
|
||||||
const int result = m_agent->set_user_selected_machine(dev_id);
|
const int result = m_agent->set_user_selected_machine(dev_id);
|
||||||
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: set new cloud selection dev_id="
|
BOOST_LOG_TRIVIAL(trace) << "Orca diagnostic: set new cloud selection dev_id="
|
||||||
<< dev_id << " result=" << result;
|
<< dev_id << " result=" << result;
|
||||||
it->second->reset();
|
it->second->reset();
|
||||||
}
|
}
|
||||||
@@ -661,7 +684,8 @@ namespace Slic3r
|
|||||||
BOOST_LOG_TRIVIAL(info) << "set_selected_machine: select new lan machine, dev_id =" << dev_id;
|
BOOST_LOG_TRIVIAL(info) << "set_selected_machine: select new lan machine, dev_id =" << dev_id;
|
||||||
it->second->reset();
|
it->second->reset();
|
||||||
#if !BBL_RELEASE_TO_PUBLIC
|
#if !BBL_RELEASE_TO_PUBLIC
|
||||||
it->second->connect(Slic3r::GUI::wxGetApp().app_config->get("enable_ssl_for_mqtt") == "true" ? true : false);
|
AppConfig* config = get_app_config();
|
||||||
|
it->second->connect(config && config->get("enable_ssl_for_mqtt") == "true");
|
||||||
#else
|
#else
|
||||||
it->second->connect(it->second->local_use_ssl);
|
it->second->connect(it->second->local_use_ssl);
|
||||||
#endif
|
#endif
|
||||||
@@ -681,7 +705,7 @@ namespace Slic3r
|
|||||||
|
|
||||||
selected_machine = dev_id;
|
selected_machine = dev_id;
|
||||||
record_user_last_machine(selected_machine);
|
record_user_last_machine(selected_machine);
|
||||||
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: DeviceManager selection complete selected_machine="
|
BOOST_LOG_TRIVIAL(trace) << "Orca diagnostic: DeviceManager selection complete selected_machine="
|
||||||
<< selected_machine;
|
<< selected_machine;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -714,7 +738,7 @@ namespace Slic3r
|
|||||||
BOOST_LOG_TRIVIAL(trace) << "add_user_subscribe: " << it->first;
|
BOOST_LOG_TRIVIAL(trace) << "add_user_subscribe: " << it->first;
|
||||||
}
|
}
|
||||||
const int result = m_agent->add_subscribe(dev_list);
|
const int result = m_agent->add_subscribe(dev_list);
|
||||||
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: add_user_subscribe count=" << dev_list.size()
|
BOOST_LOG_TRIVIAL(trace) << "Orca diagnostic: add_user_subscribe count=" << dev_list.size()
|
||||||
<< " result=" << result;
|
<< " result=" << result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -729,7 +753,7 @@ namespace Slic3r
|
|||||||
BOOST_LOG_TRIVIAL(trace) << "del_user_subscribe: " << it->first;
|
BOOST_LOG_TRIVIAL(trace) << "del_user_subscribe: " << it->first;
|
||||||
}
|
}
|
||||||
const int result = m_agent->del_subscribe(dev_list);
|
const int result = m_agent->del_subscribe(dev_list);
|
||||||
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: del_user_subscribe count=" << dev_list.size()
|
BOOST_LOG_TRIVIAL(trace) << "Orca diagnostic: del_user_subscribe count=" << dev_list.size()
|
||||||
<< " result=" << result;
|
<< " result=" << result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -851,14 +875,15 @@ namespace Slic3r
|
|||||||
json j = json::parse(body);
|
json j = json::parse(body);
|
||||||
|
|
||||||
const bool has_request_context = j.contains("provider") && j.contains("agent_id") && j.contains("generation");
|
const bool has_request_context = j.contains("provider") && j.contains("agent_id") && j.contains("generation");
|
||||||
|
const std::string current_provider = get_current_cloud_provider();
|
||||||
const std::string provider = j.contains("provider") ? j["provider"].get<std::string>()
|
const std::string provider = j.contains("provider") ? j["provider"].get<std::string>()
|
||||||
: GUI::wxGetApp().get_printer_cloud_provider();
|
: current_provider;
|
||||||
const std::string agent_id = j.contains("agent_id") ? j["agent_id"].get<std::string>()
|
const std::string agent_id = j.contains("agent_id") ? j["agent_id"].get<std::string>()
|
||||||
: get_current_printer_agent_id();
|
: get_current_printer_agent_id();
|
||||||
const std::uint64_t generation = j.value("generation", std::uint64_t(0));
|
const std::uint64_t generation = j.value("generation", std::uint64_t(0));
|
||||||
|
|
||||||
if (has_request_context &&
|
if (has_request_context &&
|
||||||
(provider != GUI::wxGetApp().get_printer_cloud_provider() ||
|
(provider != current_provider ||
|
||||||
agent_id != get_current_printer_agent_id() ||
|
agent_id != get_current_printer_agent_id() ||
|
||||||
generation != (m_agent ? m_agent->get_user_machine_list_generation() : 0))) {
|
generation != (m_agent ? m_agent->get_user_machine_list_generation() : 0))) {
|
||||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ": ignoring stale response provider="
|
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ": ignoring stale response provider="
|
||||||
@@ -903,7 +928,8 @@ namespace Slic3r
|
|||||||
|
|
||||||
if (obj->get_dev_ip().empty())
|
if (obj->get_dev_ip().empty())
|
||||||
{
|
{
|
||||||
obj->get_dev_ip() = Slic3r::GUI::wxGetApp().app_config->get("ip_address", dev_id);
|
if (AppConfig* config = get_app_config())
|
||||||
|
obj->get_dev_ip() = config->get("ip_address", dev_id);
|
||||||
}
|
}
|
||||||
userMachineList.insert(std::make_pair(dev_id, obj));
|
userMachineList.insert(std::make_pair(dev_id, obj));
|
||||||
}
|
}
|
||||||
@@ -948,7 +974,7 @@ namespace Slic3r
|
|||||||
obj->set_access_code(acc_code);
|
obj->set_access_code(acc_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: parsed cloud machine dev_id=" << dev_id
|
BOOST_LOG_TRIVIAL(trace) << "Orca diagnostic: parsed cloud machine dev_id=" << dev_id
|
||||||
<< " name=" << obj->get_dev_name()
|
<< " name=" << obj->get_dev_name()
|
||||||
<< " agent_id=" << obj->printer_agent_id
|
<< " agent_id=" << obj->printer_agent_id
|
||||||
<< " connection_type=" << obj->connection_type()
|
<< " connection_type=" << obj->connection_type()
|
||||||
@@ -968,7 +994,7 @@ namespace Slic3r
|
|||||||
iterat++;
|
iterat++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: parse_user_print_info complete provider=" << provider
|
BOOST_LOG_TRIVIAL(trace) << "Orca diagnostic: parse_user_print_info complete provider=" << provider
|
||||||
<< " parsed_count=" << new_list.size()
|
<< " parsed_count=" << new_list.size()
|
||||||
<< " stored_count=" << userMachineList.size();
|
<< " stored_count=" << userMachineList.size();
|
||||||
}
|
}
|
||||||
@@ -987,29 +1013,29 @@ namespace Slic3r
|
|||||||
unsigned int http_code;
|
unsigned int http_code;
|
||||||
std::string body;
|
std::string body;
|
||||||
int result = m_agent->get_user_print_info(&http_code, &body, provider);
|
int result = m_agent->get_user_print_info(&http_code, &body, provider);
|
||||||
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: get_user_print_info provider=" << provider
|
BOOST_LOG_TRIVIAL(trace) << "Orca diagnostic: get_user_print_info provider=" << provider
|
||||||
<< " result=" << result << " http_code=" << http_code
|
<< " result=" << result << " http_code=" << http_code
|
||||||
<< " body_bytes=" << body.size();
|
<< " body_bytes=" << body.size();
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
{
|
{
|
||||||
// parse_user_print_info and on_machine_alive (SSDP for discovery) both mutate the same userMachineList map.
|
// parse_user_print_info and on_machine_alive (SSDP for discovery) both mutate the same userMachineList map.
|
||||||
// on_machine_alive mutates the map on the UI thread, do the same for parse_user_print_info.
|
// on_machine_alive mutates the map on the UI thread, do the same for parse_user_print_info.
|
||||||
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: queueing parse_user_print_info on UI thread";
|
BOOST_LOG_TRIVIAL(trace) << "Orca diagnostic: queueing parse_user_print_info on UI thread";
|
||||||
Slic3r::GUI::wxGetApp().CallAfter([this, body]() { parse_user_print_info(body); });
|
Slic3r::GUI::wxGetApp().CallAfter([this, body]() { parse_user_print_info(body); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceManager::record_user_last_machine(const std::string& dev_id)
|
void DeviceManager::record_user_last_machine(const std::string& dev_id)
|
||||||
{
|
{
|
||||||
if (Slic3r::GUI::wxGetApp().app_config) {
|
if (AppConfig* config = get_app_config()) {
|
||||||
Slic3r::GUI::wxGetApp().app_config->set("user_last_selected_machine", dev_id);
|
config->set("user_last_selected_machine", dev_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string DeviceManager::get_user_last_machine() const
|
std::string DeviceManager::get_user_last_machine() const
|
||||||
{
|
{
|
||||||
if (Slic3r::GUI::wxGetApp().app_config) {
|
if (AppConfig* config = get_app_config()) {
|
||||||
const auto& user_last_machine = Slic3r::GUI::wxGetApp().app_config->get("user_last_selected_machine");
|
const auto& user_last_machine = config->get("user_last_selected_machine");
|
||||||
if (!user_last_machine.empty()) {
|
if (!user_last_machine.empty()) {
|
||||||
return user_last_machine;
|
return user_last_machine;
|
||||||
} else if (m_agent) {
|
} else if (m_agent) {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ namespace Slic3r
|
|||||||
struct BBLocalMachine;
|
struct BBLocalMachine;
|
||||||
class MachineObject;
|
class MachineObject;
|
||||||
class NetworkAgent;
|
class NetworkAgent;
|
||||||
|
class AppConfig;
|
||||||
|
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
class GUI_App;
|
class GUI_App;
|
||||||
@@ -24,6 +25,7 @@ class DeviceManager
|
|||||||
friend class DeviceManagerRefresher;
|
friend class DeviceManagerRefresher;
|
||||||
private:
|
private:
|
||||||
NetworkAgent* m_agent{ nullptr };
|
NetworkAgent* m_agent{ nullptr };
|
||||||
|
AppConfig* m_app_config{ nullptr };
|
||||||
DeviceManagerRefresher* m_refresher{ nullptr };
|
DeviceManagerRefresher* m_refresher{ nullptr };
|
||||||
|
|
||||||
bool m_enable_mutil_machine = false;
|
bool m_enable_mutil_machine = false;
|
||||||
@@ -35,11 +37,13 @@ private:
|
|||||||
std::map<std::string, MachineObject*> userMachineList; /* dev_id -> MachineObject* cloudMachine of User */
|
std::map<std::string, MachineObject*> userMachineList; /* dev_id -> MachineObject* cloudMachine of User */
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DeviceManager(NetworkAgent* agent = nullptr);
|
DeviceManager(NetworkAgent* agent = nullptr, bool enable_refresher = true,
|
||||||
|
AppConfig* app_config = nullptr);
|
||||||
~DeviceManager();
|
~DeviceManager();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NetworkAgent* get_agent() const { return m_agent; }
|
NetworkAgent* get_agent() const { return m_agent; }
|
||||||
|
AppConfig* get_app_config() const;
|
||||||
void set_agent(NetworkAgent* agent);
|
void set_agent(NetworkAgent* agent);
|
||||||
|
|
||||||
void start_refresher();
|
void start_refresher();
|
||||||
@@ -121,6 +125,7 @@ private:
|
|||||||
|
|
||||||
void keep_alive();
|
void keep_alive();
|
||||||
void check_pushing();
|
void check_pushing();
|
||||||
|
std::string get_current_cloud_provider() const;
|
||||||
|
|
||||||
void OnMachineBindStateChanged(MachineObject* obj, const std::string& new_state);
|
void OnMachineBindStateChanged(MachineObject* obj, const std::string& new_state);
|
||||||
void OnSelectedMachineChanged(const std::string& pre_dev_id, const std::string& new_dev_id);
|
void OnSelectedMachineChanged(const std::string& pre_dev_id, const std::string& new_dev_id);
|
||||||
@@ -133,6 +138,7 @@ public:
|
|||||||
std::string connection_type, std::string bind_state, std::string version,
|
std::string connection_type, std::string bind_state, std::string version,
|
||||||
std::string access_code);
|
std::string access_code);
|
||||||
static void update_local_machine(const MachineObject& m);
|
static void update_local_machine(const MachineObject& m);
|
||||||
|
static void update_local_machine(const MachineObject& m, AppConfig* config);
|
||||||
};
|
};
|
||||||
|
|
||||||
class DeviceManagerRefresher : public wxObject
|
class DeviceManagerRefresher : public wxObject
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "ReleaseNote.hpp"
|
#include "ReleaseNote.hpp"
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <charconv>
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <boost/typeof/typeof.hpp>
|
#include <boost/typeof/typeof.hpp>
|
||||||
@@ -477,7 +478,7 @@ void MachineObject::set_access_code(std::string code, bool only_refresh)
|
|||||||
{
|
{
|
||||||
this->access_code = code;
|
this->access_code = code;
|
||||||
if (only_refresh) {
|
if (only_refresh) {
|
||||||
AppConfig* config = GUI::wxGetApp().app_config;
|
AppConfig* config = m_manager ? m_manager->get_app_config() : GUI::wxGetApp().app_config;
|
||||||
if (config) {
|
if (config) {
|
||||||
if (is_lan_mode_printer()) {
|
if (is_lan_mode_printer()) {
|
||||||
// why: LAN codes are scoped via BBLocalMachine::access_code, keyed by dev_id and
|
// why: LAN codes are scoped via BBLocalMachine::access_code, keyed by dev_id and
|
||||||
@@ -490,7 +491,7 @@ void MachineObject::set_access_code(std::string code, bool only_refresh)
|
|||||||
// fresh from the cloud API's current response, so there's no cross-agent leakage
|
// fresh from the cloud API's current response, so there's no cross-agent leakage
|
||||||
// risk to guard against there.
|
// risk to guard against there.
|
||||||
if (!code.empty()) {
|
if (!code.empty()) {
|
||||||
DeviceManager::update_local_machine(*this);
|
DeviceManager::update_local_machine(*this, config);
|
||||||
} else {
|
} else {
|
||||||
// Only patch an existing record's code - don't persist a brand-new
|
// Only patch an existing record's code - don't persist a brand-new
|
||||||
// never-bound entry just because set_access_code("") was called on it.
|
// never-bound entry just because set_access_code("") was called on it.
|
||||||
@@ -2603,9 +2604,14 @@ void MachineObject::set_print_state(std::string status)
|
|||||||
// why: printer agents can report progress without BBL cloud task identity.
|
// why: printer agents can report progress without BBL cloud task identity.
|
||||||
void MachineObject::update_print_progress(const json& value)
|
void MachineObject::update_print_progress(const json& value)
|
||||||
{
|
{
|
||||||
if (value.is_string())
|
if (value.is_string()) {
|
||||||
mc_print_percent = stoi(value.get<std::string>());
|
const std::string progress = value.get<std::string>();
|
||||||
else if (value.is_number_integer())
|
int parsed_progress;
|
||||||
|
const auto result = std::from_chars(progress.data(), progress.data() + progress.size(), parsed_progress);
|
||||||
|
if (result.ec != std::errc{} || result.ptr != progress.data() + progress.size())
|
||||||
|
return;
|
||||||
|
mc_print_percent = parsed_progress;
|
||||||
|
} else if (value.is_number_integer())
|
||||||
mc_print_percent = value.get<int>();
|
mc_print_percent = value.get<int>();
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
@@ -4650,7 +4656,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_
|
|||||||
if (diff.count() > 10.0f) {
|
if (diff.count() > 10.0f) {
|
||||||
BOOST_LOG_TRIVIAL(trace) << "parse_json timeout = " << diff.count();
|
BOOST_LOG_TRIVIAL(trace) << "parse_json timeout = " << diff.count();
|
||||||
}
|
}
|
||||||
DeviceManager::update_local_machine(*this);
|
DeviceManager::update_local_machine(*this, m_manager ? m_manager->get_app_config() : GUI::wxGetApp().app_config);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-12
@@ -2383,19 +2383,21 @@ GUI_App::~GUI_App()
|
|||||||
|
|
||||||
bool GUI_App::is_blocking_printing(MachineObject *obj_)
|
bool GUI_App::is_blocking_printing(MachineObject *obj_)
|
||||||
{
|
{
|
||||||
DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
|
||||||
if (!dev) return true;
|
|
||||||
if (obj_ == nullptr) {
|
|
||||||
obj_ = dev->get_selected_machine();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!obj_)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
PresetBundle *preset_bundle = wxGetApp().preset_bundle;
|
PresetBundle *preset_bundle = wxGetApp().preset_bundle;
|
||||||
std::string source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
const std::string source_model = preset_bundle
|
||||||
|
? preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle)
|
||||||
|
: std::string();
|
||||||
|
return is_blocking_printing(obj_, source_model);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GUI_App::is_blocking_printing(MachineObject *obj_, const std::string& source_model)
|
||||||
|
{
|
||||||
|
DeviceManager *dev = getDeviceManager();
|
||||||
|
if (!dev) return true;
|
||||||
|
if (obj_ == nullptr)
|
||||||
|
obj_ = dev->get_selected_machine();
|
||||||
|
if (!obj_)
|
||||||
|
return false;
|
||||||
|
|
||||||
return !DevPrinterConfigUtil::is_printer_model_compatible(source_model, *obj_);
|
return !DevPrinterConfigUtil::is_printer_model_compatible(source_model, *obj_);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -368,6 +368,7 @@ public:
|
|||||||
EAppMode get_app_mode() const { return m_app_mode; }
|
EAppMode get_app_mode() const { return m_app_mode; }
|
||||||
Slic3r::DeviceManager* getDeviceManager() { return m_device_manager; }
|
Slic3r::DeviceManager* getDeviceManager() { return m_device_manager; }
|
||||||
bool is_blocking_printing(MachineObject *obj_ = nullptr);
|
bool is_blocking_printing(MachineObject *obj_ = nullptr);
|
||||||
|
bool is_blocking_printing(MachineObject *obj_, const std::string& source_model);
|
||||||
Slic3r::TaskManager* getTaskManager() { return m_task_manager; }
|
Slic3r::TaskManager* getTaskManager() { return m_task_manager; }
|
||||||
HMSQuery* get_hms_query() { return hms_query; }
|
HMSQuery* get_hms_query() { return hms_query; }
|
||||||
NetworkAgent* getAgent() { return m_agent; }
|
NetworkAgent* getAgent() { return m_agent; }
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ void MonitorPanel::msw_rescale()
|
|||||||
|
|
||||||
void MonitorPanel::select_machine(std::string machine_sn)
|
void MonitorPanel::select_machine(std::string machine_sn)
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: MonitorPanel::select_machine queueing machine_sn=" << machine_sn;
|
BOOST_LOG_TRIVIAL(trace) << "Orca diagnostic: MonitorPanel::select_machine queueing machine_sn=" << machine_sn;
|
||||||
wxCommandEvent *event = new wxCommandEvent(wxEVT_COMMAND_CHOICE_SELECTED);
|
wxCommandEvent *event = new wxCommandEvent(wxEVT_COMMAND_CHOICE_SELECTED);
|
||||||
event->SetString(machine_sn);
|
event->SetString(machine_sn);
|
||||||
wxQueueEvent(this, event);
|
wxQueueEvent(this, event);
|
||||||
@@ -280,7 +280,7 @@ void MonitorPanel::on_select_printer(wxCommandEvent& event)
|
|||||||
{
|
{
|
||||||
Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||||
const std::string requested_dev_id = event.GetString().ToStdString();
|
const std::string requested_dev_id = event.GetString().ToStdString();
|
||||||
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: MonitorPanel::on_select_printer requested_dev_id="
|
BOOST_LOG_TRIVIAL(trace) << "Orca diagnostic: MonitorPanel::on_select_printer requested_dev_id="
|
||||||
<< requested_dev_id << " device_manager=" << (dev ? "set" : "null");
|
<< requested_dev_id << " device_manager=" << (dev ? "set" : "null");
|
||||||
if (!dev) return;
|
if (!dev) return;
|
||||||
|
|
||||||
@@ -289,7 +289,7 @@ void MonitorPanel::on_select_printer(wxCommandEvent& event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const bool selected = dev->set_selected_machine(requested_dev_id);
|
const bool selected = dev->set_selected_machine(requested_dev_id);
|
||||||
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: MonitorPanel::on_select_printer set_selected_machine result="
|
BOOST_LOG_TRIVIAL(trace) << "Orca diagnostic: MonitorPanel::on_select_printer set_selected_machine result="
|
||||||
<< selected << " selected_dev_id="
|
<< selected << " selected_dev_id="
|
||||||
<< (dev->get_selected_machine() ? dev->get_selected_machine()->get_dev_id() : "<null>");
|
<< (dev->get_selected_machine() ? dev->get_selected_machine()->get_dev_id() : "<null>");
|
||||||
if (!selected)
|
if (!selected)
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
#include "MainFrame.hpp"
|
#include "MainFrame.hpp"
|
||||||
#include "DeviceCore/DevConfigUtil.h"
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
@@ -52,7 +51,7 @@ void DeviceItem::sync_state()
|
|||||||
state_printable = 6;
|
state_printable = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_blocking_printing(obj_)) {
|
if (wxGetApp().is_blocking_printing(obj_)) {
|
||||||
state_printable = 5;
|
state_printable = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,18 +104,6 @@ void DeviceItem::unselected()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeviceItem::is_blocking_printing(MachineObject* obj_)
|
|
||||||
{
|
|
||||||
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
|
||||||
if (!dev) return true;
|
|
||||||
std::string source_model = "";
|
|
||||||
|
|
||||||
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
|
||||||
source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
|
||||||
|
|
||||||
return !DevPrinterConfigUtil::is_printer_model_compatible(source_model, *obj_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceItem::update_item(const DeviceItem* item)
|
void DeviceItem::update_item(const DeviceItem* item)
|
||||||
{
|
{
|
||||||
// Except for the selected status, everything else is updated
|
// Except for the selected status, everything else is updated
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ public:
|
|||||||
|
|
||||||
void selected();
|
void selected();
|
||||||
void unselected();
|
void unselected();
|
||||||
bool is_blocking_printing(MachineObject* obj_);
|
|
||||||
void update_item(const DeviceItem* item);
|
void update_item(const DeviceItem* item);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ public:
|
|||||||
void add_with_checkbox(PrintDialogStatus state, wxString msg, wxString checkbox_label, bool checked, std::function<void(bool)> checkbox_callback);
|
void add_with_checkbox(PrintDialogStatus state, wxString msg, wxString checkbox_label, bool checked, std::function<void(bool)> checkbox_callback);
|
||||||
static ::std::string get_print_status_info(PrintDialogStatus status);
|
static ::std::string get_print_status_info(PrintDialogStatus status);
|
||||||
|
|
||||||
wxString get_pre_state_msg(PrintDialogStatus status);
|
static wxString get_pre_state_msg(PrintDialogStatus status);
|
||||||
static bool is_error(PrintDialogStatus status) { return (PrintStatusErrorBegin < status) && (PrintStatusErrorEnd > status); };
|
static bool is_error(PrintDialogStatus status) { return (PrintStatusErrorBegin < status) && (PrintStatusErrorEnd > status); };
|
||||||
static bool is_error_printer(PrintDialogStatus status) { return (PrintStatusPrinterErrorBegin < status) && (PrintStatusPrinterErrorEnd > status); };
|
static bool is_error_printer(PrintDialogStatus status) { return (PrintStatusPrinterErrorBegin < status) && (PrintStatusPrinterErrorEnd > status); };
|
||||||
static bool is_error_filament(PrintDialogStatus status) { return (PrintStatusFilamentErrorBegin < status) && (PrintStatusFilamentErrorEnd > status); };
|
static bool is_error_filament(PrintDialogStatus status) { return (PrintStatusFilamentErrorBegin < status) && (PrintStatusFilamentErrorEnd > status); };
|
||||||
|
|||||||
@@ -2518,23 +2518,13 @@ void SelectMachineDialog::on_cancel(wxCloseEvent &event)
|
|||||||
|
|
||||||
bool SelectMachineDialog::is_blocking_printing(MachineObject* obj_)
|
bool SelectMachineDialog::is_blocking_printing(MachineObject* obj_)
|
||||||
{
|
{
|
||||||
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
if (m_print_type == PrintFromType::FROM_NORMAL)
|
||||||
if (!dev) return true;
|
return wxGetApp().is_blocking_printing(obj_);
|
||||||
auto target_model = obj_->printer_type;
|
|
||||||
std::string source_model = "";
|
|
||||||
|
|
||||||
if (m_print_type == PrintFromType::FROM_NORMAL) {
|
std::string source_model;
|
||||||
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
if (m_print_type == PrintFromType::FROM_SDCARD_VIEW && !m_required_data_plate_data_list.empty())
|
||||||
source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
|
||||||
|
|
||||||
|
|
||||||
}else if (m_print_type == PrintFromType::FROM_SDCARD_VIEW) {
|
|
||||||
if (m_required_data_plate_data_list.size() > 0) {
|
|
||||||
source_model = m_required_data_plate_data_list[m_print_plate_idx]->printer_model_id;
|
source_model = m_required_data_plate_data_list[m_print_plate_idx]->printer_model_id;
|
||||||
}
|
return wxGetApp().is_blocking_printing(obj_, source_model);
|
||||||
}
|
|
||||||
|
|
||||||
return !DevPrinterConfigUtil::is_printer_model_compatible(source_model, *obj_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::unordered_set<int> _get_used_nozzle_idxes()
|
static std::unordered_set<int> _get_used_nozzle_idxes()
|
||||||
|
|||||||
@@ -738,7 +738,7 @@ void SendMultiMachinePage::on_send(wxCommandEvent& event)
|
|||||||
|
|
||||||
if (obj && obj->is_online() && !obj->can_abort() && !obj->is_in_upgrading() && it->second->get_state_selected() == 1 && it->second->state_printable <= 2) {
|
if (obj && obj->is_online() && !obj->can_abort() && !obj->is_in_upgrading() && it->second->get_state_selected() == 1 && it->second->state_printable <= 2) {
|
||||||
|
|
||||||
if (!it->second->is_blocking_printing(obj)) {
|
if (!wxGetApp().is_blocking_printing(obj)) {
|
||||||
PrintParams params = request_params(obj);
|
PrintParams params = request_params(obj);
|
||||||
print_params.push_back(params);
|
print_params.push_back(params);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1277,7 +1277,7 @@ void SendToPrinterDialog::update_show_status()
|
|||||||
reset_timeout();
|
reset_timeout();
|
||||||
|
|
||||||
// reading done
|
// reading done
|
||||||
if (is_blocking_printing(obj_)) {
|
if (wxGetApp().is_blocking_printing(obj_)) {
|
||||||
show_status(PrintDialogStatus::PrintStatusUnsupportedPrinter);
|
show_status(PrintDialogStatus::PrintStatusUnsupportedPrinter);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1342,16 +1342,6 @@ void SendToPrinterDialog::update_show_status()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SendToPrinterDialog::is_blocking_printing(MachineObject* obj_)
|
|
||||||
{
|
|
||||||
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
|
||||||
if (!dev) return true;
|
|
||||||
|
|
||||||
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
|
||||||
auto source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
|
||||||
return !DevPrinterConfigUtil::is_printer_model_compatible(source_model, *obj_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SendToPrinterDialog::Enable_Refresh_Button(bool en)
|
void SendToPrinterDialog::Enable_Refresh_Button(bool en)
|
||||||
{
|
{
|
||||||
if (!en) {
|
if (!en) {
|
||||||
|
|||||||
@@ -181,7 +181,6 @@ public:
|
|||||||
void reset_timeout();
|
void reset_timeout();
|
||||||
void update_user_printer();
|
void update_user_printer();
|
||||||
void update_show_status();
|
void update_show_status();
|
||||||
bool is_blocking_printing(MachineObject* obj_);
|
|
||||||
void prepare(int print_plate_idx);
|
void prepare(int print_plate_idx);
|
||||||
void check_focus(wxWindow* window);
|
void check_focus(wxWindow* window);
|
||||||
void check_fcous_state(wxWindow* window);
|
void check_fcous_state(wxWindow* window);
|
||||||
|
|||||||
@@ -1742,6 +1742,8 @@ void SyncAmsInfoDialog::show_status(PrintDialogStatus status, std::vector<wxStri
|
|||||||
update_print_status_msg(msg_text, true, true);
|
update_print_status_msg(msg_text, true, true);
|
||||||
} else if (status == PrintDialogStatus::PrintStatusAmsMappingSuccess) {
|
} else if (status == PrintDialogStatus::PrintStatusAmsMappingSuccess) {
|
||||||
update_print_status_msg(wxEmptyString, false, false);
|
update_print_status_msg(wxEmptyString, false, false);
|
||||||
|
} else if (status == PrintDialogStatus::PrintStatusOptionalPrinterModel) {
|
||||||
|
update_print_status_msg(PrePrintChecker::get_pre_state_msg(PrintDialogStatus::PrintStatusOptionalPrinterModel), true, true);
|
||||||
} else if (status == PrintDialogStatus::PrintStatusAmsMappingInvalid) {
|
} else if (status == PrintDialogStatus::PrintStatusAmsMappingInvalid) {
|
||||||
update_print_status_msg(wxEmptyString, true, false);
|
update_print_status_msg(wxEmptyString, true, false);
|
||||||
} else if (status == PrintDialogStatus::PrintStatusAmsMappingMixInvalid) {
|
} else if (status == PrintDialogStatus::PrintStatusAmsMappingMixInvalid) {
|
||||||
@@ -1861,19 +1863,13 @@ void SyncAmsInfoDialog::on_cancel(wxCloseEvent &event)
|
|||||||
|
|
||||||
bool SyncAmsInfoDialog::is_blocking_printing(MachineObject *obj_)
|
bool SyncAmsInfoDialog::is_blocking_printing(MachineObject *obj_)
|
||||||
{
|
{
|
||||||
DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
if (m_print_type == PrintFromType::FROM_NORMAL)
|
||||||
if (!dev) return true;
|
return wxGetApp().is_blocking_printing(obj_);
|
||||||
std::string source_model = "";
|
|
||||||
|
|
||||||
if (m_print_type == PrintFromType::FROM_NORMAL) {
|
std::string source_model;
|
||||||
PresetBundle *preset_bundle = wxGetApp().preset_bundle;
|
if (m_print_type == PrintFromType::FROM_SDCARD_VIEW && !m_required_data_plate_data_list.empty())
|
||||||
source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
source_model = m_required_data_plate_data_list[m_print_plate_idx]->printer_model_id;
|
||||||
|
return wxGetApp().is_blocking_printing(obj_, source_model);
|
||||||
} else if (m_print_type == PrintFromType::FROM_SDCARD_VIEW) {
|
|
||||||
if (m_required_data_plate_data_list.size() > 0) { source_model = m_required_data_plate_data_list[m_print_plate_idx]->printer_model_id; }
|
|
||||||
}
|
|
||||||
|
|
||||||
return !DevPrinterConfigUtil::is_printer_model_compatible(source_model, *obj_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SyncAmsInfoDialog::is_same_nozzle_type(std::string &filament_type, NozzleType &tag_nozzle_type)
|
bool SyncAmsInfoDialog::is_same_nozzle_type(std::string &filament_type, NozzleType &tag_nozzle_type)
|
||||||
@@ -2263,6 +2259,18 @@ void SyncAmsInfoDialog::update_show_status()
|
|||||||
|
|
||||||
reset_timeout();
|
reset_timeout();
|
||||||
|
|
||||||
|
bool has_optional_printer_model = DevPrinterConfigUtil::is_optional_printer_model_id(obj_->printer_type);
|
||||||
|
if (m_print_type == PrintFromType::FROM_NORMAL) {
|
||||||
|
if (PresetBundle *preset_bundle = wxGetApp().preset_bundle) {
|
||||||
|
has_optional_printer_model = has_optional_printer_model ||
|
||||||
|
DevPrinterConfigUtil::is_optional_printer_model_id(
|
||||||
|
preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle));
|
||||||
|
}
|
||||||
|
} else if (m_print_type == PrintFromType::FROM_SDCARD_VIEW && !m_required_data_plate_data_list.empty()) {
|
||||||
|
has_optional_printer_model = has_optional_printer_model ||
|
||||||
|
DevPrinterConfigUtil::is_optional_printer_model_id(m_required_data_plate_data_list[m_print_plate_idx]->printer_model_id);
|
||||||
|
}
|
||||||
|
|
||||||
if (!obj_->GetConfig()->SupportPrintAllPlates() && m_print_plate_idx == PLATE_ALL_IDX) {
|
if (!obj_->GetConfig()->SupportPrintAllPlates() && m_print_plate_idx == PLATE_ALL_IDX) {
|
||||||
show_status(PrintDialogStatus::PrintStatusNotSupportedPrintAll);
|
show_status(PrintDialogStatus::PrintStatusNotSupportedPrintAll);
|
||||||
return;
|
return;
|
||||||
@@ -2356,6 +2364,9 @@ void SyncAmsInfoDialog::update_show_status()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (has_optional_printer_model)
|
||||||
|
show_status(PrintDialogStatus::PrintStatusOptionalPrinterModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SyncAmsInfoDialog::has_timelapse_warning()
|
bool SyncAmsInfoDialog::has_timelapse_warning()
|
||||||
|
|||||||
@@ -4,13 +4,23 @@
|
|||||||
|
|
||||||
namespace Slic3r { namespace GUI {
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
WebMediaController::WebMediaController(wxWebView* webview) : m_webview(webview)
|
namespace {
|
||||||
|
|
||||||
|
void initialize_webview(wxWebView* webview)
|
||||||
{
|
{
|
||||||
if (!m_webview)
|
if (!webview)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_webview->SetBackgroundColour(*wxBLACK);
|
webview->SetBackgroundColour(*wxBLACK);
|
||||||
m_webview->SetPage("<html><head><style>html,body{margin:0;height:100%;background:#000;}</style></head><body></body></html>", "");
|
webview->SetPage("<html><head><style>html,body{margin:0;height:100%;background:#000;}</style></head><body></body></html>", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
WebMediaController::WebMediaController(wxWebView* webview)
|
||||||
|
: m_webview(webview)
|
||||||
|
{
|
||||||
|
initialize_webview(m_webview);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebMediaController::Load(wxURI url)
|
void WebMediaController::Load(wxURI url)
|
||||||
@@ -71,6 +81,8 @@ void WebMediaController::Stop()
|
|||||||
if (m_webview) {
|
if (m_webview) {
|
||||||
m_webview->RunScript("if(typeof stopCameraRefresh==='function') stopCameraRefresh();");
|
m_webview->RunScript("if(typeof stopCameraRefresh==='function') stopCameraRefresh();");
|
||||||
m_webview->Stop();
|
m_webview->Stop();
|
||||||
|
m_webview->SetPage("", "about:blank");
|
||||||
|
m_webview->ClearHistory();
|
||||||
}
|
}
|
||||||
m_url.clear();
|
m_url.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public:
|
|||||||
void Stop() override;
|
void Stop() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxWebView* m_webview;
|
wxWebView* m_webview = nullptr;
|
||||||
std::string m_url;
|
std::string m_url;
|
||||||
CameraStreamMode m_stream_mode = CameraStreamMode::http;
|
CameraStreamMode m_stream_mode = CameraStreamMode::http;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -950,11 +950,11 @@ std::string NetworkAgent::get_user_selected_machine()
|
|||||||
|
|
||||||
int NetworkAgent::set_user_selected_machine(std::string dev_id)
|
int NetworkAgent::set_user_selected_machine(std::string dev_id)
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(info) << "NetworkAgent::set_user_selected_machine: dev_id=" << dev_id
|
BOOST_LOG_TRIVIAL(trace) << "NetworkAgent::set_user_selected_machine: dev_id=" << dev_id
|
||||||
<< " printer_agent=" << (m_printer_agent ? m_printer_agent->get_agent_info().id : "<null>");
|
<< " printer_agent=" << (m_printer_agent ? m_printer_agent->get_agent_info().id : "<null>");
|
||||||
if (m_printer_agent) {
|
if (m_printer_agent) {
|
||||||
const int result = m_printer_agent->set_user_selected_machine(dev_id);
|
const int result = m_printer_agent->set_user_selected_machine(dev_id);
|
||||||
BOOST_LOG_TRIVIAL(info) << "NetworkAgent::set_user_selected_machine: result=" << result;
|
BOOST_LOG_TRIVIAL(trace) << "NetworkAgent::set_user_selected_machine: result=" << result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
BOOST_LOG_TRIVIAL(warning) << "NetworkAgent::set_user_selected_machine: no printer agent";
|
BOOST_LOG_TRIVIAL(warning) << "NetworkAgent::set_user_selected_machine: no printer agent";
|
||||||
@@ -977,11 +977,11 @@ int NetworkAgent::stop_subscribe(std::string module)
|
|||||||
|
|
||||||
int NetworkAgent::add_subscribe(std::vector<std::string> dev_list)
|
int NetworkAgent::add_subscribe(std::vector<std::string> dev_list)
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(info) << "NetworkAgent::add_subscribe: count=" << dev_list.size()
|
BOOST_LOG_TRIVIAL(trace) << "NetworkAgent::add_subscribe: count=" << dev_list.size()
|
||||||
<< " printer_agent=" << (m_printer_agent ? m_printer_agent->get_agent_info().id : "<null>");
|
<< " printer_agent=" << (m_printer_agent ? m_printer_agent->get_agent_info().id : "<null>");
|
||||||
if (m_printer_agent) {
|
if (m_printer_agent) {
|
||||||
const int result = m_printer_agent->add_subscribe(std::move(dev_list));
|
const int result = m_printer_agent->add_subscribe(std::move(dev_list));
|
||||||
BOOST_LOG_TRIVIAL(info) << "NetworkAgent::add_subscribe: result=" << result;
|
BOOST_LOG_TRIVIAL(trace) << "NetworkAgent::add_subscribe: result=" << result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
BOOST_LOG_TRIVIAL(warning) << "NetworkAgent::add_subscribe: no printer agent";
|
BOOST_LOG_TRIVIAL(warning) << "NetworkAgent::add_subscribe: no printer agent";
|
||||||
@@ -990,11 +990,11 @@ int NetworkAgent::add_subscribe(std::vector<std::string> dev_list)
|
|||||||
|
|
||||||
int NetworkAgent::del_subscribe(std::vector<std::string> dev_list)
|
int NetworkAgent::del_subscribe(std::vector<std::string> dev_list)
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(info) << "NetworkAgent::del_subscribe: count=" << dev_list.size()
|
BOOST_LOG_TRIVIAL(trace) << "NetworkAgent::del_subscribe: count=" << dev_list.size()
|
||||||
<< " printer_agent=" << (m_printer_agent ? m_printer_agent->get_agent_info().id : "<null>");
|
<< " printer_agent=" << (m_printer_agent ? m_printer_agent->get_agent_info().id : "<null>");
|
||||||
if (m_printer_agent) {
|
if (m_printer_agent) {
|
||||||
const int result = m_printer_agent->del_subscribe(std::move(dev_list));
|
const int result = m_printer_agent->del_subscribe(std::move(dev_list));
|
||||||
BOOST_LOG_TRIVIAL(info) << "NetworkAgent::del_subscribe: result=" << result;
|
BOOST_LOG_TRIVIAL(trace) << "NetworkAgent::del_subscribe: result=" << result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
BOOST_LOG_TRIVIAL(warning) << "NetworkAgent::del_subscribe: no printer agent";
|
BOOST_LOG_TRIVIAL(warning) << "NetworkAgent::del_subscribe: no printer agent";
|
||||||
|
|||||||
+25
-19
@@ -25,6 +25,12 @@
|
|||||||
} ORCA_PY_AGENT_CATCH(name) \
|
} ORCA_PY_AGENT_CATCH(name) \
|
||||||
return printer_agent_failure<ret>()
|
return printer_agent_failure<ret>()
|
||||||
|
|
||||||
|
#define ORCA_PY_AGENT_OVERRIDE_DEFAULT(ret, name, ...) \
|
||||||
|
try { \
|
||||||
|
ORCA_PY_OVERRIDE_AUDITED([] {}, PYBIND11_OVERRIDE, ret, PrinterAgentPluginCapability, name, ##__VA_ARGS__); \
|
||||||
|
} ORCA_PY_AGENT_CATCH(name) \
|
||||||
|
return printer_agent_failure<ret>()
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
// NetworkAgent's no-agent answer: -1 for a status code, the empty value (false, "", none) otherwise.
|
// NetworkAgent's no-agent answer: -1 for a status code, the empty value (false, "", none) otherwise.
|
||||||
template<typename T> T printer_agent_failure()
|
template<typename T> T printer_agent_failure()
|
||||||
@@ -67,56 +73,56 @@ public:
|
|||||||
|
|
||||||
int command_ams_refresh_rfid(std::string dev_id, std::string tray_id, int sequence_id, bool lan_mode) override
|
int command_ams_refresh_rfid(std::string dev_id, std::string tray_id, int sequence_id, bool lan_mode) override
|
||||||
{
|
{
|
||||||
ORCA_PY_AGENT_OVERRIDE(int, command_ams_refresh_rfid, dev_id, tray_id, sequence_id, lan_mode);
|
ORCA_PY_AGENT_OVERRIDE_DEFAULT(int, command_ams_refresh_rfid, dev_id, tray_id, sequence_id, lan_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
int command_ams_calibrate(std::string dev_id, int ams_id, int sequence_id, bool lan_mode) override
|
int command_ams_calibrate(std::string dev_id, int ams_id, int sequence_id, bool lan_mode) override
|
||||||
{
|
{
|
||||||
ORCA_PY_AGENT_OVERRIDE(int, command_ams_calibrate, dev_id, ams_id, sequence_id, lan_mode);
|
ORCA_PY_AGENT_OVERRIDE_DEFAULT(int, command_ams_calibrate, dev_id, ams_id, sequence_id, lan_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
int command_ams_select_tray(std::string dev_id, std::string tray_id, int sequence_id, bool lan_mode) override
|
int command_ams_select_tray(std::string dev_id, std::string tray_id, int sequence_id, bool lan_mode) override
|
||||||
{
|
{
|
||||||
ORCA_PY_AGENT_OVERRIDE(int, command_ams_select_tray, dev_id, tray_id, sequence_id, lan_mode);
|
ORCA_PY_AGENT_OVERRIDE_DEFAULT(int, command_ams_select_tray, dev_id, tray_id, sequence_id, lan_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
int command_start_camera(std::string dev_id) override
|
int command_start_camera(std::string dev_id) override
|
||||||
{
|
{
|
||||||
ORCA_PY_AGENT_OVERRIDE(int, command_start_camera, dev_id);
|
ORCA_PY_AGENT_OVERRIDE_DEFAULT(int, command_start_camera, dev_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
int command_xyz_abs(std::string dev_id, int sequence_id, bool lan_mode) override
|
int command_xyz_abs(std::string dev_id, int sequence_id, bool lan_mode) override
|
||||||
{
|
{
|
||||||
ORCA_PY_AGENT_OVERRIDE(int, command_xyz_abs, dev_id, sequence_id, lan_mode);
|
ORCA_PY_AGENT_OVERRIDE_DEFAULT(int, command_xyz_abs, dev_id, sequence_id, lan_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
int command_auto_leveling(std::string dev_id, int sequence_id, bool lan_mode) override
|
int command_auto_leveling(std::string dev_id, int sequence_id, bool lan_mode) override
|
||||||
{
|
{
|
||||||
ORCA_PY_AGENT_OVERRIDE(int, command_auto_leveling, dev_id, sequence_id, lan_mode);
|
ORCA_PY_AGENT_OVERRIDE_DEFAULT(int, command_auto_leveling, dev_id, sequence_id, lan_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
int command_go_home(std::string dev_id, bool is_printing, bool supports_mqtt_homing,
|
int command_go_home(std::string dev_id, bool is_printing, bool supports_mqtt_homing,
|
||||||
int sequence_id, bool lan_mode) override
|
int sequence_id, bool lan_mode) override
|
||||||
{
|
{
|
||||||
ORCA_PY_AGENT_OVERRIDE(int, command_go_home, dev_id, is_printing, supports_mqtt_homing, sequence_id, lan_mode);
|
ORCA_PY_AGENT_OVERRIDE_DEFAULT(int, command_go_home, dev_id, is_printing, supports_mqtt_homing, sequence_id, lan_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
int command_set_bed(std::string dev_id, int temp, bool supports_mqtt_bed_ctrl,
|
int command_set_bed(std::string dev_id, int temp, bool supports_mqtt_bed_ctrl,
|
||||||
int sequence_id, bool lan_mode) override
|
int sequence_id, bool lan_mode) override
|
||||||
{
|
{
|
||||||
ORCA_PY_AGENT_OVERRIDE(int, command_set_bed, dev_id, temp, supports_mqtt_bed_ctrl, sequence_id, lan_mode);
|
ORCA_PY_AGENT_OVERRIDE_DEFAULT(int, command_set_bed, dev_id, temp, supports_mqtt_bed_ctrl, sequence_id, lan_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
int command_set_nozzle(std::string dev_id, int temp, int sequence_id, bool lan_mode) override
|
int command_set_nozzle(std::string dev_id, int temp, int sequence_id, bool lan_mode) override
|
||||||
{
|
{
|
||||||
ORCA_PY_AGENT_OVERRIDE(int, command_set_nozzle, dev_id, temp, sequence_id, lan_mode);
|
ORCA_PY_AGENT_OVERRIDE_DEFAULT(int, command_set_nozzle, dev_id, temp, sequence_id, lan_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
int command_axis_control(std::string dev_id, std::string axis, double unit, double input_val,
|
int command_axis_control(std::string dev_id, std::string axis, double unit, double input_val,
|
||||||
int speed, bool is_core_xy, bool supports_mqtt_axis_control,
|
int speed, bool is_core_xy, bool supports_mqtt_axis_control,
|
||||||
int sequence_id, bool lan_mode) override
|
int sequence_id, bool lan_mode) override
|
||||||
{
|
{
|
||||||
ORCA_PY_AGENT_OVERRIDE(int, command_axis_control, dev_id, axis, unit, input_val, speed,
|
ORCA_PY_AGENT_OVERRIDE_DEFAULT(int, command_axis_control, dev_id, axis, unit, input_val, speed,
|
||||||
is_core_xy, supports_mqtt_axis_control, sequence_id, lan_mode);
|
is_core_xy, supports_mqtt_axis_control, sequence_id, lan_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,22 +159,22 @@ public:
|
|||||||
|
|
||||||
FilamentSyncMode get_filament_sync_mode() const override
|
FilamentSyncMode get_filament_sync_mode() const override
|
||||||
{
|
{
|
||||||
ORCA_PY_AGENT_OVERRIDE(FilamentSyncMode, get_filament_sync_mode);
|
ORCA_PY_AGENT_OVERRIDE_DEFAULT(FilamentSyncMode, get_filament_sync_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
CameraStreamMode get_camera_stream_mode() const override
|
CameraStreamMode get_camera_stream_mode() const override
|
||||||
{
|
{
|
||||||
ORCA_PY_AGENT_OVERRIDE(CameraStreamMode, get_camera_stream_mode);
|
ORCA_PY_AGENT_OVERRIDE_DEFAULT(CameraStreamMode, get_camera_stream_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get_camera_url() const override
|
std::string get_camera_url() const override
|
||||||
{
|
{
|
||||||
ORCA_PY_AGENT_OVERRIDE(std::string, get_camera_url);
|
ORCA_PY_AGENT_OVERRIDE_DEFAULT(std::string, get_camera_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fetch_filament_info(std::string dev_id, FilamentSyncMode sync_mode) override
|
bool fetch_filament_info(std::string dev_id, FilamentSyncMode sync_mode) override
|
||||||
{
|
{
|
||||||
ORCA_PY_AGENT_OVERRIDE(bool, fetch_filament_info, dev_id, sync_mode);
|
ORCA_PY_AGENT_OVERRIDE_DEFAULT(bool, fetch_filament_info, dev_id, sync_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
int check_cert() override
|
int check_cert() override
|
||||||
@@ -178,7 +184,7 @@ public:
|
|||||||
|
|
||||||
void install_device_cert(std::string dev_id, bool lan_only) override
|
void install_device_cert(std::string dev_id, bool lan_only) override
|
||||||
{
|
{
|
||||||
ORCA_PY_AGENT_OVERRIDE(void, install_device_cert, dev_id, lan_only);
|
ORCA_PY_AGENT_OVERRIDE_DEFAULT(void, install_device_cert, dev_id, lan_only);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ping_bind(std::string ping_code) override
|
int ping_bind(std::string ping_code) override
|
||||||
@@ -213,7 +219,7 @@ public:
|
|||||||
|
|
||||||
int get_hms_snapshot(std::string dev_id, std::string file_name, std::function<void(std::string, int)> callback) override
|
int get_hms_snapshot(std::string dev_id, std::string file_name, std::function<void(std::string, int)> callback) override
|
||||||
{
|
{
|
||||||
ORCA_PY_AGENT_OVERRIDE(int, get_hms_snapshot, dev_id, file_name, callback);
|
ORCA_PY_AGENT_OVERRIDE_DEFAULT(int, get_hms_snapshot, dev_id, file_name, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
int set_server_callback(OnServerErrFn fn) override
|
int set_server_callback(OnServerErrFn fn) override
|
||||||
@@ -264,8 +270,8 @@ public:
|
|||||||
// request_bind_ticket returns its ticket through a std::string* out-param, which pybind11
|
// request_bind_ticket returns its ticket through a std::string* out-param, which pybind11
|
||||||
// cannot marshal back through a plain override. We dispatch manually: the Python plugin
|
// cannot marshal back through a plain override. We dispatch manually: the Python plugin
|
||||||
// returns a (result, ticket) tuple, which we unpack into the int result and the out-param.
|
// returns a (result, ticket) tuple, which we unpack into the int result and the out-param.
|
||||||
// Not required to be implemented, so a missing override falls back to the base default
|
// Not required to be implemented, so a missing override answers with the same failure value
|
||||||
// instead of failing, mirroring what PYBIND11_OVERRIDE does for the other optional methods.
|
// as the other printer-agent operations. Leave the out-param untouched on failure.
|
||||||
int request_bind_ticket(std::string* ticket) override
|
int request_bind_ticket(std::string* ticket) override
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@@ -277,7 +283,7 @@ public:
|
|||||||
pybind11::function override =
|
pybind11::function override =
|
||||||
pybind11::get_override(static_cast<const PrinterAgentPluginCapability*>(this), "request_bind_ticket");
|
pybind11::get_override(static_cast<const PrinterAgentPluginCapability*>(this), "request_bind_ticket");
|
||||||
if (!override)
|
if (!override)
|
||||||
return PrinterAgentPluginCapability::request_bind_ticket(ticket);
|
return printer_agent_failure<int>();
|
||||||
try {
|
try {
|
||||||
pybind11::tuple result = override().cast<pybind11::tuple>();
|
pybind11::tuple result = override().cast<pybind11::tuple>();
|
||||||
if (ticket)
|
if (ticket)
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ add_executable(${_TEST_NAME}_tests
|
|||||||
test_dev_mapping.cpp
|
test_dev_mapping.cpp
|
||||||
test_filament_bitmap_utils.cpp
|
test_filament_bitmap_utils.cpp
|
||||||
test_device_progress.cpp
|
test_device_progress.cpp
|
||||||
|
test_device_manager_integration.cpp
|
||||||
|
test_web_media_controller.cpp
|
||||||
test_network_versions.cpp
|
test_network_versions.cpp
|
||||||
test_action_source.cpp
|
test_action_source.cpp
|
||||||
test_plugin_host_api.cpp
|
test_plugin_host_api.cpp
|
||||||
|
|||||||
@@ -0,0 +1,159 @@
|
|||||||
|
#include <catch2/catch_all.hpp>
|
||||||
|
|
||||||
|
#include <slic3r/GUI/DeviceCore/DevManager.h>
|
||||||
|
#include <slic3r/GUI/DeviceManager.hpp>
|
||||||
|
#include <libslic3r/AppConfig.hpp>
|
||||||
|
#include <slic3r/Utils/NetworkAgent.hpp>
|
||||||
|
#include <slic3r/Utils/OrcaCloudServiceAgent.hpp>
|
||||||
|
#include <slic3r/Utils/OrcaPrinterAgent.hpp>
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
using namespace Slic3r;
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class StubCloudAgent final : public OrcaCloudServiceAgent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StubCloudAgent() : OrcaCloudServiceAgent("") {}
|
||||||
|
|
||||||
|
int get_user_print_info(unsigned int* http_code, std::string* http_body) override
|
||||||
|
{
|
||||||
|
if (http_code)
|
||||||
|
*http_code = 200;
|
||||||
|
if (http_body)
|
||||||
|
*http_body = R"({"devices":[]})";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string get_user_name() override { return "integration-test-user"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class TestPrinterAgent final : public OrcaPrinterAgent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit TestPrinterAgent(std::string id)
|
||||||
|
: OrcaPrinterAgent(""), m_info{std::move(id), "Integration Test Agent", "1.0", "test agent"}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AgentInfo get_agent_info() override { return m_info; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
AgentInfo m_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ScopedAppConfig
|
||||||
|
{
|
||||||
|
AppConfig config;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string machine_list_response(const std::string& provider, const std::string& agent_id,
|
||||||
|
std::uint64_t generation, const std::string& name)
|
||||||
|
{
|
||||||
|
json machine;
|
||||||
|
machine["dev_id"] = "integration-device";
|
||||||
|
machine["dev_name"] = name;
|
||||||
|
machine["dev_online"] = true;
|
||||||
|
machine["task_status"] = "idle";
|
||||||
|
|
||||||
|
json response;
|
||||||
|
response["provider"] = provider;
|
||||||
|
response["agent_id"] = agent_id;
|
||||||
|
response["generation"] = generation;
|
||||||
|
response["devices"] = json::array({machine});
|
||||||
|
return response.dump();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST_CASE("Network agent stamps user-machine responses with request context", "[DeviceManager][integration]")
|
||||||
|
{
|
||||||
|
auto cloud = std::make_shared<StubCloudAgent>();
|
||||||
|
NetworkAgent network(cloud, nullptr);
|
||||||
|
network.set_printer_agent(std::make_shared<TestPrinterAgent>("integration-agent-a"));
|
||||||
|
|
||||||
|
const std::uint64_t generation_before = network.get_user_machine_list_generation();
|
||||||
|
unsigned int http_code = 0;
|
||||||
|
std::string body;
|
||||||
|
REQUIRE(network.get_user_print_info(&http_code, &body, ORCA_CLOUD_PROVIDER) == 0);
|
||||||
|
|
||||||
|
const json response = json::parse(body);
|
||||||
|
CHECK(http_code == 200);
|
||||||
|
CHECK(response["provider"] == ORCA_CLOUD_PROVIDER);
|
||||||
|
CHECK(response["agent_id"] == "integration-agent-a");
|
||||||
|
CHECK(response["generation"] == generation_before + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Device manager ignores stale cloud machine responses", "[DeviceManager][integration]")
|
||||||
|
{
|
||||||
|
ScopedAppConfig app_config;
|
||||||
|
NetworkAgent network(nullptr, std::make_shared<TestPrinterAgent>("integration-agent"));
|
||||||
|
network.set_printer_agent(std::make_shared<TestPrinterAgent>("integration-agent"));
|
||||||
|
DeviceManager manager(&network, false, &app_config.config);
|
||||||
|
|
||||||
|
const std::uint64_t current_generation = network.get_user_machine_list_generation();
|
||||||
|
manager.parse_user_print_info(machine_list_response(ORCA_CLOUD_PROVIDER, "integration-agent",
|
||||||
|
current_generation, "Fresh name"));
|
||||||
|
|
||||||
|
auto machines = manager.get_user_machinelist();
|
||||||
|
REQUIRE(machines.size() == 1);
|
||||||
|
REQUIRE(machines.at("integration-device") != nullptr);
|
||||||
|
CHECK(machines.at("integration-device")->get_dev_name() == "Fresh name");
|
||||||
|
|
||||||
|
manager.parse_user_print_info(machine_list_response(BBL_CLOUD_PROVIDER, "integration-agent",
|
||||||
|
current_generation, "Stale provider"));
|
||||||
|
manager.parse_user_print_info(machine_list_response(ORCA_CLOUD_PROVIDER, "other-agent",
|
||||||
|
current_generation, "Stale agent"));
|
||||||
|
manager.parse_user_print_info(machine_list_response(ORCA_CLOUD_PROVIDER, "integration-agent",
|
||||||
|
current_generation + 1, "Stale generation"));
|
||||||
|
|
||||||
|
machines = manager.get_user_machinelist();
|
||||||
|
REQUIRE(machines.size() == 1);
|
||||||
|
CHECK(machines.at("integration-device")->get_dev_name() == "Fresh name");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Device manager filters and rehomes devices by printer-agent ownership", "[DeviceManager][integration]")
|
||||||
|
{
|
||||||
|
ScopedAppConfig app_config;
|
||||||
|
auto agent_a = std::make_shared<TestPrinterAgent>("integration-agent-a");
|
||||||
|
auto agent_b = std::make_shared<TestPrinterAgent>("integration-agent-b");
|
||||||
|
NetworkAgent network(nullptr, agent_a);
|
||||||
|
DeviceManager manager(&network, false, &app_config.config);
|
||||||
|
|
||||||
|
BBLocalMachine machine;
|
||||||
|
machine.dev_id = "integration-lan-device";
|
||||||
|
machine.dev_name = "Integration LAN device";
|
||||||
|
machine.dev_ip = "192.0.2.10";
|
||||||
|
machine.printer_type = "C11";
|
||||||
|
|
||||||
|
MachineObject* object = manager.insert_local_device(machine, "lan", "free", "", "access-code");
|
||||||
|
REQUIRE(object != nullptr);
|
||||||
|
CHECK(object->printer_agent_id == "integration-agent-a");
|
||||||
|
CHECK(manager.get_my_machine_list("integration-agent-a").count(machine.dev_id) == 1);
|
||||||
|
CHECK(manager.get_my_machine_list("integration-agent-b").empty());
|
||||||
|
|
||||||
|
network.set_printer_agent(agent_b);
|
||||||
|
CHECK(manager.get_my_machine_list("integration-agent-b").empty());
|
||||||
|
|
||||||
|
manager.on_machine_alive(R"({
|
||||||
|
"dev_name":"Rediscovered device",
|
||||||
|
"dev_id":"integration-lan-device",
|
||||||
|
"dev_ip":"192.0.2.10",
|
||||||
|
"dev_type":"C11",
|
||||||
|
"dev_signal":"strong",
|
||||||
|
"connect_type":"lan",
|
||||||
|
"bind_state":"free"
|
||||||
|
})");
|
||||||
|
|
||||||
|
CHECK(object->printer_agent_id == "integration-agent-b");
|
||||||
|
CHECK(manager.get_my_machine_list("integration-agent-a").empty());
|
||||||
|
CHECK(manager.get_my_machine_list("integration-agent-b").count(machine.dev_id) == 1);
|
||||||
|
}
|
||||||
@@ -115,7 +115,7 @@ TEST_CASE("Malformed string progress leaves a fresh machine unchanged", "[Device
|
|||||||
MachineObject machine(nullptr, nullptr, "test", "test-device", "127.0.0.1");
|
MachineObject machine(nullptr, nullptr, "test", "test-device", "127.0.0.1");
|
||||||
REQUIRE(machine.subtask_ == nullptr);
|
REQUIRE(machine.subtask_ == nullptr);
|
||||||
|
|
||||||
CHECK_THROWS_AS(machine.update_print_progress(json("not-a-percent")), std::invalid_argument);
|
CHECK_NOTHROW(machine.update_print_progress(json("not-a-percent")));
|
||||||
CHECK(machine.mc_print_percent == 0);
|
CHECK(machine.mc_print_percent == 0);
|
||||||
CHECK(machine.subtask_ == nullptr);
|
CHECK(machine.subtask_ == nullptr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,6 +115,22 @@ TEST_CASE("A printer agent that omits its operations answers like a missing agen
|
|||||||
check_answers_like_no_agent(*agent);
|
check_answers_like_no_agent(*agent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("A printer agent uses IPrinterAgent defaults for omitted commands", "[PluginPrinterAgent][Python]")
|
||||||
|
{
|
||||||
|
ScopedPluginManager plugin_system;
|
||||||
|
if (!plugin_system.initialized)
|
||||||
|
SKIP("Bundled Python interpreter unavailable: " + PythonInterpreter::instance().last_error());
|
||||||
|
py::gil_scoped_acquire gil;
|
||||||
|
|
||||||
|
auto agent = make_agent(" def send_message(self, dev_id, json_str, qos, flag): return 7\n"
|
||||||
|
" def send_message_to_printer(self, dev_id, json_str, qos, flag): return 8\n");
|
||||||
|
REQUIRE(agent.agent);
|
||||||
|
|
||||||
|
CHECK(agent->command_xyz_abs("dev", 1, false) == 7);
|
||||||
|
CHECK(agent->command_set_nozzle("dev", 200, 2, true) == 8);
|
||||||
|
CHECK(agent->command_ams_refresh_rfid("dev", "tray", 3, false) == ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("A printer agent operation returning the wrong type answers like a missing agent", "[PluginPrinterAgent][Python]")
|
TEST_CASE("A printer agent operation returning the wrong type answers like a missing agent", "[PluginPrinterAgent][Python]")
|
||||||
{
|
{
|
||||||
ScopedPluginManager plugin_system;
|
ScopedPluginManager plugin_system;
|
||||||
|
|||||||
@@ -0,0 +1,113 @@
|
|||||||
|
#include <catch2/catch_all.hpp>
|
||||||
|
|
||||||
|
#include <slic3r/GUI/WebMediaController.hpp>
|
||||||
|
|
||||||
|
#include <wx/webview.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace Slic3r;
|
||||||
|
using namespace Slic3r::GUI;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class StubWebView final : public wxWebView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool SetBackgroundColour(const wxColour&) override
|
||||||
|
{
|
||||||
|
events.emplace_back("background");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Create(wxWindow*, wxWindowID, const wxString&, const wxPoint&, const wxSize&, long, const wxString&) override { return true; }
|
||||||
|
wxString GetCurrentTitle() const override { return {}; }
|
||||||
|
wxString GetCurrentURL() const override { return {}; }
|
||||||
|
bool IsBusy() const override { return false; }
|
||||||
|
bool IsEditable() const override { return false; }
|
||||||
|
void LoadURL(const wxString& url) override
|
||||||
|
{
|
||||||
|
events.emplace_back("url");
|
||||||
|
loaded_url = url.ToStdString();
|
||||||
|
}
|
||||||
|
void Print() override {}
|
||||||
|
void RegisterHandler(wxSharedPtr<wxWebViewHandler>) override {}
|
||||||
|
void Reload(wxWebViewReloadFlags) override {}
|
||||||
|
void SetEditable(bool) override {}
|
||||||
|
void Stop() override { events.emplace_back("stop"); }
|
||||||
|
bool CanGoBack() const override { return false; }
|
||||||
|
bool CanGoForward() const override { return false; }
|
||||||
|
void GoBack() override {}
|
||||||
|
void GoForward() override {}
|
||||||
|
void ClearHistory() override { events.emplace_back("history"); }
|
||||||
|
void EnableHistory(bool) override {}
|
||||||
|
wxVector<wxSharedPtr<wxWebViewHistoryItem>> GetBackwardHistory() override { return {}; }
|
||||||
|
wxVector<wxSharedPtr<wxWebViewHistoryItem>> GetForwardHistory() override { return {}; }
|
||||||
|
void LoadHistoryItem(wxSharedPtr<wxWebViewHistoryItem>) override {}
|
||||||
|
bool CanSetZoomType(wxWebViewZoomType) const override { return false; }
|
||||||
|
float GetZoomFactor() const override { return 1.0f; }
|
||||||
|
wxWebViewZoomType GetZoomType() const override { return wxWEBVIEW_ZOOM_TYPE_LAYOUT; }
|
||||||
|
void SetZoomFactor(float) override {}
|
||||||
|
void SetZoomType(wxWebViewZoomType) override {}
|
||||||
|
bool CanUndo() const override { return false; }
|
||||||
|
bool CanRedo() const override { return false; }
|
||||||
|
void Undo() override {}
|
||||||
|
void Redo() override {}
|
||||||
|
void* GetNativeBackend() const override { return nullptr; }
|
||||||
|
|
||||||
|
bool RunScript(const wxString& javascript, wxString*) const override
|
||||||
|
{
|
||||||
|
events.emplace_back("script");
|
||||||
|
script = javascript.ToStdString();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void DoSetPage(const wxString& html, const wxString& base_url) override
|
||||||
|
{
|
||||||
|
events.emplace_back("page");
|
||||||
|
page = html.ToStdString();
|
||||||
|
page_base = base_url.ToStdString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
mutable std::vector<std::string> events;
|
||||||
|
std::string page;
|
||||||
|
std::string page_base;
|
||||||
|
mutable std::string script;
|
||||||
|
std::string loaded_url;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST_CASE("Web media controller tears down a snapshot lifecycle", "[WebMediaController][integration]")
|
||||||
|
{
|
||||||
|
StubWebView view;
|
||||||
|
WebMediaController controller(&view);
|
||||||
|
|
||||||
|
controller.set_mode(CameraStreamMode::http_snapshot);
|
||||||
|
controller.Load(wxURI("http://camera.example/frame.jpg"));
|
||||||
|
controller.Play();
|
||||||
|
|
||||||
|
REQUIRE(view.events.size() == 3);
|
||||||
|
CHECK(view.events[0] == "background");
|
||||||
|
CHECK(view.events[1] == "page");
|
||||||
|
CHECK(view.events[2] == "page");
|
||||||
|
CHECK(view.page.find("stopCameraRefresh") != std::string::npos);
|
||||||
|
CHECK(view.page.find("http://camera.example/frame.jpg") != std::string::npos);
|
||||||
|
|
||||||
|
controller.Stop();
|
||||||
|
|
||||||
|
REQUIRE(view.events.size() == 7);
|
||||||
|
CHECK(view.events[3] == "script");
|
||||||
|
CHECK(view.events[4] == "stop");
|
||||||
|
CHECK(view.events[5] == "page");
|
||||||
|
CHECK(view.events[6] == "history");
|
||||||
|
CHECK(view.script == "if(typeof stopCameraRefresh==='function') stopCameraRefresh();");
|
||||||
|
CHECK(view.page.empty());
|
||||||
|
CHECK(view.page_base == "about:blank");
|
||||||
|
|
||||||
|
controller.Play();
|
||||||
|
CHECK(view.page.find("http://camera.example/frame.jpg") == std::string::npos);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user