mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-10-20 17:41:07 +08:00
307 lines
10 KiB
C++
307 lines
10 KiB
C++
#include "UserAccount.hpp"
|
|
|
|
#include "UserAccountUtils.hpp"
|
|
#include "format.hpp"
|
|
#include "GUI.hpp"
|
|
|
|
#include "libslic3r/Utils.hpp"
|
|
|
|
#include <boost/regex.hpp>
|
|
#include <boost/property_tree/ptree.hpp>
|
|
#include <boost/property_tree/json_parser.hpp>
|
|
#include <boost/log/trivial.hpp>
|
|
|
|
#include <wx/stdpaths.h>
|
|
|
|
namespace pt = boost::property_tree;
|
|
|
|
namespace Slic3r {
|
|
namespace GUI {
|
|
|
|
UserAccount::UserAccount(wxEvtHandler* evt_handler, AppConfig* app_config, const std::string& instance_hash)
|
|
: m_communication(std::make_unique<UserAccountCommunication>(evt_handler, app_config))
|
|
, m_instance_hash(instance_hash)
|
|
{
|
|
}
|
|
|
|
UserAccount::~UserAccount()
|
|
{}
|
|
|
|
void UserAccount::set_username(const std::string& username)
|
|
{
|
|
m_username = username;
|
|
m_communication->set_username(username);
|
|
}
|
|
|
|
void UserAccount::clear()
|
|
{
|
|
m_username = {};
|
|
m_account_user_data.clear();
|
|
m_printer_map.clear();
|
|
m_communication->do_clear();
|
|
}
|
|
|
|
void UserAccount::set_remember_session(bool remember)
|
|
{
|
|
m_communication->set_remember_session(remember);
|
|
}
|
|
void UserAccount::toggle_remember_session()
|
|
{
|
|
m_communication->set_remember_session(!m_communication->get_remember_session());
|
|
}
|
|
bool UserAccount::get_remember_session()
|
|
{
|
|
return m_communication->get_remember_session();
|
|
}
|
|
|
|
bool UserAccount::is_logged()
|
|
{
|
|
return m_communication->is_logged();
|
|
}
|
|
void UserAccount::do_login()
|
|
{
|
|
m_communication->do_login();
|
|
}
|
|
void UserAccount::do_logout()
|
|
{
|
|
m_communication->do_logout();
|
|
}
|
|
|
|
std::string UserAccount::get_access_token()
|
|
{
|
|
return m_communication->get_access_token();
|
|
}
|
|
|
|
std::string UserAccount::get_shared_session_key()
|
|
{
|
|
return m_communication->get_shared_session_key();
|
|
}
|
|
|
|
boost::filesystem::path UserAccount::get_avatar_path(bool logged) const
|
|
{
|
|
if (logged) {
|
|
const std::string filename = "prusaslicer-avatar-" + m_instance_hash + m_avatar_extension;
|
|
return into_path(wxStandardPaths::Get().GetTempDir()) / filename;
|
|
} else {
|
|
return boost::filesystem::path(resources_dir()) / "icons" / "user.svg";
|
|
}
|
|
}
|
|
|
|
void UserAccount::enqueue_connect_printer_models_action()
|
|
{
|
|
m_communication->enqueue_connect_printer_models_action();
|
|
}
|
|
void UserAccount::enqueue_connect_status_action()
|
|
{
|
|
m_communication->enqueue_connect_status_action();
|
|
}
|
|
void UserAccount::enqueue_avatar_action()
|
|
{
|
|
m_communication->enqueue_avatar_action(m_account_user_data["avatar"]);
|
|
}
|
|
void UserAccount::enqueue_printer_data_action(const std::string& uuid)
|
|
{
|
|
m_communication->enqueue_printer_data_action(uuid);
|
|
}
|
|
void UserAccount::request_refresh()
|
|
{
|
|
m_communication->request_refresh();
|
|
}
|
|
|
|
bool UserAccount::on_login_code_recieved(const std::string& url_message)
|
|
{
|
|
m_communication->on_login_code_recieved(url_message);
|
|
return true;
|
|
}
|
|
|
|
bool UserAccount::on_user_id_success(const std::string data, std::string& out_username)
|
|
{
|
|
boost::property_tree::ptree ptree;
|
|
try {
|
|
std::stringstream ss(data);
|
|
boost::property_tree::read_json(ss, ptree);
|
|
}
|
|
catch (const std::exception&) {
|
|
BOOST_LOG_TRIVIAL(error) << "UserIDUserAction Could not parse server response.";
|
|
return false;
|
|
}
|
|
m_account_user_data.clear();
|
|
for (const auto& section : ptree) {
|
|
const auto opt = ptree.get_optional<std::string>(section.first);
|
|
if (opt) {
|
|
BOOST_LOG_TRIVIAL(debug) << static_cast<std::string>(section.first) << " " << *opt;
|
|
m_account_user_data[section.first] = *opt;
|
|
}
|
|
|
|
}
|
|
if (m_account_user_data.find("public_username") == m_account_user_data.end()) {
|
|
BOOST_LOG_TRIVIAL(error) << "User ID message from PrusaAuth did not contain public_username. Login failed. Message data: " << data;
|
|
return false;
|
|
}
|
|
std::string public_username = m_account_user_data["public_username"];
|
|
set_username(public_username);
|
|
out_username = public_username;
|
|
// enqueue GET with avatar url
|
|
if (m_account_user_data.find("avatar") != m_account_user_data.end()) {
|
|
const boost::filesystem::path server_file(m_account_user_data["avatar"]);
|
|
m_avatar_extension = server_file.extension().string();
|
|
enqueue_avatar_action();
|
|
}
|
|
else {
|
|
BOOST_LOG_TRIVIAL(error) << "User ID message from PrusaAuth did not contain avatar.";
|
|
}
|
|
// update printers list
|
|
enqueue_connect_printer_models_action();
|
|
return true;
|
|
}
|
|
|
|
void UserAccount::on_communication_fail()
|
|
{
|
|
m_fail_counter++;
|
|
if (m_fail_counter > 5) // there is no deeper reason why 5
|
|
{
|
|
m_communication->enqueue_test_connection();
|
|
m_fail_counter = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool UserAccount::on_connect_printers_success(const std::string& data, AppConfig* app_config, bool& out_printers_changed)
|
|
{
|
|
BOOST_LOG_TRIVIAL(debug) << "Prusa Connect printers message: " << data;
|
|
pt::ptree ptree;
|
|
try {
|
|
std::stringstream ss(data);
|
|
pt::read_json(ss, ptree);
|
|
}
|
|
catch (const std::exception& e) {
|
|
BOOST_LOG_TRIVIAL(error) << "Could not parse prusaconnect message. " << e.what();
|
|
return false;
|
|
}
|
|
// tree format:
|
|
/*
|
|
[{
|
|
"printer_uuid": "972d2ce7-0967-4555-bff2-330c7fa0a4e1",
|
|
"printer_state" : "IDLE"
|
|
}, {
|
|
"printer_uuid": "15d160fd-c7e4-4b5a-9748-f0e531c7e0f5",
|
|
"printer_state" : "OFFLINE"
|
|
}]
|
|
*/
|
|
ConnectPrinterStateMap new_printer_map;
|
|
for (const auto& printer_tree : ptree) {
|
|
const auto printer_uuid = printer_tree.second.get_optional<std::string>("printer_uuid");
|
|
if (!printer_uuid) {
|
|
continue;
|
|
}
|
|
const auto printer_state = printer_tree.second.get_optional<std::string>("printer_state");
|
|
if (!printer_state) {
|
|
continue;
|
|
}
|
|
ConnectPrinterState state;
|
|
if (auto pair = printer_state_table.find(*printer_state); pair != printer_state_table.end()) {
|
|
state = pair->second;
|
|
} else {
|
|
assert(true); // On this assert, printer_state_table needs to be updated with *state_opt and correct ConnectPrinterState
|
|
continue;
|
|
}
|
|
if (m_printer_uuid_map.find(*printer_uuid) == m_printer_uuid_map.end()) {
|
|
BOOST_LOG_TRIVIAL(error) << "Missing printer model for printer uuid: " << *printer_uuid;
|
|
continue;
|
|
}
|
|
std::pair<std::string, std::string> model_nozzle_pair = m_printer_uuid_map[*printer_uuid];
|
|
|
|
if (new_printer_map.find(model_nozzle_pair) == new_printer_map.end()) {
|
|
new_printer_map[model_nozzle_pair].reserve(static_cast<size_t>(ConnectPrinterState::CONNECT_PRINTER_STATE_COUNT));
|
|
for (size_t i = 0; i < static_cast<size_t>(ConnectPrinterState::CONNECT_PRINTER_STATE_COUNT); i++) {
|
|
new_printer_map[model_nozzle_pair].push_back(0);
|
|
}
|
|
}
|
|
new_printer_map[model_nozzle_pair][static_cast<size_t>(state)] += 1;
|
|
}
|
|
|
|
// compare new and old printer map and update old map into new
|
|
out_printers_changed = false;
|
|
for (const auto& it : new_printer_map) {
|
|
if (m_printer_map.find(it.first) == m_printer_map.end()) {
|
|
// printer is not in old map, add it by copying data from new map
|
|
out_printers_changed = true;
|
|
m_printer_map[it.first].reserve(static_cast<size_t>(ConnectPrinterState::CONNECT_PRINTER_STATE_COUNT));
|
|
for (size_t i = 0; i < static_cast<size_t>(ConnectPrinterState::CONNECT_PRINTER_STATE_COUNT); i++) {
|
|
m_printer_map[it.first].push_back(new_printer_map[it.first][i]);
|
|
}
|
|
} else {
|
|
// printer is in old map, check state by state
|
|
for (size_t i = 0; i < static_cast<size_t>(ConnectPrinterState::CONNECT_PRINTER_STATE_COUNT); i++) {
|
|
if (m_printer_map[it.first][i] != new_printer_map[it.first][i]) {
|
|
out_printers_changed = true;
|
|
m_printer_map[it.first][i] = new_printer_map[it.first][i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool UserAccount::on_connect_uiid_map_success(const std::string& data, AppConfig* app_config, bool& out_printers_changed)
|
|
{
|
|
m_printer_uuid_map.clear();
|
|
pt::ptree ptree;
|
|
try {
|
|
std::stringstream ss(data);
|
|
pt::read_json(ss, ptree);
|
|
}
|
|
catch (const std::exception& e) {
|
|
BOOST_LOG_TRIVIAL(error) << "Could not parse prusaconnect message. " << e.what();
|
|
return false;
|
|
}
|
|
|
|
for (const auto& printer_tree : ptree) {
|
|
const auto printer_uuid = printer_tree.second.get_optional<std::string>("printer_uuid");
|
|
if (!printer_uuid) {
|
|
continue;
|
|
}
|
|
const auto printer_model = printer_tree.second.get_optional<std::string>("printer_model");
|
|
if (!printer_model) {
|
|
continue;
|
|
}
|
|
const auto nozzle_diameter_opt = printer_tree.second.get_optional<std::string>("nozzle_diameter");
|
|
const std::string nozzle_diameter = (nozzle_diameter_opt && *nozzle_diameter_opt != "0.0") ? *nozzle_diameter_opt : std::string();
|
|
std::pair<std::string, std::string> model_nozzle_pair = { *printer_model, nozzle_diameter };
|
|
m_printer_uuid_map[*printer_uuid] = model_nozzle_pair;
|
|
}
|
|
m_communication->on_uuid_map_success();
|
|
return on_connect_printers_success(data, app_config, out_printers_changed);
|
|
}
|
|
|
|
std::string UserAccount::get_current_printer_uuid_from_connect(const std::string &selected_printer_id
|
|
) const {
|
|
if (m_current_printer_data_json_from_connect.empty() || m_current_printer_uuid_from_connect.empty()) {
|
|
return {};
|
|
}
|
|
|
|
pt::ptree ptree;
|
|
try {
|
|
std::stringstream ss(m_current_printer_data_json_from_connect);
|
|
pt::read_json(ss, ptree);
|
|
}
|
|
catch (const std::exception& e) {
|
|
BOOST_LOG_TRIVIAL(error) << "Could not parse Printer data from Connect. " << e.what();
|
|
return {};
|
|
}
|
|
|
|
std::string data_uuid = UserAccountUtils::get_keyword_from_json(ptree, "", "uuid");
|
|
assert(data_uuid == m_current_printer_uuid_from_connect);
|
|
|
|
//std::string model_name = parse_tree_for_param(ptree, "printer_model");
|
|
std::vector<std::string> compatible_printers;
|
|
UserAccountUtils::fill_supported_printer_models_from_json(ptree, compatible_printers);
|
|
if (compatible_printers.empty()) {
|
|
return {};
|
|
}
|
|
|
|
return std::find(compatible_printers.begin(), compatible_printers.end(), selected_printer_id) == compatible_printers.end() ? "" : m_current_printer_uuid_from_connect;
|
|
}
|
|
|
|
}} // namespace slic3r::GUI
|