using Common.Const; using Entity.DbModel.Station; using HybirdFrameworkCore.Autofac.Attribute; using HybirdFrameworkCore.AutoTask; using HybirdFrameworkCore.Entity; using HybirdFrameworkCore.Utils; using log4net; using Newtonsoft.Json; using Repository.Station; using Service.Charger.Client; using Service.Init; namespace Service.Charger.MyTask; [Scope] public class AutoChargeTask : ITask { private static readonly ILog Log = LogManager.GetLogger(typeof(AutoChargeTask)); private volatile bool _stop; public ElecPriceModelVersionRepository elecPriceModelVersionRepository { get; set; } public ElecPriceModelVersionDetailRepository elecPriceModelVersionDetailRepository { get; set; } public BatteryOpModelRepository batteryOpModelRepository { get; set; } public BatteryOpModelDetailRepository batteryOpModelDetailRepository { get; set; } public BinInfoRepository binInfoRepository { get; set; } public EquipInfoRepository EquipInfoRepository { get; set; } public string Name() { return "AutoChargeTask"; } public int Interval() { return 1000 * 10; } public void Handle() { try { DateTime now = DateTime.Now; List allBinInfos = binInfoRepository.Query(); if (allBinInfos.Count < 0) { Log.Info("lack of binInfos"); return; } List chargerList = EquipInfoRepository.QueryListByClause(it => it.TypeCode == (int)EquipmentType.Charger); HashSet autoChargeSet = chargerList.Where(it => it.AutoCharge == 1).Select(it => it.Code).ToHashSet(); var binInfos = allBinInfos.Where(it => autoChargeSet.Contains(it.ChargerNo)).ToList(); if (ObjUtils.IsEmpty(binInfos)) { Log.Info("there is no auto charger"); return; } #region 电价模型 int ceid = StaticStationInfo.Ceid; ElecPriceModelVersion elecPriceModelVersion = elecPriceModelVersionRepository.QueryByClause(i => i.Version == ceid); if (elecPriceModelVersion == null) { Log.Info("lack of effective elecPriceModelVersion"); return; } List elecPriceModelVersionDetails = elecPriceModelVersionDetailRepository.QueryListByClause(it => it.Version == elecPriceModelVersion.Version); /*ElecPriceModelVersionDetail? elecPriceModelVersionDetail = elecPriceModelVersionDetails.Where(i => i.StartHour <= now.Hour && i.StartMinute <= now.Minute && i.EndHour > now.Hour && i.EndMinute > now.Minute).FirstOrDefault();*/ ElecPriceModelVersionDetail? elecPriceModelVersionDetail = null; foreach (var VARIABLE in elecPriceModelVersionDetails) { // 构造开始和结束的DateTime对象,使用当前日期的年月日 DateTime startTime = new DateTime(now.Year, now.Month, now.Day, VARIABLE.StartHour, VARIABLE.StartMinute, 0); DateTime endTime = new DateTime(now.Year, now.Month, now.Day, VARIABLE.EndHour, VARIABLE.EndMinute, 0); if (DateTime.Now >= startTime && DateTime.Now <= endTime) { elecPriceModelVersionDetail = VARIABLE; } } if (elecPriceModelVersionDetail == null) { Log.Info("lack of effective elecPriceModelVersionDetail"); return; } #endregion #region 运营模型 int oid = int.Parse(StaticStationInfo.Oid); BatteryOpModel batteryOpModel = batteryOpModelRepository.QueryByClause(d => d.ModelId == oid); if (batteryOpModel == null) { Log.Info("lack of effective batteryOpModel"); return; } List batteryOpModelDetails = batteryOpModelDetailRepository.QueryListByClause(d => d.ModelId == oid); List opModelDetails = new List(); /*List opModelDetails = batteryOpModelDetails.Where(t => { List start = t.StartTime.Split(":").Select(int.Parse).ToList(); List end = t.EndTime.Split(":").Select(int.Parse).ToList(); return now.Hour >= start[0] && now.Hour < end[0] && now.Minute >= start[1] && now.Minute < end[1] && now.Second >= start[2] && now.Second < end[2]; }).ToList();*/ foreach (var t in batteryOpModelDetails) { if (DateTime.Now >= DateTime.Parse(t.StartTime) && DateTime.Now <= DateTime.Parse(t.EndTime)) { opModelDetails.Add(t); } } if (opModelDetails.Count == 0) { Log.Info("lack of effective batteryOpModelDetails"); return; } int needBatteryCount = opModelDetails[0].BatteryCount ?? 8; List canSwapList = allBinInfos.Where(it => it.Soc != null && Convert.ToSingle(it.Soc) >= StaticStationInfo.SwapSoc && it.CanSwapFlag == 1) .ToList(); /*if (canSwapList.Count == needBatteryCount) { Log.Info($"lack of needBatteryCount {needBatteryCount}"); return; }*/ List chargingList = binInfos.Where(it => it.ChargeStatus == 1).ToList(); Log.Info( $"chargingList={JsonConvert.SerializeObject(chargingList.Select(info => info.Code + "," + info.ChargerNo).ToList())}"); if (canSwapList.Count <= needBatteryCount) { List canChargeList = binInfos.Where(it => it.Soc != null && Convert.ToSingle(it.Soc) < StaticStationInfo.SwapSoc && it.CanChargeFlag == 1 && it.Exists == 1) .ToList(); //启动电量高的 canChargeList.Sort((a, b) => (b.Soc ?? 0).CompareTo(a.Soc ?? 0)); byte chargeSoc = StaticStationInfo.ChargeSoc; int count = needBatteryCount - canSwapList.Count; Log.Info( $"need start count={count}, canChargeList={JsonConvert.SerializeObject(canChargeList.Select(info => info.Code + "," + info.ChargerNo).ToList())}"); int number = 0; foreach (var binInfo in canChargeList) { float? chargePower = EquipInfoRepository.QueryPowerByCode(binInfo.ChargerNo); float? power = chargePower == null ? StaticStationInfo.ChargePower : chargePower; if (binInfo.ChargeStatus != 1) { //没有充电时候在充电 Result? result = ClientMgr.GetBySn(binInfo.ChargerNo) ?.StartCharge(chargeSoc, (float)power, 0); if (result is { IsSuccess: true }) { Log.Info($"auto start charge {binInfo.ChargerNo}"); number++; } if (count == number) { Log.Info($"auto start charge count {count}"); break; } } } } #region 达到充电SOC自动停 List stopList = chargingList.Where(it => it.Soc > StaticStationInfo.ChargeSoc).ToList(); Log.Info( $"need stop count={stopList.Count}, stopList={JsonConvert.SerializeObject(stopList.Select(info => info.Code + "," + info.ChargerNo).ToList())}"); foreach (var binInfo in stopList) { Log.Info($"auto stop charge {binInfo.No} soc:{binInfo.Soc}"); ClientMgr.GetBySn(binInfo.ChargerNo)?.SendRemoteStopCharging(); } #endregion #endregion } catch (Exception e) { Log.Error("handle with error", e); } } public bool Stoped() { return _stop; } public void Stop() { _stop = true; } public void ResetStop() { _stop = false; } }