ChargePointService.cs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  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, direction: ParameterDirection.Input,size: 36);
  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 async Task<string> GetMachineIdbyChargeBoxId(string customerId, 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. parameters.Add("@CustomerId", customerId, DbType.AnsiString, ParameterDirection.Input, 36);
  107. string strSql = """
  108. Select Id from [dbo].[Machine]
  109. where CustomerId=@CustomerId and ChargeBoxId=@ChargeBoxId and IsDelete=0;
  110. """;
  111. machineId = await conn.QueryFirstOrDefaultAsync<string>(strSql, parameters);
  112. }
  113. return machineId;
  114. }
  115. public string GetVersionbyChargeBoxId(string chargeBoxId)
  116. {
  117. string version = string.Empty;
  118. using (SqlConnection conn = mainDbConneciotnFactory.Create())
  119. {
  120. var parameters = new DynamicParameters();
  121. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  122. string strSql = "Select BoardVersions from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
  123. version = conn.QueryFirstOrDefault<string>(strSql, parameters);
  124. }
  125. return version;
  126. }
  127. public async Task<EVSE> GetEVSEsbyChargeBoxId(string customerId, string chargeboxid, DateTime? dateFrom, DateTime? dateTo)
  128. {
  129. string machineId = await GetMachineIdbyChargeBoxId(customerId, chargeboxid);
  130. if (string.IsNullOrEmpty(machineId))
  131. {
  132. return null;
  133. }
  134. var _machineUpdateOn = GetLastUpdatedTimebyMachineId(machineId);
  135. var _machine = GetBasicInfobyId(machineId);
  136. _machine.LastUpdated = _machineUpdateOn;
  137. return _machine;
  138. }
  139. public EVSE GetBasicInfobyId(string machineId)
  140. {
  141. return GetBasicInfobyIdAsync(machineId).Result;
  142. }
  143. public async Task<EVSE> GetBasicInfobyIdAsync(string machineId)
  144. {
  145. EVSE cp = new EVSE();
  146. Machine _machine = new Machine();
  147. using (SqlConnection conn = await mainDbConneciotnFactory.CreateAsync())
  148. {
  149. var parameters = new DynamicParameters();
  150. parameters.Add("@Id", machineId, DbType.String, ParameterDirection.Input);
  151. string strSql = "Select ChargeBoxId,ChargePointSerialNumber,ChargePointModel,RatedPower,Online,OfflineOn ,GunAmt,Latitude,Longitude,ConnectorType from [dbo].[Machine] where Id=@Id and IsDelete=0; ";
  152. _machine = await conn.QueryFirstOrDefaultAsync<Machine>(strSql, parameters);
  153. }
  154. if (_machine != null)
  155. {
  156. cp.ChargeBoxSystemID = _machine.ChargePointModel + _machine.ChargePointSerialNumber;
  157. cp.ChargeBoxId = _machine.ChargeBoxId;
  158. cp.NumberofConnectors = _machine.GunAmt;
  159. cp.RatedPower = _machine.RatedPower;
  160. cp.Status = _machine.Online ? Status.Available : Status.Offline;
  161. cp.LastUpdated = _machine.CreatedOn > _machine.OfflineOn ? _machine.CreatedOn : _machine.OfflineOn;
  162. cp.Coordinates = new GeoLocation() { Latitude = _machine.Latitude, Longitude = _machine.Longitude };
  163. cp.Connectors = new List<Connector>();
  164. var _Connectors = await GetConnectorStatusAsync(_machine.ChargeBoxId);
  165. for (int i = 1; i <= _machine.GunAmt; i++)
  166. {
  167. var _RefConnector = _Connectors.Where(x => x.ConnectorId == i).FirstOrDefault();
  168. cp.Connectors.Add(new Connector()
  169. {
  170. ConnectorId = _RefConnector is null ? i : _RefConnector.ConnectorId,
  171. Status = cp.Status == Status.Offline ? Status.Offline : _RefConnector is null ? Status.Unknown : ConvertConnectorStatus(_RefConnector.Status),
  172. ConnectorType = ConvertConnectorType(int.Parse(_machine.ConnectorType.Split(',')[i - 1])),
  173. FaultMessage = _RefConnector is null ? ChargePointErrorCode.NoError.ToString() : ((ChargePointErrorCode)_RefConnector.ChargePointErrorCodeId).ToString() + (string.IsNullOrEmpty(_RefConnector.VendorErrorCode) ? "" : "-" + _RefConnector.VendorErrorCode)
  174. });
  175. }
  176. }
  177. return _machine == null ? null : cp;
  178. }
  179. public async Task<Dictionary<string, EVSE>> GetBasicInfobyIdAsync(IEnumerable<string> machineIds)
  180. {
  181. Dictionary<string, EVSE> cps = new();
  182. Dictionary<string , Machine> _machines = new();
  183. var parameters = new DynamicParameters();
  184. parameters.Add("@MachineIds", machineIds, direction: ParameterDirection.Input, size: 36);
  185. string strSql = """
  186. SELECT Id,ChargeBoxId,ChargePointSerialNumber,ChargePointModel,RatedPower,Online,OfflineOn ,GunAmt,Latitude,Longitude,ConnectorType
  187. FROM [dbo].[Machine]
  188. WHERE Id IN @MachineIds and IsDelete=0;
  189. """;
  190. using (SqlConnection conn = await mainDbConneciotnFactory.CreateAsync())
  191. {
  192. var result = await conn.QueryAsync<Machine>(strSql, parameters);
  193. _machines = result.ToDictionary(x => x.Id, x => x);
  194. }
  195. var chargeBoxIds = _machines.Values.Select(x => x.ChargeBoxId);
  196. var MachineConnectors = await GetConnectorStatusAsync(chargeBoxIds);
  197. foreach (var machineId in machineIds)
  198. {
  199. if (!_machines.ContainsKey(machineId))
  200. {
  201. cps.Add(machineId, null);
  202. continue;
  203. }
  204. Machine _machine = _machines[machineId];
  205. EVSE cp = new();
  206. cp.ChargeBoxSystemID = _machine.ChargePointModel + _machine.ChargePointSerialNumber;
  207. cp.ChargeBoxId = _machine.ChargeBoxId;
  208. cp.NumberofConnectors = _machine.GunAmt;
  209. cp.RatedPower = _machine.RatedPower;
  210. cp.Status = _machine.Online ? Status.Available : Status.Offline;
  211. cp.LastUpdated = _machine.CreatedOn > _machine.OfflineOn ? _machine.CreatedOn : _machine.OfflineOn;
  212. cp.Coordinates = new GeoLocation() { Latitude = _machine.Latitude, Longitude = _machine.Longitude };
  213. cp.Connectors = new List<Connector>();
  214. //var _Connectors = await GetConnectorStatusAsync(_machine.ChargeBoxId);
  215. var _Connectors = MachineConnectors[_machine.ChargeBoxId];
  216. for (int i = 1; i <= _machine.GunAmt; i++)
  217. {
  218. var _RefConnector = _Connectors.Where(x => x.ConnectorId == i).FirstOrDefault();
  219. cp.Connectors.Add(new Connector()
  220. {
  221. ConnectorId = _RefConnector is null ? i : _RefConnector.ConnectorId,
  222. Status = cp.Status == Status.Offline ? Status.Offline : _RefConnector is null ? Status.Unknown : ConvertConnectorStatus(_RefConnector.Status),
  223. ConnectorType = ConvertConnectorType(int.Parse(_machine.ConnectorType.Split(',')[i - 1])),
  224. FaultMessage = _RefConnector is null ? "Connector not found" : ((ChargePointErrorCode)_RefConnector.ChargePointErrorCodeId).ToString() + (string.IsNullOrEmpty(_RefConnector.VendorErrorCode) ? "" : "-" + _RefConnector.VendorErrorCode)
  225. });
  226. }
  227. cps.Add(_machine.Id, cp);
  228. }
  229. return cps;
  230. }
  231. public List<ConnectorStatus> GetConnectorStatus(string chargeBoxId)
  232. {
  233. return GetConnectorStatusAsync(chargeBoxId).Result;
  234. }
  235. public async Task<List<ConnectorStatus>> GetConnectorStatusAsync(string chargeBoxId)
  236. {
  237. List<ConnectorStatus> _Connectors = new List<ConnectorStatus>();
  238. using (SqlConnection conn = await mainDbConneciotnFactory.CreateAsync())
  239. {
  240. var parameters = new DynamicParameters();
  241. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  242. string strSql = "Select ConnectorId,Status,ChargePointErrorCodeId,VendorErrorCode from [dbo].[ConnectorStatus] where ChargeBoxId=@ChargeBoxId order by ConnectorId; ";
  243. _Connectors = (await conn.QueryAsync<ConnectorStatus>(strSql, parameters)).SkipWhile(x => x.ConnectorId == 0).ToList();
  244. }
  245. return _Connectors;
  246. }
  247. public async Task<Dictionary<string,List<ConnectorStatus>>> GetConnectorStatusAsync(IEnumerable<string> chargeBoxIds)
  248. {
  249. Dictionary<string, List<ConnectorStatus>> toReturn = new();
  250. IEnumerable<ConnectorStatus> _Connectors;// = new List<ConnectorStatus>();
  251. var parameters = new DynamicParameters();
  252. parameters.Add("@ChargeBoxIds", chargeBoxIds, direction: ParameterDirection.Input, size: 50);
  253. string strSql = """
  254. SELECT ChargeBoxId,ConnectorId,Status,ChargePointErrorCodeId,VendorErrorCode
  255. FROM [dbo].[ConnectorStatus]
  256. WHERE ChargeBoxId IN @ChargeBoxIds
  257. ORDER BY ConnectorId;
  258. """;
  259. using (SqlConnection conn = await mainDbConneciotnFactory.CreateAsync())
  260. {
  261. _Connectors = (await conn.QueryAsync<ConnectorStatus>(strSql, parameters)).SkipWhile(x => x.ConnectorId == 0);//.ToList();
  262. }
  263. var tempDic = _Connectors.GroupBy(x => x.ChargeBoxId).ToDictionary(x => x.Key, x => x.ToList());
  264. foreach (var chargeBoxId in chargeBoxIds)
  265. {
  266. if (tempDic.ContainsKey(chargeBoxId))
  267. {
  268. toReturn.Add(chargeBoxId, tempDic[chargeBoxId]);
  269. continue;
  270. }
  271. toReturn.Add(chargeBoxId, new List<ConnectorStatus>());
  272. }
  273. return toReturn;
  274. //return _Connectors;
  275. }
  276. public int GetNumberofConnectors(string chargeBoxId)
  277. {
  278. return GetNumberofConnectorsAsync(chargeBoxId).Result;
  279. }
  280. public async Task<int> GetNumberofConnectorsAsync(string chargeBoxId)
  281. {
  282. int count = 0;
  283. if (string.IsNullOrEmpty(chargeBoxId)) return -1;
  284. if (Exists(chargeBoxId))
  285. {
  286. var parameters = new DynamicParameters();
  287. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  288. using (SqlConnection conn = await mainDbConneciotnFactory.CreateAsync())
  289. {
  290. string strSql = "Select GunAmt from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
  291. count = await conn.ExecuteScalarAsync<int>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
  292. }
  293. }
  294. return count;
  295. }
  296. public bool Exists(string chargeBoxId)
  297. {
  298. bool exists = false;
  299. if (string.IsNullOrEmpty(chargeBoxId)) return exists;
  300. var parameters = new DynamicParameters();
  301. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  302. using (SqlConnection conn = mainDbConneciotnFactory.Create())
  303. {
  304. string strSql = "Select count(*) from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
  305. exists = conn.ExecuteScalar<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
  306. }
  307. return exists;
  308. }
  309. public int? GetConnectorwithOngoingTransaction(string chargeBoxId, int transactionId)
  310. {
  311. return GetConnectorwithOngoingTransactionAsync(chargeBoxId, transactionId).Result;
  312. }
  313. public async Task<int?> GetConnectorwithOngoingTransactionAsync(string chargeBoxId, int transactionId)
  314. {
  315. int? connectorId = null;
  316. if (string.IsNullOrEmpty(chargeBoxId)) return connectorId;
  317. var parameters = new DynamicParameters();
  318. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  319. parameters.Add("@TransactionId", transactionId, DbType.Int32, ParameterDirection.Input);
  320. using (SqlConnection conn = await mainDbConneciotnFactory.CreateAsync())
  321. {
  322. string strSql = "Select ConnectorId from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and Id= @TransactionId and StopTime='1991/01/01'; ";
  323. connectorId = await conn.QueryFirstOrDefaultAsync<int?>(strSql, parameters);
  324. }
  325. return connectorId;
  326. }
  327. public bool IsTransactionRunning(string chargeBoxId, int transactionId)
  328. {
  329. return IsTransactionRunningAsync(chargeBoxId, transactionId).Result;
  330. }
  331. public async Task<bool> IsTransactionRunningAsync(string chargeBoxId, int transactionId)
  332. {
  333. bool exists = false;
  334. if (string.IsNullOrEmpty(chargeBoxId)) return exists;
  335. var parameters = new DynamicParameters();
  336. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  337. parameters.Add("@TransactionId", transactionId, DbType.Int32, ParameterDirection.Input);
  338. using (SqlConnection conn = await mainDbConneciotnFactory.CreateAsync())
  339. {
  340. string strSql = "Select Id from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and Id= @TransactionId and StopTime='1991/01/01'; ";
  341. int id = await conn.QueryFirstOrDefaultAsync<Int32>(strSql, parameters);//.FirstOrDefault();
  342. exists = id > 0 ? true : false;
  343. }
  344. return exists;
  345. }
  346. /// <summary>
  347. /// 取得電樁或充電槍的狀態
  348. /// </summary>
  349. /// <param name="chargeBoxId">Charge Box Id</param>
  350. /// <param name="connectorId">充電槍號(0代表樁/槍號從1開始)</param>
  351. /// <returns>依據OCPP狀態回覆 NULL表示離線</returns>
  352. public ChargePointStatus? GetChargePointCurrentSatus(string chargeBoxId, int connectorId = 0)
  353. {
  354. return GetChargePointCurrentSatusAsync(chargeBoxId, connectorId).Result;
  355. }
  356. public async Task<ChargePointStatus?> GetChargePointCurrentSatusAsync(string chargeBoxId, int connectorId = 0)
  357. {
  358. ChargePointStatus? _status = null;
  359. if (string.IsNullOrEmpty(chargeBoxId)) return _status;
  360. var parameters = new DynamicParameters();
  361. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  362. parameters.Add("@ConnectorId", connectorId, DbType.Int32, ParameterDirection.Input);
  363. using (SqlConnection conn = await mainDbConneciotnFactory.CreateAsync())
  364. {
  365. string strSql = "Select online from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
  366. bool online = await conn.ExecuteScalarAsync<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
  367. if (online)
  368. {
  369. string connectorStrSql = "Select Status from [dbo].[ConnectorStatus] where ChargeBoxId=@ChargeBoxId and ConnectorId=@ConnectorId; ";
  370. int _statusfromdb = await conn.QueryFirstOrDefaultAsync<Int32>(connectorStrSql, parameters);//.FirstOrDefault();
  371. _status = (_statusfromdb <= 0 && connectorId == 0) ? ChargePointStatus.Available : (_statusfromdb <= 0 ? ((ChargePointStatus?)null) : ((ChargePointStatus)_statusfromdb));
  372. }
  373. }
  374. return _status;
  375. }
  376. public bool IsOnline(string chargeBoxId)
  377. {
  378. return IsOnlineAsync(chargeBoxId).Result;
  379. }
  380. public async Task<bool> IsOnlineAsync(string chargeBoxId)
  381. {
  382. bool online = false;
  383. if (string.IsNullOrEmpty(chargeBoxId)) return online;
  384. var parameters = new DynamicParameters();
  385. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  386. using (SqlConnection conn = await mainDbConneciotnFactory.CreateAsync())
  387. {
  388. string strSql = "Select online from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
  389. online = await conn.ExecuteScalarAsync<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
  390. }
  391. return online;
  392. }
  393. public ValueTask<bool> ContainsChargePointAsync(string chargeBoxId, string customerId)
  394. {
  395. return mainDbService.ContainsChargePointAsync(chargeBoxId, customerId);
  396. }
  397. public List<TransasctionData> GetActiveSessionInfo(string chargeBoxId, List<Measurand> requiredMeasurands, int? sessionId = null, string idTag = "")
  398. {
  399. return GetActiveSessionInfoAsync(chargeBoxId, requiredMeasurands, sessionId: sessionId,idTag: idTag).Result;
  400. }
  401. public async Task<List<TransasctionData>> GetActiveSessionInfoAsync(string chargeBoxId, List<Measurand> requiredMeasurands,string customerId = null, int? sessionId = null, string idTag = null)
  402. {
  403. List<ConnectorMeterValue> meterValues = new List<ConnectorMeterValue>();
  404. ConnectorMeterValueModel meterModel = null;
  405. List<TransasctionData> transactionDatas = null;
  406. if (string.IsNullOrEmpty(chargeBoxId))
  407. return transactionDatas;
  408. var watch = Stopwatch.StartNew();
  409. var times = new List<long>();
  410. transactionDatas = await mainDbService.GetActiveTransactionAsync(chargeBoxId, customerId, sessionId, idTag);
  411. times.Add(watch.ElapsedMilliseconds);
  412. if (transactionDatas.Count == 0)
  413. {
  414. return new List<TransasctionData>();
  415. }
  416. List<ConnectorMeterValueModel> metervalues = new();
  417. var minStartTime = transactionDatas.Select(x => x.StartTime).Min();
  418. while (minStartTime <= DateTime.Now)
  419. {
  420. var result = await meterValueDbService.GetChargeBoxTransactionMeterValues(
  421. minStartTime, chargeBoxId, transactionDatas.Select(x => x.Id), requiredMeasurands.Select(x => (int)x));
  422. metervalues.AddRange(result);
  423. minStartTime = minStartTime.AddDays(1);
  424. times.Add(watch.ElapsedMilliseconds);
  425. }
  426. var transIdMeterValuesPair = metervalues.GroupBy(x => x.TransactionId).ToDictionary(x => x.Key, x => x.ToList());
  427. foreach (var trans in transactionDatas)
  428. {
  429. if (trans.MeterValues == null)
  430. {
  431. trans.MeterValues = new List<ConnectorMeterValue>();
  432. }
  433. if (!transIdMeterValuesPair.ContainsKey(trans.Id))
  434. {
  435. continue;
  436. }
  437. var transMeterValues = transIdMeterValuesPair[trans.Id];
  438. foreach(var _meterModel in transMeterValues)
  439. {
  440. trans.MeterValues.Add(new ConnectorMeterValue()
  441. {
  442. ChargeBoxId = _meterModel.ChargeBoxId,
  443. ConnectorId = _meterModel.ConnectorId,
  444. CreatedOn = _meterModel.CreatedOn,
  445. Context = _meterModel.ContextId < 1 ? (ReadingContext?)null : (ReadingContext?)_meterModel.ContextId,
  446. Format = _meterModel.FormatId < 1 ? (ValueFormat?)null : (ValueFormat?)_meterModel.FormatId,
  447. Location = _meterModel.LocationId < 1 ? (Location?)null : (Location?)_meterModel.LocationId,
  448. Measurand = _meterModel.MeasurandId < 1 ? (Measurand?)null : (Measurand?)_meterModel.MeasurandId,
  449. Phase = _meterModel.PhaseId < 1 ? (Phase?)null : (Phase?)_meterModel.PhaseId,
  450. Unit = _meterModel.UnitId < 1 ? (UnitOfMeasure?)UnitOfMeasure.Wh : (UnitOfMeasure?)_meterModel.UnitId,
  451. Value = _meterModel.Value,
  452. TransactionId = _meterModel.TransactionId
  453. });
  454. }
  455. }
  456. times.Add(watch.ElapsedMilliseconds);
  457. watch.Stop();
  458. if (watch.ElapsedMilliseconds > 1000)
  459. {
  460. logger.LogWarning($"{nameof(GetActiveSessionInfoAsync)} {string.Join("/", times)}");
  461. }
  462. //for (int i = 0; i < requiredMeasurands.Count; i++)
  463. //{
  464. // for (int j = 0; j < transactionDatas.Count; j++)
  465. // {
  466. // var parameters = new DynamicParameters();
  467. // parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  468. // parameters.Add("@TransactionId", transactionDatas[j].Id, DbType.Int32, ParameterDirection.Input);
  469. // parameters.Add("@MeasurandId", requiredMeasurands[i], DbType.Int32, ParameterDirection.Input);
  470. // try
  471. // {
  472. // int retry = 0;
  473. // string date = DateTime.UtcNow.ToString("yyMMdd");
  474. // while (retry < 2)
  475. // {
  476. // retry++;
  477. // using (SqlConnection conn = await meterValueDbConnectionFactory.CreateAsync())
  478. // {
  479. // string strSql = $"""
  480. // SELECT Top(1) * from [dbo].[ConnectorMeterValueRecord{date}]
  481. // WHERE ChargeBoxId=@ChargeBoxId and TransactionId=@TransactionId and MeasurandId=@MeasurandId
  482. // order by CreatedOn desc;
  483. // """;
  484. // meterModel = await conn.QueryFirstOrDefaultAsync<ConnectorMeterValueModel>(strSql, parameters, commandTimeout:EVCBConfiguration.DB_DefaultConnectionTimeout);//.FirstOrDefault();
  485. // if (meterModel == null)
  486. // {
  487. // date = transactionDatas[j].StartTime.ToString("yyMMdd");
  488. // }
  489. // else
  490. // {
  491. // retry = 2;
  492. // }
  493. // }
  494. // }
  495. // if (meterModel != null)
  496. // {
  497. // if (transactionDatas[j].MeterValues == null)
  498. // {
  499. // transactionDatas[j].MeterValues = new List<ConnectorMeterValue>();
  500. // }
  501. // transactionDatas[j].MeterValues.Add(new ConnectorMeterValue()
  502. // {
  503. // ChargeBoxId = meterModel.ChargeBoxId,
  504. // ConnectorId = meterModel.ConnectorId,
  505. // CreatedOn = meterModel.CreatedOn,
  506. // Context = meterModel.ContextId < 1 ? (ReadingContext?)null : (ReadingContext?)meterModel.ContextId,
  507. // Format = meterModel.FormatId < 1 ? (ValueFormat?)null : (ValueFormat?)meterModel.FormatId,
  508. // Location = meterModel.LocationId < 1 ? (Location?)null : (Location?)meterModel.LocationId,
  509. // Measurand = meterModel.MeasurandId < 1 ? (Measurand?)null : (Measurand?)meterModel.MeasurandId,
  510. // Phase = meterModel.PhaseId < 1 ? (Phase?)null : (Phase?)meterModel.PhaseId,
  511. // Unit = meterModel.UnitId < 1 ? (UnitOfMeasure?)UnitOfMeasure.Wh : (UnitOfMeasure?)meterModel.UnitId,
  512. // Value = meterModel.Value,
  513. // TransactionId = meterModel.TransactionId
  514. // });
  515. // }
  516. // }
  517. // catch (Exception ex)
  518. // {
  519. // break;
  520. // }
  521. // }
  522. //}
  523. return transactionDatas;
  524. }
  525. public List<SessionDetail> GetSessionDetail(string chargeBoxId, int sessionId, string idTag, DateTime startTime, DateTime stopTime)
  526. {
  527. List<SessionDetail> detail = new List<SessionDetail>();
  528. List<TransactionRecordModel> transactionModel = null;
  529. if (string.IsNullOrEmpty(chargeBoxId)) return detail;
  530. var parameters = new DynamicParameters();
  531. try
  532. {
  533. bool restrictedRange = false;
  534. if (startTime != new DateTime(1991, 1, 1))
  535. {
  536. restrictedRange = true;
  537. parameters.Add("@startTime", startTime, DbType.DateTime, ParameterDirection.Input);
  538. parameters.Add("@stopTime", stopTime, DbType.DateTime, ParameterDirection.Input);
  539. }
  540. using (SqlConnection conn = mainDbConneciotnFactory.Create())
  541. {
  542. string strSql = string.Empty;
  543. if (sessionId >= 0 && string.IsNullOrEmpty(idTag))
  544. {
  545. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  546. parameters.Add("@TransactionId", sessionId, DbType.Int32, ParameterDirection.Input);
  547. 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 ;";
  548. }
  549. else if (!string.IsNullOrEmpty(idTag) && sessionId < 0)
  550. {
  551. if (!string.IsNullOrEmpty(chargeBoxId))
  552. {
  553. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  554. }
  555. parameters.Add("@StartIdTag", idTag, DbType.String, ParameterDirection.Input, 20);
  556. 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 ;";
  557. }
  558. else
  559. {
  560. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  561. 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 ;";
  562. }
  563. transactionModel = conn.Query<TransactionRecordModel>(strSql, parameters, null, true, EVCBConfiguration.DB_DefaultConnectionTimeout).ToList();
  564. }
  565. foreach (var item in transactionModel)
  566. {
  567. detail.Add(new SessionDetail()
  568. {
  569. SessionId = item.Id.ToString(),
  570. ChargeBoxId = item.ChargeBoxId,
  571. ConnectorId = (int)item.ConnectorId,
  572. IdTag = item.StartIdTag,
  573. MeterStart = item.MeterStart,
  574. MeterStop = item.MeterStop,
  575. StartTime = item.StartTime.ToString(EVCBConfiguration.UTC_DATETIMEFORMAT),
  576. StopTime = item.StopTime.ToString(EVCBConfiguration.UTC_DATETIMEFORMAT),
  577. StopReason = item.StopReasonId < 1 ? Reason.Local.ToString() : ((Reason)item.StopReasonId).ToString()
  578. });
  579. }
  580. }
  581. catch (Exception ex)
  582. {
  583. }
  584. return detail;
  585. }
  586. private Status ConvertConnectorStatus(int value)
  587. {
  588. Status result = Status.Unknown;
  589. switch (value)
  590. {
  591. case 1://Available
  592. {
  593. result = Status.Available;
  594. }
  595. break;
  596. case 2://Preparing
  597. {
  598. result = Status.Preparing;
  599. }
  600. break;
  601. case 3://Charging
  602. {
  603. result = Status.Charging;
  604. }
  605. break;
  606. case 4://SuspendedEVSE
  607. {
  608. result = Status.SuspendedEVSE;
  609. }
  610. break;
  611. case 5://SuspendedEV
  612. {
  613. result = Status.SuspendedEV;
  614. }
  615. break;
  616. case 6://Finishing
  617. {
  618. result = Status.Finishing;
  619. }
  620. break;
  621. case 8://Unavailable
  622. {
  623. result = Status.Unavailable;
  624. }
  625. break;
  626. case 7://Reserved
  627. {
  628. result = Status.Reserved;
  629. }
  630. break;
  631. case 9://Faulted
  632. {
  633. result = Status.Faulted;
  634. }
  635. break;
  636. default:
  637. break;
  638. }
  639. return result;
  640. }
  641. private ConnectorType ConvertConnectorType(int value)
  642. {
  643. ConnectorType result = (ConnectorType)value;
  644. return result;
  645. }
  646. }
  647. file class LastUpdatedTimeDto
  648. {
  649. public DateTime LastUpdatedTime { get; set;}
  650. public string Id;
  651. }
  652. }