PrusaSlicer/src/slic3r/GUI/UserAccount.cpp
David Kocik 78c9aa668c User Account: Store more user data, not only username
Compare new and old printer maps
2024-03-25 12:05:55 +01:00

252 lines
8.4 KiB
C++

#include "UserAccount.hpp"
#include <boost/regex.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
namespace pt = boost::property_tree;
namespace Slic3r {
namespace GUI {
UserAccount::UserAccount(wxEvtHandler* evt_handler, AppConfig* app_config)
: m_auth_communication(std::make_unique<PrusaAuthCommunication>(evt_handler, app_config))
{}
UserAccount::~UserAccount()
{}
void UserAccount::set_username(const std::string& username, AppConfig* app_config)
{
m_username = username;
m_auth_communication->set_username(username, app_config);
}
void UserAccount::set_remember_session(bool remember)
{
m_auth_communication->set_remember_session(remember);
}
bool UserAccount::is_logged()
{
return m_auth_communication->is_logged();
}
void UserAccount::do_login()
{
m_auth_communication->do_login();
}
void UserAccount::do_logout()
{
m_auth_communication->do_logout();
}
std::string UserAccount::get_access_token()
{
return m_auth_communication->get_access_token();
}
#if 0
void UserAccount::enqueue_user_id_action()
{
m_auth_communication->enqueue_user_id_action();
}
void UserAccount::enqueue_connect_dummy_action()
{
m_auth_communication->enqueue_connect_dummy_action();
}
#endif
void UserAccount::enqueue_connect_printers_action()
{
m_auth_communication->enqueue_connect_printers_action();
}
bool UserAccount::on_login_code_recieved(const std::string& url_message)
{
m_auth_communication->on_login_code_recieved(url_message);
return true;
}
bool UserAccount::on_user_id_success(const std::string data, AppConfig* app_config, 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_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_user_data[section.first] = *opt;
}
}
assert(m_user_data.find("public_username") != m_user_data.end());
std::string public_username = m_user_data["public_username"];
set_username(public_username, app_config);
out_username = public_username;
return true;
}
bool UserAccount::on_communication_fail(const std::string data, AppConfig* app_config)
{
// TODO: should we just declare disconnect on every fail?
//set_username({}, app_config);
return true;
}
bool UserAccount::on_logout( AppConfig* app_config)
{
set_username({}, app_config);
return true;
}
namespace {
std::string parse_tree_for_param(const pt::ptree& tree, const std::string& param)
{
for (const auto& section : tree) {
if (section.first == param) {
return section.second.data();
} else {
if (std::string res = parse_tree_for_param(section.second, param); !res.empty())
return res;
}
}
return {};
}
}
bool UserAccount::on_connect_printers_success(const std::string data, AppConfig* app_config, bool& out_printers_changed, std::string& out_message)
{
BOOST_LOG_TRIVIAL(debug) << "PrusaConnect 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;
}
// fill m_printer_map with data from ptree
// tree string is in format {"printers": [{..}, {..}]}
ConnectPrinterStateMap new_printer_map;
assert(ptree.front().first == "printers");
for (const auto& printer_tree : ptree.front().second) {
std::string name;
ConnectPrinterState state;
std::string type_string = parse_tree_for_param(printer_tree.second, "printer_type");
std::string state_string = parse_tree_for_param(printer_tree.second, "connect_state");
assert(!type_string.empty());
assert(!state_string.empty());
if (type_string.empty() || state_string.empty())
continue;
// name of printer needs to be taken from translate table, if missing
if (auto pair = printer_type_and_name_table.find(type_string); pair != printer_type_and_name_table.end()) {
name = pair->second;
} else {
assert(true); // On this assert, printer_type_and_name_table needs to be updated with type_string and correct printer name
continue;
}
// translate state string to enum value
if (auto pair = printer_state_table.find(state_string); pair != printer_state_table.end()) {
state = pair->second;
} else {
assert(true); // On this assert, printer_state_table and ConnectPrinterState needs to be updated
continue;
}
if (auto counter = new_printer_map.find(name); counter != new_printer_map.end()) {
new_printer_map[name][static_cast<size_t>(state)]++;
} else {
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(i == static_cast<size_t>(state) ? 1 : 0);
}
}
}
// compare new and old printer map and update old map into new
out_printers_changed = true;
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 = false;
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 = false;
m_printer_map[it.first][i] = new_printer_map[it.first][i];
}
}
}
}
std::string out;
for (const auto& it : m_printer_map)
{
out_message += GUI::format("%1%: O%2% I%3% P%4% F%5% \n"
, it.first
, std::to_string(it.second[static_cast<size_t>(ConnectPrinterState::CONNECT_PRINTER_OFFLINE)])
, std::to_string(it.second[static_cast<size_t>(ConnectPrinterState::CONNECT_PRINTER_IDLE)])
, std::to_string(it.second[static_cast<size_t>(ConnectPrinterState::CONNECT_PRINTER_PRINTING)])
, std::to_string(it.second[static_cast<size_t>(ConnectPrinterState::CONNECT_PRINTER_FINISHED)]));
}
return true;
}
std::string UserAccount::get_model_from_json(const std::string& message) const
{
std::string out;
try {
std::stringstream ss(message);
pt::ptree ptree;
pt::read_json(ss, ptree);
std::string printer_type = parse_tree_for_param(ptree, "printer_type");
if (auto pair = printer_type_and_name_table.find(printer_type); pair != printer_type_and_name_table.end()) {
out = pair->second;
}
else {
out = parse_tree_for_param(ptree, "printer_type_name");
}
//assert(!out.empty());
}
catch (const std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "Could not parse prusaconnect message. " << e.what();
}
return out;
}
std::string UserAccount::get_nozzle_from_json(const std::string& message) const
{
std::string out;
try {
std::stringstream ss(message);
pt::ptree ptree;
pt::read_json(ss, ptree);
out = parse_tree_for_param(ptree, "nozzle_diameter");
//assert(!out.empty());
}
catch (const std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "Could not parse prusaconnect message. " << e.what();
}
return out;
}
}} // namespace slic3r::GUI