Browse Source

optimize api/v1/cpo/station

Robert 1 year ago
parent
commit
55f48c54d9
32 changed files with 1501 additions and 575 deletions
  1. 15 3
      Dockerfile
  2. 40 60
      EVCB_OCPP.WEBAPI/Controllers/Version1/CPOController.cs
  3. 21 38
      EVCB_OCPP.WEBAPI/Controllers/Version2/V2_CPOController.cs
  4. 21 51
      EVCB_OCPP.WEBAPI/Controllers/Version2/ocpp16/OCPP16_CPOController.cs
  5. 7 25
      EVCB_OCPP.WEBAPI/Controllers/Version2/ocpp201/OCPP201_CPOController.cs
  6. BIN
      EVCB_OCPP.WEBAPI/Dll/EVCB_OCPP.Domain.dll
  7. 0 70
      EVCB_OCPP.WEBAPI/EVCB_OCPP - Backup.WEBAPI.csproj
  8. 11 11
      EVCB_OCPP.WEBAPI/EVCB_OCPP.WEBAPI.csproj
  9. 20 8
      EVCB_OCPP.WEBAPI/Handlers/CPOAuthentication.cs
  10. 4 2
      EVCB_OCPP.WEBAPI/Handlers/InernalAuthentication.cs
  11. 166 0
      EVCB_OCPP.WEBAPI/Helpers/AddPortalDbContext.cs
  12. 119 0
      EVCB_OCPP.WEBAPI/Helpers/GroupSingleHandler.cs
  13. 28 68
      EVCB_OCPP.WEBAPI/Middleware/APILogMiddleware.cs
  14. 28 17
      EVCB_OCPP.WEBAPI/Middleware/BodyRewindMiddleware.cs
  15. 40 0
      EVCB_OCPP.WEBAPI/Middleware/PerformaceMonitorMiddleware.cs
  16. 8 0
      EVCB_OCPP.WEBAPI/Models/Db/StationMachineDto.cs
  17. 2 0
      EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/ConnectorStatus.cs
  18. 13 0
      EVCB_OCPP.WEBAPI/Program.cs
  19. 281 0
      EVCB_OCPP.WEBAPI/Services/ApiLogDbService.cs
  20. 214 60
      EVCB_OCPP.WEBAPI/Services/ChargePointService.cs
  21. 234 27
      EVCB_OCPP.WEBAPI/Services/ChargingStationService.cs
  22. 17 5
      EVCB_OCPP.WEBAPI/Services/CustomerService.cs
  23. 55 46
      EVCB_OCPP.WEBAPI/Services/Integration/ChargePoint16Service.cs
  24. 27 27
      EVCB_OCPP.WEBAPI/Services/Integration/ChargePoint201Service.cs
  25. 23 14
      EVCB_OCPP.WEBAPI/Services/Integration/ChargingStationService.cs
  26. 22 17
      EVCB_OCPP.WEBAPI/Services/Integration/ServerTriggerService.cs
  27. 10 8
      EVCB_OCPP.WEBAPI/Services/ServerTriggerService.cs
  28. 16 11
      EVCB_OCPP.WEBAPI/Startup.cs
  29. 36 7
      EVCB_OCPP.WEBAPI/appsettings.json
  30. 5 0
      build.bat
  31. 6 0
      entrypoint.sh
  32. 12 0
      sshd_config

+ 15 - 3
EVCB_OCPP.WEBAPI/Dockerfile → Dockerfile

@@ -4,6 +4,16 @@
 #For more information, please see https://aka.ms/containercompat
 
 FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
+
+RUN apt-get update \
+    && apt-get install -y --no-install-recommends dialog \
+    && apt-get install -y --no-install-recommends openssh-server \
+	&& apt-get install -y tcpdump\
+	&& mkdir -p /run/sshd \
+    && echo "root:Docker!" | chpasswd 
+	
+COPY sshd_config /etc/ssh/sshd_config
+
 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
 WORKDIR /app
@@ -12,9 +22,9 @@ EXPOSE 443
 
 FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
 WORKDIR /src
-COPY ["EVCB_OCPP.WEBAPI.csproj", "EVCB_OCPP.WEBAPI/"]
+COPY ["EVCB_OCPP.WEBAPI/EVCB_OCPP.WEBAPI.csproj", "EVCB_OCPP.WEBAPI/"]
 RUN dotnet restore "EVCB_OCPP.WEBAPI/EVCB_OCPP.WEBAPI.csproj"
-COPY . "EVCB_OCPP.WEBAPI/"
+COPY . .
 WORKDIR "/src/EVCB_OCPP.WEBAPI"
 RUN dotnet build "EVCB_OCPP.WEBAPI.csproj" -c Release -o /app/build
 
@@ -24,4 +34,6 @@ RUN dotnet publish "EVCB_OCPP.WEBAPI.csproj" -c Release -o /app/publish /p:UseAp
 FROM base AS final
 WORKDIR /app
 COPY --from=publish /app/publish .
-ENTRYPOINT ["dotnet", "EVCB_OCPP.WEBAPI.dll"]
+COPY entrypoint.sh .
+RUN chmod +x /app/entrypoint.sh
+CMD ["/app/entrypoint.sh"]

+ 40 - 60
EVCB_OCPP.WEBAPI/Controllers/Version1/CPOController.cs

@@ -15,6 +15,7 @@ using Microsoft.AspNetCore.Http.Extensions;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
+using System.Diagnostics;
 
 namespace EVCB_OCPP.WEBAPI.Controllers.Version1
 {
@@ -34,22 +35,9 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
             this.logger = logger;
         }
 
-        private bool ContainsChargePoint(string chargeBoxId, out string customerId)
-        {
-            customerId = string.Empty;
-
-            if (!Request.Headers.ContainsKey(EVCBConfiguration.Header_PartnerId)) return false;
-
-            customerId = Request.Headers[EVCBConfiguration.Header_PartnerId].First();
-
-            ChargePointService _service = serviceProvider.GetRequiredService<ChargePointService>();//;new ChargePointService();
-            return _service.ContainsChargePoint(chargeBoxId, customerId);
-
-        }
-
         [Route("station")]
         [HttpGet]
-        public IActionResult Station()
+        public async Task<IActionResult> Station()
         {
             var result = new CPOOuterResponse();
             //HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
@@ -60,7 +48,9 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
                 {
                     var _customerId = Request.Headers[EVCBConfiguration.Header_PartnerId].First();
                     ChargingStationService _service = serviceProvider.GetRequiredService<ChargingStationService>();
-                    var _innerResponse = new { Stations = _service.GetStationsbyCustomerId(_customerId) };
+
+                    var _innerResponse = new { Stations = await _service.GetStationsbyCustomerIdAsync(_customerId) };
+
                     result.Data = JsonConvert.SerializeObject(_innerResponse, EVCBConfiguration.JSONSERIALIZER_FORMAT);
                     result.StatusCode = (int)CPO_StatusCode.Success;
                     result.StatusMessage = CPO_StatusMessage.Success;
@@ -78,6 +68,9 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
                 //return Request.CreateResponse(statusCode, result);
                 return StatusCode(statusCode, result);
             }
+            finally
+            {
+            }
         }
 
         [Route("information")]
@@ -193,11 +186,10 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
 
                     };
 
-                    string[] parts = Request.GetDisplayUrl().Split('/');
-                    string urlformat = "{0}//{1}";
+                    string urlformat = "{0}://{1}";
 
                     var _innerResult = await _client.Post(
-                        string.Format(urlformat, parts[0], parts[2])
+                        string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent())
                         , $"/api/v1/ocpp16/transaction?ChargeBoxId={request.ChargeBoxId}"
                         , new Dictionary<string, string>()
                         {
@@ -284,12 +276,10 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-                string[] parts = Request.GetDisplayUrl().Split('/');
-
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
 
                 var _innerResult = await _client.Put(
-                    string.Format(urlformat, parts[0], parts[2] ), 
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent() ), 
                     $"/api/v1/ocpp16/transaction?ChargeBoxId={ChargeBoxId}&TransactionId={SessionId}",
                     new Dictionary<string, string>()
                     {
@@ -375,8 +365,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-                string[] parts = Request.GetDisplayUrl().Split('/');
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
 
                 var _innerRequest = new ReserveRequest()
                 {
@@ -387,7 +376,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
                 };
 
                 var _innerResult = await _client.Post(
-                    string.Format(urlformat, parts[0], parts[2]),
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()),
                     $"/api/v1/ocpp16/reservation?ChargeBoxId={request.ChargeBoxId}",
                     new Dictionary<string, string>()
                         {
@@ -471,12 +460,10 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-                string[] parts = Request.GetDisplayUrl().Split('/');
-
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
 
                 var _innerResult = await _client.Delete(
-                    string.Format(urlformat, parts[0], parts[2]), 
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()), 
                     $"/api/v1/ocpp16/reservation?ChargeBoxId={ChargeBoxId}&ReservationId={ReservationId}",
                     new Dictionary<string, string>()
                     {
@@ -557,12 +544,10 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-                string[] parts = Request.GetDisplayUrl().Split('/');
-
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
 
                 var _innerResult = await _client.Get(
-                    string.Format(urlformat, parts[0], parts[2]),
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()),
                     $"/api/v1/ocpp16/compositeschedule?ChargeBoxId={ChargeBoxId}&ConnectorId={ConnectorId}&Duration={Duration}&ChargingRateUnit={ChargingRateUnit}",
                     new Dictionary<string, string>()
                     {
@@ -644,13 +629,10 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-
-                string[] parts = Request.GetDisplayUrl().Split('/');
-
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
 
                 var _innerResult = await _client.Post(
-                    string.Format(urlformat, parts[0], parts[2]), 
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()), 
                     $"/api/v1/ocpp16/chargingprofile?ChargeBoxId={ChargeBoxId}",
                     new Dictionary<string, string>()
                     {
@@ -746,13 +728,10 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-
-                string[] parts = Request.GetDisplayUrl().Split('/');
-
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
 
                 var _innerResult = await _client.Delete(
-                    string.Format(urlformat, parts[0], parts[2]),
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()),
                     string.Format("/api/v1/ocpp16/chargingprofile?ChargeBoxId={2}{3}", ChargeBoxId, ChargeProfileId == -1 ? "" : "&Id=" + ChargeProfileId),
                     new Dictionary<string, string>()
                     {
@@ -833,14 +812,10 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-
-
-                string[] parts = Request.GetDisplayUrl().Split('/');
-
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
 
                 var _innerResult = await _client.Post(
-                    string.Format(urlformat, parts[0], parts[2]), 
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()), 
                     $"/api/v1/ocpp16/locallist?ChargeBoxId={ChargeBoxId}",
                     new Dictionary<string, string>()
                         {
@@ -923,14 +898,10 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-
-
-                string[] parts = Request.GetDisplayUrl().ToString().Split('/');
-
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
 
                 var _innerResult = await _client.Get(
-                    string.Format(urlformat, parts[0], parts[2] ), 
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent() ), 
                     $"/api/v1/ocpp16/locallistversion?ChargeBoxId={ChargeBoxId}",
                     new Dictionary<string, string>()
                         {
@@ -1072,12 +1043,10 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
 
                 }
 
-
-                string[] parts = Request.GetDisplayUrl().Split('/');
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
 
                 var _innerResult = await _client.Get(
-                    string.Format(urlformat, parts[0], parts[2]),
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()),
                     string.Format("/api/v1/ocpp16/command?ChargeBoxId={0}{1}&SerialNo={2}", ChargeBoxId, orderNo.HasValue ? "&OrderNo=" + orderNo.Value : "", SerialNo),
                     new Dictionary<string, string>()
                     {
@@ -1319,7 +1288,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
         [Route("completedsession")]
         [Produces(typeof(CPOOuterResponse))]
         [HttpGet]
-        public IActionResult CompletedSession(string ChargeBoxId, string SessionId = "", string IdTag = "", string StartTime = "", string StopTime = "")
+        public IActionResult CompletedSession(string ChargeBoxId, int SessionId = -1, string IdTag = "", string StartTime = "", string StopTime = "")
         {
             var result = new CPOOuterResponse();
             //HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
@@ -1822,7 +1791,18 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
 
         }
 
+        private bool ContainsChargePoint(string chargeBoxId, out string customerId)
+        {
+            customerId = string.Empty;
+
+            if (!Request.Headers.ContainsKey(EVCBConfiguration.Header_PartnerId)) return false;
+
+            customerId = Request.Headers[EVCBConfiguration.Header_PartnerId].First();
 
+            ChargePointService _service = serviceProvider.GetRequiredService<ChargePointService>();//;new ChargePointService();
+            return _service.ContainsChargePoint(chargeBoxId, customerId);
+
+        }
 
 
     }

+ 21 - 38
EVCB_OCPP.WEBAPI/Controllers/Version2/V2_CPOController.cs

@@ -11,23 +11,21 @@ using Microsoft.AspNetCore.Mvc;
 using Newtonsoft.Json;
 using System;
 using System.Collections.Generic;
-using System.Configuration;
 using System.Data;
-using System.Data.SqlClient;
 using System.Linq;
 using System.Net;
-using System.Net.Http;
 using System.Threading.Tasks;
 using ChargingStationService = EVCB_OCPP.WEBAPI.Services.Integration.ChargingStationService;
 using CommandType = EVCB_OCPP.WEBAPI.Models.WebAPI.Dto.CommandType;
 using IChargePointService = EVCB_OCPP.WEBAPI.Services.Integration.IChargePointService;
 using Microsoft.Extensions.Configuration;
-using Microsoft.AspNetCore.Http.Extensions;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Data.SqlClient;
+using EVCB_OCPP.WEBAPI.Helpers;
+using EVCB_OCPP.Domain;
 
 namespace EVCB_OCPP.WEBAPI.Controllers.Version2
-{    
+{
 
     [ApiExplorerSettings(IgnoreApi = false)]
     [Route("api/v2/cpo")]
@@ -122,7 +120,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2
         [Route("contact_information")]
         [Produces(typeof(CPOOuterResponse))]
         [HttpGet]
-        public IActionResult ContactInformation([FromServices]IConfiguration configuration)
+        public IActionResult ContactInformation([FromServices]SqlConnectionFactory<MainDBContext> mainDbConnectionFactory)
         {
             var result = new CPOOuterResponse();
             //HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
@@ -132,11 +130,11 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2
                 if (Request.Headers.ContainsKey(EVCBConfiguration.Header_PartnerId))
                 {
                     var customerId = Request.Headers[EVCBConfiguration.Header_PartnerId].First();
-                    string mainConnectionString = configuration.GetConnectionString("MainDBContext");
+                    // mainConnectionString = configuration.GetConnectionString("MainDBContext");
                     var parameters = new DynamicParameters();
                     parameters.Add("@CustomerId", customerId, DbType.String, ParameterDirection.Input);
                     string hotline = string.Empty;
-                    using (SqlConnection conn = new SqlConnection(mainConnectionString))
+                    using (SqlConnection conn = mainDbConnectionFactory.Create())
                     {
                         string strSql = "SELECT [Hotline]  FROM [dbo].[Customer] where Id=@CustomerId; ";
                         hotline = conn.ExecuteScalar<string>(strSql, parameters);
@@ -329,12 +327,11 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2
                         IdTag = request.Token
                     };
 
-                    string[] parts = Request.GetDisplayUrl().ToString().Split('/');
-                    string urlformat = "{0}//{1}";
+                    string urlformat = "{0}://{1}";
                     string ocppProtocol = GetChargePointOCPPProtocol(request.ChargeBoxId) == OCPPProtocolType.OCPP16 ? "16" : "20";
 
                     var _innerResult = await _client.Post(
-                        string.Format(urlformat, parts[0], parts[2]),
+                        string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()),
                         $"/api/v1/ocpp{ocppProtocol}/transaction?ChargeBoxId={request.ChargeBoxId}",
                         new Dictionary<string, string>()
                         {
@@ -419,13 +416,11 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-                string[] parts = Request.GetDisplayUrl().Split('/');
-
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
                 string ocppProtocol = GetChargePointOCPPProtocol(ChargeBoxId) == OCPPProtocolType.OCPP16 ? "16" : "20";
 
                 var _innerResult = await _client.Put(
-                    string.Format(urlformat, parts[0], parts[2], ocppProtocol, ChargeBoxId, SessionId), 
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent(), ocppProtocol, ChargeBoxId, SessionId), 
                     $"/api/v1/ocpp{ocppProtocol}/transaction?ChargeBoxId={ChargeBoxId}&TransactionId={SessionId}",
                     new Dictionary<string, string>()
                     {
@@ -504,8 +499,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-                string[] parts = Request.GetDisplayUrl().Split('/');
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
                 string ocppProtocol = GetChargePointOCPPProtocol(request.ChargeBoxId) == OCPPProtocolType.OCPP16 ? "16" : "20";
 
                 var _innerRequest = new ReserveRequest()
@@ -517,7 +511,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2
                 };
 
                 var _innerResult = await _client.Post(
-                    string.Format(urlformat, parts[0], parts[2] ),
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent() ),
                     $"/api/v1/ocpp{ocppProtocol}/reservation?ChargeBoxId={request.ChargeBoxId}",
                     new Dictionary<string, string>()
                         {
@@ -598,13 +592,11 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
 
-                string[] parts = Request.GetDisplayUrl().ToString().Split('/');
-
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
                 string ocppProtocol = GetChargePointOCPPProtocol(ChargeBoxId) == OCPPProtocolType.OCPP16 ? "16" : "20";
 
                 var _innerResult = await _client.Delete(
-                    string.Format(urlformat, parts[0], parts[2]), 
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()), 
                     $"/api/v1/ocpp{ocppProtocol}/reservation?ChargeBoxId={ChargeBoxId}&ReservationId={ReservationId}",
                     new Dictionary<string, string>()
                     {
@@ -682,15 +674,12 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-
-
-                string[] parts = Request.GetDisplayUrl().Split('/');
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
                 string ocppProtocol = GetChargePointOCPPProtocol(ChargeBoxId) == OCPPProtocolType.OCPP16 ? "16" : "20";
 
 
                 var _innerResult = await _client.Post(
-                    string.Format(urlformat, parts[0], parts[2]), 
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()), 
                     $"/api/v1/ocpp{ocppProtocol}/locallist?ChargeBoxId={ChargeBoxId}",
                     new Dictionary<string, string>()
                     {
@@ -770,15 +759,11 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-
-
-                string[] parts = Request.GetDisplayUrl().Split('/');
-
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
                 string ocppProtocol = GetChargePointOCPPProtocol(ChargeBoxId) == OCPPProtocolType.OCPP16 ? "16" : "20";
 
                 var _innerResult = await _client.Get(
-                    string.Format(urlformat, parts[0], parts[2]), 
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()), 
                     $"/api/v1/ocpp{ocppProtocol}/locallistversion?ChargeBoxId={ChargeBoxId}",
                     new Dictionary<string, string>()
                     {
@@ -913,14 +898,12 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2
                         break;
                 }
 
-                string[] parts = Request.GetDisplayUrl().Split('/');
-
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
                 var ocppPortocol = GetChargePointOCPPProtocol(ChargeBoxId) == OCPPProtocolType.OCPP16 ? "16" : "20";
 
 
                 var _innerResult = await _client.Get(
-                    string.Format(urlformat, parts[0], parts[2]), 
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()), 
                     string.Format("/api/v1/ocpp{{0}}/command?ChargeBoxId={{1}}{{2}}&SerialNo={{3}}", ocppPortocol, ChargeBoxId, orderNo.HasValue ? "&OrderNo=" + orderNo.Value : "", SerialNo),
                     new Dictionary<string, string>()
                     {
@@ -1126,7 +1109,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2
         [Route("completedsession")]
         [Produces(typeof(CPOOuterResponse))]
         [HttpGet]
-        public IActionResult CompletedSession(string ChargeBoxId, string SessionId = "", string IdTag = "", string StartTime = "", string StopTime = "")
+        public IActionResult CompletedSession(string ChargeBoxId, int SessionId = -1, string IdTag = "", string StartTime = "", string StopTime = "")
         {
             var result = new CPOOuterResponse();
             //HttpStatusCode statusCode = HttpStatusCode.InternalServerError;

+ 21 - 51
EVCB_OCPP.WEBAPI/Controllers/Version2/ocpp16/OCPP16_CPOController.cs

@@ -202,12 +202,10 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2.ocpp16
                         IdTag = request.Token
                     };
 
-                    string[] parts = Request.GetDisplayUrl().Split('/');
-                    string urlformat = "{0}//{1}";
+                    string urlformat = "{0}://{1}";
 
-                    var url = new Uri(Request.GetDisplayUrl());
                     var _innerResult = await _client.Post(
-                        string.Format(urlformat, parts[0], parts[2]), 
+                        string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()), 
                         $"/api/v1/ocpp16/transaction?ChargeBoxId={request.ChargeBoxId}",
                         new Dictionary<string, string>()
                         {
@@ -294,12 +292,10 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2.ocpp16
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-                string[] parts = Request.GetDisplayUrl().Split('/');
-
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
 
                 var _innerResult = await _client.Put(
-                    string.Format(urlformat, parts[0], parts[2] ),
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent() ),
                     $"/api/v1/ocpp16/transaction?ChargeBoxId={ChargeBoxId}&TransactionId={SessionId}",
                     new Dictionary<string, string>()
                     {
@@ -370,8 +366,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2.ocpp16
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-                string[] parts = Request.GetDisplayUrl().Split('/');
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
 
                 var _innerRequest = new ReserveRequest()
                 {
@@ -382,7 +377,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2.ocpp16
                 };
 
                 var _innerResult = await _client.Post(
-                    string.Format(urlformat, parts[0], parts[2]), 
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()), 
                     $"/api/v1/ocpp16/reservation?ChargeBoxId={request.ChargeBoxId}",
                     new Dictionary<string, string>()
                     {
@@ -453,13 +448,10 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2.ocpp16
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-
-                string[] parts = Request.GetDisplayUrl().Split('/');
-
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
 
                 var _innerResult = await _client.Delete(
-                    string.Format(urlformat, parts[0], parts[2]), 
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()), 
                     $"/api/v1/ocpp16/reservation?ChargeBoxId={ChargeBoxId}&ReservationId={ReservationId}",
                     new Dictionary<string, string>()
                     {
@@ -527,13 +519,10 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2.ocpp16
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-
-                string[] parts = Request.GetDisplayUrl().Split('/');
-
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
 
                 var _innerResult = await _client.Get(
-                    string.Format(urlformat, parts[0], parts[2]),
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()),
                     $"/api/v1/ocpp16/compositeschedule?ChargeBoxId={ChargeBoxId}&ConnectorId={ConnectorId}&Duration={Duration}", 
                     new Dictionary<string, string>()
                     {
@@ -602,13 +591,10 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2.ocpp16
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-
-                string[] parts = Request.GetDisplayUrl().Split('/');
-
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
 
                 var _innerResult = await _client.Post(
-                    string.Format(urlformat, parts[0], parts[2] ), 
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent() ), 
                     $"/api/v1/ocpp16/chargingprofile?ChargeBoxId={ChargeBoxId}",
                     new Dictionary<string, string>()
                     {
@@ -684,13 +670,10 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2.ocpp16
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-
-                string[] parts = Request.GetDisplayUrl().Split('/');
-
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
 
                 var _innerResult = await _client.Delete(
-                    string.Format(urlformat, parts[0], parts[2]), 
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()), 
                     string.Format("/api/v1/ocpp16/chargingprofile?ChargeBoxId={0}{1}", ChargeBoxId, ChargeProfileId == -1 ? "" : "&Id=" + ChargeProfileId),
                     new Dictionary<string, string>()
                     {
@@ -758,13 +741,10 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2.ocpp16
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-
-
-                string[] parts = Request.GetDisplayUrl().Split('/');
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
 
                 var _innerResult = await _client.Post(
-                    string.Format(urlformat, parts[0], parts[2] ), 
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent() ), 
                     $"/api/v1/ocpp16/locallist?ChargeBoxId={ChargeBoxId}", 
                     new Dictionary<string, string>()
                     {
@@ -835,16 +815,10 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2.ocpp16
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-
-
-                string[] parts = Request.GetDisplayUrl().Split('/');
-
-                string urlformat = "{0}//{1}";
-
-
+                string urlformat = "{0}://{1}";
 
                 var _innerResult = await _client.Get(
-                    string.Format(urlformat, parts[0], parts[2] ), 
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()), 
                     $"/api/v1/ocpp16/locallistversion?ChargeBoxId={ChargeBoxId}",
                     new Dictionary<string, string>()
                     {
@@ -973,14 +947,10 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2.ocpp16
 
                 }
 
-
-                string[] parts = Request.GetDisplayUrl().Split('/');
-
-                string urlformat = "{0}//{1}";
-
+                string urlformat = "{0}://{1}";
 
                 var _innerResult = await _client.Get(
-                    string.Format(urlformat, parts[0], parts[2]),
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()),
                     string.Format("/api/v1/ocpp16/command?ChargeBoxId={0}{1}&SerialNo={2}", ChargeBoxId, orderNo.HasValue ? "&OrderNo=" + orderNo.Value : "", SerialNo),
                     new Dictionary<string, string>()
                     {
@@ -1207,7 +1177,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2.ocpp16
         [Route("completedsession")]
         [Produces(typeof(CPOOuterResponse))]
         [HttpGet]
-        public IActionResult CompletedSession(string ChargeBoxId, string SessionId = "", string IdTag = "", string StartTime = "", string StopTime = "")
+        public IActionResult CompletedSession(string ChargeBoxId, int SessionId = -1, string IdTag = "", string StartTime = "", string StopTime = "")
         {
             var result = new CPOOuterResponse();
             //HttpStatusCode statusCode = HttpStatusCode.InternalServerError;

+ 7 - 25
EVCB_OCPP.WEBAPI/Controllers/Version2/ocpp201/OCPP201_CPOController.cs

@@ -1,6 +1,4 @@
-using Dapper;
-using EVCB_OCPP.Packet.Messages.SubTypes;
-using EVCB_OCPP.WEBAPI.Handlers;
+using EVCB_OCPP.WEBAPI.Handlers;
 using EVCB_OCPP.WEBAPI.Models.WebAPI;
 using EVCB_OCPP.WEBAPI.Models.WebAPI.Dto;
 using EVCB_OCPP.WEBAPI.Services;
@@ -11,17 +9,10 @@ using Microsoft.AspNetCore.Mvc;
 using Newtonsoft.Json;
 using System;
 using System.Collections.Generic;
-using System.Configuration;
-using System.Data;
-using System.Data.SqlClient;
 using System.Linq;
 using System.Net;
-using System.Net.Http;
 using System.Threading.Tasks;
-using CommandType = EVCB_OCPP.WEBAPI.Models.WebAPI.Dto.CommandType;
-using ReserveNowRequest = EVCB_OCPP.WEBAPI.Models.WebAPI.Dto.ReserveNowRequest;
 using ServerTriggerService = EVCB_OCPP.WEBAPI.Services.Integration.ServerTriggerService;
-using Microsoft.AspNetCore.Http.Extensions;
 using Microsoft.Extensions.DependencyInjection;
 
 namespace EVCB_OCPP.WEBAPI.Controllers.Version2.ocpp201
@@ -82,13 +73,10 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2.ocpp201
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-
-                string[] parts = Request.GetDisplayUrl().Split('/');
-
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
 
                 var _innerResult = await _client.Post(
-                    string.Format(urlformat, parts[0], parts[2]), 
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()), 
                     $"/api/v1/ocpp20/chargingprofile?ChargeBoxId={ChargeBoxId}",
                     new Dictionary<string, string>()
                         {
@@ -166,13 +154,10 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2.ocpp201
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-
-                string[] parts = Request.GetDisplayUrl().Split('/');
-
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
 
                 var _innerResult = await _client.Delete(
-                    string.Format(urlformat, parts[0], parts[2]),
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()),
                     string.Format("/api/v1/ocpp20/chargingprofile?ChargeBoxId={0}{1}", ChargeBoxId, ChargeProfileId == -1 ? "" : "&Id=" + ChargeProfileId),
                     new Dictionary<string, string>()
                     {
@@ -240,13 +225,10 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version2.ocpp201
                 InternalHttpClient _client = serviceProvider.GetRequiredService<InternalHttpClient>();
                 ICustomerService _customer = serviceProvider.GetRequiredService<ICustomerService>();
 
-
-                string[] parts = Request.GetDisplayUrl().Split('/');
-
-                string urlformat = "{0}//{1}";
+                string urlformat = "{0}://{1}";
 
                 var _innerResult = await _client.Post(
-                    string.Format(urlformat, parts[0], parts[2]),
+                    string.Format(urlformat, Request.Scheme, Request.Host.ToUriComponent()),
                     $"/api/v1/ocpp20/datatransfer?ChargeBoxId={ChargeBoxId}&MessageId=ID_CpConfiguration",
                     new Dictionary<string, string>()
                         {

BIN
EVCB_OCPP.WEBAPI/Dll/EVCB_OCPP.Domain.dll


+ 0 - 70
EVCB_OCPP.WEBAPI/EVCB_OCPP - Backup.WEBAPI.csproj

@@ -1,70 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk.Web">
-  <PropertyGroup>
-    <OutputType>Exe</OutputType>
-  </PropertyGroup>
-  <ItemGroup>
-    <Antlr4 Remove="App_Data\**" />
-    <Compile Remove="App_Data\**" />
-    <Content Remove="App_Data\**" />
-    <EmbeddedResource Remove="App_Data\**" />
-    <None Remove="App_Data\**" />
-  </ItemGroup>
-  <ItemGroup>
-    <Reference Include="EVCB_OCPP.Packet, Version=0.1.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>Dll\EVCB_OCPP.Packet.dll</HintPath>
-    </Reference>
-    <Reference Include="EVCB_OCPP20.Packet, Version=0.1.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>Dll\EVCB_OCPP20.Packet.dll</HintPath>
-    </Reference>
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Update="Global.asax.cs">
-      <DependentUpon>Global.asax</DependentUpon>
-    </Compile>
-  </ItemGroup>
-  <ItemGroup>
-    <None Update="NLog.xsd">
-      <SubType>Designer</SubType>
-    </None>
-    <Content Update="Web.config">
-      <SubType>Designer</SubType>
-    </Content>
-    <Content Update="Web.Debug.config">
-      <DependentUpon>Web.config</DependentUpon>
-    </Content>
-    <Content Update="Web.Release.config">
-      <DependentUpon>Web.config</DependentUpon>
-    </Content>
-  </ItemGroup>
-  <ItemGroup>
-    <PackageReference Include="bootstrap" Version="5.2.2" />
-    <PackageReference Include="Dapper" Version="2.0.123" />
-    <PackageReference Include="jQuery" Version="3.6.1" />
-    <PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" />
-    <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
-    <PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
-    <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
-    <PackageReference Include="Modernizr" Version="2.8.3" />
-    <PackageReference Include="NLog.Config" Version="4.7.15" />
-    <PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
-    <PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
-    <PackageReference Include="System.Data.SqlClient" Version="4.8.5" />
-    <PackageReference Include="System.ServiceModel.Duplex" Version="4.10.0" />
-    <PackageReference Include="System.ServiceModel.NetTcp" Version="4.10.0" />
-    <PackageReference Include="System.ServiceModel.Federation" Version="4.10.0" />
-    <PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="0.4.355802">
-      <PrivateAssets>all</PrivateAssets>
-    </PackageReference>
-    <PackageReference Include="Antlr4" Version="4.6.6" />
-    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="7.0.0" />
-  </ItemGroup>
-  <PropertyGroup>
-    <TargetFramework>net7.0</TargetFramework>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
-    <OutputPath>bin\</OutputPath>
-    <UserSecretsId>ad233da0-f16a-42df-bcf6-a2f575f2d4e0</UserSecretsId>
-    <DockerDefaultTargetOS>Windows</DockerDefaultTargetOS>
-  </PropertyGroup>
-</Project>

+ 11 - 11
EVCB_OCPP.WEBAPI/EVCB_OCPP.WEBAPI.csproj

@@ -1,6 +1,11 @@
 <Project Sdk="Microsoft.NET.Sdk.Web">
   <PropertyGroup>
+	  <TargetFramework>net7.0</TargetFramework>
     <OutputType>Exe</OutputType>
+    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+    <OutputPath>bin\</OutputPath>
+    <UserSecretsId>ad233da0-f16a-42df-bcf6-a2f575f2d4e0</UserSecretsId>
+    <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
   </PropertyGroup>
   <ItemGroup>
     <Antlr4 Remove="App_Data\**" />
@@ -10,6 +15,9 @@
     <None Remove="App_Data\**" />
   </ItemGroup>
   <ItemGroup>
+    <Reference Include="EVCB_OCPP.Domain">
+      <HintPath>Dll\EVCB_OCPP.Domain.dll</HintPath>
+    </Reference>
     <Reference Include="EVCB_OCPP.Packet, Version=0.1.0.0, Culture=neutral, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
       <HintPath>Dll\EVCB_OCPP.Packet.dll</HintPath>
@@ -41,17 +49,16 @@
   <ItemGroup>
     <PackageReference Include="bootstrap" Version="5.2.2" />
     <PackageReference Include="Dapper" Version="2.0.123" />
-    <PackageReference Include="GitVersion.MsBuild" Version="5.12.0">
-      <PrivateAssets>all</PrivateAssets>
-      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
-    </PackageReference>
     <PackageReference Include="jQuery" Version="3.6.1" />
     <PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" />
     <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
     <PackageReference Include="Microsoft.Data.SqlClient" Version="5.0.1" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.5" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.5" />
     <PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
     <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
     <PackageReference Include="Modernizr" Version="2.8.3" />
+    <PackageReference Include="NLog.Extensions.Logging" Version="5.3.4" />
     <PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
     <PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
     <PackageReference Include="System.ServiceModel.Duplex" Version="4.10.0" />
@@ -63,11 +70,4 @@
     <PackageReference Include="Antlr4" Version="4.6.6" />
     <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="7.0.0" />
   </ItemGroup>
-  <PropertyGroup>
-    <TargetFramework>net7.0</TargetFramework>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
-    <OutputPath>bin\</OutputPath>
-    <UserSecretsId>ad233da0-f16a-42df-bcf6-a2f575f2d4e0</UserSecretsId>
-    <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
-  </PropertyGroup>
 </Project>

+ 20 - 8
EVCB_OCPP.WEBAPI/Handlers/CPOAuthentication.cs

@@ -20,18 +20,28 @@ using Microsoft.Extensions.Logging;
 
 namespace EVCB_OCPP.WEBAPI.Handlers
 {
-    public class CPOAuthentication : Attribute, IAuthorizationFilter
+    public class CPOAuthentication : Attribute, IAsyncAuthorizationFilter
     {
         private readonly IServiceProvider serviceProvider;
+        private readonly ICustomerService customerService;
         private readonly ILogger logger;
 
-        public CPOAuthentication(IServiceProvider serviceProvider, ILoggerFactory loggerFactory)
+        public CPOAuthentication(
+            IServiceProvider serviceProvider,
+            ICustomerService customerService,
+            ILogger<CPOAuthentication> logger)
         {
             this.serviceProvider = serviceProvider;
-            this.logger = loggerFactory.CreateLogger(nameof(CPOAuthentication));
+            this.customerService = customerService;
+            this.logger = logger;
         }
 
         public void OnAuthorization(AuthorizationFilterContext context)
+        {
+            OnAuthorizationAsync(context).RunSynchronously();
+        }
+
+        public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
         {
             HttpContext actionContext = context.HttpContext;
             int _status = StatusCodes.Status401Unauthorized;// HttpStatusCode.Unauthorized;
@@ -51,7 +61,7 @@ namespace EVCB_OCPP.WEBAPI.Handlers
                     else
                     {
                         string partnerId = actionContext.Request.Headers[EVCBConfiguration.Header_PartnerId].FirstOrDefault();
-                        string key = serviceProvider.GetRequiredService<ICustomerService>().GetAPIKey(new Guid(partnerId));
+                        string key = await customerService.GetAPIKeyAsync(Guid.Parse(partnerId));
 
                         if (IsPass(actionContext, key))
                         {
@@ -85,7 +95,8 @@ namespace EVCB_OCPP.WEBAPI.Handlers
 
 
             //context.Result = FromResult(new HttpResponseMessage(_status) { Content = new StringContent(JsonConvert.SerializeObject(_errorResponse), System.Text.Encoding.UTF8, "application/json") });
-            context.Result = new ContentResult() {
+            context.Result = new ContentResult()
+            {
                 StatusCode = _status,
                 ContentType = "application/json",
                 Content = JsonConvert.SerializeObject(_errorResponse)
@@ -163,9 +174,10 @@ namespace EVCB_OCPP.WEBAPI.Handlers
 
             //Task<string> content = actionContext.Request.Body.Content.ReadAsStringAsync();
             //string body = content.Result;
-            actionContext.Request.Body.Position = 0;
-            string body = new StreamReader(actionContext.Request.Body).ReadToEnd();
-            actionContext.Request.Body.Position = 0;
+            //actionContext.Request.Body.Position = 0;
+            //string body = new StreamReader(actionContext.Request.Body).ReadToEnd();
+            //actionContext.Request.Body.Position = 0;
+            string body = actionContext.GetPreLoadBody();
             string diplayUrl = actionContext.Request.GetDisplayUrl().Replace("%20", " ").Replace(@"\\", @"\");
             string tempText = diplayUrl.Substring(diplayUrl.IndexOf('?') + 1).ToLower();
             tempText = tempText.StartsWith("http") ? string.Empty : tempText;

+ 4 - 2
EVCB_OCPP.WEBAPI/Handlers/InernalAuthentication.cs

@@ -172,8 +172,10 @@ namespace EVCB_OCPP.WEBAPI.Handlers
 
             //Task<string> content = actionContext.Request.Content.ReadAsStringAsync();
             //string body = content.Result;
-            actionContext.Request.Body.Position = 0;
-            string body = new StreamReader(actionContext.Request.Body).ReadToEndAsync().Result;//.ReadToEnd();
+            //actionContext.Request.Body.Position = 0;
+            //string body = new StreamReader(actionContext.Request.Body).ReadToEndAsync().Result;//.ReadToEnd();
+            //actionContext.Request.Body.Position = 0;
+            string body = actionContext.GetPreLoadBody();
             string diplayUrl = actionContext.Request.GetDisplayUrl().Replace("%20"," ").Replace(@"\\", @"\");
             string tempText = diplayUrl.Substring(diplayUrl.IndexOf('?') + 1).ToLower();
             tempText = tempText.StartsWith("http") ? string.Empty : tempText;

+ 166 - 0
EVCB_OCPP.WEBAPI/Helpers/AddPortalDbContext.cs

@@ -0,0 +1,166 @@
+using EVCB_OCPP.Domain;
+using Microsoft.Data.SqlClient;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Threading.Tasks;
+
+namespace EVCB_OCPP.WEBAPI.Helpers;
+
+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(
+            new 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(
+            new 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(
+            new 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(
+            new SqlConnectionFactory<WebDBConetext>()
+            {
+                ConnectionString = conneciotnString
+            });
+        return services;
+    }
+
+    public static IServiceCollection AddOnlineLogDBContext(this IServiceCollection services, IConfiguration configuration)
+    {
+        const string DbUserIdKey = "OnlineLogDbUserId";
+        const string DbPassKey = "OnlineLogDbPass";
+        const string DbConnectionStringKey = "OnlineLogDBContext";
+
+        var conneciotnString = GetConnectionString(configuration, DbUserIdKey, DbPassKey, DbConnectionStringKey);
+        services.AddSingleton(
+            new SqlConnectionFactory<OnlineLogDBContext>()
+            {
+                ConnectionString = conneciotnString
+            });
+        return services;
+    }
+    
+    public static IServiceCollection AddAPILogDBContext(this IServiceCollection services, IConfiguration configuration)
+    {
+        const string DbUserIdKey = "APILogDbUserId";
+        const string DbPassKey = "APILogDbPass";
+        const string DbConnectionStringKey = "APILogDBContext";
+
+        var conneciotnString = GetConnectionString(configuration, DbUserIdKey, DbPassKey, DbConnectionStringKey);
+        services.AddSingleton(
+            new SqlConnectionFactory<APILogDBContext>()
+            {
+                ConnectionString = 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);
+            });
+            if (logToConsole)
+            {
+                options.LogTo(Console.WriteLine);
+            }
+        });
+    }
+
+    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
+{
+    public string ConnectionString { get; init; }
+    public SqlConnectionFactory() { }
+    public SqlConnection Create()
+    {
+        var sqlConnection = new SqlConnection(ConnectionString);
+        sqlConnection.Open();
+        return sqlConnection;
+    }
+
+    public async Task<SqlConnection> CreateAsync()
+    {
+        var sqlConnection = new SqlConnection(ConnectionString);
+        await sqlConnection.OpenAsync();
+        return sqlConnection;
+    }
+}
+
+/// <summary>
+/// Dummy
+/// </summary>
+public class WebDBConetext : DbContext { }
+
+/// <summary>
+/// Dummy
+/// </summary>
+public class OnlineLogDBContext : DbContext { }
+/// <summary>
+/// Dummy
+/// </summary>
+public class APILogDBContext : DbContext { }

+ 119 - 0
EVCB_OCPP.WEBAPI/Helpers/GroupSingleHandler.cs

@@ -0,0 +1,119 @@
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading.Tasks;
+using System.Threading;
+using System;
+using Microsoft.Extensions.Logging;
+using System.Linq;
+
+namespace EVCB_OCPP.WEBAPI.Helpers;
+
+public class GroupSingleHandler<T>
+{
+    public GroupSingleHandler(Func<IEnumerable<T>, Task> handleFunc, ILogger logger, int workerCnt = 1)
+    {
+        this.handleFunc = handleFunc;
+        this.logger = logger;
+
+        WorkerCnt = workerCnt;
+        //singleWorkLock = new(_WorkerCnt);
+    }
+
+    private int _WorkerCnt = 1;
+    public int WorkerCnt
+    {
+        get => _WorkerCnt;
+        set
+        {
+            if (IsStarted)
+            {
+                throw new Exception($"{nameof(WorkerCnt)} must not be changed afted {nameof(HandleAsync)} is called");
+            }
+
+            _WorkerCnt = value;
+            singleWorkLock = new(_WorkerCnt);
+        }
+    }
+
+    private readonly Func<IEnumerable<T>, Task> handleFunc;
+    private readonly ILogger logger;
+    private readonly ConcurrentQueue<(T param, SemaphoreSlim waitLock)> waitList = new();
+    private SemaphoreSlim singleWorkLock;// = new SemaphoreSlim(1);
+    private bool IsStarted = false;
+    private Task singleHandleTask;
+
+    public Task HandleAsync(T param)
+    {
+        IsStarted = true;
+
+        SemaphoreSlim reqLock = new(0);
+        waitList.Enqueue((param, reqLock));
+        TryStartHandler();
+        return reqLock.WaitAsync();
+    }
+
+    private void TryStartHandler()
+    {
+        if (!singleWorkLock.Wait(0))
+        {
+            return;
+        }
+
+        if (waitList.Count == 0)
+        {
+            singleWorkLock.Release();
+            return;
+        }
+
+        singleHandleTask = StartHandleTask();
+    }
+
+    private async Task StartHandleTask()
+    {
+        var timer = Stopwatch.StartNew();
+        long t0 = 0, t1 = 0, t2 = 0;
+
+        var handleList = new List<(T param, SemaphoreSlim waitLock)>();
+
+        while (waitList.TryDequeue(out var handle))
+        {
+            handleList.Add(handle);
+        }
+        t0 = timer.ElapsedMilliseconds;
+
+        int cnt = 0;
+        do
+        {
+            cnt++;
+            try
+            {
+                var task = handleFunc(handleList.Select(x => x.param));
+                await task;
+                t1 = timer.ElapsedMilliseconds;
+                break;
+            }
+            catch (Exception e)
+            {
+                logger.LogError(e, "Trying Cnt {0}", cnt);
+                logger.LogError(e.Message);
+            }
+        }
+        while (true);
+
+        foreach (var handled in handleList)
+        {
+            handled.waitLock.Release();
+        }
+        singleWorkLock.Release();
+
+        timer.Stop();
+        t2 = timer.ElapsedMilliseconds;
+        if (t2 > 1000)
+        {
+            logger.LogWarning("StartHandleTask {0}/{1}/{2}", t0, t1, t2);
+        }
+
+        TryStartHandler();
+    }
+}

+ 28 - 68
EVCB_OCPP.WEBAPI/Middleware/APILogMiddleware.cs

@@ -14,35 +14,44 @@ using System.Linq;
 using System.Net;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Data.SqlClient;
+using EVCB_OCPP.WEBAPI.Services;
 
 namespace EVCB_OCPP.WEBAPI.Middleware;
 
 public class APILogMiddleware
 {
     private readonly RequestDelegate _next;
-    private readonly string apiLogConnectionString;
+    private readonly ApiLogDbService apiLogDbService;
+    private readonly SqlConnectionFactory<APILogDBContext> apiLogDbConnectionFactory;
 
-    public APILogMiddleware(RequestDelegate next, IConfiguration configuration)
+    //private readonly string apiLogConnectionString;
+
+    public APILogMiddleware(RequestDelegate next,
+        ApiLogDbService apiLogDbService,
+        SqlConnectionFactory<APILogDBContext> apiLogDbConnectionFactory)
     {
         _next = next;
-        apiLogConnectionString = configuration.GetConnectionString("APILogDBContext");
+        this.apiLogDbService = apiLogDbService;
+        this.apiLogDbConnectionFactory = apiLogDbConnectionFactory;
+        //apiLogConnectionString = configuration.GetConnectionString("APILogDBContext");
     }
 
     public async Task Invoke(HttpContext context)
     {
         var request = context.Request;
-        string uri = request.GetDisplayUrl().ToString();
+        //string uri = request.GetDisplayUrl().ToString();
         CancellationToken cancellationToken = context?.RequestAborted ?? CancellationToken.None;
 
         var apiLogEntry = CreateApiLogEntryWithRequestData(request);
 
-        context.Request.Body.Position = 0;
-        await new StreamReader(context.Request.Body).ReadToEndAsync()
-            .ContinueWith(task =>
-            {
-                apiLogEntry.RequestContentBody = task.Result;
+        //context.Request.Body.Position = 0;
+        //await new StreamReader(context.Request.Body).ReadToEndAsync()
+        //    .ContinueWith(task =>
+        //    {
+        //        apiLogEntry.RequestContentBody = task.Result;
 
-            }, cancellationToken);
+        //    }, cancellationToken);
+        apiLogEntry.RequestContentBody = context.GetPreLoadBody();
 
         var originalBodyStream = context.Response.Body;
         var fakeResponseBody = new MemoryStream();
@@ -54,9 +63,11 @@ public class APILogMiddleware
         fakeResponseBody.Seek(0, SeekOrigin.Begin);
         await fakeResponseBody.CopyToAsync(originalBodyStream);
 
+        var test = request.Path;
+
         if (request.GetDisplayUrl().Contains("api/v1/file"))
         {
-            await fakeResponseBody.DisposeAsync();
+            fakeResponseBody.Dispose();
             return;
         }
 
@@ -73,7 +84,7 @@ public class APILogMiddleware
 
             apiLogEntry.ResponseStatusCode = (int)HttpStatusCode.InternalServerError;
             apiLogEntry.ResponseTimestamp = DateTime.Now;
-            WriteLog(apiLogEntry);
+            _ = apiLogDbService.Write(apiLogEntry);
             //return request.CreateResponse(HttpStatusCode.InternalServerError, result);
             await context.Response.WriteAsJsonAsync(result);
             return;
@@ -83,11 +94,11 @@ public class APILogMiddleware
             //var response = task.Result;
             var response = context.Response;
 
-            if (response.Body != null)
+            if (fakeResponseBody != null)
             {
                 fakeResponseBody.Seek(0, SeekOrigin.Begin);
-                var bodyData = await new StreamReader(response.Body).ReadToEndAsync();
-                response.Body.Position = 0;
+                var bodyData = new StreamReader(fakeResponseBody).ReadToEnd();
+                fakeResponseBody.Seek(0, SeekOrigin.Begin);
 
                 apiLogEntry.ResponseContentBody = bodyData;
                 apiLogEntry.ResponseContentType = response.Headers.ContentType;
@@ -110,9 +121,9 @@ public class APILogMiddleware
 
             apiLogEntry.ResponseStatusCode = (int)response.StatusCode;
             apiLogEntry.ResponseTimestamp = DateTime.Now;
-            WriteLog(apiLogEntry);
+            _ = apiLogDbService.Write(apiLogEntry);
 
-            await fakeResponseBody.DisposeAsync();
+            fakeResponseBody.Dispose();
 
             return;
         }
@@ -147,55 +158,4 @@ public class APILogMiddleware
         }
 
     }
-
-    private void WriteLog(ApiLogEntry log)
-    {
-        try
-        {
-            if (log == null) return;
-            using (var conn = new SqlConnection(apiLogConnectionString))
-            {
-                conn.Open();
-
-                using (var cmd = new SqlCommand("[dbo].[uspInsertApiLog]", conn))
-                {
-
-                    cmd.CommandType = System.Data.CommandType.StoredProcedure;
-                    cmd.Parameters.Add(new SqlParameter("Application", log.Application));
-                    cmd.Parameters.Add(new SqlParameter("User", (string.IsNullOrEmpty(log.User) ? "" : log.User)));
-                    cmd.Parameters.Add(new SqlParameter("Machine", log.Machine));
-                    cmd.Parameters.Add(new SqlParameter("RequestIpAddress", log.RequestIpAddress));
-                    cmd.Parameters.Add(new SqlParameter("RequestContentType", (string.IsNullOrEmpty(log.RequestContentType) ? "" : log.RequestContentType)));
-                    cmd.Parameters.Add(new SqlParameter("RequestUri", log.RequestUri));
-                    cmd.Parameters.Add(new SqlParameter("RequestMethod", log.RequestMethod));
-                    //cmd.Parameters.Add(new SqlParameter("RequestRouteTemplate", log.RequestRouteTemplate));
-                    cmd.Parameters.Add(new SqlParameter("RequestRouteTemplate", ""));
-                    cmd.Parameters.Add(new SqlParameter("RequestRouteData", ""));//log.RequestRouteData
-                    cmd.Parameters.Add(new SqlParameter("RequestHeaders", log.RequestHeaders));
-                    cmd.Parameters.Add(new SqlParameter("RequestTimestamp", log.RequestTimestamp));
-
-                    cmd.Parameters.Add(new SqlParameter("ResponseContentType", log.ResponseContentType));
-                    cmd.Parameters.Add(new SqlParameter("ResponseStatusCode", log.ResponseStatusCode));
-                    cmd.Parameters.Add(new SqlParameter("ResponseHeaders", log.ResponseHeaders));
-                    cmd.Parameters.Add(new SqlParameter("ResponseTimestamp", log.ResponseTimestamp));
-
-                    cmd.Parameters.Add(new SqlParameter("IsOutData", log.IsOutData));
-                    cmd.Parameters.Add(new SqlParameter("ErrorMsg", log.ErrorMsg));
-                    cmd.Parameters.Add(new SqlParameter("ErrorOn", log.ErrorOn));
-                    cmd.Parameters.Add(new SqlParameter("RequestContentBody", log.RequestContentBody));
-                    cmd.Parameters.Add(new SqlParameter("ResponseContentBody", log.ResponseContentBody));
-
-                    var result = cmd.ExecuteNonQuery();
-                }
-            }
-
-
-        }
-        catch (Exception ex)
-        {
-            Console.WriteLine(ex.ToString());
-        }
-
-
-    }
 }

+ 28 - 17
EVCB_OCPP.WEBAPI/Middleware/BodyRewindMiddleware.cs

@@ -5,31 +5,38 @@ using System;
 using System.IO;
 using System.Reflection.PortableExecutable;
 using Microsoft.AspNetCore.Mvc;
+using System.Text;
 
-namespace EVCB_OCPP.WEBAPI.Middleware;
-
-public sealed class BodyRewindMiddleware
+namespace EVCB_OCPP.WEBAPI.Middleware
 {
-    private readonly RequestDelegate _next;
-
-    public BodyRewindMiddleware(RequestDelegate next)
+    public sealed class BodyRewindMiddleware
     {
-        _next = next;
-    }
+        private readonly RequestDelegate _next;
 
-    public async Task Invoke(HttpContext context)
-    {
-        string body = new StreamReader(context.Request.Body).ReadToEndAsync().GetAwaiter().GetResult();
-        using (var injectedRequestStream = new MemoryStream())
+        public BodyRewindMiddleware(RequestDelegate next)
         {
-            var bytesToWrite = System.Text.Encoding.UTF8.GetBytes(body);
-            injectedRequestStream.Write(bytesToWrite, 0, bytesToWrite.Length);
-            injectedRequestStream.Seek(0, SeekOrigin.Begin);
-            context.Request.Body = injectedRequestStream;
+            _next = next;
+        }
+
+        public async Task Invoke(HttpContext context)
+        {
+            string body = await new StreamReader(context.Request.Body).ReadToEndAsync();
+            context.Items.Add("PreloadBody", body);
+            context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(body));
             await _next(context);
+
+            //using (var injectedRequestStream = new MemoryStream())
+            //{
+            //    var bytesToWrite = System.Text.Encoding.UTF8.GetBytes(body);
+            //    injectedRequestStream.Write(bytesToWrite, 0, bytesToWrite.Length);
+            //    injectedRequestStream.Seek(0, SeekOrigin.Begin);
+            //    context.Request.Body = injectedRequestStream;
+            //    await _next(context);
+            //}
         }
     }
 }
+
 public static class BodyRewindExtensions
 {
     public static IApplicationBuilder EnableRequestBodyRewind(this IApplicationBuilder app)
@@ -39,7 +46,11 @@ public static class BodyRewindExtensions
             throw new ArgumentNullException(nameof(app));
         }
 
-        return app.UseMiddleware<BodyRewindMiddleware>();
+        return app.UseMiddleware<EVCB_OCPP.WEBAPI.Middleware.BodyRewindMiddleware>();
     }
 
+    public static string GetPreLoadBody(this HttpContext httpContext)
+    {
+        return httpContext.Items["PreloadBody"] as string;
+    }
 }

+ 40 - 0
EVCB_OCPP.WEBAPI/Middleware/PerformaceMonitorMiddleware.cs

@@ -0,0 +1,40 @@
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Logging;
+using System.Diagnostics;
+using System.Threading.Tasks;
+
+namespace EVCB_OCPP.WEBAPI.Middleware;
+
+public class PerformaceMonitorMiddlewareOptions
+{
+    public string Label { get; set; }
+}
+
+public class PerformaceMonitorMiddleware
+{
+    private readonly RequestDelegate _next;
+    private readonly PerformaceMonitorMiddlewareOptions options;
+    private readonly ILogger<PerformaceMonitorMiddleware> logger;
+
+    public PerformaceMonitorMiddleware(
+        RequestDelegate next,
+        PerformaceMonitorMiddlewareOptions options,
+        ILogger<PerformaceMonitorMiddleware> logger)
+    {
+        _next = next;
+        this.options = options;
+        this.logger = logger;
+    }
+
+    public async Task Invoke(HttpContext context)
+    {
+        var timer = Stopwatch.StartNew();
+        await _next(context);
+        timer.Stop();
+
+        if (timer.ElapsedMilliseconds / 1000 > 1)
+        {
+            logger.LogCritical("{0} {1} {2} cost {3}", options.Label, context.Request.Method, context.Request.Path, timer.ElapsedMilliseconds);
+        }
+    }
+}

+ 8 - 0
EVCB_OCPP.WEBAPI/Models/Db/StationMachineDto.cs

@@ -0,0 +1,8 @@
+namespace EVCB_OCPP.WEBAPI.Models.Db
+{
+    public class StationMachineDto
+    {
+        public int StationId { get; set; }
+        public string MachineId { get; set; }
+    }
+}

+ 2 - 0
EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/ConnectorStatus.cs

@@ -6,6 +6,8 @@ namespace EVCB_OCPP.WEBAPI.Models.WebAPI.Dto
 {
     public class ConnectorStatus
     {
+        public string ChargeBoxId { get; set; }
+
         public int ConnectorId { set; get; }
 
      

+ 13 - 0
EVCB_OCPP.WEBAPI/Program.cs

@@ -3,8 +3,11 @@
 // This file may need updated according to the specific scenario of the application being upgraded.
 // For more information on ASP.NET Core hosting, see https://docs.microsoft.com/aspnet/core/fundamentals/host/web-host
 
+using EVCB_OCPP.WEBAPI.Helpers;
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using NLog.Extensions.Logging;
 
 namespace EVCB_OCPP.WEBAPI
 {
@@ -17,9 +20,19 @@ namespace EVCB_OCPP.WEBAPI
 
         public static IHostBuilder CreateHostBuilder(string[] args) =>
             Host.CreateDefaultBuilder(args)
+                .ConfigureLogging((context, logging) => {
+                    NLog.LogManager.Configuration = new NLogLoggingConfiguration(context.Configuration.GetSection("NLog"));
+                })
                 .ConfigureWebHostDefaults(webBuilder =>
                 {
                     webBuilder.UseStartup<Startup>();
+                })
+                .ConfigureServices((context, services) => {
+                    services.AddMainDbContext(context.Configuration);
+                    services.AddMeterValueDbContext(context.Configuration);
+                    services.AddAPILogDBContext(context.Configuration);
+                    services.AddWebDBConetext(context.Configuration);
+                    services.AddConnectionLogDbContext(context.Configuration);
                 });
     }
 }

+ 281 - 0
EVCB_OCPP.WEBAPI/Services/ApiLogDbService.cs

@@ -0,0 +1,281 @@
+using Dapper;
+using EVCB_OCPP.WEBAPI.Helpers;
+using EVCB_OCPP.WEBAPI.Models;
+using Microsoft.Data.SqlClient;
+using Microsoft.Extensions.Logging;
+using Microsoft.VisualBasic;
+using NLog.Fluent;
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace EVCB_OCPP.WEBAPI.Services
+{
+    public class ApiLogDbService
+    {
+        public ApiLogDbService(
+            SqlConnectionFactory<APILogDBContext> apiLogDbConnectionFactory,
+            ILogger<ApiLogDbService> logger)
+        {
+            this.apiLogDbConnectionFactory = apiLogDbConnectionFactory;
+            this.logger = logger;
+
+            InitInsertApiLogHandler();
+        }
+
+        private readonly SqlConnectionFactory<APILogDBContext> apiLogDbConnectionFactory;
+        private readonly ILogger<ApiLogDbService> logger;
+
+        private readonly Queue<string> _existTables = new();
+
+        private GroupSingleHandler<ApiLogEntry> insertApiLogHandler;
+
+        public Task Write(ApiLogEntry apiLogEntry)
+        {
+            if (apiLogEntry == null) return Task.CompletedTask;
+
+            try
+            {
+                return insertApiLogHandler.HandleAsync(apiLogEntry);
+                //return WriteLogWithDapperCatch(apiLogEntry);
+                //return WriteLogWithEf(apiLogEntry);
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine(ex.ToString());
+                logger.LogError(ex.Message);
+                logger.LogError(ex.StackTrace);
+
+                return Task.CompletedTask;
+            }
+        }
+
+        private void InitInsertApiLogHandler()
+        {
+            if (insertApiLogHandler is not null)
+            {
+                throw new Exception($"{nameof(InitInsertApiLogHandler)} should only called once");
+            }
+
+            insertApiLogHandler = new GroupSingleHandler<ApiLogEntry>(
+                BundleInsertWithDapperCatch,
+                logger,
+                workerCnt: 20
+                );
+        }
+
+        private async Task WriteLogWithEf(ApiLogEntry log)
+        {
+            using (var conn = await apiLogDbConnectionFactory.CreateAsync())
+            using (var cmd = new SqlCommand("[dbo].[uspInsertApiLog]", conn))
+            {
+
+                cmd.CommandType = System.Data.CommandType.StoredProcedure;
+                cmd.Parameters.Add(new SqlParameter("Application", log.Application));
+                cmd.Parameters.Add(new SqlParameter("User", (string.IsNullOrEmpty(log.User) ? "" : log.User)));
+                cmd.Parameters.Add(new SqlParameter("Machine", log.Machine));
+                cmd.Parameters.Add(new SqlParameter("RequestIpAddress", log.RequestIpAddress));
+                cmd.Parameters.Add(new SqlParameter("RequestContentType", (string.IsNullOrEmpty(log.RequestContentType) ? "" : log.RequestContentType)));
+                cmd.Parameters.Add(new SqlParameter("RequestUri", log.RequestUri));
+                cmd.Parameters.Add(new SqlParameter("RequestMethod", log.RequestMethod));
+                //cmd.Parameters.Add(new SqlParameter("RequestRouteTemplate", log.RequestRouteTemplate));
+                cmd.Parameters.Add(new SqlParameter("RequestRouteTemplate", ""));
+                cmd.Parameters.Add(new SqlParameter("RequestRouteData", ""));//log.RequestRouteData
+                cmd.Parameters.Add(new SqlParameter("RequestHeaders", log.RequestHeaders));
+                cmd.Parameters.Add(new SqlParameter("RequestTimestamp", log.RequestTimestamp));
+
+                cmd.Parameters.Add(new SqlParameter("ResponseContentType", log.ResponseContentType));
+                cmd.Parameters.Add(new SqlParameter("ResponseStatusCode", log.ResponseStatusCode));
+                cmd.Parameters.Add(new SqlParameter("ResponseHeaders", log.ResponseHeaders));
+                cmd.Parameters.Add(new SqlParameter("ResponseTimestamp", log.ResponseTimestamp));
+
+                cmd.Parameters.Add(new SqlParameter("IsOutData", log.IsOutData));
+                cmd.Parameters.Add(new SqlParameter("ErrorMsg", log.ErrorMsg));
+                cmd.Parameters.Add(new SqlParameter("ErrorOn", log.ErrorOn));
+                cmd.Parameters.Add(new SqlParameter("RequestContentBody", log.RequestContentBody));
+                cmd.Parameters.Add(new SqlParameter("ResponseContentBody", log.ResponseContentBody));
+
+                var result = await cmd.ExecuteNonQueryAsync();
+            }
+        }
+
+        private async Task WriteLogWithDapperCatch(ApiLogEntry log)
+        {
+            try
+            {
+                await WriteLogWithDapper(log);
+            }
+            catch (Exception e)
+            {
+                logger.LogCritical(e.Message);
+                logger.LogCritical(e.StackTrace);
+            }
+        }
+
+        private async Task WriteLogWithDapper(ApiLogEntry log)
+        {
+            var workTime = DateTime.UtcNow;
+            if (!await GetTableExist(workTime))
+            {
+                await WriteLogWithEf(log);
+                return;
+            }
+
+            var tableName = GetTableName(workTime);
+
+            string command = $"""
+                INSERT INTO {tableName}
+                (Application, [User], Machine, 
+                RequestIpAddress, RequestContentType, RequestUri, RequestMethod, RequestRouteTemplate, RequestRouteData, RequestHeaders, RequestTimestamp,
+                ResponseContentType, ResponseStatusCode, ResponseHeaders, ResponseTimestamp,
+                IsOutData, ErrorMsg, ErrorOn, RequestContentBody, ResponseContentBody)
+                VALUES 
+                (@Application, @User, @Machine,
+                @RequestIpAddress, @RequestContentType, @RequestUri, @RequestMethod, @RequestRouteTemplate, @RequestRouteData, @RequestHeaders, @RequestTimestamp,
+                @ResponseContentType, @ResponseStatusCode, @ResponseHeaders, @ResponseTimestamp,
+                @IsOutData, @ErrorMsg, @ErrorOn, @RequestContentBody, @ResponseContentBody);
+                """;
+
+            var parameters = new DynamicParameters();
+            parameters.Add("@Application", log.Application, DbType.String);
+            parameters.Add("@User", string.IsNullOrEmpty(log.User) ? "" : log.User, DbType.String);
+            parameters.Add("@Machine", log.Machine, DbType.String);
+
+            parameters.Add("@RequestIpAddress", log.RequestIpAddress, DbType.String);
+            parameters.Add("@RequestContentType", (string.IsNullOrEmpty(log.RequestContentType) ? "" : log.RequestContentType), DbType.String);
+            parameters.Add("@RequestUri", log.RequestUri, DbType.String);
+            parameters.Add("@RequestMethod", log.RequestMethod, DbType.String);
+            parameters.Add("@RequestRouteTemplate", "", DbType.String);
+            parameters.Add("@RequestRouteData", "", DbType.String, size: 36);
+            parameters.Add("@RequestHeaders", log.RequestHeaders, DbType.String);
+            parameters.Add("@RequestTimestamp", log.RequestTimestamp, DbType.DateTime);
+
+            parameters.Add("@ResponseContentType", log.ResponseContentType, DbType.String);
+            parameters.Add("@ResponseStatusCode", log.ResponseStatusCode, DbType.Int32);
+            parameters.Add("@ResponseHeaders", log.ResponseHeaders, DbType.String);
+            parameters.Add("@ResponseTimestamp", log.ResponseTimestamp, DbType.DateTime);
+
+            parameters.Add("@IsOutData", log.IsOutData, DbType.Boolean);
+            parameters.Add("@ErrorMsg", log.ErrorMsg, DbType.String);
+            parameters.Add("@ErrorOn", log.ErrorOn, DbType.DateTime);
+            parameters.Add("@RequestContentBody", log.RequestContentBody, DbType.String);
+            parameters.Add("@ResponseContentBody", log.ResponseContentBody, DbType.String);
+
+            using var sqlConnection = await apiLogDbConnectionFactory.CreateAsync();
+            await sqlConnection.ExecuteAsync(command, parameters);
+        }
+
+        private async Task BundleInsertWithDapperCatch(IEnumerable<ApiLogEntry> parms)
+        {
+            try
+            {
+                await BundleInsertWithDapper(parms);
+            }
+            catch (Exception e)
+            {
+                logger.LogCritical(e.Message);
+                logger.LogCritical(e.StackTrace);
+            }
+        }
+
+        private async Task BundleInsertWithDapper(IEnumerable<ApiLogEntry> parms)
+        {
+            var watch = Stopwatch.StartNew();
+            List<long> times = new();
+
+            var parmsList = parms.ToList();
+
+            if (parmsList.Count == 0)
+            {
+                return;
+            }
+
+            var workTime = DateTime.UtcNow;
+            var candidate = parmsList[0];
+            if (!await GetTableExist(workTime))
+            {
+                await WriteLogWithEf(candidate);
+                parmsList.Remove(candidate);
+            }
+
+            var tableName = GetTableName(workTime);
+
+            string command = $"""
+                INSERT INTO {tableName}
+                (Application, [User], Machine, 
+                RequestIpAddress, RequestContentType, RequestUri, RequestMethod, RequestRouteTemplate, RequestRouteData, RequestHeaders, RequestTimestamp,
+                ResponseContentType, ResponseStatusCode, ResponseHeaders, ResponseTimestamp,
+                IsOutData, ErrorMsg, ErrorOn, RequestContentBody, ResponseContentBody)
+                VALUES 
+                (@Application, @User, @Machine,
+                @RequestIpAddress, @RequestContentType, @RequestUri, @RequestMethod, @RequestRouteTemplate, @RequestRouteData, @RequestHeaders, @RequestTimestamp,
+                @ResponseContentType, @ResponseStatusCode, @ResponseHeaders, @ResponseTimestamp,
+                @IsOutData, @ErrorMsg, @ErrorOn, @RequestContentBody, @ResponseContentBody);
+                """;
+
+            using var sqlConnection = await apiLogDbConnectionFactory.CreateAsync();
+
+            foreach (var log in parmsList)
+            {
+                var parameters = new DynamicParameters();
+                parameters.Add("@Application", log.Application, DbType.String);
+                parameters.Add("@User", string.IsNullOrEmpty(log.User) ? "" : log.User, DbType.String);
+                parameters.Add("@Machine", log.Machine, DbType.String);
+
+                parameters.Add("@RequestIpAddress", log.RequestIpAddress, DbType.String);
+                parameters.Add("@RequestContentType", (string.IsNullOrEmpty(log.RequestContentType) ? "" : log.RequestContentType), DbType.String);
+                parameters.Add("@RequestUri", log.RequestUri, DbType.String);
+                parameters.Add("@RequestMethod", log.RequestMethod, DbType.String);
+                parameters.Add("@RequestRouteTemplate", "", DbType.String);
+                parameters.Add("@RequestRouteData", "", DbType.String, size: 36);
+                parameters.Add("@RequestHeaders", log.RequestHeaders, DbType.String);
+                parameters.Add("@RequestTimestamp", log.RequestTimestamp, DbType.DateTime);
+
+                parameters.Add("@ResponseContentType", log.ResponseContentType, DbType.String);
+                parameters.Add("@ResponseStatusCode", log.ResponseStatusCode, DbType.Int32);
+                parameters.Add("@ResponseHeaders", log.ResponseHeaders, DbType.String);
+                parameters.Add("@ResponseTimestamp", log.ResponseTimestamp, DbType.DateTime);
+
+                parameters.Add("@IsOutData", log.IsOutData, DbType.Boolean);
+                parameters.Add("@ErrorMsg", log.ErrorMsg, DbType.String);
+                parameters.Add("@ErrorOn", log.ErrorOn, DbType.DateTime);
+                parameters.Add("@RequestContentBody", log.RequestContentBody, DbType.String);
+                parameters.Add("@ResponseContentBody", log.ResponseContentBody, DbType.String);
+
+                await sqlConnection.ExecuteAsync(command, parameters);
+            }
+        }
+
+        private async ValueTask<bool> GetTableExist(DateTime tableDateTime)
+        {
+            var tableName = GetTableName(tableDateTime);
+            if (_existTables.Contains(tableName))
+            {
+                return true;
+            }
+
+            string checkTableSql = $"SELECT Count(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '{tableName}'";
+
+            using var conn = await apiLogDbConnectionFactory.CreateAsync();
+            var result = await conn.ExecuteScalarAsync<int>(checkTableSql);
+
+            if (result > 0)
+            {
+                _existTables.Enqueue(tableName);
+                if (_existTables.Count > 30)
+                {
+                    _existTables.TryDequeue(out _);
+                }
+                return true;
+            }
+
+            return false;
+        }
+
+        private static string GetTableName(DateTime dateTime)
+            => $"ApiLogEntry{dateTime:yyMMdd}";
+    }
+}

+ 214 - 60
EVCB_OCPP.WEBAPI/Services/ChargePointService.cs

@@ -10,6 +10,9 @@ using System.Collections.Generic;
 using System.Data;
 using System.Linq;
 using Microsoft.Data.SqlClient;
+using EVCB_OCPP.Domain;
+using EVCB_OCPP.WEBAPI.Helpers;
+using System.Threading.Tasks;
 
 namespace EVCB_OCPP.WEBAPI.Services
 {
@@ -22,27 +25,39 @@ namespace EVCB_OCPP.WEBAPI.Services
 
     public class ChargePointService : IChargePointService
     {
-        readonly string mainConnectionString;
-        readonly string meterConnectionString;
+        //readonly string mainConnectionString;
+        //readonly string meterConnectionString;
         private readonly IServiceProvider serviceProvider;
+        private readonly SqlConnectionFactory<MainDBContext> mainDbConneciotnFactory;
+        private readonly SqlConnectionFactory<MeterValueDBContext> meterValueDbConnectionFactory;
 
-        public ChargePointService(IConfiguration configuration, IServiceProvider serviceProvider)
+        public ChargePointService(
+            IServiceProvider serviceProvider,
+            SqlConnectionFactory<MainDBContext> mainDbConneciotnFactory,
+            SqlConnectionFactory<MeterValueDBContext> meterValueDbConnectionFactory)
         {
-            mainConnectionString = configuration.GetConnectionString("MainDBContext");
-            meterConnectionString = configuration.GetConnectionString("MeterValueDBContext");
+            //mainConnectionString = configuration.GetConnectionString("MainDBContext");
+            //meterConnectionString = configuration.GetConnectionString("MeterValueDBContext");
             this.serviceProvider = serviceProvider;
+            this.mainDbConneciotnFactory = mainDbConneciotnFactory;
+            this.meterValueDbConnectionFactory = meterValueDbConnectionFactory;
         }
 
         public DateTime GetLastUpdatedTimebyMachineId(string machineId)
+        {
+            return GetLastUpdatedTimebyMachineIdAsync(machineId).Result;
+        }
+
+        public async Task<DateTime> GetLastUpdatedTimebyMachineIdAsync(string machineId)
         {
             DateTime lastUpdatedOn = DateTime.UtcNow;
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = await mainDbConneciotnFactory.CreateAsync())
             {
                 var parameters = new DynamicParameters();
 
-                parameters.Add("@MachineId", machineId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@MachineId", machineId, DbType.String, ParameterDirection.Input, 36);
                 parameters.Add("@LastUpdatedTime", lastUpdatedOn, DbType.DateTime, ParameterDirection.Output);
-                conn.Execute("GetBasicInfoLastUpdatedTimeById", parameters, commandType: System.Data.CommandType.StoredProcedure);
+                await conn.ExecuteAsync("GetBasicInfoLastUpdatedTimeById", parameters, commandType: System.Data.CommandType.StoredProcedure);
                 DateTime? time = null;
                 time = parameters.Get<DateTime?>("@LastUpdatedTime");
 
@@ -54,16 +69,46 @@ namespace EVCB_OCPP.WEBAPI.Services
 
         }
 
+        public async Task<Dictionary<string, DateTime>> GetLastUpdatedTimebyMachineIdAsync(IEnumerable<string> machineIds)
+        {
+            string cmd = """
+                SELECT Id, MAX(LastUpdatedTime) as LastUpdatedTime
+                FROM 
+                (
+                	SELECT BasicMachine.Id,
+                	CASE
+                		WHEN cs.CreatedOn > BasicMachine.CreatedOn
+                			THEN cs.CreatedOn
+                		WHEN  BasicMachine.CreatedOn > BasicMachine.OfflineOn
+                			THEN BasicMachine.CreatedOn
+                		ELSE  BasicMachine.OfflineOn
+                		END AS LastUpdatedTime 
+                	FROM
+                	(SELECT Id, OfflineOn, CreatedOn, ChargeBoxId FROM [dbo].[Machine] WHERE Id IN @MachineIds) BasicMachine
+                	LEFT JOIN [dbo].[ConnectorStatus] cs
+                	On cs.ChargeBoxId = BasicMachine.ChargeBoxId 
+                ) t
+                GROUP BY t.Id
+                """;
+
+            var parameters = new DynamicParameters();
+            parameters.Add("@MachineIds", machineIds);
+
+            using SqlConnection conn = await mainDbConneciotnFactory.CreateAsync();
+            var tmp = await conn.QueryAsync<LastUpdatedTimeDto>(cmd, parameters);
+            //return tmp.Select(x => new KeyValuePair<string, DateTime>(x.Id, x.LastUpdatedTime));
+            return tmp.ToDictionary(x => x.Id, x => x.LastUpdatedTime);
+        }
+
         public string GetMachineIdbyChargeBoxId(string chargeBoxId)
         {
             string machineId = string.Empty;
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = mainDbConneciotnFactory.Create())
             {
                 var parameters = new DynamicParameters();
-                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
                 string strSql = "Select Id from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
-                machineId = conn.Query<string>(strSql, parameters).FirstOrDefault();
-
+                machineId = conn.QueryFirstOrDefault<string>(strSql, parameters);
             }
 
             return machineId;
@@ -74,12 +119,12 @@ namespace EVCB_OCPP.WEBAPI.Services
         public string GetVersionbyChargeBoxId(string chargeBoxId)
         {
             string version = string.Empty;
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = mainDbConneciotnFactory.Create())
             {
                 var parameters = new DynamicParameters();
-                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
                 string strSql = "Select BoardVersions from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
-                version = conn.Query<string>(strSql, parameters).FirstOrDefault();
+                version = conn.QueryFirstOrDefault<string>(strSql, parameters);
             }
             return version;
         }
@@ -100,15 +145,20 @@ namespace EVCB_OCPP.WEBAPI.Services
 
 
         public EVSE GetBasicInfobyId(string machineId)
+        {
+            return GetBasicInfobyIdAsync(machineId).Result;
+        }
+
+        public async Task<EVSE> GetBasicInfobyIdAsync(string machineId)
         {
             EVSE cp = new EVSE();
             Machine _machine = new Machine();
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = await mainDbConneciotnFactory.CreateAsync())
             {
                 var parameters = new DynamicParameters();
                 parameters.Add("@Id", machineId, DbType.String, ParameterDirection.Input);
                 string strSql = "Select ChargeBoxId,ChargePointSerialNumber,ChargePointModel,RatedPower,Online,OfflineOn ,GunAmt,Latitude,Longitude,ConnectorType from [dbo].[Machine] where Id=@Id and IsDelete=0; ";
-                _machine = conn.Query<Machine>(strSql, parameters).FirstOrDefault();
+                _machine = await conn.QueryFirstOrDefaultAsync<Machine>(strSql, parameters);
             }
             if (_machine != null)
             {
@@ -120,16 +170,16 @@ namespace EVCB_OCPP.WEBAPI.Services
                 cp.LastUpdated = _machine.CreatedOn > _machine.OfflineOn ? _machine.CreatedOn : _machine.OfflineOn;
                 cp.Coordinates = new GeoLocation() { Latitude = _machine.Latitude, Longitude = _machine.Longitude };
                 cp.Connectors = new List<Connector>();
-                var _Connectors = GetConnectorStatus(_machine.ChargeBoxId);
+                var _Connectors = await GetConnectorStatusAsync(_machine.ChargeBoxId);
                 for (int i = 1; i <= _machine.GunAmt; i++)
                 {
                     var _RefConnector = _Connectors.Where(x => x.ConnectorId == i).FirstOrDefault();
                     cp.Connectors.Add(new Connector()
                     {
-                        ConnectorId = _RefConnector == null ? i : _RefConnector.ConnectorId,
-                        Status = cp.Status == Status.Offline ? Status.Offline : _RefConnector == null ? Status.Unknown : ConvertConnectorStatus(_RefConnector.Status),
+                        ConnectorId = _RefConnector is null ? i : _RefConnector.ConnectorId,
+                        Status = cp.Status == Status.Offline ? Status.Offline : _RefConnector is null ? Status.Unknown : ConvertConnectorStatus(_RefConnector.Status),
                         ConnectorType = ConvertConnectorType(int.Parse(_machine.ConnectorType.Split(',')[i - 1])),
-                        FaultMessage = ((ChargePointErrorCode)_RefConnector.ChargePointErrorCodeId).ToString() + (string.IsNullOrEmpty(_RefConnector.VendorErrorCode) ? "" : "-" + _RefConnector.VendorErrorCode)
+                        FaultMessage = _RefConnector is null ? "Connector not found" : ((ChargePointErrorCode)_RefConnector.ChargePointErrorCodeId).ToString() + (string.IsNullOrEmpty(_RefConnector.VendorErrorCode) ? "" : "-" + _RefConnector.VendorErrorCode)
 
                     });
                 }
@@ -137,24 +187,121 @@ namespace EVCB_OCPP.WEBAPI.Services
             return _machine == null ? null : cp;
         }
 
+        public async Task<Dictionary<string, EVSE>> GetBasicInfobyIdAsync(IEnumerable<string> machineIds)
+        {
+            Dictionary<string, EVSE> cps = new();
+            Dictionary<string , Machine> _machines = new();
+
+            var parameters = new DynamicParameters();
+            parameters.Add("@MachineIds", machineIds);
+            string strSql = """
+                    SELECT Id,ChargeBoxId,ChargePointSerialNumber,ChargePointModel,RatedPower,Online,OfflineOn ,GunAmt,Latitude,Longitude,ConnectorType 
+                    FROM [dbo].[Machine]
+                    WHERE Id IN @MachineIds and IsDelete=0; 
+                    """;
+
+            using (SqlConnection conn = await mainDbConneciotnFactory.CreateAsync())
+            {
+                var result = await conn.QueryAsync<Machine>(strSql, parameters);
+                _machines = result.ToDictionary(x => x.Id, x => x);
+            }
+
+            var MachineConnectors = await GetConnectorStatusAsync(machineIds);
+
+            foreach (var machineId in machineIds)
+            {
+                if (!_machines.ContainsKey(machineId))
+                {
+                    cps.Add(machineId, null);
+                    continue;
+                }
+
+                var _machine = _machines[machineId];
+                EVSE cp = new();
+
+                cp.ChargeBoxSystemID = _machine.ChargePointModel + _machine.ChargePointSerialNumber;
+                cp.ChargeBoxId = _machine.ChargeBoxId;
+                cp.NumberofConnectors = _machine.GunAmt;
+                cp.RatedPower = _machine.RatedPower;
+                cp.Status = _machine.Online ? Status.Available : Status.Offline;
+                cp.LastUpdated = _machine.CreatedOn > _machine.OfflineOn ? _machine.CreatedOn : _machine.OfflineOn;
+                cp.Coordinates = new GeoLocation() { Latitude = _machine.Latitude, Longitude = _machine.Longitude };
+                cp.Connectors = new List<Connector>();
+                //var _Connectors = await GetConnectorStatusAsync(_machine.ChargeBoxId);
+                var _Connectors = MachineConnectors[machineId];
+                for (int i = 1; i <= _machine.GunAmt; i++)
+                {
+                    var _RefConnector = _Connectors.Where(x => x.ConnectorId == i).FirstOrDefault();
+                    cp.Connectors.Add(new Connector()
+                    {
+                        ConnectorId = _RefConnector is null ? i : _RefConnector.ConnectorId,
+                        Status = cp.Status == Status.Offline ? Status.Offline : _RefConnector is null ? Status.Unknown : ConvertConnectorStatus(_RefConnector.Status),
+                        ConnectorType = ConvertConnectorType(int.Parse(_machine.ConnectorType.Split(',')[i - 1])),
+                        FaultMessage = _RefConnector is null ? "Connector not found" : ((ChargePointErrorCode)_RefConnector.ChargePointErrorCodeId).ToString() + (string.IsNullOrEmpty(_RefConnector.VendorErrorCode) ? "" : "-" + _RefConnector.VendorErrorCode)
+
+                    });
+                }
 
+                cps.Add(_machine.Id, cp);
+            }
+
+            return cps;
+        }
 
 
         public List<ConnectorStatus> GetConnectorStatus(string chargeBoxId)
+        {
+            return GetConnectorStatusAsync(chargeBoxId).Result;
+        }
+
+        public async Task<List<ConnectorStatus>> GetConnectorStatusAsync(string chargeBoxId)
         {
 
             List<ConnectorStatus> _Connectors = new List<ConnectorStatus>();
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = await mainDbConneciotnFactory.CreateAsync())
             {
                 var parameters = new DynamicParameters();
-                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
                 string strSql = "Select ConnectorId,Status,ChargePointErrorCodeId,VendorErrorCode from [dbo].[ConnectorStatus] where ChargeBoxId=@ChargeBoxId order by  ConnectorId; ";
-                _Connectors = conn.Query<ConnectorStatus>(strSql, parameters).SkipWhile(x => x.ConnectorId == 0).ToList();
+                _Connectors = (await conn.QueryAsync<ConnectorStatus>(strSql, parameters)).SkipWhile(x => x.ConnectorId == 0).ToList();
             }
 
+            return _Connectors;
+        }
 
+        public async Task<Dictionary<string,List<ConnectorStatus>>> GetConnectorStatusAsync(IEnumerable<string> chargeBoxIds)
+        {
+            Dictionary<string, List<ConnectorStatus>> toReturn = new();
+            IEnumerable<ConnectorStatus> _Connectors;// = new List<ConnectorStatus>();
+            var parameters = new DynamicParameters();
+            parameters.Add("@ChargeBoxIds", chargeBoxIds);
+            string strSql = """
+                SELECT ChargeBoxId,ConnectorId,Status,ChargePointErrorCodeId,VendorErrorCode 
+                FROM [dbo].[ConnectorStatus] 
+                WHERE ChargeBoxId IN @ChargeBoxIds
+                ORDER BY ConnectorId; 
+                """;
+
+            using (SqlConnection conn = await mainDbConneciotnFactory.CreateAsync())
+            {
+                _Connectors = (await conn.QueryAsync<ConnectorStatus>(strSql, parameters)).SkipWhile(x => x.ConnectorId == 0);//.ToList();
+            }
 
-            return _Connectors;
+            var tempDic = _Connectors.GroupBy(x => x.ChargeBoxId).ToDictionary(x => x.Key, x => x.ToList());
+            foreach (var chargeBoxId in chargeBoxIds)
+            {
+                if (tempDic.ContainsKey(chargeBoxId))
+                {
+                    toReturn.Add(chargeBoxId, tempDic[chargeBoxId]);
+                    continue;
+                }
+
+                toReturn.Add(chargeBoxId, new List<ConnectorStatus>());
+            }
+
+            return toReturn;
+
+            //return _Connectors;
         }
 
 
@@ -166,8 +313,8 @@ namespace EVCB_OCPP.WEBAPI.Services
             if (Exists(chargeBoxId))
             {
                 var parameters = new DynamicParameters();
-                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
-                using (SqlConnection conn = new SqlConnection(mainConnectionString))
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
+                using (SqlConnection conn = mainDbConneciotnFactory.Create())
                 {
                     string strSql = "Select GunAmt from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId  and IsDelete=0; ";
                     count = conn.ExecuteScalarAsync<int>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout).Result;
@@ -183,8 +330,8 @@ namespace EVCB_OCPP.WEBAPI.Services
 
             if (string.IsNullOrEmpty(chargeBoxId)) return exists;
             var parameters = new DynamicParameters();
-            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
+            using (SqlConnection conn = mainDbConneciotnFactory.Create())
             {
                 string strSql = "Select count(*) from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId  and IsDelete=0; ";
                 exists = conn.ExecuteScalar<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
@@ -199,12 +346,12 @@ namespace EVCB_OCPP.WEBAPI.Services
             if (string.IsNullOrEmpty(chargeBoxId)) return connectorId;
 
             var parameters = new DynamicParameters();
-            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
             parameters.Add("@TransactionId", transactionId, DbType.Int32, ParameterDirection.Input);
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = mainDbConneciotnFactory.Create())
             {
                 string strSql = "Select ConnectorId from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and Id= @TransactionId and StopTime='1991/01/01'; ";
-                connectorId = conn.Query<Int32>(strSql, parameters).FirstOrDefault();
+                connectorId = conn.QueryFirstOrDefault<Int32>(strSql, parameters);
             }
 
             return connectorId;
@@ -220,12 +367,12 @@ namespace EVCB_OCPP.WEBAPI.Services
             if (string.IsNullOrEmpty(chargeBoxId)) return exists;
 
             var parameters = new DynamicParameters();
-            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
             parameters.Add("@TransactionId", transactionId, DbType.Int32, ParameterDirection.Input);
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = mainDbConneciotnFactory.Create())
             {
                 string strSql = "Select Id from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and Id= @TransactionId and StopTime='1991/01/01'; ";
-                int id = conn.Query<Int32>(strSql, parameters).FirstOrDefault();
+                int id = conn.QueryFirstOrDefault<Int32>(strSql, parameters);//.FirstOrDefault();
                 exists = id > 0 ? true : false;
             }
             return exists;
@@ -244,10 +391,10 @@ namespace EVCB_OCPP.WEBAPI.Services
             if (string.IsNullOrEmpty(chargeBoxId)) return _status;
 
             var parameters = new DynamicParameters();
-            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
             parameters.Add("@ConnectorId", connectorId, DbType.Int32, ParameterDirection.Input);
 
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = mainDbConneciotnFactory.Create())
             {
                 string strSql = "Select online from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId  and IsDelete=0; ";
                 bool online = conn.ExecuteScalar<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
@@ -256,7 +403,7 @@ namespace EVCB_OCPP.WEBAPI.Services
                 {
                     string connectorStrSql = "Select Status from [dbo].[ConnectorStatus] where ChargeBoxId=@ChargeBoxId and ConnectorId=@ConnectorId; ";
 
-                    int _statusfromdb = conn.Query<Int32>(connectorStrSql, parameters).FirstOrDefault();
+                    int _statusfromdb = conn.QueryFirstOrDefault<Int32>(connectorStrSql, parameters);//.FirstOrDefault();
 
                     _status = (_statusfromdb <= 0 && connectorId == 0) ? ChargePointStatus.Available : (_statusfromdb <= 0 ? ((ChargePointStatus?)null) : ((ChargePointStatus)_statusfromdb));
 
@@ -274,10 +421,10 @@ namespace EVCB_OCPP.WEBAPI.Services
             if (string.IsNullOrEmpty(chargeBoxId)) return online;
 
             var parameters = new DynamicParameters();
-            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
 
 
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = mainDbConneciotnFactory.Create())
             {
                 string strSql = "Select online from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId  and IsDelete=0; ";
                 online = conn.ExecuteScalar<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
@@ -294,11 +441,11 @@ namespace EVCB_OCPP.WEBAPI.Services
             if (string.IsNullOrEmpty(chargeBoxId)) return existed;
 
             var parameters = new DynamicParameters();
-            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
-            parameters.Add("@CustomerId", customerId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
+            parameters.Add("@CustomerId", customerId, DbType.String, ParameterDirection.Input, 36);
 
 
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = mainDbConneciotnFactory.Create())
             {
                 string strSql = "Select Count(*) from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and CustomerId=@CustomerId  and IsDelete=0; ";
                 existed = conn.ExecuteScalar<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
@@ -318,10 +465,10 @@ namespace EVCB_OCPP.WEBAPI.Services
             try
             {
                 var parameters = new DynamicParameters();
-                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
 
 
-                using (SqlConnection conn = new SqlConnection(mainConnectionString))
+                using (SqlConnection conn = mainDbConneciotnFactory.Create())
                 {
                     string date = DateTime.UtcNow.ToString("yyMMdd");
                     string strSql = string.Empty;
@@ -332,7 +479,7 @@ namespace EVCB_OCPP.WEBAPI.Services
                     }
                     else
                     {
-                        parameters.Add(string.IsNullOrEmpty(sessionId) ? "@StartIdTag" : "@Id", string.IsNullOrEmpty(sessionId) ? idTag : sessionId, DbType.String, ParameterDirection.Input);
+                        parameters.Add(string.IsNullOrEmpty(sessionId) ? "@StartIdTag" : "@Id", string.IsNullOrEmpty(sessionId) ? idTag : sessionId, DbType.String, ParameterDirection.Input, 20);
 
                         strSql = "Select Id, ConnectorId, StartTime,Fee, StartIdTag from TransactionRecord " +
                           "where StopTime = '1991-01-01 00:00:00.000' and ChargeBoxId = @ChargeBoxId and StartTime in (select  max(StartTime) from [TransactionRecord] where  " + (string.IsNullOrEmpty(sessionId) ? "StartIdTag=@StartIdTag" : "Id=@Id") + " and StopTime = '1991-01-01 00:00:00.000' and ChargeBoxId = @ChargeBoxId group by ConnectorId )";
@@ -356,9 +503,9 @@ namespace EVCB_OCPP.WEBAPI.Services
                 for (int j = 0; j < transactionDatas.Count; j++)
                 {
                     var parameters = new DynamicParameters();
-                    parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
-                    parameters.Add("@TransactionId", transactionDatas[j].Id, DbType.String, ParameterDirection.Input);
-                    parameters.Add("@MeasurandId", requiredMeasurands[i], DbType.String, ParameterDirection.Input);
+                    parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
+                    parameters.Add("@TransactionId", transactionDatas[j].Id, DbType.Int32, ParameterDirection.Input);
+                    parameters.Add("@MeasurandId", requiredMeasurands[i], DbType.Int32, ParameterDirection.Input);
 
                     try
                     {
@@ -368,10 +515,10 @@ namespace EVCB_OCPP.WEBAPI.Services
                         while (retry < 2)
                         {
                             retry++;
-                            using (SqlConnection conn = new SqlConnection(meterConnectionString))
+                            using (SqlConnection conn = meterValueDbConnectionFactory.Create())
                             {                              
                                 string strSql = "Select Top(1) * from [dbo].[ConnectorMeterValueRecord" + date + "] where ChargeBoxId=@ChargeBoxId and TransactionId=@TransactionId and MeasurandId=@MeasurandId order by CreatedOn desc;";
-                                meterModel = conn.Query<ConnectorMeterValueModel>(strSql, parameters, null, true, EVCBConfiguration.DB_DefaultConnectionTimeout).FirstOrDefault();
+                                meterModel = conn.QueryFirstOrDefault<ConnectorMeterValueModel>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);//.FirstOrDefault();
                                 if (meterModel == null)
                                 {
                                     date = transactionDatas[j].StartTime.ToString("yyMMdd");
@@ -424,7 +571,7 @@ namespace EVCB_OCPP.WEBAPI.Services
         }
 
 
-        public List<SessionDetail> GetSessionDetail(string chargeBoxId, string sessionId, string idTag, DateTime startTime, DateTime stopTime)
+        public List<SessionDetail> GetSessionDetail(string chargeBoxId, int sessionId, string idTag, DateTime startTime, DateTime stopTime)
         {
             List<SessionDetail> detail = new List<SessionDetail>();
             List<TransactionRecordModel> transactionModel = null;
@@ -444,30 +591,30 @@ namespace EVCB_OCPP.WEBAPI.Services
                     parameters.Add("@stopTime", stopTime, DbType.DateTime, ParameterDirection.Input);
                 }
 
-                using (SqlConnection conn = new SqlConnection(mainConnectionString))
+                using (SqlConnection conn = mainDbConneciotnFactory.Create())
                 {
                     string strSql = string.Empty;
-                    if (!string.IsNullOrEmpty(sessionId) && string.IsNullOrEmpty(idTag))
+                    if (sessionId >= 0 && string.IsNullOrEmpty(idTag))
                     {
-                        parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
-                        parameters.Add("@TransactionId", sessionId, DbType.String, ParameterDirection.Input);
+                        parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
+                        parameters.Add("@TransactionId", sessionId, DbType.Int32, ParameterDirection.Input);
                         strSql = "Select Top(1) * from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and Id=@TransactionId and StopTime!='1991-01-01 00:00:00.000' " + (restrictedRange ? " and StartTime >=@startTime and  StartTime <=@stopTime" : "") + " Order by Id desc ;";
                     }
-                    else if (!string.IsNullOrEmpty(idTag) && string.IsNullOrEmpty(sessionId))
+                    else if (!string.IsNullOrEmpty(idTag) && sessionId < 0)
                     {
                         if (!string.IsNullOrEmpty(chargeBoxId))
                         {
-                            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
                         }
 
-                        parameters.Add("@StartIdTag", idTag, DbType.String, ParameterDirection.Input);
+                        parameters.Add("@StartIdTag", idTag, DbType.String, ParameterDirection.Input, 20);
                         strSql = "Select  * from [dbo].[TransactionRecord] where " + (!string.IsNullOrEmpty(chargeBoxId) ? " ChargeBoxId=@ChargeBoxId and  " : "") + "  StartIdTag=@StartIdTag   and StopTime!='1991-01-01 00:00:00.000' " + (restrictedRange ? " and StartTime >=@startTime and  StartTime <=@stopTime" : "") + " Order by Id desc  ;";
 
                     }
                     else
                     {
 
-                        parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                        parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
 
                         strSql = "Select  * from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId  and StopTime!='1991-01-01 00:00:00.000' " + (restrictedRange ? " and StartTime >=@startTime and  StartTime <=@stopTime" : "") + " Order by Id desc  ;";
 
@@ -576,4 +723,11 @@ namespace EVCB_OCPP.WEBAPI.Services
         }
 
     }
+
+    file class LastUpdatedTimeDto
+    {
+        public DateTime LastUpdatedTime { get; set;}
+
+        public string Id;
+    }
 }

+ 234 - 27
EVCB_OCPP.WEBAPI/Services/ChargingStationService.cs

@@ -9,6 +9,13 @@ using System.Configuration;
 using System.Data;
 using System.Linq;
 using Microsoft.Data.SqlClient;
+using EVCB_OCPP.WEBAPI.Helpers;
+using System.Threading.Tasks;
+using System.Diagnostics;
+using Microsoft.Extensions.Logging;
+using System.Threading;
+using static System.Collections.Specialized.BitVector32;
+using EVCB_OCPP.WEBAPI.Models.Db;
 
 namespace EVCB_OCPP.WEBAPI.Services
 {
@@ -19,42 +26,90 @@ namespace EVCB_OCPP.WEBAPI.Services
 
         List<EVSE> GetEVSEsbyStationId(int stationId, DateTime? dateFrom, DateTime? dateTo, int offset, int limit);
 
+
+        Task<List<Station>> GetStationsbyCustomerIdAsync(string customerId);
+
     }
+
     public class ChargingStationService : IChargingStationService
     {
-        string mainConnectionString;
-        string webConnectionString;
+        //string mainConnectionString;
+        //string webConnectionString;
         private readonly IServiceProvider serviceProvider;
+        private readonly SqlConnectionFactory<WebDBConetext> webConnectionFactory;
+        private readonly ILogger<ChargingStationService> logger;
 
-        public ChargingStationService(IConfiguration configuration, IServiceProvider serviceProvider)
+        public ChargingStationService(
+            SqlConnectionFactory<WebDBConetext> webConnectionFactory, 
+            ILogger<ChargingStationService> logger,
+            IServiceProvider serviceProvider)
         {
-            mainConnectionString = configuration.GetConnectionString("MainDBContext");
-            webConnectionString = configuration.GetConnectionString("WebDBContext");
+            //mainConnectionString = configuration.GetConnectionString("MainDBContext");
+            //webConnectionString = configuration.GetConnectionString("WebDBContext");
             this.serviceProvider = serviceProvider;
+            this.webConnectionFactory = webConnectionFactory;
+            this.logger = logger;
         }
 
         public List<Station> GetStationsbyCustomerId(string customerId)
         {
+            return GetStationsbyCustomerIdAsync(customerId).Result;
+        }
+
+        public async Task<List<Station>> GetStationsbyCustomerIdAsync(string customerId)
+        {
+            var watch = Stopwatch.StartNew();
+            List<long> times = new();
             List<Station> _stations = new List<Station>();
 
             var parameters = new DynamicParameters();
-            parameters.Add("@CustomerId", customerId, DbType.String, ParameterDirection.Input);
-            using (SqlConnection conn = new SqlConnection(webConnectionString))
+            parameters.Add("@CustomerId", customerId, DbType.AnsiString, ParameterDirection.Input, 36);
+            using (SqlConnection conn = await webConnectionFactory.CreateAsync())
             {
                 string strSql = "Select Id, Name ,Latitude,Longitude,Address from [dbo].[Station] where CustomerId=@CustomerId; ";
-                _stations = conn.Query<Station>(strSql, parameters).ToList();
-
+                var result = await conn.QueryAsync<Station>(strSql, parameters);
+                _stations = result is null ? new List<Station>() : result.ToList();
             }
+            times.Add(watch.ElapsedMilliseconds);
 
-            if (_stations != null)
+            //if (_stations == null)
+            //{
+            //    return _stations;
+            //}
+
+            //List<Task> ts = new List<Task>();
+            //foreach (var station in _stations)
+            //{
+            //    station.Coordinates = new GetLocation() { Latitude = station.Latitude, Longitude = station.Longitude };
+            //    ts.Add(Task.Run(async () => { station.EVSEs = await GetEVSEsbyStationIdAsync(station.Id, null, null, -1, 100000); } ));
+            //}
+            //await Task.WhenAll(ts);
+
+            //await Parallel.ForEachAsync(_stations, async (station, c) => {
+            //    station.EVSEs = await GetEVSEsbyStationIdAsync(station.Id, null, null, -1, 100000);
+            //});
+
+            var stationMachinePair = await GetStationMachinePairAsync(_stations.Select(x => x.Id));
+            times.Add(watch.ElapsedMilliseconds);
+
+            foreach (var station in _stations)
             {
-                foreach (var station in _stations)
-                {
-                    station.Coordinates = new GetLocation() { Latitude = station.Latitude, Longitude = station.Longitude };
-                    station.EVSEs = GetEVSEsbyStationId(station.Id, null, null, -1, 100000);
+                station.Coordinates = new GetLocation() { Latitude = station.Latitude, Longitude = station.Longitude };
+                //station.EVSEs = await GetEVSEsbyStationIdAsync(station.Id, null, null, -1, 100000);
+                station.EVSEs = stationMachinePair.ContainsKey(station.Id)
+                    ? await GetEVSEsBytEVSEs(stationMachinePair[station.Id], null, null, -1, 100000)
+                    : new List<EVSE> { };
+                station.EVSEs.ForEach(x => x.StationId = station.Id);
 
-                }
+                times.Add(watch.ElapsedMilliseconds);
             }
+
+            watch.Stop();
+            if (watch.ElapsedMilliseconds > 1000)
+            {
+                logger.LogWarning($"GetStationsbyCustomerIdAsync {string.Join("/", times)}");
+            }
+
             return _stations;
         }
 
@@ -63,9 +118,9 @@ namespace EVCB_OCPP.WEBAPI.Services
             bool isContains = false;
 
             var parameters = new DynamicParameters();
-            parameters.Add("@CustomerId", customerId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@CustomerId", customerId, DbType.AnsiString, ParameterDirection.Input, 36);
             parameters.Add("@Id", stationId, DbType.Int32, ParameterDirection.Input);
-            using (SqlConnection conn = new SqlConnection(webConnectionString))
+            using (SqlConnection conn = webConnectionFactory.Create())
             {
                 string strSql = "Select count(*) from [dbo].[Station] where CustomerId=@CustomerId and Id=@Id; ";
                 isContains = conn.ExecuteScalar<Int32>(strSql, parameters) > 0 ? true : false;
@@ -77,23 +132,49 @@ namespace EVCB_OCPP.WEBAPI.Services
 
         public List<EVSE> GetEVSEsbyStationId(int stationId, DateTime? dateFrom, DateTime? dateTo, int offset = -1, int limit = 1000)
         {
+            return GetEVSEsbyStationIdAsync(stationId,dateFrom,dateTo,offset,limit).Result;
+        }
+
+        public async Task<List<EVSE>> GetEVSEsbyStationIdAsync(int stationId, DateTime? dateFrom, DateTime? dateTo, int offset = -1, int limit = 1000)
+        {
+            //var watch = Stopwatch.StartNew();
+            //List<long> time = new();
+
             List<EVSE> _chargePoints = new List<EVSE>();
             var parameters = new DynamicParameters();
             parameters.Add("@StationId", stationId, DbType.Int16, ParameterDirection.Input);
-            int counter = 0;
-            int startIndex = offset == -1 ? 0 : offset;
-            limit = limit + startIndex;
             List<string> machineIds = new List<string>();
-            using (SqlConnection conn = new SqlConnection(webConnectionString))
+            using (SqlConnection conn = await webConnectionFactory.CreateAsync())
             {
                 string strSql = "Select MachineId from [dbo].[StationMachine] where StationId=@StationId; ";
-                machineIds = conn.Query<String>(strSql, parameters).ToList();
+                machineIds = (await conn.QueryAsync<String>(strSql, parameters)).ToList();
             }
+            //time.Add(watch.ElapsedMilliseconds);
+
+            var result = await GetEVSEsBytEVSEs(machineIds, dateFrom, dateTo, offset, limit);
+            result.ForEach(x => x.StationId = stationId);
+
+            return result;
+        }
+
+        public Task<List<EVSE>> GetEVSEsBytEVSEs(List<string> machineIds, DateTime? dateFrom, DateTime? dateTo, int offset = -1, int limit = 1000)
+        {
+            return GetEVSEsBytEVSEsWithDapper(machineIds, dateFrom, dateTo, offset, limit);
+            //return GetEVSEsBytEVSEsWithSP(machineIds, dateFrom, dateTo, offset, limit);
+        }
+
+        public async Task<List<EVSE>> GetEVSEsBytEVSEsWithSP(List<string> machineIds, DateTime? dateFrom, DateTime? dateTo, int offset = -1, int limit = 1000)
+        {
+            var watch = Stopwatch.StartNew();
+            List<EVSE> _chargePoints = new List<EVSE>();
             ChargePointService _CPService = serviceProvider.GetRequiredService<ChargePointService>();// new ChargePointService();
+            int startIndex = offset == -1 ? 0 : offset;
+            limit += startIndex;
+
             while (startIndex < limit && startIndex < machineIds.Count)
             {
-                var _machineUpdateOn = _CPService.GetLastUpdatedTimebyMachineId(machineIds[startIndex]);
-
+                var _machineUpdateOn = await _CPService.GetLastUpdatedTimebyMachineIdAsync(machineIds[startIndex]);
+                //time.Add(watch.ElapsedMilliseconds);
 
                 if (dateFrom.HasValue && _machineUpdateOn < dateFrom.Value.ToUniversalTime())
                 {
@@ -109,13 +190,14 @@ namespace EVCB_OCPP.WEBAPI.Services
                     continue;
                 }
 
-                var _machine = _CPService.GetBasicInfobyId(machineIds[startIndex]);
+                var _machine = await _CPService.GetBasicInfobyIdAsync(machineIds[startIndex]);
+                //time.Add(watch.ElapsedMilliseconds);
+
                 if (_machine != null)
                 {
                     _machine.LastUpdated = _machineUpdateOn;
-                    _machine.StationId = stationId;
+                    //_machine.StationId = stationId;
                     _chargePoints.Add(_machine);
-
                 }
                 else
                 {
@@ -125,11 +207,136 @@ namespace EVCB_OCPP.WEBAPI.Services
                 startIndex++;
 
             }
+
+            watch.Stop();
+            if (watch.ElapsedMilliseconds > 1000)
+            {
+                logger.LogWarning($"GetEVSEsBytEVSEs {watch.ElapsedMilliseconds}");
+            }
+
             return _chargePoints;
         }
 
+        public async Task<List<EVSE>> GetEVSEsBytEVSEsWithDapper(List<string> machineIds, DateTime? dateFrom, DateTime? dateTo, int offset = -1, int limit = 1000)
+        {
+            var watch = Stopwatch.StartNew();
+            List<long> times = new();
+
+            List<EVSE> _chargePoints = new List<EVSE>();
+            ChargePointService _CPService = serviceProvider.GetRequiredService<ChargePointService>();// new ChargePointService();
+            int quota = limit;
+            int startIndex = offset == -1 ? 0 : offset;
+            limit += startIndex;
+
+            var machineIdChunks = machineIds.Chunk(100);
+            foreach(var machineIdChunk in machineIdChunks)
+            {
+                Dictionary<string, DateTime> _machineUpdateOnPairs = await _CPService.GetLastUpdatedTimebyMachineIdAsync(machineIdChunk);
+                times.Add(watch.ElapsedMilliseconds);
 
+                _machineUpdateOnPairs = _machineUpdateOnPairs
+                    .Where(x => !dateFrom.HasValue || x.Value > dateFrom.Value.ToUniversalTime())
+                    .Where(x => !dateTo.HasValue || x.Value < dateTo.Value.ToUniversalTime())
+                    .ToDictionary(x=>x.Key,x=>x.Value);
+
+
+                var pairs = await _CPService.GetBasicInfobyIdAsync(_machineUpdateOnPairs.Select(x=> x.Key));
+                times.Add(watch.ElapsedMilliseconds);
+
+                foreach (var pair in pairs)
+                {
+                    var machine = pair.Value;
+                    machine.LastUpdated = _machineUpdateOnPairs[pair.Key];
+                    _chargePoints.Add(machine);
+
+                    if (_chargePoints.Count > quota)
+                        break;
+                }
+                
+                //foreach (var pair in _machineUpdateOnPairs)
+                //{
 
+                //    var _machine = await _CPService.GetBasicInfobyIdAsync(pair.Key);
 
+                //    if (_machine != null)
+                //    {
+                //        _machine.LastUpdated = pair.Value;
+                //        //_machine.StationId = stationId;
+                //        _chargePoints.Add(_machine);
+                //    }
+
+                //    if (_chargePoints.Count > quota)
+                //        break;
+                //}
+
+                if (_chargePoints.Count > quota)
+                    break;
+            }
+
+            watch.Stop();
+            if (watch.ElapsedMilliseconds > 1000)
+            {
+                logger.LogWarning($"GetEVSEsBytEVSEs {string.Join("/", times)}");
+            }
+
+            return _chargePoints;
+
+            while (startIndex < limit && startIndex < machineIds.Count)
+            {
+                DateTime _machineUpdateOn = await _CPService.GetLastUpdatedTimebyMachineIdAsync(machineIds[startIndex]);
+                //time.Add(watch.ElapsedMilliseconds);
+
+                if (dateFrom.HasValue && _machineUpdateOn < dateFrom.Value.ToUniversalTime())
+                {
+                    limit++;
+                    startIndex++;
+                    continue;
+                }
+
+                if (dateFrom.HasValue && dateTo.HasValue && (_machineUpdateOn < dateFrom.Value.ToUniversalTime() || _machineUpdateOn > dateTo.Value.ToUniversalTime()))
+                {
+                    limit++;
+                    startIndex++;
+                    continue;
+                }
+
+                var _machine = await _CPService.GetBasicInfobyIdAsync(machineIds[startIndex]);
+                //time.Add(watch.ElapsedMilliseconds);
+
+                if (_machine != null)
+                {
+                    _machine.LastUpdated = _machineUpdateOn;
+                    //_machine.StationId = stationId;
+                    _chargePoints.Add(_machine);
+                }
+                else
+                {
+                    limit++;
+                }
+
+                startIndex++;
+
+            }
+
+            watch.Stop();
+            if (watch.ElapsedMilliseconds > 1000)
+            {
+                logger.LogWarning($"GetEVSEsBytEVSEs {watch.ElapsedMilliseconds}");
+            }
+
+            return _chargePoints;
+        }
+
+        public async Task<Dictionary<int, List<string>>> GetStationMachinePairAsync(IEnumerable<int> stationIds)
+        {
+            var parameters = new DynamicParameters();
+            parameters.Add("@StationIds", stationIds);
+            string strSql = "SELECT StationId, MachineId FROM [dbo].[StationMachine] WHERE StationId IN @StationIds; ";
+
+            using SqlConnection conn = await webConnectionFactory.CreateAsync();
+            var result = await conn.QueryAsync<StationMachineDto>(strSql, parameters);
+
+            return result.GroupBy(x => x.StationId).ToDictionary(x => x.Key, x => x.Select(x => x.MachineId).ToList());
+        }
     }
 }

+ 17 - 5
EVCB_OCPP.WEBAPI/Services/CustomerService.cs

@@ -6,6 +6,9 @@ using System.Configuration;
 using System.Data;
 using Microsoft.Data.SqlClient;
 using System.Linq;
+using EVCB_OCPP.WEBAPI.Helpers;
+using EVCB_OCPP.Domain;
+using System.Threading.Tasks;
 
 namespace EVCB_OCPP.WEBAPI.Services
 {
@@ -13,25 +16,34 @@ namespace EVCB_OCPP.WEBAPI.Services
     {
         string GetAPIKey(Guid partnerId);
 
+        Task<string> GetAPIKeyAsync(Guid partnerId);
     }
 
     public class CustomerService : ICustomerService
     {
-        readonly string mainConnectionString;
-        public CustomerService(IConfiguration configuration)
+        private readonly SqlConnectionFactory<MainDBContext> mainDbConnectionFactory;
+
+        //readonly string mainConnectionString;
+        public CustomerService(SqlConnectionFactory<MainDBContext> mainDbConnectionFactory)
         {
-            mainConnectionString = configuration.GetConnectionString("MainDBContext");
+            //mainConnectionString = configuration.GetConnectionString("MainDBContext");
+            this.mainDbConnectionFactory = mainDbConnectionFactory;
         }
 
         public string GetAPIKey(Guid partnerId)
+        {
+            return GetAPIKeyAsync(partnerId).Result;
+        }
+
+        public async Task<string> GetAPIKeyAsync(Guid partnerId)
         {
             string key = string.Empty;
             var parameters = new DynamicParameters();
             parameters.Add("@Id", partnerId, DbType.Guid, ParameterDirection.Input);
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = await mainDbConnectionFactory.CreateAsync())
             {
                 string strSql = "Select ApiKey from [dbo].[Customer] where Id=@Id; ";
-                key = conn.ExecuteScalarAsync<string>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout).Result;
+                key = await conn.ExecuteScalarAsync<string>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
             }
             return key;
 

+ 55 - 46
EVCB_OCPP.WEBAPI/Services/Integration/ChargePoint16Service.cs

@@ -12,6 +12,8 @@ using System.Configuration;
 using System.Data;
 using Microsoft.Data.SqlClient;
 using System.Linq;
+using EVCB_OCPP.WEBAPI.Helpers;
+using EVCB_OCPP.Domain;
 
 namespace EVCB_OCPP.WEBAPI.Services.Integration
 {
@@ -23,7 +25,7 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
 
         List<TransasctionData> GetActiveSessionInfo(string chargeBoxId, List<Measurand> requiredMeasurands, string sessionId = "", string idTag = "");
 
-        List<SessionDetail> GetSessionDetail(string chargeBoxId, string sessionId, string idTag, DateTime startTime, DateTime stopTime);
+        List<SessionDetail> GetSessionDetail(string chargeBoxId, int sessionId, string idTag, DateTime startTime, DateTime stopTime);
 
         EVSE GetEVSEsbyChargeBoxId(string chargeboxid, DateTime? dateFrom, DateTime? dateTo);
 
@@ -32,21 +34,28 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
 
     public class ChargePoint16Service : IChargePointService
     {
-        readonly string mainConnectionString;
-        readonly string meterConnectionString;
+        //readonly string mainConnectionString;
+        //readonly string meterConnectionString;
         private readonly IServiceProvider serviceProvider;
+        private readonly SqlConnectionFactory<MainDBContext> mainDbConnectionFactory;
+        private readonly SqlConnectionFactory<MeterValueDBContext> meterValueDbConnectionFactory;
 
-        public ChargePoint16Service(IConfiguration configuration, IServiceProvider serviceProvider)
+        public ChargePoint16Service(
+            IServiceProvider serviceProvider,
+            SqlConnectionFactory<MainDBContext> mainDbConnectionFactory,
+            SqlConnectionFactory<MeterValueDBContext> meterValueDbConnectionFactory)
         {
-            mainConnectionString = configuration.GetConnectionString("MainDBContext");
-            meterConnectionString = configuration.GetConnectionString("MeterValueDBContext");
+            //mainConnectionString = configuration.GetConnectionString("MainDBContext");
+            //meterConnectionString = configuration.GetConnectionString("MeterValueDBContext");
             this.serviceProvider = serviceProvider;
+            this.mainDbConnectionFactory = mainDbConnectionFactory;
+            this.meterValueDbConnectionFactory = meterValueDbConnectionFactory;
         }
 
         public DateTime GetLastUpdatedTimebyMachineId(string machineId)
         {
             DateTime lastUpdatedOn = DateTime.UtcNow;
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = mainDbConnectionFactory.Create())
             {
                 var parameters = new DynamicParameters();
 
@@ -78,10 +87,10 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
         public string GetMachineIdbyChargeBoxId(string chargeBoxId)
         {
             string machineId = string.Empty;
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = mainDbConnectionFactory.Create())
             {
                 var parameters = new DynamicParameters();
-                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
                 string strSql = "Select Id from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
                 machineId = conn.Query<string>(strSql, parameters).FirstOrDefault();
 
@@ -95,10 +104,10 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
         {
             DateTime dt = new DateTime();
             string machineId = string.Empty;
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = mainDbConnectionFactory.Create())
             {
                 var parameters = new DynamicParameters();
-                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
                 string strSql = "Select HeartbeatUpdatedOn from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
                 dt = conn.Query<DateTime>(strSql, parameters).FirstOrDefault();
 
@@ -112,10 +121,10 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
         public string GetVersionbyChargeBoxId(string chargeBoxId)
         {
             string version = string.Empty;
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = mainDbConnectionFactory.Create())
             {
                 var parameters = new DynamicParameters();
-                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
                 string strSql = "Select BoardVersions from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
                 version = conn.Query<string>(strSql, parameters).FirstOrDefault();
             }
@@ -141,10 +150,10 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
         {
             EVSE cp = new EVSE();
             Machine _machine = new Machine();
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = mainDbConnectionFactory.Create())
             {
                 var parameters = new DynamicParameters();
-                parameters.Add("@Id", machineId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@Id", machineId, DbType.String, ParameterDirection.Input, 36);
                 string strSql = "Select ChargeBoxId,ChargePointSerialNumber,ChargePointModel,RatedPower,Online,OfflineOn ,GunAmt,Latitude,Longitude,ConnectorType from [dbo].[Machine] where Id=@Id and IsDelete=0; ";
                 _machine = conn.Query<Machine>(strSql, parameters).FirstOrDefault();
             }
@@ -184,10 +193,10 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
         {
 
             List<ConnectorStatus> _Connectors = new List<ConnectorStatus>();
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = mainDbConnectionFactory.Create())
             {
                 var parameters = new DynamicParameters();
-                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
                 string strSql = "Select ConnectorId,Status,ChargePointErrorCodeId,VendorErrorCode from [dbo].[ConnectorStatus] where ChargeBoxId=@ChargeBoxId order by  ConnectorId; ";
                 _Connectors = conn.Query<ConnectorStatus>(strSql, parameters).SkipWhile(x => x.ConnectorId == 0).ToList();
             }
@@ -206,8 +215,8 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             if (Exists(chargeBoxId))
             {
                 var parameters = new DynamicParameters();
-                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
-                using (SqlConnection conn = new SqlConnection(mainConnectionString))
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
+                using (SqlConnection conn = mainDbConnectionFactory.Create())
                 {
                     string strSql = "Select GunAmt from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId  and IsDelete=0; ";
                     count = conn.ExecuteScalarAsync<int>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout).Result;
@@ -223,8 +232,8 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
 
             if (string.IsNullOrEmpty(chargeBoxId)) return exists;
             var parameters = new DynamicParameters();
-            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
+            using (SqlConnection conn = mainDbConnectionFactory.Create())
             {
                 string strSql = "Select count(*) from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId  and IsDelete=0; ";
                 exists = conn.ExecuteScalar<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
@@ -239,9 +248,9 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             if (string.IsNullOrEmpty(chargeBoxId)) return connectorId;
 
             var parameters = new DynamicParameters();
-            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
             parameters.Add("@TransactionId", transactionId, DbType.Int32, ParameterDirection.Input);
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = mainDbConnectionFactory.Create())
             {
                 string strSql = "Select ConnectorId from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and Id= @TransactionId and StopTime='1991/01/01'; ";
                 connectorId = conn.Query<Int32>(strSql, parameters).FirstOrDefault();
@@ -260,9 +269,9 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             if (string.IsNullOrEmpty(chargeBoxId)) return exists;
 
             var parameters = new DynamicParameters();
-            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
             parameters.Add("@TransactionId", transactionId, DbType.Int32, ParameterDirection.Input);
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = mainDbConnectionFactory.Create())
             {
                 string strSql = "Select Id from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and Id= @TransactionId and StopTime='1991/01/01'; ";
                 int id = conn.Query<Int32>(strSql, parameters).FirstOrDefault();
@@ -284,10 +293,10 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             if (string.IsNullOrEmpty(chargeBoxId)) return _status;
 
             var parameters = new DynamicParameters();
-            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
             parameters.Add("@ConnectorId", connectorId, DbType.Int32, ParameterDirection.Input);
 
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = mainDbConnectionFactory.Create())
             {
                 string strSql = "Select online from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId  and IsDelete=0; ";
                 bool online = conn.ExecuteScalar<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
@@ -314,10 +323,10 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             if (string.IsNullOrEmpty(chargeBoxId)) return online;
 
             var parameters = new DynamicParameters();
-            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
 
 
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = mainDbConnectionFactory.Create())
             {
                 string strSql = "Select online from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId  and IsDelete=0; ";
                 online = conn.ExecuteScalar<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
@@ -334,11 +343,11 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             if (string.IsNullOrEmpty(chargeBoxId)) return existed;
 
             var parameters = new DynamicParameters();
-            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
-            parameters.Add("@CustomerId", customerId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
+            parameters.Add("@CustomerId", customerId, DbType.String, ParameterDirection.Input, 36);
 
 
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = mainDbConnectionFactory.Create())
             {
                 string strSql = "Select Count(*) from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and CustomerId=@CustomerId  and IsDelete=0; ";
                 existed = conn.ExecuteScalar<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
@@ -361,7 +370,7 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
                 parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
 
 
-                using (SqlConnection conn = new SqlConnection(mainConnectionString))
+                using (SqlConnection conn = mainDbConnectionFactory.Create())
                 {
                     string date = DateTime.UtcNow.ToString("yyMMdd");
                     string strSql = string.Empty;
@@ -396,9 +405,9 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
                 for (int j = 0; j < transactionDatas.Count; j++)
                 {
                     var parameters = new DynamicParameters();
-                    parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
-                    parameters.Add("@TransactionId", transactionDatas[j].Id, DbType.String, ParameterDirection.Input);
-                    parameters.Add("@MeasurandId", requiredMeasurands[i], DbType.String, ParameterDirection.Input);
+                    parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
+                    parameters.Add("@TransactionId", transactionDatas[j].Id, DbType.Int32, ParameterDirection.Input);
+                    parameters.Add("@MeasurandId", requiredMeasurands[i], DbType.Int32, ParameterDirection.Input);
 
 
                     try
@@ -409,7 +418,7 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
                         while (retry < 2)
                         {
                             retry++;
-                            using (SqlConnection conn = new SqlConnection(meterConnectionString))
+                            using (SqlConnection conn = meterValueDbConnectionFactory.Create())
                             {
                                 string strSql = "Select Top(1) * from [dbo].[ConnectorMeterValueRecord" + date + "] where ChargeBoxId=@ChargeBoxId and TransactionId=@TransactionId and MeasurandId=@MeasurandId order by CreatedOn desc;";
                                 meterModel = conn.Query<ConnectorMeterValueModel>(strSql, parameters, null, true, EVCBConfiguration.DB_DefaultConnectionTimeout).FirstOrDefault();
@@ -465,7 +474,7 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
         }
 
 
-        public List<SessionDetail> GetSessionDetail(string chargeBoxId, string sessionId, string idTag, DateTime startTime, DateTime stopTime)
+        public List<SessionDetail> GetSessionDetail(string chargeBoxId, int sessionId, string idTag, DateTime startTime, DateTime stopTime)
         {
             List<SessionDetail> detail = new List<SessionDetail>();
             List<TransactionRecordModel> transactionModel = null;
@@ -485,30 +494,30 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
                     parameters.Add("@stopTime", stopTime, DbType.DateTime, ParameterDirection.Input);
                 }
 
-                using (SqlConnection conn = new SqlConnection(mainConnectionString))
+                using (SqlConnection conn = mainDbConnectionFactory.Create())
                 {
                     string strSql = string.Empty;
-                    if (!string.IsNullOrEmpty(sessionId) && string.IsNullOrEmpty(idTag))
+                    if (sessionId >= 0 && string.IsNullOrEmpty(idTag))
                     {
-                        parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
-                        parameters.Add("@TransactionId", sessionId, DbType.String, ParameterDirection.Input);
+                        parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
+                        parameters.Add("@TransactionId", sessionId, DbType.Int32, ParameterDirection.Input);
                         strSql = "Select Top(1) * from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and Id=@TransactionId and StopTime!='1991-01-01 00:00:00.000' " + (restrictedRange ? " and StartTime >=@startTime and  StartTime <=@stopTime" : "") + " Order by Id desc ;";
                     }
-                    else if (!string.IsNullOrEmpty(idTag) && string.IsNullOrEmpty(sessionId))
+                    else if (!string.IsNullOrEmpty(idTag) && sessionId < 0)
                     {
                         if (!string.IsNullOrEmpty(chargeBoxId))
                         {
-                            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
                         }
 
-                        parameters.Add("@StartIdTag", idTag, DbType.String, ParameterDirection.Input);
+                        parameters.Add("@StartIdTag", idTag, DbType.String, ParameterDirection.Input, 20);
                         strSql = "Select  * from [dbo].[TransactionRecord] where " + (!string.IsNullOrEmpty(chargeBoxId) ? " ChargeBoxId=@ChargeBoxId and  " : "") + "  StartIdTag=@StartIdTag   and StopTime!='1991-01-01 00:00:00.000' " + (restrictedRange ? " and StartTime >=@startTime and  StartTime <=@stopTime" : "") + " Order by Id desc  ;";
 
                     }
                     else
                     {
 
-                        parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                        parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
 
                         strSql = "Select  * from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId  and StopTime!='1991-01-01 00:00:00.000' " + (restrictedRange ? " and StartTime >=@startTime and  StartTime <=@stopTime" : "") + " Order by Id desc  ;";
 

+ 27 - 27
EVCB_OCPP.WEBAPI/Services/Integration/ChargePoint201Service.cs

@@ -38,8 +38,8 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             if (string.IsNullOrEmpty(chargeBoxId)) return existed;
 
             var parameters = new DynamicParameters();
-            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
-            parameters.Add("@CustomerId", customerId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
+            parameters.Add("@CustomerId", customerId, DbType.String, ParameterDirection.Input, 36);
 
 
             using (SqlConnection conn = new SqlConnection(mainConnectionString))
@@ -57,7 +57,7 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
 
             if (string.IsNullOrEmpty(chargeBoxId)) return exists;
             var parameters = new DynamicParameters();
-            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
             using (SqlConnection conn = new SqlConnection(mainConnectionString))
             {
                 string strSql = "Select count(*) from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId  and IsDelete=0; ";
@@ -77,7 +77,7 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             try
             {
                 var parameters = new DynamicParameters();
-                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
 
 
                 using (SqlConnection conn = new SqlConnection(mainConnectionString))
@@ -115,9 +115,9 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
                 for (int j = 0; j < transactionDatas.Count; j++)
                 {
                     var parameters = new DynamicParameters();
-                    parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
-                    parameters.Add("@TransactionId", transactionDatas[j].Id, DbType.String, ParameterDirection.Input);
-                    parameters.Add("@MeasurandId", requiredMeasurands[i], DbType.String, ParameterDirection.Input);
+                    parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
+                    parameters.Add("@TransactionId", transactionDatas[j].Id, DbType.Int32, ParameterDirection.Input);
+                    parameters.Add("@MeasurandId", requiredMeasurands[i], DbType.Int32, ParameterDirection.Input);
 
                     try
                     {
@@ -175,7 +175,7 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             using (SqlConnection conn = new SqlConnection(mainConnectionString))
             {
                 var parameters = new DynamicParameters();
-                parameters.Add("@Id", machineId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@Id", machineId, DbType.String, ParameterDirection.Input, 36);
                 string strSql = "Select ChargeBoxId,ChargePointSerialNumber,ModelName,RatedPower,Online,OfflineOn ,GunAmt,Latitude,Longitude,ConnectorType from [dbo].[Machine] where Id=@Id and IsDelete=0; ";
                 _machine = conn.Query<Machine>(strSql, parameters).FirstOrDefault();
             }
@@ -211,7 +211,7 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             if (string.IsNullOrEmpty(chargeBoxId)) return _status;
 
             var parameters = new DynamicParameters();
-            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
             parameters.Add("@ConnectorId", connectorId, DbType.Int32, ParameterDirection.Input);
 
             using (SqlConnection conn = new SqlConnection(mainConnectionString))
@@ -240,7 +240,7 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             using (SqlConnection conn = new SqlConnection(mainConnectionString))
             {
                 var parameters = new DynamicParameters();
-                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
                 string strSql = "Select ConnectorId,Status,ChargingState from [dbo].[ConnectorStatus] where ChargeBoxId=@ChargeBoxId order by  ConnectorId; ";
                 _Connectors = conn.Query<ConnectorStatus>(strSql, parameters).SkipWhile(x => x.ConnectorId == 0).ToList();
             }
@@ -257,11 +257,11 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             if (string.IsNullOrEmpty(chargeBoxId)) return connectorId;
 
             var parameters = new DynamicParameters();
-            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
             parameters.Add("@TransactionId", transactionId, DbType.Int32, ParameterDirection.Input);
             using (SqlConnection conn = new SqlConnection(mainConnectionString))
             {
-                string strSql = "Select ConnectorId from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and TransactionId= @TransactionId and StopTime='1991/01/01'; ";
+                string strSql = "Select ConnectorId from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and Id= @TransactionId and StopTime='1991/01/01'; ";
                 connectorId = conn.Query<Int32>(strSql, parameters).FirstOrDefault();
             }
 
@@ -287,7 +287,7 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             {
                 var parameters = new DynamicParameters();
 
-                parameters.Add("@MachineId", machineId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@MachineId", machineId, DbType.String, ParameterDirection.Input, 36);
                 parameters.Add("@LastUpdatedTime", lastUpdatedOn, DbType.DateTime, ParameterDirection.Output);
                 conn.Execute("GetBasicInfoLastUpdatedTimeById", parameters, commandType: System.Data.CommandType.StoredProcedure);
                 DateTime? time = null;
@@ -312,7 +312,7 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             using (SqlConnection conn = new SqlConnection(mainConnectionString))
             {
                 var parameters = new DynamicParameters();
-                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
                 string strSql = "Select Id from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
                 machineId = conn.Query<string>(strSql, parameters).FirstOrDefault();
 
@@ -329,7 +329,7 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             if (Exists(chargeBoxId))
             {
                 var parameters = new DynamicParameters();
-                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
                 using (SqlConnection conn = new SqlConnection(mainConnectionString))
                 {
                     string strSql = "Select GunAmt from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId  and IsDelete=0; ";
@@ -347,7 +347,7 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             using (SqlConnection conn = new SqlConnection(mainConnectionString))
             {
                 var parameters = new DynamicParameters();
-                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
                 string strSql = "Select HeartbeatUpdatedOn from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
                 dt = conn.Query<DateTime>(strSql, parameters).FirstOrDefault();
 
@@ -356,7 +356,7 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             return dt;
 
         }
-        public List<SessionDetail> GetSessionDetail(string chargeBoxId, string sessionId, string idTag, DateTime startTime, DateTime stopTime)
+        public List<SessionDetail> GetSessionDetail(string chargeBoxId, int sessionId, string idTag, DateTime startTime, DateTime stopTime)
         {
             List<SessionDetail> detail = new List<SessionDetail>();
             List<TransactionRecordModel> transactionModel = null;
@@ -379,27 +379,27 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
                 using (SqlConnection conn = new SqlConnection(mainConnectionString))
                 {
                     string strSql = string.Empty;
-                    if (!string.IsNullOrEmpty(sessionId) && string.IsNullOrEmpty(idTag))
+                    if (sessionId >= 0 && string.IsNullOrEmpty(idTag))
                     {
-                        parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
-                        parameters.Add("@TransactionId", sessionId, DbType.String, ParameterDirection.Input);
-                        strSql = "Select Top(1) * from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and TransactionId=@TransactionId and StopTime!='1991-01-01 00:00:00.000' " + (restrictedRange ? " and StartTime >=@startTime and  StartTime <=@stopTime" : "") + " Order by Id desc ;";
+                        parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
+                        parameters.Add("@TransactionId", sessionId, DbType.Int32, ParameterDirection.Input);
+                        strSql = "Select Top(1) * from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and Id=@TransactionId and StopTime!='1991-01-01 00:00:00.000' " + (restrictedRange ? " and StartTime >=@startTime and  StartTime <=@stopTime" : "") + " Order by Id desc ;";
                     }
-                    else if (!string.IsNullOrEmpty(idTag) && string.IsNullOrEmpty(sessionId))
+                    else if (!string.IsNullOrEmpty(idTag) && sessionId < 0)
                     {
                         if (!string.IsNullOrEmpty(chargeBoxId))
                         {
                             parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
                         }
 
-                        parameters.Add("@StartIdTag", idTag, DbType.String, ParameterDirection.Input);
+                        parameters.Add("@StartIdTag", idTag, DbType.String, ParameterDirection.Input, 20);
                         strSql = "Select  * from [dbo].[TransactionRecord] where " + (!string.IsNullOrEmpty(chargeBoxId) ? " ChargeBoxId=@ChargeBoxId and  " : "") + "  StartIdTag=@StartIdTag   and StopTime!='1991-01-01 00:00:00.000' " + (restrictedRange ? " and StartTime >=@startTime and  StartTime <=@stopTime" : "") + " Order by Id desc  ;";
 
                     }
                     else
                     {
 
-                        parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                        parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
 
                         strSql = "Select  * from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId  and StopTime!='1991-01-01 00:00:00.000' " + (restrictedRange ? " and StartTime >=@startTime and  StartTime <=@stopTime" : "") + " Order by Id desc  ;";
 
@@ -447,7 +447,7 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             using (SqlConnection conn = new SqlConnection(mainConnectionString))
             {
                 var parameters = new DynamicParameters();
-                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
                 string strSql = "Select BoardVersions from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
                 version = conn.Query<string>(strSql, parameters).FirstOrDefault();
             }
@@ -461,7 +461,7 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             if (string.IsNullOrEmpty(chargeBoxId)) return online;
 
             var parameters = new DynamicParameters();
-            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
 
 
             using (SqlConnection conn = new SqlConnection(mainConnectionString))
@@ -480,7 +480,7 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             if (string.IsNullOrEmpty(chargeBoxId)) return exists;
 
             var parameters = new DynamicParameters();
-            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
             parameters.Add("@TransactionId", transactionId, DbType.Int32, ParameterDirection.Input);
             using (SqlConnection conn = new SqlConnection(mainConnectionString))
             {

+ 23 - 14
EVCB_OCPP.WEBAPI/Services/Integration/ChargingStationService.cs

@@ -10,6 +10,8 @@ using System.Configuration;
 using System.Data;
 using Microsoft.Data.SqlClient;
 using System.Linq;
+using EVCB_OCPP.WEBAPI.Helpers;
+using EVCB_OCPP.Domain;
 
 namespace EVCB_OCPP.WEBAPI.Services.Integration
 {
@@ -21,14 +23,21 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
     public class ChargingStationService
     {
         private readonly IServiceProvider serviceProvider;
-        private readonly string webConnectionString;
-        private readonly  string main16ConnectionString;
+        private readonly SqlConnectionFactory<WebDBConetext> webDbConnectionFactory;
+        private readonly SqlConnectionFactory<MainDBContext> mainDbConnectionFactory;
 
-        public ChargingStationService(IConfiguration configuration, IServiceProvider serviceProvider)
+        //private readonly string webConnectionString;
+        //private readonly  string main16ConnectionString;
+
+        public ChargingStationService(IServiceProvider serviceProvider,
+            SqlConnectionFactory<WebDBConetext> webDbConnectionFactory,
+            SqlConnectionFactory<MainDBContext> mainDbConnectionFactory)
         {
             this.serviceProvider = serviceProvider;
-            webConnectionString = configuration.GetConnectionString("WebDBContext");
-            main16ConnectionString = configuration.GetConnectionString("MainDBContext");
+            this.webDbConnectionFactory = webDbConnectionFactory;
+            this.mainDbConnectionFactory = mainDbConnectionFactory;
+            //webConnectionString = configuration.GetConnectionString("WebDBContext");
+            //main16ConnectionString = configuration.GetConnectionString("MainDBContext");
         }
 
         public List<Station> GetStationsbyCustomerId(string customerId)
@@ -36,8 +45,8 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             List<Station> _stations = new List<Station>();
 
             var parameters = new DynamicParameters();
-            parameters.Add("@CustomerId", customerId, DbType.String, ParameterDirection.Input);
-            using (SqlConnection conn = new SqlConnection(webConnectionString))
+            parameters.Add("@CustomerId", customerId, DbType.String, ParameterDirection.Input, 36);
+            using (SqlConnection conn = webDbConnectionFactory.Create())
             {
                 string strSql = "Select Id, Name ,Latitude,Longitude from [dbo].[Station] where CustomerId=@CustomerId; ";
                 _stations = conn.Query<Station>(strSql, parameters).ToList();
@@ -61,9 +70,9 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             bool isContains = false;
 
             var parameters = new DynamicParameters();
-            parameters.Add("@CustomerId", customerId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@CustomerId", customerId, DbType.String, ParameterDirection.Input, 36);
             parameters.Add("@Id", stationId, DbType.Int32, ParameterDirection.Input);
-            using (SqlConnection conn = new SqlConnection(webConnectionString))
+            using (SqlConnection conn = webDbConnectionFactory.Create())
             {
                 string strSql = "Select count(*) from [dbo].[Station] where CustomerId=@CustomerId and Id=@Id; ";
                 isContains = conn.ExecuteScalar<Int32>(strSql, parameters) > 0 ? true : false;
@@ -82,7 +91,7 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             int startIndex = offset == -1 ? 0 : offset;
             limit = limit + startIndex;
             List<string> machineIds = new List<string>();
-            using (SqlConnection conn = new SqlConnection(webConnectionString))
+            using (SqlConnection conn = webDbConnectionFactory.Create())
             {
                 string strSql = "Select MachineId from [dbo].[StationMachine] where StationId=@StationId; ";
                 machineIds = conn.Query<String>(strSql, parameters).ToList();
@@ -136,18 +145,18 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
         {
             Station result = null;
             var parameters = new DynamicParameters();
-            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
            
             string machineId = string.Empty;
-            using (SqlConnection conn = new SqlConnection(main16ConnectionString))
+            using (SqlConnection conn = mainDbConnectionFactory.Create())
             {
                 string strSql = "SELECT Machine.Id from [dbo].[Machine] " +
                 " where ChargeBoxId=@ChargeBoxId; ";
                 machineId = conn.Query<string>(strSql, parameters).FirstOrDefault();
 
             }
-            parameters.Add("@MachineId", machineId, DbType.String, ParameterDirection.Input);
-            using (SqlConnection conn = new SqlConnection(webConnectionString))
+            parameters.Add("@MachineId", machineId, DbType.String, ParameterDirection.Input, 36);
+            using (SqlConnection conn = webDbConnectionFactory.Create())
             {
                 string strSql = "SELECT * from [dbo].[Station] station where Id in( select StationId  FROM[dbo].[Machine],[dbo].[StationMachine] " +
                 " where StationMachine.MachineId= @MachineId); ";

+ 22 - 17
EVCB_OCPP.WEBAPI/Services/Integration/ServerTriggerService.cs

@@ -12,6 +12,8 @@ using System.Linq;
 using System.Net;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Data.SqlClient;
+using EVCB_OCPP.WEBAPI.Helpers;
+using EVCB_OCPP.Domain;
 
 namespace EVCB_OCPP.WEBAPI.Services.Integration
 {
@@ -90,13 +92,16 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
 
     public class ServerTriggerService : IServerTriggerService
     {
-        readonly string mainConnectionString;
-        public ServerTriggerService(IConfiguration configuration)
+        private readonly SqlConnectionFactory<MainDBContext> mainDbConnectionFactory;
+
+        //readonly string mainConnectionString;
+        public ServerTriggerService(SqlConnectionFactory<MainDBContext> mainDbConnectionFactory)
         {
             var dt = new DateTime(1991, 1, 1).AddHours(8).ToUniversalTime();
             long ticks = dt.Ticks;
+            this.mainDbConnectionFactory = mainDbConnectionFactory;
 
-            mainConnectionString = configuration.GetConnectionString("MainDBContext");
+            //mainConnectionString = configuration.GetConnectionString("MainDBContext");
         }
 
         public void AddMessage(string ChargeBoxId, string uuid, IRequest request)
@@ -111,7 +116,7 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
 
             string key = string.Empty;
             var parameters = new DynamicParameters();
-            parameters.Add("@ChargeBoxId", ChargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@ChargeBoxId", ChargeBoxId, DbType.String, ParameterDirection.Input, 50);
             parameters.Add("@RequestType", 1, DbType.Int32, ParameterDirection.Input);
             parameters.Add("@RequestContent", JsonConvert.SerializeObject(request, EVCBConfiguration.JSONSERIALIZER_FORMAT), DbType.String, ParameterDirection.Input);
             parameters.Add("@Status", 0, DbType.Int32, ParameterDirection.Input);
@@ -119,22 +124,22 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             parameters.Add("@FinishedOn", EVCBConfiguration.DefaultTime, DbType.DateTime, ParameterDirection.Input);
             parameters.Add("@EVSE_Value", string.Empty, DbType.String, ParameterDirection.Input);
             parameters.Add("@EVSE_Status", 0, DbType.Int32, ParameterDirection.Input);
-            parameters.Add("@SerialNo", uuid, DbType.String, ParameterDirection.Input);
-            parameters.Add("@Action", request.Action, DbType.String, ParameterDirection.Input);
+            parameters.Add("@SerialNo", uuid, DbType.String, ParameterDirection.Input, 36);
+            parameters.Add("@Action", request.Action, DbType.String, ParameterDirection.Input, 30);
 
-            parameters.Add("@OutAction", request.Action, DbType.String, ParameterDirection.Input);
+            parameters.Add("@OutAction", request.Action, DbType.String, ParameterDirection.Input, 30);
             parameters.Add("@OutRequest", JsonConvert.SerializeObject(request, EVCBConfiguration.JSONSERIALIZER_FORMAT), DbType.String, ParameterDirection.Input);
             parameters.Add("@InMessage", "", DbType.String, ParameterDirection.Input);
             parameters.Add("@CreatedOn", DateTime.Now.ToUniversalTime(), DbType.DateTime, ParameterDirection.Input);
-            parameters.Add("@CreatedBy", "WebAPI", DbType.String, ParameterDirection.Input);
+            parameters.Add("@CreatedBy", "WebAPI", DbType.String, ParameterDirection.Input, 36);
             parameters.Add("@ReceivedOn", EVCBConfiguration.DefaultTime, DbType.DateTime, ParameterDirection.Input);
             parameters.Add("@UpdatedOn", EVCBConfiguration.DefaultTime, DbType.DateTime, ParameterDirection.Input);
             parameters.Add("@ReportedOn", EVCBConfiguration.DefaultTime, DbType.DateTime, ParameterDirection.Input);
 
 
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = mainDbConnectionFactory.Create())
             {
-                conn.Open();
+                //conn.Open();
                 using (var transaction = conn.BeginTransaction())
                 {
                     try
@@ -186,9 +191,9 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             parameters.Add("@ReportedOn", EVCBConfiguration.DefaultTime, DbType.DateTime, ParameterDirection.Input);
 
 
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = mainDbConnectionFactory.Create())
             {
-                conn.Open();
+                //conn.Open();
                 using (var transaction = conn.BeginTransaction())
                 {
                     try
@@ -216,13 +221,13 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
             try
             {
                 var parameters = new DynamicParameters();
-                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
-                parameters.Add("@SerialNo", uuid, DbType.String, ParameterDirection.Input);
-                parameters.Add("@Action", action.ToString(), DbType.String, ParameterDirection.Input);
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
+                parameters.Add("@SerialNo", uuid, DbType.String, ParameterDirection.Input, 36);
+                parameters.Add("@Action", action.ToString(), DbType.String, ParameterDirection.Input, 30);
 
                 MachineOperation operation = new MachineOperation();
 
-                using (SqlConnection conn = new SqlConnection(mainConnectionString))
+                using (SqlConnection conn = mainDbConnectionFactory.Create())
                 {
                     string strSql = "Select Top(1) Status,EVSE_Value,EVSE_Status,Action from [dbo].[MachineOperateRecord] where ChargeBoxId=@ChargeBoxId and SerialNo=@SerialNo and Action=@Action; ";
                     operation = conn.Query<MachineOperation>(strSql, parameters, null, true, EVCBConfiguration.DB_DefaultConnectionTimeout).FirstOrDefault();
@@ -292,7 +297,7 @@ namespace EVCB_OCPP.WEBAPI.Services.Integration
 
                 MachineOperation operation = new MachineOperation();
 
-                using (SqlConnection conn = new SqlConnection(mainConnectionString))
+                using (SqlConnection conn = mainDbConnectionFactory.Create())
                 {
                     string strSql = "Select Top(1) Status,EVSE_Value,EVSE_Status,Action from [dbo].[MachineOperateRecord] where ChargeBoxId=@ChargeBoxId and SerialNo=@SerialNo and Action=@Action; ";
                     operation = conn.Query<MachineOperation>(strSql, parameters, null, true, EVCBConfiguration.DB_DefaultConnectionTimeout).FirstOrDefault();

+ 10 - 8
EVCB_OCPP.WEBAPI/Services/ServerTriggerService.cs

@@ -11,6 +11,8 @@ using System.Data;
 using System.Linq;
 using System.Net;
 using Microsoft.Data.SqlClient;
+using EVCB_OCPP.WEBAPI.Helpers;
+using EVCB_OCPP.Domain;
 
 namespace EVCB_OCPP.WEBAPI.Services
 {
@@ -89,16 +91,17 @@ namespace EVCB_OCPP.WEBAPI.Services
 
     public class ServerTriggerService : IServerTriggerService
     {
-        private readonly string mainConnectionString;
-        private readonly IConfiguration configuration;
+        private readonly SqlConnectionFactory<MainDBContext> mainDbConnectionFactory;
 
-        public ServerTriggerService(IConfiguration configuration)
+        //private readonly string mainConnectionString;
+
+        public ServerTriggerService(SqlConnectionFactory<MainDBContext> mainDbConnectionFactory)
         {
-            this.configuration = configuration;
-            mainConnectionString = configuration.GetConnectionString("MainDBContext");
+            //mainConnectionString = configuration.GetConnectionString("MainDBContext");
 
             var dt = new DateTime(1991, 1, 1).AddHours(8).ToUniversalTime();
             long ticks = dt.Ticks;
+            this.mainDbConnectionFactory = mainDbConnectionFactory;
         }
 
         public void AddMessage(string ChargeBoxId, string uuid, IRequest request)
@@ -134,9 +137,8 @@ namespace EVCB_OCPP.WEBAPI.Services
             parameters.Add("@ReportedOn", EVCBConfiguration.DefaultTime, DbType.DateTime, ParameterDirection.Input);
 
 
-            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            using (SqlConnection conn = mainDbConnectionFactory.Create())
             {
-                conn.Open();
                 using (var transaction = conn.BeginTransaction())
                 {
                     try
@@ -170,7 +172,7 @@ namespace EVCB_OCPP.WEBAPI.Services
 
                 MachineOperation operation = new MachineOperation();
 
-                using (SqlConnection conn = new SqlConnection(mainConnectionString))
+                using (SqlConnection conn = mainDbConnectionFactory.Create())
                 {
                     string strSql = "Select Top(1) Status,EVSE_Value,EVSE_Status,Action from [dbo].[MachineOperateRecord] where ChargeBoxId=@ChargeBoxId and SerialNo=@SerialNo and Action=@Action; ";
                     operation = conn.Query<MachineOperation>(strSql, parameters, null, true, EVCBConfiguration.DB_DefaultConnectionTimeout).FirstOrDefault();

+ 16 - 11
EVCB_OCPP.WEBAPI/Startup.cs

@@ -9,6 +9,7 @@ using System.Configuration;
 using System.Linq;
 using System.Threading.Tasks;
 using EVCB_OCPP.WEBAPI.Handlers;
+using EVCB_OCPP.WEBAPI.Helpers;
 using EVCB_OCPP.WEBAPI.Middleware;
 using EVCB_OCPP.WEBAPI.Services;
 using EVCB_OCPP.WEBAPI.Services.Integration;
@@ -48,18 +49,20 @@ namespace EVCB_OCPP.WEBAPI
                     options.UseMemberCasing();
                 });
 
-            services.AddScoped<Services.ServerTriggerService>();
-            services.AddScoped<Services.ChargingStationService>();
-            services.AddScoped<Services.Integration.ServerTriggerService>();
-            services.AddScoped<Services.Integration.ChargingStationService>();
-            services.AddScoped<ICustomerService,CustomerService>();
-            services.AddScoped<ChargePointService>();
-            services.AddScoped<ChargePoint16Service>();
-            services.AddScoped<ChargePoint201Service>();
+            services.AddSingleton<Services.ServerTriggerService>();
+            services.AddSingleton<Services.ChargingStationService>();
+            services.AddSingleton<Services.Integration.ServerTriggerService>();
+            services.AddSingleton<Services.Integration.ChargingStationService>();
+            services.AddSingleton<ICustomerService,CustomerService>();
+            services.AddSingleton<ChargePointService>();
+            services.AddSingleton<ChargePoint16Service>();
+            services.AddSingleton<ChargePoint201Service>();
 
-            services.AddScoped<CPOAuthentication>();
-            services.AddScoped<InernalAuthentication>();
-            services.AddScoped<InternalHttpClient>();
+            services.AddSingleton<CPOAuthentication>();
+            services.AddSingleton<InernalAuthentication>();
+            services.AddSingleton<InternalHttpClient>();
+
+            services.AddSingleton<ApiLogDbService>();
         }
 
         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@@ -75,9 +78,11 @@ namespace EVCB_OCPP.WEBAPI
                 app.UseExceptionHandler("/Home/Error");
             }
 
+            app.UseMiddleware<PerformaceMonitorMiddleware>(new PerformaceMonitorMiddlewareOptions() { Label = "Outter" });
             app.EnableRequestBodyRewind();
             app.UseMiddleware<ExceptionMiddleware>();
             app.UseMiddleware<APILogMiddleware>();
+            app.UseMiddleware<PerformaceMonitorMiddleware>(new PerformaceMonitorMiddlewareOptions() { Label = "Inter" });
 
             //app.UseStaticFiles();
             app.UseRouting();

+ 36 - 7
EVCB_OCPP.WEBAPI/appsettings.json

@@ -13,12 +13,41 @@
   "UnobtrusiveJavaScriptEnabled": true,
   "StatisticsAPI": "http://ocpp.phihong.com.tw/StatisticsReportApi/",
   "ConnectionStrings": {
-    "Main20DBContext": "data source=172.1.0.131\\DEV_OCPP_PORTAL;initial catalog=Docker_Main;;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework;TrustServerCertificate=true",
-    "MeterValue20DBContext": "data source=172.1.0.131\\DEV_OCPP_PORTAL;initial catalog=Docker_Main;;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework;TrustServerCertificate=true",
-    "ConnectionLogDBContext": "data source=172.1.0.131\\DEV_OCPP_PORTAL;initial catalog=Docker_ConnectionLog;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework;TrustServerCertificate=true",
-    "MainDBContext": "data source=172.1.0.131\\DEV_OCPP_PORTAL;initial catalog=Docker_Main;;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework;TrustServerCertificate=true",
-    "MeterValueDBContext": "data source=172.1.0.131\\DEV_OCPP_PORTAL;initial catalog=Docker_MeterValue;;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework;TrustServerCertificate=true",
-    "APILogDBContext": "data source=172.1.0.131\\DEV_OCPP_PORTAL;initial catalog=Docker_APILog;;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework;TrustServerCertificate=true",
-    "WebDBContext": "data source=172.1.0.131\\DEV_OCPP_PORTAL;initial catalog=Docker_Web;;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework;TrustServerCertificate=true"
+    "Main20DBContext": "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",
+    "MeterValue20DBContext": "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",
+    "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",
+    "APILogDBContext": "data source=172.1.0.131;initial catalog=Docker_APILog;;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"
+  },
+  "NLog": {
+    "targets": {
+      "async": true,
+      "f": {
+        "type": "File",
+        "keepFileOpen": false,
+        "fileName": "/home/logs/api/${shortdate}.log",
+        "layout": "${longdate} ${uppercase:${level}} ${message}"
+      },
+      "Console": {
+        "type": "Console",
+        "layout": "${longdate} ${uppercase:${level}} ${message}"
+      }
+    },
+    "rules": [
+      {
+        "ruleName": "FileLog",
+        "logger": "*",
+        "minLevel": "Trace",
+        "writeTo": "f"
+      },
+      {
+        "ruleName": "ConsoleLog",
+        "logger": "*",
+        "minLevel": "Trace",
+        "writeTo": "Console"
+      }
+    ]
   }
 }

+ 5 - 0
build.bat

@@ -0,0 +1,5 @@
+for /f %%i in ('git rev-parse --short HEAD') do set ssha=%%i
+docker build ./ -t 172.1.2.214:5000/api:test --label "git-commit=%ssha%"
+::docker push 172.1.2.214:5000/api:test
+docker tag 172.1.2.214:5000/api:test evdevcontainerregistry.azurecr.io/api:test
+docker push evdevcontainerregistry.azurecr.io/api:test

+ 6 - 0
entrypoint.sh

@@ -0,0 +1,6 @@
+#!/bin/bash
+set -e
+service ssh start
+#dotnet run --project ./EVCB_OCPP.WSServer/EVCB_OCPP.WSServer.csproj
+#/app/publish/EVCB_OCPP.WSServer
+dotnet EVCB_OCPP.WEBAPI.dll

+ 12 - 0
sshd_config

@@ -0,0 +1,12 @@
+Port 			2222
+ListenAddress 		0.0.0.0
+LoginGraceTime 		180
+X11Forwarding 		yes
+Ciphers aes128-cbc,3des-cbc,aes256-cbc,aes128-ctr,aes192-ctr,aes256-ctr
+MACs hmac-sha1,hmac-sha1-96
+StrictModes 		yes
+SyslogFacility 		DAEMON
+PasswordAuthentication 	yes
+PermitEmptyPasswords 	no
+PermitRootLogin 	yes
+Subsystem sftp internal-sftp