Files
OrcaSlicer/src/slic3r/GUI/DeviceCore/DevFilaSystem.h

387 lines
13 KiB
C++

#pragma once
#include "libslic3r/CommonDefs.hpp"
#include "slic3r/Utils/json_diff.hpp"
#include "DevDefs.h"
#include "DevFilaAmsSetting.h"
#include "DevUtil.h"
#include <map>
#include <optional>
#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <wx/string.h>
#include <wx/colour.h>
#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<std::string> 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<DevFilamentDryingPreset> 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<std::string, DevAmsTray*>& 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<DryStatus> GetDryStatus() const { return m_dry_status; };
std::optional<DrySubStatus> GetDrySubStatus() const { return m_dry_sub_status; }
std::optional<DryFanStatus> GetFan1Status() const { return m_dry_fan1_status; }
std::optional<DryFanStatus> GetFan2Status() const { return m_dry_fan2_status; }
std::optional<std::vector<CannotDryReason>> GetCannotDryReason() const { return m_dry_cannot_reasons; }
std::optional<DrySettings> 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<std::string, DevAmsTray*> 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<DryStatus> m_dry_status;
std::optional<DrySubStatus> m_dry_sub_status;
std::optional<DryFanStatus> m_dry_fan1_status;
std::optional<DryFanStatus> m_dry_fan2_status;
std::optional<std::vector<CannotDryReason>> m_dry_cannot_reasons;
std::optional<DrySettings> 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<std::string, DevAms*, NumericStrCompare>& 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<wxColour>& ams_colors) const;
// extruder
int GetExtruderIdByAmsId(const std::string& ams_id) const;
/* AMS settings*/
DevAmsSystemSetting& GetAmsSystemSetting() { return m_ams_system_setting; }
std::optional<bool> 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<DevAmsSystemFirmwareSwitch> 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<std::string, DevAms*, NumericStrCompare> amsList;// key: ams[id], start with 0
DevAmsSystemSetting m_ams_system_setting{ this };
std::shared_ptr<DevAmsSystemFirmwareSwitch> 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<DevAmsType> ams_limitations; // only use ams types in the set
std::unordered_map<DevAmsType, float> filament_dev_ams_drying_time_on_idle; // hour
std::unordered_map<DevAmsType, float> filament_dev_ams_drying_temperature_on_idle;
std::unordered_map<DevAmsType, float> filament_dev_ams_drying_time_on_print; // hour
std::unordered_map<DevAmsType, float> 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