using AutoMapper; using Entity.Constant; using Entity.DbModel.Station; 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 Service.Init; using Swapping.Business.Tech; namespace Service.Execute.Step; public class CarPrepareState : IState { private readonly ILog _log = LogManager.GetLogger(typeof(CarPrepareState)); private BinInfoRepository BinInfoRepository { get; set; } private SwapAmtOrderRepository AmtOrderRepository { get; set; } private SwapOrderBatteryRepository SwapOrderBatteryRepository { get; set; } public StateResult Handle(SwappingStateMachine machine) { Thread.Sleep(500); RfidReadModel? rfidReadModel = machine.RfidReadModel; if (rfidReadModel == null) { _log.Error("rfid is null"); return new StateResult() { SwappingState = SwappingState.StationReady }; } //云平台车辆认证 var cloudCheckVel = CloudCheckVel(machine); if (cloudCheckVel != InvokeStatus.Done) { return SwappingStateMachine.ReturnWithInvokeErr(cloudCheckVel, ExceptionReason.None); } //检查tbox链接状态 InvokeStatus checkTBoxConnect = CheckTBoxConnectFlag(machine); if (checkTBoxConnect != InvokeStatus.Done) { return SwappingStateMachine.ReturnWithInvokeErr(checkTBoxConnect, ExceptionReason.None); } //车辆本地验证 InvokeStatus checkTBoxVelLocal = CheckTBoxVelLocalFlag(machine); if (checkTBoxVelLocal != InvokeStatus.Done) { return SwappingStateMachine.ReturnWithInvokeErr(checkTBoxVelLocal, ExceptionReason.None); } //云端数据上报 InvokeStatus cloudTBox = CloudTBoxFlag(machine); if (cloudTBox != InvokeStatus.Done) { return SwappingStateMachine.ReturnWithInvokeErr(cloudTBox, ExceptionReason.None); } SwappingStateMachine.ExceptionReason = ExceptionReason.None; //选包 InvokeStatus selectPack = SelectPack(machine); if (selectPack != InvokeStatus.Done) { return SwappingStateMachine.ReturnWithInvokeErr(selectPack, ExceptionReason.None); } //车辆到位 InvokeStatus carInPosition = CarInPosition(machine); if (carInPosition != InvokeStatus.Done) { return SwappingStateMachine.ReturnWithInvokeErr(carInPosition, ExceptionReason.None); } return new StateResult() { SwappingState = SwappingState.SwapCanStart }; } /// /// 车辆到位 /// /// public InvokeStatus CarInPosition(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.BusinessSwappingForCloudState = InfoEnum.BusinessSwappingForCloudState.SwapReady; SwappingStateMachine.ExceptionReason = ExceptionReason.None; CloudApi.SendStateLog(machine.SwapOrder, SwappingStateMachine.BusinessSwappingForCloudState); //清除下发的指令,等待新的指令 CloudApi.ClearCarCanStartInfo(); } } }, () => { SwappingStateMachine.ExceptionReason = ExceptionReason.CarInPositionError; machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.ErrorCarInPositionTimeout.GetLed()); SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.ErrorCarInPositionTimeout); }, false, () => { } , 20, InvokeStatus.None); } /// /// 云平台车辆认证 /// /// public InvokeStatus CloudCheckVel(SwappingStateMachine machine) { return Invoker.Invoke("cloud check vehicle", 500, 20, machine.IsCanceled, () => SwappingStateMachine.CloudVelCheckFlag, () => { if (BaseEnumExtensions.GetEnumByCode( int.Parse(StaticStationInfo.StationModel)) == StationConstant.StationModel.Remote) { bool flag = CloudApi.VehicleCheck(machine.RfidReadModel); if (!flag) { _log.Info("cloud check vehicle error"); } else { SwappingStateMachine.ExceptionReason = ExceptionReason.None; _log.Info("cloud check vehicle done"); SwappingStateMachine.CloudVelCheckFlag = true; machine.LedTool.WriteProgramContent("换电准备中:云平台车辆验证完成"); } } else { SwappingStateMachine.CloudVelCheckFlag = true; } }, () => { machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.ErrorCloudCheck.GetLed()); SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.ErrorCloudCheck); }, false, () => { SwappingStateMachine.ExceptionReason = ExceptionReason.CloudCheckError; } , 20, InvokeStatus.None); } /// /// 检查tbox连接状态 /// /// public InvokeStatus CheckTBoxConnectFlag(SwappingStateMachine machine) { return Invoker.Invoke("check TBox connect", 1000, 20, machine.IsCanceled, () => SwappingStateMachine.TBoxConnectFlag, () => { Task result = TBoxApi.IsConnected(); bool isConnect = result.Result; if (isConnect) { SwappingStateMachine.TBoxConnectFlag = true; } }, () => { 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); } /// /// 车辆本地验证:车牌校验 /// /// public InvokeStatus CheckTBoxVelLocalFlag(SwappingStateMachine machine) { return Invoker.Invoke("check TBox VelLocal", 1000, 20, machine.IsCanceled, () => SwappingStateMachine.TBoxLocalCheckFlag, () => { Task carInfo = TBoxApi.GetCarInfo(); var tBoxCarInfoModel = carInfo.Result; //TODO::不知道Tbox给的CardNo是什么 if (tBoxCarInfoModel.CarNo.Trim().Equals(machine.RfidReadModel.VelNo.Trim())) { SwappingStateMachine.TBoxLocalCheckFlag = true; } }, () => { SwappingStateMachine.ExceptionReason = ExceptionReason.LocalCheckVarError; }, true, () => { SwappingStateMachine.ExceptionReason = ExceptionReason.LocalCheckVarError; } , 3, InvokeStatus.TimeOut); } /// /// 蓝牙数据云平台上报 /// /// public InvokeStatus CloudTBoxFlag(SwappingStateMachine machine) { return Invoker.Invoke("cloud TBox upload", 500, 20, machine.IsCanceled, () => SwappingStateMachine.CloudTBoxFlag, () => { Task result = TBoxApi.GetCarInfo(); TboxCarInfoModel tBoxCarInfoModel = result.Result; machine.TBoxCarInfoModel = tBoxCarInfoModel; if (tBoxCarInfoModel != null) { if (tBoxCarInfoModel.Connected) { //将数据上报云平台 CloudApi.UploadTBoxCarInfo(machine.SwapOrder, machine.TBoxCarInfoModel); } } }, () => { machine.LedTool?.WriteProgramContent("车机蓝牙车辆数据上报异常,请联系站务人员"); }, false, () => { SwappingStateMachine.ExceptionReason = ExceptionReason.CloudCarDataUploadError; } , 20, InvokeStatus.None); } /// /// 选包: /// 有预约单: 获取预约单的电池 /// 无预约单: /// 1.仓位状态:启动 /// 2.电池在位 /// 3.充电状态:不在充电中 /// 4.未锁定 /// 5.最后一次结束充电时间> () /// 6.soc >() /// /// public InvokeStatus SelectPack(SwappingStateMachine machine) { SwapAmtOrder? swapAmtOrder = AmtOrderRepository.QueryByClause(i => i.Status == (int)InfoEnum.AmtOrderStatus.Success && i.VehicleNo.Equals(machine.TBoxCarInfoModel.CarNo)); return Invoker.Invoke("selectPack", 500, 20, machine.IsCanceled, () => SwappingStateMachine.SelectPackFlag, () => { SwapOrderBatteryInfo orderBatteryInfo = null; if (swapAmtOrder != null) { orderBatteryInfo = SelectPackArm(swapAmtOrder); } else { orderBatteryInfo = SelectPackNotArm(); } if (orderBatteryInfo.CanSwap != InfoEnum.SelectBinStatusInfo.Success) { machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.ErrorSelectPack.GetLed()); SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.ErrorSelectPack); Thread.Sleep(1000 * 3); _log.Info($"SelectPack error CanSwap={machine.SwapOrderBatteryInfo.CanSwap}"); } else { //选包成功 LockBinAndUpdateAmt(orderBatteryInfo); machine.SwapOrderBatteryInfo = orderBatteryInfo; SaveSwapBattery(machine); SwappingStateMachine.SelectPackFlag = true; } }, () => { SwappingStateMachine.ExceptionReason = ExceptionReason.SelectPackError; }); } private void SaveSwapBattery(SwappingStateMachine machine) { BinInfo UpBin = machine.SwapOrderBatteryInfo.UpBinInfo; BinInfo InBin = machine.SwapOrderBatteryInfo.InBinInfo; SwapOrderBattery swapOrderBattery = new SwapOrderBattery() { SwapOrderSn = machine.SwapOrder.Sn, UpBatterySoc = UpBin.Soc, UpBatteryNo = UpBin.BatteryNo, UpBatterySoe = UpBin.Soe, UpBatteryBinNo = int.Parse(UpBin.No), DownBatteryBinNo = int.Parse(InBin.No), }; SwapOrderBatteryRepository.Insert(swapOrderBattery); } /// /// 1.锁仓 /// 2.更改预约单 /// private void LockBinAndUpdateAmt(SwapOrderBatteryInfo orderBatteryInfo) { var configBinInfo = new MapperConfiguration(cfg => cfg.CreateMap().ReverseMap()); IMapper mapperBinInfo = configBinInfo.CreateMapper(); BinInfo dbBinInfo = mapperBinInfo.Map(orderBatteryInfo.UpBinInfo); dbBinInfo.AmtLock = InfoEnum.AmtBatLockStatus.Lock.ToString(); BinInfoRepository.Update(dbBinInfo); if (!orderBatteryInfo.isAmt) { return; } var configAmt = new MapperConfiguration(cfg => cfg.CreateMap().ReverseMap()); IMapper mapperAmt = configAmt.CreateMapper(); SwapAmtOrder swapAmtOrder = mapperAmt.Map(orderBatteryInfo.swapAmtOrder); swapAmtOrder.Status = (int)InfoEnum.AmtOrderStatus.Swapping; AmtOrderRepository.Update(swapAmtOrder); } /// 1.仓位状态:启动 /// 2.电池在位 /// 3.充电状态:不在充电中 /// 4.未锁定 /// 5.最后一次结束充电时间> () /// 6.soc >() /** * && i.ChargeStatus == 2 && i.AmtLock == "0" && new TimeSpan(DateTime.Now.Ticks - i.LastChargeFinishTime.ToDateTime().Ticks) .TotalMinutes > StaticStationInfo.SwapFinishChargeTime && i.Soc > StaticStationInfo.Soc */ private SwapOrderBatteryInfo SelectPackNotArm() { SwapOrderBatteryInfo orderBatteryInfo = new SwapOrderBatteryInfo(); UpBin(orderBatteryInfo); if (orderBatteryInfo.CanSwap != InfoEnum.SelectBinStatusInfo.Success) { return orderBatteryInfo; } InBin(orderBatteryInfo); return orderBatteryInfo; } private SwapOrderBatteryInfo SelectPackArm(SwapAmtOrder swapAmtOrder) { SwapOrderBatteryInfo orderBatteryInfo = new SwapOrderBatteryInfo(); orderBatteryInfo.swapAmtOrder = swapAmtOrder; orderBatteryInfo.isAmt = true; BinInfo UpBin = BinInfoRepository.QueryByClause(i => i.No.Equals(swapAmtOrder.AmtBinNoList)); bool CanSwap = UpBin.Exists == 1 && UpBin.Status == 1 && UpBin.ChargeStatus == 2 && UpBin.AmtLock == "1" && new TimeSpan(DateTime.Now.Ticks - UpBin.LastChargeFinishTime.ToDateTime() .Ticks) .TotalMinutes > int.Parse(StaticStationInfo.SwapFinishChargeTime) && UpBin.Soc > int.Parse(StaticStationInfo.SwapSoc); if (!CanSwap) { orderBatteryInfo.CanSwap = InfoEnum.SelectBinStatusInfo.AmtError; return orderBatteryInfo; } orderBatteryInfo.UpBinInfo = UpBin; InBin(orderBatteryInfo); return orderBatteryInfo; } /// /// 取电池判断 /// /// private void UpBin(SwapOrderBatteryInfo orderBatteryInfo) { List list = BinInfoRepository.QueryListByClause(i => i.Exists == 1 && i.Status == 1 && i.AmtLock == "0"); if (list.Count <= 0) { orderBatteryInfo.CanSwap = InfoEnum.SelectBinStatusInfo.NoBattery; return; } list = list.Where(i => i.ChargeStatus == 2).ToList(); if (list.Count <= 0) { orderBatteryInfo.CanSwap = InfoEnum.SelectBinStatusInfo.LessOfFinishCharging; return; } list = list.Where(i => i.Soc > int.Parse(StaticStationInfo.SwapSoc)).ToList(); if (list.Count <= 0) { orderBatteryInfo.CanSwap = InfoEnum.SelectBinStatusInfo.LessOfSoc; return; } list = list.Where(i => new TimeSpan(DateTime.Now.Ticks - i.LastChargeFinishTime.ToDateTime().Ticks) .TotalMinutes > int.Parse(StaticStationInfo.SwapFinishChargeTime)).ToList(); if (list.Count <= 0) { orderBatteryInfo.CanSwap = InfoEnum.SelectBinStatusInfo.LessOf3Minute; return; } orderBatteryInfo.UpBinInfo = list[0]; orderBatteryInfo.CanSwap = InfoEnum.SelectBinStatusInfo.Success; } /// /// 放电池判断 /// /// private void InBin(SwapOrderBatteryInfo orderBatteryInfo) { List list = BinInfoRepository.QueryListByClause(i => i.Exists == 1 && i.Status == 1 && i.AmtLock == "0" && i.Exists == 0); if (list.Count <= 0) { orderBatteryInfo.CanSwap = InfoEnum.SelectBinStatusInfo.LessOfEmptyBin; return; } orderBatteryInfo.InBinInfo = list[0]; orderBatteryInfo.CanSwap = InfoEnum.SelectBinStatusInfo.Success; } }