|
|
|
|
using Autofac;
|
|
|
|
|
using AutoMapper;
|
|
|
|
|
using Entity.Attr;
|
|
|
|
|
using Entity.Constant;
|
|
|
|
|
using Entity.DbModel.Station;
|
|
|
|
|
using Entity.Dto;
|
|
|
|
|
using HybirdFrameworkCore.Autofac;
|
|
|
|
|
using log4net;
|
|
|
|
|
using Repository.Station;
|
|
|
|
|
using Service.Execute.Api;
|
|
|
|
|
using Service.Execute.Model;
|
|
|
|
|
using Service.Execute.Model.Tbox;
|
|
|
|
|
using Service.Execute.StaticTools;
|
|
|
|
|
using Service.Execute.SwapException;
|
|
|
|
|
using Service.Execute.Utils;
|
|
|
|
|
using Service.Init;
|
|
|
|
|
using Service.Station;
|
|
|
|
|
|
|
|
|
|
namespace Service.Execute.Step;
|
|
|
|
|
|
|
|
|
|
public class CarPrepareState : IState
|
|
|
|
|
{
|
|
|
|
|
private readonly ILog _log = LogManager.GetLogger(typeof(CarPrepareState));
|
|
|
|
|
|
|
|
|
|
private readonly CommonMgr _CommonMgr = AppInfo.Container.Resolve<CommonMgr>();
|
|
|
|
|
|
|
|
|
|
private readonly SwapOrderBatteryRepository _swapOrderBatteryRepository =
|
|
|
|
|
AppInfo.Container.Resolve<SwapOrderBatteryRepository>();
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.TboxConnect);
|
|
|
|
|
////TBox连接
|
|
|
|
|
//if (StaticStationInfo.TboxStateConnect)
|
|
|
|
|
//{
|
|
|
|
|
// InvokeStatus tboxConnect = TboxConnect(machine);
|
|
|
|
|
// if (tboxConnect != InvokeStatus.Done)
|
|
|
|
|
// {
|
|
|
|
|
// return SwappingStateMachine.ReturnWithInvokeErr(tboxConnect, ExceptionReason.None);
|
|
|
|
|
// }
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
//当前车辆连接状态
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
machine.ExceptionReason = ExceptionReason.None;
|
|
|
|
|
SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.SelectPack);
|
|
|
|
|
//选包
|
|
|
|
|
InvokeStatus selectPack = SelectPack(machine);
|
|
|
|
|
if (selectPack != InvokeStatus.Done)
|
|
|
|
|
{
|
|
|
|
|
return SwappingStateMachine.ReturnWithInvokeErr(selectPack, ExceptionReason.None);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.BeginAuxiliarySource);
|
|
|
|
|
//下辅源
|
|
|
|
|
InvokeStatus auxiliarySource = AuxiliarySource(machine);
|
|
|
|
|
if (auxiliarySource != InvokeStatus.Done)
|
|
|
|
|
{
|
|
|
|
|
return SwappingStateMachine.ReturnWithInvokeErr(auxiliarySource, ExceptionReason.None);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//车辆到位
|
|
|
|
|
InvokeStatus carInPosition = CarInPosition(machine);
|
|
|
|
|
if (carInPosition != InvokeStatus.Done)
|
|
|
|
|
{
|
|
|
|
|
return SwappingStateMachine.ReturnWithInvokeErr(carInPosition, ExceptionReason.None);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new StateResult()
|
|
|
|
|
{
|
|
|
|
|
SwappingState = SwappingState.CarCtrl
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 车辆到位
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public InvokeStatus CarInPosition(SwappingStateMachine machine)
|
|
|
|
|
{
|
|
|
|
|
return Invoker.Invoke("check CarInPosition", 500, 5, machine.IsCanceled,
|
|
|
|
|
() => machine.VehiclesInPlaceFlag, () =>
|
|
|
|
|
{
|
|
|
|
|
var result = TBoxApi.GetCarInfo(machine.RfidReadModel.VelVin);
|
|
|
|
|
List<bool> succL = new List<bool>()
|
|
|
|
|
{
|
|
|
|
|
StaticStationInfo.TboxStateFlameout, StaticStationInfo.TboxStateBreak, StaticStationInfo.TboxStateN
|
|
|
|
|
};
|
|
|
|
|
var successCount = succL.Where(i => i).Count();
|
|
|
|
|
TboxCarInfoModel tboxCarInfoModel = result.Result;
|
|
|
|
|
|
|
|
|
|
var status = tboxCarInfoModel?.HeartBeatMsg;
|
|
|
|
|
|
|
|
|
|
if (StaticStationInfo.TboxStateFlameout)
|
|
|
|
|
{
|
|
|
|
|
//if (status?.EarPosition == 0&&status?.handbrake == 1)
|
|
|
|
|
if (status?.KeyStatus == 0)
|
|
|
|
|
{
|
|
|
|
|
machine.VehiclesInPlaceFlag = true;
|
|
|
|
|
//写入口等 :红灯
|
|
|
|
|
if (PlcApi.WriteEntranceLamp(1020))
|
|
|
|
|
{
|
|
|
|
|
// machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.InfoCarInPosition.GetLed());
|
|
|
|
|
SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.InfoCarInPosition);
|
|
|
|
|
machine.VehiclesInPlaceFlag = true;
|
|
|
|
|
//告知云平台换电准备完成
|
|
|
|
|
machine.BusinessSwappingForCloudState =
|
|
|
|
|
InfoEnum.BusinessSwappingForCloudState.SwapReady;
|
|
|
|
|
machine.ExceptionReason = ExceptionReason.None;
|
|
|
|
|
// CloudApi.SendStateLog(machine.SwapOrder, machine.BusinessSwappingForCloudState);
|
|
|
|
|
//清除下发的指令,等待新的指令
|
|
|
|
|
// CloudApi.ClearCarCanStartInfo();
|
|
|
|
|
|
|
|
|
|
_CommonMgr.InsertStep(InfoEnum.BusinessSwappingStep.CarInPositionFlag,
|
|
|
|
|
machine);
|
|
|
|
|
machine.BoxCarInfoModel = tboxCarInfoModel;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}, () =>
|
|
|
|
|
{
|
|
|
|
|
machine.ExceptionReason = ExceptionReason.CarInPositionError;
|
|
|
|
|
// machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.ErrorCarInPositionTimeout.GetLed());
|
|
|
|
|
SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.ErrorCarInPositionTimeout);
|
|
|
|
|
}, false, () => { }
|
|
|
|
|
, 10, InvokeStatus.None);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 检查tbox连接状态
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public InvokeStatus CheckTBoxConnectFlag(SwappingStateMachine machine)
|
|
|
|
|
{
|
|
|
|
|
return Invoker.Invoke("check TBox connect", 1000, 10, machine.IsCanceled,
|
|
|
|
|
() => machine.BoxConnectFlag, () =>
|
|
|
|
|
{
|
|
|
|
|
Task<bool> result = TBoxApi.IsConnected(machine.RfidReadModel.VelVin);
|
|
|
|
|
result.Wait();
|
|
|
|
|
bool isConnect = result.Result;
|
|
|
|
|
if (isConnect)
|
|
|
|
|
{
|
|
|
|
|
machine.BoxConnectFlag = true;
|
|
|
|
|
}
|
|
|
|
|
}, () =>
|
|
|
|
|
{
|
|
|
|
|
machine.ExceptionReason = ExceptionReason.ConnTBoxError;
|
|
|
|
|
SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.ErrorTBoxConn);
|
|
|
|
|
}, false, () =>
|
|
|
|
|
{
|
|
|
|
|
machine.ExceptionReason = ExceptionReason.ConnTBoxError;
|
|
|
|
|
// machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.ErrorTBoxConn.GetLed());
|
|
|
|
|
}
|
|
|
|
|
, 20, InvokeStatus.None);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///// <summary>
|
|
|
|
|
///// 连接TBox
|
|
|
|
|
///// </summary
|
|
|
|
|
///// <returns></returns>
|
|
|
|
|
//public InvokeStatus TboxConnect(SwappingStateMachine machine)
|
|
|
|
|
//{
|
|
|
|
|
// return Invoker.Invoke("TBox connect", 1000, 10, machine.IsCanceled,
|
|
|
|
|
// () => machine.BoxConnectFlag, () =>
|
|
|
|
|
// {
|
|
|
|
|
// Task<bool> result = TBoxApi.Connect(machine.RfidReadModel.VelVin);
|
|
|
|
|
// bool isConnect = result.Result;
|
|
|
|
|
// if (isConnect)
|
|
|
|
|
// {
|
|
|
|
|
// //读取车辆carNo=carVin
|
|
|
|
|
// Task<TboxCarInfoModel> carInfoResult = TBoxApi.GetCarInfo(machine.RfidReadModel.VelVin);
|
|
|
|
|
// var tboxCarInfoModel = carInfoResult.Result;
|
|
|
|
|
// var carInfo = tboxCarInfoModel?.CarInfo;
|
|
|
|
|
// if (carInfo != null)
|
|
|
|
|
// {
|
|
|
|
|
// if (carInfo.CarNo.Equals(carInfo.CarVin))
|
|
|
|
|
// {
|
|
|
|
|
// machine.BoxConnectFlag = true;
|
|
|
|
|
// SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.CheckTBoxConnectFlag);
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// }, () =>
|
|
|
|
|
// {
|
|
|
|
|
// machine.ExceptionReason = ExceptionReason.ConnTBoxError;
|
|
|
|
|
// SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.ErrorTBoxConn);
|
|
|
|
|
// }, false, () =>
|
|
|
|
|
// {
|
|
|
|
|
// machine.ExceptionReason = ExceptionReason.ConnTBoxError;
|
|
|
|
|
// // machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.ErrorTBoxConn.GetLed());
|
|
|
|
|
// }
|
|
|
|
|
// , 20, InvokeStatus.None);
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 车辆本地验证:车牌校验
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public InvokeStatus CheckTBoxVelLocalFlag(SwappingStateMachine machine)
|
|
|
|
|
{
|
|
|
|
|
return Invoker.Invoke("check TBox VelLocal", 1000, 20, machine.IsCanceled,
|
|
|
|
|
() => machine.BoxLocalCheckFlag, () =>
|
|
|
|
|
{
|
|
|
|
|
Task<TboxCarInfoModel> carInfo = TBoxApi.GetCarInfo(machine.RfidReadModel.VelVin);
|
|
|
|
|
var tBoxCarInfoModel = carInfo.Result;
|
|
|
|
|
|
|
|
|
|
if (tBoxCarInfoModel.CarNo!.Trim().Equals(machine.RfidReadModel!.VelVin.Trim()))
|
|
|
|
|
{
|
|
|
|
|
machine.BoxLocalCheckFlag = true;
|
|
|
|
|
machine.BoxCarInfoModel = tBoxCarInfoModel;
|
|
|
|
|
}
|
|
|
|
|
}, () => { machine.ExceptionReason = ExceptionReason.LocalCheckVarError; }, true, () =>
|
|
|
|
|
{
|
|
|
|
|
machine.ExceptionReason = ExceptionReason.LocalCheckVarError;
|
|
|
|
|
}
|
|
|
|
|
, 3, InvokeStatus.TimeOut);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 蓝牙数据云平台上报
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public InvokeStatus CloudTBoxFlag(SwappingStateMachine machine)
|
|
|
|
|
{
|
|
|
|
|
return Invoker.Invoke("cloud TBox upload", 500, 20, machine.IsCanceled,
|
|
|
|
|
() => machine.CloudTBoxFlag, () =>
|
|
|
|
|
{
|
|
|
|
|
Task<TboxCarInfoModel> result = TBoxApi.GetCarInfo(machine.RfidReadModel.VelVin);
|
|
|
|
|
TboxCarInfoModel tBoxCarInfoModel = result.Result;
|
|
|
|
|
machine.BoxCarInfoModel = tBoxCarInfoModel;
|
|
|
|
|
if (tBoxCarInfoModel != null)
|
|
|
|
|
{
|
|
|
|
|
if (tBoxCarInfoModel.Connected)
|
|
|
|
|
{
|
|
|
|
|
//将数据上报云平台
|
|
|
|
|
// CloudApi.UploadTBoxCarInfo(machine.SwapOrder!, machine.BoxCarInfoModel);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}, () =>
|
|
|
|
|
{
|
|
|
|
|
// machine.LedTool?.WriteProgramContent("车辆电池数据上报异常,请联系站务人员");
|
|
|
|
|
// SoundApi.PlayOneSound(InfoEnum.SwapInfo.ErrorSelectPack);
|
|
|
|
|
}, false, () => { machine.ExceptionReason = ExceptionReason.CloudCarDataUploadError; }
|
|
|
|
|
, 20, InvokeStatus.None);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 选包:
|
|
|
|
|
/// 有预约单: 获取预约单的电池
|
|
|
|
|
/// 无预约单:
|
|
|
|
|
/// 1.仓位状态:启动
|
|
|
|
|
/// 2.电池在位
|
|
|
|
|
/// 3.充电状态:不在充电中
|
|
|
|
|
/// 4.未锁定
|
|
|
|
|
/// 5.最后一次结束充电时间> ()
|
|
|
|
|
/// 6.soc >()
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="machine"></param>
|
|
|
|
|
public InvokeStatus SelectPack(SwappingStateMachine machine)
|
|
|
|
|
{
|
|
|
|
|
SwapAmtOrder? swapAmtOrder = _CommonMgr.QueryAmtOrder(machine);
|
|
|
|
|
return Invoker.Invoke("selectPack", 1000, 10, machine.IsCanceled,
|
|
|
|
|
() => machine.SelectPackFlag, () =>
|
|
|
|
|
{
|
|
|
|
|
SwapOrderBatteryInfo orderBatteryInfo = null;
|
|
|
|
|
if (swapAmtOrder != null)
|
|
|
|
|
{
|
|
|
|
|
orderBatteryInfo = _CommonMgr.SelectPackArm(swapAmtOrder, machine);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
orderBatteryInfo = _CommonMgr.SelectPackNotArm(machine);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (orderBatteryInfo.CanSwap != InfoEnum.SelectBinStatusInfo.Success)
|
|
|
|
|
{
|
|
|
|
|
_log.Info($"SelectPack error CanSwap={machine.SwapOrderBatteryInfo.CanSwap}");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
//选包成功
|
|
|
|
|
_CommonMgr.LockBinAndUpdateAmt(orderBatteryInfo);
|
|
|
|
|
machine.SwapOrderBatteryInfo = orderBatteryInfo;
|
|
|
|
|
_CommonMgr.SaveSwapBattery(machine);
|
|
|
|
|
machine.SelectPackFlag = true;
|
|
|
|
|
}
|
|
|
|
|
}, () =>
|
|
|
|
|
{
|
|
|
|
|
machine.ExceptionReason = ExceptionReason.SelectPackError;
|
|
|
|
|
SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.ErrorSelectPack);
|
|
|
|
|
}
|
|
|
|
|
, false, () => { }, 10, InvokeStatus.None);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 两个从电机下辅源
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="machine"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public InvokeStatus AuxiliarySource(SwappingStateMachine machine)
|
|
|
|
|
{
|
|
|
|
|
bool result = false;
|
|
|
|
|
return Invoker.Invoke("selectPack", 1000, 3, machine.IsCanceled,
|
|
|
|
|
() => result, () =>
|
|
|
|
|
{
|
|
|
|
|
var result1 = ChargeApi.SendAuxiliaryPower(machine.SwapOrderBatteryInfo.UpBinInfo[0].No,2);
|
|
|
|
|
var result2 = ChargeApi.SendAuxiliaryPower(machine.SwapOrderBatteryInfo.UpBinInfo[1].No,2);
|
|
|
|
|
result1.Wait();
|
|
|
|
|
result2.Wait();
|
|
|
|
|
|
|
|
|
|
result = result1.Result & result2.Result;
|
|
|
|
|
result = true;
|
|
|
|
|
}, () =>
|
|
|
|
|
{
|
|
|
|
|
machine.ExceptionReason = ExceptionReason.AuxiliarySourceError;
|
|
|
|
|
SoundApi.PlayOneSound((int)InfoEnum.SwapInfo.AuxiliarySource);
|
|
|
|
|
}
|
|
|
|
|
, false, () => { }, 10, InvokeStatus.None
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|