ChargingStationService.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. using Dapper;
  2. using EVCB_OCPP.WEBAPI.Models.WebAPI;
  3. using EVCB_OCPP.WEBAPI.Models.WebAPI.Dto;
  4. using Microsoft.Extensions.Configuration;
  5. using Microsoft.Extensions.DependencyInjection;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Configuration;
  9. using System.Data;
  10. using System.Linq;
  11. using Microsoft.Data.SqlClient;
  12. using EVCB_OCPP.WEBAPI.Helpers;
  13. using System.Threading.Tasks;
  14. using System.Diagnostics;
  15. using Microsoft.Extensions.Logging;
  16. using System.Threading;
  17. using static System.Collections.Specialized.BitVector32;
  18. using EVCB_OCPP.WEBAPI.Models.Db;
  19. namespace EVCB_OCPP.WEBAPI.Services
  20. {
  21. public interface IChargingStationService
  22. {
  23. List<Station> GetStationsbyCustomerId(string customerId);
  24. List<EVSE> GetEVSEsbyStationId(int stationId, DateTime? dateFrom, DateTime? dateTo, int offset, int limit);
  25. Task<List<Station>> GetStationsbyCustomerIdAsync(string customerId);
  26. }
  27. public class ChargingStationService : IChargingStationService
  28. {
  29. //string mainConnectionString;
  30. //string webConnectionString;
  31. private readonly IServiceProvider serviceProvider;
  32. private readonly SqlConnectionFactory<WebDBConetext> webConnectionFactory;
  33. private readonly ILogger<ChargingStationService> logger;
  34. public ChargingStationService(
  35. SqlConnectionFactory<WebDBConetext> webConnectionFactory,
  36. ILogger<ChargingStationService> logger,
  37. IServiceProvider serviceProvider)
  38. {
  39. //mainConnectionString = configuration.GetConnectionString("MainDBContext");
  40. //webConnectionString = configuration.GetConnectionString("WebDBContext");
  41. this.serviceProvider = serviceProvider;
  42. this.webConnectionFactory = webConnectionFactory;
  43. this.logger = logger;
  44. }
  45. public List<Station> GetStationsbyCustomerId(string customerId)
  46. {
  47. return GetStationsbyCustomerIdAsync(customerId).Result;
  48. }
  49. public async Task<List<Station>> GetStationsbyCustomerIdAsync(string customerId)
  50. {
  51. var watch = Stopwatch.StartNew();
  52. List<long> times = new();
  53. List<Station> _stations = new List<Station>();
  54. var parameters = new DynamicParameters();
  55. parameters.Add("@CustomerId", customerId, DbType.AnsiString, ParameterDirection.Input, 36);
  56. using (SqlConnection conn = await webConnectionFactory.CreateAsync())
  57. {
  58. string strSql = "Select Id, Name ,Latitude,Longitude,Address from [dbo].[Station] where CustomerId=@CustomerId; ";
  59. var result = await conn.QueryAsync<Station>(strSql, parameters);
  60. _stations = result is null ? new List<Station>() : result.ToList();
  61. }
  62. times.Add(watch.ElapsedMilliseconds);
  63. //if (_stations == null)
  64. //{
  65. // return _stations;
  66. //}
  67. //List<Task> ts = new List<Task>();
  68. //foreach (var station in _stations)
  69. //{
  70. // station.Coordinates = new GetLocation() { Latitude = station.Latitude, Longitude = station.Longitude };
  71. // ts.Add(Task.Run(async () => { station.EVSEs = await GetEVSEsbyStationIdAsync(station.Id, null, null, -1, 100000); } ));
  72. //}
  73. //await Task.WhenAll(ts);
  74. //await Parallel.ForEachAsync(_stations, async (station, c) => {
  75. // station.EVSEs = await GetEVSEsbyStationIdAsync(station.Id, null, null, -1, 100000);
  76. //});
  77. Dictionary<int, List<string>> stationMachinePair = await GetStationMachinePairAsync(_stations.Select(x => x.Id));
  78. times.Add(watch.ElapsedMilliseconds);
  79. foreach (var station in _stations)
  80. {
  81. station.Coordinates = new GetLocation() { Latitude = station.Latitude, Longitude = station.Longitude };
  82. //station.EVSEs = await GetEVSEsbyStationIdAsync(station.Id, null, null, -1, 100000);
  83. station.EVSEs = stationMachinePair.ContainsKey(station.Id)
  84. ? await GetEVSEsBytEVSEs(stationMachinePair[station.Id], null, null, -1, 100000)
  85. : new List<EVSE> { };
  86. station.EVSEs.ForEach(x => x.StationId = station.Id);
  87. times.Add(watch.ElapsedMilliseconds);
  88. }
  89. watch.Stop();
  90. if (watch.ElapsedMilliseconds > 1000)
  91. {
  92. logger.LogWarning($"GetStationsbyCustomerIdAsync {string.Join("/", times)}");
  93. }
  94. return _stations;
  95. }
  96. public bool ContainsStation(string customerId, int stationId)
  97. {
  98. bool isContains = false;
  99. var parameters = new DynamicParameters();
  100. parameters.Add("@CustomerId", customerId, DbType.AnsiString, ParameterDirection.Input, 36);
  101. parameters.Add("@Id", stationId, DbType.Int32, ParameterDirection.Input);
  102. using (SqlConnection conn = webConnectionFactory.Create())
  103. {
  104. string strSql = "Select count(*) from [dbo].[Station] where CustomerId=@CustomerId and Id=@Id; ";
  105. isContains = conn.ExecuteScalar<Int32>(strSql, parameters) > 0 ? true : false;
  106. }
  107. return isContains;
  108. }
  109. public List<EVSE> GetEVSEsbyStationId(int stationId, DateTime? dateFrom, DateTime? dateTo, int offset = -1, int limit = 1000)
  110. {
  111. return GetEVSEsbyStationIdAsync(stationId,dateFrom,dateTo,offset,limit).Result;
  112. }
  113. public async Task<List<EVSE>> GetEVSEsbyStationIdAsync(int stationId, DateTime? dateFrom, DateTime? dateTo, int offset = -1, int limit = 1000)
  114. {
  115. //var watch = Stopwatch.StartNew();
  116. //List<long> time = new();
  117. List<EVSE> _chargePoints = new List<EVSE>();
  118. var parameters = new DynamicParameters();
  119. parameters.Add("@StationId", stationId, DbType.Int16, ParameterDirection.Input);
  120. List<string> machineIds = new List<string>();
  121. using (SqlConnection conn = await webConnectionFactory.CreateAsync())
  122. {
  123. string strSql = "Select MachineId from [dbo].[StationMachine] where StationId=@StationId; ";
  124. machineIds = (await conn.QueryAsync<String>(strSql, parameters)).ToList();
  125. }
  126. //time.Add(watch.ElapsedMilliseconds);
  127. var result = await GetEVSEsBytEVSEs(machineIds, dateFrom, dateTo, offset, limit);
  128. result.ForEach(x => x.StationId = stationId);
  129. return result;
  130. }
  131. public Task<List<EVSE>> GetEVSEsBytEVSEs(List<string> machineIds, DateTime? dateFrom, DateTime? dateTo, int offset = -1, int limit = 1000)
  132. {
  133. return GetEVSEsBytEVSEsWithDapper(machineIds, dateFrom, dateTo, offset, limit);
  134. //return GetEVSEsBytEVSEsWithSP(machineIds, dateFrom, dateTo, offset, limit);
  135. }
  136. public async Task<List<EVSE>> GetEVSEsBytEVSEsWithSP(List<string> machineIds, DateTime? dateFrom, DateTime? dateTo, int offset = -1, int limit = 1000)
  137. {
  138. var watch = Stopwatch.StartNew();
  139. List<EVSE> _chargePoints = new List<EVSE>();
  140. ChargePointService _CPService = serviceProvider.GetRequiredService<ChargePointService>();// new ChargePointService();
  141. int startIndex = offset == -1 ? 0 : offset;
  142. limit += startIndex;
  143. while (startIndex < limit && startIndex < machineIds.Count)
  144. {
  145. var _machineUpdateOn = await _CPService.GetLastUpdatedTimebyMachineIdAsync(machineIds[startIndex]);
  146. //time.Add(watch.ElapsedMilliseconds);
  147. if (dateFrom.HasValue && _machineUpdateOn < dateFrom.Value.ToUniversalTime())
  148. {
  149. limit++;
  150. startIndex++;
  151. continue;
  152. }
  153. if (dateFrom.HasValue && dateTo.HasValue && (_machineUpdateOn < dateFrom.Value.ToUniversalTime() || _machineUpdateOn > dateTo.Value.ToUniversalTime()))
  154. {
  155. limit++;
  156. startIndex++;
  157. continue;
  158. }
  159. var _machine = await _CPService.GetBasicInfobyIdAsync(machineIds[startIndex]);
  160. //time.Add(watch.ElapsedMilliseconds);
  161. if (_machine != null)
  162. {
  163. _machine.LastUpdated = _machineUpdateOn;
  164. //_machine.StationId = stationId;
  165. _chargePoints.Add(_machine);
  166. }
  167. else
  168. {
  169. limit++;
  170. }
  171. startIndex++;
  172. }
  173. watch.Stop();
  174. if (watch.ElapsedMilliseconds > 1000)
  175. {
  176. logger.LogWarning($"GetEVSEsBytEVSEs {watch.ElapsedMilliseconds}");
  177. }
  178. return _chargePoints;
  179. }
  180. public async Task<List<EVSE>> GetEVSEsBytEVSEsWithDapper(List<string> machineIds, DateTime? dateFrom, DateTime? dateTo, int offset = -1, int limit = 1000)
  181. {
  182. var watch = Stopwatch.StartNew();
  183. List<long> times = new();
  184. List<EVSE> _chargePoints = new List<EVSE>();
  185. ChargePointService _CPService = serviceProvider.GetRequiredService<ChargePointService>();// new ChargePointService();
  186. int quota = limit;
  187. int startIndex = offset == -1 ? 0 : offset;
  188. limit += startIndex;
  189. var machineIdChunks = machineIds.Chunk(100);
  190. foreach(var machineIdChunk in machineIdChunks)
  191. {
  192. Dictionary<string, DateTime> _machineUpdateOnPairs = await _CPService.GetLastUpdatedTimebyMachineIdAsync(machineIdChunk);
  193. times.Add(watch.ElapsedMilliseconds);
  194. _machineUpdateOnPairs = _machineUpdateOnPairs
  195. .Where(x => !dateFrom.HasValue || x.Value > dateFrom.Value.ToUniversalTime())
  196. .Where(x => !dateTo.HasValue || x.Value < dateTo.Value.ToUniversalTime())
  197. .ToDictionary(x=>x.Key,x=>x.Value);
  198. Dictionary<string, EVSE> pairs = await _CPService.GetBasicInfobyIdAsync(_machineUpdateOnPairs.Select(x=> x.Key));
  199. times.Add(watch.ElapsedMilliseconds);
  200. foreach (var pair in pairs)
  201. {
  202. var machine = pair.Value;
  203. machine.LastUpdated = _machineUpdateOnPairs[pair.Key];
  204. _chargePoints.Add(machine);
  205. if (_chargePoints.Count > quota)
  206. break;
  207. }
  208. //foreach (var pair in _machineUpdateOnPairs)
  209. //{
  210. // var _machine = await _CPService.GetBasicInfobyIdAsync(pair.Key);
  211. // if (_machine != null)
  212. // {
  213. // _machine.LastUpdated = pair.Value;
  214. // //_machine.StationId = stationId;
  215. // _chargePoints.Add(_machine);
  216. // }
  217. // if (_chargePoints.Count > quota)
  218. // break;
  219. //}
  220. if (_chargePoints.Count > quota)
  221. break;
  222. }
  223. watch.Stop();
  224. if (watch.ElapsedMilliseconds > 1000)
  225. {
  226. logger.LogWarning($"GetEVSEsBytEVSEs {string.Join("/", times)}");
  227. }
  228. return _chargePoints;
  229. while (startIndex < limit && startIndex < machineIds.Count)
  230. {
  231. DateTime _machineUpdateOn = await _CPService.GetLastUpdatedTimebyMachineIdAsync(machineIds[startIndex]);
  232. //time.Add(watch.ElapsedMilliseconds);
  233. if (dateFrom.HasValue && _machineUpdateOn < dateFrom.Value.ToUniversalTime())
  234. {
  235. limit++;
  236. startIndex++;
  237. continue;
  238. }
  239. if (dateFrom.HasValue && dateTo.HasValue && (_machineUpdateOn < dateFrom.Value.ToUniversalTime() || _machineUpdateOn > dateTo.Value.ToUniversalTime()))
  240. {
  241. limit++;
  242. startIndex++;
  243. continue;
  244. }
  245. var _machine = await _CPService.GetBasicInfobyIdAsync(machineIds[startIndex]);
  246. //time.Add(watch.ElapsedMilliseconds);
  247. if (_machine != null)
  248. {
  249. _machine.LastUpdated = _machineUpdateOn;
  250. //_machine.StationId = stationId;
  251. _chargePoints.Add(_machine);
  252. }
  253. else
  254. {
  255. limit++;
  256. }
  257. startIndex++;
  258. }
  259. watch.Stop();
  260. if (watch.ElapsedMilliseconds > 1000)
  261. {
  262. logger.LogWarning($"GetEVSEsBytEVSEs {watch.ElapsedMilliseconds}");
  263. }
  264. return _chargePoints;
  265. }
  266. public async Task<Dictionary<int, List<string>>> GetStationMachinePairAsync(IEnumerable<int> stationIds)
  267. {
  268. var parameters = new DynamicParameters();
  269. parameters.Add("@StationIds", stationIds);
  270. string strSql = "SELECT StationId, MachineId FROM [dbo].[StationMachine] WHERE StationId IN @StationIds; ";
  271. using SqlConnection conn = await webConnectionFactory.CreateAsync();
  272. var result = await conn.QueryAsync<StationMachineDto>(strSql, parameters);
  273. return result.GroupBy(x => x.StationId).ToDictionary(x => x.Key, x => x.Select(x => x.MachineId).ToList());
  274. }
  275. }
  276. }