Robert 1 жил өмнө
parent
commit
df0b7e9ba7

+ 1 - 1
EVCB_OCPP.WSServer/HostedProtalServer.cs

@@ -20,7 +20,7 @@ namespace EVCB_OCPP.WSServer
             services.AddPortalServerDatabase(configuration);
             services.AddBusinessServiceFactory();
 
-            services.AddSingleton<OcppWebsocketService>();
+            services.AddOcppWsServer();
 
             services.AddSingleton<ServerMessageService>();
             services.AddSingleton<LoadingBalanceService>();

+ 8 - 8
EVCB_OCPP.WSServer/ProtalServer.cs

@@ -382,9 +382,9 @@ namespace EVCB_OCPP.WSServer
 
                     responseBuilder.AppendWithCrCf();
                     string sb = responseBuilder.ToString();
-                    byte[] data = Encoding.UTF8.GetBytes(sb);
+                    //byte[] data = Encoding.UTF8.GetBytes(sb);
 
-                    await session.Send(data, 0, data.Length);
+                    await session.Send(sb);
                     logger.LogTrace(sb);
                     return false;
                 }
@@ -419,8 +419,8 @@ namespace EVCB_OCPP.WSServer
 
                 responseBuilder.AppendWithCrCf();
                 string sb = responseBuilder.ToString();
-                byte[] data = Encoding.UTF8.GetBytes(sb);
-                await session.Send(data, 0, data.Length);
+                //byte[] data = Encoding.UTF8.GetBytes(sb);
+                await session.Send(sb);
 
                 logger.LogInformation(sb);
                 return false;
@@ -446,9 +446,9 @@ namespace EVCB_OCPP.WSServer
 
                 responseBuilder.AppendWithCrCf();
                 string sb = responseBuilder.ToString();
-                byte[] data = Encoding.UTF8.GetBytes(sb);
+                //byte[] data = Encoding.UTF8.GetBytes(sb);
 
-                await session.Send(data, 0, data.Length);
+                await session.Send(sb);
                 logger.LogInformation(sb);
                 return false;
             }
@@ -510,9 +510,9 @@ namespace EVCB_OCPP.WSServer
 
                     responseBuilder.AppendWithCrCf();
                     string sb = responseBuilder.ToString();
-                    byte[] data = Encoding.UTF8.GetBytes(sb);
+                    //byte[] data = Encoding.UTF8.GetBytes(sb);
 
-                    await session.Send(data, 0, data.Length);
+                    await session.Send(sb);
                     logger.LogInformation(sb);
                     return false;
                 }

+ 21 - 0
EVCB_OCPP.WSServer/Service/WsService/OcppWebsocketService.cs

@@ -1,12 +1,20 @@
 using Microsoft.AspNetCore.Builder;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
 using System.Net.WebSockets;
 
 namespace EVCB_OCPP.WSServer.Service.WsService;
 
 public static class AppExtention
 {
+    public static void AddOcppWsServer(this IServiceCollection services)
+    {
+        services.AddTransient<WsClientData>();
+        services.AddSingleton<OcppWebsocketService>();
+    }
+
     public static void MapOcppWsService(this WebApplication webApplication)
     {
         webApplication.UseWebSockets(new WebSocketOptions()
@@ -32,12 +40,25 @@ public static class AppExtention
 public class OcppWebsocketService : WebsocketService<WsClientData>
 {
     public static List<string> protocals = new List<string>() { "", "ocpp1.6", "ocpp2.0.1" };
+    private readonly ILogger<OcppWebsocketService> logger;
+
+    public OcppWebsocketService(
+        IServiceProvider serviceProvider,
+        ILogger<OcppWebsocketService> logger
+        ) : base(serviceProvider)
+    {
+        this.logger = logger;
+    }
 
     internal override async ValueTask<string> AcceptWebSocketHandler(HttpContext context)
     {
+        logger.LogInformation("{function}:{Path}/{SubProtocol}", nameof(AcceptWebSocketHandler), context.Request.Path, context.WebSockets.WebSocketRequestedProtocols);
+
         var protocol = GetSupportedPortocol(context.WebSockets.WebSocketRequestedProtocols, protocals);
         if (string.IsNullOrEmpty(protocol))
         {
+            logger.LogInformation("{function}:{Path} Protocol Not Supported, Disconnecting", nameof(AcceptWebSocketHandler), context.Request.Path);
+
             using WebSocket toRejectwebSocket = await context.WebSockets.AcceptWebSocketAsync();
             await toRejectwebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, null, default);
             return string.Empty;

+ 8 - 3
EVCB_OCPP.WSServer/Service/WsService/WebsocketService.cs

@@ -1,4 +1,5 @@
 using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.DependencyInjection;
 using System.Net;
 using System.Net.WebSockets;
 
@@ -6,9 +7,13 @@ namespace EVCB_OCPP.WSServer.Service.WsService;
 
 public class WebsocketService<T> where T : WsSession
 {
-    public WebsocketService() { }
+    public WebsocketService(IServiceProvider serviceProvider)
+    {
+        this.serviceProvider = serviceProvider;
+    }
 
     public Func<T, Task<bool>> ValidateHandshake;
+    private readonly IServiceProvider serviceProvider;
 
     public event EventHandler<T> NewSessionConnected;
 
@@ -37,10 +42,10 @@ public class WebsocketService<T> where T : WsSession
 
     public async Task AddWebSocket(WebSocket webSocket, HttpContext context)
     {
-        T data = Activator.CreateInstance<T>();
+        T data = serviceProvider.GetRequiredService<T>();
+        data.Path = context?.Request?.Path;
         data.ClientWebSocket = webSocket;
         data.SessionID = context.TraceIdentifier;
-        data.Path = context?.Request?.Path;
         //data.UriScheme = context?.Request?.Scheme;
         data.AuthHeader = context?.Request?.Headers?.Authorization;
         //data.Origin = context.Request.Scheme;

+ 89 - 88
EVCB_OCPP.WSServer/Service/WsService/WsClientData.cs

@@ -1,136 +1,137 @@
 
 using EVCB_OCPP.Packet.Messages.Basic;
 using EVCB_OCPP.WSServer.Dto;
+using log4net.Core;
+using Microsoft.Extensions.Logging;
 
-namespace EVCB_OCPP.WSServer.Service.WsService
-{
-    public class WsClientData : WsSession
-    { /// <summary>
-      /// 根據unique id來儲存.取出OCPP Request
-      /// </summary>
-        public Queue queue = new Queue();
+namespace EVCB_OCPP.WSServer.Service.WsService;
 
-        public EVCB_OCPP20.Packet.Messages.Basic.Queue queue20 = new EVCB_OCPP20.Packet.Messages.Basic.Queue();
+public class WsClientData : WsSession
+{ /// <summary>
+  /// 根據unique id來儲存.取出OCPP Request
+  /// </summary>
+    public Queue queue = new Queue();
 
-        public bool? IsPending { set; get; }
-        public bool IsCheckIn { set; get; } = false;
+    public EVCB_OCPP20.Packet.Messages.Basic.Queue queue20 = new EVCB_OCPP20.Packet.Messages.Basic.Queue();
 
-        public string ChargeBoxId { set; get; }
+    public bool? IsPending { set; get; }
+    public bool IsCheckIn { set; get; } = false;
 
-        public Guid CustomerId { get; set; }
+    public string ChargeBoxId { set; get; }
 
-        public string MachineId { set; get; }
+    public Guid CustomerId { get; set; }
 
-        public bool ISOCPP20 { set; get; }
+    public string MachineId { set; get; }
 
-        public bool ResetSecurityProfile { set; get; }
+    public bool ISOCPP20 { set; get; }
 
+    public bool ResetSecurityProfile { set; get; }
 
-        public bool IsAC { set; get; } = true;
 
-        #region Billing
+    public bool IsAC { set; get; } = true;
 
-        public Dictionary<string, string> UserPrices { set; get; } = new Dictionary<string, string>();
+    #region Billing
 
-        public Dictionary<string, string> UserDisplayPrices { set; get; } = new Dictionary<string, string>();
+    public Dictionary<string, string> UserPrices { set; get; } = new Dictionary<string, string>();
 
-        public List<ChargingPrice> ChargingPrices { set; get; }
+    public Dictionary<string, string> UserDisplayPrices { set; get; } = new Dictionary<string, string>();
 
-        /// <summary>
-        /// 電樁顯示費率
-        /// </summary>
-        public string DisplayPrice { set; get; }
+    public List<ChargingPrice> ChargingPrices { set; get; }
 
-        /// <summary>
-        /// 電費率 以小時計費
-        /// </summary>
-        public decimal ChargingFeebyHour { set; get; }
+    /// <summary>
+    /// 電樁顯示費率
+    /// </summary>
+    public string DisplayPrice { set; get; }
 
-        /// <summary>
-        /// 停車費率 以小時計費
-        /// </summary>
-        public decimal ParkingFee { set; get; }
+    /// <summary>
+    /// 充電費率 以小時計費
+    /// </summary>
+    public decimal ChargingFeebyHour { set; get; }
 
-        /// <summary>
-        /// 電樁是否計費
-        /// </summary>
-        public bool IsBilling { set; get; }
+    /// <summary>
+    /// 停車費率 以小時計費
+    /// </summary>
+    public decimal ParkingFee { set; get; }
 
-        /// <summary>
-        /// 收費方式 1: 以度計費 2:以小時計費
-        /// </summary>
-        public int BillingMethod { set; get; }
+    /// <summary>
+    /// 電樁是否計費
+    /// </summary>
+    public bool IsBilling { set; get; }
 
+    /// <summary>
+    /// 收費方式 1: 以度計費 2:以小時計費
+    /// </summary>
+    public int BillingMethod { set; get; }
 
-        /// <summary>
-        /// 電樁適用幣別
-        /// </summary>
-        public string Currency { get; internal set; }
 
-        #endregion
+    /// <summary>
+    /// 電樁適用幣別
+    /// </summary>
+    public string Currency { get; internal set; }
 
-        public string CustomerName { get; set; }
+    #endregion
 
-        public string StationId { set; get; }
+    public string CustomerName { get; set; }
 
-        public event EventHandler<string> m_ReceiveData;
+    public string StationId { set; get; }
 
-        private string stringBuffer = string.Empty;
+    public event EventHandler<string> m_ReceiveData;
 
+    private string stringBuffer = string.Empty;
 
-        public WsClientData()
-        {
-            ChargeBoxId = SessionID;
-            MachineId = SessionID;
-        }
 
-        internal override void HandleReceivedData(string data)
+    public WsClientData(ILogger<WsClientData> logger): base(logger)
+    {
+        ChargeBoxId = SessionID;
+        MachineId = SessionID;
+    }
+
+    internal override void HandleReceivedData(string data)
+    {
+        stringBuffer += data;
+        while (TryGetOCPPMsg(ref stringBuffer, out var msg))
         {
-            stringBuffer += data;
-            while (TryGetOCPPMsg(ref stringBuffer, out var msg))
-            {
-                m_ReceiveData?.Invoke(this, msg);
-            }
+            m_ReceiveData?.Invoke(this, msg);
         }
+    }
 
-        private bool TryGetOCPPMsg(ref string buffer, out string msg)
-        {
-            msg = string.Empty;
-            int? startIndex = null;
-            int? stopIndex = null;
-            uint cnt = 0;
+    private bool TryGetOCPPMsg(ref string buffer, out string msg)
+    {
+        msg = string.Empty;
+        int? startIndex = null;
+        int? stopIndex = null;
+        uint cnt = 0;
 
-            for (int index = 0; index < buffer.Length; index++)
+        for (int index = 0; index < buffer.Length; index++)
+        {
+            if (buffer[index] == '[')
             {
-                if (buffer[index] == '[')
+                cnt++;
+                if (startIndex == null)
                 {
-                    cnt++;
-                    if (startIndex == null)
-                    {
-                        startIndex = index;
-                    }
-                }
-
-                if (startIndex != null && buffer[index] == ']')
-                {
-                    cnt--;
+                    startIndex = index;
                 }
+            }
 
-                if (startIndex != null && cnt == 0)
-                {
-                    stopIndex = index;
-                    break;
-                }
+            if (startIndex != null && buffer[index] == ']')
+            {
+                cnt--;
             }
 
-            if (startIndex is not null && stopIndex is not null)
+            if (startIndex != null && cnt == 0)
             {
-                msg = buffer.Substring(startIndex.Value, stopIndex.Value - startIndex.Value);
-                buffer = buffer.Substring(stopIndex.Value);
-                return true;
+                stopIndex = index;
+                break;
             }
+        }
 
-            return false;
+        if (startIndex is not null && stopIndex is not null)
+        {
+            msg = buffer.Substring(startIndex.Value, stopIndex.Value - startIndex.Value);
+            buffer = buffer.Substring(stopIndex.Value);
+            return true;
         }
+
+        return false;
     }
 }

+ 134 - 116
EVCB_OCPP.WSServer/Service/WsService/WsSession.cs

@@ -1,157 +1,175 @@
 using Microsoft.AspNetCore.Http;
-using Microsoft.Extensions.Primitives;
-using System;
-using System.Collections.Generic;
-using System.Linq;
+using Microsoft.Extensions.Logging;
 using System.Net;
 using System.Net.WebSockets;
 using System.Text;
-using System.Threading.Tasks;
-using System.Timers;
-using Timer = System.Timers.Timer;
 
-namespace EVCB_OCPP.WSServer.Service.WsService
+namespace EVCB_OCPP.WSServer.Service.WsService;
+
+public class WsSession
 {
-    public class WsSession
+    public WsSession(ILogger<WsSession> logger)
     {
-        public WsSession()
-        {
-
-        }
+        this.logger = logger;
+    }
 
-        public PathString? Path { get; set; }
-        public string UriScheme { get; set; }
-        public string AuthHeader { get; set; }
-        public string SessionID { get; set; }
-        public IPEndPoint Endpoint { get; internal set; }
-        //public StringValues Origin { get; internal set; }
-        public DateTime LastActiveTime { get; set; }
+    public PathString? Path { get; set; }
+    public string UriScheme { get; set; }
+    public string AuthHeader { get; set; }
+    public string SessionID { get; set; }
+    public IPEndPoint Endpoint { get; internal set; }
+    //public StringValues Origin { get; internal set; }
+    public DateTime LastActiveTime { get; set; }
 
 
-        private WebSocket _WebSocket;
-        public WebSocket ClientWebSocket
+    private WebSocket _WebSocket;
+    public WebSocket ClientWebSocket
+    {
+        get => _WebSocket;
+        set
         {
-            get => _WebSocket;
-            set
-            {
-                Init(value);
-            }
+            Init(value);
         }
+    }
 
-        public WebSocketState State => ClientWebSocket.State;
-        public string SecWebSocketProtocol => ClientWebSocket.SubProtocol;
+    public WebSocketState State => ClientWebSocket.State;
+    public string SecWebSocketProtocol => ClientWebSocket.SubProtocol;
 
-        public SemaphoreSlim EndConnSemaphore { get; } = new SemaphoreSlim(0);
+    public SemaphoreSlim EndConnSemaphore { get; } = new SemaphoreSlim(0);
 
-        //public event OCPPClientDataEventHandler<WsSession, String> m_ReceiveData;
+    //public event OCPPClientDataEventHandler<WsSession, String> m_ReceiveData;
 
-        public event EventHandler<string> SessionClosed;
+    public event EventHandler<string> SessionClosed;
 
-        private CancellationTokenSource disconnectCancellationTokenSource = new CancellationTokenSource();
-        private Task ReceiveLoopTask;
+    private CancellationTokenSource disconnectCancellationTokenSource = new CancellationTokenSource();
+    private Task ReceiveLoopTask;
+    private readonly ILogger<WsSession> logger;
 
-        private void Init(WebSocket webSocket)
-        {
-            _WebSocket = webSocket;
-            ReceiveLoopTask = StartReceivd(webSocket, disconnectCancellationTokenSource.Token);
-        }
+    private void Init(WebSocket webSocket)
+    {
+        _WebSocket = webSocket;
+        ReceiveLoopTask = StartReceivd(webSocket, disconnectCancellationTokenSource.Token);
+    }
+
+    private async Task StartReceivd(WebSocket webSocket, CancellationToken token)
+    {
+        logger.LogInformation("{func}:{Path} Start", nameof(StartReceivd), Path);
 
-        private async Task StartReceivd(WebSocket webSocket, CancellationToken token)
+        byte[] receivdBuffer = new byte[0];
+        int bufferExpand = 1;
+        int receivedBytes = 0;
+        while (!token.IsCancellationRequested)
         {
-            string received = string.Empty;
-            while (!token.IsCancellationRequested)
+            var tempReceiveBuffer = new byte[1024 * 4];
+            WebSocketReceiveResult result = null;
+
+            try
             {
-                var buffer = new byte[1024 * 4];
-                WebSocketReceiveResult result = null;
-
-                try
-                {
-                    result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), token);
-                }
-                catch (Exception e)
-                {
-                    _ = BruteClose(e.Message);
-                    break;
-                }
-
-                if (result == null || result.CloseStatus.HasValue)
-                {
-                    //closed gracefully
-                    _ = GracefulClose(result.CloseStatus.Value);
-                    break;
-                }
-
-                received += Encoding.UTF8.GetString(buffer, 0, result.Count);
-                //m_ReceiveData?.Invoke(this, received);
-                LastActiveTime = DateTime.UtcNow;
-                if (result.EndOfMessage)
-                {
-                    HandleReceivedData(received);
-                    received = string.Empty;
-                }
+                result = await webSocket.ReceiveAsync(new ArraySegment<byte>(tempReceiveBuffer), token);
             }
-        }
-
-        internal virtual void HandleReceivedData(string data)
-        {
+            catch (Exception e)
+            {
+                _ = BruteClose(e.Message);
+                break;
+            }
+            LastActiveTime = DateTime.UtcNow;
 
-        }
+            if (result == null || result.CloseStatus.HasValue)
+            {
+                //closed gracefully
+                await GracefulClose(result.CloseStatus.Value);
+                break;
+            }
 
-        internal Task Send(string dataString)
-        {
-            var data = Encoding.UTF8.GetBytes(dataString);
-            return Send(data, 0 , data.Length);
-        }
+            receivdBuffer = new byte[1024 * 4 * bufferExpand];
+            Array.Copy(tempReceiveBuffer, 0, receivdBuffer, receivedBytes, result.Count);
+            receivedBytes += result.Count;
 
-        internal async Task Send(byte[] data, int offset, int length)
-        {
-            await ClientWebSocket.SendAsync(data, WebSocketMessageType.Text, endOfMessage: true, cancellationToken: disconnectCancellationTokenSource.Token);
-            if (ClientWebSocket.State == WebSocketState.Aborted ||
-                ClientWebSocket.State == WebSocketState.Closed)
+            if (!result.EndOfMessage)
             {
-
+                bufferExpand++;
+                continue;
             }
-        }
 
-        internal Task Close()
-        {
-            return ServerClose();
+            var received = Encoding.UTF8.GetString(receivdBuffer, 0, receivedBytes);
+            logger.LogInformation("{func}:{Path} {value}", nameof(StartReceivd), Path, received);
+
+            HandleReceivedData(received);
+
+            bufferExpand = 1;
+            receivedBytes = 0;
         }
+    }
+
+    internal virtual void HandleReceivedData(string data)
+    {
 
-        private Task ServerClose()
+    }
+
+    internal Task Send(string dataString)
+    {
+        logger.LogInformation("{func}:{Path} {value}", nameof(Send), Path, dataString);
+
+        var data = Encoding.UTF8.GetBytes(dataString);
+        return Send(data);
+    }
+
+    internal Task Close()
+    {
+        return ServerClose();
+    }
+
+    private async Task Send(byte[] data)
+    {
+        try
         {
-            SessionClosed?.Invoke(this, "ServerShutdown");
-            return InternalClose(WebSocketCloseStatus.NormalClosure, "ServerShutdown");
+            await ClientWebSocket.SendAsync(data, WebSocketMessageType.Text, endOfMessage: true, cancellationToken: disconnectCancellationTokenSource.Token);
         }
-
-        private  Task GracefulClose(WebSocketCloseStatus closeStatus)
+        catch (Exception e)
         {
-            SessionClosed?.Invoke(this, closeStatus.ToString());
-            return InternalClose(closeStatus , null);
+            logger.LogInformation("{func}:{Path} exception:{msg}", nameof(Send), Path, e.Message);
         }
+    }
+
+    private Task ServerClose()
+    {
+        logger.LogInformation("{func}:{Path}", nameof(ServerClose), Path);
+
+        SessionClosed?.Invoke(this, "ServerShutdown");
+        return InternalClose(WebSocketCloseStatus.NormalClosure, "ServerShutdown");
+    }
+
+    private  Task GracefulClose(WebSocketCloseStatus closeStatus)
+    {
+        logger.LogInformation("{func}:{Path} {value}", nameof(GracefulClose), Path, closeStatus);
+
+        SessionClosed?.Invoke(this, closeStatus.ToString());
+        return InternalClose(closeStatus , null);
+    }
+
+    private Task BruteClose(string description)
+    {
+        logger.LogInformation("{func}:{Path} {value}", nameof(ServerClose), Path, description);
 
-        private Task BruteClose(string description)
+        SessionClosed?.Invoke(this, description);
+        return InternalClose(WebSocketCloseStatus.EndpointUnavailable, description);
+    }
+
+    private async Task InternalClose(WebSocketCloseStatus closeStatus, string description)
+    {
+        try
         {
-            SessionClosed?.Invoke(this, description);
-            return InternalClose(WebSocketCloseStatus.EndpointUnavailable, description);
+            await _WebSocket.CloseAsync(closeStatus, description, default);
         }
-
-        private async Task InternalClose(WebSocketCloseStatus closeStatus, string description)
+        catch
+        { 
+        }
+        finally
         {
-            try
-            {
-                await _WebSocket.CloseAsync(closeStatus, description, default);
-            }
-            catch
-            { 
-            }
-            finally
-            {
-                _WebSocket.Dispose();
-            }
-
-            disconnectCancellationTokenSource.Cancel();
-            EndConnSemaphore.Release();
+            _WebSocket.Dispose();
         }
+
+        disconnectCancellationTokenSource.Cancel();
+        EndConnSemaphore.Release();
     }
 }

+ 2 - 69
EVCB_OCPP.WSServer/appsettings.json

@@ -6,32 +6,6 @@
   "OCPP20_WSUrl": "ws://ocpp.phihong.com.tw:5004",
   "OCPP20_WSSUrl": "ws://ocpp.phihong.com.tw:5004",
   "MaintainMode": 0,
-  "superSocket": {
-    "Servers": [
-      {
-        "Name": "SuperWebSocket",
-        "serverTypeName": "SuperWebSocket",
-        "Certificate": {
-          "filePath": "localhost.pfx",
-          "password": "supersocket",
-          "storeName": "My",
-          "thumbprint": "‎3f07fb28c158843209db8f51bfe748dbe9f52399",
-          "storeLocation": "LocalMachine",
-          "clientCertificateRequired": "false",
-          "keyStorageFlags": "Exportable"
-        }
-      }
-    ]
-  },
-  "SuperSocketServerCertificate": {
-    "filePath": "localhost.pfx",
-    "password": "supersocket",
-    "storeName": "My",
-    "thumbprint": "‎3f07fb28c158843209db8f51bfe748dbe9f52399",
-    "storeLocation": "LocalMachine",
-    "clientCertificateRequired": "false",
-    "keyStorageFlags": "Exportable"
-  },
   "Logging": {
     "LogLevel": {
       "Default": "Information",
@@ -66,14 +40,8 @@
     },
     "rules": [
       {
-        "ruleName": "OCPPServer",
-        "logger": "OCPPServer.*",
-        "minLevel": "Info",
-        "writeTo": "ws"
-      },
-      {
-        "ruleName": "SuperWebSocket",
-        "logger": "SuperWebSocket.*",
+        "ruleName": "EVCB_OCPP.WSServer.Service.WsService",
+        "logger": "EVCB_OCPP.WSServer.Service.WsService.*",
         "minLevel": "Info",
         "writeTo": "ws"
       },
@@ -121,41 +89,6 @@
       }
     ]
   },
-  "ReverseProxy": {
-    "Routes": {
-      "routeApi": {
-        "ClusterId": "api",
-        "Match": {
-          "Path": "/api/{**remainder}"
-        },
-        "Transforms": [
-          { "PathRemovePrefix": "/api" }
-        ]
-      },
-      "route1": {
-        "ClusterId": "ocpp",
-        "Match": {
-          "Path": "{**catch-all}"
-        }
-      }
-    },
-    "Clusters": {
-      "ocpp": {
-        "Destinations": {
-          "destination1": {
-            "Address": "http://localhost:54089/"
-          }
-        }
-      },
-      "api": {
-        "Destinations": {
-          "destination1": {
-            "Address": "http://localhost:54088/"
-          }
-        }
-      }
-    }
-  },
   "ConnectionStrings": {
     "ConnectionLogDBContext": "data source=zerova-ev-dev.database.windows.net;initial catalog=StandardOCPP_ConnectionLog;persist security info=True;user id=azdevsoftware;password=1h52dev#az;MultipleActiveResultSets=True;App=EntityFramework;TrustServerCertificate=true;Max Pool Size=200;Connection Lifetime=0;Pooling=true;",
     "MainDBContext": "data source=zerova-ev-dev.database.windows.net;initial catalog=StandardOCPP_Main;;persist security info=True;user id=azdevsoftware;password=1h52dev#az;MultipleActiveResultSets=True;App=EntityFramework;TrustServerCertificate=true;Max Pool Size=1024;Connection Lifetime=0;Pooling=true;Min Pool Size=150;",