kazelee
2025-05-13 78603aecf895b2615ea5bdc1908b54c0f01a1880
初始化仓库,修复部分代码问题,初步完成称重及确定终点的逻辑
91个文件已添加
9244 ■■■■■ 已修改文件
.editorconfig 178 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.JunzhouLangchao/FileContentIndex/b5d4cc0d-d072-4a06-b41d-eed5482c7ae2.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.JunzhouLangchao/FileContentIndex/read.lock 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Langchao/FileContentIndex/095323c9-fab1-4a3d-bbb9-e016bdc026ba.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Langchao/FileContentIndex/4a385bfe-ecd2-4870-b27e-b29514f713d2.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Langchao/FileContentIndex/64fc2de3-4821-4c46-8f63-3c1f84a578ce.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Langchao/FileContentIndex/read.lock 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/53a0c388-cbc5-4b2b-b4eb-cd92a4ce794b.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/76260fe3-41d2-41f5-aa6c-8c9e109555f6.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/8840fa70-8c16-4a47-a95b-02e5437b8c55.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/8c43b3a9-b113-4587-b0a9-056dfab442ea.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/read.lock 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/9c76bfe5-6ebd-4e0c-a47c-e101f5269325.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/c7280935-f5e0-40f2-8192-c372e93baa35.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/d69ea063-5070-40f2-bd3b-49ed46a407f3.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/f4b60fb6-056e-496f-be20-888bbf15af32.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/read.lock 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.LNYKAG/FileContentIndex/3911a5fd-5b86-4edf-85b1-ca6ed438a43d.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.LNYKAG/FileContentIndex/read.lock 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.Template.csproj.dtbcache.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.WeiLi/FileContentIndex/57367193-8890-401b-95eb-fa75f34fc9b1.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
App.config 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
AppStart/Config.cs 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
AppStart/Settings.cs 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
AppStart/Startup.cs 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
AppStart/SwaggerConfig.cs 255 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
AppStart/SwaggerControllerDescProvider.cs 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Consts/AgvStateCode.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Consts/AgvStateName.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Consts/AreaCode.cs 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Consts/AreaName.cs 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Consts/LockStateCode.cs 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Consts/LockStateName.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Consts/TaskName.cs 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Controllers/AgvController.cs 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Controllers/ApiModel.cs 232 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Controllers/DebugController.cs 288 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Controllers/ErpController.cs 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Controllers/MoboxController.cs 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Controllers/WmsController.cs 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Devices/ModbusHelper.cs 450 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Devices/OpcUaHelper.cs 192 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Devices/PlcHelper.cs 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Devices/S7Helper.cs 423 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Devices/ScanCodeHelper.cs 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Devices/TcpClient.cs 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Devices/TcpServer.cs 251 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dispatch/GZRobot.cs 504 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dispatch/HanAo.cs 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dispatch/HostToAGV.cs 550 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dispatch/NDC.cs 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dispatch/NDCApi.cs 271 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dispatch/NDCHelper.cs 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dtos/Request/AgvRequest.cs 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dtos/Request/MoboxRequest.cs 355 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dtos/Response/AgvResponse.cs 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dtos/Response/MoboxResponse.cs 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3.AnGang.csproj 306 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3.AnGang.sln 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Helpers/ContainerHelper.cs 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Helpers/DbHelper.cs 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Helpers/DeviceProcess.cs 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Helpers/HttpHelper.cs 286 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Helpers/LocationHelper.cs 548 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Helpers/LogHelper.cs 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Helpers/ResultHelper.cs 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Helpers/SYSHelper.cs 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Helpers/TaskHelper.cs 218 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Helpers/WCSHelper.cs 240 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Helpers/WMSHelper.cs 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/BaseModel.cs 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_CAR_IN.cs 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_CG_Detail.cs 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_Container.cs 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_Loc_Container.cs 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_Location.cs 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_Task.cs 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_Task_Action.cs 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_WorkOrder.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/Table.cs 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Program.cs 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Properties/AssemblyInfo.cs 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServiceCore/Monitor.cs 171 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServiceCore/WCSCore.cs 205 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServiceCore/WMSCore.cs 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Services/AgvService.cs 230 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Services/DebugService.cs 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Services/MoboxService.cs 367 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
config/config.json 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages.config 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
swagger.js 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.editorconfig
New file
@@ -0,0 +1,178 @@
[*.cs]
# Default severity for all analyzer diagnostics
dotnet_analyzer_diagnostic.severity = none
# CS1591: 缺少对公共可见类型或成员的 XML 注释
dotnet_diagnostic.CS1591.severity = none
[*.cs]
#### 命名样式 ####
# 命名规则
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.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
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.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
csharp_using_directive_placement = outside_namespace:silent
csharp_style_expression_bodied_methods = false:silent
csharp_style_expression_bodied_constructors = false:silent
csharp_style_expression_bodied_operators = false:silent
csharp_style_expression_bodied_properties = true:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_accessors = true:silent
csharp_style_expression_bodied_lambdas = true:silent
csharp_style_expression_bodied_local_functions = false:silent
csharp_style_conditional_delegate_call = true:suggestion
csharp_style_var_for_built_in_types = false:silent
csharp_style_var_when_type_is_apparent = false:silent
csharp_style_var_elsewhere = false:silent
csharp_space_around_binary_operators = before_and_after
csharp_indent_labels = one_less_than_current
dotnet_sort_system_directives_first = true
dotnet_separate_import_directive_groups = true
csharp_prefer_simple_using_statement = true:suggestion
csharp_prefer_braces = true:silent
csharp_style_namespace_declarations = block_scoped:silent
csharp_style_prefer_method_group_conversion = true:silent
csharp_style_prefer_top_level_statements = true:silent
csharp_prefer_static_local_function = true:suggestion
csharp_style_prefer_readonly_struct = true:suggestion
csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent
csharp_style_prefer_switch_expression = true:suggestion
csharp_style_prefer_pattern_matching = true:silent
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
csharp_style_prefer_not_pattern = true:suggestion
csharp_style_prefer_extended_property_pattern = true:suggestion
csharp_style_throw_expression = true:suggestion
csharp_style_prefer_null_check_over_type_check = true:suggestion
csharp_prefer_simple_default_expression = true:suggestion
csharp_style_prefer_local_over_anonymous_function = true:suggestion
csharp_style_prefer_index_operator = true:suggestion
csharp_style_prefer_range_operator = true:suggestion
csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
[*.vb]
#### 命名样式 ####
# 命名规则
dotnet_naming_rule.interface_should_be_以_i_开始.severity = suggestion
dotnet_naming_rule.interface_should_be_以_i_开始.symbols = interface
dotnet_naming_rule.interface_should_be_以_i_开始.style = 以_i_开始
dotnet_naming_rule.类型_should_be_帕斯卡拼写法.severity = suggestion
dotnet_naming_rule.类型_should_be_帕斯卡拼写法.symbols = 类型
dotnet_naming_rule.类型_should_be_帕斯卡拼写法.style = 帕斯卡拼写法
dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.severity = suggestion
dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.symbols = 非字段成员
dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.style = 帕斯卡拼写法
# 符号规范
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.类型.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.类型.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
dotnet_naming_symbols.类型.required_modifiers =
dotnet_naming_symbols.非字段成员.applicable_kinds = property, event, method
dotnet_naming_symbols.非字段成员.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
dotnet_naming_symbols.非字段成员.required_modifiers =
# 命名样式
dotnet_naming_style.以_i_开始.required_prefix = I
dotnet_naming_style.以_i_开始.required_suffix =
dotnet_naming_style.以_i_开始.word_separator =
dotnet_naming_style.以_i_开始.capitalization = pascal_case
dotnet_naming_style.帕斯卡拼写法.required_prefix =
dotnet_naming_style.帕斯卡拼写法.required_suffix =
dotnet_naming_style.帕斯卡拼写法.word_separator =
dotnet_naming_style.帕斯卡拼写法.capitalization = pascal_case
dotnet_naming_style.帕斯卡拼写法.required_prefix =
dotnet_naming_style.帕斯卡拼写法.required_suffix =
dotnet_naming_style.帕斯卡拼写法.word_separator =
dotnet_naming_style.帕斯卡拼写法.capitalization = pascal_case
[*.{cs,vb}]
end_of_line = crlf
dotnet_style_qualification_for_field = false:silent
dotnet_style_qualification_for_property = false:silent
dotnet_style_qualification_for_method = false:silent
dotnet_style_qualification_for_event = false:silent
tab_width = 4
indent_size = 4
dotnet_style_operator_placement_when_wrapping = beginning_of_line
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
dotnet_code_quality_unused_parameters = all:suggestion
dotnet_style_readonly_field = true:suggestion
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
dotnet_style_allow_multiple_blank_lines_experimental = true:silent
dotnet_style_allow_statement_immediately_after_block_experimental = true:silent
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
dotnet_style_prefer_auto_properties = true:silent
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
dotnet_style_prefer_conditional_expression_over_return = true:silent
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_compound_assignment = true:suggestion
dotnet_style_prefer_simplified_interpolation = true:suggestion
dotnet_style_namespace_match_folder = true:suggestion
.vs/HH.WCS.JunzhouLangchao/FileContentIndex/b5d4cc0d-d072-4a06-b41d-eed5482c7ae2.vsidx
Binary files differ
.vs/HH.WCS.JunzhouLangchao/FileContentIndex/read.lock
.vs/HH.WCS.Langchao/FileContentIndex/095323c9-fab1-4a3d-bbb9-e016bdc026ba.vsidx
Binary files differ
.vs/HH.WCS.Langchao/FileContentIndex/4a385bfe-ecd2-4870-b27e-b29514f713d2.vsidx
Binary files differ
.vs/HH.WCS.Langchao/FileContentIndex/64fc2de3-4821-4c46-8f63-3c1f84a578ce.vsidx
Binary files differ
.vs/HH.WCS.Langchao/FileContentIndex/read.lock
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/53a0c388-cbc5-4b2b-b4eb-cd92a4ce794b.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/76260fe3-41d2-41f5-aa6c-8c9e109555f6.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/8840fa70-8c16-4a47-a95b-02e5437b8c55.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/8c43b3a9-b113-4587-b0a9-056dfab442ea.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/read.lock
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/9c76bfe5-6ebd-4e0c-a47c-e101f5269325.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/c7280935-f5e0-40f2-8192-c372e93baa35.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/d69ea063-5070-40f2-bd3b-49ed46a407f3.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/f4b60fb6-056e-496f-be20-888bbf15af32.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/read.lock
.vs/HH.WCS.Mobox3.LNYKAG/FileContentIndex/3911a5fd-5b86-4edf-85b1-ca6ed438a43d.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.LNYKAG/FileContentIndex/read.lock
.vs/HH.WCS.Mobox3.Template.csproj.dtbcache.json
New file
@@ -0,0 +1 @@
{"RootPath":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\HH.WCS.Mobox3.Template","ProjectFileName":"HH.WCS.Mobox3.Template.csproj","Configuration":"Debug|AnyCPU","FrameworkPath":"","Sources":[{"SourceFile":"api\\MoboxController.cs"},{"SourceFile":"api\\AgvController.cs"},{"SourceFile":"api\\ApiModel.cs"},{"SourceFile":"core\\WMSCore.cs"},{"SourceFile":"device\\ModbusHelper.cs"},{"SourceFile":"device\\PlcHelper.cs"},{"SourceFile":"device\\TcpClient.cs"},{"SourceFile":"device\\TcpServer.cs"},{"SourceFile":"dispatch\\GZRobot.cs"},{"SourceFile":"dispatch\\NDC.cs"},{"SourceFile":"core\\Monitor.cs"},{"SourceFile":"models\\BaseModel.cs"},{"SourceFile":"models\\Area.cs"},{"SourceFile":"models\\TN_ASN_Detail.cs"},{"SourceFile":"models\\TN_ASN_Order.cs"},{"SourceFile":"models\\TN_AZ_Inventory.cs"},{"SourceFile":"models\\TN_Business_Source.cs"},{"SourceFile":"models\\CntrItemRel.cs"},{"SourceFile":"models\\TN_Check_Detail.cs"},{"SourceFile":"models\\TN_Check_List.cs"},{"SourceFile":"models\\TN_Check_Order.cs"},{"SourceFile":"models\\Container.cs"},{"SourceFile":"models\\TN_Container_Good.cs"},{"SourceFile":"models\\TN_Equipment.cs"},{"SourceFile":"models\\TN_Factory.cs"},{"SourceFile":"models\\TN_Function_Area.cs"},{"SourceFile":"models\\TN_Inspect_Detail.cs"},{"SourceFile":"models\\TN_Inspect_Order.cs"},{"SourceFile":"models\\TN_Inspect_Record.cs"},{"SourceFile":"models\\TN_LC_Log.cs"},{"SourceFile":"models\\Location.cs"},{"SourceFile":"models\\TN_Lock.cs"},{"SourceFile":"models\\LocCntrRel.cs"},{"SourceFile":"models\\TN_Loc_EQ_Link.cs"},{"SourceFile":"models\\TN_Material.cs"},{"SourceFile":"models\\TN_MQ_EQAction.cs"},{"SourceFile":"models\\TN_MQ_EQAction_Msg.cs"},{"SourceFile":"models\\TN_OnOff_Shelves.cs"},{"SourceFile":"models\\TN_OOS_Detail.cs"},{"SourceFile":"models\\TN_OOS_Order.cs"},{"SourceFile":"models\\WMSTask.cs"},{"SourceFile":"models\\TN_Outbound_Detail.cs"},{"SourceFile":"models\\TN_Outbound_Order.cs"},{"SourceFile":"models\\TN_Purchase_Detail.cs"},{"SourceFile":"models\\TN_Purchase_Order.cs"},{"SourceFile":"models\\TN_Putaway_Detail.cs"},{"SourceFile":"models\\TN_Putaway_Order.cs"},{"SourceFile":"models\\TN_Receipt_Detail.cs"},{"SourceFile":"models\\TN_Receipt_Order.cs"},{"SourceFile":"models\\ShippingDetail.cs"},{"SourceFile":"models\\ShippingOrder.cs"},{"SourceFile":"models\\TN_Sorting_Compose.cs"},{"SourceFile":"models\\TN_Sorting_Detail.cs"},{"SourceFile":"models\\SortingOrder.cs"},{"SourceFile":"models\\TN_Sorting_Result.cs"},{"SourceFile":"models\\TN_Supplier.cs"},{"SourceFile":"models\\WCSTask.cs"},{"SourceFile":"models\\TaskAction.cs"},{"SourceFile":"models\\TN_Warehouse.cs"},{"SourceFile":"process\\DeviceProcess.cs"},{"SourceFile":"core\\WCSCore.cs"},{"SourceFile":"api\\WmsController.cs"},{"SourceFile":"api\\ApiHelper.cs"},{"SourceFile":"dispatch\\HostToAGV.cs"},{"SourceFile":"process\\TaskProcess.cs"},{"SourceFile":"util\\LogHelper.cs"},{"SourceFile":"util\\StrHelper.cs"},{"SourceFile":"util\\STAttribute.cs"},{"SourceFile":"wms\\ContainerHelper.cs"},{"SourceFile":"wms\\LocationHelper.cs"},{"SourceFile":"wms\\WMSHelper.cs"},{"SourceFile":"wms\\SYSHelper.cs"},{"SourceFile":"wms\\TEST.cs"},{"SourceFile":"device\\OITcpHelper.cs"},{"SourceFile":"Program.cs"},{"SourceFile":"Properties\\AssemblyInfo.cs"},{"SourceFile":"util\\Settings.cs"},{"SourceFile":"util\\SqlHelper.cs"},{"SourceFile":"api\\Startup.cs"},{"SourceFile":"dispatch\\NDCHelper.cs"},{"SourceFile":"util\\HttpHelper.cs"},{"SourceFile":"wms\\NormalArea.cs"},{"SourceFile":"wms\\WCSHelper.cs"},{"SourceFile":"obj\\Debug\\.NETFramework,Version=v4.6.1.AssemblyAttributes.cs"}],"References":[{"Reference":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\HH.WCS.Mobox3.Template\\packages\\EasyModbusTCP.5.6.0\\lib\\net40\\EasyModbus.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\packages\\Microsoft.Bcl.AsyncInterfaces.7.0.0\\lib\\netstandard2.0\\Microsoft.Bcl.AsyncInterfaces.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\Microsoft.CSharp.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\packages\\Microsoft.Owin.4.2.2\\lib\\net45\\Microsoft.Owin.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\packages\\Microsoft.Owin.Host.HttpListener.4.2.2\\lib\\net45\\Microsoft.Owin.Host.HttpListener.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\packages\\Microsoft.Owin.Hosting.4.2.2\\lib\\net45\\Microsoft.Owin.Hosting.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\Microsoft.Win32.Primitives.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\mscorlib.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\netfx.force.conflicts.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\netstandard.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\IIS\\Microsoft Web Deploy V3\\Newtonsoft.Json.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\packages\\NLog.5.1.1\\lib\\net45\\NLog.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\packages\\Owin.1.0\\lib\\net40\\Owin.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\packages\\SqlSugar.5.1.3.47\\lib\\SqlSugar.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.AppContext.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\packages\\System.Buffers.4.5.1\\lib\\net461\\System.Buffers.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Collections.Concurrent.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Collections.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Collections.NonGeneric.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Collections.Specialized.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.ComponentModel.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.ComponentModel.EventBasedAsync.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.ComponentModel.Primitives.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.ComponentModel.TypeConverter.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\System.Configuration.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\System.Configuration.Install.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Console.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\System.Core.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Data.Common.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\System.Data.DataSetExtensions.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\System.Data.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Diagnostics.Contracts.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Diagnostics.Debug.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Diagnostics.FileVersionInfo.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Diagnostics.Process.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Diagnostics.StackTrace.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Diagnostics.TextWriterTraceListener.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Diagnostics.Tools.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Diagnostics.TraceSource.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Diagnostics.Tracing.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\System.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Drawing.Primitives.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Dynamic.Runtime.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Globalization.Calendars.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Globalization.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Globalization.Extensions.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.IO.Compression.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.IO.Compression.ZipFile.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.IO.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.IO.FileSystem.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.IO.FileSystem.DriveInfo.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.IO.FileSystem.Primitives.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.IO.FileSystem.Watcher.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.IO.IsolatedStorage.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.IO.MemoryMappedFiles.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.IO.Pipes.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.IO.UnmanagedMemoryStream.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Linq.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Linq.Expressions.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Linq.Parallel.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Linq.Queryable.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\packages\\System.Memory.4.5.5\\lib\\net461\\System.Memory.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Net.Http.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\packages\\System.Net.Http.Formatting.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Net.NameResolution.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Net.NetworkInformation.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Net.Ping.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Net.Primitives.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Net.Requests.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Net.Security.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Net.Sockets.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Net.WebHeaderCollection.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Net.WebSockets.Client.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Net.WebSockets.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\System.Numerics.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\packages\\System.Numerics.Vectors.4.5.0\\lib\\net46\\System.Numerics.Vectors.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.ObjectModel.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Reflection.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Reflection.Extensions.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Reflection.Primitives.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Resources.Reader.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Resources.ResourceManager.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Resources.Writer.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\packages\\System.Runtime.CompilerServices.Unsafe.6.0.0\\lib\\net461\\System.Runtime.CompilerServices.Unsafe.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Runtime.CompilerServices.VisualC.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Runtime.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Runtime.Extensions.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Runtime.Handles.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Runtime.InteropServices.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Runtime.InteropServices.RuntimeInformation.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Runtime.Numerics.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Runtime.Serialization.Formatters.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Runtime.Serialization.Json.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Runtime.Serialization.Primitives.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Runtime.Serialization.Xml.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Security.Claims.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Security.Cryptography.Algorithms.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Security.Cryptography.Csp.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Security.Cryptography.Encoding.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Security.Cryptography.Primitives.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Security.Cryptography.X509Certificates.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Security.Principal.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Security.SecureString.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\System.ServiceProcess.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Text.Encoding.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Text.Encoding.Extensions.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\packages\\System.Text.Encodings.Web.7.0.0\\lib\\netstandard2.0\\System.Text.Encodings.Web.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\packages\\System.Text.Json.7.0.0\\lib\\netstandard2.0\\System.Text.Json.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Text.RegularExpressions.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Threading.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Threading.Overlapped.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Threading.Tasks.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\packages\\System.Threading.Tasks.Extensions.4.5.4\\lib\\net461\\System.Threading.Tasks.Extensions.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Threading.Tasks.Parallel.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Threading.Thread.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Threading.ThreadPool.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Threading.Timer.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.ValueTuple.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\System.Web.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\packages\\System.Web.Http.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\packages\\System.Web.Http.Owin.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\System.Web.Services.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\System.Xml.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.6.1\\System.Xml.Linq.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Xml.ReaderWriter.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Xml.XDocument.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Xml.XmlDocument.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Xml.XmlSerializer.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Xml.XPath.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Microsoft\\Microsoft.NET.Build.Extensions\\net461\\lib\\System.Xml.XPath.XDocument.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\packages\\Topshelf.4.3.0\\lib\\net452\\Topshelf.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\packages\\Topshelf.NLog.4.3.0\\lib\\net452\\Topshelf.NLog.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""}],"Analyzers":[],"Outputs":[{"OutputItemFullPath":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\HH.WCS.Mobox3.Template\\bin\\Debug\\HH.WCS.Mobox3.Template.exe","OutputItemRelativePath":"HH.WCS.Mobox3.Template.exe"},{"OutputItemFullPath":"D:\\ams\\wcs\\HH.WCS.Mobox3 - 副本\\HH.WCS.Mobox3.Template\\bin\\Debug\\HH.WCS.Mobox3.Template.pdb","OutputItemRelativePath":"HH.WCS.Mobox3.Template.pdb"}],"CopyToOutputEntries":[]}
.vs/HH.WCS.Mobox3.WeiLi/FileContentIndex/57367193-8890-401b-95eb-fa75f34fc9b1.vsidx
Binary files differ
App.config
New file
@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
  </startup>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.3.0.0" newVersion="5.3.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Oracle.ManagedDataAccess" publicKeyToken="89b483f429c47342" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.122.21.1" newVersion="4.122.21.1" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Text.Json" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-8.0.0.3" newVersion="8.0.0.3" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.1.1.3" newVersion="4.1.1.3" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="BouncyCastle.Crypto" publicKeyToken="0e99375e54769942" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-1.9.0.0" newVersion="1.9.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Web.Infrastructure" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Formats.Asn1" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-8.0.0.1" newVersion="8.0.0.1" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-6.0.0.1" newVersion="6.0.0.1" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>
AppStart/Config.cs
New file
@@ -0,0 +1,26 @@
using System.Collections.Generic;
// 根据 JSON 文件 生成对应的 C# 对象;网址:https://json2csharp.com/
// 1. 将 config.json 文件复制到网址中
// 2. 将得到的内容复制到 namespace HH.WCS.Mobox3.{项目代号}.AppStart { } 大括号内部(C# 10 才支持 文件范围内的命名空间)
// 3. 将 Root 更名为 Config
// 补充:这种方式没法保留注释,需要熟悉 Config 文件的字段含义(暂不考虑代码生成 Json 文件)
namespace HH.WCS.Mobox3.AnGang.AppStart {
    // Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);
    public class Area {
        public string Name { get; set; }
        public List<string> Codes { get; set; }
    }
    public class Config {
        public string WebApiUrl { get; set; }
        public string RCSApiUrl { get; set; }
        public string NDCApiUrl { get; set; }
        public string SqlServer { get; set; }
        public string TCPServerIP { get; set; }
        public int TCPServerPort { get; set; }
        public List<Area> Areas { get; set; }
    }
}
AppStart/Settings.cs
New file
@@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.IO;
using HH.WCS.Mobox3.AnGang;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace HH.WCS.Mobox3.AnGang.AppStart {
    public class Settings {
        /// <summary>
        /// 配置文件
        /// </summary>
        public static Config Config { get; set; }
        /// <summary>
        /// 库区字典(加载后就不变)
        /// </summary>
        public static Dictionary<string, List<string>> AreaMap { get; set; } = new Dictionary<string, List<string>>();
        public static void Init() {
            // 加载配置文件
            LoadJson();
            // 针对 Areas 进行转换:将 Config 的 List 加载到 Dict 中
            LoadAreas();
        }
        private static void LoadJson() {
            LogHelper.Info("加载配置文件信息 开始");
            // JSON 文件路径
            string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "./config/config.json");
            try {
                // 读取 JSON 文件内容
                string jsonContent = File.ReadAllText(filePath);
                // 反序列化为 Config 对象
                Config = JsonConvert.DeserializeObject<Config>(jsonContent);
            }
            catch (FileNotFoundException) {
                LogHelper.Info("JSON 文件未找到");
            }
            catch (JsonException ex) {
                LogHelper.Info($"JSON 解析错误: {ex.Message}");
            }
            catch (Exception ex) {
                LogHelper.Info($"发生错误: {ex.Message}");
            }
            LogHelper.Info("加载配置文件信息 完成");
        }
        private static void LoadAreas() {
            foreach (var area in Config.Areas) {
                AreaMap.Add(area.Name, area.Codes);
            }
        }
    }
}
AppStart/Startup.cs
New file
@@ -0,0 +1,48 @@
using System;
using System.Linq;
using System.Net.Http.Formatting;
using System.Threading.Tasks;
using System.Web.Http;
using Microsoft.Owin;
using Owin;
using Swashbuckle.Application;
[assembly: OwinStartup(typeof(HH.WCS.Mobox3.AnGang.Startup))]
namespace HH.WCS.Mobox3.AnGang {
    public class Startup {
        public void Configuration(IAppBuilder app) {
            // 有关如何配置应用程序的详细信息,请访问 https://go.microsoft.com/fwlink/?LinkID=316888
            HttpConfiguration config = new HttpConfiguration();
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional }
                );
            // Web API routes
            //config.MapHttpAttributeRoutes();
            //config.EnableSwagger(c => c.SingleApiVersion("v1", "hh wms api"))
            //    .EnableSwaggerUi();
            //config.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
            //config.Formatters.Add(new JsonMediaTypeFormatter());
            //WebApiConfig.Register(config);
            // Web API routes
            config.MapHttpAttributeRoutes();
            config.EnableSwagger(c => {
                c.SingleApiVersion("v1", "hh wms api");
                c.IncludeXmlComments(System.AppDomain.CurrentDomain.BaseDirectory + "\\HH.WCS.Mobox3.DSZSH.xml");
                c.CustomProvider((defaultProvider) => new SwaggerCacheProvider(defaultProvider, $@"{System.AppDomain.CurrentDomain.BaseDirectory}\\HH.WCS.Mobox3.DSZSH.xml"));
                c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
            }
            ).EnableSwaggerUi(c => {
                c.InjectJavaScript(System.Reflection.Assembly.GetExecutingAssembly(), "swagger.js");
            });
            config.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
            config.Formatters.Add(new JsonMediaTypeFormatter());
            app.UseWebApi(config);
        }
    }
}
AppStart/SwaggerConfig.cs
New file
@@ -0,0 +1,255 @@
using System.Web.Http;
using WebActivatorEx;
using HH.WCS.Mobox3.Template;
using Swashbuckle.Application;
[assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")]
namespace HH.WCS.Mobox3.Template
{
    public class SwaggerConfig
    {
        public static void Register()
        {
            var thisAssembly = typeof(SwaggerConfig).Assembly;
            GlobalConfiguration.Configuration
                .EnableSwagger(c =>
                    {
                        // By default, the service root url is inferred from the request used to access the docs.
                        // However, there may be situations (e.g. proxy and load-balanced environments) where this does not
                        // resolve correctly. You can workaround this by providing your own code to determine the root URL.
                        //
                        //c.RootUrl(req => GetRootUrlFromAppConfig());
                        // If schemes are not explicitly provided in a Swagger 2.0 document, then the scheme used to access
                        // the docs is taken as the default. If your API supports multiple schemes and you want to be explicit
                        // about them, you can use the "Schemes" option as shown below.
                        //
                        //c.Schemes(new[] { "http", "https" });
                        // Use "SingleApiVersion" to describe a single version API. Swagger 2.0 includes an "Info" object to
                        // hold additional metadata for an API. Version and title are required but you can also provide
                        // additional fields by chaining methods off SingleApiVersion.
                        //
                        c.SingleApiVersion("v1", "HH.WCS.Mobox3.Template");
                        // If you want the output Swagger docs to be indented properly, enable the "PrettyPrint" option.
                        //
                        //c.PrettyPrint();
                        // If your API has multiple versions, use "MultipleApiVersions" instead of "SingleApiVersion".
                        // In this case, you must provide a lambda that tells Swashbuckle which actions should be
                        // included in the docs for a given API version. Like "SingleApiVersion", each call to "Version"
                        // returns an "Info" builder so you can provide additional metadata per API version.
                        //
                        //c.MultipleApiVersions(
                        //    (apiDesc, targetApiVersion) => ResolveVersionSupportByRouteConstraint(apiDesc, targetApiVersion),
                        //    (vc) =>
                        //    {
                        //        vc.Version("v2", "Swashbuckle Dummy API V2");
                        //        vc.Version("v1", "Swashbuckle Dummy API V1");
                        //    });
                        // You can use "BasicAuth", "ApiKey" or "OAuth2" options to describe security schemes for the API.
                        // See https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md for more details.
                        // NOTE: These only define the schemes and need to be coupled with a corresponding "security" property
                        // at the document or operation level to indicate which schemes are required for an operation. To do this,
                        // you'll need to implement a custom IDocumentFilter and/or IOperationFilter to set these properties
                        // according to your specific authorization implementation
                        //
                        //c.BasicAuth("basic")
                        //    .Description("Basic HTTP Authentication");
                        //
                        // NOTE: You must also configure 'EnableApiKeySupport' below in the SwaggerUI section
                        //c.ApiKey("apiKey")
                        //    .Description("API Key Authentication")
                        //    .Name("apiKey")
                        //    .In("header");
                        //
                        //c.OAuth2("oauth2")
                        //    .Description("OAuth2 Implicit Grant")
                        //    .Flow("implicit")
                        //    .AuthorizationUrl("http://petstore.swagger.wordnik.com/api/oauth/dialog")
                        //    //.TokenUrl("https://tempuri.org/token")
                        //    .Scopes(scopes =>
                        //    {
                        //        scopes.Add("read", "Read access to protected resources");
                        //        scopes.Add("write", "Write access to protected resources");
                        //    });
                        // Set this flag to omit descriptions for any actions decorated with the Obsolete attribute
                        //c.IgnoreObsoleteActions();
                        // Each operation be assigned one or more tags which are then used by consumers for various reasons.
                        // For example, the swagger-ui groups operations according to the first tag of each operation.
                        // By default, this will be controller name but you can use the "GroupActionsBy" option to
                        // override with any value.
                        //
                        //c.GroupActionsBy(apiDesc => apiDesc.HttpMethod.ToString());
                        // You can also specify a custom sort order for groups (as defined by "GroupActionsBy") to dictate
                        // the order in which operations are listed. For example, if the default grouping is in place
                        // (controller name) and you specify a descending alphabetic sort order, then actions from a
                        // ProductsController will be listed before those from a CustomersController. This is typically
                        // used to customize the order of groupings in the swagger-ui.
                        //
                        //c.OrderActionGroupsBy(new DescendingAlphabeticComparer());
                        // If you annotate Controllers and API Types with
                        // Xml comments (http://msdn.microsoft.com/en-us/library/b2s063f7(v=vs.110).aspx), you can incorporate
                        // those comments into the generated docs and UI. You can enable this by providing the path to one or
                        // more Xml comment files.
                        //
                        //c.IncludeXmlComments(GetXmlCommentsPath());
                        // Swashbuckle makes a best attempt at generating Swagger compliant JSON schemas for the various types
                        // exposed in your API. However, there may be occasions when more control of the output is needed.
                        // This is supported through the "MapType" and "SchemaFilter" options:
                        //
                        // Use the "MapType" option to override the Schema generation for a specific type.
                        // It should be noted that the resulting Schema will be placed "inline" for any applicable Operations.
                        // While Swagger 2.0 supports inline definitions for "all" Schema types, the swagger-ui tool does not.
                        // It expects "complex" Schemas to be defined separately and referenced. For this reason, you should only
                        // use the "MapType" option when the resulting Schema is a primitive or array type. If you need to alter a
                        // complex Schema, use a Schema filter.
                        //
                        //c.MapType<ProductType>(() => new Schema { type = "integer", format = "int32" });
                        // If you want to post-modify "complex" Schemas once they've been generated, across the board or for a
                        // specific type, you can wire up one or more Schema filters.
                        //
                        //c.SchemaFilter<ApplySchemaVendorExtensions>();
                        // In a Swagger 2.0 document, complex types are typically declared globally and referenced by unique
                        // Schema Id. By default, Swashbuckle does NOT use the full type name in Schema Ids. In most cases, this
                        // works well because it prevents the "implementation detail" of type namespaces from leaking into your
                        // Swagger docs and UI. However, if you have multiple types in your API with the same class name, you'll
                        // need to opt out of this behavior to avoid Schema Id conflicts.
                        //
                        //c.UseFullTypeNameInSchemaIds();
                        // Alternatively, you can provide your own custom strategy for inferring SchemaId's for
                        // describing "complex" types in your API.
                        //
                        //c.SchemaId(t => t.FullName.Contains('`') ? t.FullName.Substring(0, t.FullName.IndexOf('`')) : t.FullName);
                        // Set this flag to omit schema property descriptions for any type properties decorated with the
                        // Obsolete attribute
                        //c.IgnoreObsoleteProperties();
                        // In accordance with the built in JsonSerializer, Swashbuckle will, by default, describe enums as integers.
                        // You can change the serializer behavior by configuring the StringToEnumConverter globally or for a given
                        // enum type. Swashbuckle will honor this change out-of-the-box. However, if you use a different
                        // approach to serialize enums as strings, you can also force Swashbuckle to describe them as strings.
                        //
                        //c.DescribeAllEnumsAsStrings();
                        // Similar to Schema filters, Swashbuckle also supports Operation and Document filters:
                        //
                        // Post-modify Operation descriptions once they've been generated by wiring up one or more
                        // Operation filters.
                        //
                        //c.OperationFilter<AddDefaultResponse>();
                        //
                        // If you've defined an OAuth2 flow as described above, you could use a custom filter
                        // to inspect some attribute on each action and infer which (if any) OAuth2 scopes are required
                        // to execute the operation
                        //
                        //c.OperationFilter<AssignOAuth2SecurityRequirements>();
                        // Post-modify the entire Swagger document by wiring up one or more Document filters.
                        // This gives full control to modify the final SwaggerDocument. You should have a good understanding of
                        // the Swagger 2.0 spec. - https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md
                        // before using this option.
                        //
                        //c.DocumentFilter<ApplyDocumentVendorExtensions>();
                        // In contrast to WebApi, Swagger 2.0 does not include the query string component when mapping a URL
                        // to an action. As a result, Swashbuckle will raise an exception if it encounters multiple actions
                        // with the same path (sans query string) and HTTP method. You can workaround this by providing a
                        // custom strategy to pick a winner or merge the descriptions for the purposes of the Swagger docs
                        //
                        //c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
                        // Wrap the default SwaggerGenerator with additional behavior (e.g. caching) or provide an
                        // alternative implementation for ISwaggerProvider with the CustomProvider option.
                        //
                        //c.CustomProvider((defaultProvider) => new CachingSwaggerProvider(defaultProvider));
                    })
                .EnableSwaggerUi(c =>
                    {
                        // Use the "DocumentTitle" option to change the Document title.
                        // Very helpful when you have multiple Swagger pages open, to tell them apart.
                        //
                        //c.DocumentTitle("My Swagger UI");
                        // Use the "InjectStylesheet" option to enrich the UI with one or more additional CSS stylesheets.
                        // The file must be included in your project as an "Embedded Resource", and then the resource's
                        // "Logical Name" is passed to the method as shown below.
                        //
                        //c.InjectStylesheet(containingAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testStyles1.css");
                        // Use the "InjectJavaScript" option to invoke one or more custom JavaScripts after the swagger-ui
                        // has loaded. The file must be included in your project as an "Embedded Resource", and then the resource's
                        // "Logical Name" is passed to the method as shown above.
                        //
                        //c.InjectJavaScript(thisAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testScript1.js");
                        // The swagger-ui renders boolean data types as a dropdown. By default, it provides "true" and "false"
                        // strings as the possible choices. You can use this option to change these to something else,
                        // for example 0 and 1.
                        //
                        //c.BooleanValues(new[] { "0", "1" });
                        // By default, swagger-ui will validate specs against swagger.io's online validator and display the result
                        // in a badge at the bottom of the page. Use these options to set a different validator URL or to disable the
                        // feature entirely.
                        //c.SetValidatorUrl("http://localhost/validator");
                        //c.DisableValidator();
                        // Use this option to control how the Operation listing is displayed.
                        // It can be set to "None" (default), "List" (shows operations for each resource),
                        // or "Full" (fully expanded: shows operations and their details).
                        //
                        //c.DocExpansion(DocExpansion.List);
                        // Specify which HTTP operations will have the 'Try it out!' option. An empty paramter list disables
                        // it for all operations.
                        //
                        //c.SupportedSubmitMethods("GET", "HEAD");
                        // Use the CustomAsset option to provide your own version of assets used in the swagger-ui.
                        // It's typically used to instruct Swashbuckle to return your version instead of the default
                        // when a request is made for "index.html". As with all custom content, the file must be included
                        // in your project as an "Embedded Resource", and then the resource's "Logical Name" is passed to
                        // the method as shown below.
                        //
                        //c.CustomAsset("index", containingAssembly, "YourWebApiProject.SwaggerExtensions.index.html");
                        // If your API has multiple versions and you've applied the MultipleApiVersions setting
                        // as described above, you can also enable a select box in the swagger-ui, that displays
                        // a discovery URL for each version. This provides a convenient way for users to browse documentation
                        // for different API versions.
                        //
                        //c.EnableDiscoveryUrlSelector();
                        // If your API supports the OAuth2 Implicit flow, and you've described it correctly, according to
                        // the Swagger 2.0 specification, you can enable UI support as shown below.
                        //
                        //c.EnableOAuth2Support(
                        //    clientId: "test-client-id",
                        //    clientSecret: null,
                        //    realm: "test-realm",
                        //    appName: "Swagger UI"
                        //    //additionalQueryStringParams: new Dictionary<string, string>() { { "foo", "bar" } }
                        //);
                        // If your API supports ApiKey, you can override the default values.
                        // "apiKeyIn" can either be "query" or "header"
                        //
                        //c.EnableApiKeySupport("apiKey", "header");
                    });
        }
    }
}
AppStart/SwaggerControllerDescProvider.cs
New file
@@ -0,0 +1,82 @@
using Swashbuckle.Swagger;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Xml;
namespace HH.WCS.Mobox3.AnGang {
    /// <summary>
    /// Swagger 显示控制器的描述
    /// </summary>
    public class SwaggerCacheProvider : ISwaggerProvider
    {
        private readonly ISwaggerProvider _swaggerProvider;
        private static ConcurrentDictionary<string, SwaggerDocument> _cache = new ConcurrentDictionary<string, SwaggerDocument>();
        private readonly string _xmlPath;
        /// <summary>
        ///
        /// </summary>
        /// <param name="swaggerProvider"></param>
        /// <param name="xmlpath">xml文档路径</param>
        public SwaggerCacheProvider(ISwaggerProvider swaggerProvider, string xmlpath)
        {
            _swaggerProvider = swaggerProvider;
            _xmlPath = xmlpath;
        }
        public SwaggerDocument GetSwagger(string rootUrl, string apiVersion)
        {
            var cacheKey = string.Format("{0}_{1}", rootUrl, apiVersion);
            //只读取一次
            if (!_cache.TryGetValue(cacheKey, out SwaggerDocument srcDoc))
            {
                srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion);
                srcDoc.vendorExtensions = new Dictionary<string, object>
            {
                { "ControllerDesc", GetControllerDesc() }
            };
                _cache.TryAdd(cacheKey, srcDoc);
            }
            return srcDoc;
        }
        /// <summary>
        /// 从API文档中读取控制器描述
        /// </summary>
        /// <returns>所有控制器描述</returns>
        public ConcurrentDictionary<string, string> GetControllerDesc()
        {
            ConcurrentDictionary<string, string> controllerDescDict = new ConcurrentDictionary<string, string>();
            if (File.Exists(_xmlPath))
            {
                XmlDocument xmldoc = new XmlDocument();
                xmldoc.Load(_xmlPath);
                string[] arrPath;
                int cCount = "Controller".Length;
                foreach (XmlNode node in xmldoc.SelectNodes("//member"))
                {
                    string type = node.Attributes["name"].Value;
                    if (type.StartsWith("T:"))
                    {
                        arrPath = type.Split('.');
                        string controllerName = arrPath[arrPath.Length - 1];
                        if (controllerName.EndsWith("Controller"))  //控制器
                        {
                            //获取控制器注释
                            XmlNode summaryNode = node.SelectSingleNode("summary");
                            string key = controllerName.Remove(controllerName.Length - cCount, cCount);
                            if (summaryNode != null && !string.IsNullOrEmpty(summaryNode.InnerText) && !controllerDescDict.ContainsKey(key))
                            {
                                controllerDescDict.TryAdd(key, summaryNode.InnerText.Trim());
                            }
                        }
                    }
                }
            }
            return controllerDescDict;
        }
    }
}
Consts/AgvStateCode.cs
New file
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Consts {
    public class AgvStateCode {
        public const int 执行 = 1;
        public const int 完成 = 2;
        public const int 开始取货 = 3;
        public const int 取货完成 = 4;
        public const int 开始卸货 = 5;
        public const int 卸货完成 = 6;
        public const int 异常 = 7;
    }
}
Consts/AgvStateName.cs
New file
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Consts {
    public class AgvStateName {
        public const string 执行 = "执行";
        public const string 完成 = "完成";
        public const string 开始取货 = "开始取货";
        public const string 取货完成 = "取货完成";
        public const string 开始卸货 = "开始卸货";
        public const string 卸货完成 = "卸货完成";
        public const string 异常 = "异常";
    }
}
Consts/AreaCode.cs
New file
@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Consts {
    public class AreaCode {
        public const string 收发货位区 = "P";
    }
}
Consts/AreaName.cs
New file
@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Consts {
    public class AreaName {
        public const string 收发货位区 = "收发货位区";
        public const string 货架区 = "货架区";
    }
}
Consts/LockStateCode.cs
New file
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Consts {
    public class LockStateCode {
        public const int 无 = 0;
        public const int 入库锁 = 1;
        public const int 出库锁 = 2;
        public const int 其他锁 = 3;
    }
}
Consts/LockStateName.cs
New file
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Consts {
    /// <summary>
    /// [原则上不修改] 位置锁名称 字符串常量
    /// </summary>
    public class LockStateName {
        public const string 无 = "无";
        public const string 入库锁 = "入库锁";
        public const string 出库锁 = "出库锁";
        public const string 其他锁 = "其他锁";
    }
}
Consts/TaskName.cs
New file
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Consts {
    public class TaskName {
        public const string 货品入库 = "货品入库";
        public const string 产品部分出库 = "产品部分出库";
        public const string 产品部分回库 = "产品部分回库";
        public const string 盘点理货出库 = "盘点理货出库";
    }
}
Controllers/AgvController.cs
New file
@@ -0,0 +1,61 @@
using HH.WCS.Mobox3.AnGang.ServiceCore;
using HH.WCS.Mobox3.AnGang.Dispatch;
using HH.WCS.Mobox3.AnGang.process;
using HH.WCS.Mobox3.AnGang.Helper;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Reflection;
using System.Web.Http;
using static HH.WCS.Mobox3.AnGang.Dispatch.NDC;
using System.Linq;
using HH.WCS.Mobox3.AnGang.config;
using HH.WCS.Mobox3.AnGang.Services;
using static HH.WCS.Mobox3.AnGang.Dtos.Request.AgvRequest;
using static HH.WCS.Mobox3.AnGang.Dtos.Response.AgvResponse;
using static HH.WCS.Mobox3.AnGang.Controllers.ApiModel;
namespace HH.WCS.Mobox3.AnGang.Controllers
{
    /// <summary>
    /// 设备信息上报(hosttoagv上报、杭奥堆垛机、国自agv)
    /// </summary>
    [RoutePrefix("agv")]
    public class AgvController : ApiController
    {
        ///// <summary>
        ///// NDC HostToAGV 任务状态回报
        ///// </summary>
        ///// <param name="model"></param>
        ///// <returns></returns>
        //[HttpPost]
        //[Route("AGVCallbackState")]
        //public ReturnResult AGVCallbackState(AgvTaskState model)
        //{
        //    LogHelper.Info("NDC HostToAGV任务状态回报:" + JsonConvert.SerializeObject(model), "HosttoagvTask");
        //    return AgvService.OperateAgvTaskStatus(model);
        //}
        /// <summary>
        /// RCS国自AGV任务状态回报
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("orderStatusReport")]
        public GzResult orderStatusReport(orderStatusReportParme model) {
            return GZRobot.orderStatusReport(model);
        }
        /// <summary>
        /// AGV 与产线进行安全交互
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("safetyInteraction")]
        public ReturnResult SafetyInteraction(SafetyInteractionInfo model) {
            return AgvService.SafetyInteraction(model);
        }
    }
}
Controllers/ApiModel.cs
New file
@@ -0,0 +1,232 @@
using System.Collections.Generic;
namespace HH.WCS.Mobox3.AnGang.Controllers
{
    /// <summary>
    /// 通用model
    /// </summary>
    public class ApiModel
    {
        #region mobox 相关
        /// <summary>
        /// mobox 取消任务、标记完成任务
        /// </summary>
        public class MoboxTaskBase
        {
            public string TaskNo { get; set; }
        }
        /// <summary>
        /// mobox 接口返回
        /// </summary>
        public class SimpleResult
        {
            public int resultCode { get; set; }
            public string resultMsg { get; set; }
            public List<object> result { get; set; } = new List<object>();
        }
        public class Result
        {
            public int resultCode { get; set; }
            public string resultMsg { get; set; }
        }
        /// <summary>
        /// 绑定 参数
        /// </summary>
        public class BindParme
        {
            /// <summary>
            /// 托盘编码
            /// </summary>
            public string CntrCode { get; set; }
            /// <summary>
            /// 托盘类型
            /// </summary>
            public string CntrType { get; set; }
            /// <summary>
            /// 货位编码
            /// </summary>
            public string LocCode { get; set; }
            /// <summary>
            /// 物料编码
            /// </summary>
            public string ItemCode { get; set; }
            /// <summary>
            /// 物料数量
            /// </summary>
            public int ItemQuantity { get; set; }
        }
        /// <summary>
        /// 解绑 参数
        /// </summary>
        public class UnBindParme
        {
            /// <summary>
            /// 托盘编码
            /// </summary>
            public string CntrCode { get; set; }
        }
        public class sendTask
        {
            /// <summary>
            /// 订单名
            /// </summary>
            public string ts { get; set; }
        }
        /// <summary>
        /// 更新补货状态参数
        /// </summary>
        public class replenishmentParme
        {
            /// <summary>
            /// Y开始人工补货进入交通管制,N表示人工补货完成可以开启自动转运
            /// </summary>
            public string stauts { get; set; }
        }
        public class orderStatusReportParme
        {
            /// <summary>
            /// 订单ID
            /// </summary>
            public int orderID { get; set; }
            /// <summary>
            /// 订单名
            /// </summary>
            public string orderName { get; set; }
            /// <summary>
            /// 订单状态
            /// </summary>
            public string orderStatus { get; set; }
            /// <summary>
            /// agv车号列表
            /// </summary>
            public string agvIDList { get; set; }
            /// <summary>
            /// 优先级
            /// </summary>
            public string priority { get; set; }
            /// <summary>
            /// 订单当前的目的地
            /// </summary>
            public string currentDes { get; set; }
            /// <summary>
            /// 当前指令
            /// </summary>
            public string currentCmd { get; set; }
            /// <summary>
            /// 错误码
            /// </summary>
            public int errorCode { get; set; }
            /// <summary>
            /// 订单的截至时间
            /// </summary>
            public string deadLine { get; set; }
            /// <summary>
            /// 订单的创建时间
            /// </summary>
            public string createdTime { get; set; }
            /// <summary>
            /// 额外信息1
            /// </summary>
            public string extraInfo1 { get; set; }
            /// <summary>
            /// 额外信息2
            /// </summary>
            public string extraInfo2 { get; set; }
        }
        /// <summary>
        /// 分拣确认
        /// </summary>
        public class SortingResultCheck
        {
            public string sortNo { get; set; }
            public string cntrCode { get; set; }
            public string itemCode { get; set; }
            public float qty { get; set; }
        }
        public class CheckSortingWholeCntr
        {
            public string cntr { get; set; }
            /// <summary>
            /// 默认0,1表示自动生成分拣结果
            /// </summary>
            public int autoSort { get; set; }
        }
        /// <summary>
        /// lua 调用接口,码盘信息
        /// </summary>
        public class PalletSorting
        {
            public string cntr_code { get; set; }
            public string item_code { get; set; }
            public float qty { get; set; }
            public string arrival_no { get; set; }
        }
        public class PalletSorting1
        {
            public string cntr_code { get; set; }
            public string bar_code { get; set; }
            public string org { get; set; }
            public float qty { get; set; }
        }
        public class ShippingOrderCheck
        {
            /// <summary>
            /// 多个发货单号
            /// </summary>
            public string out_nos { get; set; }
        }
        public class SortingOrderCheck
        {
            public string s_no { get; set; }
        }
        public class ReturnResult1
        {
            public int code { get; set; }
            public string msg { get; set; }
        }
        /// <summary>
        /// 安全交互
        /// </summary>
        public class Interaction
        {
            public string station_name { get; set; }
            public string apply_code { get; set; }
            public int orderid { get; set; }
        }
        /// <summary>
        /// 返回给GZ
        /// </summary>
        public class GzResult
        {
            public int resultCode { get; set; }
            public string msg { get; set; }
            public int orderID { get; set; }
        }
        #endregion
    }
}
Controllers/DebugController.cs
New file
@@ -0,0 +1,288 @@
using System.Linq;
using HH.WCS.Mobox3.AnGang.ServiceCore;
using HH.WCS.Mobox3.AnGang.Devices;
using HH.WCS.Mobox3.AnGang.Dispatch;
using HH.WCS.Mobox3.AnGang.config;
using HH.WCS.Mobox3.AnGang.Helper;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Web.Http;
using static Opc.Ua.ContentFilter;
using System.Threading.Tasks;
using HH.WCS.Mobox3.AnGang.Models;
using HH.WCS.Mobox3.AnGang.Services;
using static HH.WCS.Mobox3.AnGang.Dtos.Request.AgvRequest;
using static HH.WCS.Mobox3.AnGang.Dtos.Response.AgvResponse;
using HH.WCS.Mobox3.AnGang.Helpers;
namespace HH.WCS.Mobox3.AnGang.Controllers
{
    /// <summary>
    /// 测试用,如果项目中要和设备对接,前期设备无法测试,用接口模拟
    /// </summary>
    [RoutePrefix("api")]
    public class DebugController : System.Web.Http.ApiController
    {
        /// <summary>
        /// AGV状态一键回报134562
        /// </summary>
        /// <param name="model">容器号</param>
        /// <returns></returns>
        [HttpPost]
        [Route("AGVSeriesReports")]
        public ReturnResults AGVSeriesReports(UpdateTaskState model)
        {
            var agvTaskState = new AgvTaskState()
            {
                task_no = model.TaskID,
                forklift_no = model.ForkliftNo,
                state = 1
            };
            ReturnResults returnResults = new ReturnResults();
            returnResults.resultList = new List<ReturnResult>();
            var temp1 =  AgvService.OperateAgvTaskStatus(agvTaskState);
            returnResults.resultList.Add(temp1);
            agvTaskState.state = 3;
            var temp3 = AgvService.OperateAgvTaskStatus(agvTaskState);
            returnResults.resultList.Add(temp3);
            agvTaskState.state = 4;
            var temp4 = AgvService.OperateAgvTaskStatus(agvTaskState);
            returnResults.resultList.Add(temp4);
            agvTaskState.state = 5;
            var temp5 = AgvService.OperateAgvTaskStatus(agvTaskState);
            returnResults.resultList.Add(temp5);
            agvTaskState.state = 6;
            var temp6 = AgvService.OperateAgvTaskStatus(agvTaskState);
            returnResults.resultList.Add(temp6);
            agvTaskState.state = 2;
            var temp2 = AgvService.OperateAgvTaskStatus(agvTaskState);
            returnResults.resultList.Add(temp2);
            return returnResults;
        }
        /// <summary>
        /// AGV状态一键回报134
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("AGVSeriesReportsPartA")]
        public ReturnResults AGVSeriesReportsPartA(UpdateTaskState model) {
            var agvTaskState = new AgvTaskState() {
                task_no = model.TaskID,
                forklift_no = model.ForkliftNo,
                state = 1
            };
            ReturnResults returnResults = new ReturnResults();
            returnResults.resultList = new List<ReturnResult>();
            var temp1 = AgvService.OperateAgvTaskStatus(agvTaskState);
            returnResults.resultList.Add(temp1);
            agvTaskState.state = 3;
            var temp3 = AgvService.OperateAgvTaskStatus(agvTaskState);
            returnResults.resultList.Add(temp3);
            agvTaskState.state = 4;
            var temp4 = AgvService.OperateAgvTaskStatus(agvTaskState);
            returnResults.resultList.Add(temp4);
            return returnResults;
        }
        /// <summary>
        /// AGV状态一键回报562
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("AGVSeriesReportsPartB")]
        public ReturnResults AGVSeriesReportsPartB(UpdateTaskState model) {
            var agvTaskState = new AgvTaskState() {
                task_no = model.TaskID,
                forklift_no = model.ForkliftNo,
                state = 4
            };
            ReturnResults returnResults = new ReturnResults();
            returnResults.resultList = new List<ReturnResult>();
            agvTaskState.state = 5;
            var temp5 = AgvService.OperateAgvTaskStatus(agvTaskState);
            returnResults.resultList.Add(temp5);
            agvTaskState.state = 6;
            var temp6 = AgvService.OperateAgvTaskStatus(agvTaskState);
            returnResults.resultList.Add(temp6);
            agvTaskState.state = 2;
            var temp2 = AgvService.OperateAgvTaskStatus(agvTaskState);
            returnResults.resultList.Add(temp2);
            return returnResults;
        }
        /// <summary>
        /// 初始化数据库
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Route("BuildDB")]
        public string BuildDB()
        {
            //bool res = false;
            try
            {
                var db = DbHelper.GetDbClient();
                //db.CodeFirst.InitTables<WCSTask>(); //所有库都支持
                //db.CodeFirst.InitTables<Zone>();
                //db.CodeFirst.InitTables<Area>();
                //db.CodeFirst.InitTables<Location>();
                //db.CodeFirst.InitTables<LocCntrRel>();
                //db.CodeFirst.InitTables<Container>();
                //db.CodeFirst.InitTables<TN_CG_Detail>();
                //db.CodeFirst.InitTables<TN_WorkOrder>();
                //db.CodeFirst.InitTables<TN_CAR_IN>();
                //db.CodeFirst.InitTables<SYSHelper.OI_SYS_MAXID>();
                //db.CodeFirst.InitTables<TN_Task_Action>();
                //db.CodeFirst.InitTables<TN_Task>();
                //db.CodeFirst.InitTables<TN_Location>();
                //db.CodeFirst.InitTables<TN_Loc_Container>();
                var locList = new List<TN_Location>();
                //foreach (var area in Settings.Areas.Skip(1).ToList()) {
                //    for (int i = 0; i < 8; i++) {
                //        for (int j = 0; j < 30; j++) {
                //            locList.Add(new TN_Location { S_SHELF_CODE = area, S_CODE = $"{area}-{i + 1}-{j + 1}", S_NAME = $"{area}货架 第{i + 1}层 第{j + 1}号货位", S_AGV_SITE = $"{area}-{i + 1}-{j + 1}", N_HEIGHT = i + 1 });
                //        }
                //    }
                //}
                locList.Add(new TN_Location { S_AREA_CODE = "B111", S_CODE = "B111-1-1", S_NAME = "B111-1-1", S_AGV_SITE = "B111-1-1"});
                locList.Add(new TN_Location { S_AREA_CODE = "B111", S_CODE = "B111-4-1", S_NAME = "B111-4-1", S_AGV_SITE = "B111-4-1"});
                locList.Add(new TN_Location { S_AREA_CODE = "B112", S_CODE = "B112-1-1", S_NAME = "B112-1-1", S_AGV_SITE = "B112-1-1"});
                //locList.Add(new TN_Location { S_AREA_CODE = Settings.Areas[0], S_SHELF_CODE = Settings.Areas[0], S_CODE = Settings.Areas[0] + "-1", S_NAME = "取放货区-1", S_AGV_SITE = "P0-1"});
                //locList.Add(new TN_Location { S_AREA_CODE = Settings.Areas[0], S_SHELF_CODE = Settings.Areas[0], S_CODE = Settings.Areas[0] + "-2", S_NAME = "取放货区-2", S_AGV_SITE = "P0-2"});
                if (db.Insertable<TN_Location>(locList).ExecuteCommand() <= 0) {
                    return "失败";
                }
            }
            catch (Exception ex)
            {
                LogHelper.Info($"发生了异常");
                return "初始化数据库错误" + ex.Message;
            }
            //return res ? "成功" : "失败";
            return "成功";
        }
        /// <summary>
        /// 修改任务的重量,便于测试
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Route("UpdateTaskWeight")]
        public string UpdateTaskWeight(UpdateTaskWeightInfo model) {
            var db = DbHelper.GetDbClient();
            var task = db.Queryable<TN_Task>().First(a => a.S_CODE == model.TaskID);
            if (task == null) {
                return "任务号不存在";
            }
            task.F_WEIGHT = model.Weight;
            try {
                using (var trans = db.Ado.UseTran()) {
                    if (db.Updateable<TN_Task>(task).ExecuteCommand() > 0) {
                        trans.CommitTran();
                        return $"成功 | 修改任务{task.S_CODE}重量为{task.F_WEIGHT}";
                    }
                    else {
                        trans.RollbackTran();
                        return $"失败 | 修改任务{task.S_CODE}重量为{task.F_WEIGHT}";
                    }
                }
            }
            catch (Exception ex) {
                return ex.Message;
            }
        }
        [HttpPost]
        public string AddCgCntrLocRel(CgInfo model) {
            var db = DbHelper.GetDbClient();
            try {
                var loc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.LocId);
                if (loc == null) {
                    var locList = new List<TN_Location>();
                    locList.Add(new TN_Location { S_CODE = model.LocId, N_CURRENT_NUM = 1 });
                    if (db.Insertable<TN_Location>(locList).ExecuteCommand() <= 0) {
                        return $"插入位置{model.LocId}失败";
                    }
                }
                if (loc.N_CURRENT_NUM == 0) {
                    loc.N_CURRENT_NUM = 1;
                    if (db.Updateable<TN_Location>(loc).UpdateColumns(it => new { it.N_CURRENT_NUM, it.T_MODIFY }).ExecuteCommand() <= 0) {
                        return $"修改位置{model.LocId}失败";
                    }
                }
                var locCntrRel = db.Queryable<TN_Loc_Container>().First(a => a.S_LOC_CODE == model.LocId && a.S_CNTR_CODE == model.CntId);
                if (loc == null) {
                    var locList = new List<TN_Loc_Container>();
                    locList.Add(new TN_Loc_Container { S_LOC_CODE = model.LocId, S_CNTR_CODE = model.CntId });
                    if (db.Insertable<TN_Loc_Container>(locList).ExecuteCommand() <= 0) {
                        return $"插入位置托盘关系{model.LocId}-{model.CntId}失败";
                    }
                }
                var cgDetail = db.Queryable<TN_CG_Detail>().First(a => a.S_CNTR_CODE == model.CntId && a.S_CG_ID == model.CgId);
                if (cgDetail == null) {
                    var locList = new List<TN_CG_Detail>();
                    locList.Add(new TN_CG_Detail { S_CNTR_CODE = model.CntId, S_CG_ID = model.CntId });
                    if (db.Insertable<TN_CG_Detail>(locList).ExecuteCommand() <= 0) {
                        return $"插入托盘物料关系{model.CntId}-{model.CgId}失败";
                    }
                }
            }
            catch (Exception ex) {
                return $"出错:{ex}";
            }
            return "success";
        }
    }
    public class CgInfo {
        public string CgId { get; set; }
        public string CntId { get; set; }
        public string LocId { get; set; }
    }
    public class UpdateTaskState
    {
        public string TaskID { set; get; } // 任务ID
        public string ForkliftNo { set; get; } // AGV 小车号
    }
    public class UpdateTaskWeightInfo {
        public string TaskID { set; get; }
        public float Weight { set; get; }
    }
    public class ReturnResults
    {
        public List<ReturnResult> resultList { set; get; }
    }
}
Controllers/ErpController.cs
New file
@@ -0,0 +1,19 @@
using System;
using HH.WCS.Mobox3.AnGang.config;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Web.Http;
using static HH.WCS.Mobox3.AnGang.Controllers.ApiModel;
namespace HH.WCS.Mobox3.AnGang.Controllers {
    /// <summary>
    /// ERP 调用的接口
    /// </summary>
    [RoutePrefix("api")]
    public class ErpController : ApiController {
    }
}
Controllers/MoboxController.cs
New file
@@ -0,0 +1,83 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Web.Http;
using HH.WCS.Mobox3.AnGang.Services;
using static HH.WCS.Mobox3.AnGang.Dtos.Request.MoboxRequest;
using static HH.WCS.Mobox3.AnGang.Dtos.Response.MoboxResponse;
namespace HH.WCS.Mobox3.AnGang.Controllers
{
    /// <summary>
    /// Mobox3 调用,脚本中调用
    /// </summary>
    [RoutePrefix("api")]
    public class MoboxController : ApiController {
        /// <summary>
        /// 货品入库(PDA)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("InWarehouse")]
        public SimpleResult InWarehouse(InWarehouseInfo model) {
            return MoboxService.InWarehouse(model);
        }
        /// <summary>
        /// PDA选择终点货位
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("SelectLocation")]
        public SimpleResult SelectLocation(SelectLocationInfo model) {
            return MoboxService.SelectLocation(model);
        }
        /// <summary>
        /// 产品部分出库(WMS)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("PartOutWarehouse")]
        public SimpleResult PartOutWarehouse(PartOutWarehouseInfo model) {
            return MoboxService.PartOutWarehouse(model);
        }
        /// <summary>
        /// 产品部分回库(WMS)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("PartInWarehouse")]
        public SimpleResult PartInWarehouse(PartInWarehouseInfo model) {
            return MoboxService.PartInWarehouse(model);
        }
        /// <summary>
        /// 盘点理货出库(WMS)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("CheckOutWarehouse")]
        public SimpleResult CheckOutWarehouse(CheckOutWarehouseInfo model) {
            return MoboxService.CheckOutWarehouse(model);
        }
        /// <summary>
        /// 盘点理货回库(WMS)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("CheckInWarehouse")]
        public SimpleResult CheckInWarehouse(CheckInWarehouseInfo model) {
            return MoboxService.CheckInWarehouse(model);
        }
    }
}
Controllers/WmsController.cs
New file
@@ -0,0 +1,18 @@

using HH.WCS.Mobox3.AnGang.config;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Web.Http;
using static HH.WCS.Mobox3.AnGang.Controllers.ApiModel;
namespace HH.WCS.Mobox3.AnGang.Controllers
{
    /// <summary>
    /// 第三方调用的接口
    /// </summary>
    [RoutePrefix("api")]
    public class WmsController : System.Web.Http.ApiController
    {
    }
}
Devices/ModbusHelper.cs
New file
@@ -0,0 +1,450 @@
using EasyModbus;
using HH.WCS.Mobox3.AnGang;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Helpers
{
    /// <summary>
    /// modbus tcp 用第三方的包
    /// </summary>
    public class ModbusHelper
    {
        //内存,连接上的mocbus通讯对象
        public static Dictionary<string, ModbusClient> ipPort_ModbusClient = new Dictionary<string, ModbusClient>();
        public ModbusHelper(string ip, int port)
        {
            Init(new ModbusConfigModel() { Ip = ip, Port = port });
        }
        /// <summary>
        /// modbus启动初始化
        /// </summary>
        public static void Init(ModbusConfigModel modbusConfigModel)
        {
            //配置文件读取所有的mocbus进行初始化
            try
            {
                if (modbusConfigModel == null)
                {
                    //读取配置信息失败
                    LogHelper.Info("Modbus:读取配置信息失败");
                    return;
                }
                var modbusClient = new ModbusClient(modbusConfigModel.Ip, modbusConfigModel.Port);
                ipPort_ModbusClient.Add($"{modbusConfigModel.Ip}:{modbusConfigModel.Port}", modbusClient);
                Link(modbusClient);
            }
            catch (Exception ex)
            {
            }
        }
        /// <summary>
        /// 重连
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        public static void Relink() {
            try {
                if (ipPort_ModbusClient.Count == 0) {
                    return;
                }
                foreach (var item in ipPort_ModbusClient) {
                    if (!item.Value.Connected) {
                        Link(item.Value);
                    }
                }
            }
            catch (Exception ex) {
            }
        }
        /// <summary>
        /// 连接modbus下位机
        /// </summary>
        /// <param name="modbusClient"></param>
        private static void Link(ModbusClient modbusClient)
        {
            try
            {
                modbusClient.Disconnect();
                modbusClient.Connect();
                if (modbusClient.Connected)
                {
                    //连接上
                }
                else
                {
                    //没连上
                }
            }
            catch (Exception ex)
            {
            }
        }
        /// <summary>
        /// 重连
        /// </summary>
        internal static void RestLink()
        {
            if (ipPort_ModbusClient.Count > 0)
            {
                foreach (var item in ipPort_ModbusClient)
                {
                    if (!item.Value.Connected)
                    {
                        Link(item.Value);
                    }
                }
            }
        }
        /// <summary>
        /// 读一个或多个线圈,返回一个bit bool数组
        /// </summary>
        /// <param name="address"></param>
        /// <param name="qty"></param>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        public static bool[] ReadCoils(int address, int qty, string ip, int port = 502)
        {
            bool[] res = new bool[0];
            var client = GetModbusClient(ip, port);
            if (client != null && client.Connected)
            {
                try
                {
                    res = client.ReadCoils(address, qty);
                    if (res.Length != 0)
                    {
                        //读取成功
                    }
                    else
                    {
                        //读取失败
                    }
                }
                catch (Exception ex)
                {
                }
            }
            else
            {
            }
            return res;
        }
        /// <summary>
        /// 写入单个线圈
        /// </summary>
        /// <param name="address"></param>
        /// <param name="value"></param>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        public static bool WriteSingleCoil(int address, bool value, string ip, int port = 502)
        {
            var res = false;
            var client = GetModbusClient(ip, port);
            if (client != null && client.Connected)
            {
                try
                {
                    client.WriteSingleCoil(address, value);
                    res = value == client.ReadCoils(address, 1)[0];
                    if (res)
                    {
                        //写入成功
                    }
                    else
                    {
                        //写入失败
                    }
                }
                catch (Exception ex)
                {
                }
            }
            else
            {
            }
            return res;
        }
        /// <summary>
        /// 写入多个线圈
        /// </summary>
        /// <param name="address"></param>
        /// <param name="values"></param>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        public static bool WriteMultipleCoils(int address, bool[] values, string ip, int port = 502)
        {
            var res = false;
            var client = GetModbusClient(ip, port);
            if (client != null && client.Connected)
            {
                try
                {
                    client.WriteMultipleCoils(address, values);
                    var dataRead = client.ReadCoils(address, values.Length);
                    res = values.SequenceEqual(dataRead);
                    if (res)
                    {
                        //写入成功
                    }
                    else
                    {
                        //写入失败
                    }
                }
                catch (Exception ex)
                {
                }
            }
            else
            {
            }
            return res;
        }
        /// <summary>
        /// 批量读取或单独读取保持寄存器,返回的是32位int数组
        /// </summary>
        /// <param name="address">读取起始位</param>
        /// <param name="qty">读取的数量</param>
        /// <param name="ip">IP地址</param>
        /// <param name="port">端口号</param>
        /// <returns></returns>
        public static int[] ReadHoldingRegisters(int address, int qty, string ip, int port = 502)
        {
            int[] res = new int[0];
            var client = GetModbusClient(ip, port);
            if (client != null && client.Connected)
            {
                try
                {
                    //一个寄存器是16位,返回2个int类型
                    res = client.ReadHoldingRegisters(address, qty);
                    if (res.Length != 0)
                    {
                        //读取成功
                    }
                    else
                    {
                        //读取失败
                    }
                }
                catch (Exception ex)
                {
                    //如果请求数量超出保持寄存器的最大数据行数,会报错
                    LogHelper.Info($"发生了异常:{ex.Message},IP:{ip},Port:{port}", "Error");
                }
            }
            else
            {
                LogHelper.Info($"未找到Modbus设备实例对象:IP:{ip},Port:{port}");
            }
            return res;
        }
        /// <summary>
        /// 写入单个寄存器数据
        /// </summary>
        /// <param name="address"></param>
        /// <param name="value"></param>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        public static bool WriteSingleRegister(int address, int value, string ip, int port = 502)
        {
            var res = false;
            var client = GetModbusClient(ip, port);
            if (client != null && client.Connected)
            {
                try
                {
                    client.WriteSingleRegister(address, value);
                    res = value == client.ReadHoldingRegisters(address, 1)[0];
                    if (res)
                    {
                        //写入成功
                    }
                    else
                    {
                        //写入失败
                    }
                }
                catch (Exception ex)
                {
                }
            }
            else
            {
            }
            return res;
        }
        /// <summary>
        /// 写入多个寄存器数据
        /// </summary>
        /// <param name="address"></param>
        /// <param name="values"></param>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        public static bool WriteMultipleRegisters(int address, int[] values, string ip, int port = 502)
        {
            var res = false;
            var client = GetModbusClient(ip, port);
            var log = string.Join(",", values.Select(x => x.ToString()));
            if (client != null && client.Connected)
            {
                try
                {
                    client.WriteMultipleRegisters(address, values);
                    var dataRead = client.ReadHoldingRegisters(address, values.Length);
                    res = values.SequenceEqual(dataRead);
                    if (res)
                    {
                        LogHelper.Info($"写入成功,IP:{ip},Port:{port},{log}");
                    }
                    else
                    {
                        LogHelper.Info($"写入失败,IP:{ip},Port:{port},{log}");
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.Info($"发生了异常:{ex.Message},IP:{ip},Port:{port},{log}","Error");
                }
            }
            else
            {
                LogHelper.Info($"未配置的设备信息,IP:{ip},Port:{port},{log}");
            }
            return res;
        }
        /// <summary>
        /// 读一个或多个离散输入,返回一个bit真假数组
        /// </summary>
        /// <param name="address"></param>
        /// <param name="qty"></param>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        public static bool[] ReadDiscreteInputs(int address, int qty, string ip, int port = 502)
        {
            bool[] res = new bool[0];
            var client = GetModbusClient(ip, port);
            if (client != null && client.Connected)
            {
                try
                {
                    res = client.ReadDiscreteInputs(address, qty);
                    if (res.Length != 0)
                    {
                        //读取成功
                    }
                    else
                    {
                        //读取失败
                    }
                }
                catch (Exception ex)
                {
                }
            }
            else
            {
            }
            return res;
        }
        /// <summary>
        /// 读一个或多个输入寄存器,返回一个int32位数组
        /// </summary>
        /// <param name="address"></param>
        /// <param name="qty"></param>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        public static int[] ReadInputRegisters(int address, int qty, string ip, int port = 502)
        {
            int[] res = new int[0];
            var client = GetModbusClient(ip, port);
            if (client != null && client.Connected)
            {
                try
                {
                    res = client.ReadInputRegisters(address, qty);
                    if (res.Length != 0)
                    {
                        //读取成功
                    }
                    else
                    {
                        //读取失败
                    }
                }
                catch (Exception ex)
                {
                }
            }
            else
            {
            }
            return res;
        }
        /// <summary>
        /// 获取modbus通讯对象
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        private static ModbusClient GetModbusClient(string ip, int port)
        {
            if (ipPort_ModbusClient.ContainsKey($"{ip}:{port}"))
            {
                return ipPort_ModbusClient[$"{ip}:{port}"];
            }
            else
            {
                return null;
            }
        }
        /// <summary>
        /// 通过Modbus协议连接下位机时需要的model,应该放在model层,这里我懒了
        /// </summary>
        public class ModbusConfigModel
        {
            public string Ip { set; get; }//IP地址
            public int Port { set; get; }//端口号
        }
    }
}
Devices/OpcUaHelper.cs
New file
@@ -0,0 +1,192 @@
using Opc.Ua.Client;
using Opc.Ua;
using System;
using Opc.Ua.Configuration;
namespace HH.WCS.Mobox3.AnGang.Devices
{
    internal class OpcUaHelper
    {
        private static Opc.Ua.Client.Session session;
        static OpcUaHelper()
        {
            CreateUpcSession();
        }
        /// <summary>
        /// 连接OPC服务
        /// </summary>
        internal static async void CreateUpcSession()
        {
            try
            {
                // 创建一个应用配置对象,用于设置应用名称、唯一标识、类型、证书和安全策略
                var config = new ApplicationConfiguration()
                {
                    ApplicationName = "MyClient",
                    ApplicationUri = Utils.Format(@"urn:{0}:MyClient", System.Net.Dns.GetHostName()),
                    ApplicationType = ApplicationType.Client,
                    SecurityConfiguration = new SecurityConfiguration
                    {
                        ApplicationCertificate = new CertificateIdentifier { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\MachineDefault", SubjectName = "MyClientSubjectName" },
                        TrustedIssuerCertificates = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\UA Certificate Authorities" },
                        TrustedPeerCertificates = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\UA Applications" },
                        RejectedCertificateStore = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\RejectedCertificates" },
                        AutoAcceptUntrustedCertificates = true,
                        RejectSHA1SignedCertificates = false,
                        MinimumCertificateKeySize = 1024,
                        NonceLength = 32,
                    },
                    TransportConfigurations = new TransportConfigurationCollection(),
                    TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
                    ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 },
                    TraceConfiguration = new TraceConfiguration()
                };
                // 验证应用配置对象
                await config.Validate(ApplicationType.Client);
                // 设置证书验证事件,用于自动接受不受信任的证书
                if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates)
                {
                    config.CertificateValidator.CertificateValidation += (s, e) => { e.Accept = (e.Error.StatusCode == StatusCodes.BadCertificateUntrusted); };
                }
                // 创建一个应用实例对象,用于检查证书
                var application = new ApplicationInstance(config);
                // 检查应用实例对象的证书
                bool check = await application.CheckApplicationInstanceCertificate(false, 2048);
                // 创建一个会话对象,用于连接到 OPC UA 服务器
                EndpointDescription endpointDescription = CoreClientUtils.SelectEndpoint("opc.tcp://172.16.57.41:4840", true);
                EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(config);
                ConfiguredEndpoint endpoint = new ConfiguredEndpoint(null, endpointDescription, endpointConfiguration);
                session = await Session.Create(config, endpoint, false, false, "DataCollector", 60000, new UserIdentity(), null);
                if (session != null && session.Connected)
                {
                    Console.WriteLine("The session is connected to the OPC UA server.");
                    LogHelper.Info($"创建OPC连接成功", "OPC");
                }
                else
                {
                    Console.WriteLine("The session is not connected to the OPC UA server.");
                    LogHelper.Info($"创建OPC连接失败", "OPC");
                }
            }
            catch (Exception e)
            {
                LogHelper.Info($"连接OPC服务异常" + e.Message, "OPC");
            }
        }
        /// <summary>
        /// 读取OPC节点数据
        /// </summary>
        /// <param name="nodeId"></param>
        internal static object ReadOpcValue(string nodeId)
        {
            try
            {
                if (session != null && session.Connected)
                {
                    // 读取数据节点
                    DataValue item = session.ReadValue(nodeId: nodeId);
                    LogHelper.Info($"OPC读取:nodeid:{nodeId},value:{item.Value}", "OPC");
                    return item.Value;
                }
                else
                {
                    Console.WriteLine("The session is not connected to the OPC UA server.");
                    LogHelper.Info($"OPC连接失败", "OPC");
                    CreateUpcSession();
                }
            }
            catch (Exception e)
            {
                LogHelper.Info($"读取OPC数据异常" + e.Message, "OPC");
            }
            return null;
        }
        /// <summary>
        /// 写OPC节点数据
        /// </summary>
        /// <param name="nodeId"></param>
        /// <param name="val"></param>
        internal static void WriteOpcValue(string nodeId,bool val)
        {
            try
            {
                if (session != null && session.Connected)
                {
                    // 写入数据到节点
                    WriteValue writeValue = new WriteValue
                    {
                        NodeId = new NodeId(nodeId),
                        AttributeId = Attributes.Value,
                        Value = new DataValue(val)
                    };
                    StatusCodeCollection results;
                    DiagnosticInfoCollection diagnosticInfos;
                    session.Write(null, new WriteValueCollection { writeValue }, out results, out diagnosticInfos);
                    Console.WriteLine($"Write Status for {nodeId}: {results[0]}");
                    LogHelper.Info($"OPC写入:nodeid:{nodeId},value:{val}", "OPC");
                }
                else
                {
                    Console.WriteLine("The session is not connected to the OPC UA server.");
                    LogHelper.Info($"OPC连接失败", "OPC");
                    CreateUpcSession();
                }
            }
            catch (Exception e)
            {
                LogHelper.Info($"写入OPC数据异常" + e.Message, "OPC");
            }
        }
        /// <summary>
        /// 写OPC节点数据
        /// </summary>
        /// <param name="nodeId"></param>
        /// <param name="val"></param>
        internal static void WriteOpcValue(string nodeId, int val)
        {
            try
            {
                if (session != null && session.Connected)
                {
                    // 写入数据到节点
                    WriteValue writeValue = new WriteValue
                    {
                        NodeId = new NodeId(nodeId),
                        AttributeId = Attributes.Value,
                        Value = new DataValue(val)
                    };
                    StatusCodeCollection results;
                    DiagnosticInfoCollection diagnosticInfos;
                    session.Write(null, new WriteValueCollection { writeValue }, out results, out diagnosticInfos);
                    Console.WriteLine($"Write Status for {nodeId}: {results[0]}");
                    LogHelper.Info($"OPC写入:nodeid:{nodeId},value:{val}", "OPC");
                }
                else
                {
                    Console.WriteLine("The session is not connected to the OPC UA server.");
                    LogHelper.Info($"OPC连接失败", "OPC");
                    CreateUpcSession();
                }
            }
            catch (Exception e)
            {
                LogHelper.Info($"写入OPC数据异常" + e.Message, "OPC");
            }
        }
    }
}
Devices/PlcHelper.cs
New file
@@ -0,0 +1,99 @@
using HH.WCS.Mobox3.AnGang.process;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Devices
{
    internal class PlcHelper
    {
        internal static void Receive(string ip, string msg) {
            //处理设备信号
            DeviceProcess.Analysis(msg, ip);
        }
        internal static bool SendHex(string ip, string msg) {
            return TcpServer.TcpServerSend(ip, Hex2Bytes(msg));
        }
        internal static void SendAscii(string ip, string msg) {
            TcpServer.TcpServerSend(ip, Encoding.ASCII.GetBytes(msg));
        }
        internal static byte[] Hex2Bytes(string hexString) {
            hexString = hexString.Replace(" ", "");
            if ((hexString.Length % 2) != 0)
                hexString += " ";
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            return returnBytes;
        }
        internal static string Hex2Ascii(string hexString) {
            hexString = hexString.Replace(" ", "");
            if ((hexString.Length % 2) != 0)
                hexString += " ";
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            return Encoding.ASCII.GetString(returnBytes);
        }
        #region 进制转换+CRC
        internal static bool CheckCRC(string hex) {
            var result = false;
            var data = hex.Replace(" ", "");
            if (data.Length % 2 == 0) {
                var code1 = data.Substring(data.Length - 4, 4).ToLower();
                var code2 = BitConverter.ToString(CRC16LH(Hex2Bytes(data.Substring(0, data.Length - 4)))).Replace("-", "").Replace(" ", "").ToLower();
                result = code1 == code2;
            }
            return result;
        }
        internal static byte[] CRC16LH(byte[] pDataBytes) {
            ushort crc = 0xffff;
            ushort polynom = 0xA001;
            for (int i = 0; i < pDataBytes.Length; i++) {
                crc ^= pDataBytes[i];
                for (int j = 0; j < 8; j++) {
                    if ((crc & 0x01) == 0x01) {
                        crc >>= 1;
                        crc ^= polynom;
                    }
                    else {
                        crc >>= 1;
                    }
                }
            }
            byte[] result = BitConverter.GetBytes(crc);
            return result;
        }
        internal static byte[] CRC16HL(byte[] pDataBytes) {
            ushort crc = 0xffff;
            ushort polynom = 0xA001;
            for (int i = 0; i < pDataBytes.Length; i++) {
                crc ^= pDataBytes[i];
                for (int j = 0; j < 8; j++) {
                    if ((crc & 0x01) == 0x01) {
                        crc >>= 1;
                        crc ^= polynom;
                    }
                    else {
                        crc >>= 1;
                    }
                }
            }
            byte[] result = BitConverter.GetBytes(crc).Reverse().ToArray();
            return result;
        }
        #endregion
    }
}
Devices/S7Helper.cs
New file
@@ -0,0 +1,423 @@
using HH.WCS.Mobox3.AnGang.Controllers;
using Newtonsoft.Json.Linq;
using S7.Net;
using S7.Net.Types;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Services.Description;
namespace HH.WCS.Mobox3.AnGang.Devices
{
    /// <summary>
    /// 西门子plc
    /// </summary>
    public class S7Helper
    {
        public static Dictionary<string, Plc> ip_Plc = new Dictionary<string, Plc>();//内存,连接上的PLC通讯对象
        public S7Helper(string ip, short rack, short slot)
        {
            Init(new S7ConfigModel() { Ip = ip, Rack = rack, Slot = slot, CpuType = CpuType.S71500 });
        }
        /// <summary>
        /// S7启动初始化
        /// </summary>
        public static void Init(S7ConfigModel s7ConfigInfo)
        {
            //配置文件读取所有的plc进行初始化
            try
            {
                if (s7ConfigInfo == null)
                {
                    //读取配置信息失败
                    return;
                }
                var plc = new Plc(s7ConfigInfo.CpuType, s7ConfigInfo.Ip, s7ConfigInfo.Rack, s7ConfigInfo.Slot);
                ip_Plc.Add(s7ConfigInfo.Ip, plc);
                Link(plc);
            }
            catch (Exception ex)
            {
                LogHelper.Info($"{ex.Message}\r\n{ex.StackTrace}");
            }
        }
        /// <summary>
        /// 重连
        /// </summary>
        public static void RestLink()
        {
            if (ip_Plc.Count>0)
            {
                foreach (var item in ip_Plc)
                {
                    if(!item.Value.IsConnected)
                    {
                        Link(item.Value);
                    }
                }
            }
        }
        /// <summary>
        /// 连接PLC
        /// </summary>
        /// <param name="plc"></param>
        private static void Link(Plc plc)
        {
            try
            {
                plc.Close();
                plc.Open();
                if (plc.IsConnected)
                {
                    LogHelper.Info($"连接上{plc.IP}");//连接上
                }
                else
                {
                    LogHelper.Info($"没连上{plc.IP}");//没连上
                }
            }
            catch (Exception ex)
            {
                LogHelper.Info($"{ex.Message}\r\n{ex.StackTrace}");
            }
        }
        /// <summary>
        /// 批量读取或单独读取DB块数据(8位byte),并转换成字符串形式
        /// </summary>
        /// <param name="deviceIp">plc设备通讯地址</param>
        /// <param name="dbNo">DB块号</param>
        /// <param name="startByteAdr">起始byte地址,最小值0,1=8位=1个Block</param>
        /// <param name="count">读取的个数,1个=8位十六进制数</param>
        /// <returns></returns>
        public static string ReadString(string deviceIp, int dbNo, int startByteAdr, int count)
        {
            string result = "";
            try
            {
                var plc = GetPlc(deviceIp);
                if (plc != null)
                {
                    if (plc.IsConnected)
                    {
                        var data = plc.ReadBytes(DataType.DataBlock, dbNo, startByteAdr, count);
                        result = System.Text.Encoding.UTF8.GetString(data).TrimEnd('\0').TrimEnd('\n').TrimEnd('\r'); ;//此方法可以把byte数组转换成字符串,但是会造成\0\u结束符不显示,需要下位机正确的数据
                        if (result == string.Empty)
                        {
                            Link(plc);//设备发送的数据为空,重连
                        }
                    }
                    else
                    {
                        Link(plc);//设备未连接,重连
                    }
                }
                else
                {
                    LogHelper.Info($"不存在的设备。配置文件中是否包含其设备。");//不存在的设备。配置文件中是否包含其设备。
                }
            }
            catch (Exception ex)
            {
                LogHelper.Info($"{ex.Message}\r\n{ex.StackTrace}");
            }
            return result;
        }
        /// <summary>
        /// 批量写入或单独写入DB块数据(8位byte),以字符串转换byte形式写入
        /// </summary>
        /// <param name="deviceIp">plc设备通讯地址</param>
        /// <param name="dbNo">DB块号</param>
        /// <param name="startByteAdr">起始byte地址,最小值0,1=8位=1个Block</param>
        /// <param name="data">要写入的数据</param>
        /// <returns></returns>
        public static bool WriteString(string deviceIp, int dbNo, int startByteAdr, string data)
        {
            var result = false;
            try
            {
                var plc = GetPlc(deviceIp);
                if (plc != null)
                {
                    if (plc.IsConnected)
                    {
                        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(data);
                        plc.WriteBytes(DataType.DataBlock, dbNo, startByteAdr, bytes);
                        if (!result)
                        {
                            //写完再读一次确认
                            var readData = ReadString(deviceIp, dbNo, startByteAdr, data.Length);
                            result = readData == data;
                        }
                    }
                    else
                    {
                        Link(plc);//设备未连接,重连
                    }
                }
                else
                {
                    //不存在的设备。配置文件中是否包含其设备。
                }
            }
            catch (Exception ex)
            {
                LogHelper.Info($"{ex.Message}\r\n{ex.StackTrace}");
            }
            return result;
        }
        /// <summary>
        /// 批量读取或单独读取DB块数据(8位byte)
        /// </summary>
        /// <param name="deviceIp">plc设备通讯地址</param>
        /// <param name="dbNo">DB块号</param>
        /// <param name="startByteAdr">起始byte地址,最小值0,1=8位=1个Block</param>
        /// <param name="count">读取的个数,1个=8位十六进制数</param>
        /// <returns></returns>
        public static byte[] ReadBytes(string deviceIp, int dbNo, int startByteAdr, int count)
        {
            byte[] result = null;
            try
            {
                var plc = GetPlc(deviceIp);
                if (plc != null)
                {
                    if (plc.IsConnected)
                    {
                        result = plc.ReadBytes(DataType.DataBlock, dbNo, startByteAdr, count);
                        if (result.Length == 0)
                        {
                            Link(plc);//设备发送的数据为空,重连
                        }
                    }
                    else
                    {
                        Link(plc);//设备未连接,重连
                    }
                }
                else
                {
                    LogHelper.Info($"不存在的设备。配置文件中是否包含其设备。");//不存在的设备。配置文件中是否包含其设备。
                }
            }
            catch (Exception ex)
            {
                LogHelper.Info($"{ex.Message}\r\n{ex.StackTrace}");
            }
            return result;
        }
        /// <summary>
        /// 批量写入或单独写入DB块数据(8位byte)
        /// </summary>
        /// <param name="deviceIp">plc设备通讯地址</param>
        /// <param name="dbNo">DB块号</param>
        /// <param name="startByteAdr">起始byte地址,最小值0,1=8位=1个Block</param>
        /// <param name="data">要写入的数据</param>
        /// <returns></returns>
        public static bool WriteBytes(string deviceIp, int dbNo, int startByteAdr, byte[] data)
        {
            var result = false;
            try
            {
                var plc = GetPlc(deviceIp);
                if (plc != null)
                {
                    if (plc.IsConnected)
                    {
                        plc.WriteBytes(DataType.DataBlock, dbNo, startByteAdr, data);
                        if (!result)
                        {
                            //写完再读一次确认
                            var readData = ReadBytes(deviceIp, dbNo, startByteAdr, data.Length);
                            result = readData.SequenceEqual(data);
                        }
                    }
                    else
                    {
                        Link(plc);//设备未连接,重连
                    }
                }
                else
                {
                    LogHelper.Info($"不存在的设备。配置文件中是否包含其设备。");//不存在的设备。配置文件中是否包含其设备。
                }
            }
            catch (Exception ex)
            {
                LogHelper.Info($"{ex.Message}\r\n{ex.StackTrace}");
            }
            return result;
        }
        /// <summary>
        /// 批量读取或单独读取DB块数据(1位bit)
        /// </summary>
        /// <param name="deviceIp">plc设备通讯地址</param>
        /// <param name="dbNo">DB块号</param>
        /// <param name="startByteAdr">起始byte地址,最小值0,1=8位=1个Block</param>
        /// <param name="count">要读取多少位</param>
        /// <param name="bitAdr">从第几位开始读取</param>
        /// <returns></returns>
        public static BitArray ReadBits(string deviceIp, int dbNo, int startByteAdr, int count, byte bitAdr = 0)
        {
            BitArray result = null;
            try
            {
                var plc = GetPlc(deviceIp);
                if (plc != null)
                {
                    if (plc.IsConnected)
                    {
                        var data = plc.Read(DataType.DataBlock, dbNo, startByteAdr, VarType.Bit, count, bitAdr);
                        if (count == 1)
                        {
                            result = new BitArray(new bool[] { (bool)data });
                        }
                        else
                        {
                            result = (BitArray)data;
                        }
                        if (result.Length == 0)
                        {
                            Link(plc);//设备发送的数据为空,重连
                        }
                    }
                    else
                    {
                        Link(plc);//设备未连接,重连
                    }
                }
                else
                {
                    LogHelper.Info($"不存在的设备。配置文件中是否包含其设备。");//不存在的设备。配置文件中是否包含其设备。
                }
            }
            catch (Exception ex)
            {
                LogHelper.Info($"{ex.Message}\r\n{ex.StackTrace}");
            }
            return result;
        }
        /// <summary>
        /// 批量写入或单独写入DB块数据(1位bit)
        /// </summary>
        /// <param name="deviceIp">plc设备通讯地址</param>
        /// <param name="dbNo">DB块号</param>
        /// <param name="startByteAdr">起始byte地址,最小值0,1=8位=1个Block</param>
        /// <param name="biteAdr">起始bit地址,从第几位开始写k</param>
        /// <param name="bitValue">要写入的数据</param>
        /// <returns></returns>
        public static bool WriteBits(string deviceIp, int dbNo, int startByteAdr, byte biteAdr, BitArray bitValue)
        {
            var result = false;
            try
            {
                var plc = GetPlc(deviceIp);
                if (plc != null)
                {
                    if (plc.IsConnected)
                    {
                        for (int i = 0; i < bitValue.Length; i++)
                        {
                            plc.WriteBit(DataType.DataBlock, dbNo, startByteAdr, biteAdr + i, bitValue[i]);
                        }
                        if (!result)
                        {
                            //写完再读一次确认
                            var readData = ReadBits(deviceIp, dbNo, startByteAdr, bitValue.Length, biteAdr);
                            result = CompareBitArray(readData, bitValue);
                        }
                    }
                    else
                    {
                        Link(plc);//设备未连接,重连
                    }
                }
                else
                {
                    LogHelper.Info($"不存在的设备。配置文件中是否包含其设备。");//不存在的设备。配置文件中是否包含其设备。
                }
            }
            catch (Exception ex)
            {
                LogHelper.Info($"{ex.Message}\r\n{ex.StackTrace}");
            }
            return result;
        }
        /// <summary>
        /// 获取PLC读写对象
        /// </summary>
        /// <param name="plc"></param>
        /// <returns></returns>
        private static Plc GetPlc(string plc)
        {
            if (ip_Plc.ContainsKey(plc))
            {
                return ip_Plc[plc];
            }
            else
            {
                return null;
            }
        }
        /// <summary>
        /// 比较两个二进制的数值是否相同
        /// </summary>
        /// <param name="b1"></param>
        /// <param name="b2"></param>
        /// <returns></returns>
        private static bool CompareBitArray(BitArray b1, BitArray b2)
        {
            bool result = true;
            b1.Xor(b2).Not();//异或操作 然后 非操作
            foreach (var item in b1)
            {
                if (!(bool)item)
                {
                    result = false;
                    break;
                }
            }
            return result;
        }
        /// <summary>
        /// 通过S7协议连接下位机时需要的model,应该放在model层,这里我懒了
        /// </summary>
        public class S7ConfigModel
        {
            public CpuType CpuType { set; get; }//协议类型
            public string Ip { set; get; }//IP地址
            public short Rack { set; get; }//架子号
            public short Slot { set; get; }//插槽号
        }
    }
}
Devices/ScanCodeHelper.cs
New file
@@ -0,0 +1,63 @@
using HH.WCS.Mobox3.AnGang.Dispatch;
using HH.WCS.Mobox3.AnGang.Models;
using HH.WCS.Mobox3.AnGang.config;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HH.WCS.Mobox3.AnGang.Helpers;
namespace HH.WCS.Mobox3.AnGang.Devices
{
    /// <summary>
    /// 小车读卡器通过TCPServer发送消息存储在这
    /// </summary>
    public class ScanCodeHelper
    {
        public static Dictionary<string, ScanInfoModel> scanInfoDic = new Dictionary<string, ScanInfoModel>();//内存信息缓存
        internal static bool GetRFIDByAgvCode(string agvCode,string RFID)
        {
            var db = DbHelper.GetDbClient();
            var task = new TN_Task();
            task = db.Queryable<TN_Task>().Where(a => a.S_EQ_NO == agvCode && a.N_B_STATE == 2).OrderByDescending(b => b.T_CREATE).First();
            if (task != null && RFID.Contains(task.S_CNTR_CODE))
            {
                LogHelper.Info($"校验成功Agv:{agvCode}容器号:{RFID}");
                return true;
            }
            else
            {
                LogHelper.Info($"校验失败Agv:{agvCode}容器号:{RFID}");
                //校验失败就取消任务
                var task1 = Task.Run(() =>
                {
                    if (task != null)
                    {
                        var res = NDCApi.ChangeOrderParam(task.S_CODE, 6, "2");
                        LogHelper.Info($"AGV校验RFID失败,发送取消任务命令参数6改为2,任务号{task.S_CODE}");
                        if (res.err_code==0)
                        {
                            LogHelper.Info($"AGV校验RFID失败,发送取消任务命令参数6改为2,任务号{task.S_CODE},结果:取消成功");
                        }
                        else
                        {
                            LogHelper.Info($"AGV校验RFID失败,发送取消任务命令参数6改为2,任务号{task.S_CODE},结果:取消失败:{res.err_msg}");
                        }
                    }
                });
                return false;
            }
        }
    }
    public class ScanInfoModel
    {
        public string AgvCode { get; set; }//agv编号
        public string AgvAddress { get; set; }//agv读卡器地址
        public string RFID { get; set; }//agv读卡器上报的RFID,托盘
    }
}
Devices/TcpClient.cs
New file
@@ -0,0 +1,85 @@
using HH.WCS.Mobox3.AnGang;
using HH.WCS.Mobox3.AnGang.Devices;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Devices {
    internal class TcpClient
    {
        /// <summary>
        ///
        /// </summary>
        /// <param name="ip">127.0.0.1</param>
        /// <param name="port">8888</param>
        /// <param name="hex">01 02 00 00 00 0C 78 0F</param>
        /// <returns></returns>
        private static string SendHexOnce(string ip, int port, string hex) {
            var res = string.Empty;
            Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            client.Connect(ip, port);
            client.ReceiveTimeout = 2000;
            if (client.Connected) {
                client.Send(PlcHelper.Hex2Bytes(hex));
                byte[] buffer = new byte[1024];
                try {
                    var length = client.Receive(buffer, SocketFlags.None);
                    byte[] data = new byte[length];
                    Array.Copy(buffer, data, length);
                    res = BitConverter.ToString(data).Replace("-", "");
                }
                catch (Exception ex) {
                    LogHelper.Error(ex.Message, ex);
                }
                client.Disconnect(true);
                client.Dispose();
            }
            client = null;
            return res;
        }
        /// <summary>
        /// 读保持寄存器,modbus rtu的封装
        /// </summary>
        /// <param name="address"></param>
        /// <param name="qty"></param>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        internal int[] ReadInputRegistersRtu(int address, int qty, string ip, int port = 502) {
            List<int> res = new List<int>();
            var hex = $"0103{address.ToString("X4")}{qty.ToString("X4")}";
            hex = hex + BitConverter.ToString(PlcHelper.CRC16LH(PlcHelper.Hex2Bytes(hex))).Replace("-", "").Replace(" ", "");
            var data = SendHexOnce(ip, port, hex);
            if (!string.IsNullOrEmpty(data)) {
                if (PlcHelper.CheckCRC(data)) {
                    var lenght = Convert.ToInt16(data.Substring(4, 2), 16) / 2;
                    for (int i = 0; i < lenght; i++) {
                        res[i] = Convert.ToInt16(data.Substring(6 + 4 * 1, 4), 16);
                    }
                }
            }
            return res.ToArray();
        }
        /// <summary>
        /// 写单个寄存器
        /// </summary>
        /// <param name="address"></param>
        /// <param name="value"></param>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        internal bool WriteSingleRegisterRtu(int address, int value, string ip, int port = 502) {
            var res = false;
            var hex = $"0106{address.ToString("X4")}{value.ToString("X4")}";
            hex = hex + BitConverter.ToString(PlcHelper.CRC16LH(PlcHelper.Hex2Bytes(hex))).Replace("-", "").Replace(" ", "");
            var data = SendHexOnce(ip, port, hex);
            if (!string.IsNullOrEmpty(data)) {
                res = true;
            }
            return res;
        }
    }
}
Devices/TcpServer.cs
New file
@@ -0,0 +1,251 @@
using HH.WCS.Mobox3.AnGang.Dispatch;
using HH.WCS.Mobox3.AnGang.config;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace HH.WCS.Mobox3.AnGang.Devices
{
    public class TcpServer
    {
        public TcpServer(string ip, int port)
        {
            Init(ip, port);
        }
        private void Init(string ip, int port)
        {
            //创建一个新的Socket,这里我们使用最常用的基于TCP的Stream Socket(流式套接字)
            var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                //将该socket绑定到主机上面的某个端口,端口应该放到配置文件中
                socket.Bind(new IPEndPoint(IPAddress.Parse(ip), port));
                Console.WriteLine(port);
                //启动监听,并且设置一个最大的队列长度
                socket.Listen(30);
                //开始接受客户端连接请求
                socket.BeginAccept(new AsyncCallback(ClientAccepted), socket);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
        public static Dictionary<string, Socket> clients = new Dictionary<string, Socket>();
        public static Dictionary<string, byte[]> buffers = new Dictionary<string, byte[]>();
        public static Dictionary<string,bool> isSend = new Dictionary<string, bool>();
        public static Dictionary<string,bool> isCheck = new Dictionary<string, bool>();
        public static Dictionary<string,int> saoMa = new Dictionary<string, int>();
        public static void ClientAccepted(IAsyncResult ar)
        {
            var socket = ar.AsyncState as Socket;
            var client = socket.EndAccept(ar);
            string remote_ip = ((System.Net.IPEndPoint)client.RemoteEndPoint).Address.ToString();
            if (clients.Keys.Contains(remote_ip))
            {
                clients[remote_ip] = client;
            }
            else
            {
                clients.Add(remote_ip, client);
            }
            if (!buffers.Keys.Contains(remote_ip))
            {
                buffers.Add(remote_ip, new byte[1024]);
            }
            if (!isSend.Keys.Contains(remote_ip))
            {
                isSend.Add(remote_ip, false);
            }
            if (!isCheck.Keys.Contains(remote_ip))
            {
                isCheck.Add(remote_ip, false);
            }
            //给客户端发送一个欢迎消息
            //client.Send(Encoding.Unicode.GetBytes("Hi there, I accept you request at " + DateTime.Now.ToString()));
            Console.WriteLine(remote_ip);
            try
            {
                client.BeginReceive(buffers[remote_ip], 0, buffers[remote_ip].Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), client);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"【接收客户端的消息异常】:" + ex.Message);
            }
            //准备接受下一个客户端请求
            socket.BeginAccept(new AsyncCallback(ClientAccepted), socket);
        }
        public static void ReceiveMessage(IAsyncResult ar)
        {
            try
            {
                var socket = ar.AsyncState as Socket;
                string remote_ip = ((System.Net.IPEndPoint)socket.RemoteEndPoint).Address.ToString();
                var length = socket.EndReceive(ar);
                if (length == 0)
                {
                    clients.Remove(remote_ip);
                    buffers.Remove(remote_ip);
                    isSend.Remove(remote_ip);
                    isCheck.Remove(remote_ip);
                    saoMa.Remove(remote_ip);
                    return;
                }
                else
                {
                    if (!clients.Keys.Contains(remote_ip))
                    {
                        clients.Add(remote_ip, socket);
                    }
                    if (!buffers.Keys.Contains(remote_ip))
                    {
                        buffers.Add(remote_ip, new byte[1024]);
                    }
                    if (!isSend.Keys.Contains(remote_ip))
                    {
                        isSend.Add(remote_ip, false);
                    }
                    if (!isCheck.Keys.Contains(remote_ip))
                    {
                        isCheck.Add(remote_ip, false);
                    }
                    if (!saoMa.Keys.Contains(remote_ip))
                    {
                        saoMa.Add(remote_ip, 3);
                    }
                }
                    //LogHelper.Info($"接收到信息,IP:{remote_ip},MSG:{BitConverter.ToString(buffers[remote_ip])}");
                    if (buffers.Keys.Contains(remote_ip))
                    {
                        var messageBytes = new byte[length];
                        Array.Copy(buffers[remote_ip], 0, messageBytes, 0, length);
                    try
                    {
                        //读卡器校验
                        var message = BitConverter.ToString(messageBytes);
                        if (!saoMa.ContainsKey(remote_ip))
                        {
                            saoMa.Add(remote_ip, 3);
                        }
                        if (messageBytes.Length <= 20 && messageBytes.Length > 0)
                        {
                            saoMa[remote_ip] = 3;//未扫到码
                        }
                        if (messageBytes.Length >= 21 && isCheck[remote_ip])
                        {
                            byte[] rfid = new byte[12];
                            Array.Copy(messageBytes, 9, rfid, 0, 12);
                            string rfids16 = BitConverter.ToString(rfid);
                            string rfids = Encoding.ASCII.GetString(rfid);
                            //LogHelper.Info($"读卡器校验对应容器号:{rfids},其16进制形式:{rfids16}");
                            //if (ScanCodeHelper.Analysis(remote_ip, rfids))//校验RFID
                            //{
                            //    isCheck[remote_ip] = false;
                            //    saoMa[remote_ip] = 1;//扫码匹配
                            //}
                            //else
                            //{
                            //    isCheck[remote_ip] = false;
                            //    saoMa[remote_ip] = 2;//扫码不匹配
                            //}
                        }
                        else
                        {
                            LogHelper.Info($"不满足读卡器校验规定:IP:{remote_ip},MSG:{message}");
                        }
                    }
                    catch(Exception ex)
                    {
                        LogHelper.Info($"扫码校验发生了异常:{ex.Message}");
                        saoMa[remote_ip] = 4;//扫码异常
                    }
                    try
                    {
                    }
                    catch(Exception ex)
                    {
                        LogHelper.Info($"卷帘门校验发生了异常:{ex.Message}");
                    }
                        //TcpServerSend(remote_ip, System.Text.Encoding.Default.GetBytes(msgSend));
                        Array.Clear(buffers[remote_ip], 0, buffers[remote_ip].Length);//清空当前IP Buffer
                    }
                    else
                    {
                        if (!buffers.Keys.Contains(remote_ip))
                        {
                            buffers.Add(remote_ip, new byte[1024]);
                        }
                    }
                //接收下一个消息(因为这是一个递归的调用,所以这样就可以一直接收消息了)
                socket.BeginReceive(buffers[remote_ip], 0, buffers[remote_ip].Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket);
            }
            catch (Exception ex)
            {
            }
        }
        private static string GetHexString(byte[] buffer, int lenght)
        {
            return BitConverter.ToString(buffer, 0, lenght).Replace("-", string.Empty).ToLower();
        }
        public static bool TcpServerSend(string ip, byte[] msg)
        {
            if (clients.Keys.Contains(ip))
            {
                var client = clients[ip];
                if (client.Connected)
                {
                    try
                    {
                        client.Send(msg);
                        LogHelper.Info($"已发送给该AGV地址{ip},{msg}");
                        return true;
                    }
                    catch (SocketException ex)
                    {
                        LogHelper.Info(ex.Message, "Error");
                        clients[ip].Close();
                        clients.Remove(ip);
                    }
                }
                else
                {
                    clients[ip].Close();
                    clients.Remove(ip);
                }
            }
            else
            {
                LogHelper.Info("未找到该设备,是否已连接?");
            }
            return false;
        }
    }
}
Dispatch/GZRobot.cs
New file
@@ -0,0 +1,504 @@
using System;
using System.Collections.Generic;
using System.IdentityModel.Protocols.WSTrust;
using System.Threading.Tasks;
using HH.WCS.Mobox3.AnGang.config;
using HH.WCS.Mobox3.AnGang.Helper;
using HH.WCS.Mobox3.AnGang.Helpers;
using HH.WCS.Mobox3.AnGang.Models;
using HH.WCS.Mobox3.AnGang.Services;
using Newtonsoft.Json;
using static HH.WCS.Mobox3.AnGang.Controllers.ApiModel;
using static HH.WCS.Mobox3.AnGang.Dtos.Request.AgvRequest;
namespace HH.WCS.Mobox3.AnGang.Dispatch {
    /// <summary>
    /// 国自调度辅助类
    /// </summary>
    public class GZRobot {
        private static readonly HttpHelper apiHelper = new HttpHelper();
        private static readonly string baseUrl = AppStart.Settings.Config.RCSApiUrl;//配置文件获取国自调度地址
        //private static readonly string logName = "guozi";
        public static List<IOState> GetIO() {
            var result = apiHelper.Get(baseUrl + "api/engine/view/iostates/");
            var data = JsonConvert.DeserializeObject<gzResult<IOState>>(result);
            return data.data;
        }
        public static void UpdateIOState() {
            var data = new { data = new List<IOSateInfo>() };
            var result = apiHelper.Post(baseUrl + "api/engine/tasks/iostates/", JsonConvert.SerializeObject(data));
            var dataResult = JsonConvert.DeserializeObject<gzResult<IOStatesInfoResult>>(result);
        }
        public static int CreateOrder(string taskNo, int priority, string param, string ts = "churuku", string created_user = "hanhe") {
            LogHelper.Info($"CreateOrder参数信息:taskNo:{taskNo},priority:{priority},param:{param},ts:{ts},created_user:{created_user}", "API");
            var msg = "";
            var orderId = 0;
            var data = new OrderInfo() { order_name = taskNo, priority = priority, dead_line = DateTime.Now, ts_name = ts, parameters = param, created_user = created_user };
            var request = JsonConvert.SerializeObject(data);
            var response = apiHelper.Post(baseUrl + "api/om/order/", request);
            LogHelper.Info($"CreateOrder:url:{baseUrl}api/om/order/,request:{request}", "API");
            msg = $"[guozi-CreateOrder] request={request} response={response}";
            Console.WriteLine(msg);
            if (response != "") {
                try {
                    var dataResult = JsonConvert.DeserializeObject<gzResult<OrderInfoResult>>(response);
                    if (dataResult.code == 0) {
                        orderId = dataResult.data[0].in_order_id;
                    }
                }
                catch (Exception ex) {
                }
            }
            else {
                msg = "[guozi-CreateOrder]创建订单失败";
                Console.WriteLine(msg);
                LogHelper.Info($"创建订单失败", "API");
            }
            return orderId;
        }
        public static bool CancelOrder(int orderId) {
            bool result = false;
            string msg = "";
            var request = new CancelOrderInfo() { order_list = new List<int>(orderId) };
            var response = apiHelper.Post(baseUrl + "api/om/order/cancel/", JsonConvert.SerializeObject(request));
            msg = $"[guozi-CancelOrder] request={request};response={response}";
            Console.WriteLine(msg);
            if (response != "") {
                var dataResult = JsonConvert.DeserializeObject<gzResult<CancelOrderInfoResult>>(response);
                if (dataResult.code == 0) {
                    result = true;
                }
            }
            else {
                msg = "[guozi-CancelOrder]取消订单失败";
                Console.WriteLine(msg);
            }
            return result;
        }
        public static bool CancelGZOrder(int orderId) {
            bool result = false;
            string msg = "";
            List<CancelGZOrderInfo> requests = new List<CancelGZOrderInfo>();
            var request = new CancelGZOrderInfo() { order_id = orderId, order_command_type_id = 2 };
            requests.Add(request);
            var response = apiHelper.Put(baseUrl + "api/om/order/order-command/", JsonConvert.SerializeObject(requests));
            msg = $"[guozi-CancelOrder] request={requests};response={response}";
            if (response != "") {
                var dataResult = JsonConvert.DeserializeObject<CancelGZOrderResult>(response);
                if (dataResult.code == 0) {
                    msg = "[guozi-CancelOrder]取消订单成功";
                    Console.WriteLine(msg);
                    result = true;
                    return result;
                }
            }
            else {
                msg = "[guozi-CancelOrder]取消订单失败";
                Console.WriteLine(msg);
            }
            return result;
        }
        /// <summary>
        /// 订单状态反馈
        /// </summary>
        /// <returns></returns>
        public static GzResult orderStatusReport(orderStatusReportParme model) {
            GzResult result = new GzResult();
            AgvTaskState agv = new AgvTaskState();
            if (model == null) {
                result.resultCode = 1;
                result.orderID = model.orderID;
                result.msg = "返回订单状态失败";
            }
            switch (model.orderStatus) {
                case "active":
                    agv.state = 1;
                    break;
                case "waiting":
                    agv.state = 1;
                    break;
                case "source_finish":
                    //取货完成
                    agv.state = 4;
                    //var checkWeightTask = Task.Run(() => {
                    //    ChooseFinalEndLoc(model);
                    //});
                    break;
                case "dest_finish":
                    //卸货完成
                    agv.state = 6;
                    break;
                case "finish":
                    agv.state = 2;
                    break;
                case "manually_finish":
                    agv.state = 2;
                    break;
                case "cancel_finish":
                    agv.state = 7;
                    break;
                case "error":
                    agv.state = 7;
                    break;
                default:
                    agv.state = 0;
                    break;
            }
            if (agv.state != 0) {
                agv.task_no = model.orderName;
                agv.forklift_no = model.agvIDList;
                AgvService.OperateAgvTaskStatus(agv);
            }
            result.resultCode = 0;
            result.msg = "返回订单状态成功";
            result.orderID = model.orderID;
            LogHelper.Info("orderStatusReport返回信息" + JsonConvert.SerializeObject(result), "API");
            return result;
        }
        //public static void ChooseFinalEndLoc(orderStatusReportParme model) {
        //    var db = DbHelper.GetDbClient();
        //    var tn_task = db.Queryable<TN_Task>().First(a => a.S_EQ_NO == model.agvIDList && a.S_END_AREA == "" && a.S_END_LOC == "" && a.S_TYPE == "产品入库(PDA)");
        //    // 只要任务为产品入库(PDA),就需要重新指定终点(默认endLoc为"")
        //    if (tn_task.S_TYPE == "产品入库(PDA)") {
        //        var endLoc = new TN_Location();
        //        // 只当之前指定终点货架后,才尝试计算终点货位,否则交给人工决定
        //        if (tn_task.S_END_AREA != "") {
        //            if (tn_task.F_WEIGHT > 1500) {
        //                // 重量超过1.5t,需要选择1-3层货架
        //                endLoc = db.Queryable<TN_Location>().First(a => a.S_SHELF_CODE == tn_task.S_END_AREA && LocationHelper.IsFree(a) && a.N_CURRENT_NUM == 0 && a.N_HEIGHT <= 3);
        //            }
        //            else if (tn_task.F_WEIGHT > 0) {
        //                // 重量未超过1.5t,在指定货架随便选择1个
        //                endLoc = db.Queryable<TN_Location>().First(a => a.S_SHELF_CODE == tn_task.S_END_AREA && LocationHelper.IsFree(a) && a.N_CURRENT_NUM == 0);
        //            }
        //            else {
        //                // 没有接收到重量,或重量出错
        //                endLoc = null;
        //                LogHelper.Info($"错误的重量信息:{tn_task.F_WEIGHT}");
        //            }
        //            // 如果没有符合条件的货位,置空,等待PDA重新确定
        //            if (endLoc == null) {
        //                tn_task.S_END_AREA = "";
        //                tn_task.S_END_LOC = "";
        //                if (db.Updateable<TN_Task>(tn_task).ExecuteCommand() > 0) {
        //                    //LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
        //                    LogHelper.Info($"重新计算后没有合适货位,任务 {tn_task.S_CODE} 修改成功,修改终点货架和货位为空");
        //                }
        //                else {
        //                    LogHelper.Info($"重新计算后没有合适货位,任务 {tn_task.S_CODE} 修改失败,修改终点货架和货位为空");
        //                }
        //            }
        //            else {
        //                // 找到合适的货位,推送
        //                tn_task.S_END_LOC = endLoc.S_CODE;
        //                using (var trans = db.Ado.UseTran()) {
        //                    if (db.Updateable<TN_Task>(tn_task).ExecuteCommand() > 0) {
        //                        LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
        //                        trans.CommitTran();
        //                        LogHelper.Info($"计算货位成功,任务 {tn_task.S_CODE} 修改成功,终点货架为 {endLoc.S_SHELF_CODE},修改终点位置为 {endLoc.S_CODE}");
        //                    }
        //                    else {
        //                        trans.RollbackTran();
        //                        LogHelper.Info($"计算货位成功,任务 {tn_task.S_CODE} 修改失败,终点货架为 {endLoc.S_SHELF_CODE},修改终点位置为 {endLoc.S_CODE}");
        //                    }
        //                }
        //            }
        //        }
        //    }
        //}
        public class CancelGZOrderInfo
        {
            public int order_id { get; set; }
            public int order_command_type_id { get; set; }
        }
        public static QueryOrderResult QueryOrder(int id) {
            //
            var result = new QueryOrderResult() { agv_list = new List<int> { 0 } };
            string msg = "";
            var response = apiHelper.Get(baseUrl + $"/api/om/order/{id}/");
            msg = $"[guozi-QueryOrderResult] request={id};response={response}";
            Console.WriteLine(msg);
            if (response != "") {
                var data = JsonConvert.DeserializeObject<gzResult<QueryOrderResult>>(response);
                result = data.data[0];
            }
            else {
                msg = "[guozi-QueryOrderResult]查询订单信息失败";
                Console.WriteLine(msg);
            }
            return result;
        }
        /// <summary>
        /// 获取交互信息
        /// </summary>
        /// <param name="typeId">1任务状态  2开门或交管  3目的点</param>
        /// <param name="status"></param>
        /// <returns></returns>
        public static List<InteractInfoResult> QueryInteractInfo(int typeId, string status = "active") {
            //string aaa = "{\"app_name\": \"Gouzi client\", \"version\": \"1.0.0\", \"code\": 0, \"msg\": \"success\", \"data\": [{\"interaction_info_id\": 233, \"interaction_info_name\": \"TN2012030001\", \"interaction_info_desp\": null, \"interaction_info_type_id\": 3, \"value_json\": {\"state\": \"4\"}, \"info_status\": \"active\", \"return_value\": null}]}";
            //var data = JsonConvert.DeserializeObject<gzResult<InteractInfoResult>>(aaa);
            var list = new List<InteractInfoResult>();
            string msg = "";
            var result = apiHelper.Get(baseUrl + $"api/om/interaction_info/find_by_type/?type_id={typeId}&info_status={status}");
            if (!string.IsNullOrEmpty(result)) {
                Console.WriteLine(result);
                // {"app_name": "Gouzi client", "version": "1.0.0", "code": 0, "msg": "success", "data": [{"interaction_info_id": 230, "interaction_info_name": "2", "interaction_info_desp": null, "interaction_info_type_id": 3, "value_json": {"state": "4"}, "info_status": "active", "return_value": null}, {"interaction_info_id": 231, "interaction_info_name": "2", "interaction_info_desp": null, "interaction_info_type_id": 3, "value_json": {"state": "6"}, "info_status": "active", "return_value": null}, {"interaction_info_id": 232, "interaction_info_name": "2", "interaction_info_desp": null, "interaction_info_type_id": 3, "value_json": {"state": "2"}, "info_status": "active", "return_value": null}, {"interaction_info_id": 233, "interaction_info_name": "TN2012030001", "interaction_info_desp": null, "interaction_info_type_id": 3, "value_json": {"state": "4"}, "info_status": "active", "return_value": null}]}
                try {
                    var data = JsonConvert.DeserializeObject<gzResult<InteractInfoResult>>(result);
                    if (data.data != null) {
                        list = data.data;
                    }
                }
                catch (Exception ex) {
                    Console.WriteLine(ex.Message);
                }
            }
            else {
                msg = "[guozi-QueryInteractInfo]读取交互信息失败";
                Console.WriteLine(msg);
            }
            return list;
        }
        public static bool UpdateInteractInfo(UpdateInteractInfo interactInfo) {
            string msg = "";
            var result = false;
            var request = JsonConvert.SerializeObject(interactInfo);
            var response = apiHelper.Post(baseUrl + "api/om/interaction_info/update/", request);
            msg = $"[mes-UpdateInteractInfo] request={request};response={response}";
            if (response != "") {
                var dataResult = JsonConvert.DeserializeObject<gzResult<object>>(response);
                result = dataResult.code == 0;
            }
            else {
                msg = "[guozi-UpdateInteractInfo]更新交互信息失败";
                Console.WriteLine(msg);
            }
            return result;
        }
        public static List<CustomData> CustomBuf() {
            var res = new List<CustomData>();
            string msg = "";
            var result = apiHelper.Get(baseUrl + $"/api/engine/agvs/custom-buf/");
            if (!string.IsNullOrEmpty(result)) {
                Console.WriteLine(result);
                try {
                    var data = JsonConvert.DeserializeObject<gzResult<CustomData>>(result);
                    if (data.data != null) {
                        res = data.data;
                    }
                }
                catch (Exception ex) {
                    Console.WriteLine(ex.Message);
                }
            }
            else {
                msg = "[guozi-CustomBuf]读取交互信息失败";
                Console.WriteLine(msg);
            }
            return res;
        }
    }
    //public class CustomBufInfo {
    //    public string app_name { get; set; }
    //    public string version { get; set; }
    //    public int code { get; set; }
    //    public string msg { get; set; }
    //    public List<CustomData> data { get; set; }
    //}
    public class CustomData {
        public string agv_id { get; set; }
        public string parameter_varchar200_up { get; set; }
        public string parameter_varchar200_down { get; set; }
    }
    public class gzResult<T>
    {
        public string app_name { get; set; }
        public string version { get; set; }
        public int code { get; set; }
        public string msg { get; set; }
        public List<T> data { get; set; }
    }
    public class IOState
    {
        public int io_id { get; set; }
        public string io_name { get; set; }
        public string io_type_id { get; set; }
        public string io_type { get; set; }
        public int io_status_id { get; set; }
        public string io_status_type { get; set; }
        public string parameter_definition_int4_1 { get; set; }
        public int io_value_int4_1 { get; set; }
        public string parameter_definition_int4_2 { get; set; }
        public int io_value_int4_2 { get; set; }
        public string parameter_definition_int4_3 { get; set; }
        public int io_value_int4_3 { get; set; }
        public string parameter_definition_int4_4 { get; set; }
        public int io_value_int4_4 { get; set; }
        public string parameter_definition_json { get; set; }
        public string io_value_json { get; set; }
    }
    public class IOSateInfo
    {
        public int io_id { get; set; }
        public int io_status_id { get; set; }
        public int io_value_int4_1 { get; set; }
        public int io_value_int4_2 { get; set; }
        public int io_value_int4_3 { get; set; }
        public int io_value_int4_4 { get; set; }
        public string io_value_json { get; set; }
    }
    public class IOStatesInfoResult
    {
        public List<ResultInfo> success_list { get; set; }
        public List<ResultInfo> error_list { get; set; }
        public class ResultInfo { public int io_id { get; set; } }
    }
    public class OrderInfo
    {
        public string order_name { get; set; }
        public int priority { get; set; }
        public DateTime dead_line { get; set; }
        public string ts_name { get; set; }
        public string parameters { get; set; }//{\"dock\":1}
        public string created_user { get; set; }
    }
    public class OrderInfoResult
    {
        public int in_order_id { get; set; }
    }
    public class CancelOrderInfo
    {
        public List<int> order_list { get; set; }
    }
    public class CancelOrderInfoResult
    {
        public List<ResultInfo> success_list { get; set; }
        public List<ResultInfo> error_list { get; set; }
        public class ResultInfo { public int order_id { get; set; } }
    }
    public class cancle
    {
        public List<success_list> success_list { get; set; }
        public List<error_list> error_list { get; set; }
    }
    public class success_list
    {
        public int order_id { get; set; }
    }
    public class error_list
    {
    }
    public class CancelGZOrderResult
    {
        public string app_name { get; set; }
        public string version { get; set; }
        public int code { get; set; }
        public string msg { get; set; }
        public cancle data { get; set; }
        public List<int> success_list { get; set; }
        public List<int> error_list { get; set; }
    }
    public class QueryOrderResult
    {
        public int order_id { get; set; }
        public string order_name { get; set; }
        public int priority { get; set; }
        public DateTime dead_line { get; set; }
        public string ts_id { get; set; }
        public string parameters { get; set; }//{"TN_LocationName":"3-2-B", "PalletType":1}",
        public string trigger { get; set; }
        public string command { get; set; }
        public string status { get; set; }
        public List<int> agv_list { get; set; }
        public string current_task { get; set; }
        public string current_dest { get; set; }
        public string current_opt { get; set; }
        public string current_omi { get; set; }
        public DateTime create_time { get; set; }
        public DateTime? active_time { get; set; }
        public DateTime? finished_time { get; set; }
        public DateTime? cancel_time { get; set; }
        public string response_timespan { get; set; }
        public string execute_timespa { get; set; }
        public string total_timespan { get; set; }
    }
    public class InteractInfoResult
    {
        public int interaction_info_id { get; set; }
        public string interaction_info_name { get; set; }
        public string interaction_info_desp { get; set; }
        public int interaction_info_type_id { get; set; }
        public object value_json { get; set; }//{"dock": 1},
        public string info_status { get; set; }
        public string return_value { get; set; }
    }
    public class UpdateInteractInfo
    {
        public int interaction_info_id { get; set; }
        public string info_status { get; set; }
        public string return_value { get; set; }
    }
    public class interaction_state
    {
        public string state { get; set; }
    }
    public class interaction_door
    {
        public string door { get; set; }
    }
    public class interaction_bit
    {
        public string order { get; set; }
    }
}
Dispatch/HanAo.cs
New file
@@ -0,0 +1,165 @@
using HH.WCS.Mobox3.AnGang.config;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Web.Services.Description;
namespace HH.WCS.Mobox3.AnGang.Dispatch {
    /// <summary>
    /// 国自调度辅助类
    /// </summary>
    public class HanAo {
        private static readonly HttpHelper apiHelper = new HttpHelper();
        private static readonly string baseUrl ="";//配置文件里获取国自调度地址
        //private static readonly string logName = "hanao";
        public static bool CreateOrder(TaskInfoModel model) {
            var msg = "";
            var result = true;
            var request = JsonConvert.SerializeObject(model);
            var response = apiHelper.Post(baseUrl + ":9001/wcs-admin/api/receive", request);
            msg = $"[hanao-CreateOrder] request={request} response={response}";
            Console.WriteLine(msg);
            if (response != "") {
                try {
                    var dataResult = JsonConvert.DeserializeObject<HAResult>(response);
                    if (dataResult.code == "0") {
                        result = true;
                    }
                }
                catch (Exception ex) {
                    Console.WriteLine(ex.Message);
                }
            }
            else {
                msg = "[hanao-CreateOrder]创建订单失败";
                Console.WriteLine(msg);
            }
            LogHelper.Info(msg,"杭奥");
            return result;
        }
        public static bool CancelOrder(CancelModel model) {
            bool result = false;
            string msg = "";
            var request = JsonConvert.SerializeObject(model);
            var response = apiHelper.Post(baseUrl + ":9002/wcs-admin/api/cancel", request);
            msg = $"[hanao-CancelOrder] request={request};response={response}";
            Console.WriteLine(msg);
            if (response != "") {
                var dataResult = JsonConvert.DeserializeObject<HAResult>(response);
                if (dataResult.code == "0") {
                    result = true;
                }
            }
            else {
                msg = "[hanao-CancelOrder]取消订单失败";
                Console.WriteLine(msg);
            }
            LogHelper.Info(msg, "杭奥");
            return result;
        }
        public static bool QueryDevice(DeviceInfoModel model) {
            bool result = false;
            string msg = "";
            var request = JsonConvert.SerializeObject(model);
            var response = apiHelper.Get(baseUrl + ":9003//wcs-admin/api/dvc-state/", request);
            msg = $"[hanao-QueryDeviceResult] request={request};response={response}";
            Console.WriteLine(msg);
            if (response != "") {
                var dataResult = JsonConvert.DeserializeObject<HAResult>(response);
                if (dataResult.code == "0") {
                    result = true;
                }
            }
            else {
                msg = "[hanao-QueryOrderResult]查询订单信息失败";
                Console.WriteLine(msg);
            }
            LogHelper.Info(msg, "杭奥");
            return result;
        }
        public class TaskInfoModel {
            /// <summary>
            /// 请求pk
            /// </summary>
            public string requestPk { get; set; }
            /// <summary>
            /// 托盘条码
            /// </summary>
            public string contNo { get; set; }
            /// <summary>
            /// 托盘类型
            /// </summary>
            public string contType { get; set; } = "";
            /// <summary>
            /// 任务类型  1-入库 2-出库 3-移库
            /// </summary>
            public string trkType { get; set; }
            /// <summary>
            /// 1-999(值越大优先级越高)
            /// </summary>
            public string trkPrty { get; set; } = "1";
            public string frmPos { get; set; }
            public string toPos { get; set; }
            public string noticeInfo { get; set; } = "";
            /// <summary>
            /// 0-空托盘 1-实物
            /// </summary>
            public string isFull { get; set; } = "0";
            public string groupNo { get; set; } = "";
            public string clientCode { get; set; } = "WMS";
            /// <summary>
            /// 格式:2022-11-11 11:32:08
            /// </summary>
            public string reqTime { get; set; } = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        }
        public class HAResult {
            public string code { get; set; }
            public string msg { get; set; }
            /// <summary>
            ///
            /// </summary>
            public string requestPk { get; set; }
        }
        public class CancelModel {
            public string requestPk { get; set; }
            public string contNo { get; set; }
            public string clientCode { get; set; }
            public string reqTime { get; set; } = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        }
        public class DeviceInfoModel {
            public string requestPk { get; set; }
            public string dvcNo { get; set; }
            public string clientCode { get; set; }
            public string reqTime { get; set; } = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        }
        public class TaskStateInfoModel {
            public string requestPk { get; set; }
            public string contNo { get; set; }
            /// <summary>
            /// 双方系统共同定义 1-入库 2-出库 3-移库 (后续如有增加再协定)
            /// </summary>
            public string noticeType { get; set; }
            public string curPos { get; set; }
            public string noticeInfo { get; set; }
            /// <summary>
            /// 0-成功 (入库上架完成/出库下架完成/库内移库完成:移库只上报最终移库上架) 或 其他-异常码(反馈相关结果原因,WMS根据情况处理
            /// 1-入库有货 2-入远近有货 3-出库无货 4-出远近有货)
            /// </summary>
            public string code { get; set; }
            public string result { get; set; }
            public string clientCode { get; set; }
            public string reqTime { get; set; } = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        }
    }
}
Dispatch/HostToAGV.cs
New file
@@ -0,0 +1,550 @@
//------------------------------------------------------------------------------
// <auto-generated>
//     此代码由工具生成。
//     运行时版本:4.0.30319.42000
//
//     对此文件的更改可能会导致不正确的行为,并且如果
//     重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Serialization;
//
// 此源代码由 wsdl 自动生成, Version=4.6.1055.0。
//
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.6.1055.0")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(Name="HostToAGV", Namespace="http://127.0.0.1:9988/HostToAGV.wsdl")]
public  class HostToAGV : System.Web.Services.Protocols.SoapHttpClientProtocol {
    private System.Threading.SendOrPostCallback StartNewOrderWithQCmdOperationCompleted;
    private System.Threading.SendOrPostCallback AddNewOrderOperationCompleted;
    private System.Threading.SendOrPostCallback CancelOrderOperationCompleted;
    private System.Threading.SendOrPostCallback ChangeOrderOperationCompleted;
    private System.Threading.SendOrPostCallback QueryOrderOperationCompleted;
    private System.Threading.SendOrPostCallback OrderAddOperationCompleted;
    private System.Threading.SendOrPostCallback OrderChangeParamOperationCompleted;
    /// <remarks/>
    public HostToAGV() {
        this.Url = "http://127.0.0.1:9988/HostToAGV.cgi";
    }
    /// <remarks/>
    public event StartNewOrderWithQCmdCompletedEventHandler StartNewOrderWithQCmdCompleted;
    /// <remarks/>
    public event AddNewOrderCompletedEventHandler AddNewOrderCompleted;
    /// <remarks/>
    public event CancelOrderCompletedEventHandler CancelOrderCompleted;
    /// <remarks/>
    public event ChangeOrderCompletedEventHandler ChangeOrderCompleted;
    /// <remarks/>
    public event QueryOrderCompletedEventHandler QueryOrderCompleted;
    /// <remarks/>
    public event OrderAddCompletedEventHandler OrderAddCompleted;
    /// <remarks/>
    public event OrderChangeParamCompletedEventHandler OrderChangeParamCompleted;
    /// <remarks/>
    [System.Web.Services.Protocols.SoapDocumentMethodAttribute("", RequestNamespace="urn:HostToAGV", ResponseNamespace="urn:HostToAGV", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
    [return: System.Xml.Serialization.XmlElementAttribute("bufout", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string StartNewOrderWithQCmd([System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)] string bufin) {
        object[] results = this.Invoke("StartNewOrderWithQCmd", new object[] {
                    bufin});
        return ((string)(results[0]));
    }
    /// <remarks/>
    public System.IAsyncResult BeginStartNewOrderWithQCmd(string bufin, System.AsyncCallback callback, object asyncState) {
        return this.BeginInvoke("StartNewOrderWithQCmd", new object[] {
                    bufin}, callback, asyncState);
    }
    /// <remarks/>
    public string EndStartNewOrderWithQCmd(System.IAsyncResult asyncResult) {
        object[] results = this.EndInvoke(asyncResult);
        return ((string)(results[0]));
    }
    /// <remarks/>
    public void StartNewOrderWithQCmdAsync(string bufin) {
        this.StartNewOrderWithQCmdAsync(bufin, null);
    }
    /// <remarks/>
    public void StartNewOrderWithQCmdAsync(string bufin, object userState) {
        if ((this.StartNewOrderWithQCmdOperationCompleted == null)) {
            this.StartNewOrderWithQCmdOperationCompleted = new System.Threading.SendOrPostCallback(this.OnStartNewOrderWithQCmdOperationCompleted);
        }
        this.InvokeAsync("StartNewOrderWithQCmd", new object[] {
                    bufin}, this.StartNewOrderWithQCmdOperationCompleted, userState);
    }
    private void OnStartNewOrderWithQCmdOperationCompleted(object arg) {
        if ((this.StartNewOrderWithQCmdCompleted != null)) {
            System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
            this.StartNewOrderWithQCmdCompleted(this, new StartNewOrderWithQCmdCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
        }
    }
    /// <remarks/>
    [System.Web.Services.Protocols.SoapDocumentMethodAttribute("", RequestNamespace="urn:HostToAGV", ResponseNamespace="urn:HostToAGV", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
    [return: System.Xml.Serialization.XmlElementAttribute("bufout", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string AddNewOrder([System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)] string bufin) {
        object[] results = this.Invoke("AddNewOrder", new object[] {
                    bufin});
        return ((string)(results[0]));
    }
    /// <remarks/>
    public System.IAsyncResult BeginAddNewOrder(string bufin, System.AsyncCallback callback, object asyncState) {
        return this.BeginInvoke("AddNewOrder", new object[] {
                    bufin}, callback, asyncState);
    }
    /// <remarks/>
    public string EndAddNewOrder(System.IAsyncResult asyncResult) {
        object[] results = this.EndInvoke(asyncResult);
        return ((string)(results[0]));
    }
    /// <remarks/>
    public void AddNewOrderAsync(string bufin) {
        this.AddNewOrderAsync(bufin, null);
    }
    /// <remarks/>
    public void AddNewOrderAsync(string bufin, object userState) {
        if ((this.AddNewOrderOperationCompleted == null)) {
            this.AddNewOrderOperationCompleted = new System.Threading.SendOrPostCallback(this.OnAddNewOrderOperationCompleted);
        }
        this.InvokeAsync("AddNewOrder", new object[] {
                    bufin}, this.AddNewOrderOperationCompleted, userState);
    }
    private void OnAddNewOrderOperationCompleted(object arg) {
        if ((this.AddNewOrderCompleted != null)) {
            System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
            this.AddNewOrderCompleted(this, new AddNewOrderCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
        }
    }
    /// <remarks/>
    [System.Web.Services.Protocols.SoapDocumentMethodAttribute("", RequestNamespace="urn:HostToAGV", ResponseNamespace="urn:HostToAGV", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
    [return: System.Xml.Serialization.XmlElementAttribute("bufout", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string CancelOrder([System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)] string bufin) {
        object[] results = this.Invoke("CancelOrder", new object[] {
                    bufin});
        return ((string)(results[0]));
    }
    /// <remarks/>
    public System.IAsyncResult BeginCancelOrder(string bufin, System.AsyncCallback callback, object asyncState) {
        return this.BeginInvoke("CancelOrder", new object[] {
                    bufin}, callback, asyncState);
    }
    /// <remarks/>
    public string EndCancelOrder(System.IAsyncResult asyncResult) {
        object[] results = this.EndInvoke(asyncResult);
        return ((string)(results[0]));
    }
    /// <remarks/>
    public void CancelOrderAsync(string bufin) {
        this.CancelOrderAsync(bufin, null);
    }
    /// <remarks/>
    public void CancelOrderAsync(string bufin, object userState) {
        if ((this.CancelOrderOperationCompleted == null)) {
            this.CancelOrderOperationCompleted = new System.Threading.SendOrPostCallback(this.OnCancelOrderOperationCompleted);
        }
        this.InvokeAsync("CancelOrder", new object[] {
                    bufin}, this.CancelOrderOperationCompleted, userState);
    }
    private void OnCancelOrderOperationCompleted(object arg) {
        if ((this.CancelOrderCompleted != null)) {
            System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
            this.CancelOrderCompleted(this, new CancelOrderCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
        }
    }
    /// <remarks/>
    [System.Web.Services.Protocols.SoapDocumentMethodAttribute("", RequestNamespace="urn:HostToAGV", ResponseNamespace="urn:HostToAGV", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
    [return: System.Xml.Serialization.XmlElementAttribute("bufout", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string ChangeOrder([System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)] string bufin) {
        object[] results = this.Invoke("ChangeOrder", new object[] {
                    bufin});
        return ((string)(results[0]));
    }
    /// <remarks/>
    public System.IAsyncResult BeginChangeOrder(string bufin, System.AsyncCallback callback, object asyncState) {
        return this.BeginInvoke("ChangeOrder", new object[] {
                    bufin}, callback, asyncState);
    }
    /// <remarks/>
    public string EndChangeOrder(System.IAsyncResult asyncResult) {
        object[] results = this.EndInvoke(asyncResult);
        return ((string)(results[0]));
    }
    /// <remarks/>
    public void ChangeOrderAsync(string bufin) {
        this.ChangeOrderAsync(bufin, null);
    }
    /// <remarks/>
    public void ChangeOrderAsync(string bufin, object userState) {
        if ((this.ChangeOrderOperationCompleted == null)) {
            this.ChangeOrderOperationCompleted = new System.Threading.SendOrPostCallback(this.OnChangeOrderOperationCompleted);
        }
        this.InvokeAsync("ChangeOrder", new object[] {
                    bufin}, this.ChangeOrderOperationCompleted, userState);
    }
    private void OnChangeOrderOperationCompleted(object arg) {
        if ((this.ChangeOrderCompleted != null)) {
            System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
            this.ChangeOrderCompleted(this, new ChangeOrderCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
        }
    }
    /// <remarks/>
    [System.Web.Services.Protocols.SoapDocumentMethodAttribute("", RequestNamespace="urn:HostToAGV", ResponseNamespace="urn:HostToAGV", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
    [return: System.Xml.Serialization.XmlElementAttribute("bufout", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string QueryOrder([System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)] string bufin) {
        object[] results = this.Invoke("QueryOrder", new object[] {
                    bufin});
        return ((string)(results[0]));
    }
    /// <remarks/>
    public System.IAsyncResult BeginQueryOrder(string bufin, System.AsyncCallback callback, object asyncState) {
        return this.BeginInvoke("QueryOrder", new object[] {
                    bufin}, callback, asyncState);
    }
    /// <remarks/>
    public string EndQueryOrder(System.IAsyncResult asyncResult) {
        object[] results = this.EndInvoke(asyncResult);
        return ((string)(results[0]));
    }
    /// <remarks/>
    public void QueryOrderAsync(string bufin) {
        this.QueryOrderAsync(bufin, null);
    }
    /// <remarks/>
    public void QueryOrderAsync(string bufin, object userState) {
        if ((this.QueryOrderOperationCompleted == null)) {
            this.QueryOrderOperationCompleted = new System.Threading.SendOrPostCallback(this.OnQueryOrderOperationCompleted);
        }
        this.InvokeAsync("QueryOrder", new object[] {
                    bufin}, this.QueryOrderOperationCompleted, userState);
    }
    private void OnQueryOrderOperationCompleted(object arg) {
        if ((this.QueryOrderCompleted != null)) {
            System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
            this.QueryOrderCompleted(this, new QueryOrderCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
        }
    }
    /// <remarks/>
    [System.Web.Services.Protocols.SoapDocumentMethodAttribute("", RequestElementName="Order-Add", RequestNamespace="urn:HostToAGV", ResponseElementName="Order-AddResponse", ResponseNamespace="urn:HostToAGV", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
    [return: System.Xml.Serialization.XmlElementAttribute("pszResponse", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string OrderAdd([System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)] string pszRequest) {
        object[] results = this.Invoke("OrderAdd", new object[] {
                    pszRequest});
        return ((string)(results[0]));
    }
    /// <remarks/>
    public System.IAsyncResult BeginOrderAdd(string pszRequest, System.AsyncCallback callback, object asyncState) {
        return this.BeginInvoke("OrderAdd", new object[] {
                    pszRequest}, callback, asyncState);
    }
    /// <remarks/>
    public string EndOrderAdd(System.IAsyncResult asyncResult) {
        object[] results = this.EndInvoke(asyncResult);
        return ((string)(results[0]));
    }
    /// <remarks/>
    public void OrderAddAsync(string pszRequest) {
        this.OrderAddAsync(pszRequest, null);
    }
    /// <remarks/>
    public void OrderAddAsync(string pszRequest, object userState) {
        if ((this.OrderAddOperationCompleted == null)) {
            this.OrderAddOperationCompleted = new System.Threading.SendOrPostCallback(this.OnOrderAddOperationCompleted);
        }
        this.InvokeAsync("OrderAdd", new object[] {
                    pszRequest}, this.OrderAddOperationCompleted, userState);
    }
    private void OnOrderAddOperationCompleted(object arg) {
        if ((this.OrderAddCompleted != null)) {
            System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
            this.OrderAddCompleted(this, new OrderAddCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
        }
    }
    /// <remarks/>
    [System.Web.Services.Protocols.SoapDocumentMethodAttribute("", RequestElementName="Order-ChangeParam", RequestNamespace="urn:HostToAGV", ResponseElementName="Order-ChangeParamResponse", ResponseNamespace="urn:HostToAGV", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
    [return: System.Xml.Serialization.XmlElementAttribute("pszResponse", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string OrderChangeParam([System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)] string pszRequest) {
        object[] results = this.Invoke("OrderChangeParam", new object[] {
                    pszRequest});
        return ((string)(results[0]));
    }
    /// <remarks/>
    public System.IAsyncResult BeginOrderChangeParam(string pszRequest, System.AsyncCallback callback, object asyncState) {
        return this.BeginInvoke("OrderChangeParam", new object[] {
                    pszRequest}, callback, asyncState);
    }
    /// <remarks/>
    public string EndOrderChangeParam(System.IAsyncResult asyncResult) {
        object[] results = this.EndInvoke(asyncResult);
        return ((string)(results[0]));
    }
    /// <remarks/>
    public void OrderChangeParamAsync(string pszRequest) {
        this.OrderChangeParamAsync(pszRequest, null);
    }
    /// <remarks/>
    public void OrderChangeParamAsync(string pszRequest, object userState) {
        if ((this.OrderChangeParamOperationCompleted == null)) {
            this.OrderChangeParamOperationCompleted = new System.Threading.SendOrPostCallback(this.OnOrderChangeParamOperationCompleted);
        }
        this.InvokeAsync("OrderChangeParam", new object[] {
                    pszRequest}, this.OrderChangeParamOperationCompleted, userState);
    }
    private void OnOrderChangeParamOperationCompleted(object arg) {
        if ((this.OrderChangeParamCompleted != null)) {
            System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
            this.OrderChangeParamCompleted(this, new OrderChangeParamCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
        }
    }
    /// <remarks/>
    public new void CancelAsync(object userState) {
        base.CancelAsync(userState);
    }
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.6.1055.0")]
public delegate void StartNewOrderWithQCmdCompletedEventHandler(object sender, StartNewOrderWithQCmdCompletedEventArgs e);
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.6.1055.0")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public  class StartNewOrderWithQCmdCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
    private object[] results;
    internal StartNewOrderWithQCmdCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
            base(exception, cancelled, userState) {
        this.results = results;
    }
    /// <remarks/>
    public string Result {
        get {
            this.RaiseExceptionIfNecessary();
            return ((string)(this.results[0]));
        }
    }
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.6.1055.0")]
public delegate void AddNewOrderCompletedEventHandler(object sender, AddNewOrderCompletedEventArgs e);
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.6.1055.0")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public  class AddNewOrderCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
    private object[] results;
    internal AddNewOrderCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
            base(exception, cancelled, userState) {
        this.results = results;
    }
    /// <remarks/>
    public string Result {
        get {
            this.RaiseExceptionIfNecessary();
            return ((string)(this.results[0]));
        }
    }
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.6.1055.0")]
public delegate void CancelOrderCompletedEventHandler(object sender, CancelOrderCompletedEventArgs e);
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.6.1055.0")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public  class CancelOrderCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
    private object[] results;
    internal CancelOrderCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
            base(exception, cancelled, userState) {
        this.results = results;
    }
    /// <remarks/>
    public string Result {
        get {
            this.RaiseExceptionIfNecessary();
            return ((string)(this.results[0]));
        }
    }
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.6.1055.0")]
public delegate void ChangeOrderCompletedEventHandler(object sender, ChangeOrderCompletedEventArgs e);
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.6.1055.0")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public  class ChangeOrderCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
    private object[] results;
    internal ChangeOrderCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
            base(exception, cancelled, userState) {
        this.results = results;
    }
    /// <remarks/>
    public string Result {
        get {
            this.RaiseExceptionIfNecessary();
            return ((string)(this.results[0]));
        }
    }
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.6.1055.0")]
public delegate void QueryOrderCompletedEventHandler(object sender, QueryOrderCompletedEventArgs e);
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.6.1055.0")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public  class QueryOrderCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
    private object[] results;
    internal QueryOrderCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
            base(exception, cancelled, userState) {
        this.results = results;
    }
    /// <remarks/>
    public string Result {
        get {
            this.RaiseExceptionIfNecessary();
            return ((string)(this.results[0]));
        }
    }
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.6.1055.0")]
public delegate void OrderAddCompletedEventHandler(object sender, OrderAddCompletedEventArgs e);
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.6.1055.0")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public  class OrderAddCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
    private object[] results;
    internal OrderAddCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
            base(exception, cancelled, userState) {
        this.results = results;
    }
    /// <remarks/>
    public string Result {
        get {
            this.RaiseExceptionIfNecessary();
            return ((string)(this.results[0]));
        }
    }
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.6.1055.0")]
public delegate void OrderChangeParamCompletedEventHandler(object sender, OrderChangeParamCompletedEventArgs e);
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.6.1055.0")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public  class OrderChangeParamCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
    private object[] results;
    internal OrderChangeParamCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
            base(exception, cancelled, userState) {
        this.results = results;
    }
    /// <remarks/>
    public string Result {
        get {
            this.RaiseExceptionIfNecessary();
            return ((string)(this.results[0]));
        }
    }
}
Dispatch/NDC.cs
New file
@@ -0,0 +1,165 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using Newtonsoft.Json;
namespace HH.WCS.Mobox3.AnGang.Dispatch {
    public class NDC
    {
        private static HostToAGV callClient = null;
        static NDC() {
            callClient = new HostToAGV();
            //callClient.Url = Settings.Config.HostToAgvServerUrl;
            callClient.Url = string.Empty;
        }
        private static string GetReqStrNew(int ts, int pri, string taskNo, Dictionary<string, string> param) {
            /*<Req>
              <Order TS='5' Pri='80' No='666' NoCallback='0' Ext1='' Ext2='' Ext3=''>
                <Param Name='From' Value='10' />
                <Param Name='To' Value='20' />
                <Param Name='Func' Value='1' />
                <Param Name='Data' Value='7' />
                <Param Name='ItemHeight' Value='1' />
                <Param Name='CntrType' Value='12' />
                <Param Name='FromCol' Value='2' />
                <Param Name='ToCol' Value='111' />
              </Order>
            </Req>*/
            var sb = new StringBuilder();
            sb.Append($"<Req><Order TS='{ts}' Pri='{pri}' No='{taskNo}'>");
            foreach (var kv in param) {
                sb.Append($"<Param Name='{kv.Key}' Value='{kv.Value}'/>");
            }
            sb.Append("</Order></Req>");
            return sb.ToString();
        }
        public AGVResult AddNewOrderNew(int ts, int pri, string taskNo, Dictionary<string, string> param) {
            //< Req >< Order TS = '1' Pri = '1' No = 'TN2302020001' Ext1 = '' Ext2 = '' N_CNTR_COUNT = '' >< Param Name = 'From' Value = '2' />< Param Name = 'To' Value = '1' /></ Order ></ Req >
            var bufin = GetReqStrNew(ts, pri, taskNo, param);
            try {
                var result = callClient.OrderAdd(bufin);
                LogHelper.Info($"任务下发结果 OrderAdd req={bufin} res={result}", "NDC");
                Console.WriteLine($"任务下发结果 OrderAdd req={bufin} res={result}");
                //LogHelper.Info(result.bufout, "ts");
                return GetResult(result);
            }
            catch (Exception e) {
                LogHelper.Info($"任务下发失败 OrderAdd req={bufin} res={e.Message}", "NDC");
                //Console.WriteLine($"任务下发失败 AddNewOrder req={bufin} res={e.Message}");
                return new AGVResult { Res = new Res { ErrCode = -1, ErrInfo = e.Message } };
            }
        }
        private static string GetReqStr(int ts, Dictionary<string, string> param) {
            //< Order  TS = '60'  Pri = '" + mst.CN_N_PRIORITY.ToString() + "' From = '" + start.CN_N_AGV_TN_Location + "' To = '" + end.CN_N_AGV_TN_Location + "'  No = '" + mst.S_CODE + "_1' Ext1 = '1' Ext2 = '" + Constants.TN_MID_COMMANDEQ_CALLAGVOrderCommandType + "'  N_CNTR_COUNT = ''   FRow = '" + sFloor + "'  TRow = '" + eFloor + "' />
            var sb = new StringBuilder();
            sb.Append($"<Req><Order ");
            if (ts != 0) {
                sb.Append($"TS='{ts}'");
            }
            foreach (var kv in param) {
                sb.Append($" {kv.Key}='{kv.Value}'");
            }
            sb.Append("/></Req>");
            return sb.ToString();
        }
        public static AGVResult AddNewOrder(int ts, Dictionary<string, string> param)
        {
            //< Req >< Order TS = '1' Pri = '1' No = 'TN2302020001' Ext1 = '' Ext2 = '' N_CNTR_COUNT = '' >< Param Name = 'From' Value = '2' />< Param Name = 'To' Value = '1' /></ Order ></ Req >
            var bufin = GetReqStr(ts, param);
            try {
                var result = callClient.AddNewOrder(bufin);
                LogHelper.Info($"AddNewOrder req={bufin} res={result}", "NDC");
                return GetResult(result);
            }
            catch (Exception e) {
                LogHelper.Info($"AddNewOrder req={bufin} res={e.Message}", "NDC");
                return new AGVResult { Res = new Res { ErrCode = -1, ErrInfo = e.Message } };
            }
        }
        public static AGVResult CancelOrder(int ts, Dictionary<string, string> param) {
            //< Req >< Order No = 'TN2302020001' >< Param Name = 'IsForce' Value = '1' /></ Order ></ Req >
            var bufin = GetReqStr(ts, param);
            try {
                var result = callClient.CancelOrder(bufin);
                LogHelper.Info($"CancelOrder req={bufin} res={result}", "NDC");
                return GetResult(result);
            }
            catch (Exception e) {
                LogHelper.Info($"CancelOrder req={bufin} res={e.Message}", "NDC");
                return new AGVResult {
                    Res = new Res {
                        ErrCode = -1,
                        ErrInfo = e.Message
                    }
                };
            }
        }
        public static AGVResult StartNewOrderWithQCmd(int ts, Dictionary<string, string> param) {
            //lpn:      <Order TS='41' Pri='' ExtDeviceNo='{0}' CtrlVal='{1}' DispInfo='{2}' No='{3}' Ext1='' Ext2='' N_CNTR_COUNT='' />
            //traccif:  <Order TS='164' From='2' To='2' ExtDeviceNo='" + lockNo + "' No='" + DateTime.Now.Ticks.ToString() + "' />
            //lock:     <Order TS='170'  CtrlVal='" + CtrlVal + "' ExtDeviceNo='" + roadway + "' No='" + DateTime.Now.Ticks.ToString() + "' />
            var bufin = GetReqStr(ts, param);
            try {
                var r = callClient.StartNewOrderWithQCmd(bufin);
                LogHelper.Info($"StartNewOrderWithQCmd req={bufin} res={r}", "NDC");
                return GetResult(r);
            }
            catch (Exception e) {
                LogHelper.Info($"StartNewOrderWithQCmd req={bufin} res={e.Message}", "NDC");
                return new AGVResult {
                    Res = new Res {
                        ErrCode = -1,
                        ErrInfo = e.Message
                    }
                };
            }
        }
        public static AGVResult ChangeOrder(Dictionary<string, string> param) {
            //< Req >< Order No = 'TN2302020002' ParamNo = '18' Param1 = '12' /></ Req >
            var bufin = GetReqStr(0, param);
            try {
                var r = callClient.ChangeOrder(bufin);
                LogHelper.Info($"ChangeOrder req={bufin} res={r}", "NDC");
                return GetResult(r);
            }
            catch (Exception e) {
                LogHelper.Info($"ChangeOrder req={bufin} res={e.Message}", "NDC");
                return new AGVResult {
                    Res = new Res {
                        ErrCode = -1,
                        ErrInfo = e.Message
                    }
                };
            }
        }
        private static AGVResult GetResult(string bufout) {
            //<Res><ErrCode>0</ErrCode><Result>11</Result></Res>
            XmlDocument xml = new XmlDocument();
            xml.LoadXml(bufout);
            var json = JsonConvert.SerializeXmlNode(xml);
            return JsonConvert.DeserializeObject<AGVResult>(json);
        }
        public class AGVResult
        {
            public Res Res { get; set; }
        }
        public class Res
        {
            public int ErrCode { get; set; }
            public string ErrInfo { get; set; }
        }
    }
}
Dispatch/NDCApi.cs
New file
@@ -0,0 +1,271 @@
using System;
using System.Collections.Generic;
using HH.WCS.Mobox3.AnGang.AppStart;
using HH.WCS.Mobox3.AnGang.config;
using Newtonsoft.Json;
namespace HH.WCS.Mobox3.AnGang.Dispatch {
    public class NDCApi
    {
        public static string NDCApiUrl { set; get; }
        static NDCApi()
        {
            NDCApiUrl = Settings.Config.NDCApiUrl;
        }
        public static AgvApiResult AddOrderNew(int ts, int pri, string taskNo, List<param> param)
        {
            var httpH = new HttpHelper();
            var agvApiResult = new AgvApiResult();
            var model = new AddOrderNewModel();
            model.ts_no = ts;
            model.pri = pri;
            model.task_no = taskNo;
            model.param = param;
            try
            {
                string jsonInfo = JsonConvert.SerializeObject(model);
                LogHelper.Info($"任务{taskNo}下发,{jsonInfo}", "NDC");
                var result = httpH.WebPost(NDCApiUrl + "Add", jsonInfo);
                LogHelper.Info($"任务下发结果res={result}", "NDC");
                agvApiResult = JsonConvert.DeserializeObject<AgvApiResult>(result);
                return agvApiResult;
            }
            catch (Exception e)
            {
                LogHelper.Info($"任务下发失败 res={e.Message}", "NDC");
                agvApiResult.err_code = -1;
                agvApiResult.err_msg = e.Message;
                return agvApiResult;
            }
        }
        public static AgvApiResult AddOrderNew(AddOrderNewModel model)
        {
            var httpH = new HttpHelper();
            var agvApiResult = new AgvApiResult();
            try
            {
                string jsonInfo = JsonConvert.SerializeObject(model);
                LogHelper.Info($"任务{model.task_no}下发,{jsonInfo}", "NDC");
                var result = httpH.WebPost(NDCApiUrl + "Add", jsonInfo);
                LogHelper.Info($"任务下发结果res={result}", "NDC");
                agvApiResult = JsonConvert.DeserializeObject<AgvApiResult>(result);
                return agvApiResult;
            }
            catch (Exception e)
            {
                LogHelper.Info($"任务下发失败 res={e.Message}", "NDC");
                agvApiResult.err_code = -1;
                agvApiResult.err_msg = e.Message;
                return agvApiResult;
            }
        }
        public static AgvApiResult CancelOrder(string tsNo, bool is_force = true)
        {
            var httpH = new HttpHelper();
            var agvApiResult = new AgvApiResult();
            var model = new CancelOrderModel();
            model.task_no = tsNo;
            model.is_force = is_force;
            try
            {
                string jsonInfo = JsonConvert.SerializeObject(model);
                LogHelper.Info($"任务{model.task_no}取消,{jsonInfo}", "NDC");
                var result = httpH.WebPost(NDCApiUrl + "Cancel", jsonInfo);
                LogHelper.Info($"任务{model.task_no}取消结果={result}", "NDC");
                agvApiResult = JsonConvert.DeserializeObject<AgvApiResult>(result);
                return agvApiResult;
            }
            catch (Exception e)
            {
                LogHelper.Info($"CancelOrder  res={e.Message}", "NDC");
                agvApiResult.err_code = -1;
                agvApiResult.err_msg = e.Message;
                return agvApiResult;
            }
        }
        public static AgvApiResult CancelOrder(CancelOrderModel model)
        {
            var httpH = new HttpHelper();
            var agvApiResult = new AgvApiResult();
            try
            {
                string jsonInfo = JsonConvert.SerializeObject(model);
                LogHelper.Info($"任务{model.task_no}取消,{jsonInfo}", "NDC");
                var result = httpH.WebPost(NDCApiUrl + "Cancel", jsonInfo);
                LogHelper.Info($"任务{model.task_no}取消结果={result}", "NDC");
                agvApiResult = JsonConvert.DeserializeObject<AgvApiResult>(result);
                return agvApiResult;
            }
            catch (Exception e)
            {
                LogHelper.Info($"CancelOrder  res={e.Message}", "NDC");
                agvApiResult.err_code = -1;
                agvApiResult.err_msg = e.Message;
                return agvApiResult;
            }
        }
        public static AgvApiResult ChangeOrderPri(string taskNo, int newPri)
        {
            var httpH = new HttpHelper();
            var agvApiResult = new AgvApiResult();
            var model = new ChangePriModel();
            model.task_no = taskNo;
            model.pri = newPri;
            try
            {
                string jsonInfo = JsonConvert.SerializeObject(model);
                LogHelper.Info($"任务{model.task_no}优先级更改,{jsonInfo}", "NDC");
                var result = httpH.WebPost(NDCApiUrl + "ChangePri", jsonInfo);
                LogHelper.Info($"任务{model.task_no}优先级更改结果={result}", "NDC");
                agvApiResult = JsonConvert.DeserializeObject<AgvApiResult>(result);
                return agvApiResult;
            }
            catch (Exception e)
            {
                LogHelper.Info($"ChangeOrderPri res={e.Message}", "NDC");
                agvApiResult.err_code = -1;
                agvApiResult.err_msg = e.Message;
                return agvApiResult;
            }
        }
        public static AgvApiResult ChangeOrderPri(ChangePriModel model)
        {
            var httpH = new HttpHelper();
            var agvApiResult = new AgvApiResult();
            try
            {
                string jsonInfo = JsonConvert.SerializeObject(model);
                LogHelper.Info($"任务{model.task_no}优先级更改,{jsonInfo}", "NDC");
                var result = httpH.WebPost(NDCApiUrl + "ChangePri", jsonInfo);
                LogHelper.Info($"任务{model.task_no}优先级更改结果={result}", "NDC");
                agvApiResult = JsonConvert.DeserializeObject<AgvApiResult>(result);
                return agvApiResult;
            }
            catch (Exception e)
            {
                LogHelper.Info($"ChangeOrderPri res={e.Message}", "NDC");
                agvApiResult.err_code = -1;
                agvApiResult.err_msg = e.Message;
                return agvApiResult;
            }
        }
        public static AgvApiResult ChangeOrderParam(string taskNo, int paramNo, string paramStr)
        {
            var httpH = new HttpHelper();
            var agvApiResult = new AgvApiResult();
            var model = new ChangeParamModel();
            model.task_no = taskNo;
            model.param_no = paramNo;
            model.param = paramStr;
            try
            {
                string jsonInfo = JsonConvert.SerializeObject(model);
                LogHelper.Info($"任务{model.task_no}参数更改,{jsonInfo}", "NDC");
                var result = httpH.WebPost(NDCApiUrl + "ChangeParam", jsonInfo);
                LogHelper.Info($"任务{model.task_no}参数更改结果={result}", "NDC");
                agvApiResult = JsonConvert.DeserializeObject<AgvApiResult>(result);
                return agvApiResult;
            }
            catch (Exception e)
            {
                LogHelper.Info($"ChangeOrderParam res={e.Message}", "NDC");
                agvApiResult.err_code = -1;
                agvApiResult.err_msg = e.Message;
                return agvApiResult;
            }
        }
        public static AgvApiResult ChangeOrderParam(ChangeParamModel model)
        {
            var httpH = new HttpHelper();
            var agvApiResult = new AgvApiResult();
            try
            {
                string jsonInfo = JsonConvert.SerializeObject(model);
                LogHelper.Info($"任务{model.task_no}参数更改,{jsonInfo}", "NDC");
                var result = httpH.WebPost(NDCApiUrl + "ChangeParam", jsonInfo);
                LogHelper.Info($"任务{model.task_no}参数更改结果={result}", "NDC");
                agvApiResult = JsonConvert.DeserializeObject<AgvApiResult>(result);
                return agvApiResult;
            }
            catch (Exception e)
            {
                LogHelper.Info($"ChangeOrderParam res={e.Message}", "NDC");
                agvApiResult.err_code = -1;
                agvApiResult.err_msg = e.Message;
                return agvApiResult;
            }
        }
    }
    /// <summary>
    /// 返回信息Model
    /// </summary>
    public class AgvApiResult
    {
        public int err_code { set; get; }//异常码:0 - 正常,其它值为异常错误码
        public string err_msg { set; get; }//返回的错误描述,在 err_code <> 0 时返回
        public object result { set; get; }//正确返回的结果内容,在 err_code = 0 且有返回内容时
    }
    public class AddOrderNewModel
    {
        public int ts_no { set; get; }//TS 号,必须有值
        public int pri { set; get; }//优先级
        public string task_no { set; get; }//上游任务编码,如果 no_feedback = 1 时,可以为空
        public List<param> param { set; get; } = new List<param>();//参数列表
    }
    public class param
    {
        public string name { set; get; }//参数名
        public string value { set; get; }//参数值
    }
    public class CancelOrderModel
    {
        public string task_no { set; get; }//上游任务编码
        public bool is_force { set; get; } = true;//是否强制取消,1 – 强制
    }
    public class ChangeParamModel
    {
        public string task_no { set; get; }//上游任务编码
        public int param_no { set; get; }//参数号
        public string param { set; get; }//参数内容,多个参数以英文分号(;)分隔
    }
    public class ChangePriModel
    {
        public string task_no { set; get; }//上游任务编码
        public int pri { set; get; }//新优先级
    }
}
Dispatch/NDCHelper.cs
New file
@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace HH.WCS.Mobox3.AnGang.Dispatch
{
    public class NDCHelper
    {
        public static void Test() {
            //dic.Add("Ext1", ""); dic.Add("Ext2", ""); dic.Add("N_CNTR_COUNT", "");
            //var r = callClient.AddNewOrderAsync(new AddNewOrderRequest() { bufin = "<Req><Order Pri='1' TS='1' From='1' To='2' No='123471118_1'  Ext1='1' Ext2='CALLADDAGV'  N_CNTR_COUNT='' /></Req>" });
            //r.Wait();
            var dic = new Dictionary<string, string>();
            dic.Add("Pri", "1"); dic.Add("From", "1"); dic.Add("To", "1"); dic.Add("No", "12311411718_2");// dic.Add("Ext1", "1"); dic.Add("Ext2", "CALLADDAGV"); dic.Add("N_CNTR_COUNT", "");
            var result = NDC.AddNewOrder(1, dic);
            var dic1 = new Dictionary<string, string>();
            var no = "3454566666";
            dic1.Add("From", "1"); dic1.Add("To", "0"); dic1.Add("No", no);
            result = NDC.AddNewOrder(101, dic1);
            var dic2 = new Dictionary<string, string>();
            dic2.Add("ExtDeviceNo", "1"); dic2.Add("From", "2"); dic2.Add("To", "2"); dic2.Add("No", DateTime.Now.Ticks.ToString()); dic2.Add("CtrlVal", "1");
            result = NDC.AddNewOrder(39, dic2);
            var dic3 = new Dictionary<string, string>();
            dic3.Add("From", "1"); dic3.Add("To", "9"); dic3.Add("No", no);
            result = NDC.CancelOrder(101, dic3);
            var dic4 = new Dictionary<string, string>();
            dic4.Add("ExtDeviceNo", "1"); dic4.Add("CtrlVal", "1"); dic4.Add("DispInfo", "AAAAAAAA"); dic4.Add("No", DateTime.Now.Ticks.ToString());
            result = NDC.StartNewOrderWithQCmd(41, dic4);
            var dic5 = new Dictionary<string, string>();
            dic5.Add("ExtDeviceNo", "1"); dic5.Add("CtrlVal", "1"); dic5.Add("No", DateTime.Now.Ticks.ToString());
            result = NDC.StartNewOrderWithQCmd(170, dic5);
            var dic6 = new Dictionary<string, string>();
            dic6.Add("ExtDeviceNo", "11"); dic6.Add("From", "2"); dic6.Add("To", "2"); dic6.Add("No", DateTime.Now.Ticks.ToString());
            result = NDC.StartNewOrderWithQCmd(164, dic6);
            var dic7 = new Dictionary<string, string>();
            dic7.Add("Param1", "50"); dic7.Add("No", DateTime.Now.Ticks.ToString());
            result = NDC.ChangeOrder(dic7);
        }
        public static bool ChangeParam(string taskNo, int param1, int paramNo = 0) {
            bool bResult = false;
            var dic = new Dictionary<string, string>();
            dic.Add("No", taskNo);
            if (paramNo >= 0) {
                dic.Add("ParamNo", paramNo.ToString());
            }
            dic.Add("Param1", param1.ToString());
            var result = NDC.ChangeOrder(dic);
            return bResult;
        }
        public static bool Traffic(string lockNo) {
            bool bResult = false;
            var dic = new Dictionary<string, string>();
            dic.Add("ExtDeviceNo", lockNo);
            dic.Add("From", "2");
            dic.Add("To", "2"); dic.Add("No", DateTime.Now.Ticks.ToString());
            var result = NDC.StartNewOrderWithQCmd(164, dic);
            return bResult;
        }
        public static bool Cancel(string taskNo) {
            bool bResult = false;
            var dic = new Dictionary<string, string>();
            dic.Add("No", taskNo);
            dic.Add("IsForce", "1");
            var result = NDC.CancelOrder(1, dic);
            return bResult;
        }
    }
}
Dtos/Request/AgvRequest.cs
New file
@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Dtos.Request {
    public class AgvRequest {
        /// <summary>
        /// hosttoagv上报任务状态
        /// </summary>
        public class AgvTaskState {
            public int state { get; set; }
            public string task_no { get; set; }
            public string forklift_no { get; set; }
            /// <summary>
            /// 安全门编号
            /// </summary>
            public string lock_no { get; set; }
            public string ext_data { get; set; }
        }
        public class SafetyInteractionInfo {
            public int station_id { get; set; }
            /// <summary>
            /// 请求上线/下线的的站台库位名称,例如work6、work8
            /// </summary>
            public string station_name { get; set; }
            /// <summary>
            /// 请求码
            /// </summary>
            public string apply_code { get; set; }
            public string task_no { set; get; }
        }
    }
}
Dtos/Request/MoboxRequest.cs
New file
@@ -0,0 +1,355 @@
using Newtonsoft.Json;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Dtos.Request {
    public class MoboxRequest {
        #region 模板数据类
        /// <summary>
        /// 模板数据类:标准出入库信息
        /// </summary>
        public class BaseBoundInfo {
            /// <summary>
            /// 起点货位
            /// </summary>
            public string startLoc { get; set; }
            /// <summary>
            /// 容器号
            /// </summary>
            public string cntId { get; set; }
            /// <summary>
            /// 终点货位
            /// </summary>
            public string endLoc { get; set; }
        }
        #endregion
        public class InWarehouseInfo {
            /// <summary>
            /// 起点货位
            /// </summary>
            [JsonProperty("StartLoc")]
            public string startLoc { get; set; }
            /// <summary>
            /// 终点货架(可选)
            /// </summary>
            [JsonProperty("Nrow")]
            public string endShelf { get; set; }
        }
        public class SelectLocationInfo {
            public string forklift_no { get; set; }
            ///// <summary>
            ///// 任务号
            ///// </summary>
            //public string taskNo { get; set; }
            public string endLoc { get; set; }
        }
        /// <summary>
        /// 产品部分回库信息
        /// </summary>
        public class PartInWarehouseInfo {
            /// <summary>
            /// 起点位置
            /// </summary>
            public string startLoc { get; set; }
            /// <summary>
            /// 终点位置
            /// </summary>
            public string endLoc { get; set; }
        }
        /// <summary>
        /// 产品部分出库信息
        /// </summary>
        public class PartOutWarehouseInfo {
            /// <summary>
            /// 起点位置
            /// </summary>
            public string startLoc { get; set; }
            /// <summary>
            /// 终点位置
            /// </summary>
            public string endLoc { get; set; }
        }
        /// <summary>
        /// 盘点理货出库信息
        /// </summary>
        public class CheckOutWarehouseInfo {
            /// <summary>
            /// 起点位置
            /// </summary>
            public string startLoc { get; set; }
            /// <summary>
            /// 终点位置
            /// </summary>
            public string endLoc { get; set; }
        }
        /// <summary>
        /// 盘点理货回库信息
        /// </summary>
        public class CheckInWarehouseInfo {
            /// <summary>
            /// 起点位置
            /// </summary>
            public string startLoc { get; set; }
            /// <summary>
            /// 终点位置
            /// </summary>
            public string endLoc { get; set; }
        }
        // ERP -> AGV
        /// <summary>
        /// 入库数据同步信息
        /// </summary>
        public class InWarehouseDataSyncInfo {
            /// <summary>
            /// 库存明细(列表)
            /// </summary>
            public List<StockTransaction> stockTransactions { get; set; }
            /// <summary>
            /// 总记录数
            /// </summary>
            public string totalRecords { get; set; }
            /// <summary>
            /// 数据生成时间戳
            /// </summary>
            public string timestamp { get; set; }
        }
        /// <summary>
        /// 库存明细信息
        /// </summary>
        public class StockTransaction {
            /// <summary>
            /// 储位码
            /// </summary>
            public string locationCode { get; set; }
            /// <summary>
            /// 库存明细交易号
            /// </summary>
            public string stockTransactionId { get; set; }
            /// <summary>
            /// 物料编码
            /// </summary>
            public string itemCode { get; set; }
            /// <summary>
            /// 物料名称
            /// </summary>
            public string itemName { get; set; }
            /// <summary>
            /// 物料短描述
            /// </summary>
            public string itemShortDesc { get; set; }
            /// <summary>
            /// 库存数量
            /// </summary>
            public string stockQuantity { get; set; }
            /// <summary>
            /// 入库数量
            /// </summary>
            public string inQuantity { get; set; }
            /// <summary>
            /// 库存总价
            /// </summary>
            public string totalPrice { get; set; }
            /// <summary>
            /// 入库时间
            /// </summary>
            public string stockInTime { get; set; }
            /// <summary>
            /// 保管员
            /// </summary>
            public string storeKeeper { get; set; }
            /// <summary>
            /// 产线部门代码
            /// </summary>
            public string lineCode { get; set; }
            /// <summary>
            /// 送货单行号
            /// </summary>
            public string deliveryItemNo { get; set; }
            /// <summary>
            /// 供应商名称
            /// </summary>
            public string supplierName { get; set; }
            /// <summary>
            /// 库存责任人姓名
            /// </summary>
            public string inventoryManager { get; set; }
            /// <summary>
            /// 备用字段1
            /// </summary>
            public string ext1 { get; set; }
            /// <summary>
            /// 备用字段2
            /// </summary>
            public string ext2 { get; set; }
            /// <summary>
            /// 备用字段3
            /// </summary>
            public string ext3 { get; set; }
            /// <summary>
            /// 备用字段4
            /// </summary>
            public string ext4 { get; set; }
            /// <summary>
            /// 备用字段5
            /// </summary>
            public string ext5 { get; set; }
        }
        /// <summary>
        /// 出库发料同步信息
        /// </summary>
        public class OutWarehouseDataSyncInfo {
            /// <summary>
            /// 发料记录明细列表
            /// </summary>
            public List<MaterialIssue> materialIssues { get; set; }
            /// <summary>
            /// 总记录数
            /// </summary>
            public string totalRecords { get; set; }
            /// <summary>
            /// 数据生成时间戳
            /// </summary>
            public string timestamp { get; set; }
        }
        /// <summary>
        /// 发料记录明细信息
        /// </summary>
        public class MaterialIssue {
            /// <summary>
            /// 储位码
            /// </summary>
            public string locationCode { get; set; }
            /// <summary>
            /// 领用单号
            /// </summary>
            public string withdrawalOrderNo { get; set; }
            /// <summary>
            /// 物料编码
            /// </summary>
            public string itemCode { get; set; }
            /// <summary>
            /// 物料名称
            /// </summary>
            public string itemName { get; set; }
            /// <summary>
            /// 物料短描述
            /// </summary>
            public string itemShortDesc { get; set; }
            /// <summary>
            /// 实发数量
            /// </summary>
            public string actualIssuedQty { get; set; }
            /// <summary>
            /// 实发金额
            /// </summary>
            public string issuedAmount { get; set; }
            /// <summary>
            /// 供应商名称
            /// </summary>
            public string supplierName { get; set; }
            /// <summary>
            /// 实发人
            /// </summary>
            public string issuer { get; set; }
            /// <summary>
            /// 发料日期
            /// </summary>
            public string issueDate { get; set; }
            /// <summary>
            /// 保管员
            /// </summary>
            public string storeKeeper { get; set; }
            /// <summary>
            /// 产线部门代码
            /// </summary>
            public string lineCode { get; set; }
            /// <summary>
            /// 批次
            /// </summary>
            public string batchNo { get; set; }
            /// <summary>
            /// 备用字段1
            /// </summary>
            public string ext1 { get; set; }
            /// <summary>
            /// 备用字段2
            /// </summary>
            public string ext2 { get; set; }
            /// <summary>
            /// 备用字段3
            /// </summary>
            public string ext3 { get; set; }
            /// <summary>
            /// 备用字段4
            /// </summary>
            public string ext4 { get; set; }
            /// <summary>
            /// 备用字段5
            /// </summary>
            public string ext5 { get; set; }
        }
    }
}
Dtos/Response/AgvResponse.cs
New file
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Dtos.Response {
    public class AgvResponse {
        /// <summary>
        /// 返回给hosttoagv
        /// </summary>
        public class ReturnResult {
            public int ResultCode { get; set; }
            public string ResultMsg { get; set; }
        }
    }
}
Dtos/Response/MoboxResponse.cs
New file
@@ -0,0 +1,21 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace HH.WCS.Mobox3.AnGang.Dtos.Response {
    public class MoboxResponse {
        /// <summary>
        /// Mobox 接口返回
        /// </summary>
        public class SimpleResult {
            [JsonProperty("resultCode")]
            public int Code { get; set; }
            [JsonProperty("resultMsg")]
            public string Message { get; set; }
            [JsonProperty("result")]
            public List<object> Results { get; set; } = new List<object>();
        }
    }
}
HH.WCS.Mobox3.AnGang.csproj
New file
@@ -0,0 +1,306 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{EBE15A59-A43A-43BE-8B4B-A6EC42E11DF6}</ProjectGuid>
    <OutputType>Exe</OutputType>
    <RootNamespace>HH.WCS.Mobox3.AnGang</RootNamespace>
    <AssemblyName>HH.WCS.Mobox3.AnGang</AssemblyName>
    <TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
    <Deterministic>true</Deterministic>
    <TargetFrameworkProfile />
    <PublishUrl>publish\</PublishUrl>
    <Install>true</Install>
    <InstallFrom>Disk</InstallFrom>
    <UpdateEnabled>false</UpdateEnabled>
    <UpdateMode>Foreground</UpdateMode>
    <UpdateInterval>7</UpdateInterval>
    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
    <UpdatePeriodically>false</UpdatePeriodically>
    <UpdateRequired>false</UpdateRequired>
    <MapFileExtensions>true</MapFileExtensions>
    <ApplicationRevision>0</ApplicationRevision>
    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
    <IsWebBootstrapper>false</IsWebBootstrapper>
    <UseApplicationTrust>false</UseApplicationTrust>
    <BootstrapperEnabled>true</BootstrapperEnabled>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <PlatformTarget>x86</PlatformTarget>
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <DocumentationFile>bin\Debug\HH.WCS.Mobox3.AnGang.xml</DocumentationFile>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <NoWarn>$(NoWarn);CS1591</NoWarn>
  </PropertyGroup>
  <PropertyGroup>
    <StartupObject>HH.WCS.Mobox3.AnGang.Program</StartupObject>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="BouncyCastle.Crypto, Version=1.9.0.0, Culture=neutral, PublicKeyToken=0e99375e54769942, processorArchitecture=MSIL">
      <HintPath>packages\Portable.BouncyCastle.1.9.0\lib\net40\BouncyCastle.Crypto.dll</HintPath>
    </Reference>
    <Reference Include="BouncyCastle.Cryptography, Version=2.0.0.0, Culture=neutral, PublicKeyToken=072edcf4a5328938, processorArchitecture=MSIL">
      <HintPath>packages\BouncyCastle.Cryptography.2.4.0\lib\net461\BouncyCastle.Cryptography.dll</HintPath>
    </Reference>
    <Reference Include="EasyModbus, Version=5.6.0.0, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>packages\EasyModbusTCP.5.6.0\lib\net40\EasyModbus.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
      <HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.8.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Bcl.HashCode, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
      <HintPath>packages\Microsoft.Bcl.HashCode.1.1.1\lib\net461\Microsoft.Bcl.HashCode.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=3.1.32.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
      <HintPath>packages\Microsoft.Extensions.Logging.Abstractions.3.1.32\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Owin, Version=4.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>..\packages\Microsoft.Owin.4.2.2\lib\net45\Microsoft.Owin.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Owin.Host.HttpListener, Version=4.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>..\packages\Microsoft.Owin.Host.HttpListener.4.2.2\lib\net45\Microsoft.Owin.Host.HttpListener.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Owin.Hosting, Version=4.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>..\packages\Microsoft.Owin.Hosting.4.2.2\lib\net45\Microsoft.Owin.Hosting.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Web.Infrastructure, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>packages\Microsoft.Web.Infrastructure.2.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
    </Reference>
    <Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
      <HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
    </Reference>
    <Reference Include="Newtonsoft.Json.Bson, Version=1.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
      <HintPath>packages\Newtonsoft.Json.Bson.1.0.2\lib\net45\Newtonsoft.Json.Bson.dll</HintPath>
    </Reference>
    <Reference Include="NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
      <HintPath>packages\NLog.5.3.4\lib\net46\NLog.dll</HintPath>
    </Reference>
    <Reference Include="Opc.Ua.Client, Version=1.5.374.0, Culture=neutral, PublicKeyToken=bfa7a73c5cf4b6e8, processorArchitecture=MSIL">
      <HintPath>packages\OPCFoundation.NetStandard.Opc.Ua.Client.1.5.374.126\lib\netstandard2.0\Opc.Ua.Client.dll</HintPath>
    </Reference>
    <Reference Include="Opc.Ua.Configuration, Version=1.5.374.0, Culture=neutral, PublicKeyToken=bfa7a73c5cf4b6e8, processorArchitecture=MSIL">
      <HintPath>packages\OPCFoundation.NetStandard.Opc.Ua.Configuration.1.5.374.126\lib\netstandard2.0\Opc.Ua.Configuration.dll</HintPath>
    </Reference>
    <Reference Include="Opc.Ua.Core, Version=1.5.374.0, Culture=neutral, PublicKeyToken=bfa7a73c5cf4b6e8, processorArchitecture=MSIL">
      <HintPath>packages\OPCFoundation.NetStandard.Opc.Ua.Core.1.5.374.126\lib\netstandard2.0\Opc.Ua.Core.dll</HintPath>
    </Reference>
    <Reference Include="Opc.Ua.Gds.Client.Common, Version=1.5.374.0, Culture=neutral, PublicKeyToken=bfa7a73c5cf4b6e8, processorArchitecture=MSIL">
      <HintPath>packages\OPCFoundation.NetStandard.Opc.Ua.Gds.Client.Common.1.5.374.126\lib\netstandard2.0\Opc.Ua.Gds.Client.Common.dll</HintPath>
    </Reference>
    <Reference Include="Opc.Ua.Gds.Server.Common, Version=1.5.374.0, Culture=neutral, PublicKeyToken=bfa7a73c5cf4b6e8, processorArchitecture=MSIL">
      <HintPath>packages\OPCFoundation.NetStandard.Opc.Ua.Gds.Server.Common.1.5.374.126\lib\netstandard2.0\Opc.Ua.Gds.Server.Common.dll</HintPath>
    </Reference>
    <Reference Include="Opc.Ua.Security.Certificates, Version=1.5.374.0, Culture=neutral, PublicKeyToken=bfa7a73c5cf4b6e8, processorArchitecture=MSIL">
      <HintPath>packages\OPCFoundation.NetStandard.Opc.Ua.Security.Certificates.1.5.374.126\lib\netstandard2.0\Opc.Ua.Security.Certificates.dll</HintPath>
    </Reference>
    <Reference Include="Opc.Ua.Server, Version=1.5.374.0, Culture=neutral, PublicKeyToken=bfa7a73c5cf4b6e8, processorArchitecture=MSIL">
      <HintPath>packages\OPCFoundation.NetStandard.Opc.Ua.Server.1.5.374.126\lib\netstandard2.0\Opc.Ua.Server.dll</HintPath>
    </Reference>
    <Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
      <HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
    </Reference>
    <Reference Include="S7.Net, Version=0.20.0.0, Culture=neutral, PublicKeyToken=d5812d469e84c693, processorArchitecture=MSIL">
      <HintPath>..\packages\S7netplus.0.20.0\lib\net452\S7.Net.dll</HintPath>
    </Reference>
    <Reference Include="SqlSugar, Version=5.1.4.168, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>packages\SqlSugar.5.1.4.169\lib\SqlSugar.dll</HintPath>
    </Reference>
    <Reference Include="Swashbuckle.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cd1bb07a5ac7c7bc, processorArchitecture=MSIL">
      <HintPath>..\packages\Swashbuckle.Core.5.6.0\lib\net40\Swashbuckle.Core.dll</HintPath>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
      <HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
    </Reference>
    <Reference Include="System.ComponentModel.Composition" />
    <Reference Include="System.Configuration" />
    <Reference Include="System.Configuration.Install" />
    <Reference Include="System.Core" />
    <Reference Include="System.Diagnostics.DiagnosticSource, Version=6.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
      <HintPath>packages\System.Diagnostics.DiagnosticSource.6.0.1\lib\net461\System.Diagnostics.DiagnosticSource.dll</HintPath>
    </Reference>
    <Reference Include="System.Formats.Asn1, Version=8.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
      <HintPath>packages\System.Formats.Asn1.8.0.1\lib\net462\System.Formats.Asn1.dll</HintPath>
    </Reference>
    <Reference Include="System.IdentityModel" />
    <Reference Include="System.IO.Compression" />
    <Reference Include="System.Management" />
    <Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
      <HintPath>..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>
    </Reference>
    <Reference Include="System.Net.Http, Version=4.1.1.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <HintPath>..\packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll</HintPath>
    </Reference>
    <Reference Include="System.Net.Http.Formatting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>packages\Microsoft.AspNet.WebApi.Client.6.0.0\lib\net45\System.Net.Http.Formatting.dll</HintPath>
    </Reference>
    <Reference Include="System.Numerics" />
    <Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
    </Reference>
    <Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
    </Reference>
    <Reference Include="System.Runtime.Serialization" />
    <Reference Include="System.Security.Cryptography.Algorithms, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <HintPath>..\packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net461\System.Security.Cryptography.Algorithms.dll</HintPath>
    </Reference>
    <Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <HintPath>..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath>
    </Reference>
    <Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <HintPath>..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
    </Reference>
    <Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.2, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <HintPath>packages\System.Security.Cryptography.X509Certificates.4.3.2\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
    </Reference>
    <Reference Include="System.ServiceModel" />
    <Reference Include="System.ServiceModel.Primitives, Version=4.10.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <HintPath>packages\System.ServiceModel.Primitives.4.10.0\lib\net461\System.ServiceModel.Primitives.dll</HintPath>
    </Reference>
    <Reference Include="System.ServiceProcess" />
    <Reference Include="System.Text.Encodings.Web, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
      <HintPath>..\packages\System.Text.Encodings.Web.8.0.0\lib\net462\System.Text.Encodings.Web.dll</HintPath>
    </Reference>
    <Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
      <HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll</HintPath>
    </Reference>
    <Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
      <HintPath>..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll</HintPath>
    </Reference>
    <Reference Include="System.Web" />
    <Reference Include="System.Web.Http, Version=5.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>packages\Microsoft.AspNet.WebApi.Core.5.3.0\lib\net45\System.Web.Http.dll</HintPath>
    </Reference>
    <Reference Include="System.Web.Http.Owin, Version=5.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>packages\Microsoft.AspNet.WebApi.Owin.5.3.0\lib\net45\System.Web.Http.Owin.dll</HintPath>
    </Reference>
    <Reference Include="System.Web.Http.WebHost, Version=5.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>packages\Microsoft.AspNet.WebApi.WebHost.5.3.0\lib\net45\System.Web.Http.WebHost.dll</HintPath>
    </Reference>
    <Reference Include="System.Web.Services" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
    <Reference Include="Topshelf, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b800c4cfcdeea87b, processorArchitecture=MSIL">
      <HintPath>..\packages\Topshelf.4.3.0\lib\net452\Topshelf.dll</HintPath>
    </Reference>
    <Reference Include="Topshelf.NLog, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b800c4cfcdeea87b, processorArchitecture=MSIL">
      <HintPath>..\packages\Topshelf.NLog.4.3.0\lib\net452\Topshelf.NLog.dll</HintPath>
    </Reference>
    <Reference Include="WebActivatorEx, Version=2.0.0.0, Culture=neutral, PublicKeyToken=7b26dc2a43f6a0d4, processorArchitecture=MSIL">
      <HintPath>packages\WebActivatorEx.2.2.0\lib\net40\WebActivatorEx.dll</HintPath>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="AppStart\Config.cs" />
    <Compile Include="Consts\AgvStateCode.cs" />
    <Compile Include="Consts\AgvStateName.cs" />
    <Compile Include="Consts\AreaCode.cs" />
    <Compile Include="Consts\AreaName.cs" />
    <Compile Include="Consts\LockStateCode.cs" />
    <Compile Include="Consts\LockStateName.cs" />
    <Compile Include="Consts\TaskName.cs" />
    <Compile Include="Controllers\DebugController.cs" />
    <Compile Include="Controllers\ErpController.cs" />
    <Compile Include="Controllers\MoboxController.cs" />
    <Compile Include="Controllers\AgvController.cs" />
    <Compile Include="Controllers\ApiModel.cs" />
    <Compile Include="AppStart\SwaggerControllerDescProvider.cs" />
    <Compile Include="Helpers\DbHelper.cs" />
    <Compile Include="Helpers\ResultHelper.cs" />
    <Compile Include="ServiceCore\WMSCore.cs" />
    <Compile Include="Models\BaseModel.cs" />
    <Compile Include="Services\DebugService.cs" />
    <Compile Include="Devices\ModbusHelper.cs" />
    <Compile Include="Devices\OpcUaHelper.cs" />
    <Compile Include="Devices\PlcHelper.cs" />
    <Compile Include="Devices\S7Helper.cs" />
    <Compile Include="Devices\ScanCodeHelper.cs" />
    <Compile Include="Devices\TcpClient.cs" />
    <Compile Include="Devices\TcpServer.cs" />
    <Compile Include="Dispatch\GZRobot.cs" />
    <Compile Include="Dispatch\HanAo.cs" />
    <Compile Include="Dispatch\NDC.cs" />
    <Compile Include="ServiceCore\Monitor.cs" />
    <Compile Include="Dispatch\NDCApi.cs" />
    <Compile Include="Dtos\Request\AgvRequest.cs" />
    <Compile Include="Dtos\Request\MoboxRequest.cs" />
    <Compile Include="Dtos\Response\AgvResponse.cs" />
    <Compile Include="Dtos\Response\MoboxResponse.cs" />
    <Compile Include="Models\TN_CG_Detail.cs" />
    <Compile Include="Models\TN_CAR_IN.cs" />
    <Compile Include="Models\TN_Container.cs" />
    <Compile Include="Models\TN_Location.cs" />
    <Compile Include="Models\TN_Loc_Container.cs" />
    <Compile Include="Models\TN_WorkOrder.cs" />
    <Compile Include="Models\TN_Task.cs" />
    <Compile Include="Models\TN_Task_Action.cs" />
    <Compile Include="Helpers\DeviceProcess.cs" />
    <Compile Include="ServiceCore\WCSCore.cs" />
    <Compile Include="Controllers\WmsController.cs" />
    <Compile Include="Dispatch\HostToAGV.cs" />
    <Compile Include="Helpers\TaskHelper.cs" />
    <Compile Include="Services\AgvService.cs" />
    <Compile Include="Services\MoboxService.cs" />
    <Compile Include="Helpers\LogHelper.cs" />
    <Compile Include="Helpers\ContainerHelper.cs" />
    <Compile Include="Helpers\LocationHelper.cs" />
    <Compile Include="Helpers\WMSHelper.cs" />
    <Compile Include="Helpers\SYSHelper.cs" />
    <Compile Include="Program.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="AppStart\Settings.cs" />
    <Compile Include="AppStart\Startup.cs" />
    <Compile Include="Dispatch\NDCHelper.cs" />
    <Compile Include="Helpers\HttpHelper.cs" />
    <Compile Include="Helpers\WCSHelper.cs" />
  </ItemGroup>
  <ItemGroup>
    <None Include=".editorconfig" />
    <None Include="App.config" />
    <None Include="config\config.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
    <None Include="packages.config" />
  </ItemGroup>
  <ItemGroup>
    <EmbeddedResource Include="swagger.js">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </EmbeddedResource>
  </ItemGroup>
  <ItemGroup>
    <BootstrapperPackage Include=".NETFramework,Version=v4.6.2">
      <Visible>False</Visible>
      <ProductName>Microsoft .NET Framework 4.6.2 %28x86 和 x64%29</ProductName>
      <Install>true</Install>
    </BootstrapperPackage>
    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
      <Visible>False</Visible>
      <ProductName>.NET Framework 3.5 SP1</ProductName>
      <Install>false</Install>
    </BootstrapperPackage>
  </ItemGroup>
  <ItemGroup />
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
HH.WCS.Mobox3.AnGang.sln
New file
@@ -0,0 +1,30 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.4.33205.214
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HH.WCS.Mobox3.AnGang", "HH.WCS.Mobox3.AnGang.csproj", "{EBE15A59-A43A-43BE-8B4B-A6EC42E11DF6}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2B600D60-6469-4E6C-9692-C01E7A42018E}"
    ProjectSection(SolutionItems) = preProject
        .editorconfig = .editorconfig
    EndProjectSection
EndProject
Global
    GlobalSection(SolutionConfigurationPlatforms) = preSolution
        Debug|Any CPU = Debug|Any CPU
        Release|Any CPU = Release|Any CPU
    EndGlobalSection
    GlobalSection(ProjectConfigurationPlatforms) = postSolution
        {EBE15A59-A43A-43BE-8B4B-A6EC42E11DF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {EBE15A59-A43A-43BE-8B4B-A6EC42E11DF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {EBE15A59-A43A-43BE-8B4B-A6EC42E11DF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {EBE15A59-A43A-43BE-8B4B-A6EC42E11DF6}.Release|Any CPU.Build.0 = Release|Any CPU
    EndGlobalSection
    GlobalSection(SolutionProperties) = preSolution
        HideSolutionNode = FALSE
    EndGlobalSection
    GlobalSection(ExtensibilityGlobals) = postSolution
        SolutionGuid = {8F82F32F-C59B-4BE6-A074-82CC2830FE2E}
    EndGlobalSection
EndGlobal
Helpers/ContainerHelper.cs
New file
@@ -0,0 +1,143 @@
using HH.WCS.Mobox3.AnGang.Models;
using HH.WCS.Mobox3.AnGang.config;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static HH.WCS.Mobox3.AnGang.Dispatch.NDC;
using HH.WCS.Mobox3.AnGang.Helpers;
namespace HH.WCS.Mobox3.AnGang.Helper {
    /// <summary>
    /// 容器帮助类
    /// </summary>
    internal class ContainerHelper
    {
        /// <summary>
        /// 容器绑定货品
        /// </summary>
        /// <param name="cnt"></param>
        /// <param name="cGs"></param>
        /// <returns></returns>
        public static string BindingCG(string cnt, List<string> cGs)
        {
            var db = DbHelper.GetDbClient();
            var logs = $"容器:{cnt},货品:{JsonConvert.SerializeObject(cGs)}";
            try
            {
                var cntCgList = db.Queryable<TN_CG_Detail>().Where(a => cGs.Contains(a.S_CG_ID) && a.S_CNTR_CODE == cnt).ToList();
                if (cntCgList.Count > 0)
                {
                    cGs = cGs.Except(cntCgList.Select(a => a.S_CNTR_CODE).ToList()).ToList();
                }
                var bindCntCgList = new List<TN_CG_Detail>();
                foreach (var item in cGs)
                {
                    bindCntCgList.Add(new TN_CG_Detail() { S_CNTR_CODE = cnt, S_CG_ID = item });
                }
                var log = JsonConvert.SerializeObject(bindCntCgList);
                if (db.Insertable<TN_CG_Detail>(bindCntCgList).ExecuteCommand() > 0)
                {
                    LogHelper.Info($"插入容器货品关系表成功,{log}");
                }
                else
                {
                    LogHelper.Info($"插入容器货品关系表失败,{log}");
                    return "容器绑定货品失败," + logs;
                }
                var cntid = db.Queryable<TN_Container>().First(a => a.S_CODE == cnt);
                if (cntid != null)
                {
                    cntid.T_MODIFY = System.DateTime.Now;
                    log = JsonConvert.SerializeObject(cntid);
                    if (db.Updateable(cntid).UpdateColumns(it => new { it.T_MODIFY }).ExecuteCommand() > 0)
                    {
                        LogHelper.Info($"更新容器表成功,{log}");
                    }
                    else
                    {
                        LogHelper.Info($"更新容器表失败,{log}");
                        return "容器绑定货品失败," + logs;
                    }
                }
                else
                {
                    LogHelper.Info($"在数据库中未找到该容器,无需更新,容器:{cnt}");
                }
                return "容器绑定货品成功," + logs;
            }
            catch (Exception ex)
            {
                LogHelper.Info($"发生了异常,货位绑定容器失败,");
                return "容器绑定货品失败," + ex.Message;
            }
        }
        /// <summary>
        /// 容器解绑货品
        /// </summary>
        /// <param name="cnt"></param>
        /// <param name="cGs"></param>
        /// <returns></returns>
        public static string UnBindingCG(string cnt, List<string> cGs)
        {
            var db = DbHelper.GetDbClient();
            var logs = $"容器:{cnt},货品:{JsonConvert.SerializeObject(cGs)}";
            try
            {
                var cntCgList = db.Queryable<TN_CG_Detail>().Where(a => cGs.Contains(a.S_CG_ID) && a.S_CNTR_CODE == cnt).ToList();
                if (cntCgList.Count == 0)
                {
                    LogHelper.Info($"容器无需解绑货品,在数据库中未找到{JsonConvert.SerializeObject(cGs)}相关的容器货品关系表信息");
                    return "容器无需解绑货品,解绑成功" + logs;
                }
                cGs = cntCgList.Select(a => a.S_CG_ID).ToList();
                var log = JsonConvert.SerializeObject(cGs);
                if (db.Deleteable<TN_CG_Detail>().Where(it => cGs.Contains(it.S_CG_ID) && it.S_CNTR_CODE == cnt).ExecuteCommand() > 0)
                {
                    LogHelper.Info($"删除容器货品关系表成功,{log}");
                }
                else
                {
                    LogHelper.Info($"删除容器货品关系表失败,{log}");
                    return "容器绑定货品失败," + logs;
                }
                var CntId = db.Queryable<TN_Container>().First(a => a.S_CODE == cnt);
                if (CntId != null)
                {
                    CntId.T_MODIFY = System.DateTime.Now;
                    log = JsonConvert.SerializeObject(CntId);
                    if (db.Updateable(CntId).UpdateColumns(it => new { it.T_MODIFY }).ExecuteCommand() > 0)
                    {
                        LogHelper.Info($"更新容器表成功,{log}");
                    }
                    else
                    {
                        LogHelper.Info($"更新容器表失败,{log}");
                        return "容器绑定货品失败," + logs;
                    }
                }
                else
                {
                    LogHelper.Info($"在数据库中未找到该容器,无需更新,容器:{cnt}");
                }
                return "容器解绑货品成功," + logs;
            }
            catch (Exception ex)
            {
                LogHelper.Info($"发生了异常,货位解绑容器失败,{ex.Message}");
                return "容器解绑货品失败," + logs;
            }
        }
    }
}
Helpers/DbHelper.cs
New file
@@ -0,0 +1,133 @@
using System;
using System.Linq;
using HH.WCS.Mobox3.AnGang.AppStart;
using SqlSugar;
using Task = System.Threading.Tasks.Task;
namespace HH.WCS.Mobox3.AnGang.Helpers {
    // SqlSugar 教程:https://www.donet5.com/Home/Doc
    /// <summary>
    /// 数据库帮助类:包括单例模式和创建新连接的方法
    /// </summary>
    public static class DbHelper {
        private static readonly SqlSugarScope _sqlSugar;
        static DbHelper() {
            _sqlSugar = new SqlSugarScope(new ConnectionConfig() {
                ConnectionString = Settings.Config.SqlServer,
                DbType = DbType.SqlServer,
                IsAutoCloseConnection = true,
                InitKeyType = InitKeyType.Attribute // 从特性读取主键自增信息
            },
            db => {
                // 监控所有超过1秒的Sql
                db.Aop.OnLogExecuted = (sql, p) =>
                {
                    // 执行时间超过1秒
                    if (db.Ado.SqlExecutionTime.TotalSeconds > 1) {
                        Console.WriteLine(sql + "\r\n" + db.Utilities.SerializeObject(p.ToDictionary(it => it.ParameterName, it => it.Value)));
                        // 代码CS文件名
                        var fileName = db.Ado.SqlStackTrace.FirstFileName;
                        // 代码行数
                        var fileLine = db.Ado.SqlStackTrace.FirstLine;
                        // 方法名
                        var FirstMethodName = db.Ado.SqlStackTrace.FirstMethodName;
                    }
                    // 相当于EF的 PrintToMiniProfiler
                };
                // 每次设置数值时都去除前导后导空格
                db.Aop.DataExecuted = (value, entity) => {
                    entity.EntityColumnInfos.ToList().ForEach(a => {
                        var pvalue = entity.GetValue(a.PropertyName);
                        if (pvalue != null && pvalue.GetType() == typeof(String)) {
                            entity.SetValue(a.PropertyName, pvalue.ToString().Trim());
                        }
                    });
                };
                // 配置AOP日志
                //db.Aop.OnLogExecuting = (sql, pars) =>
                //{
                //    Console.WriteLine(sql); // 输出纯SQL语句
                //};
                // 每N小时清理一次缓存
                Task.Run(async () => {
                    while (true) {
                        await Task.Delay(TimeSpan.FromHours(2));
                        db.QueryFilter.Clear();
                    }
                });
            });
        }
        /// <summary>
        /// 获取用于操控数据库的 SqlSugarClient 对象
        /// </summary>
        /// <returns></returns>
        public static SqlSugarScope GetDbClient() {
            return _sqlSugar;
        }
        /// <summary>
        /// 生成用于操控数据库的 SqlSugarClient 对象
        /// </summary>
        /// <remarks>
        /// 如果用 Oracle 数据需要包 Oracle.ManagedDataAccess/21.15.0,环境 netframework 4.62,太新了 4.8 有的服务器安装不上去
        /// </remarks>
        /// <param name="url"></param>
        /// <returns></returns>
        public static SqlSugarClient NewDbClient(string url = "") {
            // 创建数据库对象
            SqlSugarClient db = new SqlSugarClient(new ConnectionConfig() {
                ConnectionString = string.IsNullOrEmpty(url) ? Settings.Config.SqlServer : url,
                DbType = DbType.SqlServer,
                IsAutoCloseConnection = true,
                InitKeyType = InitKeyType.Attribute // 从特性读取主键自增信息
            });
            // 监控所有超过1秒的Sql
            db.Aop.OnLogExecuted = (sql, p) => {
                // 执行时间超过1秒
                if (db.Ado.SqlExecutionTime.TotalSeconds > 1) {
                    Console.WriteLine(sql + "\r\n" + db.Utilities.SerializeObject(p.ToDictionary(it => it.ParameterName, it => it.Value)));
                    // 代码CS文件名
                    var fileName = db.Ado.SqlStackTrace.FirstFileName;
                    // 代码行数
                    var fileLine = db.Ado.SqlStackTrace.FirstLine;
                    // 方法名
                    var FirstMethodName = db.Ado.SqlStackTrace.FirstMethodName;
                }
                // 相当于EF的 PrintToMiniProfiler
            };
            // 每次设置数值时都去除前导后导空格
            db.Aop.DataExecuted = (value, entity) => {
                entity.EntityColumnInfos.ToList().ForEach(a => {
                    var pvalue = entity.GetValue(a.PropertyName);
                    if (pvalue != null && pvalue.GetType() == typeof(String)) {
                        entity.SetValue(a.PropertyName, pvalue.ToString().Trim());
                    }
                });
            };
            // 据转换 (ExecuteCommand 才会拦截,查询不行)
            //db.Aop.DataExecuting = (value, entity) => {
            //    //var val=entity.EntityColumnInfo
            //    Console.WriteLine(entity.EntityName);
            //};
            // 用于打印 SqlSugar 解码后的 SQL 语句
            db.Aop.OnLogExecuting = (sql, pars) => {
                Console.WriteLine(sql);
            };
            return db;
        }
    }
}
Helpers/DeviceProcess.cs
New file
@@ -0,0 +1,28 @@
using HH.WCS.Mobox3.AnGang.Devices;
using HH.WCS.Mobox3.AnGang.Dispatch;
using HH.WCS.Mobox3.AnGang.config;
using HH.WCS.Mobox3.AnGang.Helper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace HH.WCS.Mobox3.AnGang.process
{
    /// <summary>
    /// 设备信号处理,主要是tcp信号,我们做server被动接收信号来处理,根据项目定制的
    /// </summary>
    internal class DeviceProcess
    {
        internal static void Analysis(string data, string ip) {
            if (data.Length >= 6) {
                //去掉消息头3F 00
                data = data.Substring(4);
                //Console.WriteLine($"{ip}-{data}");
            }
        }
    }
}
Helpers/HttpHelper.cs
New file
@@ -0,0 +1,286 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
namespace HH.WCS.Mobox3.AnGang.config {
    public class HttpHelper {
        public string WebPost(string url, string postData, string cotentType = "application/json")
        {
            Console.WriteLine(url);
            WebRequest request = WebRequest.Create(url);
            request.Method = "POST";
            //string postData = JsonConvert.SerializeObject(data); ;
            byte[] byteArray = Encoding.UTF8.GetBytes(postData);
            request.ContentType = cotentType;
            request.ContentLength = byteArray.Length;
            request.Timeout = 3000;
            StreamReader reader = null;
            Stream dataStream = null;
            WebResponse response = null;
            try
            {
                dataStream = request.GetRequestStream();
                dataStream.Write(byteArray, 0, byteArray.Length);
                dataStream.Close();
                response = request.GetResponse();
                //Console.WriteLine(((HttpWebResponse)response).StatusDescription);
                dataStream = response.GetResponseStream();
                reader = new StreamReader(dataStream, Encoding.UTF8);
                string responseFromServer = reader.ReadToEnd();
                return responseFromServer;
            }
            catch (Exception e)
            {
                LogHelper.Info($"WebPost res={e.Message}", "API");
                return "";
            }
            finally
            {
                // 释放资源
                if (reader != null) reader.Close();
                if (dataStream != null) dataStream.Close();
                if (response != null) response.Close();
            }
        }
        public string WebGet(string url) {
            WebRequest request = WebRequest.Create(url);
            request.Timeout = 6000;
            request.Method = "GET";
            StreamReader reader = null;
            Stream dataStream = null;
            WebResponse response = null;
            try {
                response = request.GetResponse();
                dataStream = response.GetResponseStream();
                reader = new StreamReader(dataStream);
                string responseFromServer = reader.ReadToEnd();
                Console.WriteLine(responseFromServer);
                return responseFromServer;
            }
            catch (Exception e) {
                LogHelper.Info($"WebGet res={e.Message}", "API");
                return "";
            }
            finally
            {
                // 释放资源
                if (reader != null) reader.Close();
                if (dataStream != null) dataStream.Close();
                if (response != null) response.Close();
            }
        }
        public string Get(string url, string contentType = "application/x-www-form-urlencoded") {
            WebRequest request = WebRequest.Create(url);
            request.Method = "Get";
            request.ContentType = contentType;
            StreamReader reader = null;
            Stream stream = null;
            WebResponse rsp = null;
            try {
                rsp = request.GetResponse();
                stream = rsp.GetResponseStream();
                reader = new StreamReader(stream);
                return reader.ReadToEnd();
            }
            catch (Exception e)
            {
                LogHelper.Info($"Get res={e.Message}", "API");
                return "";
            }
            finally {
                // 释放资源
                if (reader != null) reader.Close();
                if (stream != null) stream.Close();
                if (rsp != null) rsp.Close();
            }
        }
        public string Post(string url, string postData, string contentType = "application/json", string sessionId = "") {
            Console.WriteLine(url);
            WebRequest request = WebRequest.Create(url);
            request.Method = "POST";
            byte[] byteArray = Encoding.UTF8.GetBytes(postData);
            request.ContentType = contentType;
            request.ContentLength = byteArray.Length;
            request.Timeout = 3000;
            if (sessionId != "") {
                request.Headers.Set("ASP.NET_SessionId", sessionId);
            }
            StreamReader reader = null;
            Stream stream = null;
            WebResponse rsp = null;
            try {
                stream = request.GetRequestStream();
                stream.Write(byteArray, 0, byteArray.Length);
                stream.Close();
                rsp = request.GetResponse();
                stream = rsp.GetResponseStream();
                reader = new StreamReader(stream);
                return reader.ReadToEnd();
            }
            catch (Exception ex) {
                LogHelper.Info($"Post res={ex.Message}", "API");
                return "";
            }
            finally {
                // 释放资源
                if (reader != null) reader.Close();
                if (stream != null) stream.Close();
                if (rsp != null) rsp.Close();
            }
        }
        public string Post(string url, Dictionary<string, string> dic) {
            var param = dic.Select(a => { return string.Format("{0}={1}", a.Key, a.Value); }).ToList();
            return Post(url, string.Join("&", param), "application/x-www-form-urlencoded");
        }
        public string PostWithCookie(string url, string sessinId) {
            return PostWithCookie(url, "", "", sessinId);
        }
        public string PostWithCookie(string url, string postData, string contentType = "application/json", string sessionId = "") {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "POST";
            byte[] byteArray = Encoding.UTF8.GetBytes(postData);
            request.ContentType = contentType;
            request.ContentLength = byteArray.Length;
            if (sessionId != "") {
                request.CookieContainer = new CookieContainer();
                request.CookieContainer.SetCookies(new Uri("http://" + request.RequestUri.Authority), "ASP.NET_SessionId=" + sessionId);
            }
            StreamReader reader = null;
            Stream stream = null;
            WebResponse rsp = null;
            try {
                stream = request.GetRequestStream();
                stream.Write(byteArray, 0, byteArray.Length);
                stream.Close();
                rsp = request.GetResponse();
                stream = rsp.GetResponseStream();
                reader = new StreamReader(stream);
                return reader.ReadToEnd();
            }
            catch (Exception e)
            {
                LogHelper.Info($"PostWithCookie res={e.Message}", "API");
                return "";
            }
            finally {
                // 释放资源
                if (reader != null) reader.Close();
                if (stream != null) stream.Close();
                if (rsp != null) rsp.Close();
            }
        }
        public string Put(string url, string postData, string contentType = "application/json", string sessionId = "")
        {
            WebRequest request = WebRequest.Create(url);
            request.Method = "Put";
            byte[] byteArray = Encoding.UTF8.GetBytes(postData);
            request.ContentType = contentType;
            request.ContentLength = byteArray.Length;
            if (sessionId != "")
            {
                request.Headers.Set("ASP.NET_SessionId", sessionId);
            }
            StreamReader reader = null;
            Stream stream = null;
            WebResponse rsp = null;
            try
            {
                stream = request.GetRequestStream();
                stream.Write(byteArray, 0, byteArray.Length);
                stream.Close();
                rsp = request.GetResponse();
                stream = rsp.GetResponseStream();
                reader = new StreamReader(stream);
                return reader.ReadToEnd();
            }
            catch (Exception e)
            {
                LogHelper.Info($"Put res={e.Message}", "API");
                return "";
            }
            finally
            {
                // 释放资源
                if (reader != null) reader.Close();
                if (stream != null) stream.Close();
                if (rsp != null) rsp.Close();
            }
        }
        public string WebPostWithMD5(string url, string postData, string contentType = "application/json")
        {
            // 新增授权参数
            string appKey = ""; // 假设配置类中有AppKey和AppSecret
            string appSecret = "";
            string reqTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
            string reqVerify = CalculateMD5Hash($"{appKey}{appSecret}{reqTime}");
            WebRequest request = WebRequest.Create(url);
            request.Method = "POST";
            request.Headers.Add("AppKey", appKey);
            request.Headers.Add("ReqTime", reqTime);
            request.Headers.Add("ReqVerify", reqVerify);
            byte[] byteArray = Encoding.UTF8.GetBytes(postData);
            request.ContentType = contentType;
            request.ContentLength = byteArray.Length;
            request.Timeout = 3000;
            StreamReader reader = null;
            Stream dataStream = null;
            WebResponse response = null;
            try
            {
                dataStream = request.GetRequestStream();
                dataStream.Write(byteArray, 0, byteArray.Length);
                dataStream.Close();
                response = request.GetResponse();
                //Console.WriteLine(((HttpWebResponse)response).StatusDescription);
                dataStream = response.GetResponseStream();
                reader = new StreamReader(dataStream, Encoding.UTF8);
                string responseFromServer = reader.ReadToEnd();
                return responseFromServer;
            }
            catch (Exception e)
            {
                LogHelper.Info($"WebPost res={e.Message}", "API");
                return "";
            }
            finally
            {
                // 释放资源
                if (reader != null) reader.Close();
                if (dataStream != null) dataStream.Close();
                if (response != null) response.Close();
            }
        }
        // MD5计算辅助方法
        private static string CalculateMD5Hash(string input)
        {
            using (var md5 = System.Security.Cryptography.MD5.Create())
            {
                byte[] inputBytes = Encoding.UTF8.GetBytes(input);
                byte[] hashBytes = md5.ComputeHash(inputBytes);
                return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
            }
        }
    }
}
Helpers/LocationHelper.cs
New file
@@ -0,0 +1,548 @@
using HH.WCS.Mobox3.AnGang.Models;
using HH.WCS.Mobox3.AnGang.config;
using Newtonsoft.Json;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static HH.WCS.Mobox3.AnGang.Controllers.ApiModel;
using HH.WCS.Mobox3.AnGang.Helpers;
namespace HH.WCS.Mobox3.AnGang.Helper {
    public class LocationHelper
    {
        private static Dictionary<string, TN_Location> Locations = null;
        static LocationHelper()
        {
            try
            {
                //初始化Location加入到字典缓存
                Locations = new Dictionary<string, TN_Location>();
                var list = GetAllLocList();
                if (list.Count > 0)
                {
                    list.ForEach(a =>
                    {
                        if (!Locations.ContainsKey(a.S_CODE))
                        {
                            Locations.Add(a.S_CODE, a);
                        }
                    });
                }
                //初始化LocationExt加入到集合缓存
                //LocationExts = new Dictionary<string, LocationExt>();
                //var exts = GetAllLocExtList();
                //if (exts.Count > 0) {
                //    exts.ForEach(a => {
                //        LocationExts.Add($"{a.S_LOC_CODE.Trim()}_{a.S_PICKUP_POINT.Trim()}", a);
                //    });
                //}
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
        /// <summary>
        /// 获取所有货位信息
        /// </summary>
        /// <returns></returns>
        internal static List<TN_Location> GetAllLocList()
        {
            var db = DbHelper.GetDbClient();
            return db.Queryable<TN_Location>().ToList();
        }
        internal static TN_Location GetLocation(string loc)
        {
            if (Locations.Keys.Contains(loc))
            {
                return Locations[loc.Trim()];
            }
            return null;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="loc"></param>
        /// <returns></returns>
        public static bool IsFree(TN_Location loc) {
            return loc != null
                && loc.N_LOCK_STATE == 0
                && loc.S_LOCK_STATE == "无"
                && loc.C_ENABLE == "Y";
        }
        /// <summary>
        /// 获取货位站点信息
        /// </summary>
        /// <param name="loc"></param>
        /// <param name="isEmpty">是否属于人工空托区到空托缓存库区</param>
        /// <returns></returns>
        internal static string GetAgvSite(string loc, bool isEmpty = false)
        {
            var site = "0";
            if (Locations.Keys.Contains(loc.Trim()) && !isEmpty)
            {
                var Location = Locations[loc.Trim()];
                site = Location.S_AGV_SITE;
            }
            else
            {
                var Location = GetLoc(loc.Trim());
                if (Location != null)
                {
                    site = Location.S_AGV_SITE;
                    if (isEmpty)
                    {
                        if (Location.N_CURRENT_NUM == 0)
                        {
                            site = Location.S_AGV_SITE;
                        }
                        //if (Location.N_CURRENT_NUM == 1)
                        //{
                        //    site = Location.S_AGV_SITE2;
                        //}
                        //if (Location.N_CURRENT_NUM == 2)
                        //{
                        //    site = Location.S_AGV_SITE3;
                        //}
                        //if (Location.N_CURRENT_NUM == 3)
                        //{
                        //    site = Location.S_AGV_SITE4;
                        //}
                        //if (Location.N_CURRENT_NUM == 4)
                        //{
                        //    site = Location.S_AGV_SITE5;
                        //}
                    }
                }
            }
            return site;
        }
        internal static TN_Location GetLoc(string code)
        {
            var db = DbHelper.GetDbClient();
            return db.Queryable<TN_Location>().Where(a => a.S_CODE.Trim() == code).First();
        }
        /// <summary>
        /// 入库锁定终点,出库锁定起点
        /// 你创建任务锁定货位的时候,把锁的来源就是任务号也写上去(加锁的方法加个参数,可空的参数),解锁的时候把来源置空。
        /// </summary>
        /// <param name="loc"></param>
        /// <param name="lockState">1:入库锁、2:出库锁、2:其它锁</param>
        /// <param name="lockSource">锁的来源=任务号</param>
        /// <returns></returns>
        public static bool LockLoc(string loc, int lockState, string lockSource = "")
        {
            var res = false;
            var db = DbHelper.GetDbClient();
            var model = db.Queryable<TN_Location>().Where(a => a.S_CODE == loc).First();
            LogHelper.Info($"锁货位{loc},状态{lockState},信息" + JsonConvert.SerializeObject(model));
            if (model != null && model.N_LOCK_STATE == 0)
            {
                model.N_LOCK_STATE = lockState;
                model.S_LOCK_STATE = TN_Location.GetLockStateStr(lockState);
                model.S_LOCK_OP = lockSource;
                model.T_MODIFY = System.DateTime.Now;
                res = db.Updateable<TN_Location>(model).UpdateColumns(it => new { it.N_LOCK_STATE, it.S_LOCK_STATE, it.S_LOCK_OP, it.T_MODIFY }).ExecuteCommand() > 0;
            }
            LogHelper.Info($"锁货位{loc}返回{res}");
            return res;
        }
        /// <summary>
        /// 取货完解锁起点,卸货完解锁终点,可检验锁的来源,也可以不校验
        /// </summary>
        /// <param name="loc"></param>
        /// <returns></returns>
        public static bool UnLockLoc(string loc)
        {
            LogHelper.Info("UnLockLoc:" + loc);
            var res = false;
            var db = DbHelper.GetDbClient();
            var model = db.Queryable<TN_Location>().Where(a => a.S_CODE == loc).First();
            if (model != null)
            {
                model.S_LOCK_STATE = "无";
                model.N_LOCK_STATE = 0;
                model.S_LOCK_OP = "";
                model.T_MODIFY = System.DateTime.Now;
                res = db.Updateable(model).UpdateColumns(it => new { it.N_LOCK_STATE, it.S_LOCK_STATE, it.S_LOCK_OP, it.T_MODIFY }).ExecuteCommand() > 0;
                LogHelper.Info("UnLockLoc:解锁结果" + res);
            }
            else
            {
                LogHelper.Info("UnLockLoc 失败" + loc);
            }
            return res;
        }
        /// <summary>
        /// 货位解绑容器
        /// </summary>
        /// <param name="loc"></param>
        /// <param name="cntrs"></param>
        /// <returns></returns>
        public static string UnBindingLoc(string loc, List<string> cntrs)
        {
            var db = DbHelper.GetDbClient();
            var logs = $"货位:{loc},容器:{JsonConvert.SerializeObject(cntrs)}";
            try
            {
                var lcrList = db.Queryable<TN_Loc_Container>().Where(a => cntrs.Contains(a.S_CNTR_CODE) && a.S_LOC_CODE == loc).ToList();
                if (lcrList.Count == 0)
                {
                    LogHelper.Info($"货位无需解绑容器,在数据库中未找到{JsonConvert.SerializeObject(cntrs)}相关的货位容器关系表信息");
                }
                cntrs = lcrList.Select(a => a.S_CNTR_CODE).ToList();
                var log = JsonConvert.SerializeObject(cntrs);
                var location = db.Queryable<TN_Location>().First(a => a.S_CODE == loc);
                if (location != null)
                {
                    location.N_CURRENT_NUM = 0;
                    location.S_LOCK_STATE = "无";
                    location.N_LOCK_STATE = 0;
                    using (var tran = db.Ado.UseTran())
                    {
                        if (db.Deleteable<TN_Loc_Container>().Where(it => cntrs.Contains(it.S_CNTR_CODE) && it.S_LOC_CODE == loc).ExecuteCommand() > 0)
                        {
                            LogHelper.Info($"删除货位容器关系表成功,{log}");
                        }
                        else
                        {
                            tran.RollbackTran();
                            LogHelper.Info($"删除货位容器关系表失败,{log}");
                            return "货位解绑容器失败," + logs;
                        }
                        log = JsonConvert.SerializeObject(location);
                        if (db.Updateable(location).UpdateColumns(it => new { it.N_CURRENT_NUM, it.S_LOCK_STATE, it.N_LOCK_STATE }).ExecuteCommand() > 0)
                        {
                            tran.CommitTran();
                            LogHelper.Info($"更新货位表成功,{log}");
                        }
                        else
                        {
                            tran.RollbackTran();
                            LogHelper.Info($"更新货位表失败,{log}");
                            return "货位解绑容器失败," + logs;
                        }
                    }
                }
                else
                {
                    LogHelper.Info($"在数据库中未找到该货位,无需更新,货位:{loc}");
                }
                return "货位解绑容器成功," + logs;
            }
            catch (Exception ex)
            {
                LogHelper.Info($"发生了异常,货位解绑容器失败,{ex.Message}");
                return "货位绑定容器失败," + logs;
            }
        }
        /// <summary>
        /// 货位绑定容器
        /// </summary>
        /// <param name="loc"></param>
        /// <param name="cntrs"></param>
        /// <returns></returns>
        public static string BindingLoc(string loc, List<string> cntrs)
        {
            var db = DbHelper.GetDbClient();
            var logs = $"货位:{loc},容器:{JsonConvert.SerializeObject(cntrs)}";
            try
            {
                var lcrList = db.Queryable<TN_Loc_Container>().Where(a => cntrs.Contains(a.S_CNTR_CODE) && a.S_LOC_CODE == loc).ToList();
                if (lcrList.Count > 0)
                {
                    cntrs = cntrs.Except(lcrList.Select(a => a.S_CNTR_CODE).ToList()).ToList();
                }
                var bindLocCntList = new List<TN_Loc_Container>();
                foreach (var item in cntrs)
                {
                    bindLocCntList.Add(new TN_Loc_Container() { S_LOC_CODE = loc, S_CNTR_CODE = item });
                }
                var log = JsonConvert.SerializeObject(bindLocCntList);
                using (var tran = db.Ado.UseTran())
                {
                    if (db.Insertable<TN_Loc_Container>(bindLocCntList).ExecuteCommand() > 0)
                    {
                        LogHelper.Info($"插入货位容器关系表成功,{log}");
                    }
                    else
                    {
                        db.RollbackTran();
                        LogHelper.Info($"插入货位容器关系表失败,{log}");
                        return "货位绑定容器失败," + logs;
                    }
                    var location = db.Queryable<TN_Location>().First(a => a.S_CODE == loc);
                    if (location != null)
                    {
                        location.N_CURRENT_NUM += cntrs.Count;
                        location.S_LOCK_STATE = "无";
                        location.N_LOCK_STATE = 0;
                        log = JsonConvert.SerializeObject(location);
                        if (db.Updateable(location).UpdateColumns(it => new { it.N_CURRENT_NUM, it.S_LOCK_STATE, it.N_LOCK_STATE }).ExecuteCommand() > 0)
                        {
                            db.CommitTran();
                            LogHelper.Info($"更新货位表成功,{log}");
                        }
                        else
                        {
                            db.RollbackTran();
                            LogHelper.Info($"更新货位表失败,{log}");
                            return "货位绑定容器失败," + logs;
                        }
                    }
                    else
                    {
                        db.RollbackTran();
                        LogHelper.Info($"未找到该货位{loc},或者已锁定,{log}");
                    }
                }
                return "货位绑定容器成功," + logs;
            }
            catch (Exception ex)
            {
                LogHelper.Info($"发生了异常,货位绑定容器失败,");
                return "货位绑定容器失败," + ex.Message;
            }
        }
        /// <summary>
        /// 人工手动PDA解绑:删除货位/容器/货品三方信息,1=解绑货位与容器,2=解绑容器与货品
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult PdaUnBind(PdaUnBindInfo model)
        {
            var simpleResult = new SimpleResult();
            if (model.reqCode == 1)
            {
                var res = UnBindingLoc(model.locID, new List<string>() { model.cntID });
                simpleResult.resultCode = res.Contains("失败") ? -1 : 0;
                simpleResult.resultMsg = res;
                return simpleResult;
            }
            if (model.reqCode == 2)
            {
                var res = ContainerHelper.UnBindingCG(model.cntID, new List<string>() { model.CgId });
                simpleResult.resultCode = res.Contains("失败") ? -1 : 0;
                simpleResult.resultMsg = res;
                return simpleResult;
            }
            simpleResult.resultCode = 3;
            simpleResult.resultMsg = "人工手动PDA解绑:删除货位/容器/货品三方信息,1=解绑货位与容器,2=解绑容器与货品";
            return simpleResult;
        }
        /// <summary>
        /// 异常货位容器重置:重置货位/容器/货品三方信息,1=根据货位重置,2=直接根据容器重置
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult ErrorLocCntReset(ErrorLocCntResetInfo model)
        {
            LogHelper.Info("触发API:货位容器重置" + JsonConvert.SerializeObject(model), "API");
            var result = new SimpleResult();
            var db = DbHelper.GetDbClient();
            try
            {
                if (model.locID != string.Empty && model.reqCode == 1)
                {
                    var locCntrRels = db.Queryable<TN_Loc_Container>().Where(a => a.S_LOC_CODE == model.locID).ToList();
                    if (locCntrRels.Count == 0)
                    {
                        result.resultCode = 2;
                        result.resultMsg = $"未找到货位容器关系信息{model.locID}";
                        LogHelper.Info(result.resultMsg);
                        return result;
                    }
                    foreach (var item in locCntrRels)
                    {
                        var cG_Detail = db.Queryable<TN_CG_Detail>().Where(a => a.S_CNTR_CODE == item.S_CNTR_CODE).ToList();
                        if (cG_Detail.Count > 0)
                        {
                            if (db.Deleteable<TN_CG_Detail>(cG_Detail).ExecuteCommand() <= 0)
                            {
                                LogHelper.Info($"删除容器{model.cntID}货品明细表信息失败");
                                continue;
                            }
                        }
                    }
                    if (db.Deleteable<TN_Loc_Container>(locCntrRels).ExecuteCommand() <= 0)
                    {
                        result.resultCode = 3;
                        result.resultMsg = $"删除货位{model.locID}容器{model.cntID}关系表信息失败";
                        LogHelper.Info(result.resultMsg);
                        return result;
                    }
                    var loc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.locID);
                    if (loc != null)
                    {
                        loc.N_CURRENT_NUM = 0;
                        loc.N_LOCK_STATE = 0;
                        loc.S_LOCK_STATE = "无";
                        loc.C_ENABLE = "Y";
                        if (db.Updateable<TN_Location>(loc).UpdateColumns(it => new { it.N_CURRENT_NUM, it.N_LOCK_STATE, it.S_LOCK_STATE, it.C_ENABLE }).ExecuteCommand() <= 0)
                        {
                            result.resultCode = 4;
                            result.resultMsg = $"更新货位{loc.S_CODE}信息失败";
                            LogHelper.Info(result.resultMsg);
                            return result;
                        }
                    }
                    string ackLog = $"重置成功,货位{model.locID},容器{JsonConvert.SerializeObject(locCntrRels.Select(a => a.S_CNTR_CODE).ToList())}";
                    LogHelper.Info(ackLog);
                    result.resultCode = 0;
                    result.resultMsg = ackLog;
                    return result;
                }
                if (model.cntID != string.Empty && model.reqCode == 2)
                {
                    var locCntrRel = db.Queryable<TN_Loc_Container>().First(a => a.S_CNTR_CODE == model.cntID);
                    var cG_Detail = db.Queryable<TN_CG_Detail>().Where(a => a.S_CNTR_CODE == locCntrRel.S_CNTR_CODE).ToList();
                    if (cG_Detail.Count > 0)
                    {
                        if (db.Deleteable<TN_CG_Detail>(cG_Detail).ExecuteCommand() <= 0)
                        {
                            result.resultCode = 5;
                            result.resultMsg = $"删除容器{model.cntID}货品明细表信息失败";
                            LogHelper.Info(result.resultMsg);
                            return result;
                        }
                    }
                    var loc = db.Queryable<TN_Location>().First(a => a.S_CODE == locCntrRel.S_LOC_CODE);
                    if (loc != null)
                    {
                        loc.N_CURRENT_NUM = 0;
                        loc.N_LOCK_STATE = 0;
                        loc.S_LOCK_STATE = "无";
                        loc.C_ENABLE = "Y";
                        if (db.Updateable<TN_Location>(loc).UpdateColumns(it => new { it.N_CURRENT_NUM, it.N_LOCK_STATE, it.S_LOCK_STATE, it.C_ENABLE }).ExecuteCommand() <= 0)
                        {
                            result.resultCode = 6;
                            result.resultMsg = $"更新货位{loc.S_CODE}信息失败";
                            LogHelper.Info(result.resultMsg);
                            return result;
                        }
                    }
                }
                result.resultCode = 0;
                result.resultMsg = $"重置成功,容器{model.cntID}";
                LogHelper.Info(result.resultMsg);
                return result;
            }
            catch (Exception ex)
            {
                result.resultCode = -1;
                result.resultMsg = $"发生了异常:{ex.Message}";
                LogHelper.Info(result.resultMsg);
                return result;
            }
        }
        public static string GetStrByOk(int state)
        {
            if (state == 0)
            {
                return "合格";
            }
            if (state == 1)
            {
                return "待检";
            }
            if (state == 2)
            {
                return "不合格";
            }
            if (state == 3)
            {
                return "正在检验";
            }
            return "待检";
        }
    }
    public class PdaUnBindInfo
    {
        public string cntID { get; set; }//容器ID
        public string locID { get; set; }//货位ID
        public string CgId { get; set; }//物料编码
        public int reqCode { get; set; }//请求代码
    }
    public class EmptyUnBindInfo
    {
        public string cntID { get; set; }//容器ID
    }
    public class CancleTaskInfo
    {
        public string taskNO { get; set; }//任务号
    }
    public class PDAFullInAreaInfo
    {
        public string StartLoc { get; set; }//起点
        public string RfId { get; set; }//容器号
        public string Spe { get; set; }//规格
        public string CarCode { get; set; }//车号
    }
    public class ErrorLocCntResetInfo
    {
        public string cntID { get; set; }//容器ID
        public string locID { get; set; }//货位ID
        public int reqCode { get; set; }//请求代码
    }
    public class PDAFullCheckInfo
    {
        public string RfId { get; set; }//容器号
    }
    public class ShowCntCountBySpeInfo
    {
        public string Spe { get; set; }//规格
    }
}
Helpers/LogHelper.cs
New file
@@ -0,0 +1,142 @@
using NLog;
using NLog.Common;
using NLog.Config;
using NLog.Targets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang
{
    public class LogHelper
    {
        public static Dictionary<string, ILogger> loggers = new Dictionary<string, ILogger>();
        public static void Debug(string message, string name = "") {
            ILogger logger = null;
            if (loggers.Keys.Contains(name)) {
                logger = loggers[name];
            }
            else {
                logger = LogFactory.CreateLogger(name);
                if (logger != null) {
                    loggers.Add(name, logger);
                }
                else {
                    logger = LogFactory.CreateLogger("console");
                }
            }
            if (logger != null) {
                logger.Debug(message);
            }
        }
        public static void Info(string message, string name = "") {
            //logger.Info(message);
            ILogger logger = null;
            if (loggers.Keys.Contains(name)) {
                logger = loggers[name];
            }
            else {
                logger = LogFactory.CreateLogger(name);
                if (logger != null) {
                    loggers.Add(name, logger);
                }
                else {
                    logger = LogFactory.CreateLogger("infoFile");
                }
            }
            if (logger != null) {
                logger.Info(message);
            }
        }
        public static void Error(string message, Exception ex, string name = "") {
            //logger.Error(ex, message);
            ILogger logger = null;
            if (loggers.Keys.Contains(name)) {
                logger = loggers[name];
            }
            else {
                logger = LogFactory.CreateLogger(name);
                if (logger != null) {
                    loggers.Add(name, logger);
                }
                else {
                    logger = LogFactory.CreateLogger("errorFile");
                }
            }
            if (logger != null) {
                logger.Error($"{message}{ex.StackTrace}");
            }
        }
    }
    internal class LogFactory
    {
        /// <summary>
        /// 通过配置文件配置日志
        /// </summary>
        static LogFactory() {
            var loggerNames = new List<string>() { "HosttoagvTask", "HosttoagvCar", "NDC", "杭奥", "PLC", "API", "OPC" };
            LogManager.Configuration = DefaultConfig(loggerNames);
        }
        public static ILogger CreateLogger(string name) {
            var logger = LogManager.GetLogger(name);
            return logger;
        }
        public static LoggingConfiguration DefaultConfig(List<string> loggerNames) {
            var config = new LoggingConfiguration();
            loggerNames.ForEach(a => {
                var target = new FileTarget();
                target.ArchiveAboveSize = 1024 * 1024 * 5;//每个文件最大5M
                target.ArchiveNumbering = ArchiveNumberingMode.DateAndSequence;
                target.ArchiveFileName = @"${basedir}/Logs/" + a + "/{####}.txt";
                target.FileName = @"${basedir}/Logs/" + a + "/${shortdate}.txt";//当前文件路径
                target.Layout = @"${longdate} | ${level:uppercase=false:padding=-5} | ${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}";
                config.AddTarget(a, target);
                config.AddRuleForOneLevel(LogLevel.Info, target, a);
            });
            // 添加target-console
            var consoleTarget = new ColoredConsoleTarget();
            consoleTarget.Layout = @"${longdate} | ${level:uppercase=false:padding=-5} | ${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}";
            config.AddTarget("console", consoleTarget);
            config.AddRule(LogLevel.Debug, LogLevel.Fatal, consoleTarget);
            //添加target-info
            var infoFileTarget = new FileTarget();
            infoFileTarget.ArchiveAboveSize = 1024 * 1024 * 5;//每个文件最大5M
            infoFileTarget.ArchiveNumbering = ArchiveNumberingMode.DateAndSequence;
            infoFileTarget.ArchiveFileName = @"${basedir}/Logs/Info/{####}.txt";
            infoFileTarget.FileName = @"${basedir}/Logs/Info/${shortdate}.txt";//当前文件路径
            infoFileTarget.Layout = @"${longdate} | ${level:uppercase=false:padding=-5} | ${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}";
            config.AddTarget("infoFile", infoFileTarget);
            config.AddRuleForOneLevel(LogLevel.Info, infoFileTarget);//INFO写在Info文件
            //添加target-err
            var errorFileTarget = new FileTarget();
            errorFileTarget.ArchiveAboveSize = 1024 * 1024 * 5;//每个文件最大5M
            errorFileTarget.ArchiveNumbering = ArchiveNumberingMode.DateAndSequence;
            errorFileTarget.ArchiveFileName = @"${basedir}/Logs/Error/{####}.txt";
            errorFileTarget.FileName = @"${basedir}/Logs/Error/${shortdate}.txt";
            errorFileTarget.Layout = @"${longdate} | ${level:uppercase=false:padding=-5} | ${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}";
            config.AddTarget("errorFile", errorFileTarget);
            config.AddRule(LogLevel.Error, LogLevel.Fatal, errorFileTarget);
            return config;
        }
    }
}
Helpers/ResultHelper.cs
New file
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static HH.WCS.Mobox3.AnGang.Dtos.Response.MoboxResponse;
namespace HH.WCS.Mobox3.AnGang.Helpers {
    public class ResultHelper {
        public static SimpleResult BuildSimpleResult(int code, string message, bool pringLog = true) {
            if (pringLog) {
                LogHelper.Info(message);
            }
            return new SimpleResult { Code = code, Message = message };
        }
    }
}
Helpers/SYSHelper.cs
New file
@@ -0,0 +1,45 @@
using HH.WCS.Mobox3.AnGang.config;
using HH.WCS.Mobox3.AnGang.Helpers;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Helper
{
    internal class SYSHelper
    {
        private static object locker = new object();
        internal static int GetSerialNumber(string snType, string prefix) {
            int result = 0;
            lock (locker) {
                var db = DbHelper.GetDbClient();
                var sId = db.Queryable<OI_SYS_MAXID>().Where(a => a.CN_S_TYPE.Trim() == snType && a.CN_S_PRE.Trim() == prefix).First();
                if (sId != null) {
                    sId.CN_N_MAX++;
                    if (db.Ado.ExecuteCommand($"update OI_SYS_MAXID set CN_N_MAX={sId.CN_N_MAX} where CN_S_TYPE='{snType}' and CN_S_PRE='{prefix}' ") > 0) {
                        result = sId.CN_N_MAX;
                    }
                }
                else {
                    //插入表
                    sId = new OI_SYS_MAXID { CN_S_TYPE = snType, CN_S_PRE = prefix, CN_N_MAX = 1 };
                    result = db.Insertable<OI_SYS_MAXID>(sId).ExecuteCommand() > 0 ? 1 : 0;
                }
            }
            return result;
        }
        [SugarTable("dbo.OI_SYS_MAXID")]
        public class OI_SYS_MAXID
        {
            public string CN_S_TYPE { get; set; }
            public string CN_S_PRE { get; set; }
            public int CN_N_MAX { get; set; }
        }
    }
}
Helpers/TaskHelper.cs
New file
@@ -0,0 +1,218 @@
using HH.WCS.Mobox3.AnGang.ServiceCore;
using HH.WCS.Mobox3.AnGang.Dispatch;
using HH.WCS.Mobox3.AnGang.config;
using HH.WCS.Mobox3.AnGang.Helper;
using Newtonsoft.Json;
using Opc.Ua;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using static HH.WCS.Mobox3.AnGang.Controllers.ApiModel;
using Org.BouncyCastle.Crypto;
using HH.WCS.Mobox3.AnGang.Devices;
using HH.WCS.Mobox3.AnGang.Models;
namespace HH.WCS.Mobox3.AnGang.process {
    internal class TaskHelper {
        #region 任务相关
        //--------------------------------------------------任务相关--------------------------------------------------
        /// <summary>
        /// 取货卸货完成,缓存位状态更新
        /// </summary>
        /// <param name="mst"></param>
        /// <param name="load"></param>
        internal static void CacheBitUpdate(TN_Task mst, bool load) {
            var trayCarryCount = mst.N_CNTR_COUNT > 0 ? mst.N_CNTR_COUNT : 1;
            if (load) {
                Console.WriteLine($"任务{mst.S_CODE} 货位{mst.S_START_LOC}取货完成,起点解绑容器{mst.S_CNTR_CODE}");
                LogHelper.Info($"任务{mst.S_CODE} 货位{mst.S_START_LOC}取货完成,起点解绑容器{mst.S_CNTR_CODE}");
                LocationHelper.UnBindingLoc(mst.S_START_LOC, mst.S_CNTR_CODE.Split(',').ToList());
            }
            else {
                Console.WriteLine($"任务{mst.S_CODE} 货位{mst.S_END_LOC}卸货完成,终点绑定容器{mst.S_CNTR_CODE}");
                LogHelper.Info($"任务{mst.S_CODE} 货位{mst.S_END_LOC}卸货完成,终点绑定容器{mst.S_CNTR_CODE}");
                LocationHelper.BindingLoc(mst.S_END_LOC, mst.S_CNTR_CODE.Split(',').ToList());
            }
        }
        /// <summary>
        /// 任务取消,缓存位状态更新
        /// </summary>
        /// <param name="mst"></param>
        internal static void CacheBitCancelUpdate(TN_Task mst) {
            //任务取消,取货完成前的,起点的loadingCount和终点unLoadingCount都清除,取货完成的只处理终点
            if (WCSHelper.CheckActionRecordExist(mst.S_CODE, 4)) {
                //根据客户现场要求,如果取货完成任务失败人工拉到终点,我们就当卸货完成处理;如果是人工拉走到其它区域,我们就解锁终点,删除托盘。
                //终点绑定
                CacheBitUpdate(mst, false);
                LocationHelper.UnLockLoc(mst.S_END_LOC);
            }
            else {
                //起点终点解锁
                LocationHelper.UnLockLoc(mst.S_START_LOC);
                LocationHelper.UnLockLoc(mst.S_END_LOC);
            }
        }
        /// <summary>
        /// 任务状态更新处理
        /// </summary>
        /// <param name="mst"></param>
        /// <param name="state"></param>
        internal static void OperateStatus(TN_Task mst, int state) {
            if (state == 4)
            {
                CacheBitUpdate(mst, true);
            }
            if (state == 6)//卸货完成
            {
                CacheBitUpdate(mst, false);
            }
            if (state == 7) {
                CacheBitCancelUpdate(mst);
            }
        }
        /// <summary>
        /// 安全请求
        /// </summary>
        /// <param name="no"></param>
        /// <param name="state"></param>
        /// <param name="forkliftNo"></param>
        /// <param name="extData"></param>
        internal static void OperateReq(string no, int state, string forkliftNo, string extData = "")
        {
            if (state == 1101)
            {
                //请求取货,
            }
            if (state == 1102)
            {
                //请求卸货,
                //根据终点判断,是cb02的入口,判断内存中状态(要状态时间),允许卸货,通知agv改参数
                var dic = new Dictionary<string, string>();
                //< Req >< Order No = 'TN2302020002' ParamNo = '18' Param1 = '12' /></ Req >
                dic.Add("No", no);
                dic.Add("ParamNo", "8");
                dic.Add("Param1", "1");
                NDC.ChangeOrder(dic);
                //改完参数车子就会自己卸货
            }
            if (state == 1103)
            {
                //大铁框叉走以后通知,我们要通知输送线
            }
        }
        private static object locLocker = new object();
       /// <summary>
        /// 推送任务
        /// </summary>
        /// <param name="mst"></param>
        internal static bool SendTask(TN_Task mst)
        {
            var result = false;
            var start = "0"; var end = "0";
            var taskType = mst.S_TYPE.Trim();
            if (mst.N_B_STATE == 0) {
                if (mst.N_SCHEDULE_TYPE == 1)//通过NDC,hosttoagv调度设备
                {
                    start = LocationHelper.GetAgvSite(mst.S_START_LOC);
                    end = LocationHelper.GetAgvSite(mst.S_END_LOC);
                    if (mst.S_TYPE == "空托下线堆叠")
                    {
                        end = LocationHelper.GetAgvSite(mst.S_END_LOC,true);
                    }
                    LogHelper.Info($"NDC推送任务 {mst.S_CODE};" + "start=" + start + "end= " + end);
                    var startLoc = LocationHelper.GetLoc(mst.S_START_LOC);
                    var endLoc = LocationHelper.GetLoc(mst.S_END_LOC);
                    var dic = new List<param>();
                    dic.Add(new param() { name = "IKey", value = "IKey" });
                    dic.Add(new param() { name = "From", value = start.ToString() });
                    dic.Add(new param() { name = "To", value = end.ToString() });
                    dic.Add(new param() { name = "FUNC", value = startLoc.N_LAYER.ToString() });
                    dic.Add(new param() { name = "Ctype", value = "0" });
                    if (mst.S_TYPE == "余料下线入库" || mst.S_TYPE == "人工拆盘入库")
                    {
                        dic.Add(new param() { name = "DATA", value = "1024" });
                    }
                    else
                    {
                        dic.Add(new param() { name = "DATA", value = "0" });
                    }
                    var res = NDCApi.AddOrderNew(1, 1, mst.S_CODE, dic);//添加新命令
                    if (res != null && (res.err_code == 0 || res.err_code == 50009))
                    {
                        //推送成功,修改任务优先级
                        mst.N_B_STATE = 1;
                        mst.S_B_STATE = TN_Task.GetStateStr(1);
                        WCSHelper.UpdateStatus(mst);//更新任务状态
                        result = true;
                        LogHelper.Info($"NDC推送任务成功 {mst.S_CODE}start= {mst.S_START_LOC} + end = {mst.S_END_LOC}");
                    }
                    else
                    {
                        LogHelper.Info($"NDC推送任务失败 {mst.S_CODE};Res:" + JsonConvert.SerializeObject(res));
                    }
                }
                else if (mst.N_SCHEDULE_TYPE == 5)//通过杭奥调度设备
                {
                    //调第三方接口
                    var model = new HanAo.TaskInfoModel
                    {
                        requestPk = mst.S_CODE,
                        frmPos = mst.S_START_LOC,
                        toPos = mst.S_END_LOC,
                        trkType = mst.S_OP_NAME == "入库" ? "1" : "2",
                        contNo = mst.S_CNTR_CODE
                    };
                    if (HanAo.CreateOrder(model)) {
                        mst.N_B_STATE = 1;
                        WCSHelper.UpdateStatus(mst);
                        LogHelper.Info($"杭奥推送任务成功 {mst.S_CODE};" + "start=" + model.frmPos + "end= " + model.toPos);
                    }
                    else
                    {
                        LogHelper.Info($"杭奥推送任务失败 {mst.S_CODE};" + JsonConvert.SerializeObject(model));
                    }
                }
                else if (mst.N_SCHEDULE_TYPE == 3) //通过国自调度设备
                {
                    var code = GZRobot.CreateOrder(mst.S_CODE, mst.N_PRIORITY, JsonConvert.SerializeObject(new { src = mst.S_START_LOC, dst = mst.S_END_LOC }), "p2p");
                    if (code > 0) {
                        //更新任务状态
                        mst.N_B_STATE = 1;
                        mst.S_EQ_TASK_CODE = code.ToString();
                        WCSHelper.UpdateStatus(mst);
                        WCSHelper.UpdateEQNo(mst);
                        LogHelper.Info($"国自推送任务成功 {mst.S_CODE};" + "start=" + mst.S_START_LOC + "end= " + mst.S_END_LOC);
                    }
                    else
                    {
                        LogHelper.Info($"国自推送任务失败 {mst.S_CODE};" + JsonConvert.SerializeObject(mst));
                    }
                }
            }
            return result;
        }
        #endregion
    }
}
Helpers/WCSHelper.cs
New file
@@ -0,0 +1,240 @@
using HH.WCS.Mobox3.AnGang.Models;
using HH.WCS.Mobox3.AnGang.config;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HH.WCS.Mobox3.AnGang.Helpers;
namespace HH.WCS.Mobox3.AnGang.Helper {
    internal class WCSHelper {
        internal static string GenerateTaskNo() {
            var id = SYSHelper.GetSerialNumber("任务号", "TN");
            var date = DateTime.Now.ToString("yyMMdd");
            return $"TN{date}{id.ToString().PadLeft(4, '0')}";
        }
        internal static bool UpdateStatus(TN_Task task, string status)
        {
            var res = false;
            var db = DbHelper.GetDbClient();
            task.S_B_STATE = status;
            res = db.Updateable(task).UpdateColumns(it => new { it.S_B_STATE }).ExecuteCommand()>0;
            return res;
        }
        internal static bool UpdateStatus(TN_Task task) {
            var res = false;
            var db = DbHelper.GetDbClient();
            task.S_B_STATE = TN_Task.GetStateStr(task.N_B_STATE);
            task.T_MODIFY = DateTime.Now;
            db.Updateable(task).UpdateColumns(it => new { it.N_B_STATE, it.S_B_STATE, it.T_MODIFY }).ExecuteCommand();
            return res;
        }
        internal static bool UpdateEQNo(TN_Task task) {
            var res = false;
            var db = DbHelper.GetDbClient();
            task.T_MODIFY = DateTime.Now;
            db.Updateable(task).UpdateColumns(it => new { it.S_EQ_TASK_CODE, it.T_MODIFY }).ExecuteCommand();
            return res;
        }
        internal static TN_Task GetTask(string no) {
            var db = DbHelper.GetDbClient();
            var task = db.Queryable<TN_Task>().Where(a => a.S_CODE == no).First();
            return task;
        }
        /// <summary>
        /// 创建搬送任务
        /// </summary>
        /// <param name="no">编号</param>
        /// <param name="from">起点</param>
        /// <param name="to">终点</param>
        /// <param name="taskType">任务类型</param>
        /// <param name="pri">优先级</param>
        /// <param name="cntrInfo">容器编码</param>
        /// <returns></returns>
        internal static bool CreateTask(string from, string to, string taskType, int pri, string cntrInfo)
        {
            var fromLoc = LocationHelper.GetLocation(from);
            var endLoc = LocationHelper.GetLocation(to);
            TN_Task TN_Task = new TN_Task()
            {
                S_CODE = GenerateTaskNo(),
                S_START_AREA = fromLoc.S_AREA_CODE,
                S_END_AREA = endLoc?.S_AREA_CODE ?? "", // 如果为null返回空字符串
                S_START_LOC = from,
                S_END_LOC = to,
                S_TYPE = taskType,
                N_PRIORITY = pri,
                N_SCHEDULE_TYPE = 3, // 国自
                N_B_STATE = 0,
                S_CNTR_CODE = cntrInfo,
            };
            var log = JsonConvert.SerializeObject(TN_Task);
            var db = DbHelper.GetDbClient();
            var res = db.Insertable(TN_Task).ExecuteCommand() > 0;
            if (res)
            {
                LogHelper.Info($"插入任务成功,{log}");
            }
            else
            {
                LogHelper.Info($"插入任务失败,{log}");
            }
            return res;
        }
        /// <summary>
        /// 根据终点Area创建搬送任务
        /// </summary>
        /// <param name="from"></param>
        /// <param name="toArea"></param>
        /// <param name="taskType"></param>
        /// <param name="pri"></param>
        /// <param name="cntrInfo"></param>
        /// <returns></returns>
        internal static bool CreateTaskWithArea(string from, string toArea, string taskType, int pri, string cntrInfo) {
            var fromLoc = LocationHelper.GetLocation(from);
            //var endLoc = LocationHelper.GetLocation(to);
            TN_Task TN_Task = new TN_Task() {
                S_CODE = GenerateTaskNo(),
                S_START_AREA = fromLoc.S_AREA_CODE,
                S_END_AREA = toArea,
                S_START_LOC = from,
                S_END_LOC = "", // 不指定终点货位
                S_TYPE = taskType,
                N_PRIORITY = pri,
                N_SCHEDULE_TYPE = 3, // 国自
                N_B_STATE = 0,
                S_CNTR_CODE = cntrInfo,
            };
            var log = JsonConvert.SerializeObject(TN_Task);
            var db = DbHelper.GetDbClient();
            var res = db.Insertable(TN_Task).ExecuteCommand() > 0;
            if (res) {
                LogHelper.Info($"插入任务成功,{log}");
            }
            else {
                LogHelper.Info($"插入任务失败,{log}");
            }
            return res;
        }
        public static bool CreateTask(List<CreateTasks> modes)
        {
            if (modes != null && modes.Count > 0)
            {
                List<TN_Task> tN_Tasks = new List<TN_Task>();
                foreach (var item in modes)
                {
                    var fromLoc = LocationHelper.GetLocation(item.from);
                    var endLoc = LocationHelper.GetLocation(item.to);
                    tN_Tasks.Add(new TN_Task()
                    {
                        S_CODE = GenerateTaskNo(),
                        S_START_AREA = fromLoc.S_AREA_CODE,
                        S_END_AREA = endLoc.S_AREA_CODE,
                        S_START_LOC = item.from,
                        S_END_LOC = item.to,
                        S_TYPE = item.taskType,
                        N_PRIORITY = item.pri,
                        N_SCHEDULE_TYPE = 3, // 国自
                        N_B_STATE = 0,
                        S_CNTR_CODE = item.cntrInfo,
                    });
                }
                var log = JsonConvert.SerializeObject(tN_Tasks);
                var db = DbHelper.GetDbClient();
                var res = db.Insertable<TN_Task>(tN_Tasks).ExecuteCommand() > 0;
                if (res)
                {
                    LogHelper.Info($"插入任务成功,{log}");
                }
                else
                {
                    LogHelper.Info($"插入任务失败,{log}");
                }
                return res;
            }
            return false;
        }
        internal static bool CheckActionRecordExist(string no, int code) {
            var db = DbHelper.GetDbClient();
            return db.Queryable<TN_Task_Action>().Count(a => a.S_TASK_CODE == no && a.N_ACTION_CODE == code) > 0;
        }
        internal static void Begin(TN_Task task, string forklift_no)
        {
            var db = DbHelper.GetDbClient();
            if (task != null)
            {
                if (task.N_B_STATE == 1)
                {
                    task.N_B_STATE = 2;
                    task.S_B_STATE = TN_Task.GetStateStr(task.N_B_STATE);
                    task.T_START_TIME = System.DateTime.Now;
                    task.S_EQ_NO = forklift_no;
                    db.Updateable(task).UpdateColumns(it => new { it.N_B_STATE, it.S_B_STATE, it.T_START_TIME, it.S_EQ_NO }).ExecuteCommand();
                }
            }
        }
        internal static void End(TN_Task task) {
            var db = DbHelper.GetDbClient();
            if (task != null) {
                task.N_B_STATE = 3;
                task.S_B_STATE = TN_Task.GetStateStr(task.N_B_STATE);
                task.T_END_TIME = DateTime.Now;
                db.Updateable(task).UpdateColumns(it => new { it.N_B_STATE, it.S_B_STATE, it.T_END_TIME }).ExecuteCommand();
            }
        }
        internal static void Fail(TN_Task task) {
            var db = DbHelper.GetDbClient();
            if (task != null) {
                //判断有没有取货完成,没有就变成失败。有取货完成默认完成了(跟据项目而定,有些项目人工拉走了也没有放到终点)。
                task.N_B_STATE = 4;
                task.S_B_STATE = TN_Task.GetStateStr(task.N_B_STATE);
                db.Updateable(task).UpdateColumns(it => new { it.N_B_STATE, it.S_B_STATE }).ExecuteCommand();
            }
        }
        internal static bool AddActionRecord(string no, int state, string forkliftNo, string extData)
        {
            var db = DbHelper.GetDbClient();
            var action = new TN_Task_Action()
            {
                N_ACTION_CODE = state,
                S_TASK_CODE = no,
                S_EQ_CODE = forkliftNo,
                S_EQ_TYPE = "agv",
                S_DATA = extData
            };
            return db.Insertable(action).ExecuteCommand() > 0;
        }
        internal static List<TN_Task> GetWaitingTaskList() {
            var db = DbHelper.GetDbClient();
            return db.Queryable<TN_Task>().Where(a => a.N_B_STATE == 0 && (a.S_B_STATE == "等待" || a.S_B_STATE == "待推送")).ToList();
        }
    }
    public class CreateTasks
    {
        public string from { set; get; }
        public string to { set; get; }
        public string taskType { set; get; }
        public int pri { set; get; }
        public string cntrInfo { set; get; }
    }
}
Helpers/WMSHelper.cs
New file
@@ -0,0 +1,93 @@
using HH.WCS.Mobox3.AnGang.Controllers;
using HH.WCS.Mobox3.AnGang.Dispatch;
using HH.WCS.Mobox3.AnGang.Models;
using HH.WCS.Mobox3.AnGang.config;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading.Tasks;
using static HH.WCS.Mobox3.AnGang.Controllers.ApiModel;
using HH.WCS.Mobox3.AnGang.Helpers;
namespace HH.WCS.Mobox3.AnGang.Helper
{
    /// <summary>
    /// wms管到作业
    /// </summary>
    internal class WMSHelper
    {
        /// <summary>
        /// 人工手动PDA取消任务:1=发给AGV取消任务
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult PDACancleTask(CancleTaskInfo model)
        {
            SimpleResult simpleResult = new SimpleResult();
            var db = DbHelper.GetDbClient();
            try
            {
                if (model.taskNO.Length > 0)
                {
                    var task = db.Queryable<TN_Task>().First(a => a.S_CODE == model.taskNO);
                    if (task != null && task.S_B_STATE != "完成")
                    {
                        if (NDCApi.CancelOrder(model.taskNO).err_code == 0)
                        {
                            task.S_B_STATE = "错误";
                            task.N_B_STATE = 4;
                            if (db.Updateable<TN_Task>(task).ExecuteCommand() > 0)
                            {
                                simpleResult.resultCode = 0;
                                simpleResult.resultMsg = $"通知AGV取消该任务号,成功,{model.taskNO}";
                                LogHelper.Info(simpleResult.resultMsg);
                                return simpleResult;
                            }
                            else
                            {
                                simpleResult.resultCode = 4;
                                simpleResult.resultMsg = $"更新任务状态信息失败{model.taskNO}";
                                LogHelper.Info(simpleResult.resultMsg);
                                return simpleResult;
                            }
                        }
                        else
                        {
                            simpleResult.resultCode = 1;
                            simpleResult.resultMsg = $"通知AGV取消该任务号,失败,{model.taskNO}";
                            LogHelper.Info(simpleResult.resultMsg);
                            return simpleResult;
                        }
                    }
                    else
                    {
                        simpleResult.resultCode = 2;
                        simpleResult.resultMsg = $"未找到该任务号或该任务号已完成,无需通知AGV取消";
                        LogHelper.Info(simpleResult.resultMsg);
                        return simpleResult;
                    }
                }
                else
                {
                    simpleResult.resultCode = 3;
                    simpleResult.resultMsg = $"人工手动PDA取消任务:1=发给AGV取消任务,参数无效";
                    LogHelper.Info(simpleResult.resultMsg);
                    return simpleResult;
                }
            }
            catch (Exception ex)
            {
                simpleResult.resultCode = -1;
                simpleResult.resultMsg = $"发生了异常{ex.Message}";
                LogHelper.Info(simpleResult.resultMsg);
                return simpleResult;
            }
        }
    }
}
Models/BaseModel.cs
New file
@@ -0,0 +1,42 @@
using System;
using SqlSugar;
namespace HH.WCS.Mobox3.AnGang.Models {
    /// <summary>
    /// 【框架】模板抽象类:基本表数据模型
    /// </summary>
    public abstract class BaseModel {
        /// <summary>
        /// 唯一识别码(底层主键)
        /// </summary>
        [SugarColumn(IsPrimaryKey = true)]
        public string S_ID { get; set; } = Guid.NewGuid().ToString("D");
        /// <summary>
        /// 创建人 ID
        /// </summary>
        public string S_CREATOR_ID { get; set; } = "sa";
        /// <summary>
        /// 创建人名称
        /// </summary>
        public string S_CREATOR_NAME { get; set; } = "超级用户";
        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime T_CREATE { get; set; } = DateTime.Now;
        /// <summary>
        /// 修改时间
        /// </summary>
        public DateTime T_MODIFY { get; set; } = DateTime.Now;
        /// <summary>
        /// 数据状态:编辑、定版
        /// </summary>
        public string S_STATE { get; set; } = "编辑";
    }
}
Models/TN_CAR_IN.cs
New file
@@ -0,0 +1,19 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Models
{
    /// <summary>
    /// 容器生产车数关联子表
    /// </summary>
    [SugarTable("TN_CAR_IN")]
    public class TN_CAR_IN : BaseModel {
        public string S_CNTR_CODE { set; get; }//容器号
        public string S_CAR_CODE { set; get; }//生产车数,逗号分割
        public string S_B_STATE { set; get; }//状态
    }
}
Models/TN_CG_Detail.cs
New file
@@ -0,0 +1,42 @@
using SqlSugar;
namespace HH.WCS.Mobox3.AnGang.Models {
    /// <summary>
    /// 物料-容器 关系表
    /// </summary>
    /// <remarks>
    /// CG = Cargo Goods 货物商品
    /// </remarks>
    [SugarTable("TN_CG_Detail")]
    public class TN_CG_Detail : BaseModel
    {
        /// <summary>
        /// 货品 ID
        /// </summary>
        public string S_CG_ID { get; set; }
        public string S_CAR_CODE { get; set; }//车号
        public string S_CNTR_CODE { get; set; }//容器编码
        public string S_ITEM_CODE { get; set; }//货品编码
        public string S_ITEM_SPEC { get; set; }//货品规格
        /// <summary>
        /// 货品状态:0合格 1待检 2不合格 3正在检验;下线即待检
        /// </summary>
        public string S_ITEM_STATE { get; set; }
        /// <summary>
        /// 货品状态_字典:0合格 1待检 2不合格 3正在检验;下线即待检
        /// </summary>
        public int N_ITEM_STATE { get; set; }
        public string S_BATCH_NO { get; set; }//批次号
        public float F_QTY { get; set; }//数量
        public string S_SPE { get; set; }//规格
    }
}
Models/TN_Container.cs
New file
@@ -0,0 +1,15 @@
using SqlSugar;
using System.Collections.Generic;
namespace HH.WCS.Mobox3.AnGang.Models {
    [SugarTable("TN_Container")]
    public class TN_Container : BaseModel {
        public string S_CODE { get; set; }
        public int N_DETAIL_COUNT { get; set; }
        [SugarColumn(IsIgnore = true)]
        [Navigate(NavigateType.OneToMany, nameof(TN_CG_Detail.S_CNTR_CODE), nameof(S_CODE))]
        public List<TN_CG_Detail> CntrItemRels { get; set; }
    }
}
Models/TN_Loc_Container.cs
New file
@@ -0,0 +1,20 @@
using SqlSugar;
using System.Collections.Generic;
namespace HH.WCS.Mobox3.AnGang.Models {
    //TN_Loc_Container
    //LocCntrRel
    [SugarTable("TN_Loc_Container")]
    public class TN_Loc_Container : BaseModel
    {
        public string S_LOC_CODE { get; set; }
        public string S_CNTR_CODE { get; set; }
        [Navigate(NavigateType.OneToMany, nameof(TN_CG_Detail.S_CNTR_CODE))]
        public List<TN_CG_Detail> CntrItemRels { get; set; }
        [Navigate(NavigateType.OneToOne, nameof(S_CNTR_CODE))]
        public TN_Container Container { get; set; }
    }
}
Models/TN_Location.cs
New file
@@ -0,0 +1,87 @@
using SqlSugar;
using System.Collections.Generic;
namespace HH.WCS.Mobox3.AnGang.Models {
    [SugarTable("TN_Location")]
    public class TN_Location : BaseModel {
        /// <summary>
        /// 货位 ID
        /// </summary>
        public string S_CODE { get; set; }
        /// <summary>
        /// 货位名称
        /// </summary>
        public string S_NAME { get; set; }
        /// <summary>
        /// 货位所在区域 ID
        /// </summary>
        public string S_AREA_CODE { get; set; }
        /// <summary>
        /// 国自 AGV 对应的库位名称
        /// </summary>
        public string S_AGV_SITE { get; set; }
        /// <summary>
        /// 货位容量
        /// </summary>
        public int N_CAPACITY { get; set; } = 1;
        /// <summary>
        /// 货位当前容器数量
        /// </summary>
        public int N_CURRENT_NUM { get; set; } = 0;
        /// <summary>
        /// 货位的层数
        /// </summary>
        public int N_LAYER { get; set; } = 1;
        /// <summary>
        /// 0无 1入库锁 2出库锁 3其它锁
        /// </summary>
        public int N_LOCK_STATE { get; set; } = 0;
        /// <summary>
        /// 0"无" 1"入库锁" 2"出库锁" 3"其它锁"
        /// </summary>
        public string S_LOCK_STATE { get; set; } = "无";
        /// <summary>
        /// 货位是否启用:Y启用
        /// </summary>
        public string C_ENABLE { get; set; } = "Y";
        /// <summary>
        /// 锁的来源-任务号
        /// </summary>
        public string S_LOCK_OP { get; set; }
        [Navigate(NavigateType.OneToMany, nameof(TN_Loc_Container.S_LOC_CODE))]
        public List<TN_Loc_Container> LocCntrRels { get; set; }
        public static string GetLockStateStr(int lockState) {
            var str = "";
            switch (lockState) {
                case 0: str = "无"; break;
                case 1: str = "入库锁"; break;
                case 2: str = "出库锁"; break;
                case 3: str = "其它锁"; break;
            }
            return str;
        }
        /// <summary>
        /// 货架编码
        /// </summary>
        public string S_SHELF_CODE { get; set; }
        /// <summary>
        /// 货位高度
        /// </summary>
        public int N_HEIGHT { get; set; }
    }
}
Models/TN_Task.cs
New file
@@ -0,0 +1,61 @@
using SqlSugar;
using System;
namespace HH.WCS.Mobox3.AnGang.Models {
    [SugarTable("TN_Task")]
    public class TN_Task : BaseModel {
        public string S_START_AREA { get; set; }
        public string S_END_AREA { get; set; }
        public string S_START_LOC { get; set; }
        public string S_END_LOC { get; set; }
        public DateTime? T_START_TIME { get; set; }
        public DateTime? T_END_TIME { get; set; }
        /// <summary>
        /// AGV 车号
        /// </summary>
        public string S_EQ_NO { get; set; }
        public string S_TYPE { get; set; }
        public string S_B_STATE { get; set; } = "等待";
        /// <summary>
        /// 0等待  1已推送  2执行  3完成    4错误
        /// </summary>
        public int N_B_STATE { get; set; }
        /// <summary>
        ///0无 1NDC 2天目 3国自 4PLC 5杭奥
        /// </summary>
        public int N_SCHEDULE_TYPE { get; set; }
        public int N_PRIORITY { get; set; }
        public string S_CODE { get; set; }
        public string S_EQ_TASK_CODE { get; set; }
        public string S_CNTR_CODE { get; set; }
        public string S_OP_NAME { get; set; }
        public int N_START_LAYER { get; internal set; }
        public int N_END_LAYER { get; internal set; }
        public int N_CNTR_COUNT { get; internal set; }
        /// <summary>
        /// 任务的货物重量
        /// </summary>
        public float F_WEIGHT { get; set; }
        internal static string GetStateStr(int state) {
            //0等待      1已推送        2执行    3完成    4错误
            var status = "";
            switch (state) {
                case 0: status = "等待"; break;
                case 1: status = "已推送"; break;
                case 2: status = "执行"; break;
                case 3: status = "完成"; break;
                case 4: status = "错误"; break;
            }
            return status;
        }
    }
}
Models/TN_Task_Action.cs
New file
@@ -0,0 +1,19 @@
using SqlSugar;
namespace HH.WCS.Mobox3.AnGang.Models {
    [SugarTable("TN_Task_Action")]
    public  class TN_Task_Action : BaseModel
    {
        /// <summary>
        /// 小车类型 e.g. "agv"
        /// </summary>
        public string S_EQ_TYPE { get; set; }
        public string S_DATA { get; set; }
        public string S_TASK_CODE { get; set; }
        public string S_EQ_CODE { get; set; }
        public int N_ACTION_CODE { get; set; }
    }
}
Models/TN_WorkOrder.cs
New file
@@ -0,0 +1,17 @@
using SqlSugar;
namespace HH.WCS.Mobox3.AnGang.Models {
    /// <summary>
    /// 生产工单
    /// </summary>
    [SugarTable("TN_WorkOrder")]
    public class TN_WorkOrder : BaseModel
    {
        public string S_WORK_NO { get; set; }//工单号,主键
        public string S_B_STATE { get; set; }//工单状态,新建-开启-暂停-完成
        public string S_ITEM_CODE { get; set; }//物料编码
        public string S_BATCH_CODE { get; set; }//批次号
        public string S_ITEM_SPEC { get; set; }//规格
        public string S_LINE_NO { get; set; }//产线,不能为null
    }
}
Models/Table.cs
New file
@@ -0,0 +1,26 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Models.Basic {
    /// <summary>
    /// 基本表数据类
    /// </summary>
    public class BaseModel {
        [SugarColumn(IsPrimaryKey = true)]
        public string S_ID { get; set; } = Guid.NewGuid().ToString("D");
        public string S_CREATOR_ID { get; set; } = "sa";
        public string S_CREATOR_NAME { get; set; } = "超级用户";
        public DateTime T_CREATE { get; set; } = DateTime.Now;
        public DateTime T_MODIFY { get; set; } = DateTime.Now;
        /// <summary>
        /// 编辑、定版
        /// </summary>
        public string S_STATE { get; set; } = "编辑";
    }
}
Program.cs
New file
@@ -0,0 +1,163 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using HH.WCS.Mobox3.AnGang.AppStart;
using HH.WCS.Mobox3.AnGang.Devices;
using Microsoft.Owin.Hosting;
using Topshelf;
namespace HH.WCS.Mobox3.AnGang {
    internal class Program
    {
        static void Main(string[] args)
        {
            //基础设置信息初始化
            Settings.Init();
            //1.0 开启api
            Startup();
            //2.0 开启tcp
            StartTcp();
            //3.0 开启S7
            StartS7();
            //4.0 开启Modbus
            StartModbus();
            //5.0 开启线程
            var rc = HostFactory.Run(x =>
            {
                x.Service<WorkThread>(s =>
                {
                    s.ConstructUsing(name => new WorkThread());
                    s.WhenStarted(tc => tc.Start());
                    s.WhenStopped(tc => tc.Stop());
                });
                x.RunAsLocalSystem();
                x.SetDescription("hh123");
                x.SetDisplayName("hh123.wms");
                x.SetServiceName("hh123.wms");
            });
            var exitCode = (int)Convert.ChangeType(rc, rc.GetTypeCode());
            Environment.ExitCode = exitCode;
        }
        /// <summary>
        /// 开启API协议通讯
        /// </summary>
        private static void Startup()
        {
            Console.WriteLine("Startup ApiController");
            Task.Run(() =>
            {
                var url = Settings.Config.WebApiUrl;
                Console.WriteLine(url);
                using (WebApp.Start<Startup>(url))
                {
                    Console.WriteLine("API,Running on {0}", url);
                    Console.ReadLine();
                }
            });
        }
        /// <summary>
        /// 开启TCP协议通讯,服务端
        /// </summary>
        private static void StartTcp()
        {
            var tcpServerIP = Settings.Config.TCPServerIP;
            var tcpServerPort = Settings.Config.TCPServerPort;
            new TcpServer(tcpServerIP, tcpServerPort);
        }
        /// <summary>
        /// 开启S7协议通讯
        /// </summary>
        private static void StartS7()
        {
            //所有的S7设备
            //var allPLCDevice = Settings.ProductionLines;
            //if (allPLCDevice.Count > 0)
            //{
            //    foreach (var item in allPLCDevice)
            //    {
            //        new S7Helper(item.ProductionLine_IP, (short)item.ProductionLine_Rack, (short)item.ProductionLine_Slot);
            //        Console.WriteLine("S7ProductionLineHelper," + item.ProductionLine_IP);
            //    }
            //}
            ////称重的S7设备
            //var weightPLCDevice = Settings.WeightDevices;
            //if (weightPLCDevice.Count > 0)
            //{
            //    foreach (var item in weightPLCDevice)
            //    {
            //        new S7Helper(item.WeightDevice_IP, (short)item.WeightDevice_Rack, (short)item.WeightDevice_Slot);
            //        Console.WriteLine("S7WeightDeviceHelper," + item.WeightDevice_Name);
            //    }
            //}
        }
        /// <summary>
        /// 开启Modbus协议通讯
        /// </summary>
        private static void StartModbus()
        {
            //所有的Modbus设备
            //var allPLCDevice = Settings.ProductionLines;
            //if (allPLCDevice.Count > 0) {
            //    foreach (var item in allPLCDevice) {
            //        new ModbusHelper(item.PlcIp, item.PlcPort);
            //        Console.WriteLine("ModbusHelper," + item.PlcIp);
            //    }
            //}
        }
        public class WorkThread
        {
            public void Start()
            {
                List<Task> tasks = new List<Task>();
                // 添加任务推送线程
                //tasks.Add(GetTask(WCSCore.Dispatch));
                ////添加自定义线程
                //tasks.Add(GetTask(Monitor.CheckEmptyCnt));//检测空托盘
                ////根据S7/Modbus协议判断输送线的信号  原材料产线库区=>满托缓存库区,空托缓存库区=>原材料产线库区
                //tasks.Add(GetTask(Monitor.CheckS7Devices));
                Task.WaitAll(tasks.ToArray());
            }
            public void Stop() { Console.WriteLine("work stopped"); }
            private Task GetTask(Action action)
            {
                var task = Task.Run(() =>
                {
                    while (true)
                    {
                        try
                        {
                            action();
                        }
                        catch (Exception ex)
                        {
                            LogHelper.Error(ex.Message, ex);
                        }
                        Thread.Sleep(3000);
                    }
                });
                return task;
            }
        }
    }
}
Properties/AssemblyInfo.cs
New file
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("HH.WCS.Mobox3.DSZSH")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HH.WCS.Mobox3.DSZSH")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("8e589c0d-7d65-474d-8ced-e34e087126a1")]
// 程序集的版本信息由下列四个值组成:
//
//      主版本
//      次版本
//      生成号
//      修订号
//
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
ServiceCore/Monitor.cs
New file
@@ -0,0 +1,171 @@
using HH.WCS.Mobox3.AnGang.Devices;
using HH.WCS.Mobox3.AnGang.process;
using HH.WCS.Mobox3.AnGang.config;
using HH.WCS.Mobox3.AnGang.Helper;
using Newtonsoft.Json;
using Opc.Ua.Client;
using Opc.Ua;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Org.BouncyCastle.Ocsp;
using S7.Net.Types;
using Opc.Ua.Configuration;
using static System.Net.Mime.MediaTypeNames;
using SqlSugar.Extensions;
using static HH.WCS.Mobox3.AnGang.Dispatch.NDC;
using Newtonsoft.Json.Linq;
using HH.WCS.Mobox3.AnGang.Models;
using SqlSugar;
using HH.WCS.Mobox3.AnGang.Controllers;
using HH.WCS.Mobox3.AnGang.Dispatch;
using HH.WCS.Mobox3.AnGang.Consts;
namespace HH.WCS.Mobox3.AnGang.ServiceCore
{
    /// <summary>
    /// 定时轮询任务
    /// </summary>
    public class Monitor
    {
        ///// <summary>
        ///// 空托堆叠入库
        ///// </summary>
        //internal static void CheckEmptyCnt()
        //{
        //    var db = DbHelper.GetDbClient();
        //    try
        //    {
        //        var startLoc = db.Queryable<TN_Location>().
        //        Where(a => a.S_AREA_CODE == Settings.Areas[3] && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.N_CURRENT_NUM == a.N_CAPACITY).
        //        OrderBy(a => a.T_MODIFY, OrderByType.Desc).
        //        First();
        //        if (startLoc == null)
        //        {
        //            LogHelper.Info($"空托堆叠区{Settings.Areas[3]}暂无堆满的空托");
        //            return;
        //        }
        //        var endLoc = db.Queryable<TN_Location>().
        //            Where(a => a.S_AREA_CODE == Settings.Areas[4] && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.N_CURRENT_NUM == 0).
        //            OrderBy(a => a.N_CURRENT_NUM, OrderByType.Asc).
        //            First();
        //        if (endLoc == null)
        //        {
        //            LogHelper.Info($"未找到合适的终点货位,需满足{Settings.Areas[4]}里有未锁定且当前数量等于0的货位");
        //            return;
        //        }
        //        var cntrList = db.Queryable<TN_Loc_Container>().Where(a => a.S_LOC_CODE == startLoc.S_CODE).OrderBy(a => a.T_CREATE, OrderByType.Asc).ToList();
        //        if (cntrList.Count < 1)
        //        {
        //            LogHelper.Info($"起点{startLoc.S_CODE}未找到货位容器关系信息");
        //            return;
        //        }
        //        string cntrString = "";
        //        for (int i = 0; i < cntrList.Count; i++)
        //        {
        //            if (i == cntrList.Count - 1)//最后一个字符串连接不加逗号
        //            {
        //                cntrString += cntrList[i].S_CNTR_CODE;
        //            }
        //            else
        //            {
        //                cntrString += cntrList[i].S_CNTR_CODE + ",";
        //            }
        //        }
        //        if (WCSHelper.CreateTask(startLoc.S_CODE, endLoc.S_CODE, "空托堆叠入库", 3, cntrString))//创建搬送任务,起点终点容器
        //        {
        //            LocationHelper.LockLoc(startLoc.S_CODE, 2);//起点出库锁,
        //            LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
        //            LogHelper.Info($"生成空托堆叠入库任务成功,容器:{cntrString},起点:{startLoc.S_CODE}");
        //        }
        //        else
        //        {
        //            LogHelper.Info($"生成空托堆叠入库任务失败,容器:{cntrString},起点:{startLoc.S_CODE}");
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        LogHelper.Info($"空托堆叠入库异常:{ex.Message}");
        //    }
        //}
    }
    /// <summary>
    /// 与S7设备交互时的model
    /// </summary>
    public class CheckDeciveModel
    {
        /// <summary>
        /// 心跳
        /// </summary>
        public int Heart { set; get; }
        /// <summary>
        /// RFID,是容器是托盘
        /// </summary>
        public string RfidData { set; get; }
        /// <summary>
        /// 允许上下料  0=无任务,11=上料,21=下料,(请求AGV工作)
        /// </summary>
        public int AgvAllow { set; get; }
        /// <summary>
        /// 任务属性  1 OK,2称重失败,3条码失败,4 RFID读取失败
        /// </summary>
        public int TaskProperties { set; get; }
        /// <summary>
        /// 准备就绪  0=未准备好,1=准备好
        /// </summary>
        public int Ready { set; get; }
        /// <summary>
        /// 载货状态 0=输送线无产品,1=输送线有产品
        /// </summary>
        public int CargoStatus { set; get; }
        /// <summary>
        /// 工位状态 0待机中,1入库方向运行中,2出库方向运行中,3设备故障
        /// </summary>
        public int StationStatus { set; get; }
        /// <summary>
        /// 去向请求 0待机中,1到位请求
        /// </summary>
        public int DestinationRequests { set; get; }
        /// <summary>
        /// 扫码信息 扫码枪反馈信息
        /// </summary>
        public string BarcodeCode { set; get; }
        /// <summary>
        /// 重量
        /// </summary>
        public float Weight { set; get; }
        /// <summary>
        /// 产线地址
        /// </summary>
        public string LineIP { set; get; }
    }
}
ServiceCore/WCSCore.cs
New file
@@ -0,0 +1,205 @@
using HH.WCS.Mobox3.AnGang.Devices;
using HH.WCS.Mobox3.AnGang.Dispatch;
using HH.WCS.Mobox3.AnGang.Models;
using HH.WCS.Mobox3.AnGang.process;
using HH.WCS.Mobox3.AnGang.config;
using HH.WCS.Mobox3.AnGang.Helper;
using Newtonsoft.Json;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static HH.WCS.Mobox3.AnGang.Controllers.ApiModel;
using static HH.WCS.Mobox3.AnGang.Dtos.Response.AgvResponse;
using static HH.WCS.Mobox3.AnGang.Dtos.Request.AgvRequest;
namespace HH.WCS.Mobox3.AnGang.ServiceCore
{
    internal class WCSCore
    {
        public static ReturnResult OperateAgvTaskStatus(AgvTaskState model)
        {
            var result = new ReturnResult();
            try
            {
                switch (model.state) {
                    case 1023:
                    case 1025:
                        break;
                    case 1012:
                        break;
                    case 1004:
                        break;
                    case 1103:
                        break;
                    default:
                        // AGV 执行任务的逻辑处理
                        if (!AgvTaskProcessOk(model)) {
                            // 执行不OK,说明没有找到任务
                            result.ResultCode = 1;
                            result.ResultMsg = $"根据Model.No未找到对应的任务,{model.task_no}";
                            LogHelper.Info(result.ResultMsg, "API");
                            return result;
                        }
                        break;
                }
                result.ResultCode = 0;
                result.ResultMsg = "success";
                LogHelper.Info(result.ResultMsg, "API");
                return result;
            }
            catch(Exception ex)
            {
                result.ResultCode = -1;
                result.ResultMsg = $"发生了异常:{ex.Message}";
                LogHelper.Info(result.ResultMsg, "Error");
                return result;
            }
        }
        /// <summary>
        /// 执行AGV任务,查询不到任务返回false
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        private static bool AgvTaskProcessOk(AgvTaskState model) {
            var TN_Task = WCSHelper.GetTask(model.task_no); // 根据当前model编号查询任务
            if (TN_Task == null) { return false; }
            if (model.state > 7) {
                //安全请求等
                TaskHelper.OperateReq(model.task_no, model.state, model.forklift_no, model.ext_data);
                return true;
            }
            // AGV 任务 134562(7) 状态处理
            switch (model.state) {
                case 1:
                    WCSHelper.Begin(TN_Task, model.forklift_no); // 已推送的任务的状态改成执行
                    break;
                case 3:
                    WCSHelper.UpdateStatus(TN_Task, "开始取货"); // 任务状态改成开始取货
                    break;
                case 4:
                    WCSHelper.UpdateStatus(TN_Task, "取货完成"); // 任务状态改成取货完成
                    TaskHelper.OperateStatus(TN_Task, 4); // 起点容器货位解绑,解锁起点
                    break;
                case 5:
                    WCSHelper.UpdateStatus(TN_Task, "开始卸货"); // 任务状态改成开始卸货
                    break;
                case 6:
                    WCSHelper.UpdateStatus(TN_Task, "卸货完成"); // 任务状态改成卸货完成
                    TaskHelper.OperateStatus(TN_Task, 6); // 终点容器货位绑定,解锁终点
                    break;
                case 2:
                    WCSHelper.End(TN_Task); // 任务状态改成结束
                    break;
                case 7:
                    TaskHelper.OperateStatus(TN_Task, 7); // 异常处理
                    WCSHelper.Fail(TN_Task); // 任务状态改成错误
                    break;
            }
            WCSHelper.AddActionRecord(model.task_no, model.state, model.forklift_no, model.ext_data);
            //调用第三方接口(如果有)TaskProcess.ReportStatus,添加任务动作关系表
            return true;
        }
        /// <summary>
        /// 任务分发,根据调度类型发给不同的调度系统
        /// </summary>
        internal static void Dispatch()
        {
            //查询任务
            //获取所有等待的任务
            var list = WCSHelper.GetWaitingTaskList();
            LogHelper.Info("等待任务信息" + JsonConvert.SerializeObject(list), "API");
            if (list.Count > 0)
            {
                list.ForEach(task =>
                {
                    //使用自定义任务推送
                    TaskHelper.SendTask(task);//调度NDC或杭奥或国自设备
                    //TaskProcess.SendGZTask(task);///调度国自设备
                });
            }
            else
            {
                LogHelper.Info("暂无任务");
            }
        }
        /// <summary>
        /// 空托下线堆叠
        /// </summary>
        /// <param name="tN_Task"></param>
        //public static void EmptyInStackArea(TN_Task tN_Task)
        //{
        //    if (tN_Task.S_TYPE == "满托出库上线")
        //    {
        //        var result = new SimpleResult();
        //        var db = DbHelper.GetDbClient();
        //        try
        //        {
        //            var startLocLists =
        //                db.Queryable<TN_Location>().Where(a => a.S_AREA_CODE == Settings.Areas[6] && a.N_CURRENT_NUM >0 && a.N_LOCK_STATE==0 && a.S_LOCK_STATE == "无").ToList();
        //            if (startLocLists.Count == 0)
        //            {
        //                LogHelper.Info($"人工托盘区暂无已绑定的空托,需要满足:货位数量大于0,未锁定的,属于库区{Settings.Areas[6]}的货位");
        //                return;
        //            }
        //            foreach (var item in startLocLists)
        //            {
        //                //查询符合的未锁定已启用指定货区的当前数量合计后最接近容量的货位,终点
        //                var endLoc = db.Queryable<TN_Location>().
        //                    Where(a => a.N_CURRENT_NUM + item.N_CURRENT_NUM <= a.N_CAPACITY && a.S_AREA_CODE == Settings.Areas[3] && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y").
        //                    OrderBy(a => a.N_CURRENT_NUM + item.N_CURRENT_NUM - a.N_CAPACITY, OrderByType.Desc).First();
        //                if (endLoc == null)
        //                {
        //                    LogHelper.Info($"未找到合适的终点,需要满足:属于{Settings.Areas[3]}的未锁定的容量充足的货位");
        //                    continue;
        //                }
        //                var locCnt = db.Queryable<TN_Loc_Container>().First(a=>a.S_LOC_CODE == item.S_CODE);
        //                if (locCnt == null)
        //                {
        //                    LogHelper.Info($"货位{item.S_CODE}未绑定容器");
        //                    continue;
        //                }
        //                //创建空托下线堆叠任务
        //                if (WCSHelper.CreateTask(item.S_CODE, endLoc.S_CODE, "空托下线堆叠", 3, locCnt.S_CNTR_CODE))//创建搬送任务,起点终点容器
        //                {
        //                    LocationHelper.LockLoc(item.S_CODE, 2);//起点出库锁,
        //                    LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
        //                    LogHelper.Info($"生成空托下线堆叠任务成功,容器号{locCnt.S_CNTR_CODE},起点{item.S_CODE},终点{endLoc.S_CODE}");
        //                }
        //                else
        //                {
        //                    LogHelper.Info($"生成空托下线堆叠任务失败,容器号{locCnt.S_CNTR_CODE},起点{item.S_CODE},终点{endLoc.S_CODE}");
        //                    continue;
        //                }
        //            }
        //        }
        //        catch (Exception ex)
        //        {
        //            LogHelper.Info($"发生了异常:{ex.Message}", "Error");
        //        }
        //    }
        //}
    }
}
ServiceCore/WMSCore.cs
New file
@@ -0,0 +1,15 @@
using HH.WCS.Mobox3.AnGang.Helper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.ServiceCore {
    internal class WMSCore
    {
    }
}
Services/AgvService.cs
New file
@@ -0,0 +1,230 @@
using HH.WCS.Mobox3.AnGang.Helpers;
using HH.WCS.Mobox3.AnGang.Models;
using HH.WCS.Mobox3.AnGang.process;
using HH.WCS.Mobox3.AnGang.config;
using HH.WCS.Mobox3.AnGang.Helper;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static HH.WCS.Mobox3.AnGang.Dtos.Request.AgvRequest;
using static HH.WCS.Mobox3.AnGang.Dtos.Response.AgvResponse;
using HH.WCS.Mobox3.AnGang.Consts;
using HH.WCS.Mobox3.AnGang.Dispatch;
namespace HH.WCS.Mobox3.AnGang.Services {
    public class AgvService {
        public static ReturnResult OperateAgvTaskStatus(AgvTaskState model) {
            var result = new ReturnResult();
            try {
                switch (model.state) {
                    case 1023:
                    case 1025:
                        break;
                    case 1012:
                        break;
                    case 1004:
                        break;
                    case 1103:
                        break;
                    default:
                        // AGV 执行任务的逻辑处理
                        if (!AgvTaskProcessOk(model)) {
                            // 执行不OK,说明没有找到任务
                            result.ResultCode = 1;
                            result.ResultMsg = $"根据Model.No未找到对应的任务,{model.task_no}";
                            LogHelper.Info(result.ResultMsg, "API");
                            return result;
                        }
                        break;
                }
                result.ResultCode = 0;
                result.ResultMsg = "success";
                LogHelper.Info(result.ResultMsg, "API");
                return result;
            }
            catch (Exception ex) {
                result.ResultCode = -1;
                result.ResultMsg = $"发生了异常:+{ex.Message}";
                LogHelper.Info(result.ResultMsg, "Error");
                return result;
            }
        }
        /// <summary>
        /// 执行 AGV 任务,查询不到任务返回 <see langword="false"/>
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static bool AgvTaskProcessOk(AgvTaskState model) {
            var TN_Task = WCSHelper.GetTask(model.task_no); // 根据当前model编号查询任务
            if (TN_Task == null) { return false; }
            if (model.state > 7) {
                //安全请求等
                TaskHelper.OperateReq(model.task_no, model.state, model.forklift_no, model.ext_data);
                return true;
            }
            // AGV 任务 134562(7) 状态处理
            switch (model.state) {
                case AgvStateCode.执行:
                    WCSHelper.Begin(TN_Task, model.forklift_no); // 已推送的任务的状态改成执行
                    break;
                case AgvStateCode.开始取货:
                    WCSHelper.UpdateStatus(TN_Task, "开始取货"); // 任务状态改成开始取货
                    break;
                case AgvStateCode.取货完成:
                    WCSHelper.UpdateStatus(TN_Task, "取货完成"); // 任务状态改成取货完成
                    // TODO 拍照
                    var setEndLocTask = Task.Run(() => {
                        SetEndLoc(TN_Task);
                    });
                    TaskHelper.OperateStatus(TN_Task, 4); // 起点容器货位解绑,解锁起点
                    break;
                case AgvStateCode.开始卸货:
                    WCSHelper.UpdateStatus(TN_Task, "开始卸货"); // 任务状态改成开始卸货
                    break;
                case AgvStateCode.卸货完成:
                    WCSHelper.UpdateStatus(TN_Task, "卸货完成"); // 任务状态改成卸货完成
                    TaskHelper.OperateStatus(TN_Task, 6); // 终点容器货位绑定,解锁终点
                    break;
                case AgvStateCode.完成:
                    WCSHelper.End(TN_Task); // 任务状态改成结束
                    break;
                case AgvStateCode.异常:
                    TaskHelper.OperateStatus(TN_Task, 7); // 异常处理
                    WCSHelper.Fail(TN_Task); // 任务状态改成错误
                    break;
            }
            WCSHelper.AddActionRecord(model.task_no, model.state, model.forklift_no, model.ext_data);
            //调用第三方接口(如果有)TaskProcess.ReportStatus,添加任务动作关系表
            return true;
        }
        public static void SetEndLoc(TN_Task tn_task) {
            // 只要任务为产品入库(PDA),就需要重新指定终点(默认endLoc为"")
            if (tn_task.S_TYPE == "产品入库(PDA)") {
                var db = DbHelper.GetDbClient();
                var endLoc = new TN_Location();
                var data = GZRobot.CustomBuf();
                var weight = float.Parse(data[0].parameter_varchar200_up);
                tn_task.F_WEIGHT= weight;
                // 只当之前指定终点货架后,才尝试计算终点货位,否则交给人工决定
                if (tn_task.S_END_AREA != "") {
                    if (weight > 1500) {
                        // 重量超过1.5t,需要选择1-3层货架
                        endLoc = db.Queryable<TN_Location>().First(a => a.S_SHELF_CODE == tn_task.S_END_AREA && LocationHelper.IsFree(a) && a.N_CURRENT_NUM == 0 && a.N_HEIGHT <= 3);
                    }
                    else if (weight > 0) {
                        // 重量未超过1.5t,在指定货架随便选择1个
                        endLoc = db.Queryable<TN_Location>().First(a => a.S_SHELF_CODE == tn_task.S_END_AREA && LocationHelper.IsFree(a) && a.N_CURRENT_NUM == 0);
                    }
                    else {
                        // 没有接收到重量,或重量出错
                        endLoc = null;
                        LogHelper.Info($"错误的重量信息:{weight}");
                        return;
                    }
                    // 如果没有符合条件的货位,置空,等待PDA重新确定
                    if (endLoc == null) {
                        tn_task.S_END_AREA = "";
                        tn_task.S_END_LOC = "";
                        // 不需要再给GZ AGV传空值,一开始就没给具体货位,只给了Area
                        //var request = new UpdateInteractInfo {
                        //    interaction_info_id = 3, // 更改终点信息
                        //    info_status = "active",
                        //    return_value = "",
                        //};
                        //GZRobot.UpdateInteractInfo(request);
                        using (var trans = db.Ado.UseTran()) {
                            if (db.Updateable<TN_Task>(tn_task).UpdateColumns(it => new { it.S_END_LOC, it.F_WEIGHT })
                                .ExecuteCommand() > 0) {
                                //LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                                trans.CommitTran();
                                LogHelper.Info($"重新计算后没有合适货位,任务 {tn_task.S_CODE} 修改成功,修改终点货架和货位为空");
                            }
                            else {
                                trans.RollbackTran();
                                LogHelper.Info($"重新计算后没有合适货位,任务 {tn_task.S_CODE} 修改失败,修改终点货架和货位为空");
                            }
                        }
                    }
                    else {
                        // 找到合适的货位,推送
                        tn_task.S_END_LOC = endLoc.S_CODE;
                        using (var trans = db.Ado.UseTran()) {
                            if (db.Updateable<TN_Task>(tn_task).UpdateColumns(it => new {it.S_END_LOC, it.F_WEIGHT})
                                .ExecuteCommand() > 0) {
                                LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                                trans.CommitTran();
                                LogHelper.Info($"计算货位成功,任务 {tn_task.S_CODE} 修改成功,终点货架为 {endLoc.S_SHELF_CODE},修改终点位置为 {endLoc.S_CODE}");
                            }
                            else {
                                trans.RollbackTran();
                                LogHelper.Info($"计算货位成功,任务 {tn_task.S_CODE} 修改失败,终点货架为 {endLoc.S_SHELF_CODE},修改终点位置为 {endLoc.S_CODE}");
                            }
                        }
                    }
                }
            }
        }
        public static ReturnResult SafetyInteraction(SafetyInteractionInfo model) {
            var gzResult = new ReturnResult();
            //var db = DbHelper.GetDbClient();
            //ModbusHelper.Relink();
            //var productionLineInfo = Settings.ProductionLines[0];
            //var prodLineDevice = new ProductionLineDevice(productionLineInfo.PlcIp, productionLineInfo.PlcPort);
            //if (!prodLineDevice.LoadDeviceStateOk()) {
            //    LogHelper.Info("加载设备信息失败");
            //}
            //var tn_task = db.Queryable<TN_Task>().First(a => a.S_CODE == model.task_no);
            //if (tn_task == null) {
            //    LogHelper.Info($"任务号 '{model.task_no}' 不存在");
            //}
            //if (prodLineDevice.SystemState == 1
            //    && prodLineDevice.FullOffline == 1 && tn_task.S_TYPE == "成品胶下线-托盘(WMS)") {
            //    if (!prodLineDevice.SetAgvPicking(1)) {
            //        LogHelper.Info("写入输送线 PLC 失败");
            //    }
            //}
            //if (prodLineDevice.SystemState == 1
            //    && prodLineDevice.AllowAgvPlacePallet == 1 && tn_task.S_TYPE == "空托盘上线(WMS)") {
            //    if (!prodLineDevice.SetAgvPlacingPallet(1)) {
            //        LogHelper.Info("写入输送线 PLC 失败");
            //    }
            //}
            //LogHelper.Info(JsonConvert.SerializeObject(prodLineDevice, Formatting.Indented));
            return gzResult;
        }
    }
}
Services/DebugService.cs
New file
@@ -0,0 +1,39 @@
using HH.WCS.Mobox3.AnGang.Models;
using HH.WCS.Mobox3.AnGang.config;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HH.WCS.Mobox3.AnGang.Helpers;
namespace HH.WCS.Mobox3.AnGang.Debug {
    public class DebugService {
        /// <summary>
        /// 初始数据库建立
        /// </summary>
        /// <returns></returns>
        public string CreateDatabase() {
            try {
                var db = DbHelper.GetDbClient();
                db.CodeFirst.InitTables<TN_CG_Detail>();
                db.CodeFirst.InitTables<TN_WorkOrder>();
                db.CodeFirst.InitTables<TN_CAR_IN>();
                //db.CodeFirst.InitTables<SYSHelper.OI_SYS_MAXID>();
                db.CodeFirst.InitTables<TN_Task_Action>();
                db.CodeFirst.InitTables<TN_Task>();
                db.CodeFirst.InitTables<TN_Location>();
                db.CodeFirst.InitTables<TN_Loc_Container>();
            }
            catch (Exception ex) {
                LogHelper.Info($"发生了异常");
                return "初始化数据库错误" + ex.Message;
            }
            return "成功";
        }
    }
}
Services/MoboxService.cs
New file
@@ -0,0 +1,367 @@
using HH.WCS.Mobox3.AnGang.AppStart;
using HH.WCS.Mobox3.AnGang.config;
using HH.WCS.Mobox3.AnGang.Consts;
using HH.WCS.Mobox3.AnGang.Helper;
using HH.WCS.Mobox3.AnGang.Helpers;
using HH.WCS.Mobox3.AnGang.Models;
using Newtonsoft.Json;
using System;
using static HH.WCS.Mobox3.AnGang.Dtos.Request.MoboxRequest;
using static HH.WCS.Mobox3.AnGang.Dtos.Response.MoboxResponse;
using static HH.WCS.Mobox3.AnGang.Helpers.ResultHelper;
namespace HH.WCS.Mobox3.AnGang.Services {
    public class MoboxService {
        /// <summary>
        /// 产品入库(PDA)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult InWarehouse(InWarehouseInfo model) {
            LogHelper.Info("触发API:产品入库(PDA)" + JsonConvert.SerializeObject(model), "API");
            var db = DbHelper.GetDbClient();
            var startLoc = new TN_Location();
            //var endLoc = new TN_Location();
            try {
                // 起点位置必须:为空、无锁、启用、属于收发区域
                startLoc = db.Queryable<TN_Location>().
                    First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_SHELF_CODE == AreaCode.收发货位区);
                if (startLoc == null) {
                    return BuildSimpleResult(1, $"起点位置{model.startLoc}不存在!");
                }
                //if (!LocationHelper.IsStartLocationTransferOk(model.startLoc,
                //    a => a.S_SHELF_CODE == Settings.Areas[0],
                //    out startLoc)) {
                //    return BuildSimpleResult(1, $"起点位置{model.startLoc}不存在!");
                //}
                // 容器 ID 和 物料 ID 未指定,由系统直接生成
                var cntID = Guid.NewGuid().ToString("D");
                var CgId = Guid.NewGuid().ToString("D");
                // 初始是没有绑定信息的,先将起点位置与容器绑定,容器与物料绑定
                var cntLoc = new TN_Loc_Container() {
                    S_LOC_CODE = startLoc.S_CODE,
                    S_CNTR_CODE = cntID,
                };
                var cgCnt = new TN_CG_Detail() {
                    S_ITEM_CODE = CgId,
                    S_CNTR_CODE = cntID,
                };
                var endArea = ""; // 默认终点区域为空
                // 指定货位排号(不能为空、空字符串或空格)
                if (model.endShelf != null && model.endShelf.Trim() != "") {
                    endArea = model.endShelf;
                    // 没有在配置文件找到这个货架号
                    if (!Settings.AreaMap[AreaName.货架区].Contains(endArea)) {
                        return BuildSimpleResult(2, $"货架号 {model.endShelf} 不存在");
                    }
                }
                // 无论是否选择终点货架,都等到称重之后再计算终点货位
                using (var trans = db.Ado.UseTran()) {
                    if (db.Insertable<TN_Loc_Container>(cntLoc).ExecuteCommand() > 0
                        && db.Insertable<TN_CG_Detail>(cgCnt).ExecuteCommand() > 0) {
                        //创建产品入库任务:创建搬送任务,起点终点容器
                        if (WCSHelper.CreateTaskWithArea(startLoc.S_CODE, endArea, "产品入库(PDA)", 3, cntID)) {
                            //如果操作TN_Location会造成死锁
                            LocationHelper.LockLoc(startLoc.S_CODE, 2);//起点出库锁,
                            //LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                            trans.CommitTran();
                            return BuildSimpleResult(0, $"生成 产品入库(PDA) 成功,容器号 {cntID} ,起点 {startLoc.S_CODE} ,终点货架 {endArea} ,终点货位未指定");
                        }
                        else {
                            trans.RollbackTran();
                            return BuildSimpleResult(5, $"生成 产品入库(PDA) 失败,容器号 {cntID} ,起点 {startLoc.S_CODE} ,终点货架 {endArea} ,终点货位未指定");
                        }
                    }
                    else {
                        return BuildSimpleResult(6, $"插入表数据失败");
                    }
                }
            }
            catch (Exception ex) {
                return BuildSimpleResult(1, $"发生了异常:{ex.Message}");
            }
        }
        /// <summary>
        /// PDA选择终点货位
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult SelectLocation(SelectLocationInfo model) {
            LogHelper.Info("触发API:PDA选择终点货位" + JsonConvert.SerializeObject(model), "API");
            var db = DbHelper.GetDbClient();
            try {
                // 任务号存在:终点货架和终点位置为空,且任务为产品入库(PDA)
                //var task = db.Queryable<TN_Task>().First(a => a.S_CODE == model.taskNo && a.S_END_AREA == "" && a.S_END_LOC == "" && a.S_TYPE == "产品入库(PDA)");
                var task = db.Queryable<TN_Task>().First(a => a.S_EQ_NO == model.forklift_no && a.S_END_AREA == "" && a.S_END_LOC == "" && a.S_TYPE == "产品入库(PDA)");
                if (task == null) {
                    //return BuildSimpleResult(2, $"任务号 {model.taskNo} 不存在,或不满足终点货架为空、终点位置为空且为 产品入库(PDA) 任务");
                    return BuildSimpleResult(2, $"小车 '{model.forklift_no}' 当前不存在任务,或不满足终点货架为空、终点位置为空且为 产品入库(PDA) 任务");
                }
                var endLoc = new TN_Location();
                if (task.F_WEIGHT > 1500) {
                    // 重量超过1.5t,需要选择1-3层货架
                    endLoc = db.Queryable<TN_Location>().First(
                        a => a.S_CODE == model.endLoc && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.N_CURRENT_NUM == 0 && a.N_HEIGHT <= 3);
                }
                else {
                    endLoc = db.Queryable<TN_Location>().First(
                        a => a.S_CODE == model.endLoc && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.N_CURRENT_NUM == 0);
                }
                // 没有符合条件的货位
                if (endLoc == null) {
                    return BuildSimpleResult(3, $"货位{model.endLoc}不满足要求:不存在或不满足称重放置要求");
                }
                // 修改任务终点为PDA指定终点
                task.S_END_LOC = endLoc.S_CODE;
                task.S_END_AREA = endLoc.S_SHELF_CODE;
                using (var trans = db.Ado.UseTran()) {
                    if (db.Updateable<TN_Task>(task).ExecuteCommand() > 0) {
                        LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                        trans.CommitTran();
                        return BuildSimpleResult(0, $"任务{task.S_CODE}修改成功,修改终点位置为{endLoc.S_CODE}");
                    }
                    else {
                        trans.RollbackTran();
                        return BuildSimpleResult(4, $"任务{task.S_CODE}修改失败,修改终点位置为{endLoc.S_CODE}");
                    }
                }
            }
            catch (Exception ex) {
                return BuildSimpleResult(1, $"发生了异常:{ex.Message}");
            }
        }
        /// <summary>
        /// 产品部分出库(WMS)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult PartOutWarehouse(PartOutWarehouseInfo model) {
            LogHelper.Info("触发API:产品部分出库(WMS)" + JsonConvert.SerializeObject(model), "API");
            var db = DbHelper.GetDbClient();
            try {
                // 起点位置:货架(有货、没有锁、已启用)
                var startLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 1 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y");
                if (startLoc == null) {
                    return BuildSimpleResult(2, $"起点位置 {model.startLoc} 不存在或不具备取货要求");
                }
                var locCtnrRel = db.Queryable<TN_Loc_Container>().First(a => a.S_LOC_CODE == model.startLoc);
                if (locCtnrRel == null) {
                    return BuildSimpleResult(3, $"起点位置 {model.startLoc} 没有绑定容器,无可出库的物料");
                }
                var endLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.endLoc && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == AreaCode.收发货位区);
                if (endLoc == null) {
                    return BuildSimpleResult(4, $"终点位置 {model.endLoc} 不具备放货条件");
                }
                using (var trans = db.Ado.UseTran()) {
                    // 解绑:起点货位与待搬运容器(不需要手动deleteable操作,内部会自动操作的)
                    if (WCSHelper.CreateTask(startLoc.S_CODE, endLoc.S_CODE, "产品部分出库(WMS)", 3, locCtnrRel.S_CNTR_CODE))//创建搬送任务,起点终点容器
                        {//如果操作TN_Location会造成死锁
                        LocationHelper.LockLoc(startLoc.S_CODE, 2);//起点出库锁,
                        LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                        trans.CommitTran();
                        return BuildSimpleResult(0, $"生成 产品出库(WMS) 成功,容器号{locCtnrRel.S_CNTR_CODE},起点{startLoc.S_CODE},终点{endLoc.S_CODE}");
                    }
                    else {
                        trans.RollbackTran();
                        return BuildSimpleResult(5, $"生成 产品出库(WMS) 失败,容器号{locCtnrRel.S_CNTR_CODE},起点{startLoc.S_CODE},终点{endLoc.S_CODE}");
                    }
                }
            }
            catch (Exception ex) {
                return BuildSimpleResult(1, $"发生了异常:{ex.Message}");
            }
        }
        /// <summary>
        /// 产品部分回库(WMS)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult PartInWarehouse(PartInWarehouseInfo model) {
            LogHelper.Info("触发API:产品部分回库(WMS)" + JsonConvert.SerializeObject(model), "API");
            var db = DbHelper.GetDbClient();
            try {
                // 起点位置:取放货区(有货物、没有锁、已启用)
                var startLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 1 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == AreaCode.收发货位区);
                if (startLoc == null) {
                    return BuildSimpleResult(2, $"起点位置 {model.startLoc} 不符合回库条件");
                }
                var locCtnrRel = db.Queryable<TN_Loc_Container>().First(a => a.S_LOC_CODE == model.startLoc);
                if (locCtnrRel == null) {
                    return BuildSimpleResult(3, $"起点位置 {model.startLoc} 没有绑定容器,无可回库的物料");
                }
                // 终点位置:货架(没有货物,没有锁)
                var endLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.endLoc && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y");
                if (endLoc == null) {
                    return BuildSimpleResult(4, $"终点位置 {model.endLoc} 不具备放货条件");
                }
                using (var trans = db.Ado.UseTran()) {
                    // 解绑:起点货位与待搬运容器(不需要手动deleteable操作,内部会自动操作的)
                    if (WCSHelper.CreateTask(startLoc.S_CODE, endLoc.S_CODE, "产品部分入库(WMS)", 3, locCtnrRel.S_CNTR_CODE))//创建搬送任务,起点终点容器
                        {//如果操作TN_Location会造成死锁
                        LocationHelper.LockLoc(startLoc.S_CODE, 2);//起点出库锁,
                        LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                        trans.CommitTran();
                        return BuildSimpleResult(0, $"生成 产品部分回库(WMS) 成功,容器号{locCtnrRel.S_CNTR_CODE},起点{startLoc.S_CODE},终点{endLoc.S_CODE}");
                    }
                    else {
                        trans.RollbackTran();
                        return BuildSimpleResult(5, $"生成 产品部分回库(WMS) 成功,容器号{locCtnrRel.S_CNTR_CODE},起点{startLoc.S_CODE},终点{endLoc.S_CODE}");
                    }
                }
            }
            catch (Exception ex) {
                return BuildSimpleResult(1, $"发生了异常:{ex.Message}");
            }
        }
        /// <summary>
        /// 盘点理货出库(WMS)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult CheckOutWarehouse(CheckOutWarehouseInfo model) {
            LogHelper.Info("触发API:盘点理货出库(WMS)" + JsonConvert.SerializeObject(model), "API");
            var db = DbHelper.GetDbClient();
            try {
                // 起点位置:取放货区(有货物、没有锁、已启用)
                var startLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 1 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == AreaCode.收发货位区);
                if (startLoc == null) {
                    return BuildSimpleResult(2, $"起点位置 {model.startLoc} 不符合出库条件");
                }
                var locCtnrRel = db.Queryable<TN_Loc_Container>().First(a => a.S_LOC_CODE == model.startLoc);
                if (locCtnrRel == null) {
                    return BuildSimpleResult(3, $"起点位置 {model.startLoc} 没有绑定容器,无可回库的物料");
                }
                // 终点位置:货架(没有货物,没有锁)
                var endLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.endLoc && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y");
                if (endLoc == null) {
                    return BuildSimpleResult(4, $"终点位置 {model.endLoc} 不具备放货条件");
                }
                using (var trans = db.Ado.UseTran()) {
                    // 解绑:起点货位与待搬运容器(不需要手动deleteable操作,内部会自动操作的)
                    if (WCSHelper.CreateTask(startLoc.S_CODE, endLoc.S_CODE, "盘点理货出库(WMS)", 3, locCtnrRel.S_CNTR_CODE))//创建搬送任务,起点终点容器
                        {//如果操作TN_Location会造成死锁
                        LocationHelper.LockLoc(startLoc.S_CODE, 2);//起点出库锁,
                        LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                        trans.CommitTran();
                        return BuildSimpleResult(0, $"生成 盘点理货出库(WMS) 成功,容器号{locCtnrRel.S_CNTR_CODE},起点{startLoc.S_CODE},终点{endLoc.S_CODE}");
                    }
                    else {
                        trans.RollbackTran();
                        return BuildSimpleResult(5, $"生成 盘点理货出库(WMS) 成功,容器号{locCtnrRel.S_CNTR_CODE},起点{startLoc.S_CODE},终点{endLoc.S_CODE}");
                    }
                }
            }
            catch (Exception ex) {
                return BuildSimpleResult(1, $"发生了异常:{ex.Message}");
            }
        }
        /// <summary>
        /// 盘点理货回库(WMS)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult CheckInWarehouse(CheckInWarehouseInfo model) {
            LogHelper.Info("触发API:盘点理货回库(WMS)" + JsonConvert.SerializeObject(model), "API");
            var db = DbHelper.GetDbClient();
            try {
                // 起点位置:取放货区(有货物、没有锁、已启用)
                var startLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 1 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == AreaCode.收发货位区);
                if (startLoc == null) {
                    return BuildSimpleResult(2, $"起点位置 {model.startLoc} 不符合回库条件");
                }
                var locCtnrRel = db.Queryable<TN_Loc_Container>().First(a => a.S_LOC_CODE == model.startLoc);
                if (locCtnrRel == null) {
                    return BuildSimpleResult(3, $"起点位置 {model.startLoc} 没有绑定容器,无可回库的物料");
                }
                // 终点位置:货架(没有货物,没有锁)
                var endLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.endLoc && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y");
                if (endLoc == null) {
                    return BuildSimpleResult(4, $"终点位置 {model.endLoc} 不具备放货条件");
                }
                using (var trans = db.Ado.UseTran()) {
                    // 解绑:起点货位与待搬运容器(不需要手动deleteable操作,内部会自动操作的)
                    if (WCSHelper.CreateTask(startLoc.S_CODE, endLoc.S_CODE, "盘点理货回库(WMS)", 3, locCtnrRel.S_CNTR_CODE))//创建搬送任务,起点终点容器
                        {//如果操作TN_Location会造成死锁
                        LocationHelper.LockLoc(startLoc.S_CODE, 2);//起点出库锁,
                        LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                        trans.CommitTran();
                        return BuildSimpleResult(0, $"生成 盘点理货回库(WMS) 成功,容器号{locCtnrRel.S_CNTR_CODE},起点{startLoc.S_CODE},终点{endLoc.S_CODE}");
                    }
                    else {
                        trans.RollbackTran();
                        return BuildSimpleResult(5, $"生成 盘点理货回库(WMS) 成功,容器号{locCtnrRel.S_CNTR_CODE},起点{startLoc.S_CODE},终点{endLoc.S_CODE}");
                    }
                }
            }
            catch (Exception ex) {
                return BuildSimpleResult(1, $"发生了异常:{ex.Message}");
            }
        }
        /// <summary>
        /// 入库数据同步(ERP)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult InWarehouseDataSync(InWarehouseDataSyncInfo model) {
            return BuildSimpleResult(0, "");
        }
        /// <summary>
        /// 出库发料同步(ERP)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult OutWarehouseDataSync(OutWarehouseDataSyncInfo model) {
            return BuildSimpleResult(0, "");
        }
    }
}
config/config.json
New file
@@ -0,0 +1,18 @@
{
    "WebApiUrl": "http://127.0.0.1:8901/",
    "RCSApiUrl": "http://127.0.0.1:6001",
    "NDCApiUrl": "http://127.0.0.1:5201/api/order/",
    "SqlServer": "Data Source=(local);Initial Catalog=AnGangTest;User ID=sa;Password=123456;",
    "TCPServerIP": "127.0.0.1",
    "TCPServerPort": 8085,
    "Areas": [
        {
            "Name": "收发货位区",
            "Codes": [ "P" ]
        },
        {
            "Name": "货架区",
            "Codes": [ "B111", "B112", "B113", "B114", "B115", "B116", "B117", "B118" ]
        }
    ]
}
packages.config
New file
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="BouncyCastle.Cryptography" version="2.4.0" targetFramework="net462" />
  <package id="EasyModbusTCP" version="5.6.0" targetFramework="net461" />
  <package id="Microsoft.AspNet.WebApi.Client" version="6.0.0" targetFramework="net462" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.3.0" targetFramework="net462" />
  <package id="Microsoft.AspNet.WebApi.Owin" version="5.3.0" targetFramework="net462" />
  <package id="Microsoft.AspNet.WebApi.OwinSelfHost" version="5.3.0" targetFramework="net462" />
  <package id="Microsoft.AspNet.WebApi.WebHost" version="5.3.0" targetFramework="net462" />
  <package id="Microsoft.Bcl.AsyncInterfaces" version="8.0.0" targetFramework="net48" />
  <package id="Microsoft.Bcl.HashCode" version="1.1.1" targetFramework="net462" />
  <package id="Microsoft.Extensions.Logging.Abstractions" version="3.1.32" targetFramework="net462" />
  <package id="Microsoft.Owin" version="4.2.2" targetFramework="net461" />
  <package id="Microsoft.Owin.Host.HttpListener" version="4.2.2" targetFramework="net461" />
  <package id="Microsoft.Owin.Hosting" version="4.2.2" targetFramework="net461" />
  <package id="Microsoft.Web.Infrastructure" version="2.0.0" targetFramework="net462" />
  <package id="Newtonsoft.Json" version="13.0.3" targetFramework="net462" />
  <package id="Newtonsoft.Json.Bson" version="1.0.2" targetFramework="net462" />
  <package id="NLog" version="5.3.4" targetFramework="net462" />
  <package id="OPCFoundation.NetStandard.Opc.Ua" version="1.5.374.126" targetFramework="net462" />
  <package id="OPCFoundation.NetStandard.Opc.Ua.Client" version="1.5.374.126" targetFramework="net462" />
  <package id="OPCFoundation.NetStandard.Opc.Ua.Configuration" version="1.5.374.126" targetFramework="net462" />
  <package id="OPCFoundation.NetStandard.Opc.Ua.Core" version="1.5.374.126" targetFramework="net462" />
  <package id="OPCFoundation.NetStandard.Opc.Ua.Gds.Client.Common" version="1.5.374.126" targetFramework="net462" />
  <package id="OPCFoundation.NetStandard.Opc.Ua.Gds.Server.Common" version="1.5.374.126" targetFramework="net462" />
  <package id="OPCFoundation.NetStandard.Opc.Ua.Security.Certificates" version="1.5.374.126" targetFramework="net462" />
  <package id="OPCFoundation.NetStandard.Opc.Ua.Server" version="1.5.374.126" targetFramework="net462" />
  <package id="Owin" version="1.0" targetFramework="net461" />
  <package id="Portable.BouncyCastle" version="1.9.0" targetFramework="net462" />
  <package id="S7netplus" version="0.20.0" targetFramework="net461" requireReinstallation="true" />
  <package id="SqlSugar" version="5.1.4.169" targetFramework="net462" />
  <package id="Swashbuckle" version="5.6.0" targetFramework="net461" />
  <package id="Swashbuckle.Core" version="5.6.0" targetFramework="net461" />
  <package id="System.Buffers" version="4.5.1" targetFramework="net461" />
  <package id="System.Diagnostics.DiagnosticSource" version="6.0.1" targetFramework="net462" />
  <package id="System.Formats.Asn1" version="8.0.1" targetFramework="net462" />
  <package id="System.Memory" version="4.5.5" targetFramework="net461" />
  <package id="System.Net.Http" version="4.3.4" targetFramework="net462" />
  <package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net461" />
  <package id="System.Runtime.CompilerServices.Unsafe" version="6.0.0" targetFramework="net461" />
  <package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net452" />
  <package id="System.Security.Cryptography.Algorithms" version="4.3.1" targetFramework="net462" />
  <package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net462" />
  <package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net462" />
  <package id="System.Security.Cryptography.X509Certificates" version="4.3.2" targetFramework="net462" />
  <package id="System.ServiceModel.Primitives" version="4.10.0" targetFramework="net462" />
  <package id="System.Text.Encodings.Web" version="8.0.0" targetFramework="net48" />
  <package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net461" />
  <package id="System.ValueTuple" version="4.5.0" targetFramework="net48" requireReinstallation="true" />
  <package id="Topshelf" version="4.3.0" targetFramework="net452" />
  <package id="Topshelf.NLog" version="4.3.0" targetFramework="net452" />
  <package id="WebActivatorEx" version="2.2.0" targetFramework="net462" />
</packages>
swagger.js
New file
@@ -0,0 +1,110 @@
'use strict';
window.SwaggerTranslator = {
    _words: [],
    translate: function ()
    {
        var $this = this;
        $('[data-sw-translate]').each(function ()
        {
            $(this).html($this._tryTranslate($(this).html()));
            $(this).val($this._tryTranslate($(this).val()));
            $(this).attr('title', $this._tryTranslate($(this).attr('title')));
        });
    },
    setControllerSummary: function ()
    {
        $.ajax({
            type: "get",
            async: true,
            url: $("#input_baseUrl").val(),
            dataType: "json",
            success: function (data)
            {
                var summaryDict = data.ControllerDesc;
                var id, controllerName, strSummary;
                $("#resources_container .resource").each(function (i, item)
                {
                    id = $(item).attr("id");
                    if (id)
                    {
                        controllerName = id.substring(9);
                        strSummary = summaryDict[controllerName];
                        if (strSummary)
                        {
                            $(item).children(".heading").children(".options").first().prepend('<li class="controller-summary" title="' + strSummary + '">' + strSummary + '</li>');
                        }
                    }
                });
            }
        });
    },
    _tryTranslate: function (word)
    {
        return this._words[$.trim(word)] !== undefined ? this._words[$.trim(word)] : word;
    },
    learn: function (wordsMap)
    {
        this._words = wordsMap;
    }
};
/* jshint quotmark: float */
window.SwaggerTranslator.learn({
    "Warning: Deprecated": "警告:已过时",
    "Implementation Notes": "实现备注",
    "Response Class": "响应类",
    "Status": "״̬",
    "Parameters": "参数",
    "Parameter": "参数",
    "Value": "ֵ",
    "Description": "描述",
    "Parameter Type": "参数类型",
    "Data Type": "数据类型",
    "Response Messages": "响应消息",
    "HTTP Status Code": "HTTP 状态码",
    "Reason": "原因",
    "Response Model": "响应模型",
    "Request URL": "请求 URL",
    "Response Body": "响应体",
    "Response Code": "响应码",
    "Response Headers": "响应头",
    "Hide Response": "隐藏响应",
    "Headers": "ͷ",
    "Try it out!": "试一下!",
    "Show/Hide": "显示/隐藏",
    "List Operations": "显示操作",
    "Expand Operations": "展开操作",
    "Raw": "ԭʼ",
    "can't parse JSON.  Raw result": "无法解析 JSON。原始结果",
    "Model Schema": "模型架构",
    "Model": "模型",
    "apply": "应用",
    "Username": "用户名",
    "Password": "密码",
    "Terms of service": "服务条款",
    "Created by": "创建者",
    "See more at": "查看更多:",
    "Contact the developer": "联系开发者",
    "api version": "api 版本",
    "Response Content Type": "响应 Content Type",
    "fetching resource": "正在获取资源",
    "fetching resource list": "正在获取资源列表",
    "Explore": "浏览",
    "Show Swagger Petstore Example Apis": "显示 Swagger Petstore 示例 Apis",
    "Can't read from server.  It may not have the appropriate access-control-origin settings.": "无法从服务器读取。可能没有正确设置 access-control-origin。",
    "Please specify the protocol for": "请指定协议:",
    "Can't read swagger JSON from": "无法读取 swagger JSON于",
    "Finished Loading Resource Information. Rendering Swagger UI": "已加载资源信息。正在渲染 Swagger UI",
    "Unable to read api": "无法读取 api",
    "from path": "从路径",
    "server returned": "服务器返回"
});
$(function ()
{
    window.SwaggerTranslator.translate();
    window.SwaggerTranslator.setControllerSummary();
});