using System.Collections.Concurrent; using System.ComponentModel; using Autofac; using AutoMapper; using Common.Util; using Entity.Api.Resp; using Entity.Constant; using Entity.DbModel.Station; using Entity.Dto; using Entity.Dto.Req; using HybirdFrameworkCore.Autofac; using HybirdFrameworkCore.Autofac.Attribute; using HybirdFrameworkCore.Entity; using log4net; using Newtonsoft.Json; using OfficeOpenXml.FormulaParsing.Excel.Functions.Math; using Repository.Station; using Service.Charger.Client; using Service.Charger.Msg.Host.Req; using Service.Charger.Server; using Service.Execute; using Service.Execute.Api; using Service.Execute.Model; using Service.Execute.Utils; using Service.Init; using Service.Mgr; using Service.Padar.Client; using SqlSugar; namespace Service.Station; [Scope("SingleInstance")] public class MonitorService { private static readonly ILog Log = LogManager.GetLogger(typeof(MonitorService)); public BinInfoRepository BinInfoRepository { get; set; } public SwapOrderRepository SwapOrderRepository { get; set; } public ChargeOrderRepository ChargeOrderRepository { get; set; } public PlcTaskMgr PlcTaskMgr { get; set; } public MoveBinRecordRepository MoveBinRecordRepository { get; set; } public SwapOrderBatteryRepository _SwapOrderBatteryRepository { get; set; } public CommonMgr _CommonMgr { get; set; } //可选仓位 public List> CanSelectPackBin() { //出仓位 SelectPackDto selectPackDtoUpBin = BinInfoRepository.SelectPack(StaticStationInfo.SwapSoc, StaticStationInfo.SwapFinishChargeTime, ""); //入仓位 SelectPackDto selectPackInBin = BinInfoRepository.SelectPackInBin(); return new List>() { selectPackDtoUpBin.CanSwapBinInfo, selectPackInBin.CanSwapBinInfo }; } //手动选包 public Result SelectPackManual(int upBinId, int inBinId) { var upBin = BinInfoRepository.QueryById(upBinId); var inBin = BinInfoRepository.QueryById(inBinId); if (StationSoftMgr.SwappingStateMachine?.SwapOrderBatteryInfo == null) { StationSoftMgr.SwappingStateMachine!.SwapOrderBatteryInfo = new SwapOrderBatteryInfo(); } StationSoftMgr.SwappingStateMachine!.SwapOrderBatteryInfo.InBinInfo = inBin; StationSoftMgr.SwappingStateMachine!.SwapOrderBatteryInfo.UpBinInfo = upBin; return Result.Success(); } [DisplayName("获取移仓分页")] public async Task> Page(PageMoveBinRecordReq input) { RefAsync total = 0; var items = await MoveBinRecordRepository.QueryPageAsync( entity => true, !string.IsNullOrWhiteSpace(input.UpBatterySoc), u => u.UpBatterySoc.Equals(input.UpBatterySoc.Trim()), !string.IsNullOrWhiteSpace(input.UpBinNo), u => u.UpBinNo.Equals(input.UpBinNo.Trim()), !string.IsNullOrWhiteSpace(input.UpBatteryNo), u => u.UpBatteryNo.Equals(input.UpBatteryNo.Trim()), u => u.CreatedTime, OrderByType.Desc, input.PageNum, input.PageSize, total); return new PageResult() { PageNum = input.PageNum, PageSize = input.PageSize, ToTal = total, Rows = items, }; } public async Task Add(AddMoveBinRecordReq input) { string result = ""; MoveBinRecord moveBinRecord = await MoveBinRecordRepository.InsertAsync(input); return "新增id:" + moveBinRecord.Id; } public virtual async Task Update(UpdateMoveBinRecordReq Req) { return await MoveBinRecordRepository.UpdateAsync(Req); } public virtual async Task Delete(DeleteMoveBinRecordReq input) { var user = await MoveBinRecordRepository.QueryByClauseAsync(u => u.Id == input.Id); if (user == null) throw new ArgumentException($"不存在"); return await MoveBinRecordRepository.DeleteAsync(user); } public Result GetSwapMonitorData() { var configBinInfo = new MapperConfiguration(cfg => cfg.CreateMap().ReverseMap()); IMapper mapperBinInfo = configBinInfo.CreateMapper(); List stateInfoList = new List(); ConcurrentDictionary dictionary = StationSoftMgr.SwappingStateMachine.StepModel; stateInfoList = dictionary.Values .OrderBy(model => model.StepNo) .Select(model => mapperBinInfo.Map(model)) .ToList(); var tboxCarInfoModel = StationSoftMgr.SwappingStateMachine.BoxCarInfoModel; List binInfos = BinInfoRepository.QueryListByClause(i => i.Exists == 1 && i.Status == 1); var plcSwapModel = new PlcSwapModelResp(); if (ClientMgr.PlcClient != null) { plcSwapModel.ModelState = ClientMgr.PlcClient.Auto ? 1010 : 1000; plcSwapModel.ControlModel = ClientMgr.PlcClient.Remote ? 1010 : 1000; } SwapMonitorScreenResp monitorScreenResp = new SwapMonitorScreenResp(); monitorScreenResp.PlcSwapModel = plcSwapModel; monitorScreenResp.StateInfo = stateInfoList; monitorScreenResp.VehicleInfo = new SwapVehicleResp(); monitorScreenResp.VehicleInfo.OrderNo = StationSoftMgr.SwappingStateMachine.SwapOrder != null ? StationSoftMgr.SwappingStateMachine.SwapOrder.Sn : null; monitorScreenResp.VehicleInfo.VelMac = StationSoftMgr.SwappingStateMachine.RfidReadModel != null ? StationSoftMgr.SwappingStateMachine.RfidReadModel.VelMac : null; monitorScreenResp.VehicleInfo.LockStatus = tboxCarInfoModel != null ? tboxCarInfoModel.CarStatus?.LockStatus : null; monitorScreenResp.VehicleInfo.KeyStatus = tboxCarInfoModel != null ? tboxCarInfoModel.CarStatus?.Keys : null; monitorScreenResp.VehicleInfo.VelNo = StationSoftMgr.SwappingStateMachine.RfidReadModel != null ? StationSoftMgr.SwappingStateMachine.RfidReadModel.VelNo : null; monitorScreenResp.VehicleInfo.VelVin = StationSoftMgr.SwappingStateMachine.RfidReadModel != null ? StationSoftMgr.SwappingStateMachine.RfidReadModel.VelVin : null; monitorScreenResp.VehicleInfo.Break = StationSoftMgr.SwappingStateMachine.BoxCarInfoModel?.CarStatus?.Break; monitorScreenResp.VehicleInfo.Gear = StationSoftMgr.SwappingStateMachine.BoxCarInfoModel?.CarStatus?.Gear; monitorScreenResp.BatteryInfo = new(); monitorScreenResp.BatteryInfo.BatteryTotalCount = binInfos.Count; monitorScreenResp.BatteryInfo.UsingSwapBatteryCount = binInfos.Select(i => i.ChargeStatus == 2 && i.AmtLock == (int)InfoEnum.AmtBatLockStatus.UnLock && i.Soc > StaticStationInfo.SwapSoc && new TimeSpan(DateTime.Now.Ticks - i.LastChargeFinishTime.ToDateTime().Ticks) .TotalMinutes > StaticStationInfo.SwapFinishChargeTime).Count(); if (monitorScreenResp.VehicleInfo.OrderNo != null) { SwapOrderBattery queryByClauseAsync = _SwapOrderBatteryRepository.QueryByClause(u => u.SwapOrderSn == monitorScreenResp.VehicleInfo.OrderNo); if (queryByClauseAsync != null) { monitorScreenResp.VehicleInfo.DownBatteryBinNo = queryByClauseAsync.DownBatteryBinNo; monitorScreenResp.VehicleInfo.UpBatteryBinNo = queryByClauseAsync.UpBatteryBinNo; } SwapOrder swapOrder = SwapOrderRepository.QueryByClause(u => u.Sn == monitorScreenResp.VehicleInfo.OrderNo); if (swapOrder != null && swapOrder.SwapBeginTime.HasValue && swapOrder.SwapEndTime.HasValue) { TimeSpan duration = swapOrder.SwapEndTime.Value - swapOrder.SwapBeginTime.Value; monitorScreenResp.VehicleInfo.SwapDuration = duration.ToString(@"hh\:mm\:ss"); } else if (swapOrder != null && swapOrder.SwapBeginTime.HasValue) { TimeSpan duration = DateTime.Now - swapOrder.SwapBeginTime.Value; monitorScreenResp.VehicleInfo.SwapDuration = duration.ToString(@"hh\:mm\:ss"); } } monitorScreenResp.DeviceLogs = StationSoftMgr.DeviceLogs; monitorScreenResp.RadarResp = new() { CarStatus = PadarMgr._PadarClient?.CarState }; return Result.Success(monitorScreenResp); } /// /// 模式類 /// /// public Result GetModel() { SwapModelResp resp = new() { StationStatus = StaticStationInfo.StationStatus, StationWay = StaticStationInfo.StationWay, StationModel = StaticStationInfo.StationModel }; return Result.Success(resp); } /// /// 连接状态类 /// /// public Result GetDeviceState() { bool isConnected = StationSoftMgr.SwappingStateMachine.BoxCarInfoModel == null ? false : StationSoftMgr.SwappingStateMachine.BoxCarInfoModel.Connected; DeviceStateResp resp = new() { BoxConnectFlag = isConnected, // CloudConnectFlag = CloudClientMgr.CloudClient == null ? false : CloudClientMgr.CloudClient.Connected, PlcConnectFlag = ClientMgr.PlcClient != null && ClientMgr.PlcClient!.Connected, RfidConnectFlag = StationSoftMgr.SwappingStateMachine!.RfidConnectFlag, RadarConnectFlag = PadarMgr._PadarClient != null && PadarMgr._PadarClient!.Connected }; return Result.Success(resp); } //TODO:: 首页--当月,当日换电量 public Result SwapAndChargingCount() { SwapAndChargingCountResp chargingCountResp = new() { ChargeTodayCount = ChargeOrderRepository.GetCount(i => DateTime.Today <= i.EndTime && i.EndTime <= DateUtils.GetTomorrowFirst()), ChargeTotalCount = ChargeOrderRepository.GetCount(i => i.EndTime != null), SwapTodayCount = SwapOrderRepository.GetCount(i => i.SwapResult != 0 && DateTime.Today <= i.SwapEndTime && i.SwapEndTime <= DateUtils.GetTomorrowFirst()), SwapTotalCount = SwapOrderRepository.GetCount(i => i.SwapResult != 0), }; return Result.Success(chargingCountResp); } /// /// 电池移仓 /// /// /// /// public Result BatteryRelocation(ushort removeBinNo, ushort putBinNo) { MoveBinRecord? moveBinRecord = null; try { if (!JudgeCanMove(removeBinNo, 1)) { return Result.Fail("出仓位状态有误"); } if (!JudgeCanMove(putBinNo, 0)) { return Result.Fail("入仓位状态有误"); } moveBinRecord= BatteryMove(removeBinNo, putBinNo, 1); } catch (Exception e) { Log.Error($" BatteryRelocation move battery fail e={e.Message}"); ClientMgr.PlcClient.BatteryMoveDone = false; if (moveBinRecord != null) { moveBinRecord.Status = 3; MoveBinRecordRepository.Update(moveBinRecord); } return Result.Fail(); } return moveBinRecord!=null && moveBinRecord.Status == 2 ? Result.Success() : Result.Fail(); } /// /// 维修仓校验 /车辆 /// /// private bool JudgeMaintenBin(ushort removeBinNo, ushort putBinNo, ushort no) { //当前存在一个维修仓 HashSet set = new HashSet(); set.Add(removeBinNo); set.Add(putBinNo); return set.Contains(no); } /// /// 电池仓 /// /// private bool JudgeBin(ushort removeBinNo, ushort putBinNo) { //当前存在一个维修仓 List set = new List(); set.Add(removeBinNo.ToString()); set.Add(putBinNo.ToString()); var bin = BinInfoRepository.Query().Select(i => i.No).ToList(); return set.Intersect(bin).Count() > 0; } /// /// type : 0:入仓 1:出仓 /// /// /// /// public bool JudgeCanMove(ushort binNo, int type) { if (binNo == 10) { //车辆未有校验 return true; } if (binNo == 0) { //本体未有校验 ,未有协议知道本体上是否有电池 return true; } if (binNo == 9) { //判断维修仓是否有电池 return (type == 0 && !ClientMgr.PlcClient.Is9Exist) || (type == 1 && ClientMgr.PlcClient.Is9Exist); } if (type == 0) { BinInfo? putBin = BinInfoRepository.QueryByClause(i => i.No.Equals(binNo) && i.Exists == 0 && i.AmtLock == 0 && i.Status == 1); return putBin != null; } else { //校验:出仓位 BinInfo? removeBin = BinInfoRepository.QueryByClause(i => i.No.Equals(binNo) && (i.ChargeStatus != 1) && i.Exists == 1 && i.AmtLock == 0); return removeBin != null; } } /// /// 维修仓<->电池仓 /// code : 1代表电池仓与维修仓交互 2;代表车辆与维修仓交互 /// /// /// /// public Result Relocation(ushort removeBinNo, ushort putBinNo, int code=1) { /*if (!JudgeMaintenBin(removeBinNo, putBinNo, 9)) { return Result.Fail("请选择一个维修仓号"); } if (code == 2) { if (!JudgeMaintenBin(removeBinNo, putBinNo,10)) { return Result.Fail("请选择一个车辆仓位"); } } else { if (!JudgeBin(removeBinNo, putBinNo)) { return Result.Fail("请选择一个电池仓位"); } }*/ if (removeBinNo == putBinNo) { return Result.Fail("请勿选择同一指令"); } MoveBinRecord? moveBinRecord = null; try { if (!JudgeCanMove(removeBinNo, 1)) { return Result.Fail("出仓位状态有误"); } if (!JudgeCanMove(putBinNo, 0)) { return Result.Fail("入仓位状态有误"); } moveBinRecord = BatteryMove(removeBinNo, putBinNo, 1); } catch (Exception e) { Log.Error($" Maintenance code={code} move battery fail e={e.Message}"); ClientMgr.PlcClient.BatteryMoveDone = false; if (moveBinRecord != null) { moveBinRecord.Status = 3; MoveBinRecordRepository.Update(moveBinRecord); } return Result.Fail(); } return moveBinRecord!=null && moveBinRecord.Status == 2 ? Result.Success() : Result.Fail(); } public MoveBinRecord? BatteryMove(ushort removeBinNo, ushort putBinNo, int type) { MoveBinRecord moveBinRecord = null; try { BinInfo? removeBin = BinInfoRepository.QueryByClause(i => i.No.Equals(removeBinNo)); BinInfo? putBin = BinInfoRepository.QueryByClause(i => i.No.Equals(putBinNo)); //当前有任务进行中 if (!ClientMgr.PlcClient!.IsTaskFree()) { return null; } ClientMgr.PlcClient!.ExChangeTaskNo(1); moveBinRecord = new MoveBinRecord() { UpBinNo = removeBinNo.ToString(), UpBatteryNo = removeBin!.BatteryNo, UpBatterySoc = removeBin!.Soc.ToString(), InBatteryNo = putBin!.BatteryNo, InBatterySoc = putBin!.Soc.ToString(), InBinNo = putBinNo.ToString(), Status = 0, Type = type, CreatedTime = DateTime.Now }; moveBinRecord = MoveBinRecordRepository.Insert(moveBinRecord); moveBinRecord.Status = 2; int timeOut = 60; //接受指令完成时间 int count = 0; //发送移仓任务 PlcApi.StartBatteryMove(removeBinNo.ToString(), putBinNo.ToString()); while (!ClientMgr.PlcClient.BatteryMoveDone || count < timeOut) { count++; Thread.Sleep(3000); } if (!ClientMgr.PlcClient.BatteryMoveDone) { moveBinRecord.Status = 3; } MoveBinRecordRepository.Update(moveBinRecord); } catch (Exception e) { Log.Error($"BatteryMove err={e}"); } ClientMgr.PlcClient?.ResetTaskNo(); return moveBinRecord; } public Result> GetChargeBinOption() { List queryListByClause = BinInfoRepository.Query(); var configBinInfo = new MapperConfiguration(cfg => cfg.CreateMap().ReverseMap()); IMapper mapperBinInfo = configBinInfo.CreateMapper(); return Result>.Success(mapperBinInfo.Map>(queryListByClause)); } }