ProtalServer.cs 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229
  1. using Dapper;
  2. using EVCB_OCPP.Domain;
  3. using EVCB_OCPP.Packet.Features;
  4. using EVCB_OCPP.Packet.Messages;
  5. using EVCB_OCPP.Packet.Messages.Basic;
  6. using EVCB_OCPP.Packet.Messages.Core;
  7. using EVCB_OCPP.WSServer.Dto;
  8. using EVCB_OCPP.WSServer.Helper;
  9. using EVCB_OCPP.WSServer.Message;
  10. using EVCB_OCPP.WSServer.Service;
  11. using Microsoft.Extensions.Hosting;
  12. using Newtonsoft.Json;
  13. using System.Data;
  14. using System.Diagnostics;
  15. using System.Security.Authentication;
  16. using System.Xml.Linq;
  17. using NLog;
  18. using Microsoft.Extensions.Configuration;
  19. using Microsoft.EntityFrameworkCore;
  20. using Microsoft.Extensions.DependencyInjection;
  21. using Microsoft.AspNetCore.Builder;
  22. using NLog.Extensions.Logging;
  23. using Microsoft.Data.SqlClient;
  24. using System.Collections.Concurrent;
  25. using Microsoft.Extensions.Logging;
  26. using EVCB_OCPP.WSServer.Service.WsService;
  27. using System.Net.WebSockets;
  28. using EVCB_OCPP.Domain.ConnectionFactory;
  29. using EVCB_OCPP.WSServer.Service.DbService;
  30. using EVCB_OCPP.Packet.Messages.SubTypes;
  31. using System.Linq;
  32. using Azure;
  33. namespace EVCB_OCPP.WSServer
  34. {
  35. public class DestroyRequest : IRequest
  36. {
  37. public string Action { get; set; }
  38. public bool TransactionRelated()
  39. {
  40. return false;
  41. }
  42. public bool Validate()
  43. {
  44. return true;
  45. }
  46. }
  47. public class ProtalServer : IHostedService
  48. {
  49. //static private ILogger logger = NLog.LogManager.GetCurrentClassLogger();
  50. public ProtalServer(
  51. ILogger<ProtalServer> logger
  52. , IConfiguration configuration
  53. //, IDbContextFactory<MainDBContext> maindbContextFactory
  54. , IMainDbService mainDbService
  55. //, IDbContextFactory<ConnectionLogDBContext> connectionLogdbContextFactory
  56. , ISqlConnectionFactory<WebDBConetext> webDbConnectionFactory
  57. , ISqlConnectionFactory<MainDBContext> mainDbConnectionFactory
  58. , IHostEnvironment environment
  59. //, IOCPPWSServerFactory ocppWSServerFactory
  60. , IConnectionLogdbService connectionLogdbService
  61. , WebDbService webDbService
  62. , ServerMessageService serverMessageService
  63. , IServiceProvider serviceProvider
  64. , OcppWebsocketService websocketService
  65. , ConfirmWaitingMessageSerevice confirmWaitingMessageSerevice
  66. //, StationConfigService stationConfigService
  67. , OuterHttpClient httpClient
  68. , EnvCheckService envCheckService)
  69. {
  70. _ct = _cts.Token;
  71. this.logger = logger;
  72. this.configuration = configuration;
  73. //this.maindbContextFactory = maindbContextFactory;
  74. this.mainDbService = mainDbService;
  75. //this.webDbConnectionFactory = webDbConnectionFactory;
  76. //this.connectionLogdbContextFactory = connectionLogdbContextFactory;
  77. //this.ocppWSServerFactory = ocppWSServerFactory;
  78. this.connectionLogdbService = connectionLogdbService;
  79. this.webDbService = webDbService;
  80. this.messageService = serverMessageService;
  81. this.websocketService = websocketService;
  82. this.confirmWaitingMessageSerevice = confirmWaitingMessageSerevice;
  83. this.serviceProvider = serviceProvider;
  84. //this.stationConfigService = stationConfigService;
  85. this.httpClient = httpClient;
  86. isInDocker = !string.IsNullOrEmpty(configuration["DOTNET_RUNNING_IN_CONTAINER"]);
  87. // = configuration.GetConnectionString("WebDBContext");
  88. this.profileHandler = serviceProvider.GetService<ProfileHandler>();// new ProfileHandler(configuration, serviceProvider);
  89. _loadingBalanceService = new LoadingBalanceService(mainDbConnectionFactory, webDbConnectionFactory);
  90. envCheckService.CheckVariable();
  91. WarmUpLog();
  92. }
  93. #region private fields
  94. private OuterHttpClient httpClient;
  95. private DateTime lastcheckdt = DateTime.UtcNow.AddSeconds(-20);
  96. private ConcurrentDictionary<string, WsClientData> clientDic = new ConcurrentDictionary<string, WsClientData>();
  97. //private readonly Object _lockClientDic = new object();
  98. //private readonly Object _lockConfirmPacketList = new object();
  99. private readonly ILogger<ProtalServer> logger;
  100. private readonly IConfiguration configuration;
  101. private readonly IServiceProvider serviceProvider;
  102. //private readonly IDbContextFactory<MainDBContext> maindbContextFactory;
  103. private readonly IMainDbService mainDbService;
  104. //private readonly ISqlConnectionFactory<WebDBConetext> webDbConnectionFactory;
  105. //private readonly IDbContextFactory<ConnectionLogDBContext> connectionLogdbContextFactory;
  106. //private readonly IOCPPWSServerFactory ocppWSServerFactory;
  107. private readonly IConnectionLogdbService connectionLogdbService;
  108. private readonly WebDbService webDbService;
  109. private readonly ServerMessageService messageService;
  110. private readonly OcppWebsocketService websocketService;
  111. private readonly ConfirmWaitingMessageSerevice confirmWaitingMessageSerevice;
  112. //private readonly StationConfigService stationConfigService;
  113. private readonly ProfileHandler profileHandler;//= new ProfileHandler();
  114. //private readonly string webConnectionString;// = ConfigurationManager.ConnectionStrings["WebDBContext"].ConnectionString;
  115. private readonly bool isInDocker;
  116. //private List<NeedConfirmMessage> needConfirmPacketList = new List<NeedConfirmMessage>();
  117. private DateTime checkUpdateDt = DateTime.UtcNow;
  118. private DateTime _CheckFeeDt = DateTime.UtcNow;
  119. private DateTime _CheckLBDt = DateTime.UtcNow;
  120. private DateTime _CheckDenyListDt = DateTime.UtcNow.AddDays(-1);
  121. private readonly LoadingBalanceService _loadingBalanceService;// = new LoadingBalanceService();
  122. private List<StationInfoDto> _StationInfo = new List<StationInfoDto>();
  123. private readonly List<string> needConfirmActions = new List<string>()
  124. {
  125. "GetConfiguration",
  126. "ChangeConfiguration",
  127. "RemoteStartTransaction",
  128. "RemoteStopTransaction",
  129. "ChangeAvailability",
  130. "ClearCache",
  131. "DataTransfer",
  132. "Reset",
  133. "UnlockConnector",
  134. "TriggerMessage",
  135. "GetDiagnostics",
  136. "UpdateFirmware",
  137. "GetLocalListVersion",
  138. "SendLocalList",
  139. "SetChargingProfile",
  140. "ClearChargingProfile",
  141. "GetCompositeSchedule",
  142. "ReserveNow",
  143. "CancelReservation",
  144. "ExtendedTriggerMessage"
  145. };
  146. private readonly List<Profile> profiles = new List<Profile>()
  147. {
  148. new CoreProfile(),
  149. new FirmwareManagementProfile(),
  150. new ReservationProfile(),
  151. new RemoteTriggerProfile(),
  152. new SmartChargingProfile(),
  153. new LocalAuthListManagementProfile(),
  154. new SecurityProfile(),
  155. };
  156. private CancellationTokenSource _cts = new CancellationTokenSource();
  157. private CancellationToken _ct;
  158. private Semaphore bootSemaphore = new Semaphore(10, 10);
  159. #endregion
  160. internal Dictionary<string, WsClientData> GetClientDic()
  161. {
  162. Dictionary<string, WsClientData> toReturn = null;
  163. toReturn = new Dictionary<string, WsClientData>(clientDic);
  164. return toReturn;
  165. }
  166. internal IReadOnlyList<Profile> Profiles => profiles.AsReadOnly();
  167. internal LoadingBalanceService LoadingBalanceService => _loadingBalanceService;
  168. internal ProfileHandler ProfileHandler => profileHandler;
  169. internal readonly List<Func<WsClientData, CancellationToken, Task>> InitActions = new List<Func<WsClientData, CancellationToken, Task>>();
  170. public async Task StartAsync(CancellationToken cancellationToken)
  171. {
  172. GlobalConfig.DenyModelNames = await webDbService.GetDenyModelNames(cancellationToken);
  173. Start();
  174. return;
  175. }
  176. public Task StopAsync(CancellationToken cancellationToken)
  177. {
  178. return Task.CompletedTask;
  179. }
  180. internal void UpdateClientDisplayPrice(string key,string price)
  181. {
  182. clientDic[key].DisplayPrice = price;
  183. }
  184. internal void SendMsg(WsClientData session, string msg, string messageType, string errorMsg = "")
  185. {
  186. Send(session,msg,messageType,errorMsg);
  187. }
  188. internal void Start()
  189. {
  190. Console.WriteLine("Starting Server...");
  191. if (!GlobalConfig.LoadAPPConfig(configuration))
  192. {
  193. Console.WriteLine("Please check App.Config setting .");
  194. return;
  195. }
  196. StartWsService();
  197. //OpenNetwork();
  198. //RunHttpConsoleService();
  199. return;
  200. if (!isInDocker)
  201. {
  202. Task consoleReadTask = new Task(RunConsoleInteractive);
  203. consoleReadTask.Start();
  204. //RunConsoleInteractive();
  205. return;
  206. }
  207. }
  208. private void StartWsService()
  209. {
  210. websocketService.NewSessionConnected += AppServer_NewSessionConnected;
  211. }
  212. private void StopWsService()
  213. {
  214. websocketService.NewSessionConnected -= AppServer_NewSessionConnected;
  215. }
  216. private async void AppServer_NewSessionConnected(object sender, WsClientData session)
  217. {
  218. logger.LogDebug(string.Format("{0} NewSessionConnected", session.Path));
  219. try
  220. {
  221. bool isNotSupported = session.SecWebSocketProtocol.Contains("ocpp1.6") ? false : session.SecWebSocketProtocol.Contains("ocpp2.0") ? false : true;
  222. if (isNotSupported)
  223. {
  224. //logger.LogDebug(string.Format("ChargeBoxId:{0} SecWebSocketProtocol:{1} NotSupported", session.ChargeBoxId, session.SecWebSocketProtocol));
  225. WriteMachineLog(session, string.Format("SecWebSocketProtocol:{0} NotSupported", session.SecWebSocketProtocol), "Connection", "");
  226. return;
  227. }
  228. TryRemoveDuplicatedSession(session);
  229. clientDic[session.ChargeBoxId] = session;
  230. session.SessionClosed += AppServer_SessionClosed;
  231. session.m_ReceiveData += ReceivedMessageTimeLimited;
  232. // logger.LogDebug("------------New " + (session == null ? "Oops" : session.ChargeBoxId));
  233. WriteMachineLog(session, "NewSessionConnected", "Connection", "");
  234. await mainDbService.UpdateMachineConnectionType(session.ChargeBoxId, session.UriScheme.Contains("wss") ? 2 : 1);
  235. }
  236. catch (Exception ex)
  237. {
  238. logger.LogError(string.Format("NewSessionConnected Ex: {0}", ex.ToString()));
  239. }
  240. }
  241. private void AppServer_SessionClosed(object sender, string closeReason)
  242. {
  243. if (sender is not WsClientData session)
  244. {
  245. return;
  246. }
  247. //session.SessionClosed -= AppServer_SessionClosed;
  248. //session.m_ReceiveData -= ReceivedMessageTimeLimited;
  249. //WriteMachineLog(session, string.Format("CloseReason: {0}", closeReason), "Connection", "");
  250. RemoveClient(session, closeReason);
  251. }
  252. private void TryRemoveDuplicatedSession(WsClientData session)
  253. {
  254. if (clientDic.ContainsKey(session.ChargeBoxId))
  255. {
  256. var oldSession = clientDic[session.ChargeBoxId];
  257. //WriteMachineLog(oldSession, "Duplicate Logins", "Connection", "");
  258. RemoveClient(oldSession, "Duplicate Logins");
  259. }
  260. }
  261. private void RunConsoleInteractive()
  262. {
  263. while (true)
  264. {
  265. if (Console.In is null)
  266. {
  267. break;
  268. }
  269. var input = Console.ReadLine();
  270. switch (input.ToLower())
  271. {
  272. case "stop":
  273. Console.WriteLine("Command stop");
  274. Stop();
  275. break;
  276. case "gc":
  277. Console.WriteLine("Command GC");
  278. GC.Collect();
  279. break;
  280. case "lc":
  281. {
  282. Console.WriteLine("Command List Clients");
  283. Dictionary<string, WsClientData> _copyClientDic = null;
  284. _copyClientDic = new Dictionary<string, WsClientData>(clientDic);
  285. var list = _copyClientDic.Select(c => c.Value).ToList();
  286. int i = 1;
  287. foreach (var c in list)
  288. {
  289. Console.WriteLine(i + ":" + c.ChargeBoxId + " " + c.SessionID);
  290. i++;
  291. }
  292. }
  293. break;
  294. case "lcn":
  295. {
  296. Console.WriteLine("Command List Customer Name");
  297. Dictionary<string, WsClientData> _copyClientDic = null;
  298. _copyClientDic = new Dictionary<string, WsClientData>(clientDic);
  299. var lcn = clientDic.Select(c => c.Value.CustomerName).Distinct().ToList();
  300. int iLcn = 1;
  301. foreach (var c in lcn)
  302. {
  303. Console.WriteLine(iLcn + ":" + c + ":" + clientDic.Where(z => z.Value.CustomerName == c).Count().ToString());
  304. iLcn++;
  305. }
  306. }
  307. break;
  308. case "help":
  309. Console.WriteLine("Command help!!");
  310. Console.WriteLine("lcn : List Customer Name");
  311. Console.WriteLine("gc : GC Collect");
  312. Console.WriteLine("lc : List Clients");
  313. Console.WriteLine("cls : clear console");
  314. Console.WriteLine("silent : silent");
  315. Console.WriteLine("show : show log");
  316. // logger.Info("rcl : show Real Connection Limit");
  317. break;
  318. case "cls":
  319. Console.WriteLine("Command clear");
  320. Console.Clear();
  321. break;
  322. case "silent":
  323. Console.WriteLine("Command silent");
  324. //var xe = XElement.Load("NLog.config");
  325. //var xns = xe.GetDefaultNamespace();
  326. //var minlevelattr = xe.Descendants(xns + "rules").Elements(xns + "logger")
  327. // .Where(c => c.Attribute("writeTo").Value.Equals("console")).Attributes("minlevel").FirstOrDefault();
  328. //if (minlevelattr != null)
  329. //{
  330. // minlevelattr.Value = "Warn";
  331. //}
  332. //xe.Save("NLog.config");
  333. foreach (var rule in LogManager.Configuration.LoggingRules)
  334. {
  335. if (rule.RuleName != "ConsoleLog")
  336. {
  337. continue;
  338. }
  339. var isTargetRule = rule.Targets.Any(x => x.Name.ToLower() == "console");
  340. if (isTargetRule)
  341. {
  342. rule.SetLoggingLevels(NLog.LogLevel.Warn, NLog.LogLevel.Off);
  343. }
  344. }
  345. break;
  346. case "show":
  347. Console.WriteLine("Command show");
  348. //var xe1 = XElement.Load("NLog.config");
  349. //var xns1 = xe1.GetDefaultNamespace();
  350. //var minlevelattr1 = xe1.Descendants(xns1 + "rules").Elements(xns1 + "logger")
  351. // .Where(c => c.Attribute("writeTo").Value.Equals("console")).Attributes("minlevel").FirstOrDefault();
  352. //if (minlevelattr1 != null)
  353. //{
  354. // minlevelattr1.Value = "trace";
  355. //}
  356. //xe1.Save("NLog.config");
  357. foreach (var rule in LogManager.Configuration.LoggingRules)
  358. {
  359. if (rule.RuleName != "ConsoleLog")
  360. {
  361. continue;
  362. }
  363. var isTargetRule = rule.Targets.Any(x => x.Name.ToLower() == "console");
  364. if (isTargetRule)
  365. {
  366. rule.SetLoggingLevels(NLog.LogLevel.Trace, NLog.LogLevel.Off);
  367. }
  368. }
  369. break;
  370. case "rcl":
  371. break;
  372. default:
  373. break;
  374. }
  375. }
  376. }
  377. internal void Stop()
  378. {
  379. _cts?.Cancel();
  380. }
  381. async private void ReceivedMessageTimeLimited(object sender, string rawdata)
  382. {
  383. if (sender is not WsClientData session)
  384. {
  385. return;
  386. }
  387. CancellationTokenSource tokenSource = new();
  388. var task = ReceivedMessage(session, rawdata);
  389. var completedTask = await Task.WhenAny(task, Task.Delay(90_000, tokenSource.Token));
  390. if (completedTask != task)
  391. {
  392. logger.LogCritical("Process timeout: {0} ", rawdata);
  393. await task;
  394. return;
  395. }
  396. tokenSource.Cancel();
  397. return;
  398. }
  399. async private Task ReceivedMessage(WsClientData session, string rawdata)
  400. {
  401. try
  402. {
  403. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  404. MessageResult analysisResult = msgAnalyser.AnalysisReceiveData(session, rawdata);
  405. WriteMachineLog(session, rawdata,
  406. string.Format("{0} {1}", string.IsNullOrEmpty(analysisResult.Action) ? "unknown" : analysisResult.Action, analysisResult.Id == 2 ? "Request" : (analysisResult.Id == 3 ? "Confirmation" : "Error")), analysisResult.Exception == null ? "" : analysisResult.Exception.Message);
  407. if (session.ResetSecurityProfile)
  408. {
  409. logger.LogError(string.Format("[{0}] ChargeBoxId:{1} ResetSecurityProfile", DateTime.UtcNow, session.ChargeBoxId));
  410. RemoveClient(session, "ResetSecurityProfile");
  411. return;
  412. }
  413. if (!analysisResult.Success)
  414. {
  415. //解析RawData就發生錯誤
  416. if (!string.IsNullOrEmpty(analysisResult.CallErrorMsg))
  417. {
  418. Send(session, analysisResult.CallErrorMsg, string.Format("{0} {1}", analysisResult.Action, "Error"));
  419. }
  420. else
  421. {
  422. if (analysisResult.Message == null)
  423. {
  424. string replyMsg = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  425. string errorMsg = string.Empty;
  426. if (analysisResult.Exception != null)
  427. {
  428. errorMsg = analysisResult.Exception.ToString();
  429. }
  430. Send(session, replyMsg, string.Format("{0} {1}", "unknown", "Error"), "EVSE's sent essage has parsed Failed. ");
  431. }
  432. else
  433. {
  434. BaseMessage _baseMsg = analysisResult.Message as BaseMessage;
  435. string replyMsg = BasicMessageHandler.GenerateCallError(_baseMsg.Id, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  436. string errorMsg = string.Empty;
  437. if (analysisResult.Exception != null)
  438. {
  439. errorMsg = analysisResult.Exception.ToString();
  440. }
  441. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  442. }
  443. }
  444. }
  445. else
  446. {
  447. switch (analysisResult.Id)
  448. {
  449. case BasicMessageHandler.TYPENUMBER_CALL:
  450. {
  451. if (!session.ISOCPP20)
  452. {
  453. Actions action = Convertor.GetAction(analysisResult.Action);
  454. try
  455. {
  456. await ProcessRequestMessage(analysisResult, session, action);
  457. }
  458. catch (Exception e)
  459. {
  460. logger.LogError($"Processing {action} exception!");
  461. throw;
  462. }
  463. }
  464. else
  465. {
  466. EVCB_OCPP20.Packet.Features.Actions action = Convertor.GetActionby20(analysisResult.Action);
  467. MessageResult result = new MessageResult() { Success = true };
  468. //ocpp20 處理
  469. switch (action)
  470. {
  471. case EVCB_OCPP20.Packet.Features.Actions.BootNotification:
  472. {
  473. EVCB_OCPP20.Packet.Messages.BootNotificationRequest _request = (EVCB_OCPP20.Packet.Messages.IRequest)analysisResult.Message as EVCB_OCPP20.Packet.Messages.BootNotificationRequest;
  474. var confirm = new EVCB_OCPP20.Packet.Messages.BootNotificationResponse() { CurrentTime = DateTime.UtcNow, Interval = 180, Status = EVCB_OCPP20.Packet.DataTypes.EnumTypes.RegistrationStatusEnumType.Pending };
  475. result.Message = confirm;
  476. result.Success = true;
  477. string response = BasicMessageHandler.GenerateConfirmationofOCPP20(analysisResult.UUID, (EVCB_OCPP20.Packet.Messages.IConfirmation)result.Message);
  478. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Response"), result.Exception == null ? string.Empty : result.Exception.ToString());
  479. var request = new EVCB_OCPP20.Packet.Messages.SetNetworkProfileRequest()
  480. {
  481. ConfigurationSlot = 1,
  482. ConnectionData = new EVCB_OCPP20.Packet.DataTypes.NetworkConnectionProfileType()
  483. {
  484. OcppVersion = EVCB_OCPP20.Packet.DataTypes.EnumTypes.OCPPVersionEnumType.OCPP20,
  485. OcppTransport = EVCB_OCPP20.Packet.DataTypes.EnumTypes.OCPPTransportEnumType.JSON,
  486. MessageTimeout = 30,
  487. OcppCsmsUrl = session.UriScheme == "ws" ? GlobalConfig.OCPP20_WSUrl : GlobalConfig.OCPP20_WSSUrl,
  488. OcppInterface = EVCB_OCPP20.Packet.DataTypes.EnumTypes.OCPPInterfaceEnumType.Wired0
  489. }
  490. };
  491. var uuid = session.queue20.store(request);
  492. string requestText = BasicMessageHandler.GenerateRequestofOCPP20(uuid, "SetNetworkProfile", request);
  493. Send(session, requestText, "SetNetworkProfile");
  494. }
  495. break;
  496. default:
  497. {
  498. logger.LogError(string.Format("We don't implement messagetype:{0} of raw data :{1} by {2}", analysisResult.Id, rawdata, session.ChargeBoxId));
  499. }
  500. break;
  501. }
  502. }
  503. }
  504. break;
  505. case BasicMessageHandler.TYPENUMBER_CALLRESULT:
  506. {
  507. if (!session.ISOCPP20)
  508. {
  509. Actions action = Convertor.GetAction(analysisResult.Action);
  510. ProcessConfirmationMessage(analysisResult, session, action);
  511. }
  512. else
  513. {
  514. EVCB_OCPP20.Packet.Features.Actions action = Convertor.GetActionby20(analysisResult.Action);
  515. MessageResult result = new MessageResult() { Success = true };
  516. //ocpp20 處理
  517. switch (action)
  518. {
  519. case EVCB_OCPP20.Packet.Features.Actions.SetNetworkProfile:
  520. {
  521. EVCB_OCPP20.Packet.Messages.SetNetworkProfileResponse response = (EVCB_OCPP20.Packet.Messages.IConfirmation)analysisResult.Message as EVCB_OCPP20.Packet.Messages.SetNetworkProfileResponse;
  522. if (response.Status == EVCB_OCPP20.Packet.DataTypes.EnumTypes.SetNetworkProfileStatusEnumType.Accepted)
  523. {
  524. var request = new EVCB_OCPP20.Packet.Messages.SetVariablesRequest()
  525. {
  526. SetVariableData = new List<EVCB_OCPP20.Packet.DataTypes.SetVariableDataType>()
  527. {
  528. new EVCB_OCPP20.Packet.DataTypes.SetVariableDataType()
  529. {
  530. Component=new EVCB_OCPP20.Packet.DataTypes.ComponentType()
  531. {
  532. Name="OCPPCommCtrlr",
  533. },
  534. AttributeType= EVCB_OCPP20.Packet.DataTypes.EnumTypes.AttributeEnumType.Actual,
  535. AttributeValue= JsonConvert.SerializeObject(new List<int>(){ 1 }),
  536. Variable=new EVCB_OCPP20.Packet.DataTypes.VariableType()
  537. {
  538. Name="NetworkConfigurationPriority",
  539. }
  540. }
  541. }
  542. };
  543. var uuid = session.queue20.store(request);
  544. string requestText = BasicMessageHandler.GenerateRequestofOCPP20(uuid, "SetVariables", request);
  545. Send(session, requestText, "SetVariables");
  546. }
  547. }
  548. break;
  549. case EVCB_OCPP20.Packet.Features.Actions.SetVariables:
  550. {
  551. EVCB_OCPP20.Packet.Messages.SetVariablesResponse response = (EVCB_OCPP20.Packet.Messages.IConfirmation)analysisResult.Message as EVCB_OCPP20.Packet.Messages.SetVariablesResponse;
  552. if (response.SetVariableResult[0].AttributeStatus == EVCB_OCPP20.Packet.DataTypes.EnumTypes.SetVariableStatusEnumType.RebootRequired)
  553. {
  554. var request = new EVCB_OCPP20.Packet.Messages.ResetRequest()
  555. {
  556. Type = EVCB_OCPP20.Packet.DataTypes.EnumTypes.ResetEnumType.OnIdle
  557. };
  558. var uuid = session.queue20.store(request);
  559. string requestText = BasicMessageHandler.GenerateRequestofOCPP20(uuid, "Reset", request);
  560. Send(session, requestText, "Reset");
  561. }
  562. }
  563. break;
  564. default:
  565. {
  566. logger.LogError(string.Format("We don't implement messagetype:{0} of raw data :{1} by {2}", analysisResult.Id, rawdata, session.ChargeBoxId));
  567. }
  568. break;
  569. }
  570. }
  571. }
  572. break;
  573. case BasicMessageHandler.TYPENUMBER_CALLERROR:
  574. {
  575. //只處理 丟出Request 收到Error的訊息
  576. if (analysisResult.Success && analysisResult.Message != null)
  577. {
  578. Actions action = Convertor.GetAction(analysisResult.Action);
  579. ProcessErrorMessage(analysisResult, session, action);
  580. }
  581. }
  582. break;
  583. default:
  584. {
  585. logger.LogError(string.Format("Can't analyze messagetype:{0} of raw data :{1} by {2}", analysisResult.Id, rawdata, session.ChargeBoxId));
  586. }
  587. break;
  588. }
  589. }
  590. }
  591. catch (Exception ex)
  592. {
  593. if (ex.InnerException != null)
  594. {
  595. logger.LogError(string.Format("{0} **Inner Exception :{1} ", session.ChargeBoxId + rawdata, ex.ToString()));
  596. }
  597. else
  598. {
  599. logger.LogError(string.Format("{0} **Exception :{1} ", session.ChargeBoxId, ex.ToString()));
  600. }
  601. }
  602. finally
  603. {
  604. await Task.Delay(10);
  605. }
  606. }
  607. private async Task ProcessRequestMessage(MessageResult analysisResult, WsClientData session, Actions action)
  608. {
  609. Stopwatch outter_stopwatch = Stopwatch.StartNew();
  610. //BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  611. if (!session.IsCheckIn && action != Actions.BootNotification)
  612. {
  613. if (analysisResult.Message is IRequest request && !request.TransactionRelated())
  614. {
  615. string response = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.GenericError, OCPPErrorDescription.NotChecked);
  616. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"));
  617. }
  618. }
  619. else
  620. {
  621. var profileName = profiles.Where(x => x.IsExisted(analysisResult.Action)).Select(x => x.Name).FirstOrDefault();
  622. switch (profileName)
  623. {
  624. case "Core":
  625. {
  626. var replyResult = await profileHandler.ExecuteCoreRequest(action, session, (IRequest)analysisResult.Message).ConfigureAwait(false);
  627. var sendTimer = Stopwatch.StartNew();
  628. if (replyResult.Success)
  629. {
  630. string response = BasicMessageHandler.GenerateConfirmation(analysisResult.UUID, (IConfirmation)replyResult.Message);
  631. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Confirmation"), replyResult.Exception == null ? string.Empty : replyResult.Exception.ToString());
  632. if (action == Actions.BootNotification &&
  633. replyResult.Message is BootNotificationConfirmation bootNotificationConfirmation &&
  634. analysisResult.Message is BootNotificationRequest bootNotificationRequest)
  635. {
  636. session.ChargePointVendor = bootNotificationRequest.chargePointVendor;
  637. if (session.BootStatus == BootStatus.Startup
  638. //&& bootSemaphore.WaitOne(0)
  639. )
  640. {
  641. session.BootStatus = BootStatus.Initializing;
  642. session.AddTask(StartInitializeEVSE(session));
  643. }
  644. if (bootNotificationConfirmation.status == Packet.Messages.SubTypes.RegistrationStatus.Accepted)
  645. {
  646. session.IsCheckIn = true;
  647. session.AddTask(StartLateInitializeEVSE(session));
  648. //await confirmWaitingMessageSerevice.SendAndWaitUntilResultAsync(sendTask, session.DisconnetCancellationToken);
  649. }
  650. }
  651. if (action == Actions.Authorize && replyResult.Message is AuthorizeConfirmation)
  652. {
  653. var authorizeRequest = (IRequest)analysisResult.Message as AuthorizeRequest;
  654. if (session.UserDisplayPrices.ContainsKey(authorizeRequest.idTag))
  655. {
  656. await messageService.SendDataTransferRequest(
  657. session.ChargeBoxId,
  658. messageId: "SetUserPrice",
  659. vendorId: "Phihong Technology",
  660. data: JsonConvert.SerializeObject(
  661. new
  662. {
  663. idToken = authorizeRequest.idTag,
  664. price = session.UserDisplayPrices[authorizeRequest.idTag]
  665. })
  666. );
  667. }
  668. }
  669. }
  670. else
  671. {
  672. if (action == Actions.StopTransaction && replyResult.CallErrorMsg == "Reject Response Message")
  673. {
  674. //do nothing
  675. logger.LogWarning(replyResult.Exception.ToString());
  676. }
  677. else
  678. {
  679. string response = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  680. string errorMsg = replyResult.Exception != null ? replyResult.Exception.ToString() : string.Empty;
  681. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  682. }
  683. }
  684. sendTimer.Stop();
  685. if(sendTimer.ElapsedMilliseconds/1000 > 1)
  686. {
  687. logger.LogCritical("ProcessRequestMessage Send Cost {time} sec", sendTimer.ElapsedMilliseconds / 1000);
  688. }
  689. if (action == Actions.StartTransaction)
  690. {
  691. var stationId = await _loadingBalanceService.GetStationIdByMachineId(session.MachineId);
  692. var _powerDic = await _loadingBalanceService.GetSettingPower(stationId);
  693. if (_powerDic != null)
  694. {
  695. foreach (var kv in _powerDic)
  696. {
  697. try
  698. {
  699. if (kv.Value.HasValue)
  700. {
  701. profileHandler.SetChargingProfile(kv.Key, kv.Value.Value, Packet.Messages.SubTypes.ChargingRateUnitType.W);
  702. }
  703. }
  704. catch (Exception ex)
  705. {
  706. logger.LogError(string.Format("Set Profile Exception: {0}", ex.ToString()));
  707. }
  708. }
  709. }
  710. }
  711. if (action == Actions.StopTransaction)
  712. {
  713. var stationId = await _loadingBalanceService.GetStationIdByMachineId(session.MachineId);
  714. var _powerDic = await _loadingBalanceService.GetSettingPower(stationId);
  715. if (_powerDic != null)
  716. {
  717. foreach (var kv in _powerDic)
  718. {
  719. try
  720. {
  721. if (kv.Value.HasValue)
  722. {
  723. profileHandler.SetChargingProfile(kv.Key, kv.Value.Value, Packet.Messages.SubTypes.ChargingRateUnitType.W);
  724. }
  725. }
  726. catch (Exception ex)
  727. {
  728. logger.LogError(string.Format("Set Profile Exception: {0}", ex.ToString()));
  729. }
  730. }
  731. }
  732. }
  733. }
  734. break;
  735. case "FirmwareManagement":
  736. {
  737. var replyResult = await profileHandler.ExecuteFirmwareManagementRequest(action, session, (IRequest)analysisResult.Message);
  738. if (replyResult.Success)
  739. {
  740. string response = BasicMessageHandler.GenerateConfirmation(analysisResult.UUID, (IConfirmation)replyResult.Message);
  741. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Confirmation", replyResult.Exception == null ? string.Empty : replyResult.Exception.ToString()));
  742. }
  743. else
  744. {
  745. string response = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  746. string errorMsg = replyResult.Exception != null ? replyResult.Exception.ToString() : string.Empty;
  747. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  748. }
  749. }
  750. break;
  751. case "Security":
  752. {
  753. var replyResult = profileHandler.ExecuteSecurityRequest(action, session, (IRequest)analysisResult.Message);
  754. if (replyResult.Success)
  755. {
  756. string response = BasicMessageHandler.GenerateConfirmation(analysisResult.UUID, (IConfirmation)replyResult.Message);
  757. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Confirmation", replyResult.Exception == null ? string.Empty : replyResult.Exception.ToString()));
  758. }
  759. else
  760. {
  761. string response = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  762. string errorMsg = replyResult.Exception != null ? replyResult.Exception.ToString() : string.Empty;
  763. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  764. }
  765. }
  766. break;
  767. default:
  768. {
  769. string replyMsg = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  770. string errorMsg = string.Format("Couldn't find action name: {0} of profile", action);
  771. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  772. }
  773. break;
  774. }
  775. }
  776. outter_stopwatch.Stop();
  777. if (outter_stopwatch.ElapsedMilliseconds > 1000)
  778. {
  779. logger.LogCritical("ProcessRequestMessage {action} too long {time} sec", action.ToString(), outter_stopwatch.ElapsedMilliseconds / 1000);
  780. }
  781. }
  782. async private void ProcessConfirmationMessage(MessageResult analysisResult, WsClientData session, Actions action)
  783. {
  784. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  785. if (await confirmWaitingMessageSerevice.TryConfirmMessage(analysisResult))
  786. {
  787. var profileName = profiles.Where(x => x.IsExisted(analysisResult.Action)).Select(x => x.Name).FirstOrDefault();
  788. MessageResult confirmResult = null;
  789. switch (profileName)
  790. {
  791. case "Core":
  792. {
  793. confirmResult = await profileHandler.ExecuteCoreConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
  794. }
  795. break;
  796. case "FirmwareManagement":
  797. {
  798. confirmResult = await profileHandler.ExecuteFirmwareManagementConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
  799. }
  800. break;
  801. case "RemoteTrigger":
  802. {
  803. confirmResult = await profileHandler.ExecuteRemoteTriggerConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
  804. }
  805. break;
  806. case "Reservation":
  807. {
  808. confirmResult = await profileHandler.ExecuteReservationConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
  809. }
  810. break;
  811. case "LocalAuthListManagement":
  812. {
  813. confirmResult = await profileHandler.ExecuteLocalAuthListManagementConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
  814. }
  815. break;
  816. case "SmartCharging":
  817. {
  818. confirmResult = await profileHandler.ExecuteSmartChargingConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
  819. }
  820. break;
  821. case "Security":
  822. {
  823. confirmResult = profileHandler.ExecuteSecurityConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
  824. }
  825. break;
  826. default:
  827. {
  828. string replyMsg = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  829. string errorMsg = string.Format("Couldn't find action name: {0} of profile", action);
  830. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  831. }
  832. break;
  833. }
  834. if (confirmResult == null || !confirmResult.Success)
  835. {
  836. logger.LogError(string.Format("Action:{0} MessageId:{1} ExecuteConfirm Error:{2} ",
  837. analysisResult.Action, analysisResult.UUID, confirmResult.Exception.ToString()));
  838. }
  839. }
  840. else
  841. {
  842. string replyMsg = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  843. string errorMsg = string.Format("Action:{0} MessageId:{1} didn't exist in confirm message", analysisResult.Action, analysisResult.UUID);
  844. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  845. }
  846. }
  847. private async void ProcessErrorMessage(MessageResult analysisResult, WsClientData session, Actions action)
  848. {
  849. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  850. if (await confirmWaitingMessageSerevice.TryConfirmMessage(analysisResult))
  851. {
  852. var profileName = profiles.Where(x => x.IsExisted(analysisResult.Action)).Select(x => x.Name).FirstOrDefault();
  853. switch (profileName)
  854. {
  855. case "Core":
  856. {
  857. _ = profileHandler.ReceivedCoreError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
  858. }
  859. break;
  860. case "FirmwareManagement":
  861. {
  862. _ = profileHandler.ReceivedFirmwareManagementError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
  863. }
  864. break;
  865. case "RemoteTrigger":
  866. {
  867. _ = profileHandler.ReceivedRemoteTriggerError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
  868. }
  869. break;
  870. case "Reservation":
  871. {
  872. _ = profileHandler.ExecuteReservationError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
  873. }
  874. break;
  875. case "LocalAuthListManagement":
  876. {
  877. _ = profileHandler.ReceivedLocalAuthListManagementError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
  878. }
  879. break;
  880. case "SmartCharging":
  881. {
  882. _ = profileHandler.ReceivedSmartChargingError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
  883. }
  884. break;
  885. default:
  886. {
  887. string replyMsg = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  888. string errorMsg = string.Format("Couldn't find action name: {0} of profile", action);
  889. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  890. }
  891. break;
  892. }
  893. }
  894. else
  895. {
  896. string replyMsg = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  897. string errorMsg = string.Format("Action:{0} MessageId:{1} didn't exist in confirm message", analysisResult.Action, analysisResult.UUID);
  898. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  899. }
  900. }
  901. private async Task StartInitializeEVSE(WsClientData session)
  902. {
  903. try
  904. {
  905. await InitializeEVSE(session);
  906. }
  907. catch (Exception e)
  908. {
  909. logger.LogCritical("StartInitializeEVSE:{errormsg}", e.Message);
  910. logger.LogCritical("StartInitializeEVSE:{errorStackTrace}", e.StackTrace);
  911. }
  912. finally
  913. {
  914. session.BootStatus = BootStatus.Pending;
  915. //bootSemaphore.Release();
  916. }
  917. }
  918. private async Task InitializeEVSE(WsClientData session)
  919. {
  920. // Pending mode 下發設定
  921. string connectorType = await mainDbService.GetMachineConnectorType(session.ChargeBoxId, session.DisconnetCancellationToken);
  922. if (!string.IsNullOrEmpty(connectorType) &&
  923. (connectorType.Contains("6") || connectorType.Contains("7") || connectorType.Contains("8") || connectorType.Contains("9")))
  924. {
  925. session.IsAC = false;
  926. }
  927. string requestId = string.Empty;
  928. var displayPriceText = await webDbService.SetDefaultFee(session);
  929. UpdateClientDisplayPrice(session.ChargeBoxId, displayPriceText);
  930. Func<string, Task<string>> sendTask;
  931. sendTask = async (string serialNo) => await messageService.SendGetEVSEConfigureRequest(session.ChargeBoxId, serialNo: serialNo);
  932. var response = await confirmWaitingMessageSerevice.SendAndWaitUntilResultAsync(sendTask, session.DisconnetCancellationToken);
  933. if (!string.IsNullOrEmpty(displayPriceText))
  934. {
  935. sendTask = async (string serialNo) => await messageService.SendChangeConfigurationRequest(
  936. session.ChargeBoxId, key: "DefaultPrice", value: displayPriceText, serialNo: serialNo);
  937. await confirmWaitingMessageSerevice.SendAndWaitUntilResultAsync(sendTask, session.DisconnetCancellationToken);
  938. }
  939. if (session.CustomerId == new Guid("298918C0-6BB5-421A-88CC-4922F918E85E") || session.CustomerId == new Guid("9E6BFDCC-09FB-4DAB-A428-43FE507600A3"))
  940. {
  941. await messageService.SendChangeConfigurationRequest(
  942. session.ChargeBoxId, key: "TimeOffset", value: "+08:00");
  943. }
  944. if (session.CustomerId == new Guid("D57D5BCC-C5B0-4031-A7AE-7516E00CB028"))
  945. {
  946. await messageService.SendChangeConfigurationRequest(
  947. session.ChargeBoxId, key: "StopTransactionOnInvalidId", value: "True");
  948. }
  949. //foreach (var initFunction in InitActions)
  950. for (var index = 0; index < InitActions.Count; index++)
  951. {
  952. var initFunction = InitActions[index];
  953. await initFunction(session, session.DisconnetCancellationToken);
  954. }
  955. //await StationConfigService?.CheckAndUpdateEvseConfig(session, session.DisconnetCancellationToken);
  956. }
  957. private async Task StartLateInitializeEVSE(WsClientData session)
  958. {
  959. try
  960. {
  961. await Task.Delay(TimeSpan.FromMinutes(5));
  962. await LateInitializeEVSE(session);
  963. }
  964. catch (Exception e)
  965. {
  966. logger.LogCritical("StartLateInitializeEVSE:{errormsg}", e.Message);
  967. logger.LogCritical("StartLateInitializeEVSE:{errorStackTrace}", e.StackTrace);
  968. }
  969. finally
  970. {
  971. session.BootStatus = BootStatus.Pending;
  972. //bootSemaphore.Release();
  973. }
  974. }
  975. private async Task LateInitializeEVSE(WsClientData session)
  976. {
  977. Func<string, Task<string>> sendTask;
  978. sendTask = async (string serialNo) => await messageService.SendDataTransferRequest(
  979. session.ChargeBoxId,
  980. messageId: "ID_FirmwareVersion",
  981. vendorId: "Phihong Technology",
  982. data: string.Empty,
  983. serialNo: serialNo);
  984. await confirmWaitingMessageSerevice.SendAndWaitUntilResultAsync(sendTask, session.DisconnetCancellationToken);
  985. sendTask = async (string serialNo) => await messageService.SendTriggerMessageRequest(
  986. session.ChargeBoxId,
  987. messageTrigger: MessageTrigger.DiagnosticsStatusNotification,
  988. serialNo: serialNo);
  989. await confirmWaitingMessageSerevice.SendAndWaitUntilResultAsync(sendTask, session.DisconnetCancellationToken);
  990. }
  991. private void Send(WsClientData session, string msg, string messageType, string errorMsg = "")
  992. {
  993. try
  994. {
  995. if (session != null)
  996. {
  997. WriteMachineLog(session, msg, messageType, errorMsg, true);
  998. session.Send(msg);
  999. }
  1000. }
  1001. catch (Exception ex)
  1002. {
  1003. logger.LogError(string.Format("Send Ex:{0}", ex.ToString()));
  1004. }
  1005. }
  1006. internal async void RemoveClient(WsClientData session, string reason)
  1007. {
  1008. if (session == null)
  1009. {
  1010. return;
  1011. }
  1012. if (!string.IsNullOrEmpty(session.MachineId))
  1013. logger.LogTrace("RemoveClient[{0}]:{1}", session.ChargeBoxId, reason);
  1014. WriteMachineLog(session, string.Format("CloseReason: {0}", reason), "Connection", "");
  1015. //if (session.Connected)
  1016. //{
  1017. // session.Close(CloseReason.ServerShutdown);
  1018. //}
  1019. RemoveClientDic(session);
  1020. try
  1021. {
  1022. session.SessionClosed -= AppServer_SessionClosed;
  1023. session.m_ReceiveData -= ReceivedMessageTimeLimited;
  1024. if (session.State == WebSocketState.Open)
  1025. {
  1026. await session.Close();
  1027. }
  1028. // session.Close(CloseReason.ServerShutdown);
  1029. }
  1030. catch (Exception ex)
  1031. {
  1032. //logger.LogWarning("Close client socket error!!");
  1033. logger.LogWarning(string.Format("Close client socket error!! {0} Msg:{1}", session.ChargeBoxId, ex.Message));
  1034. }
  1035. if (session != null)
  1036. {
  1037. session = null;
  1038. }
  1039. }
  1040. private void RemoveClientDic(WsClientData session)
  1041. {
  1042. if (string.IsNullOrEmpty(session.ChargeBoxId))
  1043. {
  1044. return;
  1045. }
  1046. if (clientDic.ContainsKey(session.ChargeBoxId))
  1047. {
  1048. if (clientDic[session.ChargeBoxId].SessionID == session.SessionID)
  1049. {
  1050. logger.LogDebug(String.Format("ChargeBoxId:{0} Remove SessionId:{1} Removed SessionId:{2}", session.ChargeBoxId, session.SessionID, clientDic[session.ChargeBoxId].SessionID));
  1051. clientDic.Remove(session.ChargeBoxId, out _);
  1052. logger.LogTrace("RemoveClient ContainsKey " + session.ChargeBoxId);
  1053. }
  1054. }
  1055. }
  1056. private void WarmUpLog()
  1057. {
  1058. connectionLogdbService.WarmUpLog();
  1059. }
  1060. private void WriteMachineLog(WsClientData WsClientData, string data, string messageType, string errorMsg = "", bool isSent = false)
  1061. {
  1062. try
  1063. {
  1064. if (WsClientData == null || string.IsNullOrEmpty(data)) return;
  1065. if (WsClientData.ChargeBoxId == null)
  1066. {
  1067. logger.LogCritical(WsClientData.Path.ToString() + "]********************session ChargeBoxId null sessionId=" + WsClientData.SessionID);
  1068. }
  1069. connectionLogdbService.WriteMachineLog(WsClientData, data, messageType, errorMsg, isSent);
  1070. }
  1071. catch (Exception ex)
  1072. {
  1073. //Console.WriteLine(ex.ToString());
  1074. logger.LogError(ex,ex.Message);
  1075. }
  1076. }
  1077. }
  1078. }