using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel.DataAnnotations; using System.Data; using System.Linq; using GSF; using GSF.Data; using GSF.TimeSeries.UI; using GSF.TimeSeries.UI.DataModels; namespace PowerCalculations.UI.DataModels { public class PowerCalculation : DataModelBase { #region [ Members ] private int m_id; private string m_circuitDescription; private Measurement m_activePowerOutputMeasurement; private Measurement m_reactivePowerOutputMeasurement; private Measurement m_apparentPowerOutputMeasurement; private bool m_enabled; private Guid m_nodeID; private Phasor m_voltagePhasor; private Phasor m_currentPhasor; #endregion #region [ Properties ] public int ID { get { return m_id; } set { if (m_id == value) return; m_id = value; OnPropertyChanged(nameof(ID)); } } [Required(ErrorMessage = "Power calculation description is a required field. Please provide a value.")] [StringLength(4000, ErrorMessage = "Power calculation description cannot exceed 4000 characters")] public string CircuitDescription { get { return m_circuitDescription; } set { if (m_circuitDescription == value) return; m_circuitDescription = value; OnPropertyChanged(nameof(CircuitDescription)); } } public Measurement ActivePowerOutputMeasurement { get { return m_activePowerOutputMeasurement; } set { if (m_activePowerOutputMeasurement == value) return; m_activePowerOutputMeasurement = value; OnPropertyChanged(nameof(ActivePowerOutputMeasurement)); } } public Measurement ReactivePowerOutputMeasurement { get { return m_reactivePowerOutputMeasurement; } set { if (m_reactivePowerOutputMeasurement == value) return; m_reactivePowerOutputMeasurement = value; OnPropertyChanged(nameof(ReactivePowerOutputMeasurement)); } } public Measurement ApparentPowerOutputMeasurement { get { return m_apparentPowerOutputMeasurement; } set { if (m_apparentPowerOutputMeasurement == value) return; m_apparentPowerOutputMeasurement = value; OnPropertyChanged(nameof(ApparentPowerOutputMeasurement)); } } [Required(ErrorMessage = "Enabled is a required field. Please enter a value for the enabled flag.")] public bool Enabled { get { return m_enabled; } set { if (m_enabled == value) return; m_enabled = value; OnPropertyChanged(nameof(Enabled)); } } [Required(ErrorMessage = "Node ID is a required field. Please enter a value for the Node ID.")] public Guid NodeID { get { return m_nodeID; } set { if (m_nodeID == value) return; m_nodeID = value; OnPropertyChanged(nameof(NodeID)); } } public Phasor VoltagePhasor { get { return m_voltagePhasor; } set { if (m_voltagePhasor == value) return; m_voltagePhasor = value; OnPropertyChanged(nameof(VoltagePhasor)); UpdateCircuitDescription(); } } public Phasor CurrentPhasor { get { return m_currentPhasor; } set { if (m_currentPhasor == value) return; m_currentPhasor = value; OnPropertyChanged(nameof(CurrentPhasor)); UpdateCircuitDescription(); } } private void UpdateCircuitDescription() { if ((object)m_voltagePhasor != null && (object)m_currentPhasor != null) CircuitDescription = $"{LookupDeviceName(m_voltagePhasor.DeviceID)}-{(m_currentPhasor.Label ?? "").ToUpperInvariant().RemoveWhiteSpace()}"; } #endregion #region [ Statics ] /// /// LoadKeys information as an style list. /// /// to connection to database. /// Collection of . public static IList LoadKeys(AdoDataConnection database) { var createdConnection = false; try { createdConnection = CreateConnection(ref database); var calculationList = new List(); var queryFormat = "SELECT ID FROM PowerCalculation WHERE NodeID = {0}"; var calculationTable = database.RetrieveData(queryFormat, database.CurrentNodeID()); foreach (DataRow row in calculationTable.Rows) { calculationList.Add(row.ConvertField("ID")); } return calculationList; } finally { if (createdConnection && database != null) database.Dispose(); } } private static string LookupDeviceName(int deviceID) { AdoDataConnection database = null; string deviceName = ""; if (CreateConnection(ref database)) { deviceName = database.ExecuteScalar("SELECT Acronym FROM Device WHERE ID={0}", deviceID) ?? ""; database.Dispose(); } return deviceName; } /// /// Loads information as an style list. /// /// to connection to database. /// Keys of the measurement to be loaded from the database /// Collection of . public static ObservableCollection Load(AdoDataConnection database, IList keys) { var createdConnection = false; try { createdConnection = CreateConnection(ref database); PowerCalculation[] calculationList = null; if (keys != null && keys.Count > 0) { var commaSeparatedKeys = keys.Select(key => key.ToString()).Aggregate((str1, str2) => str1 + "," + str2); var query = string.Format("select pc.ID, pc.CircuitDescription, pc.VoltageAngleSignalID, pc.VoltageMagSignalID, pc.CurrentAngleSignalID, " + " pc.CurrentMagSignalID, pc.ActivePowerOutputSignalID, pc.ReactivePowerOutputSignalID, pc.ApparentPowerOutputSignalID, pc.Enabled, " + " pc.nodeid, vp.id voltagePhasorID, cp.id as currentPhasorID " + "from powercalculation pc " + " left join measurement vm " + " on pc.voltagemagsignalid=vm.signalid " + " left join measurement cm " + " on pc.currentmagsignalid=cm.signalid " + " left join phasor vp " + " on vm.deviceid=vp.deviceid and vm.phasorsourceindex=vp.sourceindex " + " left join phasor cp " + " on cm.deviceid=cp.deviceid and cm.phasorsourceindex=cp.sourceindex WHERE pc.ID IN ({0})", commaSeparatedKeys); var calculationTable = database.Connection.RetrieveData(database.AdapterType, query, DefaultTimeout); calculationList = new PowerCalculation[calculationTable.Rows.Count]; foreach (DataRow row in calculationTable.Rows) { var id = row.ConvertField("ID"); var voltageAngle = database.Guid(row, "VoltageAngleSignalID"); var voltageMagnitude = database.Guid(row, "VoltageMagSignalID"); var currentAngle = database.Guid(row, "CurrentAngleSignalID"); var currentMagnitude = database.Guid(row, "CurrentMagSignalID"); Guid? activePower = null; if (!row.IsNull("ActivePowerOutputSignalID")) activePower = database.Guid(row, "ActivePowerOutputSignalID"); Guid? reactivePower = null; if (!row.IsNull("ReactivePowerOutputSignalID")) reactivePower = database.Guid(row, "ReactivePowerOutputSignalID"); Guid? apparentPower = null; if (!row.IsNull("ApparentPowerOutputSignalID")) apparentPower = database.Guid(row, "ApparentPowerOutputSignalID"); var currentPhasorID = row.ConvertField("currentPhasorID"); var voltagePhasorID = row.ConvertField("voltagePhasorID"); var phasors = Phasor.Load(database, new List {currentPhasorID, voltagePhasorID}); calculationList[keys.IndexOf(id)] = new PowerCalculation { ID = row.ConvertField("ID"), CircuitDescription = row.Field("CircuitDescription"), Enabled = row.ConvertField("Enabled"), NodeID = database.Guid(row, "NodeID") }; foreach (var phasor in phasors) { if (phasor.ID == currentPhasorID) { calculationList[keys.IndexOf(id)].CurrentPhasor = phasor; } else if (phasor.ID == voltagePhasorID) { calculationList[keys.IndexOf(id)].VoltagePhasor = phasor; } } var mkeys = new List { voltageAngle, voltageMagnitude, currentAngle, currentMagnitude }; if (activePower != null) { mkeys.Add(activePower.Value); } if (reactivePower != null) { mkeys.Add(reactivePower.Value); } if (apparentPower != null) { mkeys.Add(apparentPower.Value); } var measurements = Measurement.LoadFromKeys(database, mkeys); foreach (var measurement in measurements) { if (measurement.SignalID == voltageAngle) { calculationList[keys.IndexOf(id)].VoltagePhasor.AngleMeasurement = measurement; } else if (measurement.SignalID == voltageMagnitude) { calculationList[keys.IndexOf(id)].VoltagePhasor.MagnitudeMeasurement = measurement; } else if (measurement.SignalID == currentAngle) { calculationList[keys.IndexOf(id)].CurrentPhasor.AngleMeasurement = measurement; } else if (measurement.SignalID == currentMagnitude) { calculationList[keys.IndexOf(id)].CurrentPhasor.MagnitudeMeasurement = measurement; } else if (measurement.SignalID == activePower) { calculationList[keys.IndexOf(id)].ActivePowerOutputMeasurement = measurement; } else if (measurement.SignalID == reactivePower) { calculationList[keys.IndexOf(id)].ReactivePowerOutputMeasurement = measurement; } else if (measurement.SignalID == apparentPower) { calculationList[keys.IndexOf(id)].ApparentPowerOutputMeasurement = measurement; } } } } return new ObservableCollection(calculationList ?? new PowerCalculation[0]); } finally { if (createdConnection && database != null) database.Dispose(); } } /// /// Deletes specified record from database. /// /// to connection to database. /// ID of the record to be deleted. /// String, for display use, indicating success. public static string Delete(AdoDataConnection database, int id) { bool createdConnection = false; try { createdConnection = CreateConnection(ref database); // Setup current user context for any delete triggers CommonFunctions.SetCurrentUserContext(database); database.Connection.ExecuteNonQuery(database.ParameterizedQueryString("DELETE FROM PowerCalculation WHERE ID = {0}", "companyID"), DefaultTimeout, id); return "Power Calculation deleted successfully"; } finally { if (createdConnection && database != null) database.Dispose(); } } /// /// Saves information to database. /// /// to connection to database. /// Information about . /// String, for display use, indicating success. public static string Save(AdoDataConnection database, PowerCalculation powerCalculation) { bool createdConnection = false; string query; try { createdConnection = CreateConnection(ref database); if (powerCalculation.ID == 0) { query = "INSERT INTO PowerCalculation (CircuitDescription, VoltageAngleSignalID, VoltageMagSignalID, CurrentAngleSignalID, CurrentMagSignalID, ActivePowerOutputSignalID, ReactivePowerOutputSignalID, ApparentPowerOutputSignalID, Enabled, NodeID) " + "VALUES ({0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9})"; database.ExecuteNonQuery(DefaultTimeout, query, powerCalculation.CircuitDescription, powerCalculation.VoltagePhasor.AngleMeasurement.SignalID, powerCalculation.VoltagePhasor.MagnitudeMeasurement.SignalID, powerCalculation.CurrentPhasor.AngleMeasurement.SignalID, powerCalculation.CurrentPhasor.MagnitudeMeasurement.SignalID, (object)powerCalculation.ActivePowerOutputMeasurement?.SignalID ?? DBNull.Value, (object)powerCalculation.ReactivePowerOutputMeasurement?.SignalID ?? DBNull.Value, (object)powerCalculation.ApparentPowerOutputMeasurement?.SignalID ?? DBNull.Value, powerCalculation.Enabled, database.CurrentNodeID()); } else { query = "UPDATE PowerCalculation SET CircuitDescription = {0}, VoltageAngleSignalID = {1}, VoltageMagSignalID = {2}, CurrentAngleSignalID = {3}, CurrentMagSignalID = {4}, " + "activePowerOutputSignalID = {5}, ReactivePowerOutputSignalID = {6}, ApparentPowerOutputSignalID = {7}, Enabled = {8} WHERE ID = {9}"; database.ExecuteNonQuery(DefaultTimeout, query, powerCalculation.CircuitDescription, database.Guid(powerCalculation.VoltagePhasor.AngleMeasurement.SignalID), powerCalculation.VoltagePhasor.MagnitudeMeasurement.SignalID, powerCalculation.CurrentPhasor.AngleMeasurement.SignalID, powerCalculation.CurrentPhasor.MagnitudeMeasurement.SignalID, (object)powerCalculation.ActivePowerOutputMeasurement?.SignalID ?? DBNull.Value, (object)powerCalculation.ReactivePowerOutputMeasurement?.SignalID ?? DBNull.Value, (object)powerCalculation.ApparentPowerOutputMeasurement?.SignalID ?? DBNull.Value, powerCalculation.Enabled, powerCalculation.ID); } return "Power Calculation information saved successfully"; } finally { if (createdConnection && database != null) database.Dispose(); } } #endregion } }