MainDbService.cs 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497
  1. using Dapper;
  2. using EVCB_OCPP.Domain;
  3. using EVCB_OCPP.Domain.ConnectionFactory;
  4. using EVCB_OCPP.Domain.Models.MainDb;
  5. using EVCB_OCPP.Packet.Features;
  6. using EVCB_OCPP.Packet.Messages.Core;
  7. using EVCB_OCPP.Packet.Messages.FirmwareManagement;
  8. using EVCB_OCPP.Packet.Messages.LocalAuthListManagement;
  9. using EVCB_OCPP.Packet.Messages.RemoteTrigger;
  10. using EVCB_OCPP.Packet.Messages.Reservation;
  11. using EVCB_OCPP.Packet.Messages.Security;
  12. using EVCB_OCPP.Packet.Messages.SmartCharging;
  13. using EVCB_OCPP.WSServer.Helper;
  14. using Microsoft.Data.SqlClient;
  15. using Microsoft.EntityFrameworkCore;
  16. using Microsoft.Extensions.Caching.Memory;
  17. using Microsoft.Extensions.Configuration;
  18. using Microsoft.Extensions.Logging;
  19. using Newtonsoft.Json;
  20. using OCPPPackage.Profiles;
  21. using System.Data;
  22. namespace EVCB_OCPP.WSServer.Service.DbService;
  23. public interface IMainDbService
  24. {
  25. Task<string> GetMachineAuthorizationKey(string ChargeBoxId, CancellationToken token = default);
  26. Task<string> GetMachineConfiguration(string ChargeBoxId, string configName, CancellationToken token = default);
  27. Task<string> GetMachineHeartbeatInterval(string ChargeBoxId);
  28. Task<MachineAndCustomerInfo> GetMachineIdAndCustomerInfo(string ChargeBoxId, CancellationToken token = default);
  29. Task<string> GetMachineSecurityProfile(string ChargeBoxId, CancellationToken token = default);
  30. Task UpdateMachineBasicInfo(string ChargeBoxId, Machine machine);
  31. Task AddOCMF(Ocmf oCMF);
  32. ValueTask<ConnectorStatus> GetConnectorStatus(string ChargeBoxId, int ConnectorId);
  33. Task UpdateConnectorStatus(string Id, ConnectorStatus connectorStatus);
  34. ValueTask AddConnectorStatus(string ChargeBoxId, byte ConnectorId, DateTime CreatedOn, int Status,
  35. int ChargePointErrorCodeId, string ErrorInfo, string VendorId, string VendorErrorCode);
  36. Task<string> AddServerMessage(ServerMessage message);
  37. Task<string> AddServerMessage(string ChargeBoxId, string OutAction, object OutRequest, string CreatedBy = "", DateTime? CreatedOn = null, string SerialNo = "", string InMessage = "");
  38. ValueTask AddMachineError(byte ConnectorId, DateTime CreatedOn, int Status, string ChargeBoxId, int ErrorCodeId, string ErrorInfo, int PreStatus, string VendorErrorCode, string VendorId);
  39. ValueTask FillupFinishedTimetoMachineError(string ChargeBoxId, byte ConnectorId, DateTime FinishedOn);
  40. ValueTask<Customer> GetCustomer(string id, CancellationToken token = default);
  41. ValueTask<Customer> GetCustomer(Guid id, CancellationToken token = default);
  42. Task<Guid> GetCustomerIdByChargeBoxId(string chargeboxId);
  43. Task<int?> TryGetDuplicatedTransactionId(string chargeBoxId, Guid customerId, int connectorId, DateTime timestamp);
  44. Task<int> AddNewTransactionRecord(TransactionRecord newTransaction);
  45. Task<TransactionRecord> GetTransactionForStopTransaction(int transactionId, string chargeBoxId);
  46. Task UpdateTransaction(int transactionId, int meterStop, DateTime stopTime, int stopReasonId, string stopReason, string stopIdTag, string receipt, int cost);
  47. Task<bool> UpdateHeartBeats(IEnumerable<Machine> heartBeatsData);
  48. Task<bool> UpdateHeartBeats(List<string> machineIds);
  49. Task UpdateTransactionSOC(int id, string startsoc, string stopsoc);
  50. Task UpdateMachineConnectionType(string chargeBoxId, int v);
  51. Task<string> GetMachineConnectorType(string chargeBoxId, CancellationToken token = default);
  52. Task SetMachineConnectionType(string chargeBoxId, int connectionType, CancellationToken token = default);
  53. Task UpdateServerMessageUpdateTime(int table_id);
  54. Task AddMachineConfiguration(string chargeBoxId, string key, string value, bool isReadOnly, bool isExist = true);
  55. Task UpdateMachineConfiguration(string chargeBoxId, string item, string empty, bool isReadOnly, bool isExists = true);
  56. Task<List<MachineConfigurations>> GetMachineConfiguration(string chargeBoxId);
  57. Task<object> TryGetResponseFromDb(string msgId, CancellationToken token = default);
  58. Task InsertOrUpdateTransactionPeriodEnergy(int txId, Dictionary<string, decimal> periodEnergy);
  59. Task<Dictionary<string, decimal>> GetTransactionPeriodEnergy(int transactionId);
  60. Task<bool> UpdateCustomId(string customId, string chargeboxId);
  61. Task SetTransactionBillingDone(int txId, decimal cost, string receipt);
  62. }
  63. public class MainDbService : IMainDbService
  64. {
  65. public MainDbService(
  66. IDbContextFactory<MainDBContext> contextFactory,
  67. ISqlConnectionFactory<MainDBContext> sqlConnectionFactory,
  68. IMemoryCache memoryCache,
  69. IConfiguration configuration,
  70. ILoggerFactory loggerFactory,
  71. ILogger<MainDbService> logger)
  72. {
  73. this.contextFactory = contextFactory;
  74. this.sqlConnectionFactory = sqlConnectionFactory;
  75. this.memoryCache = memoryCache;
  76. this.loggerFactory = loggerFactory;
  77. this.logger = logger;
  78. var startupLimit = GetStartupLimit(configuration);
  79. //this.connectionString = configuration.GetConnectionString("MainDBContext");
  80. startupSemaphore = new(startupLimit);
  81. var opLimit = GetOpLimit(configuration);
  82. opSemaphore = new SemaphoreSlim(opLimit);
  83. InitUpdateConnectorStatusHandler();
  84. InitUpdateMachineBasicInfoHandler();
  85. InitAddServerMessageHandler();
  86. InitUpdateServerMessageUpdateOnHandler();
  87. InitGetMachineConfigurationHandler();
  88. InitUpdateErrorFinishedOnHandler();
  89. }
  90. private const string CustomerMemCacheKeyFromat = "Customer_{0}";
  91. //private const string ChargeBoxConnectorIdMemCacheKeyFromat = "Connector_{0}{1}";
  92. private readonly IDbContextFactory<MainDBContext> contextFactory;
  93. private readonly ISqlConnectionFactory<MainDBContext> sqlConnectionFactory;
  94. private readonly IMemoryCache memoryCache;
  95. private readonly ILoggerFactory loggerFactory;
  96. private readonly ILogger<MainDbService> logger;
  97. //private string connectionString;
  98. private readonly QueueSemaphore startupSemaphore;
  99. private readonly SemaphoreSlim opSemaphore;
  100. private GroupHandler<StatusNotificationParam> statusNotificationHandler;
  101. private GroupHandler<UpdateMachineBasicInfoParam> updateMachineBasicInfoHandler;
  102. private GroupHandler<ServerMessage, string> addServerMessageHandler;
  103. private GroupHandler<int> updateServerMessageUpdateOnHandler;
  104. private GroupHandler<string, List<MachineConfigurations>> getMachineConfigurationHandler;
  105. private GroupHandler<UpdateErrofFinishedOnParam> updateErrorFinishedOnHandler;
  106. public async Task<MachineAndCustomerInfo> GetMachineIdAndCustomerInfo(string ChargeBoxId, CancellationToken token = default)
  107. {
  108. using var semaphoreWrapper = await startupSemaphore.GetToken();
  109. using var db = await contextFactory.CreateDbContextAsync(token);
  110. var machine = await db.Machine.Where(x => x.ChargeBoxId == ChargeBoxId && x.IsDelete == false).Select(x => new { x.CustomerId, x.Id }).AsNoTracking().FirstOrDefaultAsync(token);
  111. if (machine == null)
  112. {
  113. return new MachineAndCustomerInfo(string.Empty, Guid.Empty, "Unknown");
  114. }
  115. //var customerName = await db.Customer.Where(x => x.Id == machine.CustomerId).Select(x => x.Name).FirstOrDefaultAsync();
  116. var customer = await GetCustomer(machine.CustomerId, token);
  117. var customerName = customer?.Name;
  118. return new MachineAndCustomerInfo(machine.Id, machine.CustomerId, customerName);
  119. }
  120. public Task<List<MachineConfigurations>> GetMachineConfiguration(string chargeBoxId)
  121. {
  122. return getMachineConfigurationHandler.HandleAsync(chargeBoxId);
  123. }
  124. public async Task<string> GetMachineConfiguration(string ChargeBoxId, string configName, CancellationToken token = default)
  125. {
  126. using var semaphoreWrapper = await startupSemaphore.GetToken();
  127. using var db = await contextFactory.CreateDbContextAsync(token);
  128. return await db.MachineConfigurations
  129. .Where(x => x.ChargeBoxId == ChargeBoxId && x.ConfigureName == configName)
  130. .Select(x => x.ConfigureSetting).FirstOrDefaultAsync(token);
  131. }
  132. public Task<string> GetMachineSecurityProfile(string ChargeBoxId, CancellationToken token = default)
  133. {
  134. return GetMachineConfiguration(ChargeBoxId, StandardConfiguration.SecurityProfile, token);
  135. }
  136. public Task<string> GetMachineAuthorizationKey(string ChargeBoxId, CancellationToken token = default)
  137. {
  138. return GetMachineConfiguration(ChargeBoxId, StandardConfiguration.AuthorizationKey, token);
  139. }
  140. public Task<string> GetMachineHeartbeatInterval(string ChargeBoxId)
  141. {
  142. return GetMachineConfiguration(ChargeBoxId, StandardConfiguration.HeartbeatInterval);
  143. }
  144. public Task UpdateMachineBasicInfo(string ChargeBoxId, Machine machine)
  145. {
  146. //return UpdateMachineBasicInfoEF(ChargeBoxId, machine);
  147. return updateMachineBasicInfoHandler.HandleAsync(new UpdateMachineBasicInfoParam(ChargeBoxId, machine));
  148. }
  149. public async Task AddOCMF(Ocmf oCMF)
  150. {
  151. using var db = await contextFactory.CreateDbContextAsync();
  152. await db.Ocmf.AddAsync(oCMF);
  153. await db.SaveChangesAsync();
  154. }
  155. public async ValueTask AddConnectorStatus(
  156. string ChargeBoxId, byte ConnectorId, DateTime CreatedOn, int Status,
  157. int ChargePointErrorCodeId, string ErrorInfo, string VendorId, string VendorErrorCode)
  158. {
  159. using var db = await contextFactory.CreateDbContextAsync();
  160. var _currentStatus = new ConnectorStatus()
  161. {
  162. ChargeBoxId = ChargeBoxId,
  163. ConnectorId = ConnectorId,
  164. CreatedOn = CreatedOn,
  165. Status = Status,
  166. ChargePointErrorCodeId = ChargePointErrorCodeId,
  167. ErrorInfo = ErrorInfo,
  168. VendorId = VendorId,
  169. VendorErrorCode = VendorErrorCode,
  170. Id = Guid.NewGuid().ToString()
  171. };
  172. await db.ConnectorStatus.AddAsync(_currentStatus);
  173. await db.SaveChangesAsync();
  174. //memoryCache.Set(
  175. // string.Format(ChargeBoxConnectorIdMemCacheKeyFromat, ChargeBoxId, ConnectorId)
  176. // , _currentStatus, TimeSpan.FromHours(12));
  177. }
  178. public async ValueTask<ConnectorStatus> GetConnectorStatus(string ChargeBoxId, int ConnectorId)
  179. {
  180. //var key = string.Format(ChargeBoxConnectorIdMemCacheKeyFromat, ChargeBoxId, ConnectorId);
  181. //if (memoryCache.TryGetValue<ConnectorStatus>(key, out var status))
  182. //{
  183. // return status;
  184. //}
  185. using var db = await contextFactory.CreateDbContextAsync();
  186. var statusFromDb = await db.ConnectorStatus.Where(x => x.ChargeBoxId == ChargeBoxId
  187. && x.ConnectorId == ConnectorId).AsNoTracking().FirstOrDefaultAsync();
  188. //memoryCache.Set(key, statusFromDb, TimeSpan.FromHours(12));
  189. return statusFromDb;
  190. }
  191. public async Task UpdateConnectorStatus(string Id, ConnectorStatus Status)
  192. {
  193. //await statusNotificationHandler.HandleAsync(new StatusNotificationParam(Id, Status));
  194. //await UpdateConnectorStatusEF(Id, Status);
  195. await UpdateConnectorStatusDapper(Id, Status);
  196. //var key = string.Format(ChargeBoxConnectorIdMemCacheKeyFromat, Status.ChargeBoxId, Status.ConnectorId);
  197. //memoryCache.Set(key, Status, TimeSpan.FromHours(12));
  198. return;
  199. }
  200. public Task<Guid> GetCustomerIdByChargeBoxId(string chargeboxId)
  201. {
  202. //return GetCustomerIdByChargeBoxIdEF(chargeboxId);
  203. return GetCustomerIdByChargeBoxIdDapper(chargeboxId);
  204. }
  205. public Task<int?> TryGetDuplicatedTransactionId(string chargeBoxId, Guid customerId, int connectorId, DateTime timestamp)
  206. {
  207. //return TryGetDuplicatedTransactionIdEF(chargeBoxId, customerId, connectorId, timestamp);
  208. return TryGetDuplicatedTransactionIdDapper(chargeBoxId, customerId, connectorId, timestamp);
  209. }
  210. public ValueTask AddMachineError(byte ConnectorId, DateTime CreatedOn, int Status, string ChargeBoxId,
  211. int ErrorCodeId, string ErrorInfo, int PreStatus, string VendorErrorCode, string VendorId)
  212. {
  213. //return AddMachineErrorEF(ConnectorId, CreatedOn, Status, ChargeBoxId, ErrorCodeId, ErrorInfo, PreStatus, VendorErrorCode, VendorId);
  214. return AddMachineErrorDapper(ConnectorId, CreatedOn, Status, ChargeBoxId, ErrorCodeId, ErrorInfo, PreStatus, VendorErrorCode, VendorId);
  215. }
  216. public ValueTask FillupFinishedTimetoMachineError(string ChargeBoxId, byte ConnectorId, DateTime FinishedOn)
  217. {
  218. return AddFinishedTimetoMachineErrorDapper(ChargeBoxId, ConnectorId, FinishedOn);
  219. }
  220. public async Task<string> AddServerMessage(string ChargeBoxId, string OutAction, object OutRequest, string CreatedBy, DateTime? CreatedOn = null, string SerialNo = "", string InMessage = "")
  221. {
  222. if (string.IsNullOrEmpty(CreatedBy))
  223. {
  224. CreatedBy = "Server";
  225. }
  226. if (string.IsNullOrEmpty(SerialNo))
  227. {
  228. SerialNo = Guid.NewGuid().ToString();
  229. }
  230. var _CreatedOn = CreatedOn ?? DateTime.UtcNow;
  231. string _OutRequest = "";
  232. if (OutRequest is not null)
  233. {
  234. _OutRequest = JsonConvert.SerializeObject(
  235. OutRequest,
  236. new JsonSerializerSettings()
  237. {
  238. NullValueHandling = NullValueHandling.Ignore,
  239. Formatting = Formatting.None
  240. });
  241. }
  242. var data = new ServerMessage()
  243. {
  244. ChargeBoxId = ChargeBoxId,
  245. CreatedBy = CreatedBy,
  246. CreatedOn = _CreatedOn,
  247. OutAction = OutAction,
  248. OutRequest = _OutRequest,
  249. SerialNo = SerialNo,
  250. InMessage = InMessage
  251. };
  252. await AddServerMessage(data);
  253. return SerialNo;
  254. }
  255. public Task<string> AddServerMessage(ServerMessage message)
  256. {
  257. //return AddServerMessageEF(message);
  258. return addServerMessageHandler.HandleAsync(message);
  259. //var id = message.SerialNo;
  260. //await AddServerMessageDapper(message);
  261. //return id;
  262. }
  263. public ValueTask<Customer> GetCustomer(string id, CancellationToken token = default)
  264. => GetCustomer(new Guid(id), token);
  265. public async ValueTask<Customer> GetCustomer(Guid id, CancellationToken token = default)
  266. {
  267. var key = string.Format(CustomerMemCacheKeyFromat, id);
  268. if (memoryCache.TryGetValue<Customer>(key, out var customer))
  269. {
  270. return customer;
  271. }
  272. Customer toReturn = null;
  273. using (var db = await contextFactory.CreateDbContextAsync(token))
  274. {
  275. toReturn = await db.Customer.FirstOrDefaultAsync(x => x.Id == id, token);
  276. }
  277. if (toReturn is not null)
  278. {
  279. memoryCache.Set(key, toReturn, TimeSpan.FromSeconds(15));
  280. }
  281. return toReturn;
  282. }
  283. public Task<int> AddNewTransactionRecord(TransactionRecord newTransaction)
  284. {
  285. //return AddNewTransactionRecordEF(newTransaction);
  286. return AddNewTransactionRecordDapper(newTransaction);
  287. }
  288. public Task<TransactionRecord> GetTransactionForStopTransaction(int transactionId, string chargeBoxId)
  289. {
  290. //return GetTransactionForStopTransactionEF(transactionId, chargeBoxId);
  291. return GetTransactionForStopTransactionDapper(transactionId, chargeBoxId);
  292. }
  293. public Task UpdateTransaction(int transactionId, int meterStop, DateTime stopTime, int stopReasonId, string stopReason, string stopIdTag, string receipt, int cost)
  294. {
  295. //return UpdateTransactionEF(transactionId, meterStop, stopTime, stopReasonId, stopReason, stopIdTag, receipt, cost);
  296. return UpdateTransactionDapper(transactionId, meterStop, stopTime, stopReasonId, stopReason, stopIdTag, receipt, cost);
  297. }
  298. public async Task UpdateTransactionSOC(int id, string startSOC, string stopSOC)
  299. {
  300. var parameters = new DynamicParameters();
  301. parameters.Add("@TransactionId", id, DbType.Int32, ParameterDirection.Input);
  302. parameters.Add("@StartSOC", startSOC, DbType.String, ParameterDirection.Input, 3);
  303. parameters.Add("@StopSOC", stopSOC, DbType.String, ParameterDirection.Input, 3);
  304. using var conn = await sqlConnectionFactory.CreateAsync();
  305. var resultCnt = await conn.ExecuteAsync("""
  306. UPDATE TransactionRecord
  307. SET StartSOC = @StartSOC, StopSOC = @StopSOC
  308. WHERE Id = @TransactionId
  309. """, parameters);
  310. if (resultCnt != 1)
  311. {
  312. throw new Exception("Update over one columes");
  313. }
  314. return;
  315. }
  316. public Task UpdateServerMessageUpdateTime(int table_id)
  317. {
  318. return updateServerMessageUpdateOnHandler.HandleAsync(table_id);
  319. }
  320. public async Task AddMachineConfiguration(string chargeBoxId, string key, string value, bool isReadOnly, bool isExists = true)
  321. {
  322. using var db = await contextFactory.CreateDbContextAsync();
  323. await db.MachineConfigurations.AddAsync(new MachineConfigurations()
  324. {
  325. ChargeBoxId = chargeBoxId,
  326. ConfigureName = key,
  327. ReadOnly = isReadOnly,
  328. ConfigureSetting = string.IsNullOrEmpty(value) ? string.Empty : value,
  329. Exists = isExists
  330. });
  331. await db.SaveChangesAsync();
  332. }
  333. private async Task UpdateTransactionEF(int transactionId, int meterStop, DateTime stopTime, int stopReasonId, string stopReason, string stopIdTag, string receipt, int cost)
  334. {
  335. using var db = await contextFactory.CreateDbContextAsync();
  336. var _transaction = db.TransactionRecord.Where(x => x.Id == transactionId //&& x.ChargeBoxId == session.ChargeBoxId
  337. ).FirstOrDefault();
  338. _transaction.MeterStop = meterStop;
  339. _transaction.StopTime = stopTime;
  340. _transaction.StopReasonId = stopReasonId;
  341. _transaction.StopReason = stopReason;
  342. _transaction.StopIdTag = stopIdTag;
  343. _transaction.Receipt = receipt;
  344. _transaction.Cost = cost;
  345. //await db.SaveChangesAsync();
  346. await db.SaveChangesAsync();
  347. }
  348. public async Task UpdateMachineConfiguration(string chargeBoxId, string item, string value, bool isReadonly, bool isExists = true)
  349. {
  350. using var db = await contextFactory.CreateDbContextAsync();
  351. var config = await db.MachineConfigurations.FirstOrDefaultAsync(x => x.ChargeBoxId == chargeBoxId && x.ConfigureName == item);
  352. if (config is null)
  353. {
  354. return;
  355. }
  356. config.ConfigureSetting = value;
  357. config.ReadOnly = isReadonly;
  358. config.Exists = isExists;
  359. await db.SaveChangesAsync();
  360. }
  361. private async Task UpdateTransactionDapper(int transactionId, int meterStop, DateTime stopTime, int stopReasonId, string stopReason, string stopIdTag, string receipt, int cost)
  362. {
  363. var parameters = new DynamicParameters();
  364. parameters.Add("@TransactionId", transactionId, DbType.Int32, ParameterDirection.Input);
  365. parameters.Add("@MeterStop", meterStop, DbType.Decimal, ParameterDirection.Input, precision: 18, scale: 2);
  366. parameters.Add("@StopTime", stopTime, DbType.DateTime, ParameterDirection.Input);
  367. parameters.Add("@StopReasonId", stopReasonId, DbType.Int32, ParameterDirection.Input);
  368. parameters.Add("@StopReason", stopReason, DbType.String, ParameterDirection.Input, 60);
  369. parameters.Add("@StopIdTag", stopIdTag, DbType.String, ParameterDirection.Input, 20);
  370. parameters.Add("@Receipt", receipt, DbType.String, ParameterDirection.Input, 3000);
  371. parameters.Add("@Cost", cost, DbType.Decimal, ParameterDirection.Input, precision: 18, scale: 2);
  372. using var conn = await sqlConnectionFactory.CreateAsync();
  373. var resultCnt = await conn.ExecuteAsync("""
  374. UPDATE TransactionRecord
  375. SET MeterStop = @MeterStop, StopTime = @StopTime, StopReasonId = @StopReasonId,
  376. StopReason = @StopReason, StopIdTag = @StopIdTag, Receipt = @Receipt, Cost = @Cost
  377. WHERE Id = @TransactionId
  378. """, parameters);
  379. if (resultCnt != 1)
  380. {
  381. throw new Exception("Update over one columes");
  382. }
  383. return;
  384. }
  385. public Task<bool> UpdateHeartBeats(IEnumerable<Machine> heartBeatsData)
  386. {
  387. //return UpdateHeartBeatsEF(heartBeatsData);
  388. return UpdateHeartBeatsDapper(heartBeatsData);
  389. }
  390. public Task<bool> UpdateHeartBeats(List<string> machineIds)
  391. {
  392. return UpdateHeartBeatsDapper(machineIds);
  393. }
  394. public async Task<bool> UpdateCustomId(string customId,string chargeboxId)
  395. {
  396. using var conn = await sqlConnectionFactory.CreateAsync();
  397. try
  398. {
  399. var parameters = new DynamicParameters();
  400. parameters.Add("@ChargeBoxId", chargeboxId, size: 50);
  401. parameters.Add("@CustomId", customId, size: 25);
  402. var resultCnt = await conn.ExecuteAsync("""
  403. UPDATE Machine
  404. SET CustomId = @CustomId
  405. WHERE ChargeBoxId = @ChargeBoxId
  406. """, parameters);
  407. }
  408. catch (Exception e)
  409. {
  410. logger.LogError(e.Message);
  411. logger.LogCritical("UpdateCustomId update fail");
  412. return false;
  413. }
  414. return true;
  415. }
  416. public async Task UpdateMachineConnectionType(string chargeBoxId, int connectionType)
  417. {
  418. using var semaphoreWrapper = await startupSemaphore.GetToken();
  419. using var db = await contextFactory.CreateDbContextAsync();
  420. var machine = await db.Machine.Where(x => x.ChargeBoxId == chargeBoxId).FirstOrDefaultAsync();
  421. if (machine != null)
  422. {
  423. machine.ConnectionType = connectionType;
  424. await db.SaveChangesAsync();
  425. }
  426. }
  427. public async Task<object> TryGetResponseFromDb(string msgId, CancellationToken token = default)
  428. {
  429. var parameters = new DynamicParameters();
  430. parameters.Add("@MID", msgId, DbType.String, size: 36);
  431. parameters.Add("@MT", DateTime.UtcNow.AddSeconds(-5), DbType.DateTime);
  432. var sql = """
  433. SELECT [OutAction],[InMessage]
  434. FROM [ServerMessage]
  435. WHERE [SerialNo] = @MID AND CreatedOn > @MT
  436. """;
  437. using var conn = await sqlConnectionFactory.CreateAsync();
  438. ServerMessage item = null;
  439. item = await conn.QueryFirstOrDefaultAsync<ServerMessage>(new CommandDefinition(sql, parameters: parameters, cancellationToken: token));
  440. Actions action = Actions.None;
  441. if (item is null ||
  442. !Enum.TryParse(item.OutAction, out action))
  443. {
  444. return null;
  445. }
  446. switch (action)
  447. {
  448. case Actions.GetConfiguration:
  449. return JsonConvert.DeserializeObject<GetConfigurationConfirmation>(item.InMessage);
  450. case Actions.ChangeConfiguration:
  451. return JsonConvert.DeserializeObject<ChangeConfigurationConfirmation>(item.InMessage);
  452. case Actions.RemoteStartTransaction:
  453. return JsonConvert.DeserializeObject<RemoteStartTransactionConfirmation>(item.InMessage);
  454. case Actions.RemoteStopTransaction:
  455. return JsonConvert.DeserializeObject<RemoteStopTransactionConfirmation>(item.InMessage);
  456. case Actions.ChangeAvailability:
  457. return JsonConvert.DeserializeObject<ChangeAvailabilityConfirmation>(item.InMessage);
  458. case Actions.ClearCache:
  459. return JsonConvert.DeserializeObject<ClearCacheConfirmation>(item.InMessage);
  460. case Actions.DataTransfer:
  461. return JsonConvert.DeserializeObject<DataTransferConfirmation>(item.InMessage);
  462. case Actions.Reset:
  463. return JsonConvert.DeserializeObject<ResetConfirmation>(item.InMessage);
  464. case Actions.UnlockConnector:
  465. return JsonConvert.DeserializeObject<UnlockConnectorConfirmation>(item.InMessage);
  466. case Actions.TriggerMessage:
  467. return JsonConvert.DeserializeObject<TriggerMessageConfirmation>(item.InMessage);
  468. case Actions.GetDiagnostics:
  469. return JsonConvert.DeserializeObject<GetDiagnosticsConfirmation>(item.InMessage);
  470. case Actions.UpdateFirmware:
  471. return JsonConvert.DeserializeObject<UpdateFirmwareConfirmation>(item.InMessage);
  472. case Actions.GetLocalListVersion:
  473. return JsonConvert.DeserializeObject<GetLocalListVersionConfirmation>(item.InMessage);
  474. case Actions.SendLocalList:
  475. return JsonConvert.DeserializeObject<SendLocalListConfirmation>(item.InMessage);
  476. case Actions.SetChargingProfile:
  477. return JsonConvert.DeserializeObject<SetChargingProfileConfirmation>(item.InMessage);
  478. case Actions.ClearChargingProfile:
  479. return JsonConvert.DeserializeObject<ClearChargingProfileConfirmation>(item.InMessage);
  480. case Actions.GetCompositeSchedule:
  481. return JsonConvert.DeserializeObject<GetCompositeScheduleConfirmation>(item.InMessage);
  482. case Actions.ReserveNow:
  483. return JsonConvert.DeserializeObject<ReserveNowConfirmation>(item.InMessage);
  484. case Actions.CancelReservation:
  485. return JsonConvert.DeserializeObject<CancelReservationConfirmation>(item.InMessage);
  486. case Actions.ExtendedTriggerMessage:
  487. return JsonConvert.DeserializeObject<ExtendedTriggerMessageConfirmation>(item.InMessage);
  488. default:
  489. return null;
  490. }
  491. }
  492. public async Task SetTransactionBillingDone(int txId, decimal cost, string receipt)
  493. {
  494. using var db = await contextFactory.CreateDbContextAsync();
  495. TransactionRecord transaction = await db.TransactionRecord.Where(x => x.Id == txId).FirstOrDefaultAsync();
  496. if (transaction is null)
  497. {
  498. logger.LogTrace("Tx is empty");
  499. return;
  500. }
  501. transaction.Cost = cost;
  502. transaction.Receipt = receipt;
  503. transaction.BillingDone = true;
  504. db.ChangeTracker.AutoDetectChangesEnabled = false;
  505. //db.Configuration.ValidateOnSaveEnabled = false;
  506. db.TransactionRecord.Attach(transaction);
  507. db.Entry(transaction).Property(x => x.Cost).IsModified = true;
  508. db.Entry(transaction).Property(x => x.Receipt).IsModified = true;
  509. db.Entry(transaction).Property(x => x.BillingDone).IsModified = true;
  510. await db.SaveChangesAsync();
  511. }
  512. private void InitUpdateConnectorStatusHandler()
  513. {
  514. if (statusNotificationHandler is not null)
  515. {
  516. throw new Exception($"{nameof(InitUpdateConnectorStatusHandler)} should only called once");
  517. }
  518. statusNotificationHandler = new GroupHandler<StatusNotificationParam>(
  519. handleFunc: BundleUpdateConnectorStatusDapper,
  520. logger: loggerFactory.CreateLogger("StatusNotificationHandler"),
  521. workerCnt: 1);
  522. }
  523. private void InitAddServerMessageHandler()
  524. {
  525. if (addServerMessageHandler is not null)
  526. {
  527. throw new Exception($"{nameof(InitAddServerMessageHandler)} should only called once");
  528. }
  529. addServerMessageHandler = new GroupHandler<ServerMessage, string>(
  530. handleFunc: BundleAddServerMessage,
  531. logger: loggerFactory.CreateLogger("AddServerMessageHandler"));
  532. }
  533. private void InitUpdateMachineBasicInfoHandler()
  534. {
  535. if (updateMachineBasicInfoHandler is not null)
  536. {
  537. throw new Exception($"{nameof(InitUpdateMachineBasicInfoHandler)} should only called once");
  538. }
  539. updateMachineBasicInfoHandler = new GroupHandler<UpdateMachineBasicInfoParam>(
  540. handleFunc: BundelUpdateMachineBasicInfo,
  541. logger: loggerFactory.CreateLogger("UpdateMachineBasicInfoHandler"),
  542. workerCnt: 1);
  543. }
  544. private void InitUpdateServerMessageUpdateOnHandler()
  545. {
  546. if (updateServerMessageUpdateOnHandler is not null)
  547. {
  548. throw new Exception($"{nameof(InitUpdateMachineBasicInfoHandler)} should only called once");
  549. }
  550. updateServerMessageUpdateOnHandler = new GroupHandler<int>(
  551. handleFunc: BundelUpdateServerMessageUpdateOn,
  552. logger: loggerFactory.CreateLogger("UpdateServerMessageUpdateOnHandler"),
  553. workerCnt: 10);
  554. }
  555. private void InitGetMachineConfigurationHandler()
  556. {
  557. if (getMachineConfigurationHandler is not null)
  558. {
  559. throw new Exception($"{nameof(InitUpdateMachineBasicInfoHandler)} should only called once");
  560. }
  561. getMachineConfigurationHandler = new GroupHandler<string, List<MachineConfigurations>>(
  562. handleFunc: BundelGetMachineConfiguration,
  563. logger: loggerFactory.CreateLogger("GetMachineConfigurationHandler"),
  564. workerCnt: 10);
  565. }
  566. private void InitUpdateErrorFinishedOnHandler()
  567. {
  568. if (updateErrorFinishedOnHandler is not null)
  569. {
  570. throw new Exception($"{nameof(InitUpdateErrorFinishedOnHandler)} should only called once");
  571. }
  572. updateErrorFinishedOnHandler = new GroupHandler<UpdateErrofFinishedOnParam>(
  573. handleFunc: BundelUpdateErrorFinishedOn,
  574. logger: loggerFactory.CreateLogger("UpdateErrorFinishedOnHandler"),
  575. workerCnt: 1);
  576. }
  577. private async Task UpdateMachineBasicInfoEF(string chargeBoxId, Machine machine)
  578. {
  579. using var semaphoreWrapper = await startupSemaphore.GetToken();
  580. using var db = await contextFactory.CreateDbContextAsync();
  581. var _machine = await db.Machine.FirstOrDefaultAsync(x => x.ChargeBoxId == chargeBoxId);
  582. _machine.ChargeBoxSerialNumber = machine.ChargeBoxSerialNumber;
  583. _machine.ChargePointSerialNumber = machine.ChargePointSerialNumber;
  584. _machine.ChargePointModel = machine.ChargePointModel;
  585. _machine.ChargePointVendor = machine.ChargePointVendor;
  586. _machine.FwCurrentVersion = machine.FwCurrentVersion;
  587. _machine.Iccid = machine.Iccid;
  588. _machine.Imsi = machine.Imsi;
  589. _machine.MeterSerialNumber = machine.MeterSerialNumber;
  590. _machine.MeterType = machine.MeterType;
  591. await db.SaveChangesAsync();
  592. //using var semaphoreWrapper = await startupSemaphore.GetToken();
  593. }
  594. private async Task BundelUpdateMachineBasicInfo(BundleHandlerData<UpdateMachineBasicInfoParam> bundleHandlerData)
  595. {
  596. using var db = await contextFactory.CreateDbContextAsync();
  597. using var trans = await db.Database.BeginTransactionAsync();
  598. var pams = bundleHandlerData.Datas.DistinctBy(x => x.ChargeBoxId);
  599. foreach (var pam in pams)
  600. {
  601. var _machine = db.Machine.FirstOrDefault(x => x.ChargeBoxId == pam.ChargeBoxId);
  602. _machine.ChargeBoxSerialNumber = pam.machine.ChargeBoxSerialNumber;
  603. _machine.ChargePointSerialNumber = pam.machine.ChargePointSerialNumber;
  604. _machine.ChargePointModel = pam.machine.ChargePointModel;
  605. _machine.ChargePointVendor = pam.machine.ChargePointVendor;
  606. _machine.FwCurrentVersion = pam.machine.FwCurrentVersion;
  607. _machine.Iccid = pam.machine.Iccid;
  608. _machine.Imsi = pam.machine.Imsi;
  609. _machine.MeterSerialNumber = pam.machine.MeterSerialNumber;
  610. _machine.MeterType = pam.machine.MeterType;
  611. }
  612. await db.SaveChangesAsync();
  613. await trans.CommitAsync();
  614. bundleHandlerData.CompletedDatas.AddRange(bundleHandlerData.Datas);
  615. }
  616. private async Task BundelUpdateServerMessageUpdateOn(BundleHandlerData<int> bundleHandlerData)
  617. {
  618. var ids = bundleHandlerData.Datas;
  619. var sql = """
  620. UPDATE [dbo].[ServerMessage]
  621. SET UpdatedOn = @DateTimeNow
  622. WHERE Id in @Ids
  623. """;
  624. DynamicParameters parameters = new DynamicParameters();
  625. parameters.Add("DateTimeNow", DateTime.UtcNow, DbType.DateTime);
  626. parameters.Add("Ids", ids);
  627. using SqlConnection sqlConnection = await sqlConnectionFactory.CreateAsync();
  628. var cnt = await sqlConnection.ExecuteAsync(sql, parameters);
  629. if (cnt != 0 || ids.Count == 0)
  630. {
  631. bundleHandlerData.CompletedDatas.AddRange(ids);
  632. }
  633. }
  634. private async Task BundelGetMachineConfiguration(BundleHandlerData<string, List<MachineConfigurations>> bundleHandlerData)
  635. {
  636. var chargeboxIds = bundleHandlerData.Datas;
  637. var sql = """
  638. SELECT [ChargeBoxId], [ConfigureName], [ConfigureSetting], [ReadOnly], [Exists]
  639. FROM [dbo].[MachineConfigurations]
  640. WHERE ChargeBoxId IN @ChargeBoxIds
  641. """;
  642. DynamicParameters parameters = new DynamicParameters();
  643. parameters.Add("@ChargeBoxIds", chargeboxIds, direction: ParameterDirection.Input, size: 25);
  644. using SqlConnection sqlConnection = await sqlConnectionFactory.CreateAsync();
  645. var result = await sqlConnection.QueryAsync<MachineConfigurations>(sql, parameters);
  646. var gReult = result.GroupBy(x => x.ChargeBoxId);
  647. foreach (var g in gReult)
  648. {
  649. var originKey = chargeboxIds.FirstOrDefault(x => x.ToLower() == g.Key.ToLower());
  650. if (string.IsNullOrEmpty(originKey))
  651. {
  652. continue;
  653. }
  654. bundleHandlerData.AddCompletedData(originKey, g.ToList());
  655. }
  656. var getConfigChargeboxIds = gReult.Select(x => x.Key);
  657. var emptyConfigChargeboxIds = chargeboxIds.Except(getConfigChargeboxIds);
  658. foreach (var chargeboxId in emptyConfigChargeboxIds)
  659. {
  660. bundleHandlerData.AddCompletedData(chargeboxId, new List<MachineConfigurations>());
  661. }
  662. }
  663. private async Task UpdateConnectorStatusEF(string Id, ConnectorStatus Status)
  664. {
  665. using var db = await contextFactory.CreateDbContextAsync();
  666. ConnectorStatus status = new() { Id = Id };
  667. db.ChangeTracker.AutoDetectChangesEnabled = false;
  668. db.ConnectorStatus.Attach(status);
  669. status.CreatedOn = Status.CreatedOn;
  670. status.Status = Status.Status;
  671. status.ChargePointErrorCodeId = Status.ChargePointErrorCodeId;
  672. status.ErrorInfo = Status.ErrorInfo;
  673. status.VendorId = Status.VendorId;
  674. status.VendorErrorCode = Status.VendorErrorCode;
  675. db.Entry(status).Property(x => x.CreatedOn).IsModified = true;
  676. db.Entry(status).Property(x => x.Status).IsModified = true;
  677. db.Entry(status).Property(x => x.ChargePointErrorCodeId).IsModified = true;
  678. db.Entry(status).Property(x => x.ErrorInfo).IsModified = true;
  679. db.Entry(status).Property(x => x.VendorId).IsModified = true;
  680. db.Entry(status).Property(x => x.VendorErrorCode).IsModified = true;
  681. await db.SaveChangesAsync();
  682. }
  683. private async Task UpdateConnectorStatusDapper(string Id, ConnectorStatus Status)
  684. {
  685. var parameters = new DynamicParameters();
  686. parameters.Add("@Id", Id, DbType.String, ParameterDirection.Input, 36);
  687. parameters.Add("@CreatedOn", Status.CreatedOn, DbType.DateTime, ParameterDirection.Input);
  688. parameters.Add("@Status", Status.Status, DbType.Int32, ParameterDirection.Input);
  689. parameters.Add("@ChargePointErrorCodeId", Status.ChargePointErrorCodeId, DbType.Int32, ParameterDirection.Input);
  690. parameters.Add("@ErrorInfo", Status.ErrorInfo, DbType.String, ParameterDirection.Input, 50);
  691. parameters.Add("@VendorId", Status.VendorId, DbType.String, ParameterDirection.Input, 255);
  692. parameters.Add("@VendorErrorCode", Status.VendorErrorCode, DbType.String, ParameterDirection.Input, 100);
  693. using var conn = await sqlConnectionFactory.CreateAsync();
  694. await conn.ExecuteAsync("""
  695. update ConnectorStatus
  696. set
  697. CreatedOn = @CreatedOn,
  698. Status = @Status,
  699. ChargePointErrorCodeId = @ChargePointErrorCodeId,
  700. ErrorInfo = @ErrorInfo,
  701. VendorId = @VendorId,
  702. VendorErrorCode = @VendorErrorCode
  703. where Id = @Id
  704. """, parameters);
  705. }
  706. private async Task<Guid> GetCustomerIdByChargeBoxIdEF(string chargeboxId)
  707. {
  708. using var db = await contextFactory.CreateDbContextAsync();
  709. var _CustomerId = await db.Machine.Where(x => x.ChargeBoxId == chargeboxId).Select(x => x.CustomerId).FirstOrDefaultAsync();
  710. return _CustomerId;
  711. }
  712. private async Task<Guid> GetCustomerIdByChargeBoxIdDapper(string chargeboxId)
  713. {
  714. var parameters = new DynamicParameters();
  715. parameters.Add("@ChargeBoxId", chargeboxId, DbType.String, ParameterDirection.Input, 50);
  716. using var conn = await sqlConnectionFactory.CreateAsync();
  717. var _existedTx = await conn.QueryFirstOrDefaultAsync<Guid>("""
  718. select CustomerId
  719. from dbo.Machine
  720. where
  721. ChargeBoxId = @ChargeBoxId
  722. """, parameters);
  723. return _existedTx;
  724. }
  725. private async Task<int?> TryGetDuplicatedTransactionIdEF(string chargeBoxId, Guid customerId, int connectorId, DateTime timestamp)
  726. {
  727. using var db = await contextFactory.CreateDbContextAsync();
  728. var _existedTx = await db.TransactionRecord.Where(x => x.CustomerId == customerId && x.ChargeBoxId == chargeBoxId
  729. && x.ConnectorId == connectorId && x.StartTime == timestamp).Select(x => x.Id).FirstOrDefaultAsync();
  730. return _existedTx;
  731. }
  732. private async Task<int?> TryGetDuplicatedTransactionIdDapper(string chargeBoxId, Guid customerId, int connectorId, DateTime timestamp)
  733. {
  734. var parameters = new DynamicParameters();
  735. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  736. parameters.Add("@CustomerId", customerId, DbType.Guid, ParameterDirection.Input);
  737. parameters.Add("@ConnectorId", connectorId, DbType.Int16, ParameterDirection.Input);
  738. parameters.Add("@TimeStamp", timestamp, DbType.DateTime, ParameterDirection.Input);
  739. using var conn = await sqlConnectionFactory.CreateAsync();
  740. var _existedTx = await conn.QueryFirstOrDefaultAsync<int?>("""
  741. SELECT Id
  742. FROM dbo.TransactionRecord
  743. WHERE
  744. ChargeBoxId = @ChargeBoxId and
  745. CustomerId = @CustomerId and
  746. ConnectorId = @ConnectorId and
  747. StartTime = @TimeStamp
  748. """, parameters);
  749. return _existedTx;
  750. }
  751. private async ValueTask AddMachineErrorEF(byte connectorId, DateTime createdOn, int status, string chargeBoxId, int errorCodeId, string errorInfo, int preStatus, string vendorErrorCode, string vendorId)
  752. {
  753. using var db = await contextFactory.CreateDbContextAsync();
  754. await db.MachineError.AddAsync(new MachineError()
  755. {
  756. ConnectorId = connectorId,
  757. CreatedOn = createdOn,
  758. Status = status,
  759. ChargeBoxId = chargeBoxId,
  760. ErrorCodeId = errorCodeId,
  761. ErrorInfo = errorInfo,
  762. PreStatus = preStatus,
  763. VendorErrorCode = vendorErrorCode,
  764. VendorId = vendorId
  765. });
  766. await db.SaveChangesAsync();
  767. }
  768. private async ValueTask AddMachineErrorDapper(byte connectorId, DateTime createdOn, int status, string chargeBoxId, int errorCodeId, string errorInfo, int preStatus, string vendorErrorCode, string vendorId)
  769. {
  770. var parameters = new DynamicParameters();
  771. parameters.Add("@ConnectorId", connectorId, DbType.Int16, ParameterDirection.Input);
  772. parameters.Add("@PreStatus", preStatus, DbType.Int32, ParameterDirection.Input);
  773. parameters.Add("@Status", status, DbType.Int32, ParameterDirection.Input);
  774. parameters.Add("@ErrorInfo", errorInfo, DbType.String, ParameterDirection.Input, 50);
  775. parameters.Add("@VendorId", vendorId, DbType.String, ParameterDirection.Input, 255);
  776. parameters.Add("@CreatedOn", createdOn, DbType.DateTime, ParameterDirection.Input);
  777. parameters.Add("@ErrorCodeId", errorCodeId, DbType.Int32, ParameterDirection.Input);
  778. parameters.Add("@VendorErrorCode", vendorErrorCode, DbType.String, ParameterDirection.Input, 100);
  779. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  780. using var conn = await sqlConnectionFactory.CreateAsync();
  781. await conn.ExecuteAsync("""
  782. INSERT INTO MachineError
  783. (ConnectorId, PreStatus, Status, ErrorInfo, VendorId, CreatedOn, ErrorCodeId, VendorErrorCode, ChargeBoxId)
  784. VALUES (@ConnectorId, @PreStatus, @Status, @ErrorInfo, @VendorId, @CreatedOn, @ErrorCodeId, @VendorErrorCode, @ChargeBoxId)
  785. """, parameters);
  786. }
  787. private async ValueTask AddFinishedTimetoMachineErrorDapper(string chargeBoxId, byte connectorId, DateTime finishedTime)
  788. {
  789. var getCommand = """
  790. SELECT TOP(1) Id
  791. FROM [dbo].[MachineError]
  792. where ChargeBoxId=@ChargeBoxId and ConnectorId=@ConnectorId
  793. Order by Id desc
  794. """;
  795. var parameters = new DynamicParameters();
  796. parameters.Add("@ConnectorId", connectorId, DbType.Int16, ParameterDirection.Input);
  797. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  798. //parameters.Add("@CreatedOn", previousErrorOn, DbType.DateTime, ParameterDirection.Input, 50);
  799. int? recordId = null;
  800. using (var conn = await sqlConnectionFactory.CreateAsync())
  801. {
  802. recordId = await conn.QueryFirstOrDefaultAsync<int?>(getCommand, parameters);
  803. if (recordId is null)
  804. {
  805. return;
  806. }
  807. }
  808. await updateErrorFinishedOnHandler.HandleAsync(new UpdateErrofFinishedOnParam(recordId.Value, finishedTime));
  809. }
  810. private async Task BundelUpdateErrorFinishedOn(BundleHandlerData<UpdateErrofFinishedOnParam> bundleHandlerData)
  811. {
  812. var updateCommand = """
  813. Update MachineError
  814. set FinishedOn=@FinishedOn
  815. where Id=@Id
  816. """;
  817. var pams = bundleHandlerData.Datas;
  818. using var conn = await sqlConnectionFactory.CreateAsync();
  819. using var trans = await conn.BeginTransactionAsync();
  820. DynamicParameters parameters = null;
  821. foreach (var pam in pams)
  822. {
  823. parameters = new DynamicParameters();
  824. parameters.Add("@Id", pam.Id, DbType.Int32, ParameterDirection.Input);
  825. parameters.Add("@FinishedOn", pam.finishedOn, DbType.DateTime, ParameterDirection.Input);
  826. await conn.ExecuteAsync(new CommandDefinition(
  827. updateCommand,
  828. parameters: parameters,
  829. transaction: trans
  830. ));
  831. }
  832. await trans.CommitAsync();
  833. bundleHandlerData.CompletedDatas.AddRange(bundleHandlerData.Datas);
  834. }
  835. private async Task BundleUpdateConnectorStatus(IEnumerable<StatusNotificationParam> statusNotifications)
  836. {
  837. using var db = await contextFactory.CreateDbContextAsync();
  838. using var trans = await db.Database.BeginTransactionAsync();
  839. statusNotifications = statusNotifications.OrderBy(x => x.Status.CreatedOn).DistinctBy(x => x.Id);
  840. foreach (var param in statusNotifications)
  841. {
  842. ConnectorStatus status = new() { Id = param.Id };
  843. //db.ChangeTracker.AutoDetectChangesEnabled = false;
  844. db.ConnectorStatus.Attach(status);
  845. status.CreatedOn = param.Status.CreatedOn;
  846. status.Status = param.Status.Status;
  847. status.ChargePointErrorCodeId = param.Status.ChargePointErrorCodeId;
  848. status.ErrorInfo = param.Status.ErrorInfo;
  849. status.VendorId = param.Status.VendorId;
  850. status.VendorErrorCode = param.Status.VendorErrorCode;
  851. db.Entry(status).Property(x => x.CreatedOn).IsModified = true;
  852. db.Entry(status).Property(x => x.Status).IsModified = true;
  853. db.Entry(status).Property(x => x.ChargePointErrorCodeId).IsModified = true;
  854. db.Entry(status).Property(x => x.ErrorInfo).IsModified = true;
  855. db.Entry(status).Property(x => x.VendorId).IsModified = true;
  856. db.Entry(status).Property(x => x.VendorErrorCode).IsModified = true;
  857. //await db.SaveChangesAsync();
  858. }
  859. await db.SaveChangesAsync();
  860. await trans.CommitAsync();
  861. //db.ChangeTracker.Clear();
  862. }
  863. private async Task BundleUpdateConnectorStatusDapper(BundleHandlerData<StatusNotificationParam> bundleHandlerData)
  864. {
  865. using var conn = await sqlConnectionFactory.CreateAsync();
  866. foreach (var status in bundleHandlerData.Datas)
  867. {
  868. var parameters = new DynamicParameters();
  869. parameters.Add("@Id", status.Id, DbType.String, ParameterDirection.Input, 36);
  870. parameters.Add("@CreatedOn", status.Status.CreatedOn, DbType.DateTime, ParameterDirection.Input);
  871. parameters.Add("@Status", status.Status.Status, DbType.Int32, ParameterDirection.Input);
  872. parameters.Add("@ChargePointErrorCodeId", status.Status.ChargePointErrorCodeId, DbType.Int32, ParameterDirection.Input);
  873. parameters.Add("@ErrorInfo", status.Status.ErrorInfo, DbType.String, ParameterDirection.Input, 50);
  874. parameters.Add("@VendorId", status.Status.VendorId, DbType.String, ParameterDirection.Input, 255);
  875. parameters.Add("@VendorErrorCode", status.Status.VendorErrorCode, DbType.String, ParameterDirection.Input, 100);
  876. await conn.ExecuteAsync("""
  877. update ConnectorStatus
  878. set
  879. CreatedOn = @CreatedOn,
  880. Status = @Status,
  881. ChargePointErrorCodeId = @ChargePointErrorCodeId,
  882. ErrorInfo = @ErrorInfo,
  883. VendorId = @VendorId,
  884. VendorErrorCode = @VendorErrorCode
  885. where Id = @Id
  886. """, parameters);
  887. bundleHandlerData.AddCompletedData(status);
  888. }
  889. }
  890. private async Task BundleAddServerMessage(BundleHandlerData<ServerMessage, string> bundleHandlerData)
  891. {
  892. //var sql = """
  893. // INSERT INTO [ServerMessage] ([ChargeBoxId], [CreatedBy], [CreatedOn], [InMessage], [OutAction], [OutRequest], [ReceivedOn], [SerialNo], [UpdatedOn])
  894. // OUTPUT INSERTED.Id
  895. // VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8)
  896. // """;
  897. //using var conn = await sqlConnectionFactory.CreateAsync();
  898. //foreach(var data in bundleHandlerData.Datas)
  899. //{
  900. // var dymparam = new DynamicParameters();
  901. // dymparam.Add("@p0", data.ChargeBoxId);
  902. // dymparam.Add("@p1", data.CreatedBy);
  903. // dymparam.Add("@p2", data.CreatedOn);
  904. // dymparam.Add("@p3", data.InMessage);
  905. // dymparam.Add("@p4", data.OutAction);
  906. // dymparam.Add("@p5", data.OutRequest);
  907. // dymparam.Add("@p6", data.ReceivedOn);
  908. // dymparam.Add("@p7", data.SerialNo);
  909. // dymparam.Add("@p8", data.UpdatedOn);
  910. //}
  911. using var db = await contextFactory.CreateDbContextAsync();
  912. using var trans = await db.Database.BeginTransactionAsync();
  913. foreach (var message in bundleHandlerData.Datas)
  914. {
  915. await db.ServerMessage.AddAsync(message);
  916. }
  917. await db.SaveChangesAsync();
  918. await trans.CommitAsync();
  919. bundleHandlerData.CompletedDatas.AddRange(bundleHandlerData.Datas.Select(x => new KeyValuePair<ServerMessage, string>(x, x.SerialNo)));
  920. }
  921. private async Task AddServerMessageEF(ServerMessage message)
  922. {
  923. using var db = await contextFactory.CreateDbContextAsync();
  924. using var trans = await db.Database.BeginTransactionAsync();
  925. await db.ServerMessage.AddAsync(message);
  926. await db.SaveChangesAsync();
  927. await trans.CommitAsync();
  928. //db.ChangeTracker.Clear();
  929. }
  930. private async Task AddServerMessageDapper(ServerMessage message)
  931. {
  932. var parameters = new DynamicParameters();
  933. parameters.Add("@SerialNo", message.SerialNo, DbType.String, ParameterDirection.Input, 36);
  934. parameters.Add("@OutAction", message.OutAction, DbType.String, ParameterDirection.Input, 30);
  935. parameters.Add("@OutRequest", message.OutRequest, DbType.String, ParameterDirection.Input);
  936. parameters.Add("@InMessage", message.InMessage, DbType.String, ParameterDirection.Input);
  937. parameters.Add("@CreatedOn", message.CreatedOn, DbType.DateTime, ParameterDirection.Input);
  938. parameters.Add("@CreatedBy", message.CreatedBy, DbType.String, ParameterDirection.Input, 36);
  939. parameters.Add("@ReceivedOn", message.ReceivedOn, DbType.DateTime, ParameterDirection.Input);
  940. parameters.Add("@ChargeBoxId", message.ChargeBoxId, DbType.String, ParameterDirection.Input, 30);
  941. parameters.Add("@UpdatedOn", message.UpdatedOn, DbType.DateTime, ParameterDirection.Input);
  942. using var conn = await sqlConnectionFactory.CreateAsync();
  943. var resultCnt = await conn.ExecuteAsync("""
  944. INSERT INTO ServerMessage
  945. (SerialNo, OutAction, OutRequest, InMessage, CreatedOn, CreatedBy, ReceivedOn, ChargeBoxId, UpdatedOn)
  946. VALUES (@SerialNo, @OutAction, @OutRequest, @InMessage, @CreatedOn, @CreatedBy, @ReceivedOn, @ChargeBoxId, @UpdatedOn)
  947. """, parameters);
  948. if (resultCnt != 1)
  949. {
  950. throw new Exception("Insert failed");
  951. }
  952. return;
  953. }
  954. private async Task<int> AddNewTransactionRecordEF(TransactionRecord newTransaction)
  955. {
  956. using var db = await contextFactory.CreateDbContextAsync();
  957. await db.TransactionRecord.AddAsync(newTransaction);
  958. await db.SaveChangesAsync();
  959. return newTransaction.Id;
  960. }
  961. private async Task<int> AddNewTransactionRecordDapper(TransactionRecord newTransaction)
  962. {
  963. var parameters = new DynamicParameters();
  964. parameters.Add("@ChargeBoxId", newTransaction.ChargeBoxId, DbType.String, ParameterDirection.Input, 50);
  965. parameters.Add("@ConnectorId", newTransaction.ConnectorId, DbType.Int16, ParameterDirection.Input);
  966. parameters.Add("@CreatedOn", newTransaction.CreatedOn, DbType.DateTime, ParameterDirection.Input);
  967. parameters.Add("@UpdatedOn", newTransaction.UpdatedOn, DbType.DateTime, ParameterDirection.Input);
  968. parameters.Add("@StartTransactionReportedOn", newTransaction.StartTransactionReportedOn, DbType.DateTime, ParameterDirection.Input);
  969. parameters.Add("@StopTransactionReportedOn", newTransaction.StopTransactionReportedOn, DbType.DateTime, ParameterDirection.Input);
  970. parameters.Add("@StartIdTag", newTransaction.StartIdTag, DbType.String, ParameterDirection.Input, 20);
  971. parameters.Add("@MeterStart", newTransaction.MeterStart, DbType.Decimal, ParameterDirection.Input, precision: 18, scale: 2);
  972. parameters.Add("@MeterStop", newTransaction.MeterStop, DbType.Decimal, ParameterDirection.Input, precision: 18, scale: 2);
  973. parameters.Add("@CustomerId", newTransaction.CustomerId, DbType.Guid, ParameterDirection.Input);
  974. parameters.Add("@StartTime", newTransaction.StartTime, DbType.DateTime, ParameterDirection.Input);
  975. parameters.Add("@StopTime", newTransaction.StopTime, DbType.DateTime, ParameterDirection.Input);
  976. parameters.Add("@ReservationId", newTransaction.ReservationId, DbType.Int32, ParameterDirection.Input);
  977. parameters.Add("@RetryStartTransactionTimes", newTransaction.RetryStartTransactionTimes, DbType.Int32, ParameterDirection.Input);
  978. parameters.Add("@RetryStopTransactionTimes", newTransaction.RetryStopTransactionTimes, DbType.Int32, ParameterDirection.Input);
  979. parameters.Add("@Fee", newTransaction.Fee, DbType.String, ParameterDirection.Input, 1500);
  980. using var conn = await sqlConnectionFactory.CreateAsync();
  981. var id = await conn.QuerySingleAsync<int>("""
  982. INSERT INTO TransactionRecord
  983. (ChargeBoxId, ConnectorId, CreatedOn, UpdatedOn, StartTransactionReportedOn, StopTransactionReportedOn,
  984. StartIdTag, MeterStart, MeterStop, CustomerId, StartTime, StopTime, ReservationId, RetryStartTransactionTimes, RetryStopTransactionTimes, Fee)
  985. OUTPUT INSERTED.Id
  986. VALUES (@ChargeBoxId, @ConnectorId, @CreatedOn, @UpdatedOn, @StartTransactionReportedOn, @StopTransactionReportedOn,
  987. @StartIdTag, @MeterStart, @MeterStop, @CustomerId, @StartTime, @StopTime, @ReservationId, @RetryStartTransactionTimes, @RetryStopTransactionTimes, @Fee)
  988. """, parameters);
  989. return id;
  990. }
  991. private async Task<TransactionRecord> GetTransactionForStopTransactionEF(int transactionId, string chargeBoxId)
  992. {
  993. using var db = await contextFactory.CreateDbContextAsync();
  994. return await db.TransactionRecord.Where(x => x.Id == transactionId
  995. && x.ChargeBoxId == chargeBoxId).FirstOrDefaultAsync();
  996. }
  997. private async Task<TransactionRecord> GetTransactionForStopTransactionDapper(int transactionId, string chargeBoxId)
  998. {
  999. var parameters = new DynamicParameters();
  1000. parameters.Add("@TransactionId", transactionId, DbType.Int32, ParameterDirection.Input);
  1001. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
  1002. using var conn = await sqlConnectionFactory.CreateAsync();
  1003. var record = await conn.QuerySingleAsync<TransactionRecord>("""
  1004. SELECT Id, ConnectorId, MeterStop, MeterStart, StartTime, StopTime FROM TransactionRecord
  1005. WHERE Id = @TransactionId and ChargeBoxId = @ChargeBoxId
  1006. """, parameters);
  1007. return record;
  1008. }
  1009. private Task BulkInsertServerMessage(IEnumerable<ServerMessage> messages)
  1010. {
  1011. var table = new DataTable();
  1012. table.Columns.Add("ChargeBoxId");
  1013. table.Columns.Add("SerialNo");
  1014. table.Columns.Add("OutAction");
  1015. table.Columns.Add("OutRequest");
  1016. table.Columns.Add("InMessage");
  1017. table.Columns.Add("CreatedOn");
  1018. table.Columns.Add("CreatedBy");
  1019. table.Columns.Add("UpdatedOn");
  1020. table.Columns.Add("ReceivedOn");
  1021. foreach (var param in messages)
  1022. {
  1023. var row = table.NewRow();
  1024. row["ChargeBoxId"] = param.ChargeBoxId;
  1025. row["SerialNo"] = param.SerialNo;
  1026. row["OutAction"] = param.OutAction;
  1027. row["OutRequest"] = param.OutRequest;
  1028. row["InMessage"] = param.InMessage;
  1029. row["CreatedOn"] = param.CreatedOn;
  1030. row["CreatedBy"] = param.CreatedBy;
  1031. row["UpdatedOn"] = param.UpdatedOn;
  1032. row["ReceivedOn"] = param.ReceivedOn;
  1033. table.Rows.Add(row);
  1034. }
  1035. using SqlConnection sqlConnection = sqlConnectionFactory.Create();
  1036. using SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(sqlConnection);
  1037. sqlBulkCopy.BatchSize = messages.Count();
  1038. sqlBulkCopy.DestinationTableName = "ServerMessage";
  1039. sqlBulkCopy.ColumnMappings.Add("ChargeBoxId", "ChargeBoxId");
  1040. sqlBulkCopy.ColumnMappings.Add("SerialNo", "SerialNo");
  1041. sqlBulkCopy.ColumnMappings.Add("OutAction", "OutAction");
  1042. sqlBulkCopy.ColumnMappings.Add("OutRequest", "OutRequest");
  1043. sqlBulkCopy.ColumnMappings.Add("InMessage", "InMessage");
  1044. sqlBulkCopy.ColumnMappings.Add("CreatedOn", "CreatedOn");
  1045. sqlBulkCopy.ColumnMappings.Add("CreatedBy", "CreatedBy");
  1046. sqlBulkCopy.ColumnMappings.Add("UpdatedOn", "UpdatedOn");
  1047. sqlBulkCopy.ColumnMappings.Add("ReceivedOn", "ReceivedOn");
  1048. return sqlBulkCopy.WriteToServerAsync(table);
  1049. }
  1050. private int GetStartupLimit(IConfiguration configuration)
  1051. {
  1052. var limitConfig = configuration["MainDbStartupLimit"];
  1053. int limit = 5;
  1054. if (limitConfig != default)
  1055. {
  1056. int.TryParse(limitConfig, out limit);
  1057. }
  1058. return limit;
  1059. }
  1060. private int GetOpLimit(IConfiguration configuration)
  1061. {
  1062. var limitConfig = configuration["MainDbOpLimit"];
  1063. int limit = 500;
  1064. if (limitConfig != default)
  1065. {
  1066. int.TryParse(limitConfig, out limit);
  1067. }
  1068. return limit;
  1069. }
  1070. private async Task<bool> UpdateHeartBeatsDapper(IEnumerable<Machine> heartBeatsData)
  1071. {
  1072. using var conn = await sqlConnectionFactory.CreateAsync();
  1073. using var trans = await conn.BeginTransactionAsync();
  1074. try
  1075. {
  1076. foreach (var data in heartBeatsData)
  1077. {
  1078. var parameters = new DynamicParameters();
  1079. parameters.Add("@Id", data.Id, DbType.String, ParameterDirection.Input, 36);
  1080. parameters.Add("@HeartbeatUpdatedOn", data.HeartbeatUpdatedOn, DbType.DateTime, ParameterDirection.Input);
  1081. parameters.Add("@ConnectionType", data.ConnectionType, DbType.Int32, ParameterDirection.Input);
  1082. var resultCnt = await conn.ExecuteAsync("""
  1083. UPDATE Machine
  1084. SET HeartbeatUpdatedOn = @HeartbeatUpdatedOn, ConnectionType = @ConnectionType
  1085. WHERE Id = @Id
  1086. """, parameters, trans);
  1087. if (resultCnt != 1)
  1088. {
  1089. throw new Exception("Update over one columes");
  1090. }
  1091. }
  1092. await trans.CommitAsync();
  1093. }
  1094. catch
  1095. {
  1096. logger.LogCritical("HeartBeatCheckTrigger update fail, roll back");
  1097. await trans.RollbackAsync();
  1098. return false;
  1099. }
  1100. return true;
  1101. }
  1102. private async Task<bool> UpdateHeartBeatsDapper(List<string> machineIds)
  1103. {
  1104. using var conn = await sqlConnectionFactory.CreateAsync();
  1105. try
  1106. {
  1107. var parameters = new DynamicParameters();
  1108. parameters.Add("@Ids", machineIds, size: 36);
  1109. parameters.Add("@HeartbeatUpdatedOn", DateTime.UtcNow, DbType.DateTime, ParameterDirection.Input);
  1110. var resultCnt = await conn.ExecuteAsync("""
  1111. UPDATE Machine
  1112. SET HeartbeatUpdatedOn = @HeartbeatUpdatedOn
  1113. WHERE Id in @Ids
  1114. """, parameters);
  1115. }
  1116. catch (Exception e)
  1117. {
  1118. logger.LogError(e.Message);
  1119. logger.LogCritical("HeartBeatCheckTrigger update fail");
  1120. return false;
  1121. }
  1122. return true;
  1123. }
  1124. private async Task<bool> UpdateHeartBeatsEF(IEnumerable<Machine> heartBeatsData)
  1125. {
  1126. using var db = await contextFactory.CreateDbContextAsync();
  1127. using var transaction = await db.Database.BeginTransactionAsync();
  1128. try
  1129. {
  1130. foreach (var data in heartBeatsData)
  1131. {
  1132. var machine = new Machine() { Id = data.Id };
  1133. if (machine != null)
  1134. {
  1135. db.Machine.Attach(machine);
  1136. machine.HeartbeatUpdatedOn = DateTime.UtcNow;
  1137. machine.ConnectionType = data.ConnectionType;
  1138. db.Entry(machine).Property(x => x.HeartbeatUpdatedOn).IsModified = true;
  1139. db.Entry(machine).Property(x => x.ConnectionType).IsModified = true;
  1140. }
  1141. }
  1142. await db.SaveChangesAsync();
  1143. await transaction.CommitAsync();
  1144. db.ChangeTracker.Clear();
  1145. }
  1146. catch (Exception ex)
  1147. {
  1148. logger.LogCritical(ex, "HeartBeatCheckTrigger update fail, roll back");
  1149. transaction.Rollback();
  1150. return false;
  1151. }
  1152. return true;
  1153. }
  1154. public async Task<string> GetMachineConnectorType(string chargeBoxId, CancellationToken token = default)
  1155. {
  1156. using var db = await contextFactory.CreateDbContextAsync(token);
  1157. var machine = await db.Machine.Where(x => x.ChargeBoxId == chargeBoxId).FirstOrDefaultAsync(token);
  1158. if (machine == null)
  1159. {
  1160. return null;
  1161. }
  1162. return machine.ConnectorType;
  1163. }
  1164. public async Task SetMachineConnectionType(string chargeBoxId, int v, CancellationToken token = default)
  1165. {
  1166. using var db = await contextFactory.CreateDbContextAsync(token);
  1167. var machine = await db.Machine.Where(x => x.ChargeBoxId == chargeBoxId).FirstOrDefaultAsync(token);
  1168. if (machine == null)
  1169. {
  1170. return;
  1171. }
  1172. machine.ConnectionType = v;
  1173. return;
  1174. }
  1175. public async Task<Dictionary<string, decimal>> GetTransactionPeriodEnergy(int transactionId)
  1176. {
  1177. var parms = new DynamicParameters();
  1178. parms.Add("@TransactionId", transactionId);
  1179. var cmd = """
  1180. SELECT TOP(1)
  1181. [H00],[H01],[H02],[H03],[H04],[H05],[H06],[H07],[H08],[H09],[H10]
  1182. ,[H11],[H12],[H13],[H14],[H15],[H16],[H17],[H18],[H19],[H20]
  1183. ,[H21],[H22],[H23]
  1184. FROM [dbo].[TransactionPeriodEnergy]
  1185. WHERE TransactionId = @TransactionId
  1186. """;
  1187. using var dbConn = await sqlConnectionFactory.CreateAsync();
  1188. dynamic queryResult = await dbConn.QueryFirstOrDefaultAsync(cmd, parms);
  1189. if (queryResult is not IDictionary<string, object> queryResultPairs)
  1190. {
  1191. return null;
  1192. }
  1193. var toReturn = new Dictionary<string, decimal>();
  1194. for (int hour = 0; hour < 24; hour++)
  1195. {
  1196. var key = GetColName(hour);
  1197. if (queryResultPairs[key] is decimal value)
  1198. {
  1199. toReturn.Add(hour.ToString(), value);
  1200. }
  1201. }
  1202. return toReturn;
  1203. }
  1204. public async Task InsertOrUpdateTransactionPeriodEnergy(int txId, Dictionary<string, decimal> periodEnergy)
  1205. {
  1206. try
  1207. {
  1208. var isExists = await GetTransactionPeriodEnergyExists(txId);
  1209. var param = CreateParameters(txId, periodEnergy);
  1210. if (isExists)
  1211. {
  1212. await UpdateTransactionPeriodEnergy(param);
  1213. return;
  1214. }
  1215. await InsertTransactionPeriodEnergy(param);
  1216. }
  1217. catch (Exception e)
  1218. {
  1219. logger.LogError(e.Message);
  1220. }
  1221. return;
  1222. async Task<bool> GetTransactionPeriodEnergyExists(int txId)
  1223. {
  1224. var param = new DynamicParameters();
  1225. param.Add("@TransactionId", txId, DbType.Int32, ParameterDirection.Input);
  1226. var cmd = """
  1227. SELECT TransactionId
  1228. FROM TransactionPeriodEnergy
  1229. WHERE TransactionId = @TransactionId
  1230. """;
  1231. using var conn = await sqlConnectionFactory.CreateAsync();
  1232. return await conn.QueryFirstOrDefaultAsync<int?>(cmd, param) != null;
  1233. }
  1234. async Task<int> UpdateTransactionPeriodEnergy(DynamicParameters param)
  1235. {
  1236. var cmd = """
  1237. UPDATE TransactionPeriodEnergy
  1238. SET H00 = @H00, H01 = @H01, H02 = @H02, H03 = @H03, H04 = @H04, H05 = @H05, H06 = @H06, H07 = @H07, H08 = @H08,
  1239. H09 = @H09, H10 = @H10, H11 = @H11, H12 = @H12, H13 = @H13, H14 = @H14, H15 = @H15, H16 = @H16, H17 = @H17,
  1240. H18 = @H18, H19 = @H19, H20 = @H20, H21 = @H21, H22 = @H22, H23 = @H23
  1241. WHERE TransactionId = @TransactionId
  1242. """;
  1243. using var conn = await sqlConnectionFactory.CreateAsync();
  1244. return await conn.ExecuteAsync(cmd, param);
  1245. }
  1246. async Task InsertTransactionPeriodEnergy(DynamicParameters param)
  1247. {
  1248. var cmd = """
  1249. INSERT INTO TransactionPeriodEnergy
  1250. (TransactionId, H00, H01, H02, H03, H04, H05, H06, H07, H08, H09, H10, H11, H12, H13, H14, H15, H16, H17, H18, H19, H20, H21, H22, H23)
  1251. VALUES (@TransactionId, @H00, @H01, @H02, @H03, @H04, @H05, @H06, @H07, @H08, @H09, @H10, @H11, @H12, @H13, @H14, @H15, @H16, @H17, @H18, @H19, @H20, @H21, @H22, @H23)
  1252. """;
  1253. using var conn = await sqlConnectionFactory.CreateAsync();
  1254. await conn.ExecuteAsync(cmd, param);
  1255. }
  1256. DynamicParameters CreateParameters(int txId, Dictionary<string, decimal> periodEnergy)
  1257. {
  1258. var parameters = new DynamicParameters();
  1259. parameters.Add("@TransactionId", txId, DbType.Int32, ParameterDirection.Input);
  1260. for (int hour = 0; hour < 24; hour++)
  1261. {
  1262. var key = hour.ToString();
  1263. if (!periodEnergy.ContainsKey(key))
  1264. {
  1265. parameters.Add(GetColName(hour), 0, DbType.Decimal, ParameterDirection.Input, precision: 18, scale: 4);
  1266. continue;
  1267. }
  1268. parameters.Add(GetColName(hour), periodEnergy[key], DbType.Decimal, ParameterDirection.Input, precision: 18, scale: 4);
  1269. }
  1270. return parameters;
  1271. }
  1272. string GetColName(int hour)
  1273. {
  1274. return $"@H{hour.ToString("00")}";
  1275. }
  1276. }
  1277. string GetColName(int hour)
  1278. {
  1279. return $"H{hour.ToString("00")}";
  1280. }
  1281. }
  1282. public record MachineAndCustomerInfo(string MachineId, Guid CustomerId, string CustomerName);
  1283. public record StatusNotificationParam(string Id, ConnectorStatus Status);
  1284. public record UpdateMachineBasicInfoParam(string ChargeBoxId, Machine machine);
  1285. public record UpdateErrofFinishedOnParam(int Id, DateTime finishedOn);