You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

493 lines
12 KiB

using System.Collections.Concurrent;
using System.Reflection.PortableExecutable;
using Autofac;
using Entity.Attr;
using Entity.Constant;
using Entity.DbModel.Station;
using HybirdFrameworkCore.Autofac;
using log4net;
using Repository.Station;
5 months ago
using Service.Charger.Client;
using Service.Execute.Api;
using Service.Execute.Model;
using Service.Execute.Model.Tbox;
using Service.Execute.StaticTools;
using Service.Execute.Step;
using Service.Execute.SwapException;
using Service.Led;
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 bool PlcSwapFlag { get; set; } = false;
//手动确认换电成功
public bool ManualSwapSuccFlag { get; set; } = false;
//手动确认解锁/上锁成功
public bool ManualConfirmCarUnlockFlag { get; set; }
//手动确认解锁/上锁成功
public bool ManualConfirmCarLockFlag { get; set; }
public OperateModel OperateModel = null;
public readonly LedTool? LedTool = null;
private readonly Thread _executeThread;
private readonly Dictionary<SwappingState, IState> _dictionary = new Dictionary<SwappingState, IState>();
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;
public ConcurrentDictionary<string, StepModel> StepModel =
new ConcurrentDictionary<string, StepModel>
();
#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 PlcHoldFlag = 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 ToSafePositionFlag = 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.CarCtrl] = new CarCtrlState();
_dictionary[SwappingState.DoSwapping] = new DoSwappingState();
_dictionary[SwappingState.SwapDone] = new SwapDoneState();
_dictionary[SwappingState.Exception] = new ExceptionState();
_dictionary[SwappingState.Canceled] = new CancelState();
_dictionary[SwappingState.ManualSucc] = new ManualSuccState();
LedTool = new LedTool();
BinInfoRepository = AppInfo.Container.Resolve<BinInfoRepository>();
AmtOrderRepository = AppInfo.Container.Resolve<SwapAmtOrderRepository>();
}
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 if (status == InvokeStatus.ManualSucc)
{
return new StateResult() { SwappingState = SwappingState.ManualSucc };
}
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 IsManualSwapSucc()
{
return ManualSwapSuccFlag;
}
public bool Start()
{
Reset();
_executeThread.Start();
Log.Info($"start machine ok");
return true;
}
public void Reset()
{
Log.Info("reset data");
/*if (PlcMgr.PlcClient?.ReadTaskNo() == 1)
{
PlcMgr.PlcClient?.ExChangeTaskNo(0);
}*/
ResetOrderAmtStatus();
if (RfidReadModel != null)
{
//wifi数据重置
TBoxApi.Reset(RfidReadModel.VelVin);
}
5 months ago
ClientMgr.PlcClient?.Reset();
//重置所有小步状态
ResetStep();
ResetData();
//重置云平台下发的指令
// CloudApi.ClearCarCanStartInfo();
}
public bool Cancel()
{
CancelFlag = true;
Thread.Sleep(5000);
Log.Info($"Cancel machine ok");
return true;
}
public bool Manual()
{
ManualSwapSuccFlag = true;
Thread.Sleep(5000);
Log.Info($"ManualSwapSuccFlag machine ok");
return true;
}
public bool ManualConfirmLockCar()
{
ManualConfirmCarLockFlag = true;
Thread.Sleep(2000);
Log.Info($"ManualConfirmLockCar ok");
return true;
}
public bool ManualConfirmUnLockCar()
{
ManualConfirmCarUnlockFlag = true;
Thread.Sleep(2000);
Log.Info($"ManualConfirmLockCar ok");
return true;
}
private void ResetData()
{
BusinessSwappingForCloudState = InfoEnum.BusinessSwappingForCloudState.Idle;
BusinessSwappingStateUpdateTime = DateTime.Now;
ExceptionReason = ExceptionReason.None;
OperateModel = null;
;
//换电实时状态 0开始 1成功 2:失败
SwapStatus = null;
SwapFailReason = "";
RfidReadModel = null;
BoxCarInfoModel = null;
SwapOrder = null;
SwapOrderBatteryInfo = null;
StepSort = 0;
3 months ago
StepModel =
new ConcurrentDictionary<string, StepModel>
();
Array values = Enum.GetValues(typeof(InfoEnum.BusinessSwappingStep));
3 months ago
foreach (var value in values)
{
3 months ago
StepModel[value.ToInt()+""] = new StepModel()
3 months ago
{
StepNo = (int)value,
Status = 0,
StepName = BaseEnumExtensions.GetEnumDescriptionByCode<InfoEnum.BusinessSwappingStep>((int)value)
}
;
;
}
PlcSwapFlag = false;
ManualSwapSuccFlag = false;
OperateModel = null;
ManualConfirmCarUnlockFlag = false;
ManualConfirmCarLockFlag = false;
CancelFlag = false;
StopFlag = false;
}
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;
PlcHoldFlag = false;
ChannelStatusOkFlag = false;
VehiclesInPlace2Flag = false;
UnOldBatteryFlag = false;
StorageOldBatteryFlag = false;
OutNewBatteryFlag = false;
InstallNewBatteryFlag = false;
FinishNewBatteryFlag = false;
ToSafePositionFlag = false;
VelLockFlag = false;
RadarOutFlag = false;
}
//关于仓库锁定相关重置
private void ResetOrderAmtStatus()
{
// SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.ErrorTBoxConn);
LedClient.SendMsgByKey(InfoEnum.SwapInfo.WelcomeInfo.GetLed());
3 months ago
BinInfoRepository.Update(it => new BinInfo { AmtLock = 0 },
it => it.AmtLock == 1);
//仓库解锁
if (SwapOrderBatteryInfo != null)
{
if (SwapOrderBatteryInfo?.UpBinInfo != null) ;
{
BinInfoRepository.Update(i=>i.AmtLock==(int)InfoEnum.AmtBatLockStatus.UnLock,i=>i.Id==SwapOrderBatteryInfo.UpBinInfo.Id);
}
}
5 months ago
//预约单
List<SwapAmtOrder> amtOrderInfos = AmtOrderRepository.QueryListByClause(it =>
it.ExpireTime < DateTime.Now
&& it.Status == (byte)InfoEnum.AmtOrderStatus.Success).ToList();
if (amtOrderInfos.Count > 0)
{
List<string> binNos = amtOrderInfos.SelectMany(i => i.AmtBinNoList.Split(',').ToList()).Distinct().ToList();
List<BinInfo> 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,
ManualSucc,
5 months ago
}