using Autofac; using DotNetty.Common.Utilities; using Entity.Constant; using Entity.DbModel.Station; using HybirdFrameworkCore.Autofac; using log4net; using Newtonsoft.Json; using Repository.Station; using Service.Execute.Api; using Service.Execute.Model; using Service.Execute.StaticTools; using Service.Execute.Step; using Service.Execute.SwapException; namespace Service.Execute; public class SwappingStateMachine : IDisposable { private static readonly ILog Log = LogManager.GetLogger(typeof(SwappingStateMachine)); private static readonly SwappingStateMachine SwappingMachine = new SwappingStateMachine(); private BinInfoRepository BinInfoRepository { get; set; } private SwapAmtOrderRepository AmtOrderRepository { get; set; } public bool CancelFlag { get; set; } = false; public bool StopFlag { get; set; } = false; public readonly LedTool? LedTool = null; private readonly Thread _executeThread; private readonly Dictionary _dictionary = new Dictionary(); private StateResult _result = new StateResult() { SwappingState = SwappingState.Begin }; //给云平台的实时状态 public InfoEnum.BusinessSwappingForCloudState BusinessSwappingForCloudState = InfoEnum.BusinessSwappingForCloudState.UnKnown; public DateTime BusinessSwappingStateUpdateTime = DateTime.Now; public ExceptionReason ExceptionReason = ExceptionReason.None; //换电实时状态 0:开始 1:成功 2:失败 public int? SwapStatus = null; public string SwapFailReason = ""; public int StepSort = 0; public RfidReadModel? RfidReadModel = null; public TboxCarInfoModel? BoxCarInfoModel = null; public SwapOrder? SwapOrder = null; public SwapOrderBatteryInfo? SwapOrderBatteryInfo = null; #region 小步状态 //雷达检测/车辆进入 public bool RadarInFlag = false; //开始读rf public bool BeginRfidReadFlag = false; //读rfid public bool RfidReadFlag = false; //云平台车辆 public bool CloudVelCheckFlag = false; //Tbox连接 public bool BoxConnectFlag = false; //车辆lock public bool BoxLocalCheckFlag = false; //车辆数据上传 public bool CloudTBoxFlag = false; //选包 public bool SelectPackFlag = false; //车辆到位 public bool VehiclesInPlaceFlag = false; //下发选包 public bool DistributeSelectPackFlag = false; //云平台下发 public bool CloudCarCanStartFlag = false; //车辆解锁 public bool VelUnlockFlag = false; //开始换电 public bool StartSwappingFlag = false; //拍照状态 public bool ChannelStatusOkFlag = false; //二次检测车 public bool VehiclesInPlace2Flag = false; //拆旧电池 public bool UnOldBatteryFlag = false; //入库旧电池 public bool StorageOldBatteryFlag = false; //搬运新电池 public bool OutNewBatteryFlag = false; //安装新电池 public bool InstallNewBatteryFlag = false; //安装完成 public bool FinishNewBatteryFlag = false; //车辆上锁 public bool VelLockFlag = false; //车辆离开 public bool RadarOutFlag = false; #endregion private SwappingStateMachine() { _executeThread = new Thread(Work); _executeThread.Name = "Swapping main"; _dictionary[SwappingState.Begin] = new BeginState(); _dictionary[SwappingState.StationReady] = new StationReadyState(); _dictionary[SwappingState.CarPrepare] = new CarPrepareState(); _dictionary[SwappingState.SwapCanStart] = new SwapCanStartState(); _dictionary[SwappingState.CarCtrl] = new CarCtrlState(); _dictionary[SwappingState.DoSwapping] = new DoSwappingState(); _dictionary[SwappingState.SwapDone] = new SwapDoneState(); _dictionary[SwappingState.Exception] = new ExceptionState(); _dictionary[SwappingState.Canceled] = new CancelState(); LedTool = new LedTool(); BinInfoRepository = AppInfo.Container.Resolve(); AmtOrderRepository = AppInfo.Container.Resolve(); } public static SwappingStateMachine GetInstance() { return SwappingMachine; } public static StateResult ReturnWithInvokeErr(InvokeStatus status, ExceptionReason exceptionReason) { if (status == InvokeStatus.Cancel) { return new StateResult() { SwappingState = SwappingState.Canceled }; } else if (status == InvokeStatus.TimeOut) { return null; } else { return StateResult.Exception(exceptionReason, null); } } private void Work() { Log.Info("State machine begin work"); while (!StopFlag) { Log.Info($"handle = {_result.SwappingState} begin"); try { StateResult? result = _dictionary[_result.SwappingState].Handle(this); if (result != null) { _result = result; } } catch (Exception e) { Log.Error($"handle {_result.SwappingState} error", e); } Log.Info($"handle = {_result.SwappingState} end"); Thread.Sleep(500); } Log.Info("State machine canceled"); } public void Stop() { StopFlag = true; CancelFlag = true; Thread.Sleep(2000); } public bool IsCanceled() { return CancelFlag; } public bool Start() { Reset(); _executeThread.Start(); Log.Info($"start machine ok"); return true; } public void Reset() { Log.Info("reset data"); ResetOrderAmtStatus(); //wifi数据重置 TBoxApi.Reset(); //重置所有小步状态 ResetStep(); ResetData(); //重置云平台下发的指令 CloudApi.ClearCarCanStartInfo(); } public bool Cancel() { CancelFlag = true; Thread.Sleep(5000); Log.Info($"Cancel machine ok"); return true; } private void ResetData() { BusinessSwappingForCloudState = InfoEnum.BusinessSwappingForCloudState.Idle; BusinessSwappingStateUpdateTime = DateTime.Now; ExceptionReason = ExceptionReason.None; //换电实时状态 0:开始 1:成功 2:失败 SwapStatus = null; SwapFailReason = ""; RfidReadModel = null; BoxCarInfoModel = null; SwapOrder = null; SwapOrderBatteryInfo = null; StepSort = 0; } private void ResetStep() { RadarInFlag = false; BeginRfidReadFlag = false; RfidReadFlag = false; CloudVelCheckFlag = false; BoxConnectFlag = false; BoxLocalCheckFlag = false; CloudTBoxFlag = false; SelectPackFlag = false; VehiclesInPlaceFlag = false; DistributeSelectPackFlag = false; CloudCarCanStartFlag = false; VelUnlockFlag = false; StartSwappingFlag = false; ChannelStatusOkFlag = false; VehiclesInPlace2Flag = false; UnOldBatteryFlag = false; StorageOldBatteryFlag = false; OutNewBatteryFlag = false; InstallNewBatteryFlag = false; FinishNewBatteryFlag = false; VelLockFlag = false; RadarOutFlag = false; } //关于仓库锁定相关重置 private void ResetOrderAmtStatus() { //仓库解锁 if (SwapOrderBatteryInfo != null) { var upBinInfo = SwapOrderBatteryInfo.UpBinInfo; if (null != upBinInfo) { upBinInfo.AmtLock = (int)InfoEnum.AmtBatLockStatus.UnLock; BinInfoRepository.Update(upBinInfo); } } //预约单 List amtOrderInfos = AmtOrderRepository.QueryListByClause(it => it.ExpireTime < DateTime.Now && it.Status == (byte)InfoEnum.AmtOrderStatus.Success).ToList(); if (amtOrderInfos.Count > 0) { List binNos = amtOrderInfos.SelectMany(i => i.AmtBinNoList.Split(',').ToList()).Distinct().ToList(); List listByClause = BinInfoRepository.QueryListByClause(i => binNos.Contains(i.No)); foreach (var binInfo in listByClause) { binInfo.AmtLock = (int)InfoEnum.AmtBatLockStatus.UnLock; } BinInfoRepository.Update(listByClause); } } public void Dispose() { StopFlag = true; CancelFlag = true; Thread.Sleep(2000); } } public enum SwappingState { Begin, StationReady, CarPrepare, SwapCanStart, CarCtrl, DoSwapping, SwapDone, Exception, Canceled }