mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-26 18:31:11 +00:00
Merge branch 'main' of https://github.com/OrcaSlicer/OrcaSlicer_priv into feat/printer-agent-impl
This commit is contained in:
@@ -2,10 +2,17 @@
|
||||
#include "BBLNetworkPlugin.hpp"
|
||||
#include "IPrinterAgent.hpp"
|
||||
#include "NetworkAgentFactory.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "NetworkAgent.hpp"
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <nlohmann/json.hpp>
|
||||
using json = nlohmann::json;
|
||||
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <cmath>
|
||||
@@ -13,6 +20,120 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace {
|
||||
|
||||
// Bambu's own catalog ids for every filament this app ships, Bambu's own included, since Orca
|
||||
// content-addresses those too. Keyed both ways so each of the four translation entry points
|
||||
// below is a single lookup. Loaded once per process, on first use. A missing or malformed file
|
||||
// logs once and leaves both maps empty, so every translation degrades to identity. Same shape
|
||||
// as DevFilaBlacklist::load_filaments_blacklist_config.
|
||||
struct BambuFilamentIdMap { std::unordered_map<std::string, std::string> to_bambu, to_orca; };
|
||||
|
||||
const BambuFilamentIdMap& bambu_filament_id_map()
|
||||
{
|
||||
static const BambuFilamentIdMap map = [] {
|
||||
BambuFilamentIdMap m;
|
||||
const std::string path = resources_dir() + "/printers/bambu_filament_ids.json";
|
||||
try {
|
||||
boost::nowide::ifstream file(path);
|
||||
if (!file.is_open()) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Bambu filament id map not found, ids pass through untranslated: " << path;
|
||||
return m;
|
||||
}
|
||||
json doc;
|
||||
file >> doc;
|
||||
for (const auto& [orca_filament_id, row] : doc.at("filaments").items()) {
|
||||
const std::string bambu_id = row.at("bambu_id").get<std::string>();
|
||||
m.to_bambu.emplace(orca_filament_id, bambu_id);
|
||||
m.to_orca.emplace(bambu_id, orca_filament_id);
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Bambu filament id map unreadable, ids pass through untranslated: " << e.what();
|
||||
m = {};
|
||||
}
|
||||
return m;
|
||||
}();
|
||||
return map;
|
||||
}
|
||||
|
||||
// Rewrites every string under "tray_info_idx", "filament_id" or "filamentId", at any depth, in place.
|
||||
void rewrite_filament_ids(json& j, const std::unordered_map<std::string, std::string>& map)
|
||||
{
|
||||
if (j.is_object()) {
|
||||
for (auto& [key, value] : j.items()) {
|
||||
if (value.is_string() && (key == "tray_info_idx" || key == "filament_id" || key == "filamentId")) {
|
||||
auto it = map.find(value.get_ref<const std::string&>());
|
||||
if (it != map.end())
|
||||
value = it->second;
|
||||
} else
|
||||
rewrite_filament_ids(value, map);
|
||||
}
|
||||
} else if (j.is_array())
|
||||
for (auto& element : j)
|
||||
rewrite_filament_ids(element, map);
|
||||
}
|
||||
|
||||
// Text that does not parse as JSON, or that mentions none of the id keys, comes back byte-identical.
|
||||
std::string rewrite_filament_ids(std::string text, const std::unordered_map<std::string, std::string>& map)
|
||||
{
|
||||
if (map.empty() || (text.find("tray_info_idx") == std::string::npos && text.find("filament_id") == std::string::npos &&
|
||||
text.find("filamentId") == std::string::npos))
|
||||
return text; // nothing to map, skip the parse (moved, not copied)
|
||||
try {
|
||||
json j = json::parse(text);
|
||||
rewrite_filament_ids(j, map);
|
||||
return j.dump();
|
||||
} catch (const std::exception&) {
|
||||
return text; // not JSON: forward as received
|
||||
}
|
||||
}
|
||||
|
||||
// Wraps an inbound message callback so every Bambu id it delivers arrives already translated.
|
||||
// A null fn is a deregistration (see GUI_App.cpp's shutdown phase 1 and NetworkAgent::apply_printer_callbacks
|
||||
// clearing callbacks with {}), and must stay null rather than become a live wrapper around an empty target.
|
||||
OnMessageFn to_orca_messages(OnMessageFn fn)
|
||||
{
|
||||
if (!fn)
|
||||
return fn;
|
||||
return [fn = std::move(fn)](std::string dev_id, std::string msg) { fn(std::move(dev_id), BBLPrinterAgent::to_orca_payload(std::move(msg))); };
|
||||
}
|
||||
|
||||
// Retypes a plug-in entry point for an older plug-in generation. The detour through the
|
||||
// generic function pointer marks the signature change as deliberate, which a direct cast
|
||||
// between two signatures does not.
|
||||
template <typename To, typename From>
|
||||
To as_abi(From fn)
|
||||
{
|
||||
static_assert(std::is_function_v<std::remove_pointer_t<From>>, "as_abi retypes a function pointer");
|
||||
return reinterpret_cast<To>(reinterpret_cast<void (*)()>(fn));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string BBLPrinterAgent::to_orca_filament_id(const std::string& printer_filament_id) const
|
||||
{
|
||||
const auto& map = bambu_filament_id_map().to_orca;
|
||||
auto it = map.find(printer_filament_id);
|
||||
return it != map.end() ? it->second : printer_filament_id;
|
||||
}
|
||||
|
||||
std::string BBLPrinterAgent::from_orca_filament_id(const std::string& orca_filament_id) const
|
||||
{
|
||||
const auto& map = bambu_filament_id_map().to_bambu;
|
||||
auto it = map.find(orca_filament_id);
|
||||
return it != map.end() ? it->second : orca_filament_id;
|
||||
}
|
||||
|
||||
std::string BBLPrinterAgent::to_orca_payload(std::string json_text)
|
||||
{
|
||||
return rewrite_filament_ids(std::move(json_text), bambu_filament_id_map().to_orca);
|
||||
}
|
||||
|
||||
std::string BBLPrinterAgent::from_orca_payload(std::string json_text)
|
||||
{
|
||||
return rewrite_filament_ids(std::move(json_text), bambu_filament_id_map().to_bambu);
|
||||
}
|
||||
|
||||
BBLPrinterAgent::BBLPrinterAgent() = default;
|
||||
|
||||
BBLPrinterAgent::~BBLPrinterAgent() = default;
|
||||
@@ -186,6 +307,7 @@ int BBLPrinterAgent::publish(const std::string& dev_id, const nlohmann::json& j,
|
||||
|
||||
int BBLPrinterAgent::send_message(std::string dev_id, std::string json_str, int qos, int flag)
|
||||
{
|
||||
json_str = from_orca_payload(std::move(json_str));
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_send_message();
|
||||
@@ -194,7 +316,7 @@ int BBLPrinterAgent::send_message(std::string dev_id, std::string json_str, int
|
||||
// series through the legacy form would silently drop MessageFlag sign/encrypt.
|
||||
switch (plugin.network_abi()) {
|
||||
case NetworkAbi::Legacy: {
|
||||
auto legacy_func = reinterpret_cast<func_send_message_legacy>(func);
|
||||
auto legacy_func = as_abi<func_send_message_legacy>(func);
|
||||
return legacy_func(agent, std::move(dev_id), std::move(json_str), qos);
|
||||
}
|
||||
case NetworkAbi::V0203:
|
||||
@@ -231,13 +353,14 @@ int BBLPrinterAgent::disconnect_printer()
|
||||
|
||||
int BBLPrinterAgent::send_message_to_printer(std::string dev_id, std::string json_str, int qos, int flag)
|
||||
{
|
||||
json_str = from_orca_payload(std::move(json_str));
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_send_message_to_printer();
|
||||
if (func && agent) {
|
||||
switch (plugin.network_abi()) {
|
||||
case NetworkAbi::Legacy: {
|
||||
auto legacy_func = reinterpret_cast<func_send_message_to_printer_legacy>(func);
|
||||
auto legacy_func = as_abi<func_send_message_to_printer_legacy>(func);
|
||||
return legacy_func(agent, std::move(dev_id), std::move(json_str), qos);
|
||||
}
|
||||
case NetworkAbi::V0203:
|
||||
@@ -327,7 +450,7 @@ int BBLPrinterAgent::bind(std::string dev_ip, std::string dev_id, std::string de
|
||||
switch (plugin.network_abi()) {
|
||||
case NetworkAbi::Legacy:
|
||||
case NetworkAbi::V0203: {
|
||||
auto older_func = reinterpret_cast<func_bind_pre0208>(func);
|
||||
auto older_func = as_abi<func_bind_pre0208>(func);
|
||||
return older_func(agent, dev_ip, dev_id, sec_link, timezone, improved, update_fn);
|
||||
}
|
||||
case NetworkAbi::Current:
|
||||
@@ -485,11 +608,12 @@ int dispatch_start(CurrentFn func, PrintParams& params, const CallbackFns&... ca
|
||||
auto agent = plugin.get_agent();
|
||||
if (!func || !agent)
|
||||
return -1;
|
||||
params.ams_mapping_info = BBLPrinterAgent::from_orca_payload(std::move(params.ams_mapping_info));
|
||||
switch (plugin.network_abi()) {
|
||||
case NetworkAbi::Legacy:
|
||||
return reinterpret_cast<LegacyFn>(func)(agent, BBLNetworkPlugin::as_legacy(params), callbacks...);
|
||||
return as_abi<LegacyFn>(func)(agent, BBLNetworkPlugin::as_legacy(params), callbacks...);
|
||||
case NetworkAbi::V0203:
|
||||
return reinterpret_cast<Fn0203>(func)(agent, BBLNetworkPlugin::as_0203(params), callbacks...);
|
||||
return as_abi<Fn0203>(func)(agent, BBLNetworkPlugin::as_0203(params), callbacks...);
|
||||
case NetworkAbi::Current:
|
||||
return func(agent, std::move(params), callbacks...);
|
||||
default:
|
||||
@@ -579,7 +703,7 @@ int BBLPrinterAgent::set_on_message_fn(OnMessageFn fn)
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_on_message_fn();
|
||||
if (func && agent) {
|
||||
return func(agent, fn);
|
||||
return func(agent, to_orca_messages(std::move(fn)));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -612,7 +736,7 @@ int BBLPrinterAgent::set_on_local_message_fn(OnMessageFn fn)
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_on_local_message_fn();
|
||||
if (func && agent) {
|
||||
return func(agent, fn);
|
||||
return func(agent, to_orca_messages(std::move(fn)));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user