|
@@ -1,23 +1,15 @@
|
|
|
-using EVCB_OCPP.Domain;
|
|
|
+using Dapper;
|
|
|
+using EVCB_OCPP.Domain;
|
|
|
using EVCB_OCPP.Domain.Models.Database;
|
|
|
-using EVCB_OCPP.Packet.Messages.Core;
|
|
|
using EVCB_OCPP.WSServer.Helper;
|
|
|
using Microsoft.Data.SqlClient;
|
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
using Microsoft.Extensions.Caching.Memory;
|
|
|
using Microsoft.Extensions.Configuration;
|
|
|
-using Microsoft.Extensions.DependencyInjection;
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
-using MongoDB.Driver.Core.Connections;
|
|
|
using Newtonsoft.Json;
|
|
|
using OCPPPackage.Profiles;
|
|
|
-using System;
|
|
|
-using System.Collections.Generic;
|
|
|
using System.Data;
|
|
|
-using System.Linq;
|
|
|
-using System.Text;
|
|
|
-using System.Threading;
|
|
|
-using System.Threading.Tasks;
|
|
|
|
|
|
namespace EVCB_OCPP.WSServer.Service;
|
|
|
|
|
@@ -32,24 +24,31 @@ public interface IMainDbService
|
|
|
Task AddOCMF(OCMF oCMF);
|
|
|
ValueTask<ConnectorStatus> GetConnectorStatus(string ChargeBoxId, int ConnectorId);
|
|
|
Task UpdateConnectorStatus(string Id, ConnectorStatus connectorStatus);
|
|
|
+ ValueTask AddConnectorStatus(string ChargeBoxId, byte ConnectorId, DateTime CreatedOn, int Status,
|
|
|
+ int ChargePointErrorCodeId, string ErrorInfo, string VendorId, string VendorErrorCode);
|
|
|
Task AddServerMessage(ServerMessage message);
|
|
|
Task AddServerMessage(string ChargeBoxId, string OutAction, object OutRequest, string CreatedBy = "", DateTime? CreatedOn = null, string SerialNo = "", string InMessage = "");
|
|
|
+ ValueTask AddMachineError(byte ConnectorId, DateTime CreatedOn, int Status, string ChargeBoxId, int ErrorCodeId, string ErrorInfo, int PreStatus, string VendorErrorCode, string VendorId);
|
|
|
+ ValueTask<Customer> GetCustomer(string id);
|
|
|
+ ValueTask<Customer> GetCustomer(Guid id);
|
|
|
}
|
|
|
|
|
|
public class MainDbService : IMainDbService
|
|
|
{
|
|
|
public MainDbService(
|
|
|
IDbContextFactory<MainDBContext> contextFactory,
|
|
|
+ SqlConnectionFactory<MainDBContext> sqlConnectionFactory,
|
|
|
IMemoryCache memoryCache,
|
|
|
- IConfiguration configuration,
|
|
|
+ IConfiguration configuration,
|
|
|
ILoggerFactory loggerFactory)
|
|
|
{
|
|
|
this.contextFactory = contextFactory;
|
|
|
+ this.sqlConnectionFactory = sqlConnectionFactory;
|
|
|
this.memoryCache = memoryCache;
|
|
|
this.loggerFactory = loggerFactory;
|
|
|
var startupLimit = GetStartupLimit(configuration);
|
|
|
- this.connectionString = configuration.GetConnectionString("MainDBContext");
|
|
|
- this.startupSemaphore = new (startupLimit);
|
|
|
+ //this.connectionString = configuration.GetConnectionString("MainDBContext");
|
|
|
+ this.startupSemaphore = new(startupLimit);
|
|
|
|
|
|
var opLimit = GetOpLimit(configuration);
|
|
|
this.opSemaphore = new SemaphoreSlim(opLimit);
|
|
@@ -60,9 +59,10 @@ public class MainDbService : IMainDbService
|
|
|
}
|
|
|
|
|
|
private readonly IDbContextFactory<MainDBContext> contextFactory;
|
|
|
+ private readonly SqlConnectionFactory<MainDBContext> sqlConnectionFactory;
|
|
|
private readonly IMemoryCache memoryCache;
|
|
|
private readonly ILoggerFactory loggerFactory;
|
|
|
- private string connectionString;
|
|
|
+ //private string connectionString;
|
|
|
private readonly QueueSemaphore startupSemaphore;
|
|
|
private readonly SemaphoreSlim opSemaphore;
|
|
|
private GroupSingleHandler<StatusNotificationParam> statusNotificationHandler;
|
|
@@ -78,7 +78,9 @@ public class MainDbService : IMainDbService
|
|
|
{
|
|
|
return new MachineAndCustomerInfo(string.Empty, Guid.Empty, "Unknown");
|
|
|
}
|
|
|
- var customerName = await db.Customer.Where(x => x.Id == machine.CustomerId).Select(x => x.Name).FirstOrDefaultAsync();
|
|
|
+ //var customerName = await db.Customer.Where(x => x.Id == machine.CustomerId).Select(x => x.Name).FirstOrDefaultAsync();
|
|
|
+ var customer = await GetCustomer(machine.CustomerId);
|
|
|
+ var customerName = customer?.Name;
|
|
|
return new MachineAndCustomerInfo(machine.Id, machine.CustomerId, customerName);
|
|
|
}
|
|
|
|
|
@@ -134,6 +136,35 @@ public class MainDbService : IMainDbService
|
|
|
await db.SaveChangesAsync();
|
|
|
}
|
|
|
|
|
|
+ public async ValueTask AddConnectorStatus(
|
|
|
+ string ChargeBoxId, byte ConnectorId, DateTime CreatedOn, int Status,
|
|
|
+ int ChargePointErrorCodeId, string ErrorInfo, string VendorId, string VendorErrorCode)
|
|
|
+ {
|
|
|
+ using var db = contextFactory.CreateDbContext();
|
|
|
+ var _currentStatus = new Domain.Models.Database.ConnectorStatus()
|
|
|
+ {
|
|
|
+ ChargeBoxId = ChargeBoxId,
|
|
|
+ ConnectorId = ConnectorId,
|
|
|
+ CreatedOn = CreatedOn,
|
|
|
+ Status = Status,
|
|
|
+ ChargePointErrorCodeId = ChargePointErrorCodeId,
|
|
|
+ ErrorInfo = ErrorInfo,
|
|
|
+ VendorId = VendorId,
|
|
|
+ VendorErrorCode = VendorErrorCode,
|
|
|
+ Id = Guid.NewGuid().ToString()
|
|
|
+ };
|
|
|
+ db.ConnectorStatus.Add(_currentStatus);
|
|
|
+
|
|
|
+ db.SaveChanges();
|
|
|
+
|
|
|
+ Task.Run(() => {
|
|
|
+ lock (memoryCache)
|
|
|
+ {
|
|
|
+ memoryCache.Set($"{ChargeBoxId}{ConnectorId}", _currentStatus, TimeSpan.FromHours(12));
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
public async ValueTask<ConnectorStatus> GetConnectorStatus(string ChargeBoxId, int ConnectorId)
|
|
|
{
|
|
|
var key = $"{ChargeBoxId}{ConnectorId}";
|
|
@@ -144,44 +175,104 @@ public class MainDbService : IMainDbService
|
|
|
using var db = contextFactory.CreateDbContext();
|
|
|
var statusFromDb = await db.ConnectorStatus.Where(x => x.ChargeBoxId == ChargeBoxId
|
|
|
&& x.ConnectorId == ConnectorId).AsNoTracking().FirstOrDefaultAsync();
|
|
|
- memoryCache.Set(key, statusFromDb);
|
|
|
+
|
|
|
+ Task.Run(() => {
|
|
|
+ lock (memoryCache)
|
|
|
+ {
|
|
|
+ memoryCache.Set(key, statusFromDb, TimeSpan.FromHours(12));
|
|
|
+ }
|
|
|
+ });
|
|
|
return statusFromDb;
|
|
|
}
|
|
|
|
|
|
public async Task UpdateConnectorStatus(string Id, ConnectorStatus Status)
|
|
|
{
|
|
|
- //using var db = await contextFactory.CreateDbContextAsync();
|
|
|
+ //await statusNotificationHandler.HandleAsync(new StatusNotificationParam(Id, Status));
|
|
|
+ //await UpdateConnectorStatusEF(Id, Status);
|
|
|
+ await UpdateConnectorStatusDapper(Id, Status);
|
|
|
|
|
|
- //ConnectorStatus status = new() { Id = Id };
|
|
|
+ var key = $"{Status.ChargeBoxId}{Status.ConnectorId}";
|
|
|
+ Task.Run(() => {
|
|
|
+ lock (memoryCache)
|
|
|
+ {
|
|
|
+ memoryCache.Set(key, Status, TimeSpan.FromHours(12));
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ private async Task UpdateConnectorStatusEF(string Id, ConnectorStatus Status)
|
|
|
+ {
|
|
|
+ using var db = await contextFactory.CreateDbContextAsync();
|
|
|
|
|
|
- //db.ChangeTracker.AutoDetectChangesEnabled = false;
|
|
|
- //db.ConnectorStatus.Attach(status);
|
|
|
+ ConnectorStatus status = new() { Id = Id };
|
|
|
|
|
|
+ db.ChangeTracker.AutoDetectChangesEnabled = false;
|
|
|
+ db.ConnectorStatus.Attach(status);
|
|
|
|
|
|
- //status.CreatedOn = Status.CreatedOn;
|
|
|
- //status.Status = Status.Status;
|
|
|
- //status.ChargePointErrorCodeId = Status.ChargePointErrorCodeId;
|
|
|
- //status.ErrorInfo = Status.ErrorInfo;
|
|
|
- //status.VendorId = Status.VendorId;
|
|
|
- //status.VendorErrorCode = Status.VendorErrorCode;
|
|
|
|
|
|
+ status.CreatedOn = Status.CreatedOn;
|
|
|
+ status.Status = Status.Status;
|
|
|
+ status.ChargePointErrorCodeId = Status.ChargePointErrorCodeId;
|
|
|
+ status.ErrorInfo = Status.ErrorInfo;
|
|
|
+ status.VendorId = Status.VendorId;
|
|
|
+ status.VendorErrorCode = Status.VendorErrorCode;
|
|
|
|
|
|
- //db.Entry(status).Property(x => x.CreatedOn).IsModified = true;
|
|
|
- //db.Entry(status).Property(x => x.Status).IsModified = true;
|
|
|
- //db.Entry(status).Property(x => x.ChargePointErrorCodeId).IsModified = true;
|
|
|
- //db.Entry(status).Property(x => x.ErrorInfo).IsModified = true;
|
|
|
- //db.Entry(status).Property(x => x.VendorId).IsModified = true;
|
|
|
- //db.Entry(status).Property(x => x.VendorErrorCode).IsModified = true;
|
|
|
|
|
|
- //await db.SaveChangesAsync();
|
|
|
- await statusNotificationHandler.HandleAsync(new StatusNotificationParam(Id, Status));
|
|
|
- var key = $"{Status.ChargeBoxId}{Status.ConnectorId}";
|
|
|
- if (memoryCache.TryGetValue<ConnectorStatus>(key, out _))
|
|
|
+ db.Entry(status).Property(x => x.CreatedOn).IsModified = true;
|
|
|
+ db.Entry(status).Property(x => x.Status).IsModified = true;
|
|
|
+ db.Entry(status).Property(x => x.ChargePointErrorCodeId).IsModified = true;
|
|
|
+ db.Entry(status).Property(x => x.ErrorInfo).IsModified = true;
|
|
|
+ db.Entry(status).Property(x => x.VendorId).IsModified = true;
|
|
|
+ db.Entry(status).Property(x => x.VendorErrorCode).IsModified = true;
|
|
|
+
|
|
|
+ await db.SaveChangesAsync();
|
|
|
+ }
|
|
|
+
|
|
|
+ private async Task UpdateConnectorStatusDapper(string Id, ConnectorStatus Status)
|
|
|
+ {
|
|
|
+ var parameters = new DynamicParameters();
|
|
|
+ parameters.Add("@Id", Id, DbType.String, ParameterDirection.Input, 36);
|
|
|
+ parameters.Add("@CreatedOn", Status.CreatedOn, DbType.DateTime, ParameterDirection.Input);
|
|
|
+ parameters.Add("@Status", Status.Status, DbType.Int32, ParameterDirection.Input);
|
|
|
+ parameters.Add("@ChargePointErrorCodeId", Status.ChargePointErrorCodeId, DbType.Int32, ParameterDirection.Input);
|
|
|
+ parameters.Add("@ErrorInfo", Status.ErrorInfo, DbType.String, ParameterDirection.Input, 50);
|
|
|
+ parameters.Add("@VendorId", Status.VendorId, DbType.String, ParameterDirection.Input, 255);
|
|
|
+ parameters.Add("@VendorErrorCode", Status.VendorErrorCode, DbType.String, ParameterDirection.Input, 100);
|
|
|
+
|
|
|
+ using var conn = sqlConnectionFactory.Create();
|
|
|
+ await conn.ExecuteAsync("""
|
|
|
+ update ConnectorStatus
|
|
|
+ set
|
|
|
+ CreatedOn = @CreatedOn,
|
|
|
+ Status = @Status,
|
|
|
+ ChargePointErrorCodeId = @ChargePointErrorCodeId,
|
|
|
+ ErrorInfo = @ErrorInfo,
|
|
|
+ VendorId = @VendorId,
|
|
|
+ VendorErrorCode = @VendorErrorCode
|
|
|
+ where Id = @Id
|
|
|
+ """, parameters );
|
|
|
+ }
|
|
|
+
|
|
|
+ public async ValueTask AddMachineError(byte ConnectorId, DateTime CreatedOn, int Status, string ChargeBoxId,
|
|
|
+ int ErrorCodeId, string ErrorInfo, int PreStatus, string VendorErrorCode, string VendorId)
|
|
|
+ {
|
|
|
+ using var db = contextFactory.CreateDbContext();
|
|
|
+ db.MachineError.Add(new MachineError()
|
|
|
{
|
|
|
- memoryCache.Remove(key);
|
|
|
- }
|
|
|
- memoryCache.Set(key, Status);
|
|
|
- return;
|
|
|
+ ConnectorId = ConnectorId,
|
|
|
+ CreatedOn = CreatedOn,
|
|
|
+ Status = Status,
|
|
|
+ ChargeBoxId = ChargeBoxId,
|
|
|
+ ErrorCodeId = ErrorCodeId,
|
|
|
+ ErrorInfo = ErrorInfo,
|
|
|
+ PreStatus = PreStatus,
|
|
|
+ VendorErrorCode = VendorErrorCode,
|
|
|
+ VendorId = VendorId
|
|
|
+ });
|
|
|
+
|
|
|
+ db.SaveChanges();
|
|
|
+
|
|
|
}
|
|
|
|
|
|
public Task AddServerMessage(string ChargeBoxId, string OutAction, object OutRequest, string CreatedBy, DateTime? CreatedOn = null, string SerialNo = "", string InMessage = "")
|
|
@@ -226,6 +317,35 @@ public class MainDbService : IMainDbService
|
|
|
return addServerMessageHandler.HandleAsync(message);
|
|
|
}
|
|
|
|
|
|
+ public ValueTask<Customer> GetCustomer(string id)
|
|
|
+ => GetCustomer(new Guid(id));
|
|
|
+ public async ValueTask<Customer> GetCustomer(Guid id)
|
|
|
+ {
|
|
|
+ var key = $"Customer{id}";
|
|
|
+ if (memoryCache.TryGetValue<Customer>(key, out var customer))
|
|
|
+ {
|
|
|
+ return customer;
|
|
|
+ }
|
|
|
+
|
|
|
+ Customer toReturn = null;
|
|
|
+ using (var db = contextFactory.CreateDbContext())
|
|
|
+ {
|
|
|
+ toReturn = await db.Customer.FirstOrDefaultAsync(x => x.Id == id);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (toReturn is not null)
|
|
|
+ {
|
|
|
+ Task.Run(() => {
|
|
|
+ lock (memoryCache)
|
|
|
+ {
|
|
|
+ memoryCache.Set(key, toReturn, TimeSpan.FromSeconds(15));
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ return toReturn;
|
|
|
+ }
|
|
|
+
|
|
|
private void InitUpdateMachineBasicInfoHandler()
|
|
|
{
|
|
|
if (updateMachineBasicInfoHandler is not null)
|
|
@@ -272,9 +392,9 @@ public class MainDbService : IMainDbService
|
|
|
}
|
|
|
|
|
|
statusNotificationHandler = new GroupSingleHandler<StatusNotificationParam>(
|
|
|
- handleFunc: BundleUpdateConnectorStatus,
|
|
|
+ handleFunc: BundleUpdateConnectorStatusDapper,
|
|
|
logger: loggerFactory.CreateLogger("StatusNotificationHandler"),
|
|
|
- workerCnt: 10);
|
|
|
+ workerCnt: 1);
|
|
|
}
|
|
|
|
|
|
private async Task BundleUpdateConnectorStatus(IEnumerable<StatusNotificationParam> statusNotifications)
|
|
@@ -315,6 +435,39 @@ public class MainDbService : IMainDbService
|
|
|
db.ChangeTracker.Clear();
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+ private Task BundleUpdateConnectorStatusDapper(IEnumerable<StatusNotificationParam> statusNotifications)
|
|
|
+ {
|
|
|
+ using var conn = sqlConnectionFactory.Create();
|
|
|
+
|
|
|
+ foreach (var status in statusNotifications)
|
|
|
+ {
|
|
|
+
|
|
|
+ var parameters = new DynamicParameters();
|
|
|
+ parameters.Add("@Id", status.Id, DbType.String, ParameterDirection.Input, 36);
|
|
|
+ parameters.Add("@CreatedOn", status.Status.CreatedOn, DbType.DateTime, ParameterDirection.Input);
|
|
|
+ parameters.Add("@Status", status.Status.Status, DbType.Int32, ParameterDirection.Input);
|
|
|
+ parameters.Add("@ChargePointErrorCodeId", status.Status.ChargePointErrorCodeId, DbType.Int32, ParameterDirection.Input);
|
|
|
+ parameters.Add("@ErrorInfo", status.Status.ErrorInfo, DbType.String, ParameterDirection.Input, 50);
|
|
|
+ parameters.Add("@VendorId", status.Status.VendorId, DbType.String, ParameterDirection.Input, 255);
|
|
|
+ parameters.Add("@VendorErrorCode", status.Status.VendorErrorCode, DbType.String, ParameterDirection.Input, 100);
|
|
|
+
|
|
|
+ conn.Execute("""
|
|
|
+ update ConnectorStatus
|
|
|
+ set
|
|
|
+ CreatedOn = @CreatedOn,
|
|
|
+ Status = @Status,
|
|
|
+ ChargePointErrorCodeId = @ChargePointErrorCodeId,
|
|
|
+ ErrorInfo = @ErrorInfo,
|
|
|
+ VendorId = @VendorId,
|
|
|
+ VendorErrorCode = @VendorErrorCode
|
|
|
+ where Id = @Id
|
|
|
+ """, parameters);
|
|
|
+ }
|
|
|
+ return Task.CompletedTask;
|
|
|
+ }
|
|
|
+
|
|
|
private void InitAddServerMessageHandler()
|
|
|
{
|
|
|
if (addServerMessageHandler is not null)
|
|
@@ -323,7 +476,7 @@ public class MainDbService : IMainDbService
|
|
|
}
|
|
|
|
|
|
addServerMessageHandler = new GroupSingleHandler<ServerMessage>(
|
|
|
- handleFunc: BulkInsertServerMessage,
|
|
|
+ handleFunc: BundleAddServerMessage,
|
|
|
logger: loggerFactory.CreateLogger("AddServerMessageHandler"));
|
|
|
}
|
|
|
|
|
@@ -371,8 +524,7 @@ public class MainDbService : IMainDbService
|
|
|
table.Rows.Add(row);
|
|
|
}
|
|
|
|
|
|
- using SqlConnection sqlConnection = new SqlConnection(connectionString);
|
|
|
- sqlConnection.Open();
|
|
|
+ using SqlConnection sqlConnection = sqlConnectionFactory.Create();
|
|
|
using SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(sqlConnection);
|
|
|
|
|
|
sqlBulkCopy.BatchSize = messages.Count();
|