瀏覽代碼

1. fix comm DLL
2. change readonly property to function

Robert 1 年之前
父節點
當前提交
fedc5c3698
共有 32 個文件被更改,包括 559 次插入813 次删除
  1. 2 2
      Dev_Build.bat
  2. 二進制
      EVCB_OCPP.WSServer/DLL/EVCB_OCPP.Domain.dll
  3. 5 128
      EVCB_OCPP.WSServer/Helper/AddPortalDbContext.cs
  4. 6 5
      EVCB_OCPP.WSServer/Helper/MeterValueGroupSingleHandler.cs
  5. 4 9
      EVCB_OCPP.WSServer/HostedProtalServer.cs
  6. 2 2
      EVCB_OCPP.WSServer/Jobs/DenyModelCheckJob.cs
  7. 1 1
      EVCB_OCPP.WSServer/Jobs/HealthCheckTriggerJob.cs
  8. 1 1
      EVCB_OCPP.WSServer/Jobs/HeartBeatCheckJob.cs
  9. 2 10
      EVCB_OCPP.WSServer/Jobs/ServerMessageJob.cs
  10. 17 110
      EVCB_OCPP.WSServer/Jobs/ServerSetFeeJob.cs
  11. 1 1
      EVCB_OCPP.WSServer/Jobs/ServerUpdateJob.cs
  12. 4 2
      EVCB_OCPP.WSServer/Jobs/SmartChargingJob.cs
  13. 63 135
      EVCB_OCPP.WSServer/Message/CoreProfileHandler.cs
  14. 1 1
      EVCB_OCPP.WSServer/Message/FirmwareManagementProfileHandler.cs
  15. 1 1
      EVCB_OCPP.WSServer/Message/LocalAuthListManagementProfileHandler.cs
  16. 1 1
      EVCB_OCPP.WSServer/Message/RemoteTriggerHandler.cs
  17. 1 1
      EVCB_OCPP.WSServer/Message/ReservationProfileHandler.cs
  18. 1 1
      EVCB_OCPP.WSServer/Message/SecurityProfileHandler.cs
  19. 1 1
      EVCB_OCPP.WSServer/Message/SmartChargingProfileHandler.cs
  20. 5 26
      EVCB_OCPP.WSServer/Program.cs
  21. 202 345
      EVCB_OCPP.WSServer/ProtalServer.cs
  22. 3 2
      EVCB_OCPP.WSServer/Service/BlockingTreePrintService.cs
  23. 4 3
      EVCB_OCPP.WSServer/Service/ConnectionLogdbService.cs
  24. 6 3
      EVCB_OCPP.WSServer/Service/LoadingBalanceService.cs
  25. 48 5
      EVCB_OCPP.WSServer/Service/MainDbService.cs
  26. 3 2
      EVCB_OCPP.WSServer/Service/MeterValueDbService.cs
  27. 3 2
      EVCB_OCPP.WSServer/Service/MeterValueInsertHandler.cs
  28. 55 0
      EVCB_OCPP.WSServer/Service/ServerMessageService.cs
  29. 108 4
      EVCB_OCPP.WSServer/Service/WebDbService.cs
  30. 5 1
      EVCB_OCPP.WSServer/SuperSocket/OCPPWSServer.cs
  31. 2 7
      EVCB_OCPP.WSServer/SuperSocket/OCPPWSServerFactory.cs
  32. 1 1
      TestTool.RemoteTriggerAPP/MainWindow.xaml.cs

+ 2 - 2
Dev_Build.bat

@@ -1,3 +1,3 @@
 for /f %%i in ('git rev-parse --short HEAD') do set ssha=%%i
-docker build ./ -t evdevcontainerregistry.azurecr.io/nginx-reverse-proxy:test --label "git-commit=%ssha%"
-docker push evdevcontainerregistry.azurecr.io/nginx-reverse-proxy:test
+docker build ./ -t evdevcontainerregistry.azurecr.io/server:test --label "git-commit=%ssha%"
+docker push evdevcontainerregistry.azurecr.io/server:test

二進制
EVCB_OCPP.WSServer/DLL/EVCB_OCPP.Domain.dll


+ 5 - 128
EVCB_OCPP.WSServer/Helper/AddPortalDbContext.cs

@@ -1,4 +1,5 @@
 using EVCB_OCPP.Domain;
+using EVCB_OCPP.Domain.Extensions;
 using Microsoft.Data.SqlClient;
 using Microsoft.EntityFrameworkCore;
 using Microsoft.Extensions.Configuration;
@@ -18,72 +19,14 @@ namespace EVCB_OCPP.WSServer.Helper;
 
 public static class AddPortalDbContext
 {
-    public const string CommandTimeoutKey = "CommandTimeout";
-    public static IServiceCollection AddMainDbContext(this IServiceCollection services, IConfiguration configuration)
-    { 
-        const string DbUserIdKey = "MainDbUserIdKey";
-        const string DbPassKey = "MainDbPass";
-        const string DbConnectionStringKey = "MainDBContext";
-
-        var conneciotnString = GetConnectionString(configuration, DbUserIdKey, DbPassKey, DbConnectionStringKey);
-
-        services.AddSingleton(
-            (serviceProvider) =>
-            new SqlConnectionFactory<MainDBContext>(serviceProvider.GetRequiredService<ILogger<SqlConnectionFactory<MainDBContext>>>())
-            {
-                ConnectionString = conneciotnString
-            });
-        AddPortalDbContextInternal<MainDBContext>(services, configuration, conneciotnString, logToConsole: false);
-        return services;
-    }
-
-    public static IServiceCollection AddMeterValueDbContext(this IServiceCollection services, IConfiguration configuration)
-    {
-        const string DbUserIdKey = "MeterValueDbUserId";
-        const string DbPassKey = "MeterValueDbPass";
-        const string DbConnectionStringKey = "MeterValueDBContext";
-
-        var conneciotnString = GetConnectionString(configuration, DbUserIdKey, DbPassKey, DbConnectionStringKey);
-        services.AddSingleton(
-            (serviceProvider) =>
-            new SqlConnectionFactory<MeterValueDBContext>(serviceProvider.GetRequiredService<ILogger<SqlConnectionFactory<MeterValueDBContext>>>())
-            {
-                ConnectionString = conneciotnString
-            });
-        AddPortalDbContextInternal<MeterValueDBContext>(services, configuration, conneciotnString, logToConsole: false);
-        return services;
-    }
-
-    public static IServiceCollection AddConnectionLogDbContext(this IServiceCollection services, IConfiguration configuration)
-    {
-        const string DbUserIdKey = "ConnectionLogDbUserId";
-        const string DbPassKey = "ConnectionLogDbPass";
-        const string DbConnectionStringKey = "ConnectionLogDBContext";
-
-        var conneciotnString = GetConnectionString(configuration, DbUserIdKey, DbPassKey, DbConnectionStringKey);
-        services.AddSingleton(
-            (serviceProvider) =>
-            new SqlConnectionFactory<ConnectionLogDBContext>(serviceProvider.GetRequiredService<ILogger<SqlConnectionFactory<ConnectionLogDBContext>>>())
-            {
-                ConnectionString = conneciotnString
-            });
-        AddPortalDbContextInternal<ConnectionLogDBContext>(services, configuration, conneciotnString);
-        return services;
-    }
-
     public static IServiceCollection AddWebDBConetext(this IServiceCollection services, IConfiguration configuration)
     {
         const string DbUserIdKey = "WebDbUserId";
         const string DbPassKey = "WebDbPass";
         const string DbConnectionStringKey = "WebDBContext";
 
-        var conneciotnString = GetConnectionString(configuration, DbUserIdKey, DbPassKey, DbConnectionStringKey);
-        services.AddSingleton(
-            (serviceProvider) =>
-            new SqlConnectionFactory<WebDBConetext>(serviceProvider.GetRequiredService<ILogger<SqlConnectionFactory<WebDBConetext>>>())
-            {
-                ConnectionString = conneciotnString
-            });
+        var conneciotnString = configuration.GetConnectionString(DbUserIdKey, DbPassKey, DbConnectionStringKey);
+        services.AddSqlConnectionFactory<WebDBConetext>(conneciotnString);
         return services;
     }
 
@@ -93,76 +36,10 @@ public static class AddPortalDbContext
         const string DbPassKey = "OnlineLogDbPass";
         const string DbConnectionStringKey = "OnlineLogDBContext";
 
-        var conneciotnString = GetConnectionString(configuration, DbUserIdKey, DbPassKey, DbConnectionStringKey);
-        services.AddSingleton(
-            (serviceProvider) =>
-            new SqlConnectionFactory<OnlineLogDBContext>(serviceProvider.GetRequiredService<ILogger<SqlConnectionFactory<OnlineLogDBContext>>>())
-            {
-                ConnectionString = conneciotnString
-            });
+        var conneciotnString = configuration.GetConnectionString(DbUserIdKey, DbPassKey, DbConnectionStringKey);
+        services.AddSqlConnectionFactory<OnlineLogDBContext>(conneciotnString);
         return services;
     }
-
-    private static void AddPortalDbContextInternal<T>(
-        IServiceCollection services, IConfiguration configuration,
-        string connectionString,bool logToConsole = false) where T : DbContext
-    {
-
-        var commandTimeout = int.TryParse(configuration[CommandTimeoutKey], out var temp) ? temp : 180;
-        
-        services.AddPooledDbContextFactory<T>((serviceProvider, options) => {
-            options.UseSqlServer(connectionString, dbOptions =>
-            {
-                dbOptions.CommandTimeout(commandTimeout);
-            });
-            options.UseLoggerFactory(serviceProvider.GetRequiredService<ILoggerFactory>());
-        });
-    }
-
-    private static string GetConnectionString(IConfiguration configuration, string UserIdKey, string DbPassKey, string ConnectionStringKey ) 
-    {
-        string mainDbUserId = string.IsNullOrEmpty(configuration[UserIdKey]) ? string.Empty : $"user id={configuration[UserIdKey]};";
-        string mainDbUserPass = string.IsNullOrEmpty(configuration[DbPassKey]) ? string.Empty : $"password={configuration[DbPassKey]};";
-        return $"{configuration.GetConnectionString(ConnectionStringKey)}{mainDbUserId}{mainDbUserPass}";
-    }
-}
-
-public class SqlConnectionFactory<T> where T: DbContext
-{
-    private readonly ILogger<SqlConnectionFactory<T>> logger;
-
-    public string ConnectionString { get; init; }
-    public SqlConnectionFactory(ILogger<SqlConnectionFactory<T>> logger)
-    {
-        this.logger = logger;
-    }
-
-    public SqlConnection Create()
-    {
-        var sqlConnection = new SqlConnection(ConnectionString);
-        sqlConnection.Open();
-        return sqlConnection;
-    }
-
-    public async Task<SqlConnection> CreateAsync()
-    {
-        var timer = Stopwatch.StartNew();
-        long t0, t1;
-
-        var sqlConnection = new SqlConnection(ConnectionString);
-        t0 = timer.ElapsedMilliseconds;
-
-        await sqlConnection.OpenAsync();
-        t1 = timer.ElapsedMilliseconds;
-        timer.Stop();
-
-        if (t1 > 500)
-        {
-            logger.LogWarning($"{typeof(T)} SqlConnection Open slow {t0}/{t1}");
-        }
-
-        return sqlConnection;
-    }
 }
 
 /// <summary>

+ 6 - 5
EVCB_OCPP.WSServer/Helper/MeterValueGroupSingleHandler.cs

@@ -1,5 +1,6 @@
 using Dapper;
 using EVCB_OCPP.Domain;
+using EVCB_OCPP.Domain.ConnectionFactory;
 using EVCB_OCPP.WSServer.Service;
 using Microsoft.Data.SqlClient;
 using Microsoft.EntityFrameworkCore;
@@ -20,7 +21,7 @@ public class MeterValueGroupSingleHandler
 {
     public MeterValueGroupSingleHandler(
         IDbContextFactory<MeterValueDBContext> meterValueDbContextFactory,
-        SqlConnectionFactory<MeterValueDBContext> connectionFactory,
+        ISqlConnectionFactory<MeterValueDBContext> connectionFactory,
         IConfiguration configuration,
         ILogger<MeterValueGroupSingleHandler> logger)
     {
@@ -42,7 +43,7 @@ public class MeterValueGroupSingleHandler
     }
 
     private readonly IDbContextFactory<MeterValueDBContext> meterValueDbContextFactory;
-    private readonly SqlConnectionFactory<MeterValueDBContext> connectionFactory;
+    private readonly ISqlConnectionFactory<MeterValueDBContext> connectionFactory;
     private readonly IConfiguration configuration;
 
     //private readonly Func<IEnumerable<T>, Task> handleFunc;
@@ -154,8 +155,8 @@ public class MeterValueGroupSingleHandler
         t2 = watch.ElapsedMilliseconds;
         foreach (var group in gruopParams)
         {
-            using SqlConnection sqlConnection = await connectionFactory.CreateAsync();
-            using var tans = sqlConnection.BeginTransaction();
+            using SqlConnection conn = await connectionFactory.CreateAsync();
+            using SqlTransaction tans = conn.BeginTransaction();
 
             var tableName = group.Key;
             string command = $"""
@@ -176,7 +177,7 @@ public class MeterValueGroupSingleHandler
                 parameters.Add("UnitId", param.unitId, DbType.Int32);
                 parameters.Add("ChargeBoxId", param.chargeBoxId, DbType.String, size: 50);
                 parameters.Add("TransactionId", param.transactionId, DbType.Int32);
-                await sqlConnection.ExecuteAsync(command, parameters, tans);
+                await conn.ExecuteAsync(command, parameters, tans);
             }
 
             await tans.CommitAsync();

+ 4 - 9
EVCB_OCPP.WSServer/HostedProtalServer.cs

@@ -1,20 +1,12 @@
-using EVCB_OCPP.Domain;
-using EVCB_OCPP.WSServer.Fake;
+using EVCB_OCPP.Domain.Extensions;
 using EVCB_OCPP.WSServer.Helper;
 using EVCB_OCPP.WSServer.Jobs;
 using EVCB_OCPP.WSServer.Message;
 using EVCB_OCPP.WSServer.Service;
 using EVCB_OCPP.WSServer.SuperSocket;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.Caching.Memory;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.DependencyInjection;
 using Quartz;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace EVCB_OCPP.WSServer
 {
@@ -31,12 +23,15 @@ namespace EVCB_OCPP.WSServer
             services.AddTransient<OCPPWSServer>();
             services.AddTransient<IOCPPWSServerFactory, OCPPWSServerFactory>();
 
+            services.AddSingleton<ServerMessageService>();
+            services.AddSingleton<LoadingBalanceService>();
             services.AddSingleton<MeterValueDbService>();
             services.AddSingleton<WebDbService>();
             services.AddSingleton<IMainDbService, MainDbService>();
             services.AddSingleton<IConnectionLogdbService, ConnectionLogdbService>();
 
             services.AddTransient<ProfileHandler>();
+
             services.AddSingleton<ProtalServer>();
             services.AddHostedService<ProtalServer>(p => p.GetRequiredService<ProtalServer>());
 

+ 2 - 2
EVCB_OCPP.WSServer/Jobs/DenyModelCheckJob.cs

@@ -40,7 +40,7 @@ public class DenyModelCheckJob : IJob
         //logger.LogDebug("{0} Started", nameof(DenyModelCheckJob));
         try
         {
-            GlobalConfig.DenyModelNames = await webDbService.GetDenyModelNames();
+            GlobalConfig.DenyModelNames = await webDbService.GetDenyModelNames(context.CancellationToken);
             logger.LogDebug("Current DenyList:[{0}]", string.Join(",", GlobalConfig.DenyModelNames));
 
             if (string.IsNullOrEmpty(GlobalConfig.DenyModelNames[0]))
@@ -48,7 +48,7 @@ public class DenyModelCheckJob : IJob
                 return;
             }
 
-            Dictionary<string, ClientData> _copyClientDic = protalServer.ClientDic;
+            Dictionary<string, ClientData> _copyClientDic = protalServer.GetClientDic();
             foreach (var denyName in GlobalConfig.DenyModelNames)
             {
                 var removeClients = _copyClientDic.Where(x => x.Key.StartsWith(denyName)).Select(x => x.Value).ToList();

+ 1 - 1
EVCB_OCPP.WSServer/Jobs/HealthCheckTriggerJob.cs

@@ -28,7 +28,7 @@ public class HealthCheckTriggerJob : IJob
     {
         //logger.LogDebug("{0} Started", nameof(HealthCheckTriggerJob));
 
-        Dictionary<string, ClientData> _copyClientDic = protalServer.ClientDic;
+        Dictionary<string, ClientData> _copyClientDic = protalServer.GetClientDic();
 
         var removeClients = _copyClientDic.Where(x => x.Value.LastActiveTime < DateTime.UtcNow.AddSeconds(-300)).Select(x => x.Value).ToList();
 

+ 1 - 1
EVCB_OCPP.WSServer/Jobs/HeartBeatCheckJob.cs

@@ -40,7 +40,7 @@ public class HeartBeatCheckJob : IJob
         try
         {
             Stopwatch watch = new Stopwatch();
-            Dictionary<string, ClientData> _copyClientDic = protalServer.ClientDic;
+            Dictionary<string, ClientData> _copyClientDic = protalServer.GetClientDic();
 
             var cdt = DateTime.UtcNow;
             var clients = _copyClientDic.Where(x => x.Value.LastActiveTime > cdt.AddSeconds(-120)).Select(x => x.Value).ToList();

+ 2 - 10
EVCB_OCPP.WSServer/Jobs/ServerMessageJob.cs

@@ -4,17 +4,10 @@ using EVCB_OCPP.Packet.Features;
 using EVCB_OCPP.Packet.Messages;
 using EVCB_OCPP.WSServer.Message;
 using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.Logging;
 using Newtonsoft.Json;
 using OCPPServer.Protocol;
 using Quartz;
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace EVCB_OCPP.WSServer.Jobs;
 
@@ -23,7 +16,6 @@ public class ServerMessageJob : IJob
 {
     public ServerMessageJob(
         ProtalServer protalServer,
-        IConfiguration configuration,
         IDbContextFactory<MainDBContext> maindbContextFactory,
         ILogger<ServerMessageJob> logger)
     {
@@ -59,7 +51,7 @@ public class ServerMessageJob : IJob
         DateTime dt = new DateTime(1991, 1, 1);
         DateTime currentTime = dateTimeNow;
         List<ServerMessage> commandList;
-        var clientDic = protalServer.ClientDic;
+        var clientDic = protalServer.GetClientDic();
 
         using (var db = await maindbContextFactory.CreateDbContextAsync())
         {
@@ -71,7 +63,7 @@ public class ServerMessageJob : IJob
         {
             // Console.WriteLine(string.Format("Now:{0} commandList Count:{1} ", DateTime.UtcNow.ToString("yyyy/MM/dd HH:mm:ss"), commandList.Count));
         }
-        var resendList = protalServer.ResendMessage;
+        var resendList = protalServer.GetResendMessage();
         foreach (var resendItem in resendList)
         {
             ClientData session;

+ 17 - 110
EVCB_OCPP.WSServer/Jobs/ServerSetFeeJob.cs

@@ -1,5 +1,6 @@
 using Dapper;
 using EVCB_OCPP.Domain;
+using EVCB_OCPP.Domain.ConnectionFactory;
 using EVCB_OCPP.Packet.Features;
 using EVCB_OCPP.Packet.Messages.Core;
 using EVCB_OCPP.WSServer.Dto;
@@ -25,20 +26,26 @@ namespace EVCB_OCPP.WSServer.Jobs;
 public class ServerSetFeeJob : IJob
 {
     private readonly ProtalServer protalServer;
-    private readonly SqlConnectionFactory<WebDBConetext> webDbConnectionFactory;
+    private readonly ServerMessageService messageService;
+    private readonly ISqlConnectionFactory<WebDBConetext> webDbConnectionFactory;
+    private readonly WebDbService webDbService;
     private readonly IMainDbService mainDbService;
     private readonly ILogger<ServerSetFeeJob> logger;
     //private readonly string webConnectionString;
 
     public ServerSetFeeJob(
         ProtalServer protalServer,
+        ServerMessageService messageService,
         //IConfiguration configuration,
-        SqlConnectionFactory<WebDBConetext> sqlConnectionFactory,
+        ISqlConnectionFactory<WebDBConetext> sqlConnectionFactory,
+        WebDbService webDbService,
         IMainDbService mainDbService,
         ILogger<ServerSetFeeJob> logger)
     {
         this.protalServer = protalServer;
+        this.messageService = messageService;
         this.webDbConnectionFactory = sqlConnectionFactory;
+        this.webDbService = webDbService;
         this.mainDbService = mainDbService;
         this.logger = logger;
         //this.webConnectionString = configuration.GetConnectionString("WebDBContext");
@@ -48,7 +55,7 @@ public class ServerSetFeeJob : IJob
     {
         //logger.LogDebug("{0} Started", nameof(ServerSetFeeJob));
         //BasicMessageHandler msgAnalyser = new BasicMessageHandler();
-        Dictionary<string, ClientData> _copyClientDic = protalServer.ClientDic;
+        Dictionary<string, ClientData> _copyClientDic = protalServer.GetClientDic();
         //using var db = maindbContextFactory.CreateDbContextAsync();
         foreach (var item in _copyClientDic)
         {
@@ -60,7 +67,7 @@ public class ServerSetFeeJob : IJob
                     continue;
                 }
 
-                string displayPriceText = await SetDefaultFee(session);
+                string displayPriceText = await webDbService.SetDefaultFee(session);
                 if (string.IsNullOrEmpty(displayPriceText) || displayPriceText == session.DisplayPrice)
                 {
                     continue;
@@ -68,34 +75,16 @@ public class ServerSetFeeJob : IJob
 
                 protalServer.UpdateClientDisplayPrice(item.Key, displayPriceText);
 
-                await mainDbService.AddServerMessage(
-                        ChargeBoxId: session.ChargeBoxId,
-                        OutAction: Actions.ChangeConfiguration.ToString(),
-                        OutRequest: new ChangeConfigurationRequest()
-                        {
-                            key = "DefaultPrice",
-                            value = displayPriceText
-                        });
+                await messageService.SendChangeConfigurationRequest(
+                    session.ChargeBoxId, key: "DefaultPrice", value: displayPriceText);
 
                 if (session.CustomerId == new Guid("10C7F5BD-C89A-4E2A-8611-B617E0B41A73"))
                 {
-                    await mainDbService.AddServerMessage(
-                            ChargeBoxId: session.ChargeBoxId,
-                            OutAction: Actions.ChangeConfiguration.ToString(),
-                            OutRequest: new ChangeConfigurationRequest()
-                            {
-                                key = "ConnectionTimeOut",
-                                value = "120"
-                            });
+                    await messageService.SendChangeConfigurationRequest(
+                        session.ChargeBoxId, key: "ConnectionTimeOut", value: "120");
 
-                    await mainDbService.AddServerMessage(
-                            ChargeBoxId: session.ChargeBoxId,
-                            OutAction: Actions.ChangeConfiguration.ToString(),
-                            OutRequest:  new ChangeConfigurationRequest()
-                            {
-                                key = "MeterValueSampleInterval",
-                                value = "3"
-                            });
+                    await messageService.SendChangeConfigurationRequest(
+                        session.ChargeBoxId, key: "MeterValueSampleInterval", value: "3");
                 }
             }
             catch (Exception ex)
@@ -104,86 +93,4 @@ public class ServerSetFeeJob : IJob
             }
         }
     }
-
-    async private Task<string> SetDefaultFee(ClientData client)
-    {
-        string displayPriceText = string.Empty;
-        string charingPriceText = string.Empty;
-
-        if (string.IsNullOrEmpty(client.ChargeBoxId)) return displayPriceText;
-
-        try
-        {
-            using (SqlConnection conn = await webDbConnectionFactory.CreateAsync())
-            {
-                var parameters = new DynamicParameters();
-                parameters.Add("@MachineId", client.MachineId, DbType.String, ParameterDirection.Input, 36);
-                string displayPricestrSql = "";
-                string strSql = "";
-
-                if (client.IsAC)
-                {
-                    displayPricestrSql = """
-                    SELECT [AC_BillingMethod] as BillingMethod,[AC_FeeName] as FeeName,[AC_Fee] as ChargingFeebyHour ,[AC_ParkingFee] as ParkingFee, [Currency] 
-                    FROM[StationMachine] left join[dbo].[Station]
-                    on[StationMachine].StationId = Station.[Id] 
-                    where StationMachine.MachineId=@MachineId and Station.IsBilling=1;
-                    """;
-
-                    strSql = """
-                    SELECT CAST( [StartTime] as varchar(5)) StartTime,CAST( [EndTime] as varchar(5)) EndTime,[Fee] 
-                    FROM[StationMachine] left join [dbo].[StationFee]
-                    on[StationMachine].StationId = StationFee.StationId  
-                    where StationMachine.MachineId =@MachineId and StationFee.IsAC=1; 
-                    """;
-                }
-                else
-                {
-                    displayPricestrSql = """
-                    SELECT [DC_BillingMethod] as BillingMethod,[DC_FeeName] as FeeName,[DC_Fee] as ChargingFeebyHour ,[DC_ParkingFee] as ParkingFee, [Currency] 
-                    FROM[StationMachine] left join[dbo].[Station] 
-                    on[StationMachine].StationId = Station.[Id]
-                    where StationMachine.MachineId=@MachineId and Station.IsBilling=1; 
-                    """;
-
-                    strSql = """
-                    SELECT CAST( [StartTime] as varchar(5)) StartTime,CAST( [EndTime] as varchar(5)) EndTime,[Fee]
-                    FROM[StationMachine] left join [dbo].[StationFee]
-                    on[StationMachine].StationId = StationFee.StationId
-                    where StationMachine.MachineId =@MachineId and StationFee.IsAC=0;
-                    """;
-
-                }
-                var result = await conn.QueryAsync<StationFee>(displayPricestrSql, parameters);
-                if (result.Count() == 0)
-                {
-                    return string.Empty;
-                }
-                var stationPrice = result.First();
-
-                if (stationPrice.BillingMethod == 1)
-                {
-                    var chargingPriceResult = await conn.QueryAsync<ChargingPrice>(strSql, parameters);
-                    client.ChargingPrices = chargingPriceResult.ToList();
-                    if (string.IsNullOrEmpty(client.ChargingPrices[0].StartTime))
-                    {
-                        client.ChargingPrices = new List<ChargingPrice>();
-                    }
-                }
-
-                displayPriceText = stationPrice.FeeName;
-                client.BillingMethod = stationPrice.BillingMethod;
-                client.Currency = stationPrice.Currency;
-                client.ChargingFeebyHour = stationPrice.ChargingFeebyHour;
-                client.ParkingFee = stationPrice.ParkingFee;
-                client.IsBilling = true;
-            }
-        }
-        catch (Exception ex)
-        {
-            logger.LogError("SetDefaultFee", ex.ToString());
-        }
-
-        return displayPriceText;
-    }
 }

+ 1 - 1
EVCB_OCPP.WSServer/Jobs/ServerUpdateJob.cs

@@ -35,7 +35,7 @@ public class ServerUpdateJob : IJob
     {
         //logger.LogDebug("{0} Started", nameof(ServerUpdateJob));
         BasicMessageHandler msgAnalyser = new BasicMessageHandler();
-        Dictionary<string, ClientData> _copyClientDic = protalServer.ClientDic;
+        Dictionary<string, ClientData> _copyClientDic = protalServer.GetClientDic();
         var checkUpdateDt = DateTime.UtcNow;
         List<string> needUpdateChargers = new List<string>();
         using (var db = await maindbContextFactory.CreateDbContextAsync())

+ 4 - 2
EVCB_OCPP.WSServer/Jobs/SmartChargingJob.cs

@@ -12,6 +12,8 @@ using Microsoft.Extensions.Configuration;
 using Dapper;
 using Microsoft.Extensions.Logging;
 using EVCB_OCPP.WSServer.Helper;
+using EVCB_OCPP.Domain.ConnectionFactory;
+using System.Data;
 
 namespace EVCB_OCPP.WSServer.Jobs;
 
@@ -20,7 +22,7 @@ public class SmartChargingJob : IJob
 {
     public SmartChargingJob(
         ProtalServer protalServer,
-        SqlConnectionFactory<WebDBConetext> webDbConnectionFactory,
+        ISqlConnectionFactory<WebDBConetext> webDbConnectionFactory,
         //IConfiguration configuration,
         ILogger<SmartChargingJob> logger)
     {
@@ -32,7 +34,7 @@ public class SmartChargingJob : IJob
 
     //private readonly string webConnectionString;
     private readonly ProtalServer protalServer;
-    private readonly SqlConnectionFactory<WebDBConetext> webDbConnectionFactory;
+    private readonly ISqlConnectionFactory<WebDBConetext> webDbConnectionFactory;
     private readonly ILogger<SmartChargingJob> logger;
     private static List<StationInfoDto> _StationInfo = new List<StationInfoDto>();
 

+ 63 - 135
EVCB_OCPP.WSServer/Message/CoreProfileHandler.cs

@@ -9,7 +9,6 @@ using EVCB_OCPP.WSServer.Helper;
 using EVCB_OCPP.WSServer.Service;
 using Microsoft.Data.SqlClient;
 using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.Logging;
 using Newtonsoft.Json;
 using Newtonsoft.Json.Linq;
@@ -18,8 +17,8 @@ using System.Data;
 using System.Diagnostics;
 using System.Globalization;
 using SuperSocket.SocketBase;
-using Microsoft.AspNetCore.Http;
 using EVCB_OCPP.Domain.Models.MainDb;
+using EVCB_OCPP.Domain.ConnectionFactory;
 
 namespace EVCB_OCPP.WSServer.Message;
 
@@ -61,15 +60,14 @@ public class ID_ReaderStatus
 
 }
 
-internal partial class ProfileHandler
+public partial class ProfileHandler
 {
     private readonly ILogger logger;
-    private readonly BlockingTreePrintService blockingTreePrintService;
-    private readonly GoogleGetTimePrintService googleGetTimePrintService;
+    private readonly ServerMessageService messageService;
 
     //private readonly string webConnectionString;// = ConfigurationManager.ConnectionStrings[].ConnectionString;
     private readonly IDbContextFactory<MainDBContext> maindbContextFactory;
-    private readonly SqlConnectionFactory<WebDBConetext> webDbConnectionFactory;
+    private readonly ISqlConnectionFactory<WebDBConetext> webDbConnectionFactory;
     private readonly MeterValueDbService meterValueDbService;
 
     //private readonly IDbContextFactory<MeterValueDBContext> metervaluedbContextFactory;
@@ -78,23 +76,20 @@ internal partial class ProfileHandler
     private OuterHttpClient httpClient;
 
     public ProfileHandler(
-        IConfiguration configuration,
+        ServerMessageService messageService,
         IDbContextFactory<MainDBContext> maindbContextFactory,
-        SqlConnectionFactory<WebDBConetext> webDbConnectionFactory,
+        ISqlConnectionFactory<WebDBConetext> webDbConnectionFactory,
         //IDbContextFactory<MeterValueDBContext> metervaluedbContextFactory,
         MeterValueDbService meterValueDbService,
         IBusinessServiceFactory businessServiceFactory,
         IMainDbService mainDbService,
         ILogger<ProfileHandler> logger,
-        BlockingTreePrintService blockingTreePrintService,
-        GoogleGetTimePrintService googleGetTimePrintService,
         OuterHttpClient httpClient)
     {
-        //webConnectionString = configuration.GetConnectionString("WebDBContext");
-
         this.logger = logger;
-        this.blockingTreePrintService = blockingTreePrintService;
-        this.googleGetTimePrintService = googleGetTimePrintService;
+        this.messageService = messageService;
+        //this.blockingTreePrintService = blockingTreePrintService;
+        //this.googleGetTimePrintService = googleGetTimePrintService;
         this.maindbContextFactory = maindbContextFactory;
         this.webDbConnectionFactory = webDbConnectionFactory;
         this.meterValueDbService = meterValueDbService;
@@ -424,21 +419,6 @@ internal partial class ProfileHandler
                                         , locationId: sampleVaule.location.HasValue ? (int)sampleVaule.location : 0
                                         , unitId: sampleVaule.unit.HasValue ? (int)sampleVaule.unit : 0
                                         , transactionId: _request.transactionId.HasValue ? _request.transactionId.Value : -1));
-                                    //var task = meterValueDbService.InsertAsync(
-                                    //    chargeBoxId: session.ChargeBoxId
-                                    //    , connectorId: (byte)_request.connectorId
-                                    //    , value: value
-                                    //    , createdOn: item.timestamp
-                                    //    , contextId: sampleVaule.context.HasValue ? (int)sampleVaule.context : 0
-                                    //    , formatId: sampleVaule.format.HasValue ? (int)sampleVaule.format : 0
-                                    //    , measurandId: sampleVaule.measurand.HasValue ? (int)sampleVaule.measurand : 0
-                                    //    , phaseId: sampleVaule.phase.HasValue ? (int)sampleVaule.phase : 0
-                                    //    , locationId: sampleVaule.location.HasValue ? (int)sampleVaule.location : 0
-                                    //    , unitId: sampleVaule.unit.HasValue ? (int)sampleVaule.unit : 0
-                                    //    , transactionId: _request.transactionId.HasValue ? _request.transactionId.Value : -1);
-
-                                    //var task = Task.Delay(2_000); 
-                                    //insertTasks.Add(task);
                                 }
                             }
                             //insertTasksCnt = insertTasks.Count;
@@ -455,17 +435,12 @@ internal partial class ProfileHandler
                             {
                                 if (session.IsBilling)
                                 {
-                                    await mainDbService.AddServerMessage(
-                                            ChargeBoxId: session.ChargeBoxId,
-                                            OutAction: Actions.DataTransfer.ToString(),
-                                            OutRequest:
-                                                new DataTransferRequest()
-                                                {
-                                                    messageId = "ID_TxEnergy",
-                                                    vendorId = "Phihong Technology",
-                                                    data = JsonConvert.SerializeObject(new { txId = _request.transactionId, ConnectorId = _request.connectorId })
-                                                }
-                                            );
+                                    await messageService.SendDataTransferRequest(
+                                        session.ChargeBoxId,
+                                        messageId: "ID_TxEnergy",
+                                        vendorId: "Phihong Technology",
+                                        data: JsonConvert.SerializeObject(new { txId = _request.transactionId, ConnectorId = _request.connectorId })
+                                        );
                                 }
                             }
                             catch (Exception ex)
@@ -524,22 +499,10 @@ internal partial class ProfileHandler
                                 var price = authorization_result.ChargePointFee.Where(x => x.IsAC == session.IsAC).First();
                                 if (price != null)
                                 {
-
-                                    if (session.UserPrices.ContainsKey(_request.idTag))
-                                    {
-                                        session.UserPrices[_request.idTag] = price.PerkWhFee.HasValue ? JsonConvert.SerializeObject(new List<ChargingPrice>() { new ChargingPrice() { StartTime = "00:00", EndTime = "23:59", Fee = price.PerkWhFee.Value } }) : price.PerHourFee.Value.ToString();
-                                        session.UserPrices[_request.idTag] += "|+" + authorization_result.AccountBalance + "+" + "&" + price.ParkingFee + "&|" + price.Currency;
-
-                                    }
-                                    else
-                                    {
-                                        session.UserPrices.Add(_request.idTag, price.PerkWhFee.HasValue ? JsonConvert.SerializeObject(new List<ChargingPrice>() { new ChargingPrice() { StartTime = "00:00", EndTime = "23:59", Fee = price.PerkWhFee.Value } }) : price.PerHourFee.Value.ToString());
-                                        session.UserPrices[_request.idTag] += "|+" + authorization_result.AccountBalance + "+" + "&" + price.ParkingFee + "&|" + price.Currency;
-
-                                    }
+                                    session.UserPrices[_request.idTag] = price.PerkWhFee.HasValue ? JsonConvert.SerializeObject(new List<ChargingPrice>() { new ChargingPrice() { StartTime = "00:00", EndTime = "23:59", Fee = price.PerkWhFee.Value } }) : price.PerHourFee.Value.ToString();
+                                    session.UserPrices[_request.idTag] += "|+" + authorization_result.AccountBalance + "+" + "&" + price.ParkingFee + "&|" + price.Currency;
                                 }
                             }
-
                         }
 
                         //特例****飛宏客戶旗下的電樁,若遇到Portal沒回應的狀況 ~允許充電
@@ -765,16 +728,11 @@ internal partial class ProfileHandler
 
                                 if (session.IsBilling)
                                 {
-                                    await mainDbService.AddServerMessage(
-                                        ChargeBoxId: session.ChargeBoxId,
-                                        OutAction: Actions.DataTransfer.ToString(),
-                                        OutRequest:
-                                            new DataTransferRequest()
-                                            {
-                                                messageId = "ID_TxEnergy",
-                                                vendorId = "Phihong Technology",
-                                                data = JsonConvert.SerializeObject(new { txId = _request.transactionId, ConnectorId = transaction.ConnectorId })
-                                            }
+                                    await messageService.SendDataTransferRequest(
+                                        session.ChargeBoxId,
+                                        messageId: "ID_TxEnergy",
+                                        vendorId: "Phihong Technology",
+                                        data: JsonConvert.SerializeObject(new { txId = _request.transactionId, ConnectorId = transaction.ConnectorId })
                                         );
                                 }
 
@@ -861,7 +819,7 @@ internal partial class ProfileHandler
                         };
                         if (_request.idTag != "Backend")
                         {
-                            var authorization_result = await businessService.Authorize(session.ChargeBoxId, _request.idTag);
+                            IdTokenInfo authorization_result = await businessService.Authorize(session.ChargeBoxId, _request.idTag);
                             confirm.idTagInfo = authorization_result.IdTagInfo;
 
                             if (confirm.idTagInfo.status == AuthorizationStatus.Accepted && authorization_result.ChargePointFee != null)
@@ -869,28 +827,10 @@ internal partial class ProfileHandler
                                 var price = authorization_result.ChargePointFee.Where(x => x.IsAC == session.IsAC).First();
                                 if (price != null)
                                 {
+                                    session.UserPrices[_request.idTag] = price.PerkWhFee.HasValue ? JsonConvert.SerializeObject(new List<ChargingPrice>() { new ChargingPrice() { StartTime = "00:00", EndTime = "23:59", Fee = price.PerkWhFee.Value } }) : price.PerHourFee.Value.ToString();
+                                    session.UserPrices[_request.idTag] += "|+" + authorization_result.AccountBalance + "+" + "&" + price.ParkingFee + "&|" + price.Currency;
 
-                                    if (session.UserPrices.ContainsKey(_request.idTag))
-                                    {
-                                        session.UserPrices[_request.idTag] = price.PerkWhFee.HasValue ? JsonConvert.SerializeObject(new List<ChargingPrice>() { new ChargingPrice() { StartTime = "00:00", EndTime = "23:59", Fee = price.PerkWhFee.Value } }) : price.PerHourFee.Value.ToString();
-                                        session.UserPrices[_request.idTag] += "|+" + authorization_result.AccountBalance + "+" + "&" + price.ParkingFee + "&|" + price.Currency;
-
-                                    }
-                                    else
-                                    {
-                                        session.UserPrices.Add(_request.idTag, price.PerkWhFee.HasValue ? JsonConvert.SerializeObject(new List<ChargingPrice>() { new ChargingPrice() { StartTime = "00:00", EndTime = "23:59", Fee = price.PerkWhFee.Value } }) : price.PerHourFee.Value.ToString());
-                                        session.UserPrices[_request.idTag] += "|+" + authorization_result.AccountBalance + "+" + "&" + price.ParkingFee + "&|" + price.Currency;
-
-                                    }
-
-                                    if (session.UserDisplayPrices.ContainsKey(_request.idTag))
-                                    {
-                                        session.UserDisplayPrices[_request.idTag] = price.DisplayMessage;
-                                    }
-                                    else
-                                    {
-                                        session.UserDisplayPrices.Add(_request.idTag, price.DisplayMessage);
-                                    }
+                                    session.UserDisplayPrices[_request.idTag] = price.DisplayMessage;
                                 }
                             }
 
@@ -1212,32 +1152,26 @@ internal partial class ProfileHandler
 
                                         await db.SaveChangesAsync();
 
-                                        await mainDbService.AddServerMessage(
-                                            ChargeBoxId: session.ChargeBoxId,
-                                            OutAction: Actions.DataTransfer.ToString(),
-                                            OutRequest:
-                                                new DataTransferRequest()
+                                        await messageService.SendDataTransferRequest(
+                                            session.ChargeBoxId,
+                                            messageId: "FinalCost",
+                                            vendorId: "Phihong Technology",
+                                            data: JsonConvert.SerializeObject(new
+                                            {
+                                                txId = txEnergy.TxId,
+                                                description = JsonConvert.SerializeObject(new
                                                 {
-                                                    messageId = "FinalCost",
-                                                    vendorId = "Phihong Technology",
-                                                    data = JsonConvert.SerializeObject(new
-                                                    {
-                                                        txId = txEnergy.TxId,
-                                                        description = JsonConvert.SerializeObject(new
-                                                        {
-                                                            chargedEnergy = chargedEnergy,
-                                                            chargingFee = chargingCost,
-                                                            parkTime = (int)stoptime.Subtract(starttime).TotalSeconds,
-                                                            parkingFee = parkingCost,
-                                                            currency = currency,
-                                                            couponPoint = couponPoint,
-                                                            accountBalance = accountBalance - tx.Cost,
-                                                            farewellMessage = farewellMessage
-                                                        })
-                                                    })
-
-                                                }
-                                                );
+                                                    chargedEnergy = chargedEnergy,
+                                                    chargingFee = chargingCost,
+                                                    parkTime = (int)stoptime.Subtract(starttime).TotalSeconds,
+                                                    parkingFee = parkingCost,
+                                                    currency = currency,
+                                                    couponPoint = couponPoint,
+                                                    accountBalance = accountBalance - tx.Cost,
+                                                    farewellMessage = farewellMessage
+                                                })
+                                            })
+                                            );
 
                                         await meterValueDbService.InsertAsync(
                                             chargeBoxId: session.ChargeBoxId,
@@ -1280,30 +1214,24 @@ internal partial class ProfileHandler
                                     }
                                     else
                                     {
-                                        await mainDbService.AddServerMessage(
-                                            ChargeBoxId: session.ChargeBoxId,
-                                            OutAction: Actions.DataTransfer.ToString(),
-                                            OutRequest:
-                                             new DataTransferRequest()
-                                             {
-                                                 messageId = "RunningCost",
-                                                 vendorId = "Phihong Technology",
-                                                 data = JsonConvert.SerializeObject(new
-                                                 {
-                                                     txId = txEnergy.TxId,
-                                                     description = JsonConvert.SerializeObject(new
-                                                     {
-                                                         chargedEnergy = chargedEnergy,
-                                                         chargingFee = chargingCost,
-                                                         parkTime = (int)stoptime.Subtract(starttime).TotalSeconds,
-                                                         parkingFee = parkingCost,
-                                                         currency = currency
-                                                     })
-
-                                                 })
-
-                                             }
-                                        );
+                                        await messageService.SendDataTransferRequest(
+                                            session.ChargeBoxId,
+                                            messageId: "RunningCost",
+                                            vendorId: "Phihong Technology",
+                                            data: JsonConvert.SerializeObject(new
+                                            {
+                                                txId = txEnergy.TxId,
+                                                description = JsonConvert.SerializeObject(new
+                                                {
+                                                    chargedEnergy = chargedEnergy,
+                                                    chargingFee = chargingCost,
+                                                    parkTime = (int)stoptime.Subtract(starttime).TotalSeconds,
+                                                    parkingFee = parkingCost,
+                                                    currency = currency
+                                                })
+
+                                            })
+                                            );
 
                                         await meterValueDbService.InsertAsync(
                                             chargeBoxId: session.ChargeBoxId,

+ 1 - 1
EVCB_OCPP.WSServer/Message/FirmwareManagementProfileHandler.cs

@@ -13,7 +13,7 @@ using EVCB_OCPP.Domain.Models.MainDb;
 
 namespace EVCB_OCPP.WSServer.Message
 {
-    internal partial class ProfileHandler
+    public partial class ProfileHandler
     {
         internal async Task<MessageResult> ExecuteFirmwareManagementRequest(Actions action, ClientData session, IRequest request)
         {

+ 1 - 1
EVCB_OCPP.WSServer/Message/LocalAuthListManagementProfileHandler.cs

@@ -11,7 +11,7 @@ using System.Threading.Tasks;
 
 namespace EVCB_OCPP.WSServer.Message
 {
-    internal partial class ProfileHandler
+    public partial class ProfileHandler
     {
         internal async Task<MessageResult> ExecuteLocalAuthListManagementConfirm(Actions action, ClientData session, IConfirmation confirm, string requestId)
         {

+ 1 - 1
EVCB_OCPP.WSServer/Message/RemoteTriggerHandler.cs

@@ -11,7 +11,7 @@ using System.Threading.Tasks;
 
 namespace EVCB_OCPP.WSServer.Message
 {
-    internal partial class ProfileHandler
+    public partial class ProfileHandler
     {
 
 

+ 1 - 1
EVCB_OCPP.WSServer/Message/ReservationProfileHandler.cs

@@ -11,7 +11,7 @@ using System.Threading.Tasks;
 
 namespace EVCB_OCPP.WSServer.Message
 {
-    internal partial class ProfileHandler
+    public partial class ProfileHandler
     {
 
 

+ 1 - 1
EVCB_OCPP.WSServer/Message/SecurityProfileHandler.cs

@@ -6,7 +6,7 @@ using Microsoft.Extensions.Logging;
 
 namespace EVCB_OCPP.WSServer.Message
 {
-    internal partial class ProfileHandler
+    public partial class ProfileHandler
     {
         internal MessageResult ExecuteSecurityRequest(Actions action, ClientData session, IRequest request)
         {

+ 1 - 1
EVCB_OCPP.WSServer/Message/SmartChargingProfileHandler.cs

@@ -15,7 +15,7 @@ using System.Threading.Tasks;
 
 namespace EVCB_OCPP.WSServer.Message
 {
-    internal partial class ProfileHandler
+    public partial class ProfileHandler
     {
 
 

+ 5 - 26
EVCB_OCPP.WSServer/Program.cs

@@ -1,27 +1,13 @@
-using EVCB_OCPP.Domain;
-using EVCB_OCPP.WSServer.Message;
-using EVCB_OCPP.WSServer.Service;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.Configuration;
+using EVCB_OCPP.WSServer.Service;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
 using Newtonsoft.Json;
-using System;
-using NLog;
-using NLog.Web;
-using NLog.Extensions.Logging;
-using System.IO;
-using System.Data.Common;
-using Microsoft.Data.SqlClient;
 using EVCB_OCPP.WSServer.Helper;
-using Quartz;
-using EVCB_OCPP.WSServer.Jobs;
 using Microsoft.AspNetCore.Builder;
 
 namespace EVCB_OCPP.WSServer
 {
-   
+
     class Program
     {
         static void Main(string[] args)
@@ -50,23 +36,16 @@ namespace EVCB_OCPP.WSServer
             ThreadPool.SetMinThreads((int)(10), (int)(0));
 
             IHost host = Host.CreateDefaultBuilder(args)
-                //.UseEnvironment("Development")
-                //.ConfigureLogging((context, builder) => { 
-                //    builder.ClearProviders();
-                //    builder.AddAzureWebAppDiagnostics();
-                //    NLog.LogManager.Configuration = new NLogLoggingConfiguration(context.Configuration.GetSection("NLog"));
-                //})
-                //.UseNLog()
                 .AddLogServcie()
                 .ConfigureServices((hostContext, services) =>
                 {
                     //services.AddSingleton<MeterValueGroupSingleHandler>();
-                    services.AddSingleton<IHostLifetime, DummyHostLifeTime>();
+                    //services.AddSingleton<IHostLifetime, DummyHostLifeTime>();
 
                     services.AddProtalServer(hostContext.Configuration);
 
-                    services.AddTransient<BlockingTreePrintService>();
-                    services.AddTransient<GoogleGetTimePrintService>();
+                    //services.AddTransient<BlockingTreePrintService>();
+                    //services.AddTransient<GoogleGetTimePrintService>();
                 })
                 .Build();
 

+ 202 - 345
EVCB_OCPP.WSServer/ProtalServer.cs

@@ -1,42 +1,27 @@
-using Dapper;
-using EVCB_OCPP.Domain;
-using EVCB_OCPP.Packet.Features;
+using EVCB_OCPP.Packet.Features;
 using EVCB_OCPP.Packet.Messages;
 using EVCB_OCPP.Packet.Messages.Basic;
 using EVCB_OCPP.Packet.Messages.Core;
-using EVCB_OCPP.Packet.Messages.RemoteTrigger;
 using EVCB_OCPP.WSServer.Dto;
 using EVCB_OCPP.WSServer.Helper;
 using EVCB_OCPP.WSServer.Message;
 using EVCB_OCPP.WSServer.Service;
 using Microsoft.Extensions.Hosting;
 using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
 
 using OCPPServer.Protocol;
 using OCPPServer.SubProtocol;
 using SuperSocket.SocketBase;
 using SuperSocket.SocketBase.Config;
-using System;
-using System.Collections.Generic;
-using System.Configuration;
 using System.Data;
 using System.Diagnostics;
-using System.Linq;
 using System.Security.Authentication;
-using System.Threading;
-using System.Threading.Tasks;
 using System.Xml.Linq;
 using NLog;
 using Microsoft.Extensions.Configuration;
-using Microsoft.EntityFrameworkCore;
 using Microsoft.Extensions.DependencyInjection;
-using ProtoBuf.Serializers;
-using System.Net;
 using Microsoft.AspNetCore.Builder;
 using NLog.Extensions.Logging;
-using Microsoft.Data.SqlClient;
-using System.Collections.ObjectModel;
 using System.Collections.Concurrent;
 using EVCB_OCPP.WSServer.SuperSocket;
 using Microsoft.Extensions.Logging;
@@ -65,35 +50,27 @@ namespace EVCB_OCPP.WSServer
         public ProtalServer(
             ILogger<ProtalServer> logger
             , IConfiguration configuration
-            , IDbContextFactory<MainDBContext> maindbContextFactory
             , IMainDbService mainDbService
-            , IDbContextFactory<ConnectionLogDBContext> connectionLogdbContextFactory
-            , SqlConnectionFactory<WebDBConetext> webDbConnectionFactory
-            , SqlConnectionFactory<MainDBContext> mainDbConnectionFactory
-            , IHostEnvironment environment
             , IOCPPWSServerFactory ocppWSServerFactory
             , IConnectionLogdbService connectionLogdbService
+            , LoadingBalanceService loadingBalanceService
+            , ServerMessageService serverMessageService
             , WebDbService webDbService
-            , IServiceProvider serviceProvider,
+            , ProfileHandler profileHandler,
             OuterHttpClient httpClient)
         {
-            _ct = _cts.Token;
             this.logger = logger;
             this.configuration = configuration;
-            this.maindbContextFactory = maindbContextFactory;
             this.mainDbService = mainDbService;
-            this.webDbConnectionFactory = webDbConnectionFactory;
-            //this.connectionLogdbContextFactory = connectionLogdbContextFactory;
             this.ocppWSServerFactory = ocppWSServerFactory;
             this.connectionLogdbService = connectionLogdbService;
             this.webDbService = webDbService;
             this.httpClient = httpClient;
             isInDocker = !string.IsNullOrEmpty(configuration["DOTNET_RUNNING_IN_CONTAINER"]);
 
-            // = configuration.GetConnectionString("WebDBContext");
-            this.profileHandler = serviceProvider.GetService<ProfileHandler>();// new ProfileHandler(configuration, serviceProvider);
-            _loadingBalanceService = new LoadingBalanceService(mainDbConnectionFactory, webDbConnectionFactory);
-
+            this.profileHandler = profileHandler;// new ProfileHandler(configuration, serviceProvider);
+            this._loadingBalanceService = loadingBalanceService;// new LoadingBalanceService(mainDbConnectionFactory, webDbConnectionFactory);
+            this.messageService = serverMessageService;
             WarmUpLog();
         }
 
@@ -105,17 +82,12 @@ namespace EVCB_OCPP.WSServer
         private readonly Object _lockConfirmPacketList = new object();
         private readonly ILogger<ProtalServer> logger;
         private readonly IConfiguration configuration;
-        //private readonly IServiceProvider serviceProvider;
-        private readonly IDbContextFactory<MainDBContext> maindbContextFactory;
         private readonly IMainDbService mainDbService;
-        private readonly SqlConnectionFactory<WebDBConetext> webDbConnectionFactory;
 
-        //private readonly IDbContextFactory<ConnectionLogDBContext> connectionLogdbContextFactory;
         private readonly IOCPPWSServerFactory ocppWSServerFactory;
         private readonly IConnectionLogdbService connectionLogdbService;
         private readonly WebDbService webDbService;
-        private readonly ProfileHandler profileHandler;//= new ProfileHandler();
-        //private readonly string webConnectionString;// = ConfigurationManager.ConnectionStrings["WebDBContext"].ConnectionString;
+        private readonly ProfileHandler profileHandler;
         private readonly bool isInDocker;
         private List<NeedConfirmMessage> needConfirmPacketList = new List<NeedConfirmMessage>();
         private DateTime checkUpdateDt = DateTime.UtcNow;
@@ -123,6 +95,7 @@ namespace EVCB_OCPP.WSServer
         private DateTime _CheckLBDt = DateTime.UtcNow;
         private DateTime _CheckDenyListDt = DateTime.UtcNow.AddDays(-1);
         private readonly LoadingBalanceService _loadingBalanceService;// = new LoadingBalanceService();
+        private readonly ServerMessageService messageService;
         private List<StationInfoDto> _StationInfo = new List<StationInfoDto>();
 
         private readonly List<string> needConfirmActions = new List<string>()
@@ -158,33 +131,30 @@ namespace EVCB_OCPP.WSServer
              new LocalAuthListManagementProfile(),
              new SecurityProfile(),
         };
-        private CancellationTokenSource _cts = new CancellationTokenSource();
-        private CancellationToken _ct;
+
         #endregion
 
-        internal Dictionary<string, ClientData> ClientDic
+        private OCPPWSServer appServer;
+        private WebApplication appApi;
+        private WebApplication yarpApp;
+
+        internal Dictionary<string, ClientData> GetClientDic()
         {
-            get
-            {
-                Dictionary<string, ClientData> toReturn = null;
-                toReturn = new Dictionary<string, ClientData>(clientDic);
-                return toReturn;
-            }
+            Dictionary<string, ClientData> toReturn = null;
+            toReturn = new Dictionary<string, ClientData>(clientDic);
+            return toReturn;
         }
 
-        internal List<NeedConfirmMessage> ResendMessage
+        internal List<NeedConfirmMessage> GetResendMessage()
         {
-            get
+            List<NeedConfirmMessage> sendMessages = new List<NeedConfirmMessage>();
+            lock (_lockConfirmPacketList)
             {
-                List<NeedConfirmMessage> sendMessages = new List<NeedConfirmMessage>();
-                lock (_lockConfirmPacketList)
-                {
-                    sendMessages = needConfirmPacketList.Where(x => x.SentTimes > 1 && x.CreatedBy == "Server").ToList();
-
-                }
+                sendMessages = needConfirmPacketList.Where(x => x.SentTimes > 1 && x.CreatedBy == "Server").ToList();
 
-                return sendMessages;
             }
+
+            return sendMessages;
         }
 
         internal IReadOnlyList<Profile> Profiles => profiles.AsReadOnly();
@@ -200,7 +170,8 @@ namespace EVCB_OCPP.WSServer
 
         public Task StopAsync(CancellationToken cancellationToken)
         {
-            return Task.CompletedTask;
+            return Stop();
+            //return Task.CompletedTask;
         }
 
         internal void UpdateClientDisplayPrice(string key,string price)
@@ -215,19 +186,18 @@ namespace EVCB_OCPP.WSServer
 
         internal void Start()
         {
-            Console.WriteLine("Starting Server...");
+            logger.LogTrace("Starting Server...");
 
             if (!GlobalConfig.LoadAPPConfig(configuration))
             {
-                Console.WriteLine("Please check App.Config setting .");
+                logger.LogError("Please check App.Config setting .");
                 return;
             }
             
-            OpenNetwork();
+            StartWsService();
 
+            StartHttpConsoleService();
 
-            RunHttpConsoleService();
-            return;
             if (!isInDocker)
             {
                 Task consoleReadTask = new Task(RunConsoleInteractive);
@@ -235,6 +205,7 @@ namespace EVCB_OCPP.WSServer
                 //RunConsoleInteractive();
                 return;
             }
+            return;
         }
 
         private void RunConsoleInteractive()
@@ -365,11 +336,12 @@ namespace EVCB_OCPP.WSServer
             }
         }
 
-        private void RunHttpConsoleService()
+        private void StartHttpConsoleService()
         {
             var appBuilder = WebApplication.CreateBuilder();
-            appBuilder.Services.AddSingleton<IHostLifetime, DummyHostLifeTime>();
-            var app = appBuilder.Build();
+            //appBuilder.Services.AddSingleton<IHostLifetime, DummyHostLifeTime>();
+             
+            appApi = appBuilder.Build();
 
             var helpFunc = () => {
                 return string.Join("\r\n", new[] { 
@@ -381,20 +353,20 @@ namespace EVCB_OCPP.WSServer
                     "show : show log"
                 });
             };
-            app.MapGet("/", helpFunc);
-            app.MapGet("/help", helpFunc);
+            appApi.MapGet("/", helpFunc);
+            appApi.MapGet("/help", helpFunc);
 
-            app.MapPost("/stop", () => {
+            appApi.MapPost("/stop", () => {
                 Stop();
                 return "Command stop";
             });
 
-            app.MapPost("/gc", () => {
+            appApi.MapPost("/gc", () => {
                 GC.Collect();
                 return "Command GC";
             });
 
-            app.MapPost("/lc", () => {
+            appApi.MapPost("/lc", () => {
                 List<string> toReturn = new List<string>() { "Command List Clients" };
                 Dictionary<string, ClientData> _copyClientDic = null;
                 _copyClientDic = new Dictionary<string, ClientData>(clientDic);
@@ -408,7 +380,7 @@ namespace EVCB_OCPP.WSServer
                 return string.Join("\r\n", toReturn);
             });
 
-            app.MapPost("/lcn", () => {
+            appApi.MapPost("/lcn", () => {
                 List<string> toReturn = new List<string> { "Command List Customer Name" };
                 Dictionary<string, ClientData> _copyClientDic = null;
                 _copyClientDic = new Dictionary<string, ClientData>(clientDic);
@@ -422,7 +394,7 @@ namespace EVCB_OCPP.WSServer
                 return string.Join("\r\n", toReturn);
             });
 
-            app.MapPost("/silent", () => {
+            appApi.MapPost("/silent", () => {
                 foreach (var rule in LogManager.Configuration.LoggingRules)
                 {
                     if (rule.RuleName != "ConsoleLog")
@@ -440,7 +412,7 @@ namespace EVCB_OCPP.WSServer
                 return "Command silent";
             });
 
-            app.MapPost("/show", () => {
+            appApi.MapPost("/show", () => {
                 foreach (var rule in LogManager.Configuration.LoggingRules)
                 {
                     if (rule.RuleName != "ConsoleLog")
@@ -458,13 +430,13 @@ namespace EVCB_OCPP.WSServer
                 return "Command show";
             });
 
-            app.MapGet("/threads", () => {
+            appApi.MapGet("/threads", () => {
                 ThreadPool.GetMaxThreads(out var maxWorkerThread,out var maxCompletionPortThreads);
                 ThreadPool.GetAvailableThreads(out var avaliableWorkerThread, out var avaliableCompletionPortThreads);
                 return $"WorkerThread:{avaliableWorkerThread}/{maxWorkerThread} CompletionPortThreads{avaliableCompletionPortThreads}/{maxCompletionPortThreads}";
             });
 
-            app.MapPost("/threads", (int min, int max) => {
+            appApi.MapPost("/threads", (int min, int max) => {
                 ThreadPool.GetMaxThreads(out var maxWorkerThread, out var maxCompletionPortThreads);
                 ThreadPool.GetAvailableThreads(out var avaliableWorkerThread, out var avaliableCompletionPortThreads); 
                 ThreadPool.SetMinThreads(min, 0);
@@ -472,9 +444,9 @@ namespace EVCB_OCPP.WSServer
                 return $"WorkerThread:{avaliableWorkerThread}/{maxWorkerThread} CompletionPortThreads{avaliableCompletionPortThreads}/{maxCompletionPortThreads}";
             });
 
-            app.Urls.Add("http://*:54088");
+            appApi.Urls.Add("http://*:54088");
 
-            _ = app.RunAsync();
+            _ = appApi.RunAsync();
 
             var builder = WebApplication.CreateBuilder();
             //builder.Configuration.AddJsonFile("./EVCB_OCPP.WSServer/appsettings.json");
@@ -487,33 +459,27 @@ namespace EVCB_OCPP.WSServer
 
             builder.Services.AddReverseProxy()
                 .LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));
-            builder.Services.AddSingleton<IHostLifetime, DummyHostLifeTime>();
-            var yarpApp = builder.Build();
+            //builder.Services.AddSingleton<IHostLifetime, DummyHostLifeTime>();
+            yarpApp = builder.Build();
             yarpApp.Urls.Add("http://*:80");
             yarpApp.MapReverseProxy();
             _ = yarpApp.RunAsync();
         }
 
-        internal void Stop()
-        {
-            _cts?.Cancel();
-        }
-
-        private async void CheckEVSEConfigure(string chargeBoxId)
+        internal Task Stop()
         {
-            if (string.IsNullOrEmpty(chargeBoxId)) return;
-            await mainDbService.AddServerMessage(
-                ChargeBoxId: chargeBoxId,
-                OutAction: Actions.GetConfiguration.ToString(),
-                OutRequest: new GetConfigurationRequest() { key = new List<string>() }
-                );
+            appServer?.Stop();
+            return Task.WhenAll(new []{ 
+                appApi?.StopAsync(),
+                yarpApp?.StopAsync() 
+            });
         }
 
-        private void OpenNetwork()
+        private void StartWsService()
         {
 
             //載入OCPP Protocol
-            OCPPWSServer appServer = ocppWSServerFactory.Create(new List<OCPPSubProtocol>() { new OCPPSubProtocol(), new OCPPSubProtocol(" ocpp1.6"), new OCPPSubProtocol("ocpp2.0") });
+            appServer = ocppWSServerFactory.Create(new List<OCPPSubProtocol>() { new OCPPSubProtocol(), new OCPPSubProtocol(" ocpp1.6"), new OCPPSubProtocol("ocpp2.0") });
             //var appServer = new OCPPWSServer(new List<OCPPSubProtocol>() { new OCPPSubProtocol(), new OCPPSubProtocol(" ocpp1.6"), new OCPPSubProtocol("ocpp2.0") });
 
             List<IListenerConfig> llistener = new List<IListenerConfig>();
@@ -553,7 +519,8 @@ namespace EVCB_OCPP.WSServer
             //Setup with listening port
             if (!appServer.Setup(serverConfig, logFactory: new NLogLoggerFactory()))
             {
-                Console.WriteLine("Failed to setup!");
+                //Console.WriteLine("Failed to setup!");
+                logger.LogCritical("Failed to setup!");
                 return;
             }
 
@@ -564,7 +531,7 @@ namespace EVCB_OCPP.WSServer
             //Try to start the appServer
             if (!appServer.Start())
             {
-                Console.WriteLine("Failed to start!");
+                logger.LogCritical("Failed to start!");
                 //Console.ReadKey();
                 return;
             }
@@ -589,41 +556,16 @@ namespace EVCB_OCPP.WSServer
                     WriteMachineLog(session, string.Format("SecWebSocketProtocol:{0} NotSupported", session.SecWebSocketProtocol), "Connection", "");
                     return;
                 }
-                //ClientData _removeClient = null;
 
-                //var addedClient = clientDic.GetOrAdd(session.ChargeBoxId, session);
-                if (clientDic.ContainsKey(session.ChargeBoxId))
-                {
-                    var oldSession = clientDic[session.ChargeBoxId];
-                    WriteMachineLog(oldSession, "Duplicate Logins", "Connection", "");
-                    oldSession.Close(CloseReason.ServerShutdown);
-                    RemoveClient(oldSession);
-                }
+                TryRemoveDuplicatedSession(session);
                 clientDic[session.ChargeBoxId] = session;
 
-                //clientDic.TryGetValue(session.ChargeBoxId, out _removeClient);
-                //if (addedClient != session)
-                //{
-                //    WriteMachineLog(addedClient, "Duplicate Logins", "Connection", "");
-                //    addedClient.Close(CloseReason.ServerShutdown);
-                //    RemoveClient(addedClient);
-                //}
-
-                //clientDic.add.Add(session.ChargeBoxId, session);
                 session.m_ReceiveData += ReceivedMessageTimeLimited;
                 // logger.LogDebug("------------New " + (session == null ? "Oops" : session.ChargeBoxId));
                 WriteMachineLog(session, "NewSessionConnected", "Connection", "");
 
-                using (var db = await maindbContextFactory.CreateDbContextAsync())
-                {
-                    var machine = await db.Machines.Where(x => x.ChargeBoxId == session.ChargeBoxId).FirstOrDefaultAsync();
-                    if (machine != null)
-                    {
-                        machine.ConnectionType = session.Origin.Contains("https") ? 2 : 1;
-                        await db.SaveChangesAsync();
-                    }
+                await mainDbService.UpdateMachineConnectionType(session.ChargeBoxId, session.Origin.Contains("https") ? 2 : 1);
 
-                }
             }
             catch (Exception ex)
             {
@@ -633,6 +575,17 @@ namespace EVCB_OCPP.WSServer
 
         }
 
+        private void TryRemoveDuplicatedSession(ClientData session)
+        {
+            if (clientDic.ContainsKey(session.ChargeBoxId))
+            {
+                var oldSession = clientDic[session.ChargeBoxId];
+                WriteMachineLog(oldSession, "Duplicate Logins", "Connection", "");
+                oldSession.Close(CloseReason.ServerShutdown);
+                RemoveClient(oldSession);
+            }
+        }
+
         async private void ReceivedMessageTimeLimited(ClientData session, string rawdata)
         {
             CancellationTokenSource tokenSource = new();
@@ -901,197 +854,183 @@ namespace EVCB_OCPP.WSServer
             {
                 string response = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.GenericError, OCPPErrorDescription.NotChecked);
                 Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"));
+                return;
             }
-            else
-            {
-                var profileName = profiles.Where(x => x.IsExisted(analysisResult.Action)).Select(x => x.Name).FirstOrDefault();
-                switch (profileName)
-                {
-                    case "Core":
-                        {
-                            var replyResult = await profileHandler.ExecuteCoreRequest(action, session, (IRequest)analysisResult.Message).ConfigureAwait(false);
 
-                            var sendTimer = Stopwatch.StartNew();
-                            if (replyResult.Success)
-                            {
-                                string response = BasicMessageHandler.GenerateConfirmation(analysisResult.UUID, (IConfirmation)replyResult.Message);
+            var profileName = profiles.Where(x => x.IsExisted(analysisResult.Action)).Select(x => x.Name).FirstOrDefault();
+            switch (profileName)
+            {
+                case "Core":
+                    {
+                        var replyResult = await profileHandler.ExecuteCoreRequest(action, session, (IRequest)analysisResult.Message).ConfigureAwait(false);
 
+                        var sendTimer = Stopwatch.StartNew();
+                        if (replyResult.Success)
+                        {
+                            string response = BasicMessageHandler.GenerateConfirmation(analysisResult.UUID, (IConfirmation)replyResult.Message);
 
-                                Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Confirmation"), replyResult.Exception == null ? string.Empty : replyResult.Exception.ToString());
+                            Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Confirmation"), replyResult.Exception is null ? string.Empty : replyResult.Exception.ToString());
 
-                                if (action == Actions.BootNotification && replyResult.Message is BootNotificationConfirmation)
+                            if (action == Actions.BootNotification 
+                                && replyResult.Message is BootNotificationConfirmation bootNotificationConfirmation)
+                            {
+                                if (bootNotificationConfirmation.status == Packet.Messages.SubTypes.RegistrationStatus.Accepted)
                                 {
                                     session.IsCheckIn = true;
-                                    if (((BootNotificationConfirmation)replyResult.Message).status == Packet.Messages.SubTypes.RegistrationStatus.Accepted)
-                                    {
-                                        CheckEVSEConfigure(session.ChargeBoxId);
-                                        
-                                        await mainDbService.AddServerMessage(
-                                            ChargeBoxId: session.ChargeBoxId,
-                                            OutAction: Actions.ChangeConfiguration.ToString(),
-                                            OutRequest: new ChangeConfigurationRequest()
-                                            {
-                                                key = "TimeOffset",
-                                                value = "+08:00"
-                                            });
-                                    }
-                                    else
-                                    {
-                                        using (var db = await maindbContextFactory.CreateDbContextAsync())
-                                        {
-                                            var machine = await db.Machines.Where(x => x.ChargeBoxId == session.ChargeBoxId).FirstOrDefaultAsync();
-                                            if (machine != null)
-                                            {
-                                                if (machine.ConnectorType.Contains("6") || machine.ConnectorType.Contains("7") || machine.ConnectorType.Contains("8") || machine.ConnectorType.Contains("9"))
-                                                {
-                                                    session.IsAC = false;
-                                                }
-                                                machine.ConnectionType = session.Origin.Contains("https") ? 2 : 1;
-                                                await db.SaveChangesAsync();
-                                            }
-                                        }
 
-                                        await SetDefaultFee(session);
-                                    }
-                                }
+                                    await messageService.SendGetEVSEConfigureRequest(session.ChargeBoxId);
 
-                                if (action == Actions.Authorize && replyResult.Message is AuthorizeConfirmation)
+                                    await messageService.SendChangeConfigurationRequest(
+                                        session.ChargeBoxId, key: "TimeOffset", value: "+08:00");
+                                }
+                                else
                                 {
-                                    var authorizeRequest = (IRequest)analysisResult.Message as AuthorizeRequest;
-                                    if (session.UserDisplayPrices.ContainsKey(authorizeRequest.idTag))
+                                    bool? isAC = await mainDbService.GetChargeBoxIdIsAc(session.ChargeBoxId);
+                                    if (isAC is not null)
                                     {
-                                        await mainDbService.AddServerMessage(
-                                            ChargeBoxId: session.ChargeBoxId,
-                                            OutAction: Actions.DataTransfer.ToString(),
-                                            OutRequest: new DataTransferRequest() { 
-                                                messageId = "SetUserPrice", 
-                                                vendorId = "Phihong Technology",
-                                                data = JsonConvert.SerializeObject(
-                                                    new {
-                                                        idToken = authorizeRequest.idTag, 
-                                                        price = session.UserDisplayPrices[authorizeRequest.idTag] 
-                                                    }) }
-                                            );
+                                        session.IsAC = isAC.Value;
                                     }
-                                }
 
+                                    await mainDbService.UpdateMachineConnectionType(session.ChargeBoxId, session.Origin.Contains("https") ? 2 : 1);
+                                    await webDbService.SetDefaultFee(session);
+                                }
                             }
-                            else
+
+                            if (action == Actions.Authorize && replyResult.Message is AuthorizeConfirmation)
                             {
-                                if (action == Actions.StopTransaction && replyResult.CallErrorMsg == "Reject Response Message")
+                                var authorizeRequest = (IRequest)analysisResult.Message as AuthorizeRequest;
+                                if (session.UserDisplayPrices.ContainsKey(authorizeRequest.idTag))
                                 {
-                                    //do nothing 
+                                    await messageService.SendDataTransferRequest(
+                                        session.ChargeBoxId,
+                                        messageId: "SetUserPrice",
+                                        vendorId:"Phihong Technology",
+                                        data: JsonConvert.SerializeObject(
+                                            new
+                                            {
+                                                idToken = authorizeRequest.idTag,
+                                                price = session.UserDisplayPrices[authorizeRequest.idTag]
+                                            })
+                                        );
                                 }
-                                else
-                                {
-                                    string response = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
-                                    string errorMsg = replyResult.Exception != null ? replyResult.Exception.ToString() : string.Empty;
+                            }
 
-                                    Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
-                                }
+                        }
+                        else
+                        {
+                            if (action == Actions.StopTransaction && replyResult.CallErrorMsg == "Reject Response Message")
+                            {
+                                //do nothing 
                             }
-                            sendTimer.Stop();
-                            if(sendTimer.ElapsedMilliseconds/1000 > 1)
+                            else
                             {
-                                logger.LogCritical("ProcessRequestMessage Send Cost {time} sec", sendTimer.ElapsedMilliseconds / 1000);
+                                string response = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
+                                string errorMsg = replyResult.Exception != null ? replyResult.Exception.ToString() : string.Empty;
+
+                                Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
                             }
+                        }
+                        sendTimer.Stop();
+                        if(sendTimer.ElapsedMilliseconds/1000 > 1)
+                        {
+                            logger.LogCritical("ProcessRequestMessage Send Cost {time} sec", sendTimer.ElapsedMilliseconds / 1000);
+                        }
 
-                            if (action == Actions.StartTransaction)
+                        if (action == Actions.StartTransaction)
+                        {
+                            var stationId = await _loadingBalanceService.GetStationIdByMachineId(session.MachineId);
+                            var _powerDic = await _loadingBalanceService.GetSettingPower(stationId);
+                            if (_powerDic != null)
                             {
-                                var stationId = await _loadingBalanceService.GetStationIdByMachineId(session.MachineId);
-                                var _powerDic = await _loadingBalanceService.GetSettingPower(stationId);
-                                if (_powerDic != null)
+                                foreach (var kv in _powerDic)
                                 {
-                                    foreach (var kv in _powerDic)
+                                    try
                                     {
-                                        try
+                                        if (kv.Value.HasValue)
                                         {
-                                            if (kv.Value.HasValue)
-                                            {
-                                                profileHandler.SetChargingProfile(kv.Key, kv.Value.Value, Packet.Messages.SubTypes.ChargingRateUnitType.W);
-                                            }
+                                            profileHandler.SetChargingProfile(kv.Key, kv.Value.Value, Packet.Messages.SubTypes.ChargingRateUnitType.W);
                                         }
-                                        catch (Exception ex)
-                                        {
-                                            logger.LogError(string.Format("Set Profile Exception: {0}", ex.ToString()));
-                                        }
-
                                     }
+                                    catch (Exception ex)
+                                    {
+                                        logger.LogError(string.Format("Set Profile Exception: {0}", ex.ToString()));
+                                    }
+
                                 }
                             }
+                        }
 
-                            if (action == Actions.StopTransaction)
+                        if (action == Actions.StopTransaction)
+                        {
+                            var stationId = await _loadingBalanceService.GetStationIdByMachineId(session.MachineId);
+                            var _powerDic = await _loadingBalanceService.GetSettingPower(stationId);
+                            if (_powerDic != null)
                             {
-                                var stationId = await _loadingBalanceService.GetStationIdByMachineId(session.MachineId);
-                                var _powerDic = await _loadingBalanceService.GetSettingPower(stationId);
-                                if (_powerDic != null)
+                                foreach (var kv in _powerDic)
                                 {
-                                    foreach (var kv in _powerDic)
+                                    try
                                     {
-                                        try
+                                        if (kv.Value.HasValue)
                                         {
-                                            if (kv.Value.HasValue)
-                                            {
-                                                profileHandler.SetChargingProfile(kv.Key, kv.Value.Value, Packet.Messages.SubTypes.ChargingRateUnitType.W);
-                                            }
-                                        }
-                                        catch (Exception ex)
-                                        {
-                                            logger.LogError(string.Format("Set Profile Exception: {0}", ex.ToString()));
+                                            profileHandler.SetChargingProfile(kv.Key, kv.Value.Value, Packet.Messages.SubTypes.ChargingRateUnitType.W);
                                         }
                                     }
+                                    catch (Exception ex)
+                                    {
+                                        logger.LogError(string.Format("Set Profile Exception: {0}", ex.ToString()));
+                                    }
                                 }
                             }
-
                         }
-                        break;
-                    case "FirmwareManagement":
-                        {
-                            var replyResult = await profileHandler.ExecuteFirmwareManagementRequest(action, session, (IRequest)analysisResult.Message);
-                            if (replyResult.Success)
-                            {
-                                string response = BasicMessageHandler.GenerateConfirmation(analysisResult.UUID, (IConfirmation)replyResult.Message);
-                                Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Confirmation", replyResult.Exception == null ? string.Empty : replyResult.Exception.ToString()));
-
-                            }
-                            else
-                            {
-                                string response = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
-                                string errorMsg = replyResult.Exception != null ? replyResult.Exception.ToString() : string.Empty;
 
-                                Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
-                            }
+                    }
+                    break;
+                case "FirmwareManagement":
+                    {
+                        var replyResult = await profileHandler.ExecuteFirmwareManagementRequest(action, session, (IRequest)analysisResult.Message);
+                        if (replyResult.Success)
+                        {
+                            string response = BasicMessageHandler.GenerateConfirmation(analysisResult.UUID, (IConfirmation)replyResult.Message);
+                            Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Confirmation", replyResult.Exception == null ? string.Empty : replyResult.Exception.ToString()));
 
                         }
-                        break;
-                    case "Security":
+                        else
                         {
-                            var replyResult = profileHandler.ExecuteSecurityRequest(action, session, (IRequest)analysisResult.Message);
-                            if (replyResult.Success)
-                            {
-                                string response = BasicMessageHandler.GenerateConfirmation(analysisResult.UUID, (IConfirmation)replyResult.Message);
-                                Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Confirmation", replyResult.Exception == null ? string.Empty : replyResult.Exception.ToString()));
+                            string response = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
+                            string errorMsg = replyResult.Exception != null ? replyResult.Exception.ToString() : string.Empty;
 
-                            }
-                            else
-                            {
-                                string response = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
-                                string errorMsg = replyResult.Exception != null ? replyResult.Exception.ToString() : string.Empty;
-
-                                Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
-                            }
+                            Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
                         }
-                        break;
-                    default:
+
+                    }
+                    break;
+                case "Security":
+                    {
+                        var replyResult = profileHandler.ExecuteSecurityRequest(action, session, (IRequest)analysisResult.Message);
+                        if (replyResult.Success)
                         {
-                            string replyMsg = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
-                            string errorMsg = string.Format("Couldn't find action name: {0} of profile", action);
-                            Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
+                            string response = BasicMessageHandler.GenerateConfirmation(analysisResult.UUID, (IConfirmation)replyResult.Message);
+                            Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Confirmation", replyResult.Exception == null ? string.Empty : replyResult.Exception.ToString()));
+
                         }
-                        break;
+                        else
+                        {
+                            string response = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
+                            string errorMsg = replyResult.Exception != null ? replyResult.Exception.ToString() : string.Empty;
 
-                }
+                            Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
+                        }
+                    }
+                    break;
+                default:
+                    {
+                        string replyMsg = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
+                        string errorMsg = string.Format("Couldn't find action name: {0} of profile", action);
+                        Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
+                    }
+                    break;
             }
+            
             outter_stopwatch.Stop();
             if (outter_stopwatch.ElapsedMilliseconds > 1000)
             {
@@ -1242,78 +1181,6 @@ namespace EVCB_OCPP.WSServer
             {
                 logger.LogError(string.Format("Send Ex:{0}", ex.ToString()));
             }
-
-
-        }
-
-        async private Task<string> SetDefaultFee(ClientData client)
-        {
-            string displayPriceText = string.Empty;
-            string charingPriceText = string.Empty;
-
-            if (string.IsNullOrEmpty(client.ChargeBoxId)) return displayPriceText;
-
-            try
-            {
-
-                using (SqlConnection conn = await webDbConnectionFactory.CreateAsync())
-                {
-                    var parameters = new DynamicParameters();
-                    parameters.Add("@MachineId", client.MachineId, DbType.String, ParameterDirection.Input, 36);
-                    string displayPricestrSql = "";
-                    string strSql = "";
-
-                    if (client.IsAC)
-                    {
-                        displayPricestrSql = "   SELECT  [AC_BillingMethod] as BillingMethod,[AC_FeeName] as FeeName,[AC_Fee] as ChargingFeebyHour" +
-                    "  ,[AC_ParkingFee] as ParkingFee, [Currency]  FROM[StationMachine]  left join[dbo].[Station]" +
-                    "  on[StationMachine].StationId = Station.[Id]  where StationMachine.MachineId=@MachineId and Station.IsBilling=1; ";
-
-                        strSql = " SELECT CAST( [StartTime] as varchar(5)) StartTime,CAST( [EndTime] as varchar(5)) EndTime,[Fee]  FROM[StationMachine]  left join [dbo].[StationFee]" +
-                       " on[StationMachine].StationId = StationFee.StationId  where StationMachine.MachineId =@MachineId and StationFee.IsAC=1; ";
-                    }
-                    else
-                    {
-                        displayPricestrSql = "   SELECT  [DC_BillingMethod] as BillingMethod,[DC_FeeName] as FeeName,[DC_Fee] as ChargingFeebyHour" +
-                   "  ,[DC_ParkingFee] as ParkingFee, [Currency]  FROM[StationMachine]  left join[dbo].[Station]" +
-                   "  on[StationMachine].StationId = Station.[Id]  where StationMachine.MachineId=@MachineId and Station.IsBilling=1; ";
-
-                        strSql = " SELECT CAST( [StartTime] as varchar(5)) StartTime,CAST( [EndTime] as varchar(5)) EndTime,[Fee]  FROM[StationMachine]  left join [dbo].[StationFee]" +
-                       " on[StationMachine].StationId = StationFee.StationId  where StationMachine.MachineId =@MachineId and StationFee.IsAC=0; ";
-
-                    }
-                    //var result = await conn.QueryAsync<StationFee>(displayPricestrSql, parameters);
-                    var result = await conn.QueryFirstOrDefaultAsync<StationFee>(displayPricestrSql, parameters);
-                    if (result == default)
-                    {
-                        return string.Empty;
-                    }
-                    var stationPrice = result;//.First();
-
-                    if (stationPrice.BillingMethod == 1)
-                    {
-                        var chargingPriceResult = await conn.QueryAsync<ChargingPrice>(strSql, parameters);
-                        client.ChargingPrices = chargingPriceResult.ToList();
-                        if (string.IsNullOrEmpty(client.ChargingPrices[0].StartTime))
-                        {
-                            client.ChargingPrices = new List<ChargingPrice>();
-                        }
-                    }
-
-                    displayPriceText = stationPrice.FeeName;
-                    client.BillingMethod = stationPrice.BillingMethod;
-                    client.Currency = stationPrice.Currency;
-                    client.ChargingFeebyHour = stationPrice.ChargingFeebyHour;
-                    client.ParkingFee = stationPrice.ParkingFee;
-                    client.IsBilling = true;
-                }
-            }
-            catch (Exception ex)
-            {
-                logger.LogError("SetDefaultFee", ex.ToString());
-            }
-
-            return displayPriceText;
         }
 
         internal void AddConfirmMessage(string chargePointSerialNumber, int table_id, string requestId, string action, string msg_id, string createdBy, string sendMessage)
@@ -1370,19 +1237,9 @@ namespace EVCB_OCPP.WSServer
                     foundRequest.SentInterval = 0;
                     analysisResult.RequestId = foundRequest.RequestId;
 
-                    using (var db = await maindbContextFactory.CreateDbContextAsync())
-                    {
-                        var sc = await db.ServerMessages.Where(x => x.Id == foundRequest.Id).FirstOrDefaultAsync();
-                        sc.InMessage = JsonConvert.SerializeObject(analysisResult.Message, Formatting.None);
-                        sc.ReceivedOn = DateTime.UtcNow;
-                        await db.SaveChangesAsync();
-                        //  Console.WriteLine(string.Format("Now:{0} ServerMessage Id:{1} ", DateTime.UtcNow.ToString("yyyy/MM/dd HH:mm:ss"), foundRequest.Id));
-
-                    }
+                    await mainDbService.UpdateServerMessage(foundRequest.Id, inMessage: JsonConvert.SerializeObject(analysisResult.Message, Formatting.None), receivedOn: DateTime.UtcNow);
+                    
                     confirmed = true;
-
-
-
                 }
                 else if (analysisResult.Action == Actions.TriggerMessage.ToString())
                 {

+ 3 - 2
EVCB_OCPP.WSServer/Service/BlockingTreePrintService.cs

@@ -1,5 +1,6 @@
 using Dapper;
 using EVCB_OCPP.Domain;
+using EVCB_OCPP.Domain.ConnectionFactory;
 using EVCB_OCPP.WSServer.Helper;
 using Microsoft.Data.SqlClient;
 using Microsoft.Extensions.Logging;
@@ -15,7 +16,7 @@ namespace EVCB_OCPP.WSServer.Service
     public class BlockingTreePrintService
     {
         public BlockingTreePrintService(ILogger<BlockingTreePrintService> logger,
-            SqlConnectionFactory<MainDBContext> connectionFactory)
+            ISqlConnectionFactory<MainDBContext> connectionFactory)
         {
             this.logger = logger;
             this.connectionFactory = connectionFactory;
@@ -97,7 +98,7 @@ namespace EVCB_OCPP.WSServer.Service
             ORDER BY LEVEL ASC
             """;
         private readonly ILogger<BlockingTreePrintService> logger;
-        private readonly SqlConnectionFactory<MainDBContext> connectionFactory;
+        private readonly ISqlConnectionFactory<MainDBContext> connectionFactory;
     }
 
     public class TreeStruct

+ 4 - 3
EVCB_OCPP.WSServer/Service/ConnectionLogdbService.cs

@@ -1,5 +1,6 @@
 using Dapper;
 using EVCB_OCPP.Domain;
+using EVCB_OCPP.Domain.ConnectionFactory;
 using EVCB_OCPP.WSServer.Helper;
 using log4net;
 using Microsoft.Data.SqlClient;
@@ -31,7 +32,7 @@ public class ConnectionLogdbService : IConnectionLogdbService
 
     public ConnectionLogdbService(
         IDbContextFactory<ConnectionLogDBContext> connectionLogdbContextFactory,
-        SqlConnectionFactory<ConnectionLogDBContext> sqlConnectionFactory,
+        ISqlConnectionFactory<ConnectionLogDBContext> sqlConnectionFactory,
         ILogger<ConnectionLogdbService> logger,
         IConfiguration configuration)
     {
@@ -47,7 +48,7 @@ public class ConnectionLogdbService : IConnectionLogdbService
     }
 
     private readonly IDbContextFactory<ConnectionLogDBContext> connectionLogdbContextFactory;
-    private readonly SqlConnectionFactory<ConnectionLogDBContext> sqlConnectionFactory;
+    private readonly ISqlConnectionFactory<ConnectionLogDBContext> sqlConnectionFactory;
     private readonly ILogger<ConnectionLogdbService> logger;
     private readonly QueueHandler<MachineLog> queueHandler;
     //private readonly string connectionLogdbConnectionString;
@@ -303,7 +304,7 @@ public class ConnectionLogdbService : IConnectionLogdbService
         }
         t1 = watcher.ElapsedMilliseconds;
         using SqlConnection sqlConnection = await sqlConnectionFactory.CreateAsync();
-        using SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(sqlConnection);
+        using SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(sqlConnection as SqlConnection);
         t2 = watcher.ElapsedMilliseconds;
         sqlBulkCopy.BatchSize = parmsList.Count();
         sqlBulkCopy.DestinationTableName = GetTableName(workTime);

+ 6 - 3
EVCB_OCPP.WSServer/Service/LoadingBalanceService.cs

@@ -1,5 +1,6 @@
 using Dapper;
 using EVCB_OCPP.Domain;
+using EVCB_OCPP.Domain.ConnectionFactory;
 using EVCB_OCPP.WSServer.Helper;
 using Microsoft.Data.SqlClient;
 using Microsoft.Extensions.Configuration;
@@ -27,13 +28,15 @@ namespace EVCB_OCPP.WSServer.Service
     {
         //ConcurrentDictionary<int, object> _lockDic = new ConcurrentDictionary<int, object>();
         ConcurrentDictionary<int, SemaphoreSlim> _semaphoreDic = new ConcurrentDictionary<int, SemaphoreSlim>();
-        private readonly SqlConnectionFactory<MainDBContext> mainDbConnectionFactory;
-        private readonly SqlConnectionFactory<WebDBConetext> webDbConnectionFactory;
+        private readonly ISqlConnectionFactory<MainDBContext> mainDbConnectionFactory;
+        private readonly ISqlConnectionFactory<WebDBConetext> webDbConnectionFactory;
 
         //private readonly string mainConnectionString;
         //private readonly string webConnectionString;
 
-        public LoadingBalanceService(SqlConnectionFactory<MainDBContext> mainDbConnectionFactory, SqlConnectionFactory<WebDBConetext> webDbConnectionFactory)
+        public LoadingBalanceService(
+            ISqlConnectionFactory<MainDBContext> mainDbConnectionFactory,
+            ISqlConnectionFactory<WebDBConetext> webDbConnectionFactory)
         {
             this.mainDbConnectionFactory = mainDbConnectionFactory;
             this.webDbConnectionFactory = webDbConnectionFactory;

+ 48 - 5
EVCB_OCPP.WSServer/Service/MainDbService.cs

@@ -1,5 +1,6 @@
 using Dapper;
 using EVCB_OCPP.Domain;
+using EVCB_OCPP.Domain.ConnectionFactory;
 using EVCB_OCPP.Domain.Models.MainDb;
 using EVCB_OCPP.WSServer.Helper;
 using Microsoft.Data.SqlClient;
@@ -39,13 +40,16 @@ public interface IMainDbService
     Task UpdateTransaction(int transactionId, int meterStop, DateTime stopTime, int stopReasonId, string stopReason, string stopIdTag, string receipt, int cost);
     Task<bool> UpdateHeartBeats(IEnumerable<Machine> heartBeatsData);
     Task UpdateTransactionSOC(int id, string startsoc, string stopsoc);
+    Task UpdateMachineConnectionType(string chargeBoxId, int v);
+    Task<bool?> GetChargeBoxIdIsAc(string chargeBoxId);
+    Task UpdateServerMessage(int id, string inMessage, DateTime receivedOn);
 }
 
 public class MainDbService : IMainDbService
 {
     public MainDbService(
         IDbContextFactory<MainDBContext> contextFactory,
-        SqlConnectionFactory<MainDBContext> sqlConnectionFactory,
+        ISqlConnectionFactory<MainDBContext> sqlConnectionFactory,
         IMemoryCache memoryCache,
         IConfiguration configuration,
         ILoggerFactory loggerFactory,
@@ -72,7 +76,7 @@ public class MainDbService : IMainDbService
     private const string ChargeBoxConnectorIdMemCacheKeyFromat = "Connector_{0}{1}";
 
     private readonly IDbContextFactory<MainDBContext> contextFactory;
-    private readonly SqlConnectionFactory<MainDBContext> sqlConnectionFactory;
+    private readonly ISqlConnectionFactory<MainDBContext> sqlConnectionFactory;
     private readonly IMemoryCache memoryCache;
     private readonly ILoggerFactory loggerFactory;
     private readonly ILogger<MainDbService> logger;
@@ -210,7 +214,7 @@ public class MainDbService : IMainDbService
         return AddMachineErrorDapper(ConnectorId, CreatedOn, Status, ChargeBoxId, ErrorCodeId, ErrorInfo, PreStatus, VendorErrorCode, VendorId);
     }
 
-    public Task AddServerMessage(string ChargeBoxId, string OutAction, object OutRequest, string CreatedBy, DateTime? CreatedOn = null, string SerialNo = "", string InMessage = "")
+    public Task AddServerMessage(string ChargeBoxId, string OutAction, object OutRequest, string CreatedBy = "", DateTime? CreatedOn = null, string SerialNo = "", string InMessage = "")
     {
         if (string.IsNullOrEmpty(CreatedBy))
         {
@@ -222,8 +226,9 @@ public class MainDbService : IMainDbService
             SerialNo = Guid.NewGuid().ToString();
         }
         var _CreatedOn = CreatedOn ?? DateTime.UtcNow;
+        logger.LogTrace(JsonConvert.SerializeObject(_CreatedOn));
 
-        string _OutRequest = "";
+        string _OutRequest = string.Empty;
         if (OutRequest is not null)
         {
             _OutRequest = JsonConvert.SerializeObject(
@@ -369,6 +374,44 @@ public class MainDbService : IMainDbService
         //return UpdateHeartBeatsEF(heartBeatsData);
         return UpdateHeartBeatsDapper(heartBeatsData);
     }
+
+    public async Task UpdateMachineConnectionType(string chargeBoxId, int connectionType)
+    {
+        using (var db = await contextFactory.CreateDbContextAsync())
+        {
+            var machine = await db.Machines.Where(x => x.ChargeBoxId == chargeBoxId).FirstOrDefaultAsync();
+            if (machine != null)
+            {
+                machine.ConnectionType = connectionType;
+                await db.SaveChangesAsync();
+            }
+
+        }
+    }
+
+    public async Task<bool?> GetChargeBoxIdIsAc(string chargeBoxId)
+    {
+        using var db = await contextFactory.CreateDbContextAsync();
+        var machine = await db.Machines.Where(x => x.ChargeBoxId == chargeBoxId).FirstOrDefaultAsync();
+        if (machine is null)
+        {
+            return null;
+        }
+
+        return !machine.ConnectorType.Contains("6") && !machine.ConnectorType.Contains("7") && !machine.ConnectorType.Contains("8") && !machine.ConnectorType.Contains("9");
+    }
+
+    public async Task UpdateServerMessage(int id, string inMessage, DateTime receivedOn)
+    {
+        using (var db = await contextFactory.CreateDbContextAsync())
+        {
+            var sc = await db.ServerMessages.Where(x => x.Id == id).FirstOrDefaultAsync();
+            sc.InMessage = inMessage;
+            sc.ReceivedOn = receivedOn;
+            await db.SaveChangesAsync();
+        }
+    }
+
     private void InitUpdateConnectorStatusHandler()
     {
         if (statusNotificationHandler is not null)
@@ -819,7 +862,7 @@ public class MainDbService : IMainDbService
             table.Rows.Add(row);
         }
 
-        using SqlConnection sqlConnection = sqlConnectionFactory.Create();
+        using SqlConnection sqlConnection = sqlConnectionFactory.Create() as SqlConnection;
         using SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(sqlConnection);
 
         sqlBulkCopy.BatchSize = messages.Count();

+ 3 - 2
EVCB_OCPP.WSServer/Service/MeterValueDbService.cs

@@ -1,5 +1,6 @@
 using Dapper;
 using EVCB_OCPP.Domain;
+using EVCB_OCPP.Domain.ConnectionFactory;
 using EVCB_OCPP.WSServer.Dto;
 using EVCB_OCPP.WSServer.Helper;
 using Microsoft.Data.SqlClient;
@@ -16,7 +17,7 @@ namespace EVCB_OCPP.WSServer.Service;
 public class MeterValueDbService
 {
     private readonly IDbContextFactory<MeterValueDBContext> meterValueDbContextFactory;
-    private readonly SqlConnectionFactory<MeterValueDBContext> sqlConnectionFactory;
+    private readonly ISqlConnectionFactory<MeterValueDBContext> sqlConnectionFactory;
     private readonly ILoggerFactory loggerFactory;
     private readonly MeterValueGroupSingleHandler meterValueGroupSingleHandler;
     private readonly QueueSemaphore insertSemaphore;
@@ -26,7 +27,7 @@ public class MeterValueDbService
 
     public MeterValueDbService(
         IDbContextFactory<MeterValueDBContext> meterValueDbContextFactory,
-        SqlConnectionFactory<MeterValueDBContext> sqlConnectionFactory,
+        ISqlConnectionFactory<MeterValueDBContext> sqlConnectionFactory,
         ILogger<MeterValueDbService> logger,
         ILoggerFactory loggerFactory,
         IConfiguration configuration

+ 3 - 2
EVCB_OCPP.WSServer/Service/MeterValueInsertHandler.cs

@@ -1,5 +1,6 @@
 using Dapper;
 using EVCB_OCPP.Domain;
+using EVCB_OCPP.Domain.ConnectionFactory;
 using EVCB_OCPP.WSServer.Helper;
 using Microsoft.Data.SqlClient;
 using Microsoft.EntityFrameworkCore;
@@ -25,14 +26,14 @@ public class MeterValueInsertHandler : IHandler<InsertMeterValueParam>
     private static Queue<string> _existTables = new();
     private readonly IDbContextFactory<MeterValueDBContext> meterValueDbContextFactory;
     private readonly ILogger<MeterValueInsertHandler> logger;
-    private readonly SqlConnectionFactory<MeterValueDBContext> sqlConnectionFactory;
+    private readonly ISqlConnectionFactory<MeterValueDBContext> sqlConnectionFactory;
 
     //private readonly string meterValueConnectionString;
 
     public MeterValueInsertHandler(
         IDbContextFactory<MeterValueDBContext> meterValueDbContextFactory,
         ILogger<MeterValueInsertHandler> logger,
-        SqlConnectionFactory<MeterValueDBContext> sqlConnectionFactory
+        ISqlConnectionFactory<MeterValueDBContext> sqlConnectionFactory
         //IConfiguration configuration
         )
     {

+ 55 - 0
EVCB_OCPP.WSServer/Service/ServerMessageService.cs

@@ -0,0 +1,55 @@
+using EVCB_OCPP.Packet.Features;
+using EVCB_OCPP.Packet.Messages.Core;
+using Microsoft.Extensions.Logging;
+
+namespace EVCB_OCPP.WSServer.Service;
+
+public class ServerMessageService
+{
+    public ServerMessageService(
+        IMainDbService mainDbService
+        , ILogger<ServerMessageService> logger)
+    {
+        this.mainDbService = mainDbService;
+        this.logger = logger;
+    }
+
+    private readonly IMainDbService mainDbService;
+    private readonly ILogger<ServerMessageService> logger;
+
+    internal async Task SendGetEVSEConfigureRequest(string chargeBoxId)
+    {
+        if (string.IsNullOrEmpty(chargeBoxId)) return;
+        await mainDbService.AddServerMessage(
+            ChargeBoxId: chargeBoxId,
+            OutAction: Actions.GetConfiguration.ToString(),
+            OutRequest: new GetConfigurationRequest() { key = new List<string>() }
+            );
+    }
+
+    internal Task SendChangeConfigurationRequest(string chargeBoxId, string key, string value)
+    {
+        return mainDbService.AddServerMessage(
+            ChargeBoxId: chargeBoxId,
+            OutAction: Actions.ChangeConfiguration.ToString(),
+            OutRequest: new ChangeConfigurationRequest()
+            {
+                key = key,
+                value = value
+            });
+    }
+
+    internal Task SendDataTransferRequest(string chargeBoxId, string messageId, string vendorId, string data)
+    {
+        return mainDbService.AddServerMessage(
+            ChargeBoxId: chargeBoxId,
+            OutAction: Actions.DataTransfer.ToString(),
+            OutRequest: new DataTransferRequest()
+            {
+                messageId = messageId,
+                vendorId = vendorId,
+                data = data
+            }
+            );
+    }
+}

+ 108 - 4
EVCB_OCPP.WSServer/Service/WebDbService.cs

@@ -1,9 +1,16 @@
 using Dapper;
+using DnsClient.Internal;
+using EVCB_OCPP.Domain.ConnectionFactory;
+using EVCB_OCPP.WSServer.Dto;
 using EVCB_OCPP.WSServer.Helper;
+using log4net;
 using Microsoft.Data.SqlClient;
 using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging;
+using OCPPServer.Protocol;
 using System;
 using System.Collections.Generic;
+using System.Data;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
@@ -12,17 +19,21 @@ namespace EVCB_OCPP.WSServer.Service;
 
 public class WebDbService
 {
-    private readonly SqlConnectionFactory<WebDBConetext> webDbConnectionFactory;
+    private readonly ISqlConnectionFactory<WebDBConetext> webDbConnectionFactory;
+    private readonly ILogger<WebDbService> logger;
 
-    public WebDbService(SqlConnectionFactory<WebDBConetext> webDbConnectionFactory)
+    public WebDbService(
+        ISqlConnectionFactory<WebDBConetext> webDbConnectionFactory
+        , ILogger<WebDbService> logger)
     {
         this.webDbConnectionFactory = webDbConnectionFactory;
+        this.logger = logger;
         //this.webConnectionString = configuration.GetConnectionString("WebDBContext");
     }
 
     //private readonly string webConnectionString;
 
-    public async Task<List<string>> GetDenyModelNames()
+    public async Task<List<string>> GetDenyModelNames(CancellationToken token = default)
     {
         using SqlConnection conn = await webDbConnectionFactory.CreateAsync();
         string strSql = """
@@ -31,9 +42,102 @@ public class WebDbService
                 where SystemKey = 'DenyModelNames';
                 """;
 
-        var result = await conn.QueryFirstOrDefaultAsync<string>(strSql);
+        var result = await conn.QueryFirstOrDefaultAsync<string>(
+            new CommandDefinition(strSql, cancellationToken: token)
+            );
 
         return result.Split(',').ToList();
+    }
+
+    internal async Task<string> SetDefaultFee(ClientData client)
+    {
+        string displayPriceText = string.Empty;
+        string charingPriceText = string.Empty;
+
+        if (string.IsNullOrEmpty(client.ChargeBoxId)) return displayPriceText;
+
+        try
+        {
+            StationFee stationPrice = await GetStationFee(isAC: client.IsAC, client.MachineId);
+            if (stationPrice == default)
+            {
+                return string.Empty;
+            }
+
+            if (stationPrice.BillingMethod == 1)
+            {
+                client.ChargingPrices = await GetChargingPrice(client.IsAC, client.MachineId);
+                if (string.IsNullOrEmpty(client.ChargingPrices[0].StartTime))
+                {
+                    client.ChargingPrices = new List<ChargingPrice>();
+                }
+            }
+
+            displayPriceText = stationPrice.FeeName;
+            client.BillingMethod = stationPrice.BillingMethod;
+            client.Currency = stationPrice.Currency;
+            client.ChargingFeebyHour = stationPrice.ChargingFeebyHour;
+            client.ParkingFee = stationPrice.ParkingFee;
+            client.IsBilling = true;
+        }
+        catch (Exception ex)
+        {
+            logger.LogError("SetDefaultFee", ex.ToString());
+        }
+
+        return displayPriceText;
+    }
+
+    internal Task<StationFee> GetStationFee(bool isAC, string machineId)
+    {
+        return isAC ? GetAcStationFee(machineId) : GetDcStationFee(machineId);
+    }
 
+    internal async Task<List<ChargingPrice>> GetChargingPrice(bool isAC, string machineId)
+    {
+        var strSql = """
+            SELECT CAST( [StartTime] as varchar(5)) StartTime,CAST( [EndTime] as varchar(5)) EndTime,[Fee] 
+            FROM [StationMachine] 
+            left join [dbo].[StationFee] on [StationMachine].StationId = StationFee.StationId
+            WHERE StationMachine.MachineId =@MachineId and StationFee.IsAC=@IsAC; 
+            """;
+        var parameters = new DynamicParameters();
+        parameters.Add("@MachineId", machineId, DbType.String, ParameterDirection.Input, 36);
+        parameters.Add("@IsAC", isAC);
+
+        using SqlConnection conn = await webDbConnectionFactory.CreateAsync();
+        var chargingPriceResult = await conn.QueryAsync<ChargingPrice>(strSql, parameters);
+        return chargingPriceResult.ToList();
+    }
+
+    private async Task<StationFee> GetAcStationFee(string machineId)
+    {
+        var displayPricestrSql = """
+            SELECT [AC_BillingMethod] as BillingMethod,[AC_FeeName] as FeeName,[AC_Fee] as ChargingFeebyHour, [AC_ParkingFee] as ParkingFee, [Currency]
+            FROM [StationMachine]
+            left join[dbo].[Station] on [StationMachine].StationId = Station.[Id]
+            WHERE StationMachine.MachineId=@MachineId and Station.IsBilling=1;
+            """;
+        var parameters = new DynamicParameters();
+        parameters.Add("@MachineId", machineId, DbType.String, ParameterDirection.Input, 36);
+
+        using SqlConnection conn = await webDbConnectionFactory.CreateAsync();
+        var result = await conn.QueryFirstOrDefaultAsync<StationFee>(displayPricestrSql, parameters);
+        return result;
+    }
+
+    private async Task<StationFee> GetDcStationFee(string machineId)
+    {
+        using SqlConnection conn = await webDbConnectionFactory.CreateAsync();
+        var displayPricestrSql = """
+            SELECT [DC_BillingMethod] as BillingMethod,[DC_FeeName] as FeeName,[DC_Fee] as ChargingFeebyHour, [DC_ParkingFee] as ParkingFee, [Currency]
+            FROM [StationMachine]
+            left join[dbo].[Station] on [StationMachine].StationId = Station.[Id]
+            WHERE StationMachine.MachineId=@MachineId and Station.IsBilling=1;
+            """;
+        var parameters = new DynamicParameters();
+        parameters.Add("@MachineId", machineId, DbType.String, ParameterDirection.Input, 36);
+        var result = await conn.QueryFirstOrDefaultAsync<StationFee>(displayPricestrSql, parameters);
+        return result;
     }
 }

+ 5 - 1
EVCB_OCPP.WSServer/SuperSocket/OCPPWSServer.cs

@@ -96,7 +96,11 @@ public class OCPPWSServer : WebSocketServer<ClientData>
 
         foreach (var denyModel in GlobalConfig.DenyModelNames)
         {
-            if (string.IsNullOrEmpty(denyModel)) break;
+            if (string.IsNullOrEmpty(denyModel))
+            {
+                continue;
+            }
+
             if (session.ChargeBoxId.StartsWith(denyModel))
             {
 

+ 2 - 7
EVCB_OCPP.WSServer/SuperSocket/OCPPWSServerFactory.cs

@@ -1,11 +1,7 @@
-using EVCB_OCPP.WSServer.Service;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
 using OCPPServer.Protocol;
 using SuperWebSocket.SubProtocol;
-using System;
-using System.Collections.Generic;
 
 namespace EVCB_OCPP.WSServer.SuperSocket;
 
@@ -18,14 +14,13 @@ public class OCPPWSServerFactory : IOCPPWSServerFactory
 {
 
     public OCPPWSServerFactory(
-        IConfiguration configuration,
-        IMainDbService mainDbService,
         ILoggerFactory loggerFactory,
         IServiceProvider serviceProvider)
     {
         this.loggerFactory = loggerFactory;
         this.serviceProvider = serviceProvider;
     }
+
     public OCPPWSServer Create(IEnumerable<ISubProtocol<ClientData>> subProtocols)
     {
         var logger = loggerFactory.CreateLogger<OCPPWSServer>();

+ 1 - 1
TestTool.RemoteTriggerAPP/MainWindow.xaml.cs

@@ -878,7 +878,7 @@ namespace TestTool.RemoteTriggerAPP
         {
             using (var db = new MainDBContext())
             {
-                db.MachineOperateRecords.Add(new MachineOperateRecord()
+                db.MachineOperateRecord.Add(new MachineOperateRecord()
                 {
                     CreatedOn = DateTime.UtcNow.ToUniversalTime(),
                     ChargeBoxId = uxChargeBoxIdTb.Text,