Ejemplo n.º 1
0
        /// <summary>
        /// Publish <see cref="IFrame"/> of time-aligned collection of <see cref="IMeasurement"/> values that arrived within the
        /// concentrator's defined <see cref="ConcentratorBase.LagTime"/>.
        /// </summary>
        /// <param name="frame"><see cref="IFrame"/> of measurements with the same timestamp that arrived within <see cref="ConcentratorBase.LagTime"/> that are ready for processing.</param>
        /// <param name="index">Index of <see cref="IFrame"/> within a second ranging from zero to <c><see cref="ConcentratorBase.FramesPerSecond"/> - 1</c>.</param>
        protected override void PublishFrame(IFrame frame, int index)
        {
            IMeasurement bestMeasurement = GetBestMeasurement(frame);

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

            IMeasurement[] newMeasurements = OutputMeasurements
                                             .Select(measurement => Measurement.Clone(measurement))
                                             .ToArray();

            newMeasurements[0].Timestamp  = frame.Timestamp;
            newMeasurements[0].StateFlags = bestMeasurement.StateFlags;
            newMeasurements[0].Value      = bestMeasurement.Value;

            if (newMeasurements.Length > 1)
            {
                newMeasurements[1].Timestamp  = frame.Timestamp;
                newMeasurements[1].StateFlags = bestMeasurement.StateFlags;
                newMeasurements[1].Value      = Array.IndexOf(InputMeasurementKeys, bestMeasurement.Key) + 1;
            }

            OnNewMeasurements(newMeasurements);

            m_lastSelectedMeasurement = bestMeasurement.Key;
        }
        /// <summary>
        /// Initializes this <see cref="HadoopDataLoader"/>.
        /// </summary>
        public override void Initialize()
        {
            Dictionary <string, string> settings = Settings;

            // Handle misspelled property so previously configured adapters will still apply proper value
            if (settings.TryGetValue("UpdateIntervall", out string setting) && int.TryParse(setting, out _))
            {
                settings["UpdateInterval"] = setting;
            }

            new ConnectionStringParser <ConnectionStringParameterAttribute>().ParseConnectionString(ConnectionString, this);

            base.Initialize();

            //Generate Query
            m_query = $"SELECT {ValueField} AS V, {TimeStampField} AS T";

            if (!string.IsNullOrEmpty(SubSecondField))
            {
                m_query = m_query + $", {SubSecondField} AS Ticks";
            }

            m_query = m_query + $" FROM {TableName} WHERE {TimeStampField} > '{{0}}' AND {TagQuery}";

            if (!string.IsNullOrEmpty(OrderField))
            {
                m_query = $" ORDER BY {OrderField}";
            }


            //Create Mapping Dictionary
            List <string> pointTags = OutputMeasurements.Select(item => item.Metadata.TagName).ToList();

            m_queryParameter = new Dictionary <Guid, List <string> >();

            // Read Mapping File
            using (StreamReader reader = new StreamReader(FilePath.GetAbsolutePath(MappingFile)))
            {
                string line;

                while ((line = reader.ReadLine()) != null)
                {
                    List <string> entries  = line.Split(',').Select(item => item.Trim()).ToList();
                    string        pointTag = entries[0];

                    int index = pointTags.FindIndex(item => item == pointTag);
                    if (index > -1)
                    {
                        m_queryParameter.Add(OutputMeasurements[index].Key.SignalID, entries.Skip(1).ToList());
                    }
                }
            }

            //start Timer
            m_timer           = new Timer();
            m_timer.Interval  = UpdateInterval;
            m_timer.AutoReset = true;
            m_timer.Elapsed  += m_timer_Elapsed;
        }
Ejemplo n.º 3
0
        private void Timer_Elapsed(object sender, ElapsedEventArgs elapsedEventArgs)
        {
            long   now             = DateTime.UtcNow.Ticks;
            long   nextPublication = GetNextPublicationTime(m_lastPublication);
            double delta;

            while (nextPublication < now)
            {
                delta = Ticks.ToSeconds(nextPublication - m_lastPublication);

                for (int i = 0; i < OutputMeasurements.Length; i++)
                {
                    Advance(i, delta);
                }

                OnNewMeasurements(OutputMeasurements
                                  .Select((measurement, index) => Measurement.Clone(measurement, GetWrappedValue(index), m_includeTime ? nextPublication : 0L))
                                  .ToList <IMeasurement>());

                m_lastPublication = nextPublication;
                nextPublication   = GetNextPublicationTime(m_lastPublication);
            }
        }
Ejemplo n.º 4
0
        private void PollingOperation()
        {
            if ((object)m_modbusConnection == null)
            {
                return;
            }

            try
            {
                Ticks timestamp = DateTime.UtcNow.Ticks;
                Dictionary <MeasurementKey, Measurement> measurements = OutputMeasurements.Select(measurement => Measurement.Clone(measurement, timestamp)).ToDictionary(measurement => measurement.Key, measurement => measurement);
                Group[] groups = m_sequences.SelectMany(sequence => sequence.Groups).ToArray();
                int     measurementsReceived = 0;

                int overallTasksCompleted = 0;
                int overallTasksCount     = m_sequences.Count + 1;
                OnProgressUpdated(this, new ProgressUpdate(ProgressState.Processing, true, "Starting polling operation...", overallTasksCompleted, overallTasksCount));
                OnStatusMessage(MessageLevel.Info, $"Executing poll operation {m_pollOperations + 1}.");

                // Handle read/write operations for sequence groups
                try
                {
                    foreach (Sequence sequence in m_sequences)
                    {
                        foreach (Group group in sequence.Groups)
                        {
                            OnProgressUpdated(this, new ProgressUpdate(ProgressState.Processing, false, $"Executing poll for {sequence.Type.ToString().ToLowerInvariant()} sequence group \"{group.Type}@{group.StartAddress}\"...", 0, group.PointCount));

                            switch (group.Type)
                            {
                            case RecordType.DI:
                                group.DataValues = ReadDiscreteInputs(group.StartAddress, group.PointCount);
                                break;

                            case RecordType.CO:
                                if (sequence.Type == SequenceType.Read)
                                {
                                    group.DataValues = ReadCoils(group.StartAddress, group.PointCount);
                                }
                                else
                                {
                                    WriteCoils(group.StartAddress, group.DataValues);
                                }
                                break;

                            case RecordType.IR:
                                group.DataValues = ReadInputRegisters(group.StartAddress, group.PointCount);
                                break;

                            case RecordType.HR:
                                if (sequence.Type == SequenceType.Read)
                                {
                                    group.DataValues = ReadHoldingRegisters(group.StartAddress, group.PointCount);
                                }
                                else
                                {
                                    WriteHoldingRegisters(group.StartAddress, group.DataValues);
                                }
                                break;
                            }

                            OnProgressUpdated(this, new ProgressUpdate(ProgressState.Processing, false, $"Completed poll for {sequence.Type.ToString().ToLowerInvariant()} sequence group \"{group.Type}@{group.StartAddress}\".", group.PointCount, group.PointCount));
                            Thread.Sleep(m_interSequenceGroupPollDelay);
                        }

                        OnProgressUpdated(this, new ProgressUpdate(ProgressState.Processing, true, null, ++overallTasksCompleted, overallTasksCount));
                    }
                }
                catch
                {
                    m_deviceErrors++;
                    throw;
                }

                OnProgressUpdated(this, new ProgressUpdate(ProgressState.Processing, false, "Processing derived values...", 0, m_derivedValues.Count));

                // Calculate derived values
                foreach (KeyValuePair <MeasurementKey, DerivedValue> item in m_derivedValues)
                {
                    DerivedValue derivedValue = item.Value;
                    ushort[]     dataValues   = derivedValue.GetDataValues(groups);
                    Measurement  measurement;

                    if (measurements.TryGetValue(item.Key, out measurement))
                    {
                        // TODO: Properly interpret measurement types after GSF data type transport update
                        switch (derivedValue.Type)
                        {
                        case DerivedType.String:
                            if (derivedValue.AddressRecords.Count > 0)
                            {
                                m_derivedStrings[item.Key] = DeriveString(dataValues);
                                measurementsReceived++;
                            }
                            else
                            {
                                OnStatusMessage(MessageLevel.Warning, $"No address records defined for derived String value \"{item.Key}\".");
                            }
                            break;

                        case DerivedType.Single:
                            if (derivedValue.AddressRecords.Count > 1)
                            {
                                measurement.Value = DeriveSingle(dataValues[0], dataValues[1]);
                                measurementsReceived++;
                            }
                            else
                            {
                                OnStatusMessage(MessageLevel.Warning, $"{derivedValue.AddressRecords.Count} address records defined for derived Single value \"{item.Key}\", expected 2.");
                            }
                            break;

                        case DerivedType.Double:
                            if (derivedValue.AddressRecords.Count > 3)
                            {
                                measurement.Value = DeriveDouble(dataValues[0], dataValues[1], dataValues[2], dataValues[3]);
                                measurementsReceived++;
                            }
                            else
                            {
                                OnStatusMessage(MessageLevel.Warning, $"{derivedValue.AddressRecords.Count} address records defined for derived Double value \"{item.Key}\", expected 4.");
                            }
                            break;

                        case DerivedType.UInt16:
                            if (derivedValue.AddressRecords.Count > 0)
                            {
                                measurement.Value = dataValues[0];
                                measurementsReceived++;
                            }
                            else
                            {
                                OnStatusMessage(MessageLevel.Warning, $"No address records defined for UInt16 value \"{item.Key}\".");
                            }
                            break;

                        case DerivedType.Int32:
                            if (derivedValue.AddressRecords.Count > 1)
                            {
                                measurement.Value = DeriveInt32(dataValues[0], dataValues[1]);
                                measurementsReceived++;
                            }
                            else
                            {
                                OnStatusMessage(MessageLevel.Warning, $"{derivedValue.AddressRecords.Count} address records defined for derived Int32 value \"{item.Key}\", expected 2.");
                            }
                            break;

                        case DerivedType.UInt32:
                            if (derivedValue.AddressRecords.Count > 1)
                            {
                                measurement.Value = DeriveUInt32(dataValues[0], dataValues[1]);
                                measurementsReceived++;
                            }
                            else
                            {
                                OnStatusMessage(MessageLevel.Warning, $"{derivedValue.AddressRecords.Count} address records defined for derived UInt32 value \"{item.Key}\", expected 2.");
                            }
                            break;

                        case DerivedType.Int64:
                            if (derivedValue.AddressRecords.Count > 3)
                            {
                                measurement.Value = DeriveInt64(dataValues[0], dataValues[1], dataValues[2], dataValues[3]);
                                measurementsReceived++;
                            }
                            else
                            {
                                OnStatusMessage(MessageLevel.Warning, $"{derivedValue.AddressRecords.Count} address records defined for derived Int64 value \"{item.Key}\", expected 4.");
                            }
                            break;

                        case DerivedType.UInt64:
                            if (derivedValue.AddressRecords.Count > 3)
                            {
                                measurement.Value = DeriveUInt64(dataValues[0], dataValues[1], dataValues[2], dataValues[3]);
                                measurementsReceived++;
                            }
                            else
                            {
                                OnStatusMessage(MessageLevel.Warning, $"{derivedValue.AddressRecords.Count} address records defined for derived UInt64 value \"{item.Key}\", expected 4.");
                            }
                            break;
                        }
                    }

                    if (measurementsReceived % 20 == 0)
                    {
                        OnProgressUpdated(this, new ProgressUpdate(ProgressState.Processing, false, null, measurementsReceived, m_derivedValues.Count));
                    }
                }

                OnProgressUpdated(this, new ProgressUpdate(ProgressState.Processing, false, "Completed derived value processing.", m_derivedValues.Count, m_derivedValues.Count));
                OnProgressUpdated(this, new ProgressUpdate(ProgressState.Succeeded, true, "Polling operation complete.", overallTasksCount, overallTasksCount));

                OnNewMeasurements(measurements.Values.ToArray());

                m_measurementsReceived += measurementsReceived;
                m_pollOperations++;
            }
            catch (Exception ex)
            {
                OnProgressUpdated(this, new ProgressUpdate(ProgressState.Failed, true, $"Failed during poll operation: {ex.Message}", 0, 1));

                // Restart connection cycle when an exception occurs
                Start();
                throw;
            }
            finally
            {
                m_measurementsExpected += OutputMeasurements.Length;
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Initializes <see cref="ModbusPoller" />.
        /// </summary>
        public override void Initialize()
        {
            base.Initialize();

            ConnectionStringParser <ConnectionStringParameterAttribute> parser = new ConnectionStringParser <ConnectionStringParameterAttribute>();

            parser.ParseConnectionString(ConnectionString, this);

            // Register downloader with the statistics engine
            StatisticsEngine.Register(this, "Modbus", "MOD");
            StatisticsEngine.Register(m_deviceProxy, Name, "Device", "PMU");

            // Attach to output measurements for Modbus device
            OutputMeasurements = ParseOutputMeasurements(DataSource, false, $"FILTER ActiveMeasurements WHERE Device = '{Name}'");

            // Parse derived value expressions from defined signal reference fields
            m_derivedValues = OutputMeasurements.Select(measurement => measurement.Key).ToDictionary(key => key, key =>
            {
                DataTable measurements    = DataSource.Tables["ActiveMeasurements"];
                DerivedValue derivedValue = null;
                DataRow[] records         = measurements.Select($"ID = '{key}'");

                if (records.Length > 0)
                {
                    derivedValue = ParseDerivedValue(records[0]["SignalReference"].ToNonNullString());
                }

                return(derivedValue);
            });

            m_sequences = new List <Sequence>();

            Dictionary <string, string> settings = Settings;
            string setting;
            int    sequenceCount = 0;

            if (settings.TryGetValue("sequenceCount", out setting))
            {
                int.TryParse(setting, out sequenceCount);
            }

            for (int i = 0; i < sequenceCount; i++)
            {
                if (settings.TryGetValue($"sequence{i}", out setting))
                {
                    Dictionary <string, string> sequenceSettings = setting.ParseKeyValuePairs();
                    SequenceType sequenceType = SequenceType.Read;

                    if (sequenceSettings.TryGetValue("sequenceType", out setting))
                    {
                        Enum.TryParse(setting, true, out sequenceType);
                    }

                    Sequence sequence = new Sequence(sequenceType);
                    int      groupCount;

                    if (sequenceSettings.TryGetValue("groupCount", out setting) && int.TryParse(setting, out groupCount))
                    {
                        for (int j = 0; j < groupCount; j++)
                        {
                            Group group = new Group();

                            if (sequenceSettings.TryGetValue($"groupType{j}", out setting))
                            {
                                Enum.TryParse(setting, true, out group.Type);
                            }

                            if (sequenceSettings.TryGetValue($"groupStartAddress{j}", out setting))
                            {
                                ushort.TryParse(setting, out group.StartAddress);
                            }

                            if (sequenceSettings.TryGetValue($"groupPointCount{j}", out setting))
                            {
                                ushort.TryParse(setting, out group.PointCount);
                            }

                            if (group.StartAddress > 0 && group.PointCount > 0)
                            {
                                // Load any defined write sequence values
                                if (sequence.Type == SequenceType.Write)
                                {
                                    group.DataValues = new ushort[group.PointCount];

                                    for (int k = 0; k < group.PointCount; k++)
                                    {
                                        if (sequenceSettings.TryGetValue($"group{j}DataValue{k}", out setting))
                                        {
                                            ushort.TryParse(setting, out group.DataValues[k]);
                                        }
                                    }
                                }

                                sequence.Groups.Add(group);
                            }
                        }
                    }

                    if (sequence.Groups.Count > 0)
                    {
                        m_sequences.Add(sequence);
                    }
                }
            }

            if (m_sequences.Count == 0)
            {
                throw new InvalidOperationException("No sequences defined, cannot start Modbus polling.");
            }

            // Define synchronized polling operation
            m_pollingOperation = new ShortSynchronizedOperation(PollingOperation, exception => OnProcessException(MessageLevel.Warning, exception));

            // Define polling timer
            m_pollingTimer           = new Timer(m_pollingRate);
            m_pollingTimer.AutoReset = true;
            m_pollingTimer.Elapsed  += m_pollingTimer_Elapsed;
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Initializes <see cref="TimeSeriesProducer"/>.
        /// </summary>
        public override void Initialize()
        {
            base.Initialize();

            Dictionary <string, string> settings = Settings;
            string setting;
            int    intValue;
            double doubleValue;

            // Parse required settings
            if (!settings.TryGetValue(nameof(Servers), out setting) || string.IsNullOrWhiteSpace(setting))
            {
                throw new ArgumentException($"Required \"{nameof(Servers)}\" setting is missing.");
            }

            Servers   = setting.Trim();
            m_servers = Servers.Split(',').Select(uri => new Uri(uri)).ToArray();

            // Parse optional settings
            if (settings.TryGetValue(nameof(Topic), out setting) && !string.IsNullOrWhiteSpace(setting))
            {
                Topic = setting.Trim();
            }
            else
            {
                Topic = TimeSeriesProducer.DefaultTopic;
            }

            if (settings.TryGetValue(nameof(Partitions), out setting) && int.TryParse(setting, out intValue))
            {
                Partitions = intValue;
            }
            else
            {
                Partitions = TimeSeriesProducer.DefaultPartitions;
            }

            if (settings.TryGetValue(nameof(TrackConsumerOffset), out setting))
            {
                TrackConsumerOffset = setting.ParseBoolean();
            }
            else
            {
                TrackConsumerOffset = DefaultTrackConsumerIndex;
            }

            if (!settings.TryGetValue(nameof(ConsumerOffsetFileName), out setting) || string.IsNullOrWhiteSpace(setting))
            {
                setting = Name + ".offset";
            }

            ConsumerOffsetFileName = FilePath.GetAbsolutePath(setting);

            if (settings.TryGetValue(nameof(ConsumerOffsetCacheInterval), out setting) && double.TryParse(setting, out doubleValue))
            {
                ConsumerOffsetCacheInterval = doubleValue;
            }
            else
            {
                ConsumerOffsetCacheInterval = DefaultConsumerOffsetCacheInterval;
            }

            if (settings.TryGetValue(nameof(ReadDelay), out setting) && int.TryParse(setting, out intValue))
            {
                ReadDelay = intValue;
            }
            else
            {
                ReadDelay = DefaultReadDelay;
            }

            if (settings.TryGetValue(nameof(CacheMetadataLocally), out setting))
            {
                CacheMetadataLocally = setting.ParseBoolean();
            }
            else
            {
                CacheMetadataLocally = TimeSeriesProducer.DefaultCacheMetadataLocally;
            }

            if (CacheMetadataLocally)
            {
                m_cacheMetadataLocally = new LongSynchronizedOperation(() => TimeSeriesMetadata.CacheLocally(m_metadata, MetadataTopic, OnStatusMessage))
                {
                    IsBackground = true
                }
            }
            ;

            if ((object)OutputMeasurements != null && OutputMeasurements.Length > 0)
            {
                m_outputMeasurementKeys = new HashSet <MeasurementKey>(OutputMeasurements.Select(m => m.Key));
            }
        }