using EVCB_OCPP.Packet.Messages.Core; using EVCB_OCPP.WSServer.Message; using EVCB_OCPP.WSServer.Service.DbService; using EVCB_OCPP.WSServer.Service.WsService; using log4net.Core; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EVCB_OCPP.WSServer.Service; public static class StationConfigServiceExt { public static Task InitStationConfigService(this IHost host) { var server = host.Services.GetRequiredService(); var stationConfigService = host.Services.GetRequiredService(); server.InitActions.Add(stationConfigService.CheckAndUpdateEvseConfig); return host.Services.GetRequiredService().Init(); } } public class StationConfigService { public StationConfigService( ProtalServer portalServer , WebDbService webDbService , ServerMessageService messageService , ConfirmWaitingMessageSerevice confirmWaitingMessageSerevice , ILogger logger) { this.portalServer = portalServer; this.webDbService = webDbService; this.messageService = messageService; this.confirmWaitingMessageSerevice = confirmWaitingMessageSerevice; this.logger = logger; } private static string Session_Station_Key = "StationConfigService_Station"; private readonly ProtalServer portalServer; private readonly WebDbService webDbService; private readonly ServerMessageService messageService; private readonly ConfirmWaitingMessageSerevice confirmWaitingMessageSerevice; private readonly ILogger logger; internal static Dictionary> stationConfigRecord = null; public async Task Init() { stationConfigRecord = await webDbService.GetStationEvseConfigs(); } public async Task CheckAndUpdateEvseConfig(WsClientData session, CancellationToken token = default) { var chargeBoxId = session.ChargeBoxId; var stationId = await webDbService.GetEvseStation(chargeBoxId, token); if (stationId is null) { return; } int? sessionStationId = GetSessionStation(session); if (sessionStationId != stationId) { SetSessionStation(session, stationId); await UpdateEvseConfig(chargeBoxId, stationId.Value, token); } return; } public async Task CheckAndUpdateStationConfig() { await UpdateStationConfigChangedEvses(); await UpdateStationChangedEvses(); return; } private async Task UpdateStationConfigChangedEvses() { List modifiedStations = new(); var dbStationEvseConfig = await webDbService.GetStationEvseConfigs(); foreach (var stationConfig in dbStationEvseConfig) { if (!stationConfigRecord.ContainsKey(stationConfig.Key) || !CheckIsEqual(stationConfig.Value, stationConfigRecord[stationConfig.Key])) { modifiedStations.Add(stationConfig.Key); } } if (modifiedStations.Count == 0) { return; } stationConfigRecord = dbStationEvseConfig; Dictionary.ValueCollection connectedEvses = portalServer.GetClientDic().Values; foreach (WsClientData evse in connectedEvses) { int? sessionStationId = GetSessionStation(evse); if (sessionStationId is not null && modifiedStations.Contains(sessionStationId.Value)) { await UpdateEvseConfig(evse.ChargeBoxId, sessionStationId.Value); } } } private async Task UpdateStationChangedEvses() { List modifiedEvses = new(); var connectedEvses = portalServer.GetClientDic().Values.Where(x => x.IsCheckIn).ToList(); var evseStationPair = await webDbService.GetEvseStationPair(connectedEvses.Select(x => x.ChargeBoxId).ToList()); foreach (var evse in connectedEvses) { //var currentStation = await webDbService.GetEvseStation(evse.ChargeBoxId); int? currentStation = evseStationPair.ContainsKey(evse.ChargeBoxId) ? evseStationPair[evse.ChargeBoxId] : null; if (currentStation is null) { SetSessionStation(evse, null); continue; } int? sessionStationId = GetSessionStation(evse); if (sessionStationId != currentStation) { sessionStationId = currentStation; await UpdateEvseConfig(evse.ChargeBoxId, currentStation.Value); } } } private async Task UpdateEvseConfig(string chargeBoxId, int stationId, CancellationToken token = default) { GetConfigurationConfirmation confirmation = await GetEvseCurrentConfig(chargeBoxId, token); if (confirmation is null) { logger.LogWarning("{chargeBoxId} get config from evse failed", chargeBoxId); return; } if (!stationConfigRecord.ContainsKey(stationId)) { logger.LogInformation("{chargeBoxId} doesnt has station config", chargeBoxId); return; } var dbConfigs = stationConfigRecord[stationId]; Dictionary evseCurrentConfigs = new Dictionary(); evseCurrentConfigs = confirmation.configurationKey.DistinctBy(x=>x.key).ToDictionary(x => x.key, x => x.value); await ComparenUpdateConfig(chargeBoxId, evseCurrentConfigs: evseCurrentConfigs, evseDbConfigs: dbConfigs, token); } private async Task GetEvseCurrentConfig(string chargeBoxId, CancellationToken token = default) { var sendTask = async () => await messageService.SendGetEVSEConfigureRequest(chargeBoxId); var response = await confirmWaitingMessageSerevice.SendAndWaitUntilResultAsync(sendTask, token); if (response is GetConfigurationConfirmation confirmation) { return confirmation; } return null; } private async Task> GetEvseDBCurrentConfig(string chargeBoxId, CancellationToken token = default) { var receivedStaionID = await webDbService.GetEvseStation(chargeBoxId, token); if (receivedStaionID is null) { logger.LogInformation("{chargeBoxId} station not found", chargeBoxId); return null; } var staionID = receivedStaionID.Value; if (!stationConfigRecord.Keys.Contains(staionID)) { stationConfigRecord[staionID] = await webDbService.GetEvseStationConfig(staionID); } return stationConfigRecord[staionID]; //return webDbService.GetCustomerStationEvseConfig(chargeBoxId, token); } internal async Task ComparenUpdateConfig(string chargeBoxId, Dictionary evseCurrentConfigs, Dictionary evseDbConfigs, CancellationToken token = default) { foreach (var config in evseDbConfigs) { if (evseCurrentConfigs.Keys.Contains(config.Key) && evseCurrentConfigs[config.Key] == config.Value) { continue; } object response = null; var sendTask = async () => await messageService.SendChangeConfigurationRequest(chargeBoxId, config.Key, config.Value); response = await confirmWaitingMessageSerevice.SendAndWaitUntilResultAsync(sendTask, token); } } private bool CheckIsEqual(Dictionary d1, Dictionary d2) { return d1.Count == d2.Count && d1.All( (d1KV) => d2.TryGetValue(d1KV.Key, out var d2Value) && ( d1KV.Value == d2Value || d1KV.Value?.Equals(d2Value) == true) ); } private int? GetSessionStation(WsClientData session) { if (session is null || !session.Data.ContainsKey(Session_Station_Key)) { return null; } return (int?)session.Data[Session_Station_Key]; } private void SetSessionStation(WsClientData session, int? stationId) { if (session is null) { return; } session.Data[Session_Station_Key] = stationId; } }