StationConfigService.cs 9.6 KB

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