ProtalServer.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762
  1. using NLog;
  2. using OCPPServer.Protocol;
  3. using OCPPServer.SubProtocol;
  4. using SuperSocket.SocketBase;
  5. using SuperSocket.SocketBase.Config;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.IO;
  9. using System.Linq;
  10. using System.Text;
  11. using System.Xml.Linq;
  12. using EVCB_OCPP.Packet.Messages.Basic;
  13. using EVCB_OCPP.Packet.Messages.Core;
  14. using EVCB_OCPP.WSServer.Message;
  15. using EVCB_OCPP.Packet.Messages;
  16. using EVCB_OCPP.Domain;
  17. using EVCB_OCPP.Domain.Models.Database;
  18. using System.Threading;
  19. using System.Data.Entity;
  20. using EVCB_OCPP.Packet.Features;
  21. using EVCB_OCPP.Packet.Features.Core;
  22. using Newtonsoft.Json;
  23. using OCPPPackage.Profiles;
  24. using System.Threading.Tasks;
  25. using EVCB_OCPP.WSServer.Helper;
  26. using System.Data.SqlClient;
  27. namespace EVCB_OCPP.WSServer
  28. {
  29. internal class ProtalServer
  30. {
  31. internal Dictionary<string, ClientData> ClientDic = new Dictionary<string, ClientData>();
  32. static private ILogger logger = NLog.LogManager.GetCurrentClassLogger();
  33. private readonly Object _lockClientDic = new object();
  34. private readonly Object _lockConfirmPacketList = new object();
  35. ProfileHandler _profileHandler = new ProfileHandler();
  36. private List<NeedConfirmMessage> NeedConfirmPacketList = new List<NeedConfirmMessage>();
  37. private List<string> _needConfirmActions = new List<string>()
  38. {
  39. "GetConfiguration",
  40. "ChangeConfiguration",
  41. "RemoteStartTransaction",
  42. "RemoteStopTransaction",
  43. "ChangeAvailability",
  44. "ClearCache",
  45. "DataTransfer",
  46. "Reset",
  47. "UnlockConnector",
  48. };
  49. private List<Profile> profiles = new List<Profile>()
  50. {
  51. new CoreProfile(),
  52. new FirmwareManagementProfile(),
  53. new ReservationProfile(),
  54. new RemoteTriggerProfile(),
  55. new SmartChargingProfile(),
  56. new LocalAuthListManagementProfile()
  57. };
  58. private CancellationTokenSource _cts = new CancellationTokenSource();
  59. private CancellationToken _ct;
  60. internal ProtalServer()
  61. {
  62. _ct = _cts.Token;
  63. }
  64. internal void Start()
  65. {
  66. OpenNetwork();
  67. Task taskServerCommand = new Task(ServerMessageTrigger, _ct);
  68. taskServerCommand.Start();
  69. while (true)
  70. {
  71. var input = Console.ReadLine();
  72. switch (input.ToLower())
  73. {
  74. case "stop":
  75. break;
  76. case "gc":
  77. logger.Info("Command GC");
  78. GC.Collect();
  79. break;
  80. case "lc":
  81. logger.Info("Command List Clients");
  82. break;
  83. case "lcn":
  84. logger.Info("Command List Customer Name");
  85. break;
  86. case "help":
  87. logger.Info("Command help!!");
  88. logger.Info("lcn : List Customer Name");
  89. logger.Info("gc : GC Collect");
  90. logger.Info("lc : List Clients");
  91. logger.Info("cls : clear console");
  92. logger.Info("silent : silent");
  93. logger.Info("show : show log");
  94. logger.Info("rcl : show Real Connection Limit");
  95. break;
  96. case "cls":
  97. logger.Info("Command clear");
  98. Console.Clear();
  99. break;
  100. case "silent":
  101. logger.Info("Command silent");
  102. var xe = XElement.Load("NLog.config");
  103. var xns = xe.GetDefaultNamespace();
  104. var minlevelattr = xe.Descendants(xns + "rules").Elements(xns + "logger")
  105. .Where(c => c.Attribute("writeTo").Value.Equals("console")).Attributes("minlevel").FirstOrDefault();
  106. if (minlevelattr != null)
  107. {
  108. minlevelattr.Value = "info";
  109. }
  110. xe.Save("NLog.config");
  111. break;
  112. case "show":
  113. logger.Info("Command show");
  114. var xe1 = XElement.Load("NLog.config");
  115. var xns1 = xe1.GetDefaultNamespace();
  116. var minlevelattr1 = xe1.Descendants(xns1 + "rules").Elements(xns1 + "logger")
  117. .Where(c => c.Attribute("writeTo").Value.Equals("console")).Attributes("minlevel").FirstOrDefault();
  118. if (minlevelattr1 != null)
  119. {
  120. minlevelattr1.Value = "trace";
  121. }
  122. xe1.Save("NLog.config");
  123. break;
  124. case "rcl":
  125. break;
  126. default:
  127. break;
  128. }
  129. }
  130. }
  131. private void InitEVSEConfigure(string sn)
  132. {
  133. List<MachineConfigure> configures = new List<MachineConfigure>();
  134. configures.Add(new MachineConfigure() { ConfigureName = StandardConfiguration.AuthorizeRemoteTxRequests, ConfigureSetting = "" });
  135. using (var db = new MainDBContext())
  136. {
  137. var _sn = db.MachineConfigure.Where(x => x.ChargeBoxId == sn).Select(x => x.ChargeBoxId).FirstOrDefault();
  138. if (string.IsNullOrEmpty(_sn))
  139. {
  140. db.MachineConfigure.Add(new MachineConfigure()
  141. {
  142. });
  143. }
  144. }
  145. }
  146. private void OpenNetwork()
  147. {
  148. //載入OCPP Protocol
  149. var appServer = new OCPPWSServer(new OCPPSubProtocol());
  150. List<IListenerConfig> llistener = new List<IListenerConfig>();
  151. // llistener.Add(new ListenerConfig { Ip = "", Port = Convert.ToInt32(wssserverPort), Backlog = 100, Security = serverSecurity });
  152. llistener.Add(new ListenerConfig { Ip = "172.17.40.13", Port = Convert.ToInt32(2012), Backlog = 100, Security = "None" });
  153. IEnumerable<IListenerConfig> listeners = llistener;
  154. //設定server config
  155. var serverConfig = new ServerConfig
  156. {
  157. //Port = Convert.ToInt32(2012),
  158. //Ip = "172.17.40.13",
  159. MaxRequestLength = 4096,
  160. //Security = serverSecurity,
  161. // Certificate = Certificate,
  162. Listeners = listeners
  163. };
  164. //Setup with listening port
  165. if (!appServer.Setup(serverConfig, logFactory: new OCPPLogFactory()))
  166. {
  167. Console.WriteLine("Failed to setup!");
  168. return;
  169. }
  170. appServer.NewSessionConnected += AppServer_NewSessionConnected;
  171. appServer.SessionClosed += AppServer_SessionClosed;
  172. //Try to start the appServer
  173. if (!appServer.Start())
  174. {
  175. Console.WriteLine("Failed to start!");
  176. Console.ReadKey();
  177. return;
  178. }
  179. }
  180. private void AppServer_SessionClosed(ClientData session, CloseReason value)
  181. {
  182. WriteMachineLog(session.ChargeBoxId, string.Format("CloseReason: {0}", value), "Connection", "");
  183. RemoveClient(session);
  184. // close Connection
  185. }
  186. private void AppServer_NewSessionConnected(ClientData session)
  187. {
  188. session.m_ReceiveData += new ClientData.OCPPClientDataEventHandler<ClientData, String>(ReceivedMessage);
  189. try
  190. {
  191. lock (_lockClientDic)
  192. {
  193. ClientData _removeClient = null;
  194. ClientDic.TryGetValue(session.ChargeBoxId, out _removeClient);
  195. if (_removeClient != null)
  196. {
  197. RemoveClient(_removeClient);
  198. }
  199. ClientDic.Add(session.ChargeBoxId, session);
  200. WriteMachineLog(session.ChargeBoxId, "", "Connection", "");
  201. }
  202. }
  203. catch (Exception ex)
  204. {
  205. }
  206. }
  207. private void ReceivedMessage(ClientData session, string rawdata)
  208. {
  209. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  210. MessageResult analysisResult = msgAnalyser.AnalysisReceiveData(session, rawdata);
  211. WriteMachineLog(session.ChargeBoxId, rawdata,
  212. string.Format("{0} {1}", analysisResult.Action, analysisResult.Id == 2 ? "Request" : (analysisResult.Id == 3 ? "Confirmation" : "Error")));
  213. if (analysisResult.Success == false)
  214. {
  215. //解析RawData就發生錯誤
  216. if (!string.IsNullOrEmpty(analysisResult.CallErrorMsg))
  217. {
  218. Send(session, rawdata, string.Format("{0} {1}", analysisResult.Action, "Error"));
  219. }
  220. else
  221. {
  222. BaseMessage _baseMsg = analysisResult.Message as BaseMessage;
  223. string replyMsg = msgAnalyser.GenerateCallError(_baseMsg.Id, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  224. string errorMsg = string.Empty;
  225. if (analysisResult.Exception != null)
  226. {
  227. errorMsg = analysisResult.Exception.ToString();
  228. }
  229. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  230. }
  231. }
  232. else
  233. {
  234. Actions action = Convertor.GetAction(analysisResult.Action);
  235. switch (analysisResult.Id)
  236. {
  237. case BasicMessageHandler.TYPENUMBER_CALL:
  238. {
  239. ProcessRequestMessage(analysisResult, session, action);
  240. }
  241. break;
  242. case BasicMessageHandler.TYPENUMBER_CALLRESULT:
  243. {
  244. ProcessConfirmationMessage(analysisResult, session, action);
  245. }
  246. break;
  247. case BasicMessageHandler.TYPENUMBER_CALLERROR:
  248. {
  249. //只處理 丟出Request 收到Error的訊息
  250. if (analysisResult.Success)
  251. {
  252. ProcessErrorMessage(analysisResult, session, action);
  253. }
  254. }
  255. break;
  256. default:
  257. {
  258. logger.Error(string.Format("Can't analyze messagetype:{0} of raw data :{1} by {2}", analysisResult.Id, rawdata, session.ChargeBoxId));
  259. }
  260. break;
  261. }
  262. }
  263. }
  264. private void ProcessRequestMessage(MessageResult analysisResult, ClientData session, Actions action)
  265. {
  266. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  267. if (!session.IsCheckIn && action != Actions.BootNotification)
  268. {
  269. string response = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.GenericError, OCPPErrorDescription.NotChecked);
  270. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"));
  271. }
  272. else
  273. {
  274. var profileName = profiles.Where(x => x.IsExisted(analysisResult.Action)).Select(x => x.Name).FirstOrDefault();
  275. switch (profileName)
  276. {
  277. case "Core":
  278. {
  279. if (!session.IsCheckIn && action == Actions.BootNotification)
  280. {
  281. var requestId = Guid.NewGuid();
  282. //測試命令
  283. try
  284. {
  285. //using (var db = new MainDBContext())
  286. //{
  287. // //db.MachineOperateRecord.Add(new MachineOperateRecord()
  288. // //{
  289. // // CreatedOn = DateTime.Now,
  290. // // ChargePointSerialNumber = session.ChargePointSerialNumber,
  291. // // SerialNo = requestId.ToString(),
  292. // // RequestContent = JsonConvert.SerializeObject(new GetConfigurationRequest() { key = new List<string>() { StandardConfiguration.HeartbeatInterval } }),
  293. // // EVSE_Status = 0,
  294. // // Status = 0,
  295. // // RequestType = 1,
  296. // //});
  297. // //core 26 項 設定
  298. // GetConfigurationRequest core_getConfigReq = new GetConfigurationRequest()
  299. // {
  300. // key = new List<string>()
  301. // {
  302. // StandardConfiguration.AuthorizeRemoteTxRequests,
  303. // StandardConfiguration.ClockAlignedDataInterval,
  304. // StandardConfiguration.ConnectionTimeOut,
  305. // //StandardConfiguration.HeartbeatInterval,
  306. // //StandardConfiguration.HeartbeatInterval,
  307. // //StandardConfiguration.LocalAuthorizeOffline,
  308. // //StandardConfiguration.LocalPreAuthorize,
  309. // //StandardConfiguration.MeterValuesAlignedData,
  310. // //StandardConfiguration.MeterValuesAlignedDataMaxLength,
  311. // //StandardConfiguration.MeterValuesSampledData,
  312. // //StandardConfiguration.MeterValuesSampledDataMaxLength,
  313. // //StandardConfiguration.MeterValueSampleInterval,
  314. // //StandardConfiguration.NumberOfConnectors,
  315. // //StandardConfiguration.ResetRetries,
  316. // //StandardConfiguration.ConnectorPhaseRotation,
  317. // //StandardConfiguration.ConnectorPhaseRotationMaxLength,
  318. // //StandardConfiguration.StopTransactionOnEVSideDisconnect,
  319. // //StandardConfiguration.StopTransactionOnInvalidId,
  320. // //StandardConfiguration.StopTxnAlignedData,
  321. // //StandardConfiguration.StopTxnAlignedDataMaxLength,
  322. // //StandardConfiguration.StopTxnSampledData,
  323. // //StandardConfiguration.StopTxnSampledDataMaxLength,
  324. // //StandardConfiguration.SupportedFeatureProfiles,
  325. // //StandardConfiguration.SupportedFeatureProfilesMaxLength,
  326. // //StandardConfiguration.TransactionMessageAttempts,
  327. // //StandardConfiguration.TransactionMessageRetryInterval,
  328. // //StandardConfiguration.UnlockConnectorOnEVSideDisconnect,
  329. // //StandardConfiguration.WebSocketPingInterval
  330. // }
  331. // };
  332. // db.ServerMessage.Add(new ServerMessage()
  333. // {
  334. // ChargeBoxId = session.ChargeBoxId,
  335. // CreatedBy = "Server",
  336. // CreatedOn = DateTime.Now,
  337. // OutAction = Actions.GetConfiguration.ToString(),
  338. // OutRequest = JsonConvert.SerializeObject(core_getConfigReq),
  339. // SerialNo = Guid.Empty.ToString(),
  340. // InMessage = string.Empty
  341. // });
  342. // db.SaveChanges();
  343. //}
  344. }
  345. catch (Exception ex)
  346. {
  347. }
  348. }
  349. var replyResult = _profileHandler.ExecuteCoreRequest(action, session, (IRequest)analysisResult.Message);
  350. if (replyResult.Success)
  351. {
  352. string response = msgAnalyser.GenerateConfirmation(analysisResult.UUID, (IConfirmation)replyResult.Message);
  353. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Confirmation"));
  354. if (action == Actions.BootNotification && replyResult.Message is BootNotificationConfirmation)
  355. {
  356. if (((BootNotificationConfirmation)replyResult.Message).status == Packet.Messages.SubTypes.RegistrationStatus.Accepted)
  357. {
  358. session.IsCheckIn = true;
  359. }
  360. }
  361. }
  362. else
  363. {
  364. string response = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  365. string errorMsg = replyResult.Exception != null ? replyResult.Exception.ToString() : string.Empty;
  366. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  367. }
  368. }
  369. break;
  370. default:
  371. {
  372. string replyMsg = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  373. string errorMsg = string.Format("Couldn't find action name: {0} of profile", action);
  374. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  375. }
  376. break;
  377. }
  378. }
  379. }
  380. private void ProcessConfirmationMessage(MessageResult analysisResult, ClientData session, Actions action)
  381. {
  382. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  383. if (ConfirmMessage(analysisResult))
  384. {
  385. var profileName = profiles.Where(x => x.IsExisted(analysisResult.Action)).Select(x => x.Name).FirstOrDefault();
  386. MessageResult confirmResult = null;
  387. switch (profileName)
  388. {
  389. case "Core":
  390. {
  391. confirmResult = _profileHandler.ExecuteCoreConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
  392. }
  393. break;
  394. default:
  395. {
  396. string replyMsg = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  397. string errorMsg = string.Format("Couldn't find action name: {0} of profile", action);
  398. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  399. }
  400. break;
  401. }
  402. if (confirmResult == null || !confirmResult.Success)
  403. {
  404. logger.Error(string.Format("Action:{0} MessageId:{1} ExecuteConfirm Error:{2} ",
  405. analysisResult.Action, analysisResult.UUID, confirmResult.Exception.ToString()));
  406. }
  407. }
  408. else
  409. {
  410. string replyMsg = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  411. string errorMsg = string.Format("Action:{0} MessageId:{1} didn't exist in confirm message", analysisResult.Action, analysisResult.UUID);
  412. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  413. }
  414. }
  415. private void ProcessErrorMessage(MessageResult analysisResult, ClientData session, Actions action)
  416. {
  417. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  418. if (ConfirmMessage(analysisResult))
  419. {
  420. var profileName = profiles.Where(x => x.IsExisted(analysisResult.Action)).Select(x => x.Name).FirstOrDefault();
  421. switch (profileName)
  422. {
  423. case "Core":
  424. {
  425. _profileHandler.ReceivedCoreError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
  426. }
  427. break;
  428. default:
  429. {
  430. string replyMsg = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  431. string errorMsg = string.Format("Couldn't find action name: {0} of profile", action);
  432. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  433. }
  434. break;
  435. }
  436. }
  437. else
  438. {
  439. string replyMsg = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  440. string errorMsg = string.Format("Action:{0} MessageId:{1} didn't exist in confirm message", analysisResult.Action, analysisResult.UUID);
  441. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  442. }
  443. }
  444. private void Send(ClientData session, string msg, string messageType, string errorMsg = "")
  445. {
  446. try
  447. {
  448. if (session != null)
  449. {
  450. WriteMachineLog(session.ChargeBoxId, msg, messageType, errorMsg);
  451. session.Send(msg);
  452. }
  453. }
  454. catch (Exception ex)
  455. {
  456. logger.Error(string.Format("Send Ex:{0}", ex.ToString()));
  457. }
  458. }
  459. private void ServerMessageTrigger()
  460. {
  461. for (; ; )
  462. {
  463. if (_ct.IsCancellationRequested)
  464. {
  465. break;
  466. }
  467. try
  468. {
  469. RemoveConfirmMessage();
  470. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  471. using (var db = new MainDBContext())
  472. {
  473. DateTime startDt = DateTime.Now.AddSeconds(-30);
  474. DateTime dt = new DateTime(1991, 1, 1);
  475. Console.WriteLine(string.Format("{0} IN", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
  476. var commandList = db.ServerMessage.Where(c => c.ReceivedOn == dt && c.CreatedOn >= startDt && c.CreatedOn <= DateTime.Now).AsNoTracking().ToList();
  477. //處理主機傳送的有指令
  478. var cmdMachineList = commandList.Select(c => c.ChargeBoxId).Distinct().ToList();
  479. foreach (var charger_SN in cmdMachineList)
  480. {
  481. ClientData session;
  482. string uuid = string.Empty;
  483. if (ClientDic.TryGetValue(charger_SN, out session))
  484. {
  485. Console.WriteLine(string.Format("charger_SN:{0} startDt:{1} CreatedOn:{2}", charger_SN, startDt.ToString("yyyy/MM/dd HH:mm:ss"), DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
  486. if (session.IsCheckIn)
  487. {
  488. var cmdList = commandList.Where(c => c.ChargeBoxId == charger_SN).ToList();
  489. foreach (var item in cmdList)
  490. {
  491. IRequest request = null;
  492. Actions action = Actions.None;
  493. Enum.TryParse(item.OutAction, out action);
  494. Type _RequestType = null;
  495. for (int i = 0; i < profiles.Count; i++)
  496. {
  497. var feature = profiles[i].GetFeaturebyAction(item.OutAction);
  498. if (feature != null)
  499. {
  500. _RequestType = feature.GetRequestType();
  501. break;
  502. }
  503. }
  504. if (_RequestType != null)
  505. {
  506. request = JsonConvert.DeserializeObject(item.OutRequest, _RequestType) as IRequest;
  507. uuid = session.queue.store(request);
  508. string rawRequest = msgAnalyser.GenerateRequest(uuid, item.OutAction, request);
  509. Send(session, rawRequest, string.Format("{0} {1}", action, "Request"), "");
  510. }
  511. AddConfirmMessage(charger_SN, item.Id, item.SerialNo, item.OutAction, uuid);
  512. }
  513. }
  514. }
  515. }
  516. }
  517. Task.Delay(2000);
  518. }
  519. catch (Exception ex)
  520. {
  521. logger.Error("ServerMessageTrigger stop");
  522. logger.Error(ex);
  523. }
  524. }
  525. }
  526. private void AddConfirmMessage(string chargePointSerialNumber, int table_id, string requestId, string action, string msg_id)
  527. {
  528. NeedConfirmMessage _needConfirmMsg = new NeedConfirmMessage();
  529. _needConfirmMsg.Id = table_id;
  530. _needConfirmMsg.SentAction = action;
  531. _needConfirmMsg.SentOn = DateTime.Now;
  532. _needConfirmMsg.SentTimes = 1;
  533. _needConfirmMsg.ChargePointSerialNumber = chargePointSerialNumber;
  534. _needConfirmMsg.RequestId = requestId;
  535. _needConfirmMsg.SentUniqueId = msg_id;
  536. if (_needConfirmActions.Contains(action))
  537. {
  538. lock (_lockConfirmPacketList)
  539. {
  540. NeedConfirmPacketList.Add(_needConfirmMsg);
  541. }
  542. }
  543. }
  544. private void RemoveConfirmMessage()
  545. {
  546. var before_3mins = DateTime.Now.AddMinutes(-3);
  547. lock (_lockConfirmPacketList)
  548. {
  549. var removeList = NeedConfirmPacketList.Where(x => x.SentTimes == 0 || x.SentOn < before_3mins).ToList();
  550. foreach (var item in removeList)
  551. {
  552. NeedConfirmPacketList.Remove(item);
  553. }
  554. }
  555. }
  556. private bool ConfirmMessage(MessageResult analysisResult)
  557. {
  558. bool confirmed = false;
  559. if (_needConfirmActions.Contains(analysisResult.Action))
  560. {
  561. NeedConfirmMessage foundRequest = null;
  562. lock (_lockConfirmPacketList)
  563. {
  564. foundRequest = NeedConfirmPacketList.Where(x => x.SentUniqueId == analysisResult.UUID).FirstOrDefault();
  565. }
  566. if (foundRequest.Id > 0)
  567. {
  568. foundRequest.SentTimes = 0;
  569. foundRequest.SentInterval = 0;
  570. analysisResult.RequestId = foundRequest.RequestId;
  571. using (var db = new MainDBContext())
  572. {
  573. var sc = db.ServerMessage.Where(x => x.Id == foundRequest.Id).FirstOrDefault();
  574. sc.InMessage = JsonConvert.SerializeObject(analysisResult.Message, Formatting.Indented);
  575. sc.ReceivedOn = DateTime.Now;
  576. db.SaveChanges();
  577. }
  578. confirmed = true;
  579. }
  580. else
  581. {
  582. logger.Error(string.Format("Received no record Action:{0} MessageId:{1} ", analysisResult.Action, analysisResult.UUID));
  583. }
  584. }
  585. return confirmed;
  586. }
  587. private void RemoveClient(ClientData session)
  588. {
  589. logger.Trace("RemoveClient" + session.ChargeBoxId);
  590. RemoveClientDic(session);
  591. if (session != null)
  592. {
  593. try
  594. {
  595. session.m_ReceiveData -= new ClientData.OCPPClientDataEventHandler<ClientData, String>(ReceivedMessage);
  596. session.Close(CloseReason.ServerClosing);
  597. }
  598. catch (Exception ex)
  599. {
  600. //logger.Warn("Close client socket error!!");
  601. logger.Warn(string.Format("Close client socket error!! {0} Msg:{1}", session.ChargeBoxId, ex.Message));
  602. }
  603. if (session != null)
  604. {
  605. session = null;
  606. }
  607. }
  608. }
  609. private void RemoveClientDic(ClientData session)
  610. {
  611. lock (_lockClientDic)
  612. {
  613. if (ClientDic.ContainsKey(session.ChargeBoxId))
  614. {
  615. ClientDic.Remove(session.ChargeBoxId);
  616. logger.Trace("RemoveClient ContainsKey " + session.ChargeBoxId);
  617. }
  618. }
  619. }
  620. private void WriteMachineLog(string sn, string data, string messageType, string errorMsg = "")
  621. {
  622. using (var db = new ConnectionLogDBContext())
  623. {
  624. string sp = "[dbo].[uspInsertMachineConnectionLog] @CreatedOn," +
  625. "@ChargeBoxId,@MessageType,@Data,@Msg";
  626. var dd = DateTime.Now.AddDays(-1);
  627. SqlParameter[] parameter =
  628. {
  629. new SqlParameter("CreatedOn",dd),
  630. new SqlParameter("ChargeBoxId",sn.Replace("'","''")),
  631. new SqlParameter("MessageType",messageType.Replace("'","''")),
  632. new SqlParameter("Data",data.Replace("'","''")),
  633. new SqlParameter("Msg",errorMsg.Replace("'","''"))
  634. };
  635. db.Database.ExecuteSqlCommand(sp, parameter);
  636. }
  637. }
  638. }
  639. }