PageRenderTime 64ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/EntLib/CE.WebServiceClient.DRHub/DRHubClient.cs

https://bitbucket.org/jeffmccommas/acex
C# | 947 lines | 720 code | 136 blank | 91 comment | 55 complexity | cef5466f1b324ba15bb97f7376975088 MD5 | raw file
  1. using CE.ContentModel;
  2. using CE.ContentModel.ContentCache;
  3. using CE.NotificationManager.Entities;
  4. using Newtonsoft.Json.Linq;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Configuration;
  8. using System.Data;
  9. using System.Data.SqlClient;
  10. using System.IO;
  11. using System.Linq;
  12. using System.Net;
  13. using System.Net.Http;
  14. using System.Net.Http.Headers;
  15. using System.Text;
  16. using System.Threading;
  17. using System.Threading.Tasks;
  18. using System.Xml;
  19. using System.Xml.Linq;
  20. using System.Xml.Serialization;
  21. namespace CE.WebServiceClient.DRHub
  22. {
  23. public class DRHubClient : IDRHub
  24. {
  25. #region "private variables"
  26. private DRHubConfig _config;
  27. private readonly NLogger.ASyncLogger _logger;
  28. private string _environment;
  29. private readonly int _clientId;
  30. private bool _configSetUp;
  31. private string _tokenId;
  32. private string _cookieName;
  33. //private bool _simulation;
  34. //private int _simulationInterval;
  35. #endregion
  36. #region "private const"
  37. private const string PjmNoticationEvent = "PJM Notification Event";
  38. private const string SeverityHigh = "High";
  39. private const string SeverityMedium = "Medium";
  40. private const string SeverityLow = "Low";
  41. private const string CatagoryPoll = "Poll";
  42. private const string CatagoryPingPoll = "Ping Poll";
  43. private const string CatagoryAck = "Acknowledge";
  44. private const string EventBegin = "Begins";
  45. private const string EventEnd = "Ends";
  46. private const string MsgPollEvents = "PJM Poll Event";
  47. private const string MsgAckEvents = "Acknowledge Event";
  48. private const string MsgProcessResponse = "Process PJM Response";
  49. private const string MsgSimulateEvents = "PJM Event Simulation";
  50. private const string MsgProcessEvents = "Process PJM Events";
  51. private const string MsgEventsReceived = "Event Received";
  52. private const string MsgRequest = "Request";
  53. private const string MsgResponse = "Response";
  54. private const string MsgPingEvents = "Ping Poll Event";
  55. private const string MsgNoEvent = "No Event";
  56. private const string MsgNoTeamNameMapping = "No Team Name Mapping for Registration ID";
  57. private const string HeaderVerbGet = "get";
  58. private const string HeaderVerbChange = "change";
  59. private const string HeaderNounEvent = "event";
  60. private const string HeaderRevision = "1.0";
  61. private const string HeaderSource = "OECSP";
  62. private const string RequestOptionUnAck = "unack";
  63. private const string RequestOptionAck = "ack";
  64. private const string PayloadFormat = "XML";
  65. private const string ReplyCodeOkay = "ok";
  66. private const string ReplyCodeWarning = "warning";
  67. private const string ReplyCodeFatal = "fatal";
  68. private const string ErrorCode = "4005";
  69. private const int DefaultMaxRetry = 5;
  70. private const string MsgLeadTimeWarning = "Invalid Lead Time, default to Quick_30";
  71. #endregion
  72. public DRHubClient(int clientId)
  73. {
  74. //_environment = environment;
  75. _clientId = clientId;
  76. Console.WriteLine("Initiate Logger" );
  77. _logger = new NLogger.ASyncLogger(clientId, _environment);
  78. GetDRHubConfig(clientId);
  79. }
  80. #region "public methods"
  81. /// <summary>
  82. /// call the api to poll events
  83. /// </summary>
  84. /// <returns></returns>
  85. public EventsCollection PollEvents()
  86. {
  87. EventsCollection eventsCol = null;
  88. //#if DEBUG
  89. // _config.Simulation = true;
  90. //#endif
  91. if (_configSetUp)
  92. {
  93. if (_config.Simulation)
  94. {
  95. var simulate = false;
  96. var currentTime = DateTime.Now;
  97. switch (_config.SimulationInterval)
  98. {
  99. case 5:
  100. if (currentTime.Minute % 5 == 0)
  101. simulate = true;
  102. break;
  103. case 15:
  104. if (currentTime.Minute % 15 == 0)
  105. simulate = true;
  106. break;
  107. case 30:
  108. if (currentTime.Minute % 30 == 0)
  109. simulate = true;
  110. break;
  111. case 60:
  112. if (currentTime.Minute % 60 == 0)
  113. simulate = true;
  114. break;
  115. case 1440:
  116. if (currentTime.TimeOfDay.Ticks == 0)
  117. simulate = true;
  118. break;
  119. }
  120. // simulate poll pjm events
  121. eventsCol = Simulate(simulate ? GetEventsResponseString() : GetNoEventResponseString());
  122. }
  123. else
  124. {
  125. // poll pjm events
  126. eventsCol = Poll(0);
  127. }
  128. }
  129. return eventsCol;
  130. }
  131. /// <summary>
  132. /// call api to acknowledge events
  133. /// </summary>
  134. /// <param name="events"></param>
  135. /// <param name="retry"></param>
  136. public void AcknowledgeEvents(EventsCollection events, int retry)
  137. {
  138. if (_configSetUp)
  139. {
  140. string ackEventUri = _config.ServiceUrl + _config.AcknowledgeEventsAction;
  141. HttpClient client = new HttpClient();
  142. //var authCTS = new CancellationTokenSource();
  143. //Task task = Task.Run(async () =>
  144. //{
  145. client = GetAuthDRHubClient(ackEventUri, CatagoryAck);
  146. //}, authCTS.Token);
  147. //authCTS.CancelAfter(3000);
  148. //await task;
  149. try
  150. {
  151. Console.WriteLine("{0} {1}", MsgAckEvents, EventBegin);
  152. _logger.Info(CatagoryAck, SeverityLow, PjmNoticationEvent, string.Format("{0} {1}", MsgAckEvents, EventBegin));
  153. // create payload events and convert into xml doc
  154. var acknowledgementPayloadStr = events.Xml;
  155. var xmlDoc = new XmlDocument();
  156. xmlDoc.LoadXml(acknowledgementPayloadStr);
  157. var httpContent = new StringContent(acknowledgementPayloadStr, Encoding.UTF8, "application/xml");
  158. // log the request info TODO: Is this the right thing to log?
  159. _logger.Info(CatagoryAck, SeverityLow, PjmNoticationEvent, acknowledgementPayloadStr, string.Empty, MsgRequest);
  160. // TODO: #DRHUB change call to get response from REST
  161. Console.WriteLine("Send Request");
  162. HttpResponseMessage responseFromPost = new HttpResponseMessage();
  163. string responseContent = string.Empty;
  164. //var cts = new CancellationTokenSource();
  165. //Task responseTask = Task.Run(async () =>
  166. //{
  167. responseFromPost = client.PutAsync(new Uri(ackEventUri), httpContent).Result;
  168. //responseFromPost.EnsureSuccessStatusCode();
  169. responseContent = responseFromPost.Content.ReadAsStringAsync().Result;
  170. //}, cts.Token);
  171. //cts.CancelAfter(3000);
  172. //await responseTask;
  173. Console.WriteLine("Response Received");
  174. if (!responseFromPost.IsSuccessStatusCode)
  175. {
  176. string errorMsg = responseFromPost.StatusCode.ToString() + " " + responseFromPost.ReasonPhrase;
  177. _logger.Error(CatagoryAck, SeverityHigh, PjmNoticationEvent, acknowledgementPayloadStr, responseContent, string.Format("Response fatal - {0}", errorMsg));
  178. throw new Exception(string.Format("Response fatal - {0}", errorMsg));
  179. }
  180. else
  181. {
  182. //log the response info
  183. Console.WriteLine(responseContent);
  184. _logger.Info(CatagoryAck, SeverityLow, PjmNoticationEvent, string.Empty, responseContent, MsgResponse);
  185. }
  186. _logger.Info(CatagoryAck, SeverityLow, PjmNoticationEvent, string.Format("{0} {1}", MsgAckEvents, EventEnd));
  187. Console.WriteLine("{0} {1}", MsgAckEvents, EventEnd);
  188. }
  189. catch (Exception ex)
  190. {
  191. _logger.ErrorException(CatagoryAck, SeverityHigh, PjmNoticationEvent, ex);
  192. if (retry < _config.MaxRetry)
  193. {
  194. retry++;
  195. _logger.Info(CatagoryAck, SeverityLow, PjmNoticationEvent, string.Format("{0} {1}", MsgAckEvents, EventEnd));
  196. #if DEBUG
  197. Console.WriteLine("{0} {1}", MsgAckEvents, EventEnd);
  198. #endif
  199. Task.Delay(_config.RetryWaitDuration);
  200. _logger.Info(CatagoryAck, SeverityMedium, PjmNoticationEvent, string.Format("Retry Attempt: {0}", retry));
  201. #if DEBUG
  202. Console.WriteLine("Retry Attempt: {0}", retry);
  203. #endif
  204. AcknowledgeEvents(events, retry);
  205. }
  206. else
  207. {
  208. _logger.Info(CatagoryAck, SeverityLow, PjmNoticationEvent, string.Format("{0} {1}", MsgAckEvents, EventEnd));
  209. Console.WriteLine("{0} {1}", MsgAckEvents, EventEnd);
  210. _logger.EmailErrorException(CatagoryAck, SeverityHigh, PjmNoticationEvent, ex);
  211. throw;
  212. }
  213. //_logger.Error(catagoryAck, string.Empty, string.Empty, ex.Message);
  214. }
  215. finally
  216. {
  217. client.Dispose();
  218. }
  219. return;
  220. }
  221. }
  222. /// <summary>
  223. /// for standalone DRHUB REST service pinging
  224. /// </summary>
  225. public void Ping(int retry)
  226. {
  227. string getEventUri = _config.ServiceUrl + _config.GetEventsAction;
  228. HttpClient client = new HttpClient();
  229. //var authCTS = new CancellationTokenSource();
  230. //Task task = Task.Run(async () =>
  231. //{
  232. client = GetAuthDRHubClient(getEventUri, CatagoryPingPoll);
  233. //}, authCTS.Token);
  234. //authCTS.CancelAfter(3000);
  235. //await task;
  236. try
  237. {
  238. Console.WriteLine("{0} {1}", MsgPingEvents, EventBegin);
  239. _logger.Info(CatagoryPingPoll, SeverityLow, PjmNoticationEvent, string.Format("{0} {1}", MsgPingEvents, EventBegin));
  240. #if DEBUG
  241. Console.WriteLine("Send Request");
  242. #endif
  243. HttpResponseMessage restResponse = client.GetAsync(getEventUri).Result;
  244. #if DEBUG
  245. Console.WriteLine("Response Received");
  246. #endif
  247. _logger.Info(CatagoryPingPoll, SeverityLow, PjmNoticationEvent, string.Format("{0} Succeeded", MsgPingEvents));
  248. Console.WriteLine("{0} Succeeded", MsgPingEvents);
  249. _logger.Info(CatagoryPingPoll, SeverityLow, PjmNoticationEvent, string.Format("{0} {1}", MsgPingEvents, EventEnd));
  250. Console.WriteLine("{0} {1}", MsgPingEvents, EventEnd);
  251. }
  252. catch (Exception ex)
  253. {
  254. _logger.ErrorException(CatagoryPingPoll, SeverityMedium, PjmNoticationEvent, ex);
  255. if (retry < _config.MaxRetry)
  256. {
  257. retry++;
  258. _logger.Info(CatagoryPingPoll, SeverityLow, PjmNoticationEvent, string.Format("{0} {1}", MsgPingEvents, EventEnd));
  259. #if DEBUG
  260. Console.WriteLine("{0} {1}", MsgPingEvents, EventEnd);
  261. #endif
  262. Task.Delay(_config.RetryWaitDuration);
  263. _logger.Info(CatagoryPingPoll, SeverityMedium, PjmNoticationEvent, string.Format("Retry Attempt: {0}", retry));
  264. Console.WriteLine("Retry Attempt: {0}", retry);
  265. Ping(retry);
  266. }
  267. else
  268. {
  269. _logger.Info(CatagoryPingPoll, SeverityLow, PjmNoticationEvent, string.Format("{0} {1}", MsgPingEvents, EventEnd));
  270. Console.WriteLine("{0} {1}", MsgPingEvents, EventEnd);
  271. _logger.EmailErrorException(CatagoryPingPoll, SeverityMedium, PjmNoticationEvent, ex);
  272. throw;
  273. }
  274. }
  275. finally
  276. {
  277. client.Dispose();
  278. }
  279. }
  280. #endregion
  281. #region "private methods"
  282. private EventsCollection Poll(int retry)
  283. {
  284. string getEventUri = _config.ServiceUrl + _config.GetEventsAction;
  285. //var authCTS = new CancellationTokenSource();
  286. HttpClient client = new HttpClient();
  287. //Task task = Task.Run(async () =>
  288. //{
  289. client = GetAuthDRHubClient(getEventUri, CatagoryPoll);
  290. //}, authCTS.Token);
  291. //authCTS.CancelAfter(3000);
  292. //await task;
  293. EventsCollection events = new EventsCollection();
  294. try
  295. {
  296. Console.WriteLine("{0} {1}", MsgPollEvents, EventBegin);
  297. _logger.Info(CatagoryPoll, SeverityLow, PjmNoticationEvent, string.Format("{0} {1}", MsgPollEvents, EventBegin));
  298. client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/html"));
  299. client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xhtml+xml"));
  300. client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
  301. client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
  302. client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate"));
  303. client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("sdch"));
  304. client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("br"));
  305. var cts = new CancellationTokenSource();
  306. HttpResponseMessage restResponse = new HttpResponseMessage();
  307. //Task responseTask = Task.Run(async () =>
  308. //{
  309. restResponse = client.GetAsync(getEventUri).Result;
  310. restResponse.EnsureSuccessStatusCode();
  311. events = ProcessResponse(restResponse);
  312. //}, cts.Token);
  313. //cts.CancelAfter(3000);
  314. //await responseTask;
  315. }
  316. catch (Exception ex)
  317. {
  318. if (retry < _config.MaxRetry)
  319. {
  320. retry++;
  321. Console.WriteLine("{0} {1}", MsgPollEvents, EventEnd);
  322. _logger.Info(CatagoryPoll, SeverityLow, PjmNoticationEvent, string.Format("{0} {1}", MsgPollEvents, EventEnd));
  323. Task.Delay(_config.RetryWaitDuration);
  324. #if DEBUG
  325. Console.WriteLine("Retry Attempt: {0}", retry);
  326. #endif
  327. _logger.Info(CatagoryPoll, SeverityMedium, PjmNoticationEvent, string.Format("Retry Attempt: {0}", retry));
  328. events = Poll(retry);
  329. }
  330. else
  331. {
  332. var currentTime = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTime.UtcNow, "Eastern Standard Time");
  333. if (currentTime.TimeOfDay >= Convert.ToDateTime("10:00").TimeOfDay && currentTime.TimeOfDay <= Convert.ToDateTime("20:30").TimeOfDay)
  334. {
  335. _logger.ErrorException(CatagoryPoll, SeverityHigh, PjmNoticationEvent, ex);
  336. _logger.EmailErrorException(CatagoryPoll, SeverityHigh, PjmNoticationEvent, ex);
  337. }
  338. else
  339. {
  340. _logger.ErrorException(CatagoryPoll, SeverityLow, PjmNoticationEvent, ex);
  341. _logger.EmailErrorException(CatagoryPoll, SeverityLow, PjmNoticationEvent, ex);
  342. }
  343. //_logger.Error(catagoryPoll, string.Empty, string.Empty, ex.Message);
  344. _logger.Info(CatagoryPoll, SeverityLow, PjmNoticationEvent, string.Format("{0} {1}", MsgPollEvents, EventEnd));
  345. Console.WriteLine("{0} {1}", MsgPollEvents, EventEnd);
  346. throw;
  347. }
  348. }
  349. finally
  350. {
  351. client.Dispose();
  352. }
  353. return events;
  354. }
  355. private void GetDRHubConfig(int clientId)
  356. {
  357. var cacheKey = string.Empty;
  358. Console.WriteLine("Initiate content model factory contentful");
  359. var cf = new ContentModelFactoryContentful();
  360. Console.WriteLine("Create ContentCacheProvider");
  361. var contentCashProvider = ContentCacheProviderFactory.CreateContentCacheProvider();
  362. try
  363. {
  364. Console.WriteLine("Create/Retrieve DRHub Config Begins");
  365. var contentRepository = cf.CreateContentRepository(clientId);
  366. Console.WriteLine("Get Content Eviornment");
  367. _environment = contentRepository.GetContentEnvironment();
  368. _logger.Envirnoment = _environment;
  369. Console.WriteLine("Create cache Key");
  370. // TODO: HOW DO WE CHANGE THE CACHE KEY HERE TO REMOVE THE ELRS reference?
  371. cacheKey = string.Format("ElrsConfig_{0}_{1}", clientId, _environment);
  372. Console.WriteLine("Get cached config");
  373. _config = (DRHubConfig)contentCashProvider.Get(cacheKey);
  374. }
  375. catch
  376. {
  377. _config = null;
  378. }
  379. if (_config != null)
  380. {
  381. _configSetUp = true;
  382. Console.WriteLine("Create/Retrieve DRHub Config Ends");
  383. return;
  384. }
  385. try
  386. {
  387. Console.WriteLine("No cache, create new config");
  388. _config = new DRHubConfig();
  389. Console.WriteLine("Create ContentProvider");
  390. var cp = cf.CreateContentProvider(clientId);
  391. var configurationList = cp.GetContentConfiguration(ContentCategory.Notification.ToString().ToLower(), string.Empty);
  392. if (configurationList.Any())
  393. {
  394. //_config.WebServiceEndPoint = configurationList.Find(item => item.Key == "webserviceclient.elrs.endpoint").Value;
  395. _config.Username = configurationList.Find(item => item.Key == "webserviceclient.drhub.username").Value;
  396. _config.Password = configurationList.Find(item => item.Key == "webserviceclient.drhub.password").Value;
  397. _config.EventTypes = configurationList.Find(item => item.Key == "webserviceclient.drhub.eventtypes").Value
  398. .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
  399. _config.ServiceUrl = configurationList.Find(item => item.Key == "webserviceclient.drhub.serviceurl").Value;
  400. _config.GetEventsAction = configurationList.Find(item => item.Key == "webserviceclient.drhub.geteventsaction").Value;
  401. _config.AcknowledgeEventsAction = configurationList.Find(item => item.Key == "webserviceclient.drhub.ackeventsaction").Value;
  402. _config.AuthUrl = configurationList.Find(item => item.Key == "webserviceclient.drhub.authurl").Value;
  403. _config.MaxRetry = Convert.ToInt32(configurationList.Find(item => item.Key == "webserviceclient.global.maxretry").Value);
  404. if (_config.MaxRetry > DefaultMaxRetry) _config.MaxRetry = DefaultMaxRetry;
  405. _config.RetryWaitDuration = Convert.ToInt32(configurationList.Find(item => item.Key == "webserviceclient.global.retrywaitduration").Value);
  406. _config.Simulation = Convert.ToBoolean(configurationList.Find(item => item.Key == "webserviceclient.drhub.enablesimulation").Value);
  407. _config.SimulationInterval = Convert.ToInt32(configurationList.Find(item => item.Key == "webserviceclient.drhub.simulationeventinterval").Value);
  408. _config.CookieName = configurationList.Find(item => item.Key == "webserviceclient.drhub.cookiename").Value;
  409. }
  410. _configSetUp = true;
  411. contentCashProvider.Set(cacheKey, _config, DateTime.Now.AddMinutes(30));
  412. Console.WriteLine("Create/Retrieve DRHub Config Ends");
  413. }
  414. catch (Exception ex)
  415. {
  416. _logger.ErrorException(CatagoryPoll, SeverityHigh, PjmNoticationEvent, ex);
  417. _logger.EmailErrorException(CatagoryPoll, SeverityHigh, PjmNoticationEvent, ex);
  418. throw;
  419. }
  420. }
  421. private EventsCollection ProcessResponse(HttpResponseMessage response)
  422. {
  423. // responseData should contain events in xml format.
  424. EventsCollection eventsCol = null;
  425. string reqString = _config.ServiceUrl + _config.GetEventsAction;
  426. string respString = string.Empty;
  427. Console.WriteLine("{0} {1}", MsgProcessResponse, EventBegin);
  428. _logger.Info(CatagoryPoll, SeverityLow, PjmNoticationEvent, string.Format("{0} {1}", MsgProcessResponse, EventBegin));
  429. if (response.IsSuccessStatusCode)//if (response.ReasonPhrase.ToLower() == ReplyCodeOkay)
  430. {
  431. respString = response.Content.ReadAsStringAsync().Result;
  432. if (!respString.Contains("</ns2:events>")) // closing tag that will only be present if events are sent
  433. {
  434. // no events sent
  435. Console.WriteLine(MsgNoEvent);
  436. _logger.Info(CatagoryPoll, SeverityMedium, PjmNoticationEvent, reqString.ToString(), respString.ToString(), MsgNoEvent);
  437. } else
  438. {
  439. // there are events. process them.
  440. _logger.Info(CatagoryPoll, SeverityLow, PjmNoticationEvent, reqString.ToString(), respString.ToString(), string.Empty);
  441. eventsCol = ProcessEvents(respString);
  442. }
  443. }
  444. else // fatal error
  445. {
  446. _logger.EmailError(CatagoryPoll, SeverityHigh, PjmNoticationEvent, reqString.ToString(), respString.ToString(), "some really bad error"); //response.Reply.Error[0]);
  447. _logger.Error(CatagoryPoll, SeverityHigh, PjmNoticationEvent, reqString.ToString(), respString.ToString(), "some really bad error");// response.Reply.Error[0]);
  448. }
  449. _logger.Info(CatagoryPoll, SeverityLow, PjmNoticationEvent, string.Format("{0} {1}", MsgProcessResponse, EventEnd));
  450. Console.WriteLine("{0} {1}", MsgProcessResponse, EventEnd);
  451. return eventsCol;
  452. }
  453. private EventsCollection Simulate(string serializedResponse)
  454. {
  455. try
  456. {
  457. //Console.WriteLine("{0} {1}", MsgSimulateEvents, EventBegin);
  458. _logger.Info(CatagoryPoll, SeverityLow, PjmNoticationEvent, string.Format("{0} {1}", MsgSimulateEvents, EventBegin));
  459. var reader = new StringReader(serializedResponse);
  460. _logger.Info(CatagoryPoll, SeverityLow, PjmNoticationEvent, string.Format("{0} {1}", MsgSimulateEvents, EventEnd));
  461. Console.WriteLine("{0} {1}", MsgSimulateEvents, EventEnd);
  462. EventsCollection events = ProcessEvents(serializedResponse);
  463. events.Xml = serializedResponse;
  464. return events;
  465. }
  466. catch (Exception ex)
  467. {
  468. _logger.ErrorException(CatagoryPoll, SeverityHigh, PjmNoticationEvent, ex);
  469. _logger.Info(CatagoryPoll, SeverityLow, PjmNoticationEvent, string.Format("{0} {1}", MsgSimulateEvents, EventEnd));
  470. _logger.EmailErrorException(CatagoryPoll, SeverityHigh, PjmNoticationEvent, ex);
  471. throw;
  472. }
  473. }
  474. private EventsCollection ProcessEvents(string responseData)
  475. {
  476. Console.WriteLine("{0} {1}", MsgProcessEvents, EventBegin);
  477. _logger.Info(CatagoryPoll, SeverityLow, PjmNoticationEvent, string.Format("{0} {1}", MsgProcessEvents, EventBegin));
  478. // pull the team name mapping list from configuration
  479. var teamNames = GetTeamNameMappingList();
  480. var response = new EventsCollection {Xml = responseData};
  481. string eventId = string.Empty;
  482. string type = String.Empty;
  483. string target = string.Empty; // CURRENTLY NOT CAPTURED. MODEL CHANGED IN XML.
  484. string status = string.Empty;
  485. string regLeadTime = string.Empty;
  486. var startTime = DateTime.MinValue;
  487. var notifyTime = DateTime.MinValue;
  488. var endTime = DateTime.MinValue;
  489. var startUtcTime = DateTime.MinValue;
  490. var notifyUtcTime = DateTime.MinValue;
  491. var endUtcTime = DateTime.MinValue;
  492. var sleadTime = string.Empty;
  493. var zone = string.Empty;
  494. XmlDocument doc = new XmlDocument();
  495. doc.LoadXml(responseData);
  496. var nsmgr = new XmlNamespaceManager(doc.NameTable);
  497. nsmgr.AddNamespace("ns2", "http://drhub.pjm.com/");
  498. XmlNode eventsNode = doc.SelectSingleNode("//ns2:events", nsmgr);
  499. foreach (XmlNode eventSummary in eventsNode)
  500. {
  501. XmlNode idNode = eventSummary.SelectSingleNode("id");
  502. eventId = idNode.InnerText;
  503. XmlNode infoNode = eventSummary.SelectSingleNode("eventSummaryInfo");
  504. status = infoNode["status"].InnerText;
  505. regLeadTime = infoNode["regLeadTime"].InnerText;
  506. notifyTime = Convert.ToDateTime(infoNode["notifyTime"].InnerText);
  507. notifyUtcTime = Convert.ToDateTime(infoNode["notifyTime"].InnerText).ToUniversalTime();
  508. startTime = Convert.ToDateTime(infoNode["startTime"].InnerText);
  509. startUtcTime = Convert.ToDateTime(infoNode["startTime"].InnerText).ToUniversalTime();
  510. zone = infoNode["zone"].InnerText;
  511. if (infoNode["endTime"] != null)
  512. {
  513. endTime = Convert.ToDateTime(infoNode["endTime"].InnerText);
  514. endUtcTime = Convert.ToDateTime(infoNode["endTime"].InnerText).ToUniversalTime();
  515. }
  516. zone = infoNode["zone"].InnerText;
  517. var eventStatus = EventStatus.None;
  518. switch (status.ToLower())
  519. {
  520. case "scheduled":
  521. eventStatus = EventStatus.Scheduled;
  522. break;
  523. case "active":
  524. eventStatus = EventStatus.Active;
  525. break;
  526. case "completed":
  527. eventStatus = EventStatus.Completed;
  528. break;
  529. case "canceled":
  530. case "cancelled":
  531. eventStatus = EventStatus.Canceled;
  532. break;
  533. }
  534. var eventType = EventType.LoadManagement;
  535. switch (type.ToLower())
  536. {
  537. case "load management":
  538. eventType = EventType.LoadManagement;
  539. break;
  540. case "real-time dispatch":
  541. eventType = EventType.RealTimeDispatch;
  542. break;
  543. case "synchronized reserved":
  544. eventType = EventType.SynchronizedReserved;
  545. break;
  546. case "zonal test":
  547. eventType = EventType.ZonalTest;
  548. break;
  549. case "zonal retest":
  550. eventType = EventType.ZonalRetest;
  551. break;
  552. }
  553. var leadTime = LeadTimeType.Quick30;
  554. switch (regLeadTime.ToLower())
  555. {
  556. case "long_120":
  557. leadTime = LeadTimeType.Long120;
  558. break;
  559. case "short_60":
  560. leadTime = LeadTimeType.Short60;
  561. break;
  562. case "quick_30":
  563. leadTime = LeadTimeType.Quick30;
  564. break;
  565. default:
  566. leadTime = LeadTimeType.Quick30;
  567. //_logger.Error(CatagoryPoll, SeverityMedium, PjmNoticationEvent, MsgLeadTimeWarning);
  568. break;
  569. }
  570. var regInfoList = new List<RegistrationInfo>();
  571. XmlNode detailNode = eventSummary.SelectSingleNode("eventDetail");
  572. foreach (XmlNode evt in detailNode)
  573. {
  574. string regId = evt.SelectSingleNode("eventRegistration").SelectSingleNode("registrationId").InnerText;
  575. regInfoList.Add(new RegistrationInfo { RegistrationId = regId, Zone = zone, Target=target }); // TODO: CHECK ADDITION OF TARGET TO REGINFO.
  576. }
  577. var regIds = string.Empty;
  578. regInfoList.ForEach(r =>
  579. {
  580. if (regIds != string.Empty)
  581. regIds += ",";
  582. regIds += r.RegistrationId;
  583. });
  584. _logger.Info(CatagoryPoll, SeverityLow, PjmNoticationEvent, MsgEventsReceived, eventSummary.OuterXml);
  585. Console.WriteLine(eventSummary.OuterXml);
  586. GetTeamName(regInfoList, teamNames);
  587. response.Events.Add(new EventInfo
  588. {
  589. EndTime = endTime,
  590. EndUtcTime = endUtcTime,
  591. EventId = eventId,
  592. EventType = eventType,
  593. LeadTime = leadTime,
  594. NotifyTime = notifyTime,
  595. NotifyUtcTime = notifyUtcTime,
  596. RegistrationInfoList = regInfoList,
  597. StartTime = startTime,
  598. StartUtcTime = startUtcTime,
  599. Status = eventStatus,
  600. Target = target,
  601. EventXml = eventSummary.InnerXml
  602. });
  603. }
  604. return response;
  605. }
  606. /// <summary>
  607. /// get team name based on registration id
  608. /// </summary>
  609. /// <param name="regInfoList"></param>
  610. /// <param name="teamNames"></param>
  611. /// <returns></returns>
  612. private void GetTeamName(List<RegistrationInfo> regInfoList, List<TeamNameMapping> teamNames)
  613. {
  614. regInfoList.ForEach(r =>
  615. {
  616. var team = teamNames.Find(t => t.RegistrationId == r.RegistrationId);
  617. if (team != null)
  618. {
  619. r.TeamName = team.TeamName;
  620. r.IsHoneywellDlc = team.IsHoneywellDlc;
  621. }
  622. else
  623. {
  624. _logger.Error(CatagoryPoll, SeverityHigh, PjmNoticationEvent, string.Format("{0} {1}", MsgNoTeamNameMapping, r.RegistrationId));
  625. _logger.EmailError(CatagoryPoll, SeverityHigh, PjmNoticationEvent, string.Format("{0} {1}", MsgNoTeamNameMapping, r.RegistrationId));
  626. }
  627. });
  628. }
  629. private void SetPJMTokenId(int retry, string catagory)
  630. {
  631. CookieContainer cookies = new CookieContainer();
  632. HttpClientHandler handler = new HttpClientHandler();
  633. handler.CookieContainer = cookies;
  634. HttpClient client = new HttpClient(handler);
  635. HttpRequestMessage msg = new HttpRequestMessage()
  636. {
  637. RequestUri = new Uri(_config.AuthUrl),
  638. Method = HttpMethod.Post
  639. };
  640. // TODO: get username and password from config
  641. string username = _config.Username;
  642. string password = _config.Password;
  643. msg.Headers.Add("X-OpenAM-Username", username);
  644. msg.Headers.Add("X-OpenAM-Password", password);
  645. HttpResponseMessage response = new HttpResponseMessage();
  646. string responseBody = string.Empty;
  647. //var authCTS = new CancellationTokenSource();
  648. //Task task = Task.Run(async () =>
  649. //{
  650. response = client.SendAsync(msg).Result;
  651. //}, authCTS.Token);
  652. //authCTS.CancelAfter(3000);
  653. //await task;
  654. responseBody = response.Content.ReadAsStringAsync().Result;
  655. _tokenId = GetTokenId(responseBody);
  656. // retry - max 5 times; otherwise throw exception
  657. if (string.IsNullOrEmpty(_tokenId))
  658. {
  659. if (retry < _config.MaxRetry)
  660. {
  661. retry++;
  662. _logger.Info(catagory, SeverityMedium, PjmNoticationEvent, string.Format("Set PJM Token Id Retry Attempt: {0}", retry));
  663. #if DEBUG
  664. Console.WriteLine("Set PJM Token Id Retry Attempt: {0}", retry);
  665. #endif
  666. SetPJMTokenId(retry, catagory);
  667. }
  668. else
  669. {
  670. var exception = new Exception("Unable to set PJM Token Id");
  671. _logger.EmailErrorException(catagory, SeverityHigh, PjmNoticationEvent, exception);
  672. throw exception;
  673. }
  674. }
  675. }
  676. private HttpClient GetAuthDRHubClient(string requestUri, string catagory)
  677. {
  678. if (string.IsNullOrEmpty(_tokenId))
  679. {
  680. SetPJMTokenId(0, catagory);
  681. }
  682. // SET AUTH COOKIE
  683. HttpClientHandler dataClientHandler = new HttpClientHandler();
  684. dataClientHandler.CookieContainer = new CookieContainer();
  685. dataClientHandler.CookieContainer.Add(new Uri(requestUri), new Cookie(_config.CookieName, _tokenId));
  686. // Create client
  687. HttpClient dataClient = new HttpClient(dataClientHandler);
  688. return dataClient;
  689. }
  690. private List<TeamNameMapping> GetTeamNameMappingList()
  691. {
  692. var teamNames = new List<TeamNameMapping>();
  693. var mappingStr = GetTeamNameMappingXml();
  694. var teamNameDoc = XDocument.Load(new StringReader(mappingStr));
  695. var teamNameMapping = teamNameDoc.Descendants("TeamNameMapping").Select(x => x).ToList();
  696. teamNameMapping.ForEach(tm =>
  697. {
  698. tm.Descendants("MapInfo").Select(m => m).ToList().ForEach(t =>
  699. {
  700. var honeywellDlc = false;
  701. if (t.Attribute("HoneywellDLC") != null)
  702. {
  703. honeywellDlc = Convert.ToBoolean(t.Attribute("HoneywellDLC").Value);
  704. }
  705. teamNames.Add(new TeamNameMapping
  706. {
  707. RegistrationId = t.Attribute("key").Value,
  708. IsHoneywellDlc = honeywellDlc,
  709. TeamName = t.Value.Replace("&amp;", "&")
  710. });
  711. });
  712. });
  713. return teamNames;
  714. }
  715. /// <summary>
  716. /// retreive team name mapping xml from database
  717. /// </summary>
  718. /// <returns></returns>
  719. private string GetTeamNameMappingXml()
  720. {
  721. string mappingStr;
  722. var connectionStr = ConfigurationManager.ConnectionStrings["InsightsMetaDataConn"].ConnectionString;
  723. using (var sqlConnection = new SqlConnection(connectionStr))
  724. {
  725. var cmd = new SqlCommand
  726. {
  727. CommandText = "[dbo].[GetComponentXmlConfiguration]",
  728. CommandType = CommandType.StoredProcedure,
  729. Connection = sqlConnection
  730. };
  731. cmd.Parameters.Add(new SqlParameter("@ClientId", SqlDbType.Int) { Value = _clientId });
  732. cmd.Parameters.Add(new SqlParameter("@ComponentName", SqlDbType.Text) { Value = "notification" });
  733. var param = cmd.CreateParameter();
  734. param.ParameterName = "@XmlConfiguration";
  735. param.Direction = ParameterDirection.Output;
  736. param.DbType = DbType.Xml;
  737. cmd.Parameters.Add(param);
  738. sqlConnection.Open();
  739. cmd.ExecuteNonQuery();
  740. mappingStr = param.Value.ToString();
  741. }
  742. return mappingStr;
  743. }
  744. // TODO: I DON'T THINK THIS IS NECESSARY OR WORKS. JUST SEND BACK XML FOR ACKNOWLEDGEMENT.
  745. /// <summary>
  746. /// set up the acknowledgement pay load
  747. /// </summary>
  748. /// <param name="events"></param>
  749. /// <returns></returns>
  750. private string GetAcknowledgementPayloadString(List<EventInfo> events)
  751. {
  752. var acknowledgementPayloadStr = @"<Events xmlns='http://www.pjm.com/schema/drbiznet/2009/model'>";
  753. foreach (var e in events)
  754. {
  755. acknowledgementPayloadStr += "<Event><id>" + e.EventId + "</id>";
  756. double amount;
  757. if (double.TryParse(e.Target, out amount))
  758. acknowledgementPayloadStr += "<summaryInfo><ackAmount>" + e.Target + "</ackAmount></summaryInfo>";
  759. acknowledgementPayloadStr += "</Event>";
  760. }
  761. acknowledgementPayloadStr += @"</Events>";
  762. return acknowledgementPayloadStr;
  763. }
  764. private string GetNoEventResponseString()
  765. {
  766. var xmlDoc = new XmlDocument();
  767. xmlDoc.Load("Samples\\SimulateNoEvent.xml");
  768. var objectStr = xmlDoc.InnerXml;
  769. return objectStr;
  770. }
  771. // TODO: REPLACE THIS XML STUFF
  772. private string GetEventsResponseString()
  773. {
  774. var xmlDoc = new XmlDocument();
  775. xmlDoc.Load("Samples\\SimulateEvent.xml");
  776. var objectStr = xmlDoc.InnerXml;
  777. return objectStr;
  778. }
  779. public string GetTokenId(string jsonString)
  780. {
  781. var jObj = JObject.Parse(jsonString);
  782. var token = jObj.SelectToken("tokenId");
  783. return token.Value<string>();
  784. }
  785. #endregion
  786. }
  787. [Serializable]
  788. public class DRHubConfig
  789. {
  790. public string Username { get; set; }
  791. public string Password { get; set; }
  792. public string WebServiceEndPoint { get; set; }
  793. public string GetEventsAction { get; set; }
  794. public string AcknowledgeEventsAction { get; set; }
  795. public string ServiceUrl { get; set; }
  796. public string AuthUrl { get; set; }
  797. public List<string> EventTypes { get; set; }
  798. public int MaxRetry { get; set; }
  799. public int RetryWaitDuration { get; set; }
  800. public bool Simulation { get; set; }
  801. public int SimulationInterval { get; set; }
  802. public string CookieName { get; set; }
  803. }
  804. [Serializable]
  805. public class TeamNameMapping
  806. {
  807. public string RegistrationId { get; set; }
  808. public string TeamName { get; set; }
  809. public bool IsHoneywellDlc { get; set; }
  810. }
  811. }