添加机器人客户端;更新 WCS 缓存及任务
新增内容:
添加新的 RobotClient 项目及多个 RobotJob 组件(包括:BarcodeGenerator 条码生成器、ClientManager 客户端管理器、MessageHandler 消息处理器、SocketState 套接字状态、StateManager 状态管理器、TaskProcessor 任务处理器)
服务端更新:
更新 WIDESEAWCS 服务器:修改 TaskEnum 和 TaskType 枚举、TaskService 服务以及 RobotJob.cs 文件
缓存层重构:
修订缓存层及 Redis 集成(涉及 ICacheService 缓存接口、MemoryCacheService 内存缓存、HybridCacheService 混合缓存、RedisCacheService 缓存服务、CacheSyncBackgroundService 缓存同步后台服务、RedisOptions 配置选项)
更新 appsettings 配置文件
开发环境配置:
更新工作区元数据(.vs/DocumentLayout.json 文件)
添加 .claude 本地权限配置
其他变更:
包含各类 IDE 快照文件
若干与 WMS 任务相关的细微调整
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "permissions": { |
| | | "allow": [ |
| | | "Bash(dotnet new:*)", |
| | | "Bash(dotnet add:*)", |
| | | "Bash(dotnet test:*)", |
| | | "Bash(dotnet build WIDESEAWCS_Server.sln --nologo -v q)" |
| | | ] |
| | | } |
| | | } |
| | |
| | | "WorkspaceRootPath": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\", |
| | | "Documents": [ |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{83F18A31-5983-4587-A0B2-414BF70E50B5}|WIDESEAWCS_TaskInfoService\\WIDESEAWCS_TaskInfoService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_taskinfoservice\\taskservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{83F18A31-5983-4587-A0B2-414BF70E50B5}|WIDESEAWCS_TaskInfoService\\WIDESEAWCS_TaskInfoService.csproj|solutionrelative:wideseawcs_taskinfoservice\\taskservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{BFFDD936-2E61-4D3A-ABFE-7CF77FE0B184}|WIDESEAWCS_Core\\WIDESEAWCS_Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_core\\http\\http\\httpclienthelper.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{BFFDD936-2E61-4D3A-ABFE-7CF77FE0B184}|WIDESEAWCS_Core\\WIDESEAWCS_Core.csproj|solutionrelative:wideseawcs_core\\http\\http\\httpclienthelper.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\robotjob\\robottaskprocessor.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\robotjob\\robottaskprocessor.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\robotjob\\robotmessagehandler.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\robotjob\\robotmessagehandler.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\conveyorlinenewjob\\commonconveyorlinenewjob.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\conveyorlinenewjob\\commonconveyorlinenewjob.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\robotjob\\robotjob.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\robotjob\\robotjob.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\socketserver\\tcpsocketserver.clients.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\socketserver\\tcpsocketserver.clients.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | "AbsoluteMoniker": "D:0:0:{9FBC654C-51DE-422D-9E1E-6A38268DE1E2}|WIDESEAWCS_Common\\WIDESEAWCS_Common.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_common\\taskenum\\taskenumhelper.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{9FBC654C-51DE-422D-9E1E-6A38268DE1E2}|WIDESEAWCS_Common\\WIDESEAWCS_Common.csproj|solutionrelative:wideseawcs_common\\taskenum\\taskenumhelper.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{83F18A31-5983-4587-A0B2-414BF70E50B5}|WIDESEAWCS_TaskInfoService\\WIDESEAWCS_TaskInfoService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_taskinfoservice\\robottaskservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{83F18A31-5983-4587-A0B2-414BF70E50B5}|WIDESEAWCS_TaskInfoService\\WIDESEAWCS_TaskInfoService.csproj|solutionrelative:wideseawcs_taskinfoservice\\robottaskservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\socketserver\\tcpsocketserver.messaging.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\socketserver\\tcpsocketserver.messaging.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{6236BFFF-173D-44A8-9FC3-7C001EA30347}|WIDESEAWCS_QuartzJob\\WIDESEAWCS_QuartzJob.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_quartzjob\\service\\routerservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{6236BFFF-173D-44A8-9FC3-7C001EA30347}|WIDESEAWCS_QuartzJob\\WIDESEAWCS_QuartzJob.csproj|solutionrelative:wideseawcs_quartzjob\\service\\routerservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{9FBC654C-51DE-422D-9E1E-6A38268DE1E2}|WIDESEAWCS_Common\\WIDESEAWCS_Common.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_common\\taskenum\\tasktypeenum.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{9FBC654C-51DE-422D-9E1E-6A38268DE1E2}|WIDESEAWCS_Common\\WIDESEAWCS_Common.csproj|solutionrelative:wideseawcs_common\\taskenum\\tasktypeenum.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\robotjob\\robotstatemanager.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\robotjob\\robotstatemanager.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\robotjob\\robotclientmanager.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\robotjob\\robotclientmanager.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{F9886971-C3B2-4334-B014-D5109F2041DE}|WIDESEAWCS_RedisService\\WIDESEAWCS_RedisService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_redisservice\\cache\\hybridcacheservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{F9886971-C3B2-4334-B014-D5109F2041DE}|WIDESEAWCS_RedisService\\WIDESEAWCS_RedisService.csproj|solutionrelative:wideseawcs_redisservice\\cache\\hybridcacheservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{F9886971-C3B2-4334-B014-D5109F2041DE}|WIDESEAWCS_RedisService\\WIDESEAWCS_RedisService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_redisservice\\connection\\redisconnectionmanager.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{F9886971-C3B2-4334-B014-D5109F2041DE}|WIDESEAWCS_RedisService\\WIDESEAWCS_RedisService.csproj|solutionrelative:wideseawcs_redisservice\\connection\\redisconnectionmanager.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{487FA45B-EA1A-4ACA-BB5B-0F6708F462C0}|WIDESEAWCS_Server\\WIDESEAWCS_Server.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_server\\appsettings.json||{90A6B3A7-C1A3-4009-A288-E2FF89E96FA0}", |
| | |
| | | "RelativeMoniker": "D:0:0:{F9886971-C3B2-4334-B014-D5109F2041DE}|WIDESEAWCS_RedisService\\WIDESEAWCS_RedisService.csproj|solutionrelative:wideseawcs_redisservice\\extensions\\redisservicesetup.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{F9886971-C3B2-4334-B014-D5109F2041DE}|WIDESEAWCS_RedisService\\WIDESEAWCS_RedisService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_redisservice\\cache\\rediscacheservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{F9886971-C3B2-4334-B014-D5109F2041DE}|WIDESEAWCS_RedisService\\WIDESEAWCS_RedisService.csproj|solutionrelative:wideseawcs_redisservice\\cache\\rediscacheservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | "AbsoluteMoniker": "D:0:0:{9FBC654C-51DE-422D-9E1E-6A38268DE1E2}|WIDESEAWCS_Common\\WIDESEAWCS_Common.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_common\\httpenum\\configkey.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{9FBC654C-51DE-422D-9E1E-6A38268DE1E2}|WIDESEAWCS_Common\\WIDESEAWCS_Common.csproj|solutionrelative:wideseawcs_common\\httpenum\\configkey.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{487FA45B-EA1A-4ACA-BB5B-0F6708F462C0}|WIDESEAWCS_Server\\WIDESEAWCS_Server.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_server\\redis\u4F7F\u7528\u6848\u4F8B.md||{EFC0BB08-EA7D-40C6-A696-C870411A895B}", |
| | | "RelativeMoniker": "D:0:0:{487FA45B-EA1A-4ACA-BB5B-0F6708F462C0}|WIDESEAWCS_Server\\WIDESEAWCS_Server.csproj|solutionrelative:wideseawcs_server\\redis\u4F7F\u7528\u6848\u4F8B.md||{EFC0BB08-EA7D-40C6-A696-C870411A895B}" |
| | | "AbsoluteMoniker": "D:0:0:{9FBC654C-51DE-422D-9E1E-6A38268DE1E2}|WIDESEAWCS_Common\\WIDESEAWCS_Common.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_common\\redis\\redisname.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{9FBC654C-51DE-422D-9E1E-6A38268DE1E2}|WIDESEAWCS_Common\\WIDESEAWCS_Common.csproj|solutionrelative:wideseawcs_common\\redis\\redisname.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{487FA45B-EA1A-4ACA-BB5B-0F6708F462C0}|WIDESEAWCS_Server\\WIDESEAWCS_Server.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_server\\program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{487FA45B-EA1A-4ACA-BB5B-0F6708F462C0}|WIDESEAWCS_Server\\WIDESEAWCS_Server.csproj|solutionrelative:wideseawcs_server\\program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\socketserver\\tcpsocketserver.server.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\socketserver\\tcpsocketserver.server.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{BFFDD936-2E61-4D3A-ABFE-7CF77FE0B184}|WIDESEAWCS_Core\\WIDESEAWCS_Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_core\\http\\http\\httpclienthelper.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{BFFDD936-2E61-4D3A-ABFE-7CF77FE0B184}|WIDESEAWCS_Core\\WIDESEAWCS_Core.csproj|solutionrelative:wideseawcs_core\\http\\http\\httpclienthelper.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | "AbsoluteMoniker": "D:0:0:{BFFDD936-2E61-4D3A-ABFE-7CF77FE0B184}|WIDESEAWCS_Core\\WIDESEAWCS_Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_core\\http\\httprequesthelper.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{BFFDD936-2E61-4D3A-ABFE-7CF77FE0B184}|WIDESEAWCS_Core\\WIDESEAWCS_Core.csproj|solutionrelative:wideseawcs_core\\http\\httprequesthelper.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\conveyorlinenewjob\\conveyorline\\checkpalletposition.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\conveyorlinenewjob\\conveyorline\\checkpalletposition.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | "AbsoluteMoniker": "D:0:0:{9FBC654C-51DE-422D-9E1E-6A38268DE1E2}|WIDESEAWCS_Common\\WIDESEAWCS_Common.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_common\\httpenum\\baseapi.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{9FBC654C-51DE-422D-9E1E-6A38268DE1E2}|WIDESEAWCS_Common\\WIDESEAWCS_Common.csproj|solutionrelative:wideseawcs_common\\httpenum\\baseapi.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\conveyorlinenewjob\\commonconveyorlinenewjob.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\conveyorlinenewjob\\commonconveyorlinenewjob.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | "AbsoluteMoniker": "D:0:0:{6236BFFF-173D-44A8-9FC3-7C001EA30347}|WIDESEAWCS_QuartzJob\\WIDESEAWCS_QuartzJob.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_quartzjob\\quartznet\\quartznetextension.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{6236BFFF-173D-44A8-9FC3-7C001EA30347}|WIDESEAWCS_QuartzJob\\WIDESEAWCS_QuartzJob.csproj|solutionrelative:wideseawcs_quartzjob\\quartznet\\quartznetextension.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{9FBC654C-51DE-422D-9E1E-6A38268DE1E2}|WIDESEAWCS_Common\\WIDESEAWCS_Common.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_common\\redis\\redisprefix.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{9FBC654C-51DE-422D-9E1E-6A38268DE1E2}|WIDESEAWCS_Common\\WIDESEAWCS_Common.csproj|solutionrelative:wideseawcs_common\\redis\\redisprefix.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | } |
| | | ], |
| | | "DocumentGroupContainers": [ |
| | |
| | | "DocumentGroups": [ |
| | | { |
| | | "DockedWidth": 200, |
| | | "SelectedChildIndex": 14, |
| | | "SelectedChildIndex": 10, |
| | | "Children": [ |
| | | { |
| | | "$type": "Bookmark", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 1, |
| | | "Title": "TcpSocketServer.Clients.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Clients.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Clients.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Clients.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Clients.cs", |
| | | "ViewState": "AgIAAEkAAAAAAAAAAAAIwAkAAAAZAAAAAAAAAA==", |
| | | "DocumentIndex": 6, |
| | | "Title": "TaskEnumHelper.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Common\\TaskEnum\\TaskEnumHelper.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Common\\TaskEnum\\TaskEnumHelper.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Common\\TaskEnum\\TaskEnumHelper.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_Common\\TaskEnum\\TaskEnumHelper.cs", |
| | | "ViewState": "AgIAABQAAAAAAAAAAAAgwDUAAAAIAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-02T04:08:38.428Z", |
| | | "WhenOpened": "2026-03-05T07:09:01.343Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 3, |
| | | "Title": "RedisConnectionManager.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_RedisService\\Connection\\RedisConnectionManager.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_RedisService\\Connection\\RedisConnectionManager.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_RedisService\\Connection\\RedisConnectionManager.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_RedisService\\Connection\\RedisConnectionManager.cs", |
| | | "ViewState": "AgIAAD0AAAAAAAAAAAAuwE8AAAAIAAAAAAAAAA==", |
| | | "Title": "RobotMessageHandler.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\RobotMessageHandler.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\RobotJob\\RobotMessageHandler.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\RobotMessageHandler.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_Tasks\\RobotJob\\RobotMessageHandler.cs", |
| | | "ViewState": "AgIAAMgAAAAAAAAAAAAMwNIAAABHAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-02T03:52:53.567Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 2, |
| | | "Title": "HybridCacheService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_RedisService\\Cache\\HybridCacheService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_RedisService\\Cache\\HybridCacheService.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_RedisService\\Cache\\HybridCacheService.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_RedisService\\Cache\\HybridCacheService.cs", |
| | | "ViewState": "AgIAAOkAAAAAAAAAAAAqwPoAAAAjAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-02T03:39:18.734Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 5, |
| | | "Title": "RedisServiceSetup.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_RedisService\\Extensions\\RedisServiceSetup.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_RedisService\\Extensions\\RedisServiceSetup.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_RedisService\\Extensions\\RedisServiceSetup.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_RedisService\\Extensions\\RedisServiceSetup.cs", |
| | | "ViewState": "AgIAADgAAAAAAAAAAAAmwCIAAAAMAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-02T03:33:54.548Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 8, |
| | | "Title": "Program.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Server\\Program.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Server\\Program.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Server\\Program.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_Server\\Program.cs", |
| | | "ViewState": "AgIAACQAAAAAAAAAAAAqwDYAAAAeAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-02T03:16:21.765Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 6, |
| | | "Title": "RedisCacheService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_RedisService\\Cache\\RedisCacheService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_RedisService\\Cache\\RedisCacheService.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_RedisService\\Cache\\RedisCacheService.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_RedisService\\Cache\\RedisCacheService.cs", |
| | | "ViewState": "AgIAABoAAAAAAAAAAAAmwCkAAAAoAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-02T03:06:06.952Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 7, |
| | | "Title": "Redis\u4F7F\u7528\u6848\u4F8B.md", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Server\\Redis\u4F7F\u7528\u6848\u4F8B.md", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Server\\Redis\u4F7F\u7528\u6848\u4F8B.md", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Server\\Redis\u4F7F\u7528\u6848\u4F8B.md", |
| | | "RelativeToolTip": "WIDESEAWCS_Server\\Redis\u4F7F\u7528\u6848\u4F8B.md", |
| | | "ViewState": "AgIAAAgBAAAAAAAAAAAAABcBAAAPAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001818|", |
| | | "WhenOpened": "2026-03-02T02:59:29.028Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 9, |
| | | "Title": "HttpClientHelper.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Core\\Http\\HTTP\\HttpClientHelper.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Core\\Http\\HTTP\\HttpClientHelper.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Core\\Http\\HTTP\\HttpClientHelper.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_Core\\Http\\HTTP\\HttpClientHelper.cs", |
| | | "ViewState": "AgIAABQAAAAAAAAAAADwvygAAABLAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-02T02:58:50.075Z", |
| | | "WhenOpened": "2026-03-05T03:25:13.299Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 10, |
| | | "Title": "CheckPalletPosition.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\ConveyorLineNewJob\\ConveyorLine\\CheckPalletPosition.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\ConveyorLineNewJob\\ConveyorLine\\CheckPalletPosition.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\ConveyorLineNewJob\\ConveyorLine\\CheckPalletPosition.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_Tasks\\ConveyorLineNewJob\\ConveyorLine\\CheckPalletPosition.cs", |
| | | "ViewState": "AgIAAAAAAAAAAAAAAAAAAAYAAAAeAAAAAAAAAA==", |
| | | "Title": "TaskTypeEnum.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Common\\TaskEnum\\TaskTypeEnum.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Common\\TaskEnum\\TaskTypeEnum.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Common\\TaskEnum\\TaskTypeEnum.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_Common\\TaskEnum\\TaskTypeEnum.cs", |
| | | "ViewState": "AgIAACEAAAAAAAAAAADwvzwAAAAYAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-28T08:42:47.236Z", |
| | | "WhenOpened": "2026-03-05T03:17:26.276Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 4, |
| | | "DocumentIndex": 2, |
| | | "Title": "RobotTaskProcessor.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\RobotTaskProcessor.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\RobotJob\\RobotTaskProcessor.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\RobotTaskProcessor.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_Tasks\\RobotJob\\RobotTaskProcessor.cs", |
| | | "ViewState": "AgIAAIgAAAAAAAAAAAD4v54AAAApAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-05T02:51:55.934Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 15, |
| | | "Title": "RedisServiceSetup.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_RedisService\\Extensions\\RedisServiceSetup.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_RedisService\\Extensions\\RedisServiceSetup.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_RedisService\\Extensions\\RedisServiceSetup.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_RedisService\\Extensions\\RedisServiceSetup.cs", |
| | | "ViewState": "AgIAABkAAAAAAAAAAAAtwDYAAAA5AAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-03T07:51:50.169Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 7, |
| | | "Title": "RobotTaskService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_TaskInfoService\\RobotTaskService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_TaskInfoService\\RobotTaskService.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_TaskInfoService\\RobotTaskService.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_TaskInfoService\\RobotTaskService.cs", |
| | | "ViewState": "AgIAAD0AAAAAAAAAAAAMwEcAAAAdAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-03T03:03:26.246Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 19, |
| | | "Title": "HttpRequestHelper.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Core\\Http\\HttpRequestHelper.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Core\\Http\\HttpRequestHelper.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Core\\Http\\HttpRequestHelper.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_Core\\Http\\HttpRequestHelper.cs", |
| | | "ViewState": "AgIAAJ0AAAAAAAAAAADwv7AAAAAiAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-03T02:38:46.736Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 0, |
| | | "Title": "TaskService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_TaskInfoService\\TaskService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_TaskInfoService\\TaskService.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_TaskInfoService\\TaskService.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_TaskInfoService\\TaskService.cs", |
| | | "ViewState": "AgIAAHcBAAAAAAAAAAAMwJABAAAVAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-03T02:28:05.416Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 20, |
| | | "Title": "BaseAPI.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Common\\HttpEnum\\BaseAPI.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Common\\HttpEnum\\BaseAPI.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Common\\HttpEnum\\BaseAPI.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_Common\\HttpEnum\\BaseAPI.cs", |
| | | "ViewState": "AgIAAAAAAAAAAAAAAAAAABoAAAAWAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-03T02:22:49.339Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 16, |
| | | "Title": "ConfigKey.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Common\\HttpEnum\\ConfigKey.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Common\\HttpEnum\\ConfigKey.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Common\\HttpEnum\\ConfigKey.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_Common\\HttpEnum\\ConfigKey.cs", |
| | | "ViewState": "AgIAABEAAAAAAAAAAADwvwkAAAASAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-03T02:19:51.695Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 1, |
| | | "Title": "HttpClientHelper.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Core\\Http\\HTTP\\HttpClientHelper.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Core\\Http\\HTTP\\HttpClientHelper.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Core\\Http\\HTTP\\HttpClientHelper.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_Core\\Http\\HTTP\\HttpClientHelper.cs", |
| | | "ViewState": "AgIAAFgAAAAAAAAAAAD4v1sAAAAtAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-03T02:13:21.506Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 17, |
| | | "Title": "RedisName.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Common\\Redis\\RedisName.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Common\\Redis\\RedisName.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Common\\Redis\\RedisName.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_Common\\Redis\\RedisName.cs", |
| | | "ViewState": "AgIAAAwAAAAAAAAAAAAswBwAAAAfAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-03T01:52:46.175Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 22, |
| | | "Title": "RedisPrefix.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Common\\Redis\\RedisPrefix.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Common\\Redis\\RedisPrefix.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Common\\Redis\\RedisPrefix.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_Common\\Redis\\RedisPrefix.cs", |
| | | "ViewState": "AgIAAAAAAAAAAAAAAAAAAAkAAAA4AAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-03T01:50:08.45Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 9, |
| | | "Title": "RouterService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_QuartzJob\\Service\\RouterService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_QuartzJob\\Service\\RouterService.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_QuartzJob\\Service\\RouterService.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_QuartzJob\\Service\\RouterService.cs", |
| | | "ViewState": "AgIAAKoAAAAAAAAAAAAawMEAAABrAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-02T10:10:38.22Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 13, |
| | | "Title": "HybridCacheService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_RedisService\\Cache\\HybridCacheService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_RedisService\\Cache\\HybridCacheService.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_RedisService\\Cache\\HybridCacheService.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_RedisService\\Cache\\HybridCacheService.cs", |
| | | "ViewState": "AgIAAHUCAAAAAAAAAAAswI4CAABaAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-02T10:04:18.563Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 21, |
| | | "Title": "QuartzNetExtension.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_QuartzJob\\QuartzNet\\QuartzNetExtension.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_QuartzJob\\QuartzNet\\QuartzNetExtension.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_QuartzJob\\QuartzNet\\QuartzNetExtension.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_QuartzJob\\QuartzNet\\QuartzNetExtension.cs", |
| | | "ViewState": "AgIAAHoAAAAAAAAAAAAswIgAAABBAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-02T09:22:53.922Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 18, |
| | | "Title": "TcpSocketServer.Server.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Server.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Server.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Server.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Server.cs", |
| | | "ViewState": "AgIAABEAAAAAAAAAAAAhwCMAAAAbAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-02T09:11:28.744Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 8, |
| | | "Title": "TcpSocketServer.Messaging.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Messaging.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Messaging.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Messaging.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Messaging.cs", |
| | | "ViewState": "AgIAADMAAAAAAAAAAAAgwEgAAAAZAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-02T09:07:48.915Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 14, |
| | | "Title": "appsettings.json", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Server\\appsettings.json", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Server\\appsettings.json", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Server\\appsettings.json", |
| | | "RelativeToolTip": "WIDESEAWCS_Server\\appsettings.json", |
| | | "ViewState": "AgIAACUAAAAAAAAAAAAYwCsAAAAeAAAAAAAAAA==", |
| | | "ViewState": "AgIAADoAAAAAAAAAAAAYwE4AAAAbAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|", |
| | | "WhenOpened": "2026-02-28T05:50:10.851Z", |
| | | "EditorCaption": "" |
| | | "WhenOpened": "2026-02-28T05:50:10.851Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 11, |
| | | "DocumentIndex": 4, |
| | | "Title": "CommonConveyorLineNewJob.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\ConveyorLineNewJob\\CommonConveyorLineNewJob.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\ConveyorLineNewJob\\CommonConveyorLineNewJob.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\ConveyorLineNewJob\\CommonConveyorLineNewJob.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_Tasks\\ConveyorLineNewJob\\CommonConveyorLineNewJob.cs", |
| | | "ViewState": "AgIAAEoAAAAAAAAAAAAAwGAAAABTAAAAAAAAAA==", |
| | | "ViewState": "AgIAAEAAAAAAAAAAAAAswHgAAAAcAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-28T05:48:06.526Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 0, |
| | | "DocumentIndex": 11, |
| | | "Title": "RobotStateManager.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\RobotStateManager.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\RobotJob\\RobotStateManager.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\RobotStateManager.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_Tasks\\RobotJob\\RobotStateManager.cs", |
| | | "ViewState": "AgIAAFoAAAAAAAAAAAAmwAAAAAAAAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-05T02:50:08.257Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 12, |
| | | "Title": "RobotClientManager.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\RobotClientManager.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\RobotJob\\RobotClientManager.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\RobotClientManager.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_Tasks\\RobotJob\\RobotClientManager.cs", |
| | | "ViewState": "AgIAADYAAAAAAAAAAADwvwAAAAAAAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-05T01:55:28.903Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 5, |
| | | "Title": "RobotJob.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\RobotJob.cs", |
| | | "RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\RobotJob\\RobotJob.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\RobotJob.cs", |
| | | "RelativeToolTip": "WIDESEAWCS_Tasks\\RobotJob\\RobotJob.cs", |
| | | "ViewState": "AgIAADgAAAAAAAAAAAAtwEIAAAAPAAAAAAAAAA==", |
| | | "ViewState": "AgIAAGMAAAAAAAAAAAAcwHYAAABVAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-05T05:38:04.031Z", |
| | | "EditorCaption": "" |
| | |
| | | return TaskTypeGroup.OutbondGroup; |
| | | } |
| | | // å°è¯å°ä»»å¡ç±»å转æ¢ä¸ºTaskInStatusEnumæä¸¾ç±»åï¼å¦ææåï¼è¿åInboundGroup |
| | | else if (!int.TryParse(Enum.Parse<TaskOutboundTypeEnum>(taskTypeStr).ToString(), out result)) |
| | | else if (!int.TryParse(Enum.Parse<TaskInStatusEnum>(taskTypeStr).ToString(), out result)) |
| | | { |
| | | return TaskTypeGroup.InboundGroup; |
| | | } |
| | |
| | | /// è´¨æ£å
¥åº |
| | | /// </summary> |
| | | [Description("è´¨æ£å
¥åº")] |
| | | InQuality = 203 |
| | | InQuality = 203, |
| | | |
| | | /// <summary> |
| | | /// 空箱å
¥åº |
| | | /// </summary> |
| | | [Description("空箱å
¥åº")] |
| | | InEmpty = 600, |
| | | } |
| | | |
| | | public enum TaskOutboundTypeEnum |
| | |
| | | /// </summary> |
| | | [Description("è´¨æ£åºåº")] |
| | | OutQuality = 103, |
| | | |
| | | /// <summary> |
| | | /// 空箱åºåº |
| | | /// </summary> |
| | | [Description("空箱åºåº")] |
| | | OutEmpty = 140, |
| | | } |
| | | |
| | | public enum TaskRelocationTypeEnum |
| | |
| | | [Description("æ¢çä»»å¡")] |
| | | SplitPallet = 520 |
| | | } |
| | | |
| | | public enum TaskTypeEnum |
| | | { |
| | | /// <summary> |
| | | /// 颿åºåº |
| | | /// </summary> |
| | | [Description("颿åºåº")] |
| | | Outbound = 100, |
| | | /// <summary> |
| | | /// çç¹åºåº |
| | | /// </summary> |
| | | [Description("çç¹åºåº")] |
| | | OutInventory = 110, |
| | | /// <summary> |
| | | /// 忣åºåº |
| | | /// </summary> |
| | | [Description("忣åºåº")] |
| | | OutPick = 120, |
| | | /// <summary> |
| | | /// è´¨æ£åºåº |
| | | /// </summary> |
| | | [Description("è´¨æ£åºåº")] |
| | | OutQuality = 130, |
| | | |
| | | /// <summary> |
| | | /// 空箱åºåº |
| | | /// </summary> |
| | | [Description("空箱åºåº")] |
| | | OutEmpty = 140, |
| | | |
| | | /// <summary> |
| | | /// MESåºåº |
| | | /// </summary> |
| | | [Description("MESåºåº")] |
| | | MesOutbound = 200, |
| | | |
| | | /// <summary> |
| | | /// MESæå¨åºåº |
| | | /// </summary> |
| | | [Description("MESæå¨åºåº")] |
| | | MesHandOutbound = 210, |
| | | |
| | | /// <summary> |
| | | /// MESæå¨æ£éåºåº |
| | | /// </summary> |
| | | [Description("MESæå¨æ£éåºåº")] |
| | | MesHandPickOutbound = 220, |
| | | |
| | | /// <summary> |
| | | /// éè´å
¥åº |
| | | /// </summary> |
| | | [Description("éè´å
¥åº")] |
| | | Inbound = 510, |
| | | /// <summary> |
| | | /// çç¹å
¥åº |
| | | /// </summary> |
| | | [Description("çç¹å
¥åº")] |
| | | InInventory = 520, |
| | | /// <summary> |
| | | /// 忣å
¥åº |
| | | /// </summary> |
| | | [Description("忣å
¥åº")] |
| | | InPick = 530, |
| | | /// <summary> |
| | | /// è´¨æ£å
¥åº |
| | | /// </summary> |
| | | [Description("è´¨æ£å
¥åº")] |
| | | InQuality = 540, |
| | | |
| | | /// <summary> |
| | | /// çäº§éæ |
| | | /// </summary> |
| | | [Description("ç产éæ")] |
| | | ProductionReturn = 550, |
| | | |
| | | /// <summary> |
| | | /// MESéæ |
| | | /// </summary> |
| | | [Description("MESéæ")] |
| | | MesMatReturn = 560, |
| | | |
| | | /// <summary> |
| | | /// 空箱å
¥åº |
| | | /// </summary> |
| | | [Description("空箱å
¥åº")] |
| | | InEmpty = 600, |
| | | |
| | | /// <summary> |
| | | /// å··éå
ç§»åº |
| | | /// </summary> |
| | | [Description("å··éå
ç§»åº")] |
| | | Relocation = 900 |
| | | |
| | | } |
| | | } |
| | |
| | | bool TryUpdateIfChanged<T>(string key, T newValue, int expireSeconds = -1) where T : class; |
| | | |
| | | /// <summary> |
| | | /// å®å
¨æ´æ°ï¼ä»
å½å
åç¼åä¸çå¼ä¸expectedVersionå¹é
æ¶ææ´æ° |
| | | /// 鲿¢å¹¶ååå
¥æ¶æ§å¼è¦çæ°å¼ï¼éç¨äºå¤çº¿ç¨/å¤è¿ç¨åºæ¯ï¼ |
| | | /// </summary> |
| | | /// <typeparam name="T">å¼ç±»å</typeparam> |
| | | /// <param name="key">ç¼åé®</param> |
| | | /// <param name="newValue">æ°å¼</param> |
| | | /// <param name="expectedVersion">ææççæ¬ï¼éå¸¸æ¯æ§å¯¹è±¡çæä¸ªå±æ§å¼ï¼å¦æ¶é´æ³ï¼</param> |
| | | /// <param name="versionExtractor">ä»å¯¹è±¡æåçæ¬å·ç彿°</param> |
| | | /// <param name="expireSeconds">è¿ææ¶é´ï¼ç§ï¼</param> |
| | | /// <returns>æ¯å¦æ´æ°æå</returns> |
| | | bool TrySafeUpdate<T>( |
| | | string key, |
| | | T newValue, |
| | | object? expectedVersion, |
| | | Func<T, object?> versionExtractor, |
| | | int expireSeconds = -1) where T : class; |
| | | |
| | | /// <summary> |
| | | /// è·åææ·»å ï¼Keyåå¨åè¿åç°æå¼ï¼ä¸åå¨åæ·»å å¹¶è¿åæ°å¼ |
| | | /// </summary> |
| | | string GetOrAdd(string key, string value, int expireSeconds = -1); |
| | |
| | | return true; |
| | | } |
| | | |
| | | public bool TrySafeUpdate<T>( |
| | | string key, |
| | | T newValue, |
| | | object? expectedVersion, |
| | | Func<T, object?> versionExtractor, |
| | | int expireSeconds = -1) where T : class |
| | | { |
| | | var existing = Get<T>(key); |
| | | if (existing == null) return false; |
| | | |
| | | // æ£æ¥çæ¬æ¯å¦å¹é
|
| | | var currentVersion = versionExtractor(existing); |
| | | if (!Equals(currentVersion, expectedVersion)) |
| | | { |
| | | return false; // çæ¬ä¸å¹é
ï¼æç»æ´æ° |
| | | } |
| | | |
| | | Remove(key); |
| | | AddObject(key, newValue, expireSeconds); |
| | | return true; |
| | | } |
| | | |
| | | public string GetOrAdd(string key, string value, int expireSeconds = -1) |
| | | { |
| | | var existing = _cache.Get(key)?.ToString(); |
| | |
| | | try |
| | | { |
| | | var keyStr = redisKey.ToString(); |
| | | |
| | | // è·³è¿æé¤çkeyåç¼ï¼å¦è®¾å¤ç¶æçé¢ç¹åå¨çæ°æ®ï¼ |
| | | if (_options.SyncExcludePrefixes.Any(prefix => keyStr.StartsWith(prefix, StringComparison.Ordinal))) |
| | | { |
| | | _logger.LogTrace("è·³è¿æé¤çkey: {Key}", keyStr); |
| | | skippedCount++; |
| | | continue; |
| | | } |
| | | |
| | | _trackedKeys.AddOrUpdate(keyStr, true, (_, _) => true); |
| | | |
| | | // è·åRedisä¸çå¼ |
| | |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å®å
¨æ´æ°ï¼ä»
å½å
åç¼åä¸çå¼ä¸expectedVersionå¹é
æ¶ææ´æ° |
| | | /// 鲿¢å¹¶ååå
¥æ¶æ§å¼è¦çæ°å¼ |
| | | /// </summary> |
| | | /// <typeparam name="T">å¼ç±»å</typeparam> |
| | | /// <param name="key">ç¼åé®</param> |
| | | /// <param name="newValue">æ°å¼</param> |
| | | /// <param name="expectedVersion">ææççæ¬ï¼éå¸¸æ¯æ§å¯¹è±¡çåå¸å¼ææ¶é´æ³ï¼</param> |
| | | /// <param name="versionExtractor">ä»å¯¹è±¡æåçæ¬å·ç彿°</param> |
| | | /// <param name="expireSeconds">è¿ææ¶é´</param> |
| | | /// <returns>æ¯å¦æ´æ°æå</returns> |
| | | public bool TrySafeUpdate<T>( |
| | | string key, |
| | | T newValue, |
| | | object? expectedVersion, |
| | | Func<T, object?> versionExtractor, |
| | | int expireSeconds = -1) where T : class |
| | | { |
| | | var fullKey = BuildKey(key); |
| | | |
| | | // ä»Redisè·åå½åå¼ |
| | | string? existingJson = null; |
| | | T? existingValue = default; |
| | | if (RedisAvailable) |
| | | { |
| | | try |
| | | { |
| | | var value = _connectionManager.GetDatabase().StringGet(fullKey); |
| | | if (!value.IsNullOrEmpty) |
| | | { |
| | | existingJson = value.ToString(); |
| | | existingValue = _serializer.Deserialize<T>(existingJson); |
| | | } |
| | | } |
| | | catch { } |
| | | } |
| | | |
| | | // 妿Redisä¸å¯ç¨ï¼ä»å
åç¼åè·å |
| | | if (existingValue == null && _options.EnableL1Cache) |
| | | { |
| | | if (_memoryCache.TryGetValue(fullKey, out string? cached) && cached != null) |
| | | { |
| | | existingValue = _serializer.Deserialize<T>(cached); |
| | | existingJson = cached; |
| | | } |
| | | else |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | // æ£æ¥çæ¬æ¯å¦å¹é
|
| | | if (existingValue != null) |
| | | { |
| | | var currentVersion = versionExtractor(existingValue); |
| | | if (!Equals(currentVersion, expectedVersion)) |
| | | { |
| | | _logger.LogWarning("TrySafeUpdateçæ¬ä¸å¹é
, key={Key}, expected={Expected}, current={Current}", |
| | | key, expectedVersion, currentVersion); |
| | | return false; // çæ¬ä¸å¹é
ï¼æç»æ´æ° |
| | | } |
| | | } |
| | | |
| | | // çæ¬å¹é
ï¼æ§è¡æ´æ° |
| | | var newJson = _serializer.Serialize(newValue); |
| | | |
| | | // å
åå
¥Redis |
| | | if (RedisAvailable) |
| | | { |
| | | try |
| | | { |
| | | var expiry = expireSeconds > 0 ? TimeSpan.FromSeconds(expireSeconds) : (TimeSpan?)null; |
| | | if (!_connectionManager.GetDatabase().StringSet(fullKey, newJson, expiry)) |
| | | { |
| | | _logger.LogWarning("Redis TrySafeUpdateåå
¥å¤±è´¥, key={Key}", key); |
| | | return _options.FallbackToMemory && _options.EnableL1Cache; |
| | | } |
| | | else |
| | | { |
| | | _logger.LogInformation("Redis TrySafeUpdateåå
¥æå, key={Key}", key); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogWarning(ex, "Redis TrySafeUpdateåå
¥å¤±è´¥, key={Key}", key); |
| | | return _options.FallbackToMemory && _options.EnableL1Cache; |
| | | } |
| | | } |
| | | |
| | | // æ´æ°å
åç¼å |
| | | if (_options.EnableL1Cache) |
| | | { |
| | | SetMemoryCache(fullKey, newJson, expireSeconds, false); |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | public object? Get(Type type, string key) |
| | | { |
| | | var fullKey = BuildKey(key); |
| | |
| | | return Db.StringSet(fullKey, newJson, expiry, When.Exists); |
| | | } |
| | | |
| | | public bool TrySafeUpdate<T>( |
| | | string key, |
| | | T newValue, |
| | | object? expectedVersion, |
| | | Func<T, object?> versionExtractor, |
| | | int expireSeconds = -1) where T : class |
| | | { |
| | | var fullKey = BuildKey(key); |
| | | var existing = Db.StringGet(fullKey); |
| | | if (existing.IsNullOrEmpty) return false; |
| | | |
| | | // ååºååç°æå¼ |
| | | var existingValue = _serializer.Deserialize<T>(existing.ToString()!); |
| | | if (existingValue == null) return false; |
| | | |
| | | // æ£æ¥çæ¬æ¯å¦å¹é
|
| | | var currentVersion = versionExtractor(existingValue); |
| | | if (!Equals(currentVersion, expectedVersion)) |
| | | { |
| | | return false; // çæ¬ä¸å¹é
ï¼æç»æ´æ° |
| | | } |
| | | |
| | | // çæ¬å¹é
ï¼æ§è¡æ´æ° |
| | | var newJson = _serializer.Serialize(newValue); |
| | | var expiry = expireSeconds > 0 ? TimeSpan.FromSeconds(expireSeconds) : (TimeSpan?)null; |
| | | return Db.StringSet(fullKey, newJson, expiry, When.Exists); |
| | | } |
| | | |
| | | public string GetOrAdd(string key, string value, int expireSeconds = -1) |
| | | { |
| | | var fullKey = BuildKey(key); |
| | |
| | | /// </summary> |
| | | public int SyncBatchSize { get; set; } = 1000; |
| | | |
| | | /// <summary> |
| | | /// èªå¨åæ¥æé¤çkeyåç¼å表ï¼è¿äºkeyä¸ä¼è¢«èªå¨åæ¥è¦çï¼ |
| | | /// ä¾å¦ï¼["wcs:SocketDevices:"] 表示设å¤ç¶æä¸ä¼è¢«èªå¨åæ¥ |
| | | /// </summary> |
| | | public List<string> SyncExcludePrefixes { get; set; } = new(); |
| | | |
| | | public MonitoringOptions Monitoring { get; set; } = new(); |
| | | |
| | | public EvictionOptions Eviction { get; set; } = new(); |
| | |
| | | "SerializerType": "Newtonsoft", //åºååæ¹å¼ï¼Newtonsoft |
| | | "FallbackToMemory": true, //Redisä¸å¯ç¨æ¶æ¯å¦é级å°å
åç¼å |
| | | "KeyPrefix": "wcs:", //å
¨å±Keyåç¼ï¼ç¨äºé离ä¸åç³»ç»çæ°æ® |
| | | "EnableL1Cache": true, //æ¯å¦å¯ç¨L1å
åç¼åå±ãç¦ç¨ååªä½¿ç¨Redisï¼éç¨äºéè¦å¤é¨ä¿®æ¹Redisæ°æ®çåºæ¯ |
| | | "EnableAutoSync": true, //æ¯å¦å¯ç¨Rediså°å
åç¼åçèªå¨åæ¥ |
| | | "EnableL1Cache": false, //æ¯å¦å¯ç¨L1å
åç¼åå±ãç¦ç¨ååªä½¿ç¨Redisï¼éç¨äºéè¦å¤é¨ä¿®æ¹Redisæ°æ®çåºæ¯ |
| | | "EnableAutoSync": false, //æ¯å¦å¯ç¨Rediså°å
åç¼åçèªå¨åæ¥ |
| | | "SyncIntervalSeconds": 30, //èªå¨åæ¥é´éæ¶é´ï¼ç§ï¼ï¼å»ºè®®30-60ç§ |
| | | "SyncBatchSize": 1000, //忥æ¶å次æ¹éè·åçRedis keyæ°éä¸é |
| | | "SyncExcludePrefixes": [ "wcs:Code:SocketDevices:" ], //æé¤è®¾å¤ç¶ækeyä¸åä¸èªå¨åæ¥ï¼é²æ¢è¦çæ¬å°ä¿®æ¹ï¼ |
| | | "Monitoring": { |
| | | "Enabled": false, //æ¯å¦å¯ç¨çæ§ |
| | | "SlowLogThresholdMs": 100, //æ
¢æ¥è¯¢éå¼ï¼æ¯«ç§ï¼ |
| | |
| | | } |
| | | else if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.InboundGroup) |
| | | { |
| | | List<Dt_Router> routers = _routerService.QueryNextRoutes(item.SourceAddress, item.TargetAddress); |
| | | Dt_Router routers = _routerService.QueryNextRoute(item.SourceAddress); |
| | | //æä¸èèå¤è·¯å¾ |
| | | if (routers.Count > 0) |
| | | if (!routers.IsNullOrEmpty()) |
| | | { |
| | | task.TaskState = (int)TaskInStatusEnum.InNew; |
| | | task.CurrentAddress = item.SourceAddress; |
| | | task.NextAddress = routers.FirstOrDefault().ChildPosi; |
| | | task.NextAddress = routers.ChildPosi; |
| | | } |
| | | } |
| | | tasks.Add(task); |
| | |
| | | |
| | | _taskExecuteDetailService.AddTaskExecuteDetail(tasks.Select(x => x.TaskNum).ToList(), "æ¥æ¶WMSä»»å¡"); |
| | | |
| | | content = WebResponseContent.Instance.OK("æå"); |
| | | content = WebResponseContent.Instance.OK("æå", tasks); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | |
| | | task.TargetAddress = wmsTargetAddress; |
| | | task.CurrentAddress = task.NextAddress; |
| | | } |
| | | else |
| | | { |
| | | //_httpClientHelper.Post<WebResponseContent>(nameof(ConfigKey.GetTasksLocation), taskDto.ToJson(), nameof(ConfigKey.GetTasksLocation)); |
| | | //if (!result.IsSuccess && !result.Data.Status) |
| | | //{ |
| | | // return WebResponseContent.Instance.Error($"è°ç¨WMSæ¥å£è·åä»»å¡ç®æ å°å失败,ä»»å¡å·:ã{task.TaskNum}ã,é误信æ¯:ã{content.Message}ã"); |
| | | //} |
| | | } |
| | | } |
| | | else if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.OtherGroup) |
| | | { |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | namespace WIDESEAWCS_Tasks |
| | | { |
| | | /// <summary> |
| | | /// æºæ¢°ææ¡ç çæå¨ - è´è´£çææçæ¡ç |
| | | /// </summary> |
| | | public static class RobotBarcodeGenerator |
| | | { |
| | | /// <summary> |
| | | /// çææçæ¡ç |
| | | /// </summary> |
| | | /// <param name="prefix">æ¡ç åç¼ï¼é»è®¤ä¸ºç©º</param> |
| | | /// <returns>çæçæ¡ç å符串</returns> |
| | | public static string GenerateTrayBarcode(string prefix = "") |
| | | { |
| | | // å½åæ¥æ |
| | | string datePart = DateTime.Now.ToString("yyyyMMdd"); |
| | | |
| | | // æ¶é´æ³ï¼æ¶åç§ï¼ |
| | | string timePart = DateTime.Now.ToString("HHmmss"); |
| | | |
| | | // éæºæ° |
| | | string randomPart = Random.Shared.Next(100, 1000).ToString(); |
| | | |
| | | // ç»åï¼åç¼ + æ¥æ + æ¶é´ + éæºæ° |
| | | return prefix + datePart + timePart + randomPart; |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System.Collections.Concurrent; |
| | | using System.Net.Sockets; |
| | | using WIDESEAWCS_QuartzJob; |
| | | using WIDESEAWCS_Tasks.SocketServer; |
| | | |
| | | namespace WIDESEAWCS_Tasks |
| | | { |
| | | /// <summary> |
| | | /// æºæ¢°æå®¢æ·ç«¯è¿æ¥ç®¡çå¨ - è´è´£TCP客æ·ç«¯è¿æ¥ç®¡çåäºä»¶è®¢é
|
| | | /// </summary> |
| | | public class RobotClientManager |
| | | { |
| | | private readonly TcpSocketServer _tcpSocket; |
| | | private readonly RobotStateManager _stateManager; |
| | | |
| | | // è·è¸ªå·²ç»å¯å¨ HandleClientAsync ç客æ·ç«¯ |
| | | private static readonly ConcurrentDictionary<string, bool> _handleClientStarted = new(); |
| | | private static int _eventSubscribedFlag; |
| | | |
| | | public event EventHandler<RobotSocketState>? OnClientDisconnected; |
| | | |
| | | public RobotClientManager(TcpSocketServer tcpSocket, RobotStateManager stateManager) |
| | | { |
| | | _tcpSocket = tcpSocket; |
| | | _stateManager = stateManager; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// ç¡®ä¿å®¢æ·ç«¯å·²è¿æ¥å¹¶è®¢é
æ¶æ¯äºä»¶ |
| | | /// </summary> |
| | | /// <param name="ipAddress">设å¤IPå°å</param> |
| | | /// <param name="robotCrane">æºå¨äººè®¾å¤ä¿¡æ¯</param> |
| | | /// <returns>客æ·ç«¯æ¯å¦å¯ç¨ï¼å·²è¿æ¥ä¸æ¶æ¯å¤çå·²å¯å¨ï¼</returns> |
| | | public bool EnsureClientSubscribed(string ipAddress, RobotCraneDevice robotCrane) |
| | | { |
| | | // æ£æ¥æ¯å¦æè¯¥å®¢æ·ç«¯è¿æ¥ |
| | | var clientIds = _tcpSocket.GetClientIds(); |
| | | bool isClientConnected = clientIds.Contains(ipAddress); |
| | | |
| | | if (!isClientConnected) |
| | | { |
| | | // 客æ·ç«¯æªè¿æ¥ï¼æ¸
ç HandleClientAsync ç¶æ |
| | | _handleClientStarted.TryRemove(ipAddress, out _); |
| | | return false; |
| | | } |
| | | |
| | | // 订é
䏿¬¡ robot äºä»¶ï¼å
¨å±ä¸æ¬¡ï¼- messageäºä»¶ç±RobotJob订é
|
| | | if (System.Threading.Interlocked.CompareExchange(ref _eventSubscribedFlag, 1, 0) == 0) |
| | | { |
| | | _tcpSocket.RobotReceived += OnRobotReceived; |
| | | Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] æºå¨äººTCPæå¼äºä»¶å·²è®¢é
"); |
| | | } |
| | | |
| | | // è·åTcpClient |
| | | TcpClient? tcpClient = null; |
| | | _tcpSocket._clients.TryGetValue(ipAddress, out tcpClient); |
| | | |
| | | if (tcpClient == null) |
| | | { |
| | | // isClientConnected为true使 æ³è·åtcpClientï¼å表å¯è½ä¸åæ¥ |
| | | _handleClientStarted.TryRemove(ipAddress, out _); |
| | | return false; |
| | | } |
| | | |
| | | // æ£æ¥æ¯å¦å·²ç»ä¸ºè¿ä¸ªå®¢æ·ç«¯å¯å¨è¿ HandleClientAsync |
| | | bool alreadyStarted = _handleClientStarted.TryGetValue(ipAddress, out _); |
| | | |
| | | if (!alreadyStarted) |
| | | { |
| | | Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] å¯å¨å®¢æ·ç«¯æ¶æ¯å¤ç: {ipAddress}"); |
| | | |
| | | // éæ°è·åææ°ç state 对象 |
| | | var latestStateForSubscribe = _stateManager.GetState(ipAddress); |
| | | if (latestStateForSubscribe != null) |
| | | { |
| | | // æ 记为已å¯å¨ |
| | | _handleClientStarted[ipAddress] = true; |
| | | |
| | | _ = _tcpSocket.HandleClientAsync(tcpClient, robotCrane.IPAddress, _tcpSocket._cts.Token, latestStateForSubscribe) |
| | | .ContinueWith(t => |
| | | { |
| | | if (t.IsFaulted) |
| | | { |
| | | Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] HandleClientAsync error: {t.Exception?.GetBaseException().Message}"); |
| | | // åçé误æ¶ï¼ç§»é¤å¯å¨æ å¿ï¼å
è®¸ä¸æ¬¡éè¯ |
| | | _handleClientStarted.TryRemove(ipAddress, out _); |
| | | } |
| | | }, TaskContinuationOptions.OnlyOnFaulted); |
| | | |
| | | // æ´æ° IsEventSubscribed ç¶æ |
| | | _stateManager.TryUpdateStateSafely(ipAddress, s => |
| | | { |
| | | s.IsEventSubscribed = true; |
| | | return s; |
| | | }); |
| | | } |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// äºä»¶ï¼å®¢æ·ç«¯æå¼è¿æ¥æ¶è§¦å |
| | | /// </summary> |
| | | private Task<string?> OnRobotReceived(string clientId) |
| | | { |
| | | // 客æ·ç«¯æå¼è¿æ¥ï¼æ¸
ç HandleClientAsync å¯å¨æ å¿ |
| | | _handleClientStarted.TryRemove(clientId, out _); |
| | | |
| | | _stateManager.TryUpdateStateSafely(clientId, state => |
| | | { |
| | | state.IsEventSubscribed = false; |
| | | state.CurrentAction = ""; |
| | | state.OperStatus = ""; |
| | | state.RobotArmObject = 0; |
| | | state.RobotControlMode = 0; |
| | | state.RobotRunMode = 0; |
| | | return state; |
| | | }); |
| | | |
| | | // 触åæå¼è¿æ¥äºä»¶ |
| | | OnClientDisconnected?.Invoke(this, _stateManager.GetState(clientId) ?? new RobotSocketState { IPAddress = clientId }); |
| | | |
| | | return Task.FromResult<string?>(null); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ£æ¥å®¢æ·ç«¯æ¯å¦å·²è¿æ¥ |
| | | /// </summary> |
| | | public bool IsClientConnected(string ipAddress) |
| | | { |
| | | var clientIds = _tcpSocket.GetClientIds(); |
| | | return clientIds.Contains(ipAddress); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åéæ¶æ¯å°å®¢æ·ç«¯ |
| | | /// </summary> |
| | | public async Task<bool> SendToClientAsync(string ipAddress, string message) |
| | | { |
| | | return await _tcpSocket.SendToClientAsync(ipAddress, message); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åTcpSocketServerå¼ç¨ï¼ç¨äºRobotJobç´æ¥è®¿é®ï¼ |
| | | /// </summary> |
| | | public TcpSocketServer TcpSocket => _tcpSocket; |
| | | } |
| | | } |
| | |
| | | using HslCommunication; |
| | | using Newtonsoft.Json; |
| | | using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup; |
| | | using Quartz; |
| | | using System.Net; |
| | | using System.Net.Sockets; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Core; |
| | | using WIDESEAWCS_Common; |
| | | using WIDESEAWCS_Common.HttpEnum; |
| | | using WIDESEAWCS_Common.TaskEnum; |
| | | using WIDESEAWCS_Core; |
| | | using WIDESEAWCS_Core.Caches; |
| | | using WIDESEAWCS_Core.Helper; |
| | | using WIDESEAWCS_DTO.Stock; |
| | | using WIDESEAWCS_DTO.TaskInfo; |
| | | using WIDESEAWCS_ITaskInfoService; |
| | | using WIDESEAWCS_Model.Models; |
| | | using WIDESEAWCS_QuartzJob; |
| | |
| | | |
| | | namespace WIDESEAWCS_Tasks |
| | | { |
| | | /// <summary> |
| | | /// æºæ¢°æä»»å¡ä½ä¸ - è´è´£åè°æºæ¢°æå®¢æ·ç«¯è¿æ¥ãæ¶æ¯å¤çå任塿§è¡ |
| | | /// </summary> |
| | | [DisallowConcurrentExecution] |
| | | public class RobotJob : IJob |
| | | { |
| | | private const int MaxTaskTotalNum = 48; |
| | | |
| | | private readonly TcpSocketServer _TcpSocket; |
| | | private static int _messageSubscribedFlag; |
| | | |
| | | //private static readonly ConcurrentDictionary<string, RobotSocketState> _socketStates = new(); |
| | | private static int _eventSubscribedFlag; |
| | | |
| | | private readonly ITaskService _taskService; |
| | | private readonly RobotClientManager _clientManager; |
| | | private readonly RobotStateManager _stateManager; |
| | | private readonly RobotMessageHandler _messageHandler; |
| | | private readonly RobotTaskProcessor _taskProcessor; |
| | | private readonly IRobotTaskService _robotTaskService; |
| | | private readonly ICacheService _cache; |
| | | private readonly HttpClientHelper _httpClientHelper; |
| | | |
| | | private static IRobotTaskService _latestRobotTaskService = null!; |
| | | private static ITaskService _latestTaskService = null!; |
| | | |
| | | public RobotJob(TcpSocketServer TcpSocket, IRobotTaskService RobottaskService, ITaskService TaskService, ICacheService cache, HttpClientHelper httpClientHelper) |
| | | public RobotJob( |
| | | TcpSocketServer tcpSocket, |
| | | IRobotTaskService robotTaskService, |
| | | ITaskService taskService, |
| | | ICacheService cache, |
| | | HttpClientHelper httpClientHelper) |
| | | { |
| | | _TcpSocket = TcpSocket; |
| | | _robotTaskService = RobottaskService; |
| | | _taskService = TaskService; |
| | | _cache = cache; |
| | | _httpClientHelper = httpClientHelper; |
| | | _robotTaskService = robotTaskService; |
| | | |
| | | _latestRobotTaskService = RobottaskService; |
| | | _latestTaskService = TaskService; |
| | | // åå§å管çå¨ |
| | | _stateManager = new RobotStateManager(cache); |
| | | _taskProcessor = new RobotTaskProcessor(tcpSocket, _stateManager, robotTaskService, taskService, httpClientHelper); |
| | | _clientManager = new RobotClientManager(tcpSocket, _stateManager); |
| | | _messageHandler = new RobotMessageHandler(tcpSocket, _stateManager, cache, robotTaskService, _taskProcessor); |
| | | |
| | | // 订é
客æ·ç«¯ç®¡çå¨çäºä»¶ |
| | | _clientManager.OnClientDisconnected += OnClientDisconnected; |
| | | |
| | | // 订é
TCPæå¡å¨çæ¶æ¯äºä»¶ï¼å
¨å±åªè®¢é
䏿¬¡ï¼ |
| | | if (System.Threading.Interlocked.CompareExchange(ref _messageSubscribedFlag, 1, 0) == 0) |
| | | { |
| | | tcpSocket.MessageReceived += _messageHandler.HandleMessageReceivedAsync; |
| | | Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] æºå¨äººTCPæ¶æ¯äºä»¶å·²è®¢é
"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 客æ·ç«¯æå¼è¿æ¥æ¶çå¤ç |
| | | /// </summary> |
| | | private void OnClientDisconnected(object? sender, RobotSocketState state) |
| | | { |
| | | // å¯ä»¥å¨è¿éæ·»å æå¼è¿æ¥åçå¤çé»è¾ |
| | | Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 客æ·ç«¯å·²æå¼è¿æ¥: {state.IPAddress}"); |
| | | } |
| | | |
| | | public async Task Execute(IJobExecutionContext context) |
| | |
| | | string ipAddress = robotCrane.IPAddress; |
| | | |
| | | // è·åæåå»ºç¶æ |
| | | RobotSocketState state = _cache.GetOrAdd($"{RedisPrefix.Code}:{RedisName.SocketDevices}:{ipAddress}", _ => new RobotSocketState |
| | | { |
| | | IPAddress = ipAddress, |
| | | RobotCrane = robotCrane |
| | | }); |
| | | |
| | | // æ´æ°è®¾å¤ä¿¡æ¯ |
| | | RobotSocketState state = _stateManager.GetOrCreateState(ipAddress, robotCrane); |
| | | state.RobotCrane = robotCrane; |
| | | |
| | | try |
| | | { |
| | | // æ£æ¥æ¯å¦æè¯¥å®¢æ·ç«¯è¿æ¥ |
| | | var clientIds = _TcpSocket.GetClientIds(); |
| | | if (!clientIds.Contains(ipAddress)) |
| | | // ç¡®ä¿å®¢æ·ç«¯å·²è¿æ¥å¹¶è®¢é
æ¶æ¯äºä»¶ |
| | | if (!_clientManager.EnsureClientSubscribed(ipAddress, robotCrane)) |
| | | { |
| | | return; |
| | | return; // 客æ·ç«¯æªè¿æ¥æè®¢é
失败ï¼è·³è¿æ¬æ¬¡æ§è¡ |
| | | } |
| | | |
| | | // 订é
䏿¬¡ message äºä»¶ï¼å
¨å±ä¸æ¬¡ï¼ |
| | | if (Interlocked.CompareExchange(ref _eventSubscribedFlag, 1, 0) == 0) |
| | | { |
| | | _TcpSocket.MessageReceived += _TcpSocket_MessageReceived; |
| | | _TcpSocket.RobotReceived += _TcpSocket_RobotReceived; |
| | | } |
| | | |
| | | if (!state.IsEventSubscribed) |
| | | { |
| | | if (_TcpSocket._clients.TryGetValue(ipAddress, out TcpClient client)) |
| | | { |
| | | _ = _TcpSocket.HandleClientAsync(client, robotCrane.IPAddress, _TcpSocket._cts.Token, state) |
| | | .ContinueWith(t => |
| | | { |
| | | if (t.IsFaulted) |
| | | Console.WriteLine($"HandleClientAsync error: {t.Exception?.GetBaseException().Message}"); |
| | | }, TaskContinuationOptions.OnlyOnFaulted); |
| | | state.IsEventSubscribed = true; |
| | | |
| | | // æ´æ°ç¼åä¸çç¶æ |
| | | _cache.TryUpdateIfChanged($"{RedisPrefix.Code}:{RedisName.SocketDevices}:{ipAddress}", state); |
| | | } |
| | | } |
| | | |
| | | // è·åä»»å¡å¹¶ç¼åå°ç¶æä¸ |
| | | Dt_RobotTask? task = GetTask(robotCrane); |
| | | // è·åä»»å¡å¹¶å¤ç |
| | | Dt_RobotTask? task = _taskProcessor.GetTask(robotCrane); |
| | | if (task != null) |
| | | { |
| | | if (task.RobotTaskTotalNum <= MaxTaskTotalNum) |
| | | // æ¯æ¬¡å¤æåéæ°ä»ç¼åè·åææ°ç¶æ |
| | | var latestState = _stateManager.GetState(ipAddress); |
| | | if (latestState == null) return; |
| | | |
| | | if (latestState.RobotTaskTotalNum < MaxTaskTotalNum) |
| | | { |
| | | // å¤çæ£å¨æ§è¡çä»»å¡ |
| | | if (state.RobotRunMode == 2 && state.RobotControlMode == 1 && state.OperStatus != "Running") |
| | | { |
| | | if (state.CurrentAction == "PickFinished" && state.RobotArmObject == 1 && task.RobotTaskState == TaskRobotStatusEnum.RobotPickFinish.GetHashCode()) |
| | | { |
| | | string taskString = $"Putbattery,{task.RobotTargetAddress}"; |
| | | bool result = await _TcpSocket.SendToClientAsync(ipAddress, taskString); |
| | | if (result) |
| | | { |
| | | task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode(); |
| | | await _robotTaskService.UpdateRobotTaskAsync(task); |
| | | } |
| | | } |
| | | else if (state.CurrentAction == "PutFinished" && state.RobotArmObject == 0 && task.RobotTaskState == TaskRobotStatusEnum.RobotPutFinish.GetHashCode()) |
| | | { |
| | | task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode(); |
| | | await _robotTaskService.UpdateRobotTaskAsync(task); |
| | | } |
| | | else if (state.OperStatus == "Homed" && state.RobotArmObject == 0 && task.RobotTaskState != TaskRobotStatusEnum.RobotExecuting.GetHashCode()) |
| | | { |
| | | // éæºçæä¸¤å¤©æçæ¡ç åæ¾å°ä¸¤ä¸ªåééé¢ |
| | | // å®ä¹åç¼ï¼ä¾å¦ï¼TRAY代表æçï¼ |
| | | // ç»ç读åçº¿ä½æ¡ç |
| | | if (task.RobotTaskType == RobotTaskTypeEnum.GroupPallet.GetHashCode()) |
| | | { |
| | | string prefix = "TRAY"; |
| | | |
| | | // çæä¸¤ä¸ªæçæ¡ç |
| | | string trayBarcode1 = GenerateTrayBarcode(state, prefix); |
| | | string trayBarcode2 = GenerateTrayBarcode(state, prefix); |
| | | if (!trayBarcode1.IsNullOrEmpty() && !trayBarcode2.IsNullOrEmpty()) |
| | | { |
| | | |
| | | await SendSocketRobotPickAsync(task, state); |
| | | } |
| | | } |
| | | else // æ¢çç´æ¥åéåè´§å°å |
| | | { |
| | | await SendSocketRobotPickAsync(task, state); |
| | | } |
| | | } |
| | | |
| | | if (state.CurrentTask.IsNullOrEmpty() && state.ToJson() != task.ToJson()) |
| | | { |
| | | state.IsSplitPallet = task.RobotTaskType == RobotTaskTypeEnum.SplitPallet.GetHashCode(); |
| | | state.IsGroupPallet = task.RobotTaskType == RobotTaskTypeEnum.GroupPallet.GetHashCode() || task.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode(); |
| | | state.CurrentTask = task; |
| | | // æ´æ°ç¼åä¸çç¶æ |
| | | _cache.TryUpdateIfChanged($"{RedisPrefix.Code}:{RedisName.SocketDevices}:{ipAddress}", state); |
| | | } |
| | | } |
| | | await ProcessTaskAsync(latestState, task, ipAddress); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception) |
| | | { |
| | | // å¼å¸¸å¤çå·²å¨åç»ä»¶ä¸å¤ç |
| | | } |
| | | finally |
| | | { |
| | | // å¯éï¼å¨è¿éå¤çä»»ä½éè¦å¨ä»»å¡å®æåæ§è¡çæ¸
çå·¥ä½ |
| | | } |
| | | } |
| | | |
| | | //ä¸´æ¶æµè¯ç¨ |
| | | private static string GenerateTrayBarcode(RobotSocketState state, string prefix = "") |
| | | { |
| | | // å½åæ¥æ |
| | | string datePart = DateTime.Now.ToString("yyyyMMdd"); |
| | | |
| | | // æ¶é´æ³ï¼æ¶åç§ï¼ |
| | | string timePart = DateTime.Now.ToString("HHmmss"); |
| | | |
| | | // éæºæ° |
| | | string randomPart = Random.Shared.Next(100, 1000).ToString(); |
| | | |
| | | // ç»åï¼åç¼ + æ¥æ + æ¶é´ + éæºæ° |
| | | var barCode = prefix + datePart + timePart + randomPart; |
| | | state.CellBarcode.Add(barCode); |
| | | |
| | | return barCode; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// äºä»¶ï¼å®¢æ·ç«¯æå¼è¿æ¥æ¶è§¦å |
| | | /// å¤çæºæ¢°æä»»å¡ |
| | | /// </summary> |
| | | /// <param name="clientId"></param> |
| | | /// <returns></returns> |
| | | private Task<string?> _TcpSocket_RobotReceived(string clientId) |
| | | private async Task ProcessTaskAsync(RobotSocketState latestState, Dt_RobotTask task, string ipAddress) |
| | | { |
| | | var robotSocketState = _cache.Get<RobotSocketState>($"{RedisPrefix.Code}:{RedisName.SocketDevices}:{clientId}"); |
| | | robotSocketState.IsEventSubscribed = false; |
| | | robotSocketState.CurrentAction = ""; |
| | | robotSocketState.OperStatus = ""; |
| | | robotSocketState.RobotArmObject = 0; |
| | | robotSocketState.RobotControlMode = 0; |
| | | robotSocketState.RobotRunMode = 0; |
| | | _cache.TryUpdateIfChanged($"{RedisPrefix.Code}:{RedisName.SocketDevices}:{clientId}", robotSocketState); |
| | | return Task.FromResult<string?>(null); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// äºä»¶ï¼æ¶å°æ¶æ¯æ¶è§¦å |
| | | /// </summary> |
| | | /// <param name="message"></param> |
| | | /// <param name="isJson"></param> |
| | | /// <param name="client"></param> |
| | | /// <param name="state"></param> |
| | | /// <returns></returns> |
| | | private async Task<string?> _TcpSocket_MessageReceived(string message, bool isJson, TcpClient client, RobotSocketState state) |
| | | { |
| | | if (!(bool)(_cache?.TryGetValue($"{RedisPrefix.Code}:{RedisName.SocketDevices}:{client.Client.RemoteEndPoint}", out state))) |
| | | return null; |
| | | |
| | | string messageLower = message.ToLowerInvariant(); |
| | | |
| | | if (await IsSimpleCommandAsync(messageLower, state)) |
| | | // å¤çæ£å¨æ§è¡çä»»å¡ |
| | | if (latestState.RobotRunMode == 2 && latestState.RobotControlMode == 1 && latestState.OperStatus != "Running") |
| | | { |
| | | await _TcpSocket.SendMessageAsync(client, message); |
| | | } |
| | | else if (IsPrefixCommand(messageLower)) |
| | | { |
| | | try |
| | | // åè´§å®æç¶æå¤ç |
| | | if ((latestState.CurrentAction == "PickFinished" || latestState.CurrentAction == "AllPickFinished") && latestState.RobotArmObject == 1 && |
| | | task.RobotTaskState == TaskRobotStatusEnum.RobotPickFinish.GetHashCode()) |
| | | { |
| | | var parts = message.Split(','); |
| | | if (parts.Length >= 1 && state.CurrentTask != null) |
| | | { |
| | | var cmd = parts[0].ToLowerInvariant(); |
| | | int[] positions = parts.Skip(1) |
| | | .Select(p => int.TryParse(p, out int value) ? value : (int?)null) |
| | | .Where(v => v.HasValue && v.Value != 0) |
| | | .Select(v => v!.Value) |
| | | .ToArray(); |
| | | |
| | | var task = await _latestRobotTaskService.Repository.QueryFirstAsync(x => x.RobotTaskId == state.CurrentTask.RobotTaskId); |
| | | |
| | | if (cmd.StartsWith("pickfinished")) |
| | | { |
| | | if (state.IsSplitPallet) |
| | | { |
| | | var stockDTO = BuildStockDTO(state, positions); |
| | | state.LastPickPositions = positions; |
| | | |
| | | var result = _httpClientHelper.Post<WebResponseContent>(nameof(ConfigKey.SplitPalletAsync), stockDTO.ToJson()); |
| | | |
| | | if (result.Data.Status && result.IsSuccess) |
| | | { |
| | | state.CurrentAction = "PickFinished"; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | state.CurrentAction = "PickFinished"; |
| | | } |
| | | |
| | | state.LastPickPositions = positions; |
| | | task.RobotTaskState = TaskRobotStatusEnum.RobotPickFinish.GetHashCode(); |
| | | await _latestRobotTaskService.Repository.UpdateDataAsync(task); |
| | | } |
| | | else if (cmd.StartsWith("putfinished")) |
| | | { |
| | | bool putSuccess = true; |
| | | if (state.IsGroupPallet) |
| | | { |
| | | state.LastPutPositions = positions; |
| | | var stockDTO = BuildStockDTO(state, positions); |
| | | var configKey = state.CurrentTask?.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode() |
| | | ? nameof(ConfigKey.ChangePalletAsync) : nameof(ConfigKey.GroupPalletAsync); |
| | | |
| | | var result = _httpClientHelper.Post<WebResponseContent>(configKey, stockDTO.ToJson()); |
| | | putSuccess = result.Data.Status && result.IsSuccess; |
| | | } |
| | | |
| | | if (putSuccess) |
| | | { |
| | | state.CurrentAction = "PutFinished"; |
| | | state.RobotTaskTotalNum += positions.Length; |
| | | task.RobotTaskTotalNum += positions.Length; |
| | | } |
| | | |
| | | task.RobotTaskState = TaskRobotStatusEnum.RobotPutFinish.GetHashCode(); |
| | | await _latestRobotTaskService.Repository.UpdateDataAsync(task); |
| | | } |
| | | |
| | | await _TcpSocket.SendMessageAsync(client, message); |
| | | } |
| | | await HandlePickFinishedStateAsync(latestState, task, ipAddress); |
| | | } |
| | | catch (Exception ex) |
| | | // æ¾è´§å®æç¶æå¤ç |
| | | else if ((latestState.CurrentAction == "PutFinished" || latestState.CurrentAction == "AllPutFinished") && latestState.OperStatus == "Homed" && |
| | | latestState.RobotArmObject == 0 && |
| | | (task.RobotTaskState == TaskRobotStatusEnum.RobotPutFinish.GetHashCode() || |
| | | task.RobotTaskState != TaskRobotStatusEnum.RobotExecuting.GetHashCode())) |
| | | { |
| | | Console.WriteLine($"RobotJob MessageReceived Error: {ex.Message}"); |
| | | await HandlePutFinishedStateAsync(latestState, task, ipAddress); |
| | | } |
| | | } |
| | | |
| | | // æ´æ°ç¼åä¸çç¶æ |
| | | _cache.TryUpdateIfChanged($"{RedisPrefix.Code}:{RedisName.SocketDevices}:{state.IPAddress}", state); |
| | | |
| | | return null; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æºæ¢°æç®åå½ä»¤å¤ç |
| | | /// å¤çåè´§å®æç¶æ |
| | | /// </summary> |
| | | /// <param name="message"></param> |
| | | /// <param name="state"></param> |
| | | /// <returns></returns> |
| | | private async Task<bool> IsSimpleCommandAsync(string message, RobotSocketState state) |
| | | private async Task HandlePickFinishedStateAsync(RobotSocketState latestState, Dt_RobotTask task, string ipAddress) |
| | | { |
| | | switch (message) |
| | | { |
| | | case "homing": |
| | | state.OperStatus = "Homing"; |
| | | return true; |
| | | |
| | | case "homed": |
| | | state.OperStatus = "Homed"; |
| | | return true; |
| | | |
| | | case "picking": |
| | | state.CurrentAction = "Picking"; |
| | | return true; |
| | | |
| | | case "puting": |
| | | state.CurrentAction = "Putting"; |
| | | return true; |
| | | |
| | | case "allpickfinished": // åè´§å®æ |
| | | state.CurrentAction = "AllPickFinished"; |
| | | if (state.CurrentTask?.RobotTaskType == RobotTaskTypeEnum.SplitPallet.GetHashCode() || state.CurrentTask?.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode()) |
| | | { |
| | | await HandleInboundTaskAsync(state, useSourceAddress: true); |
| | | } |
| | | return true; |
| | | |
| | | case "allputfinished": // æ¾è´§å®æ |
| | | state.CurrentAction = "AllPutFinished"; |
| | | if (state.CurrentTask?.RobotTaskType == RobotTaskTypeEnum.GroupPallet.GetHashCode() || state.CurrentTask?.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode()) |
| | | { |
| | | await HandleInboundTaskAsync(state, useSourceAddress: false); |
| | | } |
| | | return true; |
| | | |
| | | case "running": |
| | | state.OperStatus = "Running"; |
| | | return true; |
| | | |
| | | case "pausing": |
| | | state.OperStatus = "Pausing"; |
| | | return true; |
| | | |
| | | case "warming": |
| | | state.OperStatus = "Warming"; |
| | | return true; |
| | | |
| | | case "emstoping": |
| | | state.OperStatus = "Emstoping"; |
| | | return true; |
| | | |
| | | case "runmode,1": |
| | | state.RobotRunMode = 1; |
| | | return true; |
| | | |
| | | case "runmode,2": |
| | | state.RobotRunMode = 2; |
| | | return true; |
| | | |
| | | case "controlmode,1": |
| | | state.RobotControlMode = 1; |
| | | return true; |
| | | |
| | | case "controlmode,2": |
| | | state.RobotControlMode = 2; |
| | | return true; |
| | | |
| | | case "armobject,1": |
| | | state.RobotArmObject = 1; |
| | | return true; |
| | | |
| | | case "armobject,0": |
| | | state.RobotArmObject = 0; |
| | | return true; |
| | | |
| | | default: |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | private async Task HandleInboundTaskAsync(RobotSocketState state, bool useSourceAddress) |
| | | { |
| | | var currentTask = state.CurrentTask; |
| | | if (currentTask == null) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | string roadway = currentTask.RobotRoadway == "1" ? "GWSC001" : currentTask.RobotRoadway == "2" ? "HCSC001" : "SC001"; |
| | | int warehouseId = currentTask.RobotRoadway == "1" ? 1 : currentTask.RobotRoadway == "2" ? 2 : 3; |
| | | |
| | | CreateTaskDto taskDto = new CreateTaskDto |
| | | { |
| | | PalletCode = currentTask.RobotTargetAddressPalletCode ?? string.Empty, |
| | | SourceAddress = currentTask.RobotSourceAddress ?? string.Empty, |
| | | TargetAddress = currentTask.RobotTargetAddress ?? string.Empty, |
| | | Roadway = roadway, |
| | | WarehouseId = warehouseId, |
| | | PalletType = 1, |
| | | TaskType = 4 |
| | | }; |
| | | var result = _httpClientHelper.Post<WebResponseContent>(nameof(ConfigKey.CreateTaskInboundAsync), taskDto.ToJson()); |
| | | if (!result.Data.Status && result.IsSuccess) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | WMSTaskDTO taskDTO = JsonConvert.DeserializeObject<WMSTaskDTO>(result.Data.ToString() ?? string.Empty) ?? new WMSTaskDTO(); |
| | | var content = _latestTaskService.ReceiveWMSTask(new List<WMSTaskDTO> { taskDTO }); |
| | | if (!content.Status) return; |
| | | |
| | | var taskInfo = _latestTaskService.QueryByTaskNum(taskDTO.TaskNum); |
| | | if (taskInfo == null) return; |
| | | |
| | | string targetAddress = useSourceAddress ? taskDTO.SourceAddress : taskDTO.TargetAddress; |
| | | |
| | | IDevice? device = Storage.Devices.FirstOrDefault(x => x.DeviceProDTOs.Any(d => d.DeviceChildCode == targetAddress)); |
| | | device?.Communicator.Write(nameof(ConveyorLineDBNameNew.Target), taskInfo.NextAddress); |
| | | device?.Communicator.Write(nameof(ConveyorLineDBNameNew.TaskNo), taskDTO.TaskNum); |
| | | device?.Communicator.Write(nameof(ConveyorLineDBNameNew.WCS_STB), 1); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æºæ¢°æåç¼å½ä»¤å¤ç |
| | | /// </summary> |
| | | /// <param name="message"></param> |
| | | /// <returns></returns> |
| | | private static bool IsPrefixCommand(string message) |
| | | { |
| | | return message.StartsWith("pickfinished") || message.StartsWith("putfinished"); |
| | | } |
| | | |
| | | private static StockDTO BuildStockDTO(RobotSocketState state, int[] positions) |
| | | { |
| | | string sss = state.ToJson(); |
| | | return new StockDTO |
| | | { |
| | | SourceLineNo = state.CurrentTask.RobotSourceAddressLineCode, |
| | | SourcePalletNo = state.CurrentTask.RobotSourceAddressPalletCode, |
| | | TargetPalletNo = state.CurrentTask.RobotTargetAddressPalletCode, |
| | | TargetLineNo = state.CurrentTask.RobotTargetAddressLineCode, |
| | | Details = positions |
| | | .Where(x => x > 0) |
| | | .OrderBy(x => x) |
| | | .Select((x, idx) => new StockDetailDTO |
| | | { |
| | | Quantity = state.RobotTaskTotalNum > 0 ? state.RobotTaskTotalNum + positions.Length : positions.Length, |
| | | Channel = x, |
| | | CellBarcode = state.CellBarcode?.Count > 0 ? state.CellBarcode[x - 1] : "" |
| | | }) |
| | | .ToList() |
| | | }; |
| | | } |
| | | |
| | | private Dt_RobotTask? GetTask(RobotCraneDevice robotCrane) |
| | | { |
| | | return _robotTaskService.QueryRobotCraneTask(robotCrane.DeviceCode); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åéæºæ¢°æåè´§å½ä»¤ |
| | | /// </summary> |
| | | /// <param name="task"></param> |
| | | /// <param name="state"></param> |
| | | /// <returns></returns> |
| | | private async Task SendSocketRobotPickAsync(Dt_RobotTask task, RobotSocketState state) |
| | | { |
| | | string taskString = $"Pickbattery,{task.RobotSourceAddress}"; |
| | | // åé任塿令 |
| | | bool result = await _TcpSocket.SendToClientAsync(state.IPAddress, taskString); |
| | | string taskString = $"Putbattery,{task.RobotTargetAddress}"; |
| | | bool result = await _clientManager.SendToClientAsync(ipAddress, taskString); |
| | | if (result) |
| | | { |
| | | // TODO å¤çæååé任塿令åçé»è¾ |
| | | task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode(); |
| | | result = await _robotTaskService.UpdateRobotTaskAsync(task); |
| | | // æ´æ°ç¼åä¸çç¶æ |
| | | _cache.TryUpdateIfChanged($"{RedisPrefix.Code}:{RedisName.SocketDevices}:{state.IPAddress}", state); |
| | | |
| | | // éæ°è·åææ°ç¶æå¹¶æ´æ° |
| | | var stateToUpdate = _stateManager.GetState(ipAddress); |
| | | if (stateToUpdate != null) |
| | | { |
| | | stateToUpdate.CurrentTask = task; |
| | | if (_stateManager.TryUpdateStateSafely(ipAddress, stateToUpdate)) |
| | | await _robotTaskService.UpdateRobotTaskAsync(task); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å¤çæ¾è´§å®æç¶æ |
| | | /// </summary> |
| | | private async Task HandlePutFinishedStateAsync(RobotSocketState latestState, Dt_RobotTask task, string ipAddress) |
| | | { |
| | | // éæ°è·åææ°ç¶æ |
| | | var stateForUpdate = _stateManager.GetState(ipAddress); |
| | | if (stateForUpdate == null) return; |
| | | |
| | | if (!stateForUpdate.IsSplitPallet && !stateForUpdate.IsGroupPallet) |
| | | { |
| | | stateForUpdate.IsSplitPallet = task.RobotTaskType == RobotTaskTypeEnum.SplitPallet.GetHashCode(); |
| | | stateForUpdate.IsGroupPallet = task.RobotTaskType == RobotTaskTypeEnum.GroupPallet.GetHashCode() || |
| | | task.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode(); |
| | | } |
| | | |
| | | if (task.RobotTaskType == RobotTaskTypeEnum.GroupPallet.GetHashCode()) |
| | | { |
| | | string prefix = "TRAY"; |
| | | |
| | | // çæä¸¤ä¸ªæçæ¡ç |
| | | string trayBarcode1 = RobotBarcodeGenerator.GenerateTrayBarcode(prefix); |
| | | string trayBarcode2 = RobotBarcodeGenerator.GenerateTrayBarcode(prefix); |
| | | if (!trayBarcode1.IsNullOrEmpty() && !trayBarcode2.IsNullOrEmpty()) |
| | | { |
| | | stateForUpdate.CellBarcode.Add(trayBarcode1); |
| | | stateForUpdate.CellBarcode.Add(trayBarcode2); |
| | | await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate); |
| | | } |
| | | } |
| | | else // ä»»å¡å¼å§æ§è¡ç´æ¥åéåè´§å°å |
| | | { |
| | | await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate); |
| | | } |
| | | } |
| | | } |
| | | |
| | | public class RobotSocketState |
| | | { |
| | | public string IPAddress { get; set; } = string.Empty; |
| | | |
| | | /// <summary> |
| | | /// æ¯å¦å·²è®¢é
æ¶æ¯äºä»¶ |
| | | /// </summary> |
| | | public bool IsEventSubscribed { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æºæ¢°æè¿è¡æ¨¡å¼ |
| | | /// </summary> |
| | | public int? RobotRunMode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æºæ¢°ææ§å¶æ¨¡å¼ |
| | | /// </summary> |
| | | public int? RobotControlMode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æºæ¢°ææ¯å¦æåç©æï¼0-æ ç©æï¼1-æç©æ |
| | | /// </summary> |
| | | public int? RobotArmObject { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æºæ¢°æè®¾å¤ä¿¡æ¯ |
| | | /// </summary> |
| | | public RobotCraneDevice? RobotCrane { get; set; } |
| | | |
| | | /// <summary> |
| | | /// å½åå¨ä½ |
| | | /// </summary> |
| | | public string? CurrentAction { get; set; } |
| | | |
| | | /// <summary> |
| | | /// å½åç¶æ |
| | | /// </summary> |
| | | public string? OperStatus { get; set; } |
| | | |
| | | /// <summary> |
| | | /// åè´§å®æä½ç½® |
| | | /// </summary> |
| | | public int[]? LastPickPositions { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æ¾è´§å®æä½ç½® |
| | | /// </summary> |
| | | public int[]? LastPutPositions { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æåä½ç½®æ¡ç |
| | | /// </summary> |
| | | public List<string> CellBarcode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// å½åæåä»»å¡ |
| | | /// </summary> |
| | | public Dt_RobotTask? CurrentTask { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æ¯å¦éè¦æç |
| | | /// </summary> |
| | | public bool IsSplitPallet { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æ¯å¦éè¦ç»ç |
| | | /// </summary> |
| | | public bool IsGroupPallet { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 任塿»æ° |
| | | /// </summary> |
| | | public int RobotTaskTotalNum { get; set; } |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System.Net.Sockets; |
| | | using WIDESEAWCS_Common; |
| | | using WIDESEAWCS_Common.HttpEnum; |
| | | using WIDESEAWCS_Common.TaskEnum; |
| | | using WIDESEAWCS_Core.Caches; |
| | | using WIDESEAWCS_Core.Helper; |
| | | using WIDESEAWCS_DTO.Stock; |
| | | using WIDESEAWCS_DTO.TaskInfo; |
| | | using WIDESEAWCS_ITaskInfoService; |
| | | using WIDESEAWCS_Model.Models; |
| | | using WIDESEAWCS_Tasks.SocketServer; |
| | | |
| | | namespace WIDESEAWCS_Tasks |
| | | { |
| | | /// <summary> |
| | | /// æºæ¢°ææ¶æ¯å¤çå¨ - è´è´£å¤çæ¥èªTCP客æ·ç«¯çæ¶æ¯ |
| | | /// </summary> |
| | | public class RobotMessageHandler |
| | | { |
| | | private readonly TcpSocketServer _tcpSocket; |
| | | private readonly RobotStateManager _stateManager; |
| | | private readonly ICacheService _cache; |
| | | private readonly IRobotTaskService _robotTaskService; |
| | | private readonly RobotTaskProcessor _taskProcessor; |
| | | |
| | | public RobotMessageHandler( |
| | | TcpSocketServer tcpSocket, |
| | | RobotStateManager stateManager, |
| | | ICacheService cache, |
| | | IRobotTaskService robotTaskService, |
| | | RobotTaskProcessor taskProcessor) |
| | | { |
| | | _tcpSocket = tcpSocket; |
| | | _stateManager = stateManager; |
| | | _cache = cache; |
| | | _robotTaskService = robotTaskService; |
| | | _taskProcessor = taskProcessor; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å¤çæ¥æ¶å°çæ¶æ¯ |
| | | /// </summary> |
| | | public async Task<string?> HandleMessageReceivedAsync(string message, bool isJson, TcpClient client, RobotSocketState state) |
| | | { |
| | | if (!(_cache?.TryGetValue($"{RedisPrefix.Code}:{RedisName.SocketDevices}:{client.Client.RemoteEndPoint}", out state)) ?? false) |
| | | return null; |
| | | |
| | | string messageLower = message.ToLowerInvariant(); |
| | | |
| | | if (await IsSimpleCommandAsync(messageLower, state)) |
| | | { |
| | | await _tcpSocket.SendMessageAsync(client, message); |
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state)) |
| | | return null; |
| | | } |
| | | else if (IsPrefixCommand(messageLower)) |
| | | { |
| | | await HandlePrefixCommandAsync(message, state, client); |
| | | } |
| | | |
| | | return null; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å¤çåç¼å½ä»¤ï¼pickfinished, putfinishedï¼ |
| | | /// </summary> |
| | | private async Task HandlePrefixCommandAsync(string message, RobotSocketState state, TcpClient client) |
| | | { |
| | | try |
| | | { |
| | | var parts = message.Split(','); |
| | | if (parts.Length >= 1 && state.CurrentTask != null) |
| | | { |
| | | var cmd = parts[0].ToLowerInvariant(); |
| | | int[] positions = parts.Skip(1) |
| | | .Select(p => int.TryParse(p, out int value) ? value : (int?)null) |
| | | .Where(v => v.HasValue && v.Value != 0) |
| | | .Select(v => v!.Value) |
| | | .ToArray(); |
| | | |
| | | var task = await _robotTaskService.Repository.QueryFirstAsync(x => x.RobotTaskId == state.CurrentTask.RobotTaskId); |
| | | |
| | | if (cmd.StartsWith("pickfinished")) |
| | | { |
| | | await HandlePickFinishedAsync(state, positions, task, client); |
| | | } |
| | | else if (cmd.StartsWith("putfinished")) |
| | | { |
| | | await HandlePutFinishedAsync(state, positions, task, client); |
| | | } |
| | | |
| | | await _tcpSocket.SendMessageAsync(client, message); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Console.WriteLine($"RobotJob MessageReceived Error: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å¤çåè´§å®æå½ä»¤ |
| | | /// </summary> |
| | | private async Task HandlePickFinishedAsync(RobotSocketState state, int[] positions, Dt_RobotTask? task, TcpClient client) |
| | | { |
| | | if (state.IsSplitPallet) |
| | | { |
| | | var stockDTO = RobotTaskProcessor.BuildStockDTO(state, positions); |
| | | state.LastPickPositions = positions; |
| | | |
| | | var result = _taskProcessor.PostSplitPalletAsync(stockDTO); |
| | | |
| | | if (result.Data.Status && result.IsSuccess) |
| | | { |
| | | state.CurrentAction = "PickFinished"; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | state.CurrentAction = "PickFinished"; |
| | | } |
| | | |
| | | state.LastPickPositions = positions; |
| | | if (task != null) |
| | | { |
| | | task.RobotTaskState = TaskRobotStatusEnum.RobotPickFinish.GetHashCode(); |
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state)) |
| | | await _robotTaskService.Repository.UpdateDataAsync(task); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å¤çæ¾è´§å®æå½ä»¤ |
| | | /// </summary> |
| | | private async Task HandlePutFinishedAsync(RobotSocketState state, int[] positions, Dt_RobotTask? task, TcpClient client) |
| | | { |
| | | bool putSuccess = true; |
| | | if (state.IsGroupPallet) |
| | | { |
| | | state.LastPutPositions = positions; |
| | | var stockDTO = RobotTaskProcessor.BuildStockDTO(state, positions); |
| | | var configKey = state.CurrentTask?.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode() |
| | | ? nameof(ConfigKey.ChangePalletAsync) : nameof(ConfigKey.GroupPalletAsync); |
| | | |
| | | var result = _taskProcessor.PostGroupPalletAsync(configKey, stockDTO); |
| | | putSuccess = result.Data.Status && result.IsSuccess; |
| | | } |
| | | |
| | | if (putSuccess) |
| | | { |
| | | state.CurrentAction = "PutFinished"; |
| | | state.RobotTaskTotalNum += positions.Length; |
| | | if (task != null) |
| | | { |
| | | task.RobotTaskTotalNum += positions.Length; |
| | | } |
| | | } |
| | | |
| | | if (task != null) |
| | | { |
| | | task.RobotTaskState = TaskRobotStatusEnum.RobotPutFinish.GetHashCode(); |
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state)) |
| | | await _robotTaskService.Repository.UpdateDataAsync(task); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æºæ¢°æç®åå½ä»¤å¤ç |
| | | /// </summary> |
| | | private async Task<bool> IsSimpleCommandAsync(string message, RobotSocketState state) |
| | | { |
| | | RobotTaskTypeEnum? GetRobotTaskType() => state.CurrentTask != null ? (RobotTaskTypeEnum)state.CurrentTask.RobotTaskType : null; |
| | | switch (message) |
| | | { |
| | | case "homing": |
| | | state.OperStatus = "Homing"; |
| | | return true; |
| | | |
| | | case "homed": |
| | | state.OperStatus = "Homed"; |
| | | return true; |
| | | |
| | | case "picking": |
| | | state.CurrentAction = "Picking"; |
| | | return true; |
| | | |
| | | case "puting": |
| | | state.CurrentAction = "Putting"; |
| | | return true; |
| | | |
| | | case "allpickfinished": // åè´§å®æ |
| | | state.CurrentAction = "AllPickFinished"; |
| | | var robotTaskType = GetRobotTaskType(); |
| | | |
| | | if (robotTaskType == RobotTaskTypeEnum.SplitPallet || robotTaskType == RobotTaskTypeEnum.ChangePallet) |
| | | { |
| | | if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: true)) |
| | | { |
| | | _taskProcessor.DeleteTask(state.CurrentTask.RobotTaskId); |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | |
| | | case "allputfinished": // æ¾è´§å®æ |
| | | state.CurrentAction = "AllPutFinished"; |
| | | robotTaskType = GetRobotTaskType(); |
| | | |
| | | if (robotTaskType == RobotTaskTypeEnum.GroupPallet || robotTaskType == RobotTaskTypeEnum.ChangePallet) |
| | | { |
| | | if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: false)) |
| | | { |
| | | _taskProcessor.DeleteTask(state.CurrentTask.RobotTaskId); |
| | | state.CurrentTask = null; |
| | | state.RobotTaskTotalNum = 0; |
| | | state.CellBarcode = new List<string>(); |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | |
| | | case "running": |
| | | state.OperStatus = "Running"; |
| | | return true; |
| | | |
| | | case "pausing": |
| | | state.OperStatus = "Pausing"; |
| | | return true; |
| | | |
| | | case "warming": |
| | | state.OperStatus = "Warming"; |
| | | return true; |
| | | |
| | | case "emstoping": |
| | | state.OperStatus = "Emstoping"; |
| | | return true; |
| | | |
| | | case "runmode,1": |
| | | state.RobotRunMode = 1; |
| | | return true; |
| | | |
| | | case "runmode,2": |
| | | state.RobotRunMode = 2; |
| | | return true; |
| | | |
| | | case "controlmode,1": |
| | | state.RobotControlMode = 1; |
| | | return true; |
| | | |
| | | case "controlmode,2": |
| | | state.RobotControlMode = 2; |
| | | return true; |
| | | |
| | | case "armobject,1": |
| | | state.RobotArmObject = 1; |
| | | return true; |
| | | |
| | | case "armobject,0": |
| | | state.RobotArmObject = 0; |
| | | return true; |
| | | |
| | | default: |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 夿æ¯å¦ä¸ºåç¼å½ä»¤ |
| | | /// </summary> |
| | | private static bool IsPrefixCommand(string message) |
| | | { |
| | | return message.StartsWith("pickfinished") || message.StartsWith("putfinished"); |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using WIDESEAWCS_Model.Models; |
| | | using WIDESEAWCS_QuartzJob; |
| | | |
| | | namespace WIDESEAWCS_Tasks |
| | | { |
| | | /// <summary> |
| | | /// æºæ¢°æSocketéä¿¡ç¶æ |
| | | /// </summary> |
| | | public class RobotSocketState |
| | | { |
| | | public string IPAddress { get; set; } = string.Empty; |
| | | |
| | | /// <summary> |
| | | /// çæ¬å·ï¼ç¨äºé²æ¢å¹¶åæ´æ°æ¶æ§å¼è¦çæ°å¼ |
| | | /// æ¯æ¬¡ä¿®æ¹ç¶ææ¶é½åºè¯¥æ´æ°æ¤å¼ |
| | | /// </summary> |
| | | public long Version { get; set; } = DateTime.UtcNow.Ticks; |
| | | |
| | | /// <summary> |
| | | /// æ¯å¦å·²è®¢é
æ¶æ¯äºä»¶ |
| | | /// </summary> |
| | | public bool IsEventSubscribed { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æºæ¢°æè¿è¡æ¨¡å¼ |
| | | /// </summary> |
| | | public int? RobotRunMode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æºæ¢°ææ§å¶æ¨¡å¼ |
| | | /// </summary> |
| | | public int? RobotControlMode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æºæ¢°ææ¯å¦æåç©æï¼0-æ ç©æï¼1-æç©æ |
| | | /// </summary> |
| | | public int? RobotArmObject { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æºæ¢°æè®¾å¤ä¿¡æ¯ |
| | | /// </summary> |
| | | public RobotCraneDevice? RobotCrane { get; set; } |
| | | |
| | | /// <summary> |
| | | /// å½åå¨ä½ |
| | | /// </summary> |
| | | public string? CurrentAction { get; set; } |
| | | |
| | | /// <summary> |
| | | /// å½åç¶æ |
| | | /// </summary> |
| | | public string? OperStatus { get; set; } |
| | | |
| | | /// <summary> |
| | | /// åè´§å®æä½ç½® |
| | | /// </summary> |
| | | public int[]? LastPickPositions { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æ¾è´§å®æä½ç½® |
| | | /// </summary> |
| | | public int[]? LastPutPositions { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æåä½ç½®æ¡ç |
| | | /// </summary> |
| | | public List<string> CellBarcode { get; set; } = new List<string>(); |
| | | |
| | | /// <summary> |
| | | /// å½åæåä»»å¡ |
| | | /// </summary> |
| | | public Dt_RobotTask? CurrentTask { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æ¯å¦éè¦æç |
| | | /// </summary> |
| | | public bool IsSplitPallet { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æ¯å¦éè¦ç»ç |
| | | /// </summary> |
| | | public bool IsGroupPallet { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 任塿»æ° |
| | | /// </summary> |
| | | public int RobotTaskTotalNum { get; set; } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using Newtonsoft.Json; |
| | | using WIDESEAWCS_Common; |
| | | using WIDESEAWCS_Core.Caches; |
| | | using WIDESEAWCS_QuartzJob; |
| | | |
| | | namespace WIDESEAWCS_Tasks |
| | | { |
| | | /// <summary> |
| | | /// æºæ¢°æç¶æç®¡çå¨ - è´è´£RobotSocketStateçå®å
¨æ´æ°åå
é |
| | | /// </summary> |
| | | public class RobotStateManager |
| | | { |
| | | private readonly ICacheService _cache; |
| | | |
| | | public RobotStateManager(ICacheService cache) |
| | | { |
| | | _cache = cache; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å®å
¨æ´æ°RobotSocketStateç¼åï¼é²æ¢å¹¶åè¦ç |
| | | /// </summary> |
| | | /// <param name="ipAddress">设å¤IPå°å</param> |
| | | /// <param name="updateAction">æ´æ°ç¶æçå§æï¼ä¼ å
¥å½åç¶æï¼è¿åä¿®æ¹åçæ°ç¶æï¼</param> |
| | | /// <returns>æ¯å¦æ´æ°æå</returns> |
| | | public bool TryUpdateStateSafely(string ipAddress, Func<RobotSocketState, RobotSocketState> updateAction) |
| | | { |
| | | var cacheKey = GetCacheKey(ipAddress); |
| | | var currentState = _cache.Get<RobotSocketState>(cacheKey); |
| | | |
| | | if (currentState == null) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | // 使ç¨å½ååå¨ççæ¬å·ä½ä¸ºææçæ¬ |
| | | var expectedVersion = currentState.Version; |
| | | |
| | | // åå»ºç¶æå¯æ¬è¿è¡ä¿®æ¹ï¼é¿å
ä¿®æ¹å对象å¼ç¨ï¼ |
| | | var stateCopy = CloneState(currentState); |
| | | var newState = updateAction(stateCopy); |
| | | newState.Version = DateTime.UtcNow.Ticks; |
| | | |
| | | return _cache.TrySafeUpdate( |
| | | cacheKey, |
| | | newState, |
| | | expectedVersion, |
| | | s => s.Version |
| | | ); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å®å
¨æ´æ°RobotSocketStateç¼åï¼ç®åçæ¬ï¼ |
| | | /// </summary> |
| | | /// <param name="ipAddress">设å¤IPå°å</param> |
| | | /// <param name="newState">æ°ç¶æï¼ä¼è¢«æ´æ°Versionåæ®µï¼</param> |
| | | /// <returns>æ¯å¦æ´æ°æå</returns> |
| | | public bool TryUpdateStateSafely(string ipAddress, RobotSocketState newState) |
| | | { |
| | | var cacheKey = GetCacheKey(ipAddress); |
| | | var currentState = _cache.Get<RobotSocketState>(cacheKey); |
| | | |
| | | if (currentState == null) |
| | | { |
| | | // å½åä¸åå¨ï¼ç´æ¥æ·»å |
| | | newState.Version = DateTime.UtcNow.Ticks; |
| | | _cache.AddObject(cacheKey, newState); |
| | | return true; |
| | | } |
| | | |
| | | // 使ç¨å½ååå¨ççæ¬å·ä½ä¸ºææçæ¬ |
| | | var expectedVersion = currentState.Version; |
| | | |
| | | // æ´æ°æ°ç¶æççæ¬å·ä¸ºææ°æ¶é´æ³ |
| | | newState.Version = DateTime.UtcNow.Ticks; |
| | | |
| | | return _cache.TrySafeUpdate( |
| | | cacheKey, |
| | | newState, |
| | | expectedVersion, |
| | | s => s.Version |
| | | ); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å
éRobotSocketState对象ï¼å建深æ·è´ï¼ |
| | | /// </summary> |
| | | public RobotSocketState CloneState(RobotSocketState source) |
| | | { |
| | | // 使ç¨åºåå/ååºååè¿è¡æ·±æ·è´ |
| | | var json = JsonConvert.SerializeObject(source); |
| | | return JsonConvert.DeserializeObject<RobotSocketState>(json) ?? new RobotSocketState { IPAddress = source.IPAddress }; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åRedisç¼åé® |
| | | /// </summary> |
| | | public static string GetCacheKey(string ipAddress) |
| | | { |
| | | return $"{RedisPrefix.Code}:{RedisName.SocketDevices}:{ipAddress}"; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// ä»ç¼åè·åç¶æ |
| | | /// </summary> |
| | | public RobotSocketState? GetState(string ipAddress) |
| | | { |
| | | return _cache.Get<RobotSocketState>(GetCacheKey(ipAddress)); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæåå»ºç¶æ |
| | | /// </summary> |
| | | public RobotSocketState GetOrCreateState(string ipAddress, RobotCraneDevice robotCrane) |
| | | { |
| | | return _cache.GetOrAdd(GetCacheKey(ipAddress), _ => new RobotSocketState |
| | | { |
| | | IPAddress = ipAddress, |
| | | RobotCrane = robotCrane |
| | | }); |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using Newtonsoft.Json; |
| | | using WIDESEA_Core; |
| | | using WIDESEAWCS_Common; |
| | | using WIDESEAWCS_Common.HttpEnum; |
| | | using WIDESEAWCS_Common.TaskEnum; |
| | | using WIDESEAWCS_Core; |
| | | using WIDESEAWCS_Core.Helper; |
| | | using WIDESEAWCS_DTO.Stock; |
| | | using WIDESEAWCS_DTO.TaskInfo; |
| | | using WIDESEAWCS_ITaskInfoService; |
| | | using WIDESEAWCS_Model.Models; |
| | | using WIDESEAWCS_QuartzJob; |
| | | using WIDESEAWCS_Tasks.SocketServer; |
| | | |
| | | namespace WIDESEAWCS_Tasks |
| | | { |
| | | /// <summary> |
| | | /// æºæ¢°æä»»å¡å¤çå¨ - è´è´£æºæ¢°æä»»å¡æ§è¡åå¤ç |
| | | /// </summary> |
| | | public class RobotTaskProcessor |
| | | { |
| | | private readonly TcpSocketServer _tcpSocket; |
| | | private readonly RobotStateManager _stateManager; |
| | | private readonly IRobotTaskService _robotTaskService; |
| | | private readonly ITaskService _taskService; |
| | | private readonly HttpClientHelper _httpClientHelper; |
| | | |
| | | public RobotTaskProcessor( |
| | | TcpSocketServer tcpSocket, |
| | | RobotStateManager stateManager, |
| | | IRobotTaskService robotTaskService, |
| | | ITaskService taskService, |
| | | HttpClientHelper httpClientHelper) |
| | | { |
| | | _tcpSocket = tcpSocket; |
| | | _stateManager = stateManager; |
| | | _robotTaskService = robotTaskService; |
| | | _taskService = taskService; |
| | | _httpClientHelper = httpClientHelper; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæºæ¢°æä»»å¡ |
| | | /// </summary> |
| | | public Dt_RobotTask? GetTask(RobotCraneDevice robotCrane) |
| | | { |
| | | return _robotTaskService.QueryRobotCraneTask(robotCrane.DeviceCode); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæºæ¢°æä»»å¡ |
| | | /// </summary> |
| | | public bool? DeleteTask(int ID) |
| | | { |
| | | return _robotTaskService.Repository.DeleteDataById(ID); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åéæºæ¢°æåè´§å½ä»¤ |
| | | /// </summary> |
| | | public async Task SendSocketRobotPickAsync(Dt_RobotTask task, RobotSocketState state) |
| | | { |
| | | string taskString = $"Pickbattery,{task.RobotSourceAddress}"; |
| | | // åé任塿令 |
| | | bool result = await _tcpSocket.SendToClientAsync(state.IPAddress, taskString); |
| | | if (result) |
| | | { |
| | | task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode(); |
| | | state.CurrentTask = task; |
| | | |
| | | // æ´æ°ç¼åä¸çç¶æï¼ä½¿ç¨å®å
¨æ´æ°é²æ¢å¹¶åè¦çï¼ |
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state)) |
| | | await _robotTaskService.UpdateRobotTaskAsync(task); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å¤çå
¥åºä»»å¡ |
| | | /// </summary> |
| | | public async Task<bool> HandleInboundTaskAsync(RobotSocketState state, bool useSourceAddress) |
| | | { |
| | | var currentTask = state.CurrentTask; |
| | | if (currentTask == null) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | string roadway = currentTask.RobotSourceAddressLineCode; |
| | | int warehouseId = currentTask.RobotRoadway == "ZYRB1" ? 1 : currentTask.RobotRoadway == "HPRB001" ? 2 : 3; |
| | | |
| | | int taskType = 0; |
| | | string SourceAddress = currentTask.RobotTargetAddressLineCode; |
| | | string TargetAddress = currentTask.RobotSourceAddressLineCode; |
| | | string PalletCode = string.Empty; |
| | | // ç´æ¥è½¬æ¢ä¸ºæä¸¾ç±»åè¿è¡æ¯è¾ |
| | | var robotTaskType = (RobotTaskTypeEnum)currentTask.RobotTaskType; |
| | | |
| | | if (useSourceAddress) |
| | | { |
| | | switch (robotTaskType) |
| | | { |
| | | case RobotTaskTypeEnum.GroupPallet: |
| | | return false; |
| | | |
| | | case RobotTaskTypeEnum.ChangePallet: |
| | | case RobotTaskTypeEnum.SplitPallet: |
| | | taskType = TaskTypeEnum.InEmpty.GetHashCode(); |
| | | PalletCode = currentTask.RobotSourceAddressPalletCode; |
| | | break; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | switch (robotTaskType) |
| | | { |
| | | case RobotTaskTypeEnum.ChangePallet: |
| | | case RobotTaskTypeEnum.GroupPallet: |
| | | taskType = TaskTypeEnum.Inbound.GetHashCode(); |
| | | PalletCode = currentTask.RobotTargetAddressPalletCode; |
| | | break; |
| | | |
| | | case RobotTaskTypeEnum.SplitPallet: |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | CreateTaskDto taskDto = new CreateTaskDto |
| | | { |
| | | PalletCode = PalletCode, |
| | | SourceAddress = SourceAddress ?? string.Empty, |
| | | TargetAddress = TargetAddress ?? string.Empty, |
| | | Roadway = roadway, |
| | | WarehouseId = warehouseId, |
| | | PalletType = 1, |
| | | TaskType = taskType |
| | | }; |
| | | var result = _httpClientHelper.Post<WebResponseContent>(nameof(ConfigKey.CreateTaskInboundAsync), taskDto.ToJson()); |
| | | if (!result.Data.Status && result.IsSuccess) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | WMSTaskDTO taskDTO = JsonConvert.DeserializeObject<WMSTaskDTO>(result.Data.Data.ToJson() ?? string.Empty) ?? new WMSTaskDTO(); |
| | | var content = _taskService.ReceiveWMSTask(new List<WMSTaskDTO> { taskDTO }); |
| | | if (!content.Status) return false; |
| | | |
| | | var taskInfo = JsonConvert.DeserializeObject<Dt_Task>(content.Data.ToJson() ?? string.Empty) ?? new Dt_Task(); |
| | | |
| | | string sourceAddress = taskDTO.SourceAddress; |
| | | |
| | | IDevice? device = Storage.Devices.FirstOrDefault(x => x.DeviceProDTOs.Any(d => d.DeviceChildCode == sourceAddress)); |
| | | if (device != null) |
| | | { |
| | | CommonConveyorLine conveyorLine = (CommonConveyorLine)device; |
| | | conveyorLine.SetValue(ConveyorLineDBNameNew.Target, taskInfo.NextAddress, sourceAddress); |
| | | conveyorLine.SetValue(ConveyorLineDBNameNew.TaskNo, taskInfo.TaskNum, sourceAddress); |
| | | conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_STB, 1, sourceAddress); |
| | | |
| | | if (_taskService.UpdateTaskStatusToNext(taskInfo).Status) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æå»ºåºåDTO |
| | | /// </summary> |
| | | public static StockDTO BuildStockDTO(RobotSocketState state, int[] positions) |
| | | { |
| | | return new StockDTO |
| | | { |
| | | SourceLineNo = state.CurrentTask.RobotSourceAddressLineCode, |
| | | SourcePalletNo = state.CurrentTask.RobotSourceAddressPalletCode, |
| | | TargetPalletNo = state.CurrentTask.RobotTargetAddressPalletCode, |
| | | TargetLineNo = state.CurrentTask.RobotTargetAddressLineCode, |
| | | Details = positions |
| | | .Where(x => x > 0) |
| | | .OrderBy(x => x) |
| | | .Select((x, idx) => new StockDetailDTO |
| | | { |
| | | Quantity = state.RobotTaskTotalNum > 0 ? state.RobotTaskTotalNum + positions.Length : positions.Length, |
| | | Channel = x, |
| | | CellBarcode = state.CellBarcode?.Count > 0 ? state.CellBarcode[x - 1] : "" |
| | | }) |
| | | .ToList() |
| | | }; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è°ç¨æçAPI |
| | | /// </summary> |
| | | public HttpResponseResult<WebResponseContent> PostSplitPalletAsync(StockDTO stockDTO) |
| | | { |
| | | return _httpClientHelper.Post<WebResponseContent>(nameof(ConfigKey.SplitPalletAsync), stockDTO.ToJson()); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è°ç¨ç»çææ¢çAPI |
| | | /// </summary> |
| | | public HttpResponseResult<WebResponseContent> PostGroupPalletAsync(string configKey, StockDTO stockDTO) |
| | | { |
| | | return _httpClientHelper.Post<WebResponseContent>(configKey, stockDTO.ToJson()); |
| | | } |
| | | } |
| | | } |
| | |
| | | "RelativeMoniker": "D:0:0:{7D7534D4-51D9-46DC-A6B7-6430042F4E12}|WIDESEA_TaskInfoService\\WIDESEA_TaskInfoService.csproj|solutionrelative:widesea_taskinfoservice\\taskservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_dto\\stock\\stockdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|solutionrelative:widesea_dto\\stock\\stockdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | "AbsoluteMoniker": "D:0:0:{AF8F3D65-1D75-4B8F-AFD9-4150E591C44D}|WIDESEA_Common\\WIDESEA_Common.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_common\\taskenum\\tasktypeenum.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{AF8F3D65-1D75-4B8F-AFD9-4150E591C44D}|WIDESEA_Common\\WIDESEA_Common.csproj|solutionrelative:widesea_common\\taskenum\\tasktypeenum.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{7DC26D42-D8EE-46F0-BA66-A13457086885}|WIDESEA_StockService\\WIDESEA_StockService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_stockservice\\stockserivce.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{7DC26D42-D8EE-46F0-BA66-A13457086885}|WIDESEA_StockService\\WIDESEA_StockService.csproj|solutionrelative:widesea_stockservice\\stockserivce.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_wmsserver\\controllers\\taskinfo\\taskcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|solutionrelative:widesea_wmsserver\\controllers\\taskinfo\\taskcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{CE0DB91F-5A68-448E-A419-4C26B5039F51}|WIDESEA_ITaskInfoService\\WIDESEA_ITaskInfoService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_itaskinfoservice\\itaskservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{CE0DB91F-5A68-448E-A419-4C26B5039F51}|WIDESEA_ITaskInfoService\\WIDESEA_ITaskInfoService.csproj|solutionrelative:widesea_itaskinfoservice\\itaskservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | "AbsoluteMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_dto\\task\\createtaskdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|solutionrelative:widesea_dto\\task\\createtaskdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{111BD7AA-9749-4506-9772-79F9EF14754C}|WIDESEA_Core\\WIDESEA_Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_core\\baserepository\\repositorybase.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{111BD7AA-9749-4506-9772-79F9EF14754C}|WIDESEA_Core\\WIDESEA_Core.csproj|solutionrelative:widesea_core\\baserepository\\repositorybase.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{AF8F3D65-1D75-4B8F-AFD9-4150E591C44D}|WIDESEA_Common\\WIDESEA_Common.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_common\\stockenum\\stockstatusemun.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{AF8F3D65-1D75-4B8F-AFD9-4150E591C44D}|WIDESEA_Common\\WIDESEA_Common.csproj|solutionrelative:widesea_common\\stockenum\\stockstatusemun.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | "AbsoluteMoniker": "D:0:0:{111BD7AA-9749-4506-9772-79F9EF14754C}|WIDESEA_Core\\WIDESEA_Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_core\\baserepository\\irepository.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{111BD7AA-9749-4506-9772-79F9EF14754C}|WIDESEA_Core\\WIDESEA_Core.csproj|solutionrelative:widesea_core\\baserepository\\irepository.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_wmsserver\\controllers\\taskinfo\\taskcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|solutionrelative:widesea_wmsserver\\controllers\\taskinfo\\taskcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{7DC26D42-D8EE-46F0-BA66-A13457086885}|WIDESEA_StockService\\WIDESEA_StockService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_stockservice\\stockserivce.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{7DC26D42-D8EE-46F0-BA66-A13457086885}|WIDESEA_StockService\\WIDESEA_StockService.csproj|solutionrelative:widesea_stockservice\\stockserivce.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_dto\\stock\\stockdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|solutionrelative:widesea_dto\\stock\\stockdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_wmsserver\\controllers\\stock\\stockcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|solutionrelative:widesea_wmsserver\\controllers\\stock\\stockcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{49716D78-720D-475D-948C-0FC6C5F079E5}|WIDESEA_IStockService\\WIDESEA_IStockService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_istockservice\\istockinfoservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{49716D78-720D-475D-948C-0FC6C5F079E5}|WIDESEA_IStockService\\WIDESEA_IStockService.csproj|solutionrelative:widesea_istockservice\\istockinfoservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{111BD7AA-9749-4506-9772-79F9EF14754C}|WIDESEA_Core\\WIDESEA_Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_core\\baseservices\\servicebase.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{111BD7AA-9749-4506-9772-79F9EF14754C}|WIDESEA_Core\\WIDESEA_Core.csproj|solutionrelative:widesea_core\\baseservices\\servicebase.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{111BD7AA-9749-4506-9772-79F9EF14754C}|WIDESEA_Core\\WIDESEA_Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_core\\baseservices\\iservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{111BD7AA-9749-4506-9772-79F9EF14754C}|WIDESEA_Core\\WIDESEA_Core.csproj|solutionrelative:widesea_core\\baseservices\\iservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{49716D78-720D-475D-948C-0FC6C5F079E5}|WIDESEA_IStockService\\WIDESEA_IStockService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_istockservice\\istockservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{49716D78-720D-475D-948C-0FC6C5F079E5}|WIDESEA_IStockService\\WIDESEA_IStockService.csproj|solutionrelative:widesea_istockservice\\istockservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{00CE9885-9F24-4B6C-A7E8-0DE8C9ED7128}|WIDESEA_Model\\WIDESEA_Model.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_model\\models\\stock\\dt_stockinfo.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{00CE9885-9F24-4B6C-A7E8-0DE8C9ED7128}|WIDESEA_Model\\WIDESEA_Model.csproj|solutionrelative:widesea_model\\models\\stock\\dt_stockinfo.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_dto\\task\\createtaskdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|solutionrelative:widesea_dto\\task\\createtaskdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | "AbsoluteMoniker": "D:0:0:{CE0DB91F-5A68-448E-A419-4C26B5039F51}|WIDESEA_ITaskInfoService\\WIDESEA_ITaskInfoService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_itaskinfoservice\\itaskservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{CE0DB91F-5A68-448E-A419-4C26B5039F51}|WIDESEA_ITaskInfoService\\WIDESEA_ITaskInfoService.csproj|solutionrelative:widesea_itaskinfoservice\\itaskservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{AF8F3D65-1D75-4B8F-AFD9-4150E591C44D}|WIDESEA_Common\\WIDESEA_Common.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_common\\stockenum\\stockstatusemun.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{AF8F3D65-1D75-4B8F-AFD9-4150E591C44D}|WIDESEA_Common\\WIDESEA_Common.csproj|solutionrelative:widesea_common\\stockenum\\stockstatusemun.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{5F260E03-095A-4870-8419-5B72CB62929E}|WIDESEA_IBasicService\\WIDESEA_IBasicService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_ibasicservice\\ilocationinfoservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{AF8F3D65-1D75-4B8F-AFD9-4150E591C44D}|WIDESEA_Common\\WIDESEA_Common.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_common\\locationenum\\locationstatusenum.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{AF8F3D65-1D75-4B8F-AFD9-4150E591C44D}|WIDESEA_Common\\WIDESEA_Common.csproj|solutionrelative:widesea_common\\locationenum\\locationstatusenum.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{49716D78-720D-475D-948C-0FC6C5F079E5}|WIDESEA_IStockService\\WIDESEA_IStockService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_istockservice\\istockinfoservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{49716D78-720D-475D-948C-0FC6C5F079E5}|WIDESEA_IStockService\\WIDESEA_IStockService.csproj|solutionrelative:widesea_istockservice\\istockinfoservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_wmsserver\\controllers\\stock\\stockcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|solutionrelative:widesea_wmsserver\\controllers\\stock\\stockcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{49716D78-720D-475D-948C-0FC6C5F079E5}|WIDESEA_IStockService\\WIDESEA_IStockService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_istockservice\\istockservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{49716D78-720D-475D-948C-0FC6C5F079E5}|WIDESEA_IStockService\\WIDESEA_IStockService.csproj|solutionrelative:widesea_istockservice\\istockservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{7DC26D42-D8EE-46F0-BA66-A13457086885}|WIDESEA_StockService\\WIDESEA_StockService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_stockservice\\stockinfoservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | |
| | | "RelativeMoniker": "D:0:0:{7DC26D42-D8EE-46F0-BA66-A13457086885}|WIDESEA_StockService\\WIDESEA_StockService.csproj|solutionrelative:widesea_stockservice\\stockviewservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{111BD7AA-9749-4506-9772-79F9EF14754C}|WIDESEA_Core\\WIDESEA_Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_core\\baserepository\\irepository.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{111BD7AA-9749-4506-9772-79F9EF14754C}|WIDESEA_Core\\WIDESEA_Core.csproj|solutionrelative:widesea_core\\baserepository\\irepository.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_dto\\gradingmachine\\inputdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|solutionrelative:widesea_dto\\gradingmachine\\inputdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | |
| | | "DocumentGroups": [ |
| | | { |
| | | "DockedWidth": 200, |
| | | "SelectedChildIndex": 24, |
| | | "SelectedChildIndex": 27, |
| | | "Children": [ |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 6, |
| | | "Title": "StockStatusEmun.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Common\\StockEnum\\StockStatusEmun.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Common\\StockEnum\\StockStatusEmun.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Common\\StockEnum\\StockStatusEmun.cs", |
| | | "RelativeToolTip": "WIDESEA_Common\\StockEnum\\StockStatusEmun.cs", |
| | | "ViewState": "AgIAACQAAAAAAAAAAAAgwDoAAAAeAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-28T06:15:43.313Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:128:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}" |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 1, |
| | | "Title": "TaskTypeEnum.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Common\\TaskEnum\\TaskTypeEnum.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Common\\TaskEnum\\TaskTypeEnum.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Common\\TaskEnum\\TaskTypeEnum.cs", |
| | | "RelativeToolTip": "WIDESEA_Common\\TaskEnum\\TaskTypeEnum.cs", |
| | | "ViewState": "AgIAAIAAAAAAAAAAAAAYwKAAAAAXAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-05T06:53:48.328Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 11, |
| | | "Title": "IService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\BaseServices\\IService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Core\\BaseServices\\IService.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\BaseServices\\IService.cs", |
| | | "RelativeToolTip": "WIDESEA_Core\\BaseServices\\IService.cs", |
| | | "ViewState": "AgIAAAYAAAAAAAAAAAASwCoAAAAbAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-03T08:25:43.974Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 10, |
| | | "Title": "ServiceBase.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\BaseServices\\ServiceBase.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Core\\BaseServices\\ServiceBase.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\BaseServices\\ServiceBase.cs", |
| | | "RelativeToolTip": "WIDESEA_Core\\BaseServices\\ServiceBase.cs", |
| | | "ViewState": "AgIAAAEAAAAAAAAAAAAAANcBAAA3AAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-03T08:32:27.552Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 15, |
| | | "Title": "StockStatusEmun.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Common\\StockEnum\\StockStatusEmun.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Common\\StockEnum\\StockStatusEmun.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Common\\StockEnum\\StockStatusEmun.cs", |
| | | "RelativeToolTip": "WIDESEA_Common\\StockEnum\\StockStatusEmun.cs", |
| | | "ViewState": "AgIAACQAAAAAAAAAAAAgwDoAAAAeAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-28T06:15:43.313Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 17, |
| | | "Title": "LocationStatusEnum.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Common\\LocationEnum\\LocationStatusEnum.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Common\\LocationEnum\\LocationStatusEnum.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 13, |
| | | "DocumentIndex": 12, |
| | | "Title": "IStockService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_IStockService\\IStockService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_IStockService\\IStockService.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_IStockService\\IStockService.cs", |
| | | "RelativeToolTip": "WIDESEA_IStockService\\IStockService.cs", |
| | | "ViewState": "AgIAAAkAAAAAAAAAAAAAABUAAAA0AAAAAAAAAA==", |
| | | "ViewState": "AgIAAAcAAAAAAAAAAAAewBkAAAAfAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-26T06:24:13.287Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 12, |
| | | "DocumentIndex": 8, |
| | | "Title": "StockController.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_WMSServer\\Controllers\\Stock\\StockController.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_WMSServer\\Controllers\\Stock\\StockController.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_WMSServer\\Controllers\\Stock\\StockController.cs", |
| | | "RelativeToolTip": "WIDESEA_WMSServer\\Controllers\\Stock\\StockController.cs", |
| | | "ViewState": "AgIAADQAAAAAAAAAAAAIwDwAAAA5AAAAAAAAAA==", |
| | | "ViewState": "AgIAABwAAAAAAAAAAAAAACoAAAAJAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-26T06:16:05.674Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 15, |
| | | "DocumentIndex": 19, |
| | | "Title": "Program.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_WMSServer\\Program.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_WMSServer\\Program.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 18, |
| | | "DocumentIndex": 22, |
| | | "Title": "HttpResponseResult.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\Helper\\HTTP\\HttpResponseResult.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Core\\Helper\\HTTP\\HttpResponseResult.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 17, |
| | | "DocumentIndex": 21, |
| | | "Title": "HttpRequestConfig.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\Helper\\HTTP\\HttpRequestConfig.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Core\\Helper\\HTTP\\HttpRequestConfig.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 16, |
| | | "DocumentIndex": 20, |
| | | "Title": "HttpClientHelper.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\Helper\\HTTP\\HttpClientHelper.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Core\\Helper\\HTTP\\HttpClientHelper.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 23, |
| | | "DocumentIndex": 26, |
| | | "Title": "OutPutDto.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_DTO\\GradingMachine\\OutPutDto.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_DTO\\GradingMachine\\OutPutDto.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 22, |
| | | "DocumentIndex": 25, |
| | | "Title": "InputDto.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_DTO\\GradingMachine\\InputDto.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_DTO\\GradingMachine\\InputDto.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 5, |
| | | "DocumentIndex": 3, |
| | | "Title": "RepositoryBase.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\BaseRepository\\RepositoryBase.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Core\\BaseRepository\\RepositoryBase.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\BaseRepository\\RepositoryBase.cs", |
| | | "RelativeToolTip": "WIDESEA_Core\\BaseRepository\\RepositoryBase.cs", |
| | | "ViewState": "AgIAALgDAAAAAAAAAAAawMsDAAAZAAAAAAAAAA==", |
| | | "ViewState": "AgIAALoDAAAAAAAAAAAawM0DAAA+AAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-14T08:55:16.1Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 21, |
| | | "DocumentIndex": 4, |
| | | "Title": "IRepository.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\BaseRepository\\IRepository.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Core\\BaseRepository\\IRepository.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\BaseRepository\\IRepository.cs", |
| | | "RelativeToolTip": "WIDESEA_Core\\BaseRepository\\IRepository.cs", |
| | | "ViewState": "AgIAAIIBAAAAAAAAAAAWwLMBAAASAAAAAAAAAA==", |
| | | "ViewState": "AgIAAKEBAAAAAAAAAAAewLMBAAASAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-14T08:53:36.522Z" |
| | | "WhenOpened": "2026-02-14T08:53:36.522Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 20, |
| | | "DocumentIndex": 24, |
| | | "Title": "StockViewService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_StockService\\StockViewService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_StockService\\StockViewService.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 9, |
| | | "DocumentIndex": 16, |
| | | "Title": "ILocationInfoService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_IBasicService\\ILocationInfoService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_IBasicService\\ILocationInfoService.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 19, |
| | | "DocumentIndex": 23, |
| | | "Title": "LocationInfoService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_BasicService\\LocationInfoService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_BasicService\\LocationInfoService.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 7, |
| | | "DocumentIndex": 13, |
| | | "Title": "Dt_StockInfo.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Model\\Models\\Stock\\Dt_StockInfo.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Model\\Models\\Stock\\Dt_StockInfo.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Model\\Models\\Stock\\Dt_StockInfo.cs", |
| | | "RelativeToolTip": "WIDESEA_Model\\Models\\Stock\\Dt_StockInfo.cs", |
| | | "ViewState": "AgIAAEAAAAAAAAAAAAAkwFIAAAAuAAAAAAAAAA==", |
| | | "ViewState": "AgIAABYAAAAAAAAAAAAAwCcAAAArAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-11T01:38:37.887Z", |
| | | "EditorCaption": "" |
| | | "WhenOpened": "2026-02-11T01:38:37.887Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 14, |
| | | "DocumentIndex": 18, |
| | | "Title": "StockInfoService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_StockService\\StockInfoService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_StockService\\StockInfoService.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 11, |
| | | "DocumentIndex": 9, |
| | | "Title": "IStockInfoService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_IStockService\\IStockInfoService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_IStockService\\IStockInfoService.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_IStockService\\IStockInfoService.cs", |
| | | "RelativeToolTip": "WIDESEA_IStockService\\IStockInfoService.cs", |
| | | "ViewState": "AgIAAAAAAAAAAAAAAAAAACsAAAAzAAAAAAAAAA==", |
| | | "ViewState": "AgIAAAAAAAAAAAAAAAAuwAgAAAAiAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-11T01:21:54.522Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 3, |
| | | "DocumentIndex": 5, |
| | | "Title": "TaskController.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_WMSServer\\Controllers\\TaskInfo\\TaskController.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_WMSServer\\Controllers\\TaskInfo\\TaskController.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_WMSServer\\Controllers\\TaskInfo\\TaskController.cs", |
| | | "RelativeToolTip": "WIDESEA_WMSServer\\Controllers\\TaskInfo\\TaskController.cs", |
| | | "ViewState": "AgIAAD0AAAAAAAAAAAAUwFUAAABJAAAAAAAAAA==", |
| | | "ViewState": "AgIAABAAAAAAAAAAAAAgwCIAAAAIAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-09T01:23:19.844Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 8, |
| | | "DocumentIndex": 2, |
| | | "Title": "CreateTaskDto.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_DTO\\Task\\CreateTaskDto.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_DTO\\Task\\CreateTaskDto.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_DTO\\Task\\CreateTaskDto.cs", |
| | | "RelativeToolTip": "WIDESEA_DTO\\Task\\CreateTaskDto.cs", |
| | | "ViewState": "AgIAABsAAAAAAAAAAAAywA4AAAARAAAAAAAAAA==", |
| | | "ViewState": "AgIAAC0AAAAAAAAAAAAUwDwAAAAcAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-06T07:58:13.932Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 4, |
| | | "DocumentIndex": 14, |
| | | "Title": "ITaskService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_ITaskInfoService\\ITaskService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_ITaskInfoService\\ITaskService.cs", |
| | |
| | | "RelativeToolTip": "WIDESEA_ITaskInfoService\\ITaskService.cs", |
| | | "ViewState": "AgIAAEAAAAAAAAAAAAAUwFEAAAAVAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-06T07:00:19.697Z", |
| | | "EditorCaption": "" |
| | | "WhenOpened": "2026-02-06T07:00:19.697Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | |
| | | "RelativeDocumentMoniker": "WIDESEA_TaskInfoService\\TaskService.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_TaskInfoService\\TaskService.cs", |
| | | "RelativeToolTip": "WIDESEA_TaskInfoService\\TaskService.cs", |
| | | "ViewState": "AgIAAAEBAAAAAAAAAAAxwPABAAAAAAAAAAAAAA==", |
| | | "ViewState": "AgIAADoAAAAAAAAAAAAgwEMAAAARAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-06T06:34:59.734Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 1, |
| | | "DocumentIndex": 7, |
| | | "Title": "StockDTO.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_DTO\\Stock\\StockDTO.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_DTO\\Stock\\StockDTO.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 2, |
| | | "DocumentIndex": 6, |
| | | "Title": "StockSerivce.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_StockService\\StockSerivce.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_StockService\\StockSerivce.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_StockService\\StockSerivce.cs", |
| | | "RelativeToolTip": "WIDESEA_StockService\\StockSerivce.cs", |
| | | "ViewState": "AgIAAAAAAAAAAAAAAAAAAD8AAAApAAAAAAAAAA==", |
| | | "ViewState": "AgIAADAAAAAAAAAAAAAawC4AAAA7AAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-06T01:53:49.077Z", |
| | | "EditorCaption": "" |
| | |
| | | "WorkspaceRootPath": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\", |
| | | "Documents": [ |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{7D7534D4-51D9-46DC-A6B7-6430042F4E12}|WIDESEA_TaskInfoService\\WIDESEA_TaskInfoService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_taskinfoservice\\taskservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{7D7534D4-51D9-46DC-A6B7-6430042F4E12}|WIDESEA_TaskInfoService\\WIDESEA_TaskInfoService.csproj|solutionrelative:widesea_taskinfoservice\\taskservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_dto\\stock\\stockdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|solutionrelative:widesea_dto\\stock\\stockdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{7DC26D42-D8EE-46F0-BA66-A13457086885}|WIDESEA_StockService\\WIDESEA_StockService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_stockservice\\stockserivce.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{7DC26D42-D8EE-46F0-BA66-A13457086885}|WIDESEA_StockService\\WIDESEA_StockService.csproj|solutionrelative:widesea_stockservice\\stockserivce.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_wmsserver\\controllers\\taskinfo\\taskcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|solutionrelative:widesea_wmsserver\\controllers\\taskinfo\\taskcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{7D7534D4-51D9-46DC-A6B7-6430042F4E12}|WIDESEA_TaskInfoService\\WIDESEA_TaskInfoService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_taskinfoservice\\taskservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{7D7534D4-51D9-46DC-A6B7-6430042F4E12}|WIDESEA_TaskInfoService\\WIDESEA_TaskInfoService.csproj|solutionrelative:widesea_taskinfoservice\\taskservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{CE0DB91F-5A68-448E-A419-4C26B5039F51}|WIDESEA_ITaskInfoService\\WIDESEA_ITaskInfoService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_itaskinfoservice\\itaskservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{CE0DB91F-5A68-448E-A419-4C26B5039F51}|WIDESEA_ITaskInfoService\\WIDESEA_ITaskInfoService.csproj|solutionrelative:widesea_itaskinfoservice\\itaskservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{AF8F3D65-1D75-4B8F-AFD9-4150E591C44D}|WIDESEA_Common\\WIDESEA_Common.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_common\\taskenum\\taskstatusenum.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{AF8F3D65-1D75-4B8F-AFD9-4150E591C44D}|WIDESEA_Common\\WIDESEA_Common.csproj|solutionrelative:widesea_common\\taskenum\\taskstatusenum.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{7DC26D42-D8EE-46F0-BA66-A13457086885}|WIDESEA_StockService\\WIDESEA_StockService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_stockservice\\stockinfoservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{7DC26D42-D8EE-46F0-BA66-A13457086885}|WIDESEA_StockService\\WIDESEA_StockService.csproj|solutionrelative:widesea_stockservice\\stockinfoservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{49716D78-720D-475D-948C-0FC6C5F079E5}|WIDESEA_IStockService\\WIDESEA_IStockService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_istockservice\\istockinfoservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{49716D78-720D-475D-948C-0FC6C5F079E5}|WIDESEA_IStockService\\WIDESEA_IStockService.csproj|solutionrelative:widesea_istockservice\\istockinfoservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{AF8F3D65-1D75-4B8F-AFD9-4150E591C44D}|WIDESEA_Common\\WIDESEA_Common.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_common\\taskenum\\tasktypeenum.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{AF8F3D65-1D75-4B8F-AFD9-4150E591C44D}|WIDESEA_Common\\WIDESEA_Common.csproj|solutionrelative:widesea_common\\taskenum\\tasktypeenum.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_dto\\task\\createtaskdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|solutionrelative:widesea_dto\\task\\createtaskdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{111BD7AA-9749-4506-9772-79F9EF14754C}|WIDESEA_Core\\WIDESEA_Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_core\\baserepository\\repositorybase.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{111BD7AA-9749-4506-9772-79F9EF14754C}|WIDESEA_Core\\WIDESEA_Core.csproj|solutionrelative:widesea_core\\baserepository\\repositorybase.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{AF8F3D65-1D75-4B8F-AFD9-4150E591C44D}|WIDESEA_Common\\WIDESEA_Common.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_common\\stockenum\\stockstatusemun.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{AF8F3D65-1D75-4B8F-AFD9-4150E591C44D}|WIDESEA_Common\\WIDESEA_Common.csproj|solutionrelative:widesea_common\\stockenum\\stockstatusemun.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | "AbsoluteMoniker": "D:0:0:{111BD7AA-9749-4506-9772-79F9EF14754C}|WIDESEA_Core\\WIDESEA_Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_core\\baserepository\\irepository.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{111BD7AA-9749-4506-9772-79F9EF14754C}|WIDESEA_Core\\WIDESEA_Core.csproj|solutionrelative:widesea_core\\baserepository\\irepository.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{7DC26D42-D8EE-46F0-BA66-A13457086885}|WIDESEA_StockService\\WIDESEA_StockService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_stockservice\\stockserivce.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{7DC26D42-D8EE-46F0-BA66-A13457086885}|WIDESEA_StockService\\WIDESEA_StockService.csproj|solutionrelative:widesea_stockservice\\stockserivce.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_dto\\stock\\stockdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|solutionrelative:widesea_dto\\stock\\stockdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_wmsserver\\controllers\\stock\\stockcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|solutionrelative:widesea_wmsserver\\controllers\\stock\\stockcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{111BD7AA-9749-4506-9772-79F9EF14754C}|WIDESEA_Core\\WIDESEA_Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_core\\baseservices\\servicebase.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{111BD7AA-9749-4506-9772-79F9EF14754C}|WIDESEA_Core\\WIDESEA_Core.csproj|solutionrelative:widesea_core\\baseservices\\servicebase.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{111BD7AA-9749-4506-9772-79F9EF14754C}|WIDESEA_Core\\WIDESEA_Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_core\\baseservices\\iservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{111BD7AA-9749-4506-9772-79F9EF14754C}|WIDESEA_Core\\WIDESEA_Core.csproj|solutionrelative:widesea_core\\baseservices\\iservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{49716D78-720D-475D-948C-0FC6C5F079E5}|WIDESEA_IStockService\\WIDESEA_IStockService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_istockservice\\istockservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{49716D78-720D-475D-948C-0FC6C5F079E5}|WIDESEA_IStockService\\WIDESEA_IStockService.csproj|solutionrelative:widesea_istockservice\\istockservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{00CE9885-9F24-4B6C-A7E8-0DE8C9ED7128}|WIDESEA_Model\\WIDESEA_Model.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_model\\models\\stock\\dt_stockinfo.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{00CE9885-9F24-4B6C-A7E8-0DE8C9ED7128}|WIDESEA_Model\\WIDESEA_Model.csproj|solutionrelative:widesea_model\\models\\stock\\dt_stockinfo.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_dto\\task\\createtaskdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|solutionrelative:widesea_dto\\task\\createtaskdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | "AbsoluteMoniker": "D:0:0:{AF8F3D65-1D75-4B8F-AFD9-4150E591C44D}|WIDESEA_Common\\WIDESEA_Common.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_common\\stockenum\\stockstatusemun.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{AF8F3D65-1D75-4B8F-AFD9-4150E591C44D}|WIDESEA_Common\\WIDESEA_Common.csproj|solutionrelative:widesea_common\\stockenum\\stockstatusemun.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{5F260E03-095A-4870-8419-5B72CB62929E}|WIDESEA_IBasicService\\WIDESEA_IBasicService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_ibasicservice\\ilocationinfoservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{AF8F3D65-1D75-4B8F-AFD9-4150E591C44D}|WIDESEA_Common\\WIDESEA_Common.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_common\\locationenum\\locationstatusenum.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{AF8F3D65-1D75-4B8F-AFD9-4150E591C44D}|WIDESEA_Common\\WIDESEA_Common.csproj|solutionrelative:widesea_common\\locationenum\\locationstatusenum.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{49716D78-720D-475D-948C-0FC6C5F079E5}|WIDESEA_IStockService\\WIDESEA_IStockService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_istockservice\\istockinfoservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{49716D78-720D-475D-948C-0FC6C5F079E5}|WIDESEA_IStockService\\WIDESEA_IStockService.csproj|solutionrelative:widesea_istockservice\\istockinfoservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_wmsserver\\controllers\\stock\\stockcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|solutionrelative:widesea_wmsserver\\controllers\\stock\\stockcontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{49716D78-720D-475D-948C-0FC6C5F079E5}|WIDESEA_IStockService\\WIDESEA_IStockService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_istockservice\\istockservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{49716D78-720D-475D-948C-0FC6C5F079E5}|WIDESEA_IStockService\\WIDESEA_IStockService.csproj|solutionrelative:widesea_istockservice\\istockservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{7DC26D42-D8EE-46F0-BA66-A13457086885}|WIDESEA_StockService\\WIDESEA_StockService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_stockservice\\stockinfoservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{7DC26D42-D8EE-46F0-BA66-A13457086885}|WIDESEA_StockService\\WIDESEA_StockService.csproj|solutionrelative:widesea_stockservice\\stockinfoservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{D81A65B5-47D1-40C1-8FDE-7D24FF003F51}|WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_wmsserver\\program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | |
| | | "RelativeMoniker": "D:0:0:{7DC26D42-D8EE-46F0-BA66-A13457086885}|WIDESEA_StockService\\WIDESEA_StockService.csproj|solutionrelative:widesea_stockservice\\stockviewservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{111BD7AA-9749-4506-9772-79F9EF14754C}|WIDESEA_Core\\WIDESEA_Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_core\\baserepository\\irepository.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{111BD7AA-9749-4506-9772-79F9EF14754C}|WIDESEA_Core\\WIDESEA_Core.csproj|solutionrelative:widesea_core\\baserepository\\irepository.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|d:\\git\\shanmeixinnengyuan\\code\\wms\\widesea_wmsserver\\widesea_dto\\gradingmachine\\inputdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{929DF936-042C-4EEC-8722-A831FC2F0AEA}|WIDESEA_DTO\\WIDESEA_DTO.csproj|solutionrelative:widesea_dto\\gradingmachine\\inputdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | }, |
| | |
| | | "DocumentGroups": [ |
| | | { |
| | | "DockedWidth": 200, |
| | | "SelectedChildIndex": 24, |
| | | "SelectedChildIndex": 25, |
| | | "Children": [ |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 3, |
| | | "Title": "TaskStatusEnum.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Common\\TaskEnum\\TaskStatusEnum.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Common\\TaskEnum\\TaskStatusEnum.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Common\\TaskEnum\\TaskStatusEnum.cs", |
| | | "RelativeToolTip": "WIDESEA_Common\\TaskEnum\\TaskStatusEnum.cs", |
| | | "ViewState": "AgIAAAAAAAAAAAAAAAAAALgAAAAhAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-05T09:14:24.547Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:128:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}" |
| | |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 6, |
| | | "Title": "TaskTypeEnum.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Common\\TaskEnum\\TaskTypeEnum.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Common\\TaskEnum\\TaskTypeEnum.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Common\\TaskEnum\\TaskTypeEnum.cs", |
| | | "RelativeToolTip": "WIDESEA_Common\\TaskEnum\\TaskTypeEnum.cs", |
| | | "ViewState": "AgIAAIAAAAAAAAAAAAAYwKAAAAAXAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-05T06:53:48.328Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 14, |
| | | "Title": "IService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\BaseServices\\IService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Core\\BaseServices\\IService.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\BaseServices\\IService.cs", |
| | | "RelativeToolTip": "WIDESEA_Core\\BaseServices\\IService.cs", |
| | | "ViewState": "AgIAAAYAAAAAAAAAAAASwCoAAAAbAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-03T08:25:43.974Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 13, |
| | | "Title": "ServiceBase.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\BaseServices\\ServiceBase.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Core\\BaseServices\\ServiceBase.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\BaseServices\\ServiceBase.cs", |
| | | "RelativeToolTip": "WIDESEA_Core\\BaseServices\\ServiceBase.cs", |
| | | "ViewState": "AgIAAAEAAAAAAAAAAAAAANcBAAA3AAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-03-03T08:32:27.552Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 17, |
| | | "Title": "StockStatusEmun.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Common\\StockEnum\\StockStatusEmun.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Common\\StockEnum\\StockStatusEmun.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 10, |
| | | "DocumentIndex": 19, |
| | | "Title": "LocationStatusEnum.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Common\\LocationEnum\\LocationStatusEnum.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Common\\LocationEnum\\LocationStatusEnum.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 13, |
| | | "DocumentIndex": 15, |
| | | "Title": "IStockService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_IStockService\\IStockService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_IStockService\\IStockService.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_IStockService\\IStockService.cs", |
| | | "RelativeToolTip": "WIDESEA_IStockService\\IStockService.cs", |
| | | "ViewState": "AgIAAAkAAAAAAAAAAAAAABUAAAA0AAAAAAAAAA==", |
| | | "ViewState": "AgIAAAcAAAAAAAAAAAAewBkAAAAfAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-26T06:24:13.287Z" |
| | | }, |
| | |
| | | "RelativeDocumentMoniker": "WIDESEA_WMSServer\\Controllers\\Stock\\StockController.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_WMSServer\\Controllers\\Stock\\StockController.cs", |
| | | "RelativeToolTip": "WIDESEA_WMSServer\\Controllers\\Stock\\StockController.cs", |
| | | "ViewState": "AgIAADQAAAAAAAAAAAAIwDwAAAA5AAAAAAAAAA==", |
| | | "ViewState": "AgIAABwAAAAAAAAAAAAAACoAAAAJAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-26T06:16:05.674Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 15, |
| | | "DocumentIndex": 20, |
| | | "Title": "Program.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_WMSServer\\Program.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_WMSServer\\Program.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 18, |
| | | "DocumentIndex": 23, |
| | | "Title": "HttpResponseResult.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\Helper\\HTTP\\HttpResponseResult.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Core\\Helper\\HTTP\\HttpResponseResult.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 17, |
| | | "DocumentIndex": 22, |
| | | "Title": "HttpRequestConfig.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\Helper\\HTTP\\HttpRequestConfig.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Core\\Helper\\HTTP\\HttpRequestConfig.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 16, |
| | | "DocumentIndex": 21, |
| | | "Title": "HttpClientHelper.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\Helper\\HTTP\\HttpClientHelper.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Core\\Helper\\HTTP\\HttpClientHelper.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 23, |
| | | "DocumentIndex": 27, |
| | | "Title": "OutPutDto.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_DTO\\GradingMachine\\OutPutDto.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_DTO\\GradingMachine\\OutPutDto.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 22, |
| | | "DocumentIndex": 26, |
| | | "Title": "InputDto.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_DTO\\GradingMachine\\InputDto.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_DTO\\GradingMachine\\InputDto.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 5, |
| | | "DocumentIndex": 8, |
| | | "Title": "RepositoryBase.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\BaseRepository\\RepositoryBase.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Core\\BaseRepository\\RepositoryBase.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\BaseRepository\\RepositoryBase.cs", |
| | | "RelativeToolTip": "WIDESEA_Core\\BaseRepository\\RepositoryBase.cs", |
| | | "ViewState": "AgIAALgDAAAAAAAAAAAawMsDAAAZAAAAAAAAAA==", |
| | | "ViewState": "AgIAALoDAAAAAAAAAAAawM0DAAA+AAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-14T08:55:16.1Z" |
| | | "WhenOpened": "2026-02-14T08:55:16.1Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 21, |
| | | "DocumentIndex": 9, |
| | | "Title": "IRepository.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\BaseRepository\\IRepository.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Core\\BaseRepository\\IRepository.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\BaseRepository\\IRepository.cs", |
| | | "RelativeToolTip": "WIDESEA_Core\\BaseRepository\\IRepository.cs", |
| | | "ViewState": "AgIAAIIBAAAAAAAAAAAWwLMBAAASAAAAAAAAAA==", |
| | | "ViewState": "AgIAAKEBAAAAAAAAAAAewLMBAAASAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-14T08:53:36.522Z" |
| | | "WhenOpened": "2026-02-14T08:53:36.522Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 20, |
| | | "DocumentIndex": 25, |
| | | "Title": "StockViewService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_StockService\\StockViewService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_StockService\\StockViewService.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 9, |
| | | "DocumentIndex": 18, |
| | | "Title": "ILocationInfoService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_IBasicService\\ILocationInfoService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_IBasicService\\ILocationInfoService.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 19, |
| | | "DocumentIndex": 24, |
| | | "Title": "LocationInfoService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_BasicService\\LocationInfoService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_BasicService\\LocationInfoService.cs", |
| | |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 7, |
| | | "DocumentIndex": 16, |
| | | "Title": "Dt_StockInfo.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Model\\Models\\Stock\\Dt_StockInfo.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_Model\\Models\\Stock\\Dt_StockInfo.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Model\\Models\\Stock\\Dt_StockInfo.cs", |
| | | "RelativeToolTip": "WIDESEA_Model\\Models\\Stock\\Dt_StockInfo.cs", |
| | | "ViewState": "AgIAAEAAAAAAAAAAAAAkwFIAAAAuAAAAAAAAAA==", |
| | | "ViewState": "AgIAABYAAAAAAAAAAAAAwCcAAAArAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-11T01:38:37.887Z" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 14, |
| | | "DocumentIndex": 4, |
| | | "Title": "StockInfoService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_StockService\\StockInfoService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_StockService\\StockInfoService.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_StockService\\StockInfoService.cs", |
| | | "RelativeToolTip": "WIDESEA_StockService\\StockInfoService.cs", |
| | | "ViewState": "AgIAAAAAAAAAAAAAAAAAABUAAAA0AAAAAAAAAA==", |
| | | "ViewState": "AgIAAAsAAAAAAAAAAAAMwB0AAAAuAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-11T01:23:56.94Z" |
| | | "WhenOpened": "2026-02-11T01:23:56.94Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 11, |
| | | "DocumentIndex": 5, |
| | | "Title": "IStockInfoService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_IStockService\\IStockInfoService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_IStockService\\IStockInfoService.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_IStockService\\IStockInfoService.cs", |
| | | "RelativeToolTip": "WIDESEA_IStockService\\IStockInfoService.cs", |
| | | "ViewState": "AgIAAAAAAAAAAAAAAAAAACsAAAAzAAAAAAAAAA==", |
| | | "ViewState": "AgIAAAMAAAAAAAAAAAAMwAgAAAAiAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-11T01:21:54.522Z" |
| | | "WhenOpened": "2026-02-11T01:21:54.522Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 3, |
| | | "DocumentIndex": 0, |
| | | "Title": "TaskController.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_WMSServer\\Controllers\\TaskInfo\\TaskController.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_WMSServer\\Controllers\\TaskInfo\\TaskController.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_WMSServer\\Controllers\\TaskInfo\\TaskController.cs", |
| | | "RelativeToolTip": "WIDESEA_WMSServer\\Controllers\\TaskInfo\\TaskController.cs", |
| | | "ViewState": "AgIAAD0AAAAAAAAAAAAUwFUAAABJAAAAAAAAAA==", |
| | | "ViewState": "AgIAAFMAAAAAAAAAAAAcwGQAAAAJAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-09T01:23:19.844Z" |
| | | "WhenOpened": "2026-02-09T01:23:19.844Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 8, |
| | | "DocumentIndex": 7, |
| | | "Title": "CreateTaskDto.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_DTO\\Task\\CreateTaskDto.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_DTO\\Task\\CreateTaskDto.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_DTO\\Task\\CreateTaskDto.cs", |
| | | "RelativeToolTip": "WIDESEA_DTO\\Task\\CreateTaskDto.cs", |
| | | "ViewState": "AgIAABsAAAAAAAAAAAAywA4AAAARAAAAAAAAAA==", |
| | | "ViewState": "AgIAAC0AAAAAAAAAAAAUwDwAAAAcAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-06T07:58:13.932Z" |
| | | "WhenOpened": "2026-02-06T07:58:13.932Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 4, |
| | | "DocumentIndex": 2, |
| | | "Title": "ITaskService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_ITaskInfoService\\ITaskService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_ITaskInfoService\\ITaskService.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_ITaskInfoService\\ITaskService.cs", |
| | | "RelativeToolTip": "WIDESEA_ITaskInfoService\\ITaskService.cs", |
| | | "ViewState": "AgIAAEAAAAAAAAAAAAAUwFEAAAAVAAAAAAAAAA==", |
| | | "ViewState": "AgIAAE8AAAAAAAAAAAAgwFwAAAAfAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-06T07:00:19.697Z" |
| | | "WhenOpened": "2026-02-06T07:00:19.697Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 0, |
| | | "DocumentIndex": 1, |
| | | "Title": "TaskService.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_TaskInfoService\\TaskService.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_TaskInfoService\\TaskService.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_TaskInfoService\\TaskService.cs", |
| | | "RelativeToolTip": "WIDESEA_TaskInfoService\\TaskService.cs", |
| | | "ViewState": "AgIAANcAAAAAAAAAAAAgwBYBAABGAAAAAAAAAA==", |
| | | "ViewState": "AgIAACIBAAAAAAAAAAAuwGMBAAAAAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-06T06:34:59.734Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 1, |
| | | "DocumentIndex": 11, |
| | | "Title": "StockDTO.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_DTO\\Stock\\StockDTO.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_DTO\\Stock\\StockDTO.cs", |
| | |
| | | "RelativeToolTip": "WIDESEA_DTO\\Stock\\StockDTO.cs", |
| | | "ViewState": "AgIAACMAAAAAAAAAAAAAADYAAAAuAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-06T02:56:51.397Z" |
| | | "WhenOpened": "2026-02-06T02:56:51.397Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 2, |
| | | "DocumentIndex": 10, |
| | | "Title": "StockSerivce.cs", |
| | | "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_StockService\\StockSerivce.cs", |
| | | "RelativeDocumentMoniker": "WIDESEA_StockService\\StockSerivce.cs", |
| | | "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_StockService\\StockSerivce.cs", |
| | | "RelativeToolTip": "WIDESEA_StockService\\StockSerivce.cs", |
| | | "ViewState": "AgIAAAAAAAAAAAAAAAAAAD8AAAApAAAAAAAAAA==", |
| | | "ViewState": "AgIAADAAAAAAAAAAAAAawC4AAAA7AAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-06T01:53:49.077Z" |
| | | "WhenOpened": "2026-02-06T01:53:49.077Z", |
| | | "EditorCaption": "" |
| | | } |
| | | ] |
| | | } |
| | |
| | | [Description("æåæºæ§è¡ä¸")] |
| | | HT_Executing = 110, |
| | | } |
| | | |
| | | public enum TaskInStatusEnum |
| | | { |
| | | /// <summary> |
| | | /// æ°å»ºå
¥åºä»»å¡ |
| | | /// </summary> |
| | | [Description("æ°å»ºå
¥åºä»»å¡")] |
| | | InNew = 200, |
| | | |
| | | ///// <summary> |
| | | ///// AGVå
¥åºæ§è¡ä¸ |
| | | ///// </summary> |
| | | //[Description("AGVå
¥åºæ§è¡ä¸")] |
| | | //AGV_InExecuting = 210, |
| | | |
| | | ///// <summary> |
| | | ///// AGVå
¥åºå®æ |
| | | ///// </summary> |
| | | //[Description("AGVæ¬è¿å®æ")] |
| | | //AGV_InFinish = 215, |
| | | |
| | | /// <summary> |
| | | /// è¾é线å
¥åºæ§è¡ä¸ |
| | | /// </summary> |
| | | [Description("è¾é线å
¥åºæ§è¡ä¸")] |
| | | Line_InExecuting = 220, |
| | | |
| | | /// <summary> |
| | | /// è¾é线å
¥åºå®æ |
| | | /// </summary> |
| | | [Description("è¾é线è¾é宿")] |
| | | Line_InFinish = 225, |
| | | |
| | | /// <summary> |
| | | /// å åæºå
¥åºæ§è¡ä¸ |
| | | /// </summary> |
| | | [Description("å åæºå
¥åºæ§è¡ä¸")] |
| | | SC_InExecuting = 230, |
| | | |
| | | /// <summary> |
| | | /// å åæºå
¥åºå®æ |
| | | /// </summary> |
| | | [Description("å åæºå
¥åºå®æ")] |
| | | SC_InFinish = 235, |
| | | |
| | | /// <summary> |
| | | /// å
¥åºä»»å¡å®æ |
| | | /// </summary> |
| | | [Description("å
¥åºä»»å¡å®æ")] |
| | | InFinish = 290, |
| | | |
| | | /// <summary> |
| | | /// å
¥åºä»»å¡æèµ· |
| | | /// </summary> |
| | | [Description("å
¥åºä»»å¡æèµ·")] |
| | | InPending = 297, |
| | | |
| | | /// <summary> |
| | | /// å
¥åºä»»å¡åæ¶ |
| | | /// </summary> |
| | | [Description("å
¥åºä»»å¡åæ¶")] |
| | | InCancel = 298, |
| | | |
| | | /// <summary> |
| | | /// å
¥åºä»»å¡å¼å¸¸ |
| | | /// </summary> |
| | | [Description("å
¥åºä»»å¡å¼å¸¸")] |
| | | InException = 299, |
| | | } |
| | | |
| | | public enum TaskOutStatusEnum |
| | | { |
| | | /// <summary> |
| | | /// æ°å»ºåºåºä»»å¡ |
| | | /// </summary> |
| | | [Description("æ°å»ºåºåºä»»å¡")] |
| | | OutNew = 100, |
| | | |
| | | /// <summary> |
| | | /// å åæºåºåºæ§è¡ä¸ |
| | | /// </summary> |
| | | [Description("å åæºåºåºæ§è¡ä¸")] |
| | | SC_OutExecuting = 110, |
| | | |
| | | /// <summary> |
| | | /// å åæºåºåºå®æ |
| | | /// </summary> |
| | | [Description("å åæºåºåºå®æ")] |
| | | SC_OutFinish = 115, |
| | | |
| | | /// <summary> |
| | | /// è¾é线åºåºæ§è¡ä¸ |
| | | /// </summary> |
| | | [Description("è¾é线åºåºæ§è¡ä¸")] |
| | | Line_OutExecuting = 120, |
| | | |
| | | /// <summary> |
| | | /// è¾é线åºåºå®æ |
| | | /// </summary> |
| | | [Description("è¾é线è¾é宿")] |
| | | Line_OutFinish = 125, |
| | | |
| | | ///// <summary> |
| | | ///// AGVåºåºæ§è¡ä¸ |
| | | ///// </summary> |
| | | //[Description("AGVåºåºæ§è¡ä¸")] |
| | | //AGV_OutExecuting = 130, |
| | | |
| | | ///// <summary> |
| | | ///// AGVåºåºå®æ |
| | | ///// </summary> |
| | | //[Description("AGVæ¬è¿å®æ")] |
| | | //AGV_OutFinish = 135, |
| | | |
| | | /// <summary> |
| | | /// åºåºä»»å¡å®æ |
| | | /// </summary> |
| | | [Description("åºåºä»»å¡å®æ")] |
| | | OutFinish = 190, |
| | | |
| | | /// <summary> |
| | | /// åºåºä»»å¡æèµ· |
| | | /// </summary> |
| | | [Description("åºåºä»»å¡æèµ·")] |
| | | OutPending = 197, |
| | | |
| | | /// <summary> |
| | | /// åºåºä»»å¡åæ¶ |
| | | /// </summary> |
| | | [Description("åºåºä»»å¡åæ¶")] |
| | | OutCancel = 198, |
| | | |
| | | /// <summary> |
| | | /// åºåºä»»å¡å¼å¸¸ |
| | | /// </summary> |
| | | [Description("åºåºä»»å¡å¼å¸¸")] |
| | | OutException = 199, |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | } |
| | | |
| | | public enum TaskInboundTypeEnum |
| | | { |
| | | /// <summary> |
| | | /// å
¥åº |
| | | /// </summary> |
| | | [Description("å
¥åº")] |
| | | Inbound = 200, |
| | | /// <summary> |
| | | /// çç¹å
¥åº |
| | | /// </summary> |
| | | [Description("çç¹å
¥åº")] |
| | | InInventory = 201, |
| | | /// <summary> |
| | | /// 忣å
¥åº |
| | | /// </summary> |
| | | [Description("忣å
¥åº")] |
| | | InPick = 202, |
| | | /// <summary> |
| | | /// è´¨æ£å
¥åº |
| | | /// </summary> |
| | | [Description("è´¨æ£å
¥åº")] |
| | | InQuality = 203, |
| | | |
| | | /// <summary> |
| | | /// 空箱å
¥åº |
| | | /// </summary> |
| | | [Description("空箱å
¥åº")] |
| | | InEmpty = 600, |
| | | } |
| | | |
| | | public enum TaskOutboundTypeEnum |
| | | { |
| | | /// <summary> |
| | | /// åºåº |
| | | /// </summary> |
| | | [Description("åºåº")] |
| | | Outbound = 100, |
| | | /// <summary> |
| | | /// çç¹åºåº |
| | | /// </summary> |
| | | [Description("çç¹åºåº")] |
| | | OutInventory = 101, |
| | | /// <summary> |
| | | /// 忣åºåº |
| | | /// </summary> |
| | | [Description("忣åºåº")] |
| | | OutPick = 102, |
| | | /// <summary> |
| | | /// è´¨æ£åºåº |
| | | /// </summary> |
| | | [Description("è´¨æ£åºåº")] |
| | | OutQuality = 103, |
| | | |
| | | /// <summary> |
| | | /// 空箱åºåº |
| | | /// </summary> |
| | | [Description("空箱åºåº")] |
| | | OutEmpty = 140, |
| | | } |
| | | |
| | | public enum TaskRelocationTypeEnum |
| | | { |
| | | /// <summary> |
| | | /// åºå
ç§»åº |
| | | /// </summary> |
| | | [Description("åºå
ç§»åº")] |
| | | Relocation = 300, |
| | | /// <summary> |
| | | /// åºå¤ç§»åº |
| | | /// </summary> |
| | | [Description("åºå¤ç§»åº")] |
| | | RelocationIn = 301 |
| | | } |
| | | |
| | | public enum TaskTypeGroup |
| | | { |
| | | /// <summary> |
| | |
| | | Task<WebResponseContent> GetOutBoundTrayTaskAsync(CreateTaskDto taskDto); |
| | | |
| | | /// <summary> |
| | | /// ä¿®æ¹ä»»å¡ç¶æï¼æ ¹æ®ä»»å¡IDä¿®æ¹ä¸ºæå®ç¶æï¼ |
| | | /// </summary> |
| | | /// <param name="taskId"></param> |
| | | /// <param name="newStatus"></param> |
| | | /// <returns></returns> |
| | | Task<WebResponseContent> UpdateTaskByStatusAsync(int taskId, int newStatus); |
| | | |
| | | /// <summary> |
| | | /// å åæºåæ¾è´§å®æåç©æµéç¥åæå容æå®æä¿¡å· |
| | | /// </summary> |
| | | /// <param name="input"></param> |
| | |
| | | using AutoMapper; |
| | | using Microsoft.AspNetCore.Components.Forms; |
| | | using SqlSugar; |
| | | using System.Text.Json; |
| | | using WIDESEA_Common.LocationEnum; |
| | |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_Core.BaseServices; |
| | | using WIDESEA_Core.Helper; |
| | | using WIDESEA_DTO; |
| | | using WIDESEA_DTO.Task; |
| | | using WIDESEA_IBasicService; |
| | |
| | | _httpClientHelper = httpClientHelper; |
| | | } |
| | | |
| | | #region WCSé»è¾å¤ç |
| | | |
| | | /// <summary> |
| | | /// å建任å¡ï¼ç»çå
¥åºä»»å¡ã空æçååºä»»å¡ï¼ |
| | | /// </summary> |
| | |
| | | { |
| | | try |
| | | { |
| | | WebResponseContent content = await GetTasksByPalletCodeAsync(taskDto.PalletCode); |
| | | if (content.Status) |
| | | { |
| | | return content; |
| | | } |
| | | |
| | | if (string.IsNullOrWhiteSpace(taskDto.PalletCode) || |
| | | string.IsNullOrWhiteSpace(taskDto.SourceAddress) || |
| | | string.IsNullOrWhiteSpace(taskDto.TargetAddress) || |
| | | string.IsNullOrWhiteSpace(taskDto.Roadway)) |
| | | { |
| | | return WebResponseContent.Instance.Error("æ æçä»»å¡è¯¦æ
"); |
| | |
| | | return WebResponseContent.Instance.Error("æ æçä»»å¡è¯¦æ
"); |
| | | } |
| | | |
| | | // ä½¿ç¨ switch è¡¨è¾¾å¼æ å°ä»»å¡ç±»å |
| | | int taskInboundType = taskDto.TaskType switch |
| | | { |
| | | TaskTypeEnum.Inbound => TaskInboundTypeEnum.Inbound.GetHashCode(), |
| | | TaskTypeEnum.InEmpty => TaskInboundTypeEnum.InEmpty.GetHashCode(), |
| | | _ => 0 // ç论ä¸ä¸ä¼èµ°å°è¿éï¼å 为已ç»éªè¯è¿äº |
| | | }; |
| | | |
| | | var task = new Dt_Task |
| | | { |
| | | TaskNum = 0, |
| | | TaskNum = await BaseDal.GetTaskNo(), |
| | | PalletCode = taskDto.PalletCode, |
| | | PalletType = taskDto.PalletType, |
| | | Roadway = taskDto.Roadway, |
| | | TaskType = taskDto.TaskType.GetHashCode(), |
| | | TaskStatus = TaskStatusEnum.New.GetHashCode(), |
| | | TaskType = taskInboundType, |
| | | TaskStatus = TaskInStatusEnum.InNew.GetHashCode(), |
| | | SourceAddress = taskDto.SourceAddress, |
| | | TargetAddress = taskDto.TargetAddress, |
| | | CurrentAddress = taskDto.SourceAddress, |
| | |
| | | { |
| | | try |
| | | { |
| | | WebResponseContent content = await GetTasksByPalletCodeAsync(taskDto.PalletCode); |
| | | if (content.Status) |
| | | { |
| | | return content; |
| | | } |
| | | |
| | | //var tasks = await BaseDal.QueryAsync(s => s.PalletCode == palletCode); |
| | | //if (tasks == null || !tasks.Any()) |
| | | // return WebResponseContent.Instance.Error("æªæ¾å°å¯¹åºçä»»å¡"); |
| | |
| | | { |
| | | try |
| | | { |
| | | |
| | | var stockInfo = await _stockInfoService.Repository.QueryFirstAsync(x => x.LocationDetails.WarehouseId == taskDto.WarehouseId && x.LocationDetails.LocationStatus == LocationStatusEnum.InStock.GetHashCode() && x.StockStatus == StockStatusEmun.空æçåºå.GetHashCode()); |
| | | if(stockInfo == null) |
| | | if (stockInfo == null) |
| | | return WebResponseContent.Instance.Error("æªæ¾å°å¯¹åºçåºåä¿¡æ¯"); |
| | | |
| | | var task = new Dt_Task() |
| | |
| | | TaskNum = await BaseDal.GetTaskNo(), |
| | | Creater = "system", |
| | | }; |
| | | var taskDtos = _mapper.Map<List<WMSTaskDTO>>(task); |
| | | var taskDtos = _mapper.Map<List<WMSTaskDTO>>(task); |
| | | return WebResponseContent.Instance.OK("æ¥è¯¢æå", taskDtos); |
| | | } |
| | | catch (Exception ex) |
| | |
| | | return WebResponseContent.Instance.Error($"æ¥è¯¢ä»»å¡å¤±è´¥: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// ä¿®æ¹ä»»å¡ç¶æï¼æ ¹æ®ä»»å¡IDä¿®æ¹ä¸ºæå®ç¶æï¼ |
| | | /// </summary> |
| | | /// <param name="taskId"></param> |
| | | /// <param name="newStatus"></param> |
| | | /// <returns></returns> |
| | | public async Task<WebResponseContent> UpdateTaskByStatusAsync(int taskId, int newStatus) |
| | | { |
| | | try |
| | | { |
| | | var tasks = await BaseDal.QueryFirstAsync(s => s.TaskId == taskId); |
| | | if (tasks == null) |
| | | return WebResponseContent.Instance.Error("æªæ¾å°å¯¹åºçä»»å¡"); |
| | | |
| | | tasks.TaskStatus = newStatus; |
| | | await BaseDal.UpdateDataAsync(tasks); |
| | | |
| | | return WebResponseContent.Instance.OK("ä¿®æ¹æå", tasks); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | return WebResponseContent.Instance.Error($"ä¿®æ¹å¤±è´¥: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// æ¥æ¾æçæ¯å¦æä»»å¡ |
| | | /// </summary> |
| | | /// <param name="palletCode"></param> |
| | | /// <returns></returns> |
| | | private async Task<WebResponseContent> GetTasksByPalletCodeAsync(string palletCode) |
| | | { |
| | | try |
| | | { |
| | | var tasks = await BaseDal.QueryFirstAsync(s => s.PalletCode == palletCode); |
| | | if (tasks == null) |
| | | return WebResponseContent.Instance.Error("æªæ¾å°å¯¹åºçä»»å¡"); |
| | | var taskDtos = _mapper.Map<List<WMSTaskDTO>>(tasks); |
| | | return WebResponseContent.Instance.OK("æ¥è¯¢æå", taskDtos); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | return WebResponseContent.Instance.Error($"æ¥è¯¢ä»»å¡å¤±è´¥: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | #endregion WCSé»è¾å¤ç |
| | | |
| | | #region åå®¹ææ¥å£ |
| | | |
| | |
| | | var result = await BaseDal.AddDataAsync(taskList) > 0; |
| | | var wmstaskDto = result ? _mapper.Map<WMSTaskDTO>(taskList) : null; |
| | | |
| | | |
| | | var httpResponse = _httpClientHelper.Post<WebResponseContent>("http://logistics-service/api/logistics/notifyoutbound", JsonSerializer.Serialize(wmstaskDto)).Data; |
| | | if (result && httpResponse != null) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | #endregion |
| | | #endregion åå®¹ææ¥å£ |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// ä¿®æ¹ä»»å¡ç¶æï¼æ ¹æ®ä»»å¡IDä¿®æ¹ä¸ºæå®ç¶æï¼ |
| | | /// </summary> |
| | | /// <param name="taskDto"></param> |
| | | /// <returns></returns> |
| | | [HttpGet, HttpPost, Route("UpdateTaskByStatus"), AllowAnonymous] |
| | | public async Task<WebResponseContent?> UpdateTaskByStatusAsync([FromBody] int taskId, int newStatus) |
| | | { |
| | | return await Service.UpdateTaskByStatusAsync(taskId, newStatus); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å åæºåæ¾è´§å®æåç©æµéç¥åæå容æå®æä¿¡å· |
| | | /// </summary> |
| | | /// <param name="input"></param> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | **/.classpath |
| | | **/.dockerignore |
| | | **/.env |
| | | **/.git |
| | | **/.gitignore |
| | | **/.project |
| | | **/.settings |
| | | **/.toolstarget |
| | | **/.vs |
| | | **/.vscode |
| | | **/*.*proj.user |
| | | **/*.dbmdl |
| | | **/*.jfm |
| | | **/azds.yaml |
| | | **/bin |
| | | **/charts |
| | | **/docker-compose* |
| | | **/Dockerfile* |
| | | **/node_modules |
| | | **/npm-debug.log |
| | | **/obj |
| | | **/secrets.dev.yaml |
| | | **/values.dev.yaml |
| | | LICENSE |
| | | README.md |
| | | !**/.gitignore |
| | | !.git/HEAD |
| | | !.git/config |
| | | !.git/packed-refs |
| | | !.git/refs/heads/** |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System.Net; |
| | | using System.Net.Sockets; |
| | | using System.Text; |
| | | |
| | | var options = ClientOptions.FromArgs(args); |
| | | |
| | | Console.WriteLine($"åå¤å¯å¨ {options.ClientCount} 个客æ·ç«¯ï¼è¿æ¥å° {options.ServerHost}:{options.ServerPort}"); |
| | | |
| | | var tasks = Enumerable.Range(0, options.ClientCount) |
| | | .Select(i => RunClientAsync(i + 1, options)) |
| | | .ToArray(); |
| | | |
| | | await Task.WhenAll(tasks); |
| | | |
| | | static async Task RunClientAsync(int clientId, ClientOptions options) |
| | | { |
| | | var localPort = options.StartLocalPort + clientId - 1; |
| | | |
| | | using var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); |
| | | client.Bind(new IPEndPoint(IPAddress.Any, localPort)); |
| | | |
| | | await client.ConnectAsync(options.ServerHost, options.ServerPort); |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} å·²è¿æ¥ï¼æ¬å°ç«¯å£: {localPort}"); |
| | | |
| | | var text = $"Hello from client #{clientId}"; |
| | | var sendBuffer = Encoding.UTF8.GetBytes(text); |
| | | await client.SendAsync(sendBuffer, SocketFlags.None); |
| | | |
| | | var receiveBuffer = new byte[1024]; |
| | | var length = await client.ReceiveAsync(receiveBuffer, SocketFlags.None); |
| | | if (length > 0) |
| | | { |
| | | var response = Encoding.UTF8.GetString(receiveBuffer, 0, length); |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} æ¶å°: {response}"); |
| | | } |
| | | |
| | | client.Shutdown(SocketShutdown.Both); |
| | | } |
| | | |
| | | file sealed class ClientOptions |
| | | { |
| | | public int ClientCount { get; init; } = 1; |
| | | public string ServerHost { get; init; } = "127.0.0.1"; |
| | | public int ServerPort { get; init; } = 5000; |
| | | public int StartLocalPort { get; init; } = 6000; |
| | | |
| | | public static ClientOptions FromArgs(string[] args) |
| | | { |
| | | var map = args |
| | | .Select(v => v.Split('=', 2, StringSplitOptions.TrimEntries)) |
| | | .Where(parts => parts.Length == 2) |
| | | .ToDictionary(parts => parts[0].TrimStart('-', '/').ToLowerInvariant(), parts => parts[1]); |
| | | |
| | | return new ClientOptions |
| | | { |
| | | ClientCount = GetInt(map, "count", 1), |
| | | ServerHost = GetString(map, "host", "127.0.0.1"), |
| | | ServerPort = GetInt(map, "serverport", 5000), |
| | | StartLocalPort = GetInt(map, "localport", 6000) |
| | | }; |
| | | } |
| | | |
| | | private static int GetInt(Dictionary<string, string> map, string key, int defaultValue) |
| | | => map.TryGetValue(key, out var value) && int.TryParse(value, out var number) ? number : defaultValue; |
| | | |
| | | private static string GetString(Dictionary<string, string> map, string key, string defaultValue) |
| | | => map.TryGetValue(key, out var value) && !string.IsNullOrWhiteSpace(value) ? value : defaultValue; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System.Net; |
| | | using System.Net.Sockets; |
| | | using System.Text; |
| | | |
| | | var options = ClientOptions.FromArgs(args); |
| | | |
| | | Console.WriteLine($"åå¤å¯å¨ {options.ClientCount} 个客æ·ç«¯ï¼è¿æ¥å° {options.ServerHost}:{options.ServerPort}"); |
| | | |
| | | var tasks = Enumerable.Range(0, options.ClientCount) |
| | | .Select(i => RunClientAsync(i + 1, options)) |
| | | .ToArray(); |
| | | |
| | | await Task.WhenAll(tasks); |
| | | |
| | | static async Task RunClientAsync(int clientId, ClientOptions options) |
| | | { |
| | | var localPort = options.StartLocalPort + clientId - 1; |
| | | |
| | | using var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); |
| | | client.Bind(new IPEndPoint(IPAddress.Any, localPort)); |
| | | |
| | | await client.ConnectAsync(options.ServerHost, options.ServerPort); |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} å·²è¿æ¥ï¼æ¬å°ç«¯å£: {localPort}"); |
| | | |
| | | var text = $"Hello from client #{clientId}"; |
| | | var sendBuffer = Encoding.UTF8.GetBytes(text); |
| | | await client.SendAsync(sendBuffer, SocketFlags.None); |
| | | |
| | | var receiveBuffer = new byte[1024]; |
| | | var length = await client.ReceiveAsync(receiveBuffer, SocketFlags.None); |
| | | if (length > 0) |
| | | { |
| | | var response = Encoding.UTF8.GetString(receiveBuffer, 0, length); |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} æ¶å°: {response}"); |
| | | } |
| | | |
| | | client.Shutdown(SocketShutdown.Both); |
| | | } |
| | | |
| | | file sealed class ClientOptions |
| | | { |
| | | public int ClientCount { get; init; } = 1; |
| | | public string ServerHost { get; init; } = "127.0.0.1"; |
| | | public int ServerPort { get; init; } = 5000; |
| | | public int StartLocalPort { get; init; } = 6000; |
| | | |
| | | public static ClientOptions FromArgs(string[] args) |
| | | { |
| | | var map = args |
| | | .Select(v => v.Split('=', 2, StringSplitOptions.TrimEntries)) |
| | | .Where(parts => parts.Length == 2) |
| | | .ToDictionary(parts => parts[0].TrimStart('-', '/').ToLowerInvariant(), parts => parts[1]); |
| | | |
| | | return new ClientOptions |
| | | { |
| | | ClientCount = GetInt(map, "count", 1), |
| | | ServerHost = GetString(map, "host", "127.0.0.1"), |
| | | ServerPort = GetInt(map, "serverport", 5000), |
| | | StartLocalPort = GetInt(map, "localport", 6000) |
| | | }; |
| | | } |
| | | |
| | | private static int GetInt(Dictionary<string, string> map, string key, int defaultValue) |
| | | => map.TryGetValue(key, out var value) && int.TryParse(value, out var number) ? number : defaultValue; |
| | | |
| | | private static string GetString(Dictionary<string, string> map, string key, string defaultValue) |
| | | => map.TryGetValue(key, out var value) && !string.IsNullOrWhiteSpace(value) ? value : defaultValue; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // See https://aka.ms/new-console-template for more information |
| | | Console.WriteLine("Hello, World!"); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // See https://aka.ms/new-console-template for more information |
| | | Console.WriteLine("Hello, World!"); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System.Net; |
| | | using System.Net.Sockets; |
| | | using System.Text; |
| | | |
| | | var options = ClientOptions.FromArgs(args); |
| | | |
| | | Console.WriteLine($"åå¤å¯å¨ {options.ClientCount} 个客æ·ç«¯ï¼è¿æ¥å° {options.ServerHost}:{options.ServerPort}"); |
| | | |
| | | var tasks = Enumerable.Range(0, options.ClientCount) |
| | | .Select(i => RunClientAsync(i + 1, options)) |
| | | .ToArray(); |
| | | |
| | | await Task.WhenAll(tasks); |
| | | |
| | | static async Task RunClientAsync(int clientId, ClientOptions options) |
| | | { |
| | | var localPort = options.StartLocalPort + clientId - 1; |
| | | |
| | | using var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); |
| | | client.Bind(new IPEndPoint(IPAddress.Any, localPort)); |
| | | |
| | | await client.ConnectAsync(options.ServerHost, options.ServerPort); |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} å·²è¿æ¥ï¼æ¬å°ç«¯å£: {localPort}"); |
| | | |
| | | await WriteMessageAsync(client, clientId, $"Hello from client #{clientId}"); |
| | | await ReadMessageAsync(client, clientId); |
| | | |
| | | client.Shutdown(SocketShutdown.Both); |
| | | } |
| | | |
| | | static async Task WriteMessageAsync(Socket client, int clientId, string message) |
| | | { |
| | | var framedMessage = $"<START>{message}<END>"; |
| | | var sendBuffer = Encoding.UTF8.GetBytes(framedMessage); |
| | | await client.SendAsync(sendBuffer, SocketFlags.None); |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} åé: {framedMessage}"); |
| | | } |
| | | |
| | | static async Task ReadMessageAsync(Socket client, int clientId) |
| | | { |
| | | var receiveBuffer = new byte[1024]; |
| | | var length = await client.ReceiveAsync(receiveBuffer, SocketFlags.None); |
| | | if (length <= 0) |
| | | { |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} æªæ¥æ¶å°æ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | var response = Encoding.UTF8.GetString(receiveBuffer, 0, length); |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} æ¶å°: {response}"); |
| | | } |
| | | |
| | | file sealed class ClientOptions |
| | | { |
| | | public int ClientCount { get; init; } = 1; |
| | | public string ServerHost { get; init; } = "127.0.0.1"; |
| | | public int ServerPort { get; init; } = 5000; |
| | | public int StartLocalPort { get; init; } = 6000; |
| | | |
| | | public static ClientOptions FromArgs(string[] args) |
| | | { |
| | | var map = args |
| | | .Select(v => v.Split('=', 2, StringSplitOptions.TrimEntries)) |
| | | .Where(parts => parts.Length == 2) |
| | | .ToDictionary(parts => parts[0].TrimStart('-', '/').ToLowerInvariant(), parts => parts[1]); |
| | | |
| | | return new ClientOptions |
| | | { |
| | | ClientCount = GetInt(map, "count", 1), |
| | | ServerHost = GetString(map, "host", "127.0.0.1"), |
| | | ServerPort = GetInt(map, "serverport", 5000), |
| | | StartLocalPort = GetInt(map, "localport", 6000) |
| | | }; |
| | | } |
| | | |
| | | private static int GetInt(Dictionary<string, string> map, string key, int defaultValue) |
| | | => map.TryGetValue(key, out var value) && int.TryParse(value, out var number) ? number : defaultValue; |
| | | |
| | | private static string GetString(Dictionary<string, string> map, string key, string defaultValue) |
| | | => map.TryGetValue(key, out var value) && !string.IsNullOrWhiteSpace(value) ? value : defaultValue; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System.Net; |
| | | using System.Net.Sockets; |
| | | using System.Text; |
| | | |
| | | var options = ClientOptions.FromArgs(args); |
| | | |
| | | Console.WriteLine($"åå¤å¯å¨ {options.ClientCount} 个客æ·ç«¯ï¼è¿æ¥å° {options.ServerHost}:{options.ServerPort}"); |
| | | |
| | | var tasks = Enumerable.Range(0, options.ClientCount) |
| | | .Select(i => RunClientAsync(i + 1, options)) |
| | | .ToArray(); |
| | | |
| | | await Task.WhenAll(tasks); |
| | | |
| | | static async Task RunClientAsync(int clientId, ClientOptions options) |
| | | { |
| | | var localPort = options.StartLocalPort + clientId - 1; |
| | | |
| | | using var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); |
| | | client.Bind(new IPEndPoint(IPAddress.Any, localPort)); |
| | | |
| | | await client.ConnectAsync(options.ServerHost, options.ServerPort); |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} å·²è¿æ¥ï¼æ¬å°ç«¯å£: {localPort}"); |
| | | |
| | | await WriteMessageAsync(client, clientId, $"Hello from client #{clientId}"); |
| | | await ReadMessageAsync(client, clientId); |
| | | |
| | | client.Shutdown(SocketShutdown.Both); |
| | | } |
| | | |
| | | static async Task WriteMessageAsync(Socket client, int clientId, string message) |
| | | { |
| | | var framedMessage = $"<START>{message}<END>"; |
| | | var sendBuffer = Encoding.UTF8.GetBytes(framedMessage); |
| | | await client.SendAsync(sendBuffer, SocketFlags.None); |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} åé: {framedMessage}"); |
| | | } |
| | | |
| | | static async Task ReadMessageAsync(Socket client, int clientId) |
| | | { |
| | | var receiveBuffer = new byte[1024]; |
| | | var length = await client.ReceiveAsync(receiveBuffer, SocketFlags.None); |
| | | if (length <= 0) |
| | | { |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} æªæ¥æ¶å°æ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | var response = Encoding.UTF8.GetString(receiveBuffer, 0, length); |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} æ¶å°: {response}"); |
| | | } |
| | | |
| | | file sealed class ClientOptions |
| | | { |
| | | public int ClientCount { get; init; } = 1; |
| | | public string ServerHost { get; init; } = "127.0.0.1"; |
| | | public int ServerPort { get; init; } = 5000; |
| | | public int StartLocalPort { get; init; } = 6000; |
| | | |
| | | public static ClientOptions FromArgs(string[] args) |
| | | { |
| | | var map = args |
| | | .Select(v => v.Split('=', 2, StringSplitOptions.TrimEntries)) |
| | | .Where(parts => parts.Length == 2) |
| | | .ToDictionary(parts => parts[0].TrimStart('-', '/').ToLowerInvariant(), parts => parts[1]); |
| | | |
| | | return new ClientOptions |
| | | { |
| | | ClientCount = GetInt(map, "count", 1), |
| | | ServerHost = GetString(map, "host", "127.0.0.1"), |
| | | ServerPort = GetInt(map, "serverport", 5000), |
| | | StartLocalPort = GetInt(map, "localport", 6000) |
| | | }; |
| | | } |
| | | |
| | | private static int GetInt(Dictionary<string, string> map, string key, int defaultValue) |
| | | => map.TryGetValue(key, out var value) && int.TryParse(value, out var number) ? number : defaultValue; |
| | | |
| | | private static string GetString(Dictionary<string, string> map, string key, string defaultValue) |
| | | => map.TryGetValue(key, out var value) && !string.IsNullOrWhiteSpace(value) ? value : defaultValue; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System.Net; |
| | | using System.Net.Sockets; |
| | | using System.Text; |
| | | |
| | | var options = ClientOptions.FromArgs(args); |
| | | |
| | | Console.WriteLine($"åå¤å¯å¨ {options.ClientCount} 个客æ·ç«¯ï¼è¿æ¥å° {options.ServerHost}:{options.ServerPort}"); |
| | | |
| | | var tasks = Enumerable.Range(0, options.ClientCount) |
| | | .Select(i => RunClientAsync(i + 1, options)) |
| | | .ToArray(); |
| | | |
| | | await Task.WhenAll(tasks); |
| | | |
| | | static async Task RunClientAsync(int clientId, ClientOptions options) |
| | | { |
| | | var localPort = options.StartLocalPort + clientId - 1; |
| | | |
| | | using var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); |
| | | client.Bind(new IPEndPoint(IPAddress.Any, localPort)); |
| | | |
| | | await client.ConnectAsync(options.ServerHost, options.ServerPort); |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} å·²è¿æ¥ï¼æ¬å°ç«¯å£: {localPort}"); |
| | | |
| | | |
| | | await WriteMessageAsync(client, clientId, $"Homed"); |
| | | await WriteMessageAsync(client, clientId, $"Runmodemode,2"); |
| | | await WriteMessageAsync(client, clientId, $"Armobject,0"); |
| | | await WriteMessageAsync(client, clientId, $"Controlmode,1"); |
| | | |
| | | await ReadMessageAsync(client, clientId); |
| | | client.Shutdown(SocketShutdown.Both); |
| | | } |
| | | |
| | | static async Task WriteMessageAsync(Socket client, int clientId, string message) |
| | | { |
| | | var framedMessage = $"<START>{message}<END>"; |
| | | var sendBuffer = Encoding.UTF8.GetBytes(framedMessage); |
| | | await client.SendAsync(sendBuffer, SocketFlags.None); |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} åé: {framedMessage}"); |
| | | } |
| | | |
| | | static async Task ReadMessageAsync(Socket client, int clientId) |
| | | { |
| | | var receiveBuffer = new byte[1024]; |
| | | var length = await client.ReceiveAsync(receiveBuffer, SocketFlags.None); |
| | | if (length <= 0) |
| | | { |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} æªæ¥æ¶å°æ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | var response = Encoding.UTF8.GetString(receiveBuffer, 0, length); |
| | | if (!response.StartsWith("<START>") || !response.EndsWith("<END>")) |
| | | { |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} æ¶å°æ ææ¶æ¯ï¼ç¼ºå°æ¶æ¯å¤´ææ¶æ¯å°¾ï¼ï¼å·²å¿½ç¥"); |
| | | return; |
| | | } |
| | | |
| | | var content = response["<START>".Length..^"<END>".Length]; |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} æ¶å°: {content}"); |
| | | } |
| | | |
| | | file sealed class ClientOptions |
| | | { |
| | | public int ClientCount { get; init; } = 1; |
| | | public string ServerHost { get; init; } = "127.0.0.1"; |
| | | public int ServerPort { get; init; } = 2000; |
| | | public int StartLocalPort { get; init; } = 62312; |
| | | |
| | | public static ClientOptions FromArgs(string[] args) |
| | | { |
| | | var map = args |
| | | .Select(v => v.Split('=', 2, StringSplitOptions.TrimEntries)) |
| | | .Where(parts => parts.Length == 2) |
| | | .ToDictionary(parts => parts[0].TrimStart('-', '/').ToLowerInvariant(), parts => parts[1]); |
| | | |
| | | return new ClientOptions |
| | | { |
| | | ClientCount = GetInt(map, "count", 1), |
| | | ServerHost = GetString(map, "host", "127.0.0.1"), |
| | | ServerPort = GetInt(map, "serverport", 2000), |
| | | StartLocalPort = GetInt(map, "localport", 62312) |
| | | }; |
| | | } |
| | | |
| | | private static int GetInt(Dictionary<string, string> map, string key, int defaultValue) |
| | | => map.TryGetValue(key, out var value) && int.TryParse(value, out var number) ? number : defaultValue; |
| | | |
| | | private static string GetString(Dictionary<string, string> map, string key, string defaultValue) |
| | | => map.TryGetValue(key, out var value) && !string.IsNullOrWhiteSpace(value) ? value : defaultValue; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System.Net; |
| | | using System.Net.Sockets; |
| | | using System.Text; |
| | | |
| | | var options = ClientOptions.FromArgs(args); |
| | | |
| | | Console.WriteLine($"åå¤å¯å¨ {options.ClientCount} 个客æ·ç«¯ï¼è¿æ¥å° {options.ServerHost}:{options.ServerPort}"); |
| | | |
| | | var tasks = Enumerable.Range(0, options.ClientCount) |
| | | .Select(i => RunClientAsync(i + 1, options)) |
| | | .ToArray(); |
| | | |
| | | await Task.WhenAll(tasks); |
| | | |
| | | static async Task RunClientAsync(int clientId, ClientOptions options) |
| | | { |
| | | var localPort = options.StartLocalPort + clientId - 1; |
| | | |
| | | using var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); |
| | | client.Bind(new IPEndPoint(IPAddress.Any, localPort)); |
| | | |
| | | await client.ConnectAsync(options.ServerHost, options.ServerPort); |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} å·²è¿æ¥ï¼æ¬å°ç«¯å£: {localPort}"); |
| | | |
| | | |
| | | await WriteMessageAsync(client, clientId, $"Homed"); |
| | | await WriteMessageAsync(client, clientId, $"Runmodemode,2"); |
| | | await WriteMessageAsync(client, clientId, $"Armobject,0"); |
| | | await WriteMessageAsync(client, clientId, $"Controlmode,1"); |
| | | |
| | | await ReadMessageAsync(client, clientId); |
| | | client.Shutdown(SocketShutdown.Both); |
| | | } |
| | | |
| | | static async Task WriteMessageAsync(Socket client, int clientId, string message) |
| | | { |
| | | var framedMessage = $"<START>{message}<END>"; |
| | | var sendBuffer = Encoding.UTF8.GetBytes(framedMessage); |
| | | await client.SendAsync(sendBuffer, SocketFlags.None); |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} åé: {framedMessage}"); |
| | | } |
| | | |
| | | static async Task ReadMessageAsync(Socket client, int clientId) |
| | | { |
| | | var receiveBuffer = new byte[1024]; |
| | | var length = await client.ReceiveAsync(receiveBuffer, SocketFlags.None); |
| | | if (length <= 0) |
| | | { |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} æªæ¥æ¶å°æ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | var response = Encoding.UTF8.GetString(receiveBuffer, 0, length); |
| | | if (!response.StartsWith("<START>") || !response.EndsWith("<END>")) |
| | | { |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} æ¶å°æ ææ¶æ¯ï¼ç¼ºå°æ¶æ¯å¤´ææ¶æ¯å°¾ï¼ï¼å·²å¿½ç¥"); |
| | | return; |
| | | } |
| | | |
| | | var content = response["<START>".Length..^"<END>".Length]; |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} æ¶å°: {content}"); |
| | | } |
| | | |
| | | file sealed class ClientOptions |
| | | { |
| | | public int ClientCount { get; init; } = 1; |
| | | public string ServerHost { get; init; } = "127.0.0.1"; |
| | | public int ServerPort { get; init; } = 2000; |
| | | public int StartLocalPort { get; init; } = 62312; |
| | | |
| | | public static ClientOptions FromArgs(string[] args) |
| | | { |
| | | var map = args |
| | | .Select(v => v.Split('=', 2, StringSplitOptions.TrimEntries)) |
| | | .Where(parts => parts.Length == 2) |
| | | .ToDictionary(parts => parts[0].TrimStart('-', '/').ToLowerInvariant(), parts => parts[1]); |
| | | |
| | | return new ClientOptions |
| | | { |
| | | ClientCount = GetInt(map, "count", 1), |
| | | ServerHost = GetString(map, "host", "127.0.0.1"), |
| | | ServerPort = GetInt(map, "serverport", 2000), |
| | | StartLocalPort = GetInt(map, "localport", 62312) |
| | | }; |
| | | } |
| | | |
| | | private static int GetInt(Dictionary<string, string> map, string key, int defaultValue) |
| | | => map.TryGetValue(key, out var value) && int.TryParse(value, out var number) ? number : defaultValue; |
| | | |
| | | private static string GetString(Dictionary<string, string> map, string key, string defaultValue) |
| | | => map.TryGetValue(key, out var value) && !string.IsNullOrWhiteSpace(value) ? value : defaultValue; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "Version": 1, |
| | | "WorkspaceRootPath": "C:\\Users\\29028\\Desktop\\\u673A\u68B0\u624B\u5BA2\u6237\u7AEF\\RobotClient\\", |
| | | "Documents": [ |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{B1C3E674-86D3-6DBD-F67F-E7F395016C7C}|RobotClient.csproj|c:\\users\\29028\\desktop\\\u673A\u68B0\u624B\u5BA2\u6237\u7AEF\\robotclient\\program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{B1C3E674-86D3-6DBD-F67F-E7F395016C7C}|RobotClient.csproj|solutionrelative:program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | } |
| | | ], |
| | | "DocumentGroupContainers": [ |
| | | { |
| | | "Orientation": 0, |
| | | "VerticalTabListWidth": 256, |
| | | "DocumentGroups": [ |
| | | { |
| | | "DockedWidth": 200, |
| | | "SelectedChildIndex": 3, |
| | | "Children": [ |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:128:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}" |
| | | }, |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:0:0:{40ea2e6b-2121-4bb8-a43e-c83c04b51041}" |
| | | }, |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:0:0:{aa2115a1-9712-457b-9047-dbb71ca2cdd2}" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 0, |
| | | "Title": "Program.cs", |
| | | "DocumentMoniker": "C:\\Users\\29028\\Desktop\\\u673A\u68B0\u624B\u5BA2\u6237\u7AEF\\RobotClient\\Program.cs", |
| | | "RelativeDocumentMoniker": "Program.cs", |
| | | "ToolTip": "C:\\Users\\29028\\Desktop\\\u673A\u68B0\u624B\u5BA2\u6237\u7AEF\\RobotClient\\Program.cs", |
| | | "RelativeToolTip": "Program.cs", |
| | | "ViewState": "AgIAAPwAAAAAAAAAAAAowBgBAABBAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-27T07:38:54.023Z", |
| | | "EditorCaption": "" |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "Version": 1, |
| | | "WorkspaceRootPath": "C:\\Users\\29028\\Desktop\\\u673A\u68B0\u624B\u5BA2\u6237\u7AEF\\RobotClient\\", |
| | | "Documents": [ |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{B1C3E674-86D3-6DBD-F67F-E7F395016C7C}|RobotClient.csproj|c:\\users\\29028\\desktop\\\u673A\u68B0\u624B\u5BA2\u6237\u7AEF\\robotclient\\program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", |
| | | "RelativeMoniker": "D:0:0:{B1C3E674-86D3-6DBD-F67F-E7F395016C7C}|RobotClient.csproj|solutionrelative:program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" |
| | | } |
| | | ], |
| | | "DocumentGroupContainers": [ |
| | | { |
| | | "Orientation": 0, |
| | | "VerticalTabListWidth": 256, |
| | | "DocumentGroups": [ |
| | | { |
| | | "DockedWidth": 200, |
| | | "SelectedChildIndex": 3, |
| | | "Children": [ |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:128:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}" |
| | | }, |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:0:0:{40ea2e6b-2121-4bb8-a43e-c83c04b51041}" |
| | | }, |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:0:0:{aa2115a1-9712-457b-9047-dbb71ca2cdd2}" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 0, |
| | | "Title": "Program.cs", |
| | | "DocumentMoniker": "C:\\Users\\29028\\Desktop\\\u673A\u68B0\u624B\u5BA2\u6237\u7AEF\\RobotClient\\Program.cs", |
| | | "RelativeDocumentMoniker": "Program.cs", |
| | | "ToolTip": "C:\\Users\\29028\\Desktop\\\u673A\u68B0\u624B\u5BA2\u6237\u7AEF\\RobotClient\\Program.cs", |
| | | "RelativeToolTip": "Program.cs", |
| | | "ViewState": "AgIAAPwAAAAAAAAAAAAowBgBAABBAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", |
| | | "WhenOpened": "2026-02-27T07:38:54.023Z", |
| | | "EditorCaption": "" |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # CLAUDE.md |
| | | |
| | | This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| | | |
| | | ## Project Overview |
| | | |
| | | RobotClient is a .NET 8.0 TCP client simulator for a robotic arm control system. It creates multiple concurrent TCP connections to a server, simulating robotic arm clients that can send/receive control commands and status messages. |
| | | |
| | | ## Build and Run Commands |
| | | |
| | | ```bash |
| | | # Build the project |
| | | dotnet build |
| | | |
| | | # Run with default settings (1 client, connects to 127.0.0.1:2000) |
| | | dotnet run |
| | | |
| | | # Run with custom options (format: key=value) |
| | | dotnet run -- count=5 host=192.168.1.100 serverport=3000 localport=50000 reconnect=false |
| | | |
| | | # Build Docker image |
| | | docker build -t robot-client . |
| | | |
| | | # Run in Docker |
| | | docker run -it robot-client |
| | | ``` |
| | | |
| | | ### Command-Line Options |
| | | |
| | | | Option | Default | Description | |
| | | |--------|---------|-------------| |
| | | | `count` | 1 | Number of client connections to create | |
| | | | `host` | 127.0.0.1 | Server host address | |
| | | | `serverport` | 2000 | Server port | |
| | | | `localport` | 62312 | Starting local port (each client uses localport + clientId) | |
| | | | `reconnect` | true | Enable automatic reconnection | |
| | | | `reconnectinterval` | 5000 | Reconnect delay in milliseconds | |
| | | | `maxreconnect` | -1 | Max reconnect attempts (-1 = infinite) | |
| | | |
| | | ## Architecture |
| | | |
| | | The entire application is contained in `Program.cs` using C# top-level statements. The architecture follows a multi-client concurrent pattern: |
| | | |
| | | ### Core Components |
| | | |
| | | 1. **ClientOptions** (line 358-397): Configuration parser that processes command-line arguments into a strongly-typed options object. |
| | | |
| | | 2. **RunClientAsync** (line 23-50): Entry point for each client. Binds to a local port, establishes initial connection, spawns a background listener with reconnection logic, and sends initialization commands. |
| | | |
| | | 3. **ConnectAsync** (line 52-67): Low-level TCP connection using `Socket` with explicit local port binding. |
| | | |
| | | 4. **RunWithReconnectAsync** (line 69-134): Wrapper around the message listener that handles automatic reconnection with configurable limits and delays. |
| | | |
| | | 5. **ListenServerMessagesAsync** (line 181-234): Continuous receive loop that buffers incoming data and parses framed messages. Properly cleans up sockets on disconnect. |
| | | |
| | | 6. **TryReadFramedMessages** (line 236-293): Parses messages using `<START>content<END>` framing protocol. Handles partial messages and buffers incomplete data. Contains simulated robot commands: |
| | | - `Pickbattery,1` â Simulates picking operation (5 seconds) |
| | | - `Putbattery,1` â Simulates placing operation (5 seconds) |
| | | |
| | | 7. **SendLoopAsync** (line 295-356): Interactive console input loop allowing manual commands to specific clients using format `clientId:message` (e.g., `1:Status`). Type `exit` to quit. |
| | | |
| | | ### Initialization Sequence |
| | | |
| | | Each client sends these commands on connection/startup: |
| | | 1. `Homed` â Wait 500ms |
| | | 2. `Runmode,2` â Wait 500ms |
| | | 3. `Armobject,0` â Wait 500ms |
| | | 4. `Controlmode,1` |
| | | |
| | | ### Protocol |
| | | |
| | | All messages use the frame format: `<START>message<END>` |
| | | |
| | | - UTF-8 encoded |
| | | - Message boundaries are explicit, allowing streaming |
| | | - Invalid data before `<START>` is discarded |
| | | - Cache limits 10KB to prevent memory exhaustion |
| | | |
| | | ### Thread Safety |
| | | |
| | | - `ConcurrentDictionary<int, Socket>` tracks active client connections |
| | | - Each client runs its own background Task for receiving messages |
| | | - Socket cleanup happens in `finally` blocks to prevent resource leaks |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # 请åé
https://aka.ms/customizecontainer 以äºè§£å¦ä½èªå®ä¹è°è¯å®¹å¨ï¼ä»¥å Visual Studio å¦ä½ä½¿ç¨æ¤ Dockerfile çææ å以æ´å¿«å°è¿è¡è°è¯ã |
| | | |
| | | # æ¤é¶æ®µç¨äºå¨å¿«é模å¼(é»è®¤ä¸ºè°è¯é
ç½®)ä¸ä» VS è¿è¡æ¶ |
| | | FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base |
| | | USER $APP_UID |
| | | WORKDIR /app |
| | | |
| | | |
| | | # æ¤é¶æ®µç¨äºçææå¡é¡¹ç® |
| | | FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build |
| | | ARG BUILD_CONFIGURATION=Release |
| | | WORKDIR /src |
| | | COPY ["RobotClient.csproj", "."] |
| | | RUN dotnet restore "./RobotClient.csproj" |
| | | COPY . . |
| | | WORKDIR "/src/." |
| | | RUN dotnet build "./RobotClient.csproj" -c $BUILD_CONFIGURATION -o /app/build |
| | | |
| | | # æ¤é¶æ®µç¨äºåå¸è¦å¤å¶å°æç»é¶æ®µçæå¡é¡¹ç® |
| | | FROM build AS publish |
| | | ARG BUILD_CONFIGURATION=Release |
| | | RUN dotnet publish "./RobotClient.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false |
| | | |
| | | # æ¤é¶æ®µå¨ç产ä¸ä½¿ç¨ï¼æå¨å¸¸è§æ¨¡å¼ä¸ä» VS è¿è¡æ¶ä½¿ç¨(å¨ä¸ä½¿ç¨è°è¯é
ç½®æ¶ä¸ºé»è®¤å¼) |
| | | FROM base AS final |
| | | WORKDIR /app |
| | | COPY --from=publish /app/publish . |
| | | ENTRYPOINT ["dotnet", "RobotClient.dll"] |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System.Net; |
| | | using System.Net.Sockets; |
| | | using System.Text; |
| | | using System.Collections.Concurrent; |
| | | |
| | | var options = ClientOptions.FromArgs(args); |
| | | var cts = new CancellationTokenSource(); |
| | | var clients = new ConcurrentDictionary<int, Socket>(); |
| | | |
| | | Console.WriteLine($"åå¤å¯å¨ {options.ClientCount} 个客æ·ç«¯ï¼è¿æ¥å° {options.ServerHost}:{options.ServerPort}"); |
| | | |
| | | // å¯å¨ææå®¢æ·ç«¯è¿æ¥ä»»å¡ |
| | | var connectTasks = Enumerable.Range(0, options.ClientCount) |
| | | .Select(i => RunClientAsync(i + 1, options, clients, cts.Token)) |
| | | .ToArray(); |
| | | |
| | | // çå¾
ææå®¢æ·ç«¯è¿æ¥å®æ |
| | | await Task.WhenAll(connectTasks); |
| | | |
| | | // å¯å¨åé循ç¯ï¼ä¸çå¬ä»»å¡å¹¶è¡è¿è¡ï¼ |
| | | await SendLoopAsync(clients, cts); |
| | | |
| | | static async Task RunClientAsync(int clientId, ClientOptions options, ConcurrentDictionary<int, Socket> clients, CancellationToken cancellationToken) |
| | | { |
| | | var localPort = options.StartLocalPort + clientId - 1; |
| | | |
| | | // éªè¯ç«¯å£èå´ |
| | | if (localPort > 65535) |
| | | { |
| | | Console.WriteLine($"é误: 客æ·ç«¯#{clientId} çæ¬å°ç«¯å£ {localPort} è¶
åºææèå´"); |
| | | return; |
| | | } |
| | | |
| | | // 馿¬¡è¿æ¥ |
| | | var client = await ConnectAsync(clientId, options, localPort, cancellationToken); |
| | | if (client == null) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | clients[clientId] = client; |
| | | |
| | | // å¯å¨å¸¦éè¿åè½ççå¬ä»»å¡ï¼åå°è¿è¡ï¼ä¸é»å¡ï¼ |
| | | _ = Task.Run(() => RunWithReconnectAsync(clientId, options, localPort, clients, cancellationToken), cancellationToken); |
| | | |
| | | // åéåå§åæ¶æ¯ |
| | | await InitializeClientAsync(client, clientId); |
| | | |
| | | // ç«å³è¿åï¼è®©ä¸»çº¿ç¨ç»§ç»æ§è¡ SendLoopAsync |
| | | } |
| | | |
| | | static async Task<Socket?> ConnectAsync(int clientId, ClientOptions options, int localPort, CancellationToken cancellationToken) |
| | | { |
| | | try |
| | | { |
| | | var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); |
| | | // å
许éç¨æ¬å°ç«¯å£ï¼è§£å³éè¿æ¶ç«¯å£è¢«å ç¨çé®é¢ |
| | | client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); |
| | | client.Bind(new IPEndPoint(IPAddress.Any, localPort)); |
| | | await client.ConnectAsync(options.ServerHost, options.ServerPort); |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} å·²è¿æ¥ï¼æ¬å°ç«¯å£: {localPort}"); |
| | | return client; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} è¿æ¥å¤±è´¥: {ex.Message}"); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | static async Task RunWithReconnectAsync(int clientId, ClientOptions options, int localPort, ConcurrentDictionary<int, Socket> clients, CancellationToken cancellationToken) |
| | | { |
| | | var reconnectCount = 0; |
| | | |
| | | while (!cancellationToken.IsCancellationRequested) |
| | | { |
| | | Socket? client = null; |
| | | try |
| | | { |
| | | // è·åå½åè¿æ¥ç Socketï¼å¦æåå¨ï¼ |
| | | if (clients.TryGetValue(clientId, out client)) |
| | | { |
| | | // ç嬿¶æ¯ï¼ç´å°è¿æ¥æå¼ |
| | | // ListenServerMessagesAsync ç finally ä¼èªå¨æ¸
çæå¼ç Socket |
| | | await ListenServerMessagesAsync(client, clientId, cancellationToken, clients); |
| | | } |
| | | |
| | | // è¿æ¥å·²æå¼ï¼è¿å
¥éè¿é»è¾ |
| | | reconnectCount++; |
| | | |
| | | // æ£æ¥æ¯å¦å¯ç¨éè¿ |
| | | if (!options.EnableReconnect) |
| | | { |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} éè¿å·²ç¦ç¨ï¼éåº"); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥éè¿æ¬¡æ°éå¶ |
| | | if (options.MaxReconnectAttempts > 0 && reconnectCount > options.MaxReconnectAttempts) |
| | | { |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} å·²è¾¾å°æå¤§éè¿æ¬¡æ° ({options.MaxReconnectAttempts})ï¼éåº"); |
| | | return; |
| | | } |
| | | |
| | | // çå¾
éè¿é´é |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} çå¾
{options.ReconnectIntervalMs / 1000} ç§åéè¿... (第 {reconnectCount} 次)"); |
| | | await Task.Delay(options.ReconnectIntervalMs, cancellationToken); |
| | | |
| | | // å°è¯éæ°è¿æ¥ |
| | | client = await ConnectAsync(clientId, options, localPort, cancellationToken); |
| | | if (client == null) |
| | | { |
| | | continue; |
| | | } |
| | | |
| | | // å°æ° Socket å å
¥åå
¸ |
| | | clients[clientId] = client; |
| | | |
| | | // éæ°åå§å |
| | | await InitializeClientAsync(client, clientId); |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} éè¿æåï¼å·²éæ°åå§å"); |
| | | } |
| | | catch (OperationCanceledException) |
| | | { |
| | | // æ£å¸¸åæ¶ |
| | | return; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} è¿è¡å¼å¸¸: {ex.Message}"); |
| | | clients.TryRemove(clientId, out _); |
| | | try { client?.Shutdown(SocketShutdown.Both); } catch { } |
| | | try { client?.Dispose(); } catch { } |
| | | } |
| | | } |
| | | } |
| | | |
| | | static async Task InitializeClientAsync(Socket client, int clientId) |
| | | { |
| | | await Task.Delay(5000); |
| | | await WriteMessageAsync(client, clientId, "Homed"); |
| | | await Task.Delay(500); |
| | | |
| | | await WriteMessageAsync(client, clientId, "Runmode,2"); |
| | | await Task.Delay(500); |
| | | |
| | | await WriteMessageAsync(client, clientId, "Armobject,0"); |
| | | await Task.Delay(500); |
| | | |
| | | await WriteMessageAsync(client, clientId, "Controlmode,1"); |
| | | } |
| | | |
| | | static async Task WriteMessageAsync(Socket client, int clientId, string message) |
| | | { |
| | | var framedMessage = $"<START>{message}<END>"; |
| | | var sendBuffer = Encoding.UTF8.GetBytes(framedMessage); |
| | | await client.SendAsync(sendBuffer, SocketFlags.None); |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} åé: {framedMessage}"); |
| | | } |
| | | |
| | | static async Task ReadMessageAsync(Socket client, int clientId) |
| | | { |
| | | var receiveBuffer = new byte[1024]; |
| | | var length = await client.ReceiveAsync(receiveBuffer, SocketFlags.None); |
| | | if (length <= 0) |
| | | { |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} æªæ¥æ¶å°æ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | var response = Encoding.UTF8.GetString(receiveBuffer, 0, length); |
| | | if (!response.StartsWith("<START>") || !response.EndsWith("<END>")) |
| | | { |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} æ¶å°æ ææ¶æ¯ï¼ç¼ºå°æ¶æ¯å¤´ææ¶æ¯å°¾ï¼ï¼å·²å¿½ç¥"); |
| | | return; |
| | | } |
| | | |
| | | var content = response["<START>".Length..^"<END>".Length]; |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} æ¶å°: {content}"); |
| | | |
| | | |
| | | } |
| | | |
| | | static async Task ListenServerMessagesAsync(Socket client, int clientId, CancellationToken cancellationToken, ConcurrentDictionary<int, Socket> clients) |
| | | { |
| | | var receiveBuffer = new byte[1024]; |
| | | var cache = new StringBuilder(); |
| | | |
| | | try |
| | | { |
| | | while (!cancellationToken.IsCancellationRequested) |
| | | { |
| | | int length; |
| | | try |
| | | { |
| | | length = await client.ReceiveAsync(receiveBuffer, SocketFlags.None, cancellationToken); |
| | | } |
| | | catch (SocketException) |
| | | { |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} 䏿å¡ç«¯æå¼è¿æ¥"); |
| | | return; |
| | | } |
| | | catch (ObjectDisposedException) |
| | | { |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} Socket å·²è¢«éæ¾"); |
| | | return; |
| | | } |
| | | |
| | | if (length <= 0) |
| | | { |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} 䏿å¡ç«¯æå¼è¿æ¥"); |
| | | return; |
| | | } |
| | | |
| | | cache.Append(Encoding.UTF8.GetString(receiveBuffer, 0, length)); |
| | | await TryReadFramedMessages(cache, clientId, client); |
| | | } |
| | | } |
| | | catch (OperationCanceledException) |
| | | { |
| | | // æ£å¸¸åæ¶ï¼ä¸éè¦è®°å½é误 |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} æ¥æ¶æ¶æ¯å¼å¸¸: {ex.Message}"); |
| | | } |
| | | finally |
| | | { |
| | | // è¿æ¥æå¼æ¶ï¼ä»åå
¸ä¸ç§»é¤è¿ä¸ª Socketï¼å¦æè¿æ¯å½åçè¯ï¼ |
| | | clients.TryRemove(clientId, out var removed); |
| | | if (removed == client) |
| | | { |
| | | try { client.Shutdown(SocketShutdown.Both); } catch { } |
| | | try { client.Dispose(); } catch { } |
| | | } |
| | | } |
| | | } |
| | | |
| | | static async Task TryReadFramedMessages(StringBuilder cache, int clientId, Socket client) |
| | | { |
| | | const string start = "<START>"; |
| | | const string end = "<END>"; |
| | | |
| | | while (true) |
| | | { |
| | | var text = cache.ToString(); |
| | | var startIndex = text.IndexOf(start, StringComparison.Ordinal); |
| | | if (startIndex < 0) |
| | | { |
| | | // æ²¡ææ¾å° START æ è®°ï¼ä¿çç¼åçå¾
æ´å¤æ°æ® |
| | | // ä½å¦æç¼åå¤ªå¤§ï¼æ¸
空以é²å
åæ³æ¼ |
| | | if (cache.Length > 10240) // 10KB éå¼ |
| | | { |
| | | cache.Clear(); |
| | | } |
| | | return; |
| | | } |
| | | |
| | | var endIndex = text.IndexOf(end, startIndex + start.Length, StringComparison.Ordinal); |
| | | if (endIndex < 0) |
| | | { |
| | | // ç§»é¤ START ä¹åçæ ææ°æ® |
| | | if (startIndex > 0) |
| | | { |
| | | cache.Remove(0, startIndex); |
| | | } |
| | | return; |
| | | } |
| | | |
| | | var contentStart = startIndex + start.Length; |
| | | var contentLength = endIndex - contentStart; |
| | | var content = text.Substring(contentStart, contentLength); |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} æ¶å°: {content}"); |
| | | |
| | | cache.Remove(0, endIndex + end.Length); |
| | | |
| | | if (content == "Pickbattery,1") |
| | | { |
| | | await WriteMessageAsync(client, clientId, "Running"); |
| | | await Task.Delay(1000); |
| | | await WriteMessageAsync(client, clientId, "Picking"); |
| | | |
| | | //await WriteMessageAsync(client, clientId, "PickFinished,1,2,3,4"); |
| | | } |
| | | else if (content == "Putbattery,1") |
| | | { |
| | | await WriteMessageAsync(client, clientId, "Running"); |
| | | await Task.Delay(500); |
| | | await WriteMessageAsync(client, clientId, "Puting"); |
| | | await Task.Delay(5000); |
| | | |
| | | //await WriteMessageAsync(client, clientId, "PutFinished,1,2,3,4"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | static async Task SendLoopAsync(ConcurrentDictionary<int, Socket> clients, CancellationTokenSource cts) |
| | | { |
| | | Console.WriteLine("è¾å
¥æ ¼å¼: 客æ·ç«¯ç¼å·:æ¶æ¯ï¼ä¾å¦ 1:Statusï¼è¾å
¥ exit éåº"); |
| | | |
| | | while (!cts.IsCancellationRequested) |
| | | { |
| | | var line = Console.ReadLine(); |
| | | if (string.IsNullOrWhiteSpace(line)) |
| | | { |
| | | continue; |
| | | } |
| | | |
| | | if (line.Equals("exit", StringComparison.OrdinalIgnoreCase)) |
| | | { |
| | | cts.Cancel(); |
| | | foreach (var socket in clients.Values) |
| | | { |
| | | try |
| | | { |
| | | socket.Shutdown(SocketShutdown.Both); |
| | | socket.Dispose(); |
| | | } |
| | | catch { } |
| | | } |
| | | return; |
| | | } |
| | | |
| | | var index = line.IndexOf(':'); |
| | | if (index <= 0 || index == line.Length - 1) |
| | | { |
| | | Console.WriteLine("è¾å
¥ä¸æ£ç¡®ï¼è¯·ä½¿ç¨: 客æ·ç«¯ç¼å·:æ¶æ¯"); |
| | | continue; |
| | | } |
| | | |
| | | var idText = line[..index]; |
| | | var message = line[(index + 1)..]; |
| | | if (!int.TryParse(idText, out var clientId) || !clients.TryGetValue(clientId, out var client)) |
| | | { |
| | | Console.WriteLine($"客æ·ç«¯#{idText} ä¸å卿æªè¿æ¥"); |
| | | continue; |
| | | } |
| | | |
| | | try |
| | | { |
| | | await WriteMessageAsync(client, clientId, message); |
| | | } |
| | | catch (ObjectDisposedException) |
| | | { |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} åé失败: Socket å·²å
³éï¼å¯è½æ£å¨éè¿ä¸ï¼"); |
| | | clients.TryRemove(clientId, out _); |
| | | } |
| | | catch (SocketException ex) |
| | | { |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} åé失败: {ex.Message}"); |
| | | clients.TryRemove(clientId, out _); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Console.WriteLine($"客æ·ç«¯#{clientId} åé失败: {ex.GetType().Name} - {ex.Message}"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | file sealed class ClientOptions |
| | | { |
| | | public int ClientCount { get; init; } = 1; |
| | | public string ServerHost { get; init; } = "127.0.0.1"; |
| | | public int ServerPort { get; init; } = 2000; |
| | | public int StartLocalPort { get; init; } = 62312; |
| | | public bool EnableReconnect { get; init; } = true; |
| | | public int ReconnectIntervalMs { get; init; } = 5000; |
| | | public int MaxReconnectAttempts { get; init; } = -1; // -1 表示æ ééè¯ |
| | | |
| | | public static ClientOptions FromArgs(string[] args) |
| | | { |
| | | var map = args |
| | | .Select(v => v.Split('=', 2, StringSplitOptions.TrimEntries)) |
| | | .Where(parts => parts.Length == 2) |
| | | .ToDictionary(parts => parts[0].TrimStart('-', '/').ToLowerInvariant(), parts => parts[1]); |
| | | |
| | | return new ClientOptions |
| | | { |
| | | ClientCount = GetInt(map, "count", 1), |
| | | ServerHost = GetString(map, "host", "127.0.0.1"), |
| | | ServerPort = GetInt(map, "serverport", 2000), |
| | | StartLocalPort = GetInt(map, "localport", 62312), |
| | | EnableReconnect = GetBool(map, "reconnect", true), |
| | | ReconnectIntervalMs = GetInt(map, "reconnectinterval", 5000), |
| | | MaxReconnectAttempts = GetInt(map, "maxreconnect", -1) |
| | | }; |
| | | } |
| | | |
| | | private static bool GetBool(Dictionary<string, string> map, string key, bool defaultValue) |
| | | => map.TryGetValue(key, out var value) |
| | | ? (bool.TryParse(value, out var result) ? result : defaultValue) |
| | | : defaultValue; |
| | | |
| | | private static int GetInt(Dictionary<string, string> map, string key, int defaultValue) |
| | | => map.TryGetValue(key, out var value) && int.TryParse(value, out var number) ? number : defaultValue; |
| | | |
| | | private static string GetString(Dictionary<string, string> map, string key, string defaultValue) |
| | | => map.TryGetValue(key, out var value) && !string.IsNullOrWhiteSpace(value) ? value : defaultValue; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "profiles": { |
| | | "RobotClient": { |
| | | "commandName": "Project" |
| | | }, |
| | | "Container (Dockerfile)": { |
| | | "commandName": "Docker" |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <Project Sdk="Microsoft.NET.Sdk"> |
| | | |
| | | <PropertyGroup> |
| | | <OutputType>Exe</OutputType> |
| | | <TargetFramework>net8.0</TargetFramework> |
| | | <ImplicitUsings>enable</ImplicitUsings> |
| | | <Nullable>enable</Nullable> |
| | | <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS> |
| | | <DockerfileContext>.</DockerfileContext> |
| | | </PropertyGroup> |
| | | |
| | | <ItemGroup> |
| | | <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.23.0" /> |
| | | </ItemGroup> |
| | | |
| | | </Project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <Solution> |
| | | <Project Path="RobotClient.csproj" /> |
| | | </Solution> |