Robert 1 年之前
父節點
當前提交
898e657cf9

+ 2 - 2
BufferedCurrentTime/CurrentTimeGetter.cs

@@ -10,7 +10,7 @@ public class CurrentTimeGetter
     /// </summary>        
     /// <value>Current time.</value>        
 
-    public static DateTime Now
+    public static DateTime UtcNow
     {
         get
         {
@@ -19,7 +19,7 @@ public class CurrentTimeGetter
             {
                 return lastDateTime;
             }
-            DateTime dt = DateTime.Now;
+            DateTime dt = DateTime.UtcNow;
             lastTicks = tickCount;
             lastDateTime = dt;
             return dt;

+ 0 - 2
Dockerfile

@@ -1,8 +1,6 @@
 #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
 
 FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
-RUN sed -i 's/TLSv1.2/TLSv1/g' /etc/ssl/openssl.cnf
-RUN sed -i 's/DEFAULT@SECLEVEL=2/DEFAULT@SECLEVEL=1/g' /etc/ssl/openssl.cnf
 EXPOSE 80
 EXPOSE 443
 EXPOSE 54088

+ 0 - 6
EVCB_OCPP.Server.sln

@@ -15,8 +15,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SuperSocket.SocketEngine",
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SuperSocket.Common", "SocketCommon\SuperSocket.Common.csproj", "{8241B98B-A7BF-4FBA-BD0B-B1536DDD1A72}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BufferedCurrentTime", "BufferedCurrentTime\BufferedCurrentTime.csproj", "{32A60C0D-54EF-4850-856B-B8872CD86C6E}"
-EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -47,10 +45,6 @@ Global
 		{8241B98B-A7BF-4FBA-BD0B-B1536DDD1A72}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{8241B98B-A7BF-4FBA-BD0B-B1536DDD1A72}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{8241B98B-A7BF-4FBA-BD0B-B1536DDD1A72}.Release|Any CPU.Build.0 = Release|Any CPU
-		{32A60C0D-54EF-4850-856B-B8872CD86C6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{32A60C0D-54EF-4850-856B-B8872CD86C6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{32A60C0D-54EF-4850-856B-B8872CD86C6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{32A60C0D-54EF-4850-856B-B8872CD86C6E}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 4 - 3
EVCB_OCPP.WSServer/Jobs/HeartBeatCheckJob.cs

@@ -43,9 +43,9 @@ public class HeartBeatCheckJob : IJob
 
             watch.Start();
 
-            foreach (var session in clients)
+            using (var db = maindbContextFactory.CreateDbContext())
             {
-                using (var db = maindbContextFactory.CreateDbContext())
+                foreach (var session in clients)
                 {
                     var machine = new Machine() { Id = session.MachineId };
                     if (machine != null)
@@ -57,7 +57,8 @@ public class HeartBeatCheckJob : IJob
                         machine.ConnectionType = session.UriScheme.Equals("wss") ? 2 : 1;
                         db.Entry(machine).Property(x => x.HeartbeatUpdatedOn).IsModified = true;
                         db.Entry(machine).Property(x => x.ConnectionType).IsModified = true;
-                        await db.SaveChangesAsync();
+                        db.SaveChanges();
+                        db.ChangeTracker.Clear();
                     }
                 }
             }

+ 83 - 83
EVCB_OCPP.WSServer/Jobs/ServerMessageJob.cs

@@ -53,123 +53,123 @@ public class ServerMessageJob : IJob
         protalServer.RemoveConfirmMessage();
 
         BasicMessageHandler msgAnalyser = new BasicMessageHandler();
-        using (var db = maindbContextFactory.CreateDbContext())
+        using var db = maindbContextFactory.CreateDbContext();
+        var dateTimeNoew = DateTime.UtcNow;
+        DateTime startDt = dateTimeNoew.AddSeconds(-30);
+        DateTime dt = new DateTime(1991, 1, 1);
+        DateTime currentTime = dateTimeNoew;
+        var commandList = await db.ServerMessage.Where(c => c.ReceivedOn == dt && c.UpdatedOn == dt && c.CreatedOn >= startDt && c.CreatedOn <= currentTime).AsNoTracking().ToListAsync();
+        var clientDic = protalServer.ClientDic;
+
+        //處理主機傳送的有指令
+        var cmdMachineList = commandList.Select(c => c.ChargeBoxId).Distinct().ToList();
+        if (commandList.Count > 0)
         {
-            var dateTimeNoew = DateTime.UtcNow;
-            DateTime startDt = dateTimeNoew.AddSeconds(-30);
-            DateTime dt = new DateTime(1991, 1, 1);
-            DateTime currentTime = dateTimeNoew;
-            var commandList = await db.ServerMessage.Where(c => c.ReceivedOn == dt && c.UpdatedOn == dt && c.CreatedOn >= startDt && c.CreatedOn <= currentTime).AsNoTracking().ToListAsync();
-            var clientDic = protalServer.ClientDic;
-
-            //處理主機傳送的有指令
-            var cmdMachineList = commandList.Select(c => c.ChargeBoxId).Distinct().ToList();
-            if (commandList.Count > 0)
-            {
-                // Console.WriteLine(string.Format("Now:{0} commandList Count:{1} ", DateTime.UtcNow.ToString("yyyy/MM/dd HH:mm:ss"), commandList.Count));
-            }
-            var resendList = protalServer.ResendMessage;
-            foreach (var resendItem in resendList)
+            // Console.WriteLine(string.Format("Now:{0} commandList Count:{1} ", DateTime.UtcNow.ToString("yyyy/MM/dd HH:mm:ss"), commandList.Count));
+        }
+        var resendList = protalServer.ResendMessage;
+        foreach (var resendItem in resendList)
+        {
+            ClientData session;
+            if (clientDic.TryGetValue(resendItem.ChargePointSerialNumber, out session))
             {
-                ClientData session;
-                if (clientDic.TryGetValue(resendItem.ChargePointSerialNumber, out session))
+                if (dateTimeNoew.Subtract(resendItem.SentOn).TotalSeconds > 1)
                 {
-                    if (dateTimeNoew.Subtract(resendItem.SentOn).TotalSeconds > 1)
-                    {
-                        resendItem.SentTimes--;
-                        resendItem.SentOn = dateTimeNoew;
-                        protalServer.SendMsg(session, resendItem.SentMessage, string.Format("{0} {1}", resendItem.SentAction, "Request"), "");
-                    }
-
+                    resendItem.SentTimes--;
+                    resendItem.SentOn = dateTimeNoew;
+                    protalServer.SendMsg(session, resendItem.SentMessage, string.Format("{0} {1}", resendItem.SentAction, "Request"), "");
                 }
 
             }
-            foreach (var charger_SN in cmdMachineList)
+
+        }
+        foreach (var charger_SN in cmdMachineList)
+        {
+            ClientData session;
+            string uuid = string.Empty;
+            if (clientDic.TryGetValue(charger_SN, out session))
             {
-                ClientData session;
-                string uuid = string.Empty;
-                if (clientDic.TryGetValue(charger_SN, out session))
+                //logger.LogDebug(string.Format("charger_SN:{0} startDt:{1} CreatedOn:{2}", charger_SN, startDt.ToString("yyyy/MM/dd HH:mm:ss"), DateTime.UtcNow.ToString("yyyy/MM/dd HH:mm:ss")));
+
+                if (session.IsCheckIn && !session.ISOCPP20)
                 {
-                    //logger.LogDebug(string.Format("charger_SN:{0} startDt:{1} CreatedOn:{2}", charger_SN, startDt.ToString("yyyy/MM/dd HH:mm:ss"), DateTime.UtcNow.ToString("yyyy/MM/dd HH:mm:ss")));
+                    string rawRequest = string.Empty;
 
-                    if (session.IsCheckIn && !session.ISOCPP20)
-                    {
-                        string rawRequest = string.Empty;
+                    var cmdList = commandList.Where(c => c.ChargeBoxId == charger_SN).ToList();
 
-                        var cmdList = commandList.Where(c => c.ChargeBoxId == charger_SN).ToList();
+                    var profiles = protalServer.Profiles;
 
-                        var profiles = protalServer.Profiles;
+                    foreach (var item in cmdList)
+                    {
+                        IRequest request = null;
+                        Actions action = Actions.None;
+                        Enum.TryParse(item.OutAction, out action);
+                        Type _RequestType = null;
 
-                        foreach (var item in cmdList)
+                        for (int i = 0; i < profiles.Count; i++)
                         {
-                            IRequest request = null;
-                            Actions action = Actions.None;
-                            Enum.TryParse(item.OutAction, out action);
-                            Type _RequestType = null;
+                            var feature = profiles[i].GetFeaturebyAction(item.OutAction);
 
-                            for (int i = 0; i < profiles.Count; i++)
+                            if (feature != null)
                             {
-                                var feature = profiles[i].GetFeaturebyAction(item.OutAction);
-
-                                if (feature != null)
-                                {
-                                    _RequestType = feature.GetRequestType();
-                                    break;
-                                }
+                                _RequestType = feature.GetRequestType();
+                                break;
                             }
+                        }
+
+                        if (_RequestType != null && item.CreatedBy != "Destroyer")
+                        {
+                            request = JsonConvert.DeserializeObject(item.OutRequest, _RequestType) as IRequest;
+                            uuid = session.queue.store(request);
+                            rawRequest = BasicMessageHandler.GenerateRequest(uuid, item.OutAction, request);
+                            protalServer.SendMsg(session, rawRequest, string.Format("{0} {1}", action, "Request"), "");
+                        }
+
+
+                        if (item.CreatedBy == "Destroyer")
+                        {
 
-                            if (_RequestType != null && item.CreatedBy != "Destroyer")
+                            if (_RequestType != null)
                             {
-                                request = JsonConvert.DeserializeObject(item.OutRequest, _RequestType) as IRequest;
+                                request = Activator.CreateInstance(_RequestType) as IRequest;
                                 uuid = session.queue.store(request);
-                                rawRequest = BasicMessageHandler.GenerateRequest(uuid, item.OutAction, request);
+                                rawRequest = BasicMessageHandler.GenerateDestroyRequest(uuid, item.OutAction, item.OutRequest);
                                 protalServer.SendMsg(session, rawRequest, string.Format("{0} {1}", action, "Request"), "");
-                            }
 
-
-                            if (item.CreatedBy == "Destroyer")
+                            }
+                            else
                             {
 
-                                if (_RequestType != null)
-                                {
-                                    request = Activator.CreateInstance(_RequestType) as IRequest;
-                                    uuid = session.queue.store(request);
-                                    rawRequest = BasicMessageHandler.GenerateDestroyRequest(uuid, item.OutAction, item.OutRequest);
-                                    protalServer.SendMsg(session, rawRequest, string.Format("{0} {1}", action, "Request"), "");
-
-                                }
-                                else
-                                {
-
-                                    rawRequest = BasicMessageHandler.GenerateDestroyRequest(Guid.NewGuid().ToString(), item.OutAction, item.OutRequest);
-                                    protalServer.SendMsg(session, rawRequest, string.Format("{0} {1}", action, "Request"), "");
+                                rawRequest = BasicMessageHandler.GenerateDestroyRequest(Guid.NewGuid().ToString(), item.OutAction, item.OutRequest);
+                                protalServer.SendMsg(session, rawRequest, string.Format("{0} {1}", action, "Request"), "");
 
-                                }
                             }
+                        }
 
-                            protalServer.AddConfirmMessage(charger_SN, item.Id, item.SerialNo, item.OutAction, uuid, item.CreatedBy, rawRequest);
-
-                            dateTimeNoew = DateTime.UtcNow;
-                            #region 更新資料表單一欄位
-                            var _UpdatedItem = new ServerMessage() { Id = item.Id, UpdatedOn = dateTimeNoew };
-                            //db.Configuration.AutoDetectChangesEnabled = false;//自動呼叫DetectChanges()比對所有的entry集合的每一個屬性Properties的新舊值
-                            //db.Configuration.ValidateOnSaveEnabled = false;// 因為Entity有些欄位必填,若不避開會有Validate錯誤
-                            // var _UpdatedItem = db.ServerMessage.Where(x => x.Id == item.Id).FirstOrDefault();
-                            db.ServerMessage.Attach(_UpdatedItem);
-                            _UpdatedItem.UpdatedOn = dateTimeNoew;
-                            db.Entry(_UpdatedItem).Property(x => x.UpdatedOn).IsModified = true;// 可以直接使用這方式強制某欄位要更新,只是查詢集合耗效能而己
+                        protalServer.AddConfirmMessage(charger_SN, item.Id, item.SerialNo, item.OutAction, uuid, item.CreatedBy, rawRequest);
 
-                            await db.SaveChangesAsync();
+                        dateTimeNoew = DateTime.UtcNow;
+                        #region 更新資料表單一欄位
+                        var _UpdatedItem = new ServerMessage() { Id = item.Id, UpdatedOn = dateTimeNoew };
+                        //db.Configuration.AutoDetectChangesEnabled = false;//自動呼叫DetectChanges()比對所有的entry集合的每一個屬性Properties的新舊值
+                        //db.Configuration.ValidateOnSaveEnabled = false;// 因為Entity有些欄位必填,若不避開會有Validate錯誤
+                        // var _UpdatedItem = db.ServerMessage.Where(x => x.Id == item.Id).FirstOrDefault();
+                        db.ServerMessage.Attach(_UpdatedItem);
+                        _UpdatedItem.UpdatedOn = dateTimeNoew;
+                        db.Entry(_UpdatedItem).Property(x => x.UpdatedOn).IsModified = true;// 可以直接使用這方式強制某欄位要更新,只是查詢集合耗效能而己
 
-                            #endregion
+                        await db.SaveChangesAsync();
+                        db.ChangeTracker.Clear();
 
-                            await Task.Delay(100);
+                        #endregion
 
-                        }
+                        await Task.Delay(100);
 
                     }
+
                 }
             }
         }
+
     }
 }

+ 3 - 6
EVCB_OCPP.WSServer/Jobs/ServerSetFeeJob.cs

@@ -45,6 +45,7 @@ public class ServerSetFeeJob : IJob
         //logger.LogDebug("{0} Started", nameof(ServerSetFeeJob));
         BasicMessageHandler msgAnalyser = new BasicMessageHandler();
         Dictionary<string, ClientData> _copyClientDic = protalServer.ClientDic;
+        using var db = maindbContextFactory.CreateDbContext();
         foreach (var item in _copyClientDic)
         {
             try
@@ -64,8 +65,6 @@ public class ServerSetFeeJob : IJob
                 protalServer.UpdateClientDisplayPrice(item.Key, displayPriceText);
 
                 var _CheckFeeDt = DateTime.UtcNow;
-                using (var db = maindbContextFactory.CreateDbContext())
-                {
                     db.ServerMessage.Add(new ServerMessage()
                     {
                         ChargeBoxId = session.ChargeBoxId,
@@ -122,10 +121,8 @@ public class ServerSetFeeJob : IJob
                         });
                     }
 
-                    await db.SaveChangesAsync();
-
-                }
-
+                    db.SaveChanges();
+                    db.ChangeTracker.Clear();
             }
             catch (Exception ex)
             {

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

@@ -204,7 +204,7 @@ public class ServerWeatherNotificationJob : IJob
 
                         });
 
-                        await db.SaveChangesAsync();
+                        db.SaveChanges();
                     }
                 }
                 catch (Exception ex)

+ 129 - 90
EVCB_OCPP.WSServer/Message/CoreProfileHandler.cs

@@ -28,6 +28,8 @@ using System.Globalization;
 using System.Linq;
 using System.Threading.Tasks;
 
+using Dapper;
+
 namespace EVCB_OCPP.WSServer.Message;
 
 public class ID_CreditDeductResult
@@ -75,6 +77,7 @@ internal partial class ProfileHandler
     private readonly IDbContextFactory<MainDBContext> maindbContextFactory;
     private readonly IDbContextFactory<MeterValueDBContext> metervaluedbContextFactory;
     private readonly IServiceProvider serviceProvider;
+    private readonly string mainDbConnectionString;
     private OuterHttpClient httpClient = new OuterHttpClient();
 
     public ProfileHandler(
@@ -89,16 +92,17 @@ internal partial class ProfileHandler
         this.maindbContextFactory = maindbContextFactory;
         this.serviceProvider = serviceProvider;
         this.metervaluedbContextFactory = metervaluedbContextFactory;
+        this.mainDbConnectionString = configuration.GetConnectionString("MainDBContext");
     }
 
     async internal Task<MessageResult> ExecuteCoreRequest(Actions action, ClientData session, IRequest request)
     {
         Stopwatch watch = new Stopwatch();
-        long getDateTimeTime, getServiceTime, getTagInfoTime, dbOpTime = 0;
-        if (action == Actions.Heartbeat || action == Actions.StopTransaction)
-        {
-            watch.Start();
-        }
+        //if (action == Actions.Heartbeat || action == Actions.StopTransaction)
+        //{
+        //    watch.Start();
+        //}
+        watch.Start();
         MessageResult result = new MessageResult() { Success = false };
 
         try
@@ -183,7 +187,7 @@ internal partial class ProfileHandler
                                     PublicKey = jo["publicKey"].Value<string>()
                                 });
 
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
 
@@ -200,7 +204,7 @@ internal partial class ProfileHandler
                         int heartbeat_interval = GlobalConfig.GetHEARTBEAT_INTERVAL();
                         using (var db = maindbContextFactory.CreateDbContext())
                         {
-                            var _machine = await db.Machine.Where(x => x.ChargeBoxId == session.ChargeBoxId).FirstOrDefaultAsync();
+                            var _machine = db.Machine.FirstOrDefault(x => x.ChargeBoxId == session.ChargeBoxId);
                             _machine.ChargeBoxSerialNumber = string.IsNullOrEmpty(_request.chargeBoxSerialNumber) ? string.Empty : _request.chargeBoxSerialNumber;
                             _machine.ChargePointSerialNumber = string.IsNullOrEmpty(_request.chargePointSerialNumber) ? string.Empty : _request.chargePointSerialNumber;
                             _machine.ChargePointModel = string.IsNullOrEmpty(_request.chargePointModel) ? string.Empty : _request.chargePointModel;
@@ -212,12 +216,9 @@ internal partial class ProfileHandler
                             _machine.MeterSerialNumber = string.IsNullOrEmpty(_request.meterSerialNumber) ? string.Empty : _request.meterSerialNumber;
                             _machine.MeterType = string.IsNullOrEmpty(_request.meterType) ? string.Empty : _request.meterType;
 
-                            await db.SaveChangesAsync();
-                        }
-
+                            db.SaveChanges();
+                            db.ChangeTracker.Clear();
 
-                        using (var db = maindbContextFactory.CreateDbContext())
-                        {
                             var configVaule = await db.MachineConfigurations
                                 .Where(x => x.ChargeBoxId == session.ChargeBoxId && x.ConfigureName == StandardConfiguration.HeartbeatInterval)
                                 .Select(x => x.ConfigureSetting)
@@ -237,16 +238,42 @@ internal partial class ProfileHandler
                     break;
                 case Actions.StatusNotification:
                     {
+                        var statusNotificationTimer = Stopwatch.StartNew();
+                        long s1 = 0, s2 = 0, s3 = 0, s4 = 0, s5 = 0;
                         //只保留最新上報狀況
                         StatusNotificationRequest _request = request as StatusNotificationRequest;
                         int preStatus = 0;
                         ConnectorStatus _oldStatus;
+
                         using (var db = maindbContextFactory.CreateDbContext())
                         {
-                            _oldStatus = await db.ConnectorStatus.Where(x => x.ChargeBoxId == session.ChargeBoxId
-                            && x.ConnectorId == _request.connectorId).AsNoTracking().FirstOrDefaultAsync();
+                            var con = db.Database.GetDbConnection();
+                            s1 = statusNotificationTimer.ElapsedMilliseconds;
+
+                            var sqlCommand = """
+                                select * from ConnectorStatus
+                                where ChargeBoxId = @ChargeBoxId and ConnectorId = @ConnectorId
+                                """;
+                            var param = new DynamicParameters();
+                            param.Add("@ChargeBoxId", session.ChargeBoxId, DbType.String, ParameterDirection.Input, 50);
+                            param.Add("@ConnectorId", _request.connectorId, DbType.Int16, ParameterDirection.Input);
+
+                            _oldStatus = con.QueryFirst<ConnectorStatus>(sqlCommand, param);
+
+                            s2 = statusNotificationTimer.ElapsedMilliseconds;
                         }
 
+                        //using (var db = maindbContextFactory.CreateDbContext())
+                        //{
+                        //    s1 = statusNotificationTimer.ElapsedMilliseconds;
+
+                        //    _oldStatus = db.ConnectorStatus.Where(x => x.ChargeBoxId == session.ChargeBoxId
+                        //    && x.ConnectorId == _request.connectorId).AsNoTracking().FirstOrDefault();
+
+                        //    s2 = statusNotificationTimer.ElapsedMilliseconds;
+                        //}
+
+                        s4 = statusNotificationTimer.ElapsedMilliseconds;
 
                         if (_oldStatus != null && (_request.status != (ChargePointStatus)_oldStatus.Status || _request.status == ChargePointStatus.Faulted))
                         {
@@ -273,7 +300,8 @@ internal partial class ProfileHandler
                                 db.Entry(_oldStatus).Property(x => x.VendorId).IsModified = true;
                                 db.Entry(_oldStatus).Property(x => x.VendorErrorCode).IsModified = true;
 
-                                await db.SaveChangesAsync();
+                                //db.SaveChanges();
+                                db.SaveChanges();
                             }
                         }
 
@@ -294,7 +322,9 @@ internal partial class ProfileHandler
                                     Id = Guid.NewGuid().ToString()
                                 };
                                 db.ConnectorStatus.Add(_currentStatus);
-                                await db.SaveChangesAsync();
+                                //db.SaveChanges();
+
+                                db.SaveChanges();
                             }
                         }
 
@@ -314,7 +344,9 @@ internal partial class ProfileHandler
                                     VendorErrorCode = string.IsNullOrEmpty(_request.vendorErrorCode) ? string.Empty : _request.vendorErrorCode,
                                     VendorId = string.IsNullOrEmpty(_request.vendorId) ? string.Empty : _request.vendorId
                                 });
-                                await db.SaveChangesAsync();
+                                //db.SaveChanges();
+
+                                db.SaveChanges();
                             }
                         }
 
@@ -333,10 +365,17 @@ internal partial class ProfileHandler
 
                             });
                         }
+                        s5 = statusNotificationTimer.ElapsedMilliseconds;
 
                         var confirm = new StatusNotificationConfirmation() { };
                         result.Message = confirm;
                         result.Success = true;
+
+                        statusNotificationTimer.Stop();
+                        if(statusNotificationTimer.ElapsedMilliseconds/1000 > 3)
+                        {
+                            logger.LogCritical(string.Format("StatusNotification took {0}/{1}/{2}/{3}/{4}", s1/1000, s2/1000, s3/1000, s4/1000, s5/1000));
+                        }
                     }
                     break;
                 case Actions.Heartbeat:
@@ -426,34 +465,31 @@ internal partial class ProfileHandler
                             try
                             {
                                 if (session.IsBilling)
-                                    if (session.IsBilling)
+                                {
+                                    using (var db = maindbContextFactory.CreateDbContext())
                                     {
-                                        using (var db = maindbContextFactory.CreateDbContext())
+                                        db.ServerMessage.Add(new ServerMessage()
                                         {
-                                            db.ServerMessage.Add(new ServerMessage()
-                                            {
-                                                ChargeBoxId = session.ChargeBoxId,
-                                                CreatedBy = "Server",
-                                                CreatedOn = DateTime.UtcNow,
-                                                OutAction = Actions.DataTransfer.ToString(),
-                                                OutRequest = JsonConvert.SerializeObject(
-                                                        new DataTransferRequest()
-                                                        {
-                                                            messageId = "ID_TxEnergy",
-                                                            vendorId = "Phihong Technology",
-                                                            data = JsonConvert.SerializeObject(new { txId = _request.transactionId, ConnectorId = _request.connectorId })
-                                                        },
-                                                        new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
-                                                SerialNo = Guid.NewGuid().ToString(),
-                                                InMessage = string.Empty
+                                            ChargeBoxId = session.ChargeBoxId,
+                                            CreatedBy = "Server",
+                                            CreatedOn = DateTime.UtcNow,
+                                            OutAction = Actions.DataTransfer.ToString(),
+                                            OutRequest = JsonConvert.SerializeObject(
+                                                    new DataTransferRequest()
+                                                    {
+                                                        messageId = "ID_TxEnergy",
+                                                        vendorId = "Phihong Technology",
+                                                        data = JsonConvert.SerializeObject(new { txId = _request.transactionId, ConnectorId = _request.connectorId })
+                                                    },
+                                                    new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
+                                            SerialNo = Guid.NewGuid().ToString(),
+                                            InMessage = string.Empty
 
-                                            });
+                                        });
 
-                                            await db.SaveChangesAsync();
-                                        }
+                                        db.SaveChanges();
                                     }
-
-
+                                }
                             }
                             catch (Exception ex)
                             {
@@ -563,7 +599,7 @@ internal partial class ProfileHandler
 
                                 db.TransactionRecord.Add(_newTransaction);
 
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
 
                                 _transactionId = _newTransaction.Id;
                                 logger.LogInformation("***************************************************** ");
@@ -591,18 +627,21 @@ internal partial class ProfileHandler
                     break;
                 case Actions.StopTransaction:
                     {
+                        long getDateTimeTime, getServiceTime, getTagInfoTime, dbOpTime = 0;
+                        var stopTrasactionTimer = Stopwatch.StartNew();
+
                         StopTransactionRequest _request = request as StopTransactionRequest;
 
                         int _ConnectorId = 0;
 
                         var utcNow = DateTime.UtcNow;
-                        getDateTimeTime = watch.ElapsedMilliseconds;
+                        getDateTimeTime = stopTrasactionTimer.ElapsedMilliseconds;
                         var businessService = await serviceProvider.GetService<BusinessServiceFactory>().CreateBusinessService(session.CustomerId.ToString());
-                        getServiceTime = watch.ElapsedMilliseconds;
+                        getServiceTime = stopTrasactionTimer.ElapsedMilliseconds;
 
                         var _idTagInfo = string.IsNullOrEmpty(_request.idTag) ? null : (_request.idTag == "Backend" ?
                             new IdTagInfo() { expiryDate = utcNow.AddDays(1), status = AuthorizationStatus.Accepted } : (await businessService.Authorize(session.ChargeBoxId, _request.idTag)).IdTagInfo);
-                        getTagInfoTime = watch.ElapsedMilliseconds;
+                        getTagInfoTime = stopTrasactionTimer.ElapsedMilliseconds;
 
                         //特例****飛宏客戶旗下的電樁,若遇到Portal沒回應的狀況 ~允許充電
                         if (session.CustomerId.ToString().ToUpper() == "8456AED9-6DD9-4BF3-A94C-9F5DCB9506F7" && _idTagInfo != null && _idTagInfo.status == AuthorizationStatus.ConcurrentTx)
@@ -610,11 +649,11 @@ internal partial class ProfileHandler
                             _idTagInfo = new IdTagInfo() { expiryDate = utcNow.AddDays(1), status = AuthorizationStatus.Accepted };
                         }
                         try
-                        {                              
+                        {
                             using (var db = maindbContextFactory.CreateDbContext())
                             {
-                                var transaction = await db.TransactionRecord.Where(x => x.Id == _request.transactionId
-                                 && x.ChargeBoxId == session.ChargeBoxId).FirstOrDefaultAsync();
+                                var transaction = db.TransactionRecord.Where(x => x.Id == _request.transactionId
+                                 && x.ChargeBoxId == session.ChargeBoxId).FirstOrDefault();
 
 
 
@@ -676,7 +715,8 @@ internal partial class ProfileHandler
                                     }
 
 
-                                    await db.SaveChangesAsync();
+                                    //db.SaveChanges();
+                                    db.SaveChanges();
 
 
                                     if (session.IsBilling)
@@ -700,7 +740,8 @@ internal partial class ProfileHandler
 
                                         });
 
-                                        await db.SaveChangesAsync();
+                                        //db.SaveChanges();
+                                        db.SaveChanges();
                                     }
 
                                     result.Message = confirm;
@@ -716,37 +757,37 @@ internal partial class ProfileHandler
                             dbOpTime = watch.ElapsedMilliseconds;
                             #region Save MeterValue
 
-                            if (_request.transactionData != null && 
+                            if (_request.transactionData != null &&
                                 _request.transactionData.Count > 0)
                             {
                                 using (var _meterDb = await metervaluedbContextFactory.CreateDbContextAsync())
                                 {
                                     foreach (var item in _request.transactionData)
-                                    foreach (var sampleVaule in item.sampledValue)
-                                    {
-                                        decimal value = Convert.ToDecimal(sampleVaule.value);
+                                        foreach (var sampleVaule in item.sampledValue)
+                                        {
+                                            decimal value = Convert.ToDecimal(sampleVaule.value);
 
 
-                                        string sp = "[dbo].[uspInsertMeterValueRecord] @ChargeBoxId," +
-                        "@ConnectorId,@Value,@CreatedOn,@ContextId,@FormatId,@MeasurandId,@PhaseId,@LocationId,@UnitId,@TransactionId";
+                                            string sp = "[dbo].[uspInsertMeterValueRecord] @ChargeBoxId," +
+                            "@ConnectorId,@Value,@CreatedOn,@ContextId,@FormatId,@MeasurandId,@PhaseId,@LocationId,@UnitId,@TransactionId";
 
                                             List<SqlParameter> parameter = new List<SqlParameter>();
                                             parameter.AddInsertMeterValueRecordSqlParameters(
                                                 chargeBoxId: session.ChargeBoxId
-                                                ,connectorId: (byte)_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
+                                                , connectorId: (byte)_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
                                                 );
 
-                                        _meterDb.Database.ExecuteSqlRaw(sp, parameter.ToArray());
-                                    }
+                                            _meterDb.Database.ExecuteSqlRaw(sp, parameter.ToArray());
+                                        }
 
                                 }
 
@@ -763,12 +804,10 @@ internal partial class ProfileHandler
                             // return result;
                         }
 
-                        watch.Stop();
-                        if (watch.ElapsedMilliseconds > 1000)
-                        {
-                            logger.Log( LogLevel.Critical, "ExecuteCoreRequest {action} {sessisonId} too long {time} sec", action.ToString(), session.SessionID , watch.ElapsedMilliseconds / 1000);
-                            logger.Log(LogLevel.Critical, "{action} {sessisonId} time {getDateTime}/{serviceTime}/{tagInfoTime}/{dbOpTime}", action.ToString(), session.SessionID, getDateTimeTime/1000 , getServiceTime/1000, getTagInfoTime/1000, dbOpTime/1000);
-                        }
+                        stopTrasactionTimer.Stop();
+                        logger.Log(LogLevel.Critical, "ExecuteCoreRequest {action} {sessisonId} took {time} sec", action.ToString(), session.SessionID, stopTrasactionTimer.ElapsedMilliseconds / 1000);
+                        logger.Log(LogLevel.Critical, "{action} {sessisonId} time {getDateTime}/{serviceTime}/{tagInfoTime}/{dbOpTime}", action.ToString(), session.SessionID, getDateTimeTime / 1000, getServiceTime / 1000, getTagInfoTime / 1000, dbOpTime / 1000);
+
                     }
                     break;
                 case Actions.Authorize:
@@ -842,14 +881,14 @@ internal partial class ProfileHandler
         }
 
 
-        if (action == Actions.Heartbeat)
-        {
+        //if (action == Actions.Heartbeat)
+        //{
             watch.Stop();
             if (watch.ElapsedMilliseconds / 1000 > 3)
             {
-                logger.LogError("Processing Hearbeat costs " + watch.ElapsedMilliseconds / 1000 + " seconds");
+            logger.LogError("Processing " + action.ToString() + " costs " + watch.ElapsedMilliseconds / 1000 + " seconds"); ;
             }
-        }
+        //}
         return result;
     }
 
@@ -876,7 +915,7 @@ internal partial class ProfileHandler
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)_confirm.status;
                                 operation.EVSE_Value = string.IsNullOrEmpty(_confirm.data) ? "" : _confirm.data;
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                             if (_request.messageId == "ID_FirmwareVersion")
@@ -889,7 +928,7 @@ internal partial class ProfileHandler
                                     db.Machine.Attach(machine);
                                     machine.BoardVersions = _confirm.data;
                                     db.Entry(machine).Property(x => x.BoardVersions).IsModified = true;
-                                    await db.SaveChangesAsync();
+                                    db.SaveChanges();
                                 }
                             }
 
@@ -1166,7 +1205,7 @@ internal partial class ProfileHandler
 
                                         }); ;
 
-                                        await db.SaveChangesAsync();
+                                        db.SaveChanges();
 
                                         using (var meterdb = await metervaluedbContextFactory.CreateDbContextAsync())
                                         {
@@ -1251,7 +1290,7 @@ internal partial class ProfileHandler
 
                                         }); ;
 
-                                        await db.SaveChangesAsync();
+                                        db.SaveChanges();
 
                                         using (var meterdb = await metervaluedbContextFactory.CreateDbContextAsync())
                                         {
@@ -1329,7 +1368,7 @@ internal partial class ProfileHandler
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)_confirm.status;
                                 operation.EVSE_Value = _confirm.status.ToString();
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                         }
@@ -1351,7 +1390,7 @@ internal partial class ProfileHandler
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)_confirm.status;
                                 operation.EVSE_Value = _confirm.status.ToString();
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                         }
@@ -1372,7 +1411,7 @@ internal partial class ProfileHandler
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)_confirm.status;
                                 operation.EVSE_Value = _confirm.status.ToString();
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                         }
@@ -1393,7 +1432,7 @@ internal partial class ProfileHandler
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)_confirm.status;
                                 operation.EVSE_Value = _confirm.status.ToString();
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                         }
@@ -1414,7 +1453,7 @@ internal partial class ProfileHandler
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)_confirm.status;
                                 operation.EVSE_Value = _confirm.status.ToString();
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                         }
@@ -1460,7 +1499,7 @@ internal partial class ProfileHandler
                                     });
                                 }
                             }
-                            await db.SaveChangesAsync();
+                            db.SaveChanges();
                         }
 
                     }
@@ -1554,7 +1593,7 @@ internal partial class ProfileHandler
 
                                 }
 
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
 
                             }
                         }
@@ -1580,7 +1619,7 @@ internal partial class ProfileHandler
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)_confirm.status;
                                 operation.EVSE_Value = _confirm.status.ToString();
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                         }
@@ -1635,7 +1674,7 @@ internal partial class ProfileHandler
                             operation.Status = 1;//電樁有回覆
                             operation.EVSE_Status = (int)255;//錯誤
                             operation.EVSE_Value = errorMsg;
-                            await db.SaveChangesAsync();
+                            db.SaveChanges();
                         }
 
                     }

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

@@ -77,7 +77,7 @@ namespace EVCB_OCPP.WSServer.Message
 
                                         });
 
-                                        await db.SaveChangesAsync();
+                                        db.SaveChanges();
 
                                     }
 
@@ -109,7 +109,7 @@ namespace EVCB_OCPP.WSServer.Message
 
 
 
-                                    await db.SaveChangesAsync();
+                                    db.SaveChanges();
                                 }
                             }
 
@@ -174,7 +174,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)1;//OK
                                 operation.EVSE_Value = string.IsNullOrEmpty(evse_rep) ? operation.EVSE_Value : evse_rep;
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                         }
@@ -212,7 +212,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)255;//錯誤
                                 operation.EVSE_Value = errorMsg;
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                         }

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

@@ -32,7 +32,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = 1;//OK
                                 operation.EVSE_Value = _confirm.listVersion.ToString();
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                         }
@@ -52,7 +52,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)_confirm.status;//OK     
                                 operation.EVSE_Value = _confirm.status.ToString();
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                         }
@@ -87,7 +87,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)255;//錯誤
                                 operation.EVSE_Value = errorMsg;
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                         }

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

@@ -34,7 +34,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)_confirm.status;//OK
                                 operation.EVSE_Value = _confirm.status.ToString();
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                         }
@@ -68,7 +68,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)255;//錯誤
                                 operation.EVSE_Value = errorMsg;
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                         }

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

@@ -34,7 +34,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)_confirm.status;//OK
                                 operation.EVSE_Value = _confirm.status.ToString();
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                         }
@@ -54,7 +54,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)_confirm.status;//OK
                                 operation.EVSE_Value = _confirm.status.ToString();
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                         }
@@ -88,7 +88,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)255;//錯誤
                                 operation.EVSE_Value = errorMsg;
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                         }
@@ -106,7 +106,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)255;//錯誤
                                 operation.EVSE_Value = errorMsg;
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                         }

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

@@ -57,7 +57,7 @@ namespace EVCB_OCPP.WSServer.Message
                     InMessage = string.Empty
 
                 });
-                await db.SaveChangesAsync();
+                db.SaveChanges();
             }
         }
 
@@ -85,7 +85,7 @@ namespace EVCB_OCPP.WSServer.Message
 
                 });
 
-                await db.SaveChangesAsync();
+                db.SaveChanges();
             }
         }
 
@@ -110,7 +110,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)_confirm.status;//OK
                                 operation.EVSE_Value = _confirm.status.ToString();
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                         }
@@ -130,7 +130,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)_confirm.status;//OK
                                 operation.EVSE_Value = _confirm.status.ToString();
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                         }
@@ -151,7 +151,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)_confirm.status;//OK
                                 operation.EVSE_Value = JsonConvert.SerializeObject(_confirm.chargingSchedule, Formatting.None);
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                         }
@@ -188,7 +188,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)255;//錯誤
                                 operation.EVSE_Value = errorMsg;
-                                await db.SaveChangesAsync();
+                                db.SaveChanges();
                             }
 
                         }

+ 21 - 4
EVCB_OCPP.WSServer/Program.cs

@@ -12,6 +12,8 @@ using NLog;
 using NLog.Web;
 using NLog.Extensions.Logging;
 using System.IO;
+using System.Data.Common;
+using Microsoft.Data.SqlClient;
 
 namespace EVCB_OCPP.WSServer
 {
@@ -47,20 +49,35 @@ namespace EVCB_OCPP.WSServer
                 {
                     services.AddPooledDbContextFactory<MainDBContext>((options) => {
                         var cString = hostContext.Configuration.GetConnectionString("MainDBContext");
-                        options.UseSqlServer(cString, dbOptions => {
-                            dbOptions.CommandTimeout(180);
+                        //var connection = new SqlConnection(cString);
+                        //connection.Open();
+                        //var com = new SqlCommand("SET ARITHABORT ON", connection);
+                        //com.ExecuteNonQuery();
+                        //com.Dispose();
+                        //connection.Close();
+                        //options.UseSqlServer(connection, dbOptions =>
+                        //{
+                        //    dbOptions.CommandTimeout(180);
+                        //});
+                        //options.LogTo(Console.WriteLine).EnableDetailedErrors();
+                        options.UseSqlServer(cString, dbOptions =>
+                        {
+                            dbOptions.EnableRetryOnFailure(int.MaxValue);
+                            dbOptions.CommandTimeout(int.MaxValue);
                         });
                     });
                     services.AddPooledDbContextFactory<MeterValueDBContext>((options) => {
                         var cString = hostContext.Configuration.GetConnectionString("MeterValueDBContext");
                         options.UseSqlServer(cString, dbOptions => {
-                            dbOptions.CommandTimeout(180);
+                            dbOptions.EnableRetryOnFailure(int.MaxValue);
+                            dbOptions.CommandTimeout(int.MaxValue);
                         });
                     });
                     services.AddPooledDbContextFactory<ConnectionLogDBContext>((options) => {
                         var cString = hostContext.Configuration.GetConnectionString("ConnectionLogDBContext");
                         options.UseSqlServer(cString, dbOptions => {
-                            dbOptions.CommandTimeout(180);
+                            dbOptions.EnableRetryOnFailure(int.MaxValue);
+                            dbOptions.CommandTimeout(int.MaxValue);
                         });
                     });
 

+ 21 - 7
EVCB_OCPP.WSServer/ProtalServer.cs

@@ -471,7 +471,7 @@ namespace EVCB_OCPP.WSServer
 
                 }); ;
 
-                await db.SaveChangesAsync();
+                db.SaveChanges();
 
             }
         }
@@ -572,7 +572,7 @@ namespace EVCB_OCPP.WSServer
                     if (machine != null)
                     {
                         machine.ConnectionType = session.Origin.Contains("https") ? 2 : 1;
-                        await db.SaveChangesAsync();
+                        db.SaveChanges();
                     }
 
                 }
@@ -649,7 +649,15 @@ namespace EVCB_OCPP.WSServer
                                 if (!session.ISOCPP20)
                                 {
                                     Actions action = Convertor.GetAction(analysisResult.Action);
-                                    ProcessRequestMessage(analysisResult, session, action);
+                                    try
+                                    {
+                                        ProcessRequestMessage(analysisResult, session, action);
+                                    }
+                                    catch (Exception e)
+                                    {
+                                        logger.Error($"Processing {action} exception!");
+                                        throw;
+                                    }
                                 }
                                 else
                                 {
@@ -838,6 +846,7 @@ namespace EVCB_OCPP.WSServer
                         {
                             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);
@@ -875,7 +884,7 @@ namespace EVCB_OCPP.WSServer
                                                 });
 
 
-                                                await db.SaveChangesAsync();
+                                                db.SaveChanges();
                                             }
 
                                         }
@@ -892,7 +901,7 @@ namespace EVCB_OCPP.WSServer
                                                     session.IsAC = false;
                                                 }
                                                 machine.ConnectionType = session.Origin.Contains("https") ? 2 : 1;
-                                                await db.SaveChangesAsync();
+                                                db.SaveChanges();
                                             }
                                         }
 
@@ -932,7 +941,7 @@ namespace EVCB_OCPP.WSServer
 
                                             });
 
-                                            await db.SaveChangesAsync();
+                                            db.SaveChanges();
                                         }
                                     }
                                 }
@@ -952,6 +961,11 @@ namespace EVCB_OCPP.WSServer
                                     Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
                                 }
                             }
+                            sendTimer.Stop();
+                            if(sendTimer.ElapsedMilliseconds/1000 > 1)
+                            {
+                                logger.Fatal("ProcessRequestMessage Send Cost {time} sec", sendTimer.ElapsedMilliseconds / 1000);
+                            }
 
                             if (action == Actions.StartTransaction)
                             {
@@ -1325,7 +1339,7 @@ namespace EVCB_OCPP.WSServer
                         var sc = await db.ServerMessage.Where(x => x.Id == foundRequest.Id).FirstOrDefaultAsync();
                         sc.InMessage = JsonConvert.SerializeObject(analysisResult.Message, Formatting.None);
                         sc.ReceivedOn = DateTime.UtcNow;
-                        await db.SaveChangesAsync();
+                        db.SaveChanges();
                         //  Console.WriteLine(string.Format("Now:{0} ServerMessage Id:{1} ", DateTime.UtcNow.ToString("yyyy/MM/dd HH:mm:ss"), foundRequest.Id));
 
                     }

+ 1 - 1
EVCB_OCPP.WSServer/Service/BusinessServiceFactory.cs

@@ -36,7 +36,7 @@ namespace EVCB_OCPP.WSServer.Service
             bool isCallOut = false;
             using (var db = this.mainDBContextFactory.CreateDbContext())
             {
-                isCallOut = await db.Customer.Where(x => x.Id == new Guid(customerId)).Select(x => x.CallPartnerApiOnSchedule).SingleOrDefaultAsync();
+                isCallOut = await db.Customer.Where(x => x.Id == new Guid(customerId)).Select(x => x.CallPartnerApiOnSchedule).FirstOrDefaultAsync();
             }
 
             //return isCallOut ? new OuterBusinessService(customerId) : new LocalBusinessService(customerId);

+ 4 - 4
EVCB_OCPP.WSServer/Service/HttpClientService.cs

@@ -65,13 +65,13 @@ namespace EVCB_OCPP.WSServer.Service
                 c.Timeout = TimeSpan.FromSeconds(_timeout);
                 c.DefaultRequestHeaders.Add("Cache-Control", "no-cache");
             })
-            .AddTypedClient<HttpClient>().SetHandlerLifetime(TimeSpan.FromMinutes(_handlerLifetime)).ConfigurePrimaryHttpMessageHandler((h =>
+            .AddTypedClient<HttpClient>()
+            .SetHandlerLifetime(TimeSpan.FromDays(1))
+            .ConfigurePrimaryHttpMessageHandler((h =>
             {
                 return new HttpClientHandler
                 {
-
-                    MaxConnectionsPerServer = _maxConnectionsPerServer
-
+                    MaxConnectionsPerServer = _maxConnectionsPerServer,
                 };
             }));
 

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

@@ -109,7 +109,7 @@ namespace OCPPServer.Protocol
             bool authorizated = false;
             using (var db = serviceProvider.GetService<IDbContextFactory<MainDBContext>>().CreateDbContext())
             {
-                var machine = db.Machine.Where(x => x.ChargeBoxId == session.ChargeBoxId && x.IsDelete == false).Select(x => new { x.CustomerId, x.Id }).FirstOrDefault();
+                var machine = db.Machine.Where(x => x.ChargeBoxId == session.ChargeBoxId && x.IsDelete == false).Select(x => new { x.CustomerId, x.Id }).AsNoTracking().FirstOrDefault();
                 session.CustomerName = machine == null ? "Unknown" : db.Customer.Where(x => x.Id == machine.CustomerId).Select(x => x.Name).FirstOrDefault();
                 session.CustomerId = machine == null ? Guid.Empty : machine.CustomerId;
                 session.MachineId = machine == null ? String.Empty : machine.Id;

+ 4 - 4
EVCB_OCPP.WSServer/appsettings.json

@@ -88,9 +88,9 @@
     ]
   },
   "ConnectionStrings": {
-    "ConnectionLogDBContext": "data source=172.1.0.131;initial catalog=Docker_ConnectionLog;;persist security info=True;user id=sa;password=B58Py42j/4cj84;MultipleActiveResultSets=True;App=EntityFramework;TrustServerCertificate=True;",
-    "MainDBContext": "data source=172.1.0.131;initial catalog=Docker_Main;;persist security info=True;user id=sa;password=B58Py42j/4cj84;MultipleActiveResultSets=True;App=EntityFramework;TrustServerCertificate=True;",
-    "MeterValueDBContext": "data source=172.1.0.131;initial catalog=Docker_MeterValue;;persist security info=True;user id=sa;password=B58Py42j/4cj84;MultipleActiveResultSets=True;App=EntityFramework;TrustServerCertificate=True;",
-    "WebDBContext": "data source=172.1.0.131;initial catalog=Docker_Web;;persist security info=True;user id=sa;password=B58Py42j/4cj84;MultipleActiveResultSets=True;App=EntityFramework;TrustServerCertificate=True;"
+    "ConnectionLogDBContext": "data source=172.1.0.131;initial catalog=Docker_ConnectionLog;;persist security info=True;user id=sa;password=B58Py42j/4cj84;MultipleActiveResultSets=False;App=EntityFramework;TrustServerCertificate=True;",
+    "MainDBContext": "data source=172.1.0.131;initial catalog=Docker_Main;;persist security info=True;user id=sa;password=B58Py42j/4cj84;MultipleActiveResultSets=False;App=EntityFramework;TrustServerCertificate=True;",
+    "MeterValueDBContext": "data source=172.1.0.131;initial catalog=Docker_MeterValue;;persist security info=True;user id=sa;password=B58Py42j/4cj84;MultipleActiveResultSets=False;App=EntityFramework;TrustServerCertificate=True;",
+    "WebDBContext": "data source=172.1.0.131;initial catalog=Docker_Web;;persist security info=True;user id=sa;password=B58Py42j/4cj84;MultipleActiveResultSets=False;App=EntityFramework;TrustServerCertificate=True;"
   }
 }

+ 7 - 0
SocketEngine/SocketSession.cs

@@ -2,6 +2,7 @@
 using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
+using System.Diagnostics;
 using System.IO;
 using System.Net;
 using System.Net.Sockets;
@@ -277,6 +278,7 @@ namespace SuperSocket.SocketEngine
 
         private void Send(SendingQueue queue)
         {
+            var stopwatch = Stopwatch.StartNew();
             if (SyncSend)
             {
                 SendSync(queue);
@@ -285,6 +287,11 @@ namespace SuperSocket.SocketEngine
             {
                 SendAsync(queue);
             }
+            stopwatch.Stop();
+            if(stopwatch.ElapsedMilliseconds/1000 > 1)
+            {
+                Console.WriteLine($"SocketSession Send take {stopwatch.ElapsedMilliseconds / 1000} sec");
+            }
         }
 
         private void StartSend(SendingQueue queue, int sendingTrackID, bool initial)