예제 #1
0
 /// <summary>
 /// Creates a new <see cref="ConnectionParameters"/>.
 /// </summary>
 public ConnectionParameters()
 {
     m_timeOffset = Common.DefaultTimeOffset;
     m_frameRate = Common.DefaultFrameRate;
     m_nominalFrequency = Common.DefaultNominalFrequency;
     m_stationName = Common.DefaultStationName;
 }
예제 #2
0
 /// <summary>
 /// Creates a new <see cref="ConnectionParameters"/> from serialization parameters.
 /// </summary>
 /// <param name="info">The <see cref="SerializationInfo"/> with populated with data.</param>
 /// <param name="context">The source <see cref="StreamingContext"/> for this deserialization.</param>
 protected ConnectionParameters(SerializationInfo info, StreamingContext context)
 {
     // Deserialize connection parameters
     m_timeOffset = info.GetInt64("timeOffset");
     m_frameRate = info.GetUInt16("frameRate");
     m_nominalFrequency = (LineFrequency)info.GetValue("nominalFrequency", typeof(LineFrequency));
     m_stationName = info.GetString("stationName");
 }
예제 #3
0
 /// <summary>
 /// Creates a new <see cref="ConnectionParameters"/> from serialization parameters.
 /// </summary>
 /// <param name="info">The <see cref="SerializationInfo"/> with populated with data.</param>
 /// <param name="context">The source <see cref="StreamingContext"/> for this deserialization.</param>
 protected ConnectionParameters(SerializationInfo info, StreamingContext context)
 {
     // Deserialize connection parameters
     m_timeOffset = info.GetOrDefault("timeOffset", Common.DefaultTimeOffset);
     m_frameRate = info.GetOrDefault("frameRate", Common.DefaultFrameRate);
     m_nominalFrequency = info.GetOrDefault("nominalFrequency", Common.DefaultNominalFrequency);
     m_stationName = info.GetOrDefault("stationName", Common.DefaultStationName);
 }
예제 #4
0
        /// <summary>
        /// Creates a new <see cref="ConfigurationCellBase"/> from specified parameters.
        /// </summary>
        /// <param name="parent">The reference to parent <see cref="IConfigurationFrame"/> of this <see cref="ConfigurationCellBase"/>.</param>
        /// <param name="idCode">The numeric ID code for this <see cref="ConfigurationCellBase"/>.</param>
        /// <param name="maximumPhasors">Sets the maximum number of phasors for the <see cref="PhasorDefinitions"/> collection.</param>
        /// <param name="maximumAnalogs">Sets the maximum number of phasors for the <see cref="AnalogDefinitions"/> collection.</param>
        /// <param name="maximumDigitals">Sets the maximum number of phasors for the <see cref="DigitalDefinitions"/> collection.</param>
        protected ConfigurationCellBase(IConfigurationFrame parent, ushort idCode, int maximumPhasors, int maximumAnalogs, int maximumDigitals)
            : base(parent, idCode)
        {
            m_nominalFrequency = LineFrequency.Hz60; // Defaulting to 60Hz

            // We convert maximum counts to last valid indicies (count - 1):
            m_phasorDefinitions = new PhasorDefinitionCollection(maximumPhasors - 1);
            m_analogDefinitions = new AnalogDefinitionCollection(maximumAnalogs - 1);
            m_digitalDefinitions = new DigitalDefinitionCollection(maximumDigitals - 1);
        }
예제 #5
0
 /// <summary>
 /// Creates a new <see cref="ConfigurationCellBase"/> from serialization parameters.
 /// </summary>
 /// <param name="info">The <see cref="SerializationInfo"/> with populated with data.</param>
 /// <param name="context">The source <see cref="StreamingContext"/> for this deserialization.</param>
 protected ConfigurationCellBase(SerializationInfo info, StreamingContext context)
     : base(info, context)
 {
     // Deserialize configuration cell values
     StationName = info.GetString("stationName");
     IDLabel = info.GetString("idLabel");
     m_phasorDefinitions = (PhasorDefinitionCollection)info.GetValue("phasorDefinitions", typeof(PhasorDefinitionCollection));
     m_frequencyDefinition = (IFrequencyDefinition)info.GetValue("frequencyDefinition", typeof(IFrequencyDefinition));
     m_analogDefinitions = (AnalogDefinitionCollection)info.GetValue("analogDefinitions", typeof(AnalogDefinitionCollection));
     m_digitalDefinitions = (DigitalDefinitionCollection)info.GetValue("digitalDefinitions", typeof(DigitalDefinitionCollection));
     m_nominalFrequency = (LineFrequency)info.GetValue("nominalFrequency", typeof(LineFrequency));
     m_revisionCount = info.GetUInt16("revisionCount");
 }
예제 #6
0
        /// <summary>
        /// Creates a new <see cref="ConfigurationFrame"/> from specified parameters.
        /// </summary>
        /// <param name="idCode">The ID code of this <see cref="ConfigurationFrame"/>.</param>
        /// <param name="timestamp">The exact timestamp, in <see cref="Ticks"/>, of the data represented by this <see cref="ConfigurationFrame"/>.</param>
        /// <param name="frameRate">The defined frame rate of this <see cref="ConfigurationFrame"/>.</param>
        /// <param name="nominalFrequency">The nominal <see cref="LineFrequency"/> of this <see cref="ConfigurationFrame"/>.</param>
        /// <param name="timeOffset">The time offset of F-NET device in <see cref="Ticks"/>.</param>
        /// <param name="stationName">The station name of the F-NET device.</param>
        /// <remarks>
        /// This constructor is used by a consumer to generate an F-NET configuration frame.
        /// </remarks>
        public ConfigurationFrame(ushort idCode, Ticks timestamp, ushort frameRate, LineFrequency nominalFrequency, Ticks timeOffset, string stationName)
            : base(idCode, new ConfigurationCellCollection(), timestamp, frameRate)
        {
            ConfigurationCell configCell = new ConfigurationCell(this, nominalFrequency, timeOffset);

            // FNet protocol sends data for one device
            Cells.Add(configCell);

            // Assign station name
            configCell.StationName = string.IsNullOrEmpty(stationName) ? $"F-NET Unit-{idCode}" : stationName;

            // Add a single frequency definition
            configCell.FrequencyDefinition = new FrequencyDefinition(configCell, "Line frequency");

            // Add a single phasor definition
            configCell.PhasorDefinitions.Add(new PhasorDefinition(configCell, "120V Phasor", PhasorType.Voltage, null));
        }
예제 #7
0
        /// <summary>
        /// Creates a new <see cref="ConfigurationFrame"/> from specified parameters.
        /// </summary>
        /// <param name="idCode">The ID code of this <see cref="ConfigurationFrame"/>.</param>
        /// <param name="timestamp">The exact timestamp, in <see cref="Ticks"/>, of the data represented by this <see cref="ConfigurationFrame"/>.</param>
        /// <param name="frameRate">The defined frame rate of this <see cref="ConfigurationFrame"/>.</param>
        /// <param name="nominalFrequency">The nominal <see cref="LineFrequency"/> of this <see cref="ConfigurationFrame"/>.</param>
        /// <param name="timeOffset">The time offset of F-NET device in <see cref="Ticks"/>.</param>
        /// <param name="stationName">The station name of the F-NET device.</param>
        /// <remarks>
        /// This constructor is used by a consumer to generate an F-NET configuration frame.
        /// </remarks>
        public ConfigurationFrame(ushort idCode, Ticks timestamp, ushort frameRate, LineFrequency nominalFrequency, Ticks timeOffset, string stationName)
            : base(idCode, new ConfigurationCellCollection(), timestamp, frameRate)
        {
            ConfigurationCell configCell = new ConfigurationCell(this, nominalFrequency, timeOffset);

            // FNet protocol sends data for one device
            Cells.Add(configCell);

            // Assign station name
            if (string.IsNullOrEmpty(stationName))
                configCell.StationName = "F-NET Unit-" + idCode;
            else
                configCell.StationName = stationName;

            // Add a single frequency definition
            configCell.FrequencyDefinition = new FrequencyDefinition(configCell, "Line frequency");

            // Add a single phasor definition
            configCell.PhasorDefinitions.Add(new PhasorDefinition(configCell, "120V Phasor", PhasorType.Voltage, null));
        }
예제 #8
0
 /// <summary>
 /// Creates a new <see cref="ConfigurationCell"/> from specified parameters.
 /// </summary>
 /// <param name="parent">The reference to parent <see cref="ConfigurationFrame1"/> of this <see cref="ConfigurationCell"/>.</param>
 /// <param name="idCode">The numeric ID code for this <see cref="ConfigurationCell"/>.</param>
 /// <param name="nominalFrequency">The nominal <see cref="LineFrequency"/> of the <see cref="FrequencyDefinition"/> of this <see cref="ConfigurationCell"/>.</param>
 public ConfigurationCell(ConfigurationFrame1 parent, ushort idCode, LineFrequency nominalFrequency)
     : this(parent)
 {
     IDCode           = idCode;
     NominalFrequency = nominalFrequency;
 }
예제 #9
0
 /// <summary>
 /// Creates a new <see cref="ConfigurationCell"/> from specified parameters.
 /// </summary>
 /// <param name="parent">The reference to parent <see cref="ConfigurationFrame"/> of this <see cref="ConfigurationCell"/>.</param>
 /// <param name="idCode">The numeric ID code for this <see cref="ConfigurationCell"/>.</param>
 /// <param name="nominalFrequency">The nominal <see cref="LineFrequency"/> of the <see cref="FrequencyDefinition"/> of this <see cref="ConfigurationCell"/>.</param>
 public ConfigurationCell(ConfigurationFrame parent, ushort idCode, LineFrequency nominalFrequency)
     : this(parent)
 {
     IDCode = idCode;
     NominalFrequency = nominalFrequency;
 }
예제 #10
0
        /// <summary>
        /// Creates a new <see cref="FrameParser"/>.
        /// </summary>
        /// <param name="checkSumValidationFrameTypes">Frame types that should perform check-sum validation; default to <see cref="GSF.PhasorProtocols.CheckSumValidationFrameTypes.AllFrames"/></param>
        /// <param name="trustHeaderLength">Determines if header lengths should be trusted over parsed byte count.</param>
        /// <param name="frameRate">The defined frame rate of this <see cref="ConfigurationFrame"/>.</param>
        /// <param name="nominalFrequency">The nominal <see cref="LineFrequency"/> of this <see cref="ConfigurationFrame"/>.</param>
        /// <param name="timeOffset">The time offset of F-NET device in <see cref="Ticks"/>.</param>
        /// <param name="stationName">The station name of the F-NET device.</param>
        public FrameParser(CheckSumValidationFrameTypes checkSumValidationFrameTypes = CheckSumValidationFrameTypes.AllFrames, bool trustHeaderLength = true, ushort frameRate = Common.DefaultFrameRate, LineFrequency nominalFrequency = Common.DefaultNominalFrequency, long timeOffset = Common.DefaultTimeOffset, string stationName = Common.DefaultStationName)
            : base(checkSumValidationFrameTypes, trustHeaderLength)
        {
            // Initialize protocol synchronization bytes for this frame parser
            base.ProtocolSyncBytes = new[] { Common.StartByte };

            FrameRate        = frameRate;
            NominalFrequency = nominalFrequency;
            TimeOffset       = timeOffset;
            StationName      = stationName;
        }
예제 #11
0
        private int m_numberOfSatellites = 1; // We'll initially assume synchronization is good until told otherwise

        #endregion

        #region [ Constructors ]

        /// <summary>
        /// Creates a new <see cref="ConfigurationCell"/> from specified parameters.
        /// </summary>
        /// <param name="parent">The reference to parent <see cref="ConfigurationFrame"/> of this <see cref="ConfigurationCell"/>.</param>
        /// <param name="nominalFrequency">The nominal <see cref="LineFrequency"/> of the <see cref="FrequencyDefinition"/> of this <see cref="ConfigurationCell"/>.</param>
        /// <param name="timeOffset">The time offset of F-NET device in <see cref="Ticks"/>.</param>
        internal ConfigurationCell(ConfigurationFrame parent, LineFrequency nominalFrequency, Ticks timeOffset)
            : base(parent, parent.IDCode, Common.MaximumPhasorValues, Common.MaximumAnalogValues, Common.MaximumDigitalValues)
        {
            NominalFrequency = nominalFrequency;
            m_timeOffset = timeOffset;
        }
예제 #12
0
        public static ConfigurationFrame Parse(string configFile, ShowMessageFunc showMessage)
        {
            string[] rows = File.ReadAllLines(configFile);

            Dictionary <string, string> configSettings = rows
                                                         .Select(row => row.Split('='))
                                                         .ToDictionary(key => key[0], value => value[1], StringComparer.OrdinalIgnoreCase);

            // Fixed for now
            LineFrequency nominalFrequency = LineFrequency.Hz60;

            // Load server name setting
            string serverName = configSettings["IPAddr"];

            // Load ID code setting
            if (!ushort.TryParse(configSettings["IdCode"], out ushort idCode))
            {
                idCode = DefaultIDCode;
            }

            // Load frame rate setting
            if (!ushort.TryParse(configSettings["DataRate"], out ushort frameRate))
            {
                frameRate = DefaultFrameRate;
            }

            // With an ID code, frame rate and server name, there's enough info to create a config frame
            ConfigurationFrame configFrame = new(idCode, frameRate, serverName);

            // Load all output PMUs
            int index = -1;

            while (configSettings.TryGetValue($"PmuId{++index}", out string setting) && ushort.TryParse(setting, out idCode))
            {
                string name = configSettings[$"PmuStn{index}"];

                if (string.IsNullOrWhiteSpace(name))
                {
                    continue;
                }

                // With a name and an ID code, there's enough info to create a config cell representing the PMU
                ConfigurationCell configCell = new(configFrame, name, idCode)
                {
                    NominalFrequency = nominalFrequency,
                };

                name = "VaChan";
                PhasorType phasorType  = PhasorType.Voltage;
                char       phase       = 'A';
                string     description = $"{configCell.StationName} phase {phase} {phasorType.ToString().ToLowerInvariant()} phasor";
                configCell.PhasorDefinitions.Add(new PhasorDefinition(configCell, name, description, phasorType, phase));

                name        = "VbChan";
                phasorType  = PhasorType.Voltage;
                phase       = 'B';
                description = $"{configCell.StationName} phase {phase} {phasorType.ToString().ToLowerInvariant()} phasor";
                configCell.PhasorDefinitions.Add(new PhasorDefinition(configCell, name, description, phasorType, phase));

                name        = "VcChan";
                phasorType  = PhasorType.Voltage;
                phase       = 'C';
                description = $"{configCell.StationName} phase {phase} {phasorType.ToString().ToLowerInvariant()} phasor";
                configCell.PhasorDefinitions.Add(new PhasorDefinition(configCell, name, description, phasorType, phase));

                name        = "IaChan";
                phasorType  = PhasorType.Current;
                phase       = 'A';
                description = $"{configCell.StationName} phase {phase} {phasorType.ToString().ToLowerInvariant()} phasor";
                configCell.PhasorDefinitions.Add(new PhasorDefinition(configCell, name, description, phasorType, phase));

                name        = "IbChan";
                phasorType  = PhasorType.Current;
                phase       = 'B';
                description = $"{configCell.StationName} phase {phase} {phasorType.ToString().ToLowerInvariant()} phasor";
                configCell.PhasorDefinitions.Add(new PhasorDefinition(configCell, name, description, phasorType, phase));

                name        = "IcChan";
                phasorType  = PhasorType.Current;
                phase       = 'C';
                description = $"{configCell.StationName} phase {phase} {phasorType.ToString().ToLowerInvariant()} phasor";
                configCell.PhasorDefinitions.Add(new PhasorDefinition(configCell, name, description, phasorType, phase));

                name        = "InChan";
                phasorType  = PhasorType.Current;
                phase       = 'N';
                description = $"{configCell.StationName} phase {phase} {phasorType.ToString().ToLowerInvariant()} phasor";
                configCell.PhasorDefinitions.Add(new PhasorDefinition(configCell, name, description, phasorType, phase));

                configFrame.Cells.Add(configCell);
            }


            // Get connection details configured for APP PDC
            configFrame.TransportProtocol = DefaultTransportProtocol;

            if (!ushort.TryParse(configSettings["PortTCP"], out ushort port))
            {
                port = DefaultPort;
            }

            //if (!ushort.TryParse(configSettings["PortUDP"], out ushort dataPort))
            //    dataPort = DefaultDataPort;

            // Setup MultiProtocolFrameParser style connection string
            Dictionary <string, string> getTcpSettings(bool commandChannel = false)
            {
                // Use of simple "protocol" key in commandChannel and separation of
                // server/port keys are required to create a proper "PmuConnection"
                // file that can be successfully parsed by the PMU Connection Tester
                return(new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase)
                {
                    [commandChannel ? "protocol": nameof(TransportProtocol)] = nameof(TransportProtocol.Tcp),
                    ["server"] = IPAddressToken,
                    ["port"] = $"{port}",
                    ["isListener"] = "false",
                    ["interface"] = "0.0.0.0"
                });
            }

            Dictionary <string, string> settings = configFrame.Settings;

            settings[nameof(PhasorProtocol)] = nameof(PhasorProtocol.IEEEC37_118V1);

            foreach (KeyValuePair <string, string> pair in getTcpSettings())
            {
                settings[pair.Key] = pair.Value;
            }

            // Save device IP configuration
            Dictionary <string, string> deviceIPs = configFrame.DeviceIPs;

            deviceIPs[serverName]      = serverName;
            configFrame.TargetDeviceIP = serverName;

            return(configFrame);
        }
예제 #13
0
        /// <summary>
        /// Initializes <see cref="PhasorDataConcentratorBase"/>.
        /// </summary>
        public override void Initialize()
        {
            base.Initialize();

            Dictionary<string, string> settings = Settings;
            string setting, commandChannel;

            // Load required parameters
            m_idCode = ushort.Parse(settings["IDCode"]);

            // Load optional parameters
            settings.TryGetValue("commandChannel", out commandChannel);

            if (settings.TryGetValue("autoPublishConfigFrame", out setting))
                m_autoPublishConfigurationFrame = setting.ParseBoolean();
            else
                m_autoPublishConfigurationFrame = !string.IsNullOrEmpty(commandChannel);

            if (settings.TryGetValue("autoStartDataChannel", out setting))
                m_autoStartDataChannel = setting.ParseBoolean();
            else
                m_autoStartDataChannel = true;

            if (settings.TryGetValue("nominalFrequency", out setting))
                m_nominalFrequency = (LineFrequency)int.Parse(setting);
            else
                m_nominalFrequency = LineFrequency.Hz60;

            // Initialize data channel
            this.DataChannel = new UdpServer(ConnectionString);

            // Initialize command channel if defined
            if (!string.IsNullOrEmpty(commandChannel))
                this.CommandChannel = new TcpServer(commandChannel);
            else
                this.CommandChannel = null;

            // Create the configuration frame
            UpdateConfiguration();
        }
예제 #14
0
 /// <summary>
 /// Creates a new <see cref="ConfigurationCell3"/> from specified parameters.
 /// </summary>
 /// <param name="parent">The reference to parent <see cref="ConfigurationFrame1"/> of this <see cref="ConfigurationCell3"/>.</param>
 /// <param name="idCode">The numeric ID code for this <see cref="ConfigurationCell3"/>.</param>
 /// <param name="nominalFrequency">The nominal <see cref="LineFrequency"/> of the <see cref="FrequencyDefinition"/> of this <see cref="ConfigurationCell3"/>.</param>
 public ConfigurationCell3(ConfigurationFrame1 parent, ushort idCode, LineFrequency nominalFrequency) //FIXME: Does this need to use config frame 3?
     : this(parent)
 {
     IDCode           = idCode;
     NominalFrequency = nominalFrequency;
 }
예제 #15
0
        // Static Methods

        /// <summary>
        /// Creates a new IEC 61850-90-5 (i.e., IEEE C37.118) <see cref="ConfigurationFrame"/> based on provided protocol independent <paramref name="baseConfigurationFrame"/>.
        /// </summary>
        /// <param name="baseConfigurationFrame">Protocol independent <see cref="GSF.PhasorProtocols.Anonymous.ConfigurationFrame"/>.</param>
        /// <param name="timeBase">Timebase to use for fraction second resolution.</param>
        /// <param name="nominalFrequency">The nominal <see cref="LineFrequency"/> to use for the new <see cref="ConfigurationFrame"/></param>.
        /// <returns>A new IEEE C37.118 <see cref="ConfigurationFrame"/>.</returns>
        public static ConfigurationFrame CreateConfigurationFrame(GSF.PhasorProtocols.Anonymous.ConfigurationFrame baseConfigurationFrame, uint timeBase, LineFrequency nominalFrequency)
        {
            ConfigurationCell newCell;
            uint maskValue;

            // Create a new IEEE C37.118 configuration frame 2 using base configuration
            ConfigurationFrame configurationFrame = new ConfigurationFrame(timeBase, baseConfigurationFrame.IDCode, DateTime.UtcNow.Ticks, baseConfigurationFrame.FrameRate);

            foreach (GSF.PhasorProtocols.Anonymous.ConfigurationCell baseCell in baseConfigurationFrame.Cells)
            {
                // Create a new IEEE C37.118 configuration cell (i.e., a PMU configuration)
                newCell = new ConfigurationCell(configurationFrame, baseCell.IDCode, nominalFrequency);

                // Update other cell level attributes
                newCell.StationName            = baseCell.StationName;
                newCell.IDLabel                = baseCell.IDLabel;
                newCell.PhasorDataFormat       = baseCell.PhasorDataFormat;
                newCell.PhasorCoordinateFormat = baseCell.PhasorCoordinateFormat;
                newCell.FrequencyDataFormat    = baseCell.FrequencyDataFormat;
                newCell.AnalogDataFormat       = baseCell.AnalogDataFormat;

                // Add phasor definitions
                foreach (IPhasorDefinition phasorDefinition in baseCell.PhasorDefinitions)
                {
                    newCell.PhasorDefinitions.Add(new PhasorDefinition(newCell, phasorDefinition.Label, phasorDefinition.ScalingValue, phasorDefinition.Offset, phasorDefinition.PhasorType, null));
                }

                // Add frequency definition
                newCell.FrequencyDefinition = new FrequencyDefinition(newCell, baseCell.FrequencyDefinition.Label);

                // Add analog definitions
                foreach (IAnalogDefinition analogDefinition in baseCell.AnalogDefinitions)
                {
                    newCell.AnalogDefinitions.Add(new AnalogDefinition(newCell, analogDefinition.Label, analogDefinition.ScalingValue, analogDefinition.Offset, analogDefinition.AnalogType));
                }

                // Add digital definitions
                foreach (IDigitalDefinition digitalDefinition in baseCell.DigitalDefinitions)
                {
                    // Attempt to derive user defined mask value if available
                    DigitalDefinition anonymousDigitalDefinition = digitalDefinition as DigitalDefinition;

                    if (anonymousDigitalDefinition != null)
                    {
                        maskValue = anonymousDigitalDefinition.MaskValue;
                    }
                    else
                    {
                        maskValue = 0U;
                    }

                    newCell.DigitalDefinitions.Add(new GSF.PhasorProtocols.IEC61850_90_5.DigitalDefinition(newCell, digitalDefinition.Label, maskValue.LowWord(), maskValue.HighWord()));
                }

                // Add new PMU configuration (cell) to protocol specific configuration frame
                configurationFrame.Cells.Add(newCell);
            }

            return(configurationFrame);
        }
예제 #16
0
        /// <summary>
        /// Initializes <see cref="PhasorDataConcentratorBase"/>.
        /// </summary>
        public override void Initialize()
        {
            base.Initialize();
            const string errorMessage = "{0} is missing from Settings - Example: IDCode=235; dataChannel={{Port=0; Clients=localhost:8800}}";

            Dictionary<string, string> settings = Settings;
            string setting, dataChannel, commandChannel;

            // Load required parameters
            if (!settings.TryGetValue("IDCode", out setting))
                throw new ArgumentException(string.Format(errorMessage, "IDCode"));

            m_idCode = ushort.Parse(setting);
            settings.TryGetValue("dataChannel", out dataChannel);
            settings.TryGetValue("commandChannel", out commandChannel);

            // Data channel and/or command channel must be defined
            if (string.IsNullOrEmpty(dataChannel) && string.IsNullOrEmpty(commandChannel))
                throw new InvalidOperationException("A data channel or command channel must be defined for a concentrator.");

            // Load optional parameters
            if (settings.TryGetValue("autoPublishConfigFrame", out setting))
                m_autoPublishConfigurationFrame = setting.ParseBoolean();
            else
                m_autoPublishConfigurationFrame = string.IsNullOrEmpty(commandChannel);

            if (settings.TryGetValue("autoStartDataChannel", out setting))
                m_autoStartDataChannel = setting.ParseBoolean();
            else
                m_autoStartDataChannel = true;

            if (settings.TryGetValue("nominalFrequency", out setting))
                m_nominalFrequency = (LineFrequency)int.Parse(setting);
            else
                m_nominalFrequency = LineFrequency.Hz60;

            if (settings.TryGetValue("dataFormat", out setting))
                m_dataFormat = (DataFormat)Enum.Parse(typeof(DataFormat), setting, true);
            else
                m_dataFormat = DataFormat.FloatingPoint;

            if (settings.TryGetValue("coordinateFormat", out setting))
                m_coordinateFormat = (CoordinateFormat)Enum.Parse(typeof(CoordinateFormat), setting, true);
            else
                m_coordinateFormat = CoordinateFormat.Polar;

            if (settings.TryGetValue("currentScalingValue", out setting))
            {
                if (!uint.TryParse(setting, out m_currentScalingValue))
                    m_currentScalingValue = unchecked((uint)int.Parse(setting));
            }
            else
            {
                m_currentScalingValue = 2423U;
            }

            if (settings.TryGetValue("voltageScalingValue", out setting))
            {
                if (!uint.TryParse(setting, out m_voltageScalingValue))
                    m_voltageScalingValue = unchecked((uint)int.Parse(setting));
            }
            else
            {
                m_voltageScalingValue = 2725785U;
            }

            if (settings.TryGetValue("analogScalingValue", out setting))
            {
                if (!uint.TryParse(setting, out m_analogScalingValue))
                    m_analogScalingValue = unchecked((uint)int.Parse(setting));
            }
            else
            {
                m_analogScalingValue = 1373291U;
            }

            if (settings.TryGetValue("digitalMaskValue", out setting))
            {
                if (!uint.TryParse(setting, out m_digitalMaskValue))
                    m_digitalMaskValue = unchecked((uint)int.Parse(setting));
            }
            else
            {
                m_digitalMaskValue = Word.MakeDoubleWord(0xFFFF, 0x0000);
            }

            if (settings.TryGetValue("processDataValidFlag", out setting))
                m_processDataValidFlag = setting.ParseBoolean();
            else
                m_processDataValidFlag = true;

            if (settings.TryGetValue("addPhaseLabelSuffix", out setting))
                m_addPhaseLabelSuffix = setting.ParseBoolean();
            else
                m_addPhaseLabelSuffix = true;

            if (settings.TryGetValue("replaceWithSpaceChar", out setting))
            {
                if (!string.IsNullOrWhiteSpace(setting) && setting.Length > 0)
                    m_replaceWithSpaceChar = setting[0];
                else
                    m_replaceWithSpaceChar = Char.MinValue;
            }
            else
            {
                m_replaceWithSpaceChar = Char.MinValue;
            }

            if (settings.TryGetValue("useAdjustedValue", out setting))
                m_useAdjustedValue = Boolean.Parse(setting);
            else
                m_useAdjustedValue = true;

            // Initialize data channel if defined
            if (!string.IsNullOrEmpty(dataChannel))
                this.DataChannel = new UdpServer(dataChannel);
            else
                this.DataChannel = null;

            // Initialize command channel if defined
            if (!string.IsNullOrEmpty(commandChannel))
                this.CommandChannel = new TcpServer(commandChannel);
            else
                this.CommandChannel = null;

            // Create the configuration frame
            UpdateConfiguration();

            // Register with the statistics engine
            StatisticsEngine.Register(this, "OutputStream", "OS");
            StatisticsEngine.Calculated += (sender, args) => ResetLatencyCounters();
            StatisticsEngine.Calculated += (sender, args) => ResetMeasurementsPerSecondCounters();
        }
예제 #17
0
        public static ConfigurationFrame Parse(string configFile, ShowMessageFunc showMessage)
        {
            XDocument config = XDocument.Load(configFile);

            // Load all "SettingsGroup" elements
            XElement[] settingsGroups = config.Descendants("SettingsGroup").ToArray();

            // Load nominal frequency from "Globals" setting group
            string nominalFrequencySetting = settingsGroups
                                             .WhereAttribute("Type").Is("Globals")
                                             .Descendants("Setting")
                                             .WhereAttribute("Name").Is("Frequency")
                                             .GetValue(DefaultLineFrequency);

            LineFrequency nominalFrequency = nominalFrequencySetting.Equals("50") ?
                                             LineFrequency.Hz50 :
                                             LineFrequency.Hz60;

            // Get server gateway instances
            XElement[] serverGatewayInstances = settingsGroups
                                                .WhereAttribute("Type").Is("ServerGateway")
                                                .Descendants("Instance")
                                                .WhereAttribute("Type").Is("Server")
                                                .ToArray();

            if (serverGatewayInstances.Length == 0)
            {
                throw new NullReferenceException($"No server gateway instances where defined in \"{Path.GetFileName(configFile)}\".");
            }

            int enabledInstanceCount = serverGatewayInstances
                                       .Count(elem => elem.Descendants("Setting")
                                              .WhereAttribute("Name").Is("Enabled")
                                              .GetValue(false));

            XElement serverGatewayInstance = null;

            if (enabledInstanceCount == 0)
            {
                if (showMessage($"No enabled server gateway instances where found in \"{Path.GetFileName(configFile)}\", do you want to load a disabled instance?", "No Enabled Server Gateways Found", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
                {
                    throw new NullReferenceException("Failed to load an enabled server gateway instance.");
                }

                serverGatewayInstance = serverGatewayInstances.FirstOrDefault();
            }
            else
            {
                if (enabledInstanceCount > 1 && showMessage($"Found {enabledInstanceCount:N0} enabled server gateway instances in \"{Path.GetFileName(configFile)}\", do you want to load first enabled instance?", "Multiple Enabled Server Gateways Found", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
                {
                    throw new NullReferenceException("Failed to load an enabled server gateway instance.");
                }

                serverGatewayInstance = serverGatewayInstances
                                        .FirstOrDefault(elem => elem.Descendants("Setting")
                                                        .WhereAttribute("Name").Is("Enabled")
                                                        .GetValue(false));
            }

            if (serverGatewayInstance is null)
            {
                throw new NullReferenceException("Failed to load any server gateway instance.");
            }

            // Load all "Setting" elements from server gateway instance
            XElement[] serverGatewaySettings = serverGatewayInstance
                                               .Descendants("Setting")
                                               .ToArray();

            // Load server name setting
            string serverName = Path.GetFileNameWithoutExtension(configFile).GetCleanAcronym();

            // Load ID code setting
            ushort idCode = serverGatewaySettings
                            .WhereAttribute("Name").Is("ID")
                            .GetValue(DefaultIDCode);

            // Load frame rate setting
            ushort frameRate = serverGatewaySettings
                               .WhereAttribute("Name").Is("DataRate")
                               .GetValue(DefaultFrameRate);

            // With an ID code, frame rate and server name, there's enough info to create a config frame
            ConfigurationFrame configFrame = new ConfigurationFrame(idCode, frameRate, serverName);

            // Load all output PMUs
            IEnumerable <XElement> pmus = serverGatewaySettings
                                          .WhereAttribute("Name").Is("OutputTags")
                                          .Descendants("PMU");

            foreach (XElement pmu in pmus)
            {
                string name = pmu.Attribute("Name")?.Value;

                if (string.IsNullOrWhiteSpace(name))
                {
                    continue;
                }

                if (!ushort.TryParse(pmu.Attribute("ID")?.Value, out idCode))
                {
                    continue;
                }

                // With a name and an ID code, there's enough info to create a config cell representing the PMU
                ConfigurationCell configCell = new ConfigurationCell(configFrame, name, idCode)
                {
                    NominalFrequency = nominalFrequency,
                };

                // Load all PMU tags
                XElement[] tags = pmu.Descendants("Tag").ToArray();

                // Load all phasor tags
                IEnumerable <XElement> phasors = tags
                                                 .WhereAttribute("Type").Is("Phasor");

                foreach (XElement phasor in phasors)
                {
                    name = phasor.Attribute("Name")?.Value;

                    if (string.IsNullOrWhiteSpace(name))
                    {
                        continue;
                    }

                    string description = phasor.Attribute("Description")?.Value;

                    string quantityType = phasor.Attribute("QuantityType")?.Value ?? DefaultPhasorType;

                    PhasorType phasorType = quantityType.Equals("Current") ?
                                            PhasorType.Current :
                                            PhasorType.Voltage;

                    string phaseSetting = phasor.Attribute("Phase")?.Value.Trim();

                    if (string.IsNullOrWhiteSpace(phaseSetting))
                    {
                        phaseSetting = GuessPhase(phasor.Attribute("OriginalName")?.Value ?? name);
                    }

                    char phase = string.IsNullOrWhiteSpace(phaseSetting) ? DefaultPhase : TranslatePhase(phaseSetting[0]);

                    if (string.IsNullOrWhiteSpace(description))
                    {
                        description = $"{configCell.StationName} phase {phase} {phasorType.ToString().ToLowerInvariant()} phasor";
                    }

                    configCell.PhasorDefinitions.Add(new PhasorDefinition(configCell, name, description, phasorType, phase));
                }

                // Load all analog tags
                IEnumerable <XElement> analogs = tags
                                                 .WhereAttribute("Type").Is("Analog");

                foreach (XElement analog in analogs)
                {
                    name = analog.Attribute("Name")?.Value;

                    if (string.IsNullOrWhiteSpace(name))
                    {
                        continue;
                    }

                    string description = analog.Attribute("Description")?.Value;

                    if (string.IsNullOrWhiteSpace(description))
                    {
                        description = $"{configCell.StationName} {name} analog value";
                    }

                    configCell.AnalogDefinitions.Add(new AnalogDefinition(configCell, name, description));
                }

                // Load all digital tags
                IEnumerable <XElement> digitals = tags
                                                  .WhereAttribute("Type").Is("Digital");

                foreach (XElement digital in digitals)
                {
                    name = digital.Attribute("Name")?.Value;

                    if (string.IsNullOrWhiteSpace(name))
                    {
                        continue;
                    }

                    string description = digital.Attribute("Description")?.Value;

                    if (string.IsNullOrWhiteSpace(description))
                    {
                        description = $"{configCell.StationName} {name} digital value";
                    }

                    configCell.DigitalDefinitions.Add(new DigitalDefinition(configCell, name, description));
                }

                configFrame.Cells.Add(configCell);
            }

            // Get connection details configured for SEL PDC
            string transportProtocol = serverGatewaySettings
                                       .WhereAttribute("Name").Is("TransportProtocol")
                                       .GetValue(DefaultTransportProtocol)
                                       .ToUpperInvariant();

            configFrame.TransportProtocol = transportProtocol;

            ushort commandPort = serverGatewaySettings
                                 .WhereAttribute("Name").Is("CommandPort")
                                 .GetValue(DefaultCommandPort);

            ushort dataPort = serverGatewaySettings
                              .WhereAttribute("Name").Is("DataPort")
                              .GetValue(DefaultDataPort);

            ushort port = serverGatewaySettings
                          .WhereAttribute("Name").Is("Port")
                          .GetValue(DefaultPort);

            bool multicastEnabled = serverGatewaySettings
                                    .WhereAttribute("Name").Is("MulticastEnabled")
                                    .GetValue(DefaultMulticastEnabled);

            string multicastGroup = serverGatewaySettings
                                    .WhereAttribute("Name").Is("MulticastGroup")
                                    .GetValue(DefaultMulticastGroup);

            // Setup MultiProtocolFrameParser style connection string
            Dictionary <string, string> getTcpSettings(bool commandChannel = false)
            {
                // Use of simple "protocol" key in commandChannel and separation of
                // server/port keys are required to create a proper "PmuConnection"
                // file that can be successfully parsed by the PMU Connection Tester
                return(new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase)
                {
                    [commandChannel ? "protocol": nameof(TransportProtocol)] = nameof(TransportProtocol.Tcp),
                    ["server"] = IPAddressToken,
                    ["port"] = commandChannel ? $"{commandPort}" : $"{port}",
                    ["isListener"] = "false",
                    ["interface"] = "0.0.0.0"
                });
            }

            Dictionary <string, string> settings = configFrame.Settings;

            settings[nameof(PhasorProtocol)] = nameof(PhasorProtocol.IEEEC37_118V1);

            if (transportProtocol == "TCP")
            {
                foreach (KeyValuePair <string, string> pair in getTcpSettings())
                {
                    settings[pair.Key] = pair.Value;
                }
            }
            else if (transportProtocol.StartsWith("UDP"))
            {
                settings[nameof(TransportProtocol)] = nameof(TransportProtocol.Udp);
                settings["localPort"] = $"{dataPort}";
                settings["interface"] = "0.0.0.0";

                switch (transportProtocol)
                {
                case "UDP_T":
                case "UDP_U":
                    settings["commandChannel"] = getTcpSettings(true).JoinKeyValuePairs();
                    break;
                }

                if (multicastEnabled)
                {
                    settings["server"]     = multicastGroup;
                    settings["remotePort"] = $"{commandPort}";
                }
            }
            else
            {
                settings["error"] = "No valid connection protocol detected";
            }

            // Save device IP configuration
            Dictionary <string, string> deviceIPs = configFrame.DeviceIPs;

            // Load "NetworkSettingsGroup" element from settings group
            XElement networkSettingsGroup = settingsGroups
                                            .WhereAttribute("Type").Is("NetworkSettingsGroup")
                                            .FirstOrDefault();

            if (networkSettingsGroup is null)
            {
                deviceIPs["loopback"] = "127.0.0.1";
            }
            else
            {
                string gatewayIP = networkSettingsGroup
                                   .Descendants("Setting")
                                   .WhereAttribute("Name").Is("Gateway")
                                   .GetValue(DefaultGatewayIP);

                // Get array of settings for each NIC interface
                IEnumerable <XElement[]> interfaceSettingsMap = networkSettingsGroup
                                                                .Descendants("SettingsGroup")
                                                                .WhereAttribute("Type").Is("NetworkGroup")
                                                                .Descendants("Instance")
                                                                .WhereAttribute("Type").Is("NetworkInterfaceCard")
                                                                .Select(element => element.Descendants("Setting").ToArray());

                foreach (XElement[] interfaceSettings in interfaceSettingsMap)
                {
                    string name = interfaceSettings
                                  .WhereAttribute("Name").Is("Name")
                                  .GetValue(null);

                    if (string.IsNullOrWhiteSpace(name))
                    {
                        continue;
                    }

                    string ipAddress = interfaceSettings
                                       .WhereAttribute("Name").Is("IPAddress")
                                       .GetValue(null);

                    if (string.IsNullOrWhiteSpace(ipAddress))
                    {
                        continue;
                    }

                    deviceIPs[name] = ipAddress;
                }

                // Set the target device IP to the one that matches gateway IP the closest,
                // this is just a guess, user must select proper device IP
                configFrame.TargetDeviceIP = deviceIPs
                                             .ToDictionary(pair => pair.Key, pair => gatewayIP.OverlapCoefficient(pair.Value))
                                             .Aggregate((x, y) => x.Value > y.Value ? x : y).Key;

                if (string.IsNullOrWhiteSpace(configFrame.TargetDeviceIP) && deviceIPs.Count > 0)
                {
                    configFrame.TargetDeviceIP = deviceIPs.First().Key;
                }
            }

            return(configFrame);
        }
예제 #18
0
 void IConfigurationFrame.SetNominalFrequency(LineFrequency value)
 {
     throw new NotImplementedException();
 }
예제 #19
0
        // Static Methods       

        /// <summary>
        /// Creates a new IEC 61850-90-5 (i.e., IEEE C37.118) <see cref="ConfigurationFrame"/> based on provided protocol independent <paramref name="baseConfigurationFrame"/>.
        /// </summary>
        /// <param name="baseConfigurationFrame">Protocol independent <see cref="GSF.PhasorProtocols.Anonymous.ConfigurationFrame"/>.</param>
        /// <param name="timeBase">Timebase to use for fraction second resolution.</param>
        /// <param name="nominalFrequency">The nominal <see cref="LineFrequency"/> to use for the new <see cref="ConfigurationFrame"/></param>.
        /// <returns>A new IEEE C37.118 <see cref="ConfigurationFrame"/>.</returns>
        public static ConfigurationFrame CreateConfigurationFrame(GSF.PhasorProtocols.Anonymous.ConfigurationFrame baseConfigurationFrame, uint timeBase, LineFrequency nominalFrequency)
        {
            ConfigurationCell newCell;
            uint maskValue;

            // Create a new IEEE C37.118 configuration frame 2 using base configuration
            ConfigurationFrame configurationFrame = new ConfigurationFrame(timeBase, baseConfigurationFrame.IDCode, DateTime.UtcNow.Ticks, baseConfigurationFrame.FrameRate);

            foreach (GSF.PhasorProtocols.Anonymous.ConfigurationCell baseCell in baseConfigurationFrame.Cells)
            {
                // Create a new IEEE C37.118 configuration cell (i.e., a PMU configuration)
                newCell = new ConfigurationCell(configurationFrame, baseCell.IDCode, nominalFrequency);

                // Update other cell level attributes
                newCell.StationName = baseCell.StationName;
                newCell.IDLabel = baseCell.IDLabel;
                newCell.PhasorDataFormat = baseCell.PhasorDataFormat;
                newCell.PhasorCoordinateFormat = baseCell.PhasorCoordinateFormat;
                newCell.FrequencyDataFormat = baseCell.FrequencyDataFormat;
                newCell.AnalogDataFormat = baseCell.AnalogDataFormat;

                // Add phasor definitions
                foreach (IPhasorDefinition phasorDefinition in baseCell.PhasorDefinitions)
                {
                    newCell.PhasorDefinitions.Add(new PhasorDefinition(newCell, phasorDefinition.Label, phasorDefinition.ScalingValue, phasorDefinition.Offset, phasorDefinition.PhasorType, null));
                }

                // Add frequency definition
                newCell.FrequencyDefinition = new FrequencyDefinition(newCell, baseCell.FrequencyDefinition.Label);

                // Add analog definitions
                foreach (IAnalogDefinition analogDefinition in baseCell.AnalogDefinitions)
                {
                    newCell.AnalogDefinitions.Add(new AnalogDefinition(newCell, analogDefinition.Label, analogDefinition.ScalingValue, analogDefinition.Offset, analogDefinition.AnalogType));
                }

                // Add digital definitions
                foreach (IDigitalDefinition digitalDefinition in baseCell.DigitalDefinitions)
                {
                    // Attempt to derive user defined mask value if available
                    DigitalDefinition anonymousDigitalDefinition = digitalDefinition as DigitalDefinition;

                    if (anonymousDigitalDefinition != null)
                        maskValue = anonymousDigitalDefinition.MaskValue;
                    else
                        maskValue = 0U;

                    newCell.DigitalDefinitions.Add(new GSF.PhasorProtocols.IEC61850_90_5.DigitalDefinition(newCell, digitalDefinition.Label, maskValue.LowWord(), maskValue.HighWord()));
                }

                // Add new PMU configuration (cell) to protocol specific configuration frame
                configurationFrame.Cells.Add(newCell);
            }

            return configurationFrame;
        }
예제 #20
0
        private int m_numberOfSatellites = 1; // We'll initially assume synchronization is good until told otherwise

        #endregion

        #region [ Constructors ]

        /// <summary>
        /// Creates a new <see cref="ConfigurationCell"/> from specified parameters.
        /// </summary>
        /// <param name="parent">The reference to parent <see cref="ConfigurationFrame"/> of this <see cref="ConfigurationCell"/>.</param>
        /// <param name="nominalFrequency">The nominal <see cref="LineFrequency"/> of the <see cref="FrequencyDefinition"/> of this <see cref="ConfigurationCell"/>.</param>
        /// <param name="timeOffset">The time offset of F-NET device in <see cref="Ticks"/>.</param>
        internal ConfigurationCell(ConfigurationFrame parent, LineFrequency nominalFrequency, Ticks timeOffset)
            : base(parent, parent.IDCode, Common.MaximumPhasorValues, Common.MaximumAnalogValues, Common.MaximumDigitalValues)
        {
            NominalFrequency = nominalFrequency;
            m_timeOffset     = timeOffset;
        }