| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # RobotState Redis â æ°æ®åºè¿ç§»è®¾è®¡ |
| | | |
| | | **æ¥æ**ï¼2026-04-19 |
| | | **ç¶æ**ï¼å·²æ¹å |
| | | |
| | | ## 1. èæ¯ä¸ç®æ |
| | | |
| | | å° `RobotSocketState` çåå¨ä» Redis åæ¢å° SQL Server æ°æ®åºï¼å©ç¨ SqlSugar ç `RowVersion` å®ç°ä¹è§å¹¶åæ§å¶ã |
| | | |
| | | ### æ¶åèå´ |
| | | |
| | | - `RobotJob/` æä»¶å¤¹ä¸ææä½¿ç¨ Redis 读å `RobotSocketState` ç代ç |
| | | - æ°å»º `Dt_RobotState` æ°æ®åºå®ä½å `IRobotStateRepository` ä»å¨å± |
| | | |
| | | ### 䏿¶ååæ´ |
| | | |
| | | - `RobotWorkflowOrchestrator`ã`RobotTaskProcessor`ã`RobotSimpleCommandHandler` çä¸å¡é»è¾ä¸å |
| | | - ä¾èµ `RobotStateManager` çè°ç¨æ¹ä»£ç ä¸åï¼åªæ¹åå¨å端 |
| | | |
| | | --- |
| | | |
| | | ## 2. æ°æ®åºå®ä½è®¾è®¡ |
| | | |
| | | **表å**ï¼`Dt_RobotState` |
| | | |
| | | **å®ä½è·¯å¾**ï¼`WIDESEAWCS_Model/Models/RobotState/Dt_RobotState.cs` |
| | | |
| | | | åæ®µå | ç±»å | 说æ | |
| | | |--------|------|------| |
| | | | `Id` | int | 主é®ï¼èªå¢ | |
| | | | `IPAddress` | string(50) | 设å¤IPï¼å¯ä¸ç´¢å¼ | |
| | | | `RowVersion` | byte[] | SqlSugar è¡çæ¬ï¼å¹¶åæ§å¶ | |
| | | | `IsEventSubscribed` | bool | æ¯å¦å·²è®¢é
æ¶æ¯ | |
| | | | `RobotRunMode` | int? | è¿è¡æ¨¡å¼ï¼1æå¨ 2èªå¨ï¼ | |
| | | | `RobotControlMode` | int? | æ§å¶æ¨¡å¼ï¼1客æ·ç«¯æ§å¶ 2å
¶ä»ï¼ | |
| | | | `RobotArmObject` | int? | æèæåç¶æï¼0æ ç©æ 1æç©æï¼ | |
| | | | `RobotCraneJson` | string(max) | 设å¤ä¿¡æ¯åºåå JSON | |
| | | | `Homed` | string(50) | åé¶ç¶æï¼Homed/Homingï¼ | |
| | | | `CurrentAction` | string(50) | å½åå¨ä½ï¼Picking/Putting/PickFinished çï¼ | |
| | | | `OperStatus` | string(50) | è¿è¡ç¶æï¼Running/Pausing/Emstoping çï¼ | |
| | | | `LastPickPositionsJson` | string(max) | åè´§ä½ç½®æ°ç» JSON | |
| | | | `LastPutPositionsJson` | string(max) | æ¾è´§ä½ç½®æ°ç» JSON | |
| | | | `CellBarcodeJson` | string(max) | çµè¯æ¡ç å表 JSON | |
| | | | `CurrentTaskJson` | string(max) | å½åä»»å¡ Dt_RobotTask åºåå JSON | |
| | | | `IsSplitPallet` | bool | æ¯å¦æçä»»å¡ | |
| | | | `IsGroupPallet` | bool | æ¯å¦ç»ç/æ¢çä»»å¡ | |
| | | | `RobotTaskTotalNum` | int | å·²å¤ç任塿»æ° | |
| | | | `IsInFakeBatteryMode` | bool | æ¯å¦åçµè¯è¡¥å
æ¨¡å¼ | |
| | | | `CurrentBatchIndex` | int | å½åæ¹æ¬¡èµ·å§ç¼å· | |
| | | | `ChangePalletPhase` | int | æ¢çä»»å¡é¶æ®µï¼0-5ï¼ | |
| | | | `IsScanNG` | bool | æ¯å¦æ«ç NG | |
| | | | `BatteryArrived` | bool | çµè¯æ¯å¦å°ä½ | |
| | | | `CreateTime` | datetime | å建æ¶é´ | |
| | | | `UpdateTime` | datetime | æåæ´æ°æ¶é´ | |
| | | |
| | | **ç´¢å¼**ï¼`IPAddress` å¯ä¸ç´¢å¼ï¼ç¨äºå¿«éå®ä½è®¾å¤ç¶æ |
| | | |
| | | **å¹¶åæ§å¶**ï¼SqlSugar `RowVersion`ï¼æ°æ®åºèªå¨éå¢ï¼æ´æ°æ¶ `WHERE RowVersion = @expected` |
| | | |
| | | --- |
| | | |
| | | ## 3. JSON åºåååæ®µ |
| | | |
| | | 以ä¸å¤æå¯¹è±¡ä»¥ JSON å符串åå¨ï¼ååºååæ¶ä¿æä¸å `RobotSocketState` 屿§å®å
¨å
¼å®¹ï¼ |
| | | |
| | | | JSON åæ®µ | 对åºå屿§ | ååºååç±»å | |
| | | |-----------|-----------|-------------| |
| | | | `RobotCraneJson` | `RobotCrane` | `RobotCraneDevice` | |
| | | | `CurrentTaskJson` | `CurrentTask` | `Dt_RobotTask` | |
| | | | `LastPickPositionsJson` | `LastPickPositions` | `int[]` | |
| | | | `LastPutPositionsJson` | `LastPutPositions` | `int[]` | |
| | | | `CellBarcodeJson` | `CellBarcode` | `List<string>` | |
| | | |
| | | åºååå·¥å
·ï¼`Newtonsoft.Json`ï¼ä¸é¡¹ç®ç°æä¿æä¸è´ï¼ |
| | | |
| | | --- |
| | | |
| | | ## 4. æ¶æåå± |
| | | |
| | | ``` |
| | | è°ç¨æ¹ï¼RobotJob / Workflow / Processorï¼ |
| | | â ä¾èµ |
| | | RobotStateManager |
| | | â ä¾èµ |
| | | IRobotStateRepositoryï¼æ¥å£ï¼ |
| | | â å®ç° |
| | | RobotStateRepositoryï¼SqlSugar å®ç°ï¼ |
| | | â æä½ |
| | | SQL Server (Dt_RobotState 表) |
| | | ``` |
| | | |
| | | ### 4.1 IRobotStateRepository æ¥å£ |
| | | |
| | | ```csharp |
| | | public interface IRobotStateRepository |
| | | { |
| | | /// <summary>æ ¹æ® IP è·åç¶æï¼ä¸åå¨è¿å null</summary> |
| | | Dt_RobotState? GetByIp(string ipAddress); |
| | | |
| | | /// <summary>è·åæåå»ºç¶æï¼æ°æ®åºæ è®°å½æ¶å建ï¼</summary> |
| | | Dt_RobotState GetOrCreate(string ipAddress, RobotCraneDevice robotCrane); |
| | | |
| | | /// <summary>å®å
¨æ´æ°ï¼ä¹è§éï¼ï¼è¿åæ¯å¦æå</summary> |
| | | bool TryUpdate(string ipAddress, Dt_RobotState newState, byte[] expectedRowVersion); |
| | | } |
| | | ``` |
| | | |
| | | ### 4.2 RobotStateRepository å®ç°è¦ç¹ |
| | | |
| | | - 注å
¥ `ISqlSugarClient` |
| | | - `GetOrCreate`ï¼å
æ¥ï¼æ è®°å½å INSERT |
| | | - `TryUpdate`ï¼æ§è¡ `UPDATE ... WHERE RowVersion = @expected`ï¼æ£æ¥å½±åè¡æ° |
| | | - æ°ç»/å¤æå¯¹è±¡ï¼å¨ Repository å±åºåå/ååºååï¼å¯¹å¤æ´é²å¼ºç±»å屿§ |
| | | |
| | | --- |
| | | |
| | | ## 5. RobotStateManager æ¹é |
| | | |
| | | **æä»¶**ï¼`WIDESEAWCS_Tasks/RobotJob/RobotStateManager.cs` |
| | | |
| | | ### æ¹é å
容 |
| | | |
| | | | 忥ï¼Redisï¼ | æ¹é åï¼DBï¼ | |
| | | |-------------|-------------| |
| | | | `ICacheService _cache` | `IRobotStateRepository _repository` | |
| | | | `GetState(ipAddress)` | `_repository.GetByIp(ipAddress)` | |
| | | | `GetOrCreateState(ipAddress, robotCrane)` | `_repository.GetOrCreate(ipAddress, robotCrane)` | |
| | | | `TryUpdateStateSafely(ipAddress, func)` | å
é¨è°ç¨ `_repository.TryUpdate`ï¼ä½¿ç¨ `RowVersion` ä½ä¸ºææçæ¬ | |
| | | | `CloneState` | ä¿çï¼JSON åºååæ·±æ·è´ï¼ | |
| | | | `GetCacheKey(ipAddress)` | ç§»é¤ï¼ä¸åéè¦ Redis Keyï¼ | |
| | | |
| | | ### æé 彿°åæ´ |
| | | |
| | | ```csharp |
| | | // 忥 |
| | | public RobotStateManager(ICacheService cache, ILogger logger) |
| | | |
| | | // æ¹é å |
| | | public RobotStateManager(IRobotStateRepository repository, ILogger logger) |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## 6. RobotJob æé 彿°æ¹é |
| | | |
| | | **æä»¶**ï¼`WIDESEAWCS_Tasks/RobotJob/RobotJob.cs` |
| | | |
| | | ```csharp |
| | | // 忥 |
| | | _stateManager = new RobotStateManager(cache, _logger); |
| | | |
| | | // æ¹é åï¼éè¦éè¿ DI 注å
¥ IRobotStateRepository |
| | | _stateManager = new RobotStateManager( |
| | | ResolvedInstances.FirstOrDefault(typeof(IRobotStateRepository)) as IRobotStateRepository, |
| | | _logger); |
| | | ``` |
| | | |
| | | **å¤éæ¹æ¡**ï¼å¦æ DI 容å¨å¨ Job æé æ¶ä¸ä¾¿è§£æï¼å¯éè¿æ¹æ³åæ°æ³¨å
¥ `IRobotStateRepository`ã |
| | | |
| | | --- |
| | | |
| | | ## 7. æä»¶åæ´æ¸
å |
| | | |
| | | | æä½ | æä»¶è·¯å¾ | |
| | | |------|---------| |
| | | | æ°å¢ | `WIDESEAWCS_Model/Models/RobotState/Dt_RobotState.cs` | |
| | | | æ°å¢ | `WIDESEAWCS_ITaskInfoRepository/IRobotStateRepository.cs` | |
| | | | æ°å¢ | `WIDESEAWCS_ITaskInfoRepository/RobotStateRepository.cs` | |
| | | | æ¹é | `WIDESEAWCS_Tasks/RobotJob/RobotStateManager.cs` | |
| | | | æ¹é | `WIDESEAWCS_Tasks/RobotJob/RobotJob.cs` | |
| | | | æ¹é | `WIDESEAWCS_Tasks/RobotJob/RobotSocketState.cs`ï¼ç§»é¤æä¿ç为 DTOï¼ï¼ | |
| | | |
| | | **说æ**ï¼`RobotSocketState.cs` 建议ä¿çä½ä¸ºå
åä¸çç¶æå¯¹è±¡ï¼DTOï¼ï¼å¨ Repository å±åå®ä½è½¬æ¢ãä¸å¡å±ç»§ç»ä½¿ç¨ `RobotSocketState`ï¼Repository å±è´è´£ä¸ `Dt_RobotState` äºè½¬ã |
| | | |
| | | --- |
| | | |
| | | ## 8. ä¾èµæ³¨å
¥æ³¨å |
| | | |
| | | å¨ `AutofacModuleRegister` æå¯¹åº DI é
ç½®ä¸æ³¨åï¼ |
| | | |
| | | ```csharp |
| | | builder.RegisterType<RobotStateRepository>().As<IRobotStateRepository>().InstancePerDependency(); |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## 9. è¿ç§»æ¥éª¤ï¼å®æ½è®¡åï¼ |
| | | |
| | | 1. **æ°å»º `Dt_RobotState` å®ä½ç±»** |
| | | 2. **æ°å»º `IRobotStateRepository` æ¥å£å `RobotStateRepository` å®ç°** |
| | | 3. **æ¹é `RobotStateManager`**ï¼ä¾èµ Repositoryï¼æ¿æ¢ Redis è°ç¨ |
| | | 4. **æ¹é `RobotJob`**ï¼æ³¨å
¥ Repository å° StateManager |
| | | 5. **æ´æ° `RobotSocketState`**ï¼ä½ä¸ºå
å DTO ä¿çï¼æä¸å®ä½åå¹¶ï¼å¾
å®ï¼ |
| | | 6. **é
ç½® DI 注å** |
| | | 7. **æµè¯éªè¯**ï¼ç¡®ä¿å¹¶åæ´æ°ãç¶ææµè½¬é»è¾ä¸åæ¥ä¸è´ |