diff --git a/Service/Cloud/Msg/Cloud/Req/CarCanStart.cs b/Service/Cloud/Msg/Cloud/Req/CarCanStart.cs index a5fe31b..0683ce9 100644 --- a/Service/Cloud/Msg/Cloud/Req/CarCanStart.cs +++ b/Service/Cloud/Msg/Cloud/Req/CarCanStart.cs @@ -25,7 +25,7 @@ namespace Service.Cloud.Msg.Cloud.Req /// public string cn { get; set; } /// - /// 是否开始换电 + /// 是否开始换电 1:可以开始换电 2:终止换电 /// public byte cs { get; set; } public string GetCmd() diff --git a/Service/Execute/Api/CloudApi.cs b/Service/Execute/Api/CloudApi.cs index 8b5f749..a16a55e 100644 --- a/Service/Execute/Api/CloudApi.cs +++ b/Service/Execute/Api/CloudApi.cs @@ -1,5 +1,7 @@ using Entity.DbModel.Station; using log4net; +using Service.Cloud.Client; +using Service.Cloud.Msg.Cloud.Req; using Service.Execute.Enum; using Service.Execute.Model; @@ -35,4 +37,22 @@ public class CloudApi { return ; } + + /// + /// 云平台下发换电指令 + /// + /// + public static CarCanStart CarCanStart() + { + return CloudClientMgr.CloudClient.CarCanStart; + } + + /// + /// 清除下发的换电指令 + /// + /// + public static CarCanStart ClearCarCanStartInfo() + { + return CloudClientMgr.CloudClient.CarCanStart=null; + } } \ No newline at end of file diff --git a/Service/Execute/Api/PlcApi.cs b/Service/Execute/Api/PlcApi.cs index 9350067..b3bff41 100644 --- a/Service/Execute/Api/PlcApi.cs +++ b/Service/Execute/Api/PlcApi.cs @@ -45,4 +45,57 @@ public class PlcApi { return true; } + + /// + /// 写出口灯 + /// 红灯:1020 + /// 绿灯:1000 + /// + /// + /// + public static bool WriteExistLamp(int data) + { + return true; + } + + /// + /// 下发选包 + /// + /// 入仓位,仓位号 + /// 出仓位,仓位号 + /// + public static bool DistributeSelectPack(string inBinNo, string outBinNo) + { + return true; + } + + + /// + /// 下发启动换电 + /// + /// + public static bool StartSwapping() + { + return true; + } + + /// + /// 查看拍照状态 + /// + /// + public static byte ChannelStatus() + { + return 0; + } + + + /// + /// 读plc任务状态 + /// + /// + public static byte ReadPlcTaskStatus() + { + return 0; + } + } \ No newline at end of file diff --git a/Service/Execute/Api/TboxApi.cs b/Service/Execute/Api/TboxApi.cs index ad18ddb..6d3896d 100644 --- a/Service/Execute/Api/TboxApi.cs +++ b/Service/Execute/Api/TboxApi.cs @@ -62,4 +62,52 @@ public class TBoxApi return false; } } + + /// + /// 车辆解锁 + /// + /// + public static async Task UnLockCar() + { + Log.Info("UnLockCar"); + string url = BASE_URL + "/CarControl/unLock"; + try + { + string s = await _httpClient.GetStringAsync(url); + + + Log.Info($"UnLockCar resp = {s}"); + return bool.Parse(s); + } + catch (Exception e) + { + Console.WriteLine(e); + return false; + } + } + + /// + /// 车辆上锁 + /// + /// + public static async Task LockCar() + { + Log.Info("LockCar"); + string url = BASE_URL + "/CarControl/lock"; + try + { + string s = await _httpClient.GetStringAsync(url); + + + Log.Info($"LockCar resp = {s}"); + return bool.Parse(s); + } + catch (Exception e) + { + Console.WriteLine(e); + return false; + } + } + + } \ No newline at end of file diff --git a/Service/Execute/Enum/InfoEnum.cs b/Service/Execute/Enum/InfoEnum.cs index 851daa6..40ef22a 100644 --- a/Service/Execute/Enum/InfoEnum.cs +++ b/Service/Execute/Enum/InfoEnum.cs @@ -8,32 +8,32 @@ public class InfoEnum public enum SwapInfo : ushort { [Info("Rfid读写失败", "Rfid读写失败")] ErrorReadRfid = 1, - [Info("车辆进站", "车辆进站")] InfoCarIn = 2, [Info("Tbox连接失败", "Tbox连接失败,请联系站务人员")] ErrorTBoxConn = 4, [Info("云端校验失败", "云端校验失败,请联系站务人员")] ErrorCloudCheck = 5, [Info("车辆已到位", "车辆已到位")] InfoCarInPosition = 6, [Info("车辆到位超时", "车辆到位超时")] ErrorCarInPositionTimeout = 7, [Info("云平台下发换电失败", "云平台下发换电超时")] CloudSendSwapError = 8, + [Info("云平台下发取消换电", "云平台下发取消换电")] CloudSendSwapCancel = 9, - - [Info("自由度调整,挂N挡,拉手刹", "自由度调整,挂N挡,拉手刹")] - InfoCarPrepare = 9, - [Info("自由度调整超时", "自由度调整超时")] ErrorCarPrepareTimeout = 10, - [Info("请选择更换电池数量", "请选择更换电池数量")] InfoSelectPack = 11, + + [Info("解锁车辆失败", "解锁车辆失败")] ErrUnLockCar = 10, + [Info("下发选包结果失败", "下发选包结果失败")] ErrDistributeSelectPack = 11, [Info("选包失败,请驶离", "选包失败,请驶离")] ErrorSelectPack = 12, - [Info("下高压失败,请联系站务人员", "下高压失败,请联系站务人员")] - ErrorHvPwrOff = 13, + - [Info("下低压失败,请联系站务人员", "下低压失败,请联系站务人员")] - ErrorLvPwrOff = 14, + [Info("通道拍照定位失败,请重新调整车辆位置", "通道拍照定位失败,请重新调整车辆位置")] + ErrChannelStatus = 14, [Info("电池拆卸中,请稍后", "电池拆卸中,请稍后")] InfoUnPack = 15, + [Info("电池安装中,请稍后", "电池安装中,请稍后")] InfoPack = 16, [Info("电池包已安装完成", "电池包已安装完成")] InfoPackFinish = 17, - [Info("车辆自检中,请稍后", "车辆自检中,请稍后")] InfoSelfCheck = 18, - [Info("自检失败,请联系站务人员", "自检失败,请联系站务人员")] ErrorSelfCheck = 19, [Info("换电已完成,请驶离", "换电已完成,请驶离")] InfoCarLeave = 20, + [Info("换电失败,请驶离", "换电失败,请驶离")] ErrInfoCarLeave = 21, + [Info("旧电池搬运中,请稍后", "旧电池搬运中,请稍后")] InfoOldBatteryCarryIn = 22, + [Info("旧电池搬运中,请稍后", "旧电池搬运中,请稍后")] InfoNewBatteryCarryOut = 23, + [Info("上锁车辆失败", "上锁车辆失败")] ErrLockCar = 24, } public enum SelectBinStatusInfo : byte @@ -50,7 +50,7 @@ public class InfoEnum [Remark("无可用捆绑")] NoGroupError } - //1:预约成功;2:预约取消;3:预约失败;4:换电完成;5:换电失败 + public enum AmtOrderStatus : byte { [Remark("预约成功")] Success = 1, @@ -59,8 +59,9 @@ public class InfoEnum [Remark("换电完成")] SwapFinish = 4, [Remark("换电失败")] SwapFail = 5, [Remark("换电中")] Swapping = 6, - [Remark("预约失败")] Expire = 7, + [Remark("预约过期")] Expire = 7, } + //云平台上报步序 public enum BusinessSwappingForCloudState : byte { @@ -87,7 +88,7 @@ public class InfoEnum public enum SwapOrderResult : byte { - Success = 0, - Fail = 1 + Success = 1, + Fail = 2 } } \ No newline at end of file diff --git a/Service/Execute/Step/CancelState.cs b/Service/Execute/Step/CancelState.cs index f91e9da..d11f102 100644 --- a/Service/Execute/Step/CancelState.cs +++ b/Service/Execute/Step/CancelState.cs @@ -1,13 +1,35 @@ -namespace Service.Execute.Step; +using log4net; +using Repository.Station; +using Service.Execute.Enum; -public class CancelState: IState +namespace Service.Execute.Step; + +public class CancelState : IState { + private SwapOrderRepository SwapOrderRepository { get; set; } + + private SwapAmtOrderRepository SwapAmtOrderRepository { get; set; } + private static readonly ILog _log = LogManager.GetLogger(typeof(CancelState)); + public StateResult Handle(SwappingStateMachine machine) { - + _log.Info($"'goto cancel"); + SwappingStateMachine.CancelFlag = false; + if (machine.SwapOrderBatteryInfo.swapAmtOrder != null) + { + machine.SwapOrderBatteryInfo.swapAmtOrder.Status = (byte)InfoEnum.AmtOrderStatus.SwapFail; + SwapAmtOrderRepository.Update(machine.SwapOrderBatteryInfo.swapAmtOrder); + } + + if (machine.SwapOrder != null) + { + machine.SwapOrder.SwapResult = (byte)InfoEnum.SwapOrderResult.Fail; + SwapOrderRepository.Update(machine.SwapOrder); + } + + machine.Reset(); return new StateResult() { - SwappingState = SwappingState.StationReady }; } diff --git a/Service/Execute/Step/CarCtrlState.cs b/Service/Execute/Step/CarCtrlState.cs index 4850a4f..6d2f6e5 100644 --- a/Service/Execute/Step/CarCtrlState.cs +++ b/Service/Execute/Step/CarCtrlState.cs @@ -1,14 +1,81 @@ -namespace Service.Execute.Step; +using log4net; +using Service.Execute.Api; +using Service.Execute.Enum; +using Service.Execute.Model; +using Service.Execute.StaticTools; +using Service.Execute.SwapException; +using Swapping.Business.Tech; -public class CarCtrlState: IState +namespace Service.Execute.Step; + +public class CarCtrlState : IState { + private readonly ILog _log = LogManager.GetLogger(typeof(CarCtrlState)); + public StateResult Handle(SwappingStateMachine machine) { - + //解锁车辆 + InvokeStatus unLockCar = UnLockCar(machine); + if (unLockCar != InvokeStatus.Done) + { + return SwappingStateMachine.ReturnWithInvokeErr(unLockCar, ExceptionReason.None); + } + + //下发选包 + InvokeStatus distributeSelectPack = DistributeSelectPack(machine); + + if (distributeSelectPack != InvokeStatus.Done) + { + return SwappingStateMachine.ReturnWithInvokeErr(distributeSelectPack, ExceptionReason.None); + } + return new StateResult() { - - SwappingState = SwappingState.StationReady + SwappingState = SwappingState.DoSwapping }; } + + /// + /// 车辆解锁 + /// + /// + public InvokeStatus UnLockCar(SwappingStateMachine machine) + { + return Invoker.Invoke("UnLockCar", 500, 100, machine.IsCanceled, + () => SwappingStateMachine.VelUnlockFlag, () => + { + Task result = TBoxApi.UnLockCar(); + bool unLock = result.Result; + if (unLock) + { + //查询车辆锁止状态 + Task carInfo = TBoxApi.GetCarInfo(); + if (carInfo.Result.HeartBeatMsg.LockStatus == 1) + { + SwappingStateMachine.VelUnlockFlag = true; + } + } + }, () => + { + machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.ErrUnLockCar.GetLed()); + SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.ErrUnLockCar); + }, false, () => { SwappingStateMachine.ExceptionReason = ExceptionReason.UnLockCarError; } + , 10, InvokeStatus.None); + } + + + /// + /// 下发选包 + /// + /// + public InvokeStatus DistributeSelectPack(SwappingStateMachine machine) + { + return Invoker.Invoke("DistributeSelectPack", 500, 10, machine.IsCanceled, + () => SwappingStateMachine.DistributeSelectPackFlag, () => + { + var swapOrderBatteryInfo = machine.SwapOrderBatteryInfo; + SwappingStateMachine.DistributeSelectPackFlag = + PlcApi.DistributeSelectPack(swapOrderBatteryInfo.InBinInfo.No, swapOrderBatteryInfo.UpBinInfo.No); + }, () => { machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.ErrDistributeSelectPack.GetLed()); }); + } } \ No newline at end of file diff --git a/Service/Execute/Step/CarPrepareState.cs b/Service/Execute/Step/CarPrepareState.cs index 0fb106a..c1623d7 100644 --- a/Service/Execute/Step/CarPrepareState.cs +++ b/Service/Execute/Step/CarPrepareState.cs @@ -84,7 +84,7 @@ public class CarPrepareState : IState return new StateResult() { - SwappingState = SwappingState.SelectPack + SwappingState = SwappingState.SwapCanStart }; } @@ -110,6 +110,13 @@ public class CarPrepareState : IState machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.InfoCarInPosition.GetLed()); SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.InfoCarInPosition); SwappingStateMachine.VehiclesInPlaceFlag = true; + //告知云平台换电准备完成 + SwappingStateMachine.BusinessSwappingForCloudState = + InfoEnum.BusinessSwappingForCloudState.SwapReady; + SwappingStateMachine.ExceptionReason = ExceptionReason.None; + CloudApi.SendStateLog(machine.SwapOrder, SwappingStateMachine.BusinessSwappingForCloudState); + //清除下发的指令,等待新的指令 + CloudApi.ClearCarCanStartInfo(); } } }, () => @@ -121,6 +128,7 @@ public class CarPrepareState : IState , 20, InvokeStatus.None); } + /// /// 云平台车辆认证 /// @@ -141,15 +149,10 @@ public class CarPrepareState : IState } else { - //置为换电准备中 ,上报换电准备中 - SwappingStateMachine.BusinessSwappingForCloudState = - InfoEnum.BusinessSwappingForCloudState.SwapReady; SwappingStateMachine.ExceptionReason = ExceptionReason.None; _log.Info("cloud check vehicle done"); SwappingStateMachine.CloudVelCheckFlag = true; machine.LedTool.WriteProgramContent("换电准备中:云平台车辆验证完成"); - CloudApi.SendStateLog(machine.SwapOrder, SwappingStateMachine.BusinessSwappingForCloudState); - SwappingStateMachine.CloudVelCheckFlag = true; } } else @@ -183,6 +186,9 @@ public class CarPrepareState : IState }, () => { SwappingStateMachine.ExceptionReason = ExceptionReason.ConnTBoxError; }, false, () => { SwappingStateMachine.ExceptionReason = ExceptionReason.ConnTBoxError; + machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.ErrorTBoxConn.GetLed()); + SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.ErrorTBoxConn); + } , 10, InvokeStatus.None); } @@ -254,7 +260,8 @@ public class CarPrepareState : IState public InvokeStatus SelectPack(SwappingStateMachine machine) { SwapAmtOrder? swapAmtOrder = - AmtOrderRepository.QueryByClause(i => i.Status == 1 && i.VehicleNo.Equals(machine.TBoxCarInfoModel.CarNo)); + AmtOrderRepository.QueryByClause(i => + i.Status == (int)InfoEnum.AmtOrderStatus.Success && i.VehicleNo.Equals(machine.TBoxCarInfoModel.CarNo)); return Invoker.Invoke("selectPack", 500, 20, machine.IsCanceled, @@ -316,7 +323,7 @@ public class CarPrepareState : IState IMapper mapperBinInfo = configBinInfo.CreateMapper(); BinInfo dbBinInfo = mapperBinInfo.Map(orderBatteryInfo.UpBinInfo); - dbBinInfo.AmtLock = "1"; + dbBinInfo.AmtLock = InfoEnum.AmtBatLockStatus.Lock.ToString(); BinInfoRepository.Update(dbBinInfo); if (!orderBatteryInfo.isAmt) { @@ -327,7 +334,7 @@ public class CarPrepareState : IState new MapperConfiguration(cfg => cfg.CreateMap().ReverseMap()); IMapper mapperAmt = configAmt.CreateMapper(); SwapAmtOrder swapAmtOrder = mapperAmt.Map(orderBatteryInfo.swapAmtOrder); - swapAmtOrder.Status = 6; + swapAmtOrder.Status = (int)InfoEnum.AmtOrderStatus.Swapping; AmtOrderRepository.Update(swapAmtOrder); } diff --git a/Service/Execute/Step/CloudSendOutSwapState.cs b/Service/Execute/Step/CloudSendOutSwapState.cs deleted file mode 100644 index b09e25f..0000000 --- a/Service/Execute/Step/CloudSendOutSwapState.cs +++ /dev/null @@ -1,52 +0,0 @@ -using Entity.Constant; - -namespace Service.Execute.Step; - -/// -/// 云平台下发换电 -/// -public class CloudSendOutSwapState: IState -{ - public StateResult Handle(SwappingStateMachine machine) - { - - return new StateResult() - { - - SwappingState = SwappingState.StationReady - }; - } - - - /// - /// 等待云平台下发换电 - /// - /// - /*public InvokeStatus CloudSendOutSwap(SwappingStateMachine machine) - { - return Invoker.Invoke("check CarInPosition", 500, 50, machine.IsCanceled, - () => SwappingStateMachine.VehiclesInPlaceFlag, () => - { - var result = TBoxApi.GetCarInfo(); - TboxCarInfoModel tboxCarInfoModel = result.Result; - - if (tboxCarInfoModel.HeartBeatMsg.KeyStatus == 0) - { - SwappingStateMachine.VehiclesInPlaceFlag = true; - //写入口等 :红灯 - if (PlcApi.WriteEntranceLamp(1020)) - { - machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.InfoCarInPosition.GetLed()); - SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.InfoCarInPosition); - SwappingStateMachine.VehiclesInPlaceFlag = true; - } - } - }, () => - { - SwappingStateMachine.ExceptionReason = ExceptionReason.CarInPositionError; - machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.ErrorCarInPositionTimeout.GetLed()); - SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.ErrorCarInPositionTimeout); - }, false, () => { } - , 20, InvokeStatus.None); - }*/ -} \ No newline at end of file diff --git a/Service/Execute/Step/DoSwappingState.cs b/Service/Execute/Step/DoSwappingState.cs index a9759b1..58eb0f5 100644 --- a/Service/Execute/Step/DoSwappingState.cs +++ b/Service/Execute/Step/DoSwappingState.cs @@ -1,14 +1,274 @@ -namespace Service.Execute.Step; +using log4net; +using Repository.Station; +using Service.Execute.Api; +using Service.Execute.Enum; +using Service.Execute.Model; +using Service.Execute.StaticTools; +using Service.Execute.SwapException; +using Swapping.Business.Tech; -public class DoSwappingState: IState +namespace Service.Execute.Step; + +public class DoSwappingState : IState { + private readonly ILog _log = LogManager.GetLogger(typeof(DoSwappingState)); + private SwapOrderRepository SwapOrderRepository { get; set; } + public StateResult Handle(SwappingStateMachine machine) { - + //上报云平台换电开始 + SwappingStateMachine.BusinessSwappingForCloudState = InfoEnum.BusinessSwappingForCloudState.BeginSwap; + SwappingStateMachine.BusinessSwappingStateUpdateTime = DateTime.Now; + _log.Info($"BusinessSwappingForCloudState={SwappingStateMachine.BusinessSwappingForCloudState}"); + CloudApi.SendStateLog(machine.SwapOrder, InfoEnum.BusinessSwappingForCloudState.BeginSwap); + + //再次读锁止状态,防止plc需要挪车 + InvokeStatus carInPosition2 = CarInPosition2(machine); + if (carInPosition2 != InvokeStatus.Done) + { + return SwappingStateMachine.ReturnWithInvokeErr(carInPosition2, ExceptionReason.None); + } + + //下发启动换电 + InvokeStatus startSwapping = StartSwapping(machine); + if (startSwapping != InvokeStatus.Done) + { + return SwappingStateMachine.ReturnWithInvokeErr(startSwapping, ExceptionReason.None); + } + + //查看通道状态 + StateResult checkChannelStatus = CheckChannelStatus(machine); + if (checkChannelStatus != null) + { + return checkChannelStatus; + } + + //旧电池拆卸 + InvokeStatus unPack = UnPack(machine); + if (unPack != InvokeStatus.Done) + { + return SwappingStateMachine.ReturnWithInvokeErr(unPack, ExceptionReason.None); + } + + //旧电池搬运 + InvokeStatus oldBatteryCarryIn = OldBatteryCarryIn(machine); + if (oldBatteryCarryIn != InvokeStatus.Done) + { + return SwappingStateMachine.ReturnWithInvokeErr(oldBatteryCarryIn, ExceptionReason.None); + } + + //新电池搬运 + InvokeStatus newBatteryCarryOut = NewBatteryCarryOut(machine); + if (newBatteryCarryOut != InvokeStatus.Done) + { + return SwappingStateMachine.ReturnWithInvokeErr(newBatteryCarryOut, ExceptionReason.None); + } + + //安装 + InvokeStatus pack = Pack(machine); + if (pack != InvokeStatus.Done) + { + return SwappingStateMachine.ReturnWithInvokeErr(pack, ExceptionReason.None); + } + + //安装完成 + InvokeStatus packFinish = PackFinish(machine); + if (packFinish != InvokeStatus.Done) + { + return SwappingStateMachine.ReturnWithInvokeErr(packFinish, ExceptionReason.None); + } + + return new StateResult() { - - SwappingState = SwappingState.StationReady + SwappingState = SwappingState.SwapDone }; } + + /// + /// 下发plc启动换电 + /// + /// + public InvokeStatus StartSwapping(SwappingStateMachine machine) + { + return Invoker.Invoke("UnLockCar", 1000, 5, machine.IsCanceled, + () => SwappingStateMachine.StartSwappingFlag, () => + { + Task result = TBoxApi.UnLockCar(); + bool unLock = result.Result; + if (unLock) + { + //查询车辆锁止状态 + var startSwapping = PlcApi.StartSwapping(); + if (startSwapping) + { + machine.SwapOrder.SwapBeginTime = DateTime.Now; + SwapOrderRepository.Update(machine.SwapOrder); + machine.SwapStatus = 0; + SwappingStateMachine.StartSwappingFlag = true; + } + } + }, () => { }); + } + + + /// + /// 读取plc任务状态电池拆卸中 + /// 读取plc任务状态电池入库搬运中 + /// 读取plc任务状态电池出库搬运中 + /// 读取plc任务状态电池安装中 + /// 读取plc任务状态电池安装完成 + /// + /// + public InvokeStatus UnPack(SwappingStateMachine machine) + { + return Invoker.Invoke("plc UnPack", 500, 5, machine.IsCanceled, + () => SwappingStateMachine.UnOldBatteryFlag, () => + { + machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.InfoUnPack.GetLed()); + SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.InfoUnPack); + + SwappingStateMachine.UnOldBatteryFlag = PlcApi.ReadPlcTaskStatus() == 1002; + }, () => { }); + } + + public InvokeStatus OldBatteryCarryIn(SwappingStateMachine machine) + { + return Invoker.Invoke("plc OldBatteryCarryIn", 500, 5, machine.IsCanceled, + () => SwappingStateMachine.StorageOldBatteryFlag, () => + { + machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.InfoOldBatteryCarryIn.GetLed()); + SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.InfoOldBatteryCarryIn); + + SwappingStateMachine.StorageOldBatteryFlag = PlcApi.ReadPlcTaskStatus() == 1003; + }, () => { }); + } + + public InvokeStatus NewBatteryCarryOut(SwappingStateMachine machine) + { + return Invoker.Invoke("plc NewBatteryCarryOut", 500, 5, machine.IsCanceled, + () => SwappingStateMachine.OutNewBatteryFlag, () => + { + machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.InfoNewBatteryCarryOut.GetLed()); + SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.InfoNewBatteryCarryOut); + + SwappingStateMachine.OutNewBatteryFlag = PlcApi.ReadPlcTaskStatus() == 1004; + }, () => { }); + } + + + public InvokeStatus Pack(SwappingStateMachine machine) + { + return Invoker.Invoke("plc Pack ing", 500, 5, machine.IsCanceled, + () => SwappingStateMachine.InstallNewBatteryFlag, () => + { + machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.InfoPack.GetLed()); + SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.InfoPack); + + SwappingStateMachine.InstallNewBatteryFlag = PlcApi.ReadPlcTaskStatus() == 1005; + }, () => { }); + } + + public InvokeStatus PackFinish(SwappingStateMachine machine) + { + return Invoker.Invoke("plc Pack Finish", 500, 5, machine.IsCanceled, + () => SwappingStateMachine.FinishNewBatteryFlag, () => + { + machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.InfoPackFinish.GetLed()); + SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.InfoPackFinish); + if (PlcApi.ReadPlcTaskStatus() == 1006) + { + SwappingStateMachine.FinishNewBatteryFlag = true; + SwappingStateMachine.BusinessSwappingForCloudState = + InfoEnum.BusinessSwappingForCloudState.SwapFinish; + CloudApi.SendStateLog(machine.SwapOrder,SwappingStateMachine.BusinessSwappingForCloudState); + SwappingStateMachine.BusinessSwappingStateUpdateTime = DateTime.Now; + //上报云平台换电完成 + machine.SwapStatus = 1; + } + }, () => { }); + } + + + /// + /// 查看通道状态 + /// :0:无效值 + /// 1000;拍照OK + ///1010;拍照NG + ///1020;拍照超限,请移车 + /// + /// + public StateResult CheckChannelStatus(SwappingStateMachine machine) + { + while (!SwappingStateMachine.ChannelStatusOkFlag) + { + _log.Info("begin plc CheckChannelStatus"); + Thread.Sleep(1000); + var channelStatus = PlcApi.ChannelStatus(); + if (channelStatus == 1000) + { + SwappingStateMachine.ChannelStatusOkFlag = true; + return null; + } + else if (channelStatus == 1020) + { + //需要移车 先解锁 提示移动车辆,等待3分钟 + var lockCar = TBoxApi.LockCar(); + if (lockCar.Result) + { + machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.ErrChannelStatus.GetLed()); + SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.ErrChannelStatus); + //等待3分钟 + Thread.Sleep(3000); + SwappingStateMachine.VehiclesInPlace2Flag = false; + SwappingStateMachine.StartSwappingFlag = false; + + //回归到本阶段的读锁止状态 + return new StateResult() + { + SwappingState = SwappingState.DoSwapping + }; + } + } + else if (channelStatus == 1010) + { + //故障 不能继续换电,提示驶离,上报云平台,修改换电订单 + machine.SwapStatus = (int)InfoEnum.SwapOrderResult.Fail; + + //跳转到SwappDone + return new StateResult() + { + SwappingState = SwappingState.SwapDone + }; + } + } + + return null; + } + + + /// + /// 车辆到位 + /// + /// + public InvokeStatus CarInPosition2(SwappingStateMachine machine) + { + return Invoker.Invoke("check CarInPosition2", 500, 50, machine.IsCanceled, + () => SwappingStateMachine.VehiclesInPlace2Flag, () => + { + var result = TBoxApi.GetCarInfo(); + TboxCarInfoModel tboxCarInfoModel = result.Result; + + if (tboxCarInfoModel.HeartBeatMsg.KeyStatus == 0) + { + SwappingStateMachine.VehiclesInPlace2Flag = true; + } + }, () => + { + SwappingStateMachine.ExceptionReason = ExceptionReason.CarInPositionError; + machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.ErrorCarInPositionTimeout.GetLed()); + SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.ErrorCarInPositionTimeout); + }, false, () => { } + , 20, InvokeStatus.None); + } } \ No newline at end of file diff --git a/Service/Execute/Step/ExceptionState.cs b/Service/Execute/Step/ExceptionState.cs index 650f7fd..0676c49 100644 --- a/Service/Execute/Step/ExceptionState.cs +++ b/Service/Execute/Step/ExceptionState.cs @@ -1,13 +1,17 @@ -namespace Service.Execute.Step; +using log4net; -public class ExceptionState: IState +namespace Service.Execute.Step; + +public class ExceptionState : IState { + private static readonly ILog _log = LogManager.GetLogger(typeof(ExceptionState)); + public StateResult Handle(SwappingStateMachine machine) { - + _log.Info($"'goto cancel"); + return new StateResult() { - SwappingState = SwappingState.StationReady }; } diff --git a/Service/Execute/Step/SwapCanStartState.cs b/Service/Execute/Step/SwapCanStartState.cs new file mode 100644 index 0000000..cc2e544 --- /dev/null +++ b/Service/Execute/Step/SwapCanStartState.cs @@ -0,0 +1,98 @@ +using Entity.Constant; +using log4net; +using Repository.Station; +using Service.Cloud.Client; +using Service.Cloud.Msg.Cloud.Req; +using Service.Execute.Api; +using Service.Execute.Enum; +using Service.Execute.StaticTools; +using Service.Execute.SwapException; +using Service.Init; +using Swapping.Business.Tech; + +namespace Service.Execute.Step; + +/// +/// 云平台下发换电 +/// +public class SwapCanStartState : IState +{ + private readonly ILog _log = LogManager.GetLogger(typeof(SwapCanStartState)); + + private SwapOrderRepository SwapOrderRepository { get; set; } + + public StateResult Handle(SwappingStateMachine machine) + { + InvokeStatus swapCanStart = SwapCanStart(machine); + + if (InvokeStatus.Done != swapCanStart) + { + return SwappingStateMachine.ReturnWithInvokeErr(swapCanStart, ExceptionReason.None); + } + + return new StateResult() + { + SwappingState = SwappingState.CarCtrl + }; + } + + + /// + /// 等待云平台下发换电 + /// + /// + public InvokeStatus SwapCanStart(SwappingStateMachine machine) + { + return Invoker.Invoke("check swapCanStart", 1000, 50, machine.IsCanceled, + () => SwappingStateMachine.CloudCarCanStartFlag, () => + { + //远程模式 + if (StationConstant.StationModel.Remote == + BaseEnumExtensions.GetEnumByCode( + int.Parse(StaticStationInfo.StationModel))) + { + CarCanStart carCanStart = CloudApi.CarCanStart(); + if (carCanStart != null) + { + //车牌号 + if (carCanStart.cn.Equals(machine.TBoxCarInfoModel.CarNo)) + { + //可以开始换电 + if (carCanStart.cs == 1) + { + _log.Info("SwapCanStart ok"); + //更新换电订单 + machine.SwapOrder.CloudSn = carCanStart.on; + SwapOrderRepository.Update(machine.SwapOrder.CloudSn); + SwappingStateMachine.CloudCarCanStartFlag = true; + } + else + { + _log.Info("SwapCanStart cancel"); + //语音提示云平台取消换电 + SwappingStateMachine.CloudCarCanStartFlag = false; + machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.CloudSendSwapCancel.GetLed()); + SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.CloudSendSwapError); + SwappingStateMachine.BusinessSwappingForCloudState = + InfoEnum.BusinessSwappingForCloudState.SwapReady; + CloudApi.SendStateLog(machine.SwapOrder, + SwappingStateMachine.BusinessSwappingForCloudState); + } + } + } + } + else + { + SwappingStateMachine.CloudCarCanStartFlag = true; + //直接下发换电 + _log.Info("SwapCanStart ok"); + } + }, () => + { + SwappingStateMachine.ExceptionReason = ExceptionReason.CloudSendSwapError; + machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.CloudSendSwapError.GetLed()); + SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.CloudSendSwapError); + }, false, () => { } + , 10, InvokeStatus.None); + } +} \ No newline at end of file diff --git a/Service/Execute/Step/SwapDoneState.cs b/Service/Execute/Step/SwapDoneState.cs index 2a47703..d1061e6 100644 --- a/Service/Execute/Step/SwapDoneState.cs +++ b/Service/Execute/Step/SwapDoneState.cs @@ -1,14 +1,141 @@ -namespace Service.Execute.Step; +using log4net; +using Repository.Station; +using Service.Execute.Api; +using Service.Execute.Enum; +using Service.Execute.Model; +using Service.Execute.StaticTools; +using Service.Execute.SwapException; +using Swapping.Business.Tech; -public class SwapDoneState: IState +namespace Service.Execute.Step; + +public class SwapDoneState : IState { + private SwapOrderRepository SwapOrderRepository { get; set; } + + private SwapAmtOrderRepository SwapAmtOrderRepository { get; set; } + + private readonly ILog _log = LogManager.GetLogger(typeof(SwapDoneState)); + + /// + /// 修改换电订单 + /// 查看是否有预约单 更新预约单的状态 + /// + /// + /// public StateResult Handle(SwappingStateMachine machine) { - + //更新换电订单 + machine.SwapOrder.SwapResult = machine.SwapStatus; + machine.SwapOrder.SwapEndTime = DateTime.Now; + machine.SwapOrder.FailReason = machine.SwapFailReason; + SwapOrderRepository.Update(machine.SwapOrder); + + + if (machine.SwapStatus == (int)InfoEnum.SwapOrderResult.Success) + { + //上传云平台换电状态 + SwappingStateMachine.BusinessSwappingForCloudState = InfoEnum.BusinessSwappingForCloudState.SwapDoneWithVel; + CloudApi.SendStateLog(machine.SwapOrder, SwappingStateMachine.BusinessSwappingForCloudState); + } + + //云平台没有匹配的失败状态 + //车辆上锁 ,提示请驶离 + InvokeStatus lockCar = LockCar(machine); + + if (lockCar != InvokeStatus.Done) + { + return SwappingStateMachine.ReturnWithInvokeErr(lockCar, ExceptionReason.None); + } + + //出口雷达监测 + InvokeStatus existRadar = ExistRadar(machine); + if (existRadar != InvokeStatus.Done) + { + return SwappingStateMachine.ReturnWithInvokeErr(existRadar, ExceptionReason.None); + } + return new StateResult() { - SwappingState = SwappingState.StationReady }; } + + /// + /// 车辆上锁 + /// + /// + public InvokeStatus LockCar(SwappingStateMachine machine) + { + return Invoker.Invoke("LockCar", 500, 100, machine.IsCanceled, + () => SwappingStateMachine.VelLockFlag, () => + { + Task result = TBoxApi.LockCar(); + bool unLock = result.Result; + if (unLock) + { + //查询车辆锁止状态 + Task carInfo = TBoxApi.GetCarInfo(); + if (carInfo.Result.HeartBeatMsg.LockStatus == 2) + { + //设置出口的是绿灯 + if (PlcApi.WriteExistLamp(1000)) + { + machine.LedTool?.WriteProgramContent( + machine.SwapStatus == (int)InfoEnum.SwapOrderResult.Success + ? InfoEnum.SwapInfo.InfoCarLeave.GetLed() + : InfoEnum.SwapInfo.ErrInfoCarLeave.GetLed()); + SoundTool.PlayOneSound(machine.SwapStatus == (int)InfoEnum.SwapOrderResult.Success + ? (int)InfoEnum.SwapInfo.InfoCarLeave + : (int)InfoEnum.SwapInfo.ErrInfoCarLeave); + SwappingStateMachine.VelLockFlag = true; + } + } + } + }, () => + { + machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.ErrLockCar.GetLed()); + SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.ErrLockCar); + }, false, () => { SwappingStateMachine.ExceptionReason = ExceptionReason.LockCarError; } + , 10, InvokeStatus.None); + } + + + public InvokeStatus ExistRadar(SwappingStateMachine machine) + { + return Invoker.Invoke("wait exist radar", 1000, 5, machine.IsCanceled, + () => SwappingStateMachine.RadarOutFlag, () => + { + if (!PlcApi.EntranceRadar()) + { + _log.Info("exist radar false"); + } + else + { + SwappingStateMachine.ExceptionReason = ExceptionReason.None; + _log.Info("exist radar true"); + + + if (PlcApi.WriteExistLamp(1020)) + { + //出口写红灯 + //更新车辆离场时间,上报云平台 + SwappingStateMachine.BusinessSwappingForCloudState = + InfoEnum.BusinessSwappingForCloudState.SwapDoneWithoutVel; + machine.SwapOrder.VehicleLeaveTime = DateTime.Now; + SwapOrderRepository.Update(machine.SwapOrder); + if (machine.SwapOrderBatteryInfo.swapAmtOrder != null) + { + machine.SwapOrderBatteryInfo.swapAmtOrder.Status = + machine.SwapStatus == (int)InfoEnum.SwapOrderResult.Success + ? (int)InfoEnum.AmtOrderStatus.SwapFinish + : (int)InfoEnum.AmtOrderStatus.SwapFail; + SwapAmtOrderRepository.Update(machine.SwapOrderBatteryInfo.swapAmtOrder); + } + + SwappingStateMachine.RadarOutFlag = true; + } + } + }); + } } \ No newline at end of file diff --git a/Service/Execute/SwapException/ExceptionReason.cs b/Service/Execute/SwapException/ExceptionReason.cs index 7dea255..2da6f1d 100644 --- a/Service/Execute/SwapException/ExceptionReason.cs +++ b/Service/Execute/SwapException/ExceptionReason.cs @@ -17,6 +17,8 @@ namespace Service.Execute.SwapException; CloudSendSwapError, SelectPackError, HvPwrOffError, + UnLockCarError, + LockCarError, LvPwrOffError, SelfCheckError, TimeOutError diff --git a/Service/Execute/SwappingStateMachine.cs b/Service/Execute/SwappingStateMachine.cs index 3028612..dd58b15 100644 --- a/Service/Execute/SwappingStateMachine.cs +++ b/Service/Execute/SwappingStateMachine.cs @@ -14,6 +14,8 @@ public class SwappingStateMachine : IDisposable { private static readonly ILog _log = LogManager.GetLogger(typeof(SwappingStateMachine)); private static SwappingStateMachine _swappingStateMachine = new SwappingStateMachine(); + + public static bool CancelFlag { get; set; } = false; public static bool StopFlag { get; set; } = false; @@ -28,7 +30,9 @@ public class SwappingStateMachine : IDisposable public static DateTime BusinessSwappingStateUpdateTime = DateTime.Now; public static ExceptionReason ExceptionReason = ExceptionReason.None; - + //换电实时状态 0:开始 1:成功 2:失败 + public int? SwapStatus = null; + public string SwapFailReason = ""; public RfidReadModel? RfidReadModel=null; public TboxCarInfoModel? TBoxCarInfoModel = null; @@ -65,21 +69,23 @@ public class SwappingStateMachine : IDisposable //车辆到位 public static bool VehiclesInPlaceFlag = false; - //通道定位 - public static bool ChannelPositioningFlag = false; //下发选包 public static bool DistributeSelectPackFlag = false; //云平台下发启动换电 - public static bool CloudPackFlag = false; + public static bool CloudCarCanStartFlag = false; //车辆解锁 public static bool VelUnlockFlag = false; //开始换电 public static bool StartSwappingFlag = false; - + //拍照状态 + public static bool ChannelStatusOkFlag = false; + + //二次检测车辆到位 + public static bool VehiclesInPlace2Flag = false; //拆旧电池 public static bool UnOldBatteryFlag = false; @@ -113,7 +119,7 @@ public class SwappingStateMachine : IDisposable Dictionary[SwappingState.Begin] = new BeginState(); Dictionary[SwappingState.StationReady] = new StationReadyState(); Dictionary[SwappingState.CarPrepare] = new CarPrepareState(); - Dictionary[SwappingState.SelectPack] = new CloudSendOutSwapState(); + Dictionary[SwappingState.SwapCanStart] = new SwapCanStartState(); Dictionary[SwappingState.CarCtrl] = new CarCtrlState(); Dictionary[SwappingState.DoSwapping] = new DoSwappingState(); Dictionary[SwappingState.SwapDone] = new SwapDoneState(); @@ -141,7 +147,7 @@ public class SwappingStateMachine : IDisposable } else { - return StateResult.Exception(ExceptionReason.ReadRfidError, null); + return StateResult.Exception(exceptionReason, null); } } @@ -209,7 +215,7 @@ public enum SwappingState Begin, StationReady, CarPrepare, - SelectPack, + SwapCanStart, CarCtrl, DoSwapping, SwapDone,