ChargePointService.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
  1. using Dapper;
  2. using EVCB_OCPP.Packet.Messages.SubTypes;
  3. using EVCB_OCPP.WEBAPI.Models;
  4. using EVCB_OCPP.WEBAPI.Models.WebAPI;
  5. using EVCB_OCPP.WEBAPI.Models.WebAPI.Dto;
  6. using Microsoft.Extensions.Configuration;
  7. using Microsoft.Extensions.DependencyInjection;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Data;
  11. using System.Linq;
  12. using Microsoft.Data.SqlClient;
  13. using EVCB_OCPP.Domain;
  14. using EVCB_OCPP.WEBAPI.Helpers;
  15. using System.Threading.Tasks;
  16. using System.Diagnostics;
  17. using Microsoft.Extensions.Logging;
  18. using NLog;
  19. namespace EVCB_OCPP.WEBAPI.Services
  20. {
  21. public interface IChargePointService
  22. {
  23. int GetNumberofConnectors(string chargeBoxId);
  24. }
  25. public class ChargePointService : IChargePointService
  26. {
  27. //readonly string mainConnectionString;
  28. //readonly string meterConnectionString;
  29. private readonly IServiceProvider serviceProvider;
  30. private readonly SqlConnectionFactory<MainDBContext> mainDbConneciotnFactory;
  31. private readonly SqlConnectionFactory<MeterValueDBContext> meterValueDbConnectionFactory;
  32. private readonly MainDbService mainDbService;
  33. private readonly MeterValueDbService meterValueDbService;
  34. private readonly ILogger<ChargePointService> logger;
  35. public ChargePointService(
  36. IServiceProvider serviceProvider,
  37. SqlConnectionFactory<MainDBContext> mainDbConneciotnFactory,
  38. SqlConnectionFactory<MeterValueDBContext> meterValueDbConnectionFactory,
  39. MainDbService mainDbService,
  40. MeterValueDbService meterValueDbService,
  41. ILogger<ChargePointService> logger)
  42. {
  43. //mainConnectionString = configuration.GetConnectionString("MainDBContext");
  44. //meterConnectionString = configuration.GetConnectionString("MeterValueDBContext");
  45. this.serviceProvider = serviceProvider;
  46. this.mainDbConneciotnFactory = mainDbConneciotnFactory;
  47. this.meterValueDbConnectionFactory = meterValueDbConnectionFactory;
  48. this.mainDbService = mainDbService;
  49. this.meterValueDbService = meterValueDbService;
  50. this.logger = logger;
  51. }
  52. public DateTime GetLastUpdatedTimebyMachineId(string machineId)
  53. {
  54. return GetLastUpdatedTimebyMachineIdAsync(machineId).Result;
  55. }
  56. public async Task<DateTime> GetLastUpdatedTimebyMachineIdAsync(string machineId)
  57. {
  58. DateTime lastUpdatedOn = DateTime.UtcNow;
  59. using (SqlConnection conn = await mainDbConneciotnFactory.CreateAsync())
  60. {
  61. var parameters = new DynamicParameters();
  62. parameters.Add("@MachineId", machineId, DbType.String, ParameterDirection.Input, 36);
  63. parameters.Add("@LastUpdatedTime", lastUpdatedOn, DbType.DateTime, ParameterDirection.Output);
  64. await conn.ExecuteAsync("GetBasicInfoLastUpdatedTimeById", parameters, commandType: System.Data.CommandType.StoredProcedure);
  65. DateTime? time = null;
  66. time = parameters.Get<DateTime?>("@LastUpdatedTime");
  67. lastUpdatedOn = DateTime.SpecifyKind(time ?? DateTime.UtcNow, DateTimeKind.Utc);
  68. }
  69. return lastUpdatedOn;
  70. }
  71. public async Task<Dictionary<string, DateTime>> GetLastUpdatedTimebyMachineIdAsync(IEnumerable<string> machineIds)
  72. {
  73. string cmd = """
  74. SELECT Id, MAX(LastUpdatedTime) as LastUpdatedTime
  75. FROM
  76. (
  77. SELECT BasicMachine.Id,
  78. CASE
  79. WHEN cs.CreatedOn > BasicMachine.CreatedOn
  80. THEN cs.CreatedOn
  81. WHEN BasicMachine.CreatedOn > BasicMachine.OfflineOn
  82. THEN BasicMachine.CreatedOn
  83. ELSE BasicMachine.OfflineOn
  84. END AS LastUpdatedTime
  85. FROM
  86. (SELECT Id, OfflineOn, CreatedOn, ChargeBoxId FROM [dbo].[Machine] WHERE Id IN @MachineIds) BasicMachine
  87. LEFT JOIN [dbo].[ConnectorStatus] cs
  88. On cs.ChargeBoxId = BasicMachine.ChargeBoxId
  89. ) t
  90. GROUP BY t.Id
  91. """;
  92. var parameters = new DynamicParameters();
  93. parameters.Add("@MachineIds", machineIds);
  94. using SqlConnection conn = await mainDbConneciotnFactory.CreateAsync();
  95. var tmp = await conn.QueryAsync<LastUpdatedTimeDto>(cmd, parameters);
  96. //return tmp.Select(x => new KeyValuePair<string, DateTime>(x.Id, x.LastUpdatedTime));
  97. return tmp.ToDictionary(x => x.Id, x => x.LastUpdatedTime);
  98. }
  99. public string GetMachineIdbyChargeBoxId(string chargeBoxId)
  100. {
  101. string machineId = string.Empty;
  102. using (SqlConnection conn = mainDbConneciotnFactory.Create())
  103. {
  104. var parameters = new DynamicParameters();
  105. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  106. string strSql = "Select Id from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
  107. machineId = conn.QueryFirstOrDefault<string>(strSql, parameters);
  108. }
  109. return machineId;
  110. }
  111. public string GetVersionbyChargeBoxId(string chargeBoxId)
  112. {
  113. string version = string.Empty;
  114. using (SqlConnection conn = mainDbConneciotnFactory.Create())
  115. {
  116. var parameters = new DynamicParameters();
  117. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  118. string strSql = "Select BoardVersions from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
  119. version = conn.QueryFirstOrDefault<string>(strSql, parameters);
  120. }
  121. return version;
  122. }
  123. public EVSE GetEVSEsbyChargeBoxId(string chargeboxid, DateTime? dateFrom, DateTime? dateTo)
  124. {
  125. string machineId = GetMachineIdbyChargeBoxId(chargeboxid);
  126. ChargePointService _CPService = serviceProvider.GetRequiredService<ChargePointService>();//new ChargePointService();
  127. var _machineUpdateOn = _CPService.GetLastUpdatedTimebyMachineId(machineId);
  128. var _machine = _CPService.GetBasicInfobyId(machineId);
  129. _machine.LastUpdated = _machineUpdateOn;
  130. return _machine;
  131. }
  132. public EVSE GetBasicInfobyId(string machineId)
  133. {
  134. return GetBasicInfobyIdAsync(machineId).Result;
  135. }
  136. public async Task<EVSE> GetBasicInfobyIdAsync(string machineId)
  137. {
  138. EVSE cp = new EVSE();
  139. Machine _machine = new Machine();
  140. using (SqlConnection conn = await mainDbConneciotnFactory.CreateAsync())
  141. {
  142. var parameters = new DynamicParameters();
  143. parameters.Add("@Id", machineId, DbType.String, ParameterDirection.Input);
  144. string strSql = "Select ChargeBoxId,ChargePointSerialNumber,ChargePointModel,RatedPower,Online,OfflineOn ,GunAmt,Latitude,Longitude,ConnectorType from [dbo].[Machine] where Id=@Id and IsDelete=0; ";
  145. _machine = await conn.QueryFirstOrDefaultAsync<Machine>(strSql, parameters);
  146. }
  147. if (_machine != null)
  148. {
  149. cp.ChargeBoxSystemID = _machine.ChargePointModel + _machine.ChargePointSerialNumber;
  150. cp.ChargeBoxId = _machine.ChargeBoxId;
  151. cp.NumberofConnectors = _machine.GunAmt;
  152. cp.RatedPower = _machine.RatedPower;
  153. cp.Status = _machine.Online ? Status.Available : Status.Offline;
  154. cp.LastUpdated = _machine.CreatedOn > _machine.OfflineOn ? _machine.CreatedOn : _machine.OfflineOn;
  155. cp.Coordinates = new GeoLocation() { Latitude = _machine.Latitude, Longitude = _machine.Longitude };
  156. cp.Connectors = new List<Connector>();
  157. var _Connectors = await GetConnectorStatusAsync(_machine.ChargeBoxId);
  158. for (int i = 1; i <= _machine.GunAmt; i++)
  159. {
  160. var _RefConnector = _Connectors.Where(x => x.ConnectorId == i).FirstOrDefault();
  161. cp.Connectors.Add(new Connector()
  162. {
  163. ConnectorId = _RefConnector is null ? i : _RefConnector.ConnectorId,
  164. Status = cp.Status == Status.Offline ? Status.Offline : _RefConnector is null ? Status.Unknown : ConvertConnectorStatus(_RefConnector.Status),
  165. ConnectorType = ConvertConnectorType(int.Parse(_machine.ConnectorType.Split(',')[i - 1])),
  166. FaultMessage = _RefConnector is null ? "Connector not found" : ((ChargePointErrorCode)_RefConnector.ChargePointErrorCodeId).ToString() + (string.IsNullOrEmpty(_RefConnector.VendorErrorCode) ? "" : "-" + _RefConnector.VendorErrorCode)
  167. });
  168. }
  169. }
  170. return _machine == null ? null : cp;
  171. }
  172. public async Task<Dictionary<string, EVSE>> GetBasicInfobyIdAsync(IEnumerable<string> machineIds)
  173. {
  174. Dictionary<string, EVSE> cps = new();
  175. Dictionary<string , Machine> _machines = new();
  176. var parameters = new DynamicParameters();
  177. parameters.Add("@MachineIds", machineIds);
  178. string strSql = """
  179. SELECT Id,ChargeBoxId,ChargePointSerialNumber,ChargePointModel,RatedPower,Online,OfflineOn ,GunAmt,Latitude,Longitude,ConnectorType
  180. FROM [dbo].[Machine]
  181. WHERE Id IN @MachineIds and IsDelete=0;
  182. """;
  183. using (SqlConnection conn = await mainDbConneciotnFactory.CreateAsync())
  184. {
  185. var result = await conn.QueryAsync<Machine>(strSql, parameters);
  186. _machines = result.ToDictionary(x => x.Id, x => x);
  187. }
  188. var MachineConnectors = await GetConnectorStatusAsync(machineIds);
  189. foreach (var machineId in machineIds)
  190. {
  191. if (!_machines.ContainsKey(machineId))
  192. {
  193. cps.Add(machineId, null);
  194. continue;
  195. }
  196. var _machine = _machines[machineId];
  197. EVSE cp = new();
  198. cp.ChargeBoxSystemID = _machine.ChargePointModel + _machine.ChargePointSerialNumber;
  199. cp.ChargeBoxId = _machine.ChargeBoxId;
  200. cp.NumberofConnectors = _machine.GunAmt;
  201. cp.RatedPower = _machine.RatedPower;
  202. cp.Status = _machine.Online ? Status.Available : Status.Offline;
  203. cp.LastUpdated = _machine.CreatedOn > _machine.OfflineOn ? _machine.CreatedOn : _machine.OfflineOn;
  204. cp.Coordinates = new GeoLocation() { Latitude = _machine.Latitude, Longitude = _machine.Longitude };
  205. cp.Connectors = new List<Connector>();
  206. //var _Connectors = await GetConnectorStatusAsync(_machine.ChargeBoxId);
  207. var _Connectors = MachineConnectors[machineId];
  208. for (int i = 1; i <= _machine.GunAmt; i++)
  209. {
  210. var _RefConnector = _Connectors.Where(x => x.ConnectorId == i).FirstOrDefault();
  211. cp.Connectors.Add(new Connector()
  212. {
  213. ConnectorId = _RefConnector is null ? i : _RefConnector.ConnectorId,
  214. Status = cp.Status == Status.Offline ? Status.Offline : _RefConnector is null ? Status.Unknown : ConvertConnectorStatus(_RefConnector.Status),
  215. ConnectorType = ConvertConnectorType(int.Parse(_machine.ConnectorType.Split(',')[i - 1])),
  216. FaultMessage = _RefConnector is null ? "Connector not found" : ((ChargePointErrorCode)_RefConnector.ChargePointErrorCodeId).ToString() + (string.IsNullOrEmpty(_RefConnector.VendorErrorCode) ? "" : "-" + _RefConnector.VendorErrorCode)
  217. });
  218. }
  219. cps.Add(_machine.Id, cp);
  220. }
  221. return cps;
  222. }
  223. public List<ConnectorStatus> GetConnectorStatus(string chargeBoxId)
  224. {
  225. return GetConnectorStatusAsync(chargeBoxId).Result;
  226. }
  227. public async Task<List<ConnectorStatus>> GetConnectorStatusAsync(string chargeBoxId)
  228. {
  229. List<ConnectorStatus> _Connectors = new List<ConnectorStatus>();
  230. using (SqlConnection conn = await mainDbConneciotnFactory.CreateAsync())
  231. {
  232. var parameters = new DynamicParameters();
  233. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  234. string strSql = "Select ConnectorId,Status,ChargePointErrorCodeId,VendorErrorCode from [dbo].[ConnectorStatus] where ChargeBoxId=@ChargeBoxId order by ConnectorId; ";
  235. _Connectors = (await conn.QueryAsync<ConnectorStatus>(strSql, parameters)).SkipWhile(x => x.ConnectorId == 0).ToList();
  236. }
  237. return _Connectors;
  238. }
  239. public async Task<Dictionary<string,List<ConnectorStatus>>> GetConnectorStatusAsync(IEnumerable<string> chargeBoxIds)
  240. {
  241. Dictionary<string, List<ConnectorStatus>> toReturn = new();
  242. IEnumerable<ConnectorStatus> _Connectors;// = new List<ConnectorStatus>();
  243. var parameters = new DynamicParameters();
  244. parameters.Add("@ChargeBoxIds", chargeBoxIds);
  245. string strSql = """
  246. SELECT ChargeBoxId,ConnectorId,Status,ChargePointErrorCodeId,VendorErrorCode
  247. FROM [dbo].[ConnectorStatus]
  248. WHERE ChargeBoxId IN @ChargeBoxIds
  249. ORDER BY ConnectorId;
  250. """;
  251. using (SqlConnection conn = await mainDbConneciotnFactory.CreateAsync())
  252. {
  253. _Connectors = (await conn.QueryAsync<ConnectorStatus>(strSql, parameters)).SkipWhile(x => x.ConnectorId == 0);//.ToList();
  254. }
  255. var tempDic = _Connectors.GroupBy(x => x.ChargeBoxId).ToDictionary(x => x.Key, x => x.ToList());
  256. foreach (var chargeBoxId in chargeBoxIds)
  257. {
  258. if (tempDic.ContainsKey(chargeBoxId))
  259. {
  260. toReturn.Add(chargeBoxId, tempDic[chargeBoxId]);
  261. continue;
  262. }
  263. toReturn.Add(chargeBoxId, new List<ConnectorStatus>());
  264. }
  265. return toReturn;
  266. //return _Connectors;
  267. }
  268. public int GetNumberofConnectors(string chargeBoxId)
  269. {
  270. int count = 0;
  271. if (string.IsNullOrEmpty(chargeBoxId)) return -1;
  272. if (Exists(chargeBoxId))
  273. {
  274. var parameters = new DynamicParameters();
  275. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  276. using (SqlConnection conn = mainDbConneciotnFactory.Create())
  277. {
  278. string strSql = "Select GunAmt from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
  279. count = conn.ExecuteScalarAsync<int>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout).Result;
  280. }
  281. }
  282. return count;
  283. }
  284. public bool Exists(string chargeBoxId)
  285. {
  286. bool exists = false;
  287. if (string.IsNullOrEmpty(chargeBoxId)) return exists;
  288. var parameters = new DynamicParameters();
  289. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  290. using (SqlConnection conn = mainDbConneciotnFactory.Create())
  291. {
  292. string strSql = "Select count(*) from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
  293. exists = conn.ExecuteScalar<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
  294. }
  295. return exists;
  296. }
  297. public int GetConnectorwithOngoingTransaction(string chargeBoxId, int transactionId)
  298. {
  299. int connectorId = -1;
  300. if (string.IsNullOrEmpty(chargeBoxId)) return connectorId;
  301. var parameters = new DynamicParameters();
  302. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  303. parameters.Add("@TransactionId", transactionId, DbType.Int32, ParameterDirection.Input);
  304. using (SqlConnection conn = mainDbConneciotnFactory.Create())
  305. {
  306. string strSql = "Select ConnectorId from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and Id= @TransactionId and StopTime='1991/01/01'; ";
  307. connectorId = conn.QueryFirstOrDefault<Int32>(strSql, parameters);
  308. }
  309. return connectorId;
  310. }
  311. public bool IsTransactionRunning(string chargeBoxId, int transactionId)
  312. {
  313. bool exists = false;
  314. if (string.IsNullOrEmpty(chargeBoxId)) return exists;
  315. var parameters = new DynamicParameters();
  316. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  317. parameters.Add("@TransactionId", transactionId, DbType.Int32, ParameterDirection.Input);
  318. using (SqlConnection conn = mainDbConneciotnFactory.Create())
  319. {
  320. string strSql = "Select Id from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and Id= @TransactionId and StopTime='1991/01/01'; ";
  321. int id = conn.QueryFirstOrDefault<Int32>(strSql, parameters);//.FirstOrDefault();
  322. exists = id > 0 ? true : false;
  323. }
  324. return exists;
  325. }
  326. /// <summary>
  327. /// 取得電樁或充電槍的狀態
  328. /// </summary>
  329. /// <param name="chargeBoxId">Charge Box Id</param>
  330. /// <param name="connectorId">充電槍號(0代表樁/槍號從1開始)</param>
  331. /// <returns>依據OCPP狀態回覆 NULL表示離線</returns>
  332. public ChargePointStatus? GetChargePointCurrentSatus(string chargeBoxId, int connectorId = 0)
  333. {
  334. ChargePointStatus? _status = null;
  335. if (string.IsNullOrEmpty(chargeBoxId)) return _status;
  336. var parameters = new DynamicParameters();
  337. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  338. parameters.Add("@ConnectorId", connectorId, DbType.Int32, ParameterDirection.Input);
  339. using (SqlConnection conn = mainDbConneciotnFactory.Create())
  340. {
  341. string strSql = "Select online from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
  342. bool online = conn.ExecuteScalar<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
  343. if (online)
  344. {
  345. string connectorStrSql = "Select Status from [dbo].[ConnectorStatus] where ChargeBoxId=@ChargeBoxId and ConnectorId=@ConnectorId; ";
  346. int _statusfromdb = conn.QueryFirstOrDefault<Int32>(connectorStrSql, parameters);//.FirstOrDefault();
  347. _status = (_statusfromdb <= 0 && connectorId == 0) ? ChargePointStatus.Available : (_statusfromdb <= 0 ? ((ChargePointStatus?)null) : ((ChargePointStatus)_statusfromdb));
  348. }
  349. }
  350. return _status;
  351. }
  352. public bool IsOnline(string chargeBoxId)
  353. {
  354. bool online = false;
  355. if (string.IsNullOrEmpty(chargeBoxId)) return online;
  356. var parameters = new DynamicParameters();
  357. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  358. using (SqlConnection conn = mainDbConneciotnFactory.Create())
  359. {
  360. string strSql = "Select online from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
  361. online = conn.ExecuteScalar<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
  362. }
  363. return online;
  364. }
  365. public ValueTask<bool> ContainsChargePointAsync(string chargeBoxId, string customerId)
  366. {
  367. return mainDbService.ContainsChargePointAsync(chargeBoxId, customerId);
  368. }
  369. public List<TransasctionData> GetActiveSessionInfo(string chargeBoxId, List<Measurand> requiredMeasurands, int? sessionId = null, string idTag = "")
  370. {
  371. return GetActiveSessionInfoAsync(chargeBoxId, requiredMeasurands, sessionId: sessionId,idTag: idTag).Result;
  372. }
  373. public async Task<List<TransasctionData>> GetActiveSessionInfoAsync(string chargeBoxId, List<Measurand> requiredMeasurands,string customerId = null, int? sessionId = null, string idTag = null)
  374. {
  375. List<ConnectorMeterValue> meterValues = new List<ConnectorMeterValue>();
  376. ConnectorMeterValueModel meterModel = null;
  377. List<TransasctionData> transactionDatas = null;
  378. if (string.IsNullOrEmpty(chargeBoxId))
  379. return transactionDatas;
  380. var watch = Stopwatch.StartNew();
  381. var times = new List<long>();
  382. transactionDatas = await mainDbService.GetActiveTransactionAsync(chargeBoxId, customerId, sessionId, idTag);
  383. times.Add(watch.ElapsedMilliseconds);
  384. if (transactionDatas.Count == 0)
  385. {
  386. return new List<TransasctionData>();
  387. }
  388. List<ConnectorMeterValueModel> metervalues = new();
  389. var minStartTime = transactionDatas.Select(x => x.StartTime).Min();
  390. while (minStartTime <= DateTime.Now)
  391. {
  392. var result = await meterValueDbService.GetChargeBoxTransactionMeterValues(
  393. minStartTime, chargeBoxId, transactionDatas.Select(x => x.Id), requiredMeasurands.Select(x => (int)x));
  394. metervalues.AddRange(result);
  395. minStartTime = minStartTime.AddDays(1);
  396. times.Add(watch.ElapsedMilliseconds);
  397. }
  398. var transIdMeterValuesPair = metervalues.GroupBy(x => x.TransactionId).ToDictionary(x => x.Key, x => x.ToList());
  399. foreach (var trans in transactionDatas)
  400. {
  401. if (trans.MeterValues == null)
  402. {
  403. trans.MeterValues = new List<ConnectorMeterValue>();
  404. }
  405. if (!transIdMeterValuesPair.ContainsKey(trans.Id))
  406. {
  407. continue;
  408. }
  409. var transMeterValues = transIdMeterValuesPair[trans.Id];
  410. foreach(var _meterModel in transMeterValues)
  411. {
  412. trans.MeterValues.Add(new ConnectorMeterValue()
  413. {
  414. ChargeBoxId = _meterModel.ChargeBoxId,
  415. ConnectorId = _meterModel.ConnectorId,
  416. CreatedOn = _meterModel.CreatedOn,
  417. Context = _meterModel.ContextId < 1 ? (ReadingContext?)null : (ReadingContext?)_meterModel.ContextId,
  418. Format = _meterModel.FormatId < 1 ? (ValueFormat?)null : (ValueFormat?)_meterModel.FormatId,
  419. Location = _meterModel.LocationId < 1 ? (Location?)null : (Location?)_meterModel.LocationId,
  420. Measurand = _meterModel.MeasurandId < 1 ? (Measurand?)null : (Measurand?)_meterModel.MeasurandId,
  421. Phase = _meterModel.PhaseId < 1 ? (Phase?)null : (Phase?)_meterModel.PhaseId,
  422. Unit = _meterModel.UnitId < 1 ? (UnitOfMeasure?)UnitOfMeasure.Wh : (UnitOfMeasure?)_meterModel.UnitId,
  423. Value = _meterModel.Value,
  424. TransactionId = _meterModel.TransactionId
  425. });
  426. }
  427. }
  428. times.Add(watch.ElapsedMilliseconds);
  429. watch.Stop();
  430. if (watch.ElapsedMilliseconds > 1000)
  431. {
  432. logger.LogWarning($"{nameof(GetActiveSessionInfoAsync)} {string.Join("/", times)}");
  433. }
  434. //for (int i = 0; i < requiredMeasurands.Count; i++)
  435. //{
  436. // for (int j = 0; j < transactionDatas.Count; j++)
  437. // {
  438. // var parameters = new DynamicParameters();
  439. // parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  440. // parameters.Add("@TransactionId", transactionDatas[j].Id, DbType.Int32, ParameterDirection.Input);
  441. // parameters.Add("@MeasurandId", requiredMeasurands[i], DbType.Int32, ParameterDirection.Input);
  442. // try
  443. // {
  444. // int retry = 0;
  445. // string date = DateTime.UtcNow.ToString("yyMMdd");
  446. // while (retry < 2)
  447. // {
  448. // retry++;
  449. // using (SqlConnection conn = await meterValueDbConnectionFactory.CreateAsync())
  450. // {
  451. // string strSql = $"""
  452. // SELECT Top(1) * from [dbo].[ConnectorMeterValueRecord{date}]
  453. // WHERE ChargeBoxId=@ChargeBoxId and TransactionId=@TransactionId and MeasurandId=@MeasurandId
  454. // order by CreatedOn desc;
  455. // """;
  456. // meterModel = await conn.QueryFirstOrDefaultAsync<ConnectorMeterValueModel>(strSql, parameters, commandTimeout:EVCBConfiguration.DB_DefaultConnectionTimeout);//.FirstOrDefault();
  457. // if (meterModel == null)
  458. // {
  459. // date = transactionDatas[j].StartTime.ToString("yyMMdd");
  460. // }
  461. // else
  462. // {
  463. // retry = 2;
  464. // }
  465. // }
  466. // }
  467. // if (meterModel != null)
  468. // {
  469. // if (transactionDatas[j].MeterValues == null)
  470. // {
  471. // transactionDatas[j].MeterValues = new List<ConnectorMeterValue>();
  472. // }
  473. // transactionDatas[j].MeterValues.Add(new ConnectorMeterValue()
  474. // {
  475. // ChargeBoxId = meterModel.ChargeBoxId,
  476. // ConnectorId = meterModel.ConnectorId,
  477. // CreatedOn = meterModel.CreatedOn,
  478. // Context = meterModel.ContextId < 1 ? (ReadingContext?)null : (ReadingContext?)meterModel.ContextId,
  479. // Format = meterModel.FormatId < 1 ? (ValueFormat?)null : (ValueFormat?)meterModel.FormatId,
  480. // Location = meterModel.LocationId < 1 ? (Location?)null : (Location?)meterModel.LocationId,
  481. // Measurand = meterModel.MeasurandId < 1 ? (Measurand?)null : (Measurand?)meterModel.MeasurandId,
  482. // Phase = meterModel.PhaseId < 1 ? (Phase?)null : (Phase?)meterModel.PhaseId,
  483. // Unit = meterModel.UnitId < 1 ? (UnitOfMeasure?)UnitOfMeasure.Wh : (UnitOfMeasure?)meterModel.UnitId,
  484. // Value = meterModel.Value,
  485. // TransactionId = meterModel.TransactionId
  486. // });
  487. // }
  488. // }
  489. // catch (Exception ex)
  490. // {
  491. // break;
  492. // }
  493. // }
  494. //}
  495. return transactionDatas;
  496. }
  497. public List<SessionDetail> GetSessionDetail(string chargeBoxId, int sessionId, string idTag, DateTime startTime, DateTime stopTime)
  498. {
  499. List<SessionDetail> detail = new List<SessionDetail>();
  500. List<TransactionRecordModel> transactionModel = null;
  501. if (string.IsNullOrEmpty(chargeBoxId)) return detail;
  502. var parameters = new DynamicParameters();
  503. try
  504. {
  505. bool restrictedRange = false;
  506. if (startTime != new DateTime(1991, 1, 1))
  507. {
  508. restrictedRange = true;
  509. parameters.Add("@startTime", startTime, DbType.DateTime, ParameterDirection.Input);
  510. parameters.Add("@stopTime", stopTime, DbType.DateTime, ParameterDirection.Input);
  511. }
  512. using (SqlConnection conn = mainDbConneciotnFactory.Create())
  513. {
  514. string strSql = string.Empty;
  515. if (sessionId >= 0 && string.IsNullOrEmpty(idTag))
  516. {
  517. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  518. parameters.Add("@TransactionId", sessionId, DbType.Int32, ParameterDirection.Input);
  519. strSql = "Select Top(1) * from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and Id=@TransactionId and StopTime!='1991-01-01 00:00:00.000' " + (restrictedRange ? " and StartTime >=@startTime and StartTime <=@stopTime" : "") + " Order by Id desc ;";
  520. }
  521. else if (!string.IsNullOrEmpty(idTag) && sessionId < 0)
  522. {
  523. if (!string.IsNullOrEmpty(chargeBoxId))
  524. {
  525. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  526. }
  527. parameters.Add("@StartIdTag", idTag, DbType.String, ParameterDirection.Input, 20);
  528. strSql = "Select * from [dbo].[TransactionRecord] where " + (!string.IsNullOrEmpty(chargeBoxId) ? " ChargeBoxId=@ChargeBoxId and " : "") + " StartIdTag=@StartIdTag and StopTime!='1991-01-01 00:00:00.000' " + (restrictedRange ? " and StartTime >=@startTime and StartTime <=@stopTime" : "") + " Order by Id desc ;";
  529. }
  530. else
  531. {
  532. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  533. strSql = "Select * from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and StopTime!='1991-01-01 00:00:00.000' " + (restrictedRange ? " and StartTime >=@startTime and StartTime <=@stopTime" : "") + " Order by Id desc ;";
  534. }
  535. transactionModel = conn.Query<TransactionRecordModel>(strSql, parameters, null, true, EVCBConfiguration.DB_DefaultConnectionTimeout).ToList();
  536. }
  537. foreach (var item in transactionModel)
  538. {
  539. detail.Add(new SessionDetail()
  540. {
  541. ChargeBoxId = item.ChargeBoxId,
  542. ConnectorId = (int)item.ConnectorId,
  543. IdTag = item.StartIdTag,
  544. MeterStart = item.MeterStart,
  545. MeterStop = item.MeterStop,
  546. StartTime = item.StartTime.ToString(EVCBConfiguration.UTC_DATETIMEFORMAT),
  547. StopTime = item.StopTime.ToString(EVCBConfiguration.UTC_DATETIMEFORMAT),
  548. StopReason = item.StopReasonId < 1 ? Reason.Local.ToString() : ((Reason)item.StopReasonId).ToString()
  549. });
  550. }
  551. }
  552. catch (Exception ex)
  553. {
  554. }
  555. return detail;
  556. }
  557. private Status ConvertConnectorStatus(int value)
  558. {
  559. Status result = Status.Unknown;
  560. switch (value)
  561. {
  562. case 1://Available
  563. {
  564. result = Status.Available;
  565. }
  566. break;
  567. case 2://Preparing
  568. {
  569. result = Status.Preparing;
  570. }
  571. break;
  572. case 3://Charging
  573. {
  574. result = Status.Charging;
  575. }
  576. break;
  577. case 4://SuspendedEVSE
  578. {
  579. result = Status.SuspendedEVSE;
  580. }
  581. break;
  582. case 5://SuspendedEV
  583. {
  584. result = Status.SuspendedEV;
  585. }
  586. break;
  587. case 6://Finishing
  588. {
  589. result = Status.Finishing;
  590. }
  591. break;
  592. case 8://Unavailable
  593. {
  594. result = Status.Unavailable;
  595. }
  596. break;
  597. case 7://Reserved
  598. {
  599. result = Status.Reserved;
  600. }
  601. break;
  602. case 9://Faulted
  603. {
  604. result = Status.Faulted;
  605. }
  606. break;
  607. default:
  608. break;
  609. }
  610. return result;
  611. }
  612. private ConnectorType ConvertConnectorType(int value)
  613. {
  614. ConnectorType result = (ConnectorType)value;
  615. return result;
  616. }
  617. }
  618. file class LastUpdatedTimeDto
  619. {
  620. public DateTime LastUpdatedTime { get; set;}
  621. public string Id;
  622. }
  623. }