You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

517 lines
18 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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<List<BinInfo>> CanSelectPackBin()
{
//出仓位
SelectPackDto selectPackDtoUpBin = BinInfoRepository.SelectPack(StaticStationInfo.SwapSoc,
StaticStationInfo.SwapFinishChargeTime,
"");
//入仓位
SelectPackDto selectPackInBin = BinInfoRepository.SelectPackInBin();
return new List<List<BinInfo>>()
{
selectPackDtoUpBin.CanSwapBinInfo, selectPackInBin.CanSwapBinInfo
};
}
//手动选包
public Result<bool> 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<bool>.Success();
}
[DisplayName("获取移仓分页")]
public async Task<PageResult<MoveBinRecord>> Page(PageMoveBinRecordReq input)
{
RefAsync<int> 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<MoveBinRecord>()
{
PageNum = input.PageNum,
PageSize = input.PageSize,
ToTal = total,
Rows = items,
};
}
public async Task<string> Add(AddMoveBinRecordReq input)
{
string result = "";
MoveBinRecord moveBinRecord = await MoveBinRecordRepository.InsertAsync(input);
return "新增id" + moveBinRecord.Id;
}
public virtual async Task<bool> Update(UpdateMoveBinRecordReq Req)
{
return await MoveBinRecordRepository.UpdateAsync(Req);
}
public virtual async Task<bool> 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<SwapMonitorScreenResp> GetSwapMonitorData()
{
var configBinInfo =
new MapperConfiguration(cfg => cfg.CreateMap<StepModel, SwappingStateInfoResp>().ReverseMap());
IMapper mapperBinInfo = configBinInfo.CreateMapper();
List<SwappingStateInfoResp> stateInfoList = new List<SwappingStateInfoResp>();
ConcurrentDictionary<string, StepModel> dictionary = StationSoftMgr.SwappingStateMachine.StepModel;
stateInfoList = dictionary.Values
.OrderBy(model => model.StepNo)
.Select(model => mapperBinInfo.Map<SwappingStateInfoResp>(model))
.ToList();
var tboxCarInfoModel = StationSoftMgr.SwappingStateMachine.BoxCarInfoModel;
List<BinInfo> 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<SwapMonitorScreenResp>.Success(monitorScreenResp);
}
/// <summary>
/// 模式類
/// </summary>
/// <returns></returns>
public Result<SwapModelResp> GetModel()
{
SwapModelResp resp = new()
{
StationStatus = StaticStationInfo.StationStatus,
StationWay = StaticStationInfo.StationWay,
StationModel = StaticStationInfo.StationModel
};
return Result<SwapModelResp>.Success(resp);
}
/// <summary>
/// 连接状态类
/// </summary>
/// <returns></returns>
public Result<DeviceStateResp> 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<DeviceStateResp>.Success(resp);
}
//TODO:: 首页--当月,当日换电量
public Result<SwapAndChargingCountResp> 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<SwapAndChargingCountResp>.Success(chargingCountResp);
}
/// <summary>
/// 电池移仓
/// </summary>
/// <param name="removeBinNo"></param>
/// <param name="putBinNo"></param>
/// <returns></returns>
public Result<bool> BatteryRelocation(ushort removeBinNo, ushort putBinNo)
{
MoveBinRecord? moveBinRecord = null;
try
{
if (!JudgeCanMove(removeBinNo, 1))
{
return Result<bool>.Fail("出仓位状态有误");
}
if (!JudgeCanMove(putBinNo, 0))
{
return Result<bool>.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<bool>.Fail();
}
return moveBinRecord!=null && moveBinRecord.Status == 2 ? Result<bool>.Success() : Result<bool>.Fail();
}
/// <summary>
/// 维修仓校验 /车辆
/// </summary>
/// <returns></returns>
private bool JudgeMaintenBin(ushort removeBinNo, ushort putBinNo, ushort no)
{
//当前存在一个维修仓
HashSet<ushort> set = new HashSet<ushort>();
set.Add(removeBinNo);
set.Add(putBinNo);
return set.Contains(no);
}
/// <summary>
/// 电池仓
/// </summary>
/// <returns></returns>
private bool JudgeBin(ushort removeBinNo, ushort putBinNo)
{
//当前存在一个维修仓
List<string> set = new List<string>();
set.Add(removeBinNo.ToString());
set.Add(putBinNo.ToString());
var bin = BinInfoRepository.Query().Select(i => i.No).ToList();
return set.Intersect(bin).Count() > 0;
}
/// <summary>
/// type : 0:入仓 1:出仓
/// </summary>
/// <param name="binNo"></param>
/// <param name="type"></param>
/// <returns></returns>
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;
}
}
/// <summary>
/// 维修仓<->电池仓
/// code : 1代表电池仓与维修仓交互 2代表车辆与维修仓交互
/// </summary>
/// <param name="removeBinNo"></param>
/// <param name="putBinNo"></param>
/// <returns></returns>
public Result<bool> Relocation(ushort removeBinNo, ushort putBinNo, int code=1)
{
/*if (!JudgeMaintenBin(removeBinNo, putBinNo, 9))
{
return Result<bool>.Fail("请选择一个维修仓号");
}
if (code == 2)
{
if (!JudgeMaintenBin(removeBinNo, putBinNo,10))
{
return Result<bool>.Fail("请选择一个车辆仓位");
}
}
else
{
if (!JudgeBin(removeBinNo, putBinNo))
{
return Result<bool>.Fail("请选择一个电池仓位");
}
}*/
if (removeBinNo == putBinNo)
{
return Result<bool>.Fail("请勿选择同一指令");
}
MoveBinRecord? moveBinRecord = null;
try
{
if (!JudgeCanMove(removeBinNo, 1))
{
return Result<bool>.Fail("出仓位状态有误");
}
if (!JudgeCanMove(putBinNo, 0))
{
return Result<bool>.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<bool>.Fail();
}
return moveBinRecord!=null && moveBinRecord.Status == 2 ? Result<bool>.Success() : Result<bool>.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*4; //接受指令完成时间
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<List<BinInfoResp>> GetChargeBinOption()
{
List<BinInfo> queryListByClause = BinInfoRepository.Query();
var configBinInfo =
new MapperConfiguration(cfg => cfg.CreateMap<BinInfo, BinInfoResp>().ReverseMap());
IMapper mapperBinInfo = configBinInfo.CreateMapper();
return Result<List<BinInfoResp>>.Success(mapperBinInfo.Map<List<BinInfoResp>>(queryListByClause));
}
}