#include #include "DevFilaSystem.h" // TODO: remove this include #include "slic3r/GUI/DeviceManager.hpp" #include "slic3r/GUI/I18N.hpp" #include "DevUtil.h" using namespace nlohmann; namespace Slic3r { static int _hex_digit_to_int(const char c) { return (c >= '0' && c <= '9') ? c - '0' : (c >= 'A' && c <= 'F') ? c - 'A' + 10 : (c >= 'a' && c <= 'f') ? c - 'a' + 10 : -1; } wxColour DevAmsTray::decode_color(const std::string &color) { std::array ret = {0, 0, 0, 0}; const char * c = color.data(); if (color.size() == 8) { for (size_t j = 0; j < 4; ++j) { int digit1 = _hex_digit_to_int(*c++); int digit2 = _hex_digit_to_int(*c++); if (digit1 == -1 || digit2 == -1) break; ret[j] = static_cast(digit1 * 16 + digit2); } } else { return wxColour(255, 255, 255, 255); } return wxColour(ret[0], ret[1], ret[2], ret[3]); } void DevAmsTray::UpdateColorFromStr(const std::string& color) { if (color.empty()) return; if (this->color != color) { wx_color = "#" + wxString::FromUTF8(color); this->color = color; } } void DevAmsTray::reset() { tag_uid = ""; setting_id = ""; filament_setting_id = ""; type = ""; sub_brands = ""; color = ""; weight = ""; diameter = ""; temp = ""; time = ""; bed_temp_type = ""; bed_temp = ""; nozzle_temp_max = ""; nozzle_temp_min = ""; xcam_info = ""; uuid = ""; k = 0.0f; n = 0.0f; is_bbl = false; hold_count = 0; remain = 0; } bool DevAmsTray::is_tray_info_ready() const { if (color.empty()) return false; if (type.empty()) return false; //if (setting_id.empty()) return false; return true; } bool DevAmsTray::is_unset_third_filament() const { if (this->is_bbl) return false; return (color.empty() || type.empty()); } std::string DevAmsTray::get_display_filament_type() const { if (type == "PLA-S") return "Sup.PLA"; if (type == "PA-S") return "Sup.PA"; if (type == "ABS-S") return "Sup.ABS"; return type; } std::string DevAmsTray::get_filament_type() { if (type == "Sup.PLA") { return "PLA-S"; } if (type == "Sup.PA") { return "PA-S"; } if (type == "Sup.ABS") { return "ABS-S"; } if (type == "Support W") { return "PLA-S"; } if (type == "Support G") { return "PA-S"; } if (type == "Support") { if (setting_id == "GFS00") { type = "PLA-S"; } else if (setting_id == "GFS01") { type = "PA-S"; } else { return "PLA-S"; } } return type; } DevAms::DevAms(const std::string& ams_id, int extruder_id, AmsType type) { m_ams_id = ams_id; m_ext_id = extruder_id; m_ams_type = type; } DevAms::DevAms(const std::string& ams_id, int nozzle_id, int type) { m_ams_id = ams_id; m_ext_id = nozzle_id; m_ams_type = (AmsType)type; assert(DUMMY < type && m_ams_type <= N3S); } DevAms::~DevAms() { for (auto it = m_trays.begin(); it != m_trays.end(); it++) { if (it->second) { delete it->second; it->second = nullptr; } } m_trays.clear(); } static unordered_map s_ams_display_formats = { {DevAms::AMS, "AMS-%d"}, {DevAms::AMS_LITE, "AMS Lite-%d"}, {DevAms::N3F, "AMS 2 PRO-%d"}, {DevAms::N3S, "AMS HT-%d"} }; wxString DevAms::GetDisplayName() const { wxString ams_display_format; auto iter = s_ams_display_formats.find(m_ams_type); if (iter != s_ams_display_formats.end()) { ams_display_format = iter->second; } else { assert(0 && __FUNCTION__); ams_display_format = "AMS-%d"; } int num_id; try { num_id = std::stoi(GetAmsId()); } catch (const std::exception& e) { assert(0 && __FUNCTION__); BOOST_LOG_TRIVIAL(error) << "Invalid AMS ID: " << GetAmsId() << ", error: " << e.what(); num_id = 0; } int loc = (num_id > 127) ? (num_id - 127) : (num_id + 1); return wxString::Format(ams_display_format, loc); } int DevAms::GetSlotCount() const { if (m_ams_type == AMS || m_ams_type == AMS_LITE || m_ams_type == N3F) { return 4; } else if (m_ams_type == N3S) { return 1; } return 1; } DevAmsTray* DevAms::GetTray(const std::string& tray_id) const { auto it = m_trays.find(tray_id); if (it != m_trays.end()) { return it->second; } return nullptr; } DevFilaSystem::~DevFilaSystem() { for (auto it = amsList.begin(); it != amsList.end(); it++) { if (it->second) { delete it->second; it->second = nullptr; } } amsList.clear(); } DevAms* DevFilaSystem::GetAmsById(const std::string& ams_id) const { auto it = amsList.find(ams_id); if (it != amsList.end()) { return it->second; } return nullptr; } DevAmsTray* DevFilaSystem::GetAmsTray(const std::string& ams_id, const std::string& tray_id) const { auto it = amsList.find(ams_id); if (it == amsList.end()) return nullptr; if (!it->second) return nullptr; return it->second->GetTray(tray_id);; } void DevFilaSystem::CollectAmsColors(std::vector& ams_colors) const { ams_colors.clear(); ams_colors.reserve(amsList.size()); for (auto ams = amsList.begin(); ams != amsList.end(); ams++) { for (auto tray = ams->second->GetTrays().begin(); tray != ams->second->GetTrays().end(); tray++) { if (tray->second->is_tray_info_ready()) { auto ams_color = DevAmsTray::decode_color(tray->second->color); ams_colors.emplace_back(ams_color); } } } } int DevFilaSystem::GetExtruderIdByAmsId(const std::string& ams_id) const { auto it = amsList.find(ams_id); if (it != amsList.end()) { return it->second->GetExtruderId(); } else if (stoi(ams_id) == VIRTUAL_TRAY_MAIN_ID) { return MAIN_EXTRUDER_ID; } else if (stoi(ams_id) == VIRTUAL_TRAY_DEPUTY_ID) { return DEPUTY_EXTRUDER_ID; } assert(false && __FUNCTION__); return 0; // not found } bool DevFilaSystem::IsAmsSettingUp() const { int setting_up_stat = DevUtil::get_flag_bits(m_ams_cali_stat, 0, 8); if (setting_up_stat == 0x01 || setting_up_stat == 0x02 || setting_up_stat == 0x03 || setting_up_stat == 0x04) { return true; } return false; } bool DevFilaSystem::IsBBL_Filament(std::string tag_uid) { if (tag_uid.empty()) { return false; } for (int i = 0; i < tag_uid.length(); i++) { if (tag_uid[i] != '0') { return true; } } return false; } void DevFilaSystemParser::ParseV1_0(const json& jj, MachineObject* obj, DevFilaSystem* system, bool key_field_only) { if (jj.contains("ams")) { if (jj["ams"].contains("ams")) { if (jj["ams"].contains("ams_exist_bits")) { obj->ams_exist_bits = stol(jj["ams"]["ams_exist_bits"].get(), nullptr, 16); } if (jj["ams"].contains("tray_exist_bits")) { obj->tray_exist_bits = stol(jj["ams"]["tray_exist_bits"].get(), nullptr, 16); } if (jj["ams"].contains("cali_stat")) { system->m_ams_cali_stat = jj["ams"]["cali_stat"].get(); } if (!key_field_only) { if (jj["ams"].contains("tray_read_done_bits")) { obj->tray_read_done_bits = stol(jj["ams"]["tray_read_done_bits"].get(), nullptr, 16); } if (jj["ams"].contains("tray_reading_bits")) { obj->tray_reading_bits = stol(jj["ams"]["tray_reading_bits"].get(), nullptr, 16); } if (jj["ams"].contains("tray_is_bbl_bits")) { obj->tray_is_bbl_bits = stol(jj["ams"]["tray_is_bbl_bits"].get(), nullptr, 16); } if (jj["ams"].contains("version")) { if (jj["ams"]["version"].is_number()) { obj->ams_version = jj["ams"]["version"].get(); } } #if 0 if (jj["ams"].contains("ams_rfid_status")) { } #endif if (time(nullptr) - obj->ams_user_setting_start > HOLD_TIME_3SEC) { if (jj["ams"].contains("insert_flag")) { system->m_ams_system_setting.SetDetectOnInsertEnabled(jj["ams"]["insert_flag"].get()); } if (jj["ams"].contains("power_on_flag")) { system->m_ams_system_setting.SetDetectOnPowerupEnabled(jj["ams"]["power_on_flag"].get()); } if (jj["ams"].contains("calibrate_remain_flag")) { system->m_ams_system_setting.SetDetectRemainEnabled(jj["ams"]["calibrate_remain_flag"].get()); } } json j_ams = jj["ams"]["ams"]; std::set ams_id_set; for (auto it = system->amsList.begin(); it != system->amsList.end(); it++) { ams_id_set.insert(it->first); } for (auto it = j_ams.begin(); it != j_ams.end(); it++) { if (!it->contains("id")) continue; std::string ams_id = (*it)["id"].get(); int extuder_id = MAIN_EXTRUDER_ID; // Default nozzle id int type_id = 1; // 0:dummy 1:ams 2:ams-lite 3:n3f 4:n3s /*ams info*/ if (it->contains("info")) { const std::string& info = (*it)["info"].get(); type_id = DevUtil::get_flag_bits(info, 0, 4); extuder_id = DevUtil::get_flag_bits(info, 8, 4); } /*AMS without initialization*/ if (extuder_id == 0xE) { ams_id_set.erase(ams_id); system->amsList.erase(ams_id); continue; } ams_id_set.erase(ams_id); DevAms* curr_ams = nullptr; auto ams_it = system->amsList.find(ams_id); if (ams_it == system->amsList.end()) { DevAms* new_ams = new DevAms(ams_id, extuder_id, type_id); system->amsList.insert(std::make_pair(ams_id, new_ams)); // new ams added event curr_ams = new_ams; } else { if (extuder_id != ams_it->second->GetExtruderId()) { ams_it->second->m_ext_id = extuder_id; } curr_ams = ams_it->second; } if (!curr_ams) continue; /*set ams type flag*/ curr_ams->SetAmsType(type_id); /*set ams exist flag*/ try { if (!ams_id.empty()) { int ams_id_int = atoi(ams_id.c_str()); if (type_id < 4) { curr_ams->m_exist = (obj->ams_exist_bits & (1 << ams_id_int)) != 0 ? true : false; } else { curr_ams->m_exist = DevUtil::get_flag_bits(obj->ams_exist_bits, 4 + (ams_id_int - 128)); } } } catch (...) { ; } if (it->contains("dry_time") && (*it)["dry_time"].is_number()) { curr_ams->m_left_dry_time = (*it)["dry_time"].get(); } if (it->contains("humidity")) { try { std::string humidity = (*it)["humidity"].get(); curr_ams->m_humidity_level = atoi(humidity.c_str()); } catch (...) { ; } } if (it->contains("humidity_raw")) { try { std::string humidity_raw = (*it)["humidity_raw"].get(); curr_ams->m_humidity_percent = atoi(humidity_raw.c_str()); } catch (...) { ; } } if (it->contains("temp")) { std::string temp = (*it)["temp"].get(); try { curr_ams->m_current_temperature = DevUtil::string_to_float(temp); } catch (...) { curr_ams->m_current_temperature = INVALID_AMS_TEMPERATURE; } } if (it->contains("tray")) { std::set tray_id_set; for (auto it = curr_ams->GetTrays().cbegin(); it != curr_ams->GetTrays().cend(); it++) { tray_id_set.insert(it->first); } for (auto tray_it = (*it)["tray"].begin(); tray_it != (*it)["tray"].end(); tray_it++) { if (!tray_it->contains("id")) continue; std::string tray_id = (*tray_it)["id"].get(); tray_id_set.erase(tray_id); // compare tray_list DevAmsTray* curr_tray = nullptr; auto tray_iter = curr_ams->GetTrays().find(tray_id); if (tray_iter == curr_ams->GetTrays().end()) { DevAmsTray* new_tray = new DevAmsTray(tray_id); curr_ams->m_trays.insert(std::make_pair(tray_id, new_tray)); curr_tray = new_tray; } else { curr_tray = tray_iter->second; } if (!curr_tray) continue; if (curr_tray->hold_count > 0) { curr_tray->hold_count--; continue; } curr_tray->id = (*tray_it)["id"].get(); if (tray_it->contains("tag_uid")) curr_tray->tag_uid = (*tray_it)["tag_uid"].get(); else curr_tray->tag_uid = "0"; if (tray_it->contains("tray_info_idx") && tray_it->contains("tray_type")) { curr_tray->setting_id = (*tray_it)["tray_info_idx"].get(); //std::string type = (*tray_it)["tray_type"].get(); std::string type = MachineObject::setting_id_to_type(curr_tray->setting_id, (*tray_it)["tray_type"].get()); if (curr_tray->setting_id == "GFS00") { curr_tray->type = "PLA-S"; } else if (curr_tray->setting_id == "GFS01") { curr_tray->type = "PA-S"; } else { curr_tray->type = type; } } else { curr_tray->setting_id = ""; curr_tray->type = ""; } if (tray_it->contains("tray_sub_brands")) curr_tray->sub_brands = (*tray_it)["tray_sub_brands"].get(); else curr_tray->sub_brands = ""; if (tray_it->contains("tray_weight")) curr_tray->weight = (*tray_it)["tray_weight"].get(); else curr_tray->weight = ""; if (tray_it->contains("tray_diameter")) curr_tray->diameter = (*tray_it)["tray_diameter"].get(); else curr_tray->diameter = ""; if (tray_it->contains("tray_temp")) curr_tray->temp = (*tray_it)["tray_temp"].get(); else curr_tray->temp = ""; if (tray_it->contains("tray_time")) curr_tray->time = (*tray_it)["tray_time"].get(); else curr_tray->time = ""; if (tray_it->contains("bed_temp_type")) curr_tray->bed_temp_type = (*tray_it)["bed_temp_type"].get(); else curr_tray->bed_temp_type = ""; if (tray_it->contains("bed_temp")) curr_tray->bed_temp = (*tray_it)["bed_temp"].get(); else curr_tray->bed_temp = ""; if (tray_it->contains("tray_color")) { auto color = (*tray_it)["tray_color"].get(); curr_tray->UpdateColorFromStr(color); } else { curr_tray->color = ""; } if (tray_it->contains("nozzle_temp_max")) { curr_tray->nozzle_temp_max = (*tray_it)["nozzle_temp_max"].get(); } else curr_tray->nozzle_temp_max = ""; if (tray_it->contains("nozzle_temp_min")) curr_tray->nozzle_temp_min = (*tray_it)["nozzle_temp_min"].get(); else curr_tray->nozzle_temp_min = ""; if (tray_it->contains("xcam_info")) curr_tray->xcam_info = (*tray_it)["xcam_info"].get(); else curr_tray->xcam_info = ""; if (tray_it->contains("tray_uuid")) curr_tray->uuid = (*tray_it)["tray_uuid"].get(); else curr_tray->uuid = "0"; if (tray_it->contains("ctype")) curr_tray->ctype = (*tray_it)["ctype"].get(); else curr_tray->ctype = 0; curr_tray->cols.clear(); if (tray_it->contains("cols")) { if ((*tray_it)["cols"].is_array()) { for (auto it = (*tray_it)["cols"].begin(); it != (*tray_it)["cols"].end(); it++) { curr_tray->cols.push_back(it.value().get()); } } } if (tray_it->contains("remain")) { curr_tray->remain = (*tray_it)["remain"].get(); } else { curr_tray->remain = -1; } int ams_id_int = 0; int tray_id_int = 0; try { if (!ams_id.empty() && !curr_tray->id.empty()) { ams_id_int = atoi(ams_id.c_str()); tray_id_int = atoi(curr_tray->id.c_str()); if (type_id < 4) { curr_tray->is_exists = (obj->tray_exist_bits & (1 << (ams_id_int * 4 + tray_id_int))) != 0 ? true : false; } else { curr_tray->is_exists = DevUtil::get_flag_bits(obj->tray_exist_bits, 16 + (ams_id_int - 128)); } } } catch (...) { } if (tray_it->contains("setting_id")) { curr_tray->filament_setting_id = (*tray_it)["setting_id"].get(); } auto curr_time = std::chrono::system_clock::now(); auto diff = std::chrono::duration_cast(curr_time - obj->extrusion_cali_set_hold_start); if (diff.count() > HOLD_TIMEOUT || diff.count() < 0 || ams_id_int != (obj->extrusion_cali_set_tray_id / 4) || tray_id_int != (obj->extrusion_cali_set_tray_id % 4)) { if (tray_it->contains("k")) { curr_tray->k = (*tray_it)["k"].get(); } if (tray_it->contains("n")) { curr_tray->n = (*tray_it)["n"].get(); } } std::string temp = tray_it->dump(); if (tray_it->contains("cali_idx")) { curr_tray->cali_idx = (*tray_it)["cali_idx"].get(); } } // remove not in trayList for (auto tray_it = tray_id_set.begin(); tray_it != tray_id_set.end(); tray_it++) { std::string tray_id = *tray_it; auto tray = curr_ams->GetTrays().find(tray_id); if (tray != curr_ams->GetTrays().end()) { curr_ams->m_trays.erase(tray_id); BOOST_LOG_TRIVIAL(trace) << "parse_json: remove ams_id=" << ams_id << ", tray_id=" << tray_id; } } } } // remove not in amsList for (auto it = ams_id_set.begin(); it != ams_id_set.end(); it++) { std::string ams_id = *it; auto ams = system->amsList.find(ams_id); if (ams != system->amsList.end()) { BOOST_LOG_TRIVIAL(trace) << "parse_json: remove ams_id=" << ams_id; system->amsList.erase(ams_id); } } } } } } }