885 lines · 49.1 KB · C#
RawDownload
//******************************************************************************************************//  TimeSeriesStartupOperations.cs - Gbtc////  Copyright © 2012, Grid Protection Alliance.  All Rights Reserved.////  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See//  the NOTICE file distributed with this work for additional information regarding copyright ownership.//  The GPA licenses this file to you under the MIT License (MIT), the "License"; you may//  not use this file except in compliance with the License. You may obtain a copy of the License at:////      http://www.opensource.org/licenses/MIT////  Unless agreed to in writing, the subject software distributed under the License is distributed on an//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the//  License for the specific language governing permissions and limitations.////  Code Modification History://  ----------------------------------------------------------------------------------------------------//  02/14/2012 - Stephen C. Wills//       Generated original version of source code.//  12/20/2012 - Starlynn Danyelle Gilliam//       Modified Header.////****************************************************************************************************** using System;using System.Collections.Generic;using System.Data;using System.Linq;using GSF.Data;using GSF.Identity; // ReSharper disable UnusedParameter.Local// ReSharper disable NotAccessedField.Local// ReSharper disable UnusedMember.Localnamespace GSF.TimeSeries{    /// <summary>    /// Defines a data operations to be performed at startup.    /// </summary>    public static class TimeSeriesStartupOperations    {        // Messaging to the service        private static Action<string> s_statusMessage;        private static Action<Exception> s_processException;         /// <summary>        /// Delegates control to the data operations that are to be performed at startup.        /// </summary>        private static void PerformTimeSeriesStartupOperations(AdoDataConnection database, string nodeIDQueryString, ulong trackingVersion, string arguments, Action<string> statusMessage, Action<Exception> processException)        {            // Set up messaging to the service            s_statusMessage = statusMessage;            s_processException = processException;             // Run data operations            ValidateDefaultNode(database, nodeIDQueryString);            ValidateAdapterCollections(database, nodeIDQueryString);            ValidateActiveMeasurements(database, nodeIDQueryString);            ValidateAccountsAndGroups(database, nodeIDQueryString);            ValidateDataPublishers(database, nodeIDQueryString, arguments);            ValidateStatistics(database, nodeIDQueryString);            ValidateAlarming(database, nodeIDQueryString);        }         /// <summary>        /// Data operation to validate and ensure there is a node in the database.        /// </summary>        private static void ValidateDefaultNode(AdoDataConnection database, string nodeIDQueryString)        {            // Queries            const string NodeCountFormat = "SELECT COUNT(*) FROM Node";             const string NodeInsertFormat = "INSERT INTO Node(Name, CompanyID, Description, Settings, MenuType, MenuData, Master, LoadOrder, Enabled) " +                "VALUES('Default', NULL, 'Default node', 'RemoteStatusServerConnectionString={server=localhost:8500};datapublisherport=6165;RealTimeStatisticServiceUrl=http://localhost:6052/historian', " +                "'File', 'Menu.xml', 1, 0, 1)";             const string NodeUpdateFormat = "UPDATE Node SET ID = {0}";             // Determine whether the node exists in the database and create it if it doesn't.            int nodeCount = Convert.ToInt32(database.Connection.ExecuteScalar(NodeCountFormat));             if (nodeCount == 0)            {                database.Connection.ExecuteNonQuery(NodeInsertFormat);                database.Connection.ExecuteNonQuery(string.Format(NodeUpdateFormat, nodeIDQueryString));            }        }         /// <summary>        /// Data operation to validate and ensure there is a record in the        /// ConfigurationEntity table for each of the adapter collections.        /// </summary>        private static void ValidateAdapterCollections(AdoDataConnection database, string nodeIDQueryString)        {            const string ConfigEntityCountFormat = "SELECT COUNT(*) FROM ConfigurationEntity WHERE RuntimeName = {0}";            const string ConfigEntityInsertFormat = "INSERT INTO ConfigurationEntity(SourceName, RuntimeName, Description, LoadOrder, Enabled) VALUES({0}, {1}, {2}, {3}, 1)";             string[] sourceNames =            {                "IaonFilterAdapter",                "IaonInputAdapter",                "IaonActionAdapter",                "IaonOutputAdapter"            };             string[] runtimeNames =            {                "FilterAdapters",                "InputAdapters",                "ActionAdapters",                "OutputAdapters"            };             string[] descriptions =            {                "Defines IFilterAdapter definitions for a PDC node",                "Defines IInputAdapter definitions for a PDC node",                "Defines IActionAdapter definitions for a PDC node",                "Defines IOutputAdapter definitions for a PDC node"            };             for (int i = 0; i < runtimeNames.Length; i++)            {                string sourceName = sourceNames[i];                string runtimeName = runtimeNames[i];                string description = descriptions[i];                int loadOrder = i + 1;                 if (database.ExecuteScalar<int>(ConfigEntityCountFormat, runtimeName) == 0)                    database.ExecuteNonQuery(ConfigEntityInsertFormat, sourceName, runtimeName, description, loadOrder);            }        }         /// <summary>        /// Data operation to validate and ensure there is a record        /// in the ConfigurationEntity table for ActiveMeasurements.        /// </summary>        private static void ValidateActiveMeasurements(AdoDataConnection database, string nodeIDQueryString)        {            const string MeasurementConfigEntityCountFormat = "SELECT COUNT(*) FROM ConfigurationEntity WHERE RuntimeName = 'ActiveMeasurements'";            const string MeasurementConfigEntityInsertFormat = "INSERT INTO ConfigurationEntity(SourceName, RuntimeName, Description, LoadOrder, Enabled) VALUES('ActiveMeasurement', 'ActiveMeasurements', 'Defines active system measurements for a TSF node', 4, 1)";             int measurementConfigEntityCount = Convert.ToInt32(database.Connection.ExecuteScalar(MeasurementConfigEntityCountFormat));             if (measurementConfigEntityCount == 0)                database.Connection.ExecuteNonQuery(MeasurementConfigEntityInsertFormat);        }         /// <summary>        /// Data operation to validate accounts and groups to ensure        /// that account names and group names are converted to SIDs.        /// </summary>        private static void ValidateAccountsAndGroups(AdoDataConnection database, string nodeIDQueryString)        {            const string SelectUserAccountQuery = "SELECT ID, Name, UseADAuthentication FROM UserAccount";            const string SelectSecurityGroupQuery = "SELECT ID, Name FROM SecurityGroup";            const string UpdateUserAccountFormat = "UPDATE UserAccount SET Name = '{0}' WHERE ID = '{1}'";            const string UpdateSecurityGroupFormat = "UPDATE SecurityGroup SET Name = '{0}' WHERE ID = '{1}'";             string id;            string sid;            string accountName;             Dictionary<string, string> updateMap = new Dictionary<string, string>();             // Find user accounts that need to be updated            using (IDataReader userAccountReader = database.Connection.ExecuteReader(SelectUserAccountQuery))            {                while (userAccountReader.Read())                {                    id = userAccountReader["ID"].ToNonNullString();                    accountName = userAccountReader["Name"].ToNonNullString();                     if (userAccountReader["UseADAuthentication"].ToNonNullString().ParseBoolean())                    {                        sid = UserInfo.UserNameToSID(accountName);                         if (!ReferenceEquals(accountName, sid) && UserInfo.IsUserSID(sid))                            updateMap.Add(id, sid);                    }                }            }             // Update user accounts            foreach (KeyValuePair<string, string> pair in updateMap)                database.Connection.ExecuteNonQuery(string.Format(UpdateUserAccountFormat, pair.Value, pair.Key));             updateMap.Clear();             // Find security groups that need to be updated            using (IDataReader securityGroupReader = database.Connection.ExecuteReader(SelectSecurityGroupQuery))            {                while (securityGroupReader.Read())                {                    id = securityGroupReader["ID"].ToNonNullString();                    accountName = securityGroupReader["Name"].ToNonNullString();                     if (accountName.Contains('\\'))                    {                        sid = UserInfo.GroupNameToSID(accountName);                         if (!ReferenceEquals(accountName, sid) && UserInfo.IsGroupSID(sid))                            updateMap.Add(id, sid);                    }                }            }             // Update security groups            foreach (KeyValuePair<string, string> pair in updateMap)                database.Connection.ExecuteNonQuery(string.Format(UpdateSecurityGroupFormat, pair.Value, pair.Key));        }         /// <summary>        /// Data operation to validate and ensure there is a record in the        /// CustomActionAdapter table for the external and TLS data publishers.        /// </summary>        private static void ValidateDataPublishers(AdoDataConnection database, string nodeIDQueryString, string arguments)        {            const string DataPublisherCountFormat = "SELECT COUNT(*) FROM CustomActionAdapter WHERE AdapterName='{0}!DATAPUBLISHER' AND NodeID = {1}";            const string GEPDataPublisherInsertFormat = "INSERT INTO CustomActionAdapter(NodeID, AdapterName, AssemblyName, TypeName, ConnectionString, Enabled) VALUES({0}, '{1}!DATAPUBLISHER', 'GSF.TimeSeries.dll', 'GSF.TimeSeries.Transport.DataPublisher', 'securityMode={2}; allowSynchronizedSubscription=false; useBaseTimeOffsets=true; {3}', {4})";            const string STTPDataPublisherInsertFormat = "INSERT INTO CustomActionAdapter(NodeID, AdapterName, AssemblyName, TypeName, ConnectionString, Enabled) VALUES({0}, '{1}!DATAPUBLISHER', 'sttp.gsf.dll', 'sttp.DataPublisher', 'securityMode={2}; {3}', {4})";             bool internalDataPublisherEnabled = true;            bool externalDataPublisherEnabled = true;            bool tlsDataPublisherEnabled = true;            bool sttpDataPublisherEnabled = true;            bool sttpsDataPublisherEnabled = true;             if (!string.IsNullOrEmpty(arguments))            {                Dictionary<string, string> kvps = arguments.ParseKeyValuePairs();                 if (kvps.TryGetValue("internalDataPublisherEnabled", out string value))                    internalDataPublisherEnabled = value.ParseBoolean();                 if (kvps.TryGetValue("externalDataPublisherEnabled", out value))                    externalDataPublisherEnabled = value.ParseBoolean();                 if (kvps.TryGetValue("tlsDataPublisherEnabled", out value))                    tlsDataPublisherEnabled = value.ParseBoolean();                 if (kvps.TryGetValue("sttpDataPublisherEnabled", out value))                    sttpDataPublisherEnabled = value.ParseBoolean();                                if (kvps.TryGetValue("sttpsDataPublisherEnabled", out value))                    sttpsDataPublisherEnabled = value.ParseBoolean();            }             int internalDataPublisherCount = Convert.ToInt32(database.Connection.ExecuteScalar(string.Format(DataPublisherCountFormat, "INTERNAL", nodeIDQueryString)));            int externalDataPublisherCount = Convert.ToInt32(database.Connection.ExecuteScalar(string.Format(DataPublisherCountFormat, "EXTERNAL", nodeIDQueryString)));            int tlsDataPublisherCount = Convert.ToInt32(database.Connection.ExecuteScalar(string.Format(DataPublisherCountFormat, "TLS", nodeIDQueryString)));            int sttpDataPublisherCount = Convert.ToInt32(database.Connection.ExecuteScalar(string.Format(DataPublisherCountFormat, "STTP", nodeIDQueryString)));            int sttpsDataPublisherCount = Convert.ToInt32(database.Connection.ExecuteScalar(string.Format(DataPublisherCountFormat, "STTPS", nodeIDQueryString)));             if (internalDataPublisherCount == 0)                database.Connection.ExecuteNonQuery(string.Format(GEPDataPublisherInsertFormat, nodeIDQueryString, "INTERNAL", "None", "cacheMeasurementKeys={FILTER ActiveMeasurements WHERE SignalType = ''STAT''}", internalDataPublisherEnabled ? 1 : 0));             if (externalDataPublisherCount == 0)                database.Connection.ExecuteNonQuery(string.Format(GEPDataPublisherInsertFormat, nodeIDQueryString, "EXTERNAL", "Gateway", "", externalDataPublisherEnabled ? 1 : 0));             if (tlsDataPublisherCount == 0)                database.Connection.ExecuteNonQuery(string.Format(GEPDataPublisherInsertFormat, nodeIDQueryString, "TLS", "TLS", "", tlsDataPublisherEnabled ? 1 : 0));             if (sttpDataPublisherCount == 0)                database.Connection.ExecuteNonQuery(string.Format(STTPDataPublisherInsertFormat, nodeIDQueryString, "STTP", "None", "cachedMeasurementExpression={FILTER ActiveMeasurements WHERE SignalType = ''STAT''}", sttpDataPublisherEnabled ? 1 : 0));             if (sttpsDataPublisherCount == 0)                database.Connection.ExecuteNonQuery(string.Format(STTPDataPublisherInsertFormat, nodeIDQueryString, "STTPS", "TLS", "", sttpsDataPublisherEnabled ? 1 : 0));        }         /// <summary>        /// Data operation to validate and ensure that certain records that        /// are required for statistics calculations exist in the database.        /// </summary>        private static void ValidateStatistics(AdoDataConnection database, string nodeIDQueryString)        {            // SELECT queries            const string StatConfigEntityCountFormat = "SELECT COUNT(*) FROM ConfigurationEntity WHERE RuntimeName = 'Statistics'";            const string StatSignalTypeCountFormat = "SELECT COUNT(*) FROM SignalType WHERE Acronym = 'STAT'";             const string StatHistorianCountFormat = "SELECT COUNT(*) FROM Historian WHERE Acronym = 'STAT' AND NodeID = {0}";            const string StatEngineCountFormat = "SELECT COUNT(*) FROM CustomActionAdapter WHERE AdapterName = 'STATISTIC!SERVICES' AND NodeID = {0}";            const string SystemStatCountFormat = "SELECT COUNT(*) FROM Statistic WHERE Source = 'System' AND AssemblyName = 'GSF.TimeSeries.dll'";            const string DeviceStatCountFormat = "SELECT COUNT(*) FROM Statistic WHERE Source = 'Device' AND AssemblyName = 'GSF.TimeSeries.dll'";            const string SubscriberStatCountFormat = "SELECT COUNT(*) FROM Statistic WHERE Source = 'Subscriber' AND AssemblyName = 'GSF.TimeSeries.dll'";            const string PublisherStatCountFormat = "SELECT COUNT(*) FROM Statistic WHERE Source = 'Publisher' AND AssemblyName = 'GSF.TimeSeries.dll'";            const string ProcessStatCountFormat = "SELECT COUNT(*) FROM Statistic WHERE Source = 'Process' AND AssemblyName = 'FileAdapters.dll'";             // INSERT queries            const string StatConfigEntityInsertFormat = "INSERT INTO ConfigurationEntity(SourceName, RuntimeName, Description, LoadOrder, Enabled) VALUES('RuntimeStatistic', 'Statistics', 'Defines statistics that are monitored for the system, devices, and output streams', 11, 1)";            const string StatSignalTypeInsertFormat = "INSERT INTO SignalType(Name, Acronym, Suffix, Abbreviation, Source, EngineeringUnits) VALUES('Statistic', 'STAT', 'ST', 'P', 'Any', '')";             const string StatHistorianInsertFormat = "INSERT INTO Historian(NodeID, Acronym, Name, AssemblyName, TypeName, ConnectionString, IsLocal, Description, LoadOrder, Enabled) VALUES({0}, 'STAT', 'Statistics Archive', 'TestingAdapters.dll', 'TestingAdapters.VirtualOutputAdapter', '', 1, 'Local historian used to archive system statistics', 9999, 1)";            const string StatEngineInsertFormat = "INSERT INTO CustomActionAdapter(NodeID, AdapterName, AssemblyName, TypeName, LoadOrder, Enabled) VALUES({0}, 'STATISTIC!SERVICES', 'GSF.TimeSeries.dll', 'GSF.TimeSeries.Statistics.StatisticsEngine', 0, 1)";            const string SystemStatInsertFormat = "INSERT INTO Statistic(Source, SignalIndex, Name, Description, AssemblyName, TypeName, MethodName, Arguments, Enabled, DataType, DisplayFormat, IsConnectedState, LoadOrder) VALUES('System', {0}, '{1}', '{2}', 'GSF.TimeSeries.dll', 'GSF.TimeSeries.Statistics.PerformanceStatistics', 'GetSystemStatistic_{3}', '', 1, '{4}', '{5}', 0, {0})";            const string DeviceStatInsertFormat = "INSERT INTO Statistic(Source, SignalIndex, Name, Description, AssemblyName, TypeName, MethodName, Arguments, Enabled, DataType, DisplayFormat, IsConnectedState, LoadOrder) VALUES('Device', {0}, '{1}', '{2}', 'GSF.TimeSeries.dll', 'GSF.TimeSeries.Statistics.DeviceStatistics', 'GetDeviceStatistic_{3}', '', 1, '{4}', '{5}', 0, {0})";            const string SubscriberStatInsertFormat = "INSERT INTO Statistic(Source, SignalIndex, Name, Description, AssemblyName, TypeName, MethodName, Arguments, Enabled, DataType, DisplayFormat, IsConnectedState, LoadOrder) VALUES('Subscriber', {0}, '{1}', '{2}', 'GSF.TimeSeries.dll', 'GSF.TimeSeries.Statistics.GatewayStatistics', 'GetSubscriberStatistic_{3}', '', 1, '{4}', '{5}', {6}, {0})";            const string PublisherStatInsertFormat = "INSERT INTO Statistic(Source, SignalIndex, Name, Description, AssemblyName, TypeName, MethodName, Arguments, Enabled, DataType, DisplayFormat, IsConnectedState, LoadOrder) VALUES('Publisher', {0}, '{1}', '{2}', 'GSF.TimeSeries.dll', 'GSF.TimeSeries.Statistics.GatewayStatistics', 'GetPublisherStatistic_{3}', '', 1, '{4}', '{5}', {6}, {0})";            const string ProcessStatInsertFormat = "INSERT INTO Statistic(Source, SignalIndex, Name, Description, AssemblyName, TypeName, MethodName, Arguments, Enabled, DataType, DisplayFormat, IsConnectedState, LoadOrder) VALUES('Process', {0}, '{1}', '{2}', 'FileAdapters.dll', 'FileAdapters.ProcessLauncher', 'GetProcessStatistic_{3}', '', 1, 'System.Double', '{{0:N3}}', 0, {0})";             // DELETE queries            const string SystemStatisticDeleteFormat = "DELETE FROM Statistic WHERE Source = 'System' AND SignalIndex <= {0}";            const string DeviceStatisticDeleteFormat = "DELETE FROM Statistic WHERE Source = 'Device' AND SignalIndex <= {0}";            const string SubscriberStatisticDeleteFormat = "DELETE FROM Statistic WHERE Source = 'Subscriber' AND SignalIndex <= {0}";            const string PublisherStatisticDeleteFormat = "DELETE FROM Statistic WHERE Source = 'Publisher' AND SignalIndex <= {0}";            const string ProcessStatisticDeleteFormat = "DELETE FROM Statistic WHERE Source = 'Process' AND SignalIndex <= {0}";             // Names and descriptions for each of the statistics             // NOTE: !! The statistic names defined in the following array are used to define associated function names (minus spaces) - as a result, do *not* leisurely change these statistic names without understanding the consequences            string[] SystemStatNames =            {                /* 01 */ "CPU Usage",                 /* 02 */ "Average CPU Usage",                 /* 03 */ "Memory Usage",                 /* 04 */ "Average Memory Usage",                 /* 05 */ "Thread Count",                 /* 06 */ "Average Thread Count",                 /* 07 */ "Threading Contention Rate",                 /* 08 */ "Average Threading Contention Rate",                 /* 09 */ "IO Usage",                 /* 10 */ "Average IO Usage",                 /* 11 */ "IP Data Send Rate",                 /* 12 */ "Average IP Data Send Rate",                 /* 13 */ "IP Data Receive Rate",                 /* 14 */ "Average IP Data Receive Rate",                 /* 15 */ "Up Time",                /* 16 */ "System CPU Usage",                /* 17 */ "Average System CPU Usage",                /* 18 */ "Available System Memory",                /* 19 */ "Average Available System Memory",                /* 20 */ "System Memory Usage",                /* 21 */ "Average Device Time",                /* 22 */ "Minimum Device Time",                /* 23 */ "Maximum Device Time",                /* 24 */ "System Time Deviation From Average",                /* 25 */ "Primary Disk Usage"            };             string[] SystemStatDescriptions =             {                /* 01 */ "Percentage of CPU currently used by this process.",                /* 02 */ "Average percentage of CPU used by this process.",                /* 03 */ "Amount of memory currently used by this process in megabytes.",                /* 04 */ "Average amount of memory used by this process in megabytes.",                /* 05 */ "Number of threads currently used by this process.",                /* 06 */ "Average number of threads used by this process.",                /* 07 */ "Current thread lock contention rate in attempts per second.",                /* 08 */ "Average thread lock contention rate in attempts per second.",                /* 09 */ "Amount of IO currently used by this process in kilobytes per second.",                /* 10 */ "Average amount of IO used by this process in kilobytes per second.",                /* 11 */ "Number of IP datagrams (or bytes on Mono) currently sent by this process per second.",                /* 12 */ "Average number of IP datagrams (or bytes on Mono) sent by this process per second.",                /* 13 */ "Number of IP datagrams (or bytes on Mono) currently received by this process per second.",                /* 14 */ "Average number of IP datagrams (or bytes on Mono) received by this process per second.",                /* 15 */ "Total number of seconds system has been running.",                /* 16 */ "Percentage of total CPU currently used by the host system.",                /* 17 */ "Average percentage of total CPU used by the host system.",                /* 18 */ "Amount of memory available on the host system in gigabytes",                /* 19 */ "Average amount of memory available on the host system in gigabytes",                /* 20 */ "Percentage of memory currently used on the host system",                /* 21 */ "Average time for all input devices",                /* 22 */ "Minimum time for all input devices",                /* 23 */ "Maximum time for all input devices",                /* 24 */ "System time deviation from average for all input devices in seconds",                /* 25 */ "Percentage of primary disk (C: or /) usage on the host system"            };             string[] SystemStatTypes =            {                /* 01 */ "System.Double",                /* 02 */ "System.Double",                /* 03 */ "System.Double",                /* 04 */ "System.Double",                /* 05 */ "System.Int32",                /* 06 */ "System.Double",                /* 07 */ "System.Double",                /* 08 */ "System.Double",                /* 09 */ "System.Double",                /* 10 */ "System.Double",                /* 11 */ "System.Double",                /* 12 */ "System.Double",                /* 13 */ "System.Double",                /* 14 */ "System.Double",                /* 15 */ "System.Double",                /* 16 */ "System.Double",                /* 17 */ "System.Double",                /* 18 */ "System.Double",                /* 19 */ "System.Double",                /* 20 */ "System.Double",                /* 21 */ "GSF.UnixTimeTag",                /* 22 */ "GSF.UnixTimeTag",                /* 23 */ "GSF.UnixTimeTag",                /* 24 */ "System.Double",                /* 25 */ "System.Double"            };             string[] SystemStatFormats =            {                /* 01 */ "{0:N3} %",                /* 02 */ "{0:N3} %",                /* 03 */ "{0:N3} MB",                /* 04 */ "{0:N3} MB",                /* 05 */ "{0:N0}",                /* 06 */ "{0:N3}",                /* 07 */ "{0:N3}",                /* 08 */ "{0:N3}",                /* 09 */ "{0:N3} KBps",                /* 10 */ "{0:N3} KBps",                /* 11 */ "{0:N3}",                /* 12 */ "{0:N3}",                /* 13 */ "{0:N3}",                /* 14 */ "{0:N3}",                /* 15 */ "{0:N3} s",                /* 16 */ "{0:N3} %",                /* 17 */ "{0:N3} %",                /* 18 */ "{0:N3} GB",                /* 19 */ "{0:N3} GB",                /* 20 */ "{0:N3} %",                /* 21 */ "{0:yyyy''-''MM''-''dd'' ''HH'':''mm'':''ss''.''fff}",                /* 22 */ "{0:yyyy''-''MM''-''dd'' ''HH'':''mm'':''ss''.''fff}",                /* 23 */ "{0:yyyy''-''MM''-''dd'' ''HH'':''mm'':''ss''.''fff}",                /* 24 */ "{0:N3} s",                /* 25 */ "{0:N3} %"            };             // NOTE: !! The statistic names defined in the following array are used to define associated function names (minus spaces) - as a result, do *not* leisurely change these statistic names without understanding the consequences            string[] DeviceStatNames =            {                 /* 01 */ "Data Quality Errors",                 /* 02 */ "Time Quality Errors",                 /* 03 */ "Device Errors",                 /* 04 */ "Measurements Received",                 /* 05 */ "Measurements Expected",                 /* 06 */ "Measurements With Error",                 /* 07 */ "Measurements Defined",                /* 08 */ "Device Time Deviation From Average"            };             string[] DeviceStatDescriptions =            {                /* 01 */ "Number of data quality errors reported by device during last reporting interval.",                /* 02 */ "Number of time quality errors reported by device during last reporting interval.",                /* 03 */ "Number of device errors reported by device during last reporting interval.",                /* 04 */ "Number of measurements received from device during last reporting interval.",                /* 05 */ "Expected number of measurements received from device during last reporting interval.",                /* 06 */ "Number of measurements received while device was reporting errors during last reporting interval.",                /* 07 */ "Number of defined measurements from device during last reporting interval.",                /* 08 */ "Device time deviation from average for all input devices in seconds"            };             string[] DeviceStatTypes =            {                /* 01 */ "System.Int32",                /* 02 */ "System.Int32",                /* 03 */ "System.Int32",                /* 04 */ "System.Int32",                /* 05 */ "System.Int32",                /* 06 */ "System.Int32",                /* 07 */ "System.Int32",                /* 08 */ "System.Double"            };             string[] DeviceStatFormats =            {                /* 01 */ "{0:N0}",                /* 02 */ "{0:N0}",                /* 03 */ "{0:N0}",                /* 04 */ "{0:N0}",                /* 05 */ "{0:N0}",                /* 06 */ "{0:N0}",                /* 07 */ "{0:N0}",                /* 08 */ "{0:N3} s"            };             string[] SubscriberStatNames =            {                /* 01 */ "Subscriber Connected",                 /* 02 */ "Subscriber Authenticated",                 /* 03 */ "Processed Measurements",                 /* 04 */ "Total Bytes Received",                 /* 05 */ "Authorized Signal Count",                 /* 06 */ "Unauthorized Signal Count",                 /* 07 */ "Lifetime Measurements",                 /* 08 */ "Lifetime Bytes Received",                 /* 09 */ "Minimum Measurements Per Second",                 /* 10 */ "Maximum Measurements Per Second",                 /* 11 */ "Average Measurements Per Second",                 /* 12 */ "Lifetime Minimum Latency",                 /* 13 */ "Lifetime Maximum Latency",                 /* 14 */ "Lifetime Average Latency",                 /* 15 */ "Up Time",                 /* 16 */ "TLS Secured Channel"            };             string[] SubscriberStatDescriptions =            {                /* 01 */ "Boolean value representing if the subscriber was continually connected during last reporting interval.",                /* 02 */ "Boolean value representing if the subscriber was authenticated to the publisher during last reporting interval.",

Lines 1–500 of 885.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t