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.

272 lines
9.7 KiB

using Autofac;
using DotNetty.Transport.Channels;
using Entity.DbModel.Station;
using HybirdFrameworkCore.Autofac;
7 months ago
using HybirdFrameworkCore.Autofac.Attribute;
using HybirdFrameworkCore.Entity;
using HybirdFrameworkDriver.Session;
using log4net;
using Repository.Station;
using Service.Charger.Common;
using Service.Equipment;
6 months ago
using Service.Init;
7 months ago
namespace Service.Charger.Client;
7 months ago
/// <summary>
6 months ago
/// 示例程序
7 months ago
/// </summary>
[Scope("SingleInstance")]
public static class ClientMgr
7 months ago
{
private static readonly ILog Log = LogManager.GetLogger(typeof(ClientMgr));
public static readonly Dictionary<string, ChargerClient> Dictionary = new();
6 months ago
private static bool AutoChargeWorking { get; set; }
public static ChargerClient? GetBySn(string sn)
7 months ago
{
Dictionary.TryGetValue(sn, out var o);
return o;
}
6 months ago
/// <summary>
/// 通过channel获取client
/// </summary>
/// <param name="channel"></param>
/// <param name="sn"></param>
/// <param name="client">获取不到client则为空</param>
/// <returns></returns>
public static bool TryGetClient(IChannel channel, out string sn, out ChargerClient? client)
{
string? snt = ChannelUtils.GetAttr(channel, ChargerConst.ChargerSn);
if (!string.IsNullOrWhiteSpace(snt))
{
var chargerClient = GetBySn(snt);
if (chargerClient != null)
{
sn = snt;
client = chargerClient;
return true;
}
}
7 months ago
sn = string.Empty;
client = null;
return false;
}
7 months ago
public static void AddBySn(string sn, ChargerClient client)
{
Dictionary[sn] = client;
}
//TODO 连接、鉴权,开始充电,结束充电,设置尖峰平谷,读取尖峰平谷,发送功率调节指令,发送辅助源控制指令,下发掉线停止充电,
public static void InitClient()
{
EquipInfoRepository equipInfoRepository = AppInfo.Container.Resolve<EquipInfoRepository>();
EquipNetInfoRepository netInfoRepository = AppInfo.Container.Resolve<EquipNetInfoRepository>();
BinInfoRepository binInfoRepository = AppInfo.Container.Resolve<BinInfoRepository>();
List<EquipInfo> equipInfos = equipInfoRepository.QueryListByClause(it => it.TypeCode == (int)EquipmentType.Charger);
if (equipInfos.Count > 0)
{
Dictionary<string, EquipInfo> set = equipInfos.ToDictionary(it => it.Code, it => it);
6 months ago
List<EquipNetInfo> equipNetInfos = netInfoRepository.QueryListByClause(it => set.Keys.Contains(it.Code));
Dictionary<string,BinInfo> binInfoMap = binInfoRepository.QueryListByClause(it => set.Keys.Contains(it.ChargerNo))
.ToDictionary(it => it.ChargerNo, it => it);
foreach (EquipNetInfo netInfo in equipNetInfos)
{
Task.Run(() =>
{
binInfoMap.TryGetValue(netInfo.Code, out var binInfo);
ConnClient(netInfo, binInfo);
});
}
6 months ago
StartAutoChargeThread();
6 months ago
StartQueryBatteryInfoThread();
}
}
private static void StartQueryBatteryInfoThread()
{
Thread thread = new Thread(QueryBatteryInfo)
{
Name = @"QueryBatteryInfoThread"
};
thread.Start();
}
private static void QueryBatteryInfo()
{
while (true)
{
try
{
Thread.Sleep(1000);
foreach (var (key, client) in Dictionary)
{
client.SendQueryBattery();
}
}
catch (Exception e)
{
Log.Error("QueryBatteryInfo error", e);
}
}
}
/// <summary>
///
/// </summary>
6 months ago
private static void StartAutoChargeThread()
{
6 months ago
if (!AutoChargeWorking)
{
6 months ago
Thread thread = new Thread(AutoChargeThread)
{
6 months ago
Name = @"AutoChargeThread"
6 months ago
};
thread.Start();
AutoChargeWorking = true;
}
}
/// <summary>
///
/// </summary>
private static void AutoChargeThread()
{
ElecPriceModelVersionRepository elecPriceModelVersionRepository =
AppInfo.Container.Resolve<ElecPriceModelVersionRepository>();
ElecPriceModelVersionDetailRepository elecPriceModelVersionDetailRepository =
AppInfo.Container.Resolve<ElecPriceModelVersionDetailRepository>();
6 months ago
BatteryOpModelRepository batteryOpModelRepository = AppInfo.Container.Resolve<BatteryOpModelRepository>();
BatteryOpModelDetailRepository batteryOpModelDetailRepository =
AppInfo.Container.Resolve<BatteryOpModelDetailRepository>();
BinInfoRepository binInfoRepository = AppInfo.Container.Resolve<BinInfoRepository>();
while (true)
{
6 months ago
try
{
6 months ago
Thread.Sleep(1000 * 30);
6 months ago
DateTime now = DateTime.Now;
6 months ago
List<BinInfo> binInfos = binInfoRepository.Query();
if (binInfos.Count < 0)
{
Log.Info("lack of binInfos");
continue;
}
var chargeSoc = StaticStationInfo.ChargeSoc;
List<BinInfo> socNeedChargeList = binInfos.Where(t => t.Soc < chargeSoc).ToList();
if (socNeedChargeList.Count < 0)
{
Log.Info($"lack of binInfos.soc < {chargeSoc}");
continue;
}
#region 电价模型
int ceid = StaticStationInfo.Ceid;
ElecPriceModelVersion elecPriceModelVersion = elecPriceModelVersionRepository.QueryByClause(i => i.Version == ceid);
6 months ago
if (elecPriceModelVersion == null)
{
6 months ago
Log.Info("lack of effective elecPriceModelVersion");
6 months ago
continue;
}
6 months ago
List<ElecPriceModelVersionDetail> 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();
if (elecPriceModelVersionDetail == null)
{
6 months ago
Log.Info("lack of effective elecPriceModelVersionDetail");
6 months ago
continue;
}
6 months ago
#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");
continue;
}
List<BatteryOpModelDetail> batteryOpModelDetails = batteryOpModelDetailRepository.QueryListByClause(d => d.ModelId == oid);
List<BatteryOpModelDetail> opModelDetails = batteryOpModelDetails.Where(t =>
{
List<int> start = t.StartTime.Split(":").Select(int.Parse).ToList();
List<int> 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();
if (opModelDetails.Count == 0)
{
Log.Info("lack of effective batteryOpModelDetails");
continue;
}
int needBatteryCount = opModelDetails[0].BatteryCount ?? 8;
if ((binInfos.Count - socNeedChargeList.Count) >= needBatteryCount)
{
Log.Info($"lack of needBatteryCount {needBatteryCount}");
continue;
}
6 months ago
#endregion
6 months ago
foreach (BinInfo binInfo in socNeedChargeList)
6 months ago
{
6 months ago
if (Dictionary.TryGetValue(binInfo.ChargerNo, out var client))
{
Result<bool> result = client.StartCharge();
Log.Info($"start {binInfo.ChargerNo} charge {result.IsSuccess}:{result.Msg}");
}
else
{
Log.Info($"can not find {binInfo.ChargerNo} in dict");
}
6 months ago
}
}
catch (Exception e)
{
6 months ago
Log.Error("AutoChargeThread error", e);
}
}
}
private static void ConnClient(EquipNetInfo netInfo, BinInfo? binInfo)
{
Log.Info($"begin to connect {netInfo.Code} {netInfo.NetAddr}:{netInfo.NetPort}");
ChargerClient client = AppInfo.Container.Resolve<ChargerClient>();
client.BinNo = binInfo.No;
client.BatteryNo = binInfo.BatteryNo;
client.InitBootstrap(netInfo.NetAddr, int.Parse(netInfo.NetPort));
Task.Run(() =>
{
client.Connect();
client.SessionAttr(netInfo.Code, netInfo.DestAddr);
Log.Info($"succeed to connect {netInfo.Code} {netInfo.NetAddr}:{netInfo.NetPort}");
});
AddBySn(netInfo.Code, client);
Log.Info($"begin to connect {netInfo.Code} {netInfo.NetAddr}:{netInfo.NetPort}");
7 months ago
}
}