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 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); if (stationId is null) { return; } if (session.StationId != stationId) { session.StationId = stationId; await UpdateEvseConfig(chargeBoxId, stationId.Value); } 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; var connectedEvses = portalServer.GetClientDic().Values; foreach (var evse in connectedEvses) { if (evse.IsCheckIn && evse.StationId is not null && modifiedStations.Contains(evse.StationId.Value)) { await UpdateEvseConfig(evse.ChargeBoxId, evse.StationId.Value); } } } private async Task UpdateStationChangedEvses() { List modifiedEvses = new(); var connectedEvses = portalServer.GetClientDic().Values.ToList(); foreach (var evse in connectedEvses) { var currentStation = await webDbService.GetEvseStation(evse.ChargeBoxId); if (currentStation is null) { evse.StationId = null; continue; } if (evse.StationId != currentStation) { evse.StationId = currentStation; await UpdateEvseConfig(evse.ChargeBoxId, currentStation.Value); } } } private async Task UpdateEvseConfig(string chargeBoxId, int stationId, CancellationToken token = default) { MessageResult getEvseCurrentConfigResponse = await GetEvseCurrentConfig(chargeBoxId, token); if (!getEvseCurrentConfigResponse.Success || getEvseCurrentConfigResponse.Message is not GetConfigurationConfirmation confirmation) { 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]; await ComparenUpdateConfig(chargeBoxId, evseCurrentConfigs: confirmation.configurationKey.ToDictionary(x => x.key, x => x.value), 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); return response; } 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; } MessageResult 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) ); } }