Esempio n. 1
0
        /// <summary>
        /// Releases the unmanaged resources used by the <see cref="AlarmAdapter"/> object and optionally releases the managed resources.
        /// </summary>
        /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
        protected override void Dispose(bool disposing)
        {
            if (!m_disposed)
            {
                try
                {
                    if (disposing)
                    {
                        if (m_alarmService != null)
                        {
                            m_alarmService.ServiceProcessException -= AlarmService_ServiceProcessException;
                            m_alarmService.Dispose();
                        }

                        lock (m_alarmLock)
                        {
                            foreach (SignalAlarms signalAlarms in m_alarmLookup.Values)
                            {
                                StatisticsEngine.Unregister(signalAlarms.Statistics);
                            }
                        }
                    }
                }
                finally
                {
                    m_disposed = true;          // Prevent duplicate dispose.
                    base.Dispose(disposing);    // Call base class Dispose().
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// If measurement is a statistic, returns the associated Statistic record; otherwise, returns <c>null</c>.
        /// </summary>
        /// <param name="metadataRecord">Record of measurement metadata used to lookup Statistic record.</param>
        /// <returns>Associated Statistic record, if measurement is a statistic; otherwise, returns <c>null</c>.</returns>
        /// <remarks>
        /// For best results, this function should be called after all statistic engine sources have been registered.
        /// <paramref name="metadataRecord"/> object expected to contain a "signalid" and "signalreference" property.
        /// </remarks>
        public Statistic GetStatistic(dynamic metadataRecord)
        {
            Guid signalID = metadataRecord.signalid;

            return(s_statisticReferences.GetOrAdd(signalID, _ =>
            {
                string signalReference = metadataRecord.signalreference;

                if (string.IsNullOrWhiteSpace(signalReference))
                {
                    return null;
                }

                if (!StatisticsEngine.TryLookupStatisticSource(signalReference, out string source, out int signalIndex))
                {
                    return null;
                }

                InitializeStatistics();

                foreach (Statistic statistic in s_statistics)
                {
                    if (statistic.Source.Equals(source, StringComparison.OrdinalIgnoreCase) && statistic.SignalIndex == signalIndex)
                    {
                        return statistic;
                    }
                }

                return null;
            }));
Esempio n. 3
0
        /// <summary>
        /// Releases the unmanaged resources used by the <see cref="ModbusPoller"/> object and optionally releases the managed resources.
        /// </summary>
        /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
        protected override void Dispose(bool disposing)
        {
            if (!m_disposed)
            {
                try
                {
                    if (disposing)
                    {
                        StatisticsEngine.Unregister(m_deviceProxy);

                        DisposeConnections();

                        if ((object)m_pollingTimer != null)
                        {
                            m_pollingTimer.Enabled  = false;
                            m_pollingTimer.Elapsed -= m_pollingTimer_Elapsed;
                            m_pollingTimer.Dispose();
                        }
                    }
                }
                finally
                {
                    m_disposed = true;          // Prevent duplicate dispose.
                    base.Dispose(disposing);    // Call base class Dispose().
                }
            }
        }
Esempio n. 4
0
        public override void Initialize()
        {
            ProcessingInterval = 0;

            OnStatusMessage(MessageLevel.Info, $"Initialising OPC for device {Name}");
            base.Initialize();

            // If more data is added to the connection string the it will have to be parsed here (Look at ModbusPoller.cs for example line 456: https://github.com/GridProtectionAlliance/gsf/blob/master/Source/Libraries/Adapters/ModbusAdapters/ModbusPoller.cs)

            // Statistics
            StatisticsEngine.Register(this, "OPCUA", "OPC");

            OutputMeasurements = ParseOutputMeasurements(DataSource, false, $"FILTER ActiveMeasurements WHERE Device = '{Name}'");
            DataTable measurements = DataSource.Tables["ActiveMeasurements"];

            items = OutputMeasurements.ToDictionary(measurement =>
            {
                DataRow[] records = measurements.Select($"ID = '{measurement.Key}'");
                var reference     = records[0]["SignalReference"].ToNonNullString();
                OnStatusMessage(MessageLevel.Info, $"Linking OPC item {reference} with tag {measurement.TagName}");
                return(reference);
            });


            // OPC Init
            ApplicationInstance application = new ApplicationInstance
            {
                ApplicationName   = "OPC UA Client",
                ApplicationType   = Opc.Ua.ApplicationType.Client,
                ConfigSectionName = "Opc.Ua.Client"
            };
            ApplicationConfiguration config = application.LoadApplicationConfiguration(false).GetAwaiter().GetResult();
            bool haveAppCertificate         = application.CheckApplicationInstanceCertificate(false, 0).GetAwaiter().GetResult();

            if (!haveAppCertificate)
            {
                throw new Exception("Application instance certificate invalid!");
            }

            if (haveAppCertificate)
            {
                config.ApplicationUri = Utils.GetApplicationUriFromCertificate(config.SecurityConfiguration.ApplicationCertificate.Certificate);
                if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates)
                {
                    autoAccept = true;
                }
                config.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation);
            }
            else
            {
                OnStatusMessage(MessageLevel.Info, $"Missing application certificate, using unsecure connection.");
            }

            m_configuration = config;
            OnStatusMessage(MessageLevel.Info, $"OPC Initialised ({ConnectionString})");
        }
Esempio n. 5
0
        private string GenerateStatsTable(string deviceAcronym, string parentAcronym)
        {
            string tbl = "ID".PadRight(11) + "Description".PadRight(201) + "Value".PadRight(21) + "Time (UTC)".PadRight(20) + "\r\n";

            tbl += string.Concat(Enumerable.Repeat("-", 253)) + "\r\n";

            // Grab Stat Measurements
            IEnumerable <MeasurementDetail> statmeasurements = DataContext.Table <MeasurementDetail>().QueryRecordsWhere("DeviceAcronym IN ({0},{1}) AND SignalAcronym = 'STAT'", deviceAcronym, parentAcronym);

            // Read Current Values (+ 30 seconds back)
            ConfigurationFile config = ConfigurationFile.Current;
            CategorizedSettingsElementCollection settings = config.Settings["statArchiveFile"];

            ArchiveReader archiveReader = new ArchiveReader();

            archiveReader.Open(settings["FileName"].ValueAsString());

            List <MetadataRecord> metadataRecords = archiveReader.MetadataFile.Read()
                                                    .Where(record => !string.IsNullOrEmpty(record.Name))
                                                    .ToList();

            Dictionary <long, IEnumerable <IDataPoint> > data = statmeasurements.Select(item => item.PointID).ToDictionary(record => record, record => archiveReader.ReadData((int)record, DateTime.UtcNow.Subtract(new TimeSpan(0, 1, 0)), DateTime.UtcNow, false));

            foreach (MeasurementDetail meas in statmeasurements)
            {
                tbl += meas.PointTag.Substring(meas.PointTag.LastIndexOf("!") + 1).Trim().PadRight(10) + " " + meas.Description.Trim().PadRight(200) + " ";
                if (data.ContainsKey(meas.PointID) && data[meas.PointID].Count() > 0)
                {
                    if (!StatisticsEngine.TryLookupStatisticSource(meas.SignalReference, out string source, out int signalIndex))
                    {
                        tbl += "N/A".PadRight(20) + " " + "N/A".PadRight(20) + "\r\n";
                    }
                    else
                    {
                        Statistic stat     = DataContext.Table <Statistic>().QueryRecordWhere("Source = {0} AND SignalIndex = {1}", source, signalIndex);
                        Type      statType = Type.GetType(stat.DataType);
                        if (statType == typeof(DateTime))
                        {
                            tbl += String.Format(stat.DisplayFormat, new GSF.UnixTimeTag((decimal)data[meas.PointID].First().Value)).PadRight(20) + " " + data[meas.PointID].First().Time.ToString("HH:mm:ss.fff").PadRight(20) + "\r\n";
                        }
                        else
                        {
                            tbl += String.Format(stat.DisplayFormat, Convert.ChangeType(data[meas.PointID].First().Value, statType)).PadRight(20) + " " + data[meas.PointID].First().Time.ToString("HH:mm:ss.fff").PadRight(20) + "\r\n";
                        }
                    }
                }
Esempio n. 6
0
        // Updates alarm definitions when the data source has been updated.
        private void UpdateAlarmDefinitions()
        {
            DateTime now;
            DataSet  alarmDataSet;

            Dictionary <int, Alarm>         definedAlarmsLookup;
            Dictionary <Guid, SignalAlarms> newAlarmLookup;

            //List<IMeasurement> alarmEvents;

            // Get the current time in case we need
            // to generate alarm events for cleared alarms
            now = DateTime.UtcNow;

            // Get the latest version of the table of defined alarms
            alarmDataSet = new DataSet();
            alarmDataSet.Tables.Add(DataSource.Tables["Alarms"].Copy());

            // Compare the latest alarm table with the previous
            // alarm table to determine if anything needs to be done
            if (DataSetEqualityComparer.Default.Equals(m_alarmDataSet, alarmDataSet))
            {
                return;
            }

            m_alarmDataSet = alarmDataSet;

            // Get list of alarms defined in the latest version of the alarm table
            definedAlarmsLookup = alarmDataSet.Tables[0].Rows.Cast <DataRow>()
                                  .Where(row => row.ConvertField <bool>("Enabled"))
                                  .Select(CreateAlarm)
                                  .ToDictionary(alarm => alarm.ID);

            // Create a list to store alarm events generated by this process
            //alarmEvents = new List<IMeasurement>();

            lock (m_alarmLock)
            {
                foreach (Alarm existingAlarm in m_alarmLookup.SelectMany(kvp => kvp.Value.Alarms))
                {
                    Alarm definedAlarm;

                    // Attempt to locate the defined alarm corresponding to the existing alarm
                    definedAlarmsLookup.TryGetValue(existingAlarm.ID, out definedAlarm);

                    // Determine if a change to the alarm's
                    // configuration has changed the alarm's behavior
                    if (BehaviorChanged(existingAlarm, definedAlarm))
                    {
                        // Clone the existing alarm so that changes to alarm
                        // states can be observed later in this process
                        Alarm clone = existingAlarm.Clone();

                        // Clear the alarm and create an event
                        clone.State = AlarmState.Cleared;
                        //alarmEvents.Add(CreateAlarmEvent(now, clone));
                    }
                    else if ((object)definedAlarm != null)
                    {
                        // Update functionally irrelevant configuration info
                        existingAlarm.TagName     = definedAlarm.TagName;
                        existingAlarm.Description = definedAlarm.Description;

                        // Use the existing alarm since the alarm is functionally the same
                        definedAlarmsLookup[definedAlarm.ID] = existingAlarm;
                    }
                }

                // Create the new alarm lookup to replace the old one
                newAlarmLookup = definedAlarmsLookup.Values
                                 .GroupBy(alarm => alarm.SignalID)
                                 .ToDictionary(grouping => grouping.Key, grouping => new SignalAlarms()
                {
                    // Alarms are sorted in order of precedence:
                    //   1) Exemptions (forces alarm state to cleared)
                    //   2) Severity (high severity takes precedence over low severity)
                    //   3) ID (relative order of alarms with same severity doesn't change)
                    Alarms = grouping
                             .OrderByDescending(alarm => alarm.Severity == AlarmSeverity.None)
                             .ThenByDescending(alarm => alarm.Severity)
                             .ThenBy(alarm => alarm.ID)
                             .ToList()
                });

                // Check for changes to alarms that need to go in the alarm log
                foreach (KeyValuePair <Guid, SignalAlarms> kvp in m_alarmLookup)
                {
                    SignalAlarms existingAlarms = kvp.Value;
                    SignalAlarms definedAlarms;

                    // Get the active alarms from both before and after the configuration changes were applied
                    Alarm existingActiveAlarm = existingAlarms.Alarms.FirstOrDefault(alarm => alarm.State == AlarmState.Raised);
                    Alarm definedActiveAlarm  = null;

                    if (newAlarmLookup.TryGetValue(kvp.Key, out definedAlarms))
                    {
                        definedAlarms.Statistics = existingAlarms.Statistics;
                        definedActiveAlarm       = definedAlarms.Alarms.FirstOrDefault(alarm => alarm.State == AlarmState.Raised);
                    }
                    else
                    {
                        StatisticsEngine.Unregister(existingAlarms.Statistics);
                    }

                    if ((object)definedActiveAlarm != null && (object)existingActiveAlarm != null)
                    {
                        // If the active alarm has changed as a result
                        // of the configuration change, log the change
                        if (definedActiveAlarm.ID != existingActiveAlarm.ID)
                        {
                            LogStateChange(kvp.Key, existingActiveAlarm, definedActiveAlarm, now, double.NaN);
                        }
                    }
                    else if ((object)existingActiveAlarm != null)
                    {
                        // If alarms were raised before the configuration change,
                        // but have all been cleared as a result of the
                        // configuration change, log the change
                        LogStateChange(kvp.Key, existingActiveAlarm, null, now, double.NaN);
                    }
                }
            }


            // Use SignalReference as the name of the signal when creating statistic source
            foreach (DataRow row in DataSource.Tables["ActiveMeasurements"].Rows)
            {
                Guid         signalID;
                SignalAlarms signalAlarms;

                if (Guid.TryParse(row["SignalID"].ToNonNullString(), out signalID) && newAlarmLookup.TryGetValue(signalID, out signalAlarms))
                {
                    signalAlarms.Name = row.Field <string>("SignalReference");
                }
            }

            // Newly added signals that do not have statistics associated
            // with them yet need to be registered with the statistics engine
            foreach (KeyValuePair <Guid, SignalAlarms> kvp in newAlarmLookup)
            {
                if ((object)kvp.Value.Statistics == null)
                {
                    if (string.IsNullOrEmpty(kvp.Value.Name))
                    {
                        kvp.Value.Name = kvp.Key.ToString().Replace("-", "");
                    }

                    kvp.Value.Statistics = new AlarmStatistics();
                    StatisticsEngine.Register(kvp.Value.Statistics, kvp.Value.Name, "Point", "PT", "{0}!{}");
                }
            }

            lock (m_alarmLock)
            {
                m_alarmLookup = newAlarmLookup;

                // Only automatically update input measurement keys if the setting is not explicitly defined
                if (m_alarmLookup.Count > 0 && !Settings.ContainsKey("inputMeasurementKeys"))
                {
                    // Generate filter expression for input measurements
                    string filterExpression = string.Join(";", m_alarmLookup.Select(kvp => kvp.Key.ToString()));

                    // Set input measurement keys for measurement routing
                    InputMeasurementKeys = ParseInputMeasurementKeys(DataSource, true, filterExpression);
                }
            }
        }
Esempio n. 7
0
        private void m_unsynchronizedSubscriber_NewMeasurements(object sender, EventArgs <ICollection <IMeasurement> > e)
        {
            if (0 == Interlocked.Exchange(ref m_processingUnsynchronizedMeasurements, 1))
            {
                try
                {
                    ObservableCollection <StatisticMeasurement> statisticMeasurements;
                    RealTimeMeasurement realTimeMeasurement;

                    HashSet <RealTimeStream> updatedStreams = new HashSet <RealTimeStream>();
                    HashSet <RealTimeDevice> updatedDevices = new HashSet <RealTimeDevice>();

                    // If it doesn't already exist, create lookup table to allow quick
                    // lookup of RealTimeMeasurements whose value has changed
                    if ((object)m_realTimeMeasurements == null)
                    {
                        m_realTimeMeasurements = ItemsSource
                                                 .SelectMany(stream => stream.DeviceList)
                                                 .SelectMany(device => device.MeasurementList)
                                                 .GroupBy(measurement => measurement.SignalID)
                                                 .Select(group => group.First())
                                                 .ToDictionary(measurement => measurement.SignalID);
                    }

                    // Update measurements that have changed
                    foreach (IMeasurement newMeasurement in e.Argument)
                    {
                        if (m_realTimeMeasurements.TryGetValue(newMeasurement.ID, out realTimeMeasurement))
                        {
                            RealTimeDevice parentDevice = realTimeMeasurement.Parent;
                            RealTimeStream parentStream = parentDevice.Parent;

                            if (newMeasurement.Timestamp > realTimeMeasurement.LastUpdated)
                            {
                                realTimeMeasurement.Quality     = newMeasurement.ValueQualityIsGood() ? "GOOD" : "BAD";
                                realTimeMeasurement.TimeTag     = newMeasurement.Timestamp.ToString("HH:mm:ss.fff");
                                realTimeMeasurement.Value       = newMeasurement.AdjustedValue.ToString("0.###");
                                realTimeMeasurement.LastUpdated = newMeasurement.Timestamp;

                                // Maintain collection of updated devices and streams
                                updatedDevices.Add(parentDevice);

                                if ((object)parentStream != null)
                                {
                                    updatedStreams.Add(parentStream);
                                }
                            }
                        }
                    }

                    // Update status color of the updated devices
                    // NOTE: Color cannot be red since we just received data from the devices
                    foreach (RealTimeDevice device in updatedDevices)
                    {
                        // By default, determine color based on measurement quality
                        List <RealTimeMeasurement> measurementList = device.MeasurementList.Where(m => m.Value != "--").ToList();

                        if (measurementList.Count > 0)
                        {
                            if (measurementList.All(m => m.Quality != "BAD"))
                            {
                                device.StatusColor = "Green";
                            }
                            else
                            {
                                device.StatusColor = "Yellow";
                            }
                        }

                        if (device.ID != null && device.ID > 0)
                        {
                            // Check to see if device has statistic measurements which define the number of errors reported by the device
                            if (!RealTimeStatistic.InputStreamStatistics.ContainsKey((int)device.ID))
                            {
                                if (RealTimeStatistic.DevicesWithStatisticMeasurements.TryGetValue((int)device.ID, out statisticMeasurements))
                                {
                                    // If there are any reported errors, force color to yellow
                                    foreach (StatisticMeasurement statisticMeasurement in statisticMeasurements)
                                    {
                                        int value;

                                        if (StatisticsEngine.RegexMatch(statisticMeasurement.SignalReference, "PMU") && int.TryParse(statisticMeasurement.Value, out value) && value > 0)
                                        {
                                            device.StatusColor = "Yellow";
                                        }
                                    }
                                }
                            }
                        }
                    }

                    // Update status color of the updated streams
                    // NOTE: Color cannot be red since we just received data from the devices
                    foreach (RealTimeStream stream in updatedStreams)
                    {
                        // Streams with ID of 0 are placeholders
                        // and must remain transparent
                        if (stream.ID > 0)
                        {
                            if (stream.DeviceList.Any(device => device.StatusColor == "Green"))
                            {
                                stream.StatusColor = "Green";
                            }
                            else
                            {
                                stream.StatusColor = "Yellow";
                            }
                        }
                    }

                    LastRefresh = "Last Refresh: " + DateTime.UtcNow.ToString("HH:mm:ss.fff");
                }
                finally
                {
                    Interlocked.Exchange(ref m_processingUnsynchronizedMeasurements, 0);
                }
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Initializes <see cref="ProcessLauncher"/>.
        /// </summary>
        public override void Initialize()
        {
            base.Initialize();

            Dictionary <string, string> settings = Settings;
            ProcessWindowStyle          windowStyle;
            int    initialInputProcessingDelay, utilizationCalculationInterval;
            string setting;

            ProcessStartInfo startInfo = m_process.StartInfo;

            // Load required parameters
            if (settings.TryGetValue(nameof(FileName), out setting))
            {
                setting = FilePath.GetAbsolutePath(setting.Trim());

                if (File.Exists(setting))
                {
                    FileName           = setting;
                    startInfo.FileName = FileName;
                }
                else
                {
                    throw new FileNotFoundException($"Cannot launch process: specified executable path and filename \"{setting}\" does not exist.");
                }
            }
            else
            {
                throw new ArgumentException($"Cannot launch process: required \"{nameof(FileName)}\" parameter is missing from connection string.");
            }

            // Load optional parameters
            if (settings.TryGetValue(nameof(SupportsTemporalProcessing), out setting))
            {
                m_supportsTemporalProcessing = setting.ParseBoolean();
            }
            else
            {
                m_supportsTemporalProcessing = DefaultSupportsTemporalProcessing;
            }

            if (settings.TryGetValue(nameof(Arguments), out setting) && setting.Length > 0)
            {
                startInfo.Arguments = setting;
            }

            if (settings.TryGetValue(nameof(WorkingDirectory), out setting))
            {
                setting = setting.Trim();

                if (Directory.Exists(setting))
                {
                    WorkingDirectory           = setting;
                    startInfo.WorkingDirectory = WorkingDirectory;
                }
                else
                {
                    throw new DirectoryNotFoundException($"Cannot launch process: specified working directory \"{setting}\" does not exist.");
                }
            }
            else
            {
                WorkingDirectory           = FilePath.GetDirectoryName(FileName);
                startInfo.WorkingDirectory = WorkingDirectory;
            }

            if (settings.TryGetValue(nameof(EnvironmentalVariables), out setting))
            {
                foreach (KeyValuePair <string, string> item in setting.ParseKeyValuePairs())
                {
                    startInfo.Environment[item.Key] = item.Value;
                }
            }

            // Note that it's possible that time-series framework is being hosted by an application
            // running in a Window making many of the following process start properties relevant.
            // Even when hosted as a service, the user may start the service logging on using the
            // local system account and select to allow the service interact with the desktop.
            if (settings.TryGetValue(nameof(CreateNoWindow), out setting))
            {
                startInfo.CreateNoWindow = setting.ParseBoolean();
            }
            else
            {
                startInfo.CreateNoWindow = DefaultCreateNoWindow;
            }

            if (settings.TryGetValue(nameof(WindowStyle), out setting) && Enum.TryParse(setting, true, out windowStyle))
            {
                startInfo.WindowStyle = windowStyle;
            }
            else
            {
                startInfo.WindowStyle = (ProcessWindowStyle)Enum.Parse(typeof(ProcessWindowStyle), DefaultWindowStyle);
            }

            if (settings.TryGetValue(nameof(ErrorDialog), out setting))
            {
                startInfo.ErrorDialog = setting.ParseBoolean();
            }
            else
            {
                startInfo.ErrorDialog = DefaultErrorDialog;
            }

            if (settings.TryGetValue(nameof(Domain), out setting) && setting.Length > 0)
            {
                startInfo.Domain = setting;
            }

            if (settings.TryGetValue(nameof(UserName), out setting) && setting.Length > 0)
            {
                startInfo.UserName = setting;
            }

            if (settings.TryGetValue(nameof(Password), out setting) && setting.Length > 0)
            {
                startInfo.Password = setting.ToSecureString();
            }

            if (settings.TryGetValue(nameof(LoadUserProfile), out setting))
            {
                startInfo.LoadUserProfile = setting.ParseBoolean();
            }

            if (settings.TryGetValue(nameof(InitialInputFileName), out setting))
            {
                setting = FilePath.GetAbsolutePath(setting.Trim());

                if (File.Exists(setting))
                {
                    InitialInputFileName = setting;
                }
                else
                {
                    throw new FileNotFoundException($"Cannot launch process: specified initial input filename \"{setting}\" does not exist.");
                }
            }

            if (settings.TryGetValue(nameof(InitialInputProcessingDelay), out setting) && int.TryParse(setting, out initialInputProcessingDelay) && initialInputProcessingDelay > -1)
            {
                InitialInputProcessingDelay = initialInputProcessingDelay;
            }

            if (settings.TryGetValue(nameof(RedirectOutputToHostEnvironment), out setting))
            {
                RedirectOutputToHostEnvironment = setting.ParseBoolean();
            }

            if (settings.TryGetValue(nameof(RedirectErrorToHostEnvironment), out setting))
            {
                RedirectErrorToHostEnvironment = setting.ParseBoolean();
            }

            if (settings.TryGetValue(nameof(UtilizationUpdateInterval), out setting) && int.TryParse(setting, out utilizationCalculationInterval))
            {
                UtilizationUpdateInterval = utilizationCalculationInterval;
            }

            startInfo.RedirectStandardOutput = RedirectOutputToHostEnvironment;
            startInfo.RedirectStandardError  = RedirectErrorToHostEnvironment;
            startInfo.RedirectStandardInput  = true;
            startInfo.UseShellExecute        = false;

            m_process.EnableRaisingEvents = true;
            m_process.OutputDataReceived += ProcessOutputDataReceived;
            m_process.ErrorDataReceived  += ProcessErrorDataReceived;

            if (settings.TryGetValue(nameof(ProcessOutputAsLogMessages), out setting))
            {
                ProcessOutputAsLogMessages = setting.ParseBoolean();
            }

            if (ProcessOutputAsLogMessages)
            {
                if (settings.TryGetValue(nameof(LogMessageTextExpression), out setting) && setting.Length > 0)
                {
                    LogMessageTextExpression = setting;
                }

                m_logMessageTextExpression = new Regex(LogMessageTextExpression, RegexOptions.Compiled);

                if (settings.TryGetValue(nameof(LogMessageLevelExpression), out setting) && setting.Length > 0)
                {
                    LogMessageLevelExpression = setting;
                }

                m_logMessageLevelExpression = new Regex(LogMessageLevelExpression, RegexOptions.Compiled);

                if (settings.TryGetValue(nameof(LogMessageLevelMappings), out setting))
                {
                    LogMessageLevelMappings = setting;
                }

                foreach (KeyValuePair <string, string> item in LogMessageLevelMappings.ParseKeyValuePairs())
                {
                    MessageLevel level;

                    if (Enum.TryParse(item.Value, true, out level))
                    {
                        m_messageLevelMap[item.Key] = level;
                    }
                }
            }

            if (settings.TryGetValue(nameof(ForceKillOnDispose), out setting))
            {
                ForceKillOnDispose = setting.ParseBoolean();
            }

            if (settings.TryGetValue(nameof(TrackProcessStatistics), out setting))
            {
                TrackProcessStatistics = setting.ParseBoolean();
            }

            m_process.Start();

            if (ForceKillOnDispose)
            {
                m_childProcessManager?.AddProcess(m_process);
            }

            if (RedirectOutputToHostEnvironment)
            {
                m_process.BeginOutputReadLine();
            }

            if (RedirectErrorToHostEnvironment)
            {
                m_process.BeginErrorReadLine();
            }

            m_processUtilizationCalculator.UpdateInterval = UtilizationUpdateInterval;
            m_processUtilizationCalculator.Initialize(m_process);

            // Register launched process with the statistics engine
            if (TrackProcessStatistics)
            {
                StatisticsEngine.Register(this, "Process", "PROC");
            }

            if (string.IsNullOrEmpty(InitialInputFileName))
            {
                return;
            }

            // Send any defined initial input to launched application
            new Action(() =>
            {
                try
                {
                    using (StreamReader reader = File.OpenText(InitialInputFileName))
                    {
                        string line;

                        while ((object)(line = reader.ReadLine()) != null)
                        {
                            Input(line);
                        }
                    }
                }
                catch (Exception ex)
                {
                    OnProcessException(MessageLevel.Warning, new InvalidOperationException($"Failed while sending text from \"{InitialInputFileName}\" to launched process standard input: {ex.Message}", ex));
                }
            })
            .DelayAndExecute(InitialInputProcessingDelay);
        }
Esempio n. 9
0
        /// <summary>
        /// Gets statistic measurements from the database for current node.
        /// </summary>
        /// <param name="database"><see cref="AdoDataConnection"/> to connection to database.</param>
        /// <returns>Collection of <see cref="StatisticMeasurement"/>.</returns>
        public static ObservableCollection <StatisticMeasurement> GetStatisticMeasurements(AdoDataConnection database)
        {
            bool createdConnection = false;

            try
            {
                createdConnection = CreateConnection(ref database);

                // Get Statistic Definitions
                ObservableCollection <Statistic> statisticDefinitions = Statistic.Load(database);

                // Get statistics measurements.
                DataTable statisticMeasurements = database.Connection.RetrieveData(database.AdapterType, database.ParameterizedQueryString("SELECT SignalID, ID, DeviceID, PointID, PointTag, SignalReference " +
                                                                                                                                           "FROM StatisticMeasurement WHERE NodeID = {0}", "nodeID"), DefaultTimeout, database.CurrentNodeID());

                // Assign min and max point IDs as we will need them to request data from web service.
                MinPointID = int.MaxValue;
                MaxPointID = int.MinValue;

                foreach (DataRow row in statisticMeasurements.Rows)
                {
                    int pointID = Convert.ToInt32(row.Field <object>("PointID"));
                    MinPointID = Math.Min(MinPointID, pointID);
                    MaxPointID = Math.Max(MaxPointID, pointID);
                }


                // Takes datarow from statisticMeasurements data table, and associates each row to their statistic source and returns KeyValuePair.
                Func <DataRow, KeyValuePair <DataRow, string> > mapFunction = measurement =>
                {
                    string signalReference = measurement.Field <string>("SignalReference");
                    string measurementSource;

                    if (StatisticsEngine.RegexMatch(signalReference, "SYSTEM"))
                    {
                        measurementSource = "System";
                    }
                    else if (StatisticsEngine.RegexMatch(signalReference, "PMU"))
                    {
                        measurementSource = "Device";
                    }
                    else if (StatisticsEngine.RegexMatch(signalReference, "OS"))
                    {
                        measurementSource = "OutputStream";
                    }
                    else if (StatisticsEngine.RegexMatch(signalReference, "IS"))
                    {
                        measurementSource = "InputStream";
                    }
                    else if (StatisticsEngine.RegexMatch(signalReference, "SUB"))
                    {
                        measurementSource = "Subscriber";
                    }
                    else if (StatisticsEngine.RegexMatch(signalReference, "PUB"))
                    {
                        measurementSource = "Publisher";
                    }
                    else
                    {
                        measurementSource = "???";
                    }

                    return(new KeyValuePair <DataRow, string>(measurement, measurementSource));
                };

                // Takes KeyValuePair and generates StatisticMeasurement record by maping statistic measurements with statistic definitions.
                Func <KeyValuePair <DataRow, string>, StatisticMeasurement> selectFunction = keyvaluepair =>
                {
                    DataRow measurement       = keyvaluepair.Key;
                    string  measurementSource = keyvaluepair.Value;
                    Debug.WriteLine(measurementSource);
                    string    signalReference     = measurement.Field <string>("SignalReference");
                    int       measurementIndex    = Convert.ToInt32(signalReference.Substring(signalReference.LastIndexOf("-ST") + 3));
                    Statistic statisticDefinition = new Statistic();

                    foreach (Statistic statistic in statisticDefinitions)
                    {
                        if (statistic.Source == measurementSource && statistic.SignalIndex == measurementIndex)
                        {
                            statisticDefinition = statistic;
                            break;
                        }
                    }

                    return(new StatisticMeasurement()
                    {
                        SignalID = database.Guid(measurement, "SignalID"),
                        ID = measurement.Field <string>("ID"),
                        DeviceID = Convert.ToInt32(measurement.Field <object>("DeviceID") ?? -1),
                        PointID = Convert.ToInt32(measurement.Field <object>("PointID")),
                        PointTag = measurement.Field <string>("PointTag"),
                        SignalReference = signalReference,
                        Source = measurementSource,
                        StatisticName = statisticDefinition.Name,
                        StatisticDescription = statisticDefinition.Description,
                        DataType = statisticDefinition.DataType,
                        DisplayFormat = statisticDefinition.DisplayFormat,
                        ConnectedState = statisticDefinition.IsConnectedState,
                        LoadOrder = statisticDefinition.LoadOrder,
                        TimeTag = "n/a",
                        Quality = "n/a",
                        Value = "--"
                    });
                };

                return(new ObservableCollection <StatisticMeasurement>(statisticMeasurements.Rows.Cast <DataRow>().Select(mapFunction).OrderBy(pair => pair.Value).Select(selectFunction).OrderBy(s => s.LoadOrder)));
            }
            finally
            {
                if (createdConnection && database != null)
                {
                    database.Dispose();
                }
            }
        }
Esempio n. 10
0
        /// <summary>
        /// Initializes <see cref="ModbusPoller" />.
        /// </summary>
        public override void Initialize()
        {
            base.Initialize();

            ConnectionStringParser <ConnectionStringParameterAttribute> parser = new ConnectionStringParser <ConnectionStringParameterAttribute>();

            parser.ParseConnectionString(ConnectionString, this);

            // Register downloader with the statistics engine
            StatisticsEngine.Register(this, "Modbus", "MOD");
            StatisticsEngine.Register(m_deviceProxy, Name, "Device", "PMU");

            // Attach to output measurements for Modbus device
            OutputMeasurements = ParseOutputMeasurements(DataSource, false, $"FILTER ActiveMeasurements WHERE Device = '{Name}'");

            // Parse derived value expressions from defined signal reference fields
            m_derivedValues = OutputMeasurements.Select(measurement => measurement.Key).ToDictionary(key => key, key =>
            {
                DataTable measurements    = DataSource.Tables["ActiveMeasurements"];
                DerivedValue derivedValue = null;
                DataRow[] records         = measurements.Select($"ID = '{key}'");

                if (records.Length > 0)
                {
                    derivedValue = ParseDerivedValue(records[0]["SignalReference"].ToNonNullString());
                }

                return(derivedValue);
            });

            m_sequences = new List <Sequence>();

            Dictionary <string, string> settings = Settings;
            string setting;
            int    sequenceCount = 0;

            if (settings.TryGetValue("sequenceCount", out setting))
            {
                int.TryParse(setting, out sequenceCount);
            }

            for (int i = 0; i < sequenceCount; i++)
            {
                if (settings.TryGetValue($"sequence{i}", out setting))
                {
                    Dictionary <string, string> sequenceSettings = setting.ParseKeyValuePairs();
                    SequenceType sequenceType = SequenceType.Read;

                    if (sequenceSettings.TryGetValue("sequenceType", out setting))
                    {
                        Enum.TryParse(setting, true, out sequenceType);
                    }

                    Sequence sequence = new Sequence(sequenceType);
                    int      groupCount;

                    if (sequenceSettings.TryGetValue("groupCount", out setting) && int.TryParse(setting, out groupCount))
                    {
                        for (int j = 0; j < groupCount; j++)
                        {
                            Group group = new Group();

                            if (sequenceSettings.TryGetValue($"groupType{j}", out setting))
                            {
                                Enum.TryParse(setting, true, out group.Type);
                            }

                            if (sequenceSettings.TryGetValue($"groupStartAddress{j}", out setting))
                            {
                                ushort.TryParse(setting, out group.StartAddress);
                            }

                            if (sequenceSettings.TryGetValue($"groupPointCount{j}", out setting))
                            {
                                ushort.TryParse(setting, out group.PointCount);
                            }

                            if (group.StartAddress > 0 && group.PointCount > 0)
                            {
                                // Load any defined write sequence values
                                if (sequence.Type == SequenceType.Write)
                                {
                                    group.DataValues = new ushort[group.PointCount];

                                    for (int k = 0; k < group.PointCount; k++)
                                    {
                                        if (sequenceSettings.TryGetValue($"group{j}DataValue{k}", out setting))
                                        {
                                            ushort.TryParse(setting, out group.DataValues[k]);
                                        }
                                    }
                                }

                                sequence.Groups.Add(group);
                            }
                        }
                    }

                    if (sequence.Groups.Count > 0)
                    {
                        m_sequences.Add(sequence);
                    }
                }
            }

            if (m_sequences.Count == 0)
            {
                throw new InvalidOperationException("No sequences defined, cannot start Modbus polling.");
            }

            // Define synchronized polling operation
            m_pollingOperation = new ShortSynchronizedOperation(PollingOperation, exception => OnProcessException(MessageLevel.Warning, exception));

            // Define polling timer
            m_pollingTimer           = new Timer(m_pollingRate);
            m_pollingTimer.AutoReset = true;
            m_pollingTimer.Elapsed  += m_pollingTimer_Elapsed;
        }
Esempio n. 11
0
        public Dictionary <Player, double> Statistics()
        {
            StatisticsEngine statistiqueEngine = new StatisticsEngine(this);

            return(statistiqueEngine.StatisticsPerPlayer());
        }
	void Init ()
	{
		mTickTimer = 0f;
		CreateResourceStore ();

		mStatsEngine = new StatisticsEngine ();
	}