Files
OrcaSlicer/src/slic3r/GUI/HMS.cpp
T
Hanif Koh 68c72c6b80 Remove using namespace std from json_diff.hpp
The directive sat at global scope in a header that DeviceManager.hpp
includes, so most of the GUI compiled with all of std in the global
namespace. 42 files had come to rely on it, mostly for string, vector
and unordered_map, four of them for the ""sv and ""ms literals.

Those sites are qualified. GCodeViewer.cpp spelled the type as
std::vector<::string>, which only resolved through the directive.
2026-10-07 01:39:17 +08:00

753 lines
27 KiB
C++

#include "HMS.hpp"
#include "GUI.hpp"
#include "GUI_App.hpp"
#include "DeviceManager.hpp"
#include "DeviceCore/DevManager.h"
#include "DeviceCore/DevUtil.h"
#include "Http.hpp"
#include "json_diff.hpp"
#include "libslic3r/AppConfig.hpp"
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/directory.hpp>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/log/trivial.hpp>
#include <unordered_set>
#include <string>
#include "libslic3r/Utils.hpp"
#include <fstream>
#include <ostream>
#include <wx/string.h>
#include <vector>
#include <cstdio>
#include <wx/image.h>
#include <mutex>
#include <ctime>
namespace fs = boost::filesystem;
static const char* HMS_PATH = "hms";
static const char* HMS_LOCAL_IMG_PATH = "hms/local_image";
// the local HMS info
// Orca: dev-id-type set trimmed to the devices Orca ships local HMS images for
static std::unordered_set<std::string> package_dev_id_types {"094", "239", "093", "22E"};
// Orca: HMS should be disabled when stealth mode is on or networking is not installed
static bool should_disable_hms()
{
Slic3r::AppConfig* config = Slic3r::GUI::wxGetApp().app_config;
if (!config) return true;
return config->get_stealth_mode() || !config->get_bool("installed_networking");
}
namespace Slic3r {
namespace GUI {
int get_hms_info_version(std::string& version)
{
AppConfig* config = wxGetApp().app_config;
if (!config)
return -1;
if (should_disable_hms())
return -1;
std::string hms_host = config->get_hms_host();
if(hms_host.empty()) {
BOOST_LOG_TRIVIAL(error) << "hms_host is empty";
return -1;
}
int result = -1;
version = "";
std::string lang;
std::string query_params = HMSQuery::build_query_params(lang);
std::string url = (boost::format("https://%1%/GetVersion.php?%2%") % hms_host % query_params).str();
Slic3r::Http http = Slic3r::Http::get(url);
http.timeout_max(10)
.on_complete([&version](std::string body, unsigned status){
try {
json j = json::parse(body);
if (j.contains("ver")) {
version = DevJsonValParser::get_longlong_val(j["ver"]);
}
} catch (...) {
;
}
})
.on_error([&result](std::string body, std::string error, unsigned status) {
BOOST_LOG_TRIVIAL(error) << "get_hms_info_version: body = " << body << ", status = " << status << ", error = " << error;
result = -1;
})
.perform_sync();
return result;
}
// Note: Download the hms into receive_json
int HMSQuery::download_hms_related(const std::string& hms_type, const std::string& dev_id_type, json* receive_json)
{
std::string local_version = "0";
load_from_local(hms_type, dev_id_type, receive_json, local_version);
AppConfig* config = wxGetApp().app_config;
if (!config) return -1;
if (should_disable_hms()) return -1;
std::string hms_host = wxGetApp().app_config->get_hms_host();
std::string lang;
std::string query_params = HMSQuery::build_query_params(lang);
std::string url;
if (hms_type.compare(QUERY_HMS_INFO) == 0) {
url = (boost::format("https://%1%/query.php?%2%") % hms_host % query_params).str();
}
else if (hms_type.compare(QUERY_HMS_ACTION) == 0) {
url = (boost::format("https://%1%/hms/GetActionImage.php?") % hms_host).str();
}
if (!local_version.empty()) { url += (url.find('?') != std::string::npos ? "&" : "?") + (boost::format("v=%1%") % local_version).str(); }
if (!dev_id_type.empty()) { url += (url.find('?') != std::string::npos ? "&" : "?") + (boost::format("d=%1%") % dev_id_type).str(); }
bool to_save_local = false;
json j;
BOOST_LOG_TRIVIAL(info) << "hms: download url = " << url;
Slic3r::Http http = Slic3r::Http::get(url);
http.on_complete([receive_json, hms_type, &to_save_local, &j, & local_version](std::string body, unsigned status) {
try {
j = json::parse(body);
if (j.contains("result")) {
if (j["result"] == 0 && j.contains("data")) {
if (!j.contains("ver"))
{
return;
}
const std::string& remote_ver = DevJsonValParser::get_longlong_val(j["ver"]);
if (remote_ver <= local_version)
{
return;
}
(*receive_json)["version"] = remote_ver;
if (hms_type.compare(QUERY_HMS_INFO) == 0)
{
(*receive_json) = j["data"];
to_save_local = true;
}
else if (hms_type.compare(QUERY_HMS_ACTION) == 0)
{
(*receive_json)["data"] = j["data"];
to_save_local = true;
}
} else if (j["result"] == 201){
BOOST_LOG_TRIVIAL(info) << "HMSQuery: HMS info is the latest version";
}else{
BOOST_LOG_TRIVIAL(info) << "HMSQuery: update hms info error = " << j["result"].get<int>();
}
}
} catch (...) {
;
}
})
.timeout_max(20)
.on_error([](std::string body, std::string error, unsigned status) {
BOOST_LOG_TRIVIAL(error) << "HMSQuery: update hms info error = " << error << ", body = " << body << ", status = " << status;
}).perform_sync();
if (to_save_local && !receive_json->empty()) {
save_to_local(lang, hms_type, dev_id_type, j);
}
return 0;
}
static void
_copy_dir(const fs::path& from_dir, const fs::path& to_dir) /* copy and override with local files*/
{
try
{
if (!fs::exists(from_dir))
{
return;
}
if (!fs::exists(to_dir))
{
fs::create_directory(to_dir);
}
for (const auto &entry : fs::directory_iterator(from_dir))
{
const fs::path &source_path = entry.path();
const fs::path &relative_path = fs::relative(source_path, from_dir);
const fs::path &dest_path = to_dir / relative_path;
if (fs::is_regular_file(source_path))
{
if (fs::exists(dest_path))
{
fs::remove(dest_path);
}
copy_file(source_path, dest_path);
}
else if (fs::is_directory(source_path))
{
_copy_dir(source_path, dest_path);
}
}
}
catch (...)
{
}
}
void HMSQuery::copy_from_data_dir_to_local()
{
const fs::path& from_dir = fs::path(Slic3r::resources_dir()) / HMS_PATH;
const fs::path& to_dir = fs::path(Slic3r::data_dir()) / HMS_PATH;
_copy_dir(from_dir, to_dir);
}
int HMSQuery::load_from_local(const std::string& hms_type, const std::string& dev_id_type, json* load_json, std::string& load_version)
{
if (data_dir().empty()) {
load_version = "0";
BOOST_LOG_TRIVIAL(error) << "HMS: load_from_local, data_dir() is empty";
return -1;
}
std::string filename = get_hms_file(hms_type, HMSQuery::hms_language_code(), dev_id_type);
auto hms_folder = (boost::filesystem::path(data_dir()) / "hms");
if (!fs::exists(hms_folder))
fs::create_directory(hms_folder);
std::string dir_str = (hms_folder / filename).make_preferred().string();
std::ifstream json_file(encode_path(dir_str.c_str()));
try {
if (json_file.is_open())
{
const json &j = json::parse(json_file);
if (hms_type.compare(QUERY_HMS_INFO) == 0) {
if (j.contains("data")) { (*load_json) = j["data"]; }
} else if (hms_type.compare(QUERY_HMS_ACTION) == 0) {
if (j.contains("data")) { (*load_json)["data"] = j["data"]; }
}
if (j.contains("version")) {
load_version = DevJsonValParser::get_longlong_val(j["version"]);
}
else if (j.contains("ver")) {
load_version = DevJsonValParser::get_longlong_val(j["ver"]);
}
else
{
BOOST_LOG_TRIVIAL(warning) << "HMS: load_from_local, no version info";
}
return 0;
}
} catch(...) {
load_version = "0";
BOOST_LOG_TRIVIAL(error) << "HMS: load_from_local failed";
return -1;
}
load_version = "0";
return 0;
}
int HMSQuery::save_to_local(std::string lang, std::string hms_type, std::string dev_id_type, json save_json)
{
if (data_dir().empty()) {
BOOST_LOG_TRIVIAL(error) << "HMS: save_to_local, data_dir() is empty";
return -1;
}
std::string filename = get_hms_file(hms_type,lang, dev_id_type);
auto hms_folder = (boost::filesystem::path(data_dir()) / "hms");
if (!fs::exists(hms_folder))
fs::create_directory(hms_folder);
std::string dir_str = (hms_folder / filename).make_preferred().string();
std::ofstream json_file(encode_path(dir_str.c_str()));
if (json_file.is_open()) {
json_file << save_json.dump(1, '\t') << std::endl; // Orca: tab-indented dump
json_file.close();
return 0;
}
BOOST_LOG_TRIVIAL(error) << "HMS: save_to_local failed";
return -1;
}
std::string HMSQuery::hms_language_code()
{
AppConfig* config = wxGetApp().app_config;
if (!config)
// set language code to en by default
return "en";
std::string lang_code = wxGetApp().app_config->get_language_code();
// Orca: the HMS host ships no catalog for these locales, so fall back to english to avoid empty texts + retries
if (lang_code.compare("uk") == 0
|| lang_code.compare("cs") == 0
|| lang_code.compare("ru") == 0
|| lang_code.compare("tr") == 0
|| lang_code.compare("pt") == 0
|| lang_code.compare("ko") == 0
)
{
BOOST_LOG_TRIVIAL(info) << "HMS: using english for lang_code = " << lang_code;
return "en";
}
else if (lang_code.empty()) {
// set language code to en by default
return "en";
}
return lang_code;
}
std::string HMSQuery::build_query_params(std::string& lang)
{
std::string lang_code = HMSQuery::hms_language_code();
lang = lang_code;
std::string query_params = (boost::format("lang=%1%") % lang_code).str();
return query_params;
}
std::string HMSQuery::get_hms_file(std::string hms_type, std::string lang, std::string dev_id_type)
{
//return hms action filename
if (hms_type.compare(QUERY_HMS_ACTION) == 0) {
return (boost::format("hms_action_%1%.json") % dev_id_type).str();
}
//return hms filename
return (boost::format("hms_%1%_%2%.json") % lang % dev_id_type).str();
}
wxString HMSQuery::query_hms_msg(const MachineObject* obj, const std::string& long_error_code)
{
if (!obj)
{
return wxEmptyString;
}
AppConfig* config = wxGetApp().app_config;
if (!config) return wxEmptyString;
const std::string& lang_code = HMSQuery::hms_language_code();
return _query_hms_msg(get_dev_id_type(obj),long_error_code, lang_code);
}
wxString HMSQuery::query_hms_msg(const std::string& dev_id, const std::string& long_error_code)
{
AppConfig* config = wxGetApp().app_config;
if (!config) return wxEmptyString;
const std::string& lang_code = HMSQuery::hms_language_code();
return _query_hms_msg(dev_id.substr(0, 3), long_error_code, lang_code);
}
std::string HMSQuery::get_dev_id_type(const MachineObject* obj) const
{
if (obj)
{
return obj->get_dev_id().substr(0, 3);
}
return std::string();
}
wxString HMSQuery::_query_hms_msg(const std::string& dev_id_type, const std::string& long_error_code, const std::string& lang_code)
{
if (long_error_code.empty())
{
return wxEmptyString;
}
init_hms_info(dev_id_type);
auto iter = m_hms_info_jsons.find(dev_id_type);
if (iter == m_hms_info_jsons.end())
{
BOOST_LOG_TRIVIAL(error) << "there are no hms info for the device";
return wxEmptyString;
}
const json& m_hms_info_json = iter->second;
if (!m_hms_info_json.is_object())
{
BOOST_LOG_TRIVIAL(error) << "the hms info is not a valid json object";
return wxEmptyString;
}
const json& device_hms_json = m_hms_info_json.value("device_hms", json());
if (device_hms_json.is_null() || !device_hms_json.is_object())
{
BOOST_LOG_TRIVIAL(error) << "there are no valid json object named device_hms";
return wxEmptyString;
}
const json& device_hms_msg_json = device_hms_json.value(lang_code, json());
if (device_hms_msg_json.is_null())
{
BOOST_LOG_TRIVIAL(error) << "hms: query_hms_msg, do not contains lang_code = " << lang_code;
if (lang_code.empty()) /*traverse all if lang_code is empty*/
{
for (const auto& lang_item : device_hms_json)
{
for (const auto& msg_item : lang_item)
{
if (msg_item.is_object())
{
const std::string& error_code = msg_item.value("ecode", json()).get<std::string>();
if (boost::to_upper_copy(error_code) == long_error_code && msg_item.contains("intro"))
{
BOOST_LOG_TRIVIAL(info) << "retry without lang_code successed.";
return wxString::FromUTF8(msg_item["intro"].get<std::string>());
}
}
}
}
}
return wxEmptyString;
}
for (const auto& item : device_hms_msg_json)
{
if (item.is_object())
{
const std::string& error_code = item.value("ecode", json()).get<std::string>();
if (boost::to_upper_copy(error_code) == long_error_code && item.contains("intro"))
{
return wxString::FromUTF8(item["intro"].get<std::string>());
}
}
}
BOOST_LOG_TRIVIAL(error) << "hms: query_hms_msg, do not contains valid message, lang_code = " << lang_code << " long_error_code = " << long_error_code;
return wxEmptyString;
}
bool HMSQuery::_is_internal_error(const std::string &dev_id_type,
const std::string &error_code,
const std::string &lang_code)
{
init_hms_info(dev_id_type);
auto iter = m_hms_info_jsons.find(dev_id_type);
if (iter == m_hms_info_jsons.end()) { return false; }
const json &m_hms_info_json = iter->second;
if (m_hms_info_json.contains("device_error")) {
if (m_hms_info_json["device_error"].contains(lang_code)) {
for (auto item = m_hms_info_json["device_error"][lang_code].begin(); item != m_hms_info_json["device_error"][lang_code].end(); item++) {
if (item->contains("ecode") && boost::to_upper_copy((*item)["ecode"].get<std::string>()) == error_code) {
if (item->contains("intro")) { return wxString::FromUTF8((*item)["intro"].get<std::string>()).IsEmpty(); }
}
}
} else {
// return first language
if (!m_hms_info_json["device_error"].empty()) {
for (auto lang : m_hms_info_json["device_error"]) {
for (auto item = lang.begin(); item != lang.end(); item++) {
if (item->contains("ecode") && boost::to_upper_copy((*item)["ecode"].get<std::string>()) == error_code) {
if (item->contains("intro")) { return wxString::FromUTF8((*item)["intro"].get<std::string>()).IsEmpty(); }
}
}
}
}
}
}
return false;
}
wxString HMSQuery::_query_error_msg(const std::string &dev_id_type,
const std::string& error_code,
const std::string& lang_code)
{
init_hms_info(dev_id_type);
auto iter = m_hms_info_jsons.find(dev_id_type);
if (iter == m_hms_info_jsons.end())
{
return wxEmptyString;
}
const json& m_hms_info_json = iter->second;
if (m_hms_info_json.contains("device_error")) {
if (m_hms_info_json["device_error"].contains(lang_code)) {
for (auto item = m_hms_info_json["device_error"][lang_code].begin(); item != m_hms_info_json["device_error"][lang_code].end(); item++) {
if (item->contains("ecode") && boost::to_upper_copy((*item)["ecode"].get<std::string>()) == error_code) {
if (item->contains("intro")) {
return wxString::FromUTF8((*item)["intro"].get<std::string>());
}
}
}
BOOST_LOG_TRIVIAL(info) << "hms: query_error_msg, not found error_code = " << error_code;
} else {
BOOST_LOG_TRIVIAL(error) << "hms: query_error_msg, do not contains lang_code = " << lang_code;
// return first language
if (!m_hms_info_json["device_error"].empty()) {
for (auto lang : m_hms_info_json["device_error"]) {
for (auto item = lang.begin(); item != lang.end(); item++) {
if (item->contains("ecode") && boost::to_upper_copy((*item)["ecode"].get<std::string>()) == error_code) {
if (item->contains("intro")) {
return wxString::FromUTF8((*item)["intro"].get<std::string>());
}
}
}
}
}
}
}
else {
BOOST_LOG_TRIVIAL(info) << "device_error is not exists";
return wxEmptyString;
}
return wxEmptyString;
}
wxString HMSQuery::_query_error_image_action(const std::string& dev_id_type, const std::string& long_error_code, std::vector<int>& button_action)
{
init_hms_info(dev_id_type);
auto iter = m_hms_action_jsons.find(dev_id_type);
if (iter == m_hms_action_jsons.end())
{
return wxEmptyString;
}
const json& m_hms_action_json = iter->second;
if (m_hms_action_json.contains("data")) {
for (auto item = m_hms_action_json["data"].begin(); item != m_hms_action_json["data"].end(); item++) {
if (item->contains("ecode") && boost::to_upper_copy((*item)["ecode"].get<std::string>()) == long_error_code) {
if (item->contains("device") && (boost::to_upper_copy((*item)["device"].get<std::string>()) == dev_id_type ||
(*item)["device"].get<std::string>() == "default")) {
if (item->contains("actions")) {
for (auto item_actions = (*item)["actions"].begin(); item_actions != (*item)["actions"].end(); item_actions++) {
button_action.emplace_back(item_actions->get<int>());
}
}
if (item->contains("image")) {
return wxString::FromUTF8((*item)["image"].get<std::string>());
}
}
}
}
}
else {
BOOST_LOG_TRIVIAL(info) << "data is not exists";
return wxEmptyString;
}
return wxEmptyString;
}
bool HMSQuery::is_internal_error(const MachineObject *obj, int print_error)
{
char buf[32];
::sprintf(buf, "%08X", print_error);
std::string lang_code = HMSQuery::hms_language_code();
return _is_internal_error(get_dev_id_type(obj), std::string(buf), lang_code);
}
wxString HMSQuery::query_print_error_msg(const MachineObject *obj, int print_error)
{
if (!obj)
{
return wxEmptyString;
}
char buf[32];
::sprintf(buf, "%08X", print_error);
std::string lang_code = HMSQuery::hms_language_code();
return _query_error_msg(get_dev_id_type(obj), std::string(buf), lang_code);
}
wxString HMSQuery::query_print_error_msg(const std::string& dev_id, int print_error)
{
char buf[32];
::sprintf(buf, "%08X", print_error);
std::string lang_code = HMSQuery::hms_language_code();
return _query_error_msg(dev_id.substr(0, 3), std::string(buf), lang_code);
}
wxString HMSQuery::query_print_image_action(const MachineObject* obj, int print_error, std::vector<int>& button_action)
{
if (!obj)
{
return wxEmptyString;
}
char buf[32];
::sprintf(buf, "%08X", print_error);
//The first three digits of SN number
const auto result = _query_error_image_action(get_dev_id_type(obj),std::string(buf), button_action);
if (should_disable_hms() && result.Contains("http")) {
return wxEmptyString;
}
return result;
}
wxImage HMSQuery::query_image_from_local(const wxString& image_name)
{
if (image_name.empty() || image_name.Contains("http"))
{
return wxImage();
}
if (m_hms_local_images.empty())
{
const fs::path& local_img_dir = fs::path(Slic3r::data_dir()) / HMS_LOCAL_IMG_PATH;
if (fs::exists(local_img_dir))
{
for (const auto &entry : fs::directory_iterator(local_img_dir))
{
const fs::path& image_path = entry.path();
const fs::path& image_name = fs::relative(image_path, local_img_dir);
// Orca: from_path() for correct UTF-8 path encoding
m_hms_local_images[from_path(image_name)] = wxImage(from_path(image_path));
}
}
}
auto iter = m_hms_local_images.find(image_name);
if (iter != m_hms_local_images.end())
{
return iter->second;
}
return wxImage();
}
void HMSQuery::clear_hms_info()
{
std::unique_lock unique_lock(m_hms_mutex);
m_hms_info_jsons.clear();
m_hms_action_jsons.clear();
m_cloud_hms_last_update_time.clear();
}
void HMSQuery::init_hms_info(const std::string& dev_type_id)
{
std::unique_lock unique_lock(m_hms_mutex);
if (package_dev_id_types.count(dev_type_id) != 0)
{
/*the local one only load once*/
if (m_hms_info_jsons.count(dev_type_id) == 0) {
std::string load_version;
load_from_local(QUERY_HMS_INFO, dev_type_id, &m_hms_info_jsons[dev_type_id], load_version);/*load from local first*/
if (load_version.empty() || load_version == "0") {
copy_from_data_dir_to_local(); // STUDIO-9512
load_from_local(QUERY_HMS_INFO, dev_type_id, &m_hms_info_jsons[dev_type_id], load_version);/*copy files to local, and retry load*/
}
}
if (m_hms_action_jsons.count(dev_type_id) == 0) {
std::string load_version;
load_from_local(QUERY_HMS_ACTION, dev_type_id, &m_hms_action_jsons[dev_type_id], load_version);/*load from local first*/
if (load_version.empty() || load_version == "0") {
copy_from_data_dir_to_local(); // STUDIO-9512
load_from_local(QUERY_HMS_ACTION, dev_type_id, &m_hms_action_jsons[dev_type_id], load_version);/*copy files to local, and retry load*/
}
}
}
/*download from cloud*/
time_t info_last_update_time = m_cloud_hms_last_update_time[dev_type_id];
/* check hms is valid or not */
bool retry = false;
if(m_hms_info_jsons[dev_type_id].empty() || m_hms_action_jsons[dev_type_id].empty()){
retry =time(nullptr) - info_last_update_time > (60 * 1); // retry after 1 minute
}
if (time(nullptr) - info_last_update_time > (60 * 60 * 24) || retry)/*do not update in one day to reduce waiting*/
{
download_hms_related(QUERY_HMS_INFO, dev_type_id, &m_hms_info_jsons[dev_type_id]);
download_hms_related(QUERY_HMS_ACTION, dev_type_id, &m_hms_action_jsons[dev_type_id]);
m_cloud_hms_last_update_time[dev_type_id] = time(nullptr);
}
}
std::string get_hms_wiki_url(std::string error_code)
{
AppConfig* config = wxGetApp().app_config;
if (!config) return "";
if (should_disable_hms()) return "";
std::string hms_host = wxGetApp().app_config->get_hms_host();
std::string lang_code = HMSQuery::hms_language_code();
std::string url = (boost::format("https://%1%/index.php?e=%2%&s=device_hms&lang=%3%")
% hms_host
% error_code
% lang_code).str();
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!dev) return url;
MachineObject* obj = dev->get_selected_machine();
if (!obj) return url;
if (!obj->get_dev_id().empty()) {
url = (boost::format("https://%1%/index.php?e=%2%&d=%3%&s=device_hms&lang=%4%")
% hms_host
% error_code
% obj->get_dev_id()
% lang_code).str();
}
return url;
}
std::string get_error_message(int error_code)
{
if (should_disable_hms()) return "";
char buf[64];
std::string result_str = "";
std::sprintf(buf,"%08X",error_code);
std::string hms_host = wxGetApp().app_config->get_hms_host();
std::string get_lang = wxGetApp().app_config->get_language_code();
std::string url = (boost::format("https://%1%/query.php?lang=%2%&e=%3%")
%hms_host
%get_lang
%buf).str();
Slic3r::Http http = Slic3r::Http::get(url);
http.header("accept", "application/json")
.timeout_max(10)
.on_complete([get_lang, &result_str](std::string body, unsigned status) {
try {
json j = json::parse(body);
if (j.contains("result")) {
if (j["result"].get<int>() == 0) {
if (j.contains("data")) {
json jj = j["data"];
if (jj.contains("device_error")) {
if (jj["device_error"].contains(get_lang)) {
if (jj["device_error"][get_lang].size() > 0) {
if (!jj["device_error"][get_lang][0]["intro"].empty() || !jj["device_error"][get_lang][0]["ecode"].empty()) {
std::string error_info = jj["device_error"][get_lang][0]["intro"].get<std::string>();
std::string error_code = jj["device_error"][get_lang][0]["ecode"].get<std::string>();
error_code.insert(4, " ");
result_str = from_u8(error_info).ToStdString() + "[" + error_code + "]";
}
}
}
}
}
}
}
} catch (...) {
;
}
})
.on_error([](std::string body, std::string error, unsigned status) {
BOOST_LOG_TRIVIAL(info) << boost::format("[BBL ErrorMessage]: status=%1%, error=%2%, body=%3%") % status % error % body;
}).perform_sync();
return result_str;
}
}
}