ProtalServer.cs 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247
  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. using EVCB_OCPP.Packet.Messages.FirmwareManagement;
  28. using EVCB_OCPP.Packet.Messages.RemoteTrigger;
  29. using System.Configuration;
  30. using System.Net;
  31. using System.Net.Security;
  32. using System.Security.Cryptography.X509Certificates;
  33. using EVCB_OCPP.WSServer.Service;
  34. using EVCB_OCPP.Packet.Messages.SmartCharging;
  35. using System.Security.Authentication;
  36. namespace EVCB_OCPP.WSServer
  37. {
  38. internal class ProtalServer
  39. {
  40. static private ILogger logger = NLog.LogManager.GetCurrentClassLogger();
  41. private Dictionary<string, ClientData> clientDic = new Dictionary<string, ClientData>();
  42. private readonly Object _lockClientDic = new object();
  43. private readonly Object _lockConfirmPacketList = new object();
  44. private ProfileHandler profileHandler = new ProfileHandler();
  45. private List<NeedConfirmMessage> needConfirmPacketList = new List<NeedConfirmMessage>();
  46. private DateTime checkUpdateDt = DateTime.Now;
  47. private LoadingBalanceService _loadingBalanceService = new LoadingBalanceService();
  48. private List<string> needConfirmActions = new List<string>()
  49. {
  50. "GetConfiguration",
  51. "ChangeConfiguration",
  52. "RemoteStartTransaction",
  53. "RemoteStopTransaction",
  54. "ChangeAvailability",
  55. "ClearCache",
  56. "DataTransfer",
  57. "Reset",
  58. "UnlockConnector",
  59. "TriggerMessage",
  60. "GetDiagnostics",
  61. "UpdateFirmware",
  62. "GetLocalListVersion",
  63. "SendLocalList",
  64. "SetChargingProfile",
  65. "ClearChargingProfile",
  66. "GetCompositeSchedule",
  67. "ReserveNow",
  68. "CancelReservation",
  69. };
  70. private List<Profile> profiles = new List<Profile>()
  71. {
  72. new CoreProfile(),
  73. new FirmwareManagementProfile(),
  74. new ReservationProfile(),
  75. new RemoteTriggerProfile(),
  76. new SmartChargingProfile(),
  77. new LocalAuthListManagementProfile()
  78. };
  79. private CancellationTokenSource _cts = new CancellationTokenSource();
  80. private CancellationToken _ct;
  81. internal ProtalServer()
  82. {
  83. _ct = _cts.Token;
  84. WarmUpLog();
  85. }
  86. internal void Start()
  87. {
  88. if (!GlobalConfig.LoadAPPConfig())
  89. {
  90. Console.WriteLine("Please check App.Config setting .");
  91. return;
  92. }
  93. OpenNetwork();
  94. Task serverCommandTask = new Task(ServerMessageTrigger, _ct);
  95. serverCommandTask.Start();
  96. Task serverUpdateTask = new Task(ServerUpdateTrigger, _ct);
  97. serverUpdateTask.Start();
  98. Task serverHealthTask = new Task(HealthAlarmTrigger, _ct);
  99. serverHealthTask.Start();
  100. while (true)
  101. {
  102. var input = Console.ReadLine();
  103. switch (input.ToLower())
  104. {
  105. case "stop":
  106. logger.Info("Command stop");
  107. Stop();
  108. break;
  109. case "gc":
  110. logger.Info("Command GC");
  111. GC.Collect();
  112. break;
  113. case "lc":
  114. {
  115. logger.Info("Command List Clients");
  116. Dictionary<string, ClientData> _copyClientDic = null;
  117. lock (_lockClientDic)
  118. {
  119. _copyClientDic = new Dictionary<string, ClientData>(clientDic);
  120. }
  121. var list = _copyClientDic.Select(c => c.Value).ToList();
  122. int i = 1;
  123. foreach (var c in list)
  124. {
  125. logger.Info(i + ":" + c.ChargeBoxId + " " + c.SessionID);
  126. i++;
  127. }
  128. }
  129. break;
  130. case "lcn":
  131. {
  132. logger.Info("Command List Customer Name");
  133. Dictionary<string, ClientData> _copyClientDic = null;
  134. lock (_lockClientDic)
  135. {
  136. _copyClientDic = new Dictionary<string, ClientData>(clientDic);
  137. }
  138. var lcn = clientDic.Select(c => c.Value.CustomerName).Distinct().ToList();
  139. int iLcn = 1;
  140. foreach (var c in lcn)
  141. {
  142. logger.Info(iLcn + ":" + c + ":" + clientDic.Where(z => z.Value.CustomerName == c).Count().ToString());
  143. iLcn++;
  144. }
  145. }
  146. break;
  147. case "help":
  148. logger.Info("Command help!!");
  149. logger.Info("lcn : List Customer Name");
  150. logger.Info("gc : GC Collect");
  151. logger.Info("lc : List Clients");
  152. logger.Info("cls : clear console");
  153. logger.Info("silent : silent");
  154. logger.Info("show : show log");
  155. // logger.Info("rcl : show Real Connection Limit");
  156. break;
  157. case "cls":
  158. logger.Info("Command clear");
  159. Console.Clear();
  160. break;
  161. case "silent":
  162. logger.Info("Command silent");
  163. var xe = XElement.Load("NLog.config");
  164. var xns = xe.GetDefaultNamespace();
  165. var minlevelattr = xe.Descendants(xns + "rules").Elements(xns + "logger")
  166. .Where(c => c.Attribute("writeTo").Value.Equals("console")).Attributes("minlevel").FirstOrDefault();
  167. if (minlevelattr != null)
  168. {
  169. minlevelattr.Value = "info";
  170. }
  171. xe.Save("NLog.config");
  172. break;
  173. case "show":
  174. logger.Info("Command show");
  175. var xe1 = XElement.Load("NLog.config");
  176. var xns1 = xe1.GetDefaultNamespace();
  177. var minlevelattr1 = xe1.Descendants(xns1 + "rules").Elements(xns1 + "logger")
  178. .Where(c => c.Attribute("writeTo").Value.Equals("console")).Attributes("minlevel").FirstOrDefault();
  179. if (minlevelattr1 != null)
  180. {
  181. minlevelattr1.Value = "trace";
  182. }
  183. xe1.Save("NLog.config");
  184. break;
  185. case "rcl":
  186. break;
  187. default:
  188. break;
  189. }
  190. }
  191. }
  192. internal void Stop()
  193. {
  194. if (_cts != null)
  195. {
  196. _cts.Cancel();
  197. }
  198. }
  199. private void CheckEVSEConfigure(string chargeBoxId)
  200. {
  201. int skipCount = 0;
  202. int takeCount = 8;
  203. using (var db = new MainDBContext())
  204. {
  205. string maxKeys = StandardConfiguration.AllConfigs.Skip(skipCount).Take(1).FirstOrDefault();
  206. if (maxKeys == StandardConfiguration.GetConfigurationMaxKeys)
  207. {
  208. var _Configure = db.MachineConfiguration.Where(x => x.ChargeBoxId == chargeBoxId && x.ConfigureName == maxKeys).Select(x => new { ConfigureSetting = x.ConfigureSetting, ConfigureName = x.ConfigureName }).FirstOrDefault();
  209. if (_Configure != null)
  210. {
  211. int cp_ConfiureCount = 0;
  212. int.TryParse(_Configure.ConfigureSetting, out cp_ConfiureCount);
  213. takeCount = takeCount > cp_ConfiureCount ? cp_ConfiureCount : takeCount;
  214. skipCount = 1;
  215. if (string.IsNullOrEmpty(_Configure.ConfigureSetting)) return;
  216. }
  217. }
  218. while (StandardConfiguration.AllConfigs.Count > skipCount)
  219. {
  220. string _key = StandardConfiguration.AllConfigs.Skip(skipCount).Take(1).FirstOrDefault();
  221. var _Configure = db.MachineConfiguration.Where(x => x.ChargeBoxId == chargeBoxId && x.ConfigureName == _key).Select(x => new { ConfigureSetting = x.ConfigureSetting, ConfigureName = x.ConfigureName }).FirstOrDefault();
  222. takeCount = StandardConfiguration.AllConfigs.Count - skipCount > takeCount ? takeCount : StandardConfiguration.AllConfigs.Count - skipCount;
  223. var _keys = StandardConfiguration.AllConfigs.Skip(skipCount).Take(takeCount).ToList();
  224. // Console.WriteLine("===============Skip:" + skipCount);
  225. if (_Configure == null)
  226. {
  227. // Console.WriteLine("_Configure == null===============Skip:" + skipCount);
  228. db.ServerMessage.Add(new ServerMessage()
  229. {
  230. ChargeBoxId = chargeBoxId,
  231. CreatedBy = "Server",
  232. CreatedOn = DateTime.Now,
  233. OutAction = Actions.GetConfiguration.ToString(),
  234. OutRequest = JsonConvert.SerializeObject(
  235. new GetConfigurationRequest()
  236. {
  237. key = _keys
  238. },
  239. new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
  240. SerialNo = Guid.NewGuid().ToString(),
  241. InMessage = string.Empty
  242. });
  243. db.SaveChanges();
  244. }
  245. skipCount = skipCount + takeCount;
  246. }
  247. }
  248. }
  249. private void OpenNetwork()
  250. {
  251. //載入OCPP Protocol
  252. var appServer = new OCPPWSServer(new List<OCPPSubProtocol>() { new OCPPSubProtocol(), new OCPPSubProtocol(" ocpp1.6") });
  253. List<IListenerConfig> llistener = new List<IListenerConfig>();
  254. //System.Net.IPAddress.Any.ToString()
  255. // llistener.Add(new ListenerConfig { Ip = "", Port = Convert.ToInt32(wssserverPort), Backlog = 100, Security = serverSecurity });
  256. llistener.Add(new ListenerConfig { Ip = System.Net.IPAddress.Any.ToString(), Port = Convert.ToInt32(GlobalConfig.GetWS_Port()), Backlog = 100, Security = "None" });
  257. llistener.Add(new ListenerConfig { Ip = System.Net.IPAddress.Any.ToString(), Port = Convert.ToInt32(GlobalConfig.GetWSS_Port()), Backlog = 100, Security = SslProtocols.Tls12.ToString() });
  258. // llistener.Add(new ListenerConfig { Ip = System.Net.IPAddress.Any.ToString(), Port = Convert.ToInt32(GlobalConfig.GetWSS_Port()), Backlog = 100, Security = SslProtocols.Tls11.ToString() });
  259. var config = ConfigurationManager.GetSection("superSocket") as IConfigurationSource;
  260. ICertificateConfig Certificate = config.Servers.ElementAt(0).Certificate;
  261. IEnumerable<IListenerConfig> listeners = llistener;
  262. //設定server config
  263. var serverConfig = new ServerConfig
  264. {
  265. //Port = Convert.ToInt32(2012),
  266. //Ip = "172.17.40.13",
  267. MaxRequestLength = 4096,
  268. //Security = serverSecurity,
  269. Certificate = Certificate,
  270. Listeners = listeners,
  271. LogAllSocketException = true,
  272. KeepAliveTime = 10,
  273. LogBasicSessionActivity = true
  274. };
  275. //Setup with listening port
  276. if (!appServer.Setup(serverConfig, logFactory: new OCPPLogFactory()))
  277. {
  278. Console.WriteLine("Failed to setup!");
  279. return;
  280. }
  281. appServer.NewSessionConnected += AppServer_NewSessionConnected;
  282. appServer.SessionClosed += AppServer_SessionClosed;
  283. //Try to start the appServer
  284. if (!appServer.Start())
  285. {
  286. Console.WriteLine("Failed to start!");
  287. Console.ReadKey();
  288. return;
  289. }
  290. }
  291. private void AppServer_SessionClosed(ClientData session, CloseReason value)
  292. {
  293. // Console.WriteLine(session.RemoteEndPoint.Address);
  294. WriteMachineLog(session, string.Format("CloseReason: {0}", value), "Connection", "");
  295. RemoveClient(session);
  296. // close Connection
  297. }
  298. private void AppServer_NewSessionConnected(ClientData session)
  299. {
  300. try
  301. {
  302. lock (_lockClientDic)
  303. {
  304. bool isNotSupported = session.SecWebSocketProtocol.Contains("ocpp1.6") ? false : true;
  305. if (isNotSupported)
  306. {
  307. //logger.Debug(string.Format("ChargeBoxId:{0} SecWebSocketProtocol:{1} NotSupported", session.ChargeBoxId, session.SecWebSocketProtocol));
  308. WriteMachineLog(session, string.Format("SecWebSocketProtocol:{0} NotSupported", session.SecWebSocketProtocol), "Connection", "");
  309. return;
  310. }
  311. ClientData _removeClient = null;
  312. clientDic.TryGetValue(session.ChargeBoxId, out _removeClient);
  313. if (_removeClient != null)
  314. {
  315. WriteMachineLog(_removeClient, "Duplicate Logins", "Connection", "");
  316. _removeClient.Close(CloseReason.ServerShutdown);
  317. RemoveClient(_removeClient);
  318. }
  319. session.IsCheckIn = true;
  320. clientDic.Add(session.ChargeBoxId, session);
  321. session.m_ReceiveData += new ClientData.OCPPClientDataEventHandler<ClientData, String>(ReceivedMessage);
  322. // logger.Debug("------------New " + (session == null ? "Oops" : session.ChargeBoxId));
  323. WriteMachineLog(session, "NewSessionConnected", "Connection", "");
  324. using (var db = new MainDBContext())
  325. {
  326. var machine = db.Machine.Where(x => x.ChargeBoxId == session.ChargeBoxId).FirstOrDefault();
  327. if (machine != null)
  328. {
  329. machine.ConnectionType = session.Origin.Contains("https") ? 2 : 1;
  330. db.SaveChanges();
  331. }
  332. }
  333. CheckEVSEConfigure(session.ChargeBoxId);
  334. }
  335. }
  336. catch (Exception ex)
  337. {
  338. logger.Error(string.Format("NewSessionConnected Ex: {0}", ex.ToString()));
  339. }
  340. }
  341. async private void ReceivedMessage(ClientData session, string rawdata)
  342. {
  343. try
  344. {
  345. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  346. MessageResult analysisResult = msgAnalyser.AnalysisReceiveData(session, rawdata);
  347. WriteMachineLog(session, rawdata,
  348. string.Format("{0} {1}", string.IsNullOrEmpty(analysisResult.Action) ? "unknown" : analysisResult.Action, analysisResult.Id == 2 ? "Request" : (analysisResult.Id == 3 ? "Confirmation" : "Error")), string.IsNullOrEmpty(analysisResult.CallErrorMsg) ? "" : analysisResult.Exception.Message);
  349. if (!analysisResult.Success)
  350. {
  351. //解析RawData就發生錯誤
  352. if (!string.IsNullOrEmpty(analysisResult.CallErrorMsg))
  353. {
  354. Send(session, analysisResult.CallErrorMsg, string.Format("{0} {1}", analysisResult.Action, "Error"));
  355. }
  356. else
  357. {
  358. BaseMessage _baseMsg = analysisResult.Message as BaseMessage;
  359. string replyMsg = msgAnalyser.GenerateCallError(_baseMsg.Id, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  360. string errorMsg = string.Empty;
  361. if (analysisResult.Exception != null)
  362. {
  363. errorMsg = analysisResult.Exception.ToString();
  364. }
  365. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  366. }
  367. }
  368. else
  369. {
  370. Actions action = Convertor.GetAction(analysisResult.Action);
  371. switch (analysisResult.Id)
  372. {
  373. case BasicMessageHandler.TYPENUMBER_CALL:
  374. {
  375. ProcessRequestMessage(analysisResult, session, action);
  376. }
  377. break;
  378. case BasicMessageHandler.TYPENUMBER_CALLRESULT:
  379. {
  380. ProcessConfirmationMessage(analysisResult, session, action);
  381. }
  382. break;
  383. case BasicMessageHandler.TYPENUMBER_CALLERROR:
  384. {
  385. //只處理 丟出Request 收到Error的訊息
  386. if (analysisResult.Success && analysisResult.Message != null)
  387. {
  388. ProcessErrorMessage(analysisResult, session, action);
  389. }
  390. }
  391. break;
  392. default:
  393. {
  394. logger.Error(string.Format("Can't analyze messagetype:{0} of raw data :{1} by {2}", analysisResult.Id, rawdata, session.ChargeBoxId));
  395. }
  396. break;
  397. }
  398. }
  399. await Task.Delay(10);
  400. }
  401. catch (Exception ex)
  402. {
  403. logger.Error(string.Format("**Exception :{0} ", ex.ToString()));
  404. if (ex.InnerException != null)
  405. {
  406. logger.Error(string.Format("**Inner exception :{0} ", ex.InnerException.ToString()));
  407. }
  408. }
  409. }
  410. async private void ProcessRequestMessage(MessageResult analysisResult, ClientData session, Actions action)
  411. {
  412. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  413. if (!session.IsCheckIn && action != Actions.BootNotification)
  414. {
  415. string response = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.GenericError, OCPPErrorDescription.NotChecked);
  416. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"));
  417. }
  418. else
  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. bool oldstatus = session.IsCheckIn;
  426. var replyResult = await profileHandler.ExecuteCoreRequest(action, session, (IRequest)analysisResult.Message);
  427. if (replyResult.Success)
  428. {
  429. string response = msgAnalyser.GenerateConfirmation(analysisResult.UUID, (IConfirmation)replyResult.Message);
  430. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Confirmation"));
  431. if (action == Actions.BootNotification && replyResult.Message is BootNotificationConfirmation)
  432. {
  433. if (((BootNotificationConfirmation)replyResult.Message).status == Packet.Messages.SubTypes.RegistrationStatus.Accepted)
  434. {
  435. session.IsCheckIn = true;
  436. if (!oldstatus)
  437. {
  438. using (var db = new MainDBContext())
  439. {
  440. var machine = db.Machine.Where(x => x.ChargeBoxId == session.ChargeBoxId).FirstOrDefault();
  441. if (machine != null)
  442. {
  443. machine.ConnectionType = session.Origin.Contains("https") ? 2 : 1;
  444. db.SaveChanges();
  445. }
  446. }
  447. // CheckEVSEConfigure(session.ChargeBoxId);
  448. }
  449. }
  450. }
  451. }
  452. else
  453. {
  454. string response = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  455. string errorMsg = replyResult.Exception != null ? replyResult.Exception.ToString() : string.Empty;
  456. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  457. }
  458. if (action == Actions.StartTransaction)
  459. {
  460. var stationId = _loadingBalanceService.GetStationIdByMachineId(session.MachineId);
  461. var _powerDic = _loadingBalanceService.GetSettingPower(stationId, session.MachineId);
  462. if (_powerDic != null)
  463. {
  464. foreach (var kv in _powerDic)
  465. {
  466. try
  467. {
  468. string chargeBoxId = string.Empty;
  469. //set profile
  470. lock (_lockClientDic)
  471. {
  472. chargeBoxId = clientDic.Where(x => x.Value.MachineId == kv.Key).Select(x => x.Value.ChargeBoxId).FirstOrDefault();
  473. }
  474. if (chargeBoxId != null && kv.Value.HasValue)
  475. {
  476. profileHandler.SetChargingProfile(chargeBoxId, kv.Value.Value, Packet.Messages.SubTypes.ChargingRateUnitType.W);
  477. }
  478. }
  479. catch (Exception ex)
  480. {
  481. logger.Error(string.Format("Set Profile Exception: {0}", ex.ToString()));
  482. }
  483. }
  484. }
  485. }
  486. if (action == Actions.StopTransaction)
  487. {
  488. var stationId = _loadingBalanceService.GetStationIdByMachineId(session.MachineId);
  489. if (_loadingBalanceService.IsNeedtoCancelSetting(stationId, session.MachineId, session.ChargeBoxId))
  490. {
  491. //Clear current profile
  492. profileHandler.ClearChargingProfile(session.ChargeBoxId);
  493. var _powerDic = _loadingBalanceService.GetRerangeSettingPower(stationId);
  494. if (_powerDic != null)
  495. {
  496. foreach (var kv in _powerDic)
  497. {
  498. try
  499. {
  500. string chargeBoxId = string.Empty;
  501. //set profile
  502. lock (_lockClientDic)
  503. {
  504. chargeBoxId = clientDic.Where(x => x.Value.MachineId == kv.Key).Select(x => x.Value.ChargeBoxId).FirstOrDefault();
  505. }
  506. if (chargeBoxId != null && kv.Value.HasValue)
  507. {
  508. profileHandler.SetChargingProfile(chargeBoxId, kv.Value.Value, Packet.Messages.SubTypes.ChargingRateUnitType.W);
  509. }
  510. }
  511. catch (Exception ex)
  512. {
  513. logger.Error(string.Format("Set Profile Exception: {0}", ex.ToString()));
  514. }
  515. }
  516. }
  517. }
  518. }
  519. }
  520. break;
  521. case "FirmwareManagement":
  522. {
  523. var replyResult = profileHandler.ExecuteFirmwareManagementRequest(action, session, (IRequest)analysisResult.Message);
  524. if (replyResult.Success)
  525. {
  526. string response = msgAnalyser.GenerateConfirmation(analysisResult.UUID, (IConfirmation)replyResult.Message);
  527. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Confirmation"));
  528. }
  529. else
  530. {
  531. string response = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  532. string errorMsg = replyResult.Exception != null ? replyResult.Exception.ToString() : string.Empty;
  533. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  534. }
  535. }
  536. break;
  537. default:
  538. {
  539. string replyMsg = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  540. string errorMsg = string.Format("Couldn't find action name: {0} of profile", action);
  541. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  542. }
  543. break;
  544. }
  545. }
  546. }
  547. private void ProcessConfirmationMessage(MessageResult analysisResult, ClientData session, Actions action)
  548. {
  549. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  550. if (ReConfirmMessage(analysisResult))
  551. {
  552. var profileName = profiles.Where(x => x.IsExisted(analysisResult.Action)).Select(x => x.Name).FirstOrDefault();
  553. MessageResult confirmResult = null;
  554. switch (profileName)
  555. {
  556. case "Core":
  557. {
  558. confirmResult = profileHandler.ExecuteCoreConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
  559. }
  560. break;
  561. case "FirmwareManagement":
  562. {
  563. confirmResult = profileHandler.ExecuteFirmwareManagementConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
  564. }
  565. break;
  566. case "RemoteTrigger":
  567. {
  568. confirmResult = profileHandler.ExecuteRemoteTriggerConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
  569. }
  570. break;
  571. case "Reservation":
  572. {
  573. confirmResult = profileHandler.ExecuteReservationConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
  574. }
  575. break;
  576. case "LocalAuthListManagement":
  577. {
  578. confirmResult = profileHandler.ExecuteLocalAuthListManagementConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
  579. }
  580. break;
  581. case "SmartCharging":
  582. {
  583. confirmResult = profileHandler.ExecuteSmartChargingConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
  584. }
  585. break;
  586. default:
  587. {
  588. string replyMsg = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  589. string errorMsg = string.Format("Couldn't find action name: {0} of profile", action);
  590. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  591. }
  592. break;
  593. }
  594. if (confirmResult == null || !confirmResult.Success)
  595. {
  596. logger.Error(string.Format("Action:{0} MessageId:{1} ExecuteConfirm Error:{2} ",
  597. analysisResult.Action, analysisResult.UUID, confirmResult.Exception.ToString()));
  598. }
  599. }
  600. else
  601. {
  602. string replyMsg = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  603. string errorMsg = string.Format("Action:{0} MessageId:{1} didn't exist in confirm message", analysisResult.Action, analysisResult.UUID);
  604. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  605. }
  606. }
  607. private void ProcessErrorMessage(MessageResult analysisResult, ClientData session, Actions action)
  608. {
  609. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  610. if (ReConfirmMessage(analysisResult))
  611. {
  612. var profileName = profiles.Where(x => x.IsExisted(analysisResult.Action)).Select(x => x.Name).FirstOrDefault();
  613. switch (profileName)
  614. {
  615. case "Core":
  616. {
  617. profileHandler.ReceivedCoreError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
  618. }
  619. break;
  620. case "FirmwareManagement":
  621. {
  622. profileHandler.ReceivedFirmwareManagementError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
  623. }
  624. break;
  625. case "RemoteTrigger":
  626. {
  627. profileHandler.ReceivedRemoteTriggerError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
  628. }
  629. break;
  630. case "Reservation":
  631. {
  632. profileHandler.ExecuteReservationError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
  633. }
  634. break;
  635. case "LocalAuthListManagement":
  636. {
  637. profileHandler.ReceivedLocalAuthListManagementError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
  638. }
  639. break;
  640. case "SmartCharging":
  641. {
  642. profileHandler.ReceivedSmartChargingError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
  643. }
  644. break;
  645. default:
  646. {
  647. string replyMsg = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  648. string errorMsg = string.Format("Couldn't find action name: {0} of profile", action);
  649. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  650. }
  651. break;
  652. }
  653. }
  654. else
  655. {
  656. string replyMsg = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  657. string errorMsg = string.Format("Action:{0} MessageId:{1} didn't exist in confirm message", analysisResult.Action, analysisResult.UUID);
  658. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  659. }
  660. }
  661. private void Send(ClientData session, string msg, string messageType, string errorMsg = "")
  662. {
  663. try
  664. {
  665. if (session != null)
  666. {
  667. WriteMachineLog(session, msg, messageType, errorMsg, true);
  668. session.Send(msg);
  669. }
  670. }
  671. catch (Exception ex)
  672. {
  673. logger.Error(string.Format("Send Ex:{0}", ex.ToString()));
  674. }
  675. }
  676. async private void ServerUpdateTrigger()
  677. {
  678. for (; ; )
  679. {
  680. if (_ct.IsCancellationRequested)
  681. {
  682. break;
  683. }
  684. var min_Interval = (DateTime.Now - checkUpdateDt).TotalMinutes;
  685. if (min_Interval > 3)
  686. {
  687. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  688. Dictionary<string, ClientData> _copyClientDic = null;
  689. lock (_lockClientDic)
  690. {
  691. _copyClientDic = new Dictionary<string, ClientData>(clientDic);
  692. }
  693. checkUpdateDt = DateTime.Now;
  694. using (var db = new MainDBContext())
  695. {
  696. //var needUpdateChargers = db.Machine.Where(x => x.FW_AssignedMachineVersionId.HasValue == true &&
  697. // x.FW_AssignedMachineVersionId != x.FW_VersionReport && x.Online == true)
  698. // .Select(x => new { x.Id, x.ChargeBoxId, x.FW_AssignedMachineVersionId }).ToList();
  699. var needUpdateChargers = db.Machine.Where(x => x.FW_AssignedVersion.HasValue == true &&
  700. x.FW_AssignedVersion != x.FW_VersionReport && x.Online == true)
  701. .Select(x => x.ChargeBoxId).AsNoTracking().ToList();
  702. foreach (var chargeBoxId in needUpdateChargers)
  703. {
  704. try
  705. {
  706. ClientData session;
  707. if (_copyClientDic.TryGetValue(chargeBoxId, out session))
  708. {
  709. string requestId = Guid.NewGuid().ToString();
  710. // using (var db = new MainDBContext())
  711. if (session.IsCheckIn)
  712. {
  713. var _request = new TriggerMessageRequest()
  714. {
  715. requestedMessage = Packet.Messages.SubTypes.MessageTrigger.FirmwareStatusNotification
  716. };
  717. var uuid = session.queue.store(_request);
  718. string rawRequest = msgAnalyser.GenerateRequest(uuid, _request.Action, _request);
  719. Send(session, rawRequest, string.Format("{0} {1}", _request.Action, "Request"), "");
  720. #region OCTT ,測試韌體更新方式
  721. //--------------------> OCTT ,測試韌體更新方式
  722. //{
  723. // var machine = db.Machine.Where(x => x.FW_AssignedMachineVersionId.HasValue == true &&
  724. // x.FW_AssignedMachineVersionId != x.FW_VersionReport && x.ChargeBoxId == session.ChargeBoxId)
  725. // .Select(x => new { x.Id, x.FW_AssignedMachineVersionId }).FirstOrDefault();
  726. // if (machine != null)
  727. // {
  728. // var mv = db.MachineVersion.Include(c => c.PublishVersion)
  729. // .Include(c => c.PublishVersion.PublishVersionFiles)
  730. // .Include(c => c.PublishVersion.PublishVersionFiles.Select(z => z.UploadFile))
  731. // .Where(c => c.Id == machine.FW_AssignedMachineVersionId.Value).First();
  732. // string downloadUrl = mv.PublishVersion.PublishVersionFiles.FirstOrDefault().UploadFile.FileUrl;
  733. // var _updateFWrequest = new UpdateFirmwareRequest()
  734. // {
  735. // location = new Uri(downloadUrl),
  736. // retries = 3,
  737. // retrieveDate = DateTime.Now,
  738. // retryInterval = 10
  739. // };
  740. // db.MachineOperateRecord.Add(new MachineOperateRecord()
  741. // {
  742. // CreatedOn = DateTime.Now,
  743. // ChargeBoxId = session.ChargeBoxId,
  744. // SerialNo = requestId,
  745. // RequestContent = JsonConvert.SerializeObject(_updateFWrequest, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
  746. // EVSE_Status = 0,
  747. // EVSE_Value = "Fw Version:" + machine.FW_AssignedMachineVersionId,
  748. // Status = 0,
  749. // RequestType = 0,
  750. // });
  751. // db.ServerMessage.Add(new ServerMessage()
  752. // {
  753. // ChargeBoxId = session.ChargeBoxId,
  754. // CreatedBy = "Server",
  755. // CreatedOn = DateTime.Now,
  756. // OutAction = _updateFWrequest.Action.ToString(),
  757. // OutRequest = JsonConvert.SerializeObject(_updateFWrequest, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
  758. // SerialNo = requestId,
  759. // InMessage = string.Empty
  760. // });
  761. // db.SaveChanges();
  762. // }
  763. //}
  764. #endregion
  765. }
  766. }
  767. }
  768. catch (Exception ex)
  769. {
  770. logger.Error(string.Format("serverUpdateTrigger ChargeBoxId:{0} Ex:{1}", chargeBoxId, ex.ToString()));
  771. }
  772. }
  773. }
  774. await Task.Delay(1000);
  775. // Thread.CurrentThread.Join(1000);
  776. }
  777. }
  778. }
  779. async private void ServerMessageTrigger()
  780. {
  781. for (; ; )
  782. {
  783. if (_ct.IsCancellationRequested)
  784. {
  785. break;
  786. }
  787. try
  788. {
  789. RemoveConfirmMessage();
  790. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  791. using (var db = new MainDBContext())
  792. {
  793. DateTime startDt = DateTime.Now.AddSeconds(-30);
  794. DateTime dt = new DateTime(1991, 1, 1);
  795. //Console.WriteLine(string.Format("{0} IN", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
  796. var commandList = db.ServerMessage.Where(c => c.ReceivedOn == dt && c.UpdatedOn == dt && c.CreatedOn >= startDt && c.CreatedOn <= DateTime.Now).AsNoTracking().ToList();
  797. //處理主機傳送的有指令
  798. var cmdMachineList = commandList.Select(c => c.ChargeBoxId).Distinct().ToList();
  799. if (commandList.Count > 0)
  800. {
  801. Console.WriteLine(string.Format("Now:{0} commandList Count:{1} ", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), commandList.Count));
  802. }
  803. foreach (var charger_SN in cmdMachineList)
  804. {
  805. ClientData session;
  806. string uuid = string.Empty;
  807. if (clientDic.TryGetValue(charger_SN, out session))
  808. {
  809. 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")));
  810. if (session.IsCheckIn)
  811. {
  812. var cmdList = commandList.Where(c => c.ChargeBoxId == charger_SN).ToList();
  813. foreach (var item in cmdList)
  814. {
  815. IRequest request = null;
  816. Actions action = Actions.None;
  817. Enum.TryParse(item.OutAction, out action);
  818. Type _RequestType = null;
  819. for (int i = 0; i < profiles.Count; i++)
  820. {
  821. var feature = profiles[i].GetFeaturebyAction(item.OutAction);
  822. if (feature != null)
  823. {
  824. _RequestType = feature.GetRequestType();
  825. break;
  826. }
  827. }
  828. if (_RequestType != null)
  829. {
  830. request = JsonConvert.DeserializeObject(item.OutRequest, _RequestType) as IRequest;
  831. uuid = session.queue.store(request);
  832. string rawRequest = msgAnalyser.GenerateRequest(uuid, item.OutAction, request);
  833. Send(session, rawRequest, string.Format("{0} {1}", action, "Request"), "");
  834. }
  835. AddConfirmMessage(charger_SN, item.Id, item.SerialNo, item.OutAction, uuid);
  836. #region 更新資料表單一欄位
  837. var _UpdatedItem = new ServerMessage() { Id = item.Id, UpdatedOn = DateTime.Now };
  838. db.Configuration.AutoDetectChangesEnabled = false;//自動呼叫DetectChanges()比對所有的entry集合的每一個屬性Properties的新舊值
  839. db.Configuration.ValidateOnSaveEnabled = false;// 因為Entity有些欄位必填,若不避開會有Validate錯誤
  840. // var _UpdatedItem = db.ServerMessage.Where(x => x.Id == item.Id).FirstOrDefault();
  841. db.ServerMessage.Attach(_UpdatedItem);
  842. _UpdatedItem.UpdatedOn = DateTime.Now;
  843. db.Entry(_UpdatedItem).Property(x => x.UpdatedOn).IsModified = true;// 可以直接使用這方式強制某欄位要更新,只是查詢集合耗效能而己
  844. db.SaveChanges();
  845. #endregion
  846. }
  847. }
  848. }
  849. }
  850. db.ChangeTracker.DetectChanges();
  851. }
  852. await Task.Delay(1000);
  853. // Thread.CurrentThread.Join(1000);
  854. }
  855. catch (Exception ex)
  856. {
  857. logger.Error(string.Format("ServerMessageTrigger Ex:{0}", ex.ToString()));
  858. }
  859. }
  860. }
  861. async private void HealthAlarmTrigger()
  862. {
  863. for (; ; )
  864. {
  865. if (_ct.IsCancellationRequested)
  866. {
  867. break;
  868. }
  869. try
  870. {
  871. Dictionary<string, ClientData> _copyClientDic = null;
  872. lock (_lockClientDic)
  873. {
  874. _copyClientDic = new Dictionary<string, ClientData>(clientDic);
  875. }
  876. var removeClients = _copyClientDic.Where(x => x.Value.LastActiveTime < DateTime.Now.AddSeconds(-120)).Select(x => x.Value).ToList();
  877. foreach (var session in removeClients)
  878. {
  879. Console.WriteLine(string.Format("Server forced to shut down ChargeBox ({0}: LastActiveTime{1})", session.ChargeBoxId, session.LastActiveTime));
  880. RemoveClient(session);
  881. }
  882. await Task.Delay(60000);
  883. }
  884. catch (Exception ex)
  885. {
  886. logger.Error(string.Format("HealthAlarmTrigger Ex:{0}", ex.ToString()));
  887. }
  888. }
  889. }
  890. private void AddConfirmMessage(string chargePointSerialNumber, int table_id, string requestId, string action, string msg_id)
  891. {
  892. NeedConfirmMessage _needConfirmMsg = new NeedConfirmMessage();
  893. _needConfirmMsg.Id = table_id;
  894. _needConfirmMsg.SentAction = action;
  895. _needConfirmMsg.SentOn = DateTime.Now;
  896. _needConfirmMsg.SentTimes = 1;
  897. _needConfirmMsg.ChargePointSerialNumber = chargePointSerialNumber;
  898. _needConfirmMsg.RequestId = requestId;
  899. _needConfirmMsg.SentUniqueId = msg_id;
  900. if (needConfirmActions.Contains(action))
  901. {
  902. lock (_lockConfirmPacketList)
  903. {
  904. needConfirmPacketList.Add(_needConfirmMsg);
  905. if (action == "GetConfiguration")
  906. {
  907. Console.WriteLine("AddConfirmMessage: " + msg_id);
  908. }
  909. }
  910. }
  911. }
  912. private void RemoveConfirmMessage()
  913. {
  914. var before_3mins = DateTime.Now.AddMinutes(-3);
  915. lock (_lockConfirmPacketList)
  916. {
  917. var removeList = needConfirmPacketList.Where(x => x.SentTimes == 0 || x.SentOn < before_3mins).ToList();
  918. foreach (var item in removeList)
  919. {
  920. needConfirmPacketList.Remove(item);
  921. }
  922. }
  923. }
  924. private bool ReConfirmMessage(MessageResult analysisResult)
  925. {
  926. bool confirmed = false;
  927. if (needConfirmActions.Contains(analysisResult.Action))
  928. {
  929. if (analysisResult.Action == "GetConfiguration")
  930. {
  931. Console.WriteLine("ReConfirmMessage: " + analysisResult.UUID);
  932. }
  933. NeedConfirmMessage foundRequest = null;
  934. lock (_lockConfirmPacketList)
  935. {
  936. foundRequest = needConfirmPacketList.Where(x => x.SentUniqueId == analysisResult.UUID).FirstOrDefault();
  937. }
  938. if (foundRequest != null && foundRequest.Id > 0)
  939. {
  940. foundRequest.SentTimes = 0;
  941. foundRequest.SentInterval = 0;
  942. analysisResult.RequestId = foundRequest.RequestId;
  943. using (var db = new MainDBContext())
  944. {
  945. var sc = db.ServerMessage.Where(x => x.Id == foundRequest.Id).FirstOrDefault();
  946. sc.InMessage = JsonConvert.SerializeObject(analysisResult.Message, Formatting.None);
  947. sc.ReceivedOn = DateTime.Now;
  948. db.SaveChanges();
  949. Console.WriteLine(string.Format("Now:{0} ServerMessage Id:{1} ", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), foundRequest.Id));
  950. }
  951. confirmed = true;
  952. }
  953. else if (analysisResult.Action == Actions.TriggerMessage.ToString())
  954. {
  955. confirmed = true;
  956. }
  957. else
  958. {
  959. logger.Error(string.Format("Received no record Action:{0} MessageId:{1} ", analysisResult.Action, analysisResult.UUID));
  960. }
  961. }
  962. return confirmed;
  963. }
  964. private void RemoveClient(ClientData session)
  965. {
  966. Console.WriteLine("*********");
  967. if (session != null)
  968. {
  969. logger.Trace("RemoveClient[" + session.ChargeBoxId + "]");
  970. if (session.Connected)
  971. {
  972. session.Close(CloseReason.ServerShutdown);
  973. }
  974. RemoveClientDic(session);
  975. try
  976. {
  977. session.m_ReceiveData -= new ClientData.OCPPClientDataEventHandler<ClientData, String>(ReceivedMessage);
  978. // session.Close(CloseReason.ServerShutdown);
  979. }
  980. catch (Exception ex)
  981. {
  982. //logger.Warn("Close client socket error!!");
  983. logger.Warn(string.Format("Close client socket error!! {0} Msg:{1}", session.ChargeBoxId, ex.Message));
  984. }
  985. if (session != null)
  986. {
  987. session = null;
  988. }
  989. }
  990. }
  991. private void RemoveClientDic(ClientData session)
  992. {
  993. if (!string.IsNullOrEmpty(session.ChargeBoxId))
  994. {
  995. lock (_lockClientDic)
  996. {
  997. if (clientDic.ContainsKey(session.ChargeBoxId))
  998. {
  999. if (clientDic[session.ChargeBoxId].SessionID == session.SessionID)
  1000. {
  1001. logger.Debug(String.Format("ChargeBoxId:{0} Remove SessionId:{1} Removed SessionId:{2}", session.ChargeBoxId, session.SessionID, clientDic[session.ChargeBoxId].SessionID));
  1002. clientDic.Remove(session.ChargeBoxId);
  1003. logger.Trace("RemoveClient ContainsKey " + session.ChargeBoxId);
  1004. }
  1005. }
  1006. }
  1007. }
  1008. }
  1009. private void WarmUpLog()
  1010. {
  1011. using (var log = new ConnectionLogDBContext())
  1012. {
  1013. log.MachineConnectionLog.ToList();
  1014. }
  1015. }
  1016. private void WriteMachineLog(ClientData clientData, string data, string messageType, string errorMsg = "", bool isSent = false)
  1017. {
  1018. try
  1019. {
  1020. if (clientData == null || string.IsNullOrEmpty(data)) return;
  1021. using (var db = new ConnectionLogDBContext())
  1022. {
  1023. string sp = "[dbo].[uspInsertMachineConnectionLog] @CreatedOn," +
  1024. "@ChargeBoxId,@MessageType,@Data,@Msg,@IsSent,@EVSEEndPoint,@Session";
  1025. var dd = DateTime.UtcNow;
  1026. SqlParameter[] parameter =
  1027. {
  1028. new SqlParameter("CreatedOn",dd),
  1029. new SqlParameter("ChargeBoxId",clientData.ChargeBoxId.Replace("'","''")),
  1030. new SqlParameter("MessageType",messageType.Replace("'","''")),
  1031. new SqlParameter("Data",data.Replace("'","''")),
  1032. new SqlParameter("Msg",errorMsg.Replace("'","''")),
  1033. new SqlParameter("IsSent",isSent),
  1034. new SqlParameter("EVSEEndPoint",clientData.RemoteEndPoint==null?"123":clientData.RemoteEndPoint.ToString()),
  1035. new SqlParameter("Session",clientData.SessionID==null?"123":clientData.SessionID)
  1036. };
  1037. db.Database.ExecuteSqlCommand(sp, parameter);
  1038. }
  1039. }
  1040. catch (Exception ex)
  1041. {
  1042. Console.WriteLine(ex.ToString());
  1043. }
  1044. }
  1045. }
  1046. }