MainDbService.cs 65 KB

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