| | |
| | | # CLAUDE.md |
| | | |
| | | This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| | | 本文件为 Claude Code (claude.ai/code) 在此代码库中工作时提供指导。 |
| | | |
| | | ## Build Commands |
| | | ## 构建命令 |
| | | |
| | | ```bash |
| | | # Build entire solution |
| | | # 构建整个解决方案 |
| | | dotnet build WIDESEAWCS_Server.sln |
| | | |
| | | # Build and run server |
| | | # 构建并运行服务器 |
| | | cd WIDESEAWCS_Server |
| | | dotnet run |
| | | |
| | | # Run tests |
| | | # 运行测试 |
| | | cd WIDESEAWCS_Tests |
| | | dotnet test |
| | | ``` |
| | | |
| | | ## Architecture Overview |
| | | ## 架构概述 |
| | | |
| | | This is a **WCS (Warehouse Control System)** built with ASP.NET Core 6.0, using: |
| | | - **Autofac** for DI with automatic service discovery via `IDependency` marker interface |
| | | - **Quartz.NET** for scheduled job execution (device communication loops) |
| | | - **SqlSugar ORM** for database access |
| | | - **Redis** (via `WIDESEAWCS_RedisService`) for distributed caching with L1+L2 hybrid pattern |
| | | - **StackExchange.Redis** for Redis operations |
| | | - **TCP Socket Server** for real-time device communication |
| | | - **HslCommunication** library for PLC/hardware communication |
| | | 这是一个基于 ASP.NET Core 6.0 构建的 **WCS(仓库控制系统)**,使用以下技术: |
| | | |
| | | ## Project Structure |
| | | - **Autofac** - 通过 `IDependency` 标记接口实现自动服务发现的依赖注入 |
| | | - **Quartz.NET** - 定时任务执行(设备通信循环) |
| | | - **SqlSugar ORM** - 数据库访问 |
| | | - **Redis**(通过 `WIDESEAWCS_RedisService`)- 采用 L1+L2 混合模式的分布式缓存 |
| | | - **StackExchange.Redis** - Redis 操作 |
| | | - **TCP Socket Server** - 实时设备通信 |
| | | - **HslCommunication** 库 - PLC/硬件通信 |
| | | |
| | | ## 项目结构 |
| | | |
| | | ``` |
| | | WIDESEAWCS_Server/ # Main ASP.NET Core API server |
| | | WIDESEAWCS_Core/ # Core infrastructure: base classes, DI, extensions, middleware |
| | | WIDESEAWCS_Model/ # Data models and DTOs |
| | | WIDESEAWCS_Communicator/ # Hardware communication drivers (Siemens, Omron, Modbus, etc.) |
| | | WIDESEAWCS_QuartzJob/ # Job scheduling infrastructure and device abstractions |
| | | WIDESEAWCS_Tasks/ # Quartz job implementations (device communication loops) |
| | | WIDESEAWCS_RedisService/ # Redis services: Cache, Lock, Counter, PubSub, etc. |
| | | WIDESEAWCS_*Repository/ # Data access layer implementations |
| | | WIDESEAWCS_*Service/ # Business service layer |
| | | WIDESEAWCS_Tests/ # Unit tests |
| | | WIDESEAWCS_Server/ # 主 ASP.NET Core API 服务器 |
| | | WIDESEAWCS_Core/ # 核心基础设施:基类、DI、扩展、中间件 |
| | | WIDESEAWCS_Model/ # 数据模型和 DTO |
| | | WIDESEAWCS_Communicator/ # 硬件通信驱动(Siemens、Omron、Modbus 等) |
| | | WIDESEAWCS_QuartzJob/ # 任务调度基础设施和设备抽象 |
| | | WIDESEAWCS_Tasks/ # Quartz 任务实现(设备通信循环) |
| | | WIDESEAWCS_RedisService/ # Redis 服务:缓存、锁、计数器、发布订阅等 |
| | | WIDESEAWCS_*Repository/ # 数据访问层实现 |
| | | WIDESEAWCS_*Service/ # 业务服务层 |
| | | WIDESEAWCS_Tests/ # 单元测试 |
| | | ``` |
| | | |
| | | ## Dependency Injection - IDependency Pattern |
| | | ## 依赖注入 - IDependency 模式 |
| | | |
| | | Services are **automatically registered** with Autofac by implementing the empty `IDependency` marker interface: |
| | | 服务通过实现空的 `IDependency` 标记接口被 Autofac **自动注册**: |
| | | |
| | | ```csharp |
| | | // In WIDESEAWCS_Core/IDependency.cs |
| | | // 在 WIDESEAWCS_Core/IDependency.cs 中 |
| | | public interface IDependency { } |
| | | |
| | | // Your service gets auto-registered |
| | | public class MyService : IDependency // Automatically registered as scoped |
| | | // 您的服务会被自动注册 |
| | | public class MyService : IDependency // 自动注册为 scoped |
| | | { |
| | | // ... |
| | | } |
| | | ``` |
| | | |
| | | Registration happens in `AutofacModuleRegister` which scans all project assemblies for `IDependency` implementations. |
| | | 注册在 `AutofacModuleRegister` 中进行,它会扫描所有项目程序集查找 `IDependency` 实现。 |
| | | |
| | | **Important**: When adding services to `IServiceCollection` (e.g., in `Program.cs`), they can be overridden by Autofac's registrations. Use `Remove()` to replace existing registrations: |
| | | **重要提示**:向 `IServiceCollection` 添加服务时(例如在 `Program.cs` 中),它们可能会被 Autofac 的注册覆盖。使用 `Remove()` 来替换现有注册: |
| | | |
| | | ```csharp |
| | | // In RedisServiceSetup.cs - removes MemoryCacheService before adding HybridCacheService |
| | | // 在 RedisServiceSetup.cs 中 - 添加 HybridCacheService 之前移除 MemoryCacheService |
| | | var existing = services.FirstOrDefault(d => d.ServiceType == typeof(ICacheService)); |
| | | if (existing != null) services.Remove(existing); |
| | | ``` |
| | | |
| | | ## Caching - ICacheService |
| | | ## 缓存 - ICacheService |
| | | |
| | | The system uses a **hybrid L1 (Memory) + L2 (Redis)** cache pattern via `ICacheService`. Three implementations exist: |
| | | - `MemoryCacheService` - Memory only |
| | | - `RedisCacheService` - Redis only |
| | | - `HybridCacheService` - L1+L2 with fallback (default when Redis enabled) |
| | | 系统通过 `ICacheService` 使用 **L1(内存)+ L2(Redis)混合缓存**模式。存在三种实现: |
| | | |
| | | **Common methods**: |
| | | - `Add/AddObject` - Add cache |
| | | - `Get/Get<T>` - Retrieve cached values |
| | | - `Remove` - Delete single key |
| | | - `RemoveByPrefix/RemoveByPattern` - Bulk delete by pattern |
| | | - `GetOrAdd<T>` - Retrieve or add with factory |
| | | - `TryAdd/TryUpdate/TryUpdateIfChanged` - ConcurrentDictionary-style operations |
| | | - `MemoryCacheService` - 仅内存 |
| | | - `RedisCacheService` - 仅 Redis |
| | | - `HybridCacheService` - L1+L2 带降级(启用 Redis 时的默认选项) |
| | | |
| | | **Configuration** in `appsettings.json`: |
| | | **常用方法**: |
| | | |
| | | - `Add/AddObject` - 添加缓存 |
| | | - `Get/Get<T>` - 获取缓存值 |
| | | - `Remove` - 删除单个键 |
| | | - `RemoveByPrefix/RemoveByPattern` - 按模式批量删除 |
| | | - `GetOrAdd<T>` - 获取或添加(带工厂方法) |
| | | - `TryAdd/TryUpdate/TryUpdateIfChanged` - ConcurrentDictionary 风格的操作 |
| | | |
| | | **配置**(在 `appsettings.json` 中): |
| | | |
| | | ```json |
| | | "RedisConfig": { |
| | | "Enabled": true, |
| | |
| | | } |
| | | ``` |
| | | |
| | | ## Quartz Jobs - Device Communication |
| | | ## Quartz 任务 - 设备通信 |
| | | |
| | | Jobs inherit from `JobBase` and implement Quartz's `IJob`: |
| | | 任务继承 `JobBase` 并实现 Quartz 的 `IJob`: |
| | | |
| | | ```csharp |
| | | public class MyDeviceJob : JobBase, IJob |
| | |
| | | public async Task Execute(IJobExecutionContext context) |
| | | { |
| | | ExecuteJob(context, async () => { |
| | | // Job logic here |
| | | WriteDebug("MyDevice", "Debug message"); |
| | | WriteInfo("MyDevice", "Info message"); |
| | | // 任务逻辑 |
| | | WriteDebug("MyDevice", "调试信息"); |
| | | WriteInfo("MyDevice", "信息"); |
| | | }); |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | Jobs are registered dynamically via `SchedulerCenterServer` using device info from `Dt_DeviceInfo` table. |
| | | 任务通过 `SchedulerCenterServer` 使用 `Dt_DeviceInfo` 表中的设备信息动态注册。 |
| | | |
| | | **Device types**: |
| | | - `IStackerCrane` - Stacker cranes |
| | | - `IConveyorLine` - Conveyor lines |
| | | - `IShuttleCar` - Shuttle cars |
| | | - `IRobot` - Robot cranes |
| | | **设备类型**: |
| | | |
| | | ## Hardware Communication |
| | | - `IStackerCrane` - 堆垛机 |
| | | - `IConveyorLine` - 输送线 |
| | | - `IShuttleCar` - 穿梭车 |
| | | - `IRobot` - 机械手 |
| | | |
| | | Communicator classes wrap the `HslCommunication` library: |
| | | - `SiemensS7Communicator` / `SiemensS7200SmartCommunicator` - Siemens PLCs |
| | | - `OmronEtherNetCommunicator` - Omron PLCs |
| | | ## 硬件通信 |
| | | |
| | | 通信器类封装 `HslCommunication` 库: |
| | | |
| | | - `SiemensS7Communicator` / `SiemensS7200SmartCommunicator` - 西门子 PLC |
| | | - `OmronEtherNetCommunicator` - 欧姆龙 PLC |
| | | - `ModbusTcpCommunicator` - Modbus TCP |
| | | - `SerialPortCommunicator` - Serial port devices |
| | | - `SerialPortCommunicator` - 串口设备 |
| | | |
| | | ## TCP Socket Server |
| | | ## TCP Socket 服务器 |
| | | |
| | | The `TcpSocketServer` (port 2000) handles real-time device communication: |
| | | - Managed as a Singleton with `SocketServerHostedService` |
| | | - Client connections stored in `ConcurrentDictionary<string, TcpClient>` |
| | | - Messages handled via `OnDataReceived` event |
| | | `TcpSocketServer`(端口 2000)处理实时设备通信: |
| | | |
| | | ## Configuration Settings |
| | | - 通过 `SocketServerHostedService` 作为 Singleton 管理 |
| | | - 客户端连接存储在 `ConcurrentDictionary<string, TcpClient>` 中 |
| | | - 通过 `OnDataReceived` 事件处理消息 |
| | | |
| | | Key settings in `appsettings.json`: |
| | | - `"urls": "http://*:9292"` - Server port |
| | | - `"QuartzJobAutoStart": true` - Auto-start scheduled jobs |
| | | - `"SocketServer:Enabled": true` - Enable TCP server |
| | | - `"RedisConfig:Enabled": true` - Enable Redis caching |
| | | - `"LogAOPEnable": false` - Enable AOP logging |
| | | - `"DBType": "SqlServer"` - Database type |
| | | ## 机械手通信系统 |
| | | |
| | | ## Service Layer Pattern |
| | | 机械手系统采用模块化架构,包含专门的组件。 |
| | | |
| | | Services follow a layered pattern: |
| | | - **Interface** in `WIDESEAWCS_IService/` (e.g., `ITaskInfoService`) |
| | | - **Implementation** in `WIDESEAWCS_Service/` (e.g., `TaskInfoService`) |
| | | - Both implement `IDependency` for auto-registration |
| | | **组件**: |
| | | |
| | | ## Base Classes |
| | | - `RobotClientManager` - 管理 TCP 客户端连接和订阅 |
| | | - `RobotStateManager` - 管理机械手状态缓存,支持安全的并发更新 |
| | | - `RobotMessageHandler` - 处理来自机械手的 TCP 消息 |
| | | - `RobotTaskProcessor` - 处理任务执行和状态转换 |
| | | - `RobotBarcodeGenerator` - 生成托盘/条码标识符 |
| | | |
| | | - `ServiceBase<T, TKey>` - Base service with CRUD operations |
| | | - `RepositoryBase<TEntity>` - Base repository with SqlSugar ORM |
| | | - `ApiBaseController` - Base API controller with common functionality |
| | | - `JobBase` - Base Quartz job with logging helpers |
| | | **任务类型**(来自 `RobotTaskTypeEnum`): |
| | | |
| | | ## Adding New Features |
| | | - `GroupPallet (500)` - 组盘任务 |
| | | - `ChangePallet (510)` - 换盘任务 |
| | | - `SplitPallet (520)` - 拆盘任务 |
| | | |
| | | 1. **New Service**: Create interface in `I*Service/` and class in `*Service/`, implement `IDependency` |
| | | 2. **New Job**: Inherit from `JobBase` and `IJob` in `WIDESEAWCS_Tasks/` |
| | | 3. **New Device Type**: Add interface in `WIDESEAWCS_QuartzJob/Device/` and implement |
| | | **状态流转**: |
| | | |
| | | ## Important Notes |
| | | 1. 机械手通过 TCP 连接 → ClientManager 跟踪连接 |
| | | 2. 任务轮询获取任务 → TaskProcessor 获取待处理任务 |
| | | 3. 接收消息 → MessageHandler 解析并更新状态 |
| | | 4. 状态转换 → TaskProcessor 向机械手发送命令 |
| | | |
| | | - The application uses **CamelCase** JSON serialization |
| | | - All services use **scoped** lifetime by default via Autofac |
| | | - Redis connection uses **Lazy initialization** - first access triggers connection |
| | | - Use `ConsoleHelper.WriteSuccessLine()` / `WriteErrorLine()` for console output in jobs |
| | | - TCP Socket server runs independently of the HTTP API |
| | | ## 通用常量 |
| | | |
| | | **通信超时**(`CommunicationConst`): |
| | | |
| | | - `WaitIntervalMs: 500` - 设备等待间隔 |
| | | - `WaitTimeoutBaseMs: 6000` - 超时基数 |
| | | - `WaitTotalTimeoutMs: 60000` - 总超时时间(10 × 基数) |
| | | - `PingIntervalMs: 100` - Ping 检测间隔 |
| | | - `HttpDefaultTimeoutSeconds: 60` - HTTP 超时 |
| | | |
| | | **系统集成 URL**(`BaseAPI`): |
| | | |
| | | - `WMSBaseUrl: "http://localhost:9291/api/"` - WMS 系统 |
| | | - `WCSBaseUrl: "http://localhost:9292/api/"` - WCS 系统(本服务器) |
| | | - `MESBaseUrl: "http://localhost:9293/api/"` - MES 系统 |
| | | - `ERPBaseUrl: "http://localhost:9294/api/"` - ERP 系统 |
| | | |
| | | **Redis 缓存前缀**(`RedisPrefix`): |
| | | |
| | | - `System: "System"` - 系统级缓存 |
| | | - `User: "User"` - 用户特定缓存 |
| | | - `Code: "Code"` - 代码/配置缓存 |
| | | |
| | | 使用这些前缀配合 `ICacheService.RemoveByPrefix()` 进行批量缓存失效。 |
| | | |
| | | ## 配置设置 |
| | | |
| | | `appsettings.json` 中的关键设置: |
| | | |
| | | - `"urls": "http://*:9292"` - 服务器端口 |
| | | - `"QuartzJobAutoStart": true` - 自动启动定时任务 |
| | | - `"SocketServer:Enabled": true` - 启用 TCP 服务器 |
| | | - `"RedisConfig:Enabled": true` - 启用 Redis 缓存 |
| | | - `"LogAOPEnable": false` - 启用 AOP 日志 |
| | | - `"DBType": "SqlServer"` - 数据库类型 |
| | | |
| | | ## 服务层模式 |
| | | |
| | | 服务遵循分层模式: |
| | | |
| | | - **接口**在 `WIDESEAWCS_IService/` 中(例如 `ITaskInfoService`) |
| | | - **实现**在 `WIDESEAWCS_Service/` 中(例如 `TaskInfoService`) |
| | | - 两者都实现 `IDependency` 以进行自动注册 |
| | | |
| | | ## 基类 |
| | | |
| | | - `ServiceBase<T, TKey>` - 带有 CRUD 操作的基础服务 |
| | | - `RepositoryBase<TEntity>` - 基于 SqlSugar ORM 的基础仓储 |
| | | - `ApiBaseController` - 带有通用功能的基础 API 控制器 |
| | | - `JobBase` - 带有日志辅助方法的基础 Quartz 任务 |
| | | |
| | | ## 添加新功能 |
| | | |
| | | 1. **新服务**:在 `I*Service/` 中创建接口,在 `*Service/` 中创建类,实现 `IDependency` |
| | | 2. **新任务**:在 `WIDESEAWCS_Tasks/` 中继承 `JobBase` 和 `IJob` |
| | | 3. **新设备类型**:在 `WIDESEAWCS_QuartzJob/Device/` 中添加接口并实现 |
| | | |
| | | ## 重要说明 |
| | | |
| | | - 应用程序使用 **CamelCase** JSON 序列化 |
| | | - 所有服务默认通过 Autofac 使用 **scoped** 生命周期 |
| | | - Redis 连接使用 **延迟初始化** - 首次访问时触发连接 |
| | | - 在任务中使用 `ConsoleHelper.WriteSuccessLine()` / `WriteErrorLine()` 进行控制台输出 |
| | | - TCP Socket 服务器独立于 HTTP API 运行 |