Changes in Connect Printer Status.

First use endpoint PrinterModels to get uuid to model map, than get statuses for uuids from Status endpoint.

Lang code trimmed to 2 chars.
This commit is contained in:
David Kocik 2024-04-22 16:01:05 +02:00
parent a474d36bfb
commit b05d438fc6
8 changed files with 116 additions and 54 deletions

View File

@ -937,7 +937,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
BOOST_LOG_TRIVIAL(error) << "Failed communication with Prusa Account: " << evt.data;
user_account->on_communication_fail();
});
this->q->Bind(EVT_UA_PRUSACONNECT_PRINTERS_SUCCESS, [this](UserAccountSuccessEvent& evt) {
this->q->Bind(EVT_UA_PRUSACONNECT_STATUS_SUCCESS, [this](UserAccountSuccessEvent& evt) {
std::string text;
bool printers_changed = false;
if (user_account->on_connect_printers_success(evt.data, wxGetApp().app_config, printers_changed)) {
@ -949,6 +949,19 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
user_account->on_communication_fail();
}
});
this->q->Bind(EVT_UA_PRUSACONNECT_PRINTER_MODELS_SUCCESS, [this](UserAccountSuccessEvent& evt) {
std::string text;
bool printers_changed = false;
if (user_account->on_connect_uiid_map_success(evt.data, wxGetApp().app_config, printers_changed)) {
if (printers_changed) {
sidebar->update_printer_presets_combobox();
}
}
else {
// message was corrupt, procceed like EVT_UA_FAIL
user_account->on_communication_fail();
}
});
this->q->Bind(EVT_UA_AVATAR_SUCCESS, [this](UserAccountSuccessEvent& evt) {
boost::filesystem::path path = user_account->get_avatar_path(true);
FILE* file;

View File

@ -84,10 +84,13 @@ boost::filesystem::path UserAccount::get_avatar_path(bool logged) const
}
}
void UserAccount::enqueue_connect_printers_action()
void UserAccount::enqueue_connect_printer_models_action()
{
m_communication->enqueue_connect_printers_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()
{
@ -137,7 +140,7 @@ bool UserAccount::on_user_id_success(const std::string data, std::string& out_us
BOOST_LOG_TRIVIAL(error) << "User ID message from PrusaAuth did not contain avatar.";
}
// update printers list
enqueue_connect_printers_action();
enqueue_connect_printer_models_action();
return true;
}
@ -149,6 +152,10 @@ void UserAccount::on_communication_fail()
m_communication->enqueue_test_connection();
m_fail_counter = 0;
}
// Printer models are called only after login, if it fails, it should repeat
if (m_printer_uuid_map.empty()) {
enqueue_connect_printer_models_action();
}
}
namespace {
@ -204,51 +211,45 @@ bool UserAccount::on_connect_printers_success(const std::string& data, AppConfig
BOOST_LOG_TRIVIAL(error) << "Could not parse prusaconnect message. " << e.what();
return false;
}
// fill m_printer_map with data from ptree
// tree string is in format {"result": [{"printer_type": "1.2.3", "states": [{"printer_state": "OFFLINE", "count": 1}, ...]}, {..}]}
// 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;
assert(ptree.front().first == "result");
for (const auto& printer_tree : ptree.front().second) {
// printer_tree is {"printer_type": "1.2.3", "states": [..]}
std::string name;
ConnectPrinterState state;
const auto type_opt = printer_tree.second.get_optional<std::string>("printer_model");
if (!type_opt) {
for (const auto& printer_tree : ptree) {
const auto printer_uuid = printer_tree.second.get_optional<std::string>("printer_uuid");
if (!printer_uuid) {
continue;
}
// printer_type is actually printer_name for now
name = *type_opt;
// printer should not appear twice
assert(new_printer_map.find(name) == new_printer_map.end());
// prepare all states on 0
new_printer_map[name].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[name].push_back(0);
const auto printer_state = printer_tree.second.get_optional<std::string>("printer_state");
if (!printer_state) {
continue;
}
for (const auto& section : printer_tree.second) {
// section is "printer_type": "1.2.3" OR "states": [..]}
if (section.first == "states") {
for (const auto& subsection : section.second) {
// subsection is {"printer_state": "OFFLINE", "count": 1}
const auto state_opt = subsection.second.get_optional<std::string>("printer_state");
const auto count_opt = subsection.second.get_optional<int>("count");
if (!state_opt || ! count_opt) {
continue;
}
if (auto pair = printer_state_table.find(*state_opt); 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;
}
new_printer_map[name][static_cast<size_t>(state)] = *count_opt;
}
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;
}
const std::string printer_model = m_printer_uuid_map[*printer_uuid];
if (new_printer_map.find(printer_model) == new_printer_map.end()) {
new_printer_map[printer_model].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[printer_model].push_back(0);
}
}
new_printer_map[printer_model][static_cast<size_t>(state)] += 1;
}
// compare new and old printer map and update old map into new
@ -274,6 +275,33 @@ bool UserAccount::on_connect_printers_success(const std::string& data, AppConfig
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;
}
m_printer_uuid_map[*printer_uuid] = *printer_model;
}
return on_connect_printers_success(data, app_config, out_printers_changed);
}
std::string UserAccount::get_model_from_json(const std::string& message) const
{
std::string out;

View File

@ -26,6 +26,7 @@ enum class ConnectPrinterState {
};
typedef std::map<std::string, std::vector<size_t>> ConnectPrinterStateMap;
typedef std::map<std::string, std::string> ConnectUUIDToModelMap;
// Class UserAccount should handle every request for entities outside PrusaSlicer like PrusaAuth or PrusaConnect.
// Outside communication is implemented in class UserAccountCommunication that runs separate thread. Results come back in events to Plater.
// All incoming data shoud be stored in UserAccount.
@ -41,7 +42,8 @@ public:
void set_remember_session(bool remember);
void toggle_remember_session();
bool get_remember_session();
void enqueue_connect_printers_action();
void enqueue_connect_status_action();
void enqueue_connect_printer_models_action();
void enqueue_avatar_action();
// Clears all data and connections, called on logout or EVT_UA_RESET
@ -54,6 +56,7 @@ public:
// Called on EVT_UA_FAIL, triggers test after several calls
void on_communication_fail();
bool on_connect_printers_success(const std::string& data, AppConfig* app_config, bool& out_printers_changed);
bool on_connect_uiid_map_success(const std::string& data, AppConfig* app_config, bool& out_printers_changed);
std::string get_username() const { return m_username; }
std::string get_access_token();
@ -80,6 +83,7 @@ private:
std::unique_ptr<Slic3r::GUI::UserAccountCommunication> m_communication;
ConnectPrinterStateMap m_printer_map;
ConnectUUIDToModelMap m_printer_uuid_map;
std::map<std::string, std::string> m_account_user_data;
std::string m_username;
size_t m_fail_counter { 0 };

View File

@ -275,14 +275,25 @@ void UserAccountCommunication::on_login_code_recieved(const std::string& url_mes
wakeup_session_thread();
}
void UserAccountCommunication::enqueue_connect_printers_action()
void UserAccountCommunication::enqueue_connect_printer_models_action()
{
{
std::lock_guard<std::mutex> lock(m_session_mutex);
if (!m_session->is_initialized()) {
BOOST_LOG_TRIVIAL(error) << "Connect Printers endpoint connection failed - Not Logged in.";
BOOST_LOG_TRIVIAL(error) << "Connect Printer Models connection failed - Not Logged in.";
return;
}
m_session->enqueue_action(UserAccountActionID::USER_ACCOUNT_ACTION_CONNECT_PRINTER_MODELS, nullptr, nullptr, {});
}
wakeup_session_thread();
}
void UserAccountCommunication::enqueue_connect_status_action()
{
{
std::lock_guard<std::mutex> lock(m_session_mutex);
if (!m_session->is_initialized()) {
BOOST_LOG_TRIVIAL(error) << "Connect Status endpoint connection failed - Not Logged in.";
return;
}
m_session->enqueue_action(UserAccountActionID::USER_ACCOUNT_ACTION_CONNECT_STATUS, nullptr, nullptr, {});

View File

@ -39,7 +39,8 @@ public:
void do_logout();
void do_clear();
// Trigger function starts various remote operations
void enqueue_connect_printers_action();
void enqueue_connect_status_action();
void enqueue_connect_printer_models_action();
void enqueue_avatar_action(const std::string& url);
void enqueue_test_connection();

View File

@ -22,7 +22,8 @@ wxDEFINE_EVENT(EVT_OPEN_PRUSAAUTH, OpenPrusaAuthEvent);
wxDEFINE_EVENT(EVT_UA_LOGGEDOUT, UserAccountSuccessEvent);
wxDEFINE_EVENT(EVT_UA_ID_USER_SUCCESS, UserAccountSuccessEvent);
wxDEFINE_EVENT(EVT_UA_SUCCESS, UserAccountSuccessEvent);
wxDEFINE_EVENT(EVT_UA_PRUSACONNECT_PRINTERS_SUCCESS, UserAccountSuccessEvent);
wxDEFINE_EVENT(EVT_UA_PRUSACONNECT_STATUS_SUCCESS, UserAccountSuccessEvent);
wxDEFINE_EVENT(EVT_UA_PRUSACONNECT_PRINTER_MODELS_SUCCESS, UserAccountSuccessEvent);
wxDEFINE_EVENT(EVT_UA_AVATAR_SUCCESS, UserAccountSuccessEvent);
wxDEFINE_EVENT(EVT_UA_FAIL, UserAccountFailEvent);
wxDEFINE_EVENT(EVT_UA_RESET, UserAccountFailEvent);

View File

@ -20,7 +20,8 @@ wxDECLARE_EVENT(EVT_OPEN_PRUSAAUTH, OpenPrusaAuthEvent);
wxDECLARE_EVENT(EVT_UA_LOGGEDOUT, UserAccountSuccessEvent);
wxDECLARE_EVENT(EVT_UA_ID_USER_SUCCESS, UserAccountSuccessEvent);
wxDECLARE_EVENT(EVT_UA_SUCCESS, UserAccountSuccessEvent);
wxDECLARE_EVENT(EVT_UA_PRUSACONNECT_PRINTERS_SUCCESS, UserAccountSuccessEvent);
wxDECLARE_EVENT(EVT_UA_PRUSACONNECT_STATUS_SUCCESS, UserAccountSuccessEvent);
wxDECLARE_EVENT(EVT_UA_PRUSACONNECT_PRINTER_MODELS_SUCCESS, UserAccountSuccessEvent);
wxDECLARE_EVENT(EVT_UA_AVATAR_SUCCESS, UserAccountSuccessEvent);
wxDECLARE_EVENT(EVT_UA_FAIL, UserAccountFailEvent); // Soft fail - clears only after some number of fails
wxDECLARE_EVENT(EVT_UA_RESET, UserAccountFailEvent); // Hard fail - clears all
@ -38,6 +39,7 @@ enum class UserAccountActionID {
USER_ACCOUNT_ACTION_TEST_ACCESS_TOKEN,
USER_ACCOUNT_ACTION_TEST_CONNECTION,
USER_ACCOUNT_ACTION_CONNECT_STATUS, // status of all printers
USER_ACCOUNT_ACTION_CONNECT_PRINTER_MODELS,
USER_ACCOUNT_ACTION_AVATAR,
};
class UserAction
@ -110,7 +112,8 @@ public:
m_actions[UserAccountActionID::USER_ACCOUNT_ACTION_USER_ID] = std::make_unique<UserActionGetWithEvent>("USER_ID", "https://account.prusa3d.com/api/v1/me/", EVT_UA_ID_USER_SUCCESS, EVT_UA_RESET);
m_actions[UserAccountActionID::USER_ACCOUNT_ACTION_TEST_ACCESS_TOKEN] = std::make_unique<UserActionGetWithEvent>("TEST_ACCESS_TOKEN", "https://account.prusa3d.com/api/v1/me/", EVT_UA_ID_USER_SUCCESS, EVT_UA_FAIL);
m_actions[UserAccountActionID::USER_ACCOUNT_ACTION_TEST_CONNECTION] = std::make_unique<UserActionGetWithEvent>("TEST_CONNECTION", "https://account.prusa3d.com/api/v1/me/", wxEVT_NULL, EVT_UA_RESET);
m_actions[UserAccountActionID::USER_ACCOUNT_ACTION_CONNECT_STATUS] = std::make_unique<UserActionGetWithEvent>("CONNECT_STATUS", "https://connect.prusa3d.com/slicer/status", EVT_UA_PRUSACONNECT_PRINTERS_SUCCESS, EVT_UA_FAIL);
m_actions[UserAccountActionID::USER_ACCOUNT_ACTION_CONNECT_STATUS] = std::make_unique<UserActionGetWithEvent>("CONNECT_STATUS", "https://connect.prusa3d.com/slicer/status", EVT_UA_PRUSACONNECT_STATUS_SUCCESS, EVT_UA_FAIL);
m_actions[UserAccountActionID::USER_ACCOUNT_ACTION_CONNECT_PRINTER_MODELS] = std::make_unique<UserActionGetWithEvent>("CONNECT_PRINTER_MODELS", "https://connect.prusa3d.com/slicer/printer_list", EVT_UA_PRUSACONNECT_PRINTER_MODELS_SUCCESS, EVT_UA_FAIL);
m_actions[UserAccountActionID::USER_ACCOUNT_ACTION_AVATAR] = std::make_unique<UserActionGetWithEvent>("AVATAR", "https://media.printables.com/media/", EVT_UA_AVATAR_SUCCESS, EVT_UA_FAIL);
}
~UserAccountSession()

View File

@ -538,7 +538,8 @@ void ConnectRequestHandler::on_request_config()
const std::string token = wxGetApp().plater()->get_user_account()->get_access_token();
//const std::string sesh = wxGetApp().plater()->get_user_account()->get_shared_session_key();
const std::string dark_mode = wxGetApp().dark_mode() ? "DARK" : "LIGHT";
const wxString language = GUI::wxGetApp().current_language_code();
wxString language = GUI::wxGetApp().current_language_code();
language = language.SubString(0, 1);
const std::string init_options = GUI::format("{\"accessToken\": \"%1%\" , \"clientVersion\": \"%2%\", \"colorMode\": \"%3%\", \"language\": \"%4%\"}", token, SLIC3R_VERSION, dark_mode, language);
wxString script = GUI::format_wxstr("window._prusaConnect_v1.init(%1%)", init_options);
run_script_bridge(script);