265 lines · 10.0 KB · C#
RawDownload
//******************************************************************************************************//  SynchronizeLocalClock.cs - Gbtc////  Copyright © 2018, Grid Protection Alliance.  All Rights Reserved.////  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See//  the NOTICE file distributed with this work for additional information regarding copyright ownership.//  The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this//  file except in compliance with the License. You may obtain a copy of the License at:////      http://opensource.org/licenses/MIT////  Unless agreed to in writing, the subject software distributed under the License is distributed on an//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the//  License for the specific language governing permissions and limitations.////  Code Modification History://  ----------------------------------------------------------------------------------------------------//  12/20/2018 - J. Ritchie Carroll//       Generated original version of source code.////****************************************************************************************************** // ReSharper disable InconsistentNaming// ReSharper disable PossibleMultipleEnumeration// ReSharper disable NotAccessedField.Local// ReSharper disable UnusedMember.Global using System;using System.Collections.Generic;using System.ComponentModel;using System.Runtime.InteropServices;using System.Timers;using GSF;using GSF.Diagnostics;using GSF.TimeSeries;using GSF.TimeSeries.Adapters; namespace TestingAdapters{    /// <summary>    /// Represents a class used to synchronize the local system clock time to the time from input measurements.    /// </summary>    [Description("System Time Sync: Synchronizes local system clock time to the time from input measurements")]    public class SynchronizeLocalClock : FacileActionAdapterBase    {        #region [ Members ]         // Nested Types         #pragma warning disable 169        #pragma warning disable 414        #pragma warning disable 649        private struct SYSTEMTIME        {            public ushort wYear;            public ushort wMonth;            public ushort wDayOfWeek;            public ushort wDay;            public ushort wHour;            public ushort wMinute;            public ushort wSecond;            public ushort wMilliseconds;        }        #pragma warning restore 169        #pragma warning restore 414        #pragma warning restore 649         // Constants         /// <summary>        /// Default value for the <see cref="UpdateFrequency"/> property.        /// </summary>        public const int DefaultUpdateFrequency = 1000;         // Fields        private Timer m_updateTimer;        private long m_clockUpdates;        private bool m_goodSourceTime;        private bool m_disposed;         #endregion         #region [ Properties ]         /// <summary>        /// Gets or sets the largest possible value generated by the adapter.        /// </summary>        [ConnectionStringParameter]        [DefaultValue(DefaultUpdateFrequency)]        [Description("Defines the update frequency, in milliseconds, for setting the local system clock time.")]        public int UpdateFrequency { get; set; } = DefaultUpdateFrequency;         /// <summary>        /// Gets or sets flag that determines whether or not to use the local clock time as real time.        /// </summary>        /// <remarks>        /// Use your local system clock as real time only if the time is locally GPS-synchronized,        /// or if the measurement values being sorted were not measured relative to a GPS-synchronized clock.        /// Turn this off if the class is intended to process historical data.        /// </remarks>        [EditorBrowsable(EditorBrowsableState.Never)] // Redeclared to hide property - value should not be changed by user        public override bool UseLocalClockAsRealTime        {            get => base.UseLocalClockAsRealTime;            set => base.UseLocalClockAsRealTime = value;        }         /// <summary>        /// Gets or sets flag to start tracking the absolute latest received measurement values.        /// </summary>        /// <remarks>        /// Latest received measurement value will be available via the <see cref="FacileActionAdapterBase.LatestMeasurements"/> property.        /// </remarks>        [EditorBrowsable(EditorBrowsableState.Never)] // Redeclared to hide property - value should not be changed by user        public override bool TrackLatestMeasurements        {            get => base.TrackLatestMeasurements;            set => base.TrackLatestMeasurements = value;        }         /// <summary>        /// Gets the flag indicating if this adapter supports temporal processing.        /// </summary>        public override bool SupportsTemporalProcessing => false;         #endregion         #region [ Methods ]         /// <summary>        /// Releases the unmanaged resources used by the <see cref="SynchronizeLocalClock"/> object and optionally releases the managed resources.        /// </summary>        /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>        protected override void Dispose(bool disposing)        {            if (!m_disposed)            {                try                {                    if (disposing)                    {                        if (m_updateTimer != null)                        {                            m_updateTimer.Stop();                            m_updateTimer.Elapsed -= m_updateTimer_Elapsed;                            m_updateTimer.Dispose();                        }                    }                }                finally                {                    m_disposed = true;          // Prevent duplicate dispose.                    base.Dispose(disposing);    // Call base class Dispose().                }            }        }         /// <summary>        /// Initializes <see cref="SynchronizeLocalClock"/>.        /// </summary>        public override void Initialize()        {            Dictionary<string, string> settings = Settings;             // Force facile adapter to use incoming timestamps as time source, i.e., "RealTime"            settings[nameof(UseLocalClockAsRealTime)] = false.ToString();            settings[nameof(TrackLatestMeasurements)] = true.ToString();             base.Initialize();             if (settings.TryGetValue(nameof(UpdateFrequency), out string setting))            {                if (int.TryParse(setting, out int updateFrequency) && updateFrequency > 0)                    UpdateFrequency = updateFrequency;            }             m_updateTimer = new Timer(UpdateFrequency);            m_updateTimer.Elapsed += m_updateTimer_Elapsed;            m_updateTimer.Start();        }         /// <summary>        /// Gets a short one-line status of this <see cref="AdapterBase"/>.        /// </summary>        /// <param name="maxLength">Maximum number of available characters for display.</param>        /// <returns>A short one-line summary of the current status of this <see cref="AdapterBase"/>.</returns>        public override string GetShortStatus(int maxLength) => $"Updated clock {m_clockUpdates:N3} times so far...".CenterText(maxLength);         /// <summary>        /// Queues a collection of measurements for processing.        /// </summary>        /// <param name="measurements">Measurements to queue for processing.</param>        public override void QueueMeasurementsForProcessing(IEnumerable<IMeasurement> measurements)        {            List<IMeasurement> measurementsWithGoodTime = new List<IMeasurement>();             foreach (IMeasurement measurement in measurements)            {                if (measurement.TimestampQualityIsGood())                    measurementsWithGoodTime.Add(measurement);            }             if (measurementsWithGoodTime.Count == 0)            {                base.QueueMeasurementsForProcessing(measurements);                m_goodSourceTime = false;            }            else            {                base.QueueMeasurementsForProcessing(measurementsWithGoodTime);                m_goodSourceTime = true;            }        }         private void m_updateTimer_Elapsed(object sender, ElapsedEventArgs e)        {            try            {                Ticks newSystemTime = RealTime;                 if (newSystemTime <= 0L)                    return;                 SetSystemTime(RealTime);                m_clockUpdates++;                 if (!m_goodSourceTime)                    OnStatusMessage(MessageLevel.Warning, "WARNING: Clock set with measurement that has bad quality -- increase measurement sources.");            }            catch (Exception ex)            {                OnProcessException(MessageLevel.Error, ex);            }        }         #endregion         #region [ Static ]         // Static Methods         [DllImport("kernel32.dll", SetLastError = true)]        private static extern bool SetSystemTime(ref SYSTEMTIME lpSystemTime);         private static void SetSystemTime(DateTime newSystemTime)        {            SYSTEMTIME systime = new SYSTEMTIME            {                wYear = (ushort)newSystemTime.Year,                wMonth = (ushort)newSystemTime.Month,                wDay = (ushort)newSystemTime.Day,                wHour = (ushort)newSystemTime.Hour,                wMinute = (ushort)newSystemTime.Minute,                wSecond = (ushort)newSystemTime.Second,                wMilliseconds = (ushort)newSystemTime.Millisecond            };             if (!SetSystemTime(ref systime))                throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to set local system time, verify service has SE_SYSTEMTIME_NAME privilege.");        }         #endregion    }}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t