Beispiel #1
0
        private static CustomActionAdapter GetOrAddActionAdapter(TableOperations <CustomActionAdapter> actionAdapterTable, string tielineID, out bool newAdd)
        {
            string adapterName = $"IMPEDANCE_{tielineID}_CALC";
            CustomActionAdapter actionAdapter = actionAdapterTable.QueryRecordWhere("NodeID = {0} AND AdapterName = {1}", nodeID, adapterName);

            if ((object)actionAdapter == null)
            {
                actionAdapter = actionAdapterTable.NewRecord();

                actionAdapter.NodeID       = nodeID;
                actionAdapter.AdapterName  = adapterName;
                actionAdapter.AssemblyName = AssemblyName;
                actionAdapter.TypeName     = TypeName;

                actionAdapterTable.AddNewRecord(actionAdapter);

                // Re-query newly added record to get auto-increment ID
                actionAdapter = actionAdapterTable.QueryRecordWhere("NodeID = {0} AND AdapterName = {1}", nodeID, adapterName);
                newAdd        = true;

                if ((object)actionAdapter == null)
                {
                    throw new InvalidOperationException($"Failed to lookup CustomActionAdapter record with AdapterName of \"{adapterName}\".");
                }
            }
            else
            {
                newAdd = false;
            }

            return(actionAdapter);
        }
Beispiel #2
0
        public void ValidateCalculatorConfigurations(int?historianID, string systemName)
        {
            const int Avg = 0, Max = 1, Min = 2;

            PowerCalculationConfigurationValidation.ValidateDatabaseDefinitions();

            TableOperations <Measurement> measurementTable = DataContext.Table <Measurement>();
            string frequencyDeviceName = string.Format(SystemFrequencyDeviceName, systemName);

            // Look for existing frequency average
            if (measurementTable.QueryRecordCountWhere($"SignalReference = '{SignalReference.ToString(frequencyDeviceName, SignalKind.Frequency)}'") > 0)
            {
                return;
            }

            TableOperations <CustomActionAdapter> customActionAdapterTable = DataContext.Table <CustomActionAdapter>();
            CustomActionAdapter avgFreqAdapter = customActionAdapterTable.QueryRecordWhere("TypeName = {0}", typeof(PowerCalculations.AverageFrequency).FullName) ?? NewCustomActionAdapter();

            Measurement[] measurements = GetCalculatedFrequencyMeasurements(historianID, systemName, frequencyDeviceName);

            double lagTime             = DefaultCalculationLagTime;

            // Reduce lag-time since dynamic calculations can depend on average frequency
            lagTime -= lagTime > 1.0 ? 1.0 : 0.5;

            if (lagTime < 0.1)
            {
                lagTime = 0.1;
            }

            avgFreqAdapter.AdapterName      = "PHASOR!AVERAGEFREQ";
            avgFreqAdapter.AssemblyName     = "PowerCalculations.dll";
            avgFreqAdapter.TypeName         = typeof(PowerCalculations.AverageFrequency).FullName;
            avgFreqAdapter.ConnectionString = $"InputMeasurementKeys={{FILTER ActiveMeasurements WHERE SignalType = 'FREQ' AND SignalReference NOT LIKE '{frequencyDeviceName}%'}}; OutputMeasurements={{{measurements[Avg].SignalID};{measurements[Max].SignalID};{measurements[Min].SignalID}}}; LagTime={lagTime}; LeadTime={DefaultCalculationLeadTime}; FramesPerSecond={DefaultCalculationFramesPerSecond}";
            avgFreqAdapter.Enabled          = true;

            customActionAdapterTable.AddNewOrUpdateRecord(avgFreqAdapter);
        }
Beispiel #3
0
        public void AddNewOrUpdateCustomActionAdapter(CustomActionAdapter customActionAdapter)
        {
            TableOperations <CustomActionAdapter> customActionAdapterTable = DataContext.Table <CustomActionAdapter>();

            if (customActionAdapterTable.QueryRecordCountWhere("AdapterName = {0}", customActionAdapter.AdapterName) == 0)
            {
                AddNewCustomActionAdapter(customActionAdapter);
            }
            else
            {
                CustomActionAdapter existingActionAdapter = customActionAdapterTable.QueryRecordWhere("AdapterName = {0}", customActionAdapter.AdapterName);

                existingActionAdapter.AssemblyName     = customActionAdapter.AssemblyName;
                existingActionAdapter.TypeName         = customActionAdapter.TypeName;
                existingActionAdapter.ConnectionString = customActionAdapter.ConnectionString;
                existingActionAdapter.LoadOrder        = customActionAdapter.LoadOrder;
                existingActionAdapter.Enabled          = customActionAdapter.Enabled;
                existingActionAdapter.UpdatedBy        = customActionAdapter.UpdatedBy;
                existingActionAdapter.UpdatedOn        = customActionAdapter.UpdatedOn;

                UpdateCustomActionAdapter(existingActionAdapter);
            }
        }
Beispiel #4
0
 public void UpdateCustomActionAdapter(CustomActionAdapter customActionAdapter)
 {
     DataContext.Table <CustomActionAdapter>().UpdateRecord(customActionAdapter);
 }
Beispiel #5
0
 public void AddNewCustomActionAdapter(CustomActionAdapter customActionAdapter)
 {
     DataContext.Table <CustomActionAdapter>().AddNewRecord(customActionAdapter);
 }
Beispiel #6
0
        private void SetupGrafanaHostingAdapter()
        {
            try
            {
                const string GrafanaProcessAdapterName = "GRAFANA!PROCESS";
                const string DefaultGrafanaServerPath  = GrafanaAuthProxyController.DefaultServerPath;

                const string GrafanaAdminRoleName        = GrafanaAuthProxyController.GrafanaAdminRoleName;
                const string GrafanaAdminRoleDescription = "Grafana Administrator Role";

                // Access needed settings from specified categories in configuration file
                CategorizedSettingsElementCollection systemSettings = ConfigurationFile.Current.Settings["systemSettings"];
                CategorizedSettingsElementCollection grafanaHosting = ConfigurationFile.Current.Settings["grafanaHosting"];
                string newNodeID = Guid.NewGuid().ToString();

                // Make sure needed settings exist
                systemSettings.Add("NodeID", newNodeID, "Unique Node ID");
                grafanaHosting.Add("ServerPath", DefaultGrafanaServerPath, "Defines the path to the Grafana server to host - set to empty string to disable hosting.");

                // Get settings as currently defined in configuration file
                Guid   nodeID            = Guid.Parse(systemSettings["NodeID"].ValueAs(newNodeID));
                string grafanaServerPath = grafanaHosting["ServerPath"].ValueAs(DefaultGrafanaServerPath);

                // Only enable adapter if file path to configured Grafana server executable is accessible
                bool enabled = File.Exists(FilePath.GetAbsolutePath(grafanaServerPath));

                // Open database connection as defined in configuration file "systemSettings" category
                using (AdoDataConnection connection = new AdoDataConnection("systemSettings"))
                {
                    // Make sure Grafana process adapter exists
                    TableOperations <CustomActionAdapter> actionAdapterTable = new TableOperations <CustomActionAdapter>(connection);
                    CustomActionAdapter actionAdapter = actionAdapterTable.QueryRecordWhere("AdapterName = {0}", GrafanaProcessAdapterName) ?? actionAdapterTable.NewRecord();

                    // Update record fields
                    actionAdapter.NodeID       = nodeID;
                    actionAdapter.AdapterName  = GrafanaProcessAdapterName;
                    actionAdapter.AssemblyName = "FileAdapters.dll";
                    actionAdapter.TypeName     = "FileAdapters.ProcessLauncher";
                    actionAdapter.Enabled      = enabled;

                    // Define default adapter connection string if none is defined
                    if (string.IsNullOrWhiteSpace(actionAdapter.ConnectionString))
                    {
                        actionAdapter.ConnectionString =
                            $"FileName={DefaultGrafanaServerPath}; " +
                            $"WorkingDirectory={FilePath.GetAbsolutePath("Grafana")}; " +
                            "ForceKillOnDispose=True; " +
                            "ProcessOutputAsLogMessages=True; " +
                            "LogMessageTextExpression={(?<=.*msg\\s*\\=\\s*\\\")[^\\\"]*(?=\\\")|(?<=.*file\\s*\\=\\s*\\\")[^\\\"]*(?=\\\")|(?<=.*file\\s*\\=\\s*)[^\\s]*(?=s|$)|(?<=.*path\\s*\\=\\s*\\\")[^\\\"]*(?=\\\")|(?<=.*path\\s*\\=\\s*)[^\\s]*(?=s|$)|(?<=.*error\\s*\\=\\s*\\\")[^\\\"]*(?=\\\")|(?<=.*reason\\s*\\=\\s*\\\")[^\\\"]*(?=\\\")|(?<=.*id\\s*\\=\\s*\\\")[^\\\"]*(?=\\\")|(?<=.*version\\s*\\=\\s*)[^\\s]*(?=\\s|$)|(?<=.*dbtype\\s*\\=\\s*)[^\\s]*(?=\\s|$)|(?<=.*)commit\\s*\\=\\s*[^\\s]*(?=\\s|$)|(?<=.*)compiled\\s*\\=\\s*[^\\s]*(?=\\s|$)|(?<=.*)address\\s*\\=\\s*[^\\s]*(?=\\s|$)|(?<=.*)protocol\\s*\\=\\s*[^\\s]*(?=\\s|$)|(?<=.*)subUrl\\s*\\=\\s*[^\\s]*(?=\\s|$)|(?<=.*)code\\s*\\=\\s*[^\\s]*(?=\\s|$)|(?<=.*name\\s*\\=\\s*)[^\\s]*(?=\\s|$)}; " +
                            "LogMessageLevelExpression={(?<=.*lvl\\s*\\=\\s*)[^\\s]*(?=\\s|$)}; " +
                            "LogMessageLevelMappings={info=Info; warn=Waning; error=Error; critical=Critical; debug=Debug}";
                    }

                    // Preserve connection string on existing records except for Grafana server executable path that comes from configuration file
                    Dictionary <string, string> settings = actionAdapter.ConnectionString.ParseKeyValuePairs();
                    settings["FileName"]           = grafanaServerPath;
                    actionAdapter.ConnectionString = settings.JoinKeyValuePairs();

                    // Save record updates
                    actionAdapterTable.AddNewOrUpdateRecord(actionAdapter);

                    // Make sure Grafana admin role exists
                    TableOperations <ApplicationRole> applicationRoleTable = new TableOperations <ApplicationRole>(connection);
                    ApplicationRole applicationRole = applicationRoleTable.QueryRecordWhere("Name = {0} AND NodeID = {1}", GrafanaAdminRoleName, nodeID);

                    if ((object)applicationRole == null)
                    {
                        applicationRole             = applicationRoleTable.NewRecord();
                        applicationRole.NodeID      = nodeID;
                        applicationRole.Name        = GrafanaAdminRoleName;
                        applicationRole.Description = GrafanaAdminRoleDescription;
                        applicationRoleTable.AddNewRecord(applicationRole);
                    }
                }
            }
            catch (Exception ex)
            {
                LogPublisher log = Logger.CreatePublisher(typeof(ServiceHost), MessageClass.Application);
                log.Publish(MessageLevel.Error, "Error Message", "Failed to setup Grafana hosting adapter", null, ex);
            }
        }
Beispiel #7
0
        static int Main()
        {
            int row = 0;

            try
            {
                Arguments args = new Arguments(Environment.CommandLine, true);
                string    sourceApp, sourceDevice, setting;
                double    lagTime, leadTime;
                int       framesPerSecond, successes = 0, failures = 0, simpleFormattedRecords = 0, explicitFormattedRecords = 0;
                bool      skipFirstRow;

                if (args.Count != RequiredArgumentCount)
                {
                    throw new ArgumentException($"Expected {RequiredArgumentCount} argument, received {args.Count}.");
                }

                if (!args.TryGetValue("sourceApp", out sourceApp))
                {
                    sourceApp = DefaultSourceApp;
                }

                if (!args.TryGetValue("sourceDevice", out sourceDevice))
                {
                    sourceDevice = DefaultSourceDevice;
                }

                if (!args.TryGetValue("lagTime", out setting) || !double.TryParse(setting, out lagTime))
                {
                    lagTime = DefaultLagTime;
                }

                if (!args.TryGetValue("leadTime", out setting) || !double.TryParse(setting, out leadTime))
                {
                    leadTime = DefaultLeadTime;
                }

                if (!args.TryGetValue("framesPerSecond", out setting) || !int.TryParse(setting, out framesPerSecond))
                {
                    framesPerSecond = DefaultFramesPerSecond;
                }

                if (args.TryGetValue("skipFirstRow", out setting))
                {
                    skipFirstRow = setting.ParseBoolean();
                }
                else
                {
                    skipFirstRow = true;
                }

                string sourceFileName = FilePath.GetAbsolutePath(args["OrderedArg1"]);

                string configFile = FilePath.GetAbsolutePath($"{sourceApp}.exe.config");

                if (!File.Exists(configFile))
                {
                    throw new FileNotFoundException($"Config file for {sourceApp} application \"{configFile}\" was not found.");
                }

                XDocument serviceConfig = XDocument.Load(configFile);

                nodeID = Guid.Parse(serviceConfig
                                    .Descendants("systemSettings")
                                    .SelectMany(systemSettings => systemSettings.Elements("add"))
                                    .Where(element => "NodeID".Equals((string)element.Attribute("name"), StringComparison.OrdinalIgnoreCase))
                                    .Select(element => (string)element.Attribute("value"))
                                    .FirstOrDefault());

                string connectionString = serviceConfig
                                          .Descendants("systemSettings")
                                          .SelectMany(systemSettings => systemSettings.Elements("add"))
                                          .Where(element => "ConnectionString".Equals((string)element.Attribute("name"), StringComparison.OrdinalIgnoreCase))
                                          .Select(element => (string)element.Attribute("value"))
                                          .FirstOrDefault();

                string dataProviderString = serviceConfig
                                            .Descendants("systemSettings")
                                            .SelectMany(systemSettings => systemSettings.Elements("add"))
                                            .Where(element => "DataProviderString".Equals((string)element.Attribute("name"), StringComparison.OrdinalIgnoreCase))
                                            .Select(element => (string)element.Attribute("value"))
                                            .FirstOrDefault();

                using (AdoDataConnection connection = new AdoDataConnection(connectionString, dataProviderString))
                    using (StreamReader reader = File.OpenText(sourceFileName))
                    {
                        TableOperations <Device>              deviceTable        = new TableOperations <Device>(connection);
                        TableOperations <Measurement>         measurementTable   = new TableOperations <Measurement>(connection);
                        TableOperations <Phasor>              phasorTable        = new TableOperations <Phasor>(connection);
                        TableOperations <CustomActionAdapter> actionAdapterTable = new TableOperations <CustomActionAdapter>(connection);

                        string line;

                        while ((object)(line = reader.ReadLine()) != null)
                        {
                            row++;

                            if (skipFirstRow)
                            {
                                skipFirstRow = false;
                                continue;
                            }

                            // Simple mode: -- simple mode only works when devices on both end of the line are measuring a single voltage and current
                            // 0        1              2
                            // TieLine, SendingDevice, ReceivingDevice

                            // Explicit mode:
                            // 0        1                  2                    3         4             5         6             7         8             9         10
                            // TieLine, SendingSubstation, ReceivingSubstation, SV1Angle, SV1Magnitude, SI1Angle, SI1Magnitude, RV1Angle, RV1Magnitude, RI1Angle, RI1Magnitude
                            string[] columns = line.Split(',');

                            if (columns.Length < 3)
                            {
                                Console.WriteLine($"Not enough columns in CSV file at row {row} - expected 3 for simple mode, encountered {columns.Length}, skipped row.");
                                continue;
                            }

                            if (columns.Length > 3 && columns.Length < 11)
                            {
                                Console.WriteLine($"Not enough columns in CSV file at row {row} - expected 11 for explicit mode, encountered {columns.Length}, skipped row.");
                                continue;
                            }

                            string        tieLineID = columns[0].ToUpperInvariant().Trim();
                            string        sendDevice = columns[1].ToUpperInvariant().Trim();
                            string        receiveDevice = columns[2].ToUpperInvariant().Trim();
                            string        sv1Angle = null, sv1Magnitude = null, si1Angle = null, si1Magnitude = null, rv1Angle = null, rv1Magnitude = null, ri1Angle = null, ri1Magnitude = null;
                            string[]      measurements;
                            bool          simpleMode        = columns.Length == 3;
                            List <string> inputMeasurements = new List <string>();
                            Dictionary <string, string> adapterConnectionString = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);

                            if (simpleMode)
                            {
                                simpleFormattedRecords++;
                            }
                            else
                            {
                                explicitFormattedRecords++;
                                sv1Angle     = columns[3].ToUpperInvariant().Trim();
                                sv1Magnitude = columns[4].ToUpperInvariant().Trim();
                                si1Angle     = columns[5].ToUpperInvariant().Trim();
                                si1Magnitude = columns[6].ToUpperInvariant().Trim();
                                rv1Angle     = columns[7].ToUpperInvariant().Trim();
                                rv1Magnitude = columns[8].ToUpperInvariant().Trim();
                                ri1Angle     = columns[9].ToUpperInvariant().Trim();
                                ri1Magnitude = columns[10].ToUpperInvariant().Trim();
                            }

                            // Add initial connection string settings
                            adapterConnectionString["FramesPerSecond"] = framesPerSecond.ToString();
                            adapterConnectionString["LagTime"]         = lagTime.ToString(CultureInfo.InvariantCulture);
                            adapterConnectionString["LeadTime"]        = leadTime.ToString(CultureInfo.InvariantCulture);

                            // Get or add virtual device to associate new output measurements with
                            Device device = GetOrAddDevice(deviceTable, sourceDevice);

                            if (simpleMode)
                            {
                                // Get input measurement IDs for sending device
                                measurements = GetInputMeasurements(deviceTable, measurementTable, phasorTable, sendDevice);

                                if ((object)measurements == null)
                                {
                                    failures++;
                                    continue;
                                }

                                inputMeasurements.AddRange(measurements);

                                // Get input measurement IDs for receiving device
                                measurements = GetInputMeasurements(deviceTable, measurementTable, phasorTable, receiveDevice);

                                if ((object)measurements == null)
                                {
                                    failures++;
                                    continue;
                                }

                                inputMeasurements.AddRange(measurements);
                            }
                            else
                            {
                                if (GetInputMeasurement(measurementTable, sv1Angle, inputMeasurements) ||
                                    GetInputMeasurement(measurementTable, sv1Magnitude, inputMeasurements) ||
                                    GetInputMeasurement(measurementTable, si1Angle, inputMeasurements) ||
                                    GetInputMeasurement(measurementTable, si1Magnitude, inputMeasurements) ||
                                    GetInputMeasurement(measurementTable, rv1Angle, inputMeasurements) ||
                                    GetInputMeasurement(measurementTable, rv1Magnitude, inputMeasurements) ||
                                    GetInputMeasurement(measurementTable, ri1Angle, inputMeasurements) ||
                                    GetInputMeasurement(measurementTable, ri1Magnitude, inputMeasurements))
                                {
                                    failures++;
                                    continue;
                                }
                            }

                            // Define input measurement keys connection string parameter
                            adapterConnectionString["InputMeasurementKeys"] = string.Join("; ", inputMeasurements);

                            bool newAdd;
                            CustomActionAdapter actionAdapter = GetOrAddActionAdapter(actionAdapterTable, tieLineID, out newAdd);
                            Console.WriteLine($"{(newAdd ? "Adding" : "Augmenting")} impedance calculation for \"{tieLineID}\"...");

                            // Get output measurement IDs for calculator adapter, creating them if needed
                            OrderedDictionary outputTypes = new OrderedDictionary(StringComparer.OrdinalIgnoreCase)
                            {
                                ["RESISTANCE"]          = "Resistance",
                                ["REACTANCE"]           = "Reactance",
                                ["CONDUCTANCE"]         = "Conductance",
                                ["SUSCEPTANCE"]         = "Susceptance",
                                ["LINEIMPEDANCE"]       = "Line Impedance",
                                ["LINEIMPEDANCEANGLE"]  = "Line Impedance Angle",
                                ["LINEADMITTANCE"]      = "Line Admittance",
                                ["LINEADMITTANCEANGLE"] = "Line Admittance Angle"
                            };

                            measurements = GetOutputMeasurements(measurementTable, device.ID, tieLineID, sendDevice, receiveDevice, outputTypes);

                            // Define input measurement keys connection string parameter
                            adapterConnectionString["OutputMeasurements"] = string.Join("; ", measurements);

                            // Save updates to action adapter
                            actionAdapter.Enabled          = true;
                            actionAdapter.ConnectionString = adapterConnectionString.JoinKeyValuePairs();
                            actionAdapterTable.UpdateRecord(actionAdapter);

                            successes++;
                        }
                    }

                Console.WriteLine();
                Console.WriteLine($"Found {simpleFormattedRecords:N0} simple formatted records.");
                Console.WriteLine($"Found {explicitFormattedRecords:N0} explicit formatted records.");
                Console.WriteLine();
                Console.WriteLine($"{successes:N0} successful imports.");
                Console.WriteLine($"{failures:N0} failed imports.");
#if DEBUG
                Console.ReadKey();
#endif
                return(0);
            }
            catch (Exception ex)
            {
                Console.WriteLine();
                Console.WriteLine($"Import halted at row {row}!");
                Console.Error.WriteLine($"Load Exception: {ex.Message}");
                return(1);
            }
        }