#pragma once #include "libslic3r/CommonDefs.hpp" #include "slic3r/Utils/json_diff.hpp" #include "DevDefs.h" #include "DevFilaAmsSetting.h" #include "DevUtil.h" #include #include #include #include #include #include #include #include #define HOLD_COUNT_MAX 3 namespace Slic3r { class MachineObject; struct DevFilamentDryingPreset; /** * DevAmsTray - Represents a single filament tray/slot in an AMS unit or virtual tray. * * Data Population: * ================ * This class is used in two contexts with different population paths: * * 1. AMS Trays (within DevFilaSystem): * NetworkAgent → MachineObject::parse_json() → DevFilaSystemParser::ParseV1_0() * * 2. Virtual Trays (MachineObject::vt_slot for external/manual filament): * NetworkAgent → MachineObject::parse_json() → MachineObject::parse_vt_tray() * * Key Fields Used by build_filament_ams_list(): * - setting_id: Filament preset identifier (tray_info_idx from printer) * - tag_uid: RFID tag unique ID for identifying filament spools * - m_fila_type: Filament material type (e.g., "PLA", "ABS", "PETG") * - color: Hex color string without '#' prefix (e.g., "FF0000") * - cols: Multi-color component list for gradient/multi-color filaments * - ctype: Color type indicator * - is_exists: Whether filament is currently loaded in the tray */ class DevAmsTray { public: DevAmsTray(std::string tray_id) { is_bbl = false; id = tray_id; } std::string id; std::string tag_uid; // tag_uid std::string setting_id; // tray_info_idx std::string filament_setting_id; // setting_id std::string m_fila_type; std::string sub_brands; std::string color; std::vector cols; std::string weight; std::string diameter; std::string temp; std::string time; std::string bed_temp_type; std::string bed_temp; std::string nozzle_temp_max; std::string nozzle_temp_min; std::string xcam_info; std::string uuid; int ctype = 0; float k = 0.0f; // k range: 0 ~ 0.5 float n = 0.0f; // k range: 0.6 ~ 2.0 int cali_idx = -1; // - 1 means default wxColour wx_color; bool is_bbl; bool is_exists = false; bool is_slot_placeholder = false; // Orca: True for empty tray slots from pull-mode agents int hold_count = 0; int remain = 0; // filament remain: 0 ~ 100 public: // operators bool operator==(DevAmsTray const& o) const { return id == o.id && m_fila_type == o.m_fila_type && filament_setting_id == o.filament_setting_id && color == o.color; } bool operator!=(DevAmsTray const& o) const { return !operator==(o); } // setters void reset(); void UpdateColorFromStr(const std::string& color); void set_hold_count() { hold_count = HOLD_COUNT_MAX; } // getter bool is_tray_info_ready() const; bool is_unset_third_filament() const; wxColour get_color() const { return decode_color(color); }; std::string get_display_filament_type() const; std::string get_filament_type(); std::optional get_ams_drying_preset() const; // static static wxColour decode_color(const std::string& color); }; /** * DevAms - Represents a single AMS (Automatic Material System) unit. * * An AMS unit is a physical hardware component that holds multiple filament trays. * Different printer models support different AMS variants with varying slot counts * and capabilities. * * Data Population: * ================ * Populated by DevFilaSystemParser from printer JSON messages received via NetworkAgent. * * Key Properties: * - m_ams_id: Unique identifier for this AMS unit (string, typically "0", "1", etc.) * - m_ext_id: Which extruder this AMS is connected to (for multi-extruder setups) * - m_trays: Map of tray IDs to DevAmsTray pointers containing filament data * * AMS Type Variants: * - AMS (type 1): Standard 4-slot AMS with humidity control * - AMS_LITE (type 2): Simplified version * - N3F/N3S (types 3,4): Newer variants with different humidity/drying support */ class DevAms { friend class DevFilaSystemParser; public: using AmsType = DevAmsType; static constexpr AmsType EXT_SPOOL = DevAmsType::EXT_SPOOL; static constexpr AmsType AMS = DevAmsType::AMS; static constexpr AmsType AMS_LITE = DevAmsType::AMS_LITE; static constexpr AmsType N3F = DevAmsType::N3F; static constexpr AmsType N3S = DevAmsType::N3S; public: enum class DryCtrlMode : int { Off = 0, OnTime = 1, OnHumidity = 2, }; enum class DryStatus : char { Off = 0, Checking = 1, Drying = 2, Cooling = 3, Stopping = 4, Error = 5, CannotStopHeatOutofControl = 6, PrdTesting = 7, }; enum class DrySubStatus { Off = 0, Heating = 1, Dehumidify = 2, }; enum class DryFanStatus : char { Off = 0, On = 1, }; enum class CannotDryReason : int { TaskOccupied = 0, InsufficientPower = 1, AmsBusy = 2, ConsumableAtAmsOutlet = 3, InitiatingAmsDrying = 4, NotSupportedIn2dMode = 5, DryingInProgress = 6, Upgrading = 7, InsufficientPowerNeedPluginPower = 8, FilamentAtAmsOutletManualUnload = 10, }; struct DrySettings { std::string dry_filament; int dry_temp = -1; // -1 means invalid int dry_hour = -1; // -1 means invalid, hours }; public: DevAms(const std::string& ams_id, int extruder_id, AmsType type); DevAms(const std::string& ams_id, int nozzle_id, int type); ~DevAms(); public: std::string GetAmsId() const { return m_ams_id; } wxString GetDisplayName() const; // display void SetAmsType(int type) { m_ams_type = (AmsType)type; } void SetAmsType(AmsType type) { m_ams_type = type; } AmsType GetAmsType() const { return m_ams_type; } // exist or not bool IsExist() const { return m_exist; } // slots int GetSlotCount() const; DevAmsTray* GetTray(const std::string& tray_id) const; const std::map& GetTrays() const { return m_trays; } // installed on the extruder int GetExtruderId() const { return m_ext_id; } // temperature and humidity float GetCurrentTemperature() const { return m_current_temperature; } bool SupportHumidity() const { return (m_ams_type == AMS) || (m_ams_type == N3F) || (m_ams_type == N3S);} int GetHumidityLevel() const { return m_humidity_level; } int GetHumidityPercent() const { return m_humidity_percent; } bool SupportDrying() const { return m_ams_type == N3F || m_ams_type == N3S; } int GetLeftDryTime() const { return m_left_dry_time; } // remote drying control bool IsSupportRemoteDry(const MachineObject* obj) const; std::optional GetDryStatus() const { return m_dry_status; }; std::optional GetDrySubStatus() const { return m_dry_sub_status; } std::optional GetFan1Status() const { return m_dry_fan1_status; } std::optional GetFan2Status() const { return m_dry_fan2_status; } std::optional> GetCannotDryReason() const { return m_dry_cannot_reasons; } std::optional GetDrySettings() const { return m_dry_settings; }; bool AmsIsDrying(); private: AmsType m_ams_type = AmsType::AMS; std::string m_ams_id; int m_ext_id;//extruder id bool m_exist = false; // slots and trays std::map m_trays;//id -> DevAmsTray* // temperature and humidity float m_current_temperature = INVALID_AMS_TEMPERATURE; // the temperature int m_humidity_level = 5; // AmsType::AMS int m_humidity_percent = -1; // N3F N3S, the percentage, -1 means invalid. eg. 100 means 100% int m_left_dry_time = 0; // see is_support_remote_dry std::optional m_dry_status; std::optional m_dry_sub_status; std::optional m_dry_fan1_status; std::optional m_dry_fan2_status; std::optional> m_dry_cannot_reasons; std::optional m_dry_settings; }; /** * DevFilaSystem - Central manager for all AMS-related data on a printer. * * This class owns and manages the hierarchy of AMS units (DevAms) and their trays (DevAmsTray). * It provides the primary interface for querying filament/AMS state used by the GUI. * * Data Flow Architecture: * ======================= * Printer Device (sends status via MQTT/LAN) * ↓ * NetworkAgent (receives JSON, invokes registered callbacks) * ↓ * MachineObject::parse_json() (delegates to DevFilaSystemParser) * ↓ * DevFilaSystemParser::ParseV1_0() (populates this DevFilaSystem instance) * ↓ * GUI functions like build_filament_ams_list() read from here * * Key Methods: * - GetAmsList(): Returns map of all AMS units (ams_id -> DevAms*) * - GetAmsTray(): Retrieves specific tray by AMS ID and tray ID * - HasAms(): Checks if any AMS units are connected * * Ownership: * - Owned by MachineObject (m_fila_system member) * - Owns all DevAms instances which in turn own DevAmsTray instances * * Note: This class does NOT directly communicate with NetworkAgent. * It is a passive data store populated by the parsing layer. */ class DevFilaSystem { friend class DevFilaSystemParser; public: DevFilaSystem(MachineObject* owner) { m_owner = owner;}; ~DevFilaSystem(); public: MachineObject* GetOwner() const { return m_owner; } bool HasAms() const { return !amsList.empty(); } bool IsAmsSettingUp() const; /* ams */ DevAms* GetAmsById(const std::string& ams_id) const; std::map& GetAmsList() { return amsList; } int GetAmsCount() const { return amsList.size(); } /* tray*/ DevAmsTray* GetAmsTray(const std::string& ams_id, const std::string& tray_id) const; void CollectAmsColors(std::vector& ams_colors) const; // extruder int GetExtruderIdByAmsId(const std::string& ams_id) const; /* AMS settings*/ DevAmsSystemSetting& GetAmsSystemSetting() { return m_ams_system_setting; } std::optional IsDetectOnInsertEnabled() const { return m_ams_system_setting.IsDetectOnInsertEnabled(); }; bool IsDetectOnPowerupEnabled() const { return m_ams_system_setting.IsDetectOnPowerupEnabled(); } bool IsDetectRemainEnabled() const { return m_ams_system_setting.IsDetectRemainEnabled(); } bool IsAutoRefillEnabled() const { return m_ams_system_setting.IsAutoRefillEnabled(); } std::weak_ptr GetAmsFirmwareSwitch() const { return m_ams_firmware_switch;} public: // ctrls int CtrlAmsReset() const; int CtrlAmsStartDryingHour(int ams_id, std::string filament_type, int tag_temp, int tag_duration_hour, bool rotate_tray, int cooling_temp, bool close_power_conflict = false) const; int CtrlAmsStopDrying(int ams_id) const; public: static bool IsBBL_Filament(std::string tag_uid); private: MachineObject* m_owner; /* ams properties */ int m_ams_cali_stat = 0; std::map amsList;// key: ams[id], start with 0 DevAmsSystemSetting m_ams_system_setting{ this }; std::shared_ptr m_ams_firmware_switch = DevAmsSystemFirmwareSwitch::Create(this); };// class DevFilaSystem /** * DevFilaSystemParser - Parses printer JSON messages to populate DevFilaSystem. * * This is the bridge between NetworkAgent's raw JSON data and the structured * DevFilaSystem/DevAms/DevAmsTray hierarchy. * * Called from MachineObject::parse_json() when AMS-related fields are present * in printer status messages received via MQTT or LAN communication. * * @see MachineObject::parse_json() - Entry point for JSON parsing * @see DevFilaSystem - Target data structure */ class DevFilaSystemParser { public: static void ParseV1_0(const json& print_json, MachineObject* obj, DevFilaSystem* system, bool key_field_only); }; struct DevFilamentDryingPreset { std::string filament_id; std::unordered_set ams_limitations; // only use ams types in the set std::unordered_map filament_dev_ams_drying_time_on_idle; // hour std::unordered_map filament_dev_ams_drying_temperature_on_idle; std::unordered_map filament_dev_ams_drying_time_on_print; // hour std::unordered_map filament_dev_ams_drying_temperature_on_print; float filament_dev_drying_cooling_temperature = 0.0f; float filament_dev_drying_softening_temperature = 0.0f; float filament_dev_ams_drying_heat_distortion_temperature = 0.0f; }; }// namespace Slic3r