Пример #1
0
        // Shamelessly copy pasted from the XDAWaveFormDataParser
        // Thanks other Stephen
        private void ParsePQDIF()
        {
            try
            {
                List <ObservationRecord> observationRecords;

                using (OpenFileDialog dialog = new OpenFileDialog())
                {
                    // Parse PQDif File Data
                    using (LogicalParser logicalParser = new LogicalParser(m_currentFilePath))
                    {
                        observationRecords = new List <ObservationRecord>();
                        logicalParser.Open();

                        while (logicalParser.HasNextObservationRecord())
                        {
                            observationRecords.Add(logicalParser.NextObservationRecord());
                        }
                    }

                    // Convert to common channel format
                    m_channels = observationRecords
                                 .SelectMany(observation => observation.ChannelInstances)
                                 .Where(channel => channel.Definition.QuantityTypeID == QuantityType.WaveForm)
                                 .Select(MakeParsedChannel)
                                 .ToList();
                }
            }
            catch (Exception e)
            {
                e.Source = m_currentFileRootName;
                ExceptionList.Add(e);
            }
        }
Пример #2
0
        /// <summary>
        /// Parses the file into a meter data set per meter contained in the file.
        /// </summary>
        /// <param name="filePath">The path to the file to be parsed.</param>
        /// <returns>List of meter data sets, one per meter.</returns>
        public void Parse(string filePath)
        {
            DataSourceRecord              dataSource = null;
            ObservationRecord             observation;
            IEnumerable <ChannelInstance> channelInstances;

            Meter      meter = null;
            Channel    channel;
            DataSeries dataSeries;

            DateTime[] timeData;

            while (m_parser.HasNextObservationRecord())
            {
                observation = m_parser.NextObservationRecord();

                if ((object)observation.DataSource == null)
                {
                    continue;
                }

                if ((object)dataSource == null)
                {
                    dataSource           = observation.DataSource;
                    meter                = ParseDataSource(dataSource);
                    m_meterDataSet.Meter = meter;
                }

                if (!AreEquivalent(dataSource, observation.DataSource))
                {
                    throw new InvalidDataException($"PQDIF file \"{filePath}\" defines too many data sources.");
                }

                channelInstances = observation.ChannelInstances
                                   .Where(channelInstance => QuantityType.IsQuantityTypeID(channelInstance.Definition.QuantityTypeID))
                                   .Where(channelInstance => channelInstance.SeriesInstances.Any())
                                   .Where(channelInstance => channelInstance.SeriesInstances[0].Definition.ValueTypeID == SeriesValueType.Time);

                foreach (ChannelInstance channelInstance in channelInstances)
                {
                    timeData = ParseTimeData(channelInstance);

                    foreach (SeriesInstance seriesInstance in channelInstance.SeriesInstances.Skip(1))
                    {
                        channel = ParseSeries(seriesInstance);

                        dataSeries            = new DataSeries();
                        dataSeries.DataPoints = timeData.Zip(ParseValueData(seriesInstance), (time, d) => new DataPoint()
                        {
                            Time = time, Value = d
                        }).ToList();
                        dataSeries.SeriesInfo = channel.Series[0];

                        meter.Channels.Add(channel);
                        m_meterDataSet.DataSeries.Add(dataSeries);
                    }
                }
            }
        }
Пример #3
0
        private void PQDIFButton_Click(object sender, EventArgs e)
        {
            List <ObservationRecord> observationRecords;

            using (OpenFileDialog dialog = new OpenFileDialog())
            {
                dialog.Filter = "PQDIF Files|*.pqd|All Files|*.*";
                dialog.Title  = "Browse PQDIF Files";

                if (dialog.ShowDialog() == DialogResult.Cancel)
                {
                    return;
                }

                if (!File.Exists(dialog.FileName))
                {
                    return;
                }

                // Parse PQDif File Data
                using (LogicalParser logicalParser = new LogicalParser(dialog.FileName))
                {
                    observationRecords = new List <ObservationRecord>();
                    logicalParser.Open();

                    while (logicalParser.HasNextObservationRecord())
                    {
                        observationRecords.Add(logicalParser.NextObservationRecord());
                    }
                }

                // Convert to common channel format
                m_channels = observationRecords
                             .SelectMany(observation => observation.ChannelInstances)
                             .Where(channel => channel.Definition.QuantityTypeID == QuantityType.WaveForm)
                             .Select(MakeParsedChannel)
                             .ToList();

                // Clear the list box and data chart
                ChannelListBox.Items.Clear();
                DataChart.Series.Clear();

                // Populate the list box with channel names
                ChannelListBox.Items.AddRange(m_channels
                                              .Select((channel, index) => string.Format("[{0}] {1}", index, channel.Name))
                                              .Cast <object>()
                                              .ToArray());

                // Select the first channel in the list
                ChannelListBox.SelectedIndex = 0;

                // Change the title text of the window to show what file the user has open
                m_fileName = dialog.SafeFileName;
                Text       = string.Format("PQDIF - [{0}]", dialog.SafeFileName);
            }
        }
        public IHttpActionResult Post([FromUri] string meterKey)
        {
            //string file = Request.Content.ReadAsStringAsync().Result;
            //byte[] bytes = System.Text.Encoding.UTF8.GetBytes(file);
            byte[] bytes = Request.Content.ReadAsByteArrayAsync().Result;

            ContainerRecord containerRecord;

            using (Stream stream = new MemoryStream(bytes))
                using (LogicalParser parser = new LogicalParser(stream))
                {
                    containerRecord = parser.ContainerRecord;
                    while (parser.HasNextObservationRecord())
                    {
                        parser.NextObservationRecord();
                    }

                    if (parser.DataSourceRecords.Count == 0)
                    {
                        return(BadRequest("File contained no useable channel definitions"));
                    }

                    IEnumerable <ChannelDefinition> channelDefinitions = parser.DataSourceRecords.First().ChannelDefinitions.Where(cd => cd.QuantityTypeID == QuantityType.WaveForm && cd.SeriesDefinitions.Where(ser => ser.QuantityCharacteristicID == QuantityCharacteristic.Instantaneous && ser.QuantityUnits != QuantityUnits.Seconds).Any() && (cd.QuantityMeasured == QuantityMeasured.Voltage || cd.QuantityMeasured == QuantityMeasured.Current));

                    var channels = channelDefinitions.Select((cd, index) => new {
                        ID                        = index + 1,
                        Meter                     = meterKey,
                        Asset                     = "",
                        MeasurementType           = cd.QuantityMeasured.ToString(),
                        MeasurementCharacteristic = "Instantaneous",
                        Phase                     = cd.Phase.ToString(),
                        Name                      = cd.ChannelName,
                        SamplesPerHour            = 0,
                        PerUnitValue              = 1,
                        HarmonicGroup             = 0,
                        Description               = cd.DataSource.DataSourceLocation + " - " + cd.ChannelName,
                        Enabled                   = true,
                        Adder                     = 0,
                        Multiplier                = 1,
                        Series                    = new [] {
                            new {
                                ID            = 0,
                                ChannelID     = 0,
                                SeriesType    = "Values",
                                SourceIndexes = ""
                            }
                        }
                    });

                    return(Ok(channels));
                }
        }
Пример #5
0
        /// <summary>
        /// Populate known voltage and current data from PQDIF file.
        /// </summary>
        /// <param name="faultDataSet">Fault data set to be populated.</param>
        /// <param name="settings">Source parameters.</param>
        public static void PopulateDataSet(FaultLocationDataSet faultDataSet, Dictionary <string, string> settings)
        {
            string fileName;

            List <ObservationRecord> observationRecords;
            ObservationRecord        faultObservation;

            ChannelInstance[] anChannels;
            ChannelInstance[] bnChannels;
            ChannelInstance[] cnChannels;

            if (!settings.TryGetValue("fileName", out fileName) || !File.Exists(fileName))
            {
                throw new ArgumentException("Parameters must define a valid \"fileName\" setting.");
            }

            // Parse PQDif File Data
            using (LogicalParser logicalParser = new LogicalParser(fileName))
            {
                observationRecords = new List <ObservationRecord>();
                logicalParser.Open();

                while (logicalParser.HasNextObservationRecord())
                {
                    observationRecords.Add(logicalParser.NextObservationRecord());
                }
            }

            // Get the first observation record that contains six wave forms.
            // Assume that this observation record will has both voltage and
            // current wave forms for each of the three phases
            faultObservation = observationRecords.FirstOrDefault(observation => observation.ChannelInstances.Count(channel => channel.Definition.QuantityTypeID == QuantityType.WaveForm) >= 6);

            if ((object)faultObservation != null)
            {
                // Get the voltage and current wave forms for each of the six phase types
                IEnumerable <ChannelInstance> waveForms = faultObservation.ChannelInstances.Where(channel => channel.Definition.QuantityTypeID == QuantityType.WaveForm).ToList();

                anChannels = waveForms.Where(channel => channel.Definition.Phase == Phase.AN).ToArray();
                bnChannels = waveForms.Where(channel => channel.Definition.Phase == Phase.BN).ToArray();
                cnChannels = waveForms.Where(channel => channel.Definition.Phase == Phase.CN).ToArray();

                // Attempt to fill in fault data for each of the three phase types
                FillFaultData(faultDataSet.Voltages.AN, faultDataSet.Currents.AN, anChannels);
                FillFaultData(faultDataSet.Voltages.BN, faultDataSet.Currents.BN, bnChannels);
                FillFaultData(faultDataSet.Voltages.CN, faultDataSet.Currents.CN, cnChannels);

                // Set the frequency in the data set to the nominal frequency of the system
                faultDataSet.Frequency = faultObservation.Settings.NominalFrequency;
            }
        }
Пример #6
0
        public void Parse(string filePath)
        {
            List <DataSourceRecord>  dataSources;
            List <ObservationRecord> observationRecords;
            List <ChannelInstance>   channelInstances;
            List <SeriesInstance>    seriesInstances;
            List <SeriesDefinition>  seriesDefinitions;

            Meter      meter;
            Channel    channel;
            DataSeries dataSeries;

            DateTime[] timeData;

            // Build the list of observation records in the PQDIF file
            observationRecords = new List <ObservationRecord>();

            while (m_parser.HasNextObservationRecord())
            {
                observationRecords.Add(m_parser.NextObservationRecord());
            }

            // Build the list of all data source records in the PQDIF file
            dataSources = observationRecords
                          .Select(observation => observation.DataSource)
                          .Distinct()
                          .ToList();

            // If there are no data sources, there is no
            // need to go any further because we won't be
            // able to interpret any of the channel data
            if (!dataSources.Any())
            {
                return;
            }

            // Validate data sources to make sure there is only one data source defined in the file
            if (!dataSources.Zip(dataSources.Skip(1), (ds1, ds2) => AreEquivalent(ds1, ds2)).All(b => b))
            {
                throw new InvalidDataException($"PQDIF file \"{filePath}\" defines too many data sources.");
            }

            // Create a meter from the parsed data source
            meter = ParseDataSource(dataSources.First());

            // Build the list of all channel instances in the PQDIF file
            channelInstances = observationRecords
                               .SelectMany(observation => observation.ChannelInstances)
                               .Where(channelInstance => QuantityType.IsQuantityTypeID(channelInstance.Definition.QuantityTypeID))
                               .Where(channelInstance => channelInstance.SeriesInstances.Any())
                               .Where(channelInstance => channelInstance.SeriesInstances[0].Definition.ValueTypeID == SeriesValueType.Time)
                               .ToList();

            // Create the list of series instances so we can
            // build it as we process each channel instance
            seriesInstances = new List <SeriesInstance>();

            Dictionary <Channel, DataSeries> startChannelsAndDataSeries = new Dictionary <Channel, DataSeries>();
            Dictionary <Channel, DataSeries> endChannelsAndDataSeries   = new Dictionary <Channel, DataSeries>();

            foreach (ChannelInstance channelInstance in channelInstances)
            {
                bool timeValueChannel =
                    channelInstance.Definition.QuantityTypeID == QuantityType.WaveForm ||
                    channelInstance.Definition.QuantityTypeID == QuantityType.ValueLog ||
                    channelInstance.Definition.QuantityTypeID == QuantityType.Phasor ||
                    channelInstance.Definition.QuantityTypeID == QuantityType.Flash ||
                    channelInstance.Definition.QuantityTypeID == QuantityType.MagDurTime ||
                    channelInstance.Definition.QuantityTypeID == QuantityType.MagDurCount;

                // TODO: Create representation for quantity types that do not define time/value data
                if (!timeValueChannel)
                {
                    continue;
                }

                // Parse time data from the channel instance
                timeData = ParseTimeData(channelInstance);

                foreach (SeriesInstance seriesInstance in channelInstance.SeriesInstances.Skip(1))
                {
                    // Create a channel from the parsed series instance
                    seriesInstances.Add(seriesInstance);
                    channel = ParseSeries(seriesInstance);

                    // Parse the values and zip them with time data to create data points
                    dataSeries            = new DataSeries();
                    dataSeries.DataPoints = timeData.Zip(ParseValueData(seriesInstance), (time, d) => new DataPoint()
                    {
                        Time = time, Value = d
                    }).ToList();
                    dataSeries.SeriesInfo = channel.Series[0];

                    // Add the new channel to the meter's channel list

                    if (channel.Name.ToLower().Contains("start"))
                    {
                        startChannelsAndDataSeries[channel] = dataSeries;
                    }
                    else if (channel.Name.ToLower().Contains("end"))
                    {
                        endChannelsAndDataSeries[channel] = dataSeries;
                    }
                    else
                    {
                        channel.Meter = meter;
                        meter.Channels.Add(channel);
                        m_meterDataSet.DataSeries.Add(dataSeries);
                    }
                }
            }

            foreach (Channel chan in startChannelsAndDataSeries.Keys)
            {
                string  baseChannelName = chan.Name.ToLower().Replace("start", "");
                Channel endChannel      = endChannelsAndDataSeries.Keys.Where(ch => ch.Name.ToLower().Replace("end", "") == baseChannelName).FirstOrDefault();

                if ((object)endChannel != null)
                {
                    Channel    combinedChannel    = chan;
                    DataSeries combinedDataSeries = startChannelsAndDataSeries[chan];

                    // Replace "Start" in combinedChannel.Name with "Start + End";
                    int index = combinedChannel.Name.IndexOf("start", StringComparison.OrdinalIgnoreCase);
                    combinedChannel.Name = combinedChannel.Name.Remove(index, 5).Insert(index, "Start + End");

                    combinedDataSeries.DataPoints.AddRange(endChannelsAndDataSeries[endChannel].DataPoints);

                    combinedChannel.Meter = meter;
                    meter.Channels.Add(combinedChannel);
                    m_meterDataSet.DataSeries.Add(combinedDataSeries);
                }
            }

            // Build a list of series definitions that were not instanced by this PQDIF file
            seriesDefinitions = dataSources
                                .SelectMany(dataSource => dataSource.ChannelDefinitions)
                                .SelectMany(channelDefinition => channelDefinition.SeriesDefinitions)
                                .Distinct()
                                .Except(seriesInstances.Select(seriesInstance => seriesInstance.Definition))
                                .ToList();

            // Add each of the series definitions which were not instanced to the meter's list of channels
            foreach (SeriesDefinition seriesDefinition in seriesDefinitions)
            {
                meter.Channels.Add(ParseSeries(seriesDefinition));
            }

            m_meterDataSet.Meter = meter;
        }
Пример #7
0
        /// <summary>
        /// Parses the file into a meter data set per meter contained in the file.
        /// </summary>
        /// <param name="filePath">The path to the file to be parsed.</param>
        /// <returns>List of meter data sets, one per meter.</returns>
        public void Parse(string filePath)
        {
            List <DataSourceRecord>  dataSources;
            List <ObservationRecord> observationRecords;
            List <ChannelInstance>   channelInstances;
            List <SeriesInstance>    seriesInstances;
            List <SeriesDefinition>  seriesDefinitions;

            Meter      meter;
            Channel    channel;
            DataSeries dataSeries;

            DateTime[] timeData;

            // Build the list of observation records in the PQDIF file
            observationRecords = new List <ObservationRecord>();

            while (m_parser.HasNextObservationRecord())
            {
                observationRecords.Add(m_parser.NextObservationRecord());
            }

            // Build the list of all data source records in the PQDIF file
            dataSources = observationRecords
                          .Select(observation => observation.DataSource)
                          .Distinct()
                          .ToList();

            // If there are no data sources, there is no
            // need to go any further because we won't be
            // able to interpret any of the channel data
            if (!dataSources.Any())
            {
                return;
            }

            // Validate data sources to make sure there is only one data source defined in the file
            if (!dataSources.Zip(dataSources.Skip(1), (ds1, ds2) => AreEquivalent(ds1, ds2)).All(b => b))
            {
                throw new InvalidDataException($"PQDIF file \"{filePath}\" defines too many data sources.");
            }

            // Create a meter from the parsed data source
            meter = ParseDataSource(dataSources.First());
            m_meterDataSet.Meter = meter;

            // Build the list of all channel instances in the PQDIF file
            channelInstances = observationRecords
                               .SelectMany(observation => observation.ChannelInstances)
                               .Where(channelInstance => QuantityType.IsQuantityTypeID(channelInstance.Definition.QuantityTypeID))
                               .Where(channelInstance => channelInstance.SeriesInstances.Any())
                               .Where(channelInstance => channelInstance.SeriesInstances[0].Definition.ValueTypeID == SeriesValueType.Time)
                               .ToList();

            // Create the list of series instances so we can
            // build it as we process each channel instance
            seriesInstances = new List <SeriesInstance>();

            foreach (ChannelInstance channelInstance in channelInstances)
            {
                bool timeValueChannel =
                    channelInstance.Definition.QuantityTypeID == QuantityType.WaveForm ||
                    channelInstance.Definition.QuantityTypeID == QuantityType.ValueLog ||
                    channelInstance.Definition.QuantityTypeID == QuantityType.Phasor ||
                    channelInstance.Definition.QuantityTypeID == QuantityType.Flash ||
                    channelInstance.Definition.QuantityTypeID == QuantityType.MagDurTime ||
                    channelInstance.Definition.QuantityTypeID == QuantityType.MagDurCount;

                // TODO: Create representation for quantity types that do not define time/value data
                if (!timeValueChannel)
                {
                    continue;
                }

                // Parse time data from the channel instance
                timeData = ParseTimeData(channelInstance);

                foreach (SeriesInstance seriesInstance in channelInstance.SeriesInstances.Skip(1))
                {
                    // Create a channel from the parsed series instance
                    seriesInstances.Add(seriesInstance);
                    channel = ParseSeries(seriesInstance);

                    // Parse the values and zip them with time data to create data points
                    dataSeries            = new DataSeries();
                    dataSeries.DataPoints = timeData.Zip(ParseValueData(seriesInstance), (time, d) => new DataPoint()
                    {
                        Time = time, Value = d
                    }).ToList();
                    dataSeries.SeriesInfo = channel.Series[0];

                    // Add the new channel to the meter's channel list
                    meter.Channels.Add(channel);
                    m_meterDataSet.DataSeries.Add(dataSeries);
                }
            }

            // Build a list of series definitions that were not instanced by this PQDIF file
            seriesDefinitions = dataSources
                                .SelectMany(dataSource => dataSource.ChannelDefinitions)
                                .SelectMany(channelDefinition => channelDefinition.SeriesDefinitions)
                                .Distinct()
                                .Except(seriesInstances.Select(seriesInstance => seriesInstance.Definition))
                                .ToList();

            // Add each of the series definitions which were not instanced to the meter's list of channels
            foreach (SeriesDefinition seriesDefinition in seriesDefinitions)
            {
                meter.Channels.Add(ParseSeries(seriesDefinition));
            }
        }
Пример #8
0
        private void Parse(string filename)
        {
            List <ObservationRecord> observationRecords;
            List <DataSourceRecord>  dataSourceRecords;

            using (LogicalParser logicalParser = new LogicalParser(filename))
            {
                observationRecords = new List <ObservationRecord>();
                logicalParser.Open();

                while (logicalParser.HasNextObservationRecord())
                {
                    observationRecords.Add(logicalParser.NextObservationRecord());
                }

                dataSourceRecords = logicalParser.DataSourceRecords;
            }

            this.m_previousProgress = this.m_previousProgress + 50;
            this.mProgress.Report(this.m_previousProgress);

            if (observationRecords.Count == 0)
            {
                return;
            }
            if (dataSourceRecords.Count != 1)
            {
                return;
            }

            //create Meter Definition
            //For now assume a single meter
            Meter meter = new Meter();

            meter.DeviceName     = dataSourceRecords[0].DataSourceName;
            meter.Owner          = dataSourceRecords[0].DataSourceOwner;
            meter.DeviceAlias    = GSF.PQDIF.Logical.Equipment.ToString(dataSourceRecords[0].EquipmentID);
            meter.DeviceLocation = dataSourceRecords[0].DataSourceLocation;
            if (dataSourceRecords[0].Latitude < uint.MaxValue)
            {
                meter.Latitude = dataSourceRecords[0].Latitude;
            }
            if (dataSourceRecords[0].Longitude < uint.MaxValue)
            {
                meter.Longitude = dataSourceRecords[0].Longitude;
            }

            meter.AccountName = GSF.PQDIF.Logical.Vendor.ToString(dataSourceRecords[0].VendorID);

            using (TransactionScope scope = new TransactionScope())
            {
                AdoDataConnection connection = new AdoDataConnection(connectionstring, dataprovider);

                GSF.Data.Model.TableOperations <Meter> meterTable = new GSF.Data.Model.TableOperations <Meter>(connection);

                meterTable.AddNewRecord(meter);
                meter.ID = ModelID.GetID <Meter>(connection);


                //create Channel Definitions
                List <PQio.Model.Channel> channels = dataSourceRecords[0].ChannelDefinitions.Select(channel => ParseChannel(meter, channel, connection)).ToList();
                List <PQio.Model.Event>   events   = new List <Event>();
                //create Event Definitions
                foreach (ObservationRecord record in observationRecords)
                {
                    //Create Event
                    Event evt = ParseObservationRecord(record, connection);

                    //create DataSeries objects
                    foreach (ChannelInstance channelInstance in record.ChannelInstances)
                    {
                        ParseSeries(channelInstance, channels[(int)channelInstance.ChannelDefinitionIndex], evt, connection);
                    }
                    events.Add(evt);
                }

                // Remove Channels whithout data
                channels = channels.FindAll(item => RemoveEmptyChannel(item, connection)).ToList();
                events   = events.FindAll(item => RemoveEmptyEvents(item, connection)).ToList();

                // Remove Channels whithout data
                channels = channels.FindAll(item => RemoveEmptyChannel(item, connection)).ToList();

                // If only one set of data it's easy to keep only single line
                int nVa = channels.Count(channel => channel.MeasurementType.ToLower() == MeasurementType.VoltageA);
                int nVb = channels.Count(channel => channel.MeasurementType.ToLower() == MeasurementType.VoltageB);
                int nVc = channels.Count(channel => channel.MeasurementType.ToLower() == MeasurementType.VoltageC);
                int nIa = channels.Count(channel => channel.MeasurementType.ToLower() == MeasurementType.CurrentA);
                int nIb = channels.Count(channel => channel.MeasurementType.ToLower() == MeasurementType.CurrentB);
                int nIc = channels.Count(channel => channel.MeasurementType.ToLower() == MeasurementType.CurrentC);

                if (nVa == 1 && nVb == 1 && nVc == 1)
                {
                    //Create new asset
                    Asset asset = new Asset()
                    {
                        AssetKey = String.Format("Asset 1 ({0})", meter.AccountName)
                    };


                    GSF.Data.Model.TableOperations <Asset> assetTable = new GSF.Data.Model.TableOperations <Asset>(connection);
                    assetTable.AddNewRecord(asset);
                    asset.ID = ModelID.GetID <Asset>(connection);

                    GSF.Data.Model.TableOperations <Channel> channelTable = new GSF.Data.Model.TableOperations <Channel>(connection);

                    Channel Va = channels.Find(item => item.MeasurementType.ToLower() == MeasurementType.VoltageA);
                    Channel Vb = channels.Find(item => item.MeasurementType.ToLower() == MeasurementType.VoltageB);
                    Channel Vc = channels.Find(item => item.MeasurementType.ToLower() == MeasurementType.VoltageC);

                    Va.AssetID = asset.ID;
                    Vb.AssetID = asset.ID;
                    Vc.AssetID = asset.ID;

                    channelTable.UpdateRecord(Va);
                    channelTable.UpdateRecord(Vb);
                    channelTable.UpdateRecord(Vc);

                    if (nIa == 1 && nIb == 1 && nIc == 1)
                    {
                        Channel Ia = channels.Find(item => item.MeasurementType.ToLower() == MeasurementType.CurrentA);
                        Channel Ib = channels.Find(item => item.MeasurementType.ToLower() == MeasurementType.CurrentB);
                        Channel Ic = channels.Find(item => item.MeasurementType.ToLower() == MeasurementType.CurrentC);

                        Ia.AssetID = asset.ID;
                        Ib.AssetID = asset.ID;
                        Ic.AssetID = asset.ID;

                        channelTable.UpdateRecord(Ia);
                        channelTable.UpdateRecord(Ib);
                        channelTable.UpdateRecord(Ic);
                    }
                }

                scope.Complete();
            }
            this.m_previousProgress = this.m_previousProgress + 50;
            this.mProgress.Report(this.m_previousProgress);
        }
Пример #9
0
        /// <summary>
        /// Parses the file into a meter data set per meter contained in the file.
        /// </summary>
        /// <param name="filePath">The path to the file to be parsed.</param>
        /// <returns>List of meter data sets, one per meter.</returns>
        public void Parse(string filePath)
        {
            List <DataSourceRecord>  dataSources;
            List <ObservationRecord> observationRecords;
            List <ChannelInstance>   channelInstances;
            List <SeriesInstance>    seriesInstances;
            List <SeriesDefinition>  seriesDefinitions;

            Meter      meter;
            Channel    channel;
            DataSeries dataSeries;

            DateTime[] timeData;

            // Build the list of observation records in the PQDIF file
            observationRecords = new List <ObservationRecord>();

            while (m_parser.HasNextObservationRecord())
            {
                observationRecords.Add(m_parser.NextObservationRecord());
            }

            // Build the list of all data source records in the PQDIF file
            dataSources = observationRecords
                          .Select(observation => observation.DataSource)
                          .Distinct()
                          .ToList();

            // If there are no data sources, there is no
            // need to go any further because we won't be
            // able to interpret any of the channel data
            if (!dataSources.Any())
            {
                return;
            }

            // Validate data sources to make sure there is only one data source defined in the file
            if (!dataSources.Zip(dataSources.Skip(1), (ds1, ds2) => AreEquivalent(ds1, ds2)).All(b => b))
            {
                throw new InvalidDataException($"PQDIF file \"{filePath}\" defines too many data sources.");
            }

            // Create a meter from the parsed data source
            meter = ParseDataSource(dataSources.First());

            // Build the list of all channel instances in the PQDIF file
            channelInstances = observationRecords
                               .SelectMany(observation => observation.ChannelInstances)
                               .Where(channelInstance => QuantityType.IsQuantityTypeID(channelInstance.Definition.QuantityTypeID))
                               .Where(channelInstance => channelInstance.SeriesInstances.Any())
                               .Where(channelInstance => channelInstance.SeriesInstances[0].Definition.ValueTypeID == SeriesValueType.Time)
                               .ToList();

            // Create the list of series instances so we can
            // build it as we process each channel instance
            seriesInstances = new List <SeriesInstance>();

            foreach (ChannelInstance channelInstance in channelInstances)
            {
                bool timeValueChannel =
                    channelInstance.Definition.QuantityTypeID == QuantityType.WaveForm ||
                    channelInstance.Definition.QuantityTypeID == QuantityType.ValueLog ||
                    channelInstance.Definition.QuantityTypeID == QuantityType.Phasor;

                if (!timeValueChannel)
                {
                    continue;
                }

                // Parse time data from the channel instance
                timeData = ParseTimeData(channelInstance, m_systemFrequency);

                foreach (SeriesInstance seriesInstance in channelInstance.SeriesInstances.Skip(1))
                {
                    // Create a channel from the parsed series instance
                    seriesInstances.Add(seriesInstance);
                    channel = ParseSeries(seriesInstance);

                    // Parse the values and zip them with time data to create data points
                    dataSeries            = new DataSeries();
                    dataSeries.DataPoints = timeData.Zip(ParseValueData(seriesInstance), (time, d) => new DataPoint()
                    {
                        Time = time, Value = d
                    }).ToList();
                    dataSeries.SeriesInfo = channel.Series[0];

                    // Add the new channel to the meter's channel list
                    channel.Meter = meter;
                    meter.Channels.Add(channel);
                    m_meterDataSet.DataSeries.Add(dataSeries);
                }
            }

            foreach (ChannelInstance channelInstance in channelInstances)
            {
                bool magDurChannel =
                    channelInstance.Definition.QuantityTypeID == QuantityType.MagDur ||
                    channelInstance.Definition.QuantityTypeID == QuantityType.MagDurCount ||
                    channelInstance.Definition.QuantityTypeID == QuantityType.MagDurTime;

                if (!magDurChannel)
                {
                    continue;
                }

                timeData = channelInstance.SeriesInstances
                           .Where(seriesInstance => seriesInstance.Definition.ValueTypeID == SeriesValueType.Time)
                           .Select(seriesInstance => ParseTimeData(seriesInstance, m_systemFrequency))
                           .FirstOrDefault();

                Guid valType = SeriesValueType.Val;
                Guid maxType = SeriesValueType.Max;
                Guid minType = SeriesValueType.Min;
                Guid avgType = SeriesValueType.Avg;

                double[] valData = channelInstance.SeriesInstances
                                   .Where(seriesInstance => seriesInstance.Definition.ValueTypeID == valType)
                                   .Select(seriesInstance => ParseValueData(seriesInstance))
                                   .FirstOrDefault();

                double[] maxData = channelInstance.SeriesInstances
                                   .Where(seriesInstance => seriesInstance.Definition.ValueTypeID == maxType)
                                   .Select(seriesInstance => ParseValueData(seriesInstance))
                                   .FirstOrDefault() ?? valData;

                double[] minData = channelInstance.SeriesInstances
                                   .Where(seriesInstance => seriesInstance.Definition.ValueTypeID == minType)
                                   .Select(seriesInstance => ParseValueData(seriesInstance))
                                   .FirstOrDefault() ?? valData;

                double[] avgData = channelInstance.SeriesInstances
                                   .Where(seriesInstance => seriesInstance.Definition.ValueTypeID == avgType)
                                   .Select(seriesInstance => ParseValueData(seriesInstance))
                                   .FirstOrDefault() ?? valData;

                TimeSpan[] durData = channelInstance.SeriesInstances
                                     .Where(seriesInstance => seriesInstance.Definition.ValueTypeID == SeriesValueType.Duration)
                                     .Select(seriesInstance => ParseTimeSpanData(seriesInstance, m_systemFrequency))
                                     .FirstOrDefault();

                int minLength = Common.Min(timeData.Length, maxData.Length, minData.Length, avgData.Length, durData.Length);

                QuantityUnits units = channelInstance.SeriesInstances
                                      .Where(seriesInstance => new[] { valType, maxType, minType, avgType }.Contains(seriesInstance.Definition.ValueTypeID))
                                      .Select(seriesInstance => seriesInstance.Definition.QuantityUnits)
                                      .FirstOrDefault();

                for (int i = 0; i < minLength; i++)
                {
                    DateTime time = ((object)timeData != null)
                        ? timeData[i]
                        : channelInstance.ObservationRecord.StartTime;

                    double   max = maxData[i];
                    double   min = minData[i];
                    double   avg = avgData[i];
                    TimeSpan dur = durData[i];

                    m_meterDataSet.ReportedDisturbances.Add(new ReportedDisturbance(channelInstance.Definition.Phase, time, max, min, avg, dur, units));
                }
            }

            // Build a list of series definitions that were not instanced by this PQDIF file
            seriesDefinitions = dataSources
                                .SelectMany(dataSource => dataSource.ChannelDefinitions)
                                .SelectMany(channelDefinition => channelDefinition.SeriesDefinitions)
                                .Distinct()
                                .Except(seriesInstances.Select(seriesInstance => seriesInstance.Definition))
                                .ToList();

            // Add each of the series definitions which were not instanced to the meter's list of channels
            foreach (SeriesDefinition seriesDefinition in seriesDefinitions)
            {
                meter.Channels.Add(ParseSeries(seriesDefinition));
            }

            m_meterDataSet.Meter = meter;

            // Parse triggers from PQube data
            m_meterDataSet.Triggers = PQubeReader.GetTriggers(observationRecords);
        }