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); }
public int GetDefaultIGridConnectionProfileID() { TableOperations <ConnectionProfileTaskQueue> profileTaskQueueTable = DataContext.Table <ConnectionProfileTaskQueue>(); TableOperations <ConnectionProfile> profileTable = DataContext.Table <ConnectionProfile>(); ConnectionProfile profile = profileTable.QueryRecordWhere("Name = {0}", DefaultIGridConnectionProfileName); if ((object)profile == null) { ConnectionProfileTaskQueue profileTaskQueue = profileTaskQueueTable.NewRecord(); profileTaskQueue.Name = DefaultIGridConnectionProfileTaskQueueName; profileTaskQueue.MaxThreadCount = 4; profileTaskQueue.UseBackgroundThreads = false; profileTaskQueue.Description = "Connection Profile Task for I-Grid Devices"; profileTaskQueueTable.AddNewRecord(profileTaskQueue); profileTaskQueue = profileTaskQueueTable.QueryRecordWhere("Name = {0}", DefaultIGridConnectionProfileTaskQueueName); profile = profileTable.NewRecord(); profile.Name = DefaultIGridConnectionProfileName; profile.Description = "Connection Profile for I-Grid Devices"; profile.DefaultTaskQueueID = profileTaskQueue.ID; profileTable.AddNewRecord(profile); profile.ID = GetDefaultIGridConnectionProfileID(); TableOperations <ConnectionProfileTask> profileTaskTable = DataContext.Table <ConnectionProfileTask>(); profileTaskTable.RootQueryRestriction[0] = profile.ID; int taskCount = profileTaskTable.QueryRecordCount(); if (taskCount == 0) { ConnectionProfileTask profileTask = profileTaskTable.NewRecord(); ConnectionProfileTaskSettings profileTaskSettings = profileTask.Settings; profileTask.ConnectionProfileID = profile.ID; profileTask.Name = "I-Grid Default Downloader Task"; profileTaskSettings.FileExtensions = "*.*"; profileTaskSettings.RemotePath = "/"; profileTaskSettings.LocalPath = Program.Host.Model.Global.DefaultLocalPath; profileTaskSettings.ExternalOperation = "IGridDownloader.exe <DeviceID> <TaskID>"; profileTaskSettings.DirectoryNamingExpression = @"<YYYY><MM>\<DeviceFolderName>"; profileTaskTable.AddNewRecord(profileTask); } } return(profile.ID); }
private static string[] GetOutputMeasurements(TableOperations <Measurement> measurementTable, int deviceID, string tieLineID, string sender, string receiver, OrderedDictionary outputTypes) { List <Measurement> measurements = new List <Measurement>(); foreach (string outputType in outputTypes.Keys) { string pointTag = $"IMPEDANCE_{tieLineID}-{outputType}:CV"; string description = $"{tieLineID} [{sender} => {receiver}] Calculated {outputTypes[outputType]} Value"; Measurement measurement = measurementTable.QueryRecordWhere("PointTag = {0}", pointTag); if ((object)measurement == null) { measurement = measurementTable.NewRecord(); measurement.DeviceID = deviceID; measurement.PointTag = pointTag; measurement.SignalReference = pointTag; measurement.Description = description; measurement.Enabled = true; measurementTable.AddNewRecord(measurement); measurement = measurementTable.QueryRecordWhere("PointTag = {0}", pointTag); if ((object)measurement == null) { throw new InvalidOperationException($"Failed to lookup Measurement record with PointTag of \"{pointTag}\"."); } } else { measurement.Description = description; measurementTable.UpdateRecord(measurement); } measurements.Add(measurement); } return(measurements.Select(m => m.SignalID.ToString()).ToArray()); }
private static Device GetOrAddDevice(TableOperations <Device> deviceTable, string acronym) { Device device = deviceTable.QueryRecordWhere("NodeID = {0} AND Acronym = {1}", nodeID, acronym); if ((object)device == null) { device = deviceTable.NewRecord(); device.NodeID = nodeID; device.Acronym = acronym; device.Name = acronym; deviceTable.AddNewRecord(device); device = deviceTable.QueryRecordWhere("NodeID = {0} AND Acronym = {1}", nodeID, acronym); if ((object)device == null) { throw new InvalidOperationException($"Failed to lookup Device record with Acronym of \"{acronym}\"."); } } return(device); }
public IEnumerable <IGridDevice> QueryIGridDevices(string baseURL) { TableOperations <Device> deviceTable = DataContext.Table <Device>(); XDocument document = XDocument.Load($"{baseURL}&action=getMonitorList"); foreach (XElement monitor in document.Descendants("monitor")) { decimal longitude, latitude; XElement location = monitor.Element("location"); XElement identification = monitor.Element("identification"); XElement model = monitor.Element("model"); string serialNumber = identification?.Element("serialNumber")?.Value; string modelNumber = model?.Element("number")?.Value; string monitorName = identification?.Element("monitorName")?.Value; if (string.IsNullOrWhiteSpace(serialNumber) || string.IsNullOrWhiteSpace(modelNumber)) { continue; } Device deviceRecord = deviceTable.QueryRecordWhere("OriginalSource = {0}", serialNumber); if ((object)deviceRecord == null) { deviceRecord = deviceTable.NewRecord(); string acronym = monitorName ?? modelNumber; // Get a clean acronym acronym = acronym .ToUpperInvariant() .ReplaceCharacters(' ', s_isInvalidAcronymChar) .RemoveDuplicateWhiteSpace(); // Truncate at any numbers in the acronym, note this is based on sample data naming convention int index = acronym.IndexOfAny(s_digits); if (index > 0) { acronym = acronym.Substring(0, index); } acronym = acronym.Trim().ReplaceWhiteSpace('-'); deviceRecord.Acronym = $"{acronym}${serialNumber}"; } decimal.TryParse(location?.Element("longitude")?.Value, out longitude); decimal.TryParse(location?.Element("latitude")?.Value, out latitude); yield return(new IGridDevice { DeviceID = deviceRecord.ID, Acronym = deviceRecord.Acronym, SerialNumber = serialNumber, Name = monitorName, Description = model.Element("description")?.Value, ModelNumber = modelNumber, Longitude = longitude, Latitude = latitude, Selected = deviceRecord.ID == 0 }); } }
/// <summary> /// Gets measurement record, creating it if needed. /// </summary> /// <param name="instance">Target <see cref="IIndependentAdapterManager"/> instance.</param> /// <param name="currentDeviceID">Device ID associated with current adapter, or zero if none.</param> /// <param name="pointTag">Point tag of measurement.</param> /// <param name="signalReference">Signal reference of measurement.</param> /// <param name="description">Description of measurement.</param> /// <param name="signalType">Signal type of measurement.</param> /// <param name="targetHistorianAcronym">Acronym of target historian for measurement.</param> /// <returns>Measurement record.</returns> public static MeasurementRecord GetMeasurementRecord(this IIndependentAdapterManager instance, int currentDeviceID, string pointTag, string signalReference, string description, SignalType signalType = SignalType.CALC, string targetHistorianAcronym = "PPA") { // Open database connection as defined in configuration file "systemSettings" category using (AdoDataConnection connection = instance.GetConfiguredConnection()) { TableOperations <DeviceRecord> deviceTable = new TableOperations <DeviceRecord>(connection); TableOperations <MeasurementRecord> measurementTable = new TableOperations <MeasurementRecord>(connection); TableOperations <HistorianRecord> historianTable = new TableOperations <HistorianRecord>(connection); TableOperations <SignalTypeRecord> signalTypeTable = new TableOperations <SignalTypeRecord>(connection); // Lookup target device ID int?deviceID = currentDeviceID > 0 ? currentDeviceID : deviceTable.QueryRecordWhere("Acronym = {0}", instance.Name)?.ID; // Lookup target historian ID int?historianID = historianTable.QueryRecordWhere("Acronym = {0}", targetHistorianAcronym)?.ID; // Lookup signal type ID int signalTypeID = signalTypeTable.QueryRecordWhere("Acronym = {0}", signalType.ToString())?.ID ?? 1; // Lookup measurement record by point tag, creating a new record if one does not exist MeasurementRecord measurement = measurementTable.QueryRecordWhere("PointTag = {0}", pointTag) ?? measurementTable.NewRecord(); // Update record fields measurement.DeviceID = deviceID; measurement.HistorianID = historianID; measurement.PointTag = pointTag; measurement.SignalReference = signalReference; measurement.SignalTypeID = signalTypeID; measurement.Description = description; // Save record updates measurementTable.AddNewOrUpdateRecord(measurement); // Re-query new records to get any database assigned information, e.g., unique Guid-based signal ID if (measurement.PointID == 0) { measurement = measurementTable.QueryRecordWhere("PointTag = {0}", pointTag); } // Notify host system of configuration changes instance.OnConfigurationChanged(); return(measurement); } }
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); } }
public static Measurement NewMeasurement(this TableOperations <Measurement> measurementTable) => measurementTable.NewRecord();
public static Device NewDevice(this TableOperations <Device> deviceTable) => deviceTable.NewRecord();
public static Phasor NewPhasor(this TableOperations <Phasor> phasorTable) => phasorTable.NewRecord();
private void SetupRequiredAdapters() { try { const string PTPdProcessName = "PTPD!PROCESS"; const string StatisticServicesName = "STATISTIC!SERVICES"; const string DataPublisherName = "INTERNAL!DATAPUBLISHER"; // Access needed settings from specified categories in configuration file CategorizedSettingsElementCollection systemSettings = ConfigurationFile.Current.Settings["systemSettings"]; string newNodeID = Guid.NewGuid().ToString(); // Make sure needed settings exist systemSettings.Add("NodeID", newNodeID, "Unique Node ID"); // Get settings as currently defined in configuration file Guid nodeID = Guid.Parse(systemSettings["NodeID"].ValueAs(newNodeID)); // 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); // Make sure Grafana process adapter exists CustomActionAdapter actionAdapter = actionAdapterTable.QueryRecordWhere("AdapterName = {0}", PTPdProcessName) ?? actionAdapterTable.NewRecord(); // Update record fields actionAdapter.NodeID = nodeID; actionAdapter.AdapterName = PTPdProcessName; actionAdapter.AssemblyName = "FileAdapters.dll"; actionAdapter.TypeName = "FileAdapters.ProcessLauncher"; actionAdapter.Enabled = true; string interfaceGuid = null; // Scan network interfaces try { NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces().Where(ni => ni.OperationalStatus == OperationalStatus.Up && ni.NetworkInterfaceType != NetworkInterfaceType.Loopback && ni.NetworkInterfaceType != NetworkInterfaceType.Tunnel).ToArray(); if (networkInterfaces.Length > 0) { interfaceGuid = networkInterfaces[0].Id; File.WriteAllText(FilePath.GetAbsolutePath("NetworkInterfaces.txt"), $"Local Network Interfaces:\r\n\r\n{string.Join("\r\n", networkInterfaces.Select(ni => $"{ni.Name} - {ni.Description}: {ni.Id}"))}"); } } catch { } // Define default adapter connection string if none is defined if (string.IsNullOrWhiteSpace(actionAdapter.ConnectionString)) { actionAdapter.ConnectionString = $"FileName=ptpd.exe; Arguments={{-b {interfaceGuid ?? "{InterfaceGuidHere}"} -V -g}}; ForceKillOnDispose=True"; } // Save record updates actionAdapterTable.AddNewOrUpdateRecord(actionAdapter); // Make sure statistic services adapter exists actionAdapter = actionAdapterTable.QueryRecordWhere("AdapterName = {0}", StatisticServicesName) ?? actionAdapterTable.NewRecord(); // Update record fields actionAdapter.NodeID = nodeID; actionAdapter.AdapterName = StatisticServicesName; actionAdapter.AssemblyName = "GSF.TimeSeries.dll"; actionAdapter.TypeName = "GSF.TimeSeries.Statistics.StatisticsEngine"; actionAdapter.Enabled = true; // Save record updates actionAdapterTable.AddNewOrUpdateRecord(actionAdapter); // Make sure internal data publisher adapter exists actionAdapter = actionAdapterTable.QueryRecordWhere("AdapterName = {0}", DataPublisherName) ?? actionAdapterTable.NewRecord(); // Update record fields actionAdapter.NodeID = nodeID; actionAdapter.AdapterName = DataPublisherName; actionAdapter.AssemblyName = "GSF.TimeSeries.dll"; actionAdapter.TypeName = "GSF.TimeSeries.Transport.DataPublisher"; actionAdapter.ConnectionString = "securityMode=None; allowSynchronizedSubscription=false; useBaseTimeOffsets=true; cacheMeasurementKeys={FILTER ActiveMeasurements WHERE SignalType = 'STAT'}"; actionAdapter.Enabled = true; // Save record updates actionAdapterTable.AddNewOrUpdateRecord(actionAdapter); } } catch (Exception ex) { LogPublisher log = Logger.CreatePublisher(typeof(ServiceHost), MessageClass.Application); log.Publish(MessageLevel.Error, "Error Message", "Failed to setup PTPd hosting adapter", null, ex); } }