Files
OrcaSlicer/docs/U1_Filament_Compatibility_Fix.md
xiaoyeliu 5989d15428 feature: add filename validation & check the compatiblity of the filament from device (#132)
* Fix: didn't check the compatiblity of the filament which is gotten from machine

* Optimize the filename validation
2026-01-22 18:30:38 +08:00

227 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# U1设备耗材兼容性检查修复
## 问题描述
当连接 Snapmaker U1 设备时,如果设备上编辑的耗材是 "Snapmaker PETG",耗材下拉框的 "Machine Filament" 部分会显示该耗材。然而,`Snapmaker PETG.json` 配置文件的 `compatible_printers` 列表中**不包含** U1 设备(仅包含 A250/A350 系列),导致显示了一个不兼容的耗材配置。
### 现象
- 引导页和选择耗材页**没有** "Snapmaker PETG @U1" 选项(正常)
- 连接 U1 设备后,下拉框 "Machine Filament" 部分**有** "Snapmaker PETG"(问题)
-`Snapmaker PETG``compatible_printers` 不包含 U1配置不匹配
## 根本原因
### 代码位置
`src/slic3r/GUI/PresetComboBoxes.cpp`
- 第一处:第 1151-1164 行(`PlaterPresetComboBox::update()` 函数)
- 第二处:第 1725-1738 行(另一个同名函数,可能是不同类)
### 问题代码
```cpp
// 修改前的代码
for (auto iter = machine_filaments.begin(); iter != machine_filaments.end();) {
std::string filament_name = iter->second.first;
// 1. 精确匹配名称
auto item_iter = std::find_if(filaments.begin(), filaments.end(),
[&filament_name, this](auto& f) { return f.name == filament_name; });
// 2. 如果没找到,尝试带 @U1 后缀
if (item_iter == filaments.end()) {
item_iter = std::find_if(filaments.begin(), filaments.end(),
[&filament_name, this](auto& f) { return f.name == filament_name + " @U1"; });
}
// 3. 只要找到就添加,没有检查 is_compatible
if (item_iter != filaments.end()) {
const_cast<Preset&>(*item_iter).is_visible = true;
// ... 添加到下拉框
}
}
```
### 缺少的检查
代码只检查了耗材名称是否匹配,**没有检查** `is_compatible` 标志。这个标志是由 `PresetCollection::update_compatible_internal()` 函数根据 `compatible_printers` 配置计算的。
### 耗材同步流程
1. 设备连接时,通过 `SSWCP_Instance::update_filament_info()`SSWCP.cpp:1440-1588同步耗材
2. 设备发送:`filament_vendor="Snapmaker"`, `filament_type="PETG"`, `filament_sub_type="NONE"`
3. 构建耗材名称:`"Snapmaker PETG"`**不带 @U1 后缀**
4. 存储到 `wxGetApp().preset_bundle->machine_filaments`
5. 下拉框更新时尝试匹配此名称
## 修复方案
### 修改内容
在两次匹配的 lambda 表达式中都增加 `&& f.is_compatible` 检查:
```cpp
// 修改后的代码
for (auto iter = machine_filaments.begin(); iter != machine_filaments.end();) {
std::string filament_name = iter->second.first;
// 第一次匹配: 精确匹配名称 + 兼容性检查
auto item_iter = std::find_if(filaments.begin(), filaments.end(),
[&filament_name, this](auto& f) { return f.name == filament_name && f.is_compatible; });
// 第二次匹配: 如果第一次失败,尝试带 @U1 后缀 + 兼容性检查
if (item_iter == filaments.end()) {
item_iter = std::find_if(filaments.begin(), filaments.end(),
[&filament_name, this](auto& f) { return f.name == filament_name + " @U1" && f.is_compatible; });
}
if (item_iter != filaments.end()) {
const_cast<Preset&>(*item_iter).is_visible = true;
// ... 添加到下拉框
} else {
iter = machine_filaments.erase(iter);
}
}
```
### 修复逻辑
1. **第一次匹配**:精确匹配 "Snapmaker PETG" + 检查 `is_compatible`
- 如果 `Snapmaker PETG.json``compatible_printers` 不包含 U1
-`is_compatible = false`,匹配失败
2. **第二次匹配**:尝试 "Snapmaker PETG @U1" + 检查 `is_compatible`
- 如果在 Snapmaker.json 中注册了 "Snapmaker PETG @U1"
- 且其 `compatible_printers` 包含 U1
- 则匹配成功
3. **结果**:只有**名称匹配且兼容**的耗材才会显示
## 技术细节
### is_compatible 计算逻辑
位置:`src/libslic3r/Preset.cpp:639-670`
```cpp
bool is_compatible_with_printer(const PresetWithVendorProfile &preset,
const PresetWithVendorProfile &active_printer,
const DynamicPrintConfig *extra_config)
{
auto *compatible_printers = preset.preset.config.option("compatible_printers");
bool has_compatible_printers = compatible_printers != nullptr &&
!compatible_printers->values.empty();
return preset.preset.is_default ||
active_printer.preset.name.empty() ||
!has_compatible_printers ||
std::find(compatible_printers->values.begin(),
compatible_printers->values.end(),
active_printer.preset.name) != compatible_printers->values.end();
}
```
### 下拉框填充顺序
`PlaterPresetComboBox::update()` 函数按以下顺序填充下拉框:
1. **Machine Filament** - 从设备同步的耗材(本次修复部分)
2. **Project-inside presets** - 项目内嵌预设
3. **User presets** - 用户自定义预设
4. **System presets** - 系统预设(本来就检查 `is_compatible`,第 1073 行)
### 两处修改的原因
`PresetComboBoxes.cpp` 中有两处几乎相同的代码,可能属于不同的类或重载函数:
- 第 1151-1164 行:`PlaterPresetComboBox::update()`
- 第 1725-1738 行:另一个相同的逻辑(可能是不同 UI 组件)
两处都需要修改以确保一致性。
## 相关配置文件
### Snapmaker PETG.json
位置:`resources/profiles/Snapmaker/filament/Snapmaker PETG.json`
```json
{
"type": "filament",
"name": "Snapmaker PETG",
"compatible_printers": [
"Snapmaker A250 (0.4 nozzle)",
"Snapmaker A250 (0.6 nozzle)",
...
"Snapmaker A350 QSKit (0.8 nozzle)"
]
}
```
**不包含 U1 设备**
### Snapmaker PETG @U1.json
位置:`resources/profiles/Snapmaker/filament/Snapmaker PETG @U1.json`
```json
{
"type": "filament",
"name": "Snapmaker PETG @U1",
"compatible_printers": [
"Snapmaker U1 (0.4 nozzle)"
]
}
```
**文件存在但未在 Snapmaker.json 中注册**
## 后续建议
要让 U1 设备正确识别 Snapmaker PETG 耗材,需要以下操作之一:
### 选项 A注册 @U1 专用配置(推荐)
`resources/profiles/Snapmaker.json``filament_list` 中添加:
```json
{
"name": "Snapmaker PETG @U1",
"sub_path": "filament/Snapmaker PETG @U1.json"
}
```
### 选项 B扩展通用配置的兼容性
`resources/profiles/Snapmaker/filament/Snapmaker PETG.json``compatible_printers` 中添加:
```json
"compatible_printers": [
...existing...,
"Snapmaker U1 (0.4 nozzle)"
]
```
## 测试建议
1. **测试不兼容耗材不显示**
- 连接 U1 设备
- 确认下拉框 "Machine Filament" 部分不显示 "Snapmaker PETG"(如果不兼容)
2. **测试兼容耗材正常显示**
- 在 Snapmaker.json 中注册 "Snapmaker PETG @U1"
- 连接 U1 设备
- 确认下拉框正确显示 "Snapmaker PETG @U1"
3. **测试其他耗材不受影响**
- 确认其他已注册的 U1 兼容耗材(如 "Snapmaker ABS @U1")正常显示
## 修改文件
- `src/slic3r/GUI/PresetComboBoxes.cpp`(两处修改)
## 修改日期
2026-01-22