StationConfigService.cs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. using EVCB_OCPP.Packet.Messages.Core;
  2. using EVCB_OCPP.WSServer.Message;
  3. using EVCB_OCPP.WSServer.Service.DbService;
  4. using EVCB_OCPP.WSServer.Service.WsService;
  5. using log4net.Core;
  6. using Microsoft.Extensions.DependencyInjection;
  7. using Microsoft.Extensions.Hosting;
  8. using Microsoft.Extensions.Logging;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Linq;
  12. using System.Text;
  13. using System.Threading.Tasks;
  14. namespace EVCB_OCPP.WSServer.Service;
  15. public static class StationConfigServiceExt
  16. {
  17. public static Task InitStationConfigService(this IHost host)
  18. {
  19. var server = host.Services.GetRequiredService<ProtalServer>();
  20. var stationConfigService = host.Services.GetRequiredService<StationConfigService>();
  21. server.InitActions.Add(stationConfigService.CheckAndUpdateEvseConfig);
  22. return host.Services.GetRequiredService<StationConfigService>().Init();
  23. }
  24. }
  25. public class StationConfigService
  26. {
  27. public StationConfigService(
  28. ProtalServer portalServer
  29. , WebDbService webDbService
  30. , ServerMessageService messageService
  31. , ConfirmWaitingMessageSerevice confirmWaitingMessageSerevice
  32. , ILogger<StationConfigService> logger)
  33. {
  34. this.portalServer = portalServer;
  35. this.webDbService = webDbService;
  36. this.messageService = messageService;
  37. this.confirmWaitingMessageSerevice = confirmWaitingMessageSerevice;
  38. this.logger = logger;
  39. }
  40. private static string Session_Station_Key = "StationConfigService_Station";
  41. private readonly ProtalServer portalServer;
  42. private readonly WebDbService webDbService;
  43. private readonly ServerMessageService messageService;
  44. private readonly ConfirmWaitingMessageSerevice confirmWaitingMessageSerevice;
  45. private readonly ILogger<StationConfigService> logger;
  46. internal static Dictionary<int, Dictionary<string, string>> stationConfigRecord = null;
  47. public async Task Init()
  48. {
  49. stationConfigRecord = await webDbService.GetStationEvseConfigs();
  50. }
  51. public async Task CheckAndUpdateEvseConfig(WsClientData session, CancellationToken token = default)
  52. {
  53. var chargeBoxId = session.ChargeBoxId;
  54. var stationId = await webDbService.GetEvseStation(chargeBoxId, token);
  55. if (stationId is null)
  56. {
  57. logger.LogInformation("{chargeBoxId} doesn't belongs to any station", chargeBoxId);
  58. return;
  59. }
  60. int? sessionStationId = GetSessionStation(session);
  61. if (sessionStationId != stationId)
  62. {
  63. SetSessionStation(session, stationId);
  64. await UpdateEvseConfig(chargeBoxId, stationId.Value, token);
  65. }
  66. return;
  67. }
  68. public async Task CheckAndUpdateStationConfig()
  69. {
  70. await UpdateStationConfigChangedEvses();
  71. await UpdateStationChangedEvses();
  72. return;
  73. }
  74. private async Task UpdateStationConfigChangedEvses()
  75. {
  76. List<int> modifiedStations = new();
  77. var dbStationEvseConfig = await webDbService.GetStationEvseConfigs();
  78. foreach (var stationConfig in dbStationEvseConfig)
  79. {
  80. if (!stationConfigRecord.ContainsKey(stationConfig.Key) ||
  81. !CheckIsEqual(stationConfig.Value, stationConfigRecord[stationConfig.Key]))
  82. {
  83. modifiedStations.Add(stationConfig.Key);
  84. }
  85. }
  86. if (modifiedStations.Count == 0)
  87. {
  88. return;
  89. }
  90. stationConfigRecord = dbStationEvseConfig;
  91. Dictionary<string, WsClientData>.ValueCollection connectedEvses = portalServer.GetClientDic().Values;
  92. List<Task> updateTasks = new List<Task>();
  93. foreach (WsClientData evse in connectedEvses)
  94. {
  95. int? sessionStationId = GetSessionStation(evse);
  96. if (sessionStationId is not null &&
  97. modifiedStations.Contains(sessionStationId.Value))
  98. {
  99. var tmp = UpdateEvseConfig(evse.ChargeBoxId, sessionStationId.Value);
  100. updateTasks.Add(tmp);
  101. }
  102. }
  103. await Task.WhenAll(updateTasks);
  104. }
  105. private async Task UpdateStationChangedEvses()
  106. {
  107. List<string> modifiedEvses = new();
  108. var connectedEvses = portalServer.GetClientDic().Values.Where(x => x.IsCheckIn).ToList();
  109. var evseStationPair = await webDbService.GetEvseStationPair(connectedEvses.Select(x => x.ChargeBoxId).ToList());
  110. foreach (var evse in connectedEvses)
  111. {
  112. //var currentStation = await webDbService.GetEvseStation(evse.ChargeBoxId);
  113. int? currentStation = evseStationPair.ContainsKey(evse.ChargeBoxId) ? evseStationPair[evse.ChargeBoxId] : null;
  114. if (currentStation is null)
  115. {
  116. SetSessionStation(evse, null);
  117. continue;
  118. }
  119. int? sessionStationId = GetSessionStation(evse);
  120. if (sessionStationId != currentStation)
  121. {
  122. sessionStationId = currentStation;
  123. await UpdateEvseConfig(evse.ChargeBoxId, currentStation.Value);
  124. SetSessionStation(evse, sessionStationId);
  125. }
  126. }
  127. }
  128. private async Task UpdateEvseConfig(string chargeBoxId, int stationId, CancellationToken token = default)
  129. {
  130. Dictionary<string, string> dbConfigs = null;
  131. if (!stationConfigRecord.ContainsKey(stationId))
  132. {
  133. logger.LogInformation("{chargeBoxId} doesnt has station config", chargeBoxId);
  134. return;
  135. }
  136. dbConfigs = stationConfigRecord[stationId];
  137. GetConfigurationConfirmation confirmation = await GetEvseCurrentConfig(chargeBoxId, ConfigKeys: dbConfigs.Keys.ToList(), token: token);
  138. if (confirmation is null)
  139. {
  140. logger.LogWarning("{chargeBoxId} get config from evse failed", chargeBoxId);
  141. return;
  142. }
  143. Dictionary<string, string> evseCurrentConfigs = new Dictionary<string, string>();
  144. evseCurrentConfigs = confirmation.configurationKey.DistinctBy(x=>x.key).ToDictionary(x => x.key, x => x.value);
  145. await CompareAndUpdateConfig(chargeBoxId,
  146. evseCurrentConfigs: evseCurrentConfigs,
  147. evseDbConfigs: dbConfigs,
  148. token);
  149. }
  150. private async Task<GetConfigurationConfirmation> GetEvseCurrentConfig(string chargeBoxId, List<string> ConfigKeys = default, CancellationToken token = default)
  151. {
  152. var sendTask = async (string serialNo) => await messageService.SendGetEVSEConfigureRequest(chargeBoxId, configKeys: ConfigKeys, serialNo: serialNo);
  153. var response = await confirmWaitingMessageSerevice.SendAndWaitUntilResultAsync(sendTask, token);
  154. if (response is GetConfigurationConfirmation confirmation)
  155. {
  156. return confirmation;
  157. }
  158. return null;
  159. }
  160. private async Task<Dictionary<string, string>> GetEvseDBCurrentConfig(string chargeBoxId, CancellationToken token = default)
  161. {
  162. var receivedStaionID = await webDbService.GetEvseStation(chargeBoxId, token);
  163. if (receivedStaionID is null)
  164. {
  165. logger.LogInformation("{chargeBoxId} station not found", chargeBoxId);
  166. return null;
  167. }
  168. var staionID = receivedStaionID.Value;
  169. if (!stationConfigRecord.Keys.Contains(staionID))
  170. {
  171. stationConfigRecord[staionID] = await webDbService.GetEvseStationConfig(staionID);
  172. }
  173. return stationConfigRecord[staionID];
  174. }
  175. internal async Task CompareAndUpdateConfig(string chargeBoxId,
  176. Dictionary<string, string> evseCurrentConfigs,
  177. Dictionary<string, string> evseDbConfigs,
  178. CancellationToken token = default)
  179. {
  180. foreach (var config in evseDbConfigs)
  181. {
  182. if (evseCurrentConfigs.Keys.Contains(config.Key) &&
  183. evseCurrentConfigs[config.Key] == config.Value)
  184. {
  185. continue;
  186. }
  187. object response = null;
  188. var sendTask = async (string serialNo) => await messageService.SendChangeConfigurationRequest(chargeBoxId, config.Key, config.Value, serialNo: serialNo);
  189. response = await confirmWaitingMessageSerevice.SendAndWaitUntilResultAsync(sendTask, token);
  190. }
  191. }
  192. private bool CheckIsEqual(Dictionary<string, string> d1, Dictionary<string, string> d2)
  193. {
  194. return d1.Count == d2.Count && d1.All(
  195. (d1KV) => d2.TryGetValue(d1KV.Key, out var d2Value) && (
  196. d1KV.Value == d2Value ||
  197. d1KV.Value?.Equals(d2Value) == true)
  198. );
  199. }
  200. private int? GetSessionStation(WsClientData session)
  201. {
  202. if (session is null ||
  203. !session.Data.ContainsKey(Session_Station_Key))
  204. {
  205. return null;
  206. }
  207. return (int?)session.Data[Session_Station_Key];
  208. }
  209. private void SetSessionStation(WsClientData session, int? stationId)
  210. {
  211. if (session is null)
  212. {
  213. return;
  214. }
  215. session.Data[Session_Station_Key] = stationId;
  216. }
  217. }