mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-05-15 01:22:07 +00:00
NEW: support send to sd card with cloud
JIRA: STUDIO-7378 Change-Id: I95fee50db29825e508d276d52c7a3e85e1347ebd (cherry picked from commit 13db95ceb4f18b8cbce1e67447eeaa6ee36cc8ad)
This commit is contained in:
@@ -39,18 +39,30 @@ wxDEFINE_EVENT(EVT_FILE_CHANGED, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_SELECT_CHANGED, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_THUMBNAIL, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_DOWNLOAD, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_MEDIA_ABILITY_CHANGED, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_UPLOADING, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_UPLOAD_CHANGED, wxCommandEvent);
|
||||
|
||||
wxDEFINE_EVENT(EVT_FILE_CALLBACK, wxCommandEvent);
|
||||
|
||||
static wxBitmap default_thumbnail;
|
||||
|
||||
static std::map<int, std::string> error_messages = {
|
||||
{PrinterFileSystem::ERROR_PIPE, L("Reconnecting the printer, the operation cannot be completed immediately, please try again later.")},
|
||||
{PrinterFileSystem::ERROR_RES_BUSY, L("The device cannot handle more conversations. Please retry later.")},
|
||||
{PrinterFileSystem::FILE_NO_EXIST, L("File does not exist.")},
|
||||
{PrinterFileSystem::FILE_CHECK_ERR, L("File checksum error. Please retry.")},
|
||||
{PrinterFileSystem::FILE_TYPE_ERR, L("Not supported on the current printer version.")},
|
||||
{PrinterFileSystem::STORAGE_UNAVAILABLE, L("Storage unavailable, insert SD card.")}
|
||||
{PrinterFileSystem::ERROR_PIPE, L("Reconnecting the printer, the operation cannot be completed immediately, please try again later.")},
|
||||
{PrinterFileSystem::ERROR_RES_BUSY, L("The device cannot handle more conversations. Please retry later.")},
|
||||
{PrinterFileSystem::ERROR_TIME_OUT, L("Timeout, please try again.")},
|
||||
{PrinterFileSystem::FILE_NO_EXIST, L("File does not exist.")},
|
||||
{PrinterFileSystem::FILE_CHECK_ERR, L("File checksum error. Please retry.")},
|
||||
{PrinterFileSystem::FILE_TYPE_ERR, L("Not supported on the current printer version.")},
|
||||
{PrinterFileSystem::STORAGE_UNAVAILABLE, L("Please check if the SD card is inserted into the printer.\nIf it still cannot be read, you can try formatting the SD card.")},
|
||||
{PrinterFileSystem::API_VERSION_UNSUPPORT, L("The firmware version of the printer is too low. Please update the firmware and try again.")},
|
||||
{PrinterFileSystem::FILE_EXIST, L("The file already exists, do you want to replace it?")},
|
||||
{PrinterFileSystem::STORAGE_SPACE_NOT_ENOUGH, L("Insufficient storage space, please clear the space and try again.")},
|
||||
{PrinterFileSystem::FILE_CREATE_ERR, L("File creation failed, please try again.")},
|
||||
{PrinterFileSystem::FILE_WRITE_ERR, L("File write failed, please try again.")},
|
||||
{PrinterFileSystem::MD5_COMPARE_ERR, L("MD5 verification failed, please try again.")},
|
||||
{PrinterFileSystem::FILE_RENAME_ERR, L("File renaming failed, please try again.")},
|
||||
{PrinterFileSystem::SEND_ERR, L("File upload failed, please try again.")}
|
||||
};
|
||||
|
||||
struct StaticBambuLib : BambuLib {
|
||||
@@ -117,7 +129,6 @@ void PrinterFileSystem::SetFileType(FileType type, std::string const &storage)
|
||||
return;
|
||||
m_status = Status::ListSyncing;
|
||||
SendChangedEvent(EVT_STATUS_CHANGED, m_status);
|
||||
ListAllFiles();
|
||||
}
|
||||
|
||||
void PrinterFileSystem::SetGroupMode(GroupMode mode)
|
||||
@@ -248,6 +259,14 @@ struct PrinterFileSystem::Download : Progress
|
||||
boost::uuids::detail::md5 boost_md5;
|
||||
};
|
||||
|
||||
struct PrinterFileSystem::Upload : Progress
|
||||
{
|
||||
std::string error;
|
||||
boost::uint32_t frag_id{0};
|
||||
MD5_CTX ctx;
|
||||
boost::filesystem::ifstream ifs;
|
||||
};
|
||||
|
||||
void PrinterFileSystem::DownloadFiles(size_t index, std::string const &path)
|
||||
{
|
||||
if (index == (size_t) -1) {
|
||||
@@ -524,6 +543,16 @@ void PrinterFileSystem::Stop(bool quit)
|
||||
m_cond.notify_all();
|
||||
}
|
||||
|
||||
void PrinterFileSystem::SetUploadFile(const std::string &path, const std::string &name, const std::string &select_storage)
|
||||
{
|
||||
if (!m_upload_file) {
|
||||
m_upload_file = std::make_unique<UploadFile>();
|
||||
}
|
||||
m_upload_file->path = path;
|
||||
m_upload_file->name = name;
|
||||
m_upload_file->select_storage = select_storage;
|
||||
}
|
||||
|
||||
void PrinterFileSystem::BuildGroups()
|
||||
{
|
||||
m_group_year.clear();
|
||||
@@ -1030,6 +1059,194 @@ void PrinterFileSystem::DumpLog(void * thiz, int, tchar const *msg)
|
||||
static_cast<PrinterFileSystem*>(thiz)->Bambu_FreeLogMsg(msg);
|
||||
}
|
||||
|
||||
boost::uint32_t PrinterFileSystem::RequestMediaAbility(int api_version)
|
||||
{
|
||||
json req;
|
||||
req["peer"] = "studio";
|
||||
req["api_version"] = api_version;
|
||||
|
||||
return SendRequest<MediaAbilityList>(
|
||||
REQUEST_MEDIA_ABILITY, req, [this](const json &resp, MediaAbilityList &list, auto) -> int {
|
||||
json abliity_list = resp["storage"];
|
||||
list = abliity_list.get<MediaAbilityList>();
|
||||
return 0;
|
||||
},
|
||||
[this](int result, MediaAbilityList list){
|
||||
if (result != 0) {
|
||||
m_last_error = result;
|
||||
m_media_ability_list.clear();
|
||||
SendChangedEvent(EVT_MEDIA_ABILITY_CHANGED, RequestMediaAbilityStatus::S_FAILED, "", m_last_error);
|
||||
return result;
|
||||
}
|
||||
|
||||
m_media_ability_list.swap(list);
|
||||
SendChangedEvent(EVT_MEDIA_ABILITY_CHANGED, RequestMediaAbilityStatus::S_SUCCESS);
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
void PrinterFileSystem::RequestUploadFile()
|
||||
{
|
||||
json req;
|
||||
req["type"] = "model";
|
||||
req["storage"] = m_upload_file->select_storage;
|
||||
req["path"] = m_upload_file->name;
|
||||
|
||||
m_upload_file->upload = std::make_unique<Upload>();
|
||||
boost::filesystem::path path = boost::filesystem::path(m_upload_file->path);
|
||||
boost::system::error_code ec;
|
||||
boost::uint32_t file_size = boost::filesystem::file_size(path, ec);
|
||||
|
||||
req["total"] = file_size;
|
||||
m_upload_file->size = file_size;
|
||||
m_upload_file->upload->total = file_size;
|
||||
|
||||
m_upload_seq = SendRequest(
|
||||
FILE_UPLOAD, req,
|
||||
[this](int result, const json& resp, auto) -> int{
|
||||
if (result != SUCCESS && result != CONTINUE && result != FILE_EXIST) {
|
||||
std::string error_msg = "";
|
||||
if (result == ERROR_CANCEL) {
|
||||
error_msg = L("User cancels task.");
|
||||
} else if (result == FILE_READ_WRITE_ERR || result == FILE_OPEN_ERR) {
|
||||
error_msg = L("Failed to read file, please try again.");
|
||||
}
|
||||
wxLogWarning("PrinterFileSystem::UploadFile error: %d\n", result);
|
||||
SendChangedEvent(EVT_UPLOAD_CHANGED, FF_UPLOADCANCEL, error_msg, result);
|
||||
} else if (result == SUCCESS) {
|
||||
SendChangedEvent(EVT_UPLOADING, 100);
|
||||
SendChangedEvent(EVT_UPLOAD_CHANGED, FF_UPLOADDONE);
|
||||
} else if (result == CONTINUE || result == FILE_EXIST) {
|
||||
if (m_upload_file) {
|
||||
m_upload_file->chunk_size = resp["chunk_size"];
|
||||
m_upload_file->upload->size = resp["offset"];
|
||||
m_upload_file->flags |= FF_UPLOADING;
|
||||
}
|
||||
|
||||
{
|
||||
boost::unique_lock l(m_mutex);
|
||||
auto cb = [this, upload_file = m_upload_file, seq = m_upload_seq](std::string &msg) -> int {
|
||||
return UploadFileTask(upload_file, seq, msg);
|
||||
};
|
||||
m_produce_message_cb_map[m_upload_seq] = cb;
|
||||
}
|
||||
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
// reset m_upload_file
|
||||
if (m_upload_file) {
|
||||
m_upload_file.reset();
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
int PrinterFileSystem::UploadFileTask(std::shared_ptr<UploadFile> upload_file, boost::uint64_t seq, std::string &msg)
|
||||
{
|
||||
if (!upload_file)
|
||||
return FILE_OPEN_ERR;
|
||||
|
||||
if (!(upload_file->flags & FF_UPLOADING))
|
||||
return FILE_OPEN_ERR;
|
||||
|
||||
auto &upload = upload_file->upload;
|
||||
if (!upload->ifs.is_open()) {
|
||||
upload->ifs.open(upload_file->path, std::ios::binary);
|
||||
if (!upload_file->upload->ifs) {
|
||||
wxLogWarning("PrinterFileSystem::UploadFile open error: %s\n", wxString::FromUTF8(upload_file->path));
|
||||
return FILE_OPEN_ERR;
|
||||
}
|
||||
MD5_Init(&upload->ctx);
|
||||
}
|
||||
|
||||
const boost::uint32_t buffer_size = upload_file->chunk_size * 1024;
|
||||
char *buffer = new char[buffer_size];
|
||||
|
||||
upload->ifs.seekg(upload->size, std::ios::beg);
|
||||
upload->ifs.read(buffer, buffer_size);
|
||||
boost::int32_t read_size = upload->ifs.gcount();
|
||||
|
||||
if (read_size <= 0) {
|
||||
wxLogWarning("PrinterFileSystem::Upload read error.\n");
|
||||
upload->ifs.close();
|
||||
|
||||
if (buffer) {
|
||||
delete[] buffer;
|
||||
buffer = nullptr;
|
||||
}
|
||||
return FILE_READ_WRITE_ERR;
|
||||
}
|
||||
|
||||
json req;
|
||||
req["frag_id"] = upload->frag_id;
|
||||
req["offset"] = upload->size;
|
||||
req["size"] = read_size;
|
||||
|
||||
MD5_Update(&upload->ctx, buffer, read_size);
|
||||
upload->size += read_size;
|
||||
if (upload->size == upload->total) {
|
||||
unsigned char digest[16];
|
||||
MD5_Final(digest, &upload->ctx);
|
||||
char md5_str[33];
|
||||
for (int j = 0; j < 16; j++) { sprintf(&md5_str[j * 2], "%02X", (unsigned int) digest[j]); }
|
||||
std::string md5_out = std::string(md5_str);
|
||||
std::transform(md5_out.begin(), md5_out.end(), md5_out.begin(), ::tolower);
|
||||
|
||||
req["file_md5"] = md5_out;
|
||||
// OutputDebugStringA(md5_out.c_str());
|
||||
// OutputDebugStringA("\n");
|
||||
}
|
||||
|
||||
if (m_upload_file && m_upload_file->flags & FF_UPLOADING) {
|
||||
upload->frag_id++;
|
||||
upload->progress = upload->size * 100 / upload->total;
|
||||
int progress = upload->progress == 100 ? 99 : upload->progress;
|
||||
SendChangedEvent(EVT_UPLOADING, progress);
|
||||
}
|
||||
|
||||
json root;
|
||||
|
||||
root["cmdtype"] = FILE_UPLOAD;
|
||||
root["sequence"] = seq;
|
||||
root["req"] = req;
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << root;
|
||||
oss << "\n\n";
|
||||
oss << std::string(buffer, read_size);
|
||||
msg = oss.str();
|
||||
|
||||
if (buffer) {
|
||||
delete[] buffer;
|
||||
buffer = nullptr;
|
||||
}
|
||||
|
||||
if (upload->size == upload->total) {
|
||||
upload->ifs.close();
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
PrinterFileSystem::MediaAbilityList PrinterFileSystem::GetMediaAbilityList() const
|
||||
{
|
||||
return m_media_ability_list;
|
||||
}
|
||||
|
||||
void PrinterFileSystem::CancelUploadTask(bool send_cancel_req)
|
||||
{
|
||||
if (!m_upload_file)
|
||||
return;
|
||||
|
||||
if (send_cancel_req) {
|
||||
CancelRequest(m_upload_seq);
|
||||
} else {
|
||||
CancelRequests2({m_upload_seq});
|
||||
}
|
||||
}
|
||||
|
||||
boost::uint32_t PrinterFileSystem::SendRequest(int type, json const &req, callback_t2 const &callback)
|
||||
{
|
||||
if (m_session.tunnel == nullptr) {
|
||||
@@ -1037,14 +1254,14 @@ boost::uint32_t PrinterFileSystem::SendRequest(int type, json const &req, callba
|
||||
callback(ERROR_PIPE, json(), nullptr);
|
||||
return 0;
|
||||
}
|
||||
boost::uint32_t seq = m_sequence + m_callbacks.size();
|
||||
boost::uint32_t seq = m_sequence + m_callbacks.size();
|
||||
json root;
|
||||
root["cmdtype"] = type;
|
||||
root["sequence"] = seq;
|
||||
root["req"] = req;
|
||||
std::ostringstream oss;
|
||||
oss << root;
|
||||
auto msg = oss.str();
|
||||
auto msg = oss.str();
|
||||
boost::unique_lock l(m_mutex);
|
||||
m_messages.push_back(msg);
|
||||
m_callbacks.push_back(callback);
|
||||
@@ -1085,13 +1302,15 @@ void PrinterFileSystem::CancelRequests2(std::vector<boost::uint32_t> const &seqs
|
||||
for (auto &f : seqs) {
|
||||
boost::uint32_t seq = f;
|
||||
seq -= m_sequence;
|
||||
if (size_t(seq) >= m_callbacks.size())
|
||||
continue;
|
||||
if (size_t(seq) >= m_callbacks.size()) continue;
|
||||
auto &c = m_callbacks[seq];
|
||||
if (c == nullptr)
|
||||
continue;
|
||||
if (c == nullptr) continue;
|
||||
callbacks.emplace_back(f, c);
|
||||
c = nullptr;
|
||||
|
||||
// erase m_produce_message_cb
|
||||
if (m_produce_message_cb_map.find(seq) != m_produce_message_cb_map.end())
|
||||
m_produce_message_cb_map.erase(seq);
|
||||
}
|
||||
while (!m_callbacks.empty() && m_callbacks.front() == nullptr) {
|
||||
m_callbacks.pop_front();
|
||||
@@ -1118,6 +1337,45 @@ void PrinterFileSystem::RecvMessageThread()
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (m_messages.empty() && !m_produce_message_cb_map.empty()) {
|
||||
auto it = m_produce_message_cb_map.begin();
|
||||
while(it != m_produce_message_cb_map.end()) {
|
||||
std::string msg;
|
||||
auto prodeuce_message_cb = it->second;
|
||||
l.unlock();
|
||||
int res = prodeuce_message_cb(msg);
|
||||
l.lock();
|
||||
if (res == CONTINUE || res == SUCCESS) {
|
||||
m_messages.emplace_back(msg);
|
||||
if (res == SUCCESS) {
|
||||
it = m_produce_message_cb_map.erase(it);
|
||||
continue;
|
||||
}
|
||||
it++;
|
||||
} else {
|
||||
int seq2 = it->first - m_sequence;
|
||||
// erase it
|
||||
it = m_produce_message_cb_map.erase(it);
|
||||
if (size_t(seq2) >= m_callbacks.size())
|
||||
continue;
|
||||
auto c = m_callbacks[seq2];
|
||||
if (c == nullptr)
|
||||
continue;;
|
||||
m_callbacks[seq2] = nullptr;
|
||||
if (seq2 == 0) {
|
||||
// if produce message return error, erase callback and sequence should plus
|
||||
while (!m_callbacks.empty() && m_callbacks.front() == nullptr) {
|
||||
m_callbacks.pop_front();
|
||||
++m_sequence;
|
||||
}
|
||||
}
|
||||
|
||||
l.unlock();
|
||||
c(res, json(), nullptr);
|
||||
l.lock();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!m_messages.empty()) {
|
||||
auto & msg = m_messages.front();
|
||||
// OutputDebugStringA(msg.c_str());
|
||||
@@ -1201,7 +1459,7 @@ void PrinterFileSystem::HandleResponse(boost::unique_lock<boost::mutex> &l, Bamb
|
||||
int result2 = c(result, resp, json_end);
|
||||
l.lock();
|
||||
if (result2 != CONTINUE) {
|
||||
int seq2 = seq - m_sequence;
|
||||
int seq2 = seq - m_sequence;
|
||||
m_callbacks[seq2] = callback_t2();
|
||||
if (seq2 == 0) {
|
||||
while (!m_callbacks.empty() && m_callbacks.front() == nullptr) {
|
||||
@@ -1214,6 +1472,11 @@ void PrinterFileSystem::HandleResponse(boost::unique_lock<boost::mutex> &l, Bamb
|
||||
CancelRequest(seq);
|
||||
l.lock();
|
||||
}
|
||||
|
||||
// error should erase m_produce_message_cb
|
||||
if (m_produce_message_cb_map.find(seq2) != m_produce_message_cb_map.end()) {
|
||||
m_produce_message_cb_map.erase(seq2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1300,12 +1563,15 @@ void PrinterFileSystem::Reconnect(boost::unique_lock<boost::mutex> &l, int resul
|
||||
SendChangedEvent(EVT_STATUS_CHANGED, m_status, "", url.size() < 2 ? 1 : m_last_error);
|
||||
m_cond.timed_wait(l, boost::posix_time::seconds(10));
|
||||
}
|
||||
m_status = Status::ListSyncing;
|
||||
SendChangedEvent(EVT_STATUS_CHANGED, m_status);
|
||||
|
||||
#ifdef PRINTER_FILE_SYSTEM_TEST
|
||||
PostCallback([this] { SendChangedEvent(EVT_FILE_CHANGED); });
|
||||
#else
|
||||
PostCallback([this] { m_task_flags = 0; ListAllFiles(); });
|
||||
PostCallback([this] {
|
||||
m_task_flags = 0;
|
||||
m_status = Status::ListSyncing;
|
||||
SendChangedEvent(EVT_STATUS_CHANGED, m_status);
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user