ProtalServer.cs 94 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989
  1. using Dapper;
  2. using EVCB_OCPP.Domain;
  3. using EVCB_OCPP.Domain.Models.Database;
  4. using EVCB_OCPP.Packet.Features;
  5. using EVCB_OCPP.Packet.Messages;
  6. using EVCB_OCPP.Packet.Messages.Basic;
  7. using EVCB_OCPP.Packet.Messages.Core;
  8. using EVCB_OCPP.Packet.Messages.RemoteTrigger;
  9. using EVCB_OCPP.WSServer.Dto;
  10. using EVCB_OCPP.WSServer.Helper;
  11. using EVCB_OCPP.WSServer.Message;
  12. using EVCB_OCPP.WSServer.Service;
  13. using Newtonsoft.Json;
  14. using Newtonsoft.Json.Linq;
  15. using NLog;
  16. using OCPPServer.Protocol;
  17. using OCPPServer.SubProtocol;
  18. using SuperSocket.SocketBase;
  19. using SuperSocket.SocketBase.Config;
  20. using System;
  21. using System.Collections.Generic;
  22. using System.Configuration;
  23. using System.Data;
  24. using System.Data.Entity;
  25. using System.Data.SqlClient;
  26. using System.Diagnostics;
  27. using System.Linq;
  28. using System.Security.Authentication;
  29. using System.Threading;
  30. using System.Threading.Tasks;
  31. using System.Xml.Linq;
  32. namespace EVCB_OCPP.WSServer
  33. {
  34. public class DestroyRequest : IRequest
  35. {
  36. public string Action { get; set; }
  37. public bool TransactionRelated()
  38. {
  39. return false;
  40. }
  41. public bool Validate()
  42. {
  43. return true;
  44. }
  45. }
  46. internal class ProtalServer
  47. {
  48. #region private fields
  49. static private ILogger logger = NLog.LogManager.GetCurrentClassLogger();
  50. private OuterHttpClient httpClient = new OuterHttpClient();
  51. private DateTime lastcheckdt = DateTime.UtcNow.AddSeconds(-20);
  52. private Dictionary<string, ClientData> clientDic = new Dictionary<string, ClientData>();
  53. private readonly Object _lockClientDic = new object();
  54. private readonly Object _lockConfirmPacketList = new object();
  55. private ProfileHandler profileHandler = new ProfileHandler();
  56. private List<NeedConfirmMessage> needConfirmPacketList = new List<NeedConfirmMessage>();
  57. private DateTime checkUpdateDt = DateTime.UtcNow;
  58. private DateTime _CheckFeeDt = DateTime.UtcNow;
  59. private DateTime _CheckLBDt = DateTime.UtcNow;
  60. private DateTime _CheckDenyListDt = DateTime.UtcNow.AddDays(-1);
  61. private LoadingBalanceService _loadingBalanceService = new LoadingBalanceService();
  62. private List<StationInfoDto> _StationInfo = new List<StationInfoDto>();
  63. private List<string> needConfirmActions = new List<string>()
  64. {
  65. "GetConfiguration",
  66. "ChangeConfiguration",
  67. "RemoteStartTransaction",
  68. "RemoteStopTransaction",
  69. "ChangeAvailability",
  70. "ClearCache",
  71. "DataTransfer",
  72. "Reset",
  73. "UnlockConnector",
  74. "TriggerMessage",
  75. "GetDiagnostics",
  76. "UpdateFirmware",
  77. "GetLocalListVersion",
  78. "SendLocalList",
  79. "SetChargingProfile",
  80. "ClearChargingProfile",
  81. "GetCompositeSchedule",
  82. "ReserveNow",
  83. "CancelReservation",
  84. "ExtendedTriggerMessage"
  85. };
  86. private List<Profile> profiles = new List<Profile>()
  87. {
  88. new CoreProfile(),
  89. new FirmwareManagementProfile(),
  90. new ReservationProfile(),
  91. new RemoteTriggerProfile(),
  92. new SmartChargingProfile(),
  93. new LocalAuthListManagementProfile(),
  94. new SecurityProfile(),
  95. };
  96. private CancellationTokenSource _cts = new CancellationTokenSource();
  97. private CancellationToken _ct;
  98. private string webConnectionString = ConfigurationManager.ConnectionStrings["WebDBContext"].ConnectionString;
  99. #endregion
  100. internal ProtalServer()
  101. {
  102. _ct = _cts.Token;
  103. WarmUpLog();
  104. DenyModelCheckTrigger(true);
  105. }
  106. internal void Start()
  107. {
  108. if (!GlobalConfig.LoadAPPConfig())
  109. {
  110. Console.WriteLine("Please check App.Config setting .");
  111. return;
  112. }
  113. OpenNetwork();
  114. Task fillinChargerDataTask = new Task(FillinChargerData, _ct);
  115. fillinChargerDataTask.Start();
  116. Task serverCommandTask = new Task(ServerMessageTrigger, _ct);
  117. serverCommandTask.Start();
  118. Task serverUpdateTask = new Task(ServerUpdateTrigger, _ct);
  119. serverUpdateTask.Start();
  120. Task serverSetFeeTask = new Task(ServerSetFeeTrigger, _ct);
  121. serverSetFeeTask.Start();
  122. Task serverBeatTask = new Task(HeartBeatCheckTrigger, _ct);
  123. serverBeatTask.Start();
  124. Task serverHealthTask = new Task(HealthCheckTrigger, _ct);
  125. serverHealthTask.Start();
  126. Task smartChargingTask = new Task(SmartChargingTrigger, _ct);
  127. smartChargingTask.Start();
  128. Task denyModelCheckTask = new Task(() => DenyModelCheckTrigger(false), _ct);
  129. denyModelCheckTask.Start();
  130. while (true)
  131. {
  132. var input = Console.ReadLine();
  133. switch (input.ToLower())
  134. {
  135. case "stop":
  136. Console.WriteLine("Command stop");
  137. Stop();
  138. break;
  139. case "gc":
  140. Console.WriteLine("Command GC");
  141. GC.Collect();
  142. break;
  143. case "lc":
  144. {
  145. Console.WriteLine("Command List Clients");
  146. Dictionary<string, ClientData> _copyClientDic = null;
  147. lock (_lockClientDic)
  148. {
  149. _copyClientDic = new Dictionary<string, ClientData>(clientDic);
  150. }
  151. var list = _copyClientDic.Where(x => x.Value.CustomerId == Guid.Empty).Select(c => c.Value).ToList();
  152. int i = 1;
  153. foreach (var c in list)
  154. {
  155. Console.WriteLine(i + ":" + c.ChargeBoxId + " " + c.SessionID);
  156. i++;
  157. }
  158. }
  159. break;
  160. case "lcn":
  161. {
  162. Console.WriteLine("Command List Customer Name");
  163. Dictionary<string, ClientData> _copyClientDic = null;
  164. lock (_lockClientDic)
  165. {
  166. _copyClientDic = new Dictionary<string, ClientData>(clientDic);
  167. }
  168. var lcn = clientDic.Select(c => c.Value.CustomerId).Distinct().ToList();
  169. int iLcn = 1;
  170. foreach (var c in lcn)
  171. {
  172. Console.WriteLine(iLcn + ":" + c + ":" + clientDic.Where(z => z.Value.CustomerId == c).Count().ToString());
  173. iLcn++;
  174. }
  175. }
  176. break;
  177. case "help":
  178. Console.WriteLine("Command help!!");
  179. Console.WriteLine("lcn : List Customer Name");
  180. Console.WriteLine("gc : GC Collect");
  181. Console.WriteLine("lc : List Clients");
  182. Console.WriteLine("cls : clear console");
  183. Console.WriteLine("silent : silent");
  184. Console.WriteLine("show : show log");
  185. // logger.Info("rcl : show Real Connection Limit");
  186. break;
  187. case "cls":
  188. Console.WriteLine("Command clear");
  189. Console.Clear();
  190. break;
  191. case "silent":
  192. Console.WriteLine("Command silent");
  193. var xe = XElement.Load("NLog.config");
  194. var xns = xe.GetDefaultNamespace();
  195. var minlevelattr = xe.Descendants(xns + "rules").Elements(xns + "logger")
  196. .Where(c => c.Attribute("writeTo").Value.Equals("console")).Attributes("minlevel").FirstOrDefault();
  197. if (minlevelattr != null)
  198. {
  199. minlevelattr.Value = "Warn";
  200. }
  201. xe.Save("NLog.config");
  202. break;
  203. case "show":
  204. Console.WriteLine("Command show");
  205. var xe1 = XElement.Load("NLog.config");
  206. var xns1 = xe1.GetDefaultNamespace();
  207. var minlevelattr1 = xe1.Descendants(xns1 + "rules").Elements(xns1 + "logger")
  208. .Where(c => c.Attribute("writeTo").Value.Equals("console")).Attributes("minlevel").FirstOrDefault();
  209. if (minlevelattr1 != null)
  210. {
  211. minlevelattr1.Value = "trace";
  212. }
  213. xe1.Save("NLog.config");
  214. break;
  215. case "rcl":
  216. break;
  217. default:
  218. break;
  219. }
  220. }
  221. }
  222. internal void Stop()
  223. {
  224. if (_cts != null)
  225. {
  226. _cts.Cancel();
  227. }
  228. }
  229. private void CheckVersion(string chargeBoxId)
  230. {
  231. if (string.IsNullOrEmpty(chargeBoxId)) return;
  232. using (var db = new MainDBContext())
  233. {
  234. db.ServerMessage.Add(new ServerMessage()
  235. {
  236. ChargeBoxId = chargeBoxId,
  237. CreatedBy = "Server",
  238. CreatedOn = DateTime.UtcNow,
  239. OutAction = Actions.DataTransfer.ToString(),
  240. OutRequest = JsonConvert.SerializeObject(
  241. new DataTransferRequest()
  242. {
  243. messageId = "ID_FirmwareVersion",
  244. vendorId = "Phihong Technology"
  245. },
  246. new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
  247. SerialNo = Guid.NewGuid().ToString(),
  248. InMessage = string.Empty
  249. });
  250. db.SaveChanges();
  251. }
  252. }
  253. private void CheckEVSEConfigure(string chargeBoxId)
  254. {
  255. if (string.IsNullOrEmpty(chargeBoxId)) return;
  256. using (var db = new MainDBContext())
  257. {
  258. db.ServerMessage.Add(new ServerMessage()
  259. {
  260. ChargeBoxId = chargeBoxId,
  261. CreatedBy = "Server",
  262. CreatedOn = DateTime.UtcNow,
  263. OutAction = Actions.GetConfiguration.ToString(),
  264. OutRequest = JsonConvert.SerializeObject(
  265. new GetConfigurationRequest()
  266. {
  267. key = new List<string>()
  268. },
  269. new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
  270. SerialNo = Guid.NewGuid().ToString(),
  271. InMessage = string.Empty
  272. }); ;
  273. db.SaveChanges();
  274. }
  275. }
  276. private void OpenNetwork()
  277. {
  278. //載入OCPP Protocol
  279. var appServer = new OCPPWSServer(new List<OCPPSubProtocol>() { new OCPPSubProtocol(), new OCPPSubProtocol(" ocpp1.6"), new OCPPSubProtocol("ocpp2.0") });
  280. List<IListenerConfig> llistener = new List<IListenerConfig>();
  281. llistener.Add(new ListenerConfig { Ip = System.Net.IPAddress.Any.ToString(), Port = Convert.ToInt32(GlobalConfig.GetWS_Port()), Backlog = 100, Security = "None" });
  282. llistener.Add(new ListenerConfig { Ip = System.Net.IPAddress.Any.ToString(), Port = Convert.ToInt32(GlobalConfig.GetWSS_Port_1()), Backlog = 100, Security = SslProtocols.Tls12.ToString() });
  283. llistener.Add(new ListenerConfig { Ip = System.Net.IPAddress.Any.ToString(), Port = Convert.ToInt32(GlobalConfig.GetWSS_Port_2()), Backlog = 100, Security = SslProtocols.Tls12.ToString() });
  284. var config = ConfigurationManager.GetSection("superSocket") as IConfigurationSource;
  285. ICertificateConfig Certificate = config.Servers.ElementAt(0).Certificate;
  286. IEnumerable<IListenerConfig> listeners = llistener;
  287. //設定server config
  288. var serverConfig = new ServerConfig
  289. {
  290. SendingQueueSize = 10,
  291. MaxRequestLength = 204800,
  292. //Security = serverSecurity,
  293. Certificate = Certificate,
  294. Listeners = listeners,
  295. // LogAllSocketException = true,
  296. KeepAliveTime = 10,
  297. // LogBasicSessionActivity = true
  298. };
  299. //Setup with listening port
  300. if (!appServer.Setup(serverConfig, logFactory: new OCPPLogFactory()))
  301. {
  302. Console.WriteLine("Failed to setup!");
  303. return;
  304. }
  305. appServer.NewSessionConnected += AppServer_NewSessionConnected;
  306. appServer.SessionClosed += AppServer_SessionClosed;
  307. //Try to start the appServer
  308. if (!appServer.Start())
  309. {
  310. Console.WriteLine("Failed to start!");
  311. Console.ReadKey();
  312. return;
  313. }
  314. }
  315. private void AppServer_SessionClosed(ClientData session, CloseReason value)
  316. {
  317. WriteMachineLog(session, string.Format("CloseReason: {0}", value), "Connection", "");
  318. RemoveClient(session);
  319. }
  320. private void AppServer_NewSessionConnected(ClientData session)
  321. {
  322. logger.Debug(string.Format("{0} NewSessionConnected", session.Path));
  323. try
  324. {
  325. lock (_lockClientDic)
  326. {
  327. bool isNotSupported = session.SecWebSocketProtocol.Contains("ocpp1.6") ? false : session.SecWebSocketProtocol.Contains("ocpp2.0") ? false : true;
  328. if (isNotSupported)
  329. {
  330. WriteMachineLog(session, string.Format("SecWebSocketProtocol:{0} NotSupported", session.SecWebSocketProtocol), "Connection", "");
  331. return;
  332. }
  333. ClientData _removeClient = null;
  334. clientDic.TryGetValue(session.ChargeBoxId, out _removeClient);
  335. if (_removeClient != null)
  336. {
  337. WriteMachineLog(_removeClient, "Duplicate Logins", "Connection", "");
  338. _removeClient.Close(CloseReason.ServerShutdown);
  339. RemoveClient(_removeClient);
  340. }
  341. clientDic.Add(session.ChargeBoxId, session);
  342. session.m_ReceiveData += new ClientData.OCPPClientDataEventHandler<ClientData, String>(ReceivedMessage);
  343. WriteMachineLog(session, "NewSessionConnected", "Connection", "");
  344. }
  345. }
  346. catch (Exception ex)
  347. {
  348. logger.Error(string.Format("NewSessionConnected Ex: {0}", ex.ToString()));
  349. }
  350. }
  351. async private void ReceivedMessage(ClientData session, string rawdata)
  352. {
  353. try
  354. {
  355. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  356. MessageResult analysisResult = msgAnalyser.AnalysisReceiveData(session, rawdata);
  357. WriteMachineLog(session, rawdata,
  358. 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);
  359. if (session.ResetSecurityProfile)
  360. {
  361. logger.Error(string.Format("[{0}] ChargeBoxId:{1} ResetSecurityProfile", DateTime.UtcNow, session.ChargeBoxId));
  362. RemoveClient(session);
  363. return;
  364. }
  365. if (!analysisResult.Success)
  366. {
  367. //解析RawData就發生錯誤
  368. if (!string.IsNullOrEmpty(analysisResult.CallErrorMsg))
  369. {
  370. Send(session, analysisResult.CallErrorMsg, string.Format("{0} {1}", analysisResult.Action, "Error"));
  371. }
  372. else
  373. {
  374. if (analysisResult.Message == null)
  375. {
  376. string replyMsg = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  377. string errorMsg = string.Empty;
  378. if (analysisResult.Exception != null)
  379. {
  380. errorMsg = analysisResult.Exception.ToString();
  381. }
  382. Send(session, replyMsg, string.Format("{0} {1}", "unknown", "Error"), "EVSE's sent essage has parsed Failed. ");
  383. }
  384. else
  385. {
  386. BaseMessage _baseMsg = analysisResult.Message as BaseMessage;
  387. string replyMsg = BasicMessageHandler.GenerateCallError(_baseMsg.Id, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  388. string errorMsg = string.Empty;
  389. if (analysisResult.Exception != null)
  390. {
  391. errorMsg = analysisResult.Exception.ToString();
  392. }
  393. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  394. }
  395. }
  396. }
  397. else
  398. {
  399. switch (analysisResult.Id)
  400. {
  401. case BasicMessageHandler.TYPENUMBER_CALL:
  402. {
  403. if (!session.ISOCPP20)
  404. {
  405. Actions action = Convertor.GetAction(analysisResult.Action);
  406. ProcessRequestMessage(analysisResult, session, action);
  407. }
  408. else
  409. {
  410. EVCB_OCPP20.Packet.Features.Actions action = Convertor.GetActionby20(analysisResult.Action);
  411. MessageResult result = new MessageResult() { Success = true };
  412. //ocpp20 處理
  413. switch (action)
  414. {
  415. case EVCB_OCPP20.Packet.Features.Actions.BootNotification:
  416. {
  417. EVCB_OCPP20.Packet.Messages.BootNotificationRequest _request = (EVCB_OCPP20.Packet.Messages.IRequest)analysisResult.Message as EVCB_OCPP20.Packet.Messages.BootNotificationRequest;
  418. var confirm = new EVCB_OCPP20.Packet.Messages.BootNotificationResponse() { CurrentTime = DateTime.UtcNow, Interval = 180, Status = EVCB_OCPP20.Packet.DataTypes.EnumTypes.RegistrationStatusEnumType.Pending };
  419. result.Message = confirm;
  420. result.Success = true;
  421. string response = BasicMessageHandler.GenerateConfirmationofOCPP20(analysisResult.UUID, (EVCB_OCPP20.Packet.Messages.IConfirmation)result.Message);
  422. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Response"), result.Exception == null ? string.Empty : result.Exception.ToString());
  423. var request = new EVCB_OCPP20.Packet.Messages.SetNetworkProfileRequest()
  424. {
  425. ConfigurationSlot = 1,
  426. ConnectionData = new EVCB_OCPP20.Packet.DataTypes.NetworkConnectionProfileType()
  427. {
  428. OcppVersion = EVCB_OCPP20.Packet.DataTypes.EnumTypes.OCPPVersionEnumType.OCPP20,
  429. OcppTransport = EVCB_OCPP20.Packet.DataTypes.EnumTypes.OCPPTransportEnumType.JSON,
  430. MessageTimeout = 30,
  431. OcppCsmsUrl = session.UriScheme == "ws" ? GlobalConfig.OCPP20_WSUrl : GlobalConfig.OCPP20_WSSUrl,
  432. OcppInterface = EVCB_OCPP20.Packet.DataTypes.EnumTypes.OCPPInterfaceEnumType.Wired0
  433. }
  434. };
  435. var uuid = session.queue20.store(request);
  436. string requestText = BasicMessageHandler.GenerateRequestofOCPP20(uuid, "SetNetworkProfile", request);
  437. Send(session, requestText, "SetNetworkProfile");
  438. }
  439. break;
  440. default:
  441. {
  442. logger.Error(string.Format("We don't implement messagetype:{0} of raw data :{1} by {2}", analysisResult.Id, rawdata, session.ChargeBoxId));
  443. }
  444. break;
  445. }
  446. }
  447. }
  448. break;
  449. case BasicMessageHandler.TYPENUMBER_CALLRESULT:
  450. {
  451. if (!session.ISOCPP20)
  452. {
  453. Actions action = Convertor.GetAction(analysisResult.Action);
  454. ProcessConfirmationMessage(analysisResult, session, action);
  455. }
  456. else
  457. {
  458. EVCB_OCPP20.Packet.Features.Actions action = Convertor.GetActionby20(analysisResult.Action);
  459. MessageResult result = new MessageResult() { Success = true };
  460. //ocpp20 處理
  461. switch (action)
  462. {
  463. case EVCB_OCPP20.Packet.Features.Actions.SetNetworkProfile:
  464. {
  465. EVCB_OCPP20.Packet.Messages.SetNetworkProfileResponse response = (EVCB_OCPP20.Packet.Messages.IConfirmation)analysisResult.Message as EVCB_OCPP20.Packet.Messages.SetNetworkProfileResponse;
  466. if (response.Status == EVCB_OCPP20.Packet.DataTypes.EnumTypes.SetNetworkProfileStatusEnumType.Accepted)
  467. {
  468. var request = new EVCB_OCPP20.Packet.Messages.SetVariablesRequest()
  469. {
  470. SetVariableData = new List<EVCB_OCPP20.Packet.DataTypes.SetVariableDataType>()
  471. {
  472. new EVCB_OCPP20.Packet.DataTypes.SetVariableDataType()
  473. {
  474. Component=new EVCB_OCPP20.Packet.DataTypes.ComponentType()
  475. {
  476. Name="OCPPCommCtrlr",
  477. },
  478. AttributeType= EVCB_OCPP20.Packet.DataTypes.EnumTypes.AttributeEnumType.Actual,
  479. AttributeValue= JsonConvert.SerializeObject(new List<int>(){ 1 }),
  480. Variable=new EVCB_OCPP20.Packet.DataTypes.VariableType()
  481. {
  482. Name="NetworkConfigurationPriority",
  483. }
  484. }
  485. }
  486. };
  487. var uuid = session.queue20.store(request);
  488. string requestText = BasicMessageHandler.GenerateRequestofOCPP20(uuid, "SetVariables", request);
  489. Send(session, requestText, "SetVariables");
  490. }
  491. }
  492. break;
  493. case EVCB_OCPP20.Packet.Features.Actions.SetVariables:
  494. {
  495. EVCB_OCPP20.Packet.Messages.SetVariablesResponse response = (EVCB_OCPP20.Packet.Messages.IConfirmation)analysisResult.Message as EVCB_OCPP20.Packet.Messages.SetVariablesResponse;
  496. if (response.SetVariableResult[0].AttributeStatus == EVCB_OCPP20.Packet.DataTypes.EnumTypes.SetVariableStatusEnumType.RebootRequired)
  497. {
  498. var request = new EVCB_OCPP20.Packet.Messages.ResetRequest()
  499. {
  500. Type = EVCB_OCPP20.Packet.DataTypes.EnumTypes.ResetEnumType.OnIdle
  501. };
  502. var uuid = session.queue20.store(request);
  503. string requestText = BasicMessageHandler.GenerateRequestofOCPP20(uuid, "Reset", request);
  504. Send(session, requestText, "Reset");
  505. }
  506. }
  507. break;
  508. default:
  509. {
  510. logger.Error(string.Format("We don't implement messagetype:{0} of raw data :{1} by {2}", analysisResult.Id, rawdata, session.ChargeBoxId));
  511. }
  512. break;
  513. }
  514. }
  515. }
  516. break;
  517. case BasicMessageHandler.TYPENUMBER_CALLERROR:
  518. {
  519. //只處理 丟出Request 收到Error的訊息
  520. if (analysisResult.Success && analysisResult.Message != null)
  521. {
  522. Actions action = Convertor.GetAction(analysisResult.Action);
  523. ProcessErrorMessage(analysisResult, session, action);
  524. }
  525. }
  526. break;
  527. default:
  528. {
  529. logger.Error(string.Format("Can't analyze messagetype:{0} of raw data :{1} by {2}", analysisResult.Id, rawdata, session.ChargeBoxId));
  530. }
  531. break;
  532. }
  533. }
  534. await Task.Delay(10);
  535. }
  536. catch (Exception ex)
  537. {
  538. if (ex.InnerException != null)
  539. {
  540. logger.Error(string.Format("{0} **Inner Exception :{1} ", session.ChargeBoxId + rawdata, ex.ToString()));
  541. }
  542. else
  543. {
  544. logger.Error(string.Format("{0} **Exception :{1} ", session.ChargeBoxId, ex.ToString()));
  545. }
  546. }
  547. }
  548. async private void ProcessRequestMessage(MessageResult analysisResult, ClientData session, Actions action)
  549. {
  550. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  551. if (!session.IsCheckIn && action != Actions.BootNotification)
  552. {
  553. string response = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.GenericError, OCPPErrorDescription.NotChecked);
  554. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"));
  555. }
  556. else
  557. {
  558. var profileName = profiles.Where(x => x.IsExisted(analysisResult.Action)).Select(x => x.Name).FirstOrDefault();
  559. switch (profileName)
  560. {
  561. case "Core":
  562. {
  563. var replyResult = await profileHandler.ExecuteCoreRequest(action, session, (IRequest)analysisResult.Message).ConfigureAwait(false);
  564. if (replyResult.Success)
  565. {
  566. string response = BasicMessageHandler.GenerateConfirmation(analysisResult.UUID, (IConfirmation)replyResult.Message);
  567. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Confirmation"), replyResult.Exception == null ? string.Empty : replyResult.Exception.ToString());
  568. if (action == Actions.BootNotification && replyResult.Message is BootNotificationConfirmation)
  569. {
  570. if (((BootNotificationConfirmation)replyResult.Message).status == Packet.Messages.SubTypes.RegistrationStatus.Accepted)
  571. {
  572. session.IsCheckIn = true;
  573. await SetDefaultFee(session);
  574. CheckVersion(session.ChargeBoxId);
  575. CheckEVSEConfigure(session.ChargeBoxId);
  576. if (session.CustomerId == new Guid("298918C0-6BB5-421A-88CC-4922F918E85E") || session.CustomerId == new Guid("9E6BFDCC-09FB-4DAB-A428-43FE507600A3"))
  577. {
  578. using (var db = new MainDBContext())
  579. {
  580. db.ServerMessage.Add(new ServerMessage()
  581. {
  582. ChargeBoxId = session.ChargeBoxId,
  583. CreatedBy = "Server",
  584. CreatedOn = DateTime.UtcNow,
  585. OutAction = Actions.ChangeConfiguration.ToString(),
  586. OutRequest = JsonConvert.SerializeObject(
  587. new ChangeConfigurationRequest()
  588. {
  589. key = "TimeOffset",
  590. value = "+08:00"
  591. },
  592. new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
  593. SerialNo = Guid.NewGuid().ToString(),
  594. InMessage = string.Empty
  595. });
  596. db.SaveChanges();
  597. }
  598. }
  599. }
  600. else
  601. {
  602. }
  603. }
  604. if (action == Actions.Authorize && replyResult.Message is AuthorizeConfirmation)
  605. {
  606. var authorizeRequest = (IRequest)analysisResult.Message as AuthorizeRequest;
  607. if (session.UserDisplayPrices.ContainsKey(authorizeRequest.idTag))
  608. {
  609. using (var db = new MainDBContext())
  610. {
  611. db.ServerMessage.Add(new ServerMessage()
  612. {
  613. ChargeBoxId = session.ChargeBoxId,
  614. CreatedBy = "Server",
  615. CreatedOn = DateTime.UtcNow,
  616. OutAction = Actions.DataTransfer.ToString(),
  617. OutRequest = JsonConvert.SerializeObject(
  618. new DataTransferRequest()
  619. {
  620. messageId = "SetUserPrice",
  621. vendorId = "Phihong Technology",
  622. data = JsonConvert.SerializeObject(
  623. new
  624. {
  625. idToken = authorizeRequest.idTag,
  626. price = session.UserDisplayPrices[authorizeRequest.idTag]
  627. })
  628. },
  629. new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
  630. SerialNo = Guid.NewGuid().ToString(),
  631. InMessage = string.Empty
  632. });
  633. db.SaveChanges();
  634. }
  635. }
  636. }
  637. }
  638. else
  639. {
  640. if (action == Actions.StopTransaction && replyResult.CallErrorMsg == "Reject Response Message")
  641. {
  642. //do nothing
  643. }
  644. else
  645. {
  646. string response = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  647. string errorMsg = replyResult.Exception != null ? replyResult.Exception.ToString() : string.Empty;
  648. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  649. }
  650. }
  651. if (action == Actions.StartTransaction)
  652. {
  653. var stationId = _loadingBalanceService.GetStationIdByMachineId(session.MachineId);
  654. var _powerDic = await _loadingBalanceService.GetSettingPower(stationId);
  655. if (_powerDic != null)
  656. {
  657. foreach (var kv in _powerDic)
  658. {
  659. try
  660. {
  661. if (kv.Value.HasValue)
  662. {
  663. profileHandler.SetChargingProfile(kv.Key, kv.Value.Value, Packet.Messages.SubTypes.ChargingRateUnitType.W);
  664. }
  665. }
  666. catch (Exception ex)
  667. {
  668. logger.Error(string.Format("Set Profile Exception: {0}", ex.ToString()));
  669. }
  670. }
  671. }
  672. }
  673. if (action == Actions.StopTransaction)
  674. {
  675. var stationId = _loadingBalanceService.GetStationIdByMachineId(session.MachineId);
  676. var _powerDic = await _loadingBalanceService.GetSettingPower(stationId);
  677. if (_powerDic != null)
  678. {
  679. foreach (var kv in _powerDic)
  680. {
  681. try
  682. {
  683. if (kv.Value.HasValue)
  684. {
  685. profileHandler.SetChargingProfile(kv.Key, kv.Value.Value, Packet.Messages.SubTypes.ChargingRateUnitType.W);
  686. }
  687. }
  688. catch (Exception ex)
  689. {
  690. logger.Error(string.Format("Set Profile Exception: {0}", ex.ToString()));
  691. }
  692. }
  693. }
  694. }
  695. }
  696. break;
  697. case "FirmwareManagement":
  698. {
  699. var replyResult = profileHandler.ExecuteFirmwareManagementRequest(action, session, (IRequest)analysisResult.Message);
  700. if (replyResult.Success)
  701. {
  702. string response = BasicMessageHandler.GenerateConfirmation(analysisResult.UUID, (IConfirmation)replyResult.Message);
  703. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Confirmation", replyResult.Exception == null ? string.Empty : replyResult.Exception.ToString()));
  704. }
  705. else
  706. {
  707. string response = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  708. string errorMsg = replyResult.Exception != null ? replyResult.Exception.ToString() : string.Empty;
  709. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  710. }
  711. }
  712. break;
  713. case "Security":
  714. {
  715. var replyResult = profileHandler.ExecuteSecurityRequest(action, session, (IRequest)analysisResult.Message);
  716. if (replyResult.Success)
  717. {
  718. string response = BasicMessageHandler.GenerateConfirmation(analysisResult.UUID, (IConfirmation)replyResult.Message);
  719. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Confirmation", replyResult.Exception == null ? string.Empty : replyResult.Exception.ToString()));
  720. }
  721. else
  722. {
  723. string response = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  724. string errorMsg = replyResult.Exception != null ? replyResult.Exception.ToString() : string.Empty;
  725. Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  726. }
  727. }
  728. break;
  729. default:
  730. {
  731. string replyMsg = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  732. string errorMsg = string.Format("Couldn't find action name: {0} of profile", action);
  733. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  734. }
  735. break;
  736. }
  737. }
  738. }
  739. async private void ProcessConfirmationMessage(MessageResult analysisResult, ClientData session, Actions action)
  740. {
  741. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  742. if (ReConfirmMessage(analysisResult))
  743. {
  744. var profileName = profiles.Where(x => x.IsExisted(analysisResult.Action)).Select(x => x.Name).FirstOrDefault();
  745. MessageResult confirmResult = null;
  746. switch (profileName)
  747. {
  748. case "Core":
  749. {
  750. confirmResult = await profileHandler.ExecuteCoreConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
  751. }
  752. break;
  753. case "FirmwareManagement":
  754. {
  755. confirmResult = profileHandler.ExecuteFirmwareManagementConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
  756. }
  757. break;
  758. case "RemoteTrigger":
  759. {
  760. confirmResult = profileHandler.ExecuteRemoteTriggerConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
  761. }
  762. break;
  763. case "Reservation":
  764. {
  765. confirmResult = profileHandler.ExecuteReservationConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
  766. }
  767. break;
  768. case "LocalAuthListManagement":
  769. {
  770. confirmResult = profileHandler.ExecuteLocalAuthListManagementConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
  771. }
  772. break;
  773. case "SmartCharging":
  774. {
  775. confirmResult = profileHandler.ExecuteSmartChargingConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
  776. }
  777. break;
  778. case "Security":
  779. {
  780. confirmResult = profileHandler.ExecuteSecurityConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
  781. }
  782. break;
  783. default:
  784. {
  785. string replyMsg = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  786. string errorMsg = string.Format("Couldn't find action name: {0} of profile", action);
  787. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  788. }
  789. break;
  790. }
  791. if (confirmResult == null || !confirmResult.Success)
  792. {
  793. logger.Error(string.Format("Action:{0} MessageId:{1} ExecuteConfirm Error:{2} ",
  794. analysisResult.Action, analysisResult.UUID, confirmResult.Exception.ToString()));
  795. }
  796. }
  797. else
  798. {
  799. string replyMsg = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  800. string errorMsg = string.Format("Action:{0} MessageId:{1} didn't exist in confirm message", analysisResult.Action, analysisResult.UUID);
  801. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  802. }
  803. }
  804. private void ProcessErrorMessage(MessageResult analysisResult, ClientData session, Actions action)
  805. {
  806. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  807. if (ReConfirmMessage(analysisResult))
  808. {
  809. var profileName = profiles.Where(x => x.IsExisted(analysisResult.Action)).Select(x => x.Name).FirstOrDefault();
  810. switch (profileName)
  811. {
  812. case "Core":
  813. {
  814. profileHandler.ReceivedCoreError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
  815. }
  816. break;
  817. case "FirmwareManagement":
  818. {
  819. profileHandler.ReceivedFirmwareManagementError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
  820. }
  821. break;
  822. case "RemoteTrigger":
  823. {
  824. profileHandler.ReceivedRemoteTriggerError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
  825. }
  826. break;
  827. case "Reservation":
  828. {
  829. profileHandler.ExecuteReservationError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
  830. }
  831. break;
  832. case "LocalAuthListManagement":
  833. {
  834. profileHandler.ReceivedLocalAuthListManagementError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
  835. }
  836. break;
  837. case "SmartCharging":
  838. {
  839. profileHandler.ReceivedSmartChargingError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
  840. }
  841. break;
  842. default:
  843. {
  844. string replyMsg = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  845. string errorMsg = string.Format("Couldn't find action name: {0} of profile", action);
  846. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  847. }
  848. break;
  849. }
  850. }
  851. else
  852. {
  853. string replyMsg = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
  854. string errorMsg = string.Format("Action:{0} MessageId:{1} didn't exist in confirm message", analysisResult.Action, analysisResult.UUID);
  855. Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
  856. }
  857. }
  858. private void Send(ClientData session, string msg, string messageType, string errorMsg = "")
  859. {
  860. try
  861. {
  862. if (session != null)
  863. {
  864. WriteMachineLog(session, msg, messageType, errorMsg, true);
  865. session.Send(msg);
  866. }
  867. }
  868. catch (Exception ex)
  869. {
  870. logger.Error(string.Format("Send Ex:{0}", ex.ToString()));
  871. }
  872. }
  873. DateTime fillinDt = DateTime.UtcNow.AddMinutes(-1);
  874. async private void FillinChargerData()
  875. {
  876. for (; ; )
  877. {
  878. if (_ct.IsCancellationRequested)
  879. {
  880. break;
  881. }
  882. var min_Interval = (DateTime.UtcNow - fillinDt).TotalSeconds;
  883. if (min_Interval > 3)
  884. {
  885. fillinDt = DateTime.UtcNow;
  886. Stopwatch watch = new Stopwatch();
  887. watch.Start();
  888. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  889. Dictionary<string, ClientData> _copyClientDic = null;
  890. lock (_lockClientDic)
  891. {
  892. _copyClientDic = new Dictionary<string, ClientData>(clientDic);
  893. }
  894. var chargers = _copyClientDic.Values.Where(x => x.CustomerId == Guid.Empty).Take(100).ToList();
  895. using (var db = new MainDBContext())
  896. {
  897. foreach (var charger in chargers)
  898. {
  899. try
  900. {
  901. var machine = db.Machine.Where(x => x.ChargeBoxId == charger.ChargeBoxId && x.IsDelete == false).Select(x => new { x.CustomerId, x.Id, x.ConnectorType }).FirstOrDefault();
  902. if (machine == null)
  903. {
  904. RemoveClient(charger);
  905. continue;
  906. }
  907. if (machine.ConnectorType.Contains("6") || machine.ConnectorType.Contains("7") || machine.ConnectorType.Contains("8") || machine.ConnectorType.Contains("9"))
  908. {
  909. charger.IsAC = false;
  910. }
  911. // charger.CustomerName = machine == null ? "Unknown" : db.Customer.Where(x => x.Id == machine.CustomerId).Select(x => x.Name).FirstOrDefault();
  912. charger.CustomerId = machine == null ? Guid.Empty : machine.CustomerId;
  913. charger.MachineId = machine == null ? String.Empty : machine.Id;
  914. }
  915. catch (Exception ex)
  916. {
  917. logger.Error(string.Format("FillinChargerData ChargeBoxId:{0} Ex:{1}", charger.ChargeBoxId, ex.ToString()));
  918. }
  919. }
  920. }
  921. watch.Stop();
  922. if (watch.ElapsedMilliseconds / 1000 > 5)
  923. {
  924. logger.Fatal("Update FillinChargerData cost " + watch.ElapsedMilliseconds / 1000 + " seconds.");
  925. }
  926. }
  927. await Task.Delay(1000);
  928. }
  929. }
  930. async private void DenyModelCheckTrigger(bool warmup)
  931. {
  932. for (; ; )
  933. {
  934. if (_ct.IsCancellationRequested)
  935. {
  936. break;
  937. }
  938. try
  939. {
  940. var min_Interval = (DateTime.UtcNow - _CheckDenyListDt).TotalMinutes;
  941. if (min_Interval > 5)
  942. {
  943. using (SqlConnection conn = new SqlConnection(webConnectionString))
  944. {
  945. string strSql = "SELECT [Value] FROM [dbo].[KernelConfig] " +
  946. "where SystemKey = 'DenyModelNames'; ";
  947. var result = await conn.QueryAsync<string>(strSql);
  948. GlobalConfig.DenyModelNames = result.FirstOrDefault().Split(',').ToList();
  949. logger.Debug(string.Format("Current DenyList:[{0}]", string.Join(",", GlobalConfig.DenyModelNames)));
  950. }
  951. _CheckDenyListDt = DateTime.UtcNow;
  952. if (!string.IsNullOrEmpty(GlobalConfig.DenyModelNames[0]))
  953. {
  954. Dictionary<string, ClientData> _copyClientDic = null;
  955. lock (_lockClientDic)
  956. {
  957. _copyClientDic = new Dictionary<string, ClientData>(clientDic);
  958. }
  959. foreach (var denyName in GlobalConfig.DenyModelNames)
  960. {
  961. var removeClients = _copyClientDic.Where(x => x.Key.StartsWith(denyName)).Select(x => x.Value).ToList();
  962. foreach (var session in removeClients)
  963. {
  964. Console.WriteLine(string.Format("Server forced to shut down ChargeBox ({0}: Reason: DenyModelName-{1}", session.ChargeBoxId, denyName));
  965. RemoveClient(session);
  966. }
  967. }
  968. }
  969. }
  970. await Task.Delay(500);
  971. }
  972. catch (Exception ex)
  973. {
  974. logger.Error(string.Format("DenyModelCheckTrigger Ex:{0}", ex.ToString()));
  975. }
  976. if (warmup) break;
  977. }
  978. }
  979. async private void ServerUpdateTrigger()
  980. {
  981. for (; ; )
  982. {
  983. if (_ct.IsCancellationRequested)
  984. {
  985. break;
  986. }
  987. var min_Interval = (DateTime.UtcNow - checkUpdateDt).TotalMinutes;
  988. if (min_Interval > 3)
  989. {
  990. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  991. Dictionary<string, ClientData> _copyClientDic = null;
  992. lock (_lockClientDic)
  993. {
  994. _copyClientDic = new Dictionary<string, ClientData>(clientDic);
  995. }
  996. checkUpdateDt = DateTime.UtcNow;
  997. using (var db = new MainDBContext())
  998. {
  999. //var needUpdateChargers = db.Machine.Where(x => x.FW_AssignedMachineVersionId.HasValue == true &&
  1000. // x.FW_AssignedMachineVersionId != x.FW_VersionReport && x.Online == true)
  1001. // .Select(x => new { x.Id, x.ChargeBoxId, x.FW_AssignedMachineVersionId }).ToList();
  1002. var needUpdateChargers = db.Machine.Where(x => x.FW_AssignedVersion.HasValue == true &&
  1003. x.FW_AssignedVersion != x.FW_VersionReport && x.Online == true)
  1004. .Select(x => x.ChargeBoxId).AsNoTracking().ToList();
  1005. foreach (var chargeBoxId in needUpdateChargers)
  1006. {
  1007. try
  1008. {
  1009. ClientData session;
  1010. if (_copyClientDic.TryGetValue(chargeBoxId, out session))
  1011. {
  1012. string requestId = Guid.NewGuid().ToString();
  1013. // using (var db = new MainDBContext())
  1014. if (session.IsCheckIn && !session.ISOCPP20)
  1015. {
  1016. var _request = new TriggerMessageRequest()
  1017. {
  1018. requestedMessage = Packet.Messages.SubTypes.MessageTrigger.FirmwareStatusNotification
  1019. };
  1020. var uuid = session.queue.store(_request);
  1021. string rawRequest = BasicMessageHandler.GenerateRequest(uuid, _request.Action, _request);
  1022. Send(session, rawRequest, string.Format("{0} {1}", _request.Action, "Request"), "");
  1023. #region OCTT ,測試韌體更新方式
  1024. //--------------------> OCTT ,測試韌體更新方式
  1025. //{
  1026. // var machine = db.Machine.Where(x => x.FW_AssignedMachineVersionId.HasValue == true &&
  1027. // x.FW_AssignedMachineVersionId != x.FW_VersionReport && x.ChargeBoxId == session.ChargeBoxId)
  1028. // .Select(x => new { x.Id, x.FW_AssignedMachineVersionId }).FirstOrDefault();
  1029. // if (machine != null)
  1030. // {
  1031. // var mv = db.MachineVersion.Include(c => c.PublishVersion)
  1032. // .Include(c => c.PublishVersion.PublishVersionFiles)
  1033. // .Include(c => c.PublishVersion.PublishVersionFiles.Select(z => z.UploadFile))
  1034. // .Where(c => c.Id == machine.FW_AssignedMachineVersionId.Value).First();
  1035. // string downloadUrl = mv.PublishVersion.PublishVersionFiles.FirstOrDefault().UploadFile.FileUrl;
  1036. // var _updateFWrequest = new UpdateFirmwareRequest()
  1037. // {
  1038. // location = new Uri(downloadUrl),
  1039. // retries = 3,
  1040. // retrieveDate = DateTime.UtcNow,
  1041. // retryInterval = 10
  1042. // };
  1043. // db.MachineOperateRecord.Add(new MachineOperateRecord()
  1044. // {
  1045. // CreatedOn = DateTime.UtcNow,
  1046. // ChargeBoxId = session.ChargeBoxId,
  1047. // SerialNo = requestId,
  1048. // RequestContent = JsonConvert.SerializeObject(_updateFWrequest, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
  1049. // EVSE_Status = 0,
  1050. // EVSE_Value = "Fw Version:" + machine.FW_AssignedMachineVersionId,
  1051. // Status = 0,
  1052. // RequestType = 0,
  1053. // });
  1054. // db.ServerMessage.Add(new ServerMessage()
  1055. // {
  1056. // ChargeBoxId = session.ChargeBoxId,
  1057. // CreatedBy = "Server",
  1058. // CreatedOn = DateTime.UtcNow,
  1059. // OutAction = _updateFWrequest.Action.ToString(),
  1060. // OutRequest = JsonConvert.SerializeObject(_updateFWrequest, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
  1061. // SerialNo = requestId,
  1062. // InMessage = string.Empty
  1063. // });
  1064. // db.SaveChanges();
  1065. // }
  1066. //}
  1067. #endregion
  1068. }
  1069. }
  1070. }
  1071. catch (Exception ex)
  1072. {
  1073. logger.Error(string.Format("serverUpdateTrigger ChargeBoxId:{0} Ex:{1}", chargeBoxId, ex.ToString()));
  1074. }
  1075. }
  1076. }
  1077. await Task.Delay(1000);
  1078. // Thread.CurrentThread.Join(1000);
  1079. }
  1080. }
  1081. }
  1082. async private void ServerMessageTrigger()
  1083. {
  1084. for (; ; )
  1085. {
  1086. if (_ct.IsCancellationRequested)
  1087. {
  1088. break;
  1089. }
  1090. try
  1091. {
  1092. RemoveConfirmMessage();
  1093. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  1094. using (var db = new MainDBContext())
  1095. {
  1096. DateTime startDt = DateTime.UtcNow.AddSeconds(-30);
  1097. DateTime dt = new DateTime(1991, 1, 1);
  1098. DateTime currentTime = DateTime.UtcNow;
  1099. var commandList = db.ServerMessage.Where(c => c.ReceivedOn == dt && c.UpdatedOn == dt && c.CreatedOn >= startDt && c.CreatedOn <= currentTime).AsNoTracking().ToList();
  1100. //處理主機傳送的有指令
  1101. var cmdMachineList = commandList.Select(c => c.ChargeBoxId).Distinct().ToList();
  1102. if (commandList.Count > 0)
  1103. {
  1104. // Console.WriteLine(string.Format("Now:{0} commandList Count:{1} ", DateTime.UtcNow.ToString("yyyy/MM/dd HH:mm:ss"), commandList.Count));
  1105. }
  1106. var resendList = GetResendMessage();
  1107. foreach (var resendItem in resendList)
  1108. {
  1109. ClientData session;
  1110. if (clientDic.TryGetValue(resendItem.ChargePointSerialNumber, out session))
  1111. {
  1112. if (DateTime.UtcNow.Subtract(resendItem.SentOn).TotalSeconds > 1)
  1113. {
  1114. resendItem.SentTimes--;
  1115. resendItem.SentOn = DateTime.UtcNow;
  1116. Send(session, resendItem.SentMessage, string.Format("{0} {1}", resendItem.SentAction, "Request"), "");
  1117. }
  1118. }
  1119. }
  1120. foreach (var charger_SN in cmdMachineList)
  1121. {
  1122. ClientData session;
  1123. string uuid = string.Empty;
  1124. if (clientDic.TryGetValue(charger_SN, out session))
  1125. {
  1126. //logger.Debug(string.Format("charger_SN:{0} startDt:{1} CreatedOn:{2}", charger_SN, startDt.ToString("yyyy/MM/dd HH:mm:ss"), DateTime.UtcNow.ToString("yyyy/MM/dd HH:mm:ss")));
  1127. if (session.IsCheckIn && !session.ISOCPP20)
  1128. {
  1129. string rawRequest = string.Empty;
  1130. var cmdList = commandList.Where(c => c.ChargeBoxId == charger_SN).ToList();
  1131. foreach (var item in cmdList)
  1132. {
  1133. IRequest request = null;
  1134. Actions action = Actions.None;
  1135. Enum.TryParse(item.OutAction, out action);
  1136. Type _RequestType = null;
  1137. for (int i = 0; i < profiles.Count; i++)
  1138. {
  1139. var feature = profiles[i].GetFeaturebyAction(item.OutAction);
  1140. if (feature != null)
  1141. {
  1142. _RequestType = feature.GetRequestType();
  1143. break;
  1144. }
  1145. }
  1146. if (_RequestType != null && item.CreatedBy != "Destroyer")
  1147. {
  1148. request = JsonConvert.DeserializeObject(item.OutRequest, _RequestType) as IRequest;
  1149. uuid = session.queue.store(request);
  1150. rawRequest = BasicMessageHandler.GenerateRequest(uuid, item.OutAction, request);
  1151. Send(session, rawRequest, string.Format("{0} {1}", action, "Request"), "");
  1152. }
  1153. if (item.CreatedBy == "Destroyer")
  1154. {
  1155. if (_RequestType != null)
  1156. {
  1157. request = Activator.CreateInstance(_RequestType) as IRequest;
  1158. uuid = session.queue.store(request);
  1159. rawRequest = BasicMessageHandler.GenerateDestroyRequest(uuid, item.OutAction, item.OutRequest);
  1160. Send(session, rawRequest, string.Format("{0} {1}", action, "Request"), "");
  1161. }
  1162. else
  1163. {
  1164. rawRequest = BasicMessageHandler.GenerateDestroyRequest(Guid.NewGuid().ToString(), item.OutAction, item.OutRequest);
  1165. Send(session, rawRequest, string.Format("{0} {1}", action, "Request"), "");
  1166. }
  1167. }
  1168. AddConfirmMessage(charger_SN, item.Id, item.SerialNo, item.OutAction, uuid, item.CreatedBy, rawRequest);
  1169. #region 更新資料表單一欄位
  1170. var _UpdatedItem = new ServerMessage() { Id = item.Id, UpdatedOn = DateTime.UtcNow };
  1171. db.Configuration.AutoDetectChangesEnabled = false;//自動呼叫DetectChanges()比對所有的entry集合的每一個屬性Properties的新舊值
  1172. db.Configuration.ValidateOnSaveEnabled = false;// 因為Entity有些欄位必填,若不避開會有Validate錯誤
  1173. // var _UpdatedItem = db.ServerMessage.Where(x => x.Id == item.Id).FirstOrDefault();
  1174. db.ServerMessage.Attach(_UpdatedItem);
  1175. _UpdatedItem.UpdatedOn = DateTime.UtcNow;
  1176. db.Entry(_UpdatedItem).Property(x => x.UpdatedOn).IsModified = true;// 可以直接使用這方式強制某欄位要更新,只是查詢集合耗效能而己
  1177. db.SaveChanges();
  1178. #endregion
  1179. await Task.Delay(100);
  1180. }
  1181. }
  1182. }
  1183. }
  1184. }
  1185. await Task.Delay(500);
  1186. }
  1187. catch (Exception ex)
  1188. {
  1189. logger.Error(string.Format("ServerMessageTrigger Ex:{0}", ex.ToString()));
  1190. }
  1191. }
  1192. }
  1193. async private void HeartBeatCheckTrigger()
  1194. {
  1195. for (; ; )
  1196. {
  1197. if (_ct.IsCancellationRequested)
  1198. {
  1199. break;
  1200. }
  1201. try
  1202. {
  1203. // if (DateTime.UtcNow.Subtract(lastcheckdt).TotalSeconds > 30)
  1204. {
  1205. // lastcheckdt = DateTime.UtcNow;
  1206. Stopwatch watch = new Stopwatch();
  1207. Dictionary<string, ClientData> _copyClientDic = null;
  1208. lock (_lockClientDic)
  1209. {
  1210. _copyClientDic = new Dictionary<string, ClientData>(clientDic);
  1211. }
  1212. var cdt = DateTime.UtcNow;
  1213. var clients = _copyClientDic.Where(x => x.Value.LastActiveTime > cdt.AddSeconds(-120)).Select(x => x.Value).ToList();
  1214. watch.Start();
  1215. foreach (var session in clients)
  1216. {
  1217. using (var db = new MainDBContext())
  1218. {
  1219. using (var transaction = db.Database.BeginTransaction())
  1220. {
  1221. try
  1222. {
  1223. var machine = new Machine() { Id = session.MachineId };
  1224. if (machine != null)
  1225. {
  1226. db.Configuration.AutoDetectChangesEnabled = false;
  1227. db.Configuration.ValidateOnSaveEnabled = false;
  1228. db.Machine.Attach(machine);
  1229. machine.HeartbeatUpdatedOn = DateTime.UtcNow;
  1230. machine.ConnectionType = session.UriScheme.Equals("wss") ? 2 : 1;
  1231. db.Entry(machine).Property(x => x.HeartbeatUpdatedOn).IsModified = true;
  1232. db.Entry(machine).Property(x => x.ConnectionType).IsModified = true;
  1233.                                             //await db.SaveChangesAsync();
  1234.                                             db.SaveChanges();
  1235. transaction.Commit();
  1236. }
  1237. }
  1238. catch (Exception ex)
  1239. {
  1240. transaction.Rollback();
  1241. }
  1242. }
  1243. }
  1244. }
  1245. watch.Stop();
  1246. if (watch.ElapsedMilliseconds / 1000 > 5)
  1247. {
  1248. logger.Fatal("Update HeartBeatCheckTrigger cost " + watch.ElapsedMilliseconds / 1000 + " seconds.");
  1249. }
  1250. }
  1251. await Task.Delay(10000);
  1252. }
  1253. catch (Exception ex)
  1254. {
  1255. Console.WriteLine("***********************************************************");
  1256. logger.Error(string.Format("HeartBeatCheckTrigger Ex:{0}", ex.ToString()));
  1257. }
  1258. }
  1259. }
  1260. async private void ServerSetFeeTrigger()
  1261. {
  1262. for (; ; )
  1263. {
  1264. if (_ct.IsCancellationRequested)
  1265. {
  1266. break;
  1267. }
  1268. var min_Interval = (DateTime.UtcNow - _CheckFeeDt).TotalMinutes;
  1269. if (min_Interval > 1)
  1270. {
  1271. BasicMessageHandler msgAnalyser = new BasicMessageHandler();
  1272. Dictionary<string, ClientData> _copyClientDic = null;
  1273. lock (_lockClientDic)
  1274. {
  1275. _copyClientDic = new Dictionary<string, ClientData>(clientDic);
  1276. }
  1277. _CheckFeeDt = DateTime.UtcNow;
  1278. foreach (var item in _copyClientDic)
  1279. {
  1280. try
  1281. {
  1282. ClientData session = item.Value;
  1283. if (session.IsCheckIn)
  1284. {
  1285. string displayPriceText = await SetDefaultFee(session);
  1286. if (!string.IsNullOrEmpty(displayPriceText) && displayPriceText != session.DisplayPrice)
  1287. {
  1288. clientDic[item.Key].DisplayPrice = displayPriceText;
  1289. using (var db = new MainDBContext())
  1290. {
  1291. db.ServerMessage.Add(new ServerMessage()
  1292. {
  1293. ChargeBoxId = session.ChargeBoxId,
  1294. CreatedBy = "Server",
  1295. CreatedOn = DateTime.UtcNow,
  1296. OutAction = Actions.ChangeConfiguration.ToString(),
  1297. OutRequest = JsonConvert.SerializeObject(
  1298. new ChangeConfigurationRequest()
  1299. {
  1300. key = "DefaultPrice",
  1301. value = clientDic[item.Key].DisplayPrice
  1302. },
  1303. new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
  1304. SerialNo = Guid.NewGuid().ToString(),
  1305. InMessage = string.Empty
  1306. }); ;
  1307. if (session.CustomerId == new Guid("10C7F5BD-C89A-4E2A-8611-B617E0B41A73"))
  1308. {
  1309. db.ServerMessage.Add(new ServerMessage()
  1310. {
  1311. ChargeBoxId = session.ChargeBoxId,
  1312. CreatedBy = "Server",
  1313. CreatedOn = DateTime.UtcNow,
  1314. OutAction = Actions.ChangeConfiguration.ToString(),
  1315. OutRequest = JsonConvert.SerializeObject(
  1316. new ChangeConfigurationRequest()
  1317. {
  1318. key = "ConnectionTimeOut",
  1319. value = "120"
  1320. },
  1321. new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
  1322. SerialNo = Guid.NewGuid().ToString(),
  1323. InMessage = string.Empty
  1324. });
  1325. db.ServerMessage.Add(new ServerMessage()
  1326. {
  1327. ChargeBoxId = session.ChargeBoxId,
  1328. CreatedBy = "Server",
  1329. CreatedOn = DateTime.UtcNow,
  1330. OutAction = Actions.ChangeConfiguration.ToString(),
  1331. OutRequest = JsonConvert.SerializeObject(
  1332. new ChangeConfigurationRequest()
  1333. {
  1334. key = "MeterValueSampleInterval",
  1335. value = "3"
  1336. },
  1337. new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
  1338. SerialNo = Guid.NewGuid().ToString(),
  1339. InMessage = string.Empty
  1340. });
  1341. }
  1342. await db.SaveChangesAsync();
  1343. }
  1344. }
  1345. }
  1346. }
  1347. catch (Exception ex)
  1348. {
  1349. logger.Error(string.Format("ServerSetFeeTrigger ChargeBoxId:{0} Ex:{1}", item.Key, ex.ToString()));
  1350. }
  1351. }
  1352. }
  1353. await Task.Delay(1000);
  1354. }
  1355. }
  1356. async private Task<string> SetDefaultFee(ClientData client)
  1357. {
  1358. string displayPriceText = string.Empty;
  1359. string charingPriceText = string.Empty;
  1360. if (string.IsNullOrEmpty(client.ChargeBoxId)) return displayPriceText;
  1361. using (SqlConnection conn = new SqlConnection(webConnectionString))
  1362. {
  1363. var parameters = new DynamicParameters();
  1364. parameters.Add("@MachineId", client.MachineId, DbType.String, ParameterDirection.Input);
  1365. string displayPricestrSql = "";
  1366. string strSql = "";
  1367. if (client.IsAC)
  1368. {
  1369. displayPricestrSql = " SELECT [AC_BillingMethod] as BillingMethod,[AC_FeeName] as FeeName,[AC_Fee] as ChargingFeebyHour" +
  1370. " ,[AC_ParkingFee] as ParkingFee, [Currency] FROM[StationMachine] left join[dbo].[Station]" +
  1371. " on[StationMachine].StationId = Station.[Id] where StationMachine.MachineId=@MachineId and Station.IsBilling=1; ";
  1372. strSql = " SELECT CAST( [StartTime] as varchar(5)) StartTime,CAST( [EndTime] as varchar(5)) EndTime,[Fee] FROM[StationMachine] left join [dbo].[StationFee]" +
  1373. " on[StationMachine].StationId = StationFee.StationId where StationMachine.MachineId =@MachineId and StationFee.IsAC=1; ";
  1374. }
  1375. else
  1376. {
  1377. displayPricestrSql = " SELECT [DC_BillingMethod] as BillingMethod,[DC_FeeName] as FeeName,[DC_Fee] as ChargingFeebyHour" +
  1378. " ,[DC_ParkingFee] as ParkingFee, [Currency] FROM[StationMachine] left join[dbo].[Station]" +
  1379. " on[StationMachine].StationId = Station.[Id] where StationMachine.MachineId=@MachineId and Station.IsBilling=1; ";
  1380. strSql = " SELECT CAST( [StartTime] as varchar(5)) StartTime,CAST( [EndTime] as varchar(5)) EndTime,[Fee] FROM[StationMachine] left join [dbo].[StationFee]" +
  1381. " on[StationMachine].StationId = StationFee.StationId where StationMachine.MachineId =@MachineId and StationFee.IsAC=0; ";
  1382. }
  1383. var result = await conn.QueryAsync<StationFee>(displayPricestrSql, parameters);
  1384. if (result.Count() == 0)
  1385. {
  1386. return string.Empty;
  1387. }
  1388. var stationPrice = result.First();
  1389. if (stationPrice.BillingMethod == 1)
  1390. {
  1391. var chargingPriceResult = await conn.QueryAsync<ChargingPrice>(strSql, parameters);
  1392. client.ChargingPrices = chargingPriceResult.ToList();
  1393. if (string.IsNullOrEmpty(client.ChargingPrices[0].StartTime))
  1394. {
  1395. client.ChargingPrices = new List<ChargingPrice>();
  1396. }
  1397. }
  1398. displayPriceText = stationPrice.FeeName;
  1399. client.BillingMethod = stationPrice.BillingMethod;
  1400. client.Currency = stationPrice.Currency;
  1401. client.ChargingFeebyHour = stationPrice.ChargingFeebyHour;
  1402. client.ParkingFee = stationPrice.ParkingFee;
  1403. client.IsBilling = true;
  1404. }
  1405. return displayPriceText;
  1406. }
  1407. async private void SmartChargingTrigger()
  1408. {
  1409. for (; ; )
  1410. {
  1411. if (_ct.IsCancellationRequested)
  1412. {
  1413. break;
  1414. }
  1415. var min_Interval = (DateTime.UtcNow - _CheckLBDt).TotalMinutes;
  1416. if (min_Interval > 1)
  1417. {
  1418. List<StationInfoDto> stations = null;
  1419. using (SqlConnection conn = new SqlConnection(webConnectionString))
  1420. {
  1421. string strSql = "SELECT[Id],[LBMode],[LBCurrent] as Availability FROM[StandardOCPP_Web].[dbo].[Station]" +
  1422. "where LBMode = 1; ";
  1423. var result = await conn.QueryAsync<StationInfoDto>(strSql);
  1424. stations = result.ToList();
  1425. }
  1426. foreach (var station in stations)
  1427. {
  1428. var compareStation = _StationInfo.Where(x => x.Id == station.Id).FirstOrDefault();
  1429. if (compareStation == null || (station.Id == compareStation.Id && station.Availability != compareStation.Availability))
  1430. {
  1431. var _powerDic = await _loadingBalanceService.GetSettingPower(station.Id);
  1432. if (_powerDic != null)
  1433. {
  1434. foreach (var kv in _powerDic)
  1435. {
  1436. try
  1437. {
  1438. if (kv.Value.HasValue)
  1439. {
  1440. profileHandler.SetChargingProfile(kv.Key, kv.Value.Value, Packet.Messages.SubTypes.ChargingRateUnitType.W);
  1441. }
  1442. }
  1443. catch (Exception ex)
  1444. {
  1445. logger.Error(string.Format("Set Profile Exception: {0}", ex.ToString()));
  1446. }
  1447. }
  1448. }
  1449. }
  1450. }
  1451. _StationInfo = stations;
  1452. _CheckLBDt = DateTime.UtcNow;
  1453. }
  1454. await Task.Delay(1000);
  1455. }
  1456. }
  1457. async private void HealthCheckTrigger()
  1458. {
  1459. for (; ; )
  1460. {
  1461. if (_ct.IsCancellationRequested)
  1462. {
  1463. break;
  1464. }
  1465. try
  1466. {
  1467. Dictionary<string, ClientData> _copyClientDic = null;
  1468. lock (_lockClientDic)
  1469. {
  1470. _copyClientDic = new Dictionary<string, ClientData>(clientDic);
  1471. }
  1472. List<string> stockedChargers = new List<string>();
  1473. using (var db = new MainDBContext())
  1474. {
  1475. stockedChargers = db.Machine.Select(x => x.ChargeBoxId).ToList();
  1476. }
  1477. foreach (var client in _copyClientDic)
  1478. {
  1479. if (!stockedChargers.Contains(client.Key))
  1480. {
  1481. client.Value.InStock = false;
  1482. }
  1483. }
  1484. var removeClients = _copyClientDic.Where(x => !x.Value.InStock || x.Value.LastActiveTime < DateTime.UtcNow.AddSeconds(-300)).Select(x => x.Value).ToList();
  1485. foreach (var session in removeClients)
  1486. {
  1487. Console.WriteLine(string.Format("Server forced to shut down ChargeBox ({0}: LastActiveTime{1} Instock:{2})", session.ChargeBoxId, session.LastActiveTime, session.InStock));
  1488. RemoveClient(session);
  1489. }
  1490. await Task.Delay(60000);
  1491. }
  1492. catch (Exception ex)
  1493. {
  1494. logger.Error(string.Format("HealthAlarmTrigger Ex:{0}", ex.ToString()));
  1495. }
  1496. }
  1497. }
  1498. private List<NeedConfirmMessage> GetResendMessage()
  1499. {
  1500. List<NeedConfirmMessage> sendMessages = new List<NeedConfirmMessage>();
  1501. lock (_lockConfirmPacketList)
  1502. {
  1503. sendMessages = needConfirmPacketList.Where(x => x.SentTimes > 1 && x.CreatedBy == "Server").ToList();
  1504. }
  1505. return sendMessages;
  1506. }
  1507. private void AddConfirmMessage(string chargePointSerialNumber, int table_id, string requestId, string action, string msg_id, string createdBy, string sendMessage)
  1508. {
  1509. NeedConfirmMessage _needConfirmMsg = new NeedConfirmMessage();
  1510. _needConfirmMsg.Id = table_id;
  1511. _needConfirmMsg.SentAction = action;
  1512. _needConfirmMsg.SentOn = DateTime.UtcNow;
  1513. _needConfirmMsg.SentTimes = 4;
  1514. _needConfirmMsg.ChargePointSerialNumber = chargePointSerialNumber;
  1515. _needConfirmMsg.RequestId = requestId;
  1516. _needConfirmMsg.SentUniqueId = msg_id;
  1517. _needConfirmMsg.CreatedBy = createdBy;
  1518. _needConfirmMsg.SentMessage = sendMessage;
  1519. if (needConfirmActions.Contains(action))
  1520. {
  1521. lock (_lockConfirmPacketList)
  1522. {
  1523. needConfirmPacketList.Add(_needConfirmMsg);
  1524. }
  1525. }
  1526. }
  1527. private void RemoveConfirmMessage()
  1528. {
  1529. var before10Mins = DateTime.UtcNow.AddMinutes(-10);
  1530. lock (_lockConfirmPacketList)
  1531. {
  1532. var removeList = needConfirmPacketList.Where(x => x.SentTimes == 0 || x.SentOn < before10Mins).ToList();
  1533. foreach (var item in removeList)
  1534. {
  1535. needConfirmPacketList.Remove(item);
  1536. }
  1537. }
  1538. }
  1539. private bool ReConfirmMessage(MessageResult analysisResult)
  1540. {
  1541. bool confirmed = false;
  1542. if (needConfirmActions.Contains(analysisResult.Action))
  1543. {
  1544. NeedConfirmMessage foundRequest = null;
  1545. lock (_lockConfirmPacketList)
  1546. {
  1547. foundRequest = needConfirmPacketList.Where(x => x.SentUniqueId == analysisResult.UUID).FirstOrDefault();
  1548. }
  1549. if (foundRequest != null && foundRequest.Id > 0)
  1550. {
  1551. foundRequest.SentTimes = 0;
  1552. foundRequest.SentInterval = 0;
  1553. analysisResult.RequestId = foundRequest.RequestId;
  1554. using (var db = new MainDBContext())
  1555. {
  1556. var sc = db.ServerMessage.Where(x => x.Id == foundRequest.Id).FirstOrDefault();
  1557. sc.InMessage = JsonConvert.SerializeObject(analysisResult.Message, Formatting.None);
  1558. sc.ReceivedOn = DateTime.UtcNow;
  1559. db.SaveChanges();
  1560. // Console.WriteLine(string.Format("Now:{0} ServerMessage Id:{1} ", DateTime.UtcNow.ToString("yyyy/MM/dd HH:mm:ss"), foundRequest.Id));
  1561. }
  1562. confirmed = true;
  1563. }
  1564. else if (analysisResult.Action == Actions.TriggerMessage.ToString())
  1565. {
  1566. confirmed = true;
  1567. }
  1568. else
  1569. {
  1570. logger.Error(string.Format("Received no record Action:{0} MessageId:{1} ", analysisResult.Action, analysisResult.UUID));
  1571. }
  1572. }
  1573. return confirmed;
  1574. }
  1575. private void RemoveClient(ClientData session)
  1576. {
  1577. if (session != null)
  1578. {
  1579. if (!string.IsNullOrEmpty(session.MachineId))
  1580. logger.Trace("RemoveClient[" + session.ChargeBoxId + "]");
  1581. if (session.Connected)
  1582. {
  1583. session.Close(CloseReason.ServerShutdown);
  1584. }
  1585. RemoveClientDic(session);
  1586. try
  1587. {
  1588. session.m_ReceiveData -= new ClientData.OCPPClientDataEventHandler<ClientData, String>(ReceivedMessage);
  1589. session.Close(CloseReason.ServerShutdown);
  1590. }
  1591. catch (Exception ex)
  1592. {
  1593. //logger.Warn("Close client socket error!!");
  1594. logger.Warn(string.Format("Close client socket error!! {0} Msg:{1}", session.ChargeBoxId, ex.Message));
  1595. }
  1596. if (session != null)
  1597. {
  1598. session = null;
  1599. }
  1600. }
  1601. }
  1602. private void RemoveClientDic(ClientData session)
  1603. {
  1604. if (!string.IsNullOrEmpty(session.ChargeBoxId))
  1605. {
  1606. lock (_lockClientDic)
  1607. {
  1608. if (clientDic.ContainsKey(session.ChargeBoxId))
  1609. {
  1610. if (clientDic[session.ChargeBoxId].SessionID == session.SessionID)
  1611. {
  1612. logger.Debug(String.Format("ChargeBoxId:{0} Remove SessionId:{1} Removed SessionId:{2}", session.ChargeBoxId, session.SessionID, clientDic[session.ChargeBoxId].SessionID));
  1613. clientDic.Remove(session.ChargeBoxId);
  1614. logger.Trace("RemoveClient ContainsKey " + session.ChargeBoxId);
  1615. }
  1616. }
  1617. }
  1618. }
  1619. }
  1620. private void WarmUpLog()
  1621. {
  1622. try
  1623. {
  1624. //using (var maindb = new MainDBContext())
  1625. //{
  1626. // GlobalConfig.Machines = maindb.Machine.ToList();
  1627. //}
  1628. using (var log = new ConnectionLogDBContext())
  1629. {
  1630. log.MachineConnectionLog.ToList();
  1631. }
  1632. }
  1633. catch (Exception ex)
  1634. {
  1635. Console.WriteLine(ex.ToString());
  1636. }
  1637. }
  1638. private void WriteMachineLog(ClientData clientData, string data, string messageType, string errorMsg = "", bool isSent = false)
  1639. {
  1640. try
  1641. {
  1642. if (clientData == null || string.IsNullOrEmpty(data)) return;
  1643. if (clientData.ChargeBoxId == null)
  1644. {
  1645. logger.Fatal(clientData.Path + "]********************session ChargeBoxId null sessionId=" + clientData.SessionID);
  1646. }
  1647. using (var db = new ConnectionLogDBContext())
  1648. {
  1649. string sp = "[dbo].[uspInsertMachineConnectionLog] @CreatedOn," +
  1650. "@ChargeBoxId,@MessageType,@Data,@Msg,@IsSent,@EVSEEndPoint,@Session";
  1651. var dd = DateTime.UtcNow;
  1652. SqlParameter[] parameter =
  1653. {
  1654. new SqlParameter("CreatedOn",dd),
  1655. new SqlParameter("ChargeBoxId",clientData.ChargeBoxId==null?"unknown":clientData.ChargeBoxId.Replace("'","''")),
  1656. new SqlParameter("MessageType",messageType.Replace("'","''")),
  1657. new SqlParameter("Data",data.Replace("'","''")),
  1658. new SqlParameter("Msg",errorMsg.Replace("'","''")),
  1659. new SqlParameter("IsSent",isSent),
  1660. new SqlParameter("EVSEEndPoint",clientData.RemoteEndPoint==null?"unknown":clientData.RemoteEndPoint.ToString()),
  1661. new SqlParameter("Session",clientData.SessionID==null?"unknown":clientData.SessionID)
  1662. };
  1663. db.Database.ExecuteSqlCommand(sp, parameter);
  1664. }
  1665. }
  1666. catch (Exception ex)
  1667. {
  1668. logger.Error(string.Format("{0}:{1} {2}", "WriteMachineLog EX", ex.ToString(), data));
  1669. }
  1670. }
  1671. }
  1672. }