コード例 #1
0
        private IEnumerable <Disturbance> DetectTransients(VIDataGroup viDataGroup)
        {
            IEnumerable <Disturbance> vaTransients  = DetectTransients(viDataGroup.VA, Phase.AN);
            IEnumerable <Disturbance> vbTransients  = DetectTransients(viDataGroup.VB, Phase.BN);
            IEnumerable <Disturbance> vcTransients  = DetectTransients(viDataGroup.VC, Phase.CN);
            IEnumerable <Disturbance> vabTransients = DetectTransients(viDataGroup.VAB, Phase.AB);
            IEnumerable <Disturbance> vbcTransients = DetectTransients(viDataGroup.VBC, Phase.BC);
            IEnumerable <Disturbance> vcaTransients = DetectTransients(viDataGroup.VCA, Phase.CA);

            List <Disturbance> transientList = vaTransients.Concat(vbTransients).Concat(vcTransients).Concat(vabTransients).Concat(vbcTransients).Concat(vcaTransients).ToList();

            Disturbance worst = null;

            foreach (Disturbance transiet in transientList)
            {
                if ((object)worst == null || transiet.PerUnitMagnitude > worst.PerUnitMagnitude)
                {
                    worst = transiet;
                }

                worst       = worst.Clone();
                worst.Phase = Phase.Worst;
            }

            if (worst != null)
            {
                transientList.Add(worst);
            }

            return(transientList);
        }
コード例 #2
0
        private void FindAllRestrikes(CycleDataResource cycleDataResource)
        {
            for (int i = 0; i < cycleDataResource.DataGroups.Count; i++)
            {
                DataGroup   dataGroup   = cycleDataResource.DataGroups[i];
                VIDataGroup viDataGroup = cycleDataResource.VIDataGroups[i];
                DataSeries  ia          = viDataGroup.IA;
                DataSeries  ib          = viDataGroup.IB;
                DataSeries  ic          = viDataGroup.IC;

                IEnumerable <Restrike> iaRestrikes = FindRestrikes(ia)
                                                     .Select(index => new Restrike(Phase.AN, index));

                IEnumerable <Restrike> ibRestrikes = FindRestrikes(ib)
                                                     .Select(index => new Restrike(Phase.BN, index));

                IEnumerable <Restrike> icRestrikes = FindRestrikes(ic)
                                                     .Select(index => new Restrike(Phase.CN, index));

                List <Restrike> allRestrikes = Enumerable.Empty <Restrike>()
                                               .Concat(iaRestrikes)
                                               .Concat(ibRestrikes)
                                               .Concat(icRestrikes)
                                               .ToList();

                if (allRestrikes.Any())
                {
                    RestrikeLookup.Add(dataGroup, allRestrikes);
                }
            }
        }
コード例 #3
0
        public override void Initialize(MeterDataSet meterDataSet)
        {
            DataGroupsResource dataGroupsResource = meterDataSet.GetResource <DataGroupsResource>();
            CycleDataResource  cycleDataResource  = meterDataSet.GetResource <CycleDataResource>();
            FaultDataResource  faultDataResource  = meterDataSet.GetResource <FaultDataResource>();

            for (int i = 0; i < cycleDataResource.DataGroups.Count; i++)
            {
                DataGroup   dataGroup   = cycleDataResource.DataGroups[i];
                VIDataGroup viDataGroup = cycleDataResource.VIDataGroups[i];
                FaultGroup  faultGroup;

                if (!faultDataResource.FaultLookup.TryGetValue(dataGroup, out faultGroup))
                {
                    faultGroup = null;
                }

                m_classifications.Add(dataGroup, Classify(meterDataSet, dataGroup, viDataGroup, faultGroup));
            }

            foreach (DataGroup dataGroup in dataGroupsResource.DataGroups)
            {
                if (dataGroup.DataSeries.Count > 0)
                {
                    continue;
                }

                m_classifications.Add(dataGroup, Classify(meterDataSet, dataGroup));
            }
        }
コード例 #4
0
        public ActionResult Get(int eventID, int pixels)
        {
            using (AdoDataConnection connection = new AdoDataConnection(m_configuration["OpenXDA:ConnectionString"], m_configuration["OpenXDA:DataProviderString"]))
            {
                Event evt = new TableOperations <Event>(connection).QueryRecordWhere("ID = {0}", eventID);
                if (evt == null)
                {
                    return(BadRequest("Must provide a valid EventID"));
                }
                Meter meter = new TableOperations <Meter>(connection).QueryRecordWhere("ID = {0}", evt.MeterID);
                meter.ConnectionFactory = () => new AdoDataConnection(m_configuration["OpenXDA:ConnectionString"], m_configuration["OpenXDA:DataProviderString"]);

                Dictionary <string, IEnumerable <double[]> > returnData = new Dictionary <string, IEnumerable <double[]> >();
                DataGroupHelper dataGroupHelper = new DataGroupHelper(m_configuration, m_memoryCache);
                DataGroup       dataGroup       = dataGroupHelper.QueryDataGroup(eventID, meter);;
                VIDataGroup     vIDataGroup     = new VIDataGroup(dataGroup);
                double          systemFrequency = connection.ExecuteScalar <double?>("SELECT Value FROM Setting WHERE Name = 'SystemFrequency'") ?? 60.0;


                Dictionary <string, List <double[]> > returnList = new Dictionary <string, List <double[]> >();

                returnList.Add("VA", GenerateFrequency(systemFrequency, vIDataGroup.VA));
                returnList.Add("VB", GenerateFrequency(systemFrequency, vIDataGroup.VB));
                returnList.Add("VC", GenerateFrequency(systemFrequency, vIDataGroup.VC));
                returnList.Add("Average", GenerateFrequency(systemFrequency, vIDataGroup.VC));

                return(Ok(returnList));
            }
        }
コード例 #5
0
        public override void Initialize(MeterDataSet meterDataSet)
        {
            MeterInfoDataContext meterInfo          = m_dbAdapterContainer.GetAdapter <MeterInfoDataContext>();
            DataGroupsResource   dataGroupsResource = meterDataSet.GetResource <DataGroupsResource>();
            Stopwatch            stopwatch          = new Stopwatch();

            m_dataGroups = dataGroupsResource.DataGroups
                           .Where(dataGroup => dataGroup.Classification == DataClassification.Event)
                           .Where(dataGroup => dataGroup.SamplesPerSecond / m_systemFrequency >= 3.999D)
                           .ToList();

            Log.Info(string.Format("Found data for {0} events.", m_dataGroups.Count));

            m_viDataGroups = m_dataGroups
                             .Select(dataGroup =>
            {
                VIDataGroup viDataGroup = new VIDataGroup(dataGroup);
                dataGroup.Add(viDataGroup.CalculateMissingCurrentChannel(meterInfo));
                return(viDataGroup);
            })
                             .ToList();

            Log.Info(string.Format("Calculating cycle data for all {0} events.", m_dataGroups.Count));

            stopwatch.Start();

            m_viCycleDataGroups = m_viDataGroups
                                  .Select(viDataGroup => Transform.ToVICycleDataGroup(viDataGroup, m_systemFrequency))
                                  .ToList();

            Log.Debug(string.Format("Cycle data calculated in {0}.", stopwatch.Elapsed));
        }
コード例 #6
0
ファイル: FaultDataResource.cs プロジェクト: daozh/openXDA
        private List <Fault> DetectFaults(VIDataGroup viDataGroup, VICycleDataGroup viCycleDataGroup)
        {
            List <Fault> iaFaults = DetectFaults(viDataGroup.IA, viCycleDataGroup.IA.RMS);
            List <Fault> ibFaults = DetectFaults(viDataGroup.IB, viCycleDataGroup.IB.RMS);
            List <Fault> icFaults = DetectFaults(viDataGroup.IC, viCycleDataGroup.IC.RMS);

            return(Merge(iaFaults, ibFaults, icFaults));
        }
コード例 #7
0
        public static DataGroup ToDataGroup(Meter meter, List <byte[]> data)
        {
            DataGroup dataGroup = new DataGroup();

            dataGroup.FromData(meter, data);
            VIDataGroup vIDataGroup = new VIDataGroup(dataGroup);

            return(vIDataGroup.ToDataGroup());
        }
コード例 #8
0
        public override void Execute(MeterDataSet meterDataSet)
        {
            // The following logic should only apply to NEXUS meters, not DFRs
            if (!meterDataSet.Meter.Model.StartsWith("NEXUS"))
            {
                return;
            }

            CycleDataResource           cycleDataResource           = meterDataSet.GetResource <CycleDataResource>();
            EventClassificationResource eventClassificationResource = meterDataSet.GetResource <EventClassificationResource>();

            for (int i = 0; i < cycleDataResource.DataGroups.Count; i++)
            {
                DataGroup   dataGroup            = cycleDataResource.DataGroups[i];
                VIDataGroup viDataGroup          = cycleDataResource.VIDataGroups[i];
                double      llPeakNominalVoltage = dataGroup.Asset.VoltageKV * 1000.0D * Math.Sqrt(2.0D);
                double      lnPeakNominalVoltage = llPeakNominalVoltage / Math.Sqrt(3.0D);

                // Nominal multipliers used for first derivative, based on:
                //   d/dt(A*sin(w*t)) = A*w*cos(w*t)
                double omega    = 2.0D * Math.PI * SystemFrequency;
                double llFactor = 1.0D / (llPeakNominalVoltage * omega);
                double lnFactor = 1.0D / (lnPeakNominalVoltage * omega);

                DataSeries[] puVoltages =
                {
                    viDataGroup.VA?.Multiply(lnFactor),
                    viDataGroup.VB?.Multiply(lnFactor),
                    viDataGroup.VC?.Multiply(lnFactor),
                    viDataGroup.VAB?.Multiply(llFactor),
                    viDataGroup.VBC?.Multiply(llFactor),
                    viDataGroup.VCA?.Multiply(llFactor)
                };

                bool invalidVoltage = false;

                foreach (DataSeries voltage in puVoltages)
                {
                    if (voltage == null)
                    {
                        continue;
                    }

                    List <DataPoint> dataPoints = voltage.DataPoints;

                    invalidVoltage |= dataPoints
                                      .Zip(dataPoints.Skip(1), (p1, p2) => (p2.Value - p1.Value) / (p2.Time - p1.Time).TotalSeconds)
                                      .Any(slope => Math.Abs(slope) > Settings.MaxVoltageSlope);
                }

                if (invalidVoltage)
                {
                    eventClassificationResource.Classifications[dataGroup] = EventClassification.MeterDataQuality;
                }
            }
        }
コード例 #9
0
 private void ProcessSnapshots(double systemFrequency, VIDataGroup viDataGroup)
 {
     ProcessSnapshots(systemFrequency, viDataGroup.VA, Phase.AN);
     ProcessSnapshots(systemFrequency, viDataGroup.IA, Phase.AN);
     ProcessSnapshots(systemFrequency, viDataGroup.VB, Phase.BN);
     ProcessSnapshots(systemFrequency, viDataGroup.IB, Phase.BN);
     ProcessSnapshots(systemFrequency, viDataGroup.VC, Phase.CN);
     ProcessSnapshots(systemFrequency, viDataGroup.IC, Phase.CN);
     ProcessSnapshots(systemFrequency, viDataGroup.VAB, Phase.AB);
     ProcessSnapshots(systemFrequency, viDataGroup.VBC, Phase.BC);
     ProcessSnapshots(systemFrequency, viDataGroup.VCA, Phase.CA);
 }
コード例 #10
0
        private void IdentifyBreakerOperations(DataGroup dataGroup, VIDataGroup viDataGroup, VICycleDataGroup viCycleDataGroup)
        {
            List <string> breakerNumbers = dataGroup.DataSeries
                                           .SelectMany(dataSeries => dataSeries.SeriesInfo.Channel.BreakerChannels)
                                           .Select(breakerChannel => breakerChannel.BreakerNumber)
                                           .Distinct()
                                           .ToList();

            // If the breaker currents are defined for breaker-and-a-half or ring bus configurations,
            // skip this data group so that timing is only applied to the breaker currents
            if (breakerNumbers.Count > 1 && breakerNumbers.Any(num => m_breakerCurrents.Contains(num)))
            {
                return;
            }

            foreach (string breakerNumber in breakerNumbers)
            {
                double breakerSpeed = ConvertBreakerSpeed(m_dbAdapterContainer.Connection.ExecuteScalar("SELECT BreakerSpeed FROM MaximoBreaker WHERE BreakerNum = @breakerNumber", breakerNumber));

                List <DataSeries> breakerDigitals = dataGroup.DataSeries
                                                    .Where(dataSeries => dataSeries.SeriesInfo.Channel.MeasurementType.Name == "Digital")
                                                    .Where(dataSeries => dataSeries.SeriesInfo.Channel.BreakerChannels.Any(breakerChannel => breakerChannel.BreakerNumber == breakerNumber))
                                                    .ToList();

                List <DataSeries> tripCoilEnergizedChannels = breakerDigitals
                                                              .Where(dataSeries => dataSeries.SeriesInfo.Channel.MeasurementCharacteristic.Name == "TCE")
                                                              .ToList();

                DataSeries breakerStatusChannel = breakerDigitals
                                                  .FirstOrDefault(dataSeries => dataSeries.SeriesInfo.Channel.MeasurementCharacteristic.Name == "BreakerStatus");

                List <XValue> breakerOperations = Range <XValue> .MergeAllOverlapping(tripCoilEnergizedChannels.SelectMany(FindTCERanges))
                                                  .Select(range => range.Start)
                                                  .ToList();

                foreach (XValue breakerOperation in breakerOperations)
                {
                    BreakerTiming breakerTiming = new BreakerTiming(breakerOperation, breakerStatusChannel, m_systemFrequency, breakerSpeed);

                    PhaseTiming aPhaseTiming = new PhaseTiming(viDataGroup.IA, viCycleDataGroup.IA, breakerTiming, m_systemFrequency, m_breakerSettings.OpenBreakerThreshold);
                    PhaseTiming bPhaseTiming = new PhaseTiming(viDataGroup.IB, viCycleDataGroup.IB, breakerTiming, m_systemFrequency, m_breakerSettings.OpenBreakerThreshold);
                    PhaseTiming cPhaseTiming = new PhaseTiming(viDataGroup.IC, viCycleDataGroup.IC, breakerTiming, m_systemFrequency, m_breakerSettings.OpenBreakerThreshold);

                    BreakerOperationRow breakerOperationRow = GetBreakerOperationRow(breakerNumber, breakerTiming, aPhaseTiming, bPhaseTiming, cPhaseTiming);

                    m_breakerOperations.Add(Tuple.Create(CreateEventKey(dataGroup), breakerOperationRow));
                }
            }
        }
コード例 #11
0
        public IHttpActionResult GetEventWaveformData(EventDataJSON json)
        {
            if (json != null && json.EventID != null)
            {
                try {
                    int eventID = int.Parse(json.EventID);
                    using (AdoDataConnection connection = new AdoDataConnection("systemSettings"))
                    {
                        Event evt   = new TableOperations <Event>(connection).QueryRecordWhere("ID = {0}", eventID);
                        Meter meter = new TableOperations <Meter>(connection).QueryRecordWhere("ID = {0}", evt.MeterID);
                        meter.ConnectionFactory = () => new AdoDataConnection("systemSettings");
                        List <byte[]> frequencyDomainData = ChannelData.DataFromEvent(eventID, connection);

                        DataGroup dataGroup = new DataGroup();
                        dataGroup.FromData(meter, frequencyDomainData);
                        VIDataGroup vIDataGroup = new VIDataGroup(dataGroup);
                        dataGroup = vIDataGroup.ToDataGroup();
                        DataTable table = new DataTable();

                        table.Columns.Add("Timestamp", typeof(DateTime));
                        foreach (var series in dataGroup.DataSeries)
                        {
                            table.Columns.Add(series.SeriesInfo.Channel.MeasurementType.Name + "(" + series.SeriesInfo.Channel.Phase.Name + ")", typeof(double));
                        }

                        for (int i = 0; i < dataGroup.DataSeries[0].DataPoints.Count(); ++i)
                        {
                            DataRow row = table.NewRow();
                            row["Timestamp"] = dataGroup.DataSeries[0].DataPoints[i].Time;
                            for (int j = 1; j < table.Columns.Count; ++j)
                            {
                                row[table.Columns[j].ColumnName] = dataGroup.DataSeries[j - 1].DataPoints[i].Value;
                            }

                            table.Rows.Add(row);
                        }
                        return(Ok(table));
                    }
                }
                catch (Exception ex)
                {
                    return(InternalServerError(ex));
                }
            }
            else
            {
                return(BadRequest("Please provide event id"));
            }
        }
コード例 #12
0
        public override void Initialize(MeterDataSet meterDataSet)
        {
            DataGroupsResource dataGroupsResource = meterDataSet.GetResource <DataGroupsResource>();
            VIDataGroup        viDataGroup;

            m_dataGroups        = new List <DataGroup>();
            m_viDataGroups      = new List <VIDataGroup>();
            m_viCycleDataGroups = new List <VICycleDataGroup>();

            Log.Info("Identifying events and calculating cycle data...");

            foreach (DataGroup dataGroup in dataGroupsResource.DataGroups)
            {
                double samplesPerCycle;

                if (dataGroup.Classification != DataClassification.Event)
                {
                    continue;
                }

                samplesPerCycle = Math.Round(dataGroup.SamplesPerSecond / m_systemFrequency);

                if (dataGroup.Samples < samplesPerCycle)
                {
                    continue;
                }

                viDataGroup = new VIDataGroup(dataGroup);

                if (viDataGroup.DefinedVoltages != 3 || viDataGroup.DefinedCurrents < 3)
                {
                    continue;
                }

                dataGroup.Add(viDataGroup.CalculateMissingCurrentChannel());

                m_dataGroups.Add(dataGroup);
                m_viDataGroups.Add(viDataGroup);
                m_viCycleDataGroups.Add(ToVICycleDataGroup(dataGroup, m_systemFrequency));
            }

            Log.Info($"Cycle data calculated for {m_dataGroups.Count} events.");
        }
コード例 #13
0
        public override void Execute(MeterDataSet meterDataSet)
        {
            CycleDataResource cycleDataResource = meterDataSet.GetResource <CycleDataResource>();

            using (AdoDataConnection connection = meterDataSet.CreateDbConnection())
            {
                TableOperations <BreakerChannel> breakerChannelTable = new TableOperations <BreakerChannel>(connection);

                List <int> channelsIDs = cycleDataResource.DataGroups
                                         .Where(dataGroup => dataGroup.Asset.AssetTypeID == (int)AssetType.Breaker)
                                         .SelectMany(dataGroup => dataGroup.DataSeries)
                                         .Select(dataSeries => dataSeries.SeriesInfo.ChannelID)
                                         .Distinct()
                                         .ToList();

                // Look up the breaker numbers for the lines
                // that represent groupings of breaker current data
                m_breakerCurrents = new HashSet <string>();
                if (channelsIDs.Count > 0)
                {
                    m_breakerCurrents.UnionWith(breakerChannelTable
                                                .QueryRecordsWhere($"ChannelID IN ({string.Join(",", channelsIDs)})")
                                                .Select(breakerChannel => breakerChannel.BreakerNumber));
                }


                FileGroup fileGroup = meterDataSet.FileGroup;

                for (int i = 0; i < cycleDataResource.DataGroups.Count; i++)
                {
                    DataGroup        dataGroup        = cycleDataResource.DataGroups[i];
                    VIDataGroup      viDataGroup      = cycleDataResource.VIDataGroups[i];
                    VICycleDataGroup viCycleDataGroup = cycleDataResource.VICycleDataGroups[i];
                    IdentifyBreakerOperations(connection, fileGroup, dataGroup, viDataGroup, viCycleDataGroup);
                }
            }
        }
コード例 #14
0
        private EventClassification Classify(MeterDataSet meterDataSet, DataGroup dataGroup, VIDataGroup viDataGroup = null, FaultGroup faultGroup = null)
        {
            SnapshotDataResource snapshotDataResource = meterDataSet.GetResource <SnapshotDataResource>();

            if (snapshotDataResource.IsSnapshot)
            {
                return(EventClassification.Snapshot);
            }

            if ((object)viDataGroup != null)
            {
                if (viDataGroup.DefinedNeutralVoltages == 0 && viDataGroup.DefinedLineVoltages == 0 && HasBreakerChannels(dataGroup))
                {
                    return(EventClassification.Breaker);
                }
            }

            if ((object)faultGroup != null)
            {
                if (faultGroup.FaultDetectionLogicResult ?? false)
                {
                    return(EventClassification.Fault);
                }

                if (!faultGroup.FaultDetectionLogicResult.HasValue && m_faultLocationSettings.UseDefaultFaultDetectionLogic)
                {
                    if (faultGroup.FaultValidationLogicResult && faultGroup.Faults.Any(fault => !fault.IsSuppressed && !fault.IsReclose))
                    {
                        return(EventClassification.Fault);
                    }

                    if (faultGroup.FaultValidationLogicResult && faultGroup.Faults.Any(fault => !fault.IsSuppressed && fault.IsReclose))
                    {
                        return(EventClassification.RecloseIntoFault);
                    }
                }
            }

            BreakerDataResource breakerOpenResource = meterDataSet.GetResource <BreakerDataResource>();

            if (breakerOpenResource.TripLookup.TryGetValue(dataGroup, out List <BreakerDataResource.Trip> trips))
            {
                return(EventClassification.BreakerOpen);
            }

            InterruptionDataResource interruptionDataResource = meterDataSet.GetResource <InterruptionDataResource>();
            SagDataResource          sagDataResource          = meterDataSet.GetResource <SagDataResource>();
            SwellDataResource        swellDataResource        = meterDataSet.GetResource <SwellDataResource>();
            TransientDataResource    transientDataResource    = meterDataSet.GetResource <TransientDataResource>();

            if (interruptionDataResource.Interruptions.ContainsKey(dataGroup))
            {
                return(EventClassification.Interruption);
            }

            if (sagDataResource.Sags.ContainsKey(dataGroup))
            {
                return(EventClassification.Sag);
            }

            if (swellDataResource.Swells.ContainsKey(dataGroup))
            {
                return(EventClassification.Swell);
            }

            if (transientDataResource.Transients.ContainsKey(dataGroup))
            {
                return(EventClassification.Transient);
            }

            return(EventClassification.Other);
        }
コード例 #15
0
        private EventClassification Classify(MeterDataSet meterDataSet, DataGroup dataGroup, VIDataGroup viDataGroup, VICycleDataGroup viCycleDataGroup, FaultGroup faultGroup)
        {
            if (viDataGroup.DefinedNeutralVoltages == 0 && viDataGroup.DefinedLineVoltages == 0 && dataGroup.DataSeries.SelectMany(series => series.SeriesInfo.Channel.BreakerChannels).Any())
            {
                return(EventClassification.Breaker);
            }

            if ((object)faultGroup != null && (faultGroup.FaultDetectionLogicResult ?? faultGroup.FaultValidationLogicResult))
            {
                return(EventClassification.Fault);
            }

            DataSeries[] rms =
            {
                viCycleDataGroup.VA?.RMS,
                viCycleDataGroup.VB?.RMS,
                viCycleDataGroup.VC?.RMS,
                viCycleDataGroup.VAB?.RMS,
                viCycleDataGroup.VBC?.RMS,
                viCycleDataGroup.VCA?.RMS
            };

            List <DataSeries> perUnitRMS = rms
                                           .Where(dataSeries => (object)dataSeries != null)
                                           .Where(dataSeries => GetPerUnitValue(dataSeries) != 0.0D)
                                           .Select(dataSeries => dataSeries.Multiply(1.0D / GetPerUnitValue(dataSeries)))
                                           .ToList();

            if (HasInterruption(perUnitRMS))
            {
                return(EventClassification.Interruption);
            }

            if (HasSag(perUnitRMS))
            {
                return(EventClassification.Sag);
            }

            if (HasSwell(perUnitRMS))
            {
                return(EventClassification.Swell);
            }

            return(EventClassification.Other);
        }
コード例 #16
0
        public void ExportToPQDS(Stream returnStream, NameValueCollection requestParameters)
        {
            int eventID = int.Parse(requestParameters["eventID"]);

            using (AdoDataConnection connection = new AdoDataConnection("dbOpenXDA"))
            {
                Event evt   = (new TableOperations <Event>(connection)).QueryRecordWhere("ID = {0}", eventID);
                Meter meter = new TableOperations <Meter>(connection).QueryRecordWhere("ID = {0}", evt.MeterID);
                meter.ConnectionFactory = () => new AdoDataConnection("dbOpenXDA");



                // only get Single Voltage and Single Current Data for This....
                List <PQDS.DataSeries>  data     = new List <PQDS.DataSeries>();
                List <PQDS.MetaDataTag> metaData = new List <PQDS.MetaDataTag>();

                VIDataGroup dataGroup = new VIDataGroup(OpenSEEController.QueryDataGroup(evt.ID, meter));

                if (dataGroup.VA != null)
                {
                    data.Add(PQDSSeries(dataGroup.VA, "va"));
                }
                if (dataGroup.VB != null)
                {
                    data.Add(PQDSSeries(dataGroup.VB, "vb"));
                }
                if (dataGroup.VC != null)
                {
                    data.Add(PQDSSeries(dataGroup.VC, "vc"));
                }

                if (dataGroup.IA != null)
                {
                    data.Add(PQDSSeries(dataGroup.IA, "ia"));
                }
                if (dataGroup.IB != null)
                {
                    data.Add(PQDSSeries(dataGroup.IB, "ib"));
                }
                if (dataGroup.IC != null)
                {
                    data.Add(PQDSSeries(dataGroup.IC, "ic"));
                }
                if (dataGroup.IR != null)
                {
                    data.Add(PQDSSeries(dataGroup.IR, "in"));
                }


                if (data.Count() == 0)
                {
                    return;
                }

                // Add MetaData Information
                metaData = PQDSMetaData(evt, meter);

                PQDS.PQDSFile file = new PQDS.PQDSFile(metaData, data, evt.StartTime);

                using (StreamWriter writer = new StreamWriter(returnStream))
                {
                    file.WriteToStream(writer);
                }
            }
        }
コード例 #17
0
 private double?CalcVoltagePeak(VIDataGroup viDataGroup) => Enumerable.Empty <DataSeries[]>()
 .Concat(new[] { new[] { viDataGroup.VA, viDataGroup.VB, viDataGroup.VC } })
 .Concat(new[] { new[] { viDataGroup.VAB, viDataGroup.VBC, viDataGroup.VCA } })
 .Where(voltageGrouping => voltageGrouping.Any(waveform => waveform != null))
 .Select(CalcPeak)
 .FirstOrDefault();
コード例 #18
0
        private BreakerRestrike ProcessRestrike(BreakerDataResource.Restrike restrike, Phase phase, Event evt, VIDataGroup dataGroup)
        {
            DataSeries voltage = (phase.Name == "AN"? dataGroup.VA: (phase.Name == "BN" ? dataGroup.VB : dataGroup.VC));
            DataSeries current = (phase.Name == "AN" ? dataGroup.IA : (phase.Name == "BN" ? dataGroup.IB : dataGroup.IC));

            BreakerRestrike result = new BreakerRestrike();

            result.EventID = evt.ID;
            result.PhaseID = phase.ID;

            result.InitialExtinguishSample  = restrike.initialExtinction;
            result.InitialExtinguishTime    = current[restrike.initialExtinction].Time;
            result.InitialExtinguishVoltage = voltage[restrike.initialExtinction].Value;

            result.RestrikeSample  = restrike.restrike;
            result.RestrikeTime    = current[restrike.restrike].Time;
            result.RestrikeVoltage = voltage[restrike.restrike].Value;

            result.RestrikeCurrentPeak = current[restrike.currentMaximum].Value;
            result.RestrikeVoltageDip  = voltage[restrike.maximumVoltageSurpression].Value;

            result.TransientPeakSample = restrike.transientOverVoltage;


            result.TransientPeakTime           = current[restrike.transientOverVoltage].Time;
            result.TransientPeakVoltage        = voltage[restrike.transientOverVoltage].Value;
            result.PerUnitTransientPeakVoltage = voltage[restrike.transientOverVoltage].Value;

            result.FinalExtinguishSample  = restrike.finalExtinction;
            result.FinalExtinguishTime    = current[restrike.finalExtinction].Time;
            result.FinalExtinguishVoltage = voltage[restrike.finalExtinction].Value;
            result.I2t = 0.0;

            return(result);
        }
コード例 #19
0
        private EventClassification Classify(MeterDataSet meterDataSet, DataGroup dataGroup, VIDataGroup viDataGroup = null, FaultGroup faultGroup = null)
        {
            if ((object)viDataGroup != null)
            {
                if (viDataGroup.DefinedNeutralVoltages == 0 && viDataGroup.DefinedLineVoltages == 0 && HasBreakerChannels(dataGroup))
                {
                    return(EventClassification.Breaker);
                }
            }

            if ((object)faultGroup != null)
            {
                if (faultGroup.FaultDetectionLogicResult ?? false)
                {
                    return(EventClassification.Fault);
                }

                if (faultGroup.FaultValidationLogicResult && faultGroup.Faults.Any(fault => !fault.IsSuppressed && !fault.IsReclose))
                {
                    return(EventClassification.Fault);
                }

                if (faultGroup.FaultValidationLogicResult && faultGroup.Faults.Any(fault => !fault.IsSuppressed && fault.IsReclose))
                {
                    return(EventClassification.RecloseIntoFault);
                }
            }

            InterruptionDataResource interruptionDataResource = meterDataSet.GetResource <InterruptionDataResource>();
            SagDataResource          sagDataResource          = meterDataSet.GetResource <SagDataResource>();
            SwellDataResource        swellDataResource        = meterDataSet.GetResource <SwellDataResource>();

            if (interruptionDataResource.Interruptions.ContainsKey(dataGroup))
            {
                return(EventClassification.Interruption);
            }

            if (sagDataResource.Sags.ContainsKey(dataGroup))
            {
                return(EventClassification.Sag);
            }

            if (swellDataResource.Swells.ContainsKey(dataGroup))
            {
                return(EventClassification.Swell);
            }

            return(EventClassification.Other);
        }
コード例 #20
0
        public override void Execute(MeterDataSet meterDataSet)
        {
            Meter         meter;
            List <Series> seriesList;
            Dictionary <SeriesKey, Series> seriesLookup;
            DataSeries dataSeries;
            Series     seriesInfo;

            Log.Info("Executing operation to locate meter in database...");

            // Search the database for a meter definition that matches the parsed meter
            meter = m_meterInfo.Meters.SingleOrDefault(m => m.AssetKey == meterDataSet.Meter.AssetKey);

            if ((object)meter != null)
            {
                Log.Info(string.Format("Found meter {0} in database.", meter.Name));

                // Get the list of series associated with the meter in the database
                seriesList = m_meterInfo.Series
                             .Where(series => series.Channel.MeterID == meter.ID)
                             .ToList();

                // Match the parsed series with the ones associated with the meter in the database
                seriesLookup = seriesList
                               .Where(series => string.IsNullOrEmpty(series.SourceIndexes))
                               .ToDictionary(GetSeriesKey);

                foreach (DataSeries series in meterDataSet.DataSeries)
                {
                    if ((object)series.SeriesInfo == null)
                    {
                        continue;
                    }

                    if (seriesLookup.TryGetValue(GetSeriesKey(series.SeriesInfo), out seriesInfo))
                    {
                        series.SeriesInfo = seriesInfo;
                    }
                }

                // Create data series for series which
                // are combinations of the parsed series
                foreach (Series series in seriesList.Where(series => !string.IsNullOrEmpty(series.SourceIndexes)))
                {
                    AddCalculatedDataSeries(meterDataSet, series);
                }

                // There may be some placeholder DataSeries objects with no data so that indexes
                // would be correct for calculating data series--now that we are finished
                // calculating data series, these need to be removed
                for (int i = meterDataSet.DataSeries.Count - 1; i >= 0; i--)
                {
                    if ((object)meterDataSet.DataSeries[i].SeriesInfo == null)
                    {
                        meterDataSet.DataSeries.RemoveAt(i);
                    }
                }

                // There may be some placeholder DataSeries objects with no data so that indexes
                // would be correct for calculating data series--now that we are finished
                // calculating data series, these need to be removed
                for (int i = meterDataSet.Digitals.Count - 1; i >= 0; i--)
                {
                    if ((object)meterDataSet.Digitals[i].SeriesInfo == null)
                    {
                        meterDataSet.Digitals.RemoveAt(i);
                    }
                }

                // Replace the parsed meter with
                // the one from the database
                meterDataSet.Meter = meter;
            }
            else
            {
                Log.Info(string.Format("No existing meter found matching meter with name {0}.", meterDataSet.Meter.Name));

                // If configuration cannot be modified and existing configuration cannot be found for this meter,
                // throw an exception to indicate the operation could not be executed
                throw new InvalidOperationException("Cannot process meter - configuration does not exist");
            }

            if (meterDataSet.FilePath.EndsWith(".pqd", StringComparison.OrdinalIgnoreCase))
            {
                // Add channels that are not already defined in the
                // configuration by assuming the meter monitors only one line
                AddUndefinedChannels(meterDataSet);
                FixUpdatedChannelInfo(meterDataSet);
            }
            else
            {
                // Remove data series that were not defined in the configuration
                // since configuration information cannot be added for it
                RemoveUndefinedDataSeries(meterDataSet);
            }

            foreach (DataGroup dataGroup in meterDataSet.GetResource <DataGroupsResource>().DataGroups)
            {
                if (dataGroup.Classification != DataClassification.Event)
                {
                    continue;
                }

                // Add missing current series based on IR = IA + IB + IC
                dataSeries = VIDataGroup.AddMissingCurrentSeries(m_meterInfo, meterDataSet.Meter, dataGroup);

                if ((object)dataSeries != null)
                {
                    meterDataSet.DataSeries.Add(dataSeries);
                }
            }
        }
コード例 #21
0
        public override void Execute(MeterDataSet meterDataSet)
        {
            CycleDataResource cycleDataResource = meterDataSet.GetResource <CycleDataResource>();
            FaultDataResource faultDataResource = meterDataSet.GetResource <FaultDataResource>();

            using (AdoDataConnection connection = meterDataSet.CreateDbConnection())
            {
                object ToDateTime2(DateTime dateTime)
                {
                    using (IDbCommand command = connection.Connection.CreateCommand())
                    {
                        IDbDataParameter parameter = command.CreateParameter();
                        parameter.DbType = DbType.DateTime2;
                        parameter.Value  = dateTime;
                        return(parameter);
                    }
                }

                TableOperations <Event>     eventTable     = new TableOperations <Event>(connection);
                TableOperations <EventStat> eventStatTable = new TableOperations <EventStat>(connection);

                for (int i = 0; i < cycleDataResource.DataGroups.Count; i++)
                {
                    const string Filter =
                        "FileGroupID = {0} AND " +
                        "AssetID = {1} AND " +
                        "StartTime = {2} AND " +
                        "EndTime = {3}";

                    DataGroup        dataGroup        = cycleDataResource.DataGroups[i];
                    VIDataGroup      viDataGroup      = cycleDataResource.VIDataGroups[i];
                    VICycleDataGroup viCycleDataGroup = cycleDataResource.VICycleDataGroups[i];
                    int    fileGroupID = meterDataSet.FileGroup.ID;
                    int    assetID     = dataGroup.Asset.ID;
                    object startTime   = ToDateTime2(dataGroup.StartTime);
                    object endTime     = ToDateTime2(dataGroup.EndTime);

                    Event evt = eventTable.QueryRecordWhere(Filter, fileGroupID, assetID, startTime, endTime);

                    if (evt == null)
                    {
                        continue;
                    }

                    double?vPeak  = CalcVoltagePeak(viDataGroup);
                    double?vaMax  = CalcMax(viCycleDataGroup.VA?.RMS);
                    double?vbMax  = CalcMax(viCycleDataGroup.VB?.RMS);
                    double?vcMax  = CalcMax(viCycleDataGroup.VC?.RMS);
                    double?vabMax = CalcMax(viCycleDataGroup.VAB?.RMS);
                    double?vbcMax = CalcMax(viCycleDataGroup.VBC?.RMS);
                    double?vcaMax = CalcMax(viCycleDataGroup.VCA?.RMS);
                    double?vaMin  = CalcMin(viCycleDataGroup.VA?.RMS);
                    double?vbMin  = CalcMin(viCycleDataGroup.VB?.RMS);
                    double?vcMin  = CalcMin(viCycleDataGroup.VC?.RMS);
                    double?vabMin = CalcMin(viCycleDataGroup.VAB?.RMS);
                    double?vbcMin = CalcMin(viCycleDataGroup.VBC?.RMS);
                    double?vcaMin = CalcMin(viCycleDataGroup.VCA?.RMS);

                    double?iPeak = CalcPeak(new[] { viDataGroup.IA, viDataGroup.IB, viDataGroup.IC });
                    double?iaMax = CalcMax(viCycleDataGroup.IA?.RMS);
                    double?ibMax = CalcMax(viCycleDataGroup.IB?.RMS);
                    double?icMax = CalcMax(viCycleDataGroup.IC?.RMS);

                    double?ia2t = null;
                    double?ib2t = null;
                    double?ic2t = null;

                    double?initialMW = CalcMW(viCycleDataGroup, true);
                    double?finalMW   = CalcMW(viCycleDataGroup, false);

                    if (faultDataResource.FaultLookup.TryGetValue(dataGroup, out DataAnalysis.FaultGroup faultGroup))
                    {
                        ia2t = CalcI2t(faultGroup, viDataGroup.IA);
                        ib2t = CalcI2t(faultGroup, viDataGroup.IB);
                        ic2t = CalcI2t(faultGroup, viDataGroup.IC);
                    }

                    int?pqviewID = null;
                    if (meterDataSet.FilePath.Contains("\\pqview4\\events\\"))
                    {
                        Regex  pattern = new Regex(@"^\\pqview4\\events\\PQView4 \d+\\\d+T\d+-(?<PQViewID>\d+).pqd$");
                        Match  match   = pattern.Match(meterDataSet.FilePath);
                        string str     = match.Groups["PQViewID"].Value;
                        if (str != null)
                        {
                            pqviewID = int.Parse(str);
                        }
                    }

                    eventStatTable.AddNewRecord(new EventStat()
                    {
                        EventID   = evt.ID,
                        VPeak     = vPeak,
                        VAMax     = vaMax,
                        VBMax     = vbMax,
                        VCMax     = vcMax,
                        VABMax    = vabMax,
                        VBCMax    = vbcMax,
                        VCAMax    = vcaMax,
                        VAMin     = vaMin,
                        VBMin     = vbMin,
                        VCMin     = vcMin,
                        VABMin    = vabMin,
                        VBCMin    = vbcMin,
                        VCAMin    = vcaMin,
                        IPeak     = iPeak,
                        IAMax     = iaMax,
                        IBMax     = ibMax,
                        ICMax     = icMax,
                        IA2t      = ia2t,
                        IB2t      = ib2t,
                        IC2t      = ic2t,
                        InitialMW = initialMW,
                        FinalMW   = finalMW,
                        PQViewID  = pqviewID
                    });
                }
            }
        }
コード例 #22
0
        private void IdentifyBreakerOperations(AdoDataConnection connection, FileGroup fileGroup, DataGroup dataGroup, VIDataGroup viDataGroup, VICycleDataGroup viCycleDataGroup)
        {
            TableOperations <Event>            eventTable            = new TableOperations <Event>(connection);
            TableOperations <BreakerChannel>   breakerChannelTable   = new TableOperations <BreakerChannel>(connection);
            TableOperations <BreakerOperation> breakerOperationTable = new TableOperations <BreakerOperation>(connection);

            List <int> channelIDs = dataGroup.DataSeries
                                    .Select(dataSeries => dataSeries.SeriesInfo.ChannelID)
                                    .Distinct()
                                    .ToList();

            if (channelIDs.Count == 0)
            {
                return;
            }

            List <string> breakerNumbers = breakerChannelTable
                                           .QueryRecordsWhere($"ChannelID IN ({string.Join(",", channelIDs)})")
                                           .Select(breakerChannel => breakerChannel.BreakerNumber)
                                           .Distinct()
                                           .ToList();

            // If the breaker currents are defined for breaker-and-a-half or ring bus configurations,
            // skip this data group so that timing is only applied to the breaker currents
            if (breakerNumbers.Count > 1 && breakerNumbers.Any(num => m_breakerCurrents.Contains(num)))
            {
                return;
            }

            Event evt = eventTable.GetEvent(fileGroup, dataGroup);

            if ((object)evt == null)
            {
                return;
            }

            foreach (string breakerNumber in breakerNumbers)
            {
                double breakerSpeed = connection.ExecuteScalar(double.NaN, "SELECT Speed FROM Breaker WHERE AssetKey = {0}", breakerNumber.TrimStart('0'));

                Func <DataSeries, bool> digitalFilter = dataSeries =>
                {
                    int channelID = dataSeries.SeriesInfo.ChannelID;

                    RecordRestriction recordRestriction =
                        new RecordRestriction("ChannelID = {0}", channelID) &
                        new RecordRestriction("BreakerNumber = {0}", breakerNumber);

                    int breakerChannelCount = breakerChannelTable.QueryRecordCount(recordRestriction);

                    return(breakerChannelCount > 0);
                };

                List <DataSeries> breakerDigitals = dataGroup.DataSeries
                                                    .Where(dataSeries => dataSeries.SeriesInfo.Channel.MeasurementType.Name == "Digital")
                                                    .Where(digitalFilter)
                                                    .ToList();

                List <DataSeries> tripCoilEnergizedChannels = breakerDigitals
                                                              .Where(dataSeries => dataSeries.SeriesInfo.Channel.MeasurementCharacteristic.Name == "TCE")
                                                              .ToList();

                DataSeries breakerStatusChannel = breakerDigitals
                                                  .FirstOrDefault(dataSeries => dataSeries.SeriesInfo.Channel.MeasurementCharacteristic.Name == "BreakerStatus");

                List <XValue> tripCoilEnergizedTriggers = Range <XValue> .MergeAllOverlapping(tripCoilEnergizedChannels.SelectMany(FindTCERanges))
                                                          .Select(range => range.Start)
                                                          .ToList();

                foreach (XValue tripCoilEnergizedTrigger in tripCoilEnergizedTriggers)
                {
                    BreakerTiming breakerTiming = new BreakerTiming(tripCoilEnergizedTrigger, breakerStatusChannel, m_systemFrequency, breakerSpeed, m_breakerSettings.MinWaitBeforeReclose);

                    PhaseTiming aPhaseTiming = new PhaseTiming(viDataGroup.IA, viCycleDataGroup.IA, breakerTiming, m_breakerSettings, m_systemFrequency);
                    PhaseTiming bPhaseTiming = new PhaseTiming(viDataGroup.IB, viCycleDataGroup.IB, breakerTiming, m_breakerSettings, m_systemFrequency);
                    PhaseTiming cPhaseTiming = new PhaseTiming(viDataGroup.IC, viCycleDataGroup.IC, breakerTiming, m_breakerSettings, m_systemFrequency);

                    BreakerOperation breakerOperation = GetBreakerOperation(connection, evt.ID, breakerNumber, breakerTiming, aPhaseTiming, bPhaseTiming, cPhaseTiming);
                    breakerOperationTable.AddNewRecord(breakerOperation);
                }
            }
        }