internal PluginManager(IEventManager eventManager, ISendReport sendReport, ILogging logging, IClientMessage sendClientMessage) : this() { _eventManager = eventManager ?? throw new ArgumentNullException(nameof(eventManager)); _sendReport = sendReport ?? throw new ArgumentNullException(nameof(sendReport)); _logging = logging ?? throw new ArgumentNullException(nameof(logging)); _sendClientMessage = sendClientMessage ?? throw new ArgumentNullException(nameof(sendClientMessage)); }
/**********************************************************/ /// <summary> /// When a METADATA report is received, all reports must be implicitly cancelled /// Send a message to the UI to set all reports to complete /// </summary> public void handleMetadataReportReceived(ISendReport sendReport) { lock (this) { List <string> completedReports = new List <string>(); foreach (ReportRequestWrapper reportRequestWrapper in m_reportRequests.Values) { if (reportRequestWrapper.ReportRequest.reportSpecifier.reportSpecifierID != "METADATA") { sendReport.processCreateReportComplete(reportRequestWrapper.ReportRequestID); completedReports.Add(reportRequestWrapper.ReportRequestID); } } foreach (string reportRequestID in completedReports) { m_reportRequests.Remove(reportRequestID); } } }
static async void StartApp() { IGetData _dataService = AppConfig.getDataService; ISendReport _reportService = AppConfig.sendReportService; await Task.Factory.StartNew( () => { while (AppConfig.electricityIsFine) { try { _reportService.SendReport(_dataService.GetData().ToReport()); } catch (Exception ex) { Console.WriteLine($"Some app error happens: {ex.ToString()}"); } Task.WaitAll(Task.Delay(AppConfig.delay_ms)); } }); }
/**********************************************************/ public void setCallback(ISendReport sendReport) { m_callbacks = sendReport; }
/**********************************************************/ public void generateUpdateReport(Dictionary <string, Interval> intervals, Dictionary <string, ReportWrapper> reports, ISendReport sendReport) { List <string> completedReports = new List <string>(); lock (this) { foreach (ReportRequestWrapper reportRequestWrapper in m_reportRequests.Values) { reportRequestWrapper.generateUpdateReport(intervals, reports, sendReport); if (reportRequestWrapper.ReportComplete) { completedReports.Add(reportRequestWrapper.ReportRequestID); } } foreach (string reportRequestID in completedReports) { m_reportRequests.Remove(reportRequestID); sendReport.processCreateReportComplete(reportRequestID); } } }
/**********************************************************/ private void doGenerateUpdateReport(Dictionary <string, Interval> intervals, DateTime dtstart, int durationSeconds, ReportWrapper reportWrapper, ISendReport sendReport) { try { // make sure only one thread is generating for this report lock (reportWrapper) { // int reportBackDurationSeconds = (int)System.Xml.XmlConvert.ToTimeSpan(m_reportRequest.reportSpecifier.reportBackDuration.duration).TotalSeconds; // these two parameters indicate when to start reporting (dtstart) and for how long to continue reporting (duration) // they're not needed by the interval // DateTime dtstartUTC = (m_reportRequest.reportSpecifier.reportInterval == null ? DateTime.Now : m_reportRequest.reportSpecifier.reportInterval.properties.dtstart.datetime); // int durationSeconds = (m_reportRequest.reportSpecifier.reportInterval == null ? 0 : (int)System.Xml.XmlConvert.ToTimeSpan(m_reportRequest.reportSpecifier.reportInterval.properties.duration.duration).TotalSeconds); // ReportWrapper reportWrapper = reports[reportSpecifierID]; foreach (SpecifierPayloadType specifierPaylod in m_reportRequest.reportSpecifier.specifierPayload) { try { string rid = specifierPaylod.rID; Interval interval = intervals[rid]; interval.addIntervalToReport(reportWrapper, dtstart, durationSeconds); } catch (KeyNotFoundException ex) { // there's a situation where a resource has been removed and the new report hasn't // yet been registered with the VTN which will cause a key not found error when we // try to generate the report. this is expected behaviour oadrlib.lib.helper.Logger.logException(ex); } catch (Exception ex) { m_reportComplete = true; oadrlib.lib.helper.Logger.logException(ex); } } oadrReportType report = reportWrapper.generateReport(m_reportRequest.reportRequestID); sendReport.sendUpdateReport(report, m_reportRequest); } } catch (Exception ex) { // an exception here indicates a problem with the xml m_reportComplete = true; oadrlib.lib.helper.Logger.logException(ex); } }
/**********************************************************/ /// <summary> /// generate the report if the next report is due /// set m_reportComplete to true if the last report was generated /// </summary> /// <param name="intervals"></param> /// <param name="reports"></param> /// <param name="sendReport"></param> public void generateUpdateReport(Dictionary <string, Interval> intervals, Dictionary <string, ReportWrapper> reports, ISendReport sendReport) { // this function is called from a thread // the lock ensures only invocation is active at a time (helps when debugging) lock (this) { try { if (m_reportComplete) { return; } // specifies how often to send the report, and the duration of the report int reportBackDurationSeconds = (int)System.Xml.XmlConvert.ToTimeSpan(m_reportRequest.reportSpecifier.reportBackDuration.duration).TotalSeconds; DateTime now = DateTime.Now; DateTime dtstart = now; int durationSeconds = 0; if (m_reportRequest.reportSpecifier.reportInterval == null) { // oneshot report; -1 tells the interval to report the most recent value dtstart = now; durationSeconds = -1; m_reportComplete = true; } else if (reportBackDurationSeconds == 0) { // history report dtstart = m_reportRequest.reportSpecifier.reportInterval.properties.dtstart.datetime.ToLocalTime(); durationSeconds = (int)System.Xml.XmlConvert.ToTimeSpan(m_reportRequest.reportSpecifier.reportInterval.properties.duration.duration).TotalSeconds; m_reportComplete = true; } else { // periodic report dtstart = m_reportRequest.reportSpecifier.reportInterval.properties.dtstart.datetime.ToLocalTime(); durationSeconds = (int)System.Xml.XmlConvert.ToTimeSpan(m_reportRequest.reportSpecifier.reportInterval.properties.duration.duration).TotalSeconds; // the report end time has passed if (now > dtstart.AddSeconds(durationSeconds + 30) && durationSeconds != 0) { m_reportComplete = true; return; } if (now >= dtstart && (now <= dtstart.AddSeconds(durationSeconds + 30) || durationSeconds == 0)) { if (now >= m_lastReported.AddSeconds(reportBackDurationSeconds)) { // // TODO: this function is crap and needs to be unit tested and cleaned up // // doGenerateUpdateReport(intervals, now, reportBackDurationSeconds, reportWrapper, sendReport); // if true, the report has been cancelled but a final report should be sent if (m_reportToFollow) { m_reportComplete = true; } m_lastReported = now; // set dtstart to the value of the newest interval // all reported intervals should have a date <= dtstart dtstart = m_lastReported; // the duration of a periodic report is equal to reportBackDurationSeconds durationSeconds = reportBackDurationSeconds; } else { return; // not time to send the next report yet } } else { return; // report dtstart hasn't passed yet } } // // time to generate a report: dtstart is the report start time and durationSeconds is the length of the report // if it's a metadata report, it's handled below (outside of the lock) // if (m_reportRequest.reportSpecifier.reportSpecifierID != "METADATA") { ReportWrapper reportWrapper = reports[m_reportRequest.reportSpecifier.reportSpecifierID]; doGenerateUpdateReport(intervals, dtstart, durationSeconds, reportWrapper, sendReport); } } catch (Exception ex) { m_reportComplete = true; oadrlib.lib.helper.Logger.logMessage("Exception caught handling reportRequest. Cancelling report."); oadrlib.lib.helper.Logger.logException(ex); } } if (m_reportRequest.reportSpecifier.reportSpecifierID == "METADATA") { sendReport.sendMetadataReport(m_reportRequest.reportRequestID); } }