diff --git a/Entity/Api/Req/OperateModelReq.cs b/Entity/Api/Req/OperateModelReq.cs new file mode 100644 index 0000000..0267ef5 --- /dev/null +++ b/Entity/Api/Req/OperateModelReq.cs @@ -0,0 +1,30 @@ +using System.ComponentModel.DataAnnotations; + +namespace Entity.Api.Req; +/// +/// +/// +public class OperateModelReq +{ + + /// + /// 操作人员名称 + /// + [Required] + public string? Operator { get; set; } + + /// + /// 操作原因 + /// + [Required] + public string? Reason { get; set; } + + + /// + /// 操作类型 : 1人工确认成功;2人工确认失败 + /// + [Required] + public int Type { get; set; } + + +} \ No newline at end of file diff --git a/Entity/DbModel/Station/ManualOperationRecord.cs b/Entity/DbModel/Station/ManualOperationRecord.cs new file mode 100644 index 0000000..5570b20 --- /dev/null +++ b/Entity/DbModel/Station/ManualOperationRecord.cs @@ -0,0 +1,43 @@ +using SqlSugar; + +namespace Entity.DbModel.Station; + +/// +/// 人工操作表 +/// +[SugarTable("manual_operation_record")] +public class ManualOperationRecord : BaseModel +{ + /// + /// Desc:id + /// Default: + /// Nullable:False + /// + [SugarColumn(IsPrimaryKey = true, ColumnName = "id")] + public int Id { get; set; } + + /// + /// 换电订单 + /// + [SugarColumn(IsPrimaryKey = true, ColumnName = "swap_order_sn")] + public string? SwapOrderSn { get; set; } + + /// + /// 原因 + /// + [SugarColumn(IsPrimaryKey = true, ColumnName = "reason")] + public string? Reason { get; set; } + + /// + /// 操作类型 : 1人工确认成功;2人工确认失败 + /// + + [SugarColumn(IsPrimaryKey = true, ColumnName = "type")] + public int Type { get; set; } + + /// + /// 操作人员 + /// + [SugarColumn(IsPrimaryKey = true, ColumnName = "operator")] + public string? Operator { get; set; } +} \ No newline at end of file diff --git a/Repository/Station/ManualOperationRecordRepository.cs b/Repository/Station/ManualOperationRecordRepository.cs new file mode 100644 index 0000000..3ecdf79 --- /dev/null +++ b/Repository/Station/ManualOperationRecordRepository.cs @@ -0,0 +1,14 @@ +using Entity.DbModel.Station; +using HybirdFrameworkCore.Autofac.Attribute; +using SqlSugar; + +namespace Repository.Station; + +[Scope("SingleInstance")] +public class ManualOperationRecordRepository:BaseRepository +{ + + public ManualOperationRecordRepository(ISqlSugarClient sqlSugar) : base(sqlSugar) + { + } +} \ No newline at end of file diff --git a/Service/Execute/Api/ChargeApi.cs b/Service/Execute/Api/ChargeApi.cs index c3276a8..49c6834 100644 --- a/Service/Execute/Api/ChargeApi.cs +++ b/Service/Execute/Api/ChargeApi.cs @@ -5,10 +5,12 @@ using Newtonsoft.Json.Linq; using Service.Execute.Model; namespace Service.Execute.Api; - +/// +/// chargeApi +/// public class ChargeApi { - private static readonly ILog Log = LogManager.GetLogger(typeof(ChargeApi)); + private static readonly ILog Log = LogManager.GetLogger("ChargeApi"); private static readonly string BASE_URL = "http://localhost:5035"; @@ -19,7 +21,7 @@ public class ChargeApi public static async Task StopCharge(string binNo) { - Log.Info("StopCharge"); + Log.Info($" ChargeApi StopCharge binNo={binNo}"); string url = BASE_URL + "/api/Charge/StopChargeByBinNo/" + binNo; try { @@ -27,6 +29,8 @@ public class ChargeApi if (!String.IsNullOrWhiteSpace(s)) { Result? succ = JsonConvert.DeserializeObject>(s); + Log.Info($" ChargeApi StopCharge binNo={binNo} resp={succ.IsSuccess}"); + if (succ.IsSuccess) { return true; @@ -39,7 +43,7 @@ public class ChargeApi } catch (Exception e) { - Console.WriteLine(e); + Log.Error($" ChargeApi StopCharge binNo={binNo} ,e={e}"); return false; } } diff --git a/Service/Execute/Api/CloudApi.cs b/Service/Execute/Api/CloudApi.cs index 02e3898..6379679 100644 --- a/Service/Execute/Api/CloudApi.cs +++ b/Service/Execute/Api/CloudApi.cs @@ -1,6 +1,7 @@ using Entity.Constant; using Entity.DbModel.Station; using log4net; +using Newtonsoft.Json; using Service.Cloud.Client; using Service.Cloud.Msg.Cloud.Req; using Service.Cloud.Msg.Cloud.Resp; @@ -14,6 +15,8 @@ public abstract class CloudApi { private const int TimeSpan = 60; + private static readonly ILog Log = LogManager.GetLogger("CloudApi"); + /// /// 云平台车辆认证 /// @@ -25,19 +28,23 @@ public abstract class CloudApi VehicleCertification vehicleCertification = new() { ty = 2, - rfid=rfidReadModel.VelVin, + rfid = rfidReadModel.VelVin, cn = rfidReadModel.VelNo, vi = rfidReadModel.VelVin, - // mac = rfidReadModel.VelMac, + // mac = rfidReadModel.VelMac, en = 0, dt = swapOrder.VehicleEnterTime, mode = 0, }; + + Log.Info( + $" CloudApi VehicleCheck SendVehicleCertification param={JsonConvert.SerializeObject(vehicleCertification)}"); VehicleCertificationResp? sendVehicleCertification = CloudClientMgr.CloudClient?.SendVehicleCertification(vehicleCertification, global::System.TimeSpan.FromSeconds(TimeSpan)); - + Log.Info( + $" CloudApi VehicleCheck SendVehicleCertification resp={JsonConvert.SerializeObject(sendVehicleCertification)}"); if (sendVehicleCertification == null) { return -1; @@ -57,8 +64,8 @@ public abstract class CloudApi { UploadSwapOrder uploadSwapOrder = new() { - rfid=swapOrder.VehicleVin, - sn=StaticStationInfo.StationNo, + rfid = swapOrder.VehicleVin, + sn = StaticStationInfo.StationNo, son = swapOrder.CloudSn, cn = swapOrder.VehicleNo, so = seq, @@ -67,7 +74,7 @@ public abstract class CloudApi dbid = swapOrderBattery.UpBatteryNo, deno = swapOrderBattery.UpBatteryBinNo, dsoc = swapOrderBattery.UpBatterySoc.ToInt(), - // dsoe = swapOrderBattery.UpBatterySoe.ToInt(), + // dsoe = swapOrderBattery.UpBatterySoe.ToInt(), et = swapOrder.SwapEndTime, od = 0, ot = swapOrder.VehicleLeaveTime, @@ -77,22 +84,26 @@ public abstract class CloudApi ubid = swapOrderBattery.DownBatteryNo, ueno = swapOrderBattery.DownBatteryBinNo, usoc = swapOrderBattery.DownBatterySoc.ToInt(), - // usoe = swapOrderBattery.DownBatterySoe.ToInt(), + // usoe = swapOrderBattery.DownBatterySoe.ToInt(), vin = swapOrder.VehicleVin, wt = new TimeSpan((swapOrder.SwapEndTime.ToDateTime().Ticks - swapOrder.SwapBeginTime.ToDateTime().Ticks)) .TotalSeconds.ToInt(), }; + Log.Info( + $" CloudApi UploadSwapOrder seq={seq} SendUploadPowerChangeOrder param={JsonConvert.SerializeObject(uploadSwapOrder)}"); + UploadSwapOrderResp? sendUploadPowerChangeOrder = CloudClientMgr.CloudClient?.SendUploadPowerChangeOrder( uploadSwapOrder, global::System.TimeSpan.FromSeconds(TimeSpan)); + Log.Info( + $" CloudApi UploadSwapOrder seq={seq} SendUploadPowerChangeOrder resp={JsonConvert.SerializeObject(sendUploadPowerChangeOrder)}"); + if (sendUploadPowerChangeOrder == null) { return -1; } return sendUploadPowerChangeOrder.re; - - } /// @@ -125,7 +136,12 @@ public abstract class CloudApi /// public static CarCanStart CarCanStart() { - return CloudClientMgr.CloudClient.CarCanStart; + Log.Info( + $" CloudApi CarCanStart "); + var cloudClientCarCanStart = CloudClientMgr.CloudClient.CarCanStart; + Log.Info( + $" CloudApi CarCanStart resp={cloudClientCarCanStart}"); + return cloudClientCarCanStart; } /// diff --git a/Service/Execute/Api/PlcApi.cs b/Service/Execute/Api/PlcApi.cs index c67c876..7817526 100644 --- a/Service/Execute/Api/PlcApi.cs +++ b/Service/Execute/Api/PlcApi.cs @@ -31,14 +31,14 @@ public class PlcApi { var isRemote = PlcMgr.IsRemote(); - Log.Info($"plc IsRemove resp={isRemote}"); + Log.Info($"PlcApi IsRemove resp={isRemote}"); return isRemote; } public static bool IsAuto() { var isAuto = PlcMgr.IsAuto(); - Log.Info($"plc IsRemove resp={isAuto}"); + Log.Info($"PlcApi IsRemove resp={isAuto}"); return isAuto; } @@ -48,8 +48,9 @@ public class PlcApi /// public static bool EntranceRadar() { - - return PlcMgr.EntranceRadar(); + var entranceRadar = PlcMgr.EntranceRadar(); + Log.Info($"PlcApi EntranceRadar resp={entranceRadar}"); + return entranceRadar; } /// @@ -58,7 +59,9 @@ public class PlcApi /// public static bool ExitRadar() { - return PlcMgr.ExitRadar(); + var exitRadar = PlcMgr.ExitRadar(); + Log.Info($"PlcApi ExitRadar resp={exitRadar}"); + return exitRadar; } /// @@ -70,7 +73,9 @@ public class PlcApi /// public static bool WriteEntranceLamp(ushort data) { - return PlcMgr.WriteEntranceLamp(data); + var writeEntranceLamp = PlcMgr.WriteEntranceLamp(data); + Log.Info($"PlcApi writeEntranceLamp resp={writeEntranceLamp}"); + return writeEntranceLamp; } /// @@ -82,7 +87,9 @@ public class PlcApi /// public static bool WriteExistLamp(ushort data) { - return PlcMgr.WriteExistLamp(data); + var writeExistLamp = PlcMgr.WriteExistLamp(data); + Log.Info($"PlcApi WriteExistLamp resp={writeExistLamp}"); + return writeExistLamp; } /// @@ -103,7 +110,12 @@ public class PlcApi /// public static bool StartSwapping(string inBinNo, string outBinNo) { - return PlcMgr.DistributeTask(ushort.Parse(inBinNo), ushort.Parse(outBinNo), 1); + + Log.Info($"PlcApi StartSwapping param= inBinNo={inBinNo}, outBinNo={outBinNo}"); + var distributeTask = PlcMgr.DistributeTask(ushort.Parse(inBinNo), ushort.Parse(outBinNo), 1); + + Log.Info($"PlcApi StartSwapping resp={distributeTask}"); + return distributeTask; } @@ -113,7 +125,10 @@ public class PlcApi /// public static bool ReadTaskStatus(ushort taskNo) { - return PlcMgr.ReadTaskStatus(taskNo); + Log.Info($"PlcApi ReadTaskStatus param= taskNo={taskNo}"); + var readTaskStatus = PlcMgr.ReadTaskStatus(taskNo); + Log.Info($"PlcApi ReadTaskStatus resp={readTaskStatus}"); + return readTaskStatus; } /// @@ -122,7 +137,10 @@ public class PlcApi /// public static bool HoldOn() { - return PlcMgr.HoldOn(); + var holdOn = PlcMgr.HoldOn(); + Log.Info($"PlcApi HoldOn resp={holdOn}"); + return holdOn; + } /// @@ -133,7 +151,7 @@ public class PlcApi { PlcMgr.ResetPlc(); var channelStatus = PlcMgr.ChannelStatus(); - Log.Info($"plc ChannelStatus = {channelStatus}"); + Log.Info($"PlcApi ChannelStatus resp= {channelStatus}"); return channelStatus; } @@ -144,6 +162,8 @@ public class PlcApi /// 6未连接 public static int ReadPlcTaskStatus() { - return PlcMgr.ReadPlcTaskStatus(); + var readPlcTaskStatus = PlcMgr.ReadPlcTaskStatus(); + Log.Info($"PlcApi ReadPlcTaskStatus resp= {readPlcTaskStatus}"); + return readPlcTaskStatus; } } \ No newline at end of file diff --git a/Service/Execute/Api/RfidApi.cs b/Service/Execute/Api/RfidApi.cs index 9ce4eff..0d460aa 100644 --- a/Service/Execute/Api/RfidApi.cs +++ b/Service/Execute/Api/RfidApi.cs @@ -6,9 +6,8 @@ namespace Service.Execute.Api; public class RfidApi { - private static readonly ILog Log = LogManager.GetLogger(typeof(RfidApi)); + private static readonly ILog Log = LogManager.GetLogger("RfidApi"); - //TODO::Rfid 服务地址 private static readonly string BASE_URL = "http://localhost:5037"; private static readonly HttpClient _httpClient = new HttpClient() @@ -23,11 +22,11 @@ public class RfidApi var connect = await Connect(); if (!connect) { - Log.Info("Rfid connect fail"); + Log.Info("RfidApi connect fail"); return false; } - Log.Info("BeginRead"); + Log.Info("RfidApi BeginRead"); string url = BASE_URL + "/Api/BeginRead"; try { @@ -44,7 +43,7 @@ public class RfidApi public static async Task StopRead() { - Log.Info("StopRead"); + Log.Info("RfidApi StopRead"); string url = BASE_URL + "/Api/StopRead"; try { @@ -63,7 +62,7 @@ public class RfidApi public static async Task DisConnect() { - Log.Info("DisConnect"); + Log.Info("RfidApi DisConnect"); string url = BASE_URL + "/Api/Close"; try { @@ -82,7 +81,7 @@ public class RfidApi { var disConnect = await DisConnect(); - Log.Info("Connect"); + Log.Info("RfidApi Connect"); string url = BASE_URL + "/Api/Open"; try { @@ -101,7 +100,7 @@ public class RfidApi { - Log.Info("ReadRifd"); + Log.Info("RfidApi ReadRifd"); string readUrl = BASE_URL + "/Api/BeginRead"; string url = BASE_URL + "/Api/ReadRfidData"; try diff --git a/Service/Execute/Api/TboxApi.cs b/Service/Execute/Api/TboxApi.cs index 9fa0cc5..41e4a89 100644 --- a/Service/Execute/Api/TboxApi.cs +++ b/Service/Execute/Api/TboxApi.cs @@ -7,7 +7,7 @@ namespace Service.Execute.Api; public class TBoxApi { - private static readonly ILog Log = LogManager.GetLogger(typeof(TBoxApi)); + private static readonly ILog Log = LogManager.GetLogger("TBoxApi"); private static readonly string BASE_URL = "http://localhost:5036"; @@ -21,7 +21,7 @@ public class TBoxApi public static async Task GetCarInfo(string carNo) { - Log.Info("GetCarInfo"); + Log.Info(" TBoxApi GetCarInfo"); string url = BASE_URL + "/getCarInfo/" + carNo; try { @@ -32,30 +32,30 @@ public class TBoxApi tboxCarInfoModel = JsonConvert.DeserializeObject(s); } - Log.Info($"GetCarInfo resp = {tboxCarInfoModel}"); + Log.Info($"TBoxApi GetCarInfo resp = {tboxCarInfoModel}"); return tboxCarInfoModel; } catch (Exception e) { - Log.Error($"GetCarInfo e = {e}"); + Log.Error($" TBoxApi GetCarInfo e = {e}"); return null; } } public static async Task Reset(string carNo) { - Log.Info("Reset"); + Log.Info(" TBoxApi Reset"); string url = BASE_URL + "/Clear/" + carNo; try { string s = await _httpClient.GetStringAsync(url); - Log.Info($"Clear Tbox resp = {s}"); + Log.Info($"TBoxApi Reset resp = {s}"); return bool.Parse(s); } catch (Exception e) { - Log.Error($"Reset e = {e}"); + Log.Error($"TBoxApi Reset e = {e}"); return false; } } @@ -86,6 +86,8 @@ public class TBoxApi public static async Task UnLockCarManyTimes(string carNo) { + Log.Info($" TBoxApi start UnLockCarManyTimes carNo={carNo} "); + List bools = new List(); for (int i = 0; i < _times; i++) { @@ -96,12 +98,14 @@ public class TBoxApi bools.Add(unLockCar); } } - + Log.Info($" TBoxApi end UnLockCarManyTimes carNo={carNo} time={_times} resp={JsonConvert.SerializeObject(bools)}"); + return bools.Select(i => i).Count() > _successTimes; } public static async Task LockCarManyTimes(string carNo) { + Log.Info($" TBoxApi start LockCarManyTimes carNo={carNo} "); List bools = new List(); for (int i = 0; i < _times; i++) { @@ -112,6 +116,7 @@ public class TBoxApi bools.Add(unLockCar); } } + Log.Info($" TBoxApi end LockCarManyTimes carNo={carNo} time={_times} resp={JsonConvert.SerializeObject(bools)}"); return bools.Select(i => i).Count() > _successTimes; } @@ -141,7 +146,7 @@ public class TBoxApi public static async Task> GetCarInfoList() { - Log.Info("GetCarInfoList"); + Log.Info(" TBoxApi GetCarInfoList start"); string url = BASE_URL + "/getCarInfoList" ; try { @@ -152,12 +157,12 @@ public class TBoxApi tboxCarInfoModels = JsonConvert.DeserializeObject>(s); } - Log.Info($"GetCarInfoList resp = {tboxCarInfoModels}"); + Log.Info($"TBoxApi GetCarInfoList resp = {tboxCarInfoModels}"); return tboxCarInfoModels; } catch (Exception e) { - Log.Error($"GetCarInfoList e = {e}"); + Log.Error($"TBoxApi GetCarInfoList e = {e}"); return null; } } diff --git a/Service/Execute/Invoker.cs b/Service/Execute/Invoker.cs index 7aefe68..7a0bd0f 100644 --- a/Service/Execute/Invoker.cs +++ b/Service/Execute/Invoker.cs @@ -119,6 +119,61 @@ public class Invoker Log.Info($" {name} done"); return InvokeStatus.Done; } + + + public static InvokeStatus Invoke(string name, int duration, int times, Func cancel,Func succ, Func done, + Action doAction, + Action timeoutAction, bool isTimeOutExit, Action exceptionAction, int timeOutActionTime, + InvokeStatus timeOutException) + { + int count = 0; + while (!done()) + { + Log.Info($"begin {name}"); + Thread.Sleep(duration); + if (cancel()) + { + Log.Info($" {name} canceled"); + return InvokeStatus.Cancel; + } + if (succ()) + { + Log.Info($" {name} ManualSucc"); + return InvokeStatus.ManualSucc; + } + + try + { + doAction(); + } + catch (Exception e) + { + Log.Error($"{name}", e); + exceptionAction(); + } + + if (count++ > times) + { + if (count % timeOutActionTime == 0) + { + timeoutAction(); + Log.Info($" {name} timeout"); + if (isTimeOutExit) + { + return timeOutException; + } + } + } + } + + Log.Info($" {name} done"); + return InvokeStatus.Done; + } + + + + + public static InvokeStatus Invoke(string name, int duration, int times, Func done, @@ -230,5 +285,6 @@ public enum InvokeStatus TimeOut, Done, Exception, - None + None, + ManualSucc, } \ No newline at end of file diff --git a/Service/Execute/Model/OperateModel.cs b/Service/Execute/Model/OperateModel.cs new file mode 100644 index 0000000..6d2307b --- /dev/null +++ b/Service/Execute/Model/OperateModel.cs @@ -0,0 +1,25 @@ +namespace Service.Execute.Model; +/// +/// +/// +public class OperateModel +{ + + /// + /// 操作人员名称 + /// + public string? Operator { get; set; } + + /// + /// 操作原因 + /// + public string? Reason { get; set; } + + + /// + /// 操作类型 : 1人工确认成功;2人工确认失败 + /// + public int Type { get; set; } + + +} \ No newline at end of file diff --git a/Service/Execute/StationSoftMgr.cs b/Service/Execute/StationSoftMgr.cs index 630568b..4731f36 100644 --- a/Service/Execute/StationSoftMgr.cs +++ b/Service/Execute/StationSoftMgr.cs @@ -26,6 +26,13 @@ namespace Service.Execute { SwappingStateMachine.Cancel(); } + /// + /// 换电流程收栋操作 + /// + public static void SwappingStateMachineManual() + { + SwappingStateMachine.Manual(); + } #endregion 换电流程启动 } diff --git a/Service/Execute/Step/CancelState.cs b/Service/Execute/Step/CancelState.cs index 089e6c4..04b389e 100644 --- a/Service/Execute/Step/CancelState.cs +++ b/Service/Execute/Step/CancelState.cs @@ -1,18 +1,26 @@ using Autofac; using Entity.Constant; +using Entity.DbModel.Station; using HybirdFrameworkCore.Autofac; using log4net; using Repository.Station; +using Service.Mgr; namespace Service.Execute.Step; public class CancelState : IState { - private readonly SwapOrderRepository _swapOrderRepository= AppInfo.Container.Resolve(); + private readonly SwapOrderRepository _swapOrderRepository = AppInfo.Container.Resolve(); + + private readonly SwapAmtOrderRepository _swapAmtOrderRepository = + AppInfo.Container.Resolve(); - private readonly SwapAmtOrderRepository _swapAmtOrderRepository = AppInfo.Container.Resolve(); private static readonly ILog _log = LogManager.GetLogger(typeof(CancelState)); + + private static readonly ManualOperationRecordRepository _manualOperationRecordRepository = + AppInfo.Container.Resolve(); + public StateResult Handle(SwappingStateMachine machine) { _log.Info($"'goto cancel"); @@ -29,6 +37,16 @@ public class CancelState : IState _swapOrderRepository.Update(machine.SwapOrder); } + _manualOperationRecordRepository.Insert(new ManualOperationRecord() + { + Type = 2, + CreatedBy = UserManager.Account, + UpdatedBy = UserManager.Account, + Operator = machine.OperateModel.Operator, + Reason = machine.OperateModel.Reason, + }); + + machine.Reset(); return new StateResult() { diff --git a/Service/Execute/Step/DoSwappingState.cs b/Service/Execute/Step/DoSwappingState.cs index dbe18d0..ff807cb 100644 --- a/Service/Execute/Step/DoSwappingState.cs +++ b/Service/Execute/Step/DoSwappingState.cs @@ -342,6 +342,13 @@ public class DoSwappingState : IState int count = 0; while (!machine.ChannelStatusOkFlag) { + + if (machine.CancelFlag) + { + _log.Info($" CheckChannelStatus canceled"); + return StateResult.Cancel; + } + _log.Info("begin plc CheckChannelStatus"); Thread.Sleep(2000); var channelStatus = PlcApi.ChannelStatus(); diff --git a/Service/Execute/Step/ManualSuccState.cs b/Service/Execute/Step/ManualSuccState.cs new file mode 100644 index 0000000..6fac46c --- /dev/null +++ b/Service/Execute/Step/ManualSuccState.cs @@ -0,0 +1,55 @@ +using Autofac; +using Entity.Constant; +using Entity.DbModel.Station; +using HybirdFrameworkCore.Autofac; +using log4net; +using Repository.Station; +using Service.Mgr; + +namespace Service.Execute.Step; + +/// +/// 手动确认成功状态 +/// +public class ManualSuccState : IState +{ + private readonly SwapOrderRepository _swapOrderRepository = AppInfo.Container.Resolve(); + + private readonly SwapAmtOrderRepository _swapAmtOrderRepository = + AppInfo.Container.Resolve(); + + private static readonly ILog _log = LogManager.GetLogger(typeof(CancelState)); + private static readonly ManualOperationRecordRepository _manualOperationRecordRepository = + AppInfo.Container.Resolve(); + public StateResult Handle(SwappingStateMachine machine) + { + _log.Info($"'goto ManualSucc"); + machine.ManualSwapSuccFlag = false; + if (machine.SwapOrderBatteryInfo.swapAmtOrder != null) + { + machine.SwapOrderBatteryInfo.swapAmtOrder.Status = (byte)InfoEnum.AmtOrderStatus.SwapFinish; + _swapAmtOrderRepository.Update(machine.SwapOrderBatteryInfo.swapAmtOrder); + } + + if (machine.SwapOrder != null) + { + machine.SwapOrder.SwapResult = (byte)InfoEnum.SwapOrderResult.Success; + machine.SwapOrder.VehicleLeaveTime = DateTime.Now; + _swapOrderRepository.Update(machine.SwapOrder); + } + + _manualOperationRecordRepository.Insert(new ManualOperationRecord() + { + Type = 2, + CreatedBy = UserManager.Account, + UpdatedBy = UserManager.Account, + Operator = machine.OperateModel.Operator, + Reason = machine.OperateModel.Reason, + }); + machine.Reset(); + return new StateResult() + { + SwappingState = SwappingState.StationReady + }; + } +} \ No newline at end of file diff --git a/Service/Execute/Step/SwapDoneState.cs b/Service/Execute/Step/SwapDoneState.cs index 9269943..b5afa14 100644 --- a/Service/Execute/Step/SwapDoneState.cs +++ b/Service/Execute/Step/SwapDoneState.cs @@ -33,6 +33,24 @@ public class SwapDoneState : IState _CommonMgr.UpdateSwapOrder(machine); + //修改预约单 + if (machine.SwapOrderBatteryInfo!.swapAmtOrder != null) + { + machine.SwapOrderBatteryInfo.swapAmtOrder.Status = + machine.SwapStatus == (int)InfoEnum.SwapOrderResult.Success + ? (int)InfoEnum.AmtOrderStatus.SwapFinish + : (int)InfoEnum.AmtOrderStatus.SwapFail; + _CommonMgr.UpdateAmtOrder(machine); + } + + //新增换电成功上报云平台数据 + _CommonMgr.InsertCloudReportForSwapSuccess(machine); + //换电成功关于bininfo表的更新 + _CommonMgr.UpdateBinInfoForSwapSuccess(machine); + + //可人工确认换电成功标识 + machine.PlcSwapFlag = true; + if (machine.SwapStatus == (int)InfoEnum.SwapOrderResult.Success) { //上传云平台换电状态 @@ -56,10 +74,6 @@ public class SwapDoneState : IState return SwappingStateMachine.ReturnWithInvokeErr(existRadar, ExceptionReason.None); } - //新增换电成功上报云平台数据 - _CommonMgr.InsertCloudReportForSwapSuccess(machine); - //换电成功关于bininfo表的更新 - _CommonMgr.UpdateBinInfoForSwapSuccess(machine); return new StateResult() { @@ -73,10 +87,11 @@ public class SwapDoneState : IState /// public InvokeStatus LockCar(SwappingStateMachine machine) { - return Invoker.Invoke("LockCar", 500, 100, machine.IsCanceled, + return Invoker.Invoke("LockCar", 500, 100, machine.IsCanceled,machine.IsManualSwapSucc, () => machine.VelLockFlag, () => { Task result = TBoxApi.LockCarManyTimes(machine.RfidReadModel.VelVin); + bool unLock = result.Result; if (unLock) { @@ -113,13 +128,12 @@ public class SwapDoneState : IState public InvokeStatus ExistRadar(SwappingStateMachine machine) { - return Invoker.Invoke("wait exist radar", 1000, 5, machine.IsCanceled, + return Invoker.Invoke("wait exist radar", 1000, 5, machine.IsCanceled,machine.IsManualSwapSucc, () => machine.RadarOutFlag, () => { if (PlcApi.ExitRadar()) { _log.Info("exist radar false"); - } else { @@ -135,14 +149,6 @@ public class SwapDoneState : IState InfoEnum.BusinessSwappingForCloudState.SwapDoneWithoutVel; machine.SwapOrder!.VehicleLeaveTime = DateTime.Now; _CommonMgr.UpdateSwapOrder(machine); - if (machine.SwapOrderBatteryInfo!.swapAmtOrder != null) - { - machine.SwapOrderBatteryInfo.swapAmtOrder.Status = - machine.SwapStatus == (int)InfoEnum.SwapOrderResult.Success - ? (int)InfoEnum.AmtOrderStatus.SwapFinish - : (int)InfoEnum.AmtOrderStatus.SwapFail; - _CommonMgr.UpdateAmtOrder(machine); - } machine.RadarOutFlag = true; @@ -158,6 +164,6 @@ public class SwapDoneState : IState SoundTool.PlayOneSound(machine.SwapStatus == (int)InfoEnum.SwapOrderResult.Success ? (int)InfoEnum.SwapInfo.InfoCarLeave : (int)InfoEnum.SwapInfo.ErrInfoCarLeave); - }, false,() => { },10,InvokeStatus.None); + }, false, () => { }, 10, InvokeStatus.None); } } \ No newline at end of file diff --git a/Service/Execute/SwappingStateMachine.cs b/Service/Execute/SwappingStateMachine.cs index 8514feb..624a088 100644 --- a/Service/Execute/SwappingStateMachine.cs +++ b/Service/Execute/SwappingStateMachine.cs @@ -27,6 +27,14 @@ public class SwappingStateMachine : IDisposable 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 OperateModel OperateModel = null; + public readonly LedTool? LedTool = null; private readonly Thread _executeThread; private readonly Dictionary _dictionary = new Dictionary(); @@ -148,6 +156,7 @@ public class SwappingStateMachine : IDisposable _dictionary[SwappingState.SwapDone] = new SwapDoneState(); _dictionary[SwappingState.Exception] = new ExceptionState(); _dictionary[SwappingState.Canceled] = new CancelState(); + _dictionary[SwappingState.ManualSucc] = new CancelState(); LedTool = new LedTool(); @@ -171,6 +180,10 @@ public class SwappingStateMachine : IDisposable { return null; } + else if (status == InvokeStatus.ManualSucc) + { + return new StateResult() { SwappingState = SwappingState.ManualSucc }; + } else { return StateResult.Exception(exceptionReason, null); @@ -214,6 +227,11 @@ public class SwappingStateMachine : IDisposable { return CancelFlag; } + + public bool IsManualSwapSucc() + { + return ManualSwapSuccFlag; + } public bool Start() { @@ -239,7 +257,7 @@ public class SwappingStateMachine : IDisposable ResetData(); //重置云平台下发的指令 - // CloudApi.ClearCarCanStartInfo(); + // CloudApi.ClearCarCanStartInfo(); } public bool Cancel() @@ -250,6 +268,14 @@ public class SwappingStateMachine : IDisposable return true; } + public bool Manual() + { + ManualSwapSuccFlag = true; + Thread.Sleep(5000); + Log.Info($"ManualSwapSuccFlag machine ok"); + return true; + } + private void ResetData() { @@ -269,6 +295,13 @@ public class SwappingStateMachine : IDisposable SwapOrderBatteryInfo = null; StepSort = 0; StepModel = new List(); + + PlcSwapFlag = false; + ManualSwapSuccFlag = false; + OperateModel = null; + + CancelFlag = false; + StopFlag = false; } private void ResetStep() @@ -394,5 +427,6 @@ public enum SwappingState DoSwapping, SwapDone, Exception, - Canceled + Canceled, + ManualSucc, } \ No newline at end of file diff --git a/Service/Mgr/SwapOrderMgr.cs b/Service/Mgr/SwapOrderMgr.cs index c8b19ef..3d2a4bc 100644 --- a/Service/Mgr/SwapOrderMgr.cs +++ b/Service/Mgr/SwapOrderMgr.cs @@ -14,9 +14,8 @@ public class SwapOrderMgr public SwapOrderBatteryRepository _swapOrderBatteryRepository { get; set; } - public BinInfoRepository _BinInfoRepository { get; set; } - public bool UploadCloud(List list) + public bool UploadCloud(List list ,int uploadType) { if (list.Count <= 0) { @@ -35,7 +34,8 @@ public class SwapOrderMgr List swapOrderSn = swapOrders.Select(i => i.Sn).ToList(); List batterys = - _swapOrderBatteryRepository.QueryListByClause(i => swapOrderSn.Contains(i.SwapOrderSn)); + _swapOrderBatteryRepository.QueryListByClause(i => + swapOrderSn.Contains(i.SwapOrderSn) && i.DownBatteryNo != null); if (batterys.Count <= 0) { @@ -44,15 +44,10 @@ public class SwapOrderMgr IDictionary dictionary = batterys.ToDictionary(i => i.SwapOrderSn); - List downBatteryBinNos = batterys.Select(i => i.DownBatteryBinNo.ToString()).ToList(); - Dictionary binInfosMap = _BinInfoRepository - .QueryListByClause(i => downBatteryBinNos.Contains(i.No)).ToDictionary(i => i.No); - Dictionary swapOrderReportClouds = list.ToDictionary(i => i.SwapOrderId); - List updateDbBattery = new List(); List updateDbOrder = new List(); List updateDbCloudReport = new List(); @@ -66,22 +61,12 @@ public class SwapOrderMgr if (null == swapOrderBattery.DownBatteryNo) { - //更新换下电池包 - binInfosMap.TryGetValue(swapOrderBattery.DownBatteryBinNo.ToString(), out BinInfo info); - if (info.BatteryNo == null || info.BatteryNo == "" || info.BatteryNo=="-1") - { - continue; - } - - swapOrderBattery.DownBatteryNo = info.BatteryNo; - swapOrderBattery.DownBatterySoc = info.Soc; - swapOrderBattery.DownBatterySoe = info.Soe; - updateDbBattery.Add(swapOrderBattery); + continue; } var count = _swapOrderRepository.GetCount(i => i.SwapResult == 1 && i.SwapEndTime >= DateTime.Today && i.SwapEndTime < swapOrder.SwapEndTime); - var uploadSwapOrder = CloudApi.UploadSwapOrder(swapOrder, count++, swapOrderBattery, 1); + var uploadSwapOrder = CloudApi.UploadSwapOrder(swapOrder, count++, swapOrderBattery, uploadType); if (uploadSwapOrder == 0) { swapOrder.CloudReportStatus = 1; @@ -92,11 +77,6 @@ public class SwapOrderMgr } } - if (updateDbBattery.Count > 0) - { - _swapOrderBatteryRepository.Update(updateDbBattery); - } - if (updateDbOrder.Count > 0) { _swapOrderRepository.Update(updateDbOrder); diff --git a/Service/MyTask/SwapOrderReportCloudTask.cs b/Service/MyTask/SwapOrderReportCloudTask.cs index a58f477..6d3b6a2 100644 --- a/Service/MyTask/SwapOrderReportCloudTask.cs +++ b/Service/MyTask/SwapOrderReportCloudTask.cs @@ -36,7 +36,7 @@ public class SwapOrderReportCloudTask : ITask { List list = ReportCloudRepository.QueryListByClause(i => i.CloudReportStatus == 0); - SwapOrderMgr.UploadCloud(list); + SwapOrderMgr.UploadCloud(list,1); } catch (Exception e) { diff --git a/Service/MyTask/UpdateDownBatteryInfoTask.cs b/Service/MyTask/UpdateDownBatteryInfoTask.cs new file mode 100644 index 0000000..0e33167 --- /dev/null +++ b/Service/MyTask/UpdateDownBatteryInfoTask.cs @@ -0,0 +1,98 @@ +using Entity.DbModel.Station; +using HybirdFrameworkCore.Autofac.Attribute; +using HybirdFrameworkCore.AutoTask; +using log4net; +using Newtonsoft.Json; +using Repository.Station; +using Service.Mgr; + +namespace Service.MyTask; + +/// +/// 充电结束上报云平台task +/// +[Scope] +public class UpdateDownBatteryInfoTask : ITask +{ + private static readonly ILog Log = LogManager.GetLogger(typeof(UpdateDownBatteryInfoTask)); + + private volatile bool _stop; + + + public SwapOrderBatteryRepository _swapOrderBatteryRepository { get; set; } + + public BinInfoRepository _BinInfoRepository { get; set; } + + public string Name() + { + return "UpdateDownBatteryInfoTask"; + } + + public int Interval() + { + return 1000 * 2; + } + + public void Handle() + { + try + { + List batterys = + _swapOrderBatteryRepository.QueryListByClause( + i => i.DownBatteryNo == null && i.DownBatteryBinNo != null); + + + if (batterys.Count <= 0) + { + return; + } + + List downBatteryBinNos = batterys.Select(i => i.DownBatteryBinNo.ToString()).ToList(); + Dictionary binInfosMap = _BinInfoRepository + .QueryListByClause(i => downBatteryBinNos.Contains(i.No)).ToDictionary(i => i.No); + + List updateDbBattery = new List(); + + foreach (var battery in batterys) + { + //更新换下电池包 + binInfosMap.TryGetValue(battery.DownBatteryBinNo.ToString(), out BinInfo info); + if (info.BatteryNo == null || info.BatteryNo == "" || info.BatteryNo == "-1") + { + continue; + } + + battery.DownBatteryNo = info.BatteryNo; + battery.DownBatterySoc = info.Soc; + battery.DownBatterySoe = info.Soe; + updateDbBattery.Add(battery); + } + + if (updateDbBattery.Count > 0) + { + Log.Info( + $" UpdateDownBatteryInfoTask update DowmBatteryInfo db={JsonConvert.SerializeObject(updateDbBattery)}"); + _swapOrderBatteryRepository.Update(updateDbBattery); + } + } + catch (Exception e) + { + Log.Error($" UpdateDownBatteryInfoTask err e={e}"); + } + } + + public bool Stoped() + { + return _stop; + } + + public void Stop() + { + _stop = true; + } + + public void ResetStop() + { + _stop = false; + } +} \ No newline at end of file diff --git a/Service/Station/SwapOrderService.cs b/Service/Station/SwapOrderService.cs index 068dd4c..203e612 100644 --- a/Service/Station/SwapOrderService.cs +++ b/Service/Station/SwapOrderService.cs @@ -38,7 +38,7 @@ public class SwapOrderService : BaseServices } - return SwapOrderMgr.UploadCloud(list) ? Result.Success() : Result.Fail(); + return SwapOrderMgr.UploadCloud(list,2) ? Result.Success() : Result.Fail(); } diff --git a/WebStarter/Controllers/SwapMonitorController.cs b/WebStarter/Controllers/SwapMonitorController.cs index e34e1cc..e515852 100644 --- a/WebStarter/Controllers/SwapMonitorController.cs +++ b/WebStarter/Controllers/SwapMonitorController.cs @@ -1,3 +1,4 @@ +using Entity.Api.Req; using Entity.Api.Resp; using Entity.Constant; using HybirdFrameworkCore.Attribute; @@ -66,7 +67,7 @@ public class SwapMonitorController : ControllerBase /// /// [HttpPost("LockCar")] - public async Task> LockCar( string carNo) + public async Task> LockCar(string carNo) { var success = await TBoxApi.LockCarManyTimes(carNo); return success ? Result.Success() : Result.Fail(); @@ -77,7 +78,7 @@ public class SwapMonitorController : ControllerBase /// /// [HttpPost("UnLockCar")] - public async Task> UnLockCar( string carNo) + public async Task> UnLockCar(string carNo) { var success = await TBoxApi.UnLockCarManyTimes(carNo); return success ? Result.Success() : Result.Fail(); @@ -115,6 +116,48 @@ public class SwapMonitorController : ControllerBase return Result.Success(); } + /// + /// 人工操作换电成功标识 + /// + /// + [HttpGet("SwapPlcSucc")] + public Result SwapPlcSucc() + { + return Result.Success(StationSoftMgr.SwappingStateMachine.PlcSwapFlag); + } + + + /// + /// 人工操作换电成功还是失败 + /// + /// + [HttpPost("ManualOperateSwap")] + public Result ManualOperateSwap([FromBody] OperateModelReq req) + { + StationSoftMgr.SwappingStateMachine.OperateModel = new OperateModel() + { + Type = req.Type, + Operator = req.Operator, + Reason = req.Reason + }; + if (req.Type == 1) + { + if (!StationSoftMgr.SwappingStateMachine.PlcSwapFlag) + { + return Result.Fail("不满足确认换电成功条件"); + } + + StationSoftMgr.SwappingStateMachineManual(); + } + else + { + StationSoftMgr.SwappingStateMachineCancel(); + } + + + return Result.Success(); + } + /// /// 红绿灯操控 /// 0:无颜色 @@ -234,5 +277,4 @@ public class SwapMonitorController : ControllerBase return Result>.Success(carInfoList); } - } \ No newline at end of file diff --git a/WebStarter/bin/Debug/net6.0/log4net.config b/WebStarter/bin/Debug/net6.0/log4net.config index 19ac038..db063ab 100644 --- a/WebStarter/bin/Debug/net6.0/log4net.config +++ b/WebStarter/bin/Debug/net6.0/log4net.config @@ -49,6 +49,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WebStarter/log4net.config b/WebStarter/log4net.config index 19ac038..db063ab 100644 --- a/WebStarter/log4net.config +++ b/WebStarter/log4net.config @@ -49,6 +49,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +