|
@@ -92,6 +92,20 @@ namespace EVCB_OCPP.WSServer
|
|
|
this.httpClient = httpClient;
|
|
|
isInDocker = !string.IsNullOrEmpty(configuration["DOTNET_RUNNING_IN_CONTAINER"]);
|
|
|
|
|
|
+ var maxBootCntConfig = configuration["MaxBootCnt"];
|
|
|
+ if (!string.IsNullOrEmpty(maxBootCntConfig) &&
|
|
|
+ int.TryParse(maxBootCntConfig, out var maxBootCntConfigInt))
|
|
|
+ {
|
|
|
+ maxBootCnt = maxBootCntConfigInt;
|
|
|
+ }
|
|
|
+ var bootReservCntConfig = configuration["BootReservCnt"];
|
|
|
+ if (!string.IsNullOrEmpty(bootReservCntConfig) &&
|
|
|
+ int.TryParse(bootReservCntConfig, out var bootReservCntConfigInt))
|
|
|
+ {
|
|
|
+ bootReservCnt = bootReservCntConfigInt;
|
|
|
+ }
|
|
|
+ bootSemaphore = new SemaphoreSlim(maxBootCnt, maxBootCnt);
|
|
|
+
|
|
|
// = configuration.GetConnectionString("WebDBContext");
|
|
|
this.profileHandler = serviceProvider.GetService<ProfileHandler>();// new ProfileHandler(configuration, serviceProvider);
|
|
|
_loadingBalanceService = new LoadingBalanceService(mainDbConnectionFactory, webDbConnectionFactory);
|
|
@@ -131,6 +145,9 @@ namespace EVCB_OCPP.WSServer
|
|
|
private DateTime _CheckLBDt = DateTime.UtcNow;
|
|
|
private DateTime _CheckDenyListDt = DateTime.UtcNow.AddDays(-1);
|
|
|
private readonly LoadingBalanceService _loadingBalanceService;// = new LoadingBalanceService();
|
|
|
+ private readonly int maxBootCnt = 10;
|
|
|
+ private readonly int bootReservCnt = 5;
|
|
|
+ private readonly SemaphoreSlim bootSemaphore = new SemaphoreSlim(20, 20);
|
|
|
private List<StationInfoDto> _StationInfo = new List<StationInfoDto>();
|
|
|
|
|
|
private readonly List<string> needConfirmActions = new List<string>()
|
|
@@ -168,7 +185,6 @@ namespace EVCB_OCPP.WSServer
|
|
|
};
|
|
|
private CancellationTokenSource _cts = new CancellationTokenSource();
|
|
|
private CancellationToken _ct;
|
|
|
- private Semaphore bootSemaphore = new Semaphore(10, 10);
|
|
|
#endregion
|
|
|
|
|
|
internal Dictionary<string, WsClientData> GetClientDic()
|
|
@@ -178,11 +194,17 @@ namespace EVCB_OCPP.WSServer
|
|
|
return toReturn;
|
|
|
}
|
|
|
|
|
|
+ internal int GetBootLockCnt()
|
|
|
+ {
|
|
|
+ return bootSemaphore.CurrentCount;
|
|
|
+ }
|
|
|
+
|
|
|
internal IReadOnlyList<Profile> Profiles => profiles.AsReadOnly();
|
|
|
internal LoadingBalanceService LoadingBalanceService => _loadingBalanceService;
|
|
|
internal ProfileHandler ProfileHandler => profileHandler;
|
|
|
|
|
|
internal readonly List<Func<WsClientData, CancellationToken, Task>> InitActions = new List<Func<WsClientData, CancellationToken, Task>>();
|
|
|
+ internal readonly List<Func<WsClientData, CancellationToken, Task>> LateInitActions = new List<Func<WsClientData, CancellationToken, Task>>();
|
|
|
|
|
|
public async Task StartAsync(CancellationToken cancellationToken)
|
|
|
{
|
|
@@ -729,16 +751,18 @@ namespace EVCB_OCPP.WSServer
|
|
|
session.ChargePointVendor = bootNotificationRequest.chargePointVendor;
|
|
|
|
|
|
if (session.BootStatus == BootStatus.Startup
|
|
|
- //&& bootSemaphore.WaitOne(0)
|
|
|
)
|
|
|
{
|
|
|
+ //session.BootStatus = BootStatus.Pending;
|
|
|
session.BootStatus = BootStatus.Initializing;
|
|
|
session.AddTask(StartInitializeEVSE(session));
|
|
|
}
|
|
|
|
|
|
- if (bootNotificationConfirmation.status == Packet.Messages.SubTypes.RegistrationStatus.Accepted)
|
|
|
+ if (bootNotificationConfirmation.status == Packet.Messages.SubTypes.RegistrationStatus.Accepted
|
|
|
+ )
|
|
|
{
|
|
|
session.IsCheckIn = true;
|
|
|
+ //session.AddTask(StartAllInitializeEVSE(session));
|
|
|
session.AddTask(StartLateInitializeEVSE(session));
|
|
|
//await confirmWaitingMessageSerevice.SendAndWaitUntilResultAsync(sendTask, session.DisconnetCancellationToken);
|
|
|
}
|
|
@@ -1015,8 +1039,28 @@ namespace EVCB_OCPP.WSServer
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private async Task StartAllInitializeEVSE(WsClientData session)
|
|
|
+ {
|
|
|
+ await bootSemaphore.WaitAsync();
|
|
|
+ try
|
|
|
+ {
|
|
|
+ await InitializeEVSE(session);
|
|
|
+ await LateInitializeEVSE(session);
|
|
|
+ }
|
|
|
+ catch (Exception e)
|
|
|
+ {
|
|
|
+ logger.LogCritical("StartAllInitializeEVSE:{errormsg}", e.Message);
|
|
|
+ logger.LogCritical("StartAllInitializeEVSE:{errorStackTrace}", e.StackTrace);
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ bootSemaphore.Release();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private async Task StartInitializeEVSE(WsClientData session)
|
|
|
{
|
|
|
+ await bootSemaphore.WaitAsync();
|
|
|
try
|
|
|
{
|
|
|
await InitializeEVSE(session);
|
|
@@ -1029,7 +1073,7 @@ namespace EVCB_OCPP.WSServer
|
|
|
finally
|
|
|
{
|
|
|
session.BootStatus = BootStatus.Pending;
|
|
|
- //bootSemaphore.Release();
|
|
|
+ bootSemaphore.Release();
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1048,15 +1092,19 @@ namespace EVCB_OCPP.WSServer
|
|
|
var displayPriceText = await webDbService.SetDefaultFee(session);
|
|
|
UpdateClientDisplayPrice(session.ChargeBoxId, displayPriceText);
|
|
|
|
|
|
- Func<string, Task<string>> sendTask;
|
|
|
- sendTask = async (string serialNo) => await messageService.SendGetEVSEConfigureRequest(session.ChargeBoxId, serialNo: serialNo);
|
|
|
- var response = await confirmWaitingMessageSerevice.SendAndWaitUntilResultAsync(sendTask, session.DisconnetCancellationToken);
|
|
|
+ Func<string , CancellationToken , Task<string>> sendTask;
|
|
|
+ sendTask = async (string serialNo, CancellationToken token) => await messageService.SendGetEVSEConfigureRequest(session.ChargeBoxId, serialNo: serialNo, token: token);
|
|
|
+ var response = await confirmWaitingMessageSerevice.SendAndWaitUntilResultAsync(sendTask, token: session.DisconnetCancellationToken);
|
|
|
+ if (response is GetConfigurationConfirmation getConfigurationConfirmation)
|
|
|
+ {
|
|
|
+ session.Data[GlobalConfig.BootData_EVSEConfig_Key] = getConfigurationConfirmation.configurationKey;
|
|
|
+ }
|
|
|
|
|
|
if (!string.IsNullOrEmpty(displayPriceText))
|
|
|
{
|
|
|
- sendTask = async (string serialNo) => await messageService.SendChangeConfigurationRequest(
|
|
|
+ sendTask = async (string serialNo, CancellationToken token) => await messageService.SendChangeConfigurationRequest(
|
|
|
session.ChargeBoxId, key: "DefaultPrice", value: displayPriceText, serialNo: serialNo);
|
|
|
- await confirmWaitingMessageSerevice.SendAndWaitUntilResultAsync(sendTask, session.DisconnetCancellationToken);
|
|
|
+ await confirmWaitingMessageSerevice.SendAndWaitResultAsync(sendTask, token: session.DisconnetCancellationToken);
|
|
|
}
|
|
|
|
|
|
if (session.CustomerId == new Guid("298918C0-6BB5-421A-88CC-4922F918E85E") || session.CustomerId == new Guid("9E6BFDCC-09FB-4DAB-A428-43FE507600A3"))
|
|
@@ -1077,14 +1125,26 @@ namespace EVCB_OCPP.WSServer
|
|
|
var initFunction = InitActions[index];
|
|
|
await initFunction(session, session.DisconnetCancellationToken);
|
|
|
}
|
|
|
+
|
|
|
+ session.Data.Remove(GlobalConfig.BootData_EVSEConfig_Key);//= getConfigurationConfirmation.configurationKey;
|
|
|
//await StationConfigService?.CheckAndUpdateEvseConfig(session, session.DisconnetCancellationToken);
|
|
|
}
|
|
|
|
|
|
private async Task StartLateInitializeEVSE(WsClientData session)
|
|
|
{
|
|
|
+ bool passed = false;
|
|
|
+ do
|
|
|
+ {
|
|
|
+ while (bootSemaphore.CurrentCount < bootReservCnt)
|
|
|
+ {
|
|
|
+ await Task.Delay(TimeSpan.FromMinutes(2), session.DisconnetCancellationToken);
|
|
|
+ }
|
|
|
+ passed = bootSemaphore.Wait(0);
|
|
|
+ } while (!passed);
|
|
|
+
|
|
|
try
|
|
|
{
|
|
|
- await Task.Delay(TimeSpan.FromMinutes(5));
|
|
|
+ //await Task.Delay(TimeSpan.FromMinutes(5));
|
|
|
await LateInitializeEVSE(session);
|
|
|
}
|
|
|
catch (Exception e)
|
|
@@ -1094,28 +1154,36 @@ namespace EVCB_OCPP.WSServer
|
|
|
}
|
|
|
finally
|
|
|
{
|
|
|
- session.BootStatus = BootStatus.Pending;
|
|
|
- //bootSemaphore.Release();
|
|
|
+ //session.BootStatus = BootStatus.Pending;
|
|
|
+ bootSemaphore.Release();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private async Task LateInitializeEVSE(WsClientData session)
|
|
|
{
|
|
|
- Func<string, Task<string>> sendTask;
|
|
|
+ Func<string, CancellationToken , Task<string>> sendTask;
|
|
|
|
|
|
- sendTask = async (string serialNo) => await messageService.SendDataTransferRequest(
|
|
|
+ sendTask = async (string serialNo, CancellationToken token) => await messageService.SendDataTransferRequest(
|
|
|
session.ChargeBoxId,
|
|
|
messageId: "ID_FirmwareVersion",
|
|
|
vendorId: "Phihong Technology",
|
|
|
data: string.Empty,
|
|
|
- serialNo: serialNo);
|
|
|
- await confirmWaitingMessageSerevice.SendAndWaitUntilResultAsync(sendTask, session.DisconnetCancellationToken);
|
|
|
+ serialNo: serialNo,
|
|
|
+ token: token);
|
|
|
+ await confirmWaitingMessageSerevice.SendAndWaitResultAsync(sendTask, token: session.DisconnetCancellationToken);
|
|
|
|
|
|
- sendTask = async (string serialNo) => await messageService.SendTriggerMessageRequest(
|
|
|
+ sendTask = async (string serialNo, CancellationToken token) => await messageService.SendTriggerMessageRequest(
|
|
|
session.ChargeBoxId,
|
|
|
messageTrigger: MessageTrigger.DiagnosticsStatusNotification,
|
|
|
- serialNo: serialNo);
|
|
|
- await confirmWaitingMessageSerevice.SendAndWaitUntilResultAsync(sendTask, session.DisconnetCancellationToken);
|
|
|
+ serialNo: serialNo,
|
|
|
+ token: token);
|
|
|
+ await confirmWaitingMessageSerevice.SendAndWaitResultAsync(sendTask, token: session.DisconnetCancellationToken);
|
|
|
+
|
|
|
+ for (var index = 0; index < LateInitActions.Count; index++)
|
|
|
+ {
|
|
|
+ var lateInitFunction = LateInitActions[index];
|
|
|
+ await lateInitFunction(session, session.DisconnetCancellationToken);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private void Send(WsClientData session, string msg, string messageType, string errorMsg = "")
|