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