添加 MX-PD-盘古 项目文件

将 MX-PD-盘古 - new 目录下的所有文件添加到主仓库
This commit is contained in:
Shi.Ji
2026-05-18 11:43:09 +08:00
parent 03632a379d
commit e31d3560bb
739 changed files with 99783 additions and 0 deletions

View File

@@ -0,0 +1,246 @@
# 如果要从更高级别的目录继承 .editorconfig 设置,请删除以下行
root = true
# c# 文件
[*.cs]
#### Core EditorConfig 选项 ####
# 缩进和间距
indent_size = 4
indent_style = space
tab_width = 4
# 新行首选项
end_of_line = crlf
insert_final_newline = false
#### .NET 代码操作 ####
# 类型成员
dotnet_hide_advanced_members = false
dotnet_member_insertion_location = with_other_members_of_the_same_kind
dotnet_property_generation_behavior = prefer_throwing_properties
# 符号搜索
dotnet_search_reference_assemblies = true
#### .NET 编码约定 ####
# 组织 Using
dotnet_separate_import_directive_groups = false
dotnet_sort_system_directives_first = false
file_header_template = unset
# this. 和 Me. 首选项
dotnet_style_qualification_for_event = false
dotnet_style_qualification_for_field = false
dotnet_style_qualification_for_method = false
dotnet_style_qualification_for_property = false
# 语言关键字与 bcl 类型首选项
dotnet_style_predefined_type_for_locals_parameters_members = true
dotnet_style_predefined_type_for_member_access = true
# 括号首选项
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
dotnet_style_parentheses_in_other_operators = never_if_unnecessary
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
# 修饰符首选项
dotnet_style_require_accessibility_modifiers = for_non_interface_members
# 表达式级首选项
dotnet_prefer_system_hash_code = true
dotnet_style_coalesce_expression = true
dotnet_style_collection_initializer = true
dotnet_style_explicit_tuple_names = true
dotnet_style_namespace_match_folder = true
dotnet_style_null_propagation = true
dotnet_style_object_initializer = true
dotnet_style_operator_placement_when_wrapping = beginning_of_line
dotnet_style_prefer_auto_properties = true
dotnet_style_prefer_collection_expression = when_types_loosely_match
dotnet_style_prefer_compound_assignment = true
dotnet_style_prefer_conditional_expression_over_assignment = true
dotnet_style_prefer_conditional_expression_over_return = true
dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed
dotnet_style_prefer_inferred_anonymous_type_member_names = true
dotnet_style_prefer_inferred_tuple_names = true
dotnet_style_prefer_is_null_check_over_reference_equality_method = true
dotnet_style_prefer_simplified_boolean_expressions = true
dotnet_style_prefer_simplified_interpolation = true
# 字段首选项
dotnet_style_readonly_field = true
# 参数首选项
dotnet_code_quality_unused_parameters = all
# 禁止显示首选项
dotnet_remove_unnecessary_suppression_exclusions = none
# 新行首选项
dotnet_style_allow_multiple_blank_lines_experimental = true
dotnet_style_allow_statement_immediately_after_block_experimental = true
#### c# 编码约定 ####
# var 首选项
csharp_style_var_elsewhere = false
csharp_style_var_for_built_in_types = false
csharp_style_var_when_type_is_apparent = false
# Expression-bodied 成员
csharp_style_expression_bodied_accessors = true
csharp_style_expression_bodied_constructors = false
csharp_style_expression_bodied_indexers = true
csharp_style_expression_bodied_lambdas = true
csharp_style_expression_bodied_local_functions = false
csharp_style_expression_bodied_methods = false
csharp_style_expression_bodied_operators = false
csharp_style_expression_bodied_properties = true
# 模式匹配首选项
csharp_style_pattern_matching_over_as_with_null_check = true
csharp_style_pattern_matching_over_is_with_cast_check = true
csharp_style_prefer_extended_property_pattern = true
csharp_style_prefer_not_pattern = true
csharp_style_prefer_pattern_matching = true
csharp_style_prefer_switch_expression = true
# Null 检查首选项
csharp_style_conditional_delegate_call = true
# 修饰符首选项
csharp_prefer_static_anonymous_function = true
csharp_prefer_static_local_function = true
csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async
csharp_style_prefer_readonly_struct = true
csharp_style_prefer_readonly_struct_member = true
# 代码块首选项
csharp_prefer_braces = true
csharp_prefer_simple_using_statement = true
csharp_prefer_system_threading_lock = true
csharp_style_namespace_declarations = block_scoped
csharp_style_prefer_method_group_conversion = true
csharp_style_prefer_primary_constructors = true
csharp_style_prefer_top_level_statements = true
# 表达式级首选项
csharp_prefer_simple_default_expression = true
csharp_style_deconstructed_variable_declaration = true
csharp_style_implicit_object_creation_when_type_is_apparent = true
csharp_style_inlined_variable_declaration = true
csharp_style_prefer_implicitly_typed_lambda_expression = true
csharp_style_prefer_index_operator = true
csharp_style_prefer_local_over_anonymous_function = true
csharp_style_prefer_null_check_over_type_check = true
csharp_style_prefer_range_operator = true
csharp_style_prefer_tuple_swap = true
csharp_style_prefer_unbound_generic_type_in_nameof = true
csharp_style_prefer_utf8_string_literals = true
csharp_style_throw_expression = true
csharp_style_unused_value_assignment_preference = discard_variable
csharp_style_unused_value_expression_statement_preference = discard_variable
# "using" 指令首选项
csharp_using_directive_placement = outside_namespace
# 新行首选项
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true
csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true
csharp_style_allow_embedded_statements_on_same_line_experimental = true
#### C# 格式规则 ####
# 新行首选项
csharp_new_line_before_catch = true
csharp_new_line_before_else = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_open_brace = all
csharp_new_line_between_query_expression_clauses = true
# 缩进首选项
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = true
csharp_indent_labels = one_less_than_current
csharp_indent_switch_labels = true
# 空格键首选项
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
# 包装首选项
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = true
#### 命名样式 ####
# 命名规则
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
# 符号规范
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types.required_modifiers =
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.non_field_members.required_modifiers =
# 命名样式
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.capitalization = pascal_case

View File

@@ -0,0 +1,106 @@
---
applyTo: "**/*.cs"
---
# C# Base Instructions
## Language Version Constraint
This repository targets .NET Framework 4.8 and C# 7.3.
Do not use:
- record
- init property setters
- switch expressions
- using declarations
- top-level statements
- nullable reference types
- range operators (`..`)
- default interface implementations
- IAsyncEnumerable<T>
Allowed:
- async/await
- pattern matching with is / switch case patterns
- tuples
- local functions
- inline out variable declarations
- throw expressions
- ref locals and ref returns
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĿĿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ .NET Framework 4.8<EFBFBD><EFBFBD>C# <20><EFBFBD>̶<EFBFBD>Ϊ 7.3<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>
- <20><>ֹʹ<D6B9><CAB9> record<72><64>init<69><74>switch <20><><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD>using <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɿ<EFBFBD><C9BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD> C# 8+ <20><><EFBFBD><EFBFBD>
- <20><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9> async/await<69><74>Ԫ<EFBFBD><EFBFBD><E9A1A2><EFBFBD>غ<EFBFBD><D8BA><EFBFBD><EFBFBD><EFBFBD>ģʽƥ<CABD><EFBFBD><E4A1A2><EFBFBD><EFBFBD> out <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> C# 7.3 ֧<>ֵĹ<D6B5><C4B9><EFBFBD>
## Style Rules
- Use explicit types, not `var`
- Use Allman braces
- Use 4 spaces indentation
- Use CRLF line endings
- Use block-scoped namespaces
- Place using directives outside namespaces
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20><>ʽ<EFBFBD><CABD><EFBFBD>ͣ<EFBFBD><CDA3><EFBFBD>ʹ<EFBFBD><CAB9> `var`
- ʹ<><CAB9> Allman <20><><EFBFBD><EFBFBD><EFBFBD>ŷ<EFBFBD><C5B7><EFBFBD>
- 4 <20>ո<EFBFBD><D5B8><EFBFBD><EFBFBD><EFBFBD>
- ʹ<><CAB9> CRLF <20><><EFBFBD><EFBFBD>
- ʹ<>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>
- using <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD>
## Naming Rules
- Public types, methods, properties, events: PascalCase
- Private fields: _camelCase
- Constants: PascalCase
- Interfaces: I + PascalCase
- Enums: PascalCase
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͡<EFBFBD><CDA1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԡ<EFBFBD><D4A1>¼<EFBFBD><C2BC><EFBFBD>PascalCase
- ˽<><CBBD><EFBFBD>ֶΣ<D6B6>`_camelCase`
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>PascalCase
- <20>ӿڣ<D3BF>`I` + PascalCase
- ö<>٣<EFBFBD>PascalCase
## Constructor Injection
Prefer constructor injection with null checks.
Example:
```csharp
public SafeAxisMotion(HardwareManager hardware, AlarmOperate alarmOperate)
{
_hardware = hardware ?? throw new ArgumentNullException(nameof(hardware));
_alarmOperate = alarmOperate ?? throw new ArgumentNullException(nameof(alarmOperate));
}
```
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ù<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> null <20><><EFBFBD>
<EFBFBD><EFBFBD>Ҫʡ<EFBFBD><EFBFBD> null <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
## Async Rules
Async methods must use Async suffix
Pass CancellationToken where appropriate
Do not block async code with .Result or .Wait() unless existing architecture requires it and the reason is explicit
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20><EFBFBD><ECB2BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Async <20><>׺
- <20><>Ҫ֧<D2AA><D6A7>ȡ<EFBFBD><C8A1><EFBFBD>ij<EFBFBD><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>봫 CancellationToken
- <20><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9> .Result <20><> .Wait() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><ECB2BD><EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>мܹ<D0BC><DCB9><EFBFBD>ȷҪ<C8B7><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
## Code Generation Preference
Keep methods focused and readable
Prefer explicit domain terminology over generic names
Avoid unnecessary abstractions
Match the existing repository style
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD><EFBFBD>ɴ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>
- <20><><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>ְ<EFBFBD><D6B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20><><EFBFBD><EFBFBD><E2B2BB>Ҫ<EFBFBD>ij<EFBFBD><C4B3><EFBFBD>
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>вֿ<D0B2><D6BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

View File

@@ -0,0 +1,68 @@
---
applyTo: "MainShell/Hardware/**/*.cs,MainShell/DeviceMaintance/**/*.cs,MainShell/Manual/**/*.cs,MainShell/ToolBox/**/*.cs"
---
# Hardware and IO Instructions
## Hardware Access Rules
- Reuse HardwareManager as the primary hardware entry point
- Do not invent parallel hardware access layers unless explicitly requested
- Keep hardware naming and organization consistent with existing project patterns
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
Ӳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- ͳһͨ<D2BB><CDA8> `HardwareManager` <20><>Ϊ<EFBFBD><CEAA>ҪӲ<D2AA><D3B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20><>Ҫƽ<D2AA><C6BD><EFBFBD>½<EFBFBD><C2BD><EFBFBD>һ<EFBFBD><D2BB>Ӳ<EFBFBD><D3B2><EFBFBD><EFBFBD><EFBFBD>ʲ<EFBFBD>
- Ӳ<><D3B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֯<EFBFBD><D6AF>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀһ<C4BF><D2BB>
## Axis Naming Rules
All axis names should be defined as constants in the existing axis naming class.
Naming pattern:
- Axis_ prefix
- Examples:
- Axis_SZ
- Axis_PHS_X1
- Axis_WS_X3
- Axis_Stage_Y3
If a new axis is introduced, define a constant in the existing axis name holder.
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>
- <20><><EFBFBD><EFBFBD>ͳһʹ<D2BB><CAB9> `Axis_` ǰ׺
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E1A3AC><EFBFBD><EFBFBD><EFBFBD><E4B3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E5A3AC>Ҫ<EFBFBD><D2AA>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӳ<EFBFBD><D3B2><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
## IO Rules
- IO point definitions are loaded from CSV configuration
- Reuse DeviceIoPointDefinition and existing IO grouping structures
- Preserve support for simulated IO states if relevant
- Keep IO service/model/event naming device-oriented
Use:
- DeviceIoMonitorService
- DeviceIoSnapshot
- DeviceCylinderService
Avoid logistics-specific names unless the domain explicitly requires them:
- ConveyorIoService
- LoaderIoMonitor
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
IO <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- IO <20><EFBFBD><E3B6A8>ͨ<EFBFBD><CDA8> CSV <20><><EFBFBD>ü<EFBFBD><C3BC><EFBFBD>
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> `DeviceIoPointDefinition` <20><> IO <20><><EFBFBD><EFBFBD><EFBFBD>
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3> IO ״̬<D7B4><CCAC><EFBFBD>ƣ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>ּ<EFBFBD><D6BC><EFBFBD>
- IO <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E8B1B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫʹ<D2AA>ù<EFBFBD><C3B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7>Ҫ
## Safety Preference
- Validate device state before critical actions
- Do not assume hardware is ready
- Keep generated code conservative and traceable
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD>ȫԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20>ؼ<EFBFBD><D8BC><EFBFBD><E8B1B8><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0>У<EFBFBD><D0A3><EFBFBD>豸״̬
- <20><>ҪĬ<D2AA><C4AC>Ӳ<EFBFBD><D3B2><EFBFBD>Ѿ<EFBFBD> ready
- <20><><EFBFBD>ɴ<EFBFBD><C9B4><EFBFBD>ʱҪƫ<D2AA><C6AB><EFBFBD>ء<EFBFBD><D8A1><EFBFBD>׷<EFBFBD><D7B7>

View File

@@ -0,0 +1,161 @@
---
applyTo: "MainShell/Common/**/*.cs,**/*ViewModel.cs,**/*Service.cs,**/*Process*.cs"
---
# Localization and Popup Instructions
## Scope
These rules apply to internal program message dialogs only.
Do not apply these rules to:
- database alarms
- PLC alarm chain
- device alarm chain
- AlarmAsync main alarm path
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD>Щ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**<2A><><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>**<2A><>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD>
- <20><><EFBFBD>ݿⱨ<DDBF><E2B1A8>
- PLC <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·
- <20><EFBFBD><E8B1B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·
- `AlarmAsync()` <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·
## Required Popup Pattern
For internal prompts:
1. define MessageKey enum value in `MainShell/Common/MessageKey.cs`
2. add mapping in `LanguageResourceHelper.ResourceKeyMap`
3. add Chinese resource in `MainShell/Language/MXJM_CN.xaml`
4. add English resource in `MainShell/Language/MXJM_EN.xaml`
5. call `LocalizedMessageBox.Show()` or `LocalizedMessageBox.ShowFormat()`
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣<EFBFBD>
1. <20><> `MessageKey.cs` <20>ж<EFBFBD><D0B6><EFBFBD>ö<EFBFBD><C3B6>
2. <20><> `LanguageResourceHelper.ResourceKeyMap` <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD><D3B3>
3. <20><> `MXJM_CN.xaml` <20>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
4. <20><> `MXJM_EN.xaml` <20>в<EFBFBD>Ӣ<EFBFBD><D3A2><EFBFBD><EFBFBD>Դ
5. ҵ<><D2B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͳһ<CDB3><D2BB><EFBFBD><EFBFBD> `LocalizedMessageBox.Show()` <20><> `ShowFormat()`
## Required Title Keys
Use:
- MessageKey.TitleInfo
- MessageKey.TitleWarning
- MessageKey.TitleError
- MessageKey.TitleConfirm
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͳһʹ<EFBFBD>ã<EFBFBD>
- `MessageKey.TitleInfo`
- `MessageKey.TitleWarning`
- `MessageKey.TitleError`
- `MessageKey.TitleConfirm`
## Formatting Rules
- For parameterized messages, use `ShowFormat()`
- Resource text should use placeholders such as `{0}`, `{1}`
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>İ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> `ShowFormat()`<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD>ı<EFBFBD>ʹ<EFBFBD><EFBFBD> `{0}`<EFBFBD><EFBFBD>`{1}` ռλ<D5BC><CEBB><EFBFBD><EFBFBD>
## Forbidden Patterns
Do not generate:
- `MwMessageBox.Show("<22><><EFBFBD><EFBFBD>")`
- `MessageBox.Show("<22><><EFBFBD><EFBFBD>")`
- `LocalizedMessageBox.Show("resourceKeyString")`
- direct resource dictionary access for popup text
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- `MwMessageBox.Show("<22><><EFBFBD><EFBFBD>")`
- `MessageBox.Show("<22><><EFBFBD><EFBFBD>")`
- `LocalizedMessageBox.Show("<22><>Դkey<65>ַ<EFBFBD><D6B7><EFBFBD>")`
- ֱ<>ӷ<EFBFBD><D3B7><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>İ<EFBFBD>
## Migration Rule
When modifying old internal prompt code, prefer migrating old MessageBox/MwMessageBox usage to LocalizedMessageBox and update:
- MessageKey enum
- ResourceKeyMap
- Chinese resource
- English resource
- business code call site
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
Ǩ<EFBFBD>ƾɴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>еij<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾʱ<EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD>ȸ<EFBFBD>Ϊ `LocalizedMessageBox` <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD>
- MessageKey ö<><C3B6>
- ResourceKeyMap ӳ<><D3B3>
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
- Ӣ<><D3A2><EFBFBD><EFBFBD>Դ
- ҵ<><D2B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD>
## Workflow / Process Error and Message Localization
Error messages, status messages, and user-facing messages generated in:
- Service layer (Service/*Service.cs)
- Activity layer (MainShell/Process/Activity/*.cs)
- ProcessService implementations
Must follow the same localization requirements as popup dialogs:
1. Define MessageKey enum values for all error/status messages
2. Register in LanguageResourceHelper.ResourceKeyMap
3. Add translations in MXJM_CN.xaml and MXJM_EN.xaml
4. Pass MessageKey enum (not raw strings) in WorkflowContext or result objects
5. Display messages using LocalizedMessageBox from ViewModel/View layer
Do not hardcode error messages or status strings in Service/Activity code.
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɵĴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD>
- Service <20>㣨Service/*Service.cs<63><73>
- Activity <20>㣨MainShell/Process/Activity/*.cs<63><73>
- ProcessService ʵ<><CAB5>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD>ı<EFBFBD><EFBFBD>ػ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
1. <20><> MessageKey <20>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD>/״̬<D7B4><CCAC>Ϣ<EFBFBD><CFA2>ö<EFBFBD><C3B6>ֵ
2. <20><> LanguageResourceHelper.ResourceKeyMap <20><>ע<EFBFBD><D7A2>
3. <20><> MXJM_CN.xaml <20><> MXJM_EN.xaml <20><><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>
4. <20><> WorkflowContext <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD> MessageKey ö<><C3B6>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭʼ<D4AD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>
5. <20><> ViewModel/View <20><>ʹ<EFBFBD><CAB9> LocalizedMessageBox <20><>ʾ<EFBFBD><CABE>Ϣ
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Service/Activity <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӳ<EFBFBD><D3B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2>״̬<D7B4>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>
## Example: Adding Workflow Error Message
For a new workflow error in a Service:
1. Define in `MessageKey.cs`:
```csharp
ProcessError_InvalidToolId,
ProcessError_HardwareTimeout,
```
2. Add to `LanguageResourceHelper.ResourceKeyMap`:
```csharp
{ MessageKey.ProcessError_InvalidToolId,
"MXJM:ProcessError_InvalidToolId" },
{ MessageKey.ProcessError_HardwareTimeout,
"MXJM:ProcessError_HardwareTimeout" },
```
3. In result object, return the message key:
```csharp
public MessageKey? ErrorMessageKey { get; set; }
```
4. In Activity's AfterExecute or ViewModel, check and display:
```csharp
if (result.ErrorMessageKey.HasValue)
{
LocalizedMessageBox.Show(result.ErrorMessageKey.Value,
MessageKey.TitleError);
}
```
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD>Թ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
1. <20><> `MessageKey.cs` <20>ж<EFBFBD><D0B6>
ProcessError_InvalidToolId
ProcessError_HardwareTimeout
2. <20><> `LanguageResourceHelper.ResourceKeyMap` <20><>ע<EFBFBD><D7A2>
3. <20><> Service <20><><EFBFBD>ض<EFBFBD><D8B6><EFBFBD><EFBFBD>а<EFBFBD><D0B0><EFBFBD> MessageKey
4. <20><> Activity AfterExecute <20><> ViewModel <20>м<EFBFBD><D0BC>ʹ<E9B2A2><CAB9> LocalizedMessageBox <20><>ʾ

View File

@@ -0,0 +1,104 @@
---
applyTo: "MainShell/Motion/**/*.cs,**/*MotionController*.cs,**/*SafeAxisMotion*.cs,**/*AxisSpeedManager*.cs"
---
# Motion Control Instructions
## Motion Architecture
Motion control uses layered design:
- SafeAxisMotion as business entry
- MotionController as single-axis controller
- IAxis / IAxisFunc as platform abstraction
Keep this layering intact.
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD>˶<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʋ<EFBFBD><EFBFBD>ù̶<EFBFBD><EFBFBD>ֲ㣺
- `SafeAxisMotion`<EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- `MotionController`<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- `IAxis / IAxisFunc`<EFBFBD><EFBFBD>ƽ̨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӿ<EFBFBD>
<EFBFBD><EFBFBD>Ҫ<EFBFBD>ƻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>зֲ<EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD>
## MotionController Rules
- Constructor should receive `IAxis`
- Convert to `IAxisFunc` when motion command capability is needed
- Use `SemaphoreSlim` to serialize motion commands per axis
- Motion methods should support async/await and CancellationToken
- Perform status validation before motion:
- servo/power status
- alarm status
- soft limit state
- Support timeout handling
- Raise motion lifecycle events such as MotionStarted / MotionFinished
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
`MotionController` <20><><EFBFBD>ƹ<EFBFBD><C6B9><EFBFBD><EFBFBD><EFBFBD>
- <20><><EFBFBD><EFBFBD><ECBAAF><EFBFBD><EFBFBD><EFBFBD><EFBFBD> `IAxis`
- <20><>Ҫ<EFBFBD>˶<EFBFBD><CBB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱת<CAB1><D7AA>Ϊ `IAxisFunc`
- ʹ<><CAB9> `SemaphoreSlim` <20><>֤<EFBFBD><D6A4><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EEB4AE>
- <20>˶<EFBFBD><CBB6><EFBFBD><EFBFBD><EFBFBD>֧<EFBFBD><D6A7> `async/await` <20><> `CancellationToken`
- <20>˶<EFBFBD>ǰҪ<C7B0><D2AA><EFBFBD><EFBFBD><EFBFBD>ŷ<EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ״̬
- ֧<>ֳ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>
- <20><><EFBFBD>`MotionStarted` / `MotionFinished` <20>¼<EFBFBD>
## Common Axis Properties
Prefer existing property patterns such as:
- AxisName
- CurrentPos
- IsBusy
- IsAlarm
- InPos
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽһ<EFBFBD>£<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- `AxisName`
- `CurrentPos`
- `IsBusy`
- `IsAlarm`
- `InPos`
## Motion Method Signatures
Keep compatibility with existing motion API patterns:
- MoveAbsAsync
- MoveRelAsync
- JogAsync
- StopAsync
- HomeAsync
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD>˶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>
- `MoveAbsAsync`
- `MoveRelAsync`
- `JogAsync`
- `StopAsync`
- `HomeAsync`
## SafeAxisMotion Rules
- Prefer SafeAxisMotion for batch-safe movement
- Resolve axis name to IAxis and MotionController through existing repository mechanisms
- Preserve alarm integration and timeout behavior
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD>ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD> `SafeAxisMotion` ʵ<>֣<EFBFBD>
- ͨ<><CDA8><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB>ư<EFBFBD><C6B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ `IAxis` <20><> `MotionController`
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺͳ<C9BA>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
## MotionResult Rules
- Use structured MotionResult
- Distinguish success, timeout, cancellation, and fault
- Use EnsureSuccess when caller expects exception-on-failure semantics
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
`MotionResult` ӦΪ<D3A6><EFBFBD><E1B9B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20><><EFBFBD>ֳɹ<D6B3><C9B9><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>
- <20><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD>Ҫ"ʧ<>ܼ<EFBFBD><DCBC><EFBFBD><EFBFBD>쳣"ʱ<><CAB1>ʹ<EFBFBD><CAB9> `EnsureSuccess()`
## Speed Management
Use AxisSpeedManager for speed control where applicable.
Do not hardcode inconsistent speed logic if a unified speed manager already exists.
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD>ٶȹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD> `AxisSpeedManager` ͳһ<CDB3><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͳһ<EFBFBD>ٶȹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD>´<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ٶ<EFBFBD><EFBFBD>߼<EFBFBD><EFBFBD><EFBFBD>

View File

@@ -0,0 +1,92 @@
---
applyTo: "MainShell/Recipe/**/*.cs,MainShell/Parameter/**/*.cs,MainShell/Log/**/*.cs,MainShell/Filewritable/**/*.cs,MainShell/Process/**/*.cs"
---
# Recipe, Persistence, and Logging Instructions
## Recipe System
Recipe hierarchy includes:
- IRecipe
- RecipeBase
- SubstrateRecipe
- WaferRecipe
- CarrierRecipe
- ProcessRecipe
Use existing recipe abstractions and managers:
- RecipeManager
- RecipeWrapManager
Do not bypass repository recipe patterns by creating incompatible configuration systems.
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD>䷽ϵͳ<EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>в㼶<EFBFBD><EFBFBD>
- `IRecipe`
- `RecipeBase`
- `SubstrateRecipe`
- `WaferRecipe`
- `CarrierRecipe`
- `ProcessRecipe`
Ӧ<EFBFBD><EFBFBD><EFBFBD>ȸ<EFBFBD><EFBFBD>ã<EFBFBD>
- `RecipeManager`
- `RecipeWrapManager`
<EFBFBD><EFBFBD>Ҫ<EFBFBD>ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD><EFBFBD>½<EFBFBD>һ<EFBFBD>ײ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD>
## Parameter and Process Input Rules
- Prefer reading process inputs from recipe objects and formal managers
- Do not pull process parameters from UI state when repository recipe/domain objects already exist
- Keep process input sources explicit and traceable
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20><><EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD><E4B7BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>󣬲<EFBFBD>Ҫ<EFBFBD><D2AA> UI ״̬<D7B4><CCAC>ȡ<EFBFBD><C8A1><EFBFBD>̲<EFBFBD><CCB2><EFBFBD>
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԴҪ<D4B4><D2AA>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD>׷<EFBFBD><D7B7>
## File Persistence Rules
Persistence follows:
- IFileWritable
- FileWriteBase
- JsonFileWritableBase
Use:
- FileWriteQueue for async queued file writes
- Newtonsoft.Json for JSON serialization
Reuse IgnorePropertiesResolver when selective serialization is needed.
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD>ļ<EFBFBD><EFBFBD>־û<EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>мܹ<EFBFBD><EFBFBD><EFBFBD>
- `IFileWritable`
- `FileWriteBase`
- `JsonFileWritableBase`
Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ã<EFBFBD>
- `FileWriteQueue` <20><><EFBFBD><EFBFBD><EFBFBD>첽д<ECB2BD><D0B4><EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><D0B9><EFBFBD>
- `Newtonsoft.Json` <20><><EFBFBD><EFBFBD> JSON <20><><EFBFBD>л<EFBFBD>
- <20><>Ҫѡ<D2AA><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD> `IgnorePropertiesResolver`
## Logging Rules
- Use `LogNameDefine` for log names
- Use `LogManager` for unified log management
- Keep logs consistent with existing MaxWellGeneralLog usage
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20><>־<EFBFBD><D6BE><EFBFBD><EFBFBD>ͳһ<CDB3><D2BB> `LogNameDefine` <20>ж<EFBFBD><D0B6><EFBFBD>
- ͨ<><CDA8> `LogManager` ͳһ<CDB3><D2BB><EFBFBD><EFBFBD>
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> `MaxWellGeneralLog` <20>÷<EFBFBD>һ<EFBFBD><D2BB>
## Logging Expectations
Generated code should:
- log major workflow and hardware steps
- log failures with enough context
- preserve traceability for production and troubleshooting
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD><EFBFBD>ɴ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>־Ӧ<EFBFBD><EFBFBD><EFBFBD>
- <20>ؼ<EFBFBD><D8BC><EFBFBD><EFBFBD>̲<EFBFBD><CCB2><EFBFBD><EFBFBD><EFBFBD>Ӳ<EFBFBD><D3B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־
- ʧ<><CAA7><EFBFBD><EFBFBD>־<EFBFBD><D6BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E3B9BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20><>֧<EFBFBD><D6A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׷<EFBFBD>ݺ<EFBFBD><DDBA>ֳ<EFBFBD><D6B3><EFBFBD><EFBFBD><EFBFBD>

View File

@@ -0,0 +1,105 @@
---
applyTo: "MainShell/Process/**/*.cs,**/*Activity.cs,**/*Workflow*.cs,**/*ProcessService.cs,**/*MotionService.cs"
---
# Workflow Instructions
## Workflow Architecture
This repository uses:
- WorkflowRunner
- AutoProductionWorkflowBuilder
- ActivityAbstractBase
- CompositeActivity
- WorkflowStepIds
- WorkflowStepIdResolver
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Workflow <20>ܹ<EFBFBD>ʵ<EFBFBD>֣<EFBFBD><D6A3><EFBFBD><EFBFBD>ɴ<EFBFBD><C9B4><EFBFBD>ʱӦ<CAB1><D3A6><EFBFBD>ȸ<EFBFBD><C8B8><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD><D0A9><EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB>ơ<EFBFBD>
## Layering Rules
- Activity layer only:
- calls Service / MotionService / ProcessService
- writes WorkflowContext
- returns execution result
- PrepareExecute and AfterExecute only handle pre/post processing
- Core workflow logic must be implemented in Service layer
- Do not place recipe parsing, compensation logic, vision logic, or hardware orchestration in Activity
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD>ֲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- Activity <20><>ֻ<EFBFBD><D6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Service<63><65>д WorkflowContext<78><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>н<EFBFBD><D0BD><EFBFBD>
- `PrepareExecute` <20><> `AfterExecute` ֻ<><D6BB>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߼<EFBFBD><DFBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Service <20><>
- <20><>Ҫ<EFBFBD><D2AA> Activity <20><>д<EFBFBD><EFBFBD><E4B7BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӿ<EFBFBD><D3BE><EFBFBD><E3B7A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߼<EFBFBD><DFBC><EFBFBD>Ӳ<EFBFBD><D3B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
## Routing Rules
- Do not place workflow jump logic in Activity
- Actual workflow transitions must be configured by WorkflowStep
- Normal business branches should use Route / SetRoute
- Failure should only be used for real failures:
- hardware error
- timeout
- communication failure
- invalid required input
- unrecoverable process error
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20><>Ҫ<EFBFBD><D2AA> Activity <20><>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD>߼<EFBFBD>
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>תͳһ<CDB3><D2BB> WorkflowStep <20><><EFBFBD><EFBFBD>
- <20><><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD>֧<EFBFBD><D6A7><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9> `Route / SetRoute`
- `Failure` ֻ<><D6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӳ<EFBFBD><D3B2><EFBFBD><EFBFBD><EFBFBD>󡢳<EFBFBD>ʱ<EFBFBD><CAB1>ͨѶʧ<D1B6>ܡ<EFBFBD><DCA1>ؼ<EFBFBD><D8BC><EFBFBD><EFBFBD><EFBFBD>ȱʧ<C8B1><CAA7><EFBFBD><EFBFBD><EFBFBD>ɻָ<C9BB><D6B8><EFBFBD><EFBFBD><EFBFBD>
## JumpConditions Rules
- JumpConditions are matched in add order
- More specific branches must be placed first
- Default flow must be placed last
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
`JumpConditions` ƥ<><C6A5>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><CBB3>ִ<EFBFBD>У<EFBFBD>
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0>
- Ĭ<>Ϸ<EFBFBD>֧<EFBFBD><D6A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
## Service Responsibilities
Service layer should be responsible for:
- reading WorkflowContext
- reading RecipeManager and current recipe
- reading teach data and process parameters
- acquiring hardware via HardwareManager
- validating inputs
- validating hardware state
- validating safety conditions
- executing workflow core steps
- computing business result or compensation result
- determining Route
- returning structured process result
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
Service <20><>ְ<EFBFBD><D6B0><EFBFBD><EFBFBD>
- <20><>ȡ `WorkflowContext`
- <20><>ȡ `RecipeManager` <20>͵<EFBFBD>ǰ<EFBFBD>
- <20><>ȡʾ<C8A1><CABE><EFBFBD><EFBFBD><EFBFBD>ݺ͹<DDBA><CDB9>ղ<EFBFBD><D5B2><EFBFBD>
- ͨ<><CDA8> `HardwareManager` <20><>ȡӲ<C8A1><D3B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- У<><D0A3><EFBFBD><EFBFBD><EFBFBD>롢Ӳ<EBA1A2><D3B2>״̬<D7B4>Ͱ<EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD>
- ִ<>к<EFBFBD><D0BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̲<EFBFBD><CCB2><EFBFBD>
- <20><><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>򲹳<EFBFBD><F2B2B9B3><EFBFBD><EFBFBD><EFBFBD>
- <20><><EFBFBD><EFBFBD> `Route`
- <20><><EFBFBD>ؽṹ<D8BD><E1B9B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
## Output Preference
When implementing workflow code, prefer:
1. Activity skeleton
2. Service skeleton
3. result object design
4. WorkflowContext write-back fields
5. WorkflowStep routing suggestion
6. JumpConditions ordering suggestion
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̴<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
1. Activity <20>Ǽ<EFBFBD>
2. Service <20>Ǽ<EFBFBD>
3. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
4. WorkflowContext <20><>д<EFBFBD>ֶ<EFBFBD>
5. WorkflowStep ·<>ɽ<EFBFBD><C9BD><EFBFBD>
6. JumpConditions ˳<><CBB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

View File

@@ -0,0 +1,72 @@
---
applyTo: "**/*ViewModel.cs,**/*.xaml,MainShell/Converter/**/*.cs,MainShell/Home/**/*.cs,MainShell/ParaSetting/**/*.cs,MainShell/DeviceMaintance/**/*.cs,MainShell/PageCalib/**/*.cs,MainShell/Manual/**/*.cs"
---
# WPF and MVVM Instructions
## Framework
This repository uses WPF with Stylet.
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ WPF <20><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9> Stylet<65><74>MVVM <20><><EFBFBD>ش<EFBFBD><D8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ Stylet <20><>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD>
## ViewModel Rules
- ViewModel classes should inherit from `Screen` or `PropertyChangedBase`
- Follow Stylet naming convention:
- XxxView ? XxxViewModel
- Do not introduce patterns that conflict with Stylet conventions
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
ViewModel <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- ViewModel <20>̳<EFBFBD> `Screen` <20><> `PropertyChangedBase`
- View <20><> ViewModel <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>
- <20><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Stylet <20><>ͻ<EFBFBD><CDBB> MVVM ģʽ
## State Management
- Prefer bindable state objects to hold UI state
- Do not scatter many unrelated primitive bindable properties if a cohesive state model is more suitable
- Distinguish device input state and output state clearly
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20><><EFBFBD><EFBFBD>ʹ<EFBFBD>ÿɰ<C3BF><C9B0><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD>ͳһ<CDB3><D2BB><EFBFBD>ؽ<EFBFBD><D8BD><EFBFBD>״̬
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>״̬<D7B4>򣬲<EFBFBD>Ҫ<EFBFBD><D2AA>ɢ<EFBFBD><C9A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ViewModel <20><>
- <20><><EFBFBD><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬Ҫ<CCAC><D2AA>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD>
## IoC Rules
- IoC registrations belong in `StartBootstrapper.ConfigureIoC()`
- Singleton services should use `[Singleton]` or be registered as singleton in IoC
- New services must be registered consistently with existing project patterns
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
IoC <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- IoC ע<><D7A2>ͳһ<CDB3><D2BB> `StartBootstrapper.ConfigureIoC()` <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8> `[Singleton]` <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><D7A2>
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD><EFBFBD><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
## XAML Rules
- Do not manually implement `InitializeComponent`
- Do not work around WPF compilation issues by writing manual code-behind loaders
- Fix page compilation through project file and proper WPF item setup
- Value converters should be placed in `Converter/` and named `XxxConverter`
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
XAML <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20><>Ҫ<EFBFBD><D2AA>д `InitializeComponent`
- <20><>Ҫͨ<D2AA><CDA8> code-behind <20>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><D2B3><EFBFBD>ƹ<EFBFBD><C6B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- ҳ<><D2B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧͨ<D3A6><CDA8> csproj <20><> WPF <20><><EFBFBD><EFBFBD><EFBFBD>޸<EFBFBD>
- ת<><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> `Converter/` <20>£<EFBFBD><C2A3><EFBFBD>ʹ<EFBFBD><CAB9> `XxxConverter` <20><><EFBFBD><EFBFBD>
## Language Resource Rules
Project language resources are loaded from:
- `Language/MaxwellFramework_{lang}.xaml`
- `Language/MXJM_{lang}.xaml`
Keep generated UI code compatible with the existing localization mechanism.
## <20><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD>ƣ<EFBFBD>
- ƽ̨<C6BD><CCA8><EFBFBD>԰<EFBFBD><D4B0><EFBFBD>`MaxwellFramework_{lang}.xaml`
- <20><>Ŀ<EFBFBD><C4BF><EFBFBD>԰<EFBFBD><D4B0><EFBFBD>`MXJM_{lang}.xaml`
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> UI <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>Ҫ<EFBFBD>ƻ<EFBFBD><C6BB><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD>Ի<EFBFBD><D4BB>ơ<EFBFBD>

View File

@@ -0,0 +1,581 @@
<?xml version="1.0"?>
<ArrayOfPersistenceObject xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<PersistenceObject xsi:type="AxisCardPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>AcsCard</CategoryName>
<ID>2d23c400-ccf2-469a-add5-ae92a98a85e6</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardPO.xml</ConfigPath>
<AxisCardType>DEMO</AxisCardType>
<AxisCardNum>0</AxisCardNum>
<PortNo>0</PortNo>
<ListAxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-X1</CategoryName>
<ID>3a9c772b-4a9c-4077-abbc-80fc038b81ee</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>AcsCard</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>0</AxisNum>
<AxisName>PHS-X1</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-X2</CategoryName>
<ID>c83e5f81-ef2c-413c-ace9-24bc97c30b32</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>AcsCard</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>1</AxisNum>
<AxisName>PHS-X2</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>WS-X3</CategoryName>
<ID>e0a2d6ed-2972-4595-a8dc-53a504187a9f</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>AcsCard</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>4</AxisNum>
<AxisName>WS-X3</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Y1</CategoryName>
<ID>4e145d2a-f7f7-4ce2-a5b0-919375a03d87</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>AcsCard</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>2</AxisNum>
<AxisName>PHS-Y1</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>WS-R</CategoryName>
<ID>cebe7f5c-8cdd-47e8-906a-6083047a078d</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>AcsCard</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>6</AxisNum>
<AxisName>WS-R</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>SZ</CategoryName>
<ID>ce1f8f65-3409-4124-9c9a-ba750c848e36</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>AcsCard</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>8</AxisNum>
<AxisName>SZ</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-Y3</CategoryName>
<ID>05dfa6d1-401b-4a55-808b-5af2efeb358c</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>AcsCard</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>7</AxisNum>
<AxisName>Stage-Y3</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
</ListAxisCardParaPO>
<Version>1</Version>
<Core>0</Core>
<CrossCompensate>0</CrossCompensate>
<IsServoSeparate>false</IsServoSeparate>
</PersistenceObject>
<PersistenceObject xsi:type="AxisCardPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>Plc</CategoryName>
<ID>80a2e320-d4da-46a6-9f35-0a6d0996ea22</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardPO.xml</ConfigPath>
<AxisCardType>DEMO</AxisCardType>
<AxisCardNum>0</AxisCardNum>
<PortNo>0</PortNo>
<ListAxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Z1</CategoryName>
<ID>471e0395-0918-4e0b-b9cb-d0727281ef6c</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>0</AxisNum>
<AxisName>PHS-Z1</AxisName>
<Direction>Z</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Z3</CategoryName>
<ID>5dd115ab-09a4-4bbb-9fdf-e9b76cc5e88e</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>1</AxisNum>
<AxisName>PHS-Z3</AxisName>
<Direction>Z</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Z4</CategoryName>
<ID>e359bc21-c1e8-4e06-acdb-1df94ee7931b</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>10</AxisNum>
<AxisName>PHS-Z4</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Z5</CategoryName>
<ID>9d948211-59ae-498c-b124-531a69855752</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>2</AxisNum>
<AxisName>PHS-Z5</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Z6</CategoryName>
<ID>477c569a-e460-4c45-917f-a0744ebed5ec</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>11</AxisNum>
<AxisName>PHS-Z6</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-Z7</CategoryName>
<ID>f761791c-8fb4-4a5b-8fef-0380e996e81f</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>7</AxisNum>
<AxisName>Stage-Z7</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-Z8</CategoryName>
<ID>28a1caa3-01bc-48ed-8551-68829b280a6f</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>8</AxisNum>
<AxisName>Stage-Z8</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-Z9</CategoryName>
<ID>71c8587a-1e85-4fa4-8809-14f00111a230</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>9</AxisNum>
<AxisName>Stage-Z9</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-Z10</CategoryName>
<ID>fc66c8d2-c35f-46b5-9c14-f3a017311e86</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>14</AxisNum>
<AxisName>Stage-Z10</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-CV-Y4</CategoryName>
<ID>6ebf862a-c91e-4bb2-a5b7-e67f307333b4</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>15</AxisNum>
<AxisName>Stage-CV-Y4</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-CV-Y5</CategoryName>
<ID>e1cf2e06-fe51-4115-8ad2-2a0b3dc53c00</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>16</AxisNum>
<AxisName>Stage-CV-Y5</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>WEU-Z11</CategoryName>
<ID>a765e366-03a3-451f-ab44-1e6129a6ac61</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>3</AxisNum>
<AxisName>WEU-Z11</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>WEU-Z12</CategoryName>
<ID>a4c43082-6841-45b4-83f2-b89a952a6547</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>4</AxisNum>
<AxisName>WEU-Z12</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>WEU-Y6</CategoryName>
<ID>670409e3-1e19-45c8-94b8-1f3fb1905dc2</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>5</AxisNum>
<AxisName>WEU-Y6</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>CV-Z13</CategoryName>
<ID>eb009565-40bf-4923-9b9b-fdf483dc1532</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>6</AxisNum>
<AxisName>CV-Z13</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>CV-Y7</CategoryName>
<ID>d75ee50a-ba99-4ec1-bb36-6e65cbd84180</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>18</AxisNum>
<AxisName>CV-Y7</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>CV-Y8</CategoryName>
<ID>8845c4e8-4d09-4f0a-b073-1b29e1ca59e6</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>19</AxisNum>
<AxisName>CV-Y8</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>CV-Y9</CategoryName>
<ID>4970be79-b46a-4004-84bf-82e922fb5cb8</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>20</AxisNum>
<AxisName>CV-Y9</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>CV-Y10</CategoryName>
<ID>36583278-40bd-48ad-a749-02b4e58dcbca</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>21</AxisNum>
<AxisName>CV-Y10</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
</ListAxisCardParaPO>
<Version>1</Version>
<Core>0</Core>
<CrossCompensate>0</CrossCompensate>
<IsServoSeparate>false</IsServoSeparate>
</PersistenceObject>
</ArrayOfPersistenceObject>

View File

@@ -0,0 +1,9 @@
# 气缸定义表
# 列顺序Name,Module,ControlType,ExtendOutputIds,RetractOutputIds,ExtendedFeedbackIds,RetractedFeedbackIds,Description
# ControlType: SingleOutput / DualOutput / MultiOutput
# ExtendOutputIds / RetractOutputIds / ExtendedFeedbackIds / RetractedFeedbackIds 支持填写多个 IO 引用,使用分号分隔
# IO 引用优先使用 Configuration\DeviceIoPoints.csv 中的 Name若 Id 在全表唯一,也兼容旧 Id 写法
Name,Module,ControlType,ExtendOutputIds,RetractOutputIds,ExtendedFeedbackIds,RetractedFeedbackIds,Description
WS θ夹紧气缸,WS,SingleOutput,PG.WS.ThetaClampCylAct,,PG.WS.ThetaClampCyl1WorkPos;PG.WS.ThetaClampCyl2WorkPos;PG.WS.ThetaClampCyl3WorkPos;PG.WS.ThetaClampCyl4WorkPos,PG.WS.ThetaClampCyl1HomePos;PG.WS.ThetaClampCyl2HomePos;PG.WS.ThetaClampCyl3HomePos;PG.WS.ThetaClampCyl4HomePos,WS θ 夹紧气缸总动作输出,对应 4 组伸出/缩回反馈
WS θ刹车压紧气缸,WS,SingleOutput,PG.WS.ThetaBrakePressCylAct,,,,当前 DeviceIoPoints.csv 未配置到位反馈
Stage 顶升同步气缸,Stage,MultiOutput,PG.Stage.LifterCyl1Act;PG.Stage.LifterCyl2Act,,PG.Stage.LifterCyl1WorkPos;PG.Stage.LifterCyl2WorkPos,PG.Stage.LifterCyl1HomePos;PG.Stage.LifterCyl2HomePos,Stage 顶升气缸1和2同步动作统一伸出/缩回
1 # 气缸定义表
2 # 列顺序:Name,Module,ControlType,ExtendOutputIds,RetractOutputIds,ExtendedFeedbackIds,RetractedFeedbackIds,Description
3 # ControlType: SingleOutput / DualOutput / MultiOutput
4 # ExtendOutputIds / RetractOutputIds / ExtendedFeedbackIds / RetractedFeedbackIds 支持填写多个 IO 引用,使用分号分隔
5 # IO 引用优先使用 Configuration\DeviceIoPoints.csv 中的 Name;若 Id 在全表唯一,也兼容旧 Id 写法
6 Name,Module,ControlType,ExtendOutputIds,RetractOutputIds,ExtendedFeedbackIds,RetractedFeedbackIds,Description
7 WS θ夹紧气缸,WS,SingleOutput,PG.WS.ThetaClampCylAct,,PG.WS.ThetaClampCyl1WorkPos;PG.WS.ThetaClampCyl2WorkPos;PG.WS.ThetaClampCyl3WorkPos;PG.WS.ThetaClampCyl4WorkPos,PG.WS.ThetaClampCyl1HomePos;PG.WS.ThetaClampCyl2HomePos;PG.WS.ThetaClampCyl3HomePos;PG.WS.ThetaClampCyl4HomePos,WS θ 夹紧气缸总动作输出,对应 4 组伸出/缩回反馈
8 WS θ刹车压紧气缸,WS,SingleOutput,PG.WS.ThetaBrakePressCylAct,,,,当前 DeviceIoPoints.csv 未配置到位反馈
9 Stage 顶升同步气缸,Stage,MultiOutput,PG.Stage.LifterCyl1Act;PG.Stage.LifterCyl2Act,,PG.Stage.LifterCyl1WorkPos;PG.Stage.LifterCyl2WorkPos,PG.Stage.LifterCyl1HomePos;PG.Stage.LifterCyl2HomePos,Stage 顶升气缸1和2同步动作,统一伸出/缩回

View File

@@ -0,0 +1,97 @@
# Device IO 定义表
# 列顺序Id Module Name Type Card StationNo LineNo Enabled DefaultValue IsInverse Description
# Module: 业务模块名(如 SubstrateLoad/ChipLoad/SubstrateOut/ChipUnload
# Type: Input/Output (也支持 IN/OUT/DI/DO)
# Card: Td/Acs
# StationNo: 台达站号
# LineNo: 实际接线线标/号码管标识
# Enabled: 1/0 或 true/false
# DefaultValue: 当 IO 未启用或无法读取时使用的默认状态1/0 或 true/false
Id,Module,Name,Type,Card,StationNo,LineNo,Enabled,DefaultValue,IsInverse,Description
0,WZ,PG.WZ.StartButton,Input,Td,1,X00100,1,1,0,WZ 启动按钮
1,WZ,PG.WZ.StopButton,Input,Td,1,X00101,1,1,0,WZ 停止按钮
2,WZ,PG.WZ.ResetButton,Input,Td,1,X00102,1,1,0,WZ 复位按钮
3,WZ,PG.WZ.EmergencyStopButton,Input,Td,1,X00103,1,1,0,WZ 急停按钮
4,WZ,PG.WZ.BlueButton,Input,Td,1,X00104,1,1,0,WZ 蓝色按钮(预留)
5,Stage,PG.Stage.ToolSetterSignal,Input,Td,1,X00105,1,1,0,Stage 对刀信号
6,Stage,PG.Stage.SubstrateInPlace,Input,Td,1,X00106,1,1,0,Stage 基板到位感应
7,Stage,PG.Stage.LifterCyl1WorkPos,Input,Td,1,X00107,1,1,0,Stage 顶升气缸1动点
8,Stage,PG.Stage.LifterCyl1HomePos,Input,Td,1,X00108,1,1,0,Stage 顶升气缸1原点
9,Stage,PG.Stage.LifterCyl2WorkPos,Input,Td,1,X00109,1,1,0,Stage 顶升气缸2动点
10,Stage,PG.Stage.LifterCyl2HomePos,Input,Td,1,X00110,1,1,0,Stage 顶升气缸2原点
11,WS,PG.WS.ThetaClampCyl1WorkPos,Input,Td,1,X00111,1,1,0,WS θ夹紧气缸1动点
12,WS,PG.WS.ThetaClampCyl1HomePos,Input,Td,1,X00112,1,1,0,WS θ夹紧气缸1原点
13,WS,PG.WS.ThetaClampCyl2WorkPos,Input,Td,1,X00113,1,1,0,WS θ夹紧气缸2动点
14,WS,PG.WS.ThetaClampCyl2HomePos,Input,Td,1,X00114,1,1,0,WS θ夹紧气缸2原点
15,WS,PG.WS.ThetaClampCyl3WorkPos,Input,Td,1,X00115,1,1,0,WS θ夹紧气缸3动点
0,WS,PG.WS.ThetaClampCyl3HomePos,Input,Td,2,X00200,1,1,0,WS θ夹紧气缸3原点
1,WS,PG.WS.ThetaClampCyl4WorkPos,Input,Td,2,X00201,1,1,0,WS θ夹紧气缸4动点
2,WS,PG.WS.ThetaClampCyl4HomePos,Input,Td,2,X00202,1,1,0,WS θ夹紧气缸4原点
3,WS,PG.WS.ThetaTrayPresentSensor1,Input,Td,2,X00203,1,1,0,WS θ料盘有无感应1
4,WS,PG.WS.ThetaTrayPresentSensor2,Input,Td,2,X00204,1,1,0,WS θ料盘有无感应2
5,WS,PG.WS.ThetaTrayPresentSensor3,Input,Td,2,X00205,1,1,0,WS θ料盘有无感应3
6,WS,PG.WS.ThetaTrayPresentSensor4,Input,Td,2,X00206,1,1,0,WS θ料盘有无感应4
7,WS,PG.WS.BondHead1InPlace,Input,Td,2,X00207,1,1,0,WS 刺晶头1在位
8,WS,PG.WS.BondHead2InPlace,Input,Td,2,X00208,1,1,0,WS 刺晶头2在位
9,WS,PG.WS.BondHead3InPlace,Input,Td,2,X00209,1,1,0,WS 刺晶头3在位
10,WS,PG.WS.BondHead4InPlace,Input,Td,2,X00210,1,1,0,WS 刺晶头4在位
11,WEU,PG.WEU.Z11MaterialSensor1,Input,Td,2,X00211,1,1,0,WEU Z11 有无料感应1
12,WEU,PG.WEU.Z11MaterialSensor2,Input,Td,2,X00212,1,1,0,WEU Z11 有无料感应2
13,WEU,PG.WEU.Z12MaterialSensor3,Input,Td,2,X00213,1,1,0,WEU Z12 有无料感应3
14,WEU,PG.WEU.Z12MaterialSensor4,Input,Td,2,X00214,1,1,0,WEU Z12 有无料感应4
0,CV,PG.CV.UpperInletSensor,Input,Td,3,X00300,1,1,0,CV 上层进料感应
1,CV,PG.CV.UpperInPlaceSensor,Input,Td,3,X00301,1,1,0,CV 上层到位感应
2,CV,PG.CV.LowerOutletSensor,Input,Td,3,X00302,1,1,0,CV 下层出料感应
3,CV,PG.CV.LowerInPlaceSensor,Input,Td,3,X00303,1,1,0,CV 下层到位感应
4,WZ,PG.WZ.SafetyDoor1Closed,Input,Td,3,X00304,1,1,0,WZ 安全门1关门检测
5,WZ,PG.WZ.SafetyDoor2Closed,Input,Td,3,X00305,1,1,0,WZ 安全门2关门检测
6,WZ,PG.WZ.SafetyDoor3Closed,Input,Td,3,X00306,1,1,0,WZ 安全门3关门检测
7,WZ,PG.WZ.SafetyDoor4Closed,Input,Td,3,X00307,1,1,0,WZ 安全门4关门检测
8,WZ,PG.WZ.SecurityDoorShield,Input,Td,3,X00308,1,1,0,WZ 安全门屏蔽
10,General,PG.General.PhaseLossSensor,Input,Td,3,X00310,1,1,0,缺相检测
11,General,PG.General.SafetyCircuitStatus1,Input,Td,3,X00311,1,1,0,安全回路状态1
12,General,PG.General.SafetyCircuitStatus2,Input,Td,3,X00312,1,1,0,安全回路状态2
13,CV,PG.CV.IonWindRodAlarmDetection,Input,Td,3,X00313,1,1,0,CV 离子风棒报警检测
14,EFEM,PG.EFEM.IonWindRodAlarmDetection1,Input,Td,3,X00314,1,1,0,EFEM离子风棒报警检测1
15,EFEM,PG.EFEM.IonWindRodAlarmDetection2,Input,Td,3,X00315,1,1,0,EFEM离子风棒报警检测2
0,AxisZ,PG.AxisZ.Z1GuideRailBrake,Output,Td,4,Y00100,1,1,0,Z1轴导轨抱闸
1,AxisZ,PG.AxisZ.Z3CameraAirCooling,Output,Td,4,Y00101,1,1,0,Z3相机气冷
2,AxisZ,PG.AxisZ.Z5CameraAirCooling,Output,Td,4,Y00102,1,1,0,Z5相机气冷
3,AxisZ,PG.AxisZ.Z10CameraAirCooling,Output,Td,4,Y00103,1,1,0,Z10相机气冷
4,AxisZ,PG.AxisZ.Z2BondHeadAirCooling,Output,Td,4,Y00104,1,1,0,Z2刺晶头气冷
5,CV,PG.CV.IonBarAct,Output,Td,4,Y00105,1,1,0,CV 离子风棒
6,WEU,PG.WEU.IonBarAct1,Output,Td,4,Y00106,1,1,0,WEU离子风棒1
7,WEU,PG.WEU.IonBarAct2,Output,Td,4,Y00107,1,1,0,WEU离子风棒2
8,WS,PG.WS.ThetaClampCylAct,Output,Td,4,Y00108,1,1,0,WS θ 夹紧气缸动作
9,WS,PG.WS.ThetaBrakePressCylAct,Output,Td,4,Y00109,1,1,0,WS θ 刹车压紧气缸动作
10,Stage,PG.Stage.LifterCyl1Act,Output,Td,4,Y00110,1,1,0,Stage 顶升气缸1动作
11,Stage,PG.Stage.LifterCyl2Act,Output,Td,4,Y00111,1,1,0,Stage 顶升气缸2动作
0,WZ,PG.WZ.StartButtonLight,Output,Td,5,Y00200,1,1,0,WZ 启动按钮灯
1,WZ,PG.WZ.StopButtonLight,Output,Td,5,Y00201,1,1,0,WZ 停止按钮灯
2,WZ,PG.WZ.ResetButtonLight,Output,Td,5,Y00202,1,1,0,WZ 复位按钮灯
3,WZ,PG.WZ.BlueButtonLight,Output,Td,5,Y00203,1,1,0,WZ 蓝色按钮灯
4,WZ,PG.WZ.WorkLight1,Output,Td,5,Y00204,1,1,0,WZ 照明灯1
6,EFEM,PG.EFEM.WorkLight1,Output,Td,5,Y00206,1,1,0,EFEM 照明灯1
8,WZ,PG.WZ.StackLightRed,Output,Td,5,Y00208,1,1,0,WZ 四色灯-红
9,WZ,PG.WZ.StackLightYellow,Output,Td,5,Y00209,1,1,0,WZ 四色灯-黄
10,WZ,PG.WZ.StackLightGreen,Output,Td,5,Y00210,1,1,0,WZ 四色灯-绿
11,WZ,PG.WZ.StackLightBlue,Output,Td,5,Y00211,1,1,0,WZ 四色灯-蓝
12,WZ,PG.WZ.BuzzerAct,Output,Td,5,Y00212,1,1,0,WZ 蜂鸣器
0,Stage,PG.Stage.BreakingTheVacuum1,Output,Td,6,Y00300,1,1,0,Stage 破真空1
1,Stage,PG.Stage.BreakingTheVacuum2,Output,Td,6,Y00301,1,1,0,STAGE 破真空2
2,Stage,PG.Stage.BreakingTheVacuum3,Output,Td,6,Y00302,1,1,0,STAGE 破真空3
3,Stage,PG.Stage.BreakingTheVacuum4,Output,Td,6,Y00303,1,1,0,STAGE 破真空4
4,WEU,PG.WEU.TrayBreakVacuum1,Output,Td,6,Y00304,1,1,0,WEU 料盘破真空1
5,WEU,PG.WEU.TrayBreakVacuum2,Output,Td,6,Y00305,1,1,0,WEU 料盘破真空2
6,AxisZ,PG.AxisZ.Z2BondHeadBreakVacuum,Output,Td,6,Y00306,1,1,0,PHS Z2 刺晶头破真空
7,Stage,PG.Stage.Vacuum1,Output,Td,6,Y00307,1,1,0,STAGE 吸真空1
8,Stage,PG.Stage.Vacuum2,Output,Td,6,Y00308,1,1,0,STAGE 吸真空2
9,Stage,PG.Stage.Vacuum3,Output,Td,6,Y00309,1,1,0,STAGE 吸真空3
10,Stage,PG.Stage.Vacuum4,Output,Td,6,Y00310,1,1,0,STAGE 吸真空4
11,WEU,PG.WEU.TrayVacuum1,Output,Td,6,Y00311,1,1,0,WEU 料盘吸真空1
12,WEU,PG.WEU.TrayVacuum2,Output,Td,6,Y00312,1,1,0,WEU 料盘吸真空2
13,AxisZ,PG.AxisZ.Z2BondHeadVacuum,Output,Td,6,Y00313,1,1,0,PHS Z2 刺晶头吸真空
1,WZ,PG.WZ.SafetyDoor1Open,Output,Td,7,Y00401,1,1,0,WZ 安全门1打开
2,WZ,PG.WZ.SafetyDoor2Open,Output,Td,7,Y00402,1,1,0,WZ 安全门2打开
3,WZ,PG.WZ.SafetyDoor3Open,Output,Td,7,Y00402,1,1,0,WZ 安全门3打开
4,WZ,PG.WZ.SafetyDoor4Open,Output,Td,7,Y00403,1,1,0,WZ 安全门4打开
1 # Device IO 定义表
2 # 列顺序:Id Module Name Type Card StationNo LineNo Enabled DefaultValue IsInverse Description
3 # Module: 业务模块名(如 SubstrateLoad/ChipLoad/SubstrateOut/ChipUnload)
4 # Type: Input/Output (也支持 IN/OUT/DI/DO)
5 # Card: Td/Acs
6 # StationNo: 台达站号
7 # LineNo: 实际接线线标/号码管标识
8 # Enabled: 1/0 或 true/false
9 # DefaultValue: 当 IO 未启用或无法读取时使用的默认状态,1/0 或 true/false
10 Id,Module,Name,Type,Card,StationNo,LineNo,Enabled,DefaultValue,IsInverse,Description
11 0,WZ,PG.WZ.StartButton,Input,Td,1,X00100,1,1,0,WZ 启动按钮
12 1,WZ,PG.WZ.StopButton,Input,Td,1,X00101,1,1,0,WZ 停止按钮
13 2,WZ,PG.WZ.ResetButton,Input,Td,1,X00102,1,1,0,WZ 复位按钮
14 3,WZ,PG.WZ.EmergencyStopButton,Input,Td,1,X00103,1,1,0,WZ 急停按钮
15 4,WZ,PG.WZ.BlueButton,Input,Td,1,X00104,1,1,0,WZ 蓝色按钮(预留)
16 5,Stage,PG.Stage.ToolSetterSignal,Input,Td,1,X00105,1,1,0,Stage 对刀信号
17 6,Stage,PG.Stage.SubstrateInPlace,Input,Td,1,X00106,1,1,0,Stage 基板到位感应
18 7,Stage,PG.Stage.LifterCyl1WorkPos,Input,Td,1,X00107,1,1,0,Stage 顶升气缸1动点
19 8,Stage,PG.Stage.LifterCyl1HomePos,Input,Td,1,X00108,1,1,0,Stage 顶升气缸1原点
20 9,Stage,PG.Stage.LifterCyl2WorkPos,Input,Td,1,X00109,1,1,0,Stage 顶升气缸2动点
21 10,Stage,PG.Stage.LifterCyl2HomePos,Input,Td,1,X00110,1,1,0,Stage 顶升气缸2原点
22 11,WS,PG.WS.ThetaClampCyl1WorkPos,Input,Td,1,X00111,1,1,0,WS θ夹紧气缸1动点
23 12,WS,PG.WS.ThetaClampCyl1HomePos,Input,Td,1,X00112,1,1,0,WS θ夹紧气缸1原点
24 13,WS,PG.WS.ThetaClampCyl2WorkPos,Input,Td,1,X00113,1,1,0,WS θ夹紧气缸2动点
25 14,WS,PG.WS.ThetaClampCyl2HomePos,Input,Td,1,X00114,1,1,0,WS θ夹紧气缸2原点
26 15,WS,PG.WS.ThetaClampCyl3WorkPos,Input,Td,1,X00115,1,1,0,WS θ夹紧气缸3动点
27 0,WS,PG.WS.ThetaClampCyl3HomePos,Input,Td,2,X00200,1,1,0,WS θ夹紧气缸3原点
28 1,WS,PG.WS.ThetaClampCyl4WorkPos,Input,Td,2,X00201,1,1,0,WS θ夹紧气缸4动点
29 2,WS,PG.WS.ThetaClampCyl4HomePos,Input,Td,2,X00202,1,1,0,WS θ夹紧气缸4原点
30 3,WS,PG.WS.ThetaTrayPresentSensor1,Input,Td,2,X00203,1,1,0,WS θ料盘有无感应1
31 4,WS,PG.WS.ThetaTrayPresentSensor2,Input,Td,2,X00204,1,1,0,WS θ料盘有无感应2
32 5,WS,PG.WS.ThetaTrayPresentSensor3,Input,Td,2,X00205,1,1,0,WS θ料盘有无感应3
33 6,WS,PG.WS.ThetaTrayPresentSensor4,Input,Td,2,X00206,1,1,0,WS θ料盘有无感应4
34 7,WS,PG.WS.BondHead1InPlace,Input,Td,2,X00207,1,1,0,WS 刺晶头1在位
35 8,WS,PG.WS.BondHead2InPlace,Input,Td,2,X00208,1,1,0,WS 刺晶头2在位
36 9,WS,PG.WS.BondHead3InPlace,Input,Td,2,X00209,1,1,0,WS 刺晶头3在位
37 10,WS,PG.WS.BondHead4InPlace,Input,Td,2,X00210,1,1,0,WS 刺晶头4在位
38 11,WEU,PG.WEU.Z11MaterialSensor1,Input,Td,2,X00211,1,1,0,WEU Z11 有无料感应1
39 12,WEU,PG.WEU.Z11MaterialSensor2,Input,Td,2,X00212,1,1,0,WEU Z11 有无料感应2
40 13,WEU,PG.WEU.Z12MaterialSensor3,Input,Td,2,X00213,1,1,0,WEU Z12 有无料感应3
41 14,WEU,PG.WEU.Z12MaterialSensor4,Input,Td,2,X00214,1,1,0,WEU Z12 有无料感应4
42 0,CV,PG.CV.UpperInletSensor,Input,Td,3,X00300,1,1,0,CV 上层进料感应
43 1,CV,PG.CV.UpperInPlaceSensor,Input,Td,3,X00301,1,1,0,CV 上层到位感应
44 2,CV,PG.CV.LowerOutletSensor,Input,Td,3,X00302,1,1,0,CV 下层出料感应
45 3,CV,PG.CV.LowerInPlaceSensor,Input,Td,3,X00303,1,1,0,CV 下层到位感应
46 4,WZ,PG.WZ.SafetyDoor1Closed,Input,Td,3,X00304,1,1,0,WZ 安全门1关门检测
47 5,WZ,PG.WZ.SafetyDoor2Closed,Input,Td,3,X00305,1,1,0,WZ 安全门2关门检测
48 6,WZ,PG.WZ.SafetyDoor3Closed,Input,Td,3,X00306,1,1,0,WZ 安全门3关门检测
49 7,WZ,PG.WZ.SafetyDoor4Closed,Input,Td,3,X00307,1,1,0,WZ 安全门4关门检测
50 8,WZ,PG.WZ.SecurityDoorShield,Input,Td,3,X00308,1,1,0,WZ 安全门屏蔽
51 10,General,PG.General.PhaseLossSensor,Input,Td,3,X00310,1,1,0,缺相检测
52 11,General,PG.General.SafetyCircuitStatus1,Input,Td,3,X00311,1,1,0,安全回路状态1
53 12,General,PG.General.SafetyCircuitStatus2,Input,Td,3,X00312,1,1,0,安全回路状态2
54 13,CV,PG.CV.IonWindRodAlarmDetection,Input,Td,3,X00313,1,1,0,CV 离子风棒报警检测
55 14,EFEM,PG.EFEM.IonWindRodAlarmDetection1,Input,Td,3,X00314,1,1,0,EFEM离子风棒报警检测1
56 15,EFEM,PG.EFEM.IonWindRodAlarmDetection2,Input,Td,3,X00315,1,1,0,EFEM离子风棒报警检测2
57 0,AxisZ,PG.AxisZ.Z1GuideRailBrake,Output,Td,4,Y00100,1,1,0,Z1轴导轨抱闸
58 1,AxisZ,PG.AxisZ.Z3CameraAirCooling,Output,Td,4,Y00101,1,1,0,Z3相机气冷
59 2,AxisZ,PG.AxisZ.Z5CameraAirCooling,Output,Td,4,Y00102,1,1,0,Z5相机气冷
60 3,AxisZ,PG.AxisZ.Z10CameraAirCooling,Output,Td,4,Y00103,1,1,0,Z10相机气冷
61 4,AxisZ,PG.AxisZ.Z2BondHeadAirCooling,Output,Td,4,Y00104,1,1,0,Z2刺晶头气冷
62 5,CV,PG.CV.IonBarAct,Output,Td,4,Y00105,1,1,0,CV 离子风棒
63 6,WEU,PG.WEU.IonBarAct1,Output,Td,4,Y00106,1,1,0,WEU离子风棒1
64 7,WEU,PG.WEU.IonBarAct2,Output,Td,4,Y00107,1,1,0,WEU离子风棒2
65 8,WS,PG.WS.ThetaClampCylAct,Output,Td,4,Y00108,1,1,0,WS θ 夹紧气缸动作
66 9,WS,PG.WS.ThetaBrakePressCylAct,Output,Td,4,Y00109,1,1,0,WS θ 刹车压紧气缸动作
67 10,Stage,PG.Stage.LifterCyl1Act,Output,Td,4,Y00110,1,1,0,Stage 顶升气缸1动作
68 11,Stage,PG.Stage.LifterCyl2Act,Output,Td,4,Y00111,1,1,0,Stage 顶升气缸2动作
69 0,WZ,PG.WZ.StartButtonLight,Output,Td,5,Y00200,1,1,0,WZ 启动按钮灯
70 1,WZ,PG.WZ.StopButtonLight,Output,Td,5,Y00201,1,1,0,WZ 停止按钮灯
71 2,WZ,PG.WZ.ResetButtonLight,Output,Td,5,Y00202,1,1,0,WZ 复位按钮灯
72 3,WZ,PG.WZ.BlueButtonLight,Output,Td,5,Y00203,1,1,0,WZ 蓝色按钮灯
73 4,WZ,PG.WZ.WorkLight1,Output,Td,5,Y00204,1,1,0,WZ 照明灯1
74 6,EFEM,PG.EFEM.WorkLight1,Output,Td,5,Y00206,1,1,0,EFEM 照明灯1
75 8,WZ,PG.WZ.StackLightRed,Output,Td,5,Y00208,1,1,0,WZ 四色灯-红
76 9,WZ,PG.WZ.StackLightYellow,Output,Td,5,Y00209,1,1,0,WZ 四色灯-黄
77 10,WZ,PG.WZ.StackLightGreen,Output,Td,5,Y00210,1,1,0,WZ 四色灯-绿
78 11,WZ,PG.WZ.StackLightBlue,Output,Td,5,Y00211,1,1,0,WZ 四色灯-蓝
79 12,WZ,PG.WZ.BuzzerAct,Output,Td,5,Y00212,1,1,0,WZ 蜂鸣器
80 0,Stage,PG.Stage.BreakingTheVacuum1,Output,Td,6,Y00300,1,1,0,Stage 破真空1
81 1,Stage,PG.Stage.BreakingTheVacuum2,Output,Td,6,Y00301,1,1,0,STAGE 破真空2
82 2,Stage,PG.Stage.BreakingTheVacuum3,Output,Td,6,Y00302,1,1,0,STAGE 破真空3
83 3,Stage,PG.Stage.BreakingTheVacuum4,Output,Td,6,Y00303,1,1,0,STAGE 破真空4
84 4,WEU,PG.WEU.TrayBreakVacuum1,Output,Td,6,Y00304,1,1,0,WEU 料盘破真空1
85 5,WEU,PG.WEU.TrayBreakVacuum2,Output,Td,6,Y00305,1,1,0,WEU 料盘破真空2
86 6,AxisZ,PG.AxisZ.Z2BondHeadBreakVacuum,Output,Td,6,Y00306,1,1,0,PHS Z2 刺晶头破真空
87 7,Stage,PG.Stage.Vacuum1,Output,Td,6,Y00307,1,1,0,STAGE 吸真空1
88 8,Stage,PG.Stage.Vacuum2,Output,Td,6,Y00308,1,1,0,STAGE 吸真空2
89 9,Stage,PG.Stage.Vacuum3,Output,Td,6,Y00309,1,1,0,STAGE 吸真空3
90 10,Stage,PG.Stage.Vacuum4,Output,Td,6,Y00310,1,1,0,STAGE 吸真空4
91 11,WEU,PG.WEU.TrayVacuum1,Output,Td,6,Y00311,1,1,0,WEU 料盘吸真空1
92 12,WEU,PG.WEU.TrayVacuum2,Output,Td,6,Y00312,1,1,0,WEU 料盘吸真空2
93 13,AxisZ,PG.AxisZ.Z2BondHeadVacuum,Output,Td,6,Y00313,1,1,0,PHS Z2 刺晶头吸真空
94 1,WZ,PG.WZ.SafetyDoor1Open,Output,Td,7,Y00401,1,1,0,WZ 安全门1打开
95 2,WZ,PG.WZ.SafetyDoor2Open,Output,Td,7,Y00402,1,1,0,WZ 安全门2打开
96 3,WZ,PG.WZ.SafetyDoor3Open,Output,Td,7,Y00402,1,1,0,WZ 安全门3打开
97 4,WZ,PG.WZ.SafetyDoor4Open,Output,Td,7,Y00403,1,1,0,WZ 安全门4打开

View File

@@ -0,0 +1,97 @@
# Device IO <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,,,,,,,,,,
"# <20><>˳<EFBFBD><CBB3><EFBFBD><EFBFBD>Id Module Name Type Card StationNo LineNo Enabled DefaultValue IsInverse Description",,,,,,,,,,
# Module: ҵ<><D2B5>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> SubstrateLoad/ChipLoad/SubstrateOut/ChipUnload<61><64>,,,,,,,,,,
# Type: Input/Output (Ҳ֧<D2B2><D6A7> IN/OUT/DI/DO),,,,,,,,,,
# Card: Td/Acs,,,,,,,,,,
# StationNo: ̨<><CCA8>վ<EFBFBD><D5BE>,,,,,,,,,,
# LineNo: ʵ<>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD>߱<EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD>ܱ<EFBFBD>ʶ,,,,,,,,,,
# Enabled: 1/0 <20><> true/false,,,,,,,,,,
# DefaultValue: <20><> IO δ<><CEB4><EFBFBD>û<EFBFBD><C3BB>޷<EFBFBD><DEB7><EFBFBD>ȡʱʹ<CAB1>õ<EFBFBD>Ĭ<EFBFBD><C4AC>״̬<D7B4><CCAC>1/0 <20><> true/false,,,,,,,,,,
Id,Module,Name,Type,Card,StationNo,LineNo,Enabled,DefaultValue,IsInverse,Description
0,WZ,PG.WZ.StartButton,Input,Td,1,X00100,1,1,0,WZ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ť
1,WZ,PG.WZ.StopButton,Input,Td,1,X00101,1,1,0,WZ ֹͣ<CDA3><D6B9>ť
2,WZ,PG.WZ.ResetButton,Input,Td,1,X00102,1,1,0,WZ <20><>λ<EFBFBD><CEBB>ť
3,WZ,PG.WZ.EmergencyStopButton,Input,Td,1,X00103,1,1,0,WZ <20><>ͣ<EFBFBD><CDA3>ť
4,WZ,PG.WZ.BlueButton,Input,Td,1,X00104,1,1,0,WZ <20><>ɫ<EFBFBD><C9AB>ť<EFBFBD><C5A5>Ԥ<EFBFBD><D4A4><EFBFBD><EFBFBD>
5,Stage,PG.Stage.ToolSetterSignal,Input,Td,1,X00105,1,1,0,Stage <20>Ե<EFBFBD><D4B5>ź<EFBFBD>
6,Stage,PG.Stage.SubstrateInPlace,Input,Td,1,X00106,1,1,0,Stage <20><><EFBFBD>嵽λ<E5B5BD><CEBB>Ӧ
7,Stage,PG.Stage.LifterCyl1WorkPos,Input,Td,1,X00107,1,1,0,Stage <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1<EFBFBD><31><EFBFBD><EFBFBD>
8,Stage,PG.Stage.LifterCyl1HomePos,Input,Td,1,X00108,1,1,0,Stage <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><31><D4AD>
9,Stage,PG.Stage.LifterCyl2WorkPos,Input,Td,1,X00109,1,1,0,Stage <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD><32><EFBFBD><EFBFBD>
10,Stage,PG.Stage.LifterCyl2HomePos,Input,Td,1,X00110,1,1,0,Stage <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><32><D4AD>
11,WS,PG.WS.ThetaClampCyl1WorkPos,Input,Td,1,X00111,1,1,0,WS <20><> <20>н<EFBFBD><D0BD><EFBFBD><EFBFBD><EFBFBD>1<EFBFBD><31><EFBFBD><EFBFBD>
12,WS,PG.WS.ThetaClampCyl1HomePos,Input,Td,1,X00112,1,1,0,WS <20><> <20>н<EFBFBD><D0BD><EFBFBD><EFBFBD><EFBFBD><31><D4AD>
13,WS,PG.WS.ThetaClampCyl2WorkPos,Input,Td,1,X00113,1,1,0,WS <20><> <20>н<EFBFBD><D0BD><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD><32><EFBFBD><EFBFBD>
14,WS,PG.WS.ThetaClampCyl2HomePos,Input,Td,1,X00114,1,1,0,WS <20><> <20>н<EFBFBD><D0BD><EFBFBD><EFBFBD><EFBFBD><32><D4AD>
15,WS,PG.WS.ThetaClampCyl3WorkPos,Input,Td,1,X00115,1,1,0,WS <20><> <20>н<EFBFBD><D0BD><EFBFBD><EFBFBD><EFBFBD>3<EFBFBD><33><EFBFBD><EFBFBD>
0,WS,PG.WS.ThetaClampCyl3HomePos,Input,Td,2,X00200,1,1,0,WS <20><> <20>н<EFBFBD><D0BD><EFBFBD><EFBFBD><EFBFBD><33><D4AD>
1,WS,PG.WS.ThetaClampCyl4WorkPos,Input,Td,2,X00201,1,1,0,WS <20><> <20>н<EFBFBD><D0BD><EFBFBD><EFBFBD><EFBFBD>4<EFBFBD><34><EFBFBD><EFBFBD>
2,WS,PG.WS.ThetaClampCyl4HomePos,Input,Td,2,X00202,1,1,0,WS <20><> <20>н<EFBFBD><D0BD><EFBFBD><EFBFBD><EFBFBD><34><D4AD>
3,WS,PG.WS.ThetaTrayPresentSensor1,Input,Td,2,X00203,1,1,0,WS <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޸<EFBFBD>Ӧ1
4,WS,PG.WS.ThetaTrayPresentSensor2,Input,Td,2,X00204,1,1,0,WS <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޸<EFBFBD>Ӧ2
5,WS,PG.WS.ThetaTrayPresentSensor3,Input,Td,2,X00205,1,1,0,WS <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޸<EFBFBD>Ӧ3
6,WS,PG.WS.ThetaTrayPresentSensor4,Input,Td,2,X00206,1,1,0,WS <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޸<EFBFBD>Ӧ4
7,WS,PG.WS.BondHead1InPlace,Input,Td,2,X00207,1,1,0,WS <20>̾<EFBFBD>ͷ1<CDB7><31>λ
8,WS,PG.WS.BondHead2InPlace,Input,Td,2,X00208,1,1,0,WS <20>̾<EFBFBD>ͷ2<CDB7><32>λ
9,WS,PG.WS.BondHead3InPlace,Input,Td,2,X00209,1,1,0,WS <20>̾<EFBFBD>ͷ3<CDB7><33>λ
10,WS,PG.WS.BondHead4InPlace,Input,Td,2,X00210,1,1,0,WS <20>̾<EFBFBD>ͷ4<CDB7><34>λ
11,WEU,PG.WEU.Z11MaterialSensor1,Input,Td,2,X00211,1,1,0,WEU Z11 <20><><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD>Ӧ1
12,WEU,PG.WEU.Z11MaterialSensor2,Input,Td,2,X00212,1,1,0,WEU Z11 <20><><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD>Ӧ2
13,WEU,PG.WEU.Z12MaterialSensor3,Input,Td,2,X00213,1,1,0,WEU Z12 <20><><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD>Ӧ3
14,WEU,PG.WEU.Z12MaterialSensor4,Input,Td,2,X00214,1,1,0,WEU Z12 <20><><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD>Ӧ4
0,CV,PG.CV.UpperInletSensor,Input,Td,3,X00300,1,1,0,CV <20>ϲ<EFBFBD><CFB2><EFBFBD><EFBFBD>ϸ<EFBFBD>Ӧ
1,CV,PG.CV.UpperInPlaceSensor,Input,Td,3,X00301,1,1,0,CV <20>ϲ㵽λ<E3B5BD><CEBB>Ӧ
2,CV,PG.CV.LowerOutletSensor,Input,Td,3,X00302,1,1,0,CV <20>²<EFBFBD><C2B2><EFBFBD><EFBFBD>ϸ<EFBFBD>Ӧ
3,CV,PG.CV.LowerInPlaceSensor,Input,Td,3,X00303,1,1,0,CV <20>²㵽λ<E3B5BD><CEBB>Ӧ
4,WZ,PG.WZ.SafetyDoor1Closed,Input,Td,3,X00304,1,1,0,WZ <20><>ȫ<EFBFBD><C8AB>1<EFBFBD><31><EFBFBD>ż<EFBFBD><C5BC><EFBFBD>
5,WZ,PG.WZ.SafetyDoor2Closed,Input,Td,3,X00305,1,1,0,WZ <20><>ȫ<EFBFBD><C8AB>2<EFBFBD><32><EFBFBD>ż<EFBFBD><C5BC><EFBFBD>
6,WZ,PG.WZ.SafetyDoor3Closed,Input,Td,3,X00306,1,1,0,WZ <20><>ȫ<EFBFBD><C8AB>3<EFBFBD><33><EFBFBD>ż<EFBFBD><C5BC><EFBFBD>
7,WZ,PG.WZ.SafetyDoor4Closed,Input,Td,3,X00307,1,1,0,WZ <20><>ȫ<EFBFBD><C8AB>4<EFBFBD><34><EFBFBD>ż<EFBFBD><C5BC><EFBFBD>
8,WZ,PG.WZ.SecurityDoorShield,Input,Td,3,X00308,1,1,0,WZ <20><>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
10,General,PG.General.PhaseLossSensor,Input,Td,3,X00310,1,1,0,ȱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
11,General,PG.General.SafetyCircuitStatus1,Input,Td,3,X00311,1,1,0,<EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD>·״̬1
12,General,PG.General.SafetyCircuitStatus2,Input,Td,3,X00312,1,1,0,<EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD>·״̬2
13,CV,PG.CV.IonWindRodAlarmDetection,Input,Td,3,X00313,1,1,0,CV <20><><EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
14,EFEM,PG.EFEM.IonWindRodAlarmDetection1,Input,Td,3,X00314,1,1,0,EFEM<EFBFBD><EFBFBD><EFBFBD>ӷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1
15,EFEM,PG.EFEM.IonWindRodAlarmDetection2,Input,Td,3,X00315,1,1,0,EFEM<EFBFBD><EFBFBD><EFBFBD>ӷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2
0,AxisZ,PG.AxisZ.Z1GuideRailBrake,Output,Td,4,Y00100,1,1,0,Z1<EFBFBD><EFBFBD>챧բ
1,AxisZ,PG.AxisZ.Z3CameraAirCooling,Output,Td,4,Y00101,1,1,0,Z3<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2,AxisZ,PG.AxisZ.Z5CameraAirCooling,Output,Td,4,Y00102,1,1,0,Z5<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
3,AxisZ,PG.AxisZ.Z10CameraAirCooling,Output,Td,4,Y00103,1,1,0,Z10<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
4,AxisZ,PG.AxisZ.Z2BondHeadAirCooling,Output,Td,4,Y00104,1,1,0,Z2<EFBFBD>̾<EFBFBD>ͷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
5,CV,PG.CV.IonBarAct,Output,Td,4,Y00105,1,1,0,CV <20><><EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD>
6,WEU,PG.WEU.IonBarAct1,Output,Td,4,Y00106,1,1,0,WEU<EFBFBD><EFBFBD><EFBFBD>ӷ<EFBFBD><EFBFBD><EFBFBD>1
7,WEU,PG.WEU.IonBarAct2,Output,Td,4,Y00107,1,1,0,WEU<EFBFBD><EFBFBD><EFBFBD>ӷ<EFBFBD><EFBFBD><EFBFBD>2
8,WS,PG.WS.ThetaClampCylAct,Output,Td,4,Y00108,1,1,0,WS <20><> <20>н<EFBFBD><D0BD><EFBFBD><EFBFBD>׶<EFBFBD><D7B6><EFBFBD>
9,WS,PG.WS.ThetaBrakePressCylAct,Output,Td,4,Y00109,1,1,0,WS <20><>ɲ<EFBFBD><C9B2>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD><EFBFBD>׶<EFBFBD><D7B6><EFBFBD>
10,Stage,PG.Stage.LifterCyl1Act,Output,Td,4,Y00110,1,1,0,Stage <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1<EFBFBD><31><EFBFBD><EFBFBD>
11,Stage,PG.Stage.LifterCyl2Act,Output,Td,4,Y00111,1,1,0,Stage <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD><32><EFBFBD><EFBFBD>
0,WZ,PG.WZ.StartButtonLight,Output,Td,5,Y00200,1,1,0,WZ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ť<EFBFBD><C5A5>
1,WZ,PG.WZ.StopButtonLight,Output,Td,5,Y00201,1,1,0,WZ ֹͣ<CDA3><D6B9>ť<EFBFBD><C5A5>
2,WZ,PG.WZ.ResetButtonLight,Output,Td,5,Y00202,1,1,0,WZ <20><>λ<EFBFBD><CEBB>ť<EFBFBD><C5A5>
3,WZ,PG.WZ.BlueButtonLight,Output,Td,5,Y00203,1,1,0,WZ <20><>ɫ<EFBFBD><C9AB>ť<EFBFBD><C5A5>
4,WZ,PG.WZ.WorkLight1,Output,Td,5,Y00204,1,1,0,WZ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1
6,EFEM,PG.EFEM.WorkLight1,Output,Td,5,Y00206,1,1,0,EFEM <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1
8,WZ,PG.WZ.StackLightRed,Output,Td,5,Y00208,1,1,0,WZ <20><>ɫ<EFBFBD><C9AB>-<2D><>
9,WZ,PG.WZ.StackLightYellow,Output,Td,5,Y00209,1,1,0,WZ <20><>ɫ<EFBFBD><C9AB>-<2D><>
10,WZ,PG.WZ.StackLightGreen,Output,Td,5,Y00210,1,1,0,WZ <20><>ɫ<EFBFBD><C9AB>-<2D><>
11,WZ,PG.WZ.StackLightBlue,Output,Td,5,Y00211,1,1,0,WZ <20><>ɫ<EFBFBD><C9AB>-<2D><>
12,WZ,PG.WZ.BuzzerAct,Output,Td,5,Y00212,1,1,0,WZ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
0,Stage,PG.Stage.BreakingTheVacuum1,Output,Td,6,Y00300,1,1,0,STAGE <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1
1,Stage,PG.Stage.BreakingTheVacuum2,Output,Td,6,Y00301,1,1,0,STAGE <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2
2,Stage,PG.Stage.BreakingTheVacuum3,Output,Td,6,Y00302,1,1,0,STAGE <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>3
3,Stage,PG.Stage.BreakingTheVacuum4,Output,Td,6,Y00303,1,1,0,STAGE <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>4
4,WEU,PG.WEU.TrayBreakVacuum1,Output,Td,6,Y00304,1,1,0,WEU <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1
5,WEU,PG.WEU.TrayBreakVacuum2,Output,Td,6,Y00305,1,1,0,WEU <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2
6,AxisZ,PG.AxisZ.Z2BondHeadBreakVacuum,Output,Td,6,Y00306,1,1,0,PHS Z2 <20>̾<EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
7,Stage,PG.Stage.Vacuum1,Output,Td,6,Y00307,1,1,0,STAGE <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1
8,Stage,PG.Stage.Vacuum2,Output,Td,6,Y00308,1,1,0,STAGE <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2
9,Stage,PG.Stage.Vacuum3,Output,Td,6,Y00309,1,1,0,STAGE <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>3
10,Stage,PG.Stage.Vacuum4,Output,Td,6,Y00310,1,1,0,STAGE <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>4
11,WEU,PG.WEU.TrayVacuum1,Output,Td,6,Y00311,1,1,0,WEU <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1
12,WEU,PG.WEU.TrayVacuum2,Output,Td,6,Y00312,1,1,0,WEU <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2
13,AxisZ,PG.AxisZ.Z2BondHeadVacuum,Output,Td,6,Y00313,1,1,0,PHS Z2 <20>̾<EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
1,WZ,PG.WZ.SafetyDoor1Open,Output,Td,7,Y00400,1,1,0,WZ <20><>ȫ<EFBFBD><C8AB>1<EFBFBD><31><EFBFBD><EFBFBD>
2,WZ,PG.WZ.SafetyDoor2Open,Output,Td,7,Y00401,1,1,0,WZ <20><>ȫ<EFBFBD><C8AB>2<EFBFBD><32><EFBFBD><EFBFBD>
3,WZ,PG.WZ.SafetyDoor3Open,Output,Td,7,Y00402,1,1,0,WZ <20><>ȫ<EFBFBD><C8AB>3<EFBFBD><33><EFBFBD><EFBFBD>
4,WZ,PG.WZ.SafetyDoor4Open,Output,Td,7,Y00403,1,1,0,WZ <20><>ȫ<EFBFBD><C8AB>4<EFBFBD><34><EFBFBD><EFBFBD>
1 # Device IO 定义表
2 # 列顺序:Id Module Name Type Card StationNo LineNo Enabled DefaultValue IsInverse Description
3 # Module: 业务模块名(如 SubstrateLoad/ChipLoad/SubstrateOut/ChipUnload)
4 # Type: Input/Output (也支持 IN/OUT/DI/DO)
5 # Card: Td/Acs
6 # StationNo: 台达站号
7 # LineNo: 实际接线线标/号码管标识
8 # Enabled: 1/0 或 true/false
9 # DefaultValue: 当 IO 未启用或无法读取时使用的默认状态,1/0 或 true/false
10 Id Module Name Type Card StationNo LineNo Enabled DefaultValue IsInverse Description
11 0 WZ PG.WZ.StartButton Input Td 1 X00100 1 1 0 WZ 启动按钮
12 1 WZ PG.WZ.StopButton Input Td 1 X00101 1 1 0 WZ 停止按钮
13 2 WZ PG.WZ.ResetButton Input Td 1 X00102 1 1 0 WZ 复位按钮
14 3 WZ PG.WZ.EmergencyStopButton Input Td 1 X00103 1 1 0 WZ 急停按钮
15 4 WZ PG.WZ.BlueButton Input Td 1 X00104 1 1 0 WZ 蓝色按钮(预留)
16 5 Stage PG.Stage.ToolSetterSignal Input Td 1 X00105 1 1 0 Stage 对刀信号
17 6 Stage PG.Stage.SubstrateInPlace Input Td 1 X00106 1 1 0 Stage 基板到位感应
18 7 Stage PG.Stage.LifterCyl1WorkPos Input Td 1 X00107 1 1 0 Stage 顶升气缸1动点
19 8 Stage PG.Stage.LifterCyl1HomePos Input Td 1 X00108 1 1 0 Stage 顶升气缸1原点
20 9 Stage PG.Stage.LifterCyl2WorkPos Input Td 1 X00109 1 1 0 Stage 顶升气缸2动点
21 10 Stage PG.Stage.LifterCyl2HomePos Input Td 1 X00110 1 1 0 Stage 顶升气缸2原点
22 11 WS PG.WS.ThetaClampCyl1WorkPos Input Td 1 X00111 1 1 0 WS θ 夹紧气缸1动点
23 12 WS PG.WS.ThetaClampCyl1HomePos Input Td 1 X00112 1 1 0 WS θ 夹紧气缸1原点
24 13 WS PG.WS.ThetaClampCyl2WorkPos Input Td 1 X00113 1 1 0 WS θ 夹紧气缸2动点
25 14 WS PG.WS.ThetaClampCyl2HomePos Input Td 1 X00114 1 1 0 WS θ 夹紧气缸2原点
26 15 WS PG.WS.ThetaClampCyl3WorkPos Input Td 1 X00115 1 1 0 WS θ 夹紧气缸3动点
27 0 WS PG.WS.ThetaClampCyl3HomePos Input Td 2 X00200 1 1 0 WS θ 夹紧气缸3原点
28 1 WS PG.WS.ThetaClampCyl4WorkPos Input Td 2 X00201 1 1 0 WS θ 夹紧气缸4动点
29 2 WS PG.WS.ThetaClampCyl4HomePos Input Td 2 X00202 1 1 0 WS θ 夹紧气缸4原点
30 3 WS PG.WS.ThetaTrayPresentSensor1 Input Td 2 X00203 1 1 0 WS θ 料盘有无感应1
31 4 WS PG.WS.ThetaTrayPresentSensor2 Input Td 2 X00204 1 1 0 WS θ 料盘有无感应2
32 5 WS PG.WS.ThetaTrayPresentSensor3 Input Td 2 X00205 1 1 0 WS θ 料盘有无感应3
33 6 WS PG.WS.ThetaTrayPresentSensor4 Input Td 2 X00206 1 1 0 WS θ 料盘有无感应4
34 7 WS PG.WS.BondHead1InPlace Input Td 2 X00207 1 1 0 WS 刺晶头1在位
35 8 WS PG.WS.BondHead2InPlace Input Td 2 X00208 1 1 0 WS 刺晶头2在位
36 9 WS PG.WS.BondHead3InPlace Input Td 2 X00209 1 1 0 WS 刺晶头3在位
37 10 WS PG.WS.BondHead4InPlace Input Td 2 X00210 1 1 0 WS 刺晶头4在位
38 11 WEU PG.WEU.Z11MaterialSensor1 Input Td 2 X00211 1 1 0 WEU Z11 有无料感应1
39 12 WEU PG.WEU.Z11MaterialSensor2 Input Td 2 X00212 1 1 0 WEU Z11 有无料感应2
40 13 WEU PG.WEU.Z12MaterialSensor3 Input Td 2 X00213 1 1 0 WEU Z12 有无料感应3
41 14 WEU PG.WEU.Z12MaterialSensor4 Input Td 2 X00214 1 1 0 WEU Z12 有无料感应4
42 0 CV PG.CV.UpperInletSensor Input Td 3 X00300 1 1 0 CV 上层进料感应
43 1 CV PG.CV.UpperInPlaceSensor Input Td 3 X00301 1 1 0 CV 上层到位感应
44 2 CV PG.CV.LowerOutletSensor Input Td 3 X00302 1 1 0 CV 下层出料感应
45 3 CV PG.CV.LowerInPlaceSensor Input Td 3 X00303 1 1 0 CV 下层到位感应
46 4 WZ PG.WZ.SafetyDoor1Closed Input Td 3 X00304 1 1 0 WZ 安全门1关门检测
47 5 WZ PG.WZ.SafetyDoor2Closed Input Td 3 X00305 1 1 0 WZ 安全门2关门检测
48 6 WZ PG.WZ.SafetyDoor3Closed Input Td 3 X00306 1 1 0 WZ 安全门3关门检测
49 7 WZ PG.WZ.SafetyDoor4Closed Input Td 3 X00307 1 1 0 WZ 安全门4关门检测
50 8 WZ PG.WZ.SecurityDoorShield Input Td 3 X00308 1 1 0 WZ 安全门屏蔽
51 10 General PG.General.PhaseLossSensor Input Td 3 X00310 1 1 0 缺相检测
52 11 General PG.General.SafetyCircuitStatus1 Input Td 3 X00311 1 1 0 安全回路状态1
53 12 General PG.General.SafetyCircuitStatus2 Input Td 3 X00312 1 1 0 安全回路状态2
54 13 CV PG.CV.IonWindRodAlarmDetection Input Td 3 X00313 1 1 0 CV 离子风棒报警检测
55 14 EFEM PG.EFEM.IonWindRodAlarmDetection1 Input Td 3 X00314 1 1 0 EFEM离子风棒报警检测1
56 15 EFEM PG.EFEM.IonWindRodAlarmDetection2 Input Td 3 X00315 1 1 0 EFEM离子风棒报警检测2
57 0 AxisZ PG.AxisZ.Z1GuideRailBrake Output Td 4 Y00100 1 1 0 Z1轴导轨抱闸
58 1 AxisZ PG.AxisZ.Z3CameraAirCooling Output Td 4 Y00101 1 1 0 Z3相机气冷
59 2 AxisZ PG.AxisZ.Z5CameraAirCooling Output Td 4 Y00102 1 1 0 Z5相机气冷
60 3 AxisZ PG.AxisZ.Z10CameraAirCooling Output Td 4 Y00103 1 1 0 Z10相机气冷
61 4 AxisZ PG.AxisZ.Z2BondHeadAirCooling Output Td 4 Y00104 1 1 0 Z2刺晶头气冷
62 5 CV PG.CV.IonBarAct Output Td 4 Y00105 1 1 0 CV 离子风棒
63 6 WEU PG.WEU.IonBarAct1 Output Td 4 Y00106 1 1 0 WEU离子风棒1
64 7 WEU PG.WEU.IonBarAct2 Output Td 4 Y00107 1 1 0 WEU离子风棒2
65 8 WS PG.WS.ThetaClampCylAct Output Td 4 Y00108 1 1 0 WS θ 夹紧气缸动作
66 9 WS PG.WS.ThetaBrakePressCylAct Output Td 4 Y00109 1 1 0 WS θ刹车压紧气缸动作
67 10 Stage PG.Stage.LifterCyl1Act Output Td 4 Y00110 1 1 0 Stage 顶升气缸1动作
68 11 Stage PG.Stage.LifterCyl2Act Output Td 4 Y00111 1 1 0 Stage 顶升气缸2动作
69 0 WZ PG.WZ.StartButtonLight Output Td 5 Y00200 1 1 0 WZ 启动按钮灯
70 1 WZ PG.WZ.StopButtonLight Output Td 5 Y00201 1 1 0 WZ 停止按钮灯
71 2 WZ PG.WZ.ResetButtonLight Output Td 5 Y00202 1 1 0 WZ 复位按钮灯
72 3 WZ PG.WZ.BlueButtonLight Output Td 5 Y00203 1 1 0 WZ 蓝色按钮灯
73 4 WZ PG.WZ.WorkLight1 Output Td 5 Y00204 1 1 0 WZ 照明灯1
74 6 EFEM PG.EFEM.WorkLight1 Output Td 5 Y00206 1 1 0 EFEM 照明灯1
75 8 WZ PG.WZ.StackLightRed Output Td 5 Y00208 1 1 0 WZ 四色灯-红
76 9 WZ PG.WZ.StackLightYellow Output Td 5 Y00209 1 1 0 WZ 四色灯-黄
77 10 WZ PG.WZ.StackLightGreen Output Td 5 Y00210 1 1 0 WZ 四色灯-绿
78 11 WZ PG.WZ.StackLightBlue Output Td 5 Y00211 1 1 0 WZ 四色灯-蓝
79 12 WZ PG.WZ.BuzzerAct Output Td 5 Y00212 1 1 0 WZ 蜂鸣器
80 0 Stage PG.Stage.BreakingTheVacuum1 Output Td 6 Y00300 1 1 0 STAGE 破真空1
81 1 Stage PG.Stage.BreakingTheVacuum2 Output Td 6 Y00301 1 1 0 STAGE 破真空2
82 2 Stage PG.Stage.BreakingTheVacuum3 Output Td 6 Y00302 1 1 0 STAGE 破真空3
83 3 Stage PG.Stage.BreakingTheVacuum4 Output Td 6 Y00303 1 1 0 STAGE 破真空4
84 4 WEU PG.WEU.TrayBreakVacuum1 Output Td 6 Y00304 1 1 0 WEU 料盘破真空1
85 5 WEU PG.WEU.TrayBreakVacuum2 Output Td 6 Y00305 1 1 0 WEU 料盘破真空2
86 6 AxisZ PG.AxisZ.Z2BondHeadBreakVacuum Output Td 6 Y00306 1 1 0 PHS Z2 刺晶头破真空
87 7 Stage PG.Stage.Vacuum1 Output Td 6 Y00307 1 1 0 STAGE 吸真空1
88 8 Stage PG.Stage.Vacuum2 Output Td 6 Y00308 1 1 0 STAGE 吸真空2
89 9 Stage PG.Stage.Vacuum3 Output Td 6 Y00309 1 1 0 STAGE 吸真空3
90 10 Stage PG.Stage.Vacuum4 Output Td 6 Y00310 1 1 0 STAGE 吸真空4
91 11 WEU PG.WEU.TrayVacuum1 Output Td 6 Y00311 1 1 0 WEU 料盘吸真空1
92 12 WEU PG.WEU.TrayVacuum2 Output Td 6 Y00312 1 1 0 WEU 料盘吸真空2
93 13 AxisZ PG.AxisZ.Z2BondHeadVacuum Output Td 6 Y00313 1 1 0 PHS Z2 刺晶头吸真空
94 1 WZ PG.WZ.SafetyDoor1Open Output Td 7 Y00400 1 1 0 WZ 安全门1打开
95 2 WZ PG.WZ.SafetyDoor2Open Output Td 7 Y00401 1 1 0 WZ 安全门2打开
96 3 WZ PG.WZ.SafetyDoor3Open Output Td 7 Y00402 1 1 0 WZ 安全门3打开
97 4 WZ PG.WZ.SafetyDoor4Open Output Td 7 Y00403 1 1 0 WZ 安全门4打开

View File

@@ -0,0 +1,130 @@
{
"Rules": [
{
"WorkflowName": "SubstrateLoadFlow",
"ParentActivityName": "*",
"ActivityName": "*",
"Stage": 0,
"DisplayFlowName": "SubstrateLoadFlow"
},
{
"WorkflowName": "SubstratePositionFlow",
"ParentActivityName": "*",
"ActivityName": "*",
"Stage": 1,
"DisplayFlowName": "SubstratePositionFlow"
},
{
"WorkflowName": "WaferAngleAdjustmentFlow",
"ParentActivityName": "*",
"ActivityName": "*",
"Stage": 1,
"DisplayFlowName": "WaferAngleAdjustmentFlow"
},
{
"WorkflowName": "DiePositionFlow",
"ParentActivityName": "*",
"ActivityName": "*",
"Stage": 1,
"DisplayFlowName": "DiePositionFlow"
},
{
"WorkflowName": "DieTransferFlow",
"ParentActivityName": "*",
"ActivityName": "*",
"Stage": 2,
"DisplayFlowName": "DieTransferFlow"
},
{
"WorkflowName": "DieRecheckFlow",
"ParentActivityName": "*",
"ActivityName": "*",
"Stage": 3,
"DisplayFlowName": "DieRecheckFlow"
},
{
"WorkflowName": "SubstrateUnloadFlow",
"ParentActivityName": "*",
"ActivityName": "*",
"Stage": 4,
"DisplayFlowName": "SubstrateUnloadFlow"
},
{
"WorkflowName": "AutoProduction",
"ParentActivityName": "SubstrateLoadFlow",
"ActivityName": "*",
"Stage": 0,
"DisplayFlowName": "SubstrateLoadFlow"
},
{
"WorkflowName": "AutoProduction",
"ParentActivityName": "DieAlignFlow",
"ActivityName": "*SubstratePosition*",
"Stage": 1,
"DisplayFlowName": "SubstratePositionFlow"
},
{
"WorkflowName": "AutoProduction",
"ParentActivityName": "DieAlignFlow",
"ActivityName": "WaferAngleAdjustmentFlow",
"Stage": 1,
"DisplayFlowName": "WaferAngleAdjustmentFlow"
},
{
"WorkflowName": "AutoProduction",
"ParentActivityName": "DieAlignFlow",
"ActivityName": "DiePositionFlow",
"Stage": 1,
"DisplayFlowName": "DiePositionFlow"
},
{
"WorkflowName": "AutoProduction",
"ParentActivityName": "DieAlignFlow",
"ActivityName": "*",
"Stage": 1,
"DisplayFlowName": "SubstratePositionFlow"
},
{
"WorkflowName": "AutoProduction",
"ParentActivityName": "DieBondFlow",
"ActivityName": "*",
"Stage": 2,
"DisplayFlowName": "DieTransferFlow"
},
{
"WorkflowName": "AutoProduction",
"ParentActivityName": "InspectFlow",
"ActivityName": "*",
"Stage": 3,
"DisplayFlowName": "DieRecheckFlow"
},
{
"WorkflowName": "AutoProduction",
"ParentActivityName": "SubstrateUnloadFlow",
"ActivityName": "*",
"Stage": 4,
"DisplayFlowName": "SubstrateUnloadFlow"
},
{
"WorkflowName": "AutoProduction",
"ParentActivityName": "DieAlignFlow",
"ActivityName": "SubstratePositionFlow",
"Stage": 1,
"DisplayFlowName": "SubstratePositionFlow"
},
{
"WorkflowName": "AutoProduction",
"ParentActivityName": "DieBondFlow",
"ActivityName": "DieTransferFlow",
"Stage": 2,
"DisplayFlowName": "DieTransferFlow"
},
{
"WorkflowName": "AutoProduction",
"ParentActivityName": "InspectFlow",
"ActivityName": "DieRecheckFlow",
"Stage": 3,
"DisplayFlowName": "DieRecheckFlow"
}
]
}

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<Layout Version="1.0.0.1" WindowHeight="1024" WindowWidth="1280" MachineId="12345678901234567">
<Header Title="PG-A1">
<HeaderItem Id="HideEMO"/>
<HeaderItem Id="HideCIMStatus"/>
</Header>
<Body>
<StatusBar>
<StatusLight Name="设备一" LangName="Device" Binding="Device"></StatusLight>
</StatusBar>
<Pages>
<Page Name="主页" LangName="PageHome" Target="Home">
</Page>
<Page Name="配方" LangName="PageRecipe" Target="Recipe">
</Page>
<Page Name="参数设置" LangName="PageSettings" Target="PageSettings" DisabledState="SemiAutomatic;Automatic" UserRightId="PageSettings">
</Page>
<Page Name="设备维护" LangName="MenuDeviceMaint" Target="MenuDeviceMaint" DisabledState="SemiAutomatic;Automatic" UserRightId="PageSettings">
</Page>
<Page Name="标定与校准" LangName="PageCalib" Target="PageCalib" DisabledState="SemiAutomatic;Automatic" UserRightId="PageCalib">
</Page>
<Page Name="半自动" LangName="ManualModeOperation" Target="ManualOperate">
</Page>
</Pages>
</Body>
<Footer Target="Footer"/>
</Layout>

View File

@@ -0,0 +1,581 @@
<?xml version="1.0"?>
<ArrayOfPersistenceObject xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<PersistenceObject xsi:type="AxisCardPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>AcsCard</CategoryName>
<ID>2d23c400-ccf2-469a-add5-ae92a98a85e6</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardPO.xml</ConfigPath>
<AxisCardType>DEMO</AxisCardType>
<AxisCardNum>0</AxisCardNum>
<PortNo>0</PortNo>
<ListAxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-X1</CategoryName>
<ID>3a9c772b-4a9c-4077-abbc-80fc038b81ee</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>AcsCard</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>0</AxisNum>
<AxisName>PHS-X1</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-X2</CategoryName>
<ID>c83e5f81-ef2c-413c-ace9-24bc97c30b32</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>AcsCard</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>1</AxisNum>
<AxisName>PHS-X2</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>WS-X3</CategoryName>
<ID>e0a2d6ed-2972-4595-a8dc-53a504187a9f</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>AcsCard</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>4</AxisNum>
<AxisName>WS-X3</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Y1</CategoryName>
<ID>4e145d2a-f7f7-4ce2-a5b0-919375a03d87</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>AcsCard</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>2</AxisNum>
<AxisName>PHS-Y1</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>WS-R</CategoryName>
<ID>cebe7f5c-8cdd-47e8-906a-6083047a078d</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>AcsCard</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>6</AxisNum>
<AxisName>WS-R</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>SZ</CategoryName>
<ID>ce1f8f65-3409-4124-9c9a-ba750c848e36</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>AcsCard</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>8</AxisNum>
<AxisName>SZ</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-Y3</CategoryName>
<ID>05dfa6d1-401b-4a55-808b-5af2efeb358c</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>AcsCard</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>7</AxisNum>
<AxisName>Stage-Y3</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
</ListAxisCardParaPO>
<Version>1</Version>
<Core>0</Core>
<CrossCompensate>0</CrossCompensate>
<IsServoSeparate>false</IsServoSeparate>
</PersistenceObject>
<PersistenceObject xsi:type="AxisCardPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>Plc</CategoryName>
<ID>80a2e320-d4da-46a6-9f35-0a6d0996ea22</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardPO.xml</ConfigPath>
<AxisCardType>DEMO</AxisCardType>
<AxisCardNum>0</AxisCardNum>
<PortNo>0</PortNo>
<ListAxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Z1</CategoryName>
<ID>471e0395-0918-4e0b-b9cb-d0727281ef6c</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>0</AxisNum>
<AxisName>PHS-Z1</AxisName>
<Direction>Z</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Z3</CategoryName>
<ID>5dd115ab-09a4-4bbb-9fdf-e9b76cc5e88e</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>1</AxisNum>
<AxisName>PHS-Z3</AxisName>
<Direction>Z</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Z4</CategoryName>
<ID>e359bc21-c1e8-4e06-acdb-1df94ee7931b</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>10</AxisNum>
<AxisName>PHS-Z4</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Z5</CategoryName>
<ID>9d948211-59ae-498c-b124-531a69855752</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>2</AxisNum>
<AxisName>PHS-Z5</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Z6</CategoryName>
<ID>477c569a-e460-4c45-917f-a0744ebed5ec</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>11</AxisNum>
<AxisName>PHS-Z6</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-Z7</CategoryName>
<ID>f761791c-8fb4-4a5b-8fef-0380e996e81f</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>7</AxisNum>
<AxisName>Stage-Z7</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-Z8</CategoryName>
<ID>28a1caa3-01bc-48ed-8551-68829b280a6f</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>8</AxisNum>
<AxisName>Stage-Z8</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-Z9</CategoryName>
<ID>71c8587a-1e85-4fa4-8809-14f00111a230</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>9</AxisNum>
<AxisName>Stage-Z9</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-Z10</CategoryName>
<ID>fc66c8d2-c35f-46b5-9c14-f3a017311e86</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>14</AxisNum>
<AxisName>Stage-Z10</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-CV-Y4</CategoryName>
<ID>6ebf862a-c91e-4bb2-a5b7-e67f307333b4</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>15</AxisNum>
<AxisName>Stage-CV-Y4</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-CV-Y5</CategoryName>
<ID>e1cf2e06-fe51-4115-8ad2-2a0b3dc53c00</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>16</AxisNum>
<AxisName>Stage-CV-Y5</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>WEU-Z11</CategoryName>
<ID>a765e366-03a3-451f-ab44-1e6129a6ac61</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>3</AxisNum>
<AxisName>WEU-Z11</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>WEU-Z12</CategoryName>
<ID>a4c43082-6841-45b4-83f2-b89a952a6547</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>4</AxisNum>
<AxisName>WEU-Z12</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>WEU-Y6</CategoryName>
<ID>670409e3-1e19-45c8-94b8-1f3fb1905dc2</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>5</AxisNum>
<AxisName>WEU-Y6</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>CV-Z13</CategoryName>
<ID>eb009565-40bf-4923-9b9b-fdf483dc1532</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>6</AxisNum>
<AxisName>CV-Z13</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>CV-Y7</CategoryName>
<ID>d75ee50a-ba99-4ec1-bb36-6e65cbd84180</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>18</AxisNum>
<AxisName>CV-Y7</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>CV-Y8</CategoryName>
<ID>8845c4e8-4d09-4f0a-b073-1b29e1ca59e6</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>19</AxisNum>
<AxisName>CV-Y8</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>CV-Y9</CategoryName>
<ID>4970be79-b46a-4004-84bf-82e922fb5cb8</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>20</AxisNum>
<AxisName>CV-Y9</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>CV-Y10</CategoryName>
<ID>36583278-40bd-48ad-a749-02b4e58dcbca</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>21</AxisNum>
<AxisName>CV-Y10</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
</ListAxisCardParaPO>
<Version>1</Version>
<Core>0</Core>
<CrossCompensate>0</CrossCompensate>
<IsServoSeparate>false</IsServoSeparate>
</PersistenceObject>
</ArrayOfPersistenceObject>

View File

@@ -0,0 +1,887 @@
<?xml version="1.0"?>
<ArrayOfPersistenceObject xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Z1</CategoryName>
<ID>aef7d248-e5cc-4753-b1ea-c2d1c971d643</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>0</CardNum>
<AxisNum>1</AxisNum>
<MaxVel>50</MaxVel>
<HomeSpeed>5</HomeSpeed>
<HomeLabel>Homing</HomeLabel>
<HomeBufferId>0</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>50</Velocity>
<Accelerate>500</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Z3</CategoryName>
<ID>cfae0e29-b625-49b0-a4d1-3738ba6919cd</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>0</CardNum>
<AxisNum>0</AxisNum>
<MaxVel>50</MaxVel>
<HomeSpeed>5</HomeSpeed>
<HomeLabel>Homing</HomeLabel>
<HomeBufferId>0</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>50</Velocity>
<Accelerate>500</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Z4</CategoryName>
<ID>f9f1ed8a-cd73-49a7-bec8-018d7b498772</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>0</CardNum>
<AxisNum>3</AxisNum>
<MaxVel>50</MaxVel>
<HomeSpeed>5</HomeSpeed>
<HomeLabel>Homing</HomeLabel>
<HomeBufferId>0</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>50</Velocity>
<Accelerate>500</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Z5</CategoryName>
<ID>8514cd0e-49f9-421f-9f0b-a8080ddcf7de</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>0</CardNum>
<AxisNum>4</AxisNum>
<MaxVel>50</MaxVel>
<HomeSpeed>5</HomeSpeed>
<HomeLabel>Homing</HomeLabel>
<HomeBufferId>0</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>50</Velocity>
<Accelerate>500</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Z6</CategoryName>
<ID>42482b11-f96c-4684-ba14-ed3dd1f595a0</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>0</CardNum>
<AxisNum>5</AxisNum>
<MaxVel>50</MaxVel>
<HomeSpeed>5</HomeSpeed>
<HomeLabel>Homing</HomeLabel>
<HomeBufferId>0</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>50</Velocity>
<Accelerate>500</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-Z7</CategoryName>
<ID>380f6bc0-35dc-4224-a792-e32aa26a22d0</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>0</CardNum>
<AxisNum>8</AxisNum>
<MaxVel>50</MaxVel>
<HomeSpeed>5</HomeSpeed>
<HomeLabel>Homing</HomeLabel>
<HomeBufferId>0</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>50</Velocity>
<Accelerate>500</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-Z8</CategoryName>
<ID>442a647d-bdc0-45b6-856d-114988b332e4</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>0</CardNum>
<AxisNum>9</AxisNum>
<MaxVel>50</MaxVel>
<HomeSpeed>5</HomeSpeed>
<HomeLabel>Homing</HomeLabel>
<HomeBufferId>0</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>50</Velocity>
<Accelerate>500</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-Z9</CategoryName>
<ID>25396ce5-106a-4a10-a7d8-98fefc970d0b</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>0</CardNum>
<AxisNum>10</AxisNum>
<MaxVel>50</MaxVel>
<HomeSpeed>5</HomeSpeed>
<HomeLabel>Homing</HomeLabel>
<HomeBufferId>0</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>50</Velocity>
<Accelerate>500</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-Z10</CategoryName>
<ID>8e10a13b-e6bf-4b1d-bc7c-86442fa85f7d</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>0</CardNum>
<AxisNum>11</AxisNum>
<MaxVel>50</MaxVel>
<HomeSpeed>5</HomeSpeed>
<HomeLabel>Homing</HomeLabel>
<HomeBufferId>0</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>50</Velocity>
<Accelerate>500</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-CV-Y4</CategoryName>
<ID>1d5273bf-4cd5-485e-a9d4-b6782b81dc76</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>0</CardNum>
<AxisNum>12</AxisNum>
<MaxVel>50</MaxVel>
<HomeSpeed>5</HomeSpeed>
<HomeLabel>Homing</HomeLabel>
<HomeBufferId>0</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>50</Velocity>
<Accelerate>500</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-CV-Y5</CategoryName>
<ID>cc9ee33f-ba66-4718-8894-8941f54d9927</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>0</CardNum>
<AxisNum>13</AxisNum>
<MaxVel>50</MaxVel>
<HomeSpeed>5</HomeSpeed>
<HomeLabel>Homing</HomeLabel>
<HomeBufferId>0</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>50</Velocity>
<Accelerate>500</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>WEU-Z11</CategoryName>
<ID>cb2a3d76-1f2e-484a-88d7-0ed23b73ab9d</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>0</CardNum>
<AxisNum>14</AxisNum>
<MaxVel>50</MaxVel>
<HomeSpeed>5</HomeSpeed>
<HomeLabel>Homing</HomeLabel>
<HomeBufferId>0</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>50</Velocity>
<Accelerate>500</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>WEU-Z12</CategoryName>
<ID>cb2a3d76-1f2e-484a-88d7-0ed23b73ab9d</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>0</CardNum>
<AxisNum>14</AxisNum>
<MaxVel>50</MaxVel>
<HomeSpeed>5</HomeSpeed>
<HomeLabel>Homing</HomeLabel>
<HomeBufferId>0</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>50</Velocity>
<Accelerate>500</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>WEU-Y6</CategoryName>
<ID>cb2a3d76-1f2e-484a-88d7-0ed23b73ab9d</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>0</CardNum>
<AxisNum>14</AxisNum>
<MaxVel>50</MaxVel>
<HomeSpeed>5</HomeSpeed>
<HomeLabel>Homing</HomeLabel>
<HomeBufferId>0</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>50</Velocity>
<Accelerate>500</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>CV-Z13</CategoryName>
<ID>cb2a3d76-1f2e-484a-88d7-0ed23b73ab9d</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>0</CardNum>
<AxisNum>14</AxisNum>
<MaxVel>50</MaxVel>
<HomeSpeed>5</HomeSpeed>
<HomeLabel>Homing</HomeLabel>
<HomeBufferId>0</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>50</Velocity>
<Accelerate>500</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>CV-Y7</CategoryName>
<ID>cb2a3d76-1f2e-484a-88d7-0ed23b73ab9d</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>0</CardNum>
<AxisNum>14</AxisNum>
<MaxVel>50</MaxVel>
<HomeSpeed>5</HomeSpeed>
<HomeLabel>Homing</HomeLabel>
<HomeBufferId>0</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>50</Velocity>
<Accelerate>500</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>CV-Y8</CategoryName>
<ID>cb2a3d76-1f2e-484a-88d7-0ed23b73ab9d</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>0</CardNum>
<AxisNum>14</AxisNum>
<MaxVel>50</MaxVel>
<HomeSpeed>5</HomeSpeed>
<HomeLabel>Homing</HomeLabel>
<HomeBufferId>0</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>50</Velocity>
<Accelerate>500</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>CV-Y9</CategoryName>
<ID>cb2a3d76-1f2e-484a-88d7-0ed23b73ab9d</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>0</CardNum>
<AxisNum>14</AxisNum>
<MaxVel>50</MaxVel>
<HomeSpeed>5</HomeSpeed>
<HomeLabel>Homing</HomeLabel>
<HomeBufferId>0</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>50</Velocity>
<Accelerate>500</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>CV-Y10</CategoryName>
<ID>cb2a3d76-1f2e-484a-88d7-0ed23b73ab9d</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>0</CardNum>
<AxisNum>14</AxisNum>
<MaxVel>50</MaxVel>
<HomeSpeed>5</HomeSpeed>
<HomeLabel>Homing</HomeLabel>
<HomeBufferId>0</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>50</Velocity>
<Accelerate>500</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-X1</CategoryName>
<ID>af7168b4-8aab-45a8-be8a-28f13976acfd</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>1</CardNum>
<AxisNum>1</AxisNum>
<MaxVel>1000</MaxVel>
<HomeSpeed>10</HomeSpeed>
<HomeLabel>HOMING_X1</HomeLabel>
<HomeBufferId>2</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>100</Velocity>
<Accelerate>1000</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>300</Velocity>
<Accelerate>3000</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-X2</CategoryName>
<ID>af7168b4-8aab-45a8-be8a-28f13976acfd</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>1</CardNum>
<AxisNum>1</AxisNum>
<MaxVel>1000</MaxVel>
<HomeSpeed>10</HomeSpeed>
<HomeLabel>HOMING_X2</HomeLabel>
<HomeBufferId>2</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>100</Velocity>
<Accelerate>1000</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>300</Velocity>
<Accelerate>3000</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>WS-X3</CategoryName>
<ID>f854496b-00b2-42be-816a-15b09cfe7f64</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>1</CardNum>
<AxisNum>0</AxisNum>
<MaxVel>1000</MaxVel>
<HomeSpeed>10</HomeSpeed>
<HomeLabel>HOMING_Y1</HomeLabel>
<HomeBufferId>1</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>100</Velocity>
<Accelerate>1000</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>300</Velocity>
<Accelerate>3000</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Y1</CategoryName>
<ID>5377b562-4e41-4dcf-914a-d0e05d14aaf4</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>1</CardNum>
<AxisNum>2</AxisNum>
<MaxVel>1000</MaxVel>
<HomeSpeed>10</HomeSpeed>
<HomeLabel>HOMING_X2</HomeLabel>
<HomeBufferId>3</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>100</Velocity>
<Accelerate>1000</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>300</Velocity>
<Accelerate>3000</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>WS-R</CategoryName>
<ID>858b75b5-8918-4856-a387-8c92eb96a2f2</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>1</CardNum>
<AxisNum>3</AxisNum>
<MaxVel>1000</MaxVel>
<HomeSpeed>10</HomeSpeed>
<HomeLabel>HOMING_Y2</HomeLabel>
<HomeBufferId>4</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
<Decelerate>100</Decelerate>
<Jerk>1000</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>10</Velocity>
<Accelerate>100</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>100</Velocity>
<Accelerate>1000</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>300</Velocity>
<Accelerate>3000</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>SZ</CategoryName>
<ID>3c7a13d8-3b7b-4d1f-bac2-61d7496ff736</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>1</CardNum>
<AxisNum>8</AxisNum>
<MaxVel>5</MaxVel>
<HomeSpeed>1</HomeSpeed>
<HomeLabel>HOMING_CYCZ</HomeLabel>
<HomeBufferId>5</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
<Decelerate>10</Decelerate>
<Jerk>100</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>0.1</Velocity>
<Accelerate>1</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>300</Velocity>
<Accelerate>3000</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
<PersistenceObject xsi:type="AxisMoveParaPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-Y3</CategoryName>
<ID>80d675b6-39c0-4f56-829b-11670fc683c9</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisMoveParaPO.xml</ConfigPath>
<CardNum>1</CardNum>
<AxisNum>9</AxisNum>
<MaxVel>5</MaxVel>
<HomeSpeed>1</HomeSpeed>
<HomeLabel>HOMING_CYCZ</HomeLabel>
<HomeBufferId>5</HomeBufferId>
<StepDistance>0</StepDistance>
<MovePara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
<Decelerate>10</Decelerate>
<Jerk>100</Jerk>
<Inc>0</Inc>
</MovePara>
<LowJogPara>
<Velocity>0.1</Velocity>
<Accelerate>1</Accelerate>
</LowJogPara>
<MidJogPara>
<Velocity>1</Velocity>
<Accelerate>10</Accelerate>
</MidJogPara>
<HighJogPara>
<Velocity>300</Velocity>
<Accelerate>3000</Accelerate>
</HighJogPara>
<AxisBand>0</AxisBand>
</PersistenceObject>
</ArrayOfPersistenceObject>

View File

@@ -0,0 +1,57 @@
<?xml version="1.0"?>
<ArrayOfPersistenceObject xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<PersistenceObject xsi:type="CameraPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>MapCamera</CategoryName>
<ID>2595f60b-d5fb-4fa8-998e-1931d1a071bf</ID>
<EnableLog>false</EnableLog>
<ConfigPath>CameraPO.xml</ConfigPath>
<Port>0</Port>
<CamType>DEMO</CamType>
<PixWidth>0</PixWidth>
<PixHeight>0</PixHeight>
<MirrorType>None</MirrorType>
<RotateType>Zero</RotateType>
<IsGanRaw>true</IsGanRaw>
<IsSimulate>false</IsSimulate>
<BufferAttach>0</BufferAttach>
<Interval>100</Interval>
<HeartBeatTime xsi:nil="true" />
</PersistenceObject>
<PersistenceObject xsi:type="CameraPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>TopWideCamera</CategoryName>
<ID>5dc88b03-cdfb-44e2-b954-f5b97e0e68a3</ID>
<EnableLog>false</EnableLog>
<ConfigPath>CameraPO.xml</ConfigPath>
<Port>0</Port>
<CamType>DEMO</CamType>
<PixWidth>0</PixWidth>
<PixHeight>0</PixHeight>
<MirrorType>None</MirrorType>
<RotateType>Zero</RotateType>
<IsGanRaw>true</IsGanRaw>
<IsSimulate>false</IsSimulate>
<BufferAttach>0</BufferAttach>
<Interval>100</Interval>
<HeartBeatTime xsi:nil="true" />
</PersistenceObject>
<PersistenceObject xsi:type="CameraPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>TopPositionCamera</CategoryName>
<ID>618de1c8-08ac-4abf-b778-17f26fa61a63</ID>
<EnableLog>false</EnableLog>
<ConfigPath>CameraPO.xml</ConfigPath>
<Port>0</Port>
<CamType>DEMO</CamType>
<PixWidth>0</PixWidth>
<PixHeight>0</PixHeight>
<MirrorType>None</MirrorType>
<RotateType>Zero</RotateType>
<IsGanRaw>true</IsGanRaw>
<IsSimulate>false</IsSimulate>
<BufferAttach>0</BufferAttach>
<Interval>100</Interval>
<HeartBeatTime xsi:nil="true" />
</PersistenceObject>
</ArrayOfPersistenceObject>

View File

@@ -0,0 +1,40 @@
{
"Nodes": [
{
"Key": "WaferLoad",
"DisplayName": "晶圆上料",
"ActivityKeywords": [
"ChipLoad",
"ChipLoadExecute"
],
"WorkflowKeywords": [],
"ParentKeywords": []
},
{
"Key": "WaferSupply",
"DisplayName": "供片准备",
"ActivityKeywords": [],
"WorkflowKeywords": [
"WaferAngleAdjustmentFlow",
"DiePositionFlow",
"DieTransferFlow",
"DieRecheckFlow"
],
"ParentKeywords": [
"DieAlign",
"DieBond",
"Inspect"
]
},
{
"Key": "WaferUnload",
"DisplayName": "晶圆下料",
"ActivityKeywords": [
"ChipUnload",
"ChipUnloadExecute"
],
"WorkflowKeywords": [],
"ParentKeywords": []
}
]
}

View File

@@ -0,0 +1,10 @@
System.NullReferenceException: 未将对象引用设置到对象的实例。
在 MaxwellFramework.Bootstrapper.OnExit(ExitEventArgs e)
在 MainShell.StartBootstrapper.OnExit(ExitEventArgs e) 位置 D:\Development\Git\MX-PD-盘古 - new\PanGu.DieBonderApp\MainShell\StartBootstrapper.cs:行号 180
在 Stylet.BootstrapperBase.<Setup>b__9_1(Object o, ExitEventArgs e)
在 System.Windows.Application.OnExit(ExitEventArgs e)
在 System.Windows.Application.DoShutdown()
在 System.Windows.Application.ShutdownImpl()
在 System.Windows.Application.ShutdownCallback(Object arg)
在 System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
在 System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)

View File

@@ -0,0 +1,132 @@
using MainShell.Log;
using MwFramework.AlarmManager;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace MainShell.Alarm
{
public class AlarmOperate : IAlarmSend, IAlarmResponse<string>
{
private const string AlarmSourceName = "AlarmOperate";
private readonly IAlarmManager _alarmManager;
public AlarmOperate(IAlarmManager alarmManager)
{
_alarmManager = alarmManager ?? throw new ArgumentNullException(nameof(alarmManager));
_alarmManager.CloseBuzzer += () =>
{
LogManager.LogAlarmEvent(AlarmSourceName, "CloseBuzzer");
};
_alarmManager.RestBuzzer += () =>
{
};
_alarmManager.ClearPLCAlarm += () =>
{
List<long> unresolvedAlarmIds = _alarmManager.UnresolvedAlarms == null
? new List<long>()
: _alarmManager.UnresolvedAlarms.Distinct().ToList();
try
{
foreach (long alarmId in unresolvedAlarmIds)
{
_alarmManager.HandleAlarmSolved(alarmId);
}
LogManager.LogAlarmEvent(
AlarmSourceName,
string.Format("ClearPLCAlarm resolved {0} alarms", unresolvedAlarmIds.Count));
}
catch (Exception ex)
{
LogManager.LogAlarmError(AlarmSourceName, "ClearPLCAlarm", ex);
throw;
}
};
}
public string Code { private get; set; }
public void Alert(int alarmID)
{
Task alertTask = AlertAsync(alarmID);
if (Application.Current != null &&
Application.Current.Dispatcher != null &&
Application.Current.Dispatcher.CheckAccess())
{
alertTask.ContinueWith(task =>
{
AggregateException ignored = task.Exception;
}, TaskContinuationOptions.OnlyOnFaulted);
return;
}
alertTask.GetAwaiter().GetResult();
}
public void Alert(int alarmID, string source, string action, string detail = null)
{
Task alertTask = AlertAsync(alarmID, source, action, detail);
if (Application.Current != null &&
Application.Current.Dispatcher != null &&
Application.Current.Dispatcher.CheckAccess())
{
alertTask.ContinueWith(task =>
{
AggregateException ignored = task.Exception;
}, TaskContinuationOptions.OnlyOnFaulted);
return;
}
alertTask.GetAwaiter().GetResult();
}
public async Task AlertAsync(int alarmID)
{
await AlertInternalAsync(alarmID, AlarmSourceName, "AlertAsync requested").ConfigureAwait(false);
}
public async Task AlertAsync(int alarmID, string source, string action, string detail = null)
{
string alarmSource = string.IsNullOrWhiteSpace(source) ? AlarmSourceName : source;
string triggerAction = BuildTriggerAction(action, detail);
await AlertInternalAsync(alarmID, alarmSource, triggerAction).ConfigureAwait(false);
}
private async Task AlertInternalAsync(int alarmID, string source, string action)
{
try
{
LogManager.LogAlarmEvent(source, action, alarmID);
await _alarmManager.HandleAlarmAsync(alarmID, this, this).ConfigureAwait(false);
LogManager.LogAlarmEvent(source, "HandleAlarmAsync completed", alarmID);
}
catch (Exception ex)
{
LogManager.LogAlarmError(source, "HandleAlarmAsync", ex, alarmID);
throw;
}
}
private static string BuildTriggerAction(string action, string detail)
{
string normalizedAction = string.IsNullOrWhiteSpace(action) ? "AlertAsync requested" : action;
if (string.IsNullOrWhiteSpace(detail))
{
return normalizedAction;
}
return string.Format("{0}. Detail={1}", normalizedAction, detail);
}
}
}

View File

@@ -0,0 +1,38 @@
using MainShell.Alarm.ViewModel;
using MwFramework.AlarmManager;
using Stylet;
using System.Threading.Tasks;
namespace MainShell.Alarm
{
[AlarmID(begin:10000, end:20011)]
public class UserAlarmProduce : AbstractAlarmAsyncProcedure
{
private readonly IAlarmManager _alarmManager;
private readonly IWindowManager _windowManager;
public UserAlarmProduce(IAlarmManager alarmManager, IWindowManager windowManager)
{
_alarmManager = alarmManager;
_windowManager = windowManager;
}
public override async Task HandleAsync(IAlarmSend inContext = null, IAlarmResponse outContext = null)
{
var dialogViewModel = new AlarmDialogViewModel
{
AlarmInfo = AlarmInfo
};
var resetRequested = false;
await Execute.OnUIThreadAsync(() =>
{
resetRequested = _windowManager.ShowDialog(dialogViewModel) == true;
}).ConfigureAwait(false);
if (resetRequested)
{
_alarmManager.ClearPLCAlarm?.Invoke();
}
}
}
}

View File

@@ -0,0 +1,113 @@
<Window x:Class="MainShell.Alarm.View.AlarmDialogView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MainShell.Alarm.View"
mc:Ignorable="d"
SizeToContent="Height"
ResizeMode="CanResizeWithGrip"
WindowStartupLocation="CenterOwner"
Title="报警提示 (Alarm)" Width="650" MinWidth="500" MaxHeight="800">
<Window.Resources>
<Style TargetType="GroupBox" BasedOn="{StaticResource LeftGroupStyle}"/>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<!-- 顶部横幅 -->
<RowDefinition Height="*"/>
<!-- 内容区域 -->
<RowDefinition Height="Auto"/>
<!-- 按钮区域 -->
</Grid.RowDefinitions>
<!-- 顶部横幅区域 -->
<Border Grid.Row="0" Background="#FFF5E5" BorderBrush="#FFCC80" BorderThickness="0,0,0,1" Padding="15,10">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock Text="⚠" Foreground="#E65100" FontSize="22" FontWeight="Bold" Margin="0,0,10,0" VerticalAlignment="Center"/>
<TextBlock Text="系统发生报警,请及时处理" Foreground="#D84315" FontSize="16" FontWeight="Bold" VerticalAlignment="Center"/>
</StackPanel>
</Border>
<!-- 内容区域 -->
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto" Margin="15,10,15,15">
<StackPanel>
<!-- 报警ID和类型 -->
<GroupBox Header="基本信息" Margin="0,0,0,10">
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="10"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="报警 ID:" Style="{StaticResource LabelStyle}" Grid.Row="0" Grid.Column="0" VerticalAlignment="Top"/>
<TextBlock Text="{Binding AlarmInfo.AlarmID}" Style="{StaticResource ValueStyle}" FontWeight="Bold" Grid.Row="0" Grid.Column="1" TextWrapping="Wrap"/>
<TextBlock Text="报警类型:" Style="{StaticResource LabelStyle}" Grid.Row="2" Grid.Column="0" VerticalAlignment="Top"/>
<TextBlock Text="{Binding AlarmInfo.AlarmType}" Style="{StaticResource ValueStyle}" Foreground="#D84315" FontWeight="SemiBold" Grid.Row="2" Grid.Column="1" TextWrapping="Wrap"/>
</Grid>
</GroupBox>
<!-- 报警消息 -->
<GroupBox Header="报警消息" Margin="0,0,0,10">
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="10"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="中文消息:" Style="{StaticResource LabelStyle}" Grid.Row="0" Grid.Column="0" VerticalAlignment="Top"/>
<TextBlock Text="{Binding AlarmInfo.AlarmMessage}" Style="{StaticResource ValueStyle}" Grid.Row="0" Grid.Column="1" TextWrapping="Wrap" LineHeight="20"/>
<TextBlock Text="英文消息:" Style="{StaticResource LabelStyle}" Grid.Row="2" Grid.Column="0" VerticalAlignment="Top"/>
<TextBlock Text="{Binding AlarmInfo.AlarmMessageEN}" Style="{StaticResource ValueStyle}" Grid.Row="2" Grid.Column="1" TextWrapping="Wrap" Foreground="#555555" LineHeight="20"/>
</Grid>
</GroupBox>
<!-- 报警原因 -->
<GroupBox Header="报警原因" Margin="0,0,0,10">
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="原因描述:" Style="{StaticResource LabelStyle}" Grid.Row="0" Grid.Column="0" VerticalAlignment="Top"/>
<TextBlock Text="{Binding AlarmInfo.AlarmReason}" Style="{StaticResource ValueStyle}" Grid.Row="0" Grid.Column="1" TextWrapping="Wrap" LineHeight="20"/>
</Grid>
</GroupBox>
<!-- 解决方案 -->
<GroupBox Header="解决方案" Margin="0,0,0,10">
<Border Background="#F9FBE7" BorderBrush="#CDDC39" BorderThickness="1" CornerRadius="4" Padding="10">
<TextBlock Text="{Binding AlarmInfo.AlarmSolution}" Style="{StaticResource ValueStyle}" TextWrapping="Wrap" Foreground="#33691E" LineHeight="20"/>
</Border>
</GroupBox>
<!-- 触发时间 -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,5,5,0">
<TextBlock Text="触发时间:" Style="{StaticResource LabelStyle}" Foreground="#888888" Margin="0,0,5,0" VerticalAlignment="Center"/>
<TextBlock Text="{Binding AlarmInfo.TriggerTime, StringFormat='{}{0:yyyy-MM-dd HH:mm:ss}'}" Style="{StaticResource ValueStyle}" Foreground="#888888" VerticalAlignment="Center"/>
</StackPanel>
</StackPanel>
</ScrollViewer>
<!-- 底部按钮区域 -->
<Border Grid.Row="2" BorderBrush="#E0E0E0" BorderThickness="0,1,0,0" Padding="10,8" Background="#F8F8F8">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="复位报警" Style="{StaticResource CloseButtonStyle}" Width="100" Height="32" Margin="0,0,10,0" Command="{Binding ResetCommand}" Cursor="Hand"/>
<Button Content="关闭" Style="{StaticResource CloseButtonStyle}" Width="100" Height="32" Command="{Binding CloseCommand}" Cursor="Hand"/>
</StackPanel>
</Border>
</Grid>
</Window>

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace MainShell.Alarm.View
{
/// <summary>
/// AlarmDialog.xaml 的交互逻辑
/// </summary>
public partial class AlarmDialogView : Window
{
public AlarmDialogView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,40 @@
using MainShell.Models;
using MaxwellFramework.Core.Common.Command;
using MwFramework.AlarmManager;
using System.Windows.Input;
namespace MainShell.Alarm.ViewModel
{
public class AlarmDialogViewModel : BaseScreen
{
public ICommand ResetCommand { get; }
public ICommand CloseCommand { get; }
public AlarmDialogViewModel()
{
DisplayName = "报警详情";
ResetCommand = new DelegateCommand(obj => Reset());
CloseCommand = new DelegateCommand(obj => Close());
}
private AlarmInfo _alarmInfo;
public AlarmInfo AlarmInfo
{
get => _alarmInfo;
set
{
SetAndNotify(ref _alarmInfo, value);
}
}
private void Close()
{
RequestClose(false);
}
private void Reset()
{
RequestClose(true);
}
}
}

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" />
<section name="templates" type="MwFramework.Controls.PatternTemplate.ConfigModule.TemplateConfigurationSection,MwFramework.Controls.PatternTemplate" />
</configSections>
<templates parserType="MwFramework.HuaruiMatch.TypeParser" caliperType="MwFramework.HuaruiMatch.CaliperTest" assemblyFile="MwFramework.HuaruiMatch.dll">
<template templateName="Shape" templateType="MwFramework.HuaruiMatch.ShapeMatch" assemblyFile="MwFramework.HuaruiMatch.dll"></template>
<template templateName="Ncc" templateType="MwFramework.HuaruiMatch.TemplateMatch" assemblyFile="MwFramework.HuaruiMatch.dll"></template>
</templates>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
<appSettings>
<add key="Demo" value="true" />
<!--语言-->
<add key="Lang" value="CN" />
<add key="SaveLogsWay" value="DataBase"/>
<!--Txt 存储路径-->
<add key="LogsPath" value="D:\\Logs" />
<add key="MachineId" value="" />
</appSettings>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.1.0" newVersion="4.2.1.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -0,0 +1,21 @@
<Application x:Class="MainShell.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MainShell" xmlns:mw="http://www.maxwell-gp.com/"
>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MaxwellControl;component/Themes/SkinTouchable.xaml" />
<mw:ApplicationLoader>
<mw:ApplicationLoader.Bootstrapper>
<local:StartBootstrapper/>
</mw:ApplicationLoader.Bootstrapper>
</mw:ApplicationLoader>
<ResourceDictionary Source="/Resources/Styles/Styles.xaml"/>
<ResourceDictionary Source="/Language/MXJM_CN.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace MainShell
{
/// <summary>
/// App.xaml 的交互逻辑
/// </summary>
public partial class App : Application
{
}
}

View File

@@ -0,0 +1,171 @@
# CLAUDE.md
## 前置指令
1. **XAML 文件可以直接更改** — 使用 Edit 工具直接修改 `.xaml` 文件
2. **CS 文件有 TSM 加密**`.cs` 文件在本地是加密的,无法直接读取或编辑。需要通过 `git show HEAD:path` 获取内容。但注意:有时最新的 CS 文件还未提交到 git此时可以让用户直接提供最新的 CS 文件内容
3. **所有回复使用中文** — 所有与用户的交流、注释说明等均使用中文
## PageCalib 目录结构
PageCalib 是标定页面模块,采用 MVVM 架构,包含 8 个标定子模块。主入口通过 `PageCalibView.xaml` + `PageCalibViewModel.cs` 管理导航。
### 目录组织
```
PageCalib/
├── View/ # 主视图
│ ├── PageCalibView.xaml # 主页面,使用 SideMenu 导航
│ └── PageCalibView.xaml.cs
├── ViewModel/ # 主视图模型
│ └── PageCalibViewModel.cs # 管理 8 个标定子模块导航
├── HeightMeasure/ # 高度标定模块
│ ├── Model/ # HeightBaseSetting, IHeightMeasure, DiastimeterHeightMeasure
│ ├── Service/ # HeightMeasureMotionService
│ ├── View/ # HeightView.xaml
│ └── ViewModel/ # HeightViewModel
├── OriginCalib/ # 原点标定模块
│ ├── Model/ # OriginCalibSetting
│ ├── Service/ # ICalibrationPostProcessor, OriginCalibrationMotionService, CalibrationPostProcessors
│ ├── View/ # OriginCalibView.xaml
│ └── ViewModel/ # OriginCalibViewModel, OriginCalibModuleViewModel, AvoidanceAxisViewModel, CalibrationAxisViewModel
└── AlgorithmCalib/ # 算法标定模块(包含多个子模块)
├── Common/ # 公共接口和结果类
│ ├── IAlgorithmCalibModule.cs
│ ├── AlgorithmCalibResult.cs
│ └── CalibrationProgressEventArgs.cs
├── Model/ # 参数模型
│ ├── AlgorithmCalibModuleNames.cs
│ ├── FusionCalibParItem.cs
│ ├── RotateCalibParItem.cs
│ └── FusionCalib/ # FusionCalibSetting, FusionCalibModuleItem
├── Task/ # 标定任务
│ ├── RotateFormCalibTask.cs
│ └── FusionCalibTask.cs
├── View/ # 各子模块视图
│ ├── PixRatioCalib/ # 像素比标定
│ ├── DistortionCorrectionCalib/ # 畸变校正标定
│ ├── RotateCenterCalib/ # 旋转中心标定
│ ├── RotateMatixFormCalib/ # 旋转表标定
│ ├── MotionCalib/ # 运动系标定
│ └── FusionCalib/ # 融合标定Die/Pad
├── ViewModel/ # 各子模块视图模型
│ ├── PixRatioCalib/
│ ├── DistortionCorrectionCalib/
│ ├── RotateCenterCalib/
│ ├── RotateMatixFormCalib/
│ ├── MotionCalib/
│ └── FusionCalib/
└── Service/ # 各子模块服务
├── RotateFormCalib/ # RotateMatixFormCalibMotionService, FileService, PostProcessor
├── MotionCalib/ # MotionCalibFileService
└── FusionCalib/ # FusionCalibMotionService, PostProcessor, FusionAlignProcessor
```
### 标定子模块列表
| 模块名称 | 中文名 | 主 ViewModel | 说明 |
|---------|--------|-------------|------|
| HeightMeasure | 高度标定 | HeightViewModel | 测高标定,包含产品和方片高度测量 |
| OriginCalib | 原点标定 | OriginCalibViewModel | 原点位置标定 |
| PixRatioCalib | 像素比标定 | PixRatioCalibContentsViewModel | 相机像素比例标定 |
| DistortionCorrectionCalib | 畸变校准标定 | DistortionCorrectionCalibContentsViewModel | 相机畸变校正 |
| MotionCalib | 运动系标定 | MotionCalibContentsViewModel | 运动系统标定 |
| RotateCenterCalib | 旋转中心标定 | RotateCenterCalibContentsViewModel | 旋转中心位置标定 |
| RotateFormCalib | 旋转表标定 | RotateMatixFormCalibViewModel | 旋转矩阵表标定 |
| FusionCalib | 融合标定 | FusionCalibViewModel | Die/Pad 融合标定 |
### 通用 UI 模式
算法标定子模块PixRatio、DistortionCorrection、RotateCenter、MotionCalib、FusionCalib采用统一的 ContentsView 布局:
- 顶部:当前标定名称 + 进度文本
- 中间ContentControl 绑定 ShowScreenVM 显示具体内容
- 底部:上一个/下一个导航按钮
旋转表标定RotateMatixFormCalib采用卡片式布局
- 左侧:相机预览
- 右侧:模块卡片(避让位置、标定参数、验证参数、进度条、操作按钮)
## 融合标定需求与实现
### 轴映射关系
| 项目 | WS轴Wafer轴 | PHS轴Pad轴 |
|------|-----------------|----------------|
| 旧项目 | X2, Y2 | X1, Y1 |
| 新项目 | X2, Y1 | X1, Y2 |
### 融合标定流程
#### 1. Die融合标定ws圆形标定融合
在X1全行程不同位置标定建立X2,Y1的die融合表用于对位晶粒。
**标定方法:**
- 在die运动系下固定X1移动X2,Y1扫描获取N×N点阵作为初始位置
- 选取X2负限位位置附近设置起始位置将X1,X2平移相同距离移动到起始位置
- 设定标定范围、标定间隔扫描一系列N×N点阵保存为die融合位置表
**验证方法:**
- 在die运动系下飞拍任意坐标
- 再选取任意X1位置使用融合位置表计算出任意坐标移动到该X1位置下的X2,Y1坐标
- 同时获取到在该X1位置下实际逼近的X2,Y1坐标
- 输出即为标定误差,可选择若干位置覆盖测试全行程误差
#### 2. Pad融合标定stage拼接融合
在Y1全行程不同位置建立X1,Y2的pad融合表用于对位pad。
**标定方法:**
- 在pad运动系下固定Y1移动X1,Y2扫描获取N×N点阵作为初始位置
- 选取Y2负限位位置附近设置起始位置将Y1,Y2平移相同距离移动到起始位置
- 设立标定范围、标定间隔扫描一系列N×N点阵保存为pad融合位置表
**验证方法:**
- 在pad运动系下飞拍任意坐标
- 再选取任意Y1位置使用融合位置表计算出任意坐标移动到该Y1位置下的X1,Y2坐标
- 同时获取到在该Y1位置下实际逼近的X1,Y2坐标
- 输出即为标定误差,可选择若干位置覆盖测试全行程误差
#### 3. 整体对位验证(对位流程)
整体对位流程为:
1. 飞拍获取die的下相机X2,Y2坐标X1坐标固定上相机die运动系X2,Y1转换为X1,Y1坐标
2. Pad定位mark获取X1,Y2坐标Y1坐标固定上相机pad运动系X1,Y2即转化为X1,Y1坐标
3. 通过查找die融合表将die X方向对齐pad此时Y1会产生少许偏移
4. 再根据此时Y1值将pad Y方向对齐dieX1会产生少许偏移
5. 此时再移动X2跟上X1的移动量此处直接移动或查表再移动
### 新项目融合标定文件结构
```
AlgorithmCalib/
├── View/FusionCalib/
│ ├── DieFusionCalibView.xaml # Die融合标定视图标定+验证Tab
│ ├── PadFusionCalibView.xaml # Pad融合标定视图标定+验证Tab
│ └── FusionAlignVerifyView.xaml # 整体对位验证视图4步骤流程
├── ViewModel/FusionCalib/
│ ├── FusionCalibViewModel.cs # Die/Pad融合标定共用ViewModel
│ ├── FusionAlignVerifyViewModel.cs # 整体对位验证ViewModel
│ └── FusionMultipleCalibViewModel.cs # 多模块融合标定ViewModel
├── Service/FusionCalib/
│ ├── FusionCalibMotionService.cs # 融合标定运动服务
│ ├── FusionCalibPostProcessor.cs # 融合标定后处理器
│ └── FusionAlignProcessor.cs # 对位处理器
└── Model/FusionCalib/
├── FusionCalibSetting.cs # 融合标定设置
└── FusionCalibModuleItem.cs # 融合标定模块参数
```
### 旧项目参考文件
旧项目融合标定参考文件位于 `AlgorithmCalib/Old_fusionCalib/` 目录:
- `oldProjectDetail.xaml` - 旧项目融合标定流程说明
- `newProjectVisionDemand.xaml` - 新项目需求说明
- `CameraFusionCali02AViewModel.xaml` - 旧项目ViewModel实现CS内容
- `CameraFusionCalibrationMotion02A.xaml` - 旧项目Motion实现CS内容
### 关键API调用
旧项目使用的JM1Vision API
- `JM1Manager.Instance.cal_wafer_fusion()` - 计算wafer融合表
- `JM1Manager.Instance.get_ws_pos()` - 根据融合表查询WS位置
- `JM1Manager.Instance.pos_verify()` - 验证标定精度
- `JM1Manager.Instance.Save()` - 保存标定数据

View File

@@ -0,0 +1,61 @@
using System;
using System.Windows;
using System.Windows.Input;
namespace MainShell.Common.Behaviors
{
public static class WindowDragMoveBehavior
{
public static readonly DependencyProperty IsEnabledProperty = DependencyProperty.RegisterAttached(
"IsEnabled",
typeof(bool),
typeof(WindowDragMoveBehavior),
new PropertyMetadata(false, OnIsEnabledChanged));
public static bool GetIsEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(IsEnabledProperty);
}
public static void SetIsEnabled(DependencyObject obj, bool value)
{
obj.SetValue(IsEnabledProperty, value);
}
private static void OnIsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var element = d as UIElement;
if (element == null)
{
return;
}
if ((bool)e.NewValue)
{
element.MouseLeftButtonDown += OnMouseLeftButtonDown;
return;
}
element.MouseLeftButtonDown -= OnMouseLeftButtonDown;
}
private static void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var element = sender as DependencyObject;
var window = element != null ? Window.GetWindow(element) : null;
if (window == null || e.ButtonState != MouseButtonState.Pressed)
{
return;
}
try
{
window.DragMove();
e.Handled = true;
}
catch (InvalidOperationException)
{
}
}
}
}

View File

@@ -0,0 +1,59 @@
using MainShell.Log;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
namespace MainShell.Common
{
public static class CommonUti
{
public static void RunOnUi(Action action)
{
if (action == null)
{
return;
}
try
{
if (Application.Current == null || Application.Current.Dispatcher.CheckAccess())
{
// 同步在当前线程执行
action();
}
else
{
// 在 UI 线程同步执行
Application.Current.Dispatcher.Invoke(action);
}
}
catch (Exception ex)
{
MaxwellControl.Controls.MessageBox.Show($"方法执行异常:{ex.ToString()}", icon: MessageBoxImage.Error);
}
}
public static Brush BrushFromString(string s)
{
if (string.IsNullOrWhiteSpace(s))
return Brushes.Transparent;
try
{
var brush = (Brush)new BrushConverter().ConvertFromString(s);
return brush ?? Brushes.Transparent;
}
catch
{
// 如果解析失败,返回默认颜色(可根据需要改为 Brushes.Black 或抛异常)
return Brushes.Transparent;
}
}
}
}

View File

@@ -0,0 +1,240 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using MainShell.Resources.CustomControl;
namespace MainShell.Common.ControlAttribute
{
public static class ControlBehavior
{
public static bool GetIsEnable(DependencyObject obj)
{
return (bool)obj.GetValue(IsEnableProperty);
}
public static void SetIsEnable(DependencyObject obj, bool value)
{
obj.SetValue(IsEnableProperty, value);
}
// Using a DependencyProperty as the backing store for IsEnable. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsEnableProperty =
DependencyProperty.RegisterAttached("IsEnable", typeof(bool), typeof(ControlBehavior), new PropertyMetadata(true, OnProppertyChanged));
public static bool GetIsNumericOnly(DependencyObject obj)
{
return (bool)obj.GetValue(IsNumericOnlyProperty);
}
public static void SetIsNumericOnly(DependencyObject obj, bool value)
{
obj.SetValue(IsNumericOnlyProperty, value);
}
public static readonly DependencyProperty IsNumericOnlyProperty =
DependencyProperty.RegisterAttached("IsNumericOnly", typeof(bool), typeof(ControlBehavior), new PropertyMetadata(false, OnIsNumericOnlyChanged));
public static bool GetRouteDieMapMouseWheel(DependencyObject obj)
{
return (bool)obj.GetValue(RouteDieMapMouseWheelProperty);
}
public static void SetRouteDieMapMouseWheel(DependencyObject obj, bool value)
{
obj.SetValue(RouteDieMapMouseWheelProperty, value);
}
public static readonly DependencyProperty RouteDieMapMouseWheelProperty =
DependencyProperty.RegisterAttached("RouteDieMapMouseWheel", typeof(bool), typeof(ControlBehavior), new PropertyMetadata(false, OnRouteDieMapMouseWheelChanged));
private static void OnProppertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is TabControl tabControl)
{
if (e.NewValue is bool isenable)
{
if (isenable)
foreach (var item in tabControl.Items)
{
if (tabControl.ItemContainerGenerator.ContainerFromItem(item) is TabItem tabItem)
{
tabItem.IsEnabled = isenable;
}
}
else
foreach (var item in tabControl.Items)
{
if (tabControl.ItemContainerGenerator.ContainerFromItem(item) is TabItem tabItem)
{
if (tabItem.IsSelected)
{
tabItem.IsEnabled = true;
}
else
tabItem.IsEnabled = isenable;
}
}
}
}
}
private static void OnIsNumericOnlyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is TextBox textBox))
return;
if ((bool)e.NewValue)
{
InputMethod.SetIsInputMethodEnabled(textBox, false);
textBox.PreviewTextInput += TextBox_PreviewTextInput;
DataObject.AddPastingHandler(textBox, OnTextBoxPaste);
}
else
{
InputMethod.SetIsInputMethodEnabled(textBox, true);
textBox.PreviewTextInput -= TextBox_PreviewTextInput;
DataObject.RemovePastingHandler(textBox, OnTextBoxPaste);
}
}
private static void OnRouteDieMapMouseWheelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ScrollViewer scrollViewer = d as ScrollViewer;
if (scrollViewer == null)
{
return;
}
bool isEnabled = e.NewValue is bool && (bool)e.NewValue;
MouseWheelEventHandler mouseWheelEventHandler = new MouseWheelEventHandler(ScrollViewer_PreviewMouseWheel);
if (isEnabled)
{
scrollViewer.RemoveHandler(UIElement.PreviewMouseWheelEvent, mouseWheelEventHandler);
scrollViewer.AddHandler(UIElement.PreviewMouseWheelEvent, mouseWheelEventHandler, true);
}
else
{
scrollViewer.RemoveHandler(UIElement.PreviewMouseWheelEvent, mouseWheelEventHandler);
}
}
private static void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
ScrollViewer scrollViewer = sender as ScrollViewer;
if (scrollViewer == null)
{
return;
}
DieMapControl dieMapControl = FindDieMapControl(scrollViewer, e);
if (dieMapControl == null)
{
return;
}
e.Handled = true;
MouseWheelEventArgs mouseWheelEventArgs = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
mouseWheelEventArgs.RoutedEvent = UIElement.MouseWheelEvent;
mouseWheelEventArgs.Source = dieMapControl;
dieMapControl.RaiseEvent(mouseWheelEventArgs);
}
private static DieMapControl FindDieMapControl(ScrollViewer scrollViewer, MouseWheelEventArgs e)
{
DependencyObject dependencyObject = e.OriginalSource as DependencyObject;
DieMapControl dieMapControl = FindAncestor<DieMapControl>(dependencyObject);
if (dieMapControl != null)
{
return dieMapControl;
}
dependencyObject = Mouse.DirectlyOver as DependencyObject;
dieMapControl = FindAncestor<DieMapControl>(dependencyObject);
if (dieMapControl != null)
{
return dieMapControl;
}
IInputElement inputElement = scrollViewer.InputHitTest(e.GetPosition(scrollViewer));
dependencyObject = inputElement as DependencyObject;
return FindAncestor<DieMapControl>(dependencyObject);
}
private static T FindAncestor<T>(DependencyObject dependencyObject) where T : DependencyObject
{
while (dependencyObject != null)
{
T target = dependencyObject as T;
if (target != null)
{
return target;
}
DependencyObject parent = VisualTreeHelper.GetParent(dependencyObject);
if (parent == null && dependencyObject is FrameworkContentElement)
{
parent = ((FrameworkContentElement)dependencyObject).Parent;
}
dependencyObject = parent;
}
return null;
}
private static void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
if (sender is TextBox textBox)
{
e.Handled = !IsValidNumericText(GetPreviewText(textBox, e.Text));
}
}
private static void OnTextBoxPaste(object sender, DataObjectPastingEventArgs e)
{
if (!(sender is TextBox textBox))
return;
if (!e.DataObject.GetDataPresent(typeof(string)))
{
e.CancelCommand();
return;
}
var pasteText = e.DataObject.GetData(typeof(string)) as string ?? string.Empty;
if (!IsValidNumericText(GetPreviewText(textBox, pasteText)))
{
e.CancelCommand();
}
}
private static string GetPreviewText(TextBox textBox, string newText)
{
var currentText = textBox.Text ?? string.Empty;
if (textBox.SelectionLength > 0)
{
currentText = currentText.Remove(textBox.SelectionStart, textBox.SelectionLength);
}
return currentText.Insert(textBox.CaretIndex, newText);
}
private static bool IsValidNumericText(string text)
{
if (string.IsNullOrWhiteSpace(text) || text == "-" || text == "." || text == "-.")
return true;
return double.TryParse(text, out _);
}
}
}

View File

@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using MessageBox = MaxwellControl.Controls.MessageBox;
namespace MainShell.Common.ControlAttribute
{
public class NumericValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
string strValue = value as string;
if (string.IsNullOrEmpty(strValue))
{
// 空值是允许的,如果需要必填,则返回 new ValidationResult(false, "不能为空");
return new ValidationResult(false, "不能为空");
}
// 尝试将字符串转换为double
if (double.TryParse(strValue, out _))
{
return ValidationResult.ValidResult;
}
else
{
return new ValidationResult(false, "请输入有效的数字。");
}
}
}
}

View File

@@ -0,0 +1,97 @@
using MaxwellFramework.Core.Common;
using MwFramework.Controls.ControlCanvas.Model;
using MwFramework.ManagerService;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MainShell.Common.Display.Models
{
public class CameraAxisDevices : ViewModelBase
{
List<HardwareDevice> _hardwareDeviceList = new List<HardwareDevice>();
HardwareDevice _selectedHardwareDevice = new HardwareDevice();
private ObservableCollection<object> _shapes = new ObservableCollection<object>();
private int _selectedIndex = 0;
private bool _cameraSwitchEnable = true;
public List<HardwareDevice> HardwareDeviceList
{
get { return _hardwareDeviceList; }
set
{
if (_hardwareDeviceList == value)
{
return;
}
_hardwareDeviceList = value;
if (_hardwareDeviceList != null && _hardwareDeviceList.Count > 0)
{
_selectedIndex = 0;
SelectedHardwareDevice = _hardwareDeviceList[_selectedIndex];
RaisePropertyChanged(nameof(SelectedIndex));
}
RaisePropertyChanged(nameof(HardwareDeviceList));
}
}
public HardwareDevice SelectedHardwareDevice
{
get { return _selectedHardwareDevice; }
set
{
if (_selectedHardwareDevice != null && _selectedHardwareDevice.Camera != null && value != null && value.Camera != null)
{
}
_selectedHardwareDevice = value; RaisePropertyChanged(nameof(SelectedHardwareDevice));
}
}
public ObservableCollection<object> Shapes
{
get { return _shapes; }
set
{
if (_shapes != value) { _shapes = value; RaisePropertyChanged(nameof(Shapes)); }
}
}
private ObservableCollection<PrimShape> _regions = new ObservableCollection<PrimShape>();
public ObservableCollection<PrimShape> Regions
{
get { return _regions; }
set
{
SetAndNotify(ref _regions, value);
}
}
public int SelectedIndex
{
get { return _selectedIndex; }
set
{
_selectedIndex = value;
if (HardwareDeviceList != null && HardwareDeviceList.Count > 0 && _selectedIndex >= 0)
{
if (_selectedIndex < HardwareDeviceList.Count)
{
SelectedHardwareDevice = HardwareDeviceList[_selectedIndex];
}
}
RaisePropertyChanged(nameof(SelectedIndex));
}
}
public bool CameraSwitchEnable
{
get { return _cameraSwitchEnable; }
set { _cameraSwitchEnable = value; RaisePropertyChanged(nameof(CameraSwitchEnable)); }
}
}
}

View File

@@ -0,0 +1,30 @@
<UserControl x:Class="MainShell.Common.Display.View.CameraAxisView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MainShell.Common.Display.View"
xmlns:control="http://www.maxwell.com/controls"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<CheckBox Panel.ZIndex="2" IsChecked="{Binding IsOpen, UpdateSourceTrigger=PropertyChanged}" Cursor="Hand" Margin="2,2" Foreground="White" HorizontalAlignment="Right" VerticalAlignment="Top">
<TextBlock Text="移动"/>
</CheckBox>
<control:CameraAxisControlA Name="cameraAxisControl"
IsShowDoubleLine="False"
IsAxisControlLDBVisible2="Visible"
Cameras="{Binding CameraAxisDevices.HardwareDeviceList}"
TabSelectedIndex ="{Binding CameraAxisDevices.SelectedIndex}"
Items="{Binding CameraAxisDevices.Shapes,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
Regions="{Binding CameraAxisDevices.Regions}" ShapeThickness="1" IsShowSolidLine="True" DrawInConcurrency="False"
>
<i:Interaction.Triggers>
<i:EventTrigger EventName="RecordPix">
<i:InvokeCommandAction Command="{Binding OnLeftMouseDownCommand}" CommandParameter="{Binding ElementName=cameraAxisControl}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</control:CameraAxisControlA>
</Grid>
</UserControl>

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace MainShell.Common.Display.View
{
/// <summary>
/// CameraAxisView.xaml 的交互逻辑
/// </summary>
public partial class CameraAxisView : UserControl
{
public CameraAxisView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,22 @@
<UserControl x:Class="MainShell.Common.Display.View.CameraView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MainShell.Common.Display.View"
xmlns:mw="http://www.maxwell.com/controls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Border BorderThickness="1" BorderBrush ="#B0B9C4">
<mw:DesignPanel x:Name="cameraDesignPanel"
Source="{Binding DisplayImage}"
Items="{Binding Shapes}"
IsVirtualPix="Visible"
IsShowSolidLine="True"
IsCrossingLineVisible="False"
IsNonRectCrossingLineVisible="False"
IsImagePix="Collapsed" />
</Border>
</Grid>
</UserControl>

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace MainShell.Common.Display.View
{
/// <summary>
/// CameraView.xaml 的交互逻辑
/// </summary>
public partial class CameraView : UserControl
{
public CameraView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,323 @@
using MainShell.Common;
using MainShell.Common.Display.Models;
using MainShell.Log;
using MainShell.Motion;
using Maxwell.SemiFramework.DefaultConfig.Vision;
using MwFramework.Controls.Components;
using MwFramework.Controls.ControlCanvas.Model;
using MwFramework.Controls.UIControl;
using MwFramework.Device;
using MwFramework.ManagerService;
using Stylet;
using StyletIoC;
using System;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
namespace MainShell.Common.Display.ViewModel
{
public class CameraAxisViewModel : Screen
{
private const double DefaultFovX = 14.1 * 10;
private const double DefaultFovY = 10.3 * 10;
private const string SafeAxisMotionNotInjectedMessage = "SafeAxisMotion is not injected.";
private readonly object _moveLock = new object();
private CameraAxisDevices _cameraAxisDevices = new CameraAxisDevices();
private double _xPixelPos;
private double _yPixelPos;
private double _cameraXIndex;
private double _cameraYIndex;
private GetConvertValue _convertFunXDelegate;
private GetConvertValue _convertFunYDelegate;
private ObservableCollection<PrimShape> _regions = new ObservableCollection<PrimShape>();
private bool _isCameraEnable = true;
private Visibility _controlVisibility = Visibility.Visible;
private bool _isOpen;
[Inject]
public SafeAxisMotion SafeAxisMotion { get; set; }
public CameraAxisViewModel()
{
ConvertFunXDelegate = new GetConvertValue(ConvertFunX);
ConvertFunYDelegate = new GetConvertValue(ConvertFunY);
OnLeftMouseDownCommand = new DelegateCommand<object>(OnLeftMouseDown);
}
public CameraAxisDevices CameraAxisDevices
{
get { return _cameraAxisDevices; }
set { SetAndNotify(ref _cameraAxisDevices, value); }
}
public double XPixelPos
{
get { return _xPixelPos; }
set { SetAndNotify(ref _xPixelPos, value); }
}
public double YPixelPos
{
get { return _yPixelPos; }
set { SetAndNotify(ref _yPixelPos, value); }
}
public double CameraXIndex
{
get { return _cameraXIndex; }
set { SetAndNotify(ref _cameraXIndex, value); }
}
public double CameraYIndex
{
get { return _cameraYIndex; }
set { SetAndNotify(ref _cameraYIndex, value); }
}
public GetConvertValue ConvertFunXDelegate
{
get { return _convertFunXDelegate; }
set { SetAndNotify(ref _convertFunXDelegate, value); }
}
public GetConvertValue ConvertFunYDelegate
{
get { return _convertFunYDelegate; }
set { SetAndNotify(ref _convertFunYDelegate, value); }
}
public ObservableCollection<PrimShape> Regions
{
get { return _regions; }
set { SetAndNotify(ref _regions, value); }
}
public bool IsCameraEnable
{
get { return _isCameraEnable; }
set { SetAndNotify(ref _isCameraEnable, value); }
}
public Visibility ControlVisibility
{
get { return _controlVisibility; }
set { SetAndNotify(ref _controlVisibility, value); }
}
public ICommand OnLeftMouseDownCommand { get; private set; }
public bool IsOpen
{
get { return _isOpen; }
set { SetAndNotify(ref _isOpen, value); }
}
public void OnLeftMouseDown(object sender)
{
try
{
HardwareDevice selectedDevice;
if (!TryGetSelectedDevice(out selectedDevice))
{
return;
}
CameraAxisControlA controlA = sender as CameraAxisControlA;
if (controlA == null)
{
return;
}
Point pixelPos = new Point(controlA.YPixPos, controlA.XPixPos);
Task.Run(() => MoveToPixelPoint(selectedDevice, pixelPos, false));
}
catch (Exception ex)
{
LogManager.LogSysError(ex);
ShowOperationFailed(ex.Message);
}
}
public void MovePosAction()
{
try
{
HardwareDevice selectedDevice;
if (!TryGetSelectedDevice(out selectedDevice))
{
return;
}
Point pixelPos = new Point(YPixelPos, XPixelPos);
Task.Run(() => MoveToPixelPoint(selectedDevice, pixelPos, true));
}
catch (Exception ex)
{
LogManager.LogSysError(ex);
ShowOperationFailed(ex.Message);
}
}
public double ConvertFunX(double interval)
{
try
{
HardwareDevice selectedDevice;
if (!TryGetSelectedDevice(out selectedDevice))
{
return 0;
}
string name = selectedDevice.Camera.Id;
double dx;
double dy;
VisionProcess.Instance.GetCameraResolution(name, out dx, out dy);
double pixelX = interval / Math.Abs(dx);
return pixelX;
}
catch (Exception ex)
{
LogManager.LogSysError(ex);
ShowOperationFailed(ex.Message);
return 0;
}
}
public double ConvertFunY(double interval)
{
try
{
HardwareDevice selectedDevice;
if (!TryGetSelectedDevice(out selectedDevice))
{
return 0;
}
string name = selectedDevice.Camera.Id;
double dx;
double dy;
VisionProcess.Instance.GetCameraResolution(name, out dx, out dy);
double pixelY = interval / Math.Abs(dy);
return pixelY;
}
catch (Exception ex)
{
LogManager.LogSysError(ex);
ShowOperationFailed(ex.Message);
return 0;
}
}
private bool TryGetSelectedDevice(out HardwareDevice selectedDevice)
{
selectedDevice = CameraAxisDevices != null ? CameraAxisDevices.SelectedHardwareDevice : null;
if (!IsOpen || selectedDevice == null)
{
return false;
}
if (selectedDevice.Camera == null || selectedDevice.Camera.Camera == null)
{
ShowDeviceNotInitialized();
return false;
}
if (!selectedDevice.Camera.Camera.IsGrabbing)
{
LocalizedMessageBox.Show(MessageKey.VisionCameraNotGrabbing, MessageKey.TitleWarning, MessageBoxButton.OK, MessageBoxImage.Warning);
return false;
}
if (selectedDevice.AxisX == null || selectedDevice.AxisY == null)
{
ShowDeviceNotInitialized();
return false;
}
return true;
}
private void MoveToPixelPoint(HardwareDevice selectedDevice, Point pixelPos, bool requireConfirmation)
{
lock (_moveLock)
{
try
{
IAxis axisX = selectedDevice.AxisX;
IAxis axisY = selectedDevice.AxisY;
Point rulerPos = new Point(axisX.State.ActualPos, axisY.State.ActualPos);
Point newRulerPoint = Algorithm.Instance.MoveToPixelPoint(selectedDevice.Camera.Id, rulerPos, pixelPos);
if (requireConfirmation)
{
double dx = newRulerPoint.X - rulerPos.X;
double dy = newRulerPoint.Y - rulerPos.Y;
if (!ValidateMoveRange(dx, dy))
{
return;
}
if (!ConfirmMove(newRulerPoint))
{
return;
}
}
if (SafeAxisMotion == null)
{
InvalidOperationException exception = new InvalidOperationException(SafeAxisMotionNotInjectedMessage);
LogManager.LogSysError(exception);
ShowOperationFailed(SafeAxisMotionNotInjectedMessage);
return;
}
SafeAxisMotion.SafeMove(
MotionMoveRequest.ForAxis(axisX, newRulerPoint.X),
MotionMoveRequest.ForAxis(axisY, newRulerPoint.Y));
}
catch (Exception ex)
{
LogManager.LogSysError(ex);
ShowOperationFailed(ex.Message);
}
}
}
private static bool ValidateMoveRange(double dx, double dy)
{
if (Math.Abs(dx) > DefaultFovX || Math.Abs(dy) > DefaultFovY)
{
LocalizedMessageBox.Show(MessageKey.ParamOutOfRange, MessageKey.TitleWarning, MessageBoxButton.OK, MessageBoxImage.Warning);
return false;
}
return true;
}
private static bool ConfirmMove(Point newRulerPoint)
{
string message = string.Format("新点的坐标({0},{1}),是否移动?", newRulerPoint.X, newRulerPoint.Y);
return MwMessageBox.Show(message, LanguageResourceHelper.GetString(MessageKey.TitleConfirm), MessageBoxButton.OKCancel, MessageBoxImage.Question, MessageBoxResult.Cancel) == MessageBoxResult.OK;
}
private static void ShowDeviceNotInitialized()
{
LocalizedMessageBox.Show(MessageKey.DeviceNotInitialized, MessageKey.TitleWarning, MessageBoxButton.OK, MessageBoxImage.Warning);
}
private static void ShowOperationFailed(string message)
{
if (string.IsNullOrWhiteSpace(message))
{
LocalizedMessageBox.Show(MessageKey.CommonOperationFailed, MessageKey.TitleError, MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
MwMessageBox.Show(message, LanguageResourceHelper.GetString(MessageKey.TitleError), MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}

View File

@@ -0,0 +1,317 @@
using MainShell.EventArgsFolder;
using MainShell.Log;
using MainShell.Vision;
using MwFramework.Device.Model;
using MwFramework.Controls.ControlCanvas.DrawingControl;
using Stylet;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
using AppCameraType = MainShell.Common.CameraType;
using System.Windows.Media;
namespace MainShell.Common.Display.ViewModel
{
public class CameraViewModel : Screen, IHandle<DisplayImageEventArgs>, IHandle<DisplayFindTemplateResultEventArgs>
{
private readonly IEventAggregator _eventAggregator;
public AppCameraType CameraType { get; }
private WriteableBitmap currentImage;
private WriteableBitmap _displayImage;
public WriteableBitmap DisplayImage
{
get { return _displayImage; }
set
{
SetAndNotify(ref _displayImage, value);
}
}
private ObservableCollection<object> _shapes = new ObservableCollection<object>();
public ObservableCollection<object> Shapes
{
get { return _shapes; }
set
{
if (_shapes != value) { _shapes = value; OnPropertyChanged(nameof(Shapes)); }
}
}
/// <summary>
/// 根据 CameraData 更新并返回 WriteableBitmap。
/// 优化要点:
/// - 重用已有 WriteableBitmap当尺寸与像素格式相同时以减少分配。
/// - 校验参数与缓冲区长度。
/// - 捕获并记录异常,失败时返回 null不抛出
/// </summary>
public WriteableBitmap UpdateBitmap(CameraData cameraData)
{
if (cameraData == null)
{
"图片数据为空".LogSysError();
return null;
}
try
{
int width = (int)cameraData.Width;
int height = (int)cameraData.Height;
int bitCnt = cameraData.Bit;
byte[] buffer = cameraData.BufferData;
if (width <= 0 || height <= 0)
{
$"CameraViewModel.UpdateBitmap: invalid size {width}x{height}".LogSysError();
return null;
}
// 选择像素格式
System.Windows.Media.PixelFormat pixelFormat = bitCnt == 1
? System.Windows.Media.PixelFormats.Gray8
: (bitCnt == 3 ? System.Windows.Media.PixelFormats.Bgr24 : System.Windows.Media.PixelFormats.Bgra32);
// 计算每行字节数stride
int bytesPerPixel = (pixelFormat.BitsPerPixel + 7) / 8;
int stride = width * bytesPerPixel;
long requiredLength = (long)stride * height;
if (buffer == null)
{
"CameraViewModel.UpdateBitmap: buffer is null".LogSysError();
return null;
}
if (buffer.Length < requiredLength)
{
($"CameraViewModel.UpdateBitmap: buffer length {buffer.Length} is less than required {requiredLength}").LogSysError();
return null;
}
// 如果现有 bitmap 可复用(尺寸和格式一致),就重用以减少 GC/分配
if (currentImage == null ||
currentImage.PixelWidth != width ||
currentImage.PixelHeight != height ||
!currentImage.Format.Equals(pixelFormat))
{
// 新建 WriteableBitmap
currentImage = new WriteableBitmap(width, height, 96, 96, pixelFormat, null);
}
// 将字节拷贝到 BackBufferUI 线程中调用)
currentImage.Lock();
try
{
// BackBuffer 为 IntPtr使用 Marshal.Copy 从 byte[] 拷贝
System.Runtime.InteropServices.Marshal.Copy(buffer, 0, currentImage.BackBuffer, (int)requiredLength);
currentImage.AddDirtyRect(new Int32Rect(0, 0, width, height));
}
finally
{
currentImage.Unlock();
}
return currentImage;
}
catch (Exception ex)
{
($"CameraViewModel.UpdateBitmap exception: {ex}").LogSysError();
return null;
}
}
public CameraViewModel(IEventAggregator eventAggregator, AppCameraType cameraType)
{
_eventAggregator = eventAggregator;
CameraType = cameraType;
_eventAggregator?.Subscribe(this);
}
public void Handle(DisplayImageEventArgs message)
{
if (message == null || message.CameraType != CameraType)
{
return;
}
CommonUti.RunOnUi(() =>
{
WriteableBitmap bmp = UpdateBitmap(message.CameraData);
// 只有在成功生成 bitmap 时才更新 DisplayImage避免把 null 赋值导致 UI 清空
if (bmp != null)
{
DisplayImage = bmp;
}
});
}
public void Handle(DisplayFindTemplateResultEventArgs message)
{
if (message == null || message.CameraType != CameraType)
{
return;
}
CommonUti.RunOnUi(() =>
{
ApplyTemplateResultShapes(message);
});
}
private void ApplyTemplateResultShapes(DisplayFindTemplateResultEventArgs message)
{
if (message.ClearShapesBeforeDisplay)
{
Shapes.Clear();
}
if (message.Result == null)
{
return;
}
AppendCenterShapes(message.Result);
AppendContourShape(message.Result.Contour);
AppendCircleShapes(message.Result.Circles);
AppendLineShapes(message.Result.Lines);
AppendRectangleShapes(message.Result.Rectangles);
}
private void AppendCenterShapes(FindTemplateResult result)
{
if (result == null || !AreFinite(result.CenterX, result.CenterY, result.Score))
{
return;
}
ShapeDrawing pointShape = new ShapeDrawing();
pointShape.X = result.CenterX;
pointShape.Y = result.CenterY;
Shapes.Add(pointShape);
TextShapeDrawing textShape = new TextShapeDrawing();
textShape.X = result.CenterX;
textShape.Y = result.CenterY;
textShape.Text = $"Score:{result.Score:F3}";
Shapes.Add(textShape);
}
private void AppendContourShape(FindTemplateContourResult contour)
{
if (contour == null || !AreFinite(contour.StartX, contour.StartY, contour.EndX, contour.EndY))
{
return;
}
RectShapeDrawing contourShape = new RectShapeDrawing();
contourShape.X = contour.StartX;
contourShape.Y = contour.StartY;
contourShape.X1 = contour.EndX;
contourShape.Y1 = contour.EndY;
Shapes.Add(contourShape);
}
private void AppendCircleShapes(IList<FindTemplateCircleResult> circles)
{
if (circles == null)
{
return;
}
foreach (FindTemplateCircleResult circle in circles)
{
if (circle == null || !AreFinite(circle.CenterX, circle.CenterY, circle.Radius))
{
continue;
}
CircleShapeDrawing circleShape = new CircleShapeDrawing();
circleShape.X = circle.CenterX;
circleShape.Y = circle.CenterY;
circleShape.CenterPoint = new Point(circle.CenterX, circle.CenterY);
circleShape.RadiusX = circle.Radius;
circleShape.RadiusY = circle.Radius;
circleShape.LineWidth = 1;
circleShape.FillColor = Brushes.Blue;
Shapes.Add(circleShape);
}
}
private void AppendLineShapes(IList<FindTemplateLineResult> lines)
{
if (lines == null)
{
return;
}
foreach (FindTemplateLineResult line in lines)
{
if (line == null || !AreFinite(line.StartX, line.StartY, line.EndX, line.EndY))
{
continue;
}
LineShapeDrawing lineShape = new LineShapeDrawing();
lineShape.X = line.StartX;
lineShape.Y = line.StartY;
lineShape.X1 = line.EndX;
lineShape.Y1 = line.EndY;
Shapes.Add(lineShape);
}
}
private void AppendRectangleShapes(IList<FindTemplateRectangleResult> rectangles)
{
if (rectangles == null)
{
return;
}
foreach (FindTemplateRectangleResult rectangle in rectangles)
{
if (rectangle == null || !AreFinite(rectangle.StartX, rectangle.StartY, rectangle.Width, rectangle.Height, rectangle.Angle))
{
continue;
}
double halfWidth = rectangle.Width / 2d;
double halfHeight = rectangle.Height / 2d;
double cosAngle = Math.Cos(rectangle.Angle);
double sinAngle = Math.Sin(rectangle.Angle);
double centerX = rectangle.StartX + (halfWidth * cosAngle) - (halfHeight * sinAngle);
double centerY = rectangle.StartY + (halfWidth * sinAngle) + (halfHeight * cosAngle);
RectShape2Drawing rectangleShape = new RectShape2Drawing();
rectangleShape.X = centerX;
rectangleShape.Y = centerY;
rectangleShape.CenterX = centerX;
rectangleShape.CenterY = centerY;
rectangleShape.HalfWidth = halfWidth;
rectangleShape.HalfHeigth = halfHeight;
rectangleShape.Angle = rectangle.Angle;
Shapes.Add(rectangleShape);
}
}
private static bool AreFinite(params double[] values)
{
if (values == null)
{
return false;
}
foreach (double value in values)
{
if (double.IsNaN(value) || double.IsInfinity(value))
{
return false;
}
}
return true;
}
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MainShell.Common
{
/// <summary>
/// 一个简单的包装类,在对象被 Dispose 时执行指定的 Action。
/// </summary>
public class DisposableAction : IDisposable
{
private readonly Action _action;
private bool _isDisposed;
public DisposableAction(Action action)
{
_action = action ?? throw new ArgumentNullException(nameof(action));
}
public void Dispose()
{
if (!_isDisposed)
{
_action();
_isDisposed = true;
}
}
}
}

View File

@@ -0,0 +1,181 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MainShell.Common
{
public enum MachineMode { Manual, Auto, Maintenance }
public enum SpeedType
{
[Description("低速")]
Low,
[Description("中速")]
Medium,
[Description("高速")]
High
}
public enum DieTransferRowTraversalStrategy
{
[Description("全部正向")]
AllPositive = 0,
[Description("全部反向")]
AllNegative = 1,
[Description("蛇形")]
Serpentine = 2
}
public enum BondingPathMode
{
S形打件 = 1,
Z形正向打件,
Z形反向打件,
}
public enum BondingStagePathMode
{
S型区域打件 = 1,
Stage正向区域打件,
Stage负向区域打件,
}
public enum BondingWSPathMode
{
S型打件 = 1,
WS正向区域打件,
WS负向区域打件,
}
public enum RunningMode
{
= 1,
,
}
public enum CameraType
{
TopPositionCamera,
TopWsCamera,
TopWideCamera,
TopWideWsCamera,
MapCamera
}
public enum TransPathType
{
[Description("就近")]
Nearest,
[Description("顺序")]
Sequence,
}
public enum TransPathDirection
{
[Description("正向")]
Positive,
[Description("反向")]
Negative,
}
public enum DieState
{
[Description("可使用")]
Available,
[Description("已使用")]
Used,
[Description("错误")]
Error,
[Description("不存在")]
NotExist,
[Description("当前")]
Current,
[Description("目标")]
Target
}
public enum ProcessExecutionStatus
{
Unknown = 0,
Running,
Paused,
Canceled,
Faulted,
Completed
}
public enum FlowDisplayStage
{
Load = 0,
Align = 1,
Bond = 2,
Inspect = 3,
Unload = 4
}
public enum WaferScanMode
{
[Description("按需扫描")]
ScanOnDemand,
[Description("全扫")]
FullScan,
}
public enum BondingSection
{
/// <summary>
/// A区
/// </summary>
A,
/// <summary>
/// B区
/// </summary>
B
}
public enum ComSupMotionType
{
/// <summary>
/// 干涉写入
/// </summary>
Interfere = 102,
/// <summary>
/// 回零写入
/// </summary>
Home = 103,
/// <summary>
/// 快打执行
/// </summary>
FastBonding = 200,
/// <summary>
/// 慢打执行
/// </summary>
SlowBonding = 201,
/// <summary>
/// 报警清楚
/// </summary>
AlarmClear = 104,
/// <summary>
/// 切PID指定
/// </summary>
ChangePid = 301,
/// <summary>
/// 触发报警
/// </summary>
OccurAlarm = 105,
/// <summary>
/// 同步PID参数
/// </summary>
SyncPIDParam = 106,
/// <summary>
/// 手动设置刺针次数
/// </summary>
NeedleWorkCount = 302,
}
}

View File

@@ -0,0 +1,25 @@
using MwFramework.Device;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MainShell.Common.Extension
{
public static class DeviceExtension
{
private static readonly int _taskNum = 3;
public static void GetLastSamples(this IDiastimeter diastimeter, out double distance)
{
var doubles = new List<double>();
for (int i = 0; i < _taskNum; i++)
{
diastimeter.GetLastSample(out double val);
if (val != double.NaN)
doubles.Add(val);
}
distance = doubles.Average();
}
}
}

View File

@@ -0,0 +1,78 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
namespace MainShell.Common
{
public static class FocusedEditorCommitHelper
{
public static void CommitFocusedEditorChanges()
{
var focusedElement = Keyboard.FocusedElement as DependencyObject;
if (focusedElement == null)
return;
CommitBinding(focusedElement);
var dataGrid = FindAncestor<DataGrid>(focusedElement);
if (dataGrid != null)
{
dataGrid.CommitEdit(DataGridEditingUnit.Cell, true);
dataGrid.CommitEdit(DataGridEditingUnit.Row, true);
}
}
private static void CommitBinding(DependencyObject dependencyObject)
{
if (dependencyObject is TextBox textBox)
{
textBox.GetBindingExpression(TextBox.TextProperty)?.UpdateSource();
return;
}
if (dependencyObject is ComboBox comboBox)
{
comboBox.GetBindingExpression(Selector.SelectedItemProperty)?.UpdateSource();
comboBox.GetBindingExpression(ComboBox.TextProperty)?.UpdateSource();
return;
}
if (dependencyObject is ToggleButton toggleButton)
{
toggleButton.GetBindingExpression(ToggleButton.IsCheckedProperty)?.UpdateSource();
}
}
private static T FindAncestor<T>(DependencyObject dependencyObject) where T : DependencyObject
{
var current = dependencyObject;
while (current != null)
{
if (current is T target)
return target;
current = GetParent(current);
}
return null;
}
private static DependencyObject GetParent(DependencyObject dependencyObject)
{
if (dependencyObject is FrameworkElement frameworkElement)
{
return frameworkElement.Parent ?? VisualTreeHelper.GetParent(frameworkElement);
}
if (dependencyObject is FrameworkContentElement frameworkContentElement)
{
return frameworkContentElement.Parent;
}
return null;
}
}
}

View File

@@ -0,0 +1,380 @@
using MainShell.Resources.CustomControl;
using MaxwellFramework.Core.Events;
using Stylet;
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Media;
namespace MainShell.Common
{
public class HeaderDeviceStatusController : PropertyChangedBase, IHandle<MainViewSelectedPageChangeEvent>
{
private enum HeaderDeviceStatusTone
{
Auto,
Manual,
Maintenance,
Recipe,
Settings,
Calibration,
Unknown
}
private readonly IEventAggregator _eventAggregator;
private bool _hasLoadingStarted;
private bool _isVisible;
private string _labelText = string.Empty;
private string _statusText = string.Empty;
private Brush _badgeBackgroundBrush;
private Brush _badgeBorderBrush;
private Brush _labelForegroundBrush;
private Brush _statusForegroundBrush;
private Brush _indicatorBrush;
public HeaderDeviceStatusController(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(eventAggregator));
_eventAggregator.Subscribe(this);
LoadingService.Instance.PropertyChanged += OnLoadingServicePropertyChanged;
UpdateStatusText("Home");
IsVisible = false;
}
public bool IsVisible
{
get
{
return _isVisible;
}
private set
{
SetAndNotify(ref _isVisible, value);
}
}
public string LabelText
{
get
{
return _labelText;
}
private set
{
SetAndNotify(ref _labelText, value);
}
}
public string StatusText
{
get
{
return _statusText;
}
private set
{
SetAndNotify(ref _statusText, value);
}
}
public Brush BadgeBackgroundBrush
{
get
{
return _badgeBackgroundBrush;
}
private set
{
SetAndNotify(ref _badgeBackgroundBrush, value);
}
}
public Brush BadgeBorderBrush
{
get
{
return _badgeBorderBrush;
}
private set
{
SetAndNotify(ref _badgeBorderBrush, value);
}
}
public Brush LabelForegroundBrush
{
get
{
return _labelForegroundBrush;
}
private set
{
SetAndNotify(ref _labelForegroundBrush, value);
}
}
public Brush StatusForegroundBrush
{
get
{
return _statusForegroundBrush;
}
private set
{
SetAndNotify(ref _statusForegroundBrush, value);
}
}
public Brush IndicatorBrush
{
get
{
return _indicatorBrush;
}
private set
{
SetAndNotify(ref _indicatorBrush, value);
}
}
public void Handle(MainViewSelectedPageChangeEvent message)
{
if (message == null)
{
return;
}
UpdateStatusText(message.SelectePageName);
if (!LoadingService.Instance.IsBusy)
{
IsVisible = true;
}
}
private void OnLoadingServicePropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (!string.Equals(e.PropertyName, nameof(LoadingService.IsBusy), StringComparison.Ordinal))
{
return;
}
if (LoadingService.Instance.IsBusy)
{
_hasLoadingStarted = true;
IsVisible = false;
return;
}
if (_hasLoadingStarted)
{
IsVisible = true;
}
}
private void UpdateStatusText(string pageName)
{
string resourceKey;
HeaderDeviceStatusTone tone;
ResolveStatusDefinition(pageName, out resourceKey, out tone);
LabelText = GetResourceText("HeaderDeviceStatusLabel", "<22><>ǰ״̬:");
StatusText = GetResourceText(resourceKey, GetFallbackStatusText(tone));
ApplyTone(tone);
}
private static void ResolveStatusDefinition(string pageName, out string resourceKey, out HeaderDeviceStatusTone tone)
{
if (string.Equals(pageName, "Home", StringComparison.OrdinalIgnoreCase))
{
resourceKey = "HeaderDeviceModeAuto";
tone = HeaderDeviceStatusTone.Auto;
return;
}
if (string.Equals(pageName, "ManualOperate", StringComparison.OrdinalIgnoreCase))
{
resourceKey = "HeaderDeviceModeManual";
tone = HeaderDeviceStatusTone.Manual;
return;
}
if (string.Equals(pageName, "MenuDeviceMaint", StringComparison.OrdinalIgnoreCase))
{
resourceKey = "HeaderDeviceModeMaintenance";
tone = HeaderDeviceStatusTone.Maintenance;
return;
}
if (string.Equals(pageName, "Recipe", StringComparison.OrdinalIgnoreCase))
{
resourceKey = "HeaderDeviceModeRecipe";
tone = HeaderDeviceStatusTone.Recipe;
return;
}
if (string.Equals(pageName, "PageSettings", StringComparison.OrdinalIgnoreCase))
{
resourceKey = "HeaderDeviceModeSettings";
tone = HeaderDeviceStatusTone.Settings;
return;
}
if (string.Equals(pageName, "PageCalib", StringComparison.OrdinalIgnoreCase))
{
resourceKey = "HeaderDeviceModeCalibration";
tone = HeaderDeviceStatusTone.Calibration;
return;
}
resourceKey = "HeaderDeviceModeUnknown";
tone = HeaderDeviceStatusTone.Unknown;
}
private static string GetFallbackStatusText(HeaderDeviceStatusTone tone)
{
switch (tone)
{
case HeaderDeviceStatusTone.Auto:
return "<22>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD> (AUTO)";
case HeaderDeviceStatusTone.Manual:
return "<22>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD><EFBFBD> (MANUAL)";
case HeaderDeviceStatusTone.Maintenance:
return "<22>豸ά<E8B1B8><CEAC> (MAINT)";
case HeaderDeviceStatusTone.Recipe:
return "<22><EFBFBD>༭ (RECIPE)";
case HeaderDeviceStatusTone.Settings:
return "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (SETUP)";
case HeaderDeviceStatusTone.Calibration:
return "<22>У׼ (CALIB)";
default:
return "״̬<D7B4><CCAC><EFBFBD><EFBFBD> (PENDING)";
}
}
private void ApplyTone(HeaderDeviceStatusTone tone)
{
BadgeBackgroundBrush = CreateBackgroundBrush(tone);
BadgeBorderBrush = CreateBorderBrush(tone);
LabelForegroundBrush = CreateSolidBrush(198, 221, 255);
StatusForegroundBrush = Brushes.White;
IndicatorBrush = CreateIndicatorBrush(tone);
}
private static Brush CreateBackgroundBrush(HeaderDeviceStatusTone tone)
{
switch (tone)
{
case HeaderDeviceStatusTone.Auto:
return CreateGradientBrush(Color.FromRgb(42, 111, 84), Color.FromRgb(24, 79, 60));
case HeaderDeviceStatusTone.Manual:
return CreateGradientBrush(Color.FromRgb(148, 103, 37), Color.FromRgb(104, 72, 24));
case HeaderDeviceStatusTone.Maintenance:
return CreateGradientBrush(Color.FromRgb(46, 104, 164), Color.FromRgb(31, 74, 125));
case HeaderDeviceStatusTone.Recipe:
return CreateGradientBrush(Color.FromRgb(95, 76, 153), Color.FromRgb(68, 54, 111));
case HeaderDeviceStatusTone.Settings:
return CreateGradientBrush(Color.FromRgb(88, 103, 124), Color.FromRgb(62, 74, 92));
case HeaderDeviceStatusTone.Calibration:
return CreateGradientBrush(Color.FromRgb(34, 124, 141), Color.FromRgb(23, 90, 102));
default:
return CreateGradientBrush(Color.FromRgb(50, 102, 177), Color.FromRgb(35, 78, 140));
}
}
private static Brush CreateBorderBrush(HeaderDeviceStatusTone tone)
{
switch (tone)
{
case HeaderDeviceStatusTone.Auto:
return CreateSolidBrush(94, 169, 128);
case HeaderDeviceStatusTone.Manual:
return CreateSolidBrush(201, 151, 76);
case HeaderDeviceStatusTone.Maintenance:
return CreateSolidBrush(94, 148, 206);
case HeaderDeviceStatusTone.Recipe:
return CreateSolidBrush(130, 112, 192);
case HeaderDeviceStatusTone.Settings:
return CreateSolidBrush(126, 143, 166);
case HeaderDeviceStatusTone.Calibration:
return CreateSolidBrush(79, 170, 187);
default:
return CreateSolidBrush(96, 145, 214);
}
}
private static Brush CreateIndicatorBrush(HeaderDeviceStatusTone tone)
{
switch (tone)
{
case HeaderDeviceStatusTone.Auto:
return CreateSolidBrush(63, 227, 123);
case HeaderDeviceStatusTone.Manual:
return CreateSolidBrush(255, 183, 66);
case HeaderDeviceStatusTone.Maintenance:
return CreateSolidBrush(72, 196, 255);
case HeaderDeviceStatusTone.Recipe:
return CreateSolidBrush(173, 121, 255);
case HeaderDeviceStatusTone.Settings:
return CreateSolidBrush(158, 172, 196);
case HeaderDeviceStatusTone.Calibration:
return CreateSolidBrush(70, 231, 219);
default:
return CreateSolidBrush(255, 93, 93);
}
}
private static Brush CreateSolidBrush(byte red, byte green, byte blue)
{
return new SolidColorBrush(Color.FromRgb(red, green, blue));
}
private static Brush CreateGradientBrush(Color startColor, Color endColor)
{
return new LinearGradientBrush(startColor, endColor, 0.0);
}
private static string GetResourceText(string resourceKey, string fallback)
{
Application application = Application.Current;
if (application == null)
{
return fallback;
}
object resource = application.TryFindResource(resourceKey);
string text = resource as string;
if (!string.IsNullOrWhiteSpace(text))
{
return text;
}
return fallback;
}
}
}

View File

@@ -0,0 +1,607 @@
using MainShell.Resources.CustomControl;
using Newtonsoft.Json;
using Stylet;
using System;
using System.Globalization;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
namespace MainShell.Common
{
public static class HeaderDeviceStatusOverlayHost
{
private static readonly object OverlayRootTag = new object();
private static readonly HeaderDeviceStatusOverlaySettings OverlaySettings = new HeaderDeviceStatusOverlaySettings();
public static void Attach(Window window, HeaderDeviceStatusController controller)
{
if (window == null)
{
throw new ArgumentNullException(nameof(window));
}
if (controller == null)
{
throw new ArgumentNullException(nameof(controller));
}
window.Dispatcher.BeginInvoke(
DispatcherPriority.Loaded,
new Action(() => AttachCore(window, controller)));
}
private static void AttachCore(Window window, HeaderDeviceStatusController controller)
{
Grid existingOverlayRoot = window.Content as Grid;
if (existingOverlayRoot != null && ReferenceEquals(existingOverlayRoot.Tag, OverlayRootTag))
{
return;
}
UIElement currentContent = window.Content as UIElement;
if (currentContent == null)
{
return;
}
Grid overlayRoot = new Grid();
overlayRoot.Tag = OverlayRootTag;
window.Content = null;
overlayRoot.Children.Add(currentContent);
overlayRoot.Children.Add(CreateOverlayElement(controller));
overlayRoot.Children.Add(CreateDebugPanelElement());
window.Content = overlayRoot;
}
private static FrameworkElement CreateOverlayElement(HeaderDeviceStatusController controller)
{
HeaderDeviceStatusView statusView = new HeaderDeviceStatusView();
statusView.DataContext = controller;
statusView.IsHitTestVisible = false;
statusView.HorizontalAlignment = HorizontalAlignment.Left;
statusView.VerticalAlignment = VerticalAlignment.Top;
Binding marginBinding = new Binding(nameof(HeaderDeviceStatusOverlaySettings.Margin));
marginBinding.Source = OverlaySettings;
BindingOperations.SetBinding(statusView, FrameworkElement.MarginProperty, marginBinding);
Panel.SetZIndex(statusView, short.MaxValue);
return statusView;
}
private static FrameworkElement CreateDebugPanelElement()
{
Border panelBorder = new Border();
panelBorder.Background = new SolidColorBrush(Color.FromArgb(235, 18, 26, 35));
panelBorder.BorderBrush = new SolidColorBrush(Color.FromRgb(72, 93, 118));
panelBorder.BorderThickness = new Thickness(1.0);
panelBorder.CornerRadius = new CornerRadius(6.0);
panelBorder.Padding = new Thickness(10.0, 8.0, 10.0, 8.0);
panelBorder.HorizontalAlignment = HorizontalAlignment.Left;
panelBorder.VerticalAlignment = VerticalAlignment.Top;
Binding panelMarginBinding = new Binding(nameof(HeaderDeviceStatusOverlaySettings.DebugPanelMargin));
panelMarginBinding.Source = OverlaySettings;
BindingOperations.SetBinding(panelBorder, FrameworkElement.MarginProperty, panelMarginBinding);
Binding panelVisibilityBinding = new Binding(nameof(HeaderDeviceStatusOverlaySettings.IsDebugPanelVisible));
panelVisibilityBinding.Source = OverlaySettings;
panelVisibilityBinding.Converter = new BooleanToVisibilityConverter();
BindingOperations.SetBinding(panelBorder, UIElement.VisibilityProperty, panelVisibilityBinding);
StackPanel rootPanel = new StackPanel();
rootPanel.Orientation = Orientation.Vertical;
DockPanel headerPanel = new DockPanel();
TextBlock titleText = new TextBlock();
titleText.Text = "Overlay Debug";
titleText.Foreground = Brushes.White;
titleText.FontSize = 13.0;
titleText.FontWeight = FontWeights.SemiBold;
titleText.Margin = new Thickness(0.0, 0.0, 8.0, 6.0);
DockPanel.SetDock(titleText, Dock.Left);
headerPanel.Children.Add(titleText);
Button closeButton = CreateDebugButton("<22><><EFBFBD><EFBFBD>", 44.0);
closeButton.Margin = new Thickness(6.0, 0.0, 0.0, 6.0);
closeButton.Click += delegate(object sender, RoutedEventArgs e)
{
OverlaySettings.HideDebugPanel();
};
DockPanel.SetDock(closeButton, Dock.Right);
headerPanel.Children.Add(closeButton);
rootPanel.Children.Add(headerPanel);
TextBlock summaryText = new TextBlock();
summaryText.Foreground = new SolidColorBrush(Color.FromRgb(210, 221, 236));
summaryText.FontSize = 12.0;
summaryText.Margin = new Thickness(0.0, 0.0, 0.0, 8.0);
Binding summaryBinding = new Binding(nameof(HeaderDeviceStatusOverlaySettings.PositionSummary));
summaryBinding.Source = OverlaySettings;
BindingOperations.SetBinding(summaryText, TextBlock.TextProperty, summaryBinding);
rootPanel.Children.Add(summaryText);
rootPanel.Children.Add(CreateDebugInputRow("Left", nameof(HeaderDeviceStatusOverlaySettings.LeftMarginText)));
rootPanel.Children.Add(CreateDebugInputRow("Top", nameof(HeaderDeviceStatusOverlaySettings.TopMarginText)));
rootPanel.Children.Add(CreateDebugInputRow("Step", nameof(HeaderDeviceStatusOverlaySettings.StepText)));
UniformGrid actionGrid = new UniformGrid();
actionGrid.Columns = 4;
actionGrid.Rows = 1;
actionGrid.Margin = new Thickness(0.0, 0.0, 0.0, 8.0);
Button leftButton = CreateDebugButton("<22><>", 40.0);
leftButton.Click += delegate(object sender, RoutedEventArgs e)
{
OverlaySettings.AdjustMargin(-OverlaySettings.Step, 0.0);
};
actionGrid.Children.Add(leftButton);
Button rightButton = CreateDebugButton("<22><>", 40.0);
rightButton.Click += delegate(object sender, RoutedEventArgs e)
{
OverlaySettings.AdjustMargin(OverlaySettings.Step, 0.0);
};
actionGrid.Children.Add(rightButton);
Button upButton = CreateDebugButton("<22><>", 40.0);
upButton.Click += delegate(object sender, RoutedEventArgs e)
{
OverlaySettings.AdjustMargin(0.0, -OverlaySettings.Step);
};
actionGrid.Children.Add(upButton);
Button downButton = CreateDebugButton("<22><>", 40.0);
downButton.Click += delegate(object sender, RoutedEventArgs e)
{
OverlaySettings.AdjustMargin(0.0, OverlaySettings.Step);
};
actionGrid.Children.Add(downButton);
rootPanel.Children.Add(actionGrid);
Button applyButton = CreateDebugButton(<><D3A6>", 0.0);
applyButton.Width = 178.0;
applyButton.Margin = new Thickness(0.0, 0.0, 0.0, 0.0);
applyButton.Click += delegate(object sender, RoutedEventArgs e)
{
OverlaySettings.ApplyTextValues();
};
rootPanel.Children.Add(applyButton);
panelBorder.Child = rootPanel;
Panel.SetZIndex(panelBorder, short.MaxValue);
return panelBorder;
}
private static FrameworkElement CreateDebugInputRow(string labelText, string bindingPath)
{
Grid rowGrid = new Grid();
rowGrid.Margin = new Thickness(0.0, 0.0, 0.0, 6.0);
rowGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(44.0) });
rowGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(92.0) });
rowGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(56.0) });
TextBlock label = new TextBlock();
label.Text = labelText;
label.Foreground = new SolidColorBrush(Color.FromRgb(210, 221, 236));
label.FontSize = 12.0;
label.VerticalAlignment = VerticalAlignment.Center;
Grid.SetColumn(label, 0);
rowGrid.Children.Add(label);
TextBox inputBox = CreateDebugTextBox(bindingPath);
Grid.SetColumn(inputBox, 1);
rowGrid.Children.Add(inputBox);
TextBlock hint = new TextBlock();
hint.Text = "<22>س<EFBFBD>";
hint.Foreground = new SolidColorBrush(Color.FromRgb(150, 167, 188));
hint.FontSize = 11.0;
hint.VerticalAlignment = VerticalAlignment.Center;
hint.HorizontalAlignment = HorizontalAlignment.Right;
Grid.SetColumn(hint, 2);
rowGrid.Children.Add(hint);
return rowGrid;
}
private static TextBox CreateDebugTextBox(string bindingPath)
{
TextBox inputBox = new TextBox();
inputBox.Height = 26.0;
inputBox.Margin = new Thickness(0.0);
inputBox.Padding = new Thickness(6.0, 2.0, 6.0, 2.0);
inputBox.Background = new SolidColorBrush(Color.FromRgb(33, 46, 60));
inputBox.BorderBrush = new SolidColorBrush(Color.FromRgb(96, 122, 149));
inputBox.Foreground = Brushes.White;
inputBox.FontSize = 12.0;
inputBox.VerticalContentAlignment = VerticalAlignment.Center;
Binding textBinding = new Binding(bindingPath);
textBinding.Source = OverlaySettings;
textBinding.Mode = BindingMode.TwoWay;
textBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding(inputBox, TextBox.TextProperty, textBinding);
inputBox.LostFocus += delegate(object sender, RoutedEventArgs e)
{
OverlaySettings.ApplyTextValues();
};
inputBox.KeyDown += delegate(object sender, KeyEventArgs e)
{
if (e.Key != Key.Enter)
{
return;
}
OverlaySettings.ApplyTextValues();
e.Handled = true;
};
return inputBox;
}
private static Button CreateDebugButton(string content, double width)
{
Button button = new Button();
button.Content = content;
if (width > 0.0)
{
button.Width = width;
}
button.Height = 28.0;
button.Margin = new Thickness(0.0, 0.0, 6.0, 0.0);
button.Padding = new Thickness(4.0, 0.0, 4.0, 0.0);
button.Background = new SolidColorBrush(Color.FromRgb(43, 62, 81));
button.BorderBrush = new SolidColorBrush(Color.FromRgb(96, 122, 149));
button.Foreground = Brushes.White;
button.FontSize = 12.0;
return button;
}
private sealed class HeaderDeviceStatusOverlaySettings : PropertyChangedBase, IDisposable
{
private const double DefaultTopMargin = 8.0;
private const double DefaultLeftMargin = 8.0;
private const double DefaultDebugPanelTopOffset = 50.0;
private const double DefaultAdjustStep = 1.0;
private const string ConfigurationDirectoryName = "Configuration";
private const string ConfigurationFileName = "HeaderDeviceStatusOverlay.json";
private readonly string _configurationDirectoryPath;
private readonly string _configurationFilePath;
private readonly FileSystemWatcher _fileWatcher;
private double _topMargin = DefaultTopMargin;
private double _leftMargin = DefaultLeftMargin;
private bool _isDebugPanelVisible;
private double _step = DefaultAdjustStep;
private string _leftMarginText = DefaultLeftMargin.ToString("0.##", CultureInfo.InvariantCulture);
private string _topMarginText = DefaultTopMargin.ToString("0.##", CultureInfo.InvariantCulture);
private string _stepText = DefaultAdjustStep.ToString("0.##", CultureInfo.InvariantCulture);
public HeaderDeviceStatusOverlaySettings()
{
_configurationDirectoryPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConfigurationDirectoryName);
_configurationFilePath = Path.Combine(_configurationDirectoryPath, ConfigurationFileName);
EnsureConfigurationFile();
LoadFromFile();
_fileWatcher = new FileSystemWatcher(_configurationDirectoryPath, ConfigurationFileName);
_fileWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.Size | NotifyFilters.CreationTime;
_fileWatcher.Changed += OnConfigurationFileChanged;
_fileWatcher.Created += OnConfigurationFileChanged;
_fileWatcher.Renamed += OnConfigurationFileRenamed;
_fileWatcher.EnableRaisingEvents = true;
}
public Thickness Margin
{
get
{
return new Thickness(_leftMargin, _topMargin, 0.0, 0.0);
}
}
public Thickness DebugPanelMargin
{
get
{
return new Thickness(_leftMargin, _topMargin + DefaultDebugPanelTopOffset, 0.0, 0.0);
}
}
public bool IsDebugPanelVisible
{
get
{
return _isDebugPanelVisible;
}
}
public double Step
{
get
{
return _step;
}
}
public string LeftMarginText
{
get
{
return _leftMarginText;
}
set
{
SetAndNotify(ref _leftMarginText, value);
}
}
public string TopMarginText
{
get
{
return _topMarginText;
}
set
{
SetAndNotify(ref _topMarginText, value);
}
}
public string StepText
{
get
{
return _stepText;
}
set
{
SetAndNotify(ref _stepText, value);
}
}
public string PositionSummary
{
get
{
return string.Format("Left={0:0.##}, Top={1:0.##}, Step={2:0.##}", _leftMargin, _topMargin, _step);
}
}
public void Dispose()
{
_fileWatcher.Changed -= OnConfigurationFileChanged;
_fileWatcher.Created -= OnConfigurationFileChanged;
_fileWatcher.Renamed -= OnConfigurationFileRenamed;
_fileWatcher.Dispose();
}
public void AdjustMargin(double leftOffset, double topOffset)
{
double leftMargin = _leftMargin + leftOffset;
double topMargin = _topMargin + topOffset;
UpdateSettings(leftMargin, topMargin, _isDebugPanelVisible, _step);
PersistCurrentConfiguration();
}
public void HideDebugPanel()
{
UpdateSettings(_leftMargin, _topMargin, false, _step);
PersistCurrentConfiguration();
}
public void ApplyTextValues()
{
double leftMargin;
double topMargin;
double step;
bool canParseLeft = TryParseInput(LeftMarginText, _leftMargin, out leftMargin);
bool canParseTop = TryParseInput(TopMarginText, _topMargin, out topMargin);
bool canParseStep = TryParseInput(StepText, _step, out step);
if (!canParseStep)
{
step = _step;
}
step = NormalizeStep(step);
UpdateSettings(leftMargin, topMargin, _isDebugPanelVisible, step);
PersistCurrentConfiguration();
}
private void OnConfigurationFileChanged(object sender, FileSystemEventArgs e)
{
ReloadOnUiThread();
}
private void OnConfigurationFileRenamed(object sender, RenamedEventArgs e)
{
ReloadOnUiThread();
}
private void ReloadOnUiThread()
{
Application currentApplication = Application.Current;
if (currentApplication == null)
{
LoadFromFile();
return;
}
currentApplication.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(LoadFromFile));
}
private void EnsureConfigurationFile()
{
if (!Directory.Exists(_configurationDirectoryPath))
{
Directory.CreateDirectory(_configurationDirectoryPath);
}
if (File.Exists(_configurationFilePath))
{
return;
}
HeaderDeviceStatusOverlayPositionConfiguration configuration = new HeaderDeviceStatusOverlayPositionConfiguration();
configuration.TopMargin = DefaultTopMargin;
configuration.LeftMargin = DefaultLeftMargin;
configuration.ShowDebugPanel = false;
configuration.AdjustStep = DefaultAdjustStep;
SaveConfiguration(configuration);
}
private void LoadFromFile()
{
HeaderDeviceStatusOverlayPositionConfiguration configuration = TryReadConfiguration();
if (configuration == null)
{
return;
}
double topMargin = NormalizeMargin(configuration.TopMargin, DefaultTopMargin);
double leftMargin = NormalizeMargin(configuration.LeftMargin, DefaultLeftMargin);
double adjustStep = NormalizeStep(configuration.AdjustStep);
UpdateSettings(leftMargin, topMargin, configuration.ShowDebugPanel, adjustStep);
}
private HeaderDeviceStatusOverlayPositionConfiguration TryReadConfiguration()
{
for (int attempt = 0; attempt < 3; attempt++)
{
try
{
string content = File.ReadAllText(_configurationFilePath);
if (string.IsNullOrWhiteSpace(content))
{
return new HeaderDeviceStatusOverlayPositionConfiguration();
}
HeaderDeviceStatusOverlayPositionConfiguration configuration = JsonConvert.DeserializeObject<HeaderDeviceStatusOverlayPositionConfiguration>(content);
return configuration ?? new HeaderDeviceStatusOverlayPositionConfiguration();
}
catch (IOException)
{
}
catch (UnauthorizedAccessException)
{
}
catch (JsonException)
{
return null;
}
}
return null;
}
private void SaveConfiguration(HeaderDeviceStatusOverlayPositionConfiguration configuration)
{
string content = JsonConvert.SerializeObject(configuration, Formatting.Indented);
File.WriteAllText(_configurationFilePath, content);
}
private void PersistCurrentConfiguration()
{
HeaderDeviceStatusOverlayPositionConfiguration configuration = new HeaderDeviceStatusOverlayPositionConfiguration();
configuration.TopMargin = _topMargin;
configuration.LeftMargin = _leftMargin;
configuration.ShowDebugPanel = _isDebugPanelVisible;
configuration.AdjustStep = _step;
SaveConfiguration(configuration);
}
private static double NormalizeMargin(double value, double fallbackValue)
{
if (double.IsNaN(value) || double.IsInfinity(value))
{
return fallbackValue;
}
return value;
}
private static double NormalizeStep(double value)
{
if (double.IsNaN(value) || double.IsInfinity(value) || value <= 0.0)
{
return DefaultAdjustStep;
}
return value;
}
private void UpdateSettings(double leftMargin, double topMargin, bool isDebugPanelVisible, double step)
{
bool hasChanged = !leftMargin.Equals(_leftMargin)
|| !topMargin.Equals(_topMargin)
|| !isDebugPanelVisible.Equals(_isDebugPanelVisible)
|| !step.Equals(_step);
if (!hasChanged)
{
return;
}
_leftMargin = leftMargin;
_topMargin = topMargin;
_isDebugPanelVisible = isDebugPanelVisible;
_step = step;
LeftMarginText = FormatValue(_leftMargin);
TopMarginText = FormatValue(_topMargin);
StepText = FormatValue(_step);
NotifyOfPropertyChange(nameof(Margin));
NotifyOfPropertyChange(nameof(DebugPanelMargin));
NotifyOfPropertyChange(nameof(IsDebugPanelVisible));
NotifyOfPropertyChange(nameof(Step));
NotifyOfPropertyChange(nameof(PositionSummary));
}
private static bool TryParseInput(string text, double fallbackValue, out double value)
{
string trimmedText = string.IsNullOrWhiteSpace(text) ? string.Empty : text.Trim();
if (string.IsNullOrEmpty(trimmedText))
{
value = fallbackValue;
return false;
}
return double.TryParse(trimmedText, NumberStyles.Float, CultureInfo.InvariantCulture, out value)
|| double.TryParse(trimmedText, NumberStyles.Float, CultureInfo.CurrentCulture, out value);
}
private static string FormatValue(double value)
{
return value.ToString("0.##", CultureInfo.InvariantCulture);
}
}
private sealed class HeaderDeviceStatusOverlayPositionConfiguration
{
public double TopMargin { get; set; }
public double LeftMargin { get; set; }
public bool ShowDebugPanel { get; set; }
public double AdjustStep { get; set; }
}
}
}

View File

@@ -0,0 +1,164 @@
using System;
using System.Collections.Generic;
using System.Windows;
namespace MainShell.Common
{
/// <summary>
/// Localization resource helper.
/// </summary>
public static class LanguageResourceHelper
{
private static readonly IReadOnlyDictionary<MessageKey, string> ResourceKeyMap =
new Dictionary<MessageKey, string>
{
{ MessageKey.TitleInfo, "Msg_Title_Info" },
{ MessageKey.TitleWarning, "Msg_Title_Warning" },
{ MessageKey.TitleError, "Msg_Title_Error" },
{ MessageKey.TitleConfirm, "Msg_Title_Confirm" },
{ MessageKey.VisionCameraNotFound, "Msg_Vision_CameraNotFound" },
{ MessageKey.VisionCameraNotOpen, "Msg_Vision_CameraNotOpen" },
{ MessageKey.VisionCameraNotGrabbing, "Msg_Vision_CameraNotGrabbing" },
{ MessageKey.VisionCaptureTimeout, "Msg_Vision_CaptureTimeout" },
{ MessageKey.VisionNoFrameReturned, "Msg_Vision_NoFrameReturned" },
{ MessageKey.VisionSoftTriggerFailed, "Msg_Vision_SoftTriggerFailed" },
{ MessageKey.VisionDriverError, "Msg_Vision_DriverError" },
{ MessageKey.VisionImageIsNull, "Msg_Vision_ImageIsNull" },
{ MessageKey.VisionRequestInvalid, "Msg_Vision_RequestInvalid" },
{ MessageKey.VisionTimeoutInvalid, "Msg_Vision_TimeoutInvalid" },
{ MessageKey.VisionOperationCancelled, "Msg_Vision_OperationCancelled" },
{ MessageKey.VisionTemplatePathEmpty, "Msg_Vision_TemplatePathEmpty" },
{ MessageKey.VisionTemplateRoiInvalid, "Msg_Vision_TemplateRoiInvalid" },
{ MessageKey.VisionTemplateMinScoreInvalid, "Msg_Vision_TemplateMinScoreInvalid" },
{ MessageKey.VisionTemplateAlgorithmNotImplemented, "Msg_Vision_TemplateAlgorithmNotImplemented" },
{ MessageKey.VisionTemplateMatchFailed, "Msg_Vision_TemplateMatchFailed" },
{ MessageKey.VisionCommonAlgorithmNotSupported, "Msg_Vision_CommonAlgorithmNotSupported" },
{ MessageKey.VisionCommonAlgorithmExecutionFailed, "Msg_Vision_CommonAlgorithmExecutionFailed" },
{ MessageKey.VisionChipMapSortInputInvalid, "Msg_Vision_ChipMapSortInputInvalid" },
{ MessageKey.CommonUnknownError, "Msg_Common_UnknownError" },
{ MessageKey.CommonOperationSucceeded, "Msg_Common_OperationSucceeded" },
{ MessageKey.CommonOperationFailed, "Msg_Common_OperationFailed" },
{ MessageKey.CommonSaveSucceeded, "Msg_Common_SaveSucceeded" },
{ MessageKey.CommonSaveFailed, "Msg_Common_SaveFailed" },
{ MessageKey.AxisSoftLimitSaveConfirm, "Msg_AxisSoftLimit_SaveConfirm" },
{ MessageKey.AxisSoftLimitSaveFailedWithReason, "Msg_AxisSoftLimit_SaveFailedWithReason" },
{ MessageKey.AxisSoftLimitLoadFailedWithReason, "Msg_AxisSoftLimit_LoadFailedWithReason" },
{ MessageKey.AxisSoftLimitRangeInvalid, "Msg_AxisSoftLimit_RangeInvalid" },
{ MessageKey.AxisSoftLimitApplySucceeded, "Msg_AxisSoftLimit_ApplySucceeded" },
{ MessageKey.AxisSoftLimitApplyFailedWithReason, "Msg_AxisSoftLimit_ApplyFailedWithReason" },
{ MessageKey.AxisSoftLimitApplyAllSucceeded, "Msg_AxisSoftLimit_ApplyAllSucceeded" },
{ MessageKey.AxisSoftLimitApplyAllFailedWithReason, "Msg_AxisSoftLimit_ApplyAllFailedWithReason" },
{ MessageKey.AxisSoftLimitNoAxisData, "Msg_AxisSoftLimit_NoAxisData" },
{ MessageKey.AxisSoftLimitSelectedAxisRequired, "Msg_AxisSoftLimit_SelectedAxisRequired" },
{ MessageKey.CommonDeleteConfirm, "Msg_Common_DeleteConfirm" },
{ MessageKey.CommonExitConfirm, "Msg_Common_ExitConfirm" },
{ MessageKey.DeviceNotInitialized, "Msg_Device_NotInitialized" },
{ MessageKey.DeviceBusy, "Msg_Device_Busy" },
{ MessageKey.DeviceDisconnected, "Msg_Device_Disconnected" },
{ MessageKey.DeviceHomeRequired, "Msg_Device_HomeRequired" },
{ MessageKey.ParamInvalid, "Msg_Param_Invalid" },
{ MessageKey.ParamEmpty, "Msg_Param_Empty" },
{ MessageKey.ParamOutOfRange, "Msg_Param_OutOfRange" },
{ MessageKey.StartProcessConfirm, "Msg_Process_StartConfirm" },
{ MessageKey.StartProcessFailed, "Msg_Process_StartFailed" },
{ MessageKey.StopProcessConfirm, "Msg_Process_StopConfirm" },
{ MessageKey.StopProcessFailed, "Msg_Process_StopFailed" },
{ MessageKey.ProcessFailed, "Msg_Process_Failed" },
{ MessageKey.ProcessFailedWithReason, "Msg_Process_FailedWithReason" },
{ MessageKey.ProcessStepFailedWithReason, "Msg_Process_StepFailedWithReason" },
{ MessageKey.ProcessSubstratePositionFailedWithReason, "Msg_Process_SubstratePositionFailedWithReason" },
{ MessageKey.ProcessSubstratePositionRecipeNotLoaded, "Msg_Process_SubstratePositionRecipeNotLoaded" },
{ MessageKey.ProcessSubstratePositionMarkParameterMissing, "Msg_Process_SubstratePositionMarkParameterMissing" },
{ MessageKey.ProcessSubstratePositionNoEnabledMarks, "Msg_Process_SubstratePositionNoEnabledMarks" },
{ MessageKey.ProcessSubstratePositionAlignmentFailedWithReason, "Msg_Process_SubstratePositionAlignmentFailedWithReason" },
{ MessageKey.ProcessDiePositionFailedWithReason, "Msg_Process_DiePositionFailedWithReason" },
{ MessageKey.ProcessDiePositionRecipeNotLoaded, "Msg_Process_DiePositionRecipeNotLoaded" },
{ MessageKey.ProcessDiePositionCoordinateGenerationMissing, "Msg_Process_DiePositionCoordinateGenerationMissing" },
{ MessageKey.ProcessDiePositionWaferInfoMissing, "Msg_Process_DiePositionWaferInfoMissing" },
{ MessageKey.ProcessSubstrateHeightMeasureFailedWithReason, "Msg_Process_SubstrateHeightMeasureFailedWithReason" },
{ MessageKey.ProcessSubstrateHeightMeasureRecipeNotLoaded, "Msg_Process_SubstrateHeightMeasureRecipeNotLoaded" },
{ MessageKey.ProcessSubstrateHeightMeasureSettingMissing, "Msg_Process_SubstrateHeightMeasureSettingMissing" },
{ MessageKey.ProcessSubstrateHeightMeasureNoPoints, "Msg_Process_SubstrateHeightMeasureNoPoints" },
{ MessageKey.ProcessSubstrateHeightMeasurePointPositionInvalid, "Msg_Process_SubstrateHeightMeasurePointPositionInvalid" },
{ MessageKey.NeedleCalibrationLoadFailed, "Msg_NeedleCalibration_LoadFailed" },
{ MessageKey.NeedleCalibrationTouchCountMustGreaterThanZero, "Msg_NeedleCalibration_TouchCountMustGreaterThanZero" },
{ MessageKey.NeedleCalibrationCompleted, "Msg_NeedleCalibration_Completed" },
{ MessageKey.NeedleCalibrationStopped, "Msg_NeedleCalibration_Stopped" },
{ MessageKey.NeedleCalibrationCanceled, "Msg_NeedleCalibration_Canceled" },
{ MessageKey.OriginCalibOpenVisionTemplateFailed, "Msg_OriginCalib_OpenVisionTemplateFailed" },
{ MessageKey.OriginCalibAxisNotFound, "Msg_OriginCalib_AxisNotFound" },
{ MessageKey.OriginCalibReadPositionFailed, "Msg_OriginCalib_ReadPositionFailed" },
{ MessageKey.OriginCalibMoveFailed, "Msg_OriginCalib_MoveFailed" },
{ MessageKey.OriginCalibDeleteAxisFailed, "Msg_OriginCalib_DeleteAxisFailed" },
{ MessageKey.OriginCalibDeleteAxisDuringCalibration, "Msg_OriginCalib_DeleteAxisDuringCalibration" },
{ MessageKey.OriginCalibCalibrationCanceled, "Msg_OriginCalib_CalibrationCanceled" },
{ MessageKey.OriginCalibCalibrationFailed, "Msg_OriginCalib_CalibrationFailed" },
{ MessageKey.OriginCalibConfigSaved, "Msg_OriginCalib_ConfigSaved" },
{ MessageKey.OriginCalibConfigSaveFailed, "Msg_OriginCalib_ConfigSaveFailed" },
{ MessageKey.OriginCalibNoCalibratedModules, "Msg_OriginCalib_NoCalibratedModules" },
{ MessageKey.OriginCalibControllerWriteCompleted, "Msg_OriginCalib_ControllerWriteCompleted" },
{ MessageKey.OriginCalibControllerWriteNotReady, "Msg_OriginCalib_ControllerWriteNotReady" },
{ MessageKey.OriginCalibControllerWritePartialSuccess, "Msg_OriginCalib_ControllerWritePartialSuccess" },
{ MessageKey.OriginCalibControllerWriteNotImplemented, "Msg_OriginCalib_ControllerWriteNotImplemented" },
{ MessageKey.PidNoProfileSelected, "Msg_Pid_NoProfileSelected" },
{ MessageKey.PidNoFilteringParameterSelected, "Msg_Pid_NoFilteringParameterSelected" },
{ MessageKey.PidReadSucceeded, "Msg_Pid_ReadSucceeded" },
{ MessageKey.PidReadFailed, "Msg_Pid_ReadFailed" },
{ MessageKey.PidWriteSucceeded, "Msg_Pid_WriteSucceeded" },
{ MessageKey.PidWriteFailed, "Msg_Pid_WriteFailed" },
{ MessageKey.DieRecheckSelectedPointRequired, "Msg_DieRecheck_SelectedPointRequired" },
{ MessageKey.DieRecheckMoveDeviceUnavailable, "Msg_DieRecheck_MoveDeviceUnavailable" },
{ MessageKey.DieRecheckStatusOk, "Msg_DieRecheck_StatusOk" },
{ MessageKey.DieRecheckStatusMissingBond, "Msg_DieRecheck_StatusMissingBond" },
{ MessageKey.DieRecheckStatusXExceeded, "Msg_DieRecheck_StatusXExceeded" },
{ MessageKey.DieRecheckStatusYExceeded, "Msg_DieRecheck_StatusYExceeded" }
};
public static string GetString(MessageKey messageKey)
{
return GetString(messageKey, messageKey.ToString());
}
public static string GetString(MessageKey messageKey, string fallback)
{
if (messageKey == MessageKey.None)
{
return fallback ?? string.Empty;
}
if (!ResourceKeyMap.TryGetValue(messageKey, out var resourceKey))
{
return fallback ?? messageKey.ToString();
}
var application = Application.Current;
if (application == null)
{
return fallback ?? resourceKey;
}
var resource = application.TryFindResource(resourceKey);
if (resource is string text && !string.IsNullOrWhiteSpace(text))
{
return text;
}
return fallback ?? resourceKey;
}
public static string Format(MessageKey messageKey, params object[] args)
{
var format = GetString(messageKey);
return args == null || args.Length == 0
? format
: string.Format(format, args);
}
}
}

View File

@@ -0,0 +1,104 @@
using MainShell.Resources.CustomControl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace MainShell.Common
{
public static class Loading
{
private static LoadingWaitView _view;
// 全局初始化:在主程序启动或插件加载时调用一次
public static void Initialize(Window mainWindow)
{
if (_view != null) return; // 避免重复加载
_view = new LoadingWaitView();
// 获取窗口的根内容
var rootContent = mainWindow.Content;
if (rootContent is Panel rootPanel)
{
// 如果根部本来就是 Panel (Grid/Canvas等),直接添加
rootPanel.Children.Add(_view);
}
else if (rootContent is ContentControl contentControl)
{
// 如果根部是 ContentControl我们需要把原本的内容包在一个新的 Grid 里
var originalContent = contentControl.Content as UIElement;
contentControl.Content = null;
var wrapperGrid = new Grid();
wrapperGrid.Children.Add(originalContent); // 原有内容
wrapperGrid.Children.Add(_view); // 我们的遮罩层
contentControl.Content = wrapperGrid;
}
// 确保遮罩层铺满并置于顶层
Grid.SetColumnSpan(_view, 99);
Grid.SetRowSpan(_view, 99);
Panel.SetZIndex(_view, 9999);
}
// 基础调用Loading.Show("计算中...");
public static void Show(string msg, bool isIndeterminate, bool canCancel = true) => LoadingService.Instance.Show(msg, canCancel, isIndeterminate);
public static void Hide() => LoadingService.Instance.Hide();
public static void Report(double val) => LoadingService.Instance.Report(val);
// 获取当前令牌Loading.Token
public static CancellationToken Token => LoadingService.Instance.Token;
// 高级用法:使用 using 块自动开启和关闭
public static IDisposable Manager(string msg, bool canCancel = true)
{
Show(msg, canCancel);
return new DisposableAction(() => Hide());
}
public static async Task<bool> RunAsync(
Func<CancellationToken, IProgress<double>, Task> work,
string message,
bool canCancel = true, bool isIndeterminate = false,
Action<Exception> onError = null)
{
using (Manager(message, canCancel))
{
try
{
LoadingService.Instance.Show(message, isIndeterminate, canCancel);
var progress = new Progress<double>(val =>
Application.Current.Dispatcher.Invoke(() => LoadingService.Instance.ProgressValue = val));
await Task.Run(() => work(LoadingService.Instance.Token, progress), LoadingService.Instance.Token);
return true; // 执行成功
}
catch (OperationCanceledException)
{
// 用户点击了取消,通常不需要弹窗,直接返回 false
return false;
}
catch (Exception ex)
{
// 捕获其他所有异常(硬件错误、逻辑错误等)
if (onError != null)
onError(ex);
else
MessageBox.Show($"操作失败: {ex.Message}", "系统错误", MessageBoxButton.OK, MessageBoxImage.Error);
return false;
}
}
}
}
}

View File

@@ -0,0 +1,55 @@
using System.Windows;
namespace MainShell.Common
{
/// <summary>
/// <20><><EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD><EFBFBD>ö<EFBFBD><C3B6><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><D7B0>
/// </summary>
public static class LocalizedMessageBox
{
public static MessageBoxResult Show(MessageKey messageKey)
{
return Show(null, messageKey, MessageKey.TitleInfo, MessageBoxButton.OK, MessageBoxImage.None, MessageBoxResult.None);
}
public static MessageBoxResult Show(MessageKey messageKey, MessageKey captionKey)
{
return Show(null, messageKey, captionKey, MessageBoxButton.OK, MessageBoxImage.None, MessageBoxResult.None);
}
public static MessageBoxResult Show(MessageKey messageKey, MessageKey captionKey, MessageBoxButton button, MessageBoxImage icon)
{
return Show(null, messageKey, captionKey, button, icon, MessageBoxResult.None);
}
public static MessageBoxResult Show(Window owner, MessageKey messageKey, MessageKey captionKey, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult = MessageBoxResult.None)
{
return MwMessageBox.InvokeOnUiThread(() => ShowCore(owner, messageKey, captionKey, button, icon, defaultResult));
}
public static MessageBoxResult ShowFormat(MessageKey messageKey, MessageKey captionKey, MessageBoxButton button, MessageBoxImage icon, params object[] args)
{
return MwMessageBox.InvokeOnUiThread(() => ShowFormatCore(messageKey, captionKey, button, icon, args));
}
private static MessageBoxResult ShowCore(Window owner, MessageKey messageKey, MessageKey captionKey, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult)
{
string message = LanguageResourceHelper.GetString(messageKey);
string caption = captionKey == MessageKey.None
? string.Empty
: LanguageResourceHelper.GetString(captionKey);
return MwMessageBox.Show(owner, message, caption, button, icon, defaultResult);
}
private static MessageBoxResult ShowFormatCore(MessageKey messageKey, MessageKey captionKey, MessageBoxButton button, MessageBoxImage icon, object[] args)
{
string message = LanguageResourceHelper.Format(messageKey, args);
string caption = captionKey == MessageKey.None
? string.Empty
: LanguageResourceHelper.GetString(captionKey);
return MwMessageBox.Show(message, caption, button, icon);
}
}
}

View File

@@ -0,0 +1,37 @@
using System;
namespace MainShell.Common
{
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD> MessageKey <20><>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD>ܿ<EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public class LocalizedProcessException : Exception
{
public MessageKey FailureMessageKey { get; }
public string[] FailureMessageArguments { get; }
public LocalizedProcessException(MessageKey failureMessageKey, params string[] failureMessageArguments)
: base(LanguageResourceHelper.Format(failureMessageKey, ConvertArguments(failureMessageArguments)))
{
FailureMessageKey = failureMessageKey;
FailureMessageArguments = failureMessageArguments ?? Array.Empty<string>();
}
public static object[] ConvertArguments(string[] failureMessageArguments)
{
if (failureMessageArguments == null || failureMessageArguments.Length == 0)
{
return Array.Empty<object>();
}
object[] convertedArguments = new object[failureMessageArguments.Length];
for (int i = 0; i < failureMessageArguments.Length; i++)
{
convertedArguments[i] = failureMessageArguments[i];
}
return convertedArguments;
}
}
}

View File

@@ -0,0 +1,121 @@
using System;
namespace MainShell.Common
{
/// <summary>
/// Message keys used by the localization system.
/// </summary>
public enum MessageKey
{
None = 0,
TitleInfo,
TitleWarning,
TitleError,
TitleConfirm,
VisionCameraNotFound,
VisionCameraNotOpen,
VisionCameraNotGrabbing,
VisionCaptureTimeout,
VisionNoFrameReturned,
VisionSoftTriggerFailed,
VisionDriverError,
VisionImageIsNull,
VisionRequestInvalid,
VisionTimeoutInvalid,
VisionOperationCancelled,
VisionTemplatePathEmpty,
VisionTemplateRoiInvalid,
VisionTemplateMinScoreInvalid,
VisionTemplateAlgorithmNotImplemented,
VisionTemplateMatchFailed,
VisionCommonAlgorithmNotSupported,
VisionCommonAlgorithmExecutionFailed,
VisionChipMapSortInputInvalid,
CommonUnknownError,
CommonOperationSucceeded,
CommonOperationFailed,
CommonSaveSucceeded,
CommonSaveFailed,
AxisSoftLimitSaveConfirm,
AxisSoftLimitSaveFailedWithReason,
AxisSoftLimitLoadFailedWithReason,
AxisSoftLimitRangeInvalid,
AxisSoftLimitApplySucceeded,
AxisSoftLimitApplyFailedWithReason,
AxisSoftLimitApplyAllSucceeded,
AxisSoftLimitApplyAllFailedWithReason,
AxisSoftLimitNoAxisData,
AxisSoftLimitSelectedAxisRequired,
CommonDeleteConfirm,
CommonExitConfirm,
DeviceNotInitialized,
DeviceBusy,
DeviceDisconnected,
DeviceHomeRequired,
ParamInvalid,
ParamEmpty,
ParamOutOfRange,
StartProcessConfirm,
StartProcessFailed,
StopProcessConfirm,
StopProcessFailed,
ProcessFailed,
ProcessFailedWithReason,
ProcessStepFailedWithReason,
ProcessSubstratePositionFailedWithReason,
ProcessSubstratePositionRecipeNotLoaded,
ProcessSubstratePositionMarkParameterMissing,
ProcessSubstratePositionNoEnabledMarks,
ProcessSubstratePositionAlignmentFailedWithReason,
ProcessDiePositionFailedWithReason,
ProcessDiePositionRecipeNotLoaded,
ProcessDiePositionCoordinateGenerationMissing,
ProcessDiePositionWaferInfoMissing,
ProcessSubstrateHeightMeasureFailedWithReason,
ProcessSubstrateHeightMeasureRecipeNotLoaded,
ProcessSubstrateHeightMeasureSettingMissing,
ProcessSubstrateHeightMeasureNoPoints,
ProcessSubstrateHeightMeasurePointPositionInvalid,
NeedleCalibrationLoadFailed,
NeedleCalibrationTouchCountMustGreaterThanZero,
NeedleCalibrationCompleted,
NeedleCalibrationStopped,
NeedleCalibrationCanceled,
OriginCalibOpenVisionTemplateFailed,
OriginCalibAxisNotFound,
OriginCalibReadPositionFailed,
OriginCalibMoveFailed,
OriginCalibDeleteAxisFailed,
OriginCalibDeleteAxisDuringCalibration,
OriginCalibCalibrationCanceled,
OriginCalibCalibrationFailed,
OriginCalibConfigSaved,
OriginCalibConfigSaveFailed,
OriginCalibNoCalibratedModules,
OriginCalibControllerWriteCompleted,
OriginCalibControllerWriteNotReady,
OriginCalibControllerWritePartialSuccess,
OriginCalibControllerWriteNotImplemented,
PidNoProfileSelected,
PidNoFilteringParameterSelected,
PidReadSucceeded,
PidReadFailed,
PidWriteSucceeded,
PidWriteFailed,
DieRecheckSelectedPointRequired,
DieRecheckMoveDeviceUnavailable,
DieRecheckStatusOk,
DieRecheckStatusMissingBond,
DieRecheckStatusXExceeded,
DieRecheckStatusYExceeded
}
}

View File

@@ -0,0 +1,639 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using MainShell.Common.View;
using MainShell.Common.ViewModel;
namespace MainShell.Common
{
public static class MwMessageBoxGlyphs
{
public const string None = "\uE686";
public const string Information = "\uE625";
public const string Warning = "\uE7BD";
public const string Error = "\uE76C";
public const string Question = "\uE686";
}
public sealed class MwMessageBoxButtonText
{
public string Ok { get; set; } = <><C8B7>";
public string Cancel { get; set; } = <><C8A1>";
public string Yes { get; set; } = "<22><>";
public string No { get; set; } = "<22><>";
public string Retry { get; set; } = "<22><><EFBFBD><EFBFBD>";
public string Abort { get; set; } = "<22><>ֹ";
public string Ignore { get; set; } = "<22><><EFBFBD><EFBFBD>";
public static MwMessageBoxButtonText CreateDefault()
{
return new MwMessageBoxButtonText();
}
}
public sealed class MwMessageBoxButtonDefinition
{
public string Text { get; set; }
public MessageBoxResult Result { get; set; }
public bool IsDefault { get; set; }
public bool IsCancel { get; set; }
public bool IsPrimary { get; set; }
public Style ButtonStyle { get; set; }
}
public sealed class MwMessageBoxIconTheme
{
public string NoneGlyph { get; set; } = MwMessageBoxGlyphs.None;
public string InformationGlyph { get; set; } = MwMessageBoxGlyphs.Information;
public string WarningGlyph { get; set; } = MwMessageBoxGlyphs.Warning;
public string ErrorGlyph { get; set; } = MwMessageBoxGlyphs.Error;
public string QuestionGlyph { get; set; } = MwMessageBoxGlyphs.Question;
public static MwMessageBoxIconTheme CreateDefault()
{
return new MwMessageBoxIconTheme();
}
}
public sealed class MwMessageBoxColorPalette
{
public MwMessageBoxColorPalette()
{
}
public MwMessageBoxColorPalette(string accentColor, string iconBackgroundColor, string iconForegroundColor)
{
AccentColor = accentColor;
IconBackgroundColor = iconBackgroundColor;
IconForegroundColor = iconForegroundColor;
}
public string AccentColor { get; set; }
public string IconBackgroundColor { get; set; }
public string IconForegroundColor { get; set; }
}
public sealed class MwMessageBoxButtonColorTheme
{
public MwMessageBoxButtonColorTheme()
{
}
public MwMessageBoxButtonColorTheme(string backgroundColor, string hoverBackgroundColor, string pressedBackgroundColor, string borderColor, string foregroundColor)
{
BackgroundColor = backgroundColor;
HoverBackgroundColor = hoverBackgroundColor;
PressedBackgroundColor = pressedBackgroundColor;
BorderColor = borderColor;
ForegroundColor = foregroundColor;
}
public string BackgroundColor { get; set; }
public string HoverBackgroundColor { get; set; }
public string PressedBackgroundColor { get; set; }
public string BorderColor { get; set; }
public string ForegroundColor { get; set; }
}
public sealed class MwMessageBoxVisualTheme
{
public MwMessageBoxColorPalette NonePalette { get; set; } = new MwMessageBoxColorPalette("#9CA3AF", "#F3F4F6", "#6B7280");
public MwMessageBoxColorPalette InformationPalette { get; set; } = new MwMessageBoxColorPalette("#38BDF8", "#E0F2FE", "#0284C7");
public MwMessageBoxColorPalette WarningPalette { get; set; } = new MwMessageBoxColorPalette("#F59E0B", "#FEF3C7", "#D97706");
public MwMessageBoxColorPalette ErrorPalette { get; set; } = new MwMessageBoxColorPalette("#EF4444", "#FEE2E2", "#DC2626");
public MwMessageBoxColorPalette QuestionPalette { get; set; } = new MwMessageBoxColorPalette("#3B82F6", "#DBEAFE", "#2563EB");
public MwMessageBoxButtonColorTheme PrimaryButtonTheme { get; set; } = new MwMessageBoxButtonColorTheme("#0E6AE8", "#0B5AD0", "#094BAC", "#0E6AE8", "#FFFFFF");
public MwMessageBoxButtonColorTheme SecondaryButtonTheme { get; set; } = new MwMessageBoxButtonColorTheme("#F3F4F6", "#E5E7EB", "#D1D5DB", "#D1D5DB", "#374151");
public static MwMessageBoxVisualTheme CreateDefault()
{
return new MwMessageBoxVisualTheme();
}
}
public sealed class MwMessageBoxState
{
public string Caption { get; set; }
public string Message { get; set; }
public string IconGlyph { get; set; }
public string IconPathData { get; set; }
public string TimeText { get; set; }
public Brush AccentBrush { get; set; }
public Brush IconBackgroundBrush { get; set; }
public Brush IconForegroundBrush { get; set; }
public IReadOnlyList<MwMessageBoxButtonDefinition> Buttons { get; set; }
public MessageBoxResult DefaultResult { get; set; }
public TextAlignment MessageTextAlignment { get; set; } = TextAlignment.Left;
public FlowDirection WindowFlowDirection { get; set; } = FlowDirection.LeftToRight;
public FlowDirection MessageFlowDirection { get; set; } = FlowDirection.LeftToRight;
}
public static class MwMessageBox
{
public static MwMessageBoxButtonText DefaultButtonText { get; set; } = MwMessageBoxButtonText.CreateDefault();
public static MwMessageBoxIconTheme IconTheme { get; set; } = MwMessageBoxIconTheme.CreateDefault();
public static MwMessageBoxVisualTheme VisualTheme { get; set; } = MwMessageBoxVisualTheme.CreateDefault();
public static MessageBoxResult Show(string messageBoxText)
{
return Show(null, messageBoxText, string.Empty, MessageBoxButton.OK, MessageBoxImage.None, MessageBoxResult.None, 0, null);
}
public static MessageBoxResult Show(string messageBoxText, string caption)
{
return Show(null, messageBoxText, caption, MessageBoxButton.OK, MessageBoxImage.None, MessageBoxResult.None, 0, null);
}
public static MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button)
{
return Show(null, messageBoxText, caption, button, MessageBoxImage.None, MessageBoxResult.None, 0, null);
}
public static MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon)
{
return Show(null, messageBoxText, caption, button, icon, MessageBoxResult.None, 0, null);
}
public static MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult)
{
return Show(null, messageBoxText, caption, button, icon, defaultResult, 0, null);
}
public static MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options)
{
return Show(null, messageBoxText, caption, button, icon, defaultResult, options, null);
}
public static MessageBoxResult Show(Window owner, string messageBoxText)
{
return Show(owner, messageBoxText, string.Empty, MessageBoxButton.OK, MessageBoxImage.None, MessageBoxResult.None, 0, null);
}
public static MessageBoxResult Show(Window owner, string messageBoxText, string caption)
{
return Show(owner, messageBoxText, caption, MessageBoxButton.OK, MessageBoxImage.None, MessageBoxResult.None, 0, null);
}
public static MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button)
{
return Show(owner, messageBoxText, caption, button, MessageBoxImage.None, MessageBoxResult.None, 0, null);
}
public static MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon)
{
return Show(owner, messageBoxText, caption, button, icon, MessageBoxResult.None, 0, null);
}
public static MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult)
{
return Show(owner, messageBoxText, caption, button, icon, defaultResult, 0, null);
}
public static MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options)
{
return Show(owner, messageBoxText, caption, button, icon, defaultResult, options, null);
}
public static MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MwMessageBoxButtonText buttonText)
{
return Show(null, messageBoxText, caption, button, icon, MessageBoxResult.None, 0, buttonText);
}
public static MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MwMessageBoxButtonText buttonText)
{
return Show(owner, messageBoxText, caption, button, icon, MessageBoxResult.None, 0, buttonText);
}
public static MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options, MwMessageBoxButtonText buttonText)
{
return InvokeOnUiThread(() => ShowCore(owner, messageBoxText, caption, button, icon, defaultResult, options, buttonText));
}
public static MessageBoxResult ShowCustom(string messageBoxText, string caption, MessageBoxImage icon, params MwMessageBoxButtonDefinition[] buttons)
{
return ShowCustom(null, messageBoxText, caption, icon, MessageBoxResult.None, 0, buttons);
}
public static MessageBoxResult ShowCustom(Window owner, string messageBoxText, string caption, MessageBoxImage icon, params MwMessageBoxButtonDefinition[] buttons)
{
return ShowCustom(owner, messageBoxText, caption, icon, MessageBoxResult.None, 0, buttons);
}
public static MessageBoxResult ShowCustom(Window owner, string messageBoxText, string caption, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options, params MwMessageBoxButtonDefinition[] buttons)
{
return InvokeOnUiThread(() => ShowCustomCore(owner, messageBoxText, caption, icon, defaultResult, options, buttons));
}
internal static T InvokeOnUiThread<T>(Func<T> callback)
{
if (callback == null)
{
throw new ArgumentNullException(nameof(callback));
}
Application application = Application.Current;
if (application == null)
{
return callback();
}
if (application.Dispatcher == null || application.Dispatcher.CheckAccess())
{
return callback();
}
return application.Dispatcher.Invoke(callback);
}
private static MessageBoxResult ShowCore(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options, MwMessageBoxButtonText buttonText)
{
owner = owner ?? GetActiveWindow();
List<MwMessageBoxButtonDefinition> definitions = CreateButtonDefinitions(button, defaultResult, buttonText ?? DefaultButtonText).ToList();
MwMessageBoxState state = CreateState(messageBoxText, caption, icon, definitions, defaultResult, options);
MwMessageBoxWindowViewModel viewModel = new MwMessageBoxWindowViewModel(state);
MwMessageBoxWindow dialog = new MwMessageBoxWindow(viewModel);
if (owner != null)
{
dialog.Owner = owner;
dialog.WindowStartupLocation = WindowStartupLocation.CenterOwner;
}
dialog.ShowDialog();
return viewModel.Result;
}
private static MessageBoxResult ShowCustomCore(Window owner, string messageBoxText, string caption, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options, params MwMessageBoxButtonDefinition[] buttons)
{
owner = owner ?? GetActiveWindow();
List<MwMessageBoxButtonDefinition> definitions = NormalizeButtonDefinitions(buttons, defaultResult).ToList();
MwMessageBoxState state = CreateState(messageBoxText, caption, icon, definitions, defaultResult, options);
MwMessageBoxWindowViewModel viewModel = new MwMessageBoxWindowViewModel(state);
MwMessageBoxWindow dialog = new MwMessageBoxWindow(viewModel);
if (owner != null)
{
dialog.Owner = owner;
dialog.WindowStartupLocation = WindowStartupLocation.CenterOwner;
}
dialog.ShowDialog();
return viewModel.Result;
}
private static IEnumerable<MwMessageBoxButtonDefinition> CreateButtonDefinitions(MessageBoxButton button, MessageBoxResult defaultResult, MwMessageBoxButtonText buttonText)
{
var labels = buttonText ?? MwMessageBoxButtonText.CreateDefault();
var definitions = new List<MwMessageBoxButtonDefinition>();
switch (button)
{
case MessageBoxButton.OK:
definitions.Add(CreateDefinition(labels.Ok, MessageBoxResult.OK, true));
break;
case MessageBoxButton.OKCancel:
definitions.Add(CreateDefinition(labels.Ok, MessageBoxResult.OK, true));
definitions.Add(CreateDefinition(labels.Cancel, MessageBoxResult.Cancel, false, true));
break;
case MessageBoxButton.YesNo:
definitions.Add(CreateDefinition(labels.Yes, MessageBoxResult.Yes, true));
definitions.Add(CreateDefinition(labels.No, MessageBoxResult.No));
break;
case MessageBoxButton.YesNoCancel:
definitions.Add(CreateDefinition(labels.Yes, MessageBoxResult.Yes, true));
definitions.Add(CreateDefinition(labels.No, MessageBoxResult.No));
definitions.Add(CreateDefinition(labels.Cancel, MessageBoxResult.Cancel, false, true));
break;
default:
definitions.Add(CreateDefinition(labels.Ok, MessageBoxResult.OK, true));
break;
}
return NormalizeButtonDefinitions(definitions, defaultResult);
}
private static IEnumerable<MwMessageBoxButtonDefinition> NormalizeButtonDefinitions(IEnumerable<MwMessageBoxButtonDefinition> buttons, MessageBoxResult defaultResult)
{
var definitions = (buttons ?? Enumerable.Empty<MwMessageBoxButtonDefinition>())
.Where(item => item != null)
.Select(item => new MwMessageBoxButtonDefinition
{
Text = string.IsNullOrWhiteSpace(item.Text) ? item.Result.ToString() : item.Text,
Result = item.Result,
IsCancel = item.IsCancel,
IsDefault = item.IsDefault,
IsPrimary = item.IsPrimary,
ButtonStyle = item.ButtonStyle
})
.ToList();
if (definitions.Count == 0)
{
definitions.Add(CreateDefinition(DefaultButtonText.Ok, MessageBoxResult.OK, true));
}
var targetDefault = defaultResult == MessageBoxResult.None
? definitions.FirstOrDefault(item => item.IsDefault)?.Result ?? definitions[0].Result
: defaultResult;
foreach (var item in definitions)
{
item.IsDefault = item.Result == targetDefault;
}
if (!definitions.Any(item => item.IsCancel))
{
var cancelButton = definitions.FirstOrDefault(item => item.Result == MessageBoxResult.Cancel);
if (cancelButton != null)
{
cancelButton.IsCancel = true;
}
}
if (!definitions.Any(item => item.IsPrimary))
{
var primary = definitions.FirstOrDefault(item => item.IsDefault) ?? definitions[0];
primary.IsPrimary = true;
}
foreach (var item in definitions)
{
item.ButtonStyle = item.ButtonStyle ?? GetButtonStyle(item.IsPrimary);
}
return definitions;
}
private static MwMessageBoxButtonDefinition CreateDefinition(string text, MessageBoxResult result, bool isPrimary = false, bool isCancel = false)
{
return new MwMessageBoxButtonDefinition
{
Text = text,
Result = result,
IsPrimary = isPrimary,
IsDefault = isPrimary,
IsCancel = isCancel,
ButtonStyle = GetButtonStyle(isPrimary)
};
}
internal static Style GetButtonStyle(bool isPrimary)
{
if (Application.Current != null)
{
var key = isPrimary ? "SaveButtonStyle" : "SettingsButtonStyle";
var resourceStyle = Application.Current.TryFindResource(key) as Style;
if (resourceStyle != null)
{
return resourceStyle;
}
}
var visualTheme = VisualTheme ?? MwMessageBoxVisualTheme.CreateDefault();
var buttonTheme = isPrimary ? visualTheme.PrimaryButtonTheme : visualTheme.SecondaryButtonTheme;
var style = new Style(typeof(System.Windows.Controls.Button));
style.Setters.Add(new Setter(System.Windows.Controls.Control.BackgroundProperty, CreateBrush(buttonTheme.BackgroundColor)));
style.Setters.Add(new Setter(System.Windows.Controls.Control.BorderBrushProperty, CreateBrush(buttonTheme.BorderColor)));
style.Setters.Add(new Setter(System.Windows.Controls.Control.BorderThicknessProperty, new Thickness(1)));
style.Setters.Add(new Setter(System.Windows.Controls.Control.ForegroundProperty, CreateBrush(buttonTheme.ForegroundColor)));
style.Setters.Add(new Setter(System.Windows.Controls.Control.FontSizeProperty, 14d));
style.Setters.Add(new Setter(System.Windows.Controls.Control.FontWeightProperty, FontWeights.SemiBold));
style.Setters.Add(new Setter(System.Windows.Controls.Control.CursorProperty, System.Windows.Input.Cursors.Hand));
var hoverTrigger = new Trigger { Property = UIElement.IsMouseOverProperty, Value = true };
hoverTrigger.Setters.Add(new Setter(System.Windows.Controls.Control.BackgroundProperty, CreateBrush(buttonTheme.HoverBackgroundColor)));
style.Triggers.Add(hoverTrigger);
var pressedTrigger = new Trigger { Property = System.Windows.Controls.Primitives.ButtonBase.IsPressedProperty, Value = true };
pressedTrigger.Setters.Add(new Setter(System.Windows.Controls.Control.BackgroundProperty, CreateBrush(buttonTheme.PressedBackgroundColor)));
style.Triggers.Add(pressedTrigger);
return style;
}
internal static MessageBoxResult ResolveFallbackResult(MwMessageBoxState state)
{
if (state == null)
{
return MessageBoxResult.None;
}
if (state.DefaultResult != MessageBoxResult.None)
{
return state.DefaultResult;
}
var cancelButton = state.Buttons != null ? state.Buttons.FirstOrDefault(item => item.IsCancel) : null;
if (cancelButton != null)
{
return cancelButton.Result;
}
var defaultButton = state.Buttons != null ? state.Buttons.FirstOrDefault(item => item.IsDefault) ?? state.Buttons.FirstOrDefault() : null;
return defaultButton != null ? defaultButton.Result : MessageBoxResult.None;
}
private static Window GetActiveWindow()
{
if (Application.Current == null)
{
return null;
}
var active = Application.Current.Windows.OfType<Window>().FirstOrDefault(w => w.IsActive);
if (active != null)
{
return active;
}
if (Application.Current.MainWindow != null && Application.Current.MainWindow.IsVisible)
{
return Application.Current.MainWindow;
}
return Application.Current.Windows.OfType<Window>()
.Where(w => w.IsVisible)
.OrderByDescending(w => w.IsLoaded)
.FirstOrDefault();
}
private static MwMessageBoxState CreateState(string message, string caption, MessageBoxImage icon, IReadOnlyList<MwMessageBoxButtonDefinition> buttons, MessageBoxResult defaultResult, MessageBoxOptions options)
{
var palette = CreatePaletteBrushes(GetPalette(icon));
return new MwMessageBoxState
{
Caption = ResolveCaption(caption, icon),
Message = message,
IconGlyph = GetIconText(icon, IconTheme),
IconPathData = GetIconPathData(icon),
TimeText = DateTime.Now.ToString("HH:mm:ss"),
AccentBrush = palette.AccentBrush,
IconBackgroundBrush = palette.IconBackgroundBrush,
IconForegroundBrush = palette.IconForegroundBrush,
Buttons = buttons,
DefaultResult = defaultResult,
MessageTextAlignment = (options & MessageBoxOptions.RightAlign) == MessageBoxOptions.RightAlign ? TextAlignment.Right : TextAlignment.Left,
WindowFlowDirection = (options & MessageBoxOptions.RtlReading) == MessageBoxOptions.RtlReading ? FlowDirection.RightToLeft : FlowDirection.LeftToRight,
MessageFlowDirection = (options & MessageBoxOptions.RtlReading) == MessageBoxOptions.RtlReading ? FlowDirection.RightToLeft : FlowDirection.LeftToRight
};
}
private static string ResolveCaption(string caption, MessageBoxImage icon)
{
if (!string.IsNullOrWhiteSpace(caption))
{
return caption;
}
switch (icon)
{
case MessageBoxImage.Warning:
return "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ";
case MessageBoxImage.Error:
return "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ";
case MessageBoxImage.Information:
return "<22><>Ϣ<EFBFBD><CFA2>ʾ";
case MessageBoxImage.Question:
return "<22><><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7>";
default:
return "<22><>ʾ";
}
}
private static string GetIconText(MessageBoxImage icon, MwMessageBoxIconTheme iconTheme)
{
var theme = iconTheme ?? MwMessageBoxIconTheme.CreateDefault();
switch (icon)
{
case MessageBoxImage.None:
return theme.NoneGlyph;
case MessageBoxImage.Warning:
return theme.WarningGlyph;
case MessageBoxImage.Error:
return theme.ErrorGlyph;
case MessageBoxImage.Information:
return theme.InformationGlyph;
case MessageBoxImage.Question:
return theme.QuestionGlyph;
default:
return theme.NoneGlyph;
}
}
private static string GetIconPathData(MessageBoxImage icon)
{
switch (icon)
{
case MessageBoxImage.Warning:
return "M11,4 H13 V14 H11 Z M11,16 H13 V18 H11 Z";
case MessageBoxImage.Error:
return "M7.76,6.34 L12,10.59 L16.24,6.34 L17.66,7.76 L13.41,12 L17.66,16.24 L16.24,17.66 L12,13.41 L7.76,17.66 L6.34,16.24 L10.59,12 L6.34,7.76 Z";
case MessageBoxImage.Information:
return "M11,5 H13 V7 H11 Z M11,9 H13 V19 H11 Z";
case MessageBoxImage.Question:
return "M10.2,8.8 C10.27,7.69 11.17,6.82 12.3,6.82 C13.46,6.82 14.36,7.66 14.36,8.75 C14.36,9.52 13.96,10.12 13.02,10.82 C11.74,11.78 11.1,12.65 11.1,14.35 L12.9,14.35 C12.9,13.26 13.27,12.74 14.1,12.09 C15.29,11.17 16,10.14 16,8.72 C16,6.69 14.37,5 12.3,5 C10.23,5 8.56,6.63 8.4,8.8 Z M11.05,16.2 H13.15 V18.3 H11.05 Z";
default:
return "M8,11 H16 V13 H8 Z";
}
}
private static MwMessageBoxColorPalette GetPalette(MessageBoxImage icon)
{
var visualTheme = VisualTheme ?? MwMessageBoxVisualTheme.CreateDefault();
switch (icon)
{
case MessageBoxImage.Warning:
return CreatePalette(visualTheme.WarningPalette, visualTheme.NonePalette);
case MessageBoxImage.Error:
return CreatePalette(visualTheme.ErrorPalette, visualTheme.NonePalette);
case MessageBoxImage.Information:
return CreatePalette(visualTheme.InformationPalette, visualTheme.NonePalette);
case MessageBoxImage.Question:
return CreatePalette(visualTheme.QuestionPalette, visualTheme.NonePalette);
default:
return CreatePalette(visualTheme.NonePalette, MwMessageBoxVisualTheme.CreateDefault().NonePalette);
}
}
private static MwMessageBoxPaletteBrushes CreatePaletteBrushes(MwMessageBoxColorPalette palette)
{
return new MwMessageBoxPaletteBrushes(palette);
}
private static MwMessageBoxColorPalette CreatePalette(MwMessageBoxColorPalette palette, MwMessageBoxColorPalette fallbackPalette)
{
var resolvedFallback = fallbackPalette ?? MwMessageBoxVisualTheme.CreateDefault().NonePalette;
var resolvedPalette = palette ?? resolvedFallback;
return new MwMessageBoxColorPalette(
resolvedPalette.AccentColor ?? resolvedFallback.AccentColor,
resolvedPalette.IconBackgroundColor ?? resolvedFallback.IconBackgroundColor,
resolvedPalette.IconForegroundColor ?? resolvedFallback.IconForegroundColor);
}
private static SolidColorBrush CreateBrush(string color)
{
return (SolidColorBrush)new BrushConverter().ConvertFromString(color);
}
private sealed class MwMessageBoxPaletteBrushes
{
public MwMessageBoxPaletteBrushes(MwMessageBoxColorPalette palette)
{
var resolvedPalette = palette ?? MwMessageBoxVisualTheme.CreateDefault().NonePalette;
AccentBrush = CreateBrush(resolvedPalette.AccentColor ?? "#9CA3AF");
IconBackgroundBrush = CreateBrush(resolvedPalette.IconBackgroundColor ?? "#F3F4F6");
IconForegroundBrush = CreateBrush(resolvedPalette.IconForegroundColor ?? "#6B7280");
}
public Brush AccentBrush { get; }
public Brush IconBackgroundBrush { get; }
public Brush IconForegroundBrush { get; }
private static SolidColorBrush CreateBrush(string color)
{
return (SolidColorBrush)new BrushConverter().ConvertFromString(color);
}
}
}
}

View File

@@ -0,0 +1,296 @@
<Window x:Class="MainShell.Common.View.MwMessageBoxWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:common="clr-namespace:MainShell.Common"
xmlns:behaviors="clr-namespace:MainShell.Common.Behaviors"
mc:Ignorable="d"
MinWidth="360"
MinHeight="220"
MaxWidth="720"
SizeToContent="WidthAndHeight"
ResizeMode="NoResize"
WindowStartupLocation="CenterScreen"
AllowsTransparency="True"
WindowStyle="None"
Background="Transparent"
ShowInTaskbar="False"
Title="{Binding State.Caption}"
FlowDirection="{Binding State.WindowFlowDirection}"
UseLayoutRounding="True"
SnapsToDevicePixels="True"
common:WindowService.DialogResult="{Binding DialogResult}">
<Window.Resources>
<Style x:Key="MwMessageBoxButtonStyle" TargetType="Button">
<Setter Property="Foreground" Value="#374151"/>
<Setter Property="Background" Value="#FFFFFF"/>
<Setter Property="BorderBrush" Value="#C9D5E5"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="FontSize" Value="15"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="3">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding DataContext.IsPrimary, RelativeSource={RelativeSource TemplatedParent}}" Value="True">
<Setter Property="Background" Value="#2E5FA7"/>
<Setter Property="BorderBrush" Value="#2E5FA7"/>
<Setter Property="Foreground" Value="#FFFFFF"/>
</DataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding DataContext.IsPrimary, RelativeSource={RelativeSource TemplatedParent}}" Value="False"/>
<Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource TemplatedParent}}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="#F5F8FC"/>
<Setter Property="BorderBrush" Value="#AFC3DD"/>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding DataContext.IsPrimary, RelativeSource={RelativeSource TemplatedParent}}" Value="False"/>
<Condition Binding="{Binding IsPressed, RelativeSource={RelativeSource TemplatedParent}}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="#E8EEF6"/>
<Setter Property="BorderBrush" Value="#9FB7D6"/>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding DataContext.IsPrimary, RelativeSource={RelativeSource TemplatedParent}}" Value="True"/>
<Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource TemplatedParent}}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="#254F8D"/>
<Setter Property="BorderBrush" Value="#254F8D"/>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding DataContext.IsPrimary, RelativeSource={RelativeSource TemplatedParent}}" Value="True"/>
<Condition Binding="{Binding IsPressed, RelativeSource={RelativeSource TemplatedParent}}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="#1E4174"/>
<Setter Property="BorderBrush" Value="#1E4174"/>
</MultiDataTrigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="#9CA3AF"/>
<Setter Property="Background" Value="#F3F4F6"/>
<Setter Property="BorderBrush" Value="#E5E7EB"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="MwMessageBoxCaptionStyle" TargetType="TextBlock">
<Setter Property="Text" Value="{Binding State.Caption}"/>
<Setter Property="Visibility" Value="Visible"/>
<Style.Triggers>
<Trigger Property="Text" Value="">
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="MwMessageBoxCloseButtonStyle" TargetType="Button">
<Setter Property="Width" Value="44"/>
<Setter Property="Height" Value="32"/>
<Setter Property="Foreground" Value="#FFFFFF"/>
<Setter Property="Background" Value="#2E5FA7"/>
<Setter Property="BorderBrush" Value="#2E5FA7"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#C94A4A"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="#A53B3B"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<i:InvokeCommandAction Command="{Binding WindowClosingCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<Border Background="#FFFFFF"
CornerRadius="2"
BorderBrush="#C6D1DF"
BorderThickness="1">
<Border.Effect>
<DropShadowEffect Color="#1F3A5A"
BlurRadius="18"
ShadowDepth="2"
Opacity="0.18"/>
</Border.Effect>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="#2E5FA7">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0"
behaviors:WindowDragMoveBehavior.IsEnabled="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Width="16"
Height="16"
Margin="10,0,8,0"
VerticalAlignment="Center"
BorderBrush="#D8E6F7"
BorderThickness="1"
CornerRadius="8">
<TextBlock Text="i"
Foreground="#FFFFFF"
FontSize="11"
FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<TextBlock Grid.Column="1"
VerticalAlignment="Center"
Foreground="#FFFFFF"
FontSize="13"
FontWeight="Normal"
TextTrimming="CharacterEllipsis">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="{Binding State.Caption}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding State.Caption}" Value="{x:Null}">
<Setter Property="Text" Value="{DynamicResource Msg_Title_Info}"/>
</DataTrigger>
<DataTrigger Binding="{Binding State.Caption}" Value="">
<Setter Property="Text" Value="{DynamicResource Msg_Title_Info}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
<Button Grid.Column="1"
x:Name="CloseButton"
Style="{StaticResource MwMessageBoxCloseButtonStyle}"
Click="OnCloseButtonClick"/>
</Grid>
<Grid Grid.Row="1" Margin="28,28,28,22">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border Width="62"
Height="62"
HorizontalAlignment="Center"
Background="#FFFFFF"
BorderBrush="{Binding State.AccentBrush}"
BorderThickness="1.5"
CornerRadius="31">
<Viewbox Width="26"
Height="26"
Stretch="Uniform">
<Path Data="{Binding State.IconPathData}"
Fill="{Binding State.IconForegroundBrush}"
Stretch="Uniform"/>
</Viewbox>
</Border>
<TextBlock Grid.Row="1"
Margin="0,18,0,0"
HorizontalAlignment="Center"
Foreground="#1F2937"
FontSize="17"
FontWeight="SemiBold"
TextAlignment="Center"
Style="{StaticResource MwMessageBoxCaptionStyle}"/>
<TextBlock Grid.Row="2"
Margin="0,14,0,0"
MaxWidth="540"
Text="{Binding State.Message}"
TextWrapping="Wrap"
Foreground="#4B5563"
FontSize="14"
LineHeight="23"
TextAlignment="Center"
FlowDirection="{Binding State.MessageFlowDirection}"/>
</Grid>
<Grid Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition Height="1"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border Grid.Row="0"
Background="#E7EEF7"/>
<ItemsControl Grid.Row="1"
Margin="0,18,0,20"
ItemsSource="{Binding State.Buttons}"
HorizontalAlignment="Center"
MaxWidth="560">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" HorizontalAlignment="Center"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Text}"
MinWidth="96"
Height="38"
Margin="8,0,8,0"
Padding="22,0,22,0"
IsDefault="{Binding IsDefault}"
IsCancel="{Binding IsCancel}"
Style="{Binding ButtonStyle, TargetNullValue={StaticResource MwMessageBoxButtonStyle}}"
Command="{Binding DataContext.SelectButtonCommand, RelativeSource={RelativeSource AncestorType=Window}}"
CommandParameter="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Grid>
</Border>
</Window>

View File

@@ -0,0 +1,20 @@
using System.Windows;
using MainShell.Common.ViewModel;
namespace MainShell.Common.View
{
public partial class MwMessageBoxWindow : Window
{
public MwMessageBoxWindow(MwMessageBoxWindowViewModel viewModel)
{
InitializeComponent();
DataContext = viewModel ?? throw new System.ArgumentNullException(nameof(viewModel));
CloseButton.Content = "\u00D7";
}
private void OnCloseButtonClick(object sender, System.Windows.RoutedEventArgs e)
{
this.Close();
}
}
}

View File

@@ -0,0 +1,61 @@
using System;
using System.Windows;
using System.Windows.Input;
using MaxwellFramework.Core.Common.Command;
using Stylet;
namespace MainShell.Common.ViewModel
{
public class MwMessageBoxWindowViewModel : PropertyChangedBase
{
private bool? _dialogResult;
private MessageBoxResult _result;
public MwMessageBoxWindowViewModel(MwMessageBoxState state)
{
State = state ?? throw new ArgumentNullException(nameof(state));
SelectButtonCommand = new DelegateCommand(OnSelectButton);
WindowClosingCommand = new DelegateCommand(OnWindowClosing);
}
public MwMessageBoxState State { get; }
public bool? DialogResult
{
get => _dialogResult;
set => SetAndNotify(ref _dialogResult, value);
}
public MessageBoxResult Result
{
get => _result;
private set => SetAndNotify(ref _result, value);
}
public ICommand SelectButtonCommand { get; }
public ICommand WindowClosingCommand { get; }
private void OnSelectButton(object parameter)
{
var definition = parameter as MwMessageBoxButtonDefinition;
if (definition == null)
{
return;
}
Result = definition.Result;
DialogResult = true;
}
private void OnWindowClosing(object parameter)
{
if (Result != MessageBoxResult.None)
{
return;
}
Result = MwMessageBox.ResolveFallbackResult(State);
}
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Markup;
namespace MainShell.Common
{
[MarkupExtensionReturnType(typeof(string))]
public class PropDescExtension : MarkupExtension
{
public Type ForType { get; set; }
public string Property { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (ForType == null || string.IsNullOrWhiteSpace(Property)) return Property;
var pd = TypeDescriptor.GetProperties(ForType)[Property];
if (pd == null) return Property;
var desc = pd.Attributes.OfType<DescriptionAttribute>().FirstOrDefault();
return string.IsNullOrWhiteSpace(desc?.Description) ? Property : desc.Description;
}
}
}

View File

@@ -0,0 +1,232 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace MainShell.Common
{
public class RetryMechanism
{
// 自定义异常:操作失败
public class RetryException : Exception
{
public RetryException(string message) : base(message) { }
}
public class RetryResult
{
public bool Succeeded { get; set; }
public bool IsAborted { get; set; }
public int AttemptCount { get; set; }
public int MaxAttempts { get; set; }
public string Message { get; set; }
}
/// <summary>
/// 向后兼容旧接口:默认直接继续重试直到达到最大次数,失败时抛异常。
/// 新代码建议优先使用 <see cref="RetryOrThrow(Func{bool}, Func{int, bool}, string, int)"/> 或返回结果对象的重载。
/// </summary>
public static void RetryIfNeeded(Func<bool> checkCondition, string message, int maxAttempts = 3)
{
RetryOrThrow(checkCondition, attempt => true, message, maxAttempts);
}
/// <summary>
/// 执行同步重试并返回结果对象。
/// </summary>
/// <param name="checkCondition">
/// 每次尝试时执行的检查逻辑。
/// 返回 <c>true</c> 表示成功,返回 <c>false</c> 表示本次失败并根据 <paramref name="shouldRetry"/> 决定是否继续。
/// 如果该委托抛出异常,则异常会直接向外传播,不会被当前重试机制捕获或吞掉,也不会自动进入下一次重试。
/// </param>
/// <param name="shouldRetry">当一次尝试失败后,决定是否继续重试。参数为当前已完成的尝试次数,从 1 开始计数。</param>
/// <param name="message">操作描述信息。</param>
/// <param name="maxAttempts">最大尝试次数,必须大于 0。</param>
public static RetryResult RetryIfNeeded(Func<bool> checkCondition, Func<int, bool> shouldRetry, string message, int maxAttempts = 3)
{
if (checkCondition == null)
{
throw new ArgumentNullException(nameof(checkCondition));
}
if (shouldRetry == null)
{
throw new ArgumentNullException(nameof(shouldRetry));
}
if (maxAttempts <= 0)
{
throw new ArgumentOutOfRangeException(nameof(maxAttempts), "maxAttempts must be greater than 0.");
}
for (int attempt = 1; attempt <= maxAttempts; attempt++)
{
bool conditionMet = checkCondition();
if (conditionMet)
{
return new RetryResult
{
Succeeded = true,
AttemptCount = attempt,
MaxAttempts = maxAttempts,
Message = message
};
}
if (attempt == maxAttempts)
{
return new RetryResult
{
Succeeded = false,
AttemptCount = attempt,
MaxAttempts = maxAttempts,
Message = message
};
}
bool continueRetry = shouldRetry(attempt);
if (!continueRetry)
{
return new RetryResult
{
Succeeded = false,
IsAborted = true,
AttemptCount = attempt,
MaxAttempts = maxAttempts,
Message = message
};
}
}
return new RetryResult
{
Succeeded = false,
AttemptCount = maxAttempts,
MaxAttempts = maxAttempts,
Message = message
};
}
// 保留抛异常风格的兼容方法
public static void RetryOrThrow(Func<bool> checkCondition, Func<int, bool> shouldRetry, string message, int maxAttempts = 3)
{
var result = RetryIfNeeded(checkCondition, shouldRetry, message, maxAttempts);
EnsureSuccess(result);
}
/// <summary>
/// 向后兼容旧接口的异步版本:默认直接继续重试直到达到最大次数,失败时抛异常。
/// 新代码建议优先使用 <see cref="RetryOrThrowAsync(Func{Task{bool}}, Func{int, Task{bool}}, string, int, CancellationToken)"/> 或返回结果对象的重载。
/// </summary>
public static async Task RetryIfNeededAsync(Func<Task<bool>> checkConditionAsync, string message, int maxAttempts = 3)
{
await RetryOrThrowAsync(checkConditionAsync, attempt => Task.FromResult(true), message, maxAttempts, CancellationToken.None).ConfigureAwait(false);
}
/// <summary>
/// 执行异步重试并返回结果对象。
/// </summary>
/// <param name="checkConditionAsync">
/// 每次尝试时执行的异步检查逻辑。
/// 返回 <c>true</c> 表示成功,返回 <c>false</c> 表示本次失败并根据 <paramref name="shouldRetryAsync"/> 决定是否继续。
/// 如果该委托抛出异常,则异常会直接向外传播,不会被当前重试机制捕获或吞掉,也不会自动进入下一次重试。
/// </param>
/// <param name="shouldRetryAsync">当一次尝试失败后,决定是否继续重试。参数为当前已完成的尝试次数,从 1 开始计数。</param>
/// <param name="message">操作描述信息。</param>
/// <param name="maxAttempts">最大尝试次数,必须大于 0。</param>
/// <param name="cancellationToken">用于取消异步重试流程。</param>
public static async Task<RetryResult> RetryIfNeededAsync(Func<Task<bool>> checkConditionAsync, Func<int, Task<bool>> shouldRetryAsync, string message, int maxAttempts = 3, CancellationToken cancellationToken = default(CancellationToken))
{
if (checkConditionAsync == null)
{
throw new ArgumentNullException(nameof(checkConditionAsync));
}
if (shouldRetryAsync == null)
{
throw new ArgumentNullException(nameof(shouldRetryAsync));
}
if (maxAttempts <= 0)
{
throw new ArgumentOutOfRangeException(nameof(maxAttempts), "maxAttempts must be greater than 0.");
}
for (int attempt = 1; attempt <= maxAttempts; attempt++)
{
cancellationToken.ThrowIfCancellationRequested();
bool conditionMet = await checkConditionAsync().ConfigureAwait(false);
if (conditionMet)
{
return new RetryResult
{
Succeeded = true,
AttemptCount = attempt,
MaxAttempts = maxAttempts,
Message = message
};
}
if (attempt == maxAttempts)
{
return new RetryResult
{
Succeeded = false,
AttemptCount = attempt,
MaxAttempts = maxAttempts,
Message = message
};
}
cancellationToken.ThrowIfCancellationRequested();
bool continueRetry = await shouldRetryAsync(attempt).ConfigureAwait(false);
if (!continueRetry)
{
return new RetryResult
{
Succeeded = false,
IsAborted = true,
AttemptCount = attempt,
MaxAttempts = maxAttempts,
Message = message
};
}
}
return new RetryResult
{
Succeeded = false,
AttemptCount = maxAttempts,
MaxAttempts = maxAttempts,
Message = message
};
}
// 保留抛异常风格的异步兼容方法
public static async Task RetryOrThrowAsync(Func<Task<bool>> checkConditionAsync, Func<int, Task<bool>> shouldRetryAsync, string message, int maxAttempts = 3, CancellationToken cancellationToken = default(CancellationToken))
{
var result = await RetryIfNeededAsync(checkConditionAsync, shouldRetryAsync, message, maxAttempts, cancellationToken).ConfigureAwait(false);
EnsureSuccess(result);
}
private static void EnsureSuccess(RetryResult result)
{
if (result.Succeeded)
{
return;
}
if (result.IsAborted)
{
throw new RetryException($"{result.Message} 已中止重试,操作失败。尝试次数: {result.AttemptCount}/{result.MaxAttempts}");
}
throw new RetryException($"{result.Message} 已达到最大重试次数,操作失败。尝试次数: {result.AttemptCount}/{result.MaxAttempts}");
}
}
}

View File

@@ -0,0 +1,77 @@
using System;
using System.Diagnostics;
using System.Threading;
namespace MainShell.Common
{
class TimeoutRetryMechanism
{
public class WaitForConditionResult
{
public bool Succeeded { get; set; }
public bool TimedOut { get; set; }
public bool IsAborted { get; set; }
}
/// <summary>
/// 在指定超时时间内轮询等待条件成立。
/// 当 <paramref name="timeout"/> 为 <c>null</c> 时,表示无限等待,直到条件成立或外部取消。
/// </summary>
/// <param name="condition">待检查的条件,返回 <c>true</c> 表示条件成立。</param>
/// <param name="timeout">最大等待时间。传入 <c>null</c> 表示无限等待;传入具体值时必须大于 0。</param>
/// <param name="pollingInterval">轮询间隔,必须大于 0。</param>
/// <param name="cancellationToken">用于中止等待流程。</param>
public static WaitForConditionResult WaitForConditionWithTimeout(Func<bool> condition, TimeSpan? timeout, TimeSpan pollingInterval, CancellationToken cancellationToken)
{
if (condition == null)
{
throw new ArgumentNullException(nameof(condition));
}
if (timeout.HasValue && timeout.Value <= TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException(nameof(timeout), "timeout must be greater than zero when specified.");
}
if (pollingInterval <= TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException(nameof(pollingInterval), "pollingInterval must be greater than zero.");
}
var stopwatch = Stopwatch.StartNew();
while (true)
{
if (condition())
{
return new WaitForConditionResult
{
Succeeded = true
};
}
if (timeout.HasValue && stopwatch.Elapsed > timeout.Value)
{
return new WaitForConditionResult
{
Succeeded = false,
TimedOut = true
};
}
if (cancellationToken.IsCancellationRequested)
{
return new WaitForConditionResult
{
Succeeded = false,
IsAborted = true
};
}
Thread.Sleep(pollingInterval);
}
}
}
}

View File

@@ -0,0 +1,63 @@
<Window x:Class="MainShell.Common.View.CameraSettingsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MainShell.Common.View"
xmlns:custom="clr-namespace:MainShell.Resources.CustomControl" xmlns:mw="http://www.maxwell-gp.com/"
mc:Ignorable="d"
Title="相机设置"
Width="450" SizeToContent="Height"
WindowStartupLocation="CenterScreen"
ResizeMode="NoResize"
WindowStyle="ToolWindow"
d:DesignHeight="300" d:DesignWidth="350">
<StackPanel Margin="5">
<!-- 相机参数设置 -->
<GroupBox Header="{DynamicResource CameraPar}" Margin="0,0,0,5" Style="{StaticResource GroupBoxSecondary}">
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- 曝光时间 -->
<TextBlock Grid.Row="0" Grid.Column="0" Text="曝光时间:" VerticalAlignment="Center" Style="{StaticResource LabelStyle}"/>
<mw:IntNumberBox Grid.Row="0" Grid.Column="1"
Value="{Binding CameraConfig.ExposureTime}"
Minimum="10" Maximum="1000000"
mw:NumericKeypadAttach.IsEnabled="True"
HorizontalContentAlignment="Right" Margin="5,2,0,2"/>
<!-- 增益 -->
<TextBlock Grid.Row="1" Grid.Column="0" Text="增益:" VerticalAlignment="Center" Style="{StaticResource LabelStyle}"/>
<mw:IntNumberBox Grid.Row="1" Grid.Column="1"
Value="{Binding CameraConfig.Gain}"
Minimum="1" Maximum="100"
mw:NumericKeypadAttach.IsEnabled="True"
HorizontalContentAlignment="Right" Margin="5,2,0,2"/>
</Grid>
</GroupBox>
<!-- 光源参数设置 -->
<!-- 使用 ItemsControl 动态生成 LightControl需要 ViewModel 提供光源通道列表 -->
<GroupBox Header="{DynamicResource LightSetting}" Style="{StaticResource GroupBoxSecondary}">
<ItemsControl ItemsSource="{Binding LightChannels}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<custom:LightControl Header="{Binding Name}"
Value="{Binding Value, Mode=TwoWay}"
Min="0" Max="255" Margin="0,2"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</GroupBox>
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<Button Content="{DynamicResource GetParameter}" Style="{StaticResource TeachButtonStyle}" Margin="5" IsDefault="True" Command="{Binding ReadFromHardwareCommand}"/>
</StackPanel>
</StackPanel>
</Window>

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace MainShell.Common.View
{
/// <summary>
/// CameraSettingsControl.xaml 的交互逻辑
/// </summary>
public partial class CameraSettingsView : Window
{
public CameraSettingsView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,254 @@
using MainShell.Common;
using MainShell.Hardware;
using MainShell.Models;
using MwFramework.Controls.ControlCanvas;
using Stylet;
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Reflection;
using System.Windows.Input;
namespace MainShell.Common.ViewModel
{
/// <summary>
/// 单个光源通道的包装类
/// </summary>
public class LightChannelViewModel : PropertyChangedBase
{
private readonly object _sourceConfig;
private readonly PropertyInfo _propertyInfo;
public string Name { get; set; }
public int Value
{
get => (int)_propertyInfo.GetValue(_sourceConfig);
set
{
if (value != Value)
{
_propertyInfo.SetValue(_sourceConfig, value);
NotifyOfPropertyChange();
}
}
}
public LightChannelViewModel(object sourceConfig, PropertyInfo propertyInfo, string displayName)
{
_sourceConfig = sourceConfig;
_propertyInfo = propertyInfo;
Name = displayName;
}
}
/// <summary>
/// 相机及光源参数设置弹窗 ViewModel
/// </summary>
public class CameraSettingsViewModel : Screen
{
private readonly IWindowManager _windowManager;
private readonly HardwareManager _hardwareManager;
// 核心标志位:是否正在从硬件同步数据
private bool _isSyncingFromHardware;
private CameraType _currentCameraType;
private object _currentLightConfig;
private CameraConfig _cameraConfig;
public CameraConfig CameraConfig
{
get => _cameraConfig;
set => SetAndNotify(ref _cameraConfig, value);
}
private ObservableCollection<LightChannelViewModel> _lightChannels;
public ObservableCollection<LightChannelViewModel> LightChannels
{
get => _lightChannels;
set => SetAndNotify(ref _lightChannels, value);
}
public ICommand ReadFromHardwareCommand { get; }
public ICommand SaveAndCloseCommand { get; }
public CameraSettingsViewModel(IWindowManager windowManager, HardwareManager hardwareManager)
{
_windowManager = windowManager;
_hardwareManager = hardwareManager;
ReadFromHardwareCommand = new DelegateCommand(ReadFromHardware);
SaveAndCloseCommand = new DelegateCommand(SaveAndClose);
DisplayName = "相机光源参数设置";
}
/// <summary>
/// 初始化并绑定数据
/// </summary>
public void Initialize(CameraConfig cameraConfig, object lightConfig, CameraType cameraType)
{
// 1. 解绑旧对象的事件(如果有)
if (CameraConfig != null) CameraConfig.PropertyChanged -= OnConfigPropertyChanged;
if (_currentLightConfig is INotifyPropertyChanged oldLight) oldLight.PropertyChanged -= OnConfigPropertyChanged;
_currentCameraType = cameraType;
CameraConfig = cameraConfig;
_currentLightConfig = lightConfig;
// 2. 重新订阅事件
if (CameraConfig != null) CameraConfig.PropertyChanged += OnConfigPropertyChanged;
if (_currentLightConfig is INotifyPropertyChanged newLight) newLight.PropertyChanged += OnConfigPropertyChanged;
// 3. 生成光源通道列表
LightChannels = new ObservableCollection<LightChannelViewModel>();
if (lightConfig != null)
{
var properties = lightConfig.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var prop in properties)
{
if (prop.PropertyType == typeof(int) && prop.CanRead && prop.CanWrite)
{
var descAttr = prop.GetCustomAttribute<DescriptionAttribute>();
// 必须有 Description 才认为是光源通道
if (descAttr != null)
{
var vm = new LightChannelViewModel(lightConfig, prop, descAttr.Description);
LightChannels.Add(vm);
}
}
}
}
}
/// <summary>
/// 统一处理属性变更事件 => 设置硬件
/// </summary>
private void OnConfigPropertyChanged(object sender, PropertyChangedEventArgs e)
{
// 关键逻辑:如果是从硬件读取过程中,则忽略,不要反向设置回去
if (_isSyncingFromHardware) return;
ApplySettingToHardware(sender, e.PropertyName);
}
private void ApplySettingToHardware(object source, string propertyName)
{
// 1. 设置相机参数
if (source == CameraConfig)
{
// TODO: 替换为实际的 set 相机参数代码
/*
var camDevice = _hardwareManager.GetCamera(_currentCameraType);
if (propertyName == nameof(CameraConfig.ExposureTime))
{
camDevice.SetExposure(CameraConfig.ExposureTime);
}
else if (propertyName == nameof(CameraConfig.Gain))
{
camDevice.SetGain(CameraConfig.Gain);
}
*/
System.Diagnostics.Debug.WriteLine($"[Hardware Set] Cam: {_currentCameraType}, Prop: {propertyName}");
return;
}
// 2. 设置光源参数 (根据类型直接判断)
if (source is MapCamLightConfig mapConfig)
{
if (propertyName == nameof(MapCamLightConfig.RedLight))
{
// TODO: _hardwareManager.SetMapRedLight(mapConfig.RedLight);
System.Diagnostics.Debug.WriteLine($"[Hardware Set] MapCam Red: {mapConfig.RedLight}");
}
else if (propertyName == nameof(MapCamLightConfig.BlueLight))
{
// TODO: _hardwareManager.SetMapBlueLight(mapConfig.BlueLight);
System.Diagnostics.Debug.WriteLine($"[Hardware Set] MapCam Blue: {mapConfig.BlueLight}");
}
}
else if (source is UpCamLightConfig upConfig)
{
if (propertyName == nameof(UpCamLightConfig.PointRedLight))
{
// TODO: _hardwareManager.SetUpPointRed(upConfig.PointRedLight);
System.Diagnostics.Debug.WriteLine($"[Hardware Set] UpCam PointRed: {upConfig.PointRedLight}");
}
else if (propertyName == nameof(UpCamLightConfig.RingRedLight))
{
// TODO: ...
}
// ... 处理其他 UpCam 通道
}
else if (source is DownCamLightConfig downConfig)
{
if (propertyName == nameof(DownCamLightConfig.PointRedLight))
{
// TODO: ...
}
// ... 处理其他 DownCam 通道
}
}
/// <summary>
/// 从硬件读取当前值 => 更新 UI (不触发设置)
/// </summary>
private void ReadFromHardware()
{
try
{
_isSyncingFromHardware = true; // 开启静默模式
// 1. 读取相机实际参数
/*
var camDevice = _hardwareManager.GetCamera(_currentCameraType);
if (camDevice != null) {
CameraConfig.ExposureTime = (int)camDevice.CurrentExposure;
CameraConfig.Gain = (int)camDevice.CurrentGain;
}
*/
// 2. 读取光源实际参数
if (_currentLightConfig is MapCamLightConfig mapConfig)
{
// TODO: 读取实际硬件值
mapConfig.RedLight = _hardwareManager.GetMapRedLightIntensity();
mapConfig.BlueLight = _hardwareManager.GetMapBlueLightIntensity();
}
else if (_currentLightConfig is UpCamLightConfig upConfig)
{
upConfig.PointRedLight = _hardwareManager.GetUpPointRedLightIntensity();
upConfig.PointBlueLight=_hardwareManager.GetUpPointBlueLightIntensity();
upConfig.RingRedLight=_hardwareManager.GetUpRingRedLightIntensity();
upConfig.RingBlueLight=_hardwareManager.GetUpRingBlueLightIntensity();
upConfig.RedBackLight=_hardwareManager.GetUpRedBackLightIntensity();
// ...
}
else if (_currentLightConfig is DownCamLightConfig downConfig)
{
// downConfig.PointRedLight = ...
downConfig.PointRedLight = _hardwareManager.GetDownPointRedLightIntensity();
downConfig.PointBlueLight = _hardwareManager.GetDownPointBlueLightIntensity();
downConfig.RingRedLight = _hardwareManager.GetDownRingRedLightIntensity();
downConfig.RingBlueLight = _hardwareManager.GetDownRingBlueLightIntensity();
// ...
}
}
finally
{
foreach (var channel in LightChannels)
{
// 强制刷新 UI
channel.Refresh();
}
_isSyncingFromHardware = false; // 必须复位
}
}
private void SaveAndClose()
{
RequestClose(true);
}
}
}

View File

@@ -0,0 +1,28 @@
<UserControl x:Class="MainShell.Common.VisionTemple.View.VisionTempleView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MainShell.Common.VisionTemple.View" xmlns:control="http://www.maxwell.com/controls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<control:CameraVision DataContext="{Binding Service}" Name="cameraVision">
<control:CameraVision.CameraHost>
<control:CameraAxisControlA
Items="{Binding CameraModel.CameraShowViewModel.Items}"
Source="{Binding CameraModel.CameraShowViewModel.CurrentImage, Mode=OneWay}"
TabSelectedIndex="{Binding SelectCameraIndex}"
Cameras="{Binding Cameras}"
Device="{Binding SelectItem}"
ImportFile="{Binding CameraModel.ImportFile}"
Regions="{Binding CameraModel.CameraShowViewModel.Regions}"
IsClear="{Binding CameraModel.CameraShowViewModel.IsClear}"
IsShowContext="True"
ShapeThickness="1" IsShowSolidLine="True" DrawInConcurrency = "False"/>
</control:CameraVision.CameraHost>
</control:CameraVision>
</Grid>
</UserControl>

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace MainShell.Common.VisionTemple.View
{
/// <summary>
/// VisionTempleView.xaml 的交互逻辑
/// </summary>
public partial class VisionTempleView : UserControl
{
public VisionTempleView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,16 @@
<Window x:Class="MainShell.Common.VisionTemple.View.VisionTempleWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:view="clr-namespace:MainShell.Common.VisionTemple.View"
mc:Ignorable="d"
Title="{Binding DisplayName}"
Height="875"
Width="1000"
WindowStartupLocation="CenterOwner"
Background="White">
<Grid Background="White">
<view:VisionTempleView DataContext="{Binding VisionTemple}" />
</Grid>
</Window>

View File

@@ -0,0 +1,15 @@
using System.Windows;
namespace MainShell.Common.VisionTemple.View
{
/// <summary>
/// VisionTempleWindow.xaml 的交互逻辑
/// </summary>
public partial class VisionTempleWindow : Window
{
public VisionTempleWindow()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,32 @@
using MwFramework.Controls.PatternTemplate.ViewModel;
using Stylet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MainShell.Common.VisionTemple.ViewModel
{
public class VisionTempleViewModel : Screen
{
public string Name { get; set; } = "VisionTempleModel";
private MatchTemplateService _service;
public MatchTemplateService Service
{
get { return _service; }
set
{
_service = value;
OnPropertyChanged(nameof(Service));
}
}
public VisionTempleViewModel()
{
_service = new MatchTemplateService();
}
}
}

View File

@@ -0,0 +1,114 @@
using MainShell.Common.VisionTemple.View;
using MainShell.Hardware;
using Stylet;
using System.ComponentModel;
using System.Windows;
namespace MainShell.Common.VisionTemple.ViewModel
{
public class VisionTempleWindowViewModel : Screen
{
private readonly VisionTempleViewModel _visionTemple;
private VisionTempleWindow _window;
private bool _isShuttingDown;
private readonly HardwareManager _hardwareManager;
public VisionTempleWindowViewModel(HardwareManager hardwareManager)
{
DisplayName = "视觉模板制作";
_visionTemple = new VisionTempleViewModel();
_visionTemple.Service = new MwFramework.Controls.PatternTemplate.ViewModel.MatchTemplateService();
_visionTemple.Service.CameraModel.IsShowFoldDialog = false;
_hardwareManager = hardwareManager;
}
private string _templatePath;
/// <summary>
/// 模版路径
/// </summary>
public string TemplatePath
{
get { return _templatePath; }
set
{
_templatePath = value;
_visionTemple.Service.CameraModel.TemplatePath = value;
}
}
public VisionTempleViewModel VisionTemple
{
get
{
return _visionTemple;
}
}
public void SetCamera(CameraType cameraType)
{
switch (cameraType)
{
case CameraType.MapCamera:
_visionTemple.Service.Cameras = _hardwareManager.CameraAxisManager.BottomCameraAxisDevices;
break;
case CameraType.TopPositionCamera:
_visionTemple.Service.Cameras = _hardwareManager.CameraAxisManager.TopCameraAxisDevices;
break;
case CameraType.TopWideCamera:
_visionTemple.Service.Cameras = _hardwareManager.CameraAxisManager.WideCameraAxisDevices;
break;
default:
break;
}
if(_visionTemple.Service.Cameras!=null&& _visionTemple.Service.Cameras.Count>0)
{
_visionTemple.Service.SelectItem = _visionTemple.Service.Cameras[0];
}
}
public void ShowWindow()
{
if (_window == null)
{
_window = new VisionTempleWindow();
_window.DataContext = this;
_window.Closing += OnWindowClosing;
}
Window owner = Application.Current != null ? Application.Current.MainWindow : null;
if (owner != null && _window.Owner == null)
{
_window.Owner = owner;
owner.Closing += OnOwnerClosing;
}
if (_window.IsVisible)
{
if (_window.WindowState == WindowState.Minimized)
{
_window.WindowState = WindowState.Normal;
}
_window.Activate();
return;
}
_window.Show();
_window.Activate();
}
private void OnWindowClosing(object sender, CancelEventArgs e)
{
if (!_isShuttingDown)
{
e.Cancel = true;
_window.Hide();
}
}
private void OnOwnerClosing(object sender, CancelEventArgs e)
{
_isShuttingDown = true;
}
}
}

View File

@@ -0,0 +1,40 @@
using System.Windows;
namespace MainShell.Common
{
public class WindowService
{
// 定义一个名为 DialogResult 的附加属性
public static readonly DependencyProperty DialogResultProperty =
DependencyProperty.RegisterAttached(
"DialogResult",
typeof(bool?),
typeof(WindowService),
new PropertyMetadata(DialogResultChanged)); // 当此属性值改变时,调用 DialogResultChanged 方法
// 提供 Set 方法供外部设置附加属性的值
public static void SetDialogResult(UIElement element, bool? value)
{
element.SetValue(DialogResultProperty, value);
}
// 提供 Get 方法供外部获取附加属性的值
public static bool? GetDialogResult(UIElement element)
{
return (bool?)element.GetValue(DialogResultProperty);
}
// 当 DialogResult 附加属性的值改变时调用的回调方法
private static void DialogResultChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// 确保附加属性应用在一个 Window 控件上,并且新的值是 bool 类型
if (d is Window window && e.NewValue is bool result)
{
// 设置窗口的 DialogResult
window.DialogResult = result;
// 关闭窗口
window.Close();
}
}
}
}

View File

@@ -0,0 +1,234 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MainShell.Common
{
public static class WorkflowContextKeys
{
/// <summary>
/// 用于传递 IEventAggregator 实例
/// </summary>
public const string EventAggregator = "EventAggregator";
/// <summary>
/// 用于传递请求令牌 (Guid)
/// </summary>
public const string RequestToken = "RequestToken";
/// <summary>
/// 当前配方
/// </summary>
public const string RecipeManager = "RecipeManager";
/// <summary>
/// 流程结果管理器 Key
/// </summary>
public const string ProcessResultManager = "ProcessResultManager";
/// <summary>
/// 恢复目标活动名称
/// </summary>
public const string ResumeTargetActivityName="ResumeTargetActivityName";
/// <summary>
/// 流程名称
/// </summary>
public const string WorkflowName = "WorkflowName";
/// <summary>
/// 当前步骤ID
/// </summary>
public const string CurrentStepId = "CurrentStepId";
/// <summary>
/// 下一步骤ID
/// </summary>
public const string NextStepId = "NextStepId";
/// <summary>
/// 流程路由配置
/// </summary>
public const string WorkflowRoutes = "WorkflowRoutes";
/// <summary>
/// 晶片转移路由
/// </summary>
public const string DieTransferRoute = "DieTransferRoute";
/// <summary>
/// 自动生产路由
/// </summary>
public const string AutoProductionRoute = "AutoProductionRoute";
/// <summary>
/// 流程运行时追踪器
/// </summary>
public const string WorkflowRuntimeTracker = "WorkflowRuntimeTracker";
/// <summary>
/// 流程失败消息
/// </summary>
public const string WorkflowFailureMessage = "WorkflowFailureMessage";
/// <summary>
/// 流程失败消息键
/// </summary>
public const string WorkflowFailureMessageKey = "WorkflowFailureMessageKey";
/// <summary>
/// 流程失败消息参数
/// </summary>
public const string WorkflowFailureMessageArguments = "WorkflowFailureMessageArguments";
/// <summary>
/// 准备区服务
/// </summary>
public const string PreparationAreaService = "PreparationAreaService";
/// <summary>
/// 当前晶片状态服务
/// </summary>
public const string CurrentChipStateService = "CurrentChipStateService";
/// <summary>
/// 自动生产运行时状态服务
/// </summary>
public const string AutoProductionRuntimeStateService = "AutoProductionRuntimeStateService";
/// <summary>
/// 准备区状态
/// </summary>
public const string PreparationAreaStatus = "PreparationAreaStatus";
/// <summary>
/// 当前晶片状态
/// </summary>
public const string CurrentChipState = "CurrentChipState";
/// <summary>
/// 基板处理状态
/// </summary>
public const string SubstrateProcessState = "SubstrateProcessState";
/// <summary>
/// 待加载晶片
/// </summary>
public const string PendingChipLoad = "PendingChipLoad";
/// <summary>
/// 当前基板待处理数量
/// </summary>
public const string CurrentSubstratePendingCount = "CurrentSubstratePendingCount";
/// <summary>
/// 当前基板已处理数量
/// </summary>
public const string CurrentSubstrateProcessedCount = "CurrentSubstrateProcessedCount";
/// <summary>
/// 当前晶片剩余数量
/// </summary>
public const string CurrentChipRemainingCount = "CurrentChipRemainingCount";
/// <summary>
/// 转移需要重新检查
/// </summary>
public const string TransferNeedsRecheck = "TransferNeedsRecheck";
/// <summary>
/// 转移晶片已耗尽
/// </summary>
public const string TransferChipExhausted = "TransferChipExhausted";
/// <summary>
/// 晶片转移决策结果
/// </summary>
public const string DieTransferDecisionResult = "DieTransferDecisionResult";
/// <summary>
/// 晶片转移路径生成请求
/// </summary>
public const string DieTransferPathRequest = "DieTransferPathRequest";
/// <summary>
/// 晶片转移路径生成结果
/// </summary>
public const string DieTransferPathPlan = "DieTransferPathPlan";
/// <summary>
/// 当前父级活动/子流程名称
/// </summary>
public const string ParentActivityName = "ParentActivityName";
/// <summary>
/// 针头Z对刀次数
/// </summary>
public const string NeedleZCalibrationTouchCount = "NeedleZCalibrationTouchCount";
/// <summary>
/// 针头Z对刀完成后是否自动抬高
/// </summary>
public const string NeedleZCalibrationAutoRaiseZ1 = "NeedleZCalibrationAutoRaiseZ1";
/// <summary>
/// 针头Z对刀取消令牌
/// </summary>
public const string NeedleZCalibrationCancellationToken = "NeedleZCalibrationCancellationToken";
/// <summary>
/// 针头Z对刀工作流请求数据
/// </summary>
public const string NeedleZCalibrationWorkflowData = "NeedleZCalibrationWorkflowData";
/// <summary>
/// 针头Z对刀结果集合
/// </summary>
public const string NeedleZCalibrationResults = "NeedleZCalibrationResults";
/// <summary>
/// 针头Z对刀最后一次结果
/// </summary>
public const string NeedleZCalibrationLastResult = "NeedleZCalibrationLastResult";
/// <summary>
/// 针头Z对刀平均结果
/// </summary>
public const string NeedleZCalibrationAverageResult = "NeedleZCalibrationAverageResult";
/// <summary>
/// 基板定位结果
/// </summary>
public const string SubstratePositionResult = "SubstratePositionResult";
/// <summary>
/// 芯片定位结果
/// </summary>
public const string DiePositionResult = "DiePositionResult";
/// <summary>
/// 芯片定位运行态上下文
/// </summary>
public const string DiePositionContext = "DiePositionContext";
/// <summary>
/// 芯片定位扫描规划结果
/// </summary>
public const string DiePositionScanPlan = "DiePositionScanPlan";
/// <summary>
/// 基板测高结果
/// </summary>
public const string SubstrateHeightMeasureResult = "SubstrateHeightMeasureResult";
/// <summary>
/// 精度复检结果
/// </summary>
public const string DieRecheckResult = "DieRecheckResult";
/// <summary>
/// 基板Mark识别服务
/// </summary>
public const string SubstrateMarkRecognitionService = "SubstrateMarkRecognitionService";
}
}

View File

@@ -0,0 +1,581 @@
<?xml version="1.0"?>
<ArrayOfPersistenceObject xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<PersistenceObject xsi:type="AxisCardPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>AcsCard</CategoryName>
<ID>2d23c400-ccf2-469a-add5-ae92a98a85e6</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardPO.xml</ConfigPath>
<AxisCardType>DEMO</AxisCardType>
<AxisCardNum>0</AxisCardNum>
<PortNo>0</PortNo>
<ListAxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-X1</CategoryName>
<ID>3a9c772b-4a9c-4077-abbc-80fc038b81ee</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>AcsCard</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>0</AxisNum>
<AxisName>PHS-X1</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-X2</CategoryName>
<ID>c83e5f81-ef2c-413c-ace9-24bc97c30b32</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>AcsCard</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>1</AxisNum>
<AxisName>PHS-X2</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>WS-X3</CategoryName>
<ID>e0a2d6ed-2972-4595-a8dc-53a504187a9f</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>AcsCard</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>4</AxisNum>
<AxisName>WS-X3</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Y1</CategoryName>
<ID>4e145d2a-f7f7-4ce2-a5b0-919375a03d87</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>AcsCard</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>2</AxisNum>
<AxisName>PHS-Y1</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>WS-R</CategoryName>
<ID>cebe7f5c-8cdd-47e8-906a-6083047a078d</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>AcsCard</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>6</AxisNum>
<AxisName>WS-R</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>SZ</CategoryName>
<ID>ce1f8f65-3409-4124-9c9a-ba750c848e36</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>AcsCard</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>8</AxisNum>
<AxisName>SZ</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-Y3</CategoryName>
<ID>05dfa6d1-401b-4a55-808b-5af2efeb358c</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>AcsCard</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>7</AxisNum>
<AxisName>Stage-Y3</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
</ListAxisCardParaPO>
<Version>1</Version>
<Core>0</Core>
<CrossCompensate>0</CrossCompensate>
<IsServoSeparate>false</IsServoSeparate>
</PersistenceObject>
<PersistenceObject xsi:type="AxisCardPO">
<AlarmOffset>0</AlarmOffset>
<CategoryName>Plc</CategoryName>
<ID>80a2e320-d4da-46a6-9f35-0a6d0996ea22</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardPO.xml</ConfigPath>
<AxisCardType>DEMO</AxisCardType>
<AxisCardNum>0</AxisCardNum>
<PortNo>0</PortNo>
<ListAxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Z1</CategoryName>
<ID>471e0395-0918-4e0b-b9cb-d0727281ef6c</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>0</AxisNum>
<AxisName>PHS-Z1</AxisName>
<Direction>Z</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Z3</CategoryName>
<ID>5dd115ab-09a4-4bbb-9fdf-e9b76cc5e88e</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>1</AxisNum>
<AxisName>PHS-Z3</AxisName>
<Direction>Z</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Z4</CategoryName>
<ID>e359bc21-c1e8-4e06-acdb-1df94ee7931b</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>10</AxisNum>
<AxisName>PHS-Z4</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Z5</CategoryName>
<ID>9d948211-59ae-498c-b124-531a69855752</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>2</AxisNum>
<AxisName>PHS-Z5</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>PHS-Z6</CategoryName>
<ID>477c569a-e460-4c45-917f-a0744ebed5ec</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>11</AxisNum>
<AxisName>PHS-Z6</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-Z7</CategoryName>
<ID>f761791c-8fb4-4a5b-8fef-0380e996e81f</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>7</AxisNum>
<AxisName>Stage-Z7</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-Z8</CategoryName>
<ID>28a1caa3-01bc-48ed-8551-68829b280a6f</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>8</AxisNum>
<AxisName>Stage-Z8</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-Z9</CategoryName>
<ID>71c8587a-1e85-4fa4-8809-14f00111a230</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>9</AxisNum>
<AxisName>Stage-Z9</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-Z10</CategoryName>
<ID>fc66c8d2-c35f-46b5-9c14-f3a017311e86</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>14</AxisNum>
<AxisName>Stage-Z10</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-CV-Y4</CategoryName>
<ID>6ebf862a-c91e-4bb2-a5b7-e67f307333b4</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>15</AxisNum>
<AxisName>Stage-CV-Y4</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>Stage-CV-Y5</CategoryName>
<ID>e1cf2e06-fe51-4115-8ad2-2a0b3dc53c00</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>16</AxisNum>
<AxisName>Stage-CV-Y5</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>WEU-Z11</CategoryName>
<ID>a765e366-03a3-451f-ab44-1e6129a6ac61</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>3</AxisNum>
<AxisName>WEU-Z11</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>WEU-Z12</CategoryName>
<ID>a4c43082-6841-45b4-83f2-b89a952a6547</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>4</AxisNum>
<AxisName>WEU-Z12</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>WEU-Y6</CategoryName>
<ID>670409e3-1e19-45c8-94b8-1f3fb1905dc2</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>5</AxisNum>
<AxisName>WEU-Y6</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>CV-Z13</CategoryName>
<ID>eb009565-40bf-4923-9b9b-fdf483dc1532</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>6</AxisNum>
<AxisName>CV-Z13</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>CV-Y7</CategoryName>
<ID>d75ee50a-ba99-4ec1-bb36-6e65cbd84180</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>18</AxisNum>
<AxisName>CV-Y7</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>CV-Y8</CategoryName>
<ID>8845c4e8-4d09-4f0a-b073-1b29e1ca59e6</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>19</AxisNum>
<AxisName>CV-Y8</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>CV-Y9</CategoryName>
<ID>4970be79-b46a-4004-84bf-82e922fb5cb8</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>20</AxisNum>
<AxisName>CV-Y9</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
<AxisCardParaPO>
<AlarmOffset>0</AlarmOffset>
<CategoryName>CV-Y10</CategoryName>
<ID>36583278-40bd-48ad-a749-02b4e58dcbca</ID>
<EnableLog>false</EnableLog>
<ConfigPath>AxisCardParaPO.xml</ConfigPath>
<AxisCardId>0</AxisCardId>
<AxisCardName>Plc</AxisCardName>
<AxisCardNum>0</AxisCardNum>
<AxisNum>21</AxisNum>
<AxisName>CV-Y10</AxisName>
<Direction>X</Direction>
<GoogalCore>0</GoogalCore>
<GoogalAxisNum>0</GoogalAxisNum>
<GoolgalPosErr>0</GoolgalPosErr>
<HomeDir>0</HomeDir>
<EscapeStep>0</EscapeStep>
<HomeMode>HOME_MODE_ERROR</HomeMode>
<HomeCheck>false</HomeCheck>
<MaxCheckPos>0.001</MaxCheckPos>
</AxisCardParaPO>
</ListAxisCardParaPO>
<Version>1</Version>
<Core>0</Core>
<CrossCompensate>0</CrossCompensate>
<IsServoSeparate>false</IsServoSeparate>
</PersistenceObject>
</ArrayOfPersistenceObject>

View File

@@ -0,0 +1,9 @@
# 气缸定义表
# 列顺序Name,Module,ControlType,ExtendOutputIds,RetractOutputIds,ExtendedFeedbackIds,RetractedFeedbackIds,Description
# ControlType: SingleOutput / DualOutput / MultiOutput
# ExtendOutputIds / RetractOutputIds / ExtendedFeedbackIds / RetractedFeedbackIds 支持填写多个 IO 引用,使用分号分隔
# IO 引用优先使用 Configuration\DeviceIoPoints.csv 中的 Name若 Id 在全表唯一,也兼容旧 Id 写法
Name,Module,ControlType,ExtendOutputIds,RetractOutputIds,ExtendedFeedbackIds,RetractedFeedbackIds,Description
WS θ夹紧气缸,WS,SingleOutput,PG.WS.ThetaClampCylAct,,PG.WS.ThetaClampCyl1WorkPos;PG.WS.ThetaClampCyl2WorkPos;PG.WS.ThetaClampCyl3WorkPos;PG.WS.ThetaClampCyl4WorkPos,PG.WS.ThetaClampCyl1HomePos;PG.WS.ThetaClampCyl2HomePos;PG.WS.ThetaClampCyl3HomePos;PG.WS.ThetaClampCyl4HomePos,WS θ 夹紧气缸总动作输出,对应 4 组伸出/缩回反馈
WS θ刹车压紧气缸,WS,SingleOutput,PG.WS.ThetaBrakePressCylAct,,,,当前 DeviceIoPoints.csv 未配置到位反馈
Stage 顶升同步气缸,Stage,MultiOutput,PG.Stage.LifterCyl1Act;PG.Stage.LifterCyl2Act,,PG.Stage.LifterCyl1WorkPos;PG.Stage.LifterCyl2WorkPos,PG.Stage.LifterCyl1HomePos;PG.Stage.LifterCyl2HomePos,Stage 顶升气缸1和2同步动作统一伸出/缩回
1 # 气缸定义表
2 # 列顺序:Name,Module,ControlType,ExtendOutputIds,RetractOutputIds,ExtendedFeedbackIds,RetractedFeedbackIds,Description
3 # ControlType: SingleOutput / DualOutput / MultiOutput
4 # ExtendOutputIds / RetractOutputIds / ExtendedFeedbackIds / RetractedFeedbackIds 支持填写多个 IO 引用,使用分号分隔
5 # IO 引用优先使用 Configuration\DeviceIoPoints.csv 中的 Name;若 Id 在全表唯一,也兼容旧 Id 写法
6 Name,Module,ControlType,ExtendOutputIds,RetractOutputIds,ExtendedFeedbackIds,RetractedFeedbackIds,Description
7 WS θ夹紧气缸,WS,SingleOutput,PG.WS.ThetaClampCylAct,,PG.WS.ThetaClampCyl1WorkPos;PG.WS.ThetaClampCyl2WorkPos;PG.WS.ThetaClampCyl3WorkPos;PG.WS.ThetaClampCyl4WorkPos,PG.WS.ThetaClampCyl1HomePos;PG.WS.ThetaClampCyl2HomePos;PG.WS.ThetaClampCyl3HomePos;PG.WS.ThetaClampCyl4HomePos,WS θ 夹紧气缸总动作输出,对应 4 组伸出/缩回反馈
8 WS θ刹车压紧气缸,WS,SingleOutput,PG.WS.ThetaBrakePressCylAct,,,,当前 DeviceIoPoints.csv 未配置到位反馈
9 Stage 顶升同步气缸,Stage,MultiOutput,PG.Stage.LifterCyl1Act;PG.Stage.LifterCyl2Act,,PG.Stage.LifterCyl1WorkPos;PG.Stage.LifterCyl2WorkPos,PG.Stage.LifterCyl1HomePos;PG.Stage.LifterCyl2HomePos,Stage 顶升气缸1和2同步动作,统一伸出/缩回

View File

@@ -0,0 +1,97 @@
# Device IO 定义表
# 列顺序Id Module Name Type Card StationNo LineNo Enabled DefaultValue IsInverse Description
# Module: 业务模块名(如 SubstrateLoad/ChipLoad/SubstrateOut/ChipUnload
# Type: Input/Output (也支持 IN/OUT/DI/DO)
# Card: Td/Acs
# StationNo: 台达站号
# LineNo: 实际接线线标/号码管标识
# Enabled: 1/0 或 true/false
# DefaultValue: 当 IO 未启用或无法读取时使用的默认状态1/0 或 true/false
Id,Module,Name,Type,Card,StationNo,LineNo,Enabled,DefaultValue,IsInverse,Description
0,WZ,PG.WZ.StartButton,Input,Td,1,X00100,1,1,0,WZ 启动按钮
1,WZ,PG.WZ.StopButton,Input,Td,1,X00101,1,1,0,WZ 停止按钮
2,WZ,PG.WZ.ResetButton,Input,Td,1,X00102,1,1,0,WZ 复位按钮
3,WZ,PG.WZ.EmergencyStopButton,Input,Td,1,X00103,1,1,0,WZ 急停按钮
4,WZ,PG.WZ.BlueButton,Input,Td,1,X00104,1,1,0,WZ 蓝色按钮(预留)
5,Stage,PG.Stage.ToolSetterSignal,Input,Td,1,X00105,1,1,0,Stage 对刀信号
6,Stage,PG.Stage.SubstrateInPlace,Input,Td,1,X00106,1,1,0,Stage 基板到位感应
7,Stage,PG.Stage.LifterCyl1WorkPos,Input,Td,1,X00107,1,1,0,Stage 顶升气缸1动点
8,Stage,PG.Stage.LifterCyl1HomePos,Input,Td,1,X00108,1,1,0,Stage 顶升气缸1原点
9,Stage,PG.Stage.LifterCyl2WorkPos,Input,Td,1,X00109,1,1,0,Stage 顶升气缸2动点
10,Stage,PG.Stage.LifterCyl2HomePos,Input,Td,1,X00110,1,1,0,Stage 顶升气缸2原点
11,WS,PG.WS.ThetaClampCyl1WorkPos,Input,Td,1,X00111,1,1,0,WS θ夹紧气缸1动点
12,WS,PG.WS.ThetaClampCyl1HomePos,Input,Td,1,X00112,1,1,0,WS θ夹紧气缸1原点
13,WS,PG.WS.ThetaClampCyl2WorkPos,Input,Td,1,X00113,1,1,0,WS θ夹紧气缸2动点
14,WS,PG.WS.ThetaClampCyl2HomePos,Input,Td,1,X00114,1,1,0,WS θ夹紧气缸2原点
15,WS,PG.WS.ThetaClampCyl3WorkPos,Input,Td,1,X00115,1,1,0,WS θ夹紧气缸3动点
0,WS,PG.WS.ThetaClampCyl3HomePos,Input,Td,2,X00200,1,1,0,WS θ夹紧气缸3原点
1,WS,PG.WS.ThetaClampCyl4WorkPos,Input,Td,2,X00201,1,1,0,WS θ夹紧气缸4动点
2,WS,PG.WS.ThetaClampCyl4HomePos,Input,Td,2,X00202,1,1,0,WS θ夹紧气缸4原点
3,WS,PG.WS.ThetaTrayPresentSensor1,Input,Td,2,X00203,1,1,0,WS θ料盘有无感应1
4,WS,PG.WS.ThetaTrayPresentSensor2,Input,Td,2,X00204,1,1,0,WS θ料盘有无感应2
5,WS,PG.WS.ThetaTrayPresentSensor3,Input,Td,2,X00205,1,1,0,WS θ料盘有无感应3
6,WS,PG.WS.ThetaTrayPresentSensor4,Input,Td,2,X00206,1,1,0,WS θ料盘有无感应4
7,WS,PG.WS.BondHead1InPlace,Input,Td,2,X00207,1,1,0,WS 刺晶头1在位
8,WS,PG.WS.BondHead2InPlace,Input,Td,2,X00208,1,1,0,WS 刺晶头2在位
9,WS,PG.WS.BondHead3InPlace,Input,Td,2,X00209,1,1,0,WS 刺晶头3在位
10,WS,PG.WS.BondHead4InPlace,Input,Td,2,X00210,1,1,0,WS 刺晶头4在位
11,WEU,PG.WEU.Z11MaterialSensor1,Input,Td,2,X00211,1,1,0,WEU Z11 有无料感应1
12,WEU,PG.WEU.Z11MaterialSensor2,Input,Td,2,X00212,1,1,0,WEU Z11 有无料感应2
13,WEU,PG.WEU.Z12MaterialSensor3,Input,Td,2,X00213,1,1,0,WEU Z12 有无料感应3
14,WEU,PG.WEU.Z12MaterialSensor4,Input,Td,2,X00214,1,1,0,WEU Z12 有无料感应4
0,CV,PG.CV.UpperInletSensor,Input,Td,3,X00300,1,1,0,CV 上层进料感应
1,CV,PG.CV.UpperInPlaceSensor,Input,Td,3,X00301,1,1,0,CV 上层到位感应
2,CV,PG.CV.LowerOutletSensor,Input,Td,3,X00302,1,1,0,CV 下层出料感应
3,CV,PG.CV.LowerInPlaceSensor,Input,Td,3,X00303,1,1,0,CV 下层到位感应
4,WZ,PG.WZ.SafetyDoor1Closed,Input,Td,3,X00304,1,1,0,WZ 安全门1关门检测
5,WZ,PG.WZ.SafetyDoor2Closed,Input,Td,3,X00305,1,1,0,WZ 安全门2关门检测
6,WZ,PG.WZ.SafetyDoor3Closed,Input,Td,3,X00306,1,1,0,WZ 安全门3关门检测
7,WZ,PG.WZ.SafetyDoor4Closed,Input,Td,3,X00307,1,1,0,WZ 安全门4关门检测
8,WZ,PG.WZ.SecurityDoorShield,Input,Td,3,X00308,1,1,0,WZ 安全门屏蔽
10,General,PG.General.PhaseLossSensor,Input,Td,3,X00310,1,1,0,缺相检测
11,General,PG.General.SafetyCircuitStatus1,Input,Td,3,X00311,1,1,0,安全回路状态1
12,General,PG.General.SafetyCircuitStatus2,Input,Td,3,X00312,1,1,0,安全回路状态2
13,CV,PG.CV.IonWindRodAlarmDetection,Input,Td,3,X00313,1,1,0,CV 离子风棒报警检测
14,EFEM,PG.EFEM.IonWindRodAlarmDetection1,Input,Td,3,X00314,1,1,0,EFEM离子风棒报警检测1
15,EFEM,PG.EFEM.IonWindRodAlarmDetection2,Input,Td,3,X00315,1,1,0,EFEM离子风棒报警检测2
0,AxisZ,PG.AxisZ.Z1GuideRailBrake,Output,Td,4,Y00100,1,1,0,Z1轴导轨抱闸
1,AxisZ,PG.AxisZ.Z3CameraAirCooling,Output,Td,4,Y00101,1,1,0,Z3相机气冷
2,AxisZ,PG.AxisZ.Z5CameraAirCooling,Output,Td,4,Y00102,1,1,0,Z5相机气冷
3,AxisZ,PG.AxisZ.Z10CameraAirCooling,Output,Td,4,Y00103,1,1,0,Z10相机气冷
4,AxisZ,PG.AxisZ.Z2BondHeadAirCooling,Output,Td,4,Y00104,1,1,0,Z2刺晶头气冷
5,CV,PG.CV.IonBarAct,Output,Td,4,Y00105,1,1,0,CV 离子风棒
6,WEU,PG.WEU.IonBarAct1,Output,Td,4,Y00106,1,1,0,WEU离子风棒1
7,WEU,PG.WEU.IonBarAct2,Output,Td,4,Y00107,1,1,0,WEU离子风棒2
8,WS,PG.WS.ThetaClampCylAct,Output,Td,4,Y00108,1,1,0,WS θ 夹紧气缸动作
9,WS,PG.WS.ThetaBrakePressCylAct,Output,Td,4,Y00109,1,1,0,WS θ 刹车压紧气缸动作
10,Stage,PG.Stage.LifterCyl1Act,Output,Td,4,Y00110,1,1,0,Stage 顶升气缸1动作
11,Stage,PG.Stage.LifterCyl2Act,Output,Td,4,Y00111,1,1,0,Stage 顶升气缸2动作
0,WZ,PG.WZ.StartButtonLight,Output,Td,5,Y00200,1,1,0,WZ 启动按钮灯
1,WZ,PG.WZ.StopButtonLight,Output,Td,5,Y00201,1,1,0,WZ 停止按钮灯
2,WZ,PG.WZ.ResetButtonLight,Output,Td,5,Y00202,1,1,0,WZ 复位按钮灯
3,WZ,PG.WZ.BlueButtonLight,Output,Td,5,Y00203,1,1,0,WZ 蓝色按钮灯
4,WZ,PG.WZ.WorkLight1,Output,Td,5,Y00204,1,1,0,WZ 照明灯1
6,EFEM,PG.EFEM.WorkLight1,Output,Td,5,Y00206,1,1,0,EFEM 照明灯1
8,WZ,PG.WZ.StackLightRed,Output,Td,5,Y00208,1,1,0,WZ 四色灯-红
9,WZ,PG.WZ.StackLightYellow,Output,Td,5,Y00209,1,1,0,WZ 四色灯-黄
10,WZ,PG.WZ.StackLightGreen,Output,Td,5,Y00210,1,1,0,WZ 四色灯-绿
11,WZ,PG.WZ.StackLightBlue,Output,Td,5,Y00211,1,1,0,WZ 四色灯-蓝
12,WZ,PG.WZ.BuzzerAct,Output,Td,5,Y00212,1,1,0,WZ 蜂鸣器
0,Stage,PG.Stage.BreakingTheVacuum1,Output,Td,6,Y00300,1,1,0,Stage 破真空1
1,Stage,PG.Stage.BreakingTheVacuum2,Output,Td,6,Y00301,1,1,0,STAGE 破真空2
2,Stage,PG.Stage.BreakingTheVacuum3,Output,Td,6,Y00302,1,1,0,STAGE 破真空3
3,Stage,PG.Stage.BreakingTheVacuum4,Output,Td,6,Y00303,1,1,0,STAGE 破真空4
4,WEU,PG.WEU.TrayBreakVacuum1,Output,Td,6,Y00304,1,1,0,WEU 料盘破真空1
5,WEU,PG.WEU.TrayBreakVacuum2,Output,Td,6,Y00305,1,1,0,WEU 料盘破真空2
6,AxisZ,PG.AxisZ.Z2BondHeadBreakVacuum,Output,Td,6,Y00306,1,1,0,PHS Z2 刺晶头破真空
7,Stage,PG.Stage.Vacuum1,Output,Td,6,Y00307,1,1,0,STAGE 吸真空1
8,Stage,PG.Stage.Vacuum2,Output,Td,6,Y00308,1,1,0,STAGE 吸真空2
9,Stage,PG.Stage.Vacuum3,Output,Td,6,Y00309,1,1,0,STAGE 吸真空3
10,Stage,PG.Stage.Vacuum4,Output,Td,6,Y00310,1,1,0,STAGE 吸真空4
11,WEU,PG.WEU.TrayVacuum1,Output,Td,6,Y00311,1,1,0,WEU 料盘吸真空1
12,WEU,PG.WEU.TrayVacuum2,Output,Td,6,Y00312,1,1,0,WEU 料盘吸真空2
13,AxisZ,PG.AxisZ.Z2BondHeadVacuum,Output,Td,6,Y00313,1,1,0,PHS Z2 刺晶头吸真空
1,WZ,PG.WZ.SafetyDoor1Open,Output,Td,7,Y00401,1,1,0,WZ 安全门1打开
2,WZ,PG.WZ.SafetyDoor2Open,Output,Td,7,Y00402,1,1,0,WZ 安全门2打开
3,WZ,PG.WZ.SafetyDoor3Open,Output,Td,7,Y00402,1,1,0,WZ 安全门3打开
4,WZ,PG.WZ.SafetyDoor4Open,Output,Td,7,Y00403,1,1,0,WZ 安全门4打开
1 # Device IO 定义表
2 # 列顺序:Id Module Name Type Card StationNo LineNo Enabled DefaultValue IsInverse Description
3 # Module: 业务模块名(如 SubstrateLoad/ChipLoad/SubstrateOut/ChipUnload)
4 # Type: Input/Output (也支持 IN/OUT/DI/DO)
5 # Card: Td/Acs
6 # StationNo: 台达站号
7 # LineNo: 实际接线线标/号码管标识
8 # Enabled: 1/0 或 true/false
9 # DefaultValue: 当 IO 未启用或无法读取时使用的默认状态,1/0 或 true/false
10 Id,Module,Name,Type,Card,StationNo,LineNo,Enabled,DefaultValue,IsInverse,Description
11 0,WZ,PG.WZ.StartButton,Input,Td,1,X00100,1,1,0,WZ 启动按钮
12 1,WZ,PG.WZ.StopButton,Input,Td,1,X00101,1,1,0,WZ 停止按钮
13 2,WZ,PG.WZ.ResetButton,Input,Td,1,X00102,1,1,0,WZ 复位按钮
14 3,WZ,PG.WZ.EmergencyStopButton,Input,Td,1,X00103,1,1,0,WZ 急停按钮
15 4,WZ,PG.WZ.BlueButton,Input,Td,1,X00104,1,1,0,WZ 蓝色按钮(预留)
16 5,Stage,PG.Stage.ToolSetterSignal,Input,Td,1,X00105,1,1,0,Stage 对刀信号
17 6,Stage,PG.Stage.SubstrateInPlace,Input,Td,1,X00106,1,1,0,Stage 基板到位感应
18 7,Stage,PG.Stage.LifterCyl1WorkPos,Input,Td,1,X00107,1,1,0,Stage 顶升气缸1动点
19 8,Stage,PG.Stage.LifterCyl1HomePos,Input,Td,1,X00108,1,1,0,Stage 顶升气缸1原点
20 9,Stage,PG.Stage.LifterCyl2WorkPos,Input,Td,1,X00109,1,1,0,Stage 顶升气缸2动点
21 10,Stage,PG.Stage.LifterCyl2HomePos,Input,Td,1,X00110,1,1,0,Stage 顶升气缸2原点
22 11,WS,PG.WS.ThetaClampCyl1WorkPos,Input,Td,1,X00111,1,1,0,WS θ夹紧气缸1动点
23 12,WS,PG.WS.ThetaClampCyl1HomePos,Input,Td,1,X00112,1,1,0,WS θ夹紧气缸1原点
24 13,WS,PG.WS.ThetaClampCyl2WorkPos,Input,Td,1,X00113,1,1,0,WS θ夹紧气缸2动点
25 14,WS,PG.WS.ThetaClampCyl2HomePos,Input,Td,1,X00114,1,1,0,WS θ夹紧气缸2原点
26 15,WS,PG.WS.ThetaClampCyl3WorkPos,Input,Td,1,X00115,1,1,0,WS θ夹紧气缸3动点
27 0,WS,PG.WS.ThetaClampCyl3HomePos,Input,Td,2,X00200,1,1,0,WS θ夹紧气缸3原点
28 1,WS,PG.WS.ThetaClampCyl4WorkPos,Input,Td,2,X00201,1,1,0,WS θ夹紧气缸4动点
29 2,WS,PG.WS.ThetaClampCyl4HomePos,Input,Td,2,X00202,1,1,0,WS θ夹紧气缸4原点
30 3,WS,PG.WS.ThetaTrayPresentSensor1,Input,Td,2,X00203,1,1,0,WS θ料盘有无感应1
31 4,WS,PG.WS.ThetaTrayPresentSensor2,Input,Td,2,X00204,1,1,0,WS θ料盘有无感应2
32 5,WS,PG.WS.ThetaTrayPresentSensor3,Input,Td,2,X00205,1,1,0,WS θ料盘有无感应3
33 6,WS,PG.WS.ThetaTrayPresentSensor4,Input,Td,2,X00206,1,1,0,WS θ料盘有无感应4
34 7,WS,PG.WS.BondHead1InPlace,Input,Td,2,X00207,1,1,0,WS 刺晶头1在位
35 8,WS,PG.WS.BondHead2InPlace,Input,Td,2,X00208,1,1,0,WS 刺晶头2在位
36 9,WS,PG.WS.BondHead3InPlace,Input,Td,2,X00209,1,1,0,WS 刺晶头3在位
37 10,WS,PG.WS.BondHead4InPlace,Input,Td,2,X00210,1,1,0,WS 刺晶头4在位
38 11,WEU,PG.WEU.Z11MaterialSensor1,Input,Td,2,X00211,1,1,0,WEU Z11 有无料感应1
39 12,WEU,PG.WEU.Z11MaterialSensor2,Input,Td,2,X00212,1,1,0,WEU Z11 有无料感应2
40 13,WEU,PG.WEU.Z12MaterialSensor3,Input,Td,2,X00213,1,1,0,WEU Z12 有无料感应3
41 14,WEU,PG.WEU.Z12MaterialSensor4,Input,Td,2,X00214,1,1,0,WEU Z12 有无料感应4
42 0,CV,PG.CV.UpperInletSensor,Input,Td,3,X00300,1,1,0,CV 上层进料感应
43 1,CV,PG.CV.UpperInPlaceSensor,Input,Td,3,X00301,1,1,0,CV 上层到位感应
44 2,CV,PG.CV.LowerOutletSensor,Input,Td,3,X00302,1,1,0,CV 下层出料感应
45 3,CV,PG.CV.LowerInPlaceSensor,Input,Td,3,X00303,1,1,0,CV 下层到位感应
46 4,WZ,PG.WZ.SafetyDoor1Closed,Input,Td,3,X00304,1,1,0,WZ 安全门1关门检测
47 5,WZ,PG.WZ.SafetyDoor2Closed,Input,Td,3,X00305,1,1,0,WZ 安全门2关门检测
48 6,WZ,PG.WZ.SafetyDoor3Closed,Input,Td,3,X00306,1,1,0,WZ 安全门3关门检测
49 7,WZ,PG.WZ.SafetyDoor4Closed,Input,Td,3,X00307,1,1,0,WZ 安全门4关门检测
50 8,WZ,PG.WZ.SecurityDoorShield,Input,Td,3,X00308,1,1,0,WZ 安全门屏蔽
51 10,General,PG.General.PhaseLossSensor,Input,Td,3,X00310,1,1,0,缺相检测
52 11,General,PG.General.SafetyCircuitStatus1,Input,Td,3,X00311,1,1,0,安全回路状态1
53 12,General,PG.General.SafetyCircuitStatus2,Input,Td,3,X00312,1,1,0,安全回路状态2
54 13,CV,PG.CV.IonWindRodAlarmDetection,Input,Td,3,X00313,1,1,0,CV 离子风棒报警检测
55 14,EFEM,PG.EFEM.IonWindRodAlarmDetection1,Input,Td,3,X00314,1,1,0,EFEM离子风棒报警检测1
56 15,EFEM,PG.EFEM.IonWindRodAlarmDetection2,Input,Td,3,X00315,1,1,0,EFEM离子风棒报警检测2
57 0,AxisZ,PG.AxisZ.Z1GuideRailBrake,Output,Td,4,Y00100,1,1,0,Z1轴导轨抱闸
58 1,AxisZ,PG.AxisZ.Z3CameraAirCooling,Output,Td,4,Y00101,1,1,0,Z3相机气冷
59 2,AxisZ,PG.AxisZ.Z5CameraAirCooling,Output,Td,4,Y00102,1,1,0,Z5相机气冷
60 3,AxisZ,PG.AxisZ.Z10CameraAirCooling,Output,Td,4,Y00103,1,1,0,Z10相机气冷
61 4,AxisZ,PG.AxisZ.Z2BondHeadAirCooling,Output,Td,4,Y00104,1,1,0,Z2刺晶头气冷
62 5,CV,PG.CV.IonBarAct,Output,Td,4,Y00105,1,1,0,CV 离子风棒
63 6,WEU,PG.WEU.IonBarAct1,Output,Td,4,Y00106,1,1,0,WEU离子风棒1
64 7,WEU,PG.WEU.IonBarAct2,Output,Td,4,Y00107,1,1,0,WEU离子风棒2
65 8,WS,PG.WS.ThetaClampCylAct,Output,Td,4,Y00108,1,1,0,WS θ 夹紧气缸动作
66 9,WS,PG.WS.ThetaBrakePressCylAct,Output,Td,4,Y00109,1,1,0,WS θ 刹车压紧气缸动作
67 10,Stage,PG.Stage.LifterCyl1Act,Output,Td,4,Y00110,1,1,0,Stage 顶升气缸1动作
68 11,Stage,PG.Stage.LifterCyl2Act,Output,Td,4,Y00111,1,1,0,Stage 顶升气缸2动作
69 0,WZ,PG.WZ.StartButtonLight,Output,Td,5,Y00200,1,1,0,WZ 启动按钮灯
70 1,WZ,PG.WZ.StopButtonLight,Output,Td,5,Y00201,1,1,0,WZ 停止按钮灯
71 2,WZ,PG.WZ.ResetButtonLight,Output,Td,5,Y00202,1,1,0,WZ 复位按钮灯
72 3,WZ,PG.WZ.BlueButtonLight,Output,Td,5,Y00203,1,1,0,WZ 蓝色按钮灯
73 4,WZ,PG.WZ.WorkLight1,Output,Td,5,Y00204,1,1,0,WZ 照明灯1
74 6,EFEM,PG.EFEM.WorkLight1,Output,Td,5,Y00206,1,1,0,EFEM 照明灯1
75 8,WZ,PG.WZ.StackLightRed,Output,Td,5,Y00208,1,1,0,WZ 四色灯-红
76 9,WZ,PG.WZ.StackLightYellow,Output,Td,5,Y00209,1,1,0,WZ 四色灯-黄
77 10,WZ,PG.WZ.StackLightGreen,Output,Td,5,Y00210,1,1,0,WZ 四色灯-绿
78 11,WZ,PG.WZ.StackLightBlue,Output,Td,5,Y00211,1,1,0,WZ 四色灯-蓝
79 12,WZ,PG.WZ.BuzzerAct,Output,Td,5,Y00212,1,1,0,WZ 蜂鸣器
80 0,Stage,PG.Stage.BreakingTheVacuum1,Output,Td,6,Y00300,1,1,0,Stage 破真空1
81 1,Stage,PG.Stage.BreakingTheVacuum2,Output,Td,6,Y00301,1,1,0,STAGE 破真空2
82 2,Stage,PG.Stage.BreakingTheVacuum3,Output,Td,6,Y00302,1,1,0,STAGE 破真空3
83 3,Stage,PG.Stage.BreakingTheVacuum4,Output,Td,6,Y00303,1,1,0,STAGE 破真空4
84 4,WEU,PG.WEU.TrayBreakVacuum1,Output,Td,6,Y00304,1,1,0,WEU 料盘破真空1
85 5,WEU,PG.WEU.TrayBreakVacuum2,Output,Td,6,Y00305,1,1,0,WEU 料盘破真空2
86 6,AxisZ,PG.AxisZ.Z2BondHeadBreakVacuum,Output,Td,6,Y00306,1,1,0,PHS Z2 刺晶头破真空
87 7,Stage,PG.Stage.Vacuum1,Output,Td,6,Y00307,1,1,0,STAGE 吸真空1
88 8,Stage,PG.Stage.Vacuum2,Output,Td,6,Y00308,1,1,0,STAGE 吸真空2
89 9,Stage,PG.Stage.Vacuum3,Output,Td,6,Y00309,1,1,0,STAGE 吸真空3
90 10,Stage,PG.Stage.Vacuum4,Output,Td,6,Y00310,1,1,0,STAGE 吸真空4
91 11,WEU,PG.WEU.TrayVacuum1,Output,Td,6,Y00311,1,1,0,WEU 料盘吸真空1
92 12,WEU,PG.WEU.TrayVacuum2,Output,Td,6,Y00312,1,1,0,WEU 料盘吸真空2
93 13,AxisZ,PG.AxisZ.Z2BondHeadVacuum,Output,Td,6,Y00313,1,1,0,PHS Z2 刺晶头吸真空
94 1,WZ,PG.WZ.SafetyDoor1Open,Output,Td,7,Y00401,1,1,0,WZ 安全门1打开
95 2,WZ,PG.WZ.SafetyDoor2Open,Output,Td,7,Y00402,1,1,0,WZ 安全门2打开
96 3,WZ,PG.WZ.SafetyDoor3Open,Output,Td,7,Y00402,1,1,0,WZ 安全门3打开
97 4,WZ,PG.WZ.SafetyDoor4Open,Output,Td,7,Y00403,1,1,0,WZ 安全门4打开

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<Layout Version="1.0.0.1" WindowHeight="1024" WindowWidth="1280" MachineId="12345678901234567">
<Header Title="PG-A1">
<HeaderItem Id="HideEMO"/>
<HeaderItem Id="HideCIMStatus"/>
</Header>
<Body>
<StatusBar>
<StatusLight Name="设备一" LangName="Device" Binding="Device"></StatusLight>
</StatusBar>
<Pages>
<Page Name="主页" LangName="PageHome" Target="Home">
</Page>
<Page Name="配方" LangName="PageRecipe" Target="Recipe">
</Page>
<Page Name="参数设置" LangName="PageSettings" Target="PageSettings" DisabledState="SemiAutomatic;Automatic" UserRightId="PageSettings">
</Page>
<Page Name="设备维护" LangName="MenuDeviceMaint" Target="MenuDeviceMaint" DisabledState="SemiAutomatic;Automatic" UserRightId="PageSettings">
</Page>
<Page Name="标定与校准" LangName="PageCalib" Target="PageCalib" DisabledState="SemiAutomatic;Automatic" UserRightId="PageCalib">
</Page>
<Page Name="半自动" LangName="ManualModeOperation" Target="ManualOperate">
</Page>
</Pages>
</Body>
<Footer Target="Footer"/>
</Layout>

View File

@@ -0,0 +1,28 @@
using MainShell.Common;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
namespace MainShell.Converter
{
public class BondingPathModeToBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
BondingPathMode speedMode = (BondingPathMode)value;
int mode = System.Convert.ToInt32(parameter.ToString());
return mode == (int)speedMode ? true : false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
int mode = System.Convert.ToInt32(parameter.ToString());
return (BondingPathMode)mode;
}
}
}

View File

@@ -0,0 +1,28 @@
using MainShell.Common;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
namespace MainShell.Converter
{
public class BondingRegionModeToBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
BondingStagePathMode speedMode = (BondingStagePathMode)value;
int mode = System.Convert.ToInt32(parameter.ToString());
return mode == (int)speedMode ? true : false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
int mode = System.Convert.ToInt32(parameter.ToString());
return (BondingStagePathMode)mode;
}
}
}

View File

@@ -0,0 +1,28 @@
using MainShell.Common;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
namespace MainShell.Converter
{
public class BondingWsPathModeToBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
BondingWSPathMode speedMode = (BondingWSPathMode)value;
int mode = System.Convert.ToInt32(parameter.ToString());
return mode == (int)speedMode ? true : false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
int mode = System.Convert.ToInt32(parameter.ToString());
return (BondingWSPathMode)mode;
}
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
namespace MainShell.Converter
{
public class BoolToInversionConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null)
{
return !System.Convert.ToBoolean(value);
}
else
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,94 @@
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace MainShell.Converter
{
public class BoolToVisibleConverter : IValueConverter
{
// 将 bool (或可转换为 bool 的值) 转换为 Visibility
// parameter 支持:
// 包含 "invert" / "inverse" / "not" / "!" 的字符串 — 反转布尔值
// 包含 "hidden" 的字符串 — 当为 false 时返回 Visibility.Hidden 而不是 Collapsed
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
bool isVisible = false;
if (value is bool b)
{
isVisible = b;
}
else if (value is bool?)
{
isVisible = ((bool?)value) ?? false;
}
else if (value is string s)
{
bool.TryParse(s, out isVisible);
}
else if (value != null)
{
try
{
isVisible = System.Convert.ToBoolean(value);
}
catch
{
isVisible = false;
}
}
var paramString = parameter as string;
bool invert = false;
bool useHidden = false;
if (!string.IsNullOrEmpty(paramString))
{
var p = paramString.ToLowerInvariant();
if (p.Contains("invert") || p.Contains("inverse") || p.Contains("not") || p.Contains("!"))
invert = true;
if (p.Contains("hidden"))
useHidden = true;
}
if (invert)
isVisible = !isVisible;
return isVisible ? Visibility.Visible : (useHidden ? Visibility.Hidden : Visibility.Collapsed);
}
// 将 Visibility 转换回 bool
// Visible => trueHidden/Collapsed => false
// 支持与 Convert 相同的 parameter 反转语义
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is Visibility))
return Binding.DoNothing;
var vis = (Visibility)value;
bool result = vis == Visibility.Visible;
var paramString = parameter as string;
if (!string.IsNullOrEmpty(paramString))
{
var p = paramString.ToLowerInvariant();
if (p.Contains("invert") || p.Contains("inverse") || p.Contains("not") || p.Contains("!"))
result = !result;
}
if (targetType == typeof(bool) || targetType == typeof(object))
return result;
if (targetType == typeof(bool?))
return (bool?)result;
try
{
return System.Convert.ChangeType(result, targetType);
}
catch
{
return result;
}
}
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
namespace MainShell.Converter
{
public class DateTimeToStringConverter : IValueConverter
{
public string Format { get; set; } = "yyyy-MM-dd HH:mm:ss";
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return string.Empty;
if (!(value is DateTime dt)) return string.Empty;
if (dt == DateTime.MinValue) return string.Empty;
// parameter 优先用于临时格式覆盖
var fmt = parameter as string ?? Format;
return dt.ToString(fmt, culture);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
}

View File

@@ -0,0 +1,39 @@
using System;
using System.Linq;
using System.Windows.Markup;
namespace MainShell.Converter
{
// XAML 中可直接写 {conv:EnumBindingSource {x:Type local:MyEnum}}
public class EnumBindingSourceExtension : MarkupExtension
{
public Type EnumType { get; set; }
public bool UseDescription { get; set; } = true;
public EnumBindingSourceExtension() { }
public EnumBindingSourceExtension(Type enumType)
{
EnumType = enumType;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (EnumType == null || !EnumType.IsEnum) return null;
var values = Enum.GetValues(EnumType).Cast<Enum>();
return values.Select(v => new EnumItem
{
Value = v,
Description = UseDescription ? EnumHelper.GetEnumDescription(v) : v.ToString()
}).ToList();
}
}
public class EnumItem
{
public Enum Value { get; set; }
public string Description { get; set; }
public int IntValue => Convert.ToInt32(Value);
}
}

View File

@@ -0,0 +1,79 @@
using MwFramework.Device;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
namespace MainShell.Converter
{
/// <summary>
/// 获取枚举类型的Description描述信息
/// </summary>
public class EnumDescriptionConverter : IValueConverter
{
object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value.ToString() != "")
{
Enum myEnum = (Enum)value;
string description = EnumHelper.GetEnumDescription(myEnum);
return description;
}
else
{
return "";
}
}
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return string.Empty;
}
}
public class EnumToBool : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (int)value == (int)parameter;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if ((bool)value)
{
return parameter;
}
else
{
return Binding.DoNothing;
}
}
}
public static class EnumHelper
{
public static string GetEnumDescription(Enum enumObj)
{
FieldInfo fieldInfo = enumObj.GetType().GetField(enumObj.ToString());
var descriptionAttr = fieldInfo
.GetCustomAttributes(false)
.OfType<DescriptionAttribute>()
.Cast<DescriptionAttribute>()
.SingleOrDefault();
if (descriptionAttr == null)
{
return enumObj.ToString();
}
else
{
return descriptionAttr.Description;
}
}
}
}

View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
namespace MainShell.Converter
{
public class ObjectToBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value != null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,30 @@
using MainShell.Common;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Data;
namespace MainShell.Converter
{
public class RunningModeEnumToBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
RunningMode speedMode = (RunningMode)value;
int mode = System.Convert.ToInt32(parameter.ToString());
return mode == (int)speedMode ? true : false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
int mode = System.Convert.ToInt32(parameter.ToString());
return (RunningMode)mode;
}
}
}

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
namespace MainShell.Converter
{
public class ScreenToViewModelConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return null;
var viewModelType = value.GetType();
var viewName = viewModelType.FullName.Replace("ViewModel", "View");
var viewType = Type.GetType(viewName);
if (viewType != null)
{
// 创建View实例并设置其DataContext为当前的ViewModel
var view = (FrameworkElement)Activator.CreateInstance(viewType);
view.DataContext = value;
return view;
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,29 @@
using MainShell.Recipe.Models.SubstrateParameter;
using System;
using System.Globalization;
using System.Windows.Data;
namespace MainShell.Converter
{
public class SubstrateHeightMeasureModeToBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var mode = value is SubstrateHeightMeasureMode measureMode ? measureMode : SubstrateHeightMeasureMode.StandardTeachPosition;
var parameterValue = System.Convert.ToInt32(parameter, CultureInfo.InvariantCulture);
return parameterValue == (int)mode;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is bool isChecked) || !isChecked)
{
return Binding.DoNothing;
}
var parameterValue = System.Convert.ToInt32(parameter, CultureInfo.InvariantCulture);
return (SubstrateHeightMeasureMode)parameterValue;
}
}
}

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
namespace MainShell.Converter
{
public class WidthToMarginConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
double actualWidth = 0;
if (value is double d) actualWidth = d;
double expanded = 200;
double extra = 0;
if (parameter is string s)
{
var parts = s.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length >= 1 && double.TryParse(parts[0], out var p0)) expanded = p0;
if (parts.Length >= 2 && double.TryParse(parts[1], out var p1)) extra = p1;
}
// 计算右侧 Margin
// 当 actualWidth == expanded 时返回 0不偏移
// 当 actualWidth 减小时会返回正值,从而把 ToggleButton 向左推(或根据需要调整公式)
double right = Math.Max(0, expanded - actualWidth) + extra;
// 根据布局需要你可以修改这里返回的 Thickness 的哪一项Left/Right
return new Thickness(-30, 0, 0, 0);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,49 @@
using System.Collections.Generic;
namespace MainShell.DeviceMaintance.Model
{
public enum CylinderControlType
{
SingleOutput = 0,
DualOutput = 1,
MultiOutput = 2
}
public enum CylinderConditionType
{
PointOn = 0,
PointOff = 1
}
public class CylinderActionConditionDefinition
{
public CylinderConditionType ConditionType { get; set; }
public string PointReference { get; set; }
public string Message { get; set; }
public bool ExpectedState => ConditionType == CylinderConditionType.PointOn;
}
public class CylinderDefinition
{
public string Name { get; set; }
public string Description { get; set; }
public string Module { get; set; }
public CylinderControlType ControlType { get; set; }
public List<string> ExtendOutputPoints { get; set; } = new List<string>();
public List<string> RetractOutputPoints { get; set; } = new List<string>();
public List<string> ExtendedFeedbackPoints { get; set; } = new List<string>();
public List<string> RetractedFeedbackPoints { get; set; } = new List<string>();
public List<CylinderActionConditionDefinition> ExtendConditions { get; set; } = new List<CylinderActionConditionDefinition>();
public List<CylinderActionConditionDefinition> RetractConditions { get; set; } = new List<CylinderActionConditionDefinition>();
public bool HasRetractOutputs => RetractOutputPoints != null && RetractOutputPoints.Count > 0;
}
public class CylinderExecutionResult
{
public bool Success { get; set; }
public string FailureReason { get; set; }
public IReadOnlyList<string> FailurePointReferences { get; set; } = new List<string>();
}
}

View File

@@ -0,0 +1,209 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace MainShell.DeviceMaintance.Model
{
public static class CylinderDefinitionLoader
{
private const string CylinderConfigFileName = "CylinderDefinitions.csv";
public static IReadOnlyList<CylinderDefinition> LoadDefinitions()
{
var definitions = new List<CylinderDefinition>();
var path = ResolveConfigPath();
if (string.IsNullOrWhiteSpace(path) || !File.Exists(path))
{
return definitions;
}
var lines = File.ReadAllLines(path, Encoding.UTF8);
foreach (var raw in lines)
{
if (string.IsNullOrWhiteSpace(raw))
{
continue;
}
var line = raw.Trim();
if (line.StartsWith("#") || line.StartsWith("Name", StringComparison.OrdinalIgnoreCase))
{
continue;
}
var cols = line.Split(',');
if (cols.Length < 7)
{
continue;
}
var extendOutputPoints = ParsePointReferences(cols[3]);
if (extendOutputPoints.Count == 0)
{
continue;
}
var retractOutputPoints = ParsePointReferences(cols[4]);
var hasConditionColumns = cols.Length >= 10;
var extendConditionIndex = hasConditionColumns ? 7 : -1;
var retractConditionIndex = hasConditionColumns ? 8 : -1;
var descriptionIndex = hasConditionColumns ? 9 : 7;
definitions.Add(new CylinderDefinition
{
Name = cols[0].Trim(),
Module = cols[1].Trim(),
ControlType = ParseControlType(cols[2]),
ExtendOutputPoints = extendOutputPoints,
RetractOutputPoints = retractOutputPoints,
ExtendedFeedbackPoints = ParsePointReferences(cols[5]),
RetractedFeedbackPoints = ParsePointReferences(cols[6]),
ExtendConditions = extendConditionIndex >= 0 ? ParseConditions(cols[extendConditionIndex]) : new List<CylinderActionConditionDefinition>(),
RetractConditions = retractConditionIndex >= 0 ? ParseConditions(cols[retractConditionIndex]) : new List<CylinderActionConditionDefinition>(),
Description = cols.Length > descriptionIndex ? string.Join(",", cols.Skip(descriptionIndex)).Trim() : string.Empty
});
}
return definitions;
}
private static CylinderControlType ParseControlType(string raw)
{
if (string.Equals(raw, "DualOutput", StringComparison.OrdinalIgnoreCase) ||
string.Equals(raw, "Dual", StringComparison.OrdinalIgnoreCase))
{
return CylinderControlType.DualOutput;
}
if (string.Equals(raw, "MultiOutput", StringComparison.OrdinalIgnoreCase) ||
string.Equals(raw, "Multi", StringComparison.OrdinalIgnoreCase))
{
return CylinderControlType.MultiOutput;
}
return CylinderControlType.SingleOutput;
}
private static List<string> ParsePointReferences(string raw)
{
return (raw ?? string.Empty)
.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.Trim())
.Where(x => !string.IsNullOrWhiteSpace(x))
.ToList();
}
private static List<CylinderActionConditionDefinition> ParseConditions(string raw)
{
return (raw ?? string.Empty)
.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
.Select(ParseCondition)
.Where(x => x != null)
.ToList();
}
private static CylinderActionConditionDefinition ParseCondition(string raw)
{
if (string.IsNullOrWhiteSpace(raw))
{
return null;
}
var parts = raw.Split(new[] { ':' }, 3);
if (parts.Length < 2)
{
return null;
}
var pointReference = parts[1].Trim();
if (string.IsNullOrWhiteSpace(pointReference))
{
return null;
}
CylinderConditionType conditionType;
switch ((parts[0] ?? string.Empty).Trim().ToUpperInvariant())
{
case "POINTON":
case "ON":
conditionType = CylinderConditionType.PointOn;
break;
case "POINTOFF":
case "OFF":
conditionType = CylinderConditionType.PointOff;
break;
default:
return null;
}
return new CylinderActionConditionDefinition
{
ConditionType = conditionType,
PointReference = pointReference,
Message = parts.Length > 2 ? parts[2].Trim() : string.Empty
};
}
private static string ResolveConfigPath()
{
var baseDir = AppDomain.CurrentDomain.BaseDirectory;
var localPath = Path.Combine(baseDir, "Configuration", CylinderConfigFileName);
var sourcePath = ResolveRootConfigPath(baseDir);
if (TrySyncConfigToLocal(sourcePath, localPath))
{
return localPath;
}
return File.Exists(localPath) ? localPath : sourcePath;
}
private static string ResolveRootConfigPath(string baseDir)
{
var current = new DirectoryInfo(baseDir);
while (current != null)
{
var rootConfigDir = Path.Combine(current.FullName, "Configuration");
if (Directory.Exists(rootConfigDir) && Directory.Exists(Path.Combine(current.FullName, "MainShell")))
{
var path = Path.Combine(rootConfigDir, CylinderConfigFileName);
if (File.Exists(path))
{
return path;
}
}
current = current.Parent;
}
return null;
}
private static bool TrySyncConfigToLocal(string sourcePath, string localPath)
{
if (string.IsNullOrWhiteSpace(sourcePath) || !File.Exists(sourcePath))
{
return false;
}
if (!string.Equals(Path.GetFullPath(sourcePath), Path.GetFullPath(localPath), StringComparison.OrdinalIgnoreCase))
{
var localDir = Path.GetDirectoryName(localPath);
if (!string.IsNullOrWhiteSpace(localDir))
{
Directory.CreateDirectory(localDir);
}
if (!File.Exists(localPath) || File.GetLastWriteTimeUtc(localPath) < File.GetLastWriteTimeUtc(sourcePath))
{
File.Copy(sourcePath, localPath, true);
}
}
return true;
}
}
}

View File

@@ -0,0 +1,19 @@
using Stylet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MainShell.DeviceMaintance.Model
{
public class DeviceMaintanceBaseViewModel : Screen
{
public event Action<bool> UiStateChangedEvent = null;
protected void OnUiStateChanged(bool uiStateChanged)
{
UiStateChangedEvent?.Invoke(uiStateChanged);
}
}
}

View File

@@ -0,0 +1,97 @@
using MainShell.Filewritable;
using Newtonsoft.Json;
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace MainShell.DeviceMaintance.Model
{
public class LaserCompensationSetting : MXJM.FileWritable.JsonFileWritableBase, INotifyPropertyChanged
{
private string _axisName = "Axis_Stage_Y3";
public string AxisName
{
get { return _axisName; }
set { SetAndNotify(ref _axisName, value); }
}
private double _startPos;
public double StartPos
{
get { return _startPos; }
set { SetAndNotify(ref _startPos, value); }
}
private double _steps = 1.0d;
public double Steps
{
get { return _steps; }
set { SetAndNotify(ref _steps, value); }
}
private int _stepsCount = 5;
public int StepsCount
{
get { return _stepsCount; }
set { SetAndNotify(ref _stepsCount, value); }
}
private double _jumpPos = 1.0d;
public double JumpPos
{
get { return _jumpPos; }
set { SetAndNotify(ref _jumpPos, value); }
}
private int _workCount = 1;
public int WorkCount
{
get { return _workCount; }
set { SetAndNotify(ref _workCount, value); }
}
private double _speed = 5.0d;
public double Speed
{
get { return _speed; }
set { SetAndNotify(ref _speed, value); }
}
private double _dwellTime = 0.5d;
public double DwellTime
{
get { return _dwellTime; }
set { SetAndNotify(ref _dwellTime, value); }
}
[JsonIgnore]
public override string Dir => Paths.CalibSettingPath;
[JsonIgnore]
public override string FileName => "LaserCompensationSetting.json";
public event PropertyChangedEventHandler PropertyChanged;
public void LoadFromFile()
{
Read();
}
public void SaveToFile()
{
Write();
}
protected bool SetAndNotify<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (Equals(field, value))
{
return false;
}
field = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
return true;
}
}
}

View File

@@ -0,0 +1,64 @@
using MainShell.Common;
using MainShell.Filewritable;
using MaxwellControl.Controls;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MainShell.DeviceMaintance.Model
{
public enum MaintanceType
{
= 1,
= 2,
= 3,
}
public class MaintanceRecord
{
/// <summary>
/// 设备编号
/// </summary>
public string DeviceId { get; set; }
/// <summary>
/// 设备名称
/// </summary>
public string DeviceName { get; set; }
/// <summary>
/// 维护时间
/// </summary>
public DateTime MaintanceTime { get; set; }
/// <summary>
/// 维护内容
/// </summary>
public MaintanceType MaintanceType { get; set; }
public void WriteToFile(string info)
{
try
{
if (!Directory.Exists(Paths.MaintanceRecordDir))
{
Directory.CreateDirectory(Paths.MaintanceRecordDir);
}
string filePath = Path.Combine(Paths.MaintanceRecordDir, $"{MaintanceType}_MaintanceRecord.txt");
using (var writer = new System.IO.StreamWriter(filePath, true))
{
if (!File.Exists(filePath))
{
writer.WriteLine("设备ID,日期,信息");
}
writer.WriteLine($"{DeviceId},{DateTime.Now}: {info}");
writer.Flush();
}
}
catch (Exception ex)
{
MessageBox.Show($"写入文件失败: {ex.Message}");
}
}
}
}

View File

@@ -0,0 +1,757 @@
using MwFramework.Controls.UIControl;
using MwFramework.ManagerService;
using Stylet;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MainShell.DeviceMaintance.Model
{
[Export(typeof(IParameter))]
public class NeedleCalibrationSetting : ParameterBase
{
public NeedleZCalibrationItem NeedleZCalibrationItem { get; set; } = new NeedleZCalibrationItem();
public NeedleXYCalibrationItem NeedleXYCalibrationItem { get; set; } = new NeedleXYCalibrationItem();
public NeedleXYCalibrationItemNew NeedleXYCalibrationItemNew { get; set; } = new NeedleXYCalibrationItemNew();
public override void Copy(IParameter source)
{
NeedleCalibrationSetting setting = source as NeedleCalibrationSetting;
if (setting != null)
{
ReflectionExtension.Copy<NeedleZCalibrationItem>(NeedleZCalibrationItem, setting.NeedleZCalibrationItem);
ReflectionExtension.Copy<NeedleXYCalibrationItem>(NeedleXYCalibrationItem, setting.NeedleXYCalibrationItem);
ReflectionExtension.Copy<NeedleXYCalibrationItemNew>(NeedleXYCalibrationItemNew, setting.NeedleXYCalibrationItemNew);
}
}
}
public class NeedleZCalibrationItem : PropertyChangedBase, IParameterItem
{
private double _supportPinPositionX;
[WatchValue("针尖对准对刀仪X1位置")]
public double SupportPinPositionX
{
get { return _supportPinPositionX; }
set { if (_supportPinPositionX != value) { _supportPinPositionX = value; OnPropertyChanged(nameof(SupportPinPositionX)); } }
}
private double _supportPinPositionY;
[WatchValue("针尖对准对刀仪Y1位置")]
public double SupportPinPositionY
{
get { return _supportPinPositionY; }
set { if (_supportPinPositionY != value) { _supportPinPositionY = value; OnPropertyChanged(nameof(SupportPinPositionY)); } }
}
private double _knifeOffset;
[WatchValue("对刀仪偏差")]
/// <summary>
/// 对刀仪偏差
/// </summary>
public double KnifeOffset
{
get { return _knifeOffset; }
set { if (_knifeOffset != value) { _knifeOffset = value; OnPropertyChanged(nameof(KnifeOffset)); } }
}
private double _cZHeight = -0.725;
[WatchValue("SZ高度")]
public double CZHeight
{
get { return _cZHeight; }
set { if (_cZHeight != value) { _cZHeight = value; OnPropertyChanged(nameof(CZHeight)); } }
}
private double _stageHeight;
[WatchValue("载台高度")]
public double StageHeight
{
get { return _stageHeight; }
set { if (_stageHeight != value) { _stageHeight = value; OnPropertyChanged(nameof(StageHeight)); } }
}
private double _gantry2AvoidPositionX = 10;
[WatchValue("对刀时龙门X2的避让位置")]
public double Gantry2AvoidPositionX
{
get { return _gantry2AvoidPositionX; }
set { if (_gantry2AvoidPositionX != value) { _gantry2AvoidPositionX = value; OnPropertyChanged(nameof(Gantry2AvoidPositionX)); } }
}
private double _gantry2AvoidPositionY = 200;
[WatchValue("对刀时龙门Y2的避让位置")]
public double Gantry2AvoidPositionY
{
get { return _gantry2AvoidPositionY; }
set { if (_gantry2AvoidPositionY != value) { _gantry2AvoidPositionY = value; OnPropertyChanged(nameof(Gantry2AvoidPositionY)); } }
}
private double _z1StartPosition;
[WatchValue("Z1开始位置")]
public double Z1StartPosition
{
get { return _z1StartPosition; }
set { if (_z1StartPosition != value) { _z1StartPosition = value; OnPropertyChanged(nameof(Z1StartPosition)); } }
}
private double _z1Speed;
[WatchValue("Z1速度")]
public double Z1Speed
{
get { return _z1Speed; }
set { if (_z1Speed != value) { _z1Speed = value; OnPropertyChanged(nameof(Z1Speed)); } }
}
private double _z1DropMaxPosition;
[WatchValue("Z1下降距离")]
public double Z1DropMaxPosition
{
get { return _z1DropMaxPosition; }
set { if (_z1DropMaxPosition != value) { _z1DropMaxPosition = value; OnPropertyChanged(nameof(Z1DropMaxPosition)); } }
}
private int _needleTouchCount = 1;
[WatchValue("对刀次数")]
public int NeedleTouchCount
{
get { return _needleTouchCount; }
set { if (_needleTouchCount != value) { _needleTouchCount = value; OnPropertyChanged(nameof(NeedleTouchCount)); } }
}
private double _needleTouchHeight = 14;
/// <summary>
/// Z1接触对刀仪高度
/// </summary>
[WatchValue("Z1接触对刀仪高度")]
public double NeedleTouchHeight
{
get { return _needleTouchHeight; }
set { if (_needleTouchHeight != value) { _needleTouchHeight = value; OnPropertyChanged(nameof(NeedleTouchHeight)); } }
}
private double _needleTouchHeightBase;
/// <summary>
/// 基准值
/// </summary>
[WatchValue("基准值")]
public double NeedleTouchHeightBase
{
get { return _needleTouchHeightBase; }
set { if (_needleTouchHeightBase != value) { _needleTouchHeightBase = value; OnPropertyChanged(nameof(NeedleTouchHeightBase)); } }
}
private double _currentNeedleTouchHeight;
[WatchValue("当前使用对刀高度")]
/// <summary>
/// 当前使用对刀高度
/// </summary>
public double CurrentNeedleTouchHeight
{
get { return _currentNeedleTouchHeight; }
set { if (_currentNeedleTouchHeight != value) { _currentNeedleTouchHeight = value; OnPropertyChanged(nameof(CurrentNeedleTouchHeight)); } }
}
private double _needleTouchOffset;
[WatchValue("对刀与基准偏差")]
/// <summary>
/// 对刀与基准偏差
/// </summary>
public double NeedleTouchOffset
{
get { return _needleTouchOffset; }
set { if (_needleTouchOffset != value) { _needleTouchOffset = value; OnPropertyChanged(nameof(NeedleTouchOffset)); } }
}
private double _needleTouchHeightAve;
[WatchValue("Z1对刀平均高度")]
/// <summary>
/// Z1对刀平均高度
/// </summary>
public double NeedleTouchHeightAve
{
get { return _needleTouchHeightAve; }
set { if (_needleTouchHeightAve != value) { _needleTouchHeightAve = value; OnPropertyChanged(nameof(NeedleTouchHeightAve)); } }
}
private ObservableCollection<NeedleTouchRecord> _needleTouchRecords = new ObservableCollection<NeedleTouchRecord>();
public ObservableCollection<NeedleTouchRecord> NeedleTouchRecords
{
get { return _needleTouchRecords; }
set
{
_needleTouchRecords = value;
OnPropertyChanged(nameof(NeedleTouchRecords));
}
}
private double _laserToNeedleOffset = 0;
public double LaserToNeedleOffset
{
get { return _laserToNeedleOffset; }
set { if (_laserToNeedleOffset != value) { _laserToNeedleOffset = value; OnPropertyChanged(nameof(LaserToNeedleOffset)); } }
}
private double _needleCameraHeightOffset;
public double NeedleCameraHeightOffset
{
get { return _needleCameraHeightOffset; }
set { if (_needleCameraHeightOffset != value) { _needleCameraHeightOffset = value; OnPropertyChanged(nameof(NeedleCameraHeightOffset)); } }
}
public IParameterItem Clone()
{
NeedleZCalibrationItem clone = new NeedleZCalibrationItem();
clone.CurrentNeedleTouchHeight = _needleCameraHeightOffset;
clone.CZHeight = CZHeight;
clone.Gantry2AvoidPositionX = Gantry2AvoidPositionX;
clone.Gantry2AvoidPositionY = Gantry2AvoidPositionY;
clone.LaserToNeedleOffset = LaserToNeedleOffset;
clone.NeedleCameraHeightOffset = NeedleCameraHeightOffset;
clone.NeedleTouchCount = NeedleTouchCount;
clone.NeedleTouchHeight = NeedleTouchHeight;
clone.NeedleTouchHeightAve = NeedleTouchHeightAve;
clone.NeedleTouchHeightBase = NeedleTouchHeightBase;
clone.NeedleTouchOffset = NeedleTouchOffset;
clone.StageHeight = StageHeight;
clone.SupportPinPositionX = SupportPinPositionX;
clone.SupportPinPositionY = SupportPinPositionY;
clone.Z1DropMaxPosition = Z1DropMaxPosition;
clone.Z1Speed = Z1Speed;
clone.Z1StartPosition = Z1StartPosition;
if (this.NeedleTouchRecords != null)
{
foreach (var item in this.NeedleTouchRecords)
{
clone.NeedleTouchRecords.Add(item.Clone() as NeedleTouchRecord);
}
}
return clone;
}
}
public class NeedleXYCalibrationItem : PropertyChangedBase, IParameterItem
{
private double _needleX;
[WatchValue("设置—刺晶头X")]
public double NeedleX
{
get { return _needleX; }
set { if (_needleX != value) { _needleX = value; OnPropertyChanged(nameof(NeedleX)); } }
}
private double _needleY;
[WatchValue("设置—刺晶头Y")]
public double NeedleY
{
get { return _needleY; }
set { if (_needleY != value) { _needleY = value; OnPropertyChanged(nameof(NeedleY)); } }
}
private double _cameraX;
[WatchValue("设置—相机X")]
public double CameraX
{
get { return _cameraX; }
set { if (_cameraX != value) { _cameraX = value; OnPropertyChanged(nameof(CameraX)); } }
}
private double _cameraY;
[WatchValue("设置—相机Y")]
public double CameraY
{
get { return _cameraY; }
set { if (_cameraY != value) { _cameraY = value; OnPropertyChanged(nameof(CameraY)); } }
}
private double _needleZ1 = 0.0;
[WatchValue("设置—刺晶头Z1")]
public double NeedleZ1
{
get { return _needleZ1; }
set { if (_needleZ1 != value) { _needleZ1 = value; OnPropertyChanged(nameof(NeedleZ1)); } }
}
private double _offsetX;
[WatchValue("X方向偏差")]
public double OffsetX
{
get { return _offsetX; }
set { if (_offsetX != value) { _offsetX = value; OnPropertyChanged(nameof(OffsetX)); } }
}
private double _offsetY;
[WatchValue("Y方向偏差")]
public double OffsetY
{
get { return _offsetY; }
set { if (_offsetY != value) { _offsetY = value; OnPropertyChanged(nameof(OffsetY)); } }
}
private double _initialOffsetX;
/// <summary>
/// 针和相机之间的X初始偏差不加补偿
/// </summary>
[WatchValue("X方向初始偏差")]
public double InitialOffsetX
{
get { return _initialOffsetX; }
set { if (_initialOffsetX != value) { _initialOffsetX = value; OnPropertyChanged(nameof(InitialOffsetX)); } }
}
private double _initialOffsetY;
/// <summary>
/// 针和相机之间的Y初始偏差不加补偿
/// </summary>
[WatchValue("Y方向初始偏差")]
public double InitialOffsetY
{
get { return _initialOffsetY; }
set { if (_initialOffsetY != value) { _initialOffsetY = value; OnPropertyChanged(nameof(InitialOffsetY)); } }
}
private double _compensateX;
/// <summary>
/// 针和相机之间的X方向偏差补偿
/// </summary>
[WatchValue("X方向补偿")]
public double CompensateX
{
get { return _compensateX; }
set { if (_compensateX != value) { _compensateX = value; OnPropertyChanged(nameof(CompensateX)); } }
}
private double _compensateY;
/// <summary>
/// 针和相机之间的Y方向偏差补偿
/// </summary>
[WatchValue("Y方向补偿")]
public double CompensateY
{
get { return _compensateY; }
set { if (_compensateY != value) { _compensateY = value; OnPropertyChanged(nameof(CompensateY)); } }
}
private double _offsetXMax;
[WatchValue("偏差限制—X偏差最大值")]
public double OffsetXMax
{
get { return _offsetXMax; }
set { if (_offsetXMax != value) { _offsetXMax = value; OnPropertyChanged(nameof(OffsetXMax)); } }
}
private double _offsetXMin;
[WatchValue("偏差限制—X偏差最小值")]
public double OffsetXMin
{
get { return _offsetXMin; }
set { if (_offsetXMin != value) { _offsetXMin = value; OnPropertyChanged(nameof(OffsetXMin)); } }
}
private double _offsetYMax;
[WatchValue("偏差限制—Y偏差最大值")]
public double OffsetYMax
{
get { return _offsetYMax; }
set { if (_offsetYMax != value) { _offsetYMax = value; OnPropertyChanged(nameof(OffsetYMax)); } }
}
private double _offsetYMin;
[WatchValue("偏差限制—Y偏差最小值")]
public double OffsetYMin
{
get { return _offsetYMin; }
set { if (_offsetYMin != value) { _offsetYMin = value; OnPropertyChanged(nameof(OffsetYMin)); } }
}
/// <summary>
/// 扎铜箔时龙门X2避让位置
/// </summary>
private double _x2AvoidPosition;
[WatchValue("扎铜箔时龙门X2避让位置")]
public double X2AvoidPosition
{
get { return _x2AvoidPosition; }
set { if (_x2AvoidPosition != value) { _x2AvoidPosition = value; OnPropertyChanged(nameof(X2AvoidPosition)); } }
}
/// <summary>
/// 扎铜箔时龙门Y2避让位置
/// </summary>
private double _y2AvoidPosition;
[WatchValue("扎铜箔时龙门Y2避让位置")]
public double Y2AvoidPosition
{
get { return _y2AvoidPosition; }
set { if (_y2AvoidPosition != value) { _y2AvoidPosition = value; OnPropertyChanged(nameof(Y2AvoidPosition)); } }
}
/// <summary>
/// 扎铜箔时Stage的位置
/// </summary>
private double _stagePosition;
[WatchValue("扎铜箔时Stage的位置")]
public double StagePosition
{
get { return _stagePosition; }
set { if (_stagePosition != value) { _stagePosition = value; OnPropertyChanged(nameof(StagePosition)); } }
}
public IParameterItem Clone()
{
NeedleXYCalibrationItem clone = new NeedleXYCalibrationItem();
clone.NeedleX = this.NeedleX;
clone.NeedleY = this.NeedleY;
clone.CameraX = this.CameraY;
clone.CameraY = this.CameraY;
clone.OffsetX = this.OffsetX;
clone.OffsetY = this.OffsetY;
clone.OffsetXMax = this.OffsetXMax;
clone.OffsetXMin = this.OffsetXMin;
clone.OffsetYMax = this.OffsetYMax;
clone.OffsetYMin = this.OffsetYMin;
return this.MemberwiseClone() as IParameterItem;
}
}
public class NeedleXYCalibrationItemNew : PropertyChangedBase, IParameterItem
{
//private VisionParData _needleVisionParData;
//public VisionParData NeedleVisionParData
//{
// get { return _needleVisionParData ?? new VisionParData() { Exposure = 2000 }; }
// set { SetAndNotify(ref _needleVisionParData, value); }
//}
private double _x1Calib;
/// <summary>
/// 相机标定位X1
/// </summary>
[WatchValue("相机标定位X1")]
public double X1Calib
{
get { return _x1Calib; }
set { if (_x1Calib != value) { _x1Calib = value; OnPropertyChanged(nameof(X1Calib)); } }
}
private double _x1MechanicalOffset = 0.0;
/// <summary>
/// 机械X1Offset
/// </summary>
[WatchValue("机械X1Offset")]
public double X1MechanicalOffset
{
get { return _x1MechanicalOffset; }
set { if (_x1MechanicalOffset != value) { _x1MechanicalOffset = value; OnPropertyChanged(nameof(X1MechanicalOffset)); } }
}
private double _wSCalibX2;
/// <summary>
/// 方片标定位X2
/// </summary>
[WatchValue("方片标定位X2")]
public double WSCalibX2
{
get { return _wSCalibX2; }
set { if (_wSCalibX2 != value) { _wSCalibX2 = value; OnPropertyChanged(nameof(WSCalibX2)); } }
}
private double _wSCalibY2;
/// <summary>
/// 方片标定位Y2
/// </summary>
[WatchValue("方片标定位Y2")]
public double WSCalibY2
{
get { return _wSCalibY2; }
set { if (_wSCalibY2 != value) { _wSCalibY2 = value; OnPropertyChanged(nameof(WSCalibY2)); } }
}
private double _needleX1;
[WatchValue("刺晶头X1")]
public double NeedleX1
{
get { return _needleX1; }
set { if (_needleX1 != value) { _needleX1 = value; OnPropertyChanged(nameof(NeedleX1)); } }
}
private double _needleZ1 = 0.0;
[WatchValue("刺晶头Z1")]
public double NeedleZ1
{
get { return _needleZ1; }
set { if (_needleZ1 != value) { _needleZ1 = value; OnPropertyChanged(nameof(NeedleZ1)); } }
}
private int _z1WorkTime = 0;
/// <summary>
/// Z1保持下扎时长
/// </summary>
[WatchValue("Z1保持下扎时长")]
public int Z1WorkTime
{
get { return _z1WorkTime; }
set { if (_z1WorkTime != value) { _z1WorkTime = value; OnPropertyChanged(nameof(Z1WorkTime)); } }
}
private double _offsetX;
/// <summary>
/// 针和相机之间的X初始偏差不加补偿
/// </summary>
[WatchValue("X方向偏差")]
public double OffsetX
{
get { return _offsetX; }
set { if (_offsetX != value) { _offsetX = value; OnPropertyChanged(nameof(OffsetX)); } }
}
private double _offsetY;
/// <summary>
/// 针和相机之间的Y初始偏差不加补偿
/// </summary>
[WatchValue("Y方向偏差")]
public double OffsetY
{
get { return _offsetY; }
set { if (_offsetY != value) { _offsetY = value; OnPropertyChanged(nameof(OffsetY)); } }
}
private double _compensateX;
/// <summary>
/// 针和相机之间的X方向偏差补偿
/// </summary>
[WatchValue("X方向补偿")]
public double CompensateX
{
get { return _compensateX; }
set { if (_compensateX != value) { _compensateX = value; OnPropertyChanged(nameof(CompensateX)); } }
}
private double _compensateY;
/// <summary>
/// 针和相机之间的Y方向偏差补偿
/// </summary>
[WatchValue("Y方向补偿")]
public double CompensateY
{
get { return _compensateY; }
set { if (_compensateY != value) { _compensateY = value; OnPropertyChanged(nameof(CompensateY)); } }
}
private double _offsetXMax;
[WatchValue("偏差限制—X偏差最大值")]
public double OffsetXMax
{
get { return _offsetXMax; }
set { if (_offsetXMax != value) { _offsetXMax = value; OnPropertyChanged(nameof(OffsetXMax)); } }
}
private double _offsetXMin;
[WatchValue("偏差限制—X偏差最小值")]
public double OffsetXMin
{
get { return _offsetXMin; }
set { if (_offsetXMin != value) { _offsetXMin = value; OnPropertyChanged(nameof(OffsetXMin)); } }
}
private double _offsetYMax;
[WatchValue("偏差限制—Y偏差最大值")]
public double OffsetYMax
{
get { return _offsetYMax; }
set { if (_offsetYMax != value) { _offsetYMax = value; OnPropertyChanged(nameof(OffsetYMax)); } }
}
private double _offsetYMin;
[WatchValue("偏差限制—Y偏差最小值")]
public double OffsetYMin
{
get { return _offsetYMin; }
set { if (_offsetYMin != value) { _offsetYMin = value; OnPropertyChanged(nameof(OffsetYMin)); } }
}
private double _wSApproachX2;
/// <summary>
/// 方片逼近位X2
/// </summary>
[WatchValue("方片逼近位X2")]
public double WSApproachX2
{
get { return _wSApproachX2; }
set { if (_wSApproachX2 != value) { _wSApproachX2 = value; OnPropertyChanged(nameof(WSApproachX2)); } }
}
private double _wSApproachY2;
/// <summary>
/// 方片逼近位Y2
/// </summary>
[WatchValue("方片逼近位Y2")]
public double WSApproachY2
{
get { return _wSApproachY2; }
set { if (_wSApproachY2 != value) { _wSApproachY2 = value; OnPropertyChanged(nameof(WSApproachY2)); } }
}
private double _stampThreRadius;
/// <summary>
/// 针印理论半径
/// </summary>
[WatchValue("针印理论半径")]
public double StampThreRadius
{
get { return _stampThreRadius; }
set { if (_stampThreRadius != value) { _stampThreRadius = value; OnPropertyChanged(nameof(StampThreRadius)); } }
}
private double _stampThreErrorRange;
/// <summary>
/// 针印误差范围
/// </summary>
[WatchValue("针印误差范围")]
public double StampThreErrorRange
{
get { return _stampThreErrorRange; }
set { if (_stampThreErrorRange != value) { _stampThreErrorRange = value; OnPropertyChanged(nameof(StampThreErrorRange)); } }
}
private double _stampMinCircularity;
/// <summary>
/// 针印最小圆度
/// </summary>
[WatchValue("针印最小圆度")]
public double StampMinCircularity
{
get { return _stampMinCircularity; }
set { if (_stampMinCircularity != value) { _stampMinCircularity = value; OnPropertyChanged(nameof(StampMinCircularity)); } }
}
private double _stampPolarity;
/// <summary>
/// 针印颜色,0黑1白
/// </summary>
[WatchValue("针印理论半径")]
public double StampPolarity
{
get { return _stampPolarity; }
set { if (_stampPolarity != value) { _stampPolarity = value; OnPropertyChanged(nameof(StampPolarity)); } }
}
private bool _isBlack = false;
public bool IsBlack
{
get
{
return _isBlack;
}
set
{
_isBlack = value;
StampPolarityUpdate();
OnPropertyChanged(nameof(IsBlack));
}
}
public void StampPolarityUpdate()
{
if (IsBlack)
{
StampPolarity = 0;
}
else
{
StampPolarity = 1;
}
}
public IParameterItem Clone()
{
NeedleXYCalibrationItemNew clone = new NeedleXYCalibrationItemNew();
clone.NeedleX1 = this.NeedleX1;
clone.NeedleZ1 = this.NeedleZ1;
clone.WSApproachX2 = this.WSApproachX2;
clone.WSApproachY2 = this.WSApproachY2;
clone.Z1WorkTime = Z1WorkTime;
clone.X1MechanicalOffset = X1MechanicalOffset;
clone.X1Calib = X1Calib;
clone.WSCalibX2 = WSCalibX2;
clone.WSCalibY2 = WSCalibY2;
clone.CompensateX = CompensateX;
clone.CompensateY = CompensateY;
clone.OffsetX = this.OffsetX;
clone.OffsetY = this.OffsetY;
clone.OffsetXMax = this.OffsetXMax;
clone.OffsetXMin = this.OffsetXMin;
clone.OffsetYMax = this.OffsetYMax;
clone.OffsetYMin = this.OffsetYMin;
clone.IsBlack = this.IsBlack;
clone.StampMinCircularity = this.StampMinCircularity;
clone.StampPolarity = this.StampPolarity;
clone.StampThreErrorRange = this.StampThreErrorRange;
clone.StampThreRadius = this.StampThreRadius;
//clone.NeedleVisionParData.Exposure = this.NeedleVisionParData.Exposure;
//clone.NeedleVisionParData.Gain = this.NeedleVisionParData.Gain;
//clone.NeedleVisionParData.LightSourceBack = this.NeedleVisionParData.LightSourceBack;
//clone.NeedleVisionParData.LightSourcePointBlue = this.NeedleVisionParData.LightSourcePointBlue;
//clone.NeedleVisionParData.LightSourcePointRed = this.NeedleVisionParData.LightSourcePointRed;
//clone.NeedleVisionParData.LightSourceRingBlue = this.NeedleVisionParData.LightSourceRingBlue;
//clone.NeedleVisionParData.LightSourceRingRed = this.NeedleVisionParData.LightSourceRingRed;
//clone.NeedleVisionParData.Z2 = this.NeedleVisionParData.Z2;
return this.MemberwiseClone() as IParameterItem;
}
}
public class NeedleTouchRecord : PropertyChangedBase, IParameterItem
{
private int _CurrentCount;
/// <summary>
/// 当前次数
/// </summary>
public int CurrentCount
{
get { return _CurrentCount; }
set
{ SetAndNotify(ref _CurrentCount, value); }
}
private double _Height;
/// <summary>
/// 高度
/// </summary>
public double Height
{
get { return _Height; }
set
{ SetAndNotify(ref _Height, value); }
}
public NeedleTouchRecord()
{
}
public NeedleTouchRecord(int count, double height)
{
CurrentCount = count;
Height = height;
}
public IParameterItem Clone()
{
return this.MemberwiseClone() as IParameterItem;
}
}
}

View File

@@ -0,0 +1,104 @@
using MainShell.Models;
using MwFramework.ManagerService;
using Stylet;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MainShell.DeviceMaintance.Model
{
[Export(typeof(IParameter))]
public class NeedlePrintCalibrateSetting : ParameterBase
{
public NeedlePrintCalibrateParameter NeedlePrintCalibrateParameter { get; set; } = new NeedlePrintCalibrateParameter();
public NeedlePrintCalibrateSetting() { }
public override void Copy(IParameter source)
{
if (source is NeedlePrintCalibrateSetting setting)
{
ReflectionExtension.Copy(NeedlePrintCalibrateParameter, setting.NeedlePrintCalibrateParameter);
}
}
}
public class NeedlePrintCalibrateParameter : PropertyChangedBase, IParameterItem
{
private MPoint _startPoint = new MPoint();
public MPoint StartPoint
{
get { return _startPoint; }
set { SetAndNotify(ref _startPoint, value); }
}
private MPoint _endPoint = new MPoint();
public MPoint EndPoint
{
get { return _endPoint; }
set { SetAndNotify(ref _endPoint, value); }
}
private MPoint _avoidancePoint = new MPoint();
public MPoint AvoidancePoint
{
get { return _avoidancePoint; }
set { SetAndNotify(ref _avoidancePoint, value); }
}
private double _z1WorkHeight;
public double Z1WorkHeight
{
get { return _z1WorkHeight; }
set { SetAndNotify(ref _z1WorkHeight, value); }
}
private double _z2WorkHeight;
public double Z2WorkHeight
{
get { return _z2WorkHeight; }
set { SetAndNotify(ref _z2WorkHeight, value); }
}
private double _xPitch;
public double Xpitch
{
get { return _xPitch; }
set { SetAndNotify(ref _xPitch, value); }
}
private double _yPitch;
public double Ypitch
{
get { return _yPitch; }
set { SetAndNotify(ref _yPitch, value); }
}
private int _usedNum;
public int UsedNum
{
get { return _usedNum; }
set { SetAndNotify(ref _usedNum, value); }
}
private int _sleepTime = 1000;
public int SleepTime
{
get { return _sleepTime; }
set { SetAndNotify(ref _sleepTime, value); }
}
public IParameterItem Clone()
{
return MemberwiseClone() as NeedlePrintCalibrateParameter;
}
}
}

View File

@@ -0,0 +1,109 @@
<UserControl x:Class="MainShell.DeviceMaintance.View.CameraAccuracyCalibrationView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MainShell.DeviceMaintance.View"
xmlns:mwControls="http://www.maxwell-gp.com/"
xmlns:customControl="clr-namespace:MainShell.Resources.CustomControl"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="700">
<UserControl.Resources>
<Style TargetType="GroupBox" BasedOn="{StaticResource GroupStepControl}"/>
<Style TargetType="Label" BasedOn="{StaticResource {x:Type Label}}">
<Setter Property="HorizontalContentAlignment" Value="Right"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Right"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Height" Value="35"/>
</Style>
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}" >
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="Margin" Value="3"/>
<Setter Property="Height" Value="35"/>
<Setter Property="Width" Value="90"/>
</Style>
</UserControl.Resources>
<Grid mwControls:ParameterAttach.DelayAcceptValue ="{Binding ParameterHelper}">
<StackPanel>
<GroupBox IsEnabled="{Binding UiEnable}" Header="【第一步】针尖高度设置">
<customControl:AxisMoveControl LableContent1="Z1(mm)"
Value1="{Binding QuickNeedlePrintParameter.Z1InkHeight}"
IsAllShow="False"
ReadCommand="{mwControls:Action TeachZ1Pos}"
IsReadOnly="False"
MoveCommand="{mwControls:Action MoveToZ1Pos}"/>
</GroupBox>
<GroupBox IsEnabled="{Binding UiEnable}" Header="【第二步】WS避让位">
<GroupBox.Content>
<customControl:AxisMoveControl LableContent1="X2(mm)"
Value1="{Binding QuickNeedlePrintParameter.AvoidancePoint.PointX}"
LableContent2="Y2(mm)"
Value2="{Binding QuickNeedlePrintParameter.AvoidancePoint.PointY}"
ReadCommand="{mwControls:Action TeachWSPos}"
MoveCommand="{mwControls:Action MoveToWsPos}"
IsReadOnly="True"/>
<!--<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Label VerticalAlignment="Center" Content="X2:"/>
<mwControls:NumberBox Value="{Binding QuickNeedlePrintParameter.AvoidancePoint.PointX}" IsReadOnly="True" Width="80" Margin="4,0" />
<Label VerticalAlignment="Center" Content="Y2:"/>
<mwControls:NumberBox Value="{Binding QuickNeedlePrintParameter.AvoidancePoint.PointY}" IsReadOnly="True" Width="80" Margin="4,0" />
<Button Margin="2,0" Click="{mwControls:Action TeachWSPos}" Content="示教"/>
<Button Margin="2,0" Click="{mwControls:Action MoveToWsPos}" Content="移动"/>
</StackPanel>-->
</GroupBox.Content>
</GroupBox>
<GroupBox IsEnabled="{Binding UiEnable}" Margin="2" Header="【第三步】墨水位置">
<GroupBox.Content>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<customControl:AxisMoveControl LableContent1="X2(mm)"
Value1="{Binding QuickNeedlePrintParameter.InkPos.PointX}"
LableContent2="Y2(mm)"
Value2="{Binding QuickNeedlePrintParameter.InkPos.PointY}"
ReadCommand="{mwControls:Action TeachInkPos}"
MoveCommand="{mwControls:Action MoveToInkPos}"
IsReadOnly="True"/>
<Button Margin="2,0" HorizontalAlignment="Right" Click="{mwControls:Action InkSmearing}" Content="涂墨"/>
</Grid>
</GroupBox.Content>
</GroupBox>
<GroupBox Header="【第四步】快打针印参数设置">
<StackPanel>
<StackPanel Orientation="Horizontal">
<Label VerticalAlignment="Center" HorizontalAlignment="Left" Content="打件颗数:"/>
<mwControls:IntNumberBox Value="{Binding BondingNumber}" IsReadOnly="True" Width="75" Margin="4,0" />
<Button IsEnabled="{Binding UiEnable}" Margin="2,0" Click="{mwControls:Action PositiveBonding}" Content="快打正向"/>
<Button IsEnabled="{Binding UiEnable}" Margin="2,0" Click="{mwControls:Action NegativeBonding}" Content="快打反向"/>
<Button IsEnabled="{Binding UiEnable}" Margin="2,0" Click="{mwControls:Action SlowBonding}" Content="补打"/>
<Button Margin="2,0" Content="停止打件" Click="{mwControls:Action StopBonding}"/>
</StackPanel>
<Label Content="正向针印查看:" HorizontalAlignment="Left"/>
<StackPanel IsEnabled="{Binding UiEnable}" HorizontalAlignment="Left" Orientation="Horizontal">
<Button Margin="2,0" IsEnabled="{Binding CanLastPositiveIndex}" Click="{mwControls:Action LastPositiveIndex}" Content="上一个"/>
<Button Margin="2,0" IsEnabled="{Binding CanNextPositiveIndex}" Click="{mwControls:Action NextPositiveIndex}" Content="下一个"/>
</StackPanel>
<Label Content="反向针印查看:" HorizontalAlignment="Left"/>
<StackPanel IsEnabled="{Binding UiEnable}" HorizontalAlignment="Left" Orientation="Horizontal">
<Button Margin="2,0" IsEnabled="{Binding CanLastNegativeIndex}" Click="{mwControls:Action LastNegativeIndex}" Content="上一个"/>
<Button Margin="2,0" IsEnabled="{Binding CanNextNegativeIndex}" Click="{mwControls:Action NextNegativeIndex}" Content="下一个"/>
</StackPanel>
<Label Content="补打针印查看:" HorizontalAlignment="Left"/>
<StackPanel IsEnabled="{Binding UiEnable}" HorizontalAlignment="Left" Orientation="Horizontal">
<Button Margin="2,0" IsEnabled="{Binding CanLastSlowIndex}" Click="{mwControls:Action LastSlowIndex}" Content="上一个"/>
<Button Margin="2,0" IsEnabled="{Binding CanNextSlowIndex}" Click="{mwControls:Action NextSlowIndex}" Content="下一个"/>
</StackPanel>
<Button IsEnabled="{Binding UiEnable}" HorizontalAlignment="Right" Click="{mwControls:Action SaveParameter}" Margin="10,2" Content="保存"/>
</StackPanel>
</GroupBox>
</StackPanel>
</Grid>
</UserControl>

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace MainShell.DeviceMaintance.View
{
/// <summary>
/// CameraAccuracyCalibrationView.xaml 的交互逻辑
/// </summary>
public partial class CameraAccuracyCalibrationView : UserControl
{
public CameraAccuracyCalibrationView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,176 @@
<UserControl x:Class="MainShell.DeviceMaintance.View.CylinderView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MainShell.DeviceMaintance.View"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<Style x:Key="CylinderCardStyle" TargetType="Border">
<Setter Property="Background" Value="#F8FAFD"/>
<Setter Property="BorderBrush" Value="#D4DCE8"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="8"/>
<Setter Property="Padding" Value="14"/>
<Setter Property="Margin" Value="0,0,0,12"/>
</Style>
<Style x:Key="CylinderDotStyle" TargetType="Ellipse">
<Setter Property="Width" Value="10"/>
<Setter Property="Height" Value="10"/>
<Setter Property="Fill" Value="#CBD5E1"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsOn}" Value="True">
<Setter Property="Fill" Value="#22C55E"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="CylinderActionButtonStyle" TargetType="Button">
<Setter Property="Foreground" Value="White"/>
<Setter Property="Padding" Value="12,6"/>
<Setter Property="MinWidth" Value="90"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Margin" Value="0,0,8,0"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"
CornerRadius="18"
Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid Background="#EDF1F7">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Margin="12,12,12,8">
<TextBlock Text="CYLINDER CONTROL / 气缸控制" FontSize="20" FontWeight="Bold" Foreground="#0F3B7A"/>
<Border Background="#EFF6FF" BorderBrush="#BFDBFE" BorderThickness="1" CornerRadius="6" Padding="10" Margin="0,8,0,0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="最近操作:" Foreground="#475569" Margin="0,0,8,0"/>
<TextBlock Text="{Binding PageState.LastActionTime, StringFormat={}{0:HH:mm:ss}}" Foreground="#0F172A" FontWeight="Bold" Margin="0,0,12,0"/>
<TextBlock Text="{Binding PageState.LastActionMessage}" Foreground="#1D4ED8" FontWeight="SemiBold" TextWrapping="Wrap"/>
</StackPanel>
</Border>
</StackPanel>
<ScrollViewer Grid.Row="1" Margin="12,0,12,12" VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding PageState.Cylinders}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Style="{StaticResource CylinderCardStyle}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel>
<TextBlock Text="{Binding Name}" FontSize="18" FontWeight="Bold" Foreground="#0F3B7A"/>
<TextBlock Text="{Binding Description}" Foreground="#64748B" Margin="0,4,0,0"/>
</StackPanel>
<Border Grid.Column="1" Background="#FEF3C7" CornerRadius="12" Padding="10,4" VerticalAlignment="Center">
<TextBlock Text="{Binding ControlTypeText}" Foreground="#92400E" FontWeight="Bold"/>
</Border>
</Grid>
<Grid Grid.Row="1" Margin="0,12,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Margin="0,0,16,0">
<TextBlock Text="控制" Foreground="#1D4ED8" FontWeight="Bold" Margin="0,0,0,8"/>
<StackPanel Orientation="Horizontal">
<Button Content="伸出"
Command="{Binding ExtendCommand}"
Background="#2563EB"
BorderBrush="#2563EB"
Style="{StaticResource CylinderActionButtonStyle}"/>
<Button Content="缩回"
Command="{Binding RetractCommand}"
Background="#F97316"
BorderBrush="#F97316"
Style="{StaticResource CylinderActionButtonStyle}"/>
</StackPanel>
</StackPanel>
<StackPanel Grid.Column="1" Margin="0,0,16,0">
<TextBlock Text="输出信号" Foreground="#C2410C" FontWeight="Bold" Margin="0,0,0,8"/>
<ItemsControl ItemsSource="{Binding OutputSignals}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="#FFF7ED" BorderBrush="#FED7AA" BorderThickness="1" CornerRadius="4" Padding="8,6" Margin="0,0,0,6">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Ellipse Style="{StaticResource CylinderDotStyle}" VerticalAlignment="Center" Margin="0,0,8,0"/>
<StackPanel Grid.Column="1">
<TextBlock Text="{Binding Name}" Foreground="#9A3412" FontWeight="SemiBold"/>
<TextBlock Text="{Binding IoNameText}" Foreground="#7C2D12" FontSize="11" TextWrapping="Wrap"/>
<TextBlock Text="{Binding LineNo, StringFormat=线标:{0}}" Foreground="#C2410C" FontSize="11"/>
</StackPanel>
<TextBlock Grid.Column="2" Text="{Binding StateText}" Foreground="#C2410C" FontWeight="Bold"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Text="反馈信号" Foreground="#166534" FontWeight="Bold" Margin="0,0,0,8"/>
<ItemsControl ItemsSource="{Binding FeedbackSignals}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="#F0FDF4" BorderBrush="#BBF7D0" BorderThickness="1" CornerRadius="4" Padding="8,6" Margin="0,0,0,6">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Ellipse Style="{StaticResource CylinderDotStyle}" VerticalAlignment="Center" Margin="0,0,8,0"/>
<StackPanel Grid.Column="1">
<TextBlock Text="{Binding Name}" Foreground="#166534" FontWeight="SemiBold"/>
<TextBlock Text="{Binding IoNameText}" Foreground="#15803D" FontSize="11" TextWrapping="Wrap"/>
<TextBlock Text="{Binding LineNo, StringFormat=线标:{0}}" Foreground="#15803D" FontSize="11"/>
</StackPanel>
<TextBlock Grid.Column="2" Text="{Binding StateText}" Foreground="#166534" FontWeight="Bold"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</UserControl>

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace MainShell.DeviceMaintance.View
{
/// <summary>
/// CylinderView.xaml 的交互逻辑
/// </summary>
public partial class CylinderView : UserControl
{
public CylinderView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,310 @@
<UserControl x:Class="MainShell.DeviceMaintance.View.DeviceIoView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="900">
<UserControl.Resources>
<Style x:Key="IoCardStyle" TargetType="Border">
<Setter Property="Background" Value="#F8FAFD"/>
<Setter Property="BorderBrush" Value="#D4DCE8"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="8"/>
<Setter Property="Margin" Value="0,0,0,12"/>
<Setter Property="Padding" Value="14"/>
</Style>
<Style x:Key="StatusBadgeBorderStyle" TargetType="Border">
<Setter Property="CornerRadius" Value="12"/>
<Setter Property="Padding" Value="10,4"/>
<Setter Property="Margin" Value="0,0,8,0"/>
<Setter Property="Background" Value="#E2E8F0"/>
</Style>
<Style x:Key="InputStatusDotStyle" TargetType="Ellipse">
<Setter Property="Width" Value="10"/>
<Setter Property="Height" Value="10"/>
<Setter Property="Fill" Value="#93C5FD"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsOn}" Value="True">
<Setter Property="Fill" Value="#2563EB"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="OutputStatusDotStyle" TargetType="Ellipse">
<Setter Property="Width" Value="10"/>
<Setter Property="Height" Value="10"/>
<Setter Property="Fill" Value="#FCD34D"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsOn}" Value="True">
<Setter Property="Fill" Value="#F97316"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="InputItemBorderStyle" TargetType="Border">
<Setter Property="Background" Value="#EFF6FF"/>
<Setter Property="BorderBrush" Value="#DBEAFE"/>
<Setter Property="BorderThickness" Value="0,0,0,1"/>
<Setter Property="Padding" Value="8,6"/>
<Setter Property="Margin" Value="0,0,0,4"/>
<Setter Property="CornerRadius" Value="4"/>
</Style>
<Style x:Key="OutputItemBorderStyle" TargetType="Border">
<Setter Property="Background" Value="#FFF7ED"/>
<Setter Property="BorderBrush" Value="#FED7AA"/>
<Setter Property="BorderThickness" Value="0,0,0,1"/>
<Setter Property="Padding" Value="8,6"/>
<Setter Property="Margin" Value="0,0,0,4"/>
<Setter Property="CornerRadius" Value="4"/>
</Style>
<Style x:Key="IoSectionBorderStyle" TargetType="Border">
<Setter Property="CornerRadius" Value="6"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="10"/>
</Style>
<Style x:Key="IoOutputToggleButtonStyle" TargetType="ToggleButton">
<Setter Property="Width" Value="90"/>
<Setter Property="Height" Value="30"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border x:Name="Root" Background="#CBD5E1" BorderBrush="#94A3B8" BorderThickness="1" CornerRadius="15">
<Grid Margin="2">
<Border x:Name="Knob" Width="24" Height="24" Background="White" CornerRadius="12" HorizontalAlignment="Left"/>
<TextBlock x:Name="ToggleLabel" Text="OFF" Foreground="#334155" FontWeight="Bold" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,10,0"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Root" Property="Background" Value="#16A34A"/>
<Setter TargetName="Root" Property="BorderBrush" Value="#16A34A"/>
<Setter TargetName="Knob" Property="HorizontalAlignment" Value="Right"/>
<Setter TargetName="ToggleLabel" Property="Text" Value="ON"/>
<Setter TargetName="ToggleLabel" Property="Foreground" Value="White"/>
<Setter TargetName="ToggleLabel" Property="HorizontalAlignment" Value="Left"/>
<Setter TargetName="ToggleLabel" Property="Margin" Value="10,0,0,0"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Root" Property="Opacity" Value="0.45"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid Background="#EDF1F7">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Margin="10,10,10,8">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="DEVICE IO MONITOR / 设备IO监控" FontSize="20" FontWeight="Bold" Foreground="#0F3B7A"/>
<StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center">
<Border Style="{StaticResource StatusBadgeBorderStyle}">
<TextBlock Text="{Binding PageState.LastRefreshTime, StringFormat=刷新:{0:HH:mm:ss}}" Foreground="#475569"/>
</Border>
<Border>
<Border.Style>
<Style TargetType="Border" BasedOn="{StaticResource StatusBadgeBorderStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding PageState.IsOnline}" Value="True">
<Setter Property="Background" Value="#DCFCE7"/>
</DataTrigger>
<DataTrigger Binding="{Binding PageState.IsOnline}" Value="False">
<Setter Property="Background" Value="#FEE2E2"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBlock Text="{Binding PageState.OnlineText}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="#B91C1C"/>
<Style.Triggers>
<DataTrigger Binding="{Binding PageState.IsOnline}" Value="True">
<Setter Property="Foreground" Value="#166534"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Border>
</StackPanel>
</Grid>
<Border Margin="0,8,0,0" Padding="12,6">
<Border.Style>
<Style TargetType="Border" BasedOn="{StaticResource StatusBadgeBorderStyle}">
<Setter Property="Background" Value="#EFF6FF"/>
<Style.Triggers>
<DataTrigger Binding="{Binding PageState.IsWriteSuccess}" Value="True">
<Setter Property="Background" Value="#DCFCE7"/>
</DataTrigger>
<DataTrigger Binding="{Binding PageState.IsWriteSuccess}" Value="False">
<Setter Property="Background" Value="#FEF3C7"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding PageState.LastWriteTime, StringFormat=写入时间:{0:HH:mm:ss}}" Foreground="#475569" Margin="0,0,14,0"/>
<TextBlock Text="{Binding PageState.LastWriteMessage}" FontWeight="SemiBold" TextWrapping="Wrap"/>
</StackPanel>
</Border>
</StackPanel>
<ScrollViewer Grid.Row="1" Margin="10,0,10,10" VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding PageState.Modules}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Style="{StaticResource IoCardStyle}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Name}" FontSize="18" FontWeight="Bold" Foreground="#0F3B7A"/>
<Grid Grid.Row="1" Margin="0,10,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition>
<ColumnDefinition.Style>
<Style TargetType="ColumnDefinition">
<Setter Property="Width" Value="*"/>
<Style.Triggers>
<DataTrigger Binding="{Binding HasInputs}" Value="False">
<Setter Property="Width" Value="0"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ColumnDefinition.Style>
</ColumnDefinition>
<ColumnDefinition>
<ColumnDefinition.Style>
<Style TargetType="ColumnDefinition">
<Setter Property="Width" Value="*"/>
<Style.Triggers>
<DataTrigger Binding="{Binding HasOutputs}" Value="False">
<Setter Property="Width" Value="0"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ColumnDefinition.Style>
</ColumnDefinition>
</Grid.ColumnDefinitions>
<Border BorderBrush="#BFDBFE" Background="#F8FBFF">
<Border.Style>
<Style TargetType="Border" BasedOn="{StaticResource IoSectionBorderStyle}">
<Setter Property="Margin" Value="0,0,6,0"/>
<Style.Triggers>
<DataTrigger Binding="{Binding HasInputs}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
<DataTrigger Binding="{Binding HasOutputs}" Value="False">
<Setter Property="Margin" Value="0"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<StackPanel>
<TextBlock Text="输入 IO" Foreground="#1D4ED8" FontWeight="Bold" Margin="0,0,0,8"/>
<ItemsControl ItemsSource="{Binding InputPoints}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Style="{StaticResource InputItemBorderStyle}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Ellipse Style="{StaticResource InputStatusDotStyle}" VerticalAlignment="Center" Margin="0,0,8,0"/>
<StackPanel Grid.Column="1">
<TextBlock Text="{Binding Description}" Foreground="#1E3A8A" FontWeight="SemiBold"/>
<TextBlock Text="{Binding StationNo, StringFormat=站号:{0}}" Foreground="#1D4ED8" FontSize="11"/>
<TextBlock Text="{Binding LineNo, StringFormat=线标:{0}}" Foreground="#1D4ED8" FontSize="11"/>
<TextBlock Text="{Binding Name}" Foreground="#64748B" FontSize="11" TextWrapping="Wrap"/>
</StackPanel>
<TextBlock Grid.Column="2" Text="{Binding StateText}" VerticalAlignment="Center" Foreground="#1E40AF" FontWeight="Bold"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
<Border Grid.Column="1" BorderBrush="#FDBA74" Background="#FFF9F2">
<Border.Style>
<Style TargetType="Border" BasedOn="{StaticResource IoSectionBorderStyle}">
<Setter Property="Margin" Value="6,0,0,0"/>
<Style.Triggers>
<DataTrigger Binding="{Binding HasOutputs}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
<DataTrigger Binding="{Binding HasInputs}" Value="False">
<Setter Property="Margin" Value="0"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<StackPanel>
<TextBlock Text="输出 IO" Foreground="#C2410C" FontWeight="Bold" Margin="0,0,0,8"/>
<ItemsControl ItemsSource="{Binding OutputPoints}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Style="{StaticResource OutputItemBorderStyle}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Ellipse Style="{StaticResource OutputStatusDotStyle}" VerticalAlignment="Center" Margin="0,0,8,0"/>
<StackPanel Grid.Column="1">
<TextBlock Text="{Binding Description}" Foreground="#9A3412" FontWeight="SemiBold"/>
<TextBlock Text="{Binding StationNo, StringFormat=站号:{0}}" Foreground="#C2410C" FontSize="11"/>
<TextBlock Text="{Binding LineNo, StringFormat=线标:{0}}" Foreground="#C2410C" FontSize="11"/>
<TextBlock Text="{Binding Name}" Foreground="#7C2D12" FontSize="11" TextWrapping="Wrap"/>
</StackPanel>
<TextBlock Grid.Column="2" Text="{Binding StateText}" Margin="0,0,10,0" VerticalAlignment="Center" Foreground="#C2410C" FontWeight="Bold"/>
<ToggleButton Grid.Column="3"
Style="{StaticResource IoOutputToggleButtonStyle}"
IsChecked="{Binding IsOn, Mode=OneWay}"
Command="{Binding ToggleCommand}"
IsEnabled="{Binding CanWrite}"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
</Grid>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</UserControl>

View File

@@ -0,0 +1,12 @@
using System.Windows.Controls;
namespace MainShell.DeviceMaintance.View
{
public partial class DeviceIoView : UserControl
{
public DeviceIoView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,38 @@
<UserControl x:Class="MainShell.DeviceMaintance.View.DeviceMaintanceView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MainShell.DeviceMaintance.View"
xmlns:mw="http://www.maxwell-gp.com/"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Margin="-40,0,0,0" Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<mw:SideMenu ItemsSource="{Binding MenuItemWraps}"
SelectedItem="{Binding SelectedMenuItem, Mode=TwoWay}"
Grid.Row ="0" Width="180"
ExpandMode="Accordion"
AutoSelect="True"
>
<mw:SideMenu.ItemContainerStyle>
<Style TargetType="{x:Type mw:SideMenuItem}" BasedOn="{StaticResource SideMenuItemHeaderAccordionBaseStyle}">
<Setter Property="Header" Value="{Binding Header}" />
<Setter Property="Tag" Value="{Binding Tag}" />
</Style>
</mw:SideMenu.ItemContainerStyle>
</mw:SideMenu>
</Grid>
<ContentControl Margin="5,0" Grid.Column="1" mw:View.Model="{Binding CurrentScreen}"/>
</Grid>
</UserControl>

Some files were not shown because too many files have changed in this diff Show More