NEW: print with emmc

jira: [STUDIO-14427]
Change-Id: I8b0c56ce1c2b7b90949b72c49acfdbb31c876df1
(cherry picked from commit 76e45bde2540ee418719e00b999c5fd724baec71)
This commit is contained in:
haolin.tian 2025-09-23 20:20:06 +08:00 committed by Noisyfox
parent d6e40352c2
commit aa75c444aa
8 changed files with 145 additions and 10 deletions

View file

@ -4986,6 +4986,18 @@ void MachineObject::parse_new_info(json print)
is_support_idelheadingprotect_detection = get_flag_bits(fun, 62);
}
/*fun2*/
std::string fun2;
if (print.contains("fun2") && print["fun2"].is_string()) {
fun2 = print["fun2"].get<std::string>();
BOOST_LOG_TRIVIAL(info) << "new print data fun2 = " << fun;
}
// fun2 may have infinite length, use get_flag_bits_no_border
if (!fun2.empty()) {
is_support_print_with_emmc = get_flag_bits_no_border(fun2, 0) == 1;
}
/*aux*/
std::string aux = print["aux"].get<std::string>();
@ -4993,7 +5005,6 @@ void MachineObject::parse_new_info(json print)
if (!aux.empty()) {
m_storage->set_sdcard_state(get_flag_bits(aux, 12, 2));
//sdcard_state = MachineObject::SdcardState(get_flag_bits(aux, 12, 2));
}
/*stat*/
@ -5036,6 +5047,10 @@ void MachineObject::parse_new_info(json print)
}
}
static bool is_hex_digit(char c) {
return std::isxdigit(static_cast<unsigned char>(c)) != 0;
}
int MachineObject::get_flag_bits(std::string str, int start, int count) const
{
try {
@ -5043,7 +5058,94 @@ int MachineObject::get_flag_bits(std::string str, int start, int count) const
unsigned long long mask = (1ULL << count) - 1;
int flag = (decimal_value >> start) & mask;
return flag;
} catch (...) {
}
catch (...) {
return 0;
}
}
uint32_t MachineObject::get_flag_bits_no_border(std::string str, int start_idx, int count) const
{
if (start_idx < 0 || count <= 0) return 0;
try {
// --- 1) trim ---
auto ltrim = [](std::string& s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
[](unsigned char ch) { return !std::isspace(ch); }));
};
auto rtrim = [](std::string& s) {
s.erase(std::find_if(s.rbegin(), s.rend(),
[](unsigned char ch) { return !std::isspace(ch); }).base(), s.end());
};
ltrim(str); rtrim(str);
// --- 2) remove 0x/0X prefix ---
if (str.size() >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
str.erase(0, 2);
}
// --- 3) keep only hex digits ---
std::string hex;
hex.reserve(str.size());
for (char c : str) {
if (std::isxdigit(static_cast<unsigned char>(c))) hex.push_back(c);
}
if (hex.empty()) return 0;
// --- 4) use size_t for all index/bit math ---
const size_t total_bits = hex.size() * 4ULL;
const size_t ustart = static_cast<size_t>(start_idx);
if (ustart >= total_bits) return 0;
const int int_bits = std::numeric_limits<uint32_t>::digits; // typically 32
const size_t need_bits = static_cast<size_t>(std::min(count, int_bits));
// [first_bit, last_bit]
const size_t first_bit = ustart;
const size_t last_bit = std::min(ustart + need_bits, total_bits) - 1ULL;
if (last_bit < first_bit) return 0;
const size_t right_index = hex.size() - 1ULL;
const size_t first_nibble = first_bit / 4ULL;
const size_t last_nibble = last_bit / 4ULL;
const size_t start_idx = right_index - last_nibble;
const size_t end_idx = right_index - first_nibble;
if (end_idx < start_idx) return 0;
const size_t sub_len = end_idx - start_idx + 1ULL;
if (end_idx >= hex.size()) return 0;
const std::string sub_hex = hex.substr(start_idx, sub_len);
unsigned long long chunk = std::stoull(sub_hex, nullptr, 16);
const unsigned nibble_offset = static_cast<unsigned>(first_bit % 4ULL);
const unsigned long long shifted =
(nibble_offset == 0U) ? chunk : (chunk >> nibble_offset);
uint32_t mask;
if (need_bits >= static_cast<size_t>(std::numeric_limits<uint32_t>::digits)) {
mask = std::numeric_limits<uint32_t>::max();
}
else {
mask = static_cast<uint32_t>((1ULL << need_bits) - 1ULL);
}
const uint32_t val = static_cast<uint32_t>(shifted & mask);
return val;
}
catch (const std::invalid_argument&) {
return 0;
}
catch (const std::out_of_range&) {
return 0;
}
catch (...) {
return 0;
}
}

View file

@ -605,6 +605,9 @@ public:
bool is_support_airprinting_detection{false};
bool is_support_idelheadingprotect_detection{false};
// fun2
bool is_support_print_with_emmc{false};
bool installed_upgrade_kit{false};
int bed_temperature_limit = -1;
@ -858,6 +861,7 @@ public:
bool check_enable_np(const json& print) const;
void parse_new_info(json print);
int get_flag_bits(std::string str, int start, int count = 1) const;
uint32_t get_flag_bits_no_border(std::string str, int start_idx, int count = 1) const;
int get_flag_bits(int num, int start, int count = 1, int base = 10) const;
/* Device Filament Check */

View file

@ -12,6 +12,8 @@
#include "slic3r/GUI/DeviceCore/DevManager.h"
#include "slic3r/GUI/DeviceCore/DevUtil.h"
#include "slic3r/Utils/FileTransferUtils.hpp"
namespace Slic3r {
namespace GUI {
@ -206,13 +208,26 @@ void PrintJob::process(Ctl &ctl)
// check access code and ip address
if (this->connection_type == "lan" && m_print_type == "from_normal") {
params.dev_id = m_dev_id;
params.project_name = "verify_job";
params.filename = job_data._temp_path.string();
params.connection_type = this->connection_type;
bool emmc_ok = false;
bool ftp_ok = false;
if (could_emmc_print) {
std::string devIP = m_dev_ip;
std::string accessCode = m_access_code;
std::string url = "bambu:///local/" + devIP + "?port=6000&user=" + "bblp" + "&passwd=" + accessCode;
std::unique_ptr<FileTransferTunnel> tunnel = std::make_unique<FileTransferTunnel>(module(), url);
emmc_ok = tunnel->sync_start_connect();
}
{
params.dev_id = m_dev_id;
params.project_name = "verify_job";
params.filename = job_data._temp_path.string();
params.connection_type = this->connection_type;
result = m_agent->start_send_gcode_to_sdcard(params, nullptr, nullptr, nullptr);
if (result != 0) {
result = m_agent->start_send_gcode_to_sdcard(params, nullptr, nullptr, nullptr);
ftp_ok = result == 0;
}
if (!emmc_ok && !ftp_ok) {
BOOST_LOG_TRIVIAL(error) << "access code is invalid";
m_enter_ip_address_fun_fail();
m_job_finished = true;
@ -563,7 +578,7 @@ void PrintJob::process(Ctl &ctl)
}
}
} else {
if (this->has_sdcard) {
if (this->has_sdcard || this->could_emmc_print) {
ctl.update_status(curr_percent, _u8L("Sending print job over LAN"));
result = m_agent->start_local_print(params, update_fn, cancel_fn);
} else {

View file

@ -82,6 +82,7 @@ public:
bool task_layer_inspect;
bool cloud_print_only { false };
bool has_sdcard { false };
bool could_emmc_print { false };
bool task_use_ams { true };
bool task_ext_change_assist { false };

View file

@ -2524,6 +2524,7 @@ void SelectMachineDialog::on_send_print()
}
m_print_job->has_sdcard = obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::HAS_SDCARD_NORMAL;
m_print_job->could_emmc_print = obj_->is_support_print_with_emmc;
bool timelapse_option = m_checkbox_list["timelapse"]->IsShown()?true:false;
@ -3322,7 +3323,8 @@ void SelectMachineDialog::update_show_status(MachineObject* obj_)
/*check sdcard when if lan mode printer*/
if (obj_->is_lan_mode_printer()) {
if (obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::NO_SDCARD) {
if (obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::NO_SDCARD
&& !obj_->is_support_print_with_emmc) {
show_status(PrintDialogStatus::PrintStatusLanModeNoSdcard);
return;
} else if (obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::HAS_SDCARD_ABNORMAL || obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::HAS_SDCARD_READONLY) {

View file

@ -1832,6 +1832,7 @@ void CalibUtils::send_to_print(const CalibInfo &calib_info, wxString &error_mess
print_job->set_calibration_task(true);
print_job->has_sdcard = obj_->GetStorage()->get_sdcard_state() == DevStorage::HAS_SDCARD_NORMAL;
print_job->could_emmc_print = obj_->is_support_print_with_emmc;
print_job->set_print_config(MachineBedTypeString[bed_type], true, false, false, false, true, false, 0, 0, 0);
print_job->set_print_job_finished_event(wxGetApp().plater()->get_send_calibration_finished_event(), print_job->m_project_name);
@ -1948,6 +1949,7 @@ void CalibUtils::send_to_print(const std::vector<CalibInfo> &calib_infos, wxStri
print_job->set_calibration_task(true);
print_job->has_sdcard = obj_->GetStorage()->get_sdcard_state() == DevStorage::HAS_SDCARD_NORMAL;
print_job->could_emmc_print = obj_->is_support_print_with_emmc;
print_job->set_print_config(MachineBedTypeString[bed_type], true, true, false, false, true, false, 0, 1, 0);
print_job->set_print_job_finished_event(wxGetApp().plater()->get_send_calibration_finished_event(), print_job->m_project_name);

View file

@ -19,6 +19,7 @@ FileTransferModule::FileTransferModule(ModuleHandle networking_module, int requi
ft_tunnel_retain = sym_lookup<fn_ft_tunnel_retain>(networking_, "ft_tunnel_retain");
ft_tunnel_release = sym_lookup<fn_ft_tunnel_release>(networking_, "ft_tunnel_release");
ft_tunnel_start_connect = sym_lookup<fn_ft_tunnel_start_connect>(networking_, "ft_tunnel_start_connect");
ft_tunnel_sync_connect = sym_lookup<fn_ft_tunnel_sync_connect>(networking_, "ft_tunnel_sync_connect");
ft_tunnel_set_status_cb = sym_lookup<fn_ft_tunnel_set_status_cb>(networking_, "ft_tunnel_set_status_cb");
ft_tunnel_shutdown = sym_lookup<fn_ft_tunnel_shutdown>(networking_, "ft_tunnel_shutdown");
@ -69,6 +70,11 @@ void FileTransferTunnel::start_connect()
if (m_->ft_tunnel_start_connect(h_, tramp, &conn_cb_) == ft_err::FT_EXCEPTION) { throw std::runtime_error("ft_tunnel_start_connect failed"); }
}
bool FileTransferTunnel::sync_start_connect()
{
return m_->ft_tunnel_sync_connect(h_) == FT_OK;
}
void FileTransferTunnel::on_connection(ConnectionCb cb) { conn_cb_ = std::move(cb); }
void FileTransferTunnel::on_status(TunnelStatusCb cb) { status_cb_ = std::move(cb); }

View file

@ -76,6 +76,7 @@ using fn_ft_tunnel_create = ft_err(FT_CALL *)(const char *url, FT_TunnelH
using fn_ft_tunnel_retain = void(FT_CALL *)(FT_TunnelHandle *);
using fn_ft_tunnel_release = void(FT_CALL *)(FT_TunnelHandle *);
using fn_ft_tunnel_start_connect = ft_err(FT_CALL *)(FT_TunnelHandle *, void(FT_CALL *)(void *user, int ok, int err, const char *msg), void *user);
using fn_ft_tunnel_sync_connect = ft_err(FT_CALL *)(FT_TunnelHandle *);
using fn_ft_tunnel_set_status_cb = ft_err(FT_CALL *)(FT_TunnelHandle *, void(FT_CALL *)(void *user, int old_status, int new_status, int err, const char *msg), void *user);
using fn_ft_tunnel_shutdown = ft_err(FT_CALL *)(FT_TunnelHandle *);
@ -107,6 +108,7 @@ struct FileTransferModule
fn_ft_tunnel_retain ft_tunnel_retain{};
fn_ft_tunnel_release ft_tunnel_release{};
fn_ft_tunnel_start_connect ft_tunnel_start_connect{};
fn_ft_tunnel_sync_connect ft_tunnel_sync_connect{};
fn_ft_tunnel_set_status_cb ft_tunnel_set_status_cb{};
fn_ft_tunnel_shutdown ft_tunnel_shutdown{};
@ -146,6 +148,7 @@ public:
FileTransferTunnel &operator=(FileTransferTunnel &&) = delete;
void start_connect();
bool sync_start_connect();
void on_connection(ConnectionCb cb);
void on_status(TunnelStatusCb cb);