编辑 | blame | 历史 | 原始文档

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Build Commands

# 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

Project Structure

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

Dependency Injection - IDependency Pattern

Services are automatically registered with Autofac by implementing the empty IDependency marker interface:

// In WIDESEAWCS_Core/IDependency.cs
public interface IDependency { }

// Your service gets auto-registered
public class MyService : IDependency  // Automatically registered as scoped
{
    // ...
}

Registration happens in AutofacModuleRegister which scans all project assemblies for IDependency implementations.

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:

// In RedisServiceSetup.cs - removes MemoryCacheService before adding HybridCacheService
var existing = services.FirstOrDefault(d => d.ServiceType == typeof(ICacheService));
if (existing != null) services.Remove(existing);

Caching - 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)

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

Configuration in appsettings.json:
json "RedisConfig": { "Enabled": true, "ConnectionString": "127.0.0.1:6379,password=P@ssw0rd,...", "KeyPrefix": "wcs:" }

Quartz Jobs - Device Communication

Jobs inherit from JobBase and implement Quartz's IJob:

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");
        });
    }
}

Jobs are registered dynamically via SchedulerCenterServer using device info from Dt_DeviceInfo table.

Device types:
- IStackerCrane - Stacker cranes
- IConveyorLine - Conveyor lines
- IShuttleCar - Shuttle cars
- IRobot - Robot cranes

Hardware Communication

Communicator classes wrap the HslCommunication library:
- SiemensS7Communicator / SiemensS7200SmartCommunicator - Siemens PLCs
- OmronEtherNetCommunicator - Omron PLCs
- ModbusTcpCommunicator - Modbus TCP
- SerialPortCommunicator - Serial port devices

TCP Socket Server

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

Robot Communication System

The robot crane system uses a modular architecture with specialized components.

Components:

  • RobotClientManager - Manages TCP client connections and subscriptions
  • RobotStateManager - Manages robot state cache with safe concurrent updates
  • RobotMessageHandler - Processes incoming TCP messages from robots
  • RobotTaskProcessor - Handles task execution and state transitions
  • RobotBarcodeGenerator - Generates tray/barcode identifiers

Task Types (from RobotTaskTypeEnum):

  • GroupPallet (500) - 组盘任务
  • ChangePallet (510) - 换盘任务
  • SplitPallet (520) - 拆盘任务

State Flow:

  1. Robot connects via TCP → ClientManager tracks connection
  2. Job polls for tasks → TaskProcessor gets pending tasks
  3. Message received → MessageHandler parses and updates state
  4. State transitions → TaskProcessor sends commands back to robot

Common Constants

Communication Timeouts (CommunicationConst):

  • WaitIntervalMs: 500 - Device wait interval
  • WaitTimeoutBaseMs: 6000 - Timeout base
  • WaitTotalTimeoutMs: 60000 - Total timeout (10 × base)
  • PingIntervalMs: 100 - Ping check interval
  • HttpDefaultTimeoutSeconds: 60 - HTTP timeout

System Integration URLs (BaseAPI):

  • WMSBaseUrl: "http://localhost:9291/api/" - WMS system
  • WCSBaseUrl: "http://localhost:9292/api/" - WCS system (this server)
  • MESBaseUrl: "http://localhost:9293/api/" - MES system
  • ERPBaseUrl: "http://localhost:9294/api/" - ERP system

Redis Cache Prefixes (RedisPrefix):

  • System: "System" - System-level cache
  • User: "User" - User-specific cache
  • Code: "Code" - Code/configuration cache

Use these prefixes with ICacheService.RemoveByPrefix() for bulk cache invalidation.

Configuration Settings

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

  • 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

Adding New Features

  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

  • 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